def __init__(self, observations, ast_filename=None, abg_filename=None): if observations is None: try: self.orbit = orbfit.Orbfit(None, ast_filename, abg_filename) self.name = os.path.basename(ast_filename).split('.')[0] except Exception as ex: logging.error("Failed to compute orbit using inputs {}".format( ast_filename)) raise ex else: self.orbit = orbfit.Orbfit(observations.mpc_observations, ast_filename, abg_filename) try: # Previously discovered objects can have 'discovery-marked' lines that predate the OSSOS survey. discoveries = [ n for n in observations.mpc_observations if (n.discovery.is_discovery and n.date > parameters.SURVEY_START) ] # Some objects were linked to independent OSSOS-observed triples; these are also multiply 'discovery-marked' if len(discoveries) > 1: discoveries.sort(key=lambda x: x.date) # once sorted and restricted to within the survey timeframe, it's always the earliest such marked line. self.discovery = discoveries[0] except Exception as ex: self.discovery = False self.name = observations[0].provisional_name.rstrip( '.ast').split('.')[0] self.mag = None for observation in self.orbit.observations: if observation.mag is not None: self.mag = (self.mag is None or self.mag < observation.mag ) and observation.mag or self.mag
def plot_prediction(ax, obj): ra = [] dec = [] start = Time(parameters.SURVEY_START) # min([d.date for d in obj.mpc_observations]) - TimeDelta(90, format='jd') end = Time('2016-01-01') date = start orbit = orbfit.Orbfit(obj.mpc_observations) while date < end: orbit.predict(date) ra.append(orbit.coordinate.ra.degree) dec.append(orbit.coordinate.dec.degree) date = date + TimeDelta(10, format='jd') ax.plot(ra, dec, 'r-', linewidth=0.6) # some labels for different times orbit.predict(start) ax.annotate(parameters.SURVEY_START, (orbit.coordinate.ra.degree - 0.1, orbit.coordinate.dec.degree), size=7, color='k') orbit.predict(end) ax.annotate(end.datetime.strftime('%Y-%m-%d'), (orbit.coordinate.ra.degree - 0.1, orbit.coordinate.dec.degree), size=7, color='k') return ax
def build_summary_plot(mpc_obs): orbit = orbfit.Orbfit(mpc_obs) residuals = orbit.residuals mags = [] errs = [] ras = [] decs = [] perrs = [] times = [] for ob in mpc_obs: if ob.comment.mag is None: continue if ob.null_observation: continue try: mags.append(float(ob.comment.mag)) errs.append(float(ob.comment.mag_uncertainty)) times.append(float(ob.date.jd)) ras.append(float(ob.ra_residual)) decs.append(float(ob.dec_residual)) perrs.append(float(ob.comment.plate_uncertainty)) except Exception as err: sys.write.stderr(str(err)) ras = numpy.array(ras) decs = numpy.array(decs) mags = numpy.array(mags) mags = mags - mags.mean() times = numpy.array(times) ax1.plot(times, mags, '.', alpha=0.05) ax3.plot(times, ras, '.', alpha=0.1) ax4.plot(times, decs, '.', alpha=0.1) ax2.plot(ras, decs, '+', alpha=0.1)
def load_objects(self, directory_name=None): """Load the targets from a file """ for name in Neptune: self.kbos[name] = Neptune[name] if directory_name is not None: working_context = context.get_context(directory_name) for filename in working_context.get_listing('ast'): fhandle = working_context.open(filename) observations = [] lines = fhandle.read().split('\n') fhandle.close() for line in lines: if len(line) > 0 and not line.startswith( '#' ): # skip the comments, don't care about them here observations.append(mpc.Observation.from_string(line)) name = filename.rstrip( '.ast') # observations[0].provisional_name try: this_orbit = orbfit.Orbfit(observations) self.kbos[name] = this_orbit except Exception as e: logging.error("Failed loading: {}".format(name)) logging.error(str(e)) self.doplot()
def test_null_obseravtion(self): mpc_lines = ( "! HL7j2 C2013 04 03.62926 17 12 01.16 +04 13 33.3 24.1 R 568", " HL7j2 C2013 04 04.58296 17 11 59.80 +04 14 05.5 24.0 R 568", " HL7j2 C2013 05 03.52252 17 10 38.28 +04 28 00.9 23.4 R 568", " HL7j2 C2013 05 08.56725 17 10 17.39 +04 29 47.8 23.4 R 568" ) observations = [] for line in mpc_lines: observations.append(mpc.Observation.from_string(line)) HL7j2 = orbfit.Orbfit(observations) self.assertAlmostEqual(HL7j2.a, 135.75, 1)
def cfeps_residuals(version='L7', regenerate=False): if version == 'L4': header = ['obsnum', 'arclen', 'date', 'ra_resid', 'date2', 'dec_resid'] data = Table.read(path + 'L4resid.txt', format='ascii', guess=False, delimiter=' ', data_start=0, names=header) cfeps_mas = (np.sqrt(data['ra_resid']**2 + data['dec_resid']**2)) * 1000 else: all_resids = [] if regenerate: data_path = '/Users/bannisterm/Dropbox/mpc/' for filename in os.listdir(data_path): observations = mpc.MPCReader(data_path + filename) print(observations.provisional_name) orbit = orbfit.Orbfit(observations.mpc_observations) try: residuals = orbit.residuals(overall=True) all_resids += residuals except Exception as e: print(observations.provisional_name) print(e) continue print(all_resids) with open('cfeps_resids_{}.dat'.format(version), 'w') as outfile: for r in all_resids: outfile.write("{}\n".format(r)) else: assert os.path.exists('cfeps_resids_{}.dat'.format(version)) with open('cfeps_resids_{}.dat'.format(version), 'r') as infile: lines = infile.readlines() for line in lines: all_resids.append(float(line)) print(len(all_resids)) cfeps_mas = np.array(all_resids) print(cfeps_mas) print('cfeps', np.median(cfeps_mas)) return cfeps_mas
def parse_kbo(kbo_filename, camera_filter, search_start_date=Time('2013-02-08', scale='utc'), search_end_date=Time( datetime.datetime.now().strftime('%Y-%m-%d'), scale='utc')): mpc_observations = mpc.MPCReader(kbo_filename).mpc_observations orbit = orbfit.Orbfit(mpc_observations) sys.stderr.write("Sending query on %s to SSOS\n" % orbit.name) query = Query( mpc_observations, search_start_date=search_start_date, search_end_date=search_end_date) # searches full survey period obs_in_filter = parse_ssois_return(query.get(), camera_filter=camera_filter) return orbit, obs_in_filter
def test_orbfit_residuals(self): mpc_lines = ( " HL7j2 C2013 04 03.62926 17 12 01.16 +04 13 33.3 24.1 R 568", " HL7j2 C2013 04 04.58296 17 11 59.80 +04 14 05.5 24.0 R 568", " HL7j2 C2013 05 03.52252 17 10 38.28 +04 28 00.9 23.4 R 568", " HL7j2 C2013 05 08.56725 17 10 17.39 +04 29 47.8 23.4 R 568" ) observations = [] for line in mpc_lines: observations.append(mpc.Observation.from_string(line)) HL7j2 = orbfit.Orbfit(observations=observations) for observation in observations: HL7j2.predict(observation.date, 568) self.assertLess(observation.ra_residual, 0.3) self.assertLess(observation.dec_residual, 0.3)
def ossos_discoveries(no_nt_and_u=True): """ Returns a list of orbfit.Orbfit objects with the observations in the Orbfit.observations field. """ retval = [] # discovery_files = [n for n in os.listdir(parameters.REAL_KBO_AST_DIR)]# if n.endswith('.mpc') or n.endswith( # '.ast')] for filename in storage.listdir(parameters.REAL_KBO_AST_DIR): # keep out the not-tracked and uncharacterised. if no_nt_and_u: if not (filename.__contains__('nt') or filename.__contains__('u')): print(filename) observations = mpc.MPCReader(parameters.REAL_KBO_AST_DIR + filename) orbit = orbfit.Orbfit(observations.mpc_observations) retval.append((observations, orbit)) return retval
math.degrees(kbo.dec), marker='x', s=4, facecolor='r', edgecolor='r', alpha=0.3) if PLOT_REAL_KBOS: reader = mpc.MPCReader() print("PLOTTING LOCATIONS OF OSSOS KBOs (using directory {})".format( REAL_KBO_AST_DIR)) for ast in os.listdir(REAL_KBO_AST_DIR): if not ast.startswith('u'): obs = reader.read(REAL_KBO_AST_DIR + ast) try: kbo = orbfit.Orbfit(obs) except: continue kbo.predict(ephem.julian_date(ephem.date(plot_date))) # if not field_polygon.isInside(float(kbo.coordinate.ra.degrees), float(kbo.coordinate.dec.degrees)): # continue if obs[0].mag < 23.6: c = 'b' if LABEL_FIELDS: ax.text(kbo.coordinate.ra.degree, kbo.coordinate.dec.degree, ast.split('.')[0], horizontalalignment='center', verticalalignment='baseline', fontdict={ 'size': 4,
note1=None, note2=config.read('MPC.NOTE2DEFAULT')[0], date=date, ra=cutout.ra, dec=cutout.dec, mag=obs_mag, mag_err=obs_mag_err, frame=reading.obs.rawname, band=header['FILTER'], xpos=cutout.observed_x, ypos=cutout.observed_y, comment='AUTO', astrometric_level=cutout.astrom_header.get( 'ASTLEVEL', None)) source_obs.append(obs) with open(name + ".mpc", 'a') as fout: fout.write(obs.to_tnodb() + "\n") if len(source_obs) == 3: mags = 0 for source in source_obs: mags += source.mag mags = mags / len(source_obs) orbit = orbfit.Orbfit(source_obs) residuals = orbit.residuals(overall=True) print(orbit.summarize()) if orbit.a > 5 * units.AU and mags < 24.7: file('keepers.txt', 'a').write("{}\n".format(source_obs[0].provisional_name))
def ephem_search(mpc_filename, search_date="2014 07 24.0"): """ builds a TSV file in the format of SSOIS by querying for possible observations in CADC/CAOM2. This is a fall back program, should only be useful when SSOIS is behind. """ columns = ('Image', 'Ext', 'X', 'Y', 'MJD', 'Filter', 'Exptime', 'Object_RA', 'Object_Dec', 'Image_target', 'Telescope/Instrument', 'MetaData', 'Datalink') ephem_table = Table(names=columns, dtypes=('S10', 'i4', 'f8', 'f8', 'f8', 'S10', 'f8', 'f8', 'f8', 'S20', 'S20', 'S20', 'S50')) ephem_table.pprint() o = orbfit.Orbfit(mpc.MPCReader(mpc_filename).mpc_observations) o.predict(search_date) fields = storage.cone_search(o.coordinate.ra.degrees, o.coordinate.dec.degrees, dra=0.3, ddec=0.3, calibration_level=1) mjdates = numpy.unique(fields['mjdate']) collectionIDs = [] for mjdate in mjdates: jd = 2400000.5 + mjdate o.predict(jd) for field in storage.cone_search(o.coordinate.ra.degrees, o.coordinate.dec.degrees, dra=30. / 3600.0, ddec=30. / 3600.0, mjdate=mjdate, calibration_level=1): collectionIDs.append(field['collectionID']) expnums = numpy.unique(numpy.array(collectionIDs)) for expnum in expnums: header = storage.get_astheader(expnum, 22) o.predict(header['MJDATE'] + 2400000.5) print(o.time.iso, o.coordinate.ra.degrees, o.coordinate.dec.degrees) for ccd in range(36): header = storage.get_astheader(expnum, ccd) w = wcs.WCS(header) (x, y) = w.sky2xy(o.coordinate.ra.degrees, o.coordinate.dec.degrees) print(ccd, x, y) if 0 < x < header['NAXIS1'] and 0 < y < header['NAXIS2']: ephem_table.add_row([ expnum, ccd + 1, x, y, header['MJDATE'], header['FILTER'], header['EXPTIME'], o.coordinate.ra.degrees, o.coordinate.dec.degrees, header['OBJECT'], 'CFHT/MegaCam', None, "https://www.cadc-ccda.hia-iha.nrc-cnrc.gc.ca/data/pub/CFHT/{}p[{}]" .format(expnum, ccd) ]) break ephem_table.pprint() ephem_table.write('backdoor.tsv', format='ascii', delimiter='\t')
24.13 0.12 UUUU % """ import tempfile import astropy import numpy from astropy import units as u from ossos import mpc from ossos import orbfit obs = [] for line in input_orbit_mpc_lines.split('\n'): obs.append(mpc.Observation.from_string(line)) orbit = orbfit.Orbfit(obs) from astropy import units # # now create a set of lines to act as input observations. ## these are HST observations. ephem_file = tempfile.NamedTemporaryFile() date = '2013 01 01' orbit.predict(date, 568) ra1 = orbit.coordinate.ra.degrees dec1 = orbit.coordinate.dec.degrees start_date = mpc.Time('2013 01 01', scale='utc', precision=6) for trial in range(1000): new_obs = [] for dt in [0, 0.01, 0.02, 2.0, 5.0, 30, 60]: date = start_date.jd + dt date = mpc.Time(val=int(date), val2=date - int(date), format='jd', scale='utc').copy(format='mpc')
else: obs = mpc.MPCReader(parameters.REAL_KBO_AST_DIR + tno + '.ast') mpc_obs = list(obs.mpc_observations) for ob in mpc_obs: if ob.discovery: t0 = ob.date.jd break # sort by absolute distance from discovery mpc_obs.sort(key=lambda x: math.fabs(x.date.jd - t0)) # need minimum of 3 observations to start fitting an orbit t = [] da = [] for idx in range(3, len(mpc_obs) + 1): short_arc = mpc_obs[:idx] orb = orbfit.Orbfit(short_arc) short_arc.sort(key=lambda x: x.date.jd) arclen = short_arc[-1].date.jd - short_arc[0].date.jd # print len(short_arc), arclen, abs(mpc_obs[:idx][-1].date.jd - mpc_obs[:idx][0].date.jd) t.append(arclen / 365.25) da.append(orb.da / orb.a) with open(pfilename, 'w') as pf: pickle.dump((t, da), pf) # change colour at the two-year point if classification has shifted from insecure to secure fullarc_sec = tnos['sh'][tnos['object'] == tno][0] one_opp_sec = one_opp_tnos['sh'][one_opp_tnos['object'] == tno][0] one_opp = 1.6 # want to differentiate security with one opp since discovery and security with third year obs one_opp_col = security_colour.get(one_opp_sec, 'b') fullarc_col = security_colour.get(fullarc_sec, 'b')
def main(mpc_file, cor_file, skip_mags=False): """ :param mpc_file: A file containing the astrometric lines to be updated. :param cor_file: The base name for the updated astrometry and diagnostic files. :param skip_mags: Should we skip recomputing the magnitude of sources? :return: :raise ValueError: If actions on the mpc_obs indicate this is not a valid OSSOS observations """ observations = mpc.MPCReader(mpc_file).mpc_observations original_obs = [] modified_obs = [] for mpc_in in observations: logging.info("orig: {}".format(mpc_in.to_string())) mpc_obs = remeasure(mpc_in) if skip_mags and not mpc_obs.comment.photometry_note[0] == "Z": mpc_mag = remeasure(recompute_mag(mpc_obs)) else: mpc_mag = mpc_obs sep = mpc_in.coordinate.separation(mpc_mag.coordinate).degrees * 3600.0 if sep > TOLERANCE: logging.error("Large offset: {} arc-sec".format(sep)) logging.error("orig: {}".format(mpc_in.to_string())) logging.error(" new: {}".format(mpc_mag.to_string())) logging.info("modi: {}".format(mpc_mag.to_string())) logging.info("") original_obs.append(mpc_in) modified_obs.append(mpc_mag) origin = orbfit.Orbfit(original_obs) modified = orbfit.Orbfit(modified_obs) orbpt = file(cor_file+".orb", 'w') orbpt.write(modified.summarize()+"\n") orbpt.write(origin.summarize()+"\n") for element in ['a', 'e', 'inc', 'om', 'Node', 'T']: oval = getattr(origin, element) doval = getattr(origin, "d"+element) mval = getattr(modified, element) dmval = getattr(modified, "d"+element) precision = max(int(-1*math.floor(math.log10(dmval))), int(-1*math.floor(math.log10(doval)))) + 1 precision = max(0, precision) vdigits = 12 ddigits = 6 vpadding = " "*int(vdigits-precision) dpadding = " "*int(ddigits-precision) orbpt.write("{element:>5s}: " "{oval[0]:>{vdigits}.{vdigits}}.{oval[1]:<{precision}.{precision}} {vpadding} +/- " "{doval[0]:>{ddigits}.{ddigits}}.{doval[1]:<{precision}.{precision}} {dpadding} ==> " "{mval[0]:>{vdigits}.{vdigits}}.{mval[1]:<{precision}.{precision}} {vpadding} +/- " "{dmval[0]:>{ddigits}.{ddigits}}.{dmval[1]:<{precision}.{precision}}\n".format( element=element, dpadding=dpadding, vpadding=vpadding, vdigits=vdigits, ddigits=ddigits, oval="{:12.12f}".format(oval).split("."), doval="{:12.12f}".format(doval).split("."), mval="{:12.12f}".format(mval).split("."), dmval="{:12.12f}".format(dmval).split("."), precision=precision) ) delta = math.fabs(oval - mval) if delta > 3.5 * doval: logging.warn("large delta for element {}: {} --> {}".format(element, oval, mval)) for orb in [orbfit.Orbfit(modified_obs)]: residuals = orb.residuals dra = [] ddec = [] for observation in orb.observations: if not observation.null_observation: dra.append(observation.ra_residual) ddec.append(observation.dec_residual) if observation.comment.plate_uncertainty * 5.0 < \ ((observation.ra_residual ** 2 + observation.dec_residual ** 2) ** 0.5): logging.warn("LARGE RESIDUAL ON: {}".format(observation.to_string())) logging.warn("Fit residual unreasonably large.") dra = numpy.array(dra) ddec = numpy.array(ddec) orbpt.write("STD: {} {}\n".format(dra.std(), ddec.std())) orbpt.close() optr = file(cor_file+".tlf", 'w') for idx in range(len(modified_obs)): inp = original_obs[idx] out = modified_obs[idx] if inp != out: optr.write(out.to_tnodb()+"\n") optr.close() return True
def compare_orbits(original_obs, modified_obs, cor_file): """Compare the orbit fit given the oringal and modified astrometry.""" origin = orbfit.Orbfit(original_obs) modified = orbfit.Orbfit(modified_obs) orbpt = file(cor_file + ".orb", 'w') # Dump summaries of the orbits orbpt.write("#" * 80 + "\n") orbpt.write("# ORIGINAL ORBIT\n") orbpt.write(origin.summarize() + "\n") orbpt.write("#" * 80 + "\n") orbpt.write("# MODIFIED ORBIT\n") orbpt.write(modified.summarize() + "\n") orbpt.write("#" * 80 + "\n") # Create a report of the change in orbit parameter uncertainty for element in ['a', 'e', 'inc', 'om', 'Node', 'T']: oval = getattr(origin, element).value doval = getattr(origin, "d" + element).value mval = getattr(modified, element).value dmval = getattr(modified, "d" + element).value precision = max(int(-1 * math.floor(math.log10(dmval))), int(-1 * math.floor(math.log10(doval)))) + 1 precision = max(0, precision) vdigits = 12 ddigits = 6 vpadding = " " * int(vdigits - precision) dpadding = " " * int(ddigits - precision) orbpt.write( "{element:>5s}: " "{oval[0]:>{vdigits}.{vdigits}}.{oval[1]:<{precision}.{precision}} {vpadding} +/- " "{doval[0]:>{ddigits}.{ddigits}}.{doval[1]:<{precision}.{precision}} {dpadding} ==> " "{mval[0]:>{vdigits}.{vdigits}}.{mval[1]:<{precision}.{precision}} {vpadding} +/- " "{dmval[0]:>{ddigits}.{ddigits}}.{dmval[1]:<{precision}.{precision}}\n" .format(element=element, dpadding=dpadding, vpadding=vpadding, vdigits=vdigits, ddigits=ddigits, oval="{:12.12f}".format(oval).split("."), doval="{:12.12f}".format(doval).split("."), mval="{:12.12f}".format(mval).split("."), dmval="{:12.12f}".format(dmval).split("."), precision=precision)) delta = math.fabs(oval - mval) if delta > 3.5 * doval: logging.warn("large delta for element {}: {} --> {}".format( element, oval, mval)) # Compute the stdev of the residuals and report the change given the new observations orbpt.write("*" * 80 + "\n") orbpt.write("Change in orbital parameters \n") sep = "Change in scatter between initial and recalibrated obseravtions. \n" for orb in [origin, modified]: orbpt.write(sep) sep = "\n ==> becomes ==> \n" residuals = orb.residuals dra = [] ddec = [] mags = {} for observation in orb.observations: if not observation.null_observation: dra.append(observation.ra_residual) ddec.append(observation.dec_residual) filter = observation.band if filter is not None: if filter not in mags: mags[filter] = [] try: mags[filter].append(float(observation.mag)) except: pass if observation.comment.plate_uncertainty * 5.0 < \ ((observation.ra_residual ** 2 + observation.dec_residual ** 2) ** 0.5): logging.warn("LARGE RESIDUAL ON: {}".format( observation.to_string())) logging.warn("Fit residual unreasonably large.") dra = numpy.array(dra) ddec = numpy.array(ddec) merr_str = "" for filter in mags: mag = numpy.percentile(numpy.array(mags[filter]), (50)) mags[filter] = numpy.percentile(numpy.array(mags[filter]), (5, 95)) merr = (mags[filter][1] - mags[filter][0]) / 6.0 merr_str += " {}: {:8.2f} +/- {:8.2f}".format(filter, mag, merr) orbpt.write("ra_std:{:8.4} dec_std:{:8.4} mag: {}".format( dra.std(), ddec.std(), merr_str)) orbpt.write("\n") orbpt.close()