def notebook_bokeh(stcs): patch_xs = parse_s_region(stcs)['ra'] patch_ys = parse_s_region(stcs)['dec'] p = figure(plot_width=700, x_axis_label="RA (deg)", y_axis_label="Dec (deg)") data = {'x': [patch_xs], 'y': [patch_ys]} p.patches('x', 'y', source=data, fill_alpha=0.1, line_color="black", line_width=0.5) p.add_layout( Arrow(end=VeeHead(line_color="black", line_width=1), line_width=2, x_start=patch_xs[0], y_start=patch_ys[0], x_end=patch_xs[1], y_end=patch_ys[1])) p.y_range.flipped = True output_notebook() show(p)
def quick_plot(stcs): patch_xs = parse_s_region(stcs)['ra'] patch_ys = parse_s_region(stcs)['dec'] f, ax = plt.subplots(figsize=(8, 4)) ax.scatter(patch_xs, patch_ys, edgecolors="black", marker='.', linestyle='None', s=50, facecolors='black') for i in range(len(patch_xs)): ax.text(patch_xs[i], patch_ys[i], str(i)) plt.show()
def quick_bokeh(stcs, outfile='test.html'): patch_xs = parse_s_region(stcs)['ra'] patch_ys = parse_s_region(stcs)['dec'] p = figure(plot_width=700) data = {'x': [patch_xs], 'y': [patch_ys]} p.patches('x', 'y', source=data, fill_alpha=0.1, line_color="black", line_width=0.5) output_file(outfile) show(p)
def clean_up_results(t_init, obj_name, id_type='smallbody', location=None, radius=0.0083): """ Function to clean up results. Will check if the target is inside the observation footprint. If a radius is provided, will also construct a circle and check if the observation center is in the target circle. Parameters ---------- t_init: atropy Table Initial astropy Table obj_name: str Object name. May require specific formatting (i.e. selecting between the codes for Jupiter and Jupiter barycenter). See JPL Horizons documentation 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 radius : float Size of target for intersection calculations Returns ------- t: astropy Table Astropy Table with only those where the moving target was in the footprint """ t = t_init.copy() # Add mid-point time and sort by that first t['t_mid'] = (t['t_max'] + t['t_min'])/2 + 2400000.5 t.sort('t_mid') # Ephemerides results are sorted by time, hence the initial sort print('Verifying footprints...') eph = Horizons(id=obj_name, location=location, id_type=id_type, epochs=t['t_mid']).ephemerides() # For each row in table, check s_region versus target position at mid-time check_list = [] for i, row in enumerate(t): # print(row['t_mid'], eph['datetime_jd'][i], eph['RA'][i], eph['DEC'][i]) # Create a polygon for the footprint and check if target is inside polygon try: stcs = parse_s_region(row['s_region']) xs = stcs['ra'] ys = stcs['dec'] polygon_pix = PolygonPixelRegion(vertices=PixCoord(x=xs, y=ys)) target_coords = PixCoord(eph['RA'][i], eph['DEC'][i]) if radius is None or radius <= 0: flag = target_coords in polygon_pix else: target_circle = CirclePixelRegion(center=target_coords, radius=radius) observation_coords = PixCoord(row['s_ra'], row['s_dec']) flag = (target_coords in polygon_pix) or (observation_coords in target_circle) # print(stcs, flag) except Exception as e: print(f"ERROR checking footprint for {row['obs_id']} with: {e}" f"\nAssuming False") flag = False check_list.append(flag) # Set the flags t['in_footprint'] = check_list return t[t['in_footprint']]
end_time=end_time, maxrec=100) print(results) filtered_results = clean_up_results(results, obj_name=obj_name, id_type=id_type, location=location) print(filtered_results) # Using regions import matplotlib.pyplot as plt from astropy.coordinates import SkyCoord from regions import PixCoord, PolygonSkyRegion, PolygonPixelRegion, CirclePixelRegion patch_xs = parse_s_region(stcs)['ra'] patch_ys = parse_s_region(stcs)['dec'] polygon_sky = PolygonSkyRegion( vertices=SkyCoord(patch_xs, patch_ys, unit='deg', frame='icrs')) # Treating as pixels for simplicity (and since I have no WCS) polygon_pix = PolygonPixelRegion(vertices=PixCoord(x=patch_xs, y=patch_ys)) PixCoord(eph['RA'][1], eph['DEC'][1]) in polygon_pix radius = 0.0083 target_coords = PixCoord(eph['RA'][0], eph['DEC'][0]) target_circle = CirclePixelRegion(center=target_coords, radius=radius) intersection = target_circle & polygon_pix # intersection.area # not implemented yet fig, ax = plt.subplots(figsize=(8, 4)) patch = polygon_pix.as_artist(facecolor='none', edgecolor='red', lw=2)
def mast_bokeh(eph, mast_results, stcs=None, display=False): # Function to produce a Bokeh plot of MAST results with the target path p = figure(plot_width=700, x_axis_label="RA (deg)", y_axis_label="Dec (deg)") # Target path eph_data = { 'eph_x': eph['RA'], 'eph_y': eph['DEC'], 'Date': eph['datetime_str'] } eph_plot1 = p.line(x='eph_x', y='eph_y', source=eph_data, line_width=2, line_color='black', legend=eph['targetname'][0]) eph_plot2 = p.circle(x='eph_x', y='eph_y', source=eph_data, fill_color="black", size=12, legend=eph['targetname'][0]) p.add_tools( HoverTool(renderers=[eph_plot1, eph_plot2], tooltips=[('Date', "@Date")])) # Target footprint patch_xs = parse_s_region(stcs)['ra'] patch_ys = parse_s_region(stcs)['dec'] stcs_data = {'stcs_x': [patch_xs], 'stcs_y': [patch_ys]} p.patches('stcs_x', 'stcs_y', source=stcs_data, fill_alpha=0., line_color="grey", line_width=0.8, line_dash='dashed', legend='Search Area') # Prepare MAST footprints obsDF = mast_results.to_pandas() obsDF['coords'] = obsDF.apply(lambda x: parse_s_region(x['s_region']), axis=1) for col in mast_results.colnames: if isinstance(obsDF[col][0], bytes): obsDF[col] = obsDF[col].str.decode('utf-8') # Loop over missions, coloring each separately mast_plots = [] for mission, color in zip(obsDF['obs_collection'].unique(), Spectral4): ind = obsDF['obs_collection'] == mission # Add patches with the observation footprings patch_xs = [c['ra'] for c in obsDF['coords'][ind]] patch_ys = [c['dec'] for c in obsDF['coords'][ind]] data = { 'x': patch_xs, 'y': patch_ys, 'obs_collection': obsDF['obs_collection'][ind], 'instrument_name': obsDF['instrument_name'][ind], 'obs_id': obsDF['obs_id'][ind], 'target_name': obsDF['target_name'][ind], 'proposal_pi': obsDF['proposal_pi'][ind] } mast_plots.append( p.patches('x', 'y', source=data, legend=mission, fill_color=color, fill_alpha=0.1, line_color="white", line_width=0.5)) # Add hover tooltip for MAST observations tooltip = [("instrument_name", "@instrument_name"), ("obs_id", "@obs_id"), ("target_name", "@target_name"), ('proposal_pi', '@proposal_pi')] p.add_tools(HoverTool(renderers=mast_plots, tooltips=tooltip)) # Additional settings p.legend.click_policy = "hide" p.x_range.flipped = True if display: output_notebook() show(p) else: return p