def test_pyephem(): """ test PyEphem interface, if PyEphem is available """ try: import ephem except ImportError: return None asteroid_targetname = 'Ceres' target = callhorizons.query(asteroid_targetname) target.set_discreteepochs([2451544.500000]) # create pyephem object and calculate ra and dec for a given date ephobj = target.export2pyephem()[0] ephobj.compute('2000-01-10') # retrieve astrometric geocentric coordinates ephem_ra = np.rad2deg(ephobj.a_ra) ephem_dec = np.rad2deg(ephobj.a_dec) ephem_mag = ephobj.mag # query horizons for exact positions and check if residuals are negligible # i.e., less than 0.5 arcsec target = callhorizons.query(asteroid_targetname) target.set_discreteepochs([2451553.5]) target.get_ephemerides(500) assert ((target['RA'][0] - ephem_ra) * 3600) < 0.1 assert ((target['DEC'][0] - ephem_dec) * 3600) < 0.1 assert (target['V'][0] - ephem_mag) < 0.1
def COMproperties(Des): try: try: q = callhorizons.query(Des) UTC = datetime.datetime.utcnow() Year = UTC.year Month = UTC.month Day = UTC.day + int(UTC.hour/24) + int(UTC.minute/1440) + int(UTC.second/86400) Epoch = gregToJD((Year, Month, Day)) q.set_discreteepochs(str(Epoch)) q.get_elements() web = q.url except: try: DesParts = Des.split(" ") if len(Des) != 1: Des = DesParts[0] + " " + DesParts[1] q = callhorizons.query(Des) UTC = datetime.datetime.utcnow() Year = UTC.year Month = UTC.month Day = UTC.day + int(UTC.hour/24) + int(UTC.minute/1440) + int(UTC.second/86400) Epoch = gregToJD((Year, Month, Day)) q.set_discreteepochs(str(Epoch)) q.get_elements() web = q.url else: DesParts = Des.split("/") Des = DesParts[0] + " " + DesParts[1] q = callhorizons.query(Des) UTC = datetime.datetime.utcnow() Year = UTC.year Month = UTC.month Day = UTC.day + int(UTC.hour/24) + int(UTC.minute/1440) + int(UTC.second/86400) Epoch = gregToJD((Year, Month, Day)) q.set_discreteepochs(str(Epoch)) q.get_elements() web = q.url except: print("error") return "n.a.", "n.a." req = request.urlopen(web) data = req.read().decode("utf-8") req.close() GMloc = data.find(" GM=") for i in range(7, 30): GM = data[GMloc + 6: GMloc + i] if GM[-1] == " ": RAD = data[GMloc + 6: GMloc + i - 1] break RADloc = data.find(" RAD=") for i in range(8, 30): RAD = data[RADloc + 7: RADloc + i] if RAD[-1] == " ": RAD = data[RADloc + 7: RADloc + i - 1] break return GM.strip(" "), RAD.strip(" ") except: return "n.a.", "n.a."
def solSys(Des): try: time.sleep(1) q = callhorizons.query(int(SolarSystem[Des]), smallbody=False) UTC = datetime.datetime.utcnow() Year = UTC.year Month = UTC.month Day = UTC.day + float(UTC.hour/24) + float(UTC.minute/1440) + float(UTC.second/86400) Epoch = gregToJD((Year, Month, Day)) Type = "Major Planet" Parent = "Sol" q.set_discreteepochs(str(Epoch)) q.get_elements() a = q["a"][0] e = q["e"][0] i = q["incl"][0] AoP = q["argper"][0] LoAN = q["node"][0] MA = q["meananomaly"][0] MA = str(MAcheck(float(MA))) if extra == True: GM, RAD, ROTPER, OBL, RA = SSproperties(Des) datalist = (Des, Type, Parent, a, e, i, AoP, LoAN, Epoch, MA, GM, RAD, ROTPER, OBL) else: datalist = (Des, Type, Parent, a, e, i, AoP, LoAN, Epoch, MA) DataStruct = (("%s,"*len(datalist))[0:-1] + "\n")%datalist output = open("OutputO.txt", "a", newline='\r\n') output.write(DataStruct) output.close() infoOut = "\rGathering Planet Data " + Des + " " print(infoOut, end = "") except: time.sleep(5) solSys(Des)
def test_elements(): """ check orbital elements output for one moon """ moon_targetname = 501 target = callhorizons.query(moon_targetname, smallbody=False) target.set_epochrange('2000-01-01', '2000-01-02', '1d') target.get_elements('500@5') # elements relative to Jupiter barycenter # compare all query results to values taken directly from Horizons # queried on Nov 6, 2016 assert target['targetname'][0] == 'Io (501)' assert np.isnan(target['H'][0]) assert np.isnan(target['G'][0]) assert target['datetime_jd'][0] == 2451544.5 assert target['e'][0] == 0.003654784965339888 assert target['p'][0] == 2.811473523687107E-03 assert target['a'][0] == 2.821786546733507E-03 assert target['incl'][0] == 2.212609179741271E+00 assert target['node'][0] == 3.368501231726219E+02 assert target['argper'][0] == 6.218469675691234E+01 assert target['Tp'][0] == 2451545.103514090180 assert target['meananomaly'][0] == 2.373891296290639E+02 assert target['trueanomaly'][0] == 2.370372158041970E+02 assert target['period'][0] == 1.771988665071993 / 365.256 assert target['Q'][0] == 2.832099569779908E-03
def get_target_ephemeris(desg, start_date, end_date, smallbody=True): """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. """ from urllib.request import urlopen try: import callhorizons except ImportError: print("The callhorizons module cannot be loaded. It is required for moving targets.") sys.exit(1) # cap: current apparition (for comets) q = callhorizons.query(desg, smallbody=smallbody, cap=True) q.set_epochrange(start_date, end_date, '1d') # 1 day step size try: n = q.get_ephemerides('@jwst') except ValueError as e: with urlopen(q.url) as horizons: err = horizons.read().decode() raise ValueError('Error retrieving ephemeris for "{}". URL: {}\n{}'.format(desg, q.url, err)) return q['targetname'][0], q['RA'], q['DEC']
def ecliptic_RADEC_horizons(discrete_epoch=None, start_epoch=None, stop_epoch=None, step_size=None, alpha_sort=True): ''' Queries the exact RA DEC of the ecliptic plane for given time. Parameters ---------- alpha_sort : bool, optional Wether to sort the output RA and DEC based on the RA. ''' is_discrete = True if discrete_epoch is None: if (start_epoch is None) ^ (stop_epoch is None) ^ (step_size is None): raise ValueError( 'If discrete_epoch is not given, all others must be given.') dq = callhorizons.query('sun', smallbody=False) if is_discrete: dq.set_discreteepochs(discrete_epoch) else: dq.set_epochrange(start_epoch, stop_epoch, step_size) dq.get_ephemerides(500) # TODO: There must be a better way to achieve this... ra, dec = dq['RA'], dq['DEC'] if alpha_sort: sort_idx = ra.argsort() ra, dec = ra[sort_idx], dec[sort_idx] return ra, dec
def test_designations(): """Test comet and asteroid name to designation transformations.""" # name: expected result comets = { '1P/Halley': '1P', '3D/Biela': '3D', '9P/Tempel 1': '9P', '73P/Schwassmann Wachmann 3 C': '73P', # Note the missing "C"! '73P-C/Schwassmann Wachmann 3 C': '73P-C', '73P-BB': '73P-BB', '322P': '322P', 'X/1106 C1': 'X/1106 C1', 'P/1994 N2 (McNaught-Hartley)': 'P/1994 N2', 'P/2001 YX127 (LINEAR)': 'P/2001 YX127', 'C/-146 P1': 'C/-146 P1', 'C/2001 A2-A (LINEAR)': 'C/2001 A2-A', 'C/2013 US10': 'C/2013 US10', 'C/2015 V2 (Johnson)': 'C/2015 V2', } asteroids = { '1': '1', '(2) Pallas': '2', '(2001) Einstein': '2001', '2001 AT1': '2001 AT1', '(1714) Sy': '1714', '1714 SY': '1714 SY', # not real; note pot. confusion with prev. item '2014 MU69': '2014 MU69', '2017 AA': '2017 AA', } for comet, des in comets.items(): q = callhorizons.query(comet, smallbody=True) _des = q.parse_comet() assert _des == des, 'Parsed {}: {} != {}'.format(comet, _des, des) for asteroid, des in asteroids.items(): q = callhorizons.query(asteroid, smallbody=True) _des = q.parse_asteroid() assert _des == des, 'Parsed {}: {} != {}'.format(asteroid, _des, des)
def __getitem__(self, name): if name not in self.satellites: q = callhorizons.query(name, smallbody=False) q.set_discreteepochs(ephem.julian_date(self.epoch)) try: sats = q.export2pyephem() except ValueError as e: if e.message.startswith('Unknown target'): raise KeyError('%s not found in %s' % (name, repr(self))) raise self.satellites[name] = sats[0] return self.satellites[name]
def __getitem__(self, name): if name not in self.satellites: q = callhorizons.query(name, smallbody=False) q.set_discreteepochs(ephem.julian_date(self.epoch)) try: sats = q.export2pyephem() except ValueError as e: if e.message.startswith('Unknown target'): raise KeyError('%s not found in %s' % (name, repr(self))) raise self.satellites[name] = sats[0] return self.satellites[name]
def test_ephemerides(): """ check ephemerides output for one asteroid """ asteroid_targetname = 'Ceres' target = callhorizons.query(asteroid_targetname) target.set_discreteepochs([2451544.500000]) target.get_ephemerides(568) # compare all query results to values taken directly from Horizons # queried on Nov 6, 2016 assert target['targetname'][0] == u'1 Ceres', target['targetname'][0] assert agrees(target['H'][0], 3.34), target['H'][0] assert agrees(target['G'][0], 0.12), target['G'][0] assert target['datetime'][0] == u'2000-Jan-01 00:00:00.000', \ target['datetime'][0] assert agrees(target['datetime_jd'][0], 2451544.5), target['datetime_jd'][0] assert target['solar_presence'][0] == 'daylight', \ target['solar_presence'][0] assert target['lunar_presence'][0] == 'dark', target['lunar_presence'][0] assert agrees(target['RA'][0], 188.70187), target['RA'][0] assert agrees(target['DEC'][0], 9.09786), target['DEC'][0] assert agrees(target['RA_rate'][0], 0.00967404166667), target['RA_rate'][0] assert agrees(target['DEC_rate'][0], -2.82060 / 3600), target['DEC_rate'][0] assert agrees(target['AZ'][0], 288.3275), target['AZ'][0] assert agrees(target['EL'][0], -20.5230), target['EL'][0] assert np.isnan(target['airmass'][0]) assert np.isnan(target['magextinct'][0]) assert agrees(target['V'][0], 8.27), target['V'][0] assert agrees(target['illumination'][0], 96.171), target['illumination'][0] assert agrees(target['EclLon'][0], 161.3828), target['EclLon'][0] assert agrees(target['EclLat'][0], 10.4528), target['EclLat'][0] assert agrees(target['r'][0], 2.551098889601), target['r'][0] assert agrees(target['r_rate'][0], 0.1744499), target['r_rate'][0] assert agrees(target['delta'][0], 2.26316614786857), target['delta'][0] assert agrees(target['delta_rate'][0], -21.5499080), target['delta_rate'][0] assert agrees(target['lighttime'][0], 18.822179 * 60), target['lighttime'][0] assert agrees(target['elong'][0], 95.3997), target['elong'][0] assert target['elongFlag'][0] == u'leading', target['elongFlag'][0] assert agrees(target['alpha'][0], 22.5690), target['alpha'][0] assert agrees(target['sunTargetPA'][0], 292.552), target['sunTargetPA'][0] assert agrees(target['velocityPA'][0], 296.849), target['velocityPA'][0] assert agrees(target['GlxLon'][0], 289.861684), target['GlxLon'][0] assert agrees(target['GlxLat'][0], 71.545053), target['GlxLat'][0] assert agrees(target['RA_3sigma'][0], 0.0), target['RA_3sigma'][0] assert agrees(target['DEC_3sigma'][0], 0.0), target['DEC_3sigma'][0]
def test_comet(): """Test CAP and orbit record numbers for a comet.""" # test failure when multiple orbital solutions are available target = callhorizons.query('9P', cap=False) target.set_discreteepochs([2451544.500000]) try: target.get_ephemerides('G37') except ValueError as e: assert 'Ambiguous target name' in str(e) else: raise # switch to current ephemeris, this should be successful target.cap = True target.get_ephemerides('G37') assert len(target) == 1 # Test orbit record number, note that NAIF may change these at any time. target = callhorizons.query('900191') target.set_discreteepochs([2451544.500000]) target.get_ephemerides('G37') assert len(target) == 1
def query(self, depoch=100, smallbody=True, cap=True, comet=False, asteroid=False, airmass_lessthan=99, solar_elongation=(0, 180), skip_daylight=False): ''' Parameters ---------- depoch: int, optional The number of discrete epochs to be chopped. This is needed because the HORIZONS query does not accept infinitely many epochs at one time. I guess ~ 600 epochs are maximum we can query at a time. Note ---- Other parameters are explained in ``callhorizons`` manual v 1.0.11. ''' # TODO: add ``comet`` and ``asteroid`` to ``callhorizons.query`` if depoch > 100: Warning('If query for more than about 100 epochs, ' 'HORIZONS sometimes does not work correctly.') Nepoch = np.shape(self.discreteepochs)[0] Nquery = (Nepoch - 1) // depoch + 1 tabs = [] print(f'Query: {self.targetname} at {self.observatory_code} for {Nepoch} epochs') for i in range(Nquery): if Nquery != 1: print(f"Querying {i+1} / {Nquery} batch.") dq = callhorizons.query(self.targetname, smallbody=smallbody, cap=cap) # TODO: add comet and asteroids to ``callhorizons.query`` dq.set_discreteepochs(self.discreteepochs[i * depoch:(i + 1) * depoch]) dq.get_ephemerides(self.observatory_code, airmass_lessthan=airmass_lessthan, solar_elongation=solar_elongation, skip_daylight=skip_daylight) tabs.append(Table(dq.data)) if len(tabs) == 1: self.query_table = tabs[0] elif len(tabs) > 1: self.query_table = vstack(tabs) print("Query done.")
def test_ephemerides(): """ check ephemerides output for one asteroid """ asteroid_targetname = 'Ceres' target = callhorizons.query(asteroid_targetname) target.set_discreteepochs([2451544.500000]) target.get_ephemerides(568) # compare all query results to values taken directly from Horizons # queried on Nov 6, 2016 assert target['targetname'][0] == u'1 Ceres' assert target['H'][0] == 3.34 assert target['G'][0] == 0.12 assert target['datetime'][0] == u'2000-Jan-01 00:00:00.000' assert target['datetime_jd'][0] == 2451544.5 assert target['solar_presence'][0] == 'daylight' assert target['lunar_presence'][0] == 'dark' assert target['RA'][0] == 188.70188 assert target['DEC'][0] == 9.09786 assert target['RA_rate'][0] == 34.82656 / 3600 assert target['DEC_rate'][0] == -2.82060 / 3600 assert target['AZ'][0] == 288.3275 assert target['EL'][0] == -20.5230 assert np.isnan(target['airmass'][0]) assert np.isnan(target['magextinct'][0]) assert target['V'][0] == 8.27 assert target['illumination'][0] == 96.171 assert target['EclLon'][0] == 161.3828 assert target['EclLat'][0] == 10.4528 assert target['r'][0] == 2.551098889601 assert target['r_rate'][0] == 0.1744499 assert target['delta'][0] == 2.26316614786857 assert target['delta_rate'][0] == -21.5499080 assert target['lighttime'][0] == 18.822179 * 60 assert target['elong'][0] == 95.3997 assert target['elongFlag'][0] == u'leading' assert target['alpha'][0] == 22.5690 assert target['sunTargetPA'][0] == 292.552 assert target['velocityPA'][0] == 296.849 assert target['GlxLon'][0] == 289.861684 assert target['GlxLat'][0] == 71.545053 assert target['RA_3sigma'][0] == 0.058 assert target['DEC_3sigma'][0] == 0.05
def get_ephemeris(self, obs): """Get the comet ephemeris from JPL/HORIZONS.""" import logging from astropy.coordinates import SkyCoord import callhorizons from . import lco logger = logging.getLogger('tgk.science') logger.debug(' Get geometry from HORIZONS.') q = callhorizons.query('41P') q.set_discreteepochs([obs.time.jd]) obs_code = lco.mpc_codes[(obs.site[0], obs.enclosure[0], obs.telescope[0])] n = q.get_ephemerides(obs_code) if n != 1: raise EphemerisError( 'Bad return from JPL/HORIZONS, check URL: {}'.format(q.url)) self._horizons_query = q
def main(name, fromdate, todate, obscode=568, spacing='1h'): log.debug(f'Querying horizons for: "{name}"') target = callhorizons.query(name) fromstr = fromdate.strftime('%Y-%m-%d %H:%M') tostr = todate.strftime('%Y-%m-%d %H:%M') log.debug(f' From: "{fromstr}"') log.debug(f' To: "{tostr}"') log.debug(f' Increment: "{spacing}"') target.set_epochrange(fromstr, tostr, spacing) try: target.get_ephemerides(obscode) except ValueError as e: log.error("Failed to get ephemerides") print(e.args[0]) tab = Table(target.data) if len(tab) == 0: log.error("ephemerides have zero length") name = name.replace("/", "") name = name.replace(" ", "_") wasup = True for entry in tab: time = (entry['datetime'].split(' ')[1]).replace(':', '') starlistname = f'{name[0:9]:s}_{time:s}' if np.isnan(float(entry['airmass'])) == True: if wasup == True: print(f"# Target {name} is down at {time}") wasup = False else: line = [f'{starlistname:15s}'] coord = SkyCoord(entry['RA'], entry['DEC'], frame='fk5', unit=(u.deg, u.deg)) line.append(f'{coord.to_string("hmsdms", sep=" ", precision=2)}') line.append(f'{coord.equinox.jyear:.2f}') line.append(f'dra={float(entry["RA_rate"])/15*3600:.3f}') line.append(f'ddec={float(entry["DEC_rate"])*3600:.3f}') line.append(f'vmag={float(entry["V"]):.2f}') line.append(f'# airmass={float(entry["airmass"]):.2f}') print(' '.join(line))
def get_lighttime_correction(analysis): jd = get_jd_for_analysis(analysis) q = callhorizons.query(analysis.lightcurve.target_name) q.set_discreteepochs(jd) # TODO(ian): Allow user to set observatory code, or choose the one closest # to them. https://www.minorplanetcenter.net/iau/lists/ObsCodesF.html # Currently defaulting to Greenwich. q.get_ephemerides(0) if 'lighttime' not in q.fields: logger.warn('Could not look up lighttime for target %s. Got %s' % \ (analysis.lightcurve.target_name, q.fields)) return None sec = q['lighttime'][0] adjusted_dt = analysis.image_datetime - timedelta(seconds=sec) ret = Time(adjusted_dt).jd logger.info('Applied lighttime correction of %f sec to target %s: %f -> %f' % \ (sec, analysis.lightcurve.target_name, jd, ret)) return ret
def main(name, fromdate, todate, obscode=568, spacing='1h'): log.debug(f'Querying horizons for: "{name}"') target = callhorizons.query(name) fromstr = fromdate.strftime('%Y-%m-%d %H:%M') tostr = todate.strftime('%Y-%m-%d %H:%M') log.debug(f' From: "{fromstr}"') log.debug(f' To: "{tostr}"') log.debug(f' Increment: "{spacing}"') target.set_epochrange(fromstr, tostr, spacing) try: target.get_ephemerides(obscode) except ValueError as e: log.error("Failed to get ephemerides") print(e.args[0]) tab = Table(target.data) if len(tab) == 0: log.error("ephemerides have zero length") name = name.replace("/", "") name = name.replace(" ", "_") wasup = True for entry in tab: time = (entry['datetime'].split(' ')[1]).replace(':', '') starlistname = f'{name[0:9]:s}_{time:s}' if np.isnan(float(entry['airmass'])) == True: if wasup == True: print(f"# Target {name} is down at {time}") wasup = False else: line = [f'{starlistname:15s}'] coord = SkyCoord(entry['RA'], entry['DEC'], frame='fk5', unit=(u.deg, u.deg)) line.append(f'{coord.to_string("hmsdms", sep=" ", precision=2)}') line.append(f'{coord.equinox.jyear:.2f}') line.append(f'dra={float(entry["RA_rate"])/15*3600:.3f}') line.append(f'ddec={float(entry["DEC_rate"])*3600:.3f}') line.append(f'vmag={float(entry["V"]):.2f}') line.append(f'# airmass={float(entry["airmass"]):.2f}') print(' '.join(line))
#use the callhorizons env to run, ie: #(C:\Users\paul.egan1\AppData\Local\Continuum\Miniconda3) C:\Users\paul.egan1>activate callhorizons firstJan2050 = 2469807.5 #from http://www.onlineconversion.com/julian_date.htm import callhorizons saturn = callhorizons.query('699', smallbody=False) #saturn.set_discreteepochs('2451234.5') saturn.set_discreteepochs(firstJan2050) saturn.get_elements() for fieldName in saturn.fields: print(fieldName, saturn[fieldName])
#where is the asteroid going to be at the *midpoint* of the exposure? #first, calculate the *time* of the *midpoint* of the exposure: t = now + t_pointing (in sec) + t_exposure/2 (in sec) #second, calculate the RA/DEC of the target at *that* time using JPL Horizons (via callhorizons) start = datetime.datetime.utcnow() start += datetime.timedelta(seconds=t_pointing) start += datetime.timedelta(seconds=t_exposure / 2.0) #JPL Horizons requires start *and* end times where end > start (by at least 1 minute!) end = start + datetime.timedelta(seconds=60) #print start, end #get ephemerides for target in JPL Horizons from start to end times #assume it is a small body, e.g. asteroid or comet! #slackdebug('Calculating position of target (%s) at %s...'%(target, start.strftime("%Y/%m/%d %H:%M:%S"))) ch = callhorizons.query(target.upper(), smallbody=True) ch.set_epochrange(start.strftime("%Y/%m/%d %H:%M:%S"), end.strftime("%Y/%m/%d %H:%M:%S"), '1m') ch.get_ephemerides(observatory) #check results if len(ch) == 2: logger.debug('name=%s,dt=%s,RA=%s,DEC=%s,EL=%s,AZ=%s' % (ch['targetname'][0], ch['datetime'][0], ch['RA'][0], ch['DEC'][0], ch['EL'][0], ch['AZ'][0])) else: logger.error('Error. Could not obtain ephemerides for target (%s).' % target) os.sys.exit(1) #ensure tracking is on, tx track on
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]: eph = callhorizons.query(targetname, smallbody=smallbody) #eph = callhorizons.query(targetname, smallbody=False) eph.set_discreteepochs(cat.obstime[0]) n = 0 try: n = eph.get_ephemerides(obsparam['observatory_code']) except ValueError: if display and smallbody is True: print("'%s' is not an asteroid" % targetname) logging.warning("'%s' is not an asteroid" % 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 eph = callhorizons.query(targetname, smallbody=is_asteroid) #eph = callhorizons.query(targetname, smallbody=False) eph.set_discreteepochs(cat.obstime[0]) try: n = eph.get_ephemerides(obsparam['observatory_code']) 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' % eph.url) 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'] - old_div(offset[0], 3600.), 'dec.deg': eph[0]['DEC'] - old_div(offset[1], 3600.) }) logging.info('Successfully grabbed Horizons position for %s ' % cat.obj.replace('_', ' ')) logging.info('HORIZONS call: %s' % eph.url) if display and not message_shown: print(cat.obj.replace('_', ' '), "identified") message_shown = True return objects
def combine(filenames, obsparam, comoving, targetname, manual_rates, combine_method, keep_files, 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 eph = callhorizons.query(targetname) eph.set_discreteepochs(date) try: n = eph.get_ephemerides(str(obsparam['observatory_code'])) 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' % eph.query) 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 N '+ '-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, 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
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 eph = callhorizons.query(targetname.replace('_', ' ')) eph.set_discreteepochs(date) try: n = eph.get_ephemerides(str(obsparam['observatory_code'])) 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) 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) # 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] > old_div(_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( old_div(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( old_div( 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( old_div(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( old_div(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), old_div(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), old_div(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(_pp_conf.diagroot + '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: diag.add_photometry(output, extraction) pass # 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
#!/usr/bin/python # -*- coding: iso-8859-15 -*- import callhorizons if __name__=='__main__': dq = callhorizons.query('-125544', smallbody=False) dq.set_epochrange('2016-12-04 18:40', '2016-12-04 19:10', '1m') po=dq.get_ephemerides('J20') #print dq.fields #print dq.query print "DATE,RA,DEC" for i in range(po): print dq['datetime'][i],",",dq['RA'][i],",",dq['DEC'][i],dq['delta'][i]
def test_designations(): """Test comet and asteroid name to designation transformations.""" # name: expected result comets = { '1P/Halley': (None, '1P', 'Halley'), '3D/Biela': (None, '3D', 'Biela'), '9P/Tempel 1': (None, '9P', 'Tempel 1'), '73P/Schwassmann Wachmann 3 C': (None, '73P', 'Schwassmann Wachmann 3 C'), '73P-C/Schwassmann Wachmann 3 C': (None, '73P-C', 'Schwassmann Wachmann 3 C'), '73P-BB': (None, '73P-BB', None), '322P': (None, '322P', None), 'X/1106 C1': ('1106 C1', 'X', None), 'P/1994 N2 (McNaught-Hartley)': ('1994 N2', 'P', 'McNaught-Hartley'), 'P/2001 YX127 (LINEAR)': ('2001 YX127', 'P', 'LINEAR'), 'C/-146 P1': ('-146 P1', 'C', None), 'C/2001 A2-A (LINEAR)': ('2001 A2-A', 'C', 'LINEAR'), 'C/2013 US10': ('2013 US10', 'C', None), 'C/2015 V2 (Johnson)': ('2015 V2', 'C', 'Johnson'), 'C/2016 KA (Catalina)': ('2016 KA', 'C', 'Catalina') } asteroids = { '1': (None, 1, None), '(2) Pallas': (None, 2, 'Pallas'), '(2001) Einstein': (None, 2001, 'Einstein'), '2001 AT1': ('2001 AT1', None, None), '(1714) Sy': (None, 1714, 'Sy'), '1714 SY': ('1714 SY', None, None), # not real, just for testing '2014 MU69': ('2014 MU69', None, None), '(228195) 6675 P-L': ('6675 P-L', 228195, None), '4101 T-3': ('4101 T-3', None, None), '4015 Wilson-Harrington (1979 VA)': ('1979 VA', 4015, 'Wilson-Harrington'), 'J95X00A': ('1995 XA', None, None), 'K07Tf8A': ('2007 TA418', None, None), 'G3693': (None, 163693, None), '2017 U1': (None, None, None) } for comet, des in comets.items(): q = callhorizons.query(comet, smallbody=True) _ident = q.parse_comet() assert _ident[0] == des[0], 'Parsed {}: {} != {}'.format( comet, _ident[0], des[0]) assert _ident[1] == des[1], 'Parsed {}: {} != {}'.format( comet, _ident[1], des[1]) assert _ident[2] == des[2], 'Parsed {}: {} != {}'.format( comet, _ident[2], des[2]) for asteroid, des in asteroids.items(): q = callhorizons.query(asteroid, smallbody=True) _ident = q.parse_asteroid() assert _ident[0] == des[0], 'Parsed {}: {} != {}'.format( asteroid, _ident[0], des[0]) assert _ident[1] == des[1], 'Parsed {}: {} != {}'.format( asteroid, _ident[1], des[1]) assert _ident[2] == des[2], 'Parsed {}: {} != {}'.format( asteroid, _ident[2], des[2])
print (julian) print ('Created Julian Dates') time.sleep(.5) print ('Parsing Times') parsed = parser.parse(fTime) parsed1 = parser.parse(fOneTime) #un-parsing time.sleep(.5) startTime = parsed.strftime('%Y-%m-%d %H:%M:%S') endTime = parsed1.strftime('%Y-%m-%d %H:%M:%S') print ('Start Observation Time : '+ startTime) print ('End Observation Time : '+ endTime) print ('Talking to Solar System Dynamics Group, Jet Propulsion Laboratory Pasadena CA 91109 USA') elements = callhorizons.query(asteroidName) elements.set_discreteepochs(julianList) elements.get_ephemerides(obsCode) #uncomment the next line if you are having a problem with this part of the code and go to the link printed in the command line or terminal #print (elements.query) time.sleep(1) RA = elements['RA'] DEC = elements['DEC'] time.sleep(1) print ('Generating Epheris') print ('-------Epheris-------') print (RA) print (DEC) print ('-------Epheris-------')
print(" between ", start_time, " to ", end_time, " (local)") print(" with a limiting V magnitude of ", mag_lim, ".") print("") print("* Objects checked (of %d): " % (num_rot), end="") # Retrieve data on each fast rotating asteroid and convert to pyephem data for manipulation num_found = 0 # Number of observable fast rotating asteroids found for i in range(num_rot): # print(" * Checking ", fast_rotators_name[i], " (asteroid ", i + 1, " of ", num_rot, ")") if i % 25 == 0: print("%d.." % i, end="") sys.stdout.flush() # The following line FAILS in Python 3.5 with a # AttributeError: module 'callhorizons' has no attribute 'query' fast_rot_cand = callhorizons.query(fast_rotators_recnum[i]) fast_rot_cand.set_epochrange(start_time, end_time, '1h') # lines = fast_rot_cand.get_ephemerides(730) # Get info for UND obs. code # print('Number of lines of ephemeris retrieved: ', lines) fast_rot_cand_pyephem = fast_rot_cand.export2pyephem() aster = fast_rot_cand_pyephem[0] # Check visibility at Feder feder.date = ephem.date(start_of_Obs) end = ephem.date(end_of_Obs) minutes_visible = 0 maxmag = 0 minairmass = 20 while feder.date < end: aster.compute(feder) # Only consider it observable if airmass is < 3