def non_sidereal_ra(target_name): global eph_obj_coords if eph_obj_coords is None: try: # if there is a space in the nane, assume the first string is an acceptable name obj = Horizons(id=target_name[0].split()[0], epochs=Time.now().jd) eph_obj_coords = [ obj.ephemerides()['RA'][0], obj.ephemerides()['DEC'][0] ] return eph_obj_coords[0] except: pass return None
def horizons(location, target, cat): Rarray = np.empty(1) Decarray = np.empty(1) for i in range(0, len(cat), 350): print 'loop ' + str(i) epoch = cat[i:i + 350] print len(epoch) epochs = [] for j in range(0, len(epoch)): epochs.append(epoch[j][1]) print epochs epochs = np.array(epochs) obj = Horizons(id=target, location=location, id_type='majorbody', epochs=epochs) eph = obj.ephemerides() newRA = np.array(eph['RA']) print eph['targetname'] newDec = np.array(eph['DEC']) Rarray = np.concatenate((Rarray, newRA)) Decarray = np.concatenate((Decarray, newDec)) for i in range(0, len(cat)): cat[i][5] = Rarray[i + 1] cat[i][6] = Decarray[i + 1] return cat
def get_earth_ephemerides(epoch_start, epoch_stop, step_size, type_elements): # step: step size, [10m, 1d, 1y] obj = Horizons(id='Geocenter', location='500@10', epochs={ 'start': epoch_start, 'stop': epoch_stop, 'step': step_size }, id_type='majorbody') if type_elements.lower() == 'vectors': data_output = obj.vectors() # vectorial elements elif type_elements.lower() == 'ephemerides': data_output = obj.ephemerides() len_rows = len(data_output) len_cols = 6 # 3 positions 'x','y','z', and 3 velocities 'vx', 'vy', 'vz' idx_x = 3 # 'x' is at position 3 in the table data = np.zeros([len_rows, len_cols]) for row in range(len_rows): for col in range(6): idx_col_in_table = idx_x + col # because the 'x' start at 3rd col, going up till the 9th that is 'vz' data[row, col] = data_output[row][idx_col_in_table] return data
def get_ephemeris(args): epochs = dict(start=args.start_date.iso, stop=args.stop_date.iso, step=args.step) id_type = args.type # ephemeris options opts = dict(solar_elongation=(85, 135), cache=(not args.no_cache)) # comets need special care: use closest orbital elements by date, do not # search for related fragments if args.type == 'comet': id_type = 'designation' opts.update(closest_apparition=True, no_fragments=True) horizons = Horizons(args.target, location='@jwst', epochs=epochs, id_type=id_type) eph = horizons.ephemerides(**opts) eph['date'] = Time(eph['datetime_jd'], format='jd') if len(eph) == 0: print('''No epochs observable by JWST. Try a new date range and/or finer time steps.''') sys.exit(1) return eph
def get_target_ephemeris(desg, start_date, end_date, smallbody=False): """Ephemeris from JPL/HORIZONS. smallbody : bool, optional Set to `True` for comets and asteroids, `False` for planets, spacecraft, or moons. Returns : target name from HORIZONS, RA, and Dec. """ if smallbody: bodytype = 'smallbody' else: bodytype = 'majorbody' obj = Horizons(id=desg, location='500@-170', id_type=bodytype, epochs={ 'start': start_date, 'stop': end_date, 'step': '1d' }) eph = obj.ephemerides(cache=False, quantities=(1)) return eph['targetname'][0], eph['RA'], eph['DEC']
def photod_rate(time, time_scale, target, id_type, observatory, time_format, mol_tag): # imported here to avoid circular dependency with activity.gas from ..activity.gas import photo_timescale epoch = Time(time, scale=time_scale, format=time_format) obj = Horizons(id=target, epochs=epoch.jd, location=observatory, id_type=id_type) try: orb = obj.ephemerides() except ValueError: raise delta = (orb['delta'].data * u.au).to('m') r = (orb['r'].data) cat = JPLSpec.get_species_table() mol = cat[cat['TAG'] == mol_tag] name = mol['NAME'].data[0] timescale = photo_timescale(name) if timescale.ndim != 0: # array timescale = timescale[0] beta = (timescale) * r**2 return beta, delta
def _get_object_RADEC_from_horizons(self, object_name, obs_code, times, object_type='smallbody'): ''' Query horizons for the RA & DEC of a *known object* at a sequence of times. input: object_name - string obs_code - string - Note that Horizons uses some weird ones sometimes, like "500@-95" for Tess. times - array of times (JD) object_type - string - Usually the default "smallbody" is fine, but for some objects, like natsats, it's neccessary. ''' horizons_query = Horizons(id=object_name, location=obs_code, epochs=times, id_type=object_type) horizons_ephem = horizons_query.ephemerides(extra_precision=False) self.RA, self.Dec = np.array( [horizons_ephem['RA'], horizons_ephem['DEC']])
def get_target_xyz(t): """ Returns the vectors of the Horizons body at a certain time t. Arguments: t: days Julian date of observation Returns: xyz: numpy array A position vector of the observed object uvw: numpy array An instantaneous velocity vector of the observed object """ obj = Horizons(id=name, location=loc, epochs=t, id_type='majorbody') obj1 = obj.vectors(aberrations=cor, refplane='earth') xyz = np.array([float(obj1['x']), float(obj1['y']), float(obj1['z'])]) uvw = np.array( [float(obj1['vx']), float(obj1['vy']), float(obj1['vz'])]) obj2 = obj.ephemerides(refsystem='J2000', extra_precision=True) radec = np.array( [float(obj2['RA']), float(obj2['DEC']), float(obj1['range'])]) return xyz, uvw, radec
def get_planet_timelines(planet_id, start_date, end_date, time_step): #planet_id can be either a 3digit number from the IAU #catalogue either the barycenter of the planet #insert date in form YYYYMMDD filefolder ='//Users/nadia/Downloads/' #convert the dates into the correct form YYYY-MM-DD start_date = str(start_date)[:4]+'-'+str(start_date)[4:6]+'-'+str(start_date)[6:] end_date = str(end_date)[:4]+'-'+str(end_date)[4:6]+'-'+str(end_date)[6:] time_step = str(time_step)+'d' Epochs = {'start':start_date,'stop':end_date, 'step':time_step} obj = Horizons(id = str(planet_id), id_type = 'majorbody', location = None, epochs = Epochs) eph = obj.ephemerides() ra = np.array(eph['RA']) dec = np.array(eph['DEC']) t = np.array(eph['datetime_jd']) timelines = {'t':t, 'ra':ra, 'dec':dec} np.save(opj(filefolder, 'Planet_'+str(planet_id)+'_timelines'), timelines) return(ra,dec)
def get_planetary_positions(target,type='majorbody'): ''' Gets ephemerides data (planetary positions) using JPL Horizons program for given planet at predefined times ''' planet_pos_data = Horizons(id=target, id_type=type, location=LOCATION, epochs=EPOCHS) eph = planet_pos_data.ephemerides() eph['r'].convert_unit_to('km') return eph['targetname','datetime_str','EclLon','EclLat','r']
def download_ephemeris_data(self, body, dates, coordinates): """Downloads ephemeris data by querying the JPL Horizons site""" bodies_class = Bodies(*self.get_body_list()) bodykey = bodies_class.get_body_code(body) uncertainties = [] downloaded_data = [] log_file = "Log.txt" for i in tqdm(range(0, len(dates), 380)): jpl_horizon = Horizons(id=bodykey, location=coordinates, epochs=dates[i:i + 380], id_type='id') eph = jpl_horizon.ephemerides(quantities='1,9,36', get_raw_response=True, refsystem='B1950', refraction=True).split("\n") for i in range(0, len(eph)): if "$$SOE" in eph[i]: lower_bound = i if "$$EOE" in eph[i]: upper_bound = i data_points = eph[lower_bound + 1:upper_bound] break try: for i in range(0, len(data_points)): if len(data_points[i]) == 10: uncertainties = [ data.strip() for data in data_points[i].split(",")[8:10] ] else: uncertainties = [ data.strip() for data in data_points[i].split(",")[7:9] ] data_points[i] = [ data.strip() for data in data_points[i].split(",")[4:7] ] data_points[i] += uncertainties downloaded_data.append(" ".join(data_points[i])) except UnboundLocalError: with open(os.path.join(self.temp_files, log_file)) as error_logger: for line in eph: logging.write("{}\n".format(line)) raise Exception( "Problem With Loading Ephemeris Data, Check Log.txt File For More Details" ) with open(os.path.join(self.temp_files, log_file), "w") as logging: print("Writing Ephemeris Log") for line in eph: logging.write("{}\n".format(line)) self.cache_ephemeris_data(body, downloaded_data) return downloaded_data
def getHorizonsEphemeris( obj_ids, observers, id_type="smallbody" ): """ Query JPL Horizons (through astroquery) for an object's ephemerides at the given times viewed from the given location. Parameters ---------- obj_ids : `~numpy.ndarray` (N) Object IDs / designations recognizable by HORIZONS. observers : dict or `~pandas.DataFrame` A dictionary with observatory/location codes as keys and observation_times (`~astropy.time.core.Time`) as values. Location of the observer which can be an MPC observatory code (eg, 'I41', 'I11') or a NAIF code ('0' for solar system barycenter, '10' for heliocenter) id_type : {'majorbody', 'smallbody', 'designation', 'name', 'asteroid_name', 'comet_name', 'id'} ID type, Horizons will find closest match under any given type. Returns ------- ephemeris : `~pandas.DataFrame` Dataframe containing the RA, DEC, r, r_rate, delta, delta_rate and light time of the object at each time. """ dfs = [] for orbit_id, obj_id in enumerate(obj_ids): for observatory_code, observation_times in observers.items(): _checkTime(observation_times, "observation_times") obj = Horizons( id=obj_id, epochs=observation_times.utc.mjd, location=observatory_code, id_type=id_type ) ephemeris = obj.ephemerides( # RA, DEC, r, r_rate, delta, delta_rate, lighttime #quantities="1, 2, 19, 20, 21", extra_precision=True ).to_pandas() ephemeris["orbit_id"] = [orbit_id for i in range(len(ephemeris))] ephemeris["observatory_code"] = [observatory_code for i in range(len(ephemeris))] ephemeris["mjd_utc"] = observation_times.utc.mjd dfs.append(ephemeris) ephemeris = pd.concat(dfs) ephemeris.sort_values( by=["orbit_id", "observatory_code", "datetime_jd"], inplace=True ) ephemeris.reset_index( inplace=True, drop=True ) return ephemeris
def obj_query(identifier, location, start_date, stop_date, step_size, min_mag, ): """ Responsible for pulling ephemeris information from JPL Horizons""" # Calls object identified with date information from JPL horizons. obj = Horizons(id=identifier, location=location, epochs={'start':start_date, 'stop':stop_date, 'step':step_size}, ) # Checks if Daylight needs to be skipped if skip_day == 'y': # Creating Ephemeris without daylight hours eph = obj.ephemerides(skip_daylight=True) else: # Creating ephemeris object at all hours eph = obj.ephemerides(skip_daylight=False) # Convert table to pandas dataframe (easier to manipulate). eph_df = eph[column_names].to_pandas() # Removes objects with airmass higher then limit if airmass_q == True: eph = airmass_limit(eph_df, airmass_lim) # Check if Plots need to be saved before editing dataframe. if save_plot[0].lower() == 'y': plotter(eph_df, identifier, min_mag) else: pass # Uses find oppositions to find opposition dates. min_eph_df = find_oppositions(min_mag, eph_df) return min_eph_df
def Anal(filenames,Plot,Target,Aperture,SS): Res = [] JD = [] Alpha = [] PlAng = [] All = [] retarder =[] Stoke_Final = [] for elem in filenames: stokes = [] with open(elem,'r') as f: for elem in f.readlines(): print(elem) stokes.append(float(elem.replace('\n',' ').replace('\t',' ').split()[2])) Stoke_Final.append(stokes) JD.append(float(elem.replace('\n',' ').replace('\t',' ').split()[0])) retarder.append(float(elem.replace('\n',' ').replace('\t',' ').split()[1])) if not SS: obj = Horizons(id=Target, location='679', epochs=float(elem.replace('\n',' ').replace('\t',' ').split()[0])) eph = obj.ephemerides() Alpha.append(eph['alpha'][0]) PlAng.append(eph['sunTargetPA'][0]) All.append(stokes) if Plot: plt.plot(stokes) # Res.append(np.median(stokes[Aperture])) All = np.array(All) print(np.sqrt((1./2*(All[0,:]-All[2,:]))**2+(1./2*(All[1,:]+All[3,:]))**2)) plt.plot(np.sqrt((1./2*(All[0,:]-All[2,:]))**2+(1./2*(All[1,:]-All[3,:]))**2),Linewidth = 3) plt.show() if not Aperture: Aperture = int(raw_input("What aperture to you want to use? ")) print() Res = All[:,Aperture] if not SS: with open('result.txt', 'w') as f: for idx,elem in enumerate(Res): f.write(str(retarder[idx]) + '\t' + str(JD[idx]) + '\t' + str(Alpha[idx]) + '\t' + str(PlAng[idx]) + '\t' + str(elem) + '\n') else: with open('result_Standard.txt', 'w') as f: for idx,elem in enumerate(Res): f.write(str(retarder[idx]) + '\t' + str(JD[idx]) + '\t' + str(0) + '\t' + str(0) + '\t' + str(elem) + '\n')
def get_sso_ephem(self, name, epoch_start, epoch_end, epoch_step="1min", location="A84"): """Instantiate JPL query. Parameters ---------- name : str, required Name, number, or designation of the object to be queried location : str or dict, optional Observer's location for ephemerides queries or center body name for orbital element or vector queries. Uses the same codes as JPL Horizons. If no location is provided, Earth's center is used for ephemerides queries and the Sun's center for elements and vectors queries. Arbitrary topocentic coordinates for ephemerides queries can be provided in the format of a dictionary. The dictionary has to be of the form {``'lon'``: longitude in deg (East positive, West negative), ``'lat'``: latitude in deg (North positive, South negative), ``'elevation'``: elevation in km above the reference ellipsoid, [``'body'``: Horizons body ID of the central body; optional; if this value is not provided it is assumed that this location is on Earth]}. epochs : scalar, list-like, or dictionary, optional Either a list of epochs in JD or MJD format or a dictionary defining a range of times and dates; the range dictionary has to be of the form {``'start'``:'YYYY-MM-DD [HH:MM:SS]', ``'stop'``:'YYYY-MM-DD [HH:MM:SS]', ``'step'``:'n[y|d|m|s]'}. Epoch timescales depend on the type of query performed: UTC for ephemerides queries, TDB for element queries, CT for vector queries. If no epochs are provided, the current time is used. id_type : str, optional Identifier type, options: ``'smallbody'``, ``'majorbody'`` (planets but also anything that is not a small body), ``'designation'``, ``'name'``, ``'asteroid_name'``, ``'comet_name'``, ``'id'`` (Horizons id number), or ``'smallbody'`` (find the closest match under any id_type), default: ``'smallbody'`` Examples -------- >>> from astroquery.jplhorizons import Horizons >>> eros = Horizons(id='433', location='568', ... epochs={'start':'2017-01-01', ... 'stop':'2017-02-01', ... 'step':'1d'}) >>> print(eros) # doctest: +SKIP JPLHorizons instance "433"; location=568, epochs={'start': '2017-01-01', 'step': '1d', 'stop': '2017-02-01'}, id_type=smallbody """ obj = Horizons(id=name, location=location, epochs={'start': '{}'.format(epoch_start), 'stop': '{}'.format(epoch_end), 'step': '{}'.format(epoch_step)}) eph = obj.ephemerides() return eph
def targetEphemerisFromHorizons(target_id, observer_location, tstart, tstop, ephemeris_dt='12h'): """Query JPL Horizons via astroquery to get sun-observer state vectors. Parameters: ----------- target_id ... Horizons identifyer target, e.g. 'Ceres' observer_location ... Horizons identifyer of observer location, e.g. 'I11' tstart ... start time for ephemeris in Horizons format, e.g. 'JD2456789.5' tstop ... end time for ephemeris in Horizons format, e.g. 'JD2456799.5' ephemeris_dt ... Time step for ephemeris query. Typically 1h since the actual times will be interpolated later. Returns: -------- RA, DEC ... Right Ascension and Declination of target wrt observer ephemeris_jd ... Ephemeris epochs (JD / UTC) External Function Requirements: ------------------------------- # External API's from astroquery.jplhorizons import Horizons """ try: # Get observer locations (caution: choose the right plane of reference and direction of the vectors!) # check query by copy/pasting the output of print(observer_sun.uri) into a webbrowser if there are problems. # tmin = 'JD'+str(tstart) # tmax = 'JD'+str(tstop+1.) tmin = tstart tmax = tstop observer2target = Horizons(id=target_id, location=observer_location, epochs={ 'start': tmin, 'stop': tmax, 'step': ephemeris_dt }) ra, dec = observer2target.ephemerides()['RA', 'DEC'] jd = (observer2target.vectors())['datetime_jd'] except: print( "Error in observer_state_from_horizons: potential online ephemeris query failure." ) raise return ephemeris_jd, ra, dec
def get_radec_fromjpl(ssid='',location='511',jd=2454545.0): """Get Solar System Object position from Horizons Parameters ---------- ssid : string, optional JPL id of the object to be found. Default is empty string. location : string, optional IAU observatory code. Default is '511' (OHP). jd : float, optional Juliand day for the computation of the ephemeris. Default is J2000. Returns ------- skycoo : astropy.coordinates.Skycoordinate Object Sky coordinates (RA,DEC) of the object. """ defhorserver() sshor = Horizons(id=ssid,location=location,epochs=jd) try: eph = sshor.ephemerides() except Exception as e: if ('Ambiguous' in str(e)): ssidjpl = str(e).split('\n')[-2].split()[0] t120.log.warning('Ambiguous name detected! Corrected to id='+ssidjpl) try: sshor = Horizons(id=ssidjpl,location=location,epochs=jd) eph = sshor.ephemerides() except Exception as e: raise(e) else: raise(e) skycoo = SkyCoord(eph['RA'][0],eph['DEC'][0],unit='deg',obstime=Time(jd,format='jd')) t120.log.info(ssid+' '+skycoo.to_string(style='hmsdms')) return skycoo
def get_path(obj_name, times, id_type='smallbody', location=None): """ # See more details at https://astroquery.readthedocs.io/en/latest/jplhorizons/jplhorizons.html # For valid locations: https://minorplanetcenter.net//iau/lists/ObsCodesF.html Parameters ---------- obj_name: str Object name. May require specific formatting (i.e. selecting between the codes for Jupiter and Jupiter barycenter). See JPL Horizons documentation times: float or arr Times to check, input as a float, array, or specified start/stop/step (example: {'start':'2019-01-01', 'stop':'2019-12-31', 'step':'1d'}) id_type: str Object ID type for JPL Horizons. Defaults to smallbody (an asteroid or comet). Best to be as specific as possible to find the correct body. majorbody: planets and satellites smallbody: asteroids and comets asteroid_name: name of asteroid comet_name: name of comet name: any target name designation: any asteroid or comet designation location: str Default of None uses a geocentric location for queries. For specific spacecrafts, insert location Examples: TESS: @TESS Hubble: @hst Kepler: 500@-227 Returns ------- eph: Astropy table Table object with the JPL Horizons calculated ephemerides """ obj = Horizons(id=obj_name, location=location, id_type=id_type, epochs=times) eph = obj.ephemerides() return eph
def dl_flats(xtag, idx, locationx, epochsx, quantitiesx): ''' Standard set-up for downloading flatfiles. Minimal preprocessing. ''' obj = Horizons(id=idx, location=locationx, epochs=epochsx, id_type='majorbody') # Precision increases only for the RA DEC only, not the angles eph = obj.ephemerides(quantities=quantitiesx, extra_precision=True) dropthese = ['targetname'] del eph[dropthese] oldcol = list(eph.columns) oldcol = [s for s in oldcol if not s.startswith('datetime')] newcol = [xtag + '_' + s for s in oldcol] eph.rename_columns(oldcol, newcol) return eph
def query(self, depoch=100, *args, **kwargs): ''' Parameters ---------- depoch : int, optional The number of discrete epochs to be chopped. args, kwargs : optional. Passed to ``.ephemerides()`` of ``Horizons``. ''' Nepoch = np.shape(self.epochs)[0] Nquery = (Nepoch - 1) // depoch + 1 tabs = [] print(f'Query: {self.targetname} ' + f'at {self.location} for {Nepoch} epochs' '') if Nquery > 1: print(f"Query chopped into {Nquery} chunks: Doing ", end=' ') for i in range(Nquery): print(f"{i+1}...", end=' ') i_0 = i * depoch i_1 = (i + 1) * depoch epochs_i = self.epochs[i_0:i_1] obj = Horizons( id=self.targetname, # location=self.location, # epochs=epochs_i, # id_type=self.id_type) eph = obj.ephemerides(*args, **kwargs) tabs.append(eph) self.uri.append(obj.uri) if len(tabs) == 1: self.query_table = tabs[0] elif len(tabs) > 1: self.query_table = vstack(tabs) print("Query done.") return self.query_table
def check_detectability(obj_id="2020 DA4", obs_lat=69.3908, obs_lon=20.2673, obs_el=0.0, start="2020-01-01", stop="2020-06-01", step="2h", min_el=30.0, id_type="smallbody", debug=False): e3d = {'lon': obs_lon, 'lat': obs_lat, 'elevation': obs_el} obj = Horizons(id=obj_id, location=e3d, epochs={ "start": start, "stop": stop, "step": step }, id_type=id_type) # t0=obj.ephemerides(quantities="4,20",get_raw_response=True) t = obj.ephemerides(quantities="4,20", get_raw_response=False) if debug: print(t) els = [] ranges = [] range_rates = [] dates = [] for r in t: name = r[0] date = r[1] az = r[7] # deg el = r[8] # deg if el > min_el: delta = r[9] * c.au # m delta_rate = r[10] * 1e3 #m/s # print("el %1.2f range %1.2g range-rate %1.2f gain %1.2f"%(el,delta,delta_rate/1e3,g_dB)) els.append(float(el)) ranges.append(delta) range_rates.append(delta_rate) dates.append(r[1]) return (n.array(ranges), n.array(range_rates), n.array(els), dates)
def test_Ephemerides_Vectors_Astrometric(): strstartdate = '2021-1-1 12:00:00' strenddate = '2021-1-2 12:00:00' start_time = Time(strstartdate) start_time_tdb = start_time.tdb end_time = Time(strenddate) end_time_tdb = end_time.tdb # print(start_time.value, start_time_tdb.value) mars_by_earth_obs = Horizons(id='499', id_type='majorbody', location='500', epochs={ 'start': start_time.value, 'stop': end_time.value, 'step': '1' }) mars_by_earth_vec = Horizons(id='499', id_type='majorbody', location='500', epochs={ 'start': start_time_tdb.value, 'stop': end_time_tdb.value, 'step': '1' }) mars_by_earth_obs_data = mars_by_earth_obs.ephemerides( quantities='1,2,4,20,31') mars_by_earth_vec_astrometric = mars_by_earth_vec.vectors( refplane='earth', aberrations='astrometric', delta_T=True) mars_by_earth_vec_apparent = mars_by_earth_vec.vectors( refplane='earth', aberrations='apparent', delta_T=True) mars_by_earth_vec_geometric = mars_by_earth_vec.vectors(refplane='earth', delta_T=True) print( "比較 Horizons 中,用 Observer 模式查得的 RA/DEC與用Vectors模式(aberrations='astrometric')查得的是否相同?是相同!" ) print(mars_by_earth_obs_data['datetime_str', 'RA', 'DEC', 'RA_app', 'DEC_app', 'delta']) # print(mars_by_earth_vec_astrometric['x','y','z','lighttime']) astrometric_position = SkyCoord( x=mars_by_earth_vec_astrometric['x'].tolist() * u.au, y=mars_by_earth_vec_astrometric['y'].tolist() * u.au, z=mars_by_earth_vec_astrometric['z'].tolist() * u.au, representation_type='cartesian', frame='gcrs') astrometric_position.representation_type = 'spherical' print(astrometric_position)
def horizons(location, target, cat, id_type): extra = np.zeros((len(cat))) extra2 = np.zeros((len(cat))) extra3 = np.zeros((len(cat))) cat = np.column_stack((cat, extra, extra2, extra3)) Rarray = np.empty(1) Decarray = np.empty(1) galbarray = np.empty(1) gallarray = np.empty(1) magarray = np.empty(1) for i in range(0, len(cat), 350): progress = round((i * 100 / float(len(cat))), 1) print str(progress) + '%' epoch = cat[i:i + 350] epochs = [] for j in range(0, len(epoch)): epochs.append(epoch[j][1]) epochs = np.array(epochs) obj = Horizons(id=target, location=location, id_type=id_type, epochs=epochs) eph = obj.ephemerides() if i == 0: targetname = eph['targetname'][i] newRA = np.array(eph['RA']) newDec = np.array(eph['DEC']) newgalb = np.array(eph['GlxLat']) newgall = np.array(eph['GlxLon']) newMag = np.array(eph['V']) Rarray = np.concatenate((Rarray, newRA)) Decarray = np.concatenate((Decarray, newDec)) galbarray = np.concatenate((galbarray, newgalb)) gallarray = np.concatenate((gallarray, newgall)) magarray = np.concatenate((magarray, newMag)) for i in range(0, len(cat)): cat[i][5] = Rarray[i + 1] cat[i][6] = Decarray[i + 1] cat[i][8] = gallarray[i + 1] cat[i][9] = galbarray[i + 1] cat[i][10] = magarray[i + 1] cat[:, 5] = np.radians(cat[:, 5]) cat[:, 6] = np.radians(cat[:, 6]) targetname = targetname.replace(' ', '_') return cat, targetname
def getRadec(obsid,horizon_id,coord,aster): # coord: '@swift' or 500 img_name = 'sw'+str(obsid)+'ugu_sk.img.gz' #img_name = 'sw'+obsid+'uw2_sk.img' img_path = '/Users/zexixing/Research/swiftASTER/data/'+aster+'/'+\ obsid+'/uvot/image/'+img_name hdul = fits.open(img_path) start = Time(hdul[0].header['DATE-OBS']) end = Time(hdul[0].header['DATE-END']) dt = end-start mid_time = start + 1/2*dt obj = Horizons(id=horizon_id, location=coord, epochs=mid_time.jd) eph = obj.ephemerides()[0] ra = eph['RA'] dec = eph['DEC'] return ra, dec
def _query_jpl_horizons(self) -> None: """Takes the object name from the text box, queries JPL Horizons, and fills the RA/Dec inputs with the result.""" from astroquery.jplhorizons import Horizons # clear solar system and simbad self.comboSolarSystemBody.setCurrentText("") self.textSimbadName.clear() # wait cursor QtWidgets.QApplication.setOverrideCursor(QtCore.Qt.WaitCursor) # query try: # query obj = Horizons(id=self.textJplHorizonsName.text(), location=None, epochs=Time.now().jd) # get ephemerides eph = obj.ephemerides() except InvalidQueryError: QtWidgets.QMessageBox.critical(self, "JPL Horizons", "No result found") return except ValueError: QtWidgets.QMessageBox.critical(self, "JPL Horizons", "Invalid result") return finally: # restore cursor QtWidgets.QApplication.restoreOverrideCursor() # always use first result coord = SkyCoord(eph["RA"][0] * u.deg, eph["DEC"][0] * u.deg, frame="icrs") self.textMoveRA.setText(coord.ra.to_string(unit=u.hour, sep=" ")) self.textMoveDec.setText(coord.dec.to_string(sep=" ")) # update destination self._calc_dest_equatorial(clear=False)
def mag2afr(horizon_id, mag_v, mag_v_err, aperture, obs_log_name, phase_name, phase_corr): #def mag2afr(horizon_id, mag_v, mag_v_err, aperture, r, delta, phase, phase_name, phase_corr): obs_log_path = get_path('../docs/' + obs_log_name) obs_log = pd.read_csv(obs_log_path, sep=' ', index_col=['FILTER']) obs_log = obs_log[['HELIO', 'HELIO_V', 'START', 'END', 'OBS_DIS']] obs_log = obs_log.loc['V'] if obs_log.index.name == 'FILTER': start = obs_log['START'].iloc[0] end = obs_log['END'].iloc[-1] else: start = obs_log['START'] end = obs_log['END'] dt = Time(end) - Time(start) mid_time = Time(start) + 1 / 2 * dt obj = Horizons(id=horizon_id, location='@swift', epochs=mid_time.jd) eph = obj.ephemerides()[0] r = eph['r'] delta = eph['delta'] phase = eph['alpha'] # afr mag_sun = -26.75 rou = au2km(as2au(aperture, delta)) * 1000 factor = np.power(2 * au2km(delta) * r * 1000, 2) / rou afr = np.power(10, 0.4 * (mag_sun - mag_v)) * factor afr_err = 0.4 * np.log(10) * np.power( 10, 0.4 * (mag_sun - mag_v)) * mag_v_err * factor # phase effect correction phase_path = get_path('../docs/' + phase_name) phase_file = np.loadtxt(phase_path) deg = phase_file[:, 0] corr_coef = phase_file[:, 1] pha_corr = interpolate.interp1d(deg, corr_coef, fill_value='extrapolate') corr_coef = pha_corr(phase) if phase_corr == True: afr = afr / corr_coef afr_err = afr_err / corr_coef else: pass return afr, afr_err
def query_ephemerides(cfg): #create observer location gs = { 'lon': cfg['gs']['longitude'], 'lat': cfg['gs']['latitude'], 'elevation': cfg['gs']['altitude_m'] / 1000.0 } #create query object if 'id' in cfg['horizons'].keys(): id = cfg['horizons']['id'] else: id = cfg['horizons']['name'] obj = Horizons(id=id, location=gs, id_type=cfg['horizons']['id_type'], epochs=cfg['horizons']['epochs']) eph = obj.ephemerides(quantities=cfg['horizons']['quantities']) keys = [ 'datetime_str', 'datetime_jd', 'AZ', 'AZ_rate', 'EL', 'EL_rate', 'delta', 'delta_rate', 'lighttime' ] df = pd.DataFrame(np.array(eph[keys]), columns=keys) df['AZ_rate'] = df[ 'AZ_rate'] * 4.62963e-6 # arcsec per min to degrees per sec df['EL_rate'] = df[ 'EL_rate'] * 4.62963e-6 # arcsec per min to degrees per sec df['delta'] = df['delta'] * au2km # AU to km df['lighttime'] = df['lighttime'] * 60 #minutes to seconds column_map = { 'datetime_str': 'datetime_str [UTC]', 'datetime_jd': 'datetime_jd [UTC]', 'AZ': 'Azimuth [deg]', 'AZ_rate': 'Azimuth Rate [deg/sec]', 'EL': 'Elevation [deg]', 'EL_rate': 'Elevation Rate [deg/sec]', 'delta': 'Range [km]', 'delta_rate': 'Range Rate [km/sec]', 'lighttime': '1-Way Prop Delay [sec]' } df = df.rename(columns=column_map) df['datetime [ISO UTC]'] = pd.to_datetime(df['datetime_str [UTC]'], format="%Y-%b-%d %H:%M") return df
def get_current_pos(object_name, start_date, end_date, time_step): if 'COMET' in object_name: obj = Horizons(id=object_name[object_name.find(' ') + 1:], epochs={ 'start': start_time, 'stop': end_time, 'step': step }, id_type='id') if not 'COMET' in object_name: obj = Horizons(id=object_name, epochs={ 'start': start_date, 'stop': end_date, 'step': time_step }) eph = obj.ephemerides() pos = SkyCoord(eph['RA'], eph['DEC'], unit='deg') vec = obj.vectors() times = Time(np.asarray(vec['datetime_jd']), format='jd', scale='utc') return np.asarray(pos.ra), np.asarray(pos.dec), times, np.asarray( eph['RA_rate']), np.asarray(eph['DEC_rate']), np.asarray(eph['V'])
def get_ephem_jpl(el_jpl, start, stop, obs): ''' Parameters ---------- el_jpl : `~numpy.ndarray` (N, 12) Orbital elements as returned by jpl. start : `str` Beginning time of integration, UTC. stop : `str` End time of integration, UTC. obs : `str` Observatory code. Returns ------- coord_jpl : `~numpy.ndarray` (N, 2) RA and DEC coordinates of ephemderides as determined by JPL, units deg RA : first column of coord_jpl DEC : second column of coord_jpl mag_jpl : `~numpy.ndarray` (N, 1) Contains magnitudes of object as determined by JPL, units mags ''' obj_id = el_jpl['targetname'][0] ephem_obj = Horizons(id=obj_id, location=obs, epochs={ 'start': start, 'stop': stop, 'step': '1d' }) ephem_jpl = ephem_obj.ephemerides() coord_jpl = np.array([ephem_jpl['RA'], ephem_jpl['DEC']]) * u.deg mag_jpl = np.array([ephem_jpl['V']]) * u.mag return coord_jpl, mag_jpl
def getPlanetInfo(planet): obj = Horizons(id=planet, location='000', epochs=None, id_type='majorbody') eph = obj.ephemerides() return eph
def moving_primary_target(catalogs, man_targetname, offset, is_asteroid=None, display=True): """ is_asteroid == True: this object is an asteroid is_asteroid == False: this object is a planet/moon/spacecraft is_asteroid == None: no information on target nature """ if display: print('# check JPL Horizons for primary target... ') sys.stdout.flush() logging.info('check JPL Horizons for primary target') obsparam = _pp_conf.telescope_parameters[ catalogs[0].origin.split(';')[0].strip()] objects = [] # check for target nature, if unknown if is_asteroid is None: cat = catalogs[0] targetname = cat.obj.replace('_', ' ') if man_targetname is not None: targetname = man_targetname.replace('_', ' ') for smallbody in [True, False]: obj = Horizons(targetname.replace('_', ' '), id_type={True: 'smallbody', False: 'majorbody'}[smallbody], epochs=cat.obstime[0], location=obsparam['observatory_code']) n = 0 try: eph = obj.ephemerides() n = len(eph) except ValueError: if display and smallbody is True: print("'%s' is not a small body" % targetname) logging.warning("'%s' is not a small body" % targetname) if display and smallbody is False: print("'%s' is not a Solar System object" % targetname) logging.warning("'%s' is not a Solar System object" % targetname) pass if n > 0: is_asteroid = smallbody break # if is_asteroid is still None, this object is not in the Horizons db if is_asteroid is None: return objects message_shown = False # query information for each image for cat_idx, cat in enumerate(catalogs): targetname = cat.obj.replace('_', ' ') if man_targetname is not None: targetname = man_targetname.replace('_', ' ') cat.obj = targetname obj = Horizons(targetname.replace('_', ' '), id_type={True: 'smallbody', False: 'majorbody'}[is_asteroid], epochs=cat.obstime[0], location=obsparam['observatory_code']) try: eph = obj.ephemerides() n = len(eph) except ValueError: # if is_asteroid: # if display and not message_shown: # print 'is \'%s\' an asteroid?' % targetname # logging.warning('Target (%s) is not an asteroid' % targetname) # else: # if display and not message_shown: # print ('is \'%s\' a different Solar System object?' % # )targetname # logging.warning('Target (%s) is not a Solar System object' % # targetname) # n = None pass if n is None or n == 0: logging.warning('WARNING: No position from Horizons! ' + 'Name (%s) correct?' % cat.obj.replace('_', ' ')) logging.warning('HORIZONS call: %s' % obj.uri) if display and not message_shown: print(' no Horizons data for %s ' % cat.obj.replace('_', ' ')) message_shown = True else: objects.append({'ident': eph[0]['targetname'].replace(" ", "_"), 'obsdate.jd': cat.obstime[0], 'cat_idx': cat_idx, 'ra_deg': eph[0]['RA']-offset[0]/3600, 'dec_deg': eph[0]['DEC']-offset[1]/3600}) logging.info('Successfully grabbed Horizons position for %s ' % cat.obj.replace('_', ' ')) logging.info('HORIZONS call: %s' % obj.uri) if display and not message_shown: print(cat.obj.replace('_', ' '), "identified") message_shown = True return objects
def curve_of_growth_analysis(filenames, parameters, display=False, diagnostics=False): output = {} obsparam = parameters['obsparam'] logging.info('starting photometry with parameters: %s' % (', '.join([('%s: %s' % (var, str(val))) for var, val in list(locals().items())]))) # re-extract sources for curve-of-growth analysis aprads = parameters['aprad'] if not isinstance(aprads, list) and not isinstance(aprads, numpy.ndarray): print('need a list of aprads...') os.abort() logging.info('run pp_extract using %d apertures' % len(aprads)) print('* extract sources from %d images using %d apertures' % (len(filenames), len(aprads))) extractparameters = {'sex_snr': parameters['sex_snr'], 'source_minarea': parameters['source_minarea'], 'paramfile': _pp_conf.rootpath + '/setup/twentyapertures.sexparam', 'aprad': aprads, 'telescope': parameters['telescope'], 'quiet': False} extraction = pp_extract.extract_multiframe(filenames, extractparameters) extraction = [e for e in extraction if len(e) > 0] # curve-of-growth analysis # arrays for accumulating source information as a function of aprad background_flux = [] # numpy.zeros(len(aprads)) target_flux = [] # numpy.zeros(len(aprads)) background_snr = [] # numpy.zeros(len(aprads)) target_snr = [] # numpy.zeros(len(aprads)) for filename in filenames: if display: print('processing curve-of-growth for frame %s' % filename) if not parameters['background_only']: hdu = fits.open(filename, ignore_missing_end=True) # pull target coordinates from Horizons targetname = hdu[0].header[obsparam['object']] if parameters['manobjectname'] is not None: targetname = parameters['manobjectname'].translate( _pp_conf.target2filename) image = hdu[0].data # derive MIDTIMJD, if not yet in the FITS header obsparam = parameters['obsparam'] if not 'MIDTIMJD' in hdu[0].header: exptime = float(hdu[0].header[obsparam['exptime']]) if obsparam['date_keyword'].find('|') == -1: date = hdu[0].header[obsparam['date_keyword']] date = dateobs_to_jd(date) + exptime/2./86400. else: date_key = obsparam['date_keyword'].split('|')[0] time_key = obsparam['date_keyword'].split('|')[1] date = hdu[0].header[date_key]+'T' +\ hdu[0].header[time_key] date = dateobs_to_jd(date) + exptime/2./86400. else: date = hdu[0].header['MIDTIMJD'] # call HORIZONS to get target coordinates obj = Horizons(targetname.replace('_', ' '), epochs=date, location=str(obsparam['observatory_code'])) try: eph = obj.ephemerides() n = len(eph) except ValueError: print('Target (%s) not a small body' % targetname) logging.warning('Target (%s) not a small body' % targetname) n = None if n is None or n == 0: logging.warning('WARNING: No position from Horizons!' + 'Name (%s) correct?' % targetname) logging.warning('HORIZONS call: %s' % obj.uri) logging.info('proceeding with background sources analysis') parameters['background_only'] = True else: logging.info('ephemerides for %s pulled from Horizons' % targetname) target_ra, target_dec = eph[0]['RA'], eph[0]['DEC'] # pull data from LDAC file ldac_filename = filename[:filename.find('.fit')]+'.ldac' data = catalog('Sextractor_LDAC') data.read_ldac(ldac_filename, maxflag=3) if data.shape[0] == 0: continue # identify target and extract its curve-of-growth n_target_identified = 0 if not parameters['background_only']: residuals = numpy.sqrt((data['ra_deg']-target_ra)**2 + (data['dec_deg']-target_dec)**2) target_idx = numpy.argmin(residuals) if residuals[target_idx] > _pp_conf.pos_epsilon/3600: logging.warning(('WARNING: frame %s, large residual to ' + 'HORIZONS position of %s: %f arcsec; ' + 'ignore this frame') % (filename, targetname, residuals[numpy.argmin(residuals)]*3600.)) else: target_flux.append(data[target_idx]['FLUX_'+_pp_conf.photmode] / max(data[target_idx][ 'FLUX_'+_pp_conf.photmode])) target_snr.append( data[target_idx]['FLUX_'+_pp_conf.photmode] / data[target_idx]['FLUXERR_'+_pp_conf.photmode] / max(data[target_idx]['FLUX_'+_pp_conf.photmode] / data[target_idx]['FLUXERR_'+_pp_conf.photmode])) n_target_identified += 1 # extract background source fluxes and snrs # assume n_background_sources >> 1, do not reject target if not parameters['target_only']: # n_src = data.shape[0] # use all sources n_src = 50 # use only 50 sources for idx, src in enumerate(data.data[:n_src]): if (numpy.any(numpy.isnan(src['FLUX_'+_pp_conf.photmode])) or numpy.any(numpy.isnan(src['FLUXERR_'+_pp_conf.photmode])) or src['FLAGS'] > 3): continue # create growth curve background_flux.append(src['FLUX_'+_pp_conf.photmode] / max(src['FLUX_'+_pp_conf.photmode])) background_snr.append(src['FLUX_'+_pp_conf.photmode] / src['FLUXERR_'+_pp_conf.photmode] / max(src['FLUX_'+_pp_conf.photmode] / src['FLUXERR_'+_pp_conf.photmode])) # investigate curve-of-growth logging.info('investigate curve-of-growth based on %d frames' % len(filenames)) # combine results n_target = len(target_flux) if n_target > 0: target_flux = (numpy.median(target_flux, axis=0), numpy.std(target_flux, axis=0)/numpy.sqrt(n_target)) target_snr = numpy.median(target_snr, axis=0) else: target_flux = (numpy.zeros(len(aprads)), numpy.zeros(len(aprads))) target_snr = numpy.zeros(len(aprads)) n_background = len(background_flux) if n_background > 0: background_flux = (numpy.median(background_flux, axis=0), numpy.std(background_flux, axis=0) / numpy.sqrt(n_background)) background_snr = numpy.median(background_snr, axis=0) else: background_flux = (numpy.zeros(len(aprads)), numpy.zeros(len(aprads))) background_snr = numpy.zeros(len(aprads)) if n_target == 0: logging.info('No target fluxes available, using background sources, ' + 'only') parameters['background_only'] = True if n_background == 0: logging.info('No background fluxes available, using target, only') parameters['target_only'] = True # find optimum aperture radius if parameters['target_only']: aprad_strategy = 'smallest target aprad that meets fluxlimit criterion' optimum_aprad_idx = numpy.argmin(numpy.fabs(target_flux[0] - _pp_conf.fluxlimit_aprad)) elif parameters['background_only']: aprad_strategy = 'smallest background aprad that meets fluxlimit ' + \ 'criterion' optimum_aprad_idx = numpy.argmin(numpy.fabs(background_flux[0] - _pp_conf.fluxlimit_aprad)) else: # flux_select: indices where target+background fluxes > fluxlimit flux_select = numpy.where((target_flux[0] > _pp_conf.fluxlimit_aprad) & (background_flux[0] > _pp_conf.fluxlimit_aprad))[0] flux_res = numpy.fabs(target_flux[0][flux_select] - background_flux[0][flux_select]) if numpy.min(flux_res) < _pp_conf.fluxmargin_aprad: aprad_strategy = 'target+background fluxes > fluxlimit, ' + \ 'flux difference < margin' optimum_aprad_idx = flux_select[numpy.where(flux_res < _pp_conf.fluxmargin_aprad)[0][0]] else: aprad_strategy = 'target+background fluxes > fluxlimit, ' + \ 'flux difference minimal' optimum_aprad_idx = flux_select[numpy.argmin(flux_res)] optimum_aprad = parameters['aprad'][optimum_aprad_idx] output['aprad_strategy'] = aprad_strategy output['optimum_aprad'] = optimum_aprad output['pos_epsilon'] = _pp_conf.pos_epsilon output['fluxlimit_aprad'] = _pp_conf.fluxlimit_aprad output['fluxmargin_aprad'] = _pp_conf.fluxmargin_aprad output['n_target'] = len(target_flux[0]) output['n_bkg'] = len(background_flux[0]) output['target_flux'] = target_flux output['target_snr'] = target_snr output['background_flux'] = background_flux output['background_snr'] = background_snr output['parameters'] = parameters # write results to file outf = open('aperturephotometry_curveofgrowth.dat', 'w') outf.writelines('# background target flux\n' + '# rad flux sigma snr flux sigma snr residual\n') for i in range(len(parameters['aprad'])): outf.writelines(('%5.2f %5.3f %5.3f %4.2f %6.3f %5.3f %4.2f ' + '%6.3f\n') % (parameters['aprad'][i], background_flux[0][i], background_flux[1][i], background_snr[i], target_flux[0][i], target_flux[1][i], target_snr[i], target_flux[0][i]-background_flux[0][i])) outf.close() # extraction content # # -> see pp_extract.py # ### # output content # # { 'aprad_strategy' : optimum aperture finding strategy, # 'optimum_aprad' : optimum aperature radius, # 'pos_epsilon' : required positional uncertainty ("), # 'fluxlimit_aprad' : min flux for both target and background, # 'fluxmargin_aprad': max flux difference between target and background, # 'n_target' : number of frames with target flux measurements, # 'n_bkg' : number of frames with background measurements, # 'target_flux' : target fluxes as a function of aprad, # 'target_snr' : target snrs as a function of aprad, # 'background_flux' : background fluxes as a function of aprad, # 'background_snr' : background snrs as a function of aprad, # 'parameters' : source extractor parameters # } ### # diagnostics if diagnostics: if display: print('creating diagnostic output') logging.info(' ~~~~~~~~~ creating diagnostic output') diag.add_photometry(output, extraction) # update image headers for filename in filenames: hdu = fits.open(filename, mode='update', ignore_missing_end=True) hdu[0].header['APRAD'] = (optimum_aprad, 'aperture phot radius (px)') hdu[0].header['APIDX'] = (optimum_aprad_idx, 'optimum aprad index') hdu.flush() hdu.close() # display results if display: print('\n#################################### PHOTOMETRY SUMMARY:\n###') print('### best-fit aperture radius %5.2f (px)' % (optimum_aprad)) print('###\n#####################################################\n') logging.info('==> best-fit aperture radius: %3.1f (px)' % (optimum_aprad)) return output
def combine(filenames, obsparam, comoving, targetname, manual_rates, combine_method, keep_files, backsub=False, display=True, diagnostics=True): """ image combination wrapper output: diagnostic properties """ # start logging logging.info('starting image combination with parameters: %s' % (', '.join([('%s: %s' % (var, str(val))) for var, val in list(locals().items())]))) # check if images have been run through pp_prepare try: midtime_jd = fits.open(filenames[0], verify='silentfix', ignore_missing_end=True)[0].header['MIDTIMJD'] except KeyError: raise KeyError(('%s image header incomplete, have the data run ' + 'through pp_prepare?') % filenames[0]) return None # adopt first frame as reference frame hdulist = fits.open(filenames[0]) header = hdulist[0].header refdate = float(header['MIDTIMJD']) # read out ra and dec from header if obsparam['radec_separator'] == 'XXX': ref_ra_deg = float(header[obsparam['ra']]) ref_dec_deg = float(header[obsparam['dec']]) if obsparam['telescope_keyword'] == 'UKIRTWFCAM': ref_ra_deg = ref_ra_deg/24.*360. - 795/3600. ref_dec_deg -= 795/3600. else: ra_string = header[obsparam['ra']].split( obsparam['radec_separator']) dec_string = header[obsparam['dec']].split( obsparam['radec_separator']) ref_ra_deg = 15.*(float(ra_string[0]) + old_div(float(ra_string[1]), 60.) + old_div(float(ra_string[2]), 3600.)) ref_dec_deg = (abs(float(dec_string[0])) + old_div(float(dec_string[1]), 60.) + old_div(float(dec_string[2]), 3600.)) if dec_string[0].find('-') > -1: ref_dec_deg = -1 * ref_dec_deg if obsparam['telescope_keyword'] == 'UKIRTWFCAM': ref_ra_deg = ref_ra_deg/24.*360. if obsparam['telescope_keyword'] == "UKIRTWFCAM": ref_ra_deg -= float(header['TRAOFF'])/3600 ref_dec_deg -= float(header['TDECOFF'])/3600 hdulist.close() # modify individual frames if comoving == True if comoving: movingfilenames = [] # sort filenames by MIDTIMJD mjds = [] for filename in filenames: hdulist = fits.open(filename) mjds.append(float(hdulist[0].header['MIDTIMJD'])) filenames = [filenames[i] for i in numpy.argsort(mjds)] for filename in filenames: movingfilename = filename[:filename.find('.fits')]+'_moving.fits' print('shifting %s -> %s' % (filename, movingfilename)) logging.info('shifting %s -> %s' % (filename, movingfilename)) # read out date and pointing information hdulist = fits.open(filename) header = hdulist[0].header date = hdulist[0].header['MIDTIMJD'] data = hdulist[0].data hdulist.close() # use ephemerides from Horizons if no manual rates are provided if manual_rates is None: # call HORIZONS to get target coordinates obj = Horizons(targetname.replace('_', ' '), epochs=date, location=str(obsparam['observatory_code'])) try: eph = obj.ephemerides() n = len(eph) except ValueError: print('Target (%s) not an asteroid' % targetname) logging.warning('Target (%s) not an asteroid' % targetname) n = None if n is None or n == 0: logging.warning('WARNING: No position from Horizons!' + 'Name (%s) correct?' % targetname) logging.warning('HORIZONS call: %s' % eph.url) raise(ValueError, 'no Horizons ephemerides available') else: logging.info('ephemerides for %s pulled from Horizons' % targetname) logging.info('Horizons call: %s' % obj.uri) target_ra, target_dec = eph[0]['RA'], eph[0]['DEC'] # get image pointing from header if obsparam['radec_separator'] == 'XXX': ra_deg = float(header[obsparam['ra']]) dec_deg = float(header[obsparam['dec']]) if obsparam['telescope_keyword'] == 'UKIRTWFCAM': ra_deg = ra_deg/24.*360. - 795/3600. dec_deg -= 795/3600. else: ra_string = header[obsparam['ra']].split( obsparam['radec_separator']) dec_string = header[obsparam['dec']].split( obsparam['radec_separator']) ra_deg = 15.*(float(ra_string[0]) + old_div(float(ra_string[1]), 60.) + old_div(float(ra_string[2]), 3600.)) dec_deg = (abs(float(dec_string[0])) + old_div(float(dec_string[1]), 60.) + old_div(float(dec_string[2]), 3600.)) if dec_string[0].find('-') > -1: dec_deg = -1 * dec_deg if filename == filenames[0]: ref_offset_ra = target_ra - ref_ra_deg ref_offset_dec = target_dec - ref_dec_deg offset_ra = target_ra - ref_ra_deg - ref_offset_ra offset_dec = target_dec - ref_dec_deg - ref_offset_dec else: # use manual rates (since they are provided) offset_ra = ((float(header['MIDTIMJD'])-refdate)*86400 * float(manual_rates[0]))/3600 offset_dec = ((float(header['MIDTIMJD'])-refdate)*86400 * float(manual_rates[1]))/3600 logging.info('offsets in RA and Dec: %f, %f arcsec' % (offset_ra*3600, offset_dec*3600)) crval1 = float(header['CRVAL1']) crval2 = float(header['CRVAL2']) # write new CRVALi keywords in different file new_hdu = fits.PrimaryHDU(data) new_hdu.header = header new_hdu.header['CRVAL1'] = (crval1-offset_ra, 'updated in the moving frame of the object') new_hdu.header['CRVAL2'] = (crval2-offset_dec, 'updated in the moving frame of the object') movingfilenames.append(movingfilename) new_hdu.writeto(movingfilename, overwrite=True, output_verify='silentfix') if comoving: outfile_name = 'comove.fits' fileline = " ".join(movingfilenames) n_frames = len(movingfilenames) else: outfile_name = 'skycoadd.fits' fileline = " ".join(filenames) n_frames = len(filenames) # run swarp on all image catalogs using different catalogs commandline = (('swarp -combine Y -combine_type %s -delete_tmpfiles ' + 'Y -imageout_name %s -interpolate Y -subtract_back %s ' + '-weight_type NONE -copy_keywords %s -write_xml N ' + '-CENTER_TYPE MOST %s') % ({'median': 'MEDIAN', 'average': 'AVERAGE', 'clipped': 'CLIPPED -CLIP_AMPFRAC 0.2 -CLIP_SIGMA 0.1 '} [combine_method], outfile_name, {True: 'Y', False: 'N'}[backsub], obsparam['copy_keywords'], fileline)) logging.info('call SWARP as: %s' % commandline) print('running SWARP to combine {:d} frames...'.format(n_frames)) try: swarp = subprocess.Popen(shlex.split(commandline), stdout=DEVNULL, stderr=DEVNULL, close_fds=True) # do not direct stdout to subprocess.PIPE: # for large FITS files, PIPE will clog, stalling # subprocess.Popen except Exception as e: print('SWARP call:', (e)) logging.error('SWARP call:', (e)) return None swarp.wait() print('done!') # remove files that are not needed anymore if not keep_files: if comoving: for filename in movingfilenames: os.remove(filename) # update combined image header total_exptime = 0 for filename in filenames: hdulist = fits.open(filename) total_exptime += float(hdulist[0].header[obsparam['exptime']]) hdulist = fits.open(outfile_name, mode='update') hdulist[0].header[obsparam['exptime']] = (total_exptime, 'PP: cumulative') hdulist[0].header['COMBO_N'] = (len(filenames), 'PP: N files combo') hdulist[0].header['COMBO_M'] = (combine_method, 'PP: combo method') hdulist[0].header['COMOVE'] = (str(comoving), 'PP: comoving?') hdulist.flush() return n_frames