Filtering¶
Let's start from all the transiting exoplanets in the NASA Exoplanet Archive, and then filter down into a Population
of planets we might want to consider observing.
import exoatlas as ea
import exoatlas.visualizations as vi
ea.version()
'0.6.6'
Download Exoplanet Data¶
Let's download a recent list of transiting exoplanets from the NASA Exoplanet Archive. We should, as always, be careful not to completely trust every detail of this database. For any particular planet, there's a possibility that details might be wrong or missing so for anything super crucial, it would be very wise to double check.
e = ea.TransitingExoplanets()
s = ea.SolarSystem()
Throughout, let's use PlanetGallery
to visualize how the various filtering cuts remove planets from our observing sample.
vi.PlanetGallery().build(e);
Define Filtering Criteria¶
Let's make some cuts to this sample in order to select systems that might be worth trying to observe at the telescope. We'll start by defining an unfiltered populatioin, for comparison.
unfiltered = e[:]
unfiltered.color = "orchid"
unfiltered.label = "Unfiltered"
Is it big enough?¶
To ensure that a planet has a hydrogen-dominated atmosphere (which makes interpreting a transmission spectrum a lot easier), we could place a cut on the planet's radius. "Most 1.6 Earth-radius planets are not rocky", so let's try cutting there.
import astropy.units as u
is_big = e.radius() > 1.6 * u.Rearth
filtered = e[is_big]
filtered.label = "Big"
filtered
✨ Big | 3060 elements ✨
vi.PlanetGallery().build([unfiltered, filtered]);
Is the duration short enough?¶
An ideal transit observation would include at least some baseline before the start and after the end of the transit itself. When observing from a ground-based telescope, practically that means it's really hard to observe (complete) transits with durations longer than about a few hours.
is_short = e.transit_duration() < 3 * u.hour
filtered = e[is_short]
filtered.label = "Short"
filtered
✨ Short | 2002 elements ✨
vi.PlanetGallery().build([unfiltered, filtered]);
Is transmission spectroscopy possible?¶
The best precision we could possibly acheive on measuring a transit depth is set by the number of photons that we can gather with our telescope. If the signal we're hoping to detect for transmission spectroscopy (see Observing) is smaller than that expected precision, it's basically hopeless that we'll see anything. So, let's at least limit our sample to targets with a reasonably high predicted signal-to-noise ratio.
import matplotlib.pyplot as plt
import numpy as np
signal = e.transmission_signal()
wavelength = 0.7 * u.micron
dt = 1 * u.hour
R = 10
noise = e.depth_uncertainty(telescope="APO", wavelength=wavelength, dt=dt, R=R)
snr = signal / noise
plt.figure(figsize=(8, 5))
plt.scatter(noise, signal, c=snr, vmin=1, vmax=10)
plt.xscale("log")
plt.yscale("log")
plt.axis("scaled")
plt.xlabel("")
plt.ylim(1e-6, 1e-2)
plt.xlim(1e-6, 1e-2)
plt.plot(
[1e-6, 1e-2], [1e-6, 1e-2], color="black", linewidth=3, linestyle="--", alpha=0.3
)
plt.colorbar(label="S/N")
plt.xlabel(rf"Predicted Photon Noise\n($\lambda=${wavelength}, dt={dt}, R={R})")
plt.ylabel(r"Possible Transmission\nSignal Size ($2HR_p/R_{\star}^2$)");
is_snr = snr > 5
filtered = e[is_snr]
filtered.label = "High S/N"
filtered
✨ High S/N | 253 elements ✨
vi.PlanetGallery().build([unfiltered, filtered]);
Is it above the horizon at night?¶
If we're observing at a particular time of year from a particular observatory, only some targets will be high enough in the sky to be observable at night. Let's place a cut on the airmass) at midnight on some particular night, so we don't waste time considering planets that are beneath the Earth when we might be trying to observe.
from astroplan import Observer
from astropy.time import Time
date = Time.now()
observatory = Observer.at_site("APO", timezone="US/Mountain")
local_midnight = observatory.midnight(date)
sidereal_time_at_midnight = observatory.local_sidereal_time(local_midnight)
ra_at_midnight = sidereal_time_at_midnight
ra_at_midnight
declination_at_zenith = observatory.latitude
declination_at_zenith
airmass = e.airmass(where=observatory, when=local_midnight)
is_up = airmass < 2
filtered = e[is_up]
filtered.name = "Up at Midnight"
plt.figure()
plt.scatter(e.ra(), e.dec(), color="black", marker=".", s=2, alpha=0.2)
plt.scatter(filtered.ra(), filtered.dec(), color="black", marker="o", facecolor="none")
plt.scatter(e.ra(), e.dec(), c=airmass, cmap="viridis_r", vmin=1, vmax=10, zorder=-1)
plt.axvline(ra_at_midnight, color="gray")
plt.axhline(declination_at_zenith, color="gray")
plt.xlabel("Right Ascension (degree)")
plt.ylabel("Declination (degree)")
plt.axis("scaled")
plt.ylim(-90, 90)
plt.xlim(360, 0)
plt.colorbar(label="airmass")
plt.title(f"{observatory.name} | {local_midnight.iso} UTC");
vi.PlanetGallery().build([unfiltered, filtered]);
Make Target Sample¶
After looking at each of them one by one, let's put all of those filtering criteria together.
targets = e[is_big * is_short * is_snr * is_up]
targets.label = "Observable?!"
targets
✨ Observable?! | 31 elements ✨
vi.PlanetGallery().build([unfiltered, targets]);
Let's print out the names of the planets that made it through all our cuts.
print(targets.name())
['GJ 1214 b' 'HAT-P-11 b' 'HAT-P-12 b' 'HAT-P-18 b' 'HAT-P-26 b' 'HD 189733 b' 'HD 191939 b' 'HD 219134 b' 'K2-31 b' 'KELT-23 A b' 'Kepler-51 c' 'NGTS-5 b' 'Qatar-10 b' 'Qatar-6 b' 'TOI-1173 b' 'TOI-1248 b' 'TOI-1259 A b' 'TOI-1273 b' 'TOI-1408 b' 'TOI-1431 b' 'TOI-1855 b' 'TOI-2134 b' 'TOI-4463 A b' 'TrES-1 b' 'WASP-39 b' 'WASP-67 b' 'WASP-69 b' 'WASP-74 b' 'WASP-80 b' 'XO-1 b' 'XO-7 b']
Let's also make a table that includes more useful information, like positions and transit ephemerides, which we could use as an input to plan an observing run.
table = targets.create_planning_table()
table
name | ra | dec | period | transit_midpoint | transit_duration | radius | relative_insolation | stellar_radius | stellar_teff | distance |
---|---|---|---|---|---|---|---|---|---|---|
deg | deg | d | d | h | earthRad | solRad | K | pc | ||
str29 | float64 | float64 | float64 | float64 | float64 | float64 | float64 | float64 | float64 | float64 |
GJ 1214 b | 258.8313991 | 4.9606795 | 1.580404531 | 2459639.7812619 | 0.86966 | 2.733 | 17.21817034577689 | 0.2162 | 3101.0 | 14.6427 |
HAT-P-11 b | 297.7101763 | 48.0818635 | 4.888 | 2454957.8132067 | 2.35562 | 4.36 | 98.02544814710485 | 0.683 | 4653.0 | 37.7647 |
HAT-P-12 b | 209.3886452 | 43.49331 | 3.2130598 | 2454419.19556 | 2.3376 | 10.749 | 142.34347084035403 | 0.701 | 4650.0 | 142.751 |
HAT-P-18 b | 256.346376 | 33.0123251 | 5.508023 | 2454715.02174 | 2.7144 | 11.153 | 86.33291087921891 | 0.749 | 4803.0 | 161.4 |
HAT-P-26 b | 213.1565508 | 4.0594175 | 4.23452 | 2456901.059458 | 2.4552 | 7.06167 | 190.5675599152924 | 0.87 | 5079.0 | 141.837 |
HD 189733 b | 300.1821223 | 22.7097759 | 2.21857567 | 2453955.5255511 | 1.8233621 | 12.66617 | 353.86047213972984 | 0.75 | 5052.0 | 19.7638 |
HD 191939 b | 302.0256247 | 66.8503014 | 8.8803256 | 2459443.54236 | 2.939 | 3.41 | 100.5536645439072 | 0.94 | 5348.0 | 53.6089 |
HD 219134 b | 348.3372026 | 57.1696255 | 3.092926 | 2457126.69913 | 0.945 | 1.602 | 176.12559092759645 | 0.778 | 4699.0 | 6.53127 |
K2-31 b | 245.4405531 | -23.548273 | 1.25785 | 2457191.70889 | 0.9816 | 11.88154 | 1602.7826713097115 | 0.78 | 5280.0 | 110.527 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
TOI-4463 A b | 279.3581286 | 18.7299522 | 2.8807198 | 2459291.64004 | 1.85 | 13.26022417 | 629.8653023803159 | 1.062 | 5640.0 | 173.117 |
TrES-1 b | 286.0408755 | 36.632536 | 3.03007 | 2453186.806341 | 2.508 | 12.66617 | 324.79600430434164 | 0.85 | 5230.0 | 159.658 |
WASP-39 b | 217.3266477 | -3.4444994 | 4.0552842 | 2459783.5015 | 2.8032 | 14.930388 | 315.36062051908334 | 0.918 | 5485.0 | 213.982 |
WASP-67 b | 295.7438485 | -19.9497314 | 4.61442 | 2456618.0537 | 1.896 | 12.89035 | 189.27714560988787 | 0.88 | 5200.0 | 189.469 |
WASP-69 b | 315.0259661 | -5.094857 | 3.86814 | 2459798.775459 | 2.1610195 | 12.44199 | 166.35384100958626 | 0.86 | 4700.0 | 49.9605 |
WASP-74 b | 304.538843 | -1.0760033 | 2.13775 | 2457103.325971 | 2.292 | 15.24424 | 2117.5611209480976 | 1.42 | 5990.0 | 149.216 |
WASP-80 b | 303.1667996 | -2.1444369 | 3.06785234 | 2456487.425006 | 2.131 | 11.197791 | 77.07315102540811 | 0.586 | 4143.0 | 49.7876 |
XO-1 b | 240.5492745 | 28.1696248 | 3.94153 | 2455385.51978 | 2.9712 | 12.77826 | 344.2550786936063 | 0.88 | 5750.0 | 163.553 |
XO-7 b | 277.4780753 | 85.2333208 | 2.8641424 | 2457917.47503 | 2.772 | 15.389957 | 1381.2712428658124 | 1.48 | 6250.0 | 234.149 |
Let's save that table out to a text file, and also make sure we can load it back in again.
observatory_string = observatory.name.replace(" ", "-")
date_string = local_midnight.iso.split()[0]
table.write(
f"planets-to-observe-{observatory_string}-{date_string}.ecsv", overwrite=True
)
from astropy.io.ascii import read
read(f"planets-to-observe-{observatory_string}-{date_string}.ecsv")
name | ra | dec | period | transit_midpoint | transit_duration | radius | relative_insolation | stellar_radius | stellar_teff | distance |
---|---|---|---|---|---|---|---|---|---|---|
deg | deg | d | d | h | earthRad | solRad | K | pc | ||
str12 | float64 | float64 | float64 | float64 | float64 | float64 | float64 | float64 | float64 | float64 |
GJ 1214 b | 258.8313991 | 4.9606795 | 1.580404531 | 2459639.78126 | 0.86966 | 2.733 | 17.2181703458 | 0.2162 | 3101.0 | 14.6427 |
HAT-P-11 b | 297.7101763 | 48.0818635 | 4.888 | 2454957.81321 | 2.35562 | 4.36 | 98.0254481471 | 0.683 | 4653.0 | 37.7647 |
HAT-P-12 b | 209.3886452 | 43.49331 | 3.2130598 | 2454419.19556 | 2.3376 | 10.749 | 142.34347084 | 0.701 | 4650.0 | 142.751 |
HAT-P-18 b | 256.346376 | 33.0123251 | 5.508023 | 2454715.02174 | 2.7144 | 11.153 | 86.3329108792 | 0.749 | 4803.0 | 161.4 |
HAT-P-26 b | 213.1565508 | 4.0594175 | 4.23452 | 2456901.05946 | 2.4552 | 7.06167 | 190.567559915 | 0.87 | 5079.0 | 141.837 |
HD 189733 b | 300.1821223 | 22.7097759 | 2.21857567 | 2453955.52555 | 1.8233621 | 12.66617 | 353.86047214 | 0.75 | 5052.0 | 19.7638 |
HD 191939 b | 302.0256247 | 66.8503014 | 8.8803256 | 2459443.54236 | 2.939 | 3.41 | 100.553664544 | 0.94 | 5348.0 | 53.6089 |
HD 219134 b | 348.3372026 | 57.1696255 | 3.092926 | 2457126.69913 | 0.945 | 1.602 | 176.125590928 | 0.778 | 4699.0 | 6.53127 |
K2-31 b | 245.4405531 | -23.548273 | 1.25785 | 2457191.70889 | 0.9816 | 11.88154 | 1602.78267131 | 0.78 | 5280.0 | 110.527 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
TOI-4463 A b | 279.3581286 | 18.7299522 | 2.8807198 | 2459291.64004 | 1.85 | 13.26022417 | 629.86530238 | 1.062 | 5640.0 | 173.117 |
TrES-1 b | 286.0408755 | 36.632536 | 3.03007 | 2453186.80634 | 2.508 | 12.66617 | 324.796004304 | 0.85 | 5230.0 | 159.658 |
WASP-39 b | 217.3266477 | -3.4444994 | 4.0552842 | 2459783.5015 | 2.8032 | 14.930388 | 315.360620519 | 0.918 | 5485.0 | 213.982 |
WASP-67 b | 295.7438485 | -19.9497314 | 4.61442 | 2456618.0537 | 1.896 | 12.89035 | 189.27714561 | 0.88 | 5200.0 | 189.469 |
WASP-69 b | 315.0259661 | -5.094857 | 3.86814 | 2459798.77546 | 2.1610195 | 12.44199 | 166.35384101 | 0.86 | 4700.0 | 49.9605 |
WASP-74 b | 304.538843 | -1.0760033 | 2.13775 | 2457103.32597 | 2.292 | 15.24424 | 2117.56112095 | 1.42 | 5990.0 | 149.216 |
WASP-80 b | 303.1667996 | -2.1444369 | 3.06785234 | 2456487.42501 | 2.131 | 11.197791 | 77.0731510254 | 0.586 | 4143.0 | 49.7876 |
XO-1 b | 240.5492745 | 28.1696248 | 3.94153 | 2455385.51978 | 2.9712 | 12.77826 | 344.255078694 | 0.88 | 5750.0 | 163.553 |
XO-7 b | 277.4780753 | 85.2333208 | 2.8641424 | 2457917.47503 | 2.772 | 15.389957 | 1381.27124287 | 1.48 | 6250.0 | 234.149 |
You can try filtering populations for your own devious and wonderful purposes, using whatever criteria you like!