<jupyter_start><jupyter_text>Moving Targets in the Kepler/K2 Fields Searching for observations of moving targets can be challenging since their positions change across time and it is not always possible to tag each possible target on an observation's set of metadata. To that end, services like the JPL Horizons service exist to compute locations as a function of time for known moving targets. In this notebook, we demonstrate how to use this service, alongside some custom functions, to perform queries for Kepler and K2 data in the MAST Archive.  RequirementsTo get started, we'll need to install some software first, including the astroquery and pyVO packages. For simplicity, this is all taken care of with the MovingMast package at https://github.com/dr-rodriguez/MovingMast. To install this package and all it's requirements, run `pip install git+https://github.com/dr-rodriguez/MovingMast`<jupyter_code># Import for use later
from astropy.table import Table
from movingmast import target, plotting, mast_tap<jupyter_output><empty_output><jupyter_text>Generete EphemerisTo search for moving targets, we will first generate an ephemeris, the trajectory of our target over some period of time. We will utilize the [JPL HORIZONS service](https://ssd.jpl.nasa.gov/), as implemented in the `astroquery.jplhorizons` [module](https://astroquery.readthedocs.io/en/latest/jplhorizons/jplhorizons.html), to facilitate this. For simplicity, we will use the Earth as our viewer location, but other locations, including satellites like Kepler or TESS can be provided for ephemerides calculations.  List of targets to considerHere are a handful of asteroids in various K2 fields to consider.<jupyter_code>txt = """id,name,k2 campaign,start,end,type
1143,1143 Odysseus,6,2015-07-14,2015-09-30,smallbody
C/2013 A1,Comet.C/2013 A1 (Siding Springs),2,2014-08-23,2014-11-13,smallbody
278361,TNO.(278361) 2007 JJ43,2,2014-08-23,2014-11-13,smallbody
8,Neptune,19,2018-08-29,2018-09-26,majorbody
8,Neptune,3,2014-11-14,2015-02-03,majorbody
250112,TNO.(250112) 2002 KY14,4,2015-02-07,2015-04-23,smallbody
126154,TNO.(126154) 2001 YH140,5,2015-04-27, 2015-07-10,smallbody
10989,Trojan.(10989),6,2015-08-20,2015-09-01,smallbody
51930,Trojan.(51930),6,2015-08-20,2015-09-01,smallbody
5244,Trojan.(5244),6,2015-08-20,2015-09-01,smallbody
5652,Trojan.(5652),6,2015-08-20,2015-09-01,smallbody
9,TNO.Pluto,7,2015-10-04,2015-12-26,majorbody
Hilda,Asteroid.Hilda.1988 RO12,10,2016-07-06,2016-09-20,smallbody
90000688,Comet.67P/Churyumov-Gerasimenko,10,2016-07-06,2016-09-20,smallbody
1062,Asteroid.Main-belt.1062 Ljuba,19,2018-08-29,2018-09-26,smallbody
50000,TNO.Quaoar,9,2016-04-21,2016-07-01,smallbody
"""
tab = Table.read(txt, format='csv')
tab.show_in_notebook()<jupyter_output><empty_output><jupyter_text>For this example, we'll select one of them, but feel free to update this to any other from the table or for your own favorite target. Note that not all asteroids will have been observed by Kepler and K2 and a valid identifier must be provided to the Horizons ephemerides service.<jupyter_code># Specify row number (idx) from table above to load an object
row = 0

obj_name = tab['id'][row]
id_type = tab['type'][row]
times = {'start': tab['start'][row], 'stop': tab['end'][row], 'step': '1d'}

# Viewer location (None=default geocentric)
location = None<jupyter_output><empty_output><jupyter_text>We will use the `target.get_path` function, which wraps calls to the JPL Horizons service and returns an astropy table for later use. For the sake of this prototype, we recommend keeping your time range within a month or so.<jupyter_code>eph = target.get_path(obj_name, id_type=id_type, times=times, location=location)
eph.show_in_notebook()<jupyter_output><empty_output><jupyter_text>Search MASTWith our target ephemeris, we are now ready to explore data in MAST. We will first create a search polygon with the `target.convert_path_to_polygon` function. This will create a simple polygon in a string format recognizable by our MAST queries that describes the path of the target.<jupyter_code># Generate a polygon for the provided ephemeris
# Radius is the half the width of the polygon in degrees (default: 30")
search_polygon = target.convert_path_to_polygon(eph, radius=0.0083)<jupyter_output><empty_output><jupyter_text>This search polygon will be provided to the `mast_tap.run_tap_query` function, which constructs an ADQL query to be passed along to the MAST TAP service via the pyVO package. It also takes start and end times, which we gather from the ephemeris and convert to Modified Julian Days. Output is returned as an Astropy Table and is very similar to the output from the `astroquery.mast` module.<jupyter_code># Convert time boundaries to MJD
start_time = min(eph['datetime_jd']) - 2400000.5
end_time = max(eph['datetime_jd']) - 2400000.5

mast_results = mast_tap.run_tap_query(search_polygon, start_time=start_time, end_time=end_time, 
                                      maxrec=100, mission='Kepler,K2,KeplerFFI')
print(f'{len(mast_results)} observations found.')<jupyter_output><empty_output><jupyter_text>For clarity, I'm going to remove High-Level Science Products (HLSPs) that have been built from the Kepler and K2 observations. You can skip this cell if you'd like to keep them.<jupyter_code># Mask out HLSP from results
not_hlsp = ['hlsp' not in x for x in mast_results['project']]
mast_results = mast_results[not_hlsp]
# Show results
mast_results[['obs_collection', 'obs_id', 'target_name', 
              'proposal_id', 'project', 'start_date', 'end_date']].show_in_notebook()<jupyter_output><empty_output><jupyter_text>Note that not all observations listed are guaranteed to have the target in their field of view at the time the target was closest. This is a limitation of our search- it includes any observation within the search area that was observed at any time in the range provided, regardless of the exact location of the target at the date of observation.  Examine ResultsIt is sometimes constructive to examine these results in a plot. Here we use the `plotting.mast_bokeh` function to generate an interactive Bokeh figure of the target ephemeris, the search polygon, and the MAST observations. Hover tooltips provide more information and users can zoom and pan the display as needed.<jupyter_code># Make a Bokeh plot of the target location, the search area, and the MAST observation footprints
p = plotting.mast_bokeh(eph, mast_results, search_polygon, display=True)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.0872565557429842, 'fraction_numerical': 0.06931452231252876, 'mean_word_length': 5.779625779625779, 'pattern_counts': {'":': 0, '<': 33, '<?xml version=': 0, '>': 33, 'https://': 4, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 1, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '8', 'dir': 'jupyter-structured-clean-dedup', 'id': '311081', 'license': 'MIT', 'n_tokens_mistral': 2346, 'n_tokens_neox': 2025, 'n_words': 720, 'path': 'Kepler_Search_Example.ipynb', 'repo_name': 'dr-rodriguez/MovingMast', 'size': '6521'}