def plot_exoplanetarchive_Rp_vs_P_age_cuts(whichcut='none'): tab = NasaExoplanetArchive.get_confirmed_planets_table(all_columns=True) f, ax = plt.subplots(figsize=(6, 4)) xval = nparr(tab['pl_orbper']) yval = nparr(tab['pl_rade']) age = nparr(tab['st_age']) age_perr = nparr(tab['st_ageerr1']) age_merr = nparr(tab['st_ageerr2']) age_err = np.maximum(age_perr, np.abs(age_merr)) transits = nparr(tab['pl_tranflag']).astype(bool) sel = (np.isfinite(xval) & (xval > 0) & np.isfinite(yval) & (yval > 0) & transits) if whichcut in [ 'finiteage', 'sigmatau_by_tau_pt5', 'sigmatau_by_tau_pt2', 'age_lt_1Gyr', 'age_gt_10Gyr', 'age_gt_8Gyr', 'age_lt_500Myr', 'age_lt_100Myr' ]: sel &= np.isfinite(age) sel &= (age > 0) sel &= np.isfinite(age_perr) sel &= (age_perr > 0) sel &= np.isfinite(age_merr) sel &= (np.abs(age_merr) > 0) if whichcut == 'sigmatau_by_tau_pt5': sel &= (age_err / age < 0.5) if whichcut == 'sigmatau_by_tau_pt2': sel &= (age_err / age < 0.2) if whichcut.endswith('Gyr'): cutval = int(whichcut.split('Gyr')[0].split('_')[-1]) if '_gt_' in whichcut: sel &= age > cutval elif '_lt_' in whichcut: sel &= age < cutval if whichcut.endswith('Myr'): cutval_Myr = int(whichcut.split('Myr')[0].split('_')[-1]) cutval = (cutval_Myr / 1e3) if '_gt_' in whichcut: sel &= age > cutval elif '_lt_' in whichcut: sel &= age < cutval ax.scatter(xval[sel], yval[sel], rasterized=True, alpha=0.8, zorder=3, c='k', lw=0, s=6) ax.set_xlabel('Orbital period [days]') ax.set_ylabel('Radius [$R_\oplus$]') ax.set_xscale('log') ax.set_yscale('log') ax.set_xlim((0.09, 3.1e3)) ax.set_ylim((0.25, 25)) datestr = datetime.today().isoformat().split('T')[0] if whichcut == 'none': txtstr = ('{} transiting\n{}\nExoplanet Archive'.format( len(xval[sel]), datestr)) elif whichcut == 'finiteage': txtstr = ('{} transiting, w/ "age"\n{}\nExoplanet Archive'.format( len(xval[sel]), datestr)) elif whichcut == 'sigmatau_by_tau_pt5': selectionstr = r'$\sigma_\tau / \tau < 0.5$' txtstr = ('{} transiting, w/ {}\n{}\nExoplanet Archive'.format( len(xval[sel]), selectionstr, datestr)) elif whichcut == 'sigmatau_by_tau_pt2': selectionstr = r'$\sigma_\tau / \tau < 0.2$' txtstr = ('{} transiting, w/ {}\n{}\nExoplanet Archive'.format( len(xval[sel]), selectionstr, datestr)) elif whichcut.endswith('Gyr'): if '_gt_' in whichcut: selectionstr = r'$\tau > {}$ Gyr'.format(cutval) elif '_lt_' in whichcut: selectionstr = r'$\tau < {}$ Gyr'.format(cutval) txtstr = ('{} transiting, w/ {}\n{}\nExoplanet Archive'.format( len(xval[sel]), selectionstr, datestr)) elif whichcut.endswith('Myr'): if '_gt_' in whichcut: selectionstr = r'$\tau > {}$ Myr'.format(cutval_Myr) elif '_lt_' in whichcut: selectionstr = r'$\tau < {}$ Myr'.format(cutval_Myr) txtstr = ('{} transiting, w/ {}\n{}\nExoplanet Archive'.format( len(xval[sel]), selectionstr, datestr)) ax.text(0.98, 0.02, txtstr, ha='right', va='bottom', fontsize='small', transform=ax.transAxes) savdir = '../results/exoplanet_archive_age_cut_plots/' savpath = os.path.join( savdir, 'exoplanetarchive_Rp_vs_P_cut{}.png'.format(whichcut)) f.savefig(savpath, bbox_inches='tight', dpi=400) print('made {}'.format(savpath)) return tab
def _get_period_guess_given_plname(plname): from astroquery.mast import Catalogs res = Catalogs.query_object(plname, catalog="TIC", radius=0.5*1/3600) if len(res) != 1: raise ValueError('for {}, got result:\n{}'.format(plname, repr(res))) ticid = int(res["ID"]) litdir = '../data/literature_physicalparams/{}/'.format(ticid) if not os.path.exists(litdir): os.mkdir(litdir) litpath = os.path.join(litdir,'params.csv') try: lpdf = pd.read_csv(litpath) period_guess = float(lpdf['period_day']) except FileNotFoundError: from astrobase.services.mast import tic_objectsearch ticres = tic_objectsearch(ticid) with open(ticres['cachefname'], 'r') as json_file: data = json.load(json_file) ra = data['data'][0]['ra'] dec = data['data'][0]['dec'] targetcoordstr = '{} {}'.format(ra, dec) # attempt to get physical parameters of planet -- period, a/Rstar, and # inclination -- for the initial guesses. from astroquery.nasa_exoplanet_archive import NasaExoplanetArchive eatab = NasaExoplanetArchive.get_confirmed_planets_table() pl_coords = eatab['sky_coord'] tcoord = SkyCoord(targetcoordstr, frame='icrs', unit=(u.deg, u.deg)) print('got match w/ separation {}'.format( np.min(tcoord.separation(pl_coords).to(u.arcsec)))) pl_row = eatab[np.argmin(tcoord.separation(pl_coords).to(u.arcsec))] # all dimensionful period = pl_row['pl_orbper'].value incl = pl_row['pl_orbincl'].value semimaj_au = pl_row['pl_orbsmax'] rstar = pl_row['st_rad'] a_by_rstar = (semimaj_au / rstar).cgs.value litdf = pd.DataFrame( {'period_day':period, 'a_by_rstar':a_by_rstar, 'inclination_deg':incl }, index=[0] ) # get the fixed physical parameters from the data. period_day, # a_by_rstar, and inclination_deg are comma-separated in this file. litdf.to_csv(litpath, index=False, header=True, sep=',') lpdf = pd.read_csv(litpath, sep=',') period_guess = float(lpdf['period_day']) return period_guess
def known_pls(name=None, ra=None, dec=None, radius=5.0, table='ps', values='all', verbose=False): #!!Reduce number of columns queried with each iteration for shorter # runtime!! #!!Allow to search for planets that are not confirmed on the archive!! #!!Allow user to pass values through as list to be queried for more # specific query values!! #!!Not working with object parsing!! """ A function to gather information on any known planets in a given system. Queries the NASA Exoplanet Archive for objects and their known parameters. Parameters ---------- name : str Common name of the system being checked. Optional if RA/Dec are provided. ra : float RA in decimal degrees. Optional if name is provided. If provided, Dec is also required. dec : float Dec in decimal degrees. Optional if name is provided. If provided, RA is also required. radius : float Radius in arcseconds around which the provided RA and Dec will be searched for planets. table : str Specifies the table to search for planet parameters. See documentation on the Exoplanet Archive website for a full list of possible tables and their contents. Default is the 'exoplanets' table, which is the default for the Exoplanet Archive. values : str Specifies how many values are collected. Current supported options are 'minimum' and 'all'. verbose : bool Flag to determine whether some of the parameters of the known planets in the system are printed. Returns ------- info : list of dicts List containing a dictionary of all known planet parameters for each planet in the queried system. """ if not name and (not ra or not dec): raise ValueError('Either name or both RA & Dec must be provided') if values == 'minimum': select = ('pl_name, pl_orbper, pl_orbpererr1, pl_orbpererr2, ' + 'pl_tranmid, pl_tranmiderr1, pl_tranmiderr2, pl_trandur, ' + 'pl_trandurerr1, pl_trandurerr2, pl_trandep, pl_trandeperr1,' + ' pl_trandeperr2, pl_ratdor, pl_ratdorerr1, pl_ratdorerr2, ' + 'pl_ratror, pl_ratrorerr1, pl_ratrorerr2, pl_radj, ' + 'pl_radjerr1, pl_radjerr2, pl_bmassj, pl_bmassjerr1, ' + 'pl_bmassjerr2, pl_hostname') else: select = '*' if name is not None: results = nea.query_object(str(name), table=table, select=select) elif ra is not None and dec is not None: results = nea.query_region( coordinates=coord.SkyCoord(ra * u.deg, dec * u.deg), radius = radius * u.arcsec, table=table, select=select ) pls = len(results) if verbose: print(str(pls) + ' known planets found in system') print('Gathering info for each planet...') if pls > 0: names = results.colnames info = [dict(zip(names, row)) for row in results] for i in range(pls): info[i]['t0'] = (Time(val=info[i]['pl_tranmid'].value, format='jd').to_value(format='mjd') - 56999.5) query_fault = False else: query_fault = True if verbose and not query_fault: for i in range(pls): try: pl = info[i] print(pl['pl_name']) print('Period = %.5f +%.5f %.5f %s' % (pl['pl_orbper'].value, pl['pl_orbpererr1'].value, pl['pl_orbpererr2'].value, pl['pl_orbper'].unit)) print('t0 = %.5f +2457000 BTJD +%.5f %.5f' % (pl['t0'], pl['pl_tranmiderr1'].value, pl['pl_tranmiderr2'].value)) print('Duration = %.5f +%.5f %.5f %s' % (pl['pl_trandur'].value, pl['pl_trandurerr1'].value, pl['pl_trandurerr2'].value, pl['pl_trandur'].unit)) print('Transit depth = %.5f +%.5f -%.5f' % (pl['pl_trandep'].value, pl['pl_trandeperr1'].value, pl['pl_trandeperr2'].value)) print('a/Rs = %.5f +%.5f %.5f' % (pl['pl_ratdor'], pl['pl_ratdorerr1'], pl['pl_ratdorerr2'])) print('Rp/Rs = %.5f +%.5f %.5f' % (pl['pl_ratror'], pl['pl_ratrorerr1'], pl['pl_ratrorerr2'])) print('Radius = %.5f +%.5f %.5f %s' % (pl['pl_radj'].value, pl['pl_radjerr1'].value, pl['pl_radjerr2'].value, pl['pl_radj'].unit)) print('Mass = %.5f +%.5f %.5f %s' % (pl['pl_bmassj'].value, pl['pl_bmassjerr1'].value, pl['pl_bmassjerr2'].value, pl['pl_bmassj'].unit)) print('') except: continue elif verbose and query_fault: print('Known planet found but parameters were not found in Exoplanet ' + 'Archive for some reason.') info = None return info
sd18_glat = arr(sd18['b']) * u.rad f_glon = np.isfinite(sd18_glon) f_glat = np.isfinite(sd18_glat) goodflag = (sd18['flag'] == 0) good_sd18_inds = (f_glon) & (f_glat) #& (goodflag) c_sd18 = SkyCoord(sd18_glon[good_sd18_inds], sd18_glat[good_sd18_inds], frame='galactic') c_sd18 = c_sd18.icrs # crossmatch vs exoarchive by ra and dec. ea_tab = NasaExoplanetArchive.get_confirmed_planets_table( all_columns=True, show_progress=True) ea_rad = arr(ea_tab['ra']) * u.deg ea_dec = arr(ea_tab['dec']) * u.deg c_ea = SkyCoord(ra=ea_rad, dec=ea_dec) seplimit = 10 * u.arcsec # do the crossmatch. the first extra step helps by cacheing a kdtree. c_ea_sub = c_ea[:10] idx_ea_sub, idx_sd18, d2d, _ = c_sd18.search_around_sky(c_ea_sub, seplimit) print('beginning crossmatch') idx_ea, idx_sd18, d2d, _ = c_sd18.search_around_sky(c_ea, seplimit) print('completed crossmatch')
def plot_rp_vs_age_scatter(active_targets=1, specialyoung=1): # # columns described at # https://exoplanetarchive.ipac.caltech.edu/docs/API_exoplanet_columns.html # ea_tab = NasaExoplanetArchive.query_criteria(table="exoplanets", select="*", cache=True) # # get systems with finite ages (has a value, and +/- error bar) # has_age_value = ~ea_tab['st_age'].mask has_age_errs = (~ea_tab['st_ageerr1'].mask) & (~ea_tab['st_ageerr2'].mask) has_rp_value = ~ea_tab['pl_rade'].mask has_rp_errs = (~ea_tab['pl_radeerr1'].mask) & (~ea_tab['pl_radeerr2'].mask) transits = (ea_tab['pl_tranflag'] == 1) sel = (has_age_value & has_age_errs & has_rp_value & has_rp_errs & transits) t = ea_tab[sel] tyoung = t[(t['st_age'] < 0.1 * u.Gyr) & (t['st_age'] > 0 * u.Gyr)] # # read params # age = t['st_age'] age_perr = t['st_ageerr1'] age_merr = np.abs(t['st_ageerr2']) age_errs = np.array([age_perr, age_merr]).reshape(2, len(age)) rp = t['pl_rade'] rp_perr = t['pl_radeerr1'] rp_merr = t['pl_radeerr2'] rp_errs = np.array([rp_perr, rp_merr]).reshape(2, len(age)) # rp /= 11.2089 # used jupiter radii # # plot age vs rp. (age is on y axis b/c it has the error bars, and I at # least skimmed the footnotes of Hogg 2010) # fig, ax = plt.subplots(figsize=(4, 3)) label = ('Exoplanet Archive') print(f'Mean age unc: {np.mean(age_errs):.2f} Gyr') print(f'Median age unc: {np.median(age_errs):.2f} Gyr') ax.scatter(age, rp, color='darkgray', s=3, zorder=1, marker='o', linewidth=0, label=label, alpha=1) # # targets # target_age = (np.array([3.5e7]) * u.yr).to(u.Gyr) target_rp = (np.array([0.82]) * u.Rjup).to(u.Rearth) target_rp_unc = (np.array([0.03, 0.09]) * u.Rjup).to(u.Rearth)[:, None] if active_targets: label = ('TOI$\,$837') ax.plot(target_age, target_rp, mew=0.5, markerfacecolor='yellow', markersize=15, marker='*', color='k', lw=0, label=label, zorder=3) if specialyoung: youngnames = tyoung['pl_hostname'] markertypes = ['o', 'v', 'X', 's', 'P', 'd'] for ix, y in enumerate(np.unique(youngnames)): s = (tyoung['pl_hostname'] == y) ax.plot(tyoung[s]['st_age'], tyoung[s]['pl_rade'], mew=0.5, markerfacecolor='white', markersize=7, marker=markertypes[ix], color='k', lw=0, label=y, zorder=2) # two extra systems... N_uniq = len(np.unique(youngnames)) ax.plot(1.5e7 / 1e9, 10.02, mew=0.5, markerfacecolor='white', markersize=7, marker=markertypes[N_uniq], color='k', lw=0, label='HIP 67522', zorder=2) # HD 63433 (TOI 1726, TIC 130181866) omitted -- 400 Myr is old! # flip default legend order handles, labels = ax.get_legend_handles_labels() leg = ax.legend(handles[::-1], labels[::-1], loc='upper left', borderpad=0.3, handletextpad=0.5, fontsize=6, framealpha=0) leg.get_frame().set_linewidth(0.5) ax.set_xlabel('Age [billion years]') ax.set_ylabel('Planet size [Earth radii]') ax.set_xlim([6e-3, 17]) format_ax(ax) # ax.set_ylim([0.13, 85]) # ax.set_yscale('log') ax.set_xscale('log') # ax.tick_params(top=True, bottom=True, left=True, right=True, which='both') # ax.yaxis.set_major_formatter(StrMethodFormatter('{x:.2g}')) savstr = '_no_overplot' if not active_targets else '_toi837' outpath = ( '../results/rp_vs_age_scatter/rp_vs_age_scatter_{}{}.png'.format( today_YYYYMMDD(), savstr)) savefig(fig, outpath, writepdf=1, dpi=400)
# Licensed under a 3-clause BSD style license - see LICENSE.rst import numpy as np import astropy.units as u from astropy.table import Column, Table, unique, vstack from astroquery.nasa_exoplanet_archive import NasaExoplanetArchive exo = NasaExoplanetArchive.get_confirmed_planets_table(all_columns=True) # We don't need the planets for this project that don't have a distance, # know radius or orbital period planet_filter = np.logical_or.reduce( (exo['st_dist'] == 0, exo['pl_radj'] == 0, exo['pl_orbper'] == 0)) to_remove_idx = np.where(planet_filter)[0] exo.remove_rows(to_remove_idx) # We currently can't yet unique a Table that has mixins, but we don't need the # mixins here anyway, so copy what we need to a new table hosts = unique(Table(exo['pl_hostname', 'ra', 'dec', 'st_dist', 'st_teff'])) exoplanets = Table(exo['pl_hostname', 'pl_name', 'pl_orbper', 'pl_radj', 'pl_orbsmax', 'pl_orbeccen']) # Add the Solar System manually hosts.add_row(['Sun', 0, 0, 0, 5777])
def plot_rp_vs_insol_scatter(active_targets=1, specialyoung=1, show_legend=1): set_style() # # columns described at # https://exoplanetarchive.ipac.caltech.edu/docs/API_exoplanet_columns.html # ea_tab = NasaExoplanetArchive.query_criteria( table="exoplanets", select="*", cache=True ) # # get systems with finite ages (has a value, and +/- error bar) # has_age_value = ~ea_tab['st_age'].mask has_age_errs = (~ea_tab['st_ageerr1'].mask) & (~ea_tab['st_ageerr2'].mask) has_rp_value = ~ea_tab['pl_rade'].mask has_rp_errs = (~ea_tab['pl_radeerr1'].mask) & (~ea_tab['pl_radeerr2'].mask) rp_gt_0 = (ea_tab['pl_rade'] > 0) transits = (ea_tab['pl_tranflag']==1) sel = ( has_age_value & has_age_errs & has_rp_value & has_rp_errs & transits & rp_gt_0 ) t = ea_tab[sel] tyoung = t[(t['st_age'] < 0.1*u.Gyr) & (t['st_age'] > 0*u.Gyr)] # # read params # age = t['st_age'] age_perr = t['st_ageerr1'] age_merr = np.abs(t['st_ageerr2']) age_errs = np.array([age_perr, age_merr]).reshape(2, len(age)) rp = t['pl_rade'] rp_perr = t['pl_radeerr1'] rp_merr = t['pl_radeerr2'] rp_errs = np.array([rp_perr, rp_merr]).reshape(2, len(age)) # rp /= 11.2089 # used jupiter radii insol = t['pl_insol'] # # plot age vs rp. (age is on y axis b/c it has the error bars, and I at # least skimmed the footnotes of Hogg 2010) # fig,ax = plt.subplots(figsize=(4,3)) label = ( 'Exoplanet Archive' ) print(f'Mean age unc: {np.mean(age_errs):.2f} Gyr') print(f'Median age unc: {np.median(age_errs):.2f} Gyr') ax.scatter(insol, rp, color='darkgray', s=3, zorder=1, marker='o', linewidth=0, label=label, alpha=1) # # targets # target_age = (np.array([3.5e7])*u.yr).to(u.Gyr) target_rp = (np.array([0.82])*u.Rjup).to(u.Rearth) target_rp_unc = (np.array([0.03, 0.09])*u.Rjup).to(u.Rearth)[:,None] target_period = (np.array([8.3])*u.day) from astropy import constants as const Teff = 6047*u.K Lstar = 4*np.pi*(1.022*u.Rsun)**2 * (const.sigma_sb * Teff**4) target_insol = ( ( Lstar/(1*u.Lsun) ).cgs * ((( 17.54*1.022*u.Rsun )/(1*u.AU)).cgs)**(-2) ) # insol/insolEarth = (L*/Lsun) * (AU/a)^2 if active_targets: label = ( 'TOI$\,$837' ) ax.plot(target_insol, target_rp, mew=0.5, markerfacecolor='yellow', markersize=15, marker='*', color='k', lw=0, label=label, zorder=10) if specialyoung: youngnames = tyoung['pl_hostname'] markertypes= ['o', 'v', 'X', 's', 'P', 'd'] zorders= [9, 8, 7, 6, 5, 4] for ix, y, z in zip(range(len(zorders)), np.unique(youngnames), zorders): s = (tyoung['pl_hostname'] == y) ax.plot(tyoung[s]['pl_orbper'], tyoung[s]['pl_rade'], mew=0.5, markerfacecolor='white', markersize=7, marker=markertypes[ix], color='k', lw=0, label=y, zorder=z) # two extra systems... N_uniq = len(np.unique(youngnames)) insol_67522 = (1.74) * (( (11.73*1.38*u.Rsun) / (1*u.AU) ).cgs)**(-2) ax.plot(insol_67522, 10.02, mew=0.5, markerfacecolor='white', markersize=7, marker=markertypes[N_uniq], color='k', lw=0, label='HIP 67522', zorder=2) # HD 63433 (TOI 1726, TIC 130181866) omitted -- 400 Myr is old! # flip default legend order if show_legend: handles, labels = ax.get_legend_handles_labels() leg = ax.legend(handles[::-1], labels[::-1], loc='upper right', borderpad=0.3, handletextpad=0.5, fontsize=6, framealpha=0) leg.get_frame().set_linewidth(0.5) ax.set_xlabel('Planet insolation [Earth flux]') ax.set_ylabel('Planet size [Earth radii]') #ax.set_xlim(list(ax.get_xlim())[::-1]) ax.set_xlim([1e5, 0.1]) format_ax(ax) # ax.set_ylim([0.13, 85]) # ax.set_yscale('log') ax.set_xscale('log') # ax.tick_params(top=True, bottom=True, left=True, right=True, which='both') # ax.yaxis.set_major_formatter(StrMethodFormatter('{x:.2g}')) savstr = '_no_overplot' if not active_targets else '_toi837' if show_legend: savstr += '_yeslegend' else: savstr += '_nolegend' outpath = ( '../results/rp_vs_insol_scatter/rp_vs_insol_scatter_{}{}.png'. format(today_YYYYMMDD(), savstr) ) savefig(fig, outpath, writepdf=1, dpi=400)
def plot_rp_vs_age_scatter(active_targets=1, specialyoung=1, showcandidates=0, deemph837=0): set_style() # # columns described at # https://exoplanetarchive.ipac.caltech.edu/docs/API_exoplanet_columns.html # ea_tab = NasaExoplanetArchive.query_criteria( table="exoplanets", select="*", cache=True ) # # get systems with finite ages (has a value, and +/- error bar) # has_age_value = ~ea_tab['st_age'].mask has_age_errs = (~ea_tab['st_ageerr1'].mask) & (~ea_tab['st_ageerr2'].mask) has_rp_value = ~ea_tab['pl_rade'].mask has_rp_errs = (~ea_tab['pl_radeerr1'].mask) & (~ea_tab['pl_radeerr2'].mask) rp_gt_0 = (ea_tab['pl_rade'] > 0) transits = (ea_tab['pl_tranflag']==1) sel = ( has_age_value & has_age_errs & has_rp_value & has_rp_errs & transits & rp_gt_0 ) t = ea_tab[sel] tyoung = t[(t['st_age'] < 0.1*u.Gyr) & (t['st_age'] > 0*u.Gyr)] # # read params # age = t['st_age'] age_perr = t['st_ageerr1'] age_merr = np.abs(t['st_ageerr2']) age_errs = np.array([age_perr, age_merr]).reshape(2, len(age)) rp = t['pl_rade'] rp_perr = t['pl_radeerr1'] rp_merr = t['pl_radeerr2'] rp_errs = np.array([rp_perr, rp_merr]).reshape(2, len(age)) # rp /= 11.2089 # used jupiter radii # # plot age vs rp. (age is on y axis b/c it has the error bars, and I at # least skimmed the footnotes of Hogg 2010) # fig,ax = plt.subplots(figsize=(4,3)) label = ( 'Exoplanet Archive' ) print(f'Mean age unc: {np.mean(age_errs):.2f} Gyr') print(f'Median age unc: {np.median(age_errs):.2f} Gyr') print(42*'-') print('Ages below 500 Myr:') _t = t[(t['st_age'] < 0.5*u.Gyr) & (t['st_age'] > 0*u.Gyr)] _t.sort('st_age') print(_t['st_age', 'pl_hostname', 'pl_rade', 'pl_orbper']) print(42*'-') ax.scatter(age*1e9, rp, color='darkgray', s=3, zorder=1, marker='o', linewidth=0, label=label, alpha=1) # # targets # target_age = (np.array([3.5e7])*u.yr).to(u.Gyr) target_rp = (np.array([0.77])*u.Rjup).to(u.Rearth) target_rp_unc = (np.array([0.07, 0.09])*u.Rjup).to(u.Rearth)[:,None] if active_targets: label = ( 'TOI$\,$837' ) mfc = 'yellow' if not deemph837 else 'white' ms = 15 if not deemph837 else 8 ax.plot(target_age*1e9, target_rp, mew=0.5, markerfacecolor=mfc, markersize=ms, marker='*', color='k', lw=0, label=label, zorder=3) if specialyoung: youngnames = tyoung['pl_hostname'] markertypes= ['o', 'v', 'X', 's', 'P', 'd'] for ix, y in enumerate(np.unique(youngnames)): s = (tyoung['pl_hostname'] == y) ax.plot(tyoung[s]['st_age']*1e9, tyoung[s]['pl_rade'], mew=0.5, markerfacecolor='white', markersize=7, marker=markertypes[ix], color='k', lw=0, label=y, zorder=2) # two extra systems... N_uniq = len(np.unique(youngnames)) ax.plot(1.5e7, 10.02, mew=0.5, markerfacecolor='white', markersize=7, marker=markertypes[N_uniq], color='k', lw=0, label='HIP 67522', zorder=2) # HD 63433 (TOI 1726, TIC 130181866) omitted -- 400 Myr is old! if showcandidates: from cdips_followup.manage_candidates import get_candidate_params vdf, sdf, _age, _rp, _rp_unc, _period = ( get_candidate_params(isvalidated=0, ismanualsubset=1) ) l = 'New Planet Candidates' if not deemph837 else 'Active Targets' ax.plot(_age*1e9, _rp, mew=0.5, markerfacecolor='lightskyblue', markersize=8, marker='*', color='k', lw=0, label=l, zorder=1) # flip default legend order handles, labels = ax.get_legend_handles_labels() leg = ax.legend(handles[::-1], labels[::-1], loc='upper left', borderpad=0.3, handletextpad=0.5, fontsize=6, framealpha=0) leg.get_frame().set_linewidth(0.5) ax.set_xlabel('Age [years]') ax.set_ylabel('Planet size [Earth radii]') ax.set_xlim([6e-3*1e9, 17*1e9]) format_ax(ax) ax.set_xscale('log') savstr = '_no_overplot' if not active_targets else '_toi837' if showcandidates: savstr += '_showcandidates' if deemph837: savstr += '_deemph837' outpath = ( '../results/rp_vs_age_scatter/rp_vs_age_scatter_{}{}.png'. format(today_YYYYMMDD(), savstr) ) savefig(fig, outpath, writepdf=1, dpi=400)
import numpy as np import matplotlib.pyplot as plt import os pwd = os.getcwd() plt.ion() from astroquery.nasa_exoplanet_archive import NasaExoplanetArchive pl = NasaExoplanetArchive.get_confirmed_planets_table() pl.keys() jup_to_sun = 1.89813e30 / 1.989e33 m = pl['pl_bmassj'].value # [M_J] mu = pl['pl_bmassjerr1'].value # upper bound ml = pl['pl_bmassjerr2'].value # lower pl['pl_bmassjlim'].value # whether the mass is M sin i d = pl['st_dist'].value # [pc] du = pl['st_disterr1'].value # upper dl = pl['st_disterr2'].value # lower #m *= jup_to_sun # [M_\odot] #mu *= jup_to_sun #ml *= jup_to_sun bins = np.logspace(-3, np.log10(50), 100) hist, bin_edges = np.histogram(m, bins) hist, bin_edges print(np.sum(hist), 'planets in bins.\n', len(m), 'planets in dataset.')
def plot_mass_vs_period_scatter(active_targets=1, specialyoung=1, show_legend=1): set_style() # # columns described at # https://exoplanetarchive.ipac.caltech.edu/docs/API_exoplanet_columns.html # ea_tab = NasaExoplanetArchive.query_criteria(table="exoplanets", select="*", cache=True) # # get systems with finite ages (has a value, and +/- error bar) # has_age_value = ~ea_tab['st_age'].mask has_age_errs = (~ea_tab['st_ageerr1'].mask) & (~ea_tab['st_ageerr2'].mask) has_rp_value = ~ea_tab['pl_rade'].mask has_rp_errs = (~ea_tab['pl_radeerr1'].mask) & (~ea_tab['pl_radeerr2'].mask) has_mp_value = ~ea_tab['pl_massj'].mask has_mp_errs = (~ea_tab['pl_massjerr1'].mask) & ( ~ea_tab['pl_massjerr2'].mask) rp_gt_0 = (ea_tab['pl_rade'] > 0) mp_gt_0 = (ea_tab['pl_massj'] > 0) transits = (ea_tab['pl_tranflag'] == 1) sel = ( has_age_value & has_age_errs & has_mp_value & mp_gt_0 # has_rp_value & has_rp_errs & transits & rp_gt_0 ) t = ea_tab[sel] tyoung = t[(t['st_age'] < 0.1 * u.Gyr) & (t['st_age'] > 0 * u.Gyr)] # # read params # age = t['st_age'] age_perr = t['st_ageerr1'] age_merr = np.abs(t['st_ageerr2']) age_errs = np.array([age_perr, age_merr]).reshape(2, len(age)) mp = t['pl_massj'] # rp /= 11.2089 # used jupiter radii period = t['pl_orbper'] # # plot age vs rp. (age is on y axis b/c it has the error bars, and I at # least skimmed the footnotes of Hogg 2010) # fig, ax = plt.subplots(figsize=(4, 3)) label = ('Exoplanet Archive') print(f'Mean age unc: {np.mean(age_errs):.2f} Gyr') print(f'Median age unc: {np.median(age_errs):.2f} Gyr') ax.scatter(period, mp, color='darkgray', s=3, zorder=1, marker='o', linewidth=0, label=label, alpha=1) # # targets # target_age = (np.array([3.5e7]) * u.yr).to(u.Gyr) target_rp = (np.array([0.77]) * u.Rjup).to(u.Rearth) target_rp_unc = (np.array([0.07, 0.09]) * u.Rjup).to(u.Rearth)[:, None] target_period = (np.array([8.3]) * u.day) if active_targets: raise NotImplementedError('uber young planets dont have masses!') label = ('TOI$\,$837') ax.plot(target_period, target_rp, mew=0.5, markerfacecolor='yellow', markersize=15, marker='*', color='k', lw=0, label=label, zorder=10) if specialyoung: youngnames = tyoung['pl_hostname'] markertypes = ['o', 'v', 'X', 's', 'P', 'd'] zorders = [9, 8, 7, 6, 5, 4] for ix, y, z in zip(range(len(zorders)), np.unique(youngnames), zorders): s = (tyoung['pl_hostname'] == y) ax.plot(tyoung[s]['pl_orbper'], tyoung[s]['pl_rade'], mew=0.5, markerfacecolor='white', markersize=7, marker=markertypes[ix], color='k', lw=0, label=y, zorder=z) # two extra systems... N_uniq = len(np.unique(youngnames)) ax.plot(6.9596, 10.02, mew=0.5, markerfacecolor='white', markersize=7, marker=markertypes[N_uniq], color='k', lw=0, label='HIP 67522', zorder=2) # HD 63433 (TOI 1726, TIC 130181866) omitted -- 400 Myr is old! # flip default legend order if show_legend: handles, labels = ax.get_legend_handles_labels() leg = ax.legend(handles[::-1], labels[::-1], loc='upper right', borderpad=0.3, handletextpad=0.5, fontsize=6, framealpha=0) leg.get_frame().set_linewidth(0.5) ax.set_xlabel('Orbital period [days]') ax.set_ylabel('Planet mass [Jupiter masses]') ax.set_xlim([0.1, 1100]) ax.set_ylim([0.001, 100]) format_ax(ax) # ax.set_ylim([0.13, 85]) ax.set_yscale('log') ax.set_xscale('log') # ax.tick_params(top=True, bottom=True, left=True, right=True, which='both') # ax.yaxis.set_major_formatter(StrMethodFormatter('{x:.2g}')) savstr = '_no_overplot' if not active_targets else '_toi837' if show_legend: savstr += '_yeslegend' else: savstr += '_nolegend' outpath = ( '../results/mass_vs_period_scatter/mass_vs_period_scatter_{}{}.png'. format(today_YYYYMMDD(), savstr)) savefig(fig, outpath, writepdf=1, dpi=400)
import os import pandas as pd import numpy as np from astroquery.nasa_exoplanet_archive import NasaExoplanetArchive as query # reads a data file (.csv) from a designated file path params_df = pd.read_csv("\\path\\to\\data") # retrieves data from the archive through astroquery exoplanet_archive_table = query.get_confirmed_planets_table() # pl_hostname refers to the the planet's star host names # pl_pnum refers to the number of planets around the host star_names = exoplanet_archive_table["pl_hostname"] num_of_planets = exoplanet_archive_table["pl_pnum"] def create_new_df(names, num_of_planets): """Creates a new pandas DataFrame that will be used to add to an existing data set Arguments: names {astropy.table.column.MaskedColumn} -- a column of host star names num_of_planets {astropy.table.column.MaskedColumn} -- a column of the number of planets for each star in the names column Returns: pandas.DataFrame -- consisting of the star names and number of planets as two columns """ names_df = pd.Series(data=star_names)
def plot_rp_vs_age_scatter(active_targets=0, split_toi_ctoi=0, hjs_only=0, ismanualsubset=0, isvalidated=0, ispublictalk=0): # # columns described at # https://exoplanetarchive.ipac.caltech.edu/docs/API_exoplanet_columns.html # ea_tab = NasaExoplanetArchive.query_criteria(table="exoplanets", select="*", cache=True) # # get systems with finite ages (has a value, and +/- error bar) # has_age_value = ~ea_tab['st_age'].mask has_age_errs = (~ea_tab['st_ageerr1'].mask) & (~ea_tab['st_ageerr2'].mask) has_rp_value = ~ea_tab['pl_rade'].mask has_rp_errs = (~ea_tab['pl_radeerr1'].mask) & (~ea_tab['pl_radeerr2'].mask) transits = (ea_tab['pl_tranflag'] == 1) sel = (has_age_value & has_age_errs & has_rp_value & has_rp_errs & transits) t = ea_tab[sel] if hjs_only: is_hj = (t['pl_orbper'] < 10 * u.day) & (t['pl_rade'] > 7) t = t[is_hj] # # read params # age = t['st_age'] age_perr = t['st_ageerr1'] age_merr = np.abs(t['st_ageerr2']) age_errs = np.array([age_perr, age_merr]).reshape(2, len(age)) rp = t['pl_rade'] rp_perr = t['pl_radeerr1'] rp_merr = t['pl_radeerr2'] rp_errs = np.array([rp_perr, rp_merr]).reshape(2, len(age)) # # plot age vs rp. (age is on y axis b/c it has the error bars, and I at # least skimmed the footnotes of Hogg 2010) # set_style() f, ax = plt.subplots(figsize=(4, 3)) label = ('Exoplanet Archive, ' + r"$\langle \sigma_{{\mathrm{{age}}}} \rangle$ = " + "{:.1f} Gyr".format(np.median(age_errs))) color = 'C1' if hjs_only: label = ('Known hot Jupiters') rp /= 11.2089 # used jupiter radii color = 'C1' if ispublictalk: label = 'Known' color = 'lightgray' ax.scatter(age, rp, color=color, s=3, zorder=1, marker='o', linewidth=0, label=label, alpha=1) # # targets # from cdips_followup.manage_candidates import get_candidate_params vdf, sdf, target_age, target_rp, target_rp_unc, target_period = ( get_candidate_params(isvalidated=isvalidated, ismanualsubset=ismanualsubset)) if active_targets: label = (r'Active targets, $\langle \sigma_{{\mathrm{{age}}}} \rangle$' '< 0.1 Gyr') if hjs_only: label = ('Possible hot Jupiters') istoi = ~(sdf.toi == '--') if split_toi_ctoi: ax.scatter(target_age[istoi], target_rp[istoi], color='C0', s=10, zorder=3, marker='s', linewidth=0) ax.scatter(target_age[~istoi], target_rp[~istoi], color='C0', s=25, zorder=3, marker='*', linewidth=0, label=label) elif hjs_only: hj = (target_rp > 7) & (target_rp < 29) ax.scatter(target_age[hj], target_rp[hj] / 11.2089, color='C0', s=35, zorder=3, marker='*', linewidth=0, label=label) else: if isvalidated: if len(vdf) > 1: raise NotImplementedError('might want to just assign ages') val_age = 4e7 / 1e9 val_rp = np.array(vdf.rp) ax.plot(val_age, val_rp, mew=0.5, markerfacecolor='yellow', markersize=12, marker='*', color='k', lw=0, label='Validated', zorder=4) ax.scatter(target_age, target_rp, s=40, color='C0', zorder=3, marker='*', linewidth=0, label="Potential") else: ax.scatter(target_age, target_rp, color='C0', s=25, zorder=3, marker='*', linewidth=0, label=label) sel = (~pd.isnull(target_age)) & (~pd.isnull(target_rp)) print('{} targets w/ finite ages and radii'.format(len( target_age[sel]))) print('{} targets w/ finite ages and radii that are TOIs'.format( len(target_age[sel & istoi]))) print('{} targets w/ finite ages and radii that are not TOIs'.format( len(target_age[sel & ~istoi]))) target_rp_rel_unc = target_rp_unc / target_rp ########## if hjs_only: # HACK: force to 10% relative uncertainty (eep) sel = target_rp_rel_unc > 0.1 target_rp_unc[sel] = target_rp[sel] * 0.1 * (np.random.uniform( 0.8, 1.2, size=len(target_rp[sel]))) else: # HACK: for the one very small object... sel = target_rp_rel_unc > 0.33 target_rp_unc[sel] = target_rp[sel] * 0.33 ########## if hjs_only: pass #ax.errorbar(target_age[hj], target_rp[hj], yerr=target_rp_unc[hj], # elinewidth=0.3, ecolor='k', capsize=0, capthick=0, # linewidth=0, fmt='*', ms=0, zorder=2, color='black', # alpha=0.5) else: if not ispublictalk: ax.errorbar(target_age, target_rp, yerr=target_rp_unc, elinewidth=0.3, ecolor='k', capsize=0, capthick=0, linewidth=0, fmt='*', ms=0, zorder=2, color='black', alpha=0.5) # flip default legend order handles, labels = ax.get_legend_handles_labels() if not hjs_only: leg = ax.legend(handles[::-1], labels[::-1], loc='lower left', borderpad=0.3, handletextpad=0.3, fontsize='small', framealpha=1) else: leg = ax.legend(handles[::-1], labels[::-1], loc='upper right', borderpad=0.3, handletextpad=0.3, fontsize='small', framealpha=0) leg.get_frame().set_linewidth(0.5) ax.set_xlabel('Planet age [billion years]') ax.set_ylabel('Planet size [Earth radii]') if hjs_only: ax.set_ylabel('Planet size [Jupiter radii]') ax.set_xlim([6e-3, 17]) if not hjs_only: ax.set_ylim([0.13, 85]) ax.set_yscale('log') if hjs_only: ax.set_ylim([0.1, 3]) ax.set_yscale('linear') ax.set_xscale('log') if hjs_only: ax.xaxis.set_major_formatter(StrMethodFormatter('{x:.2g}')) else: ax.yaxis.set_major_formatter(StrMethodFormatter('{x:.2g}')) f.tight_layout() savstr = '_no_overplot' if not active_targets else '_active_targets' if split_toi_ctoi: savstr += '_split_ctoi' if hjs_only: savstr += '_onlyhjs' if ispublictalk: savstr += '_ispublic' if isvalidated: savstr += '_hasvalidated' outpath = ( '../results/rp_vs_age_scatter/rp_vs_age_scatter_{}{}.png'.format( today_YYYYMMDD(), savstr)) f.savefig(outpath, bbox_inches='tight', dpi=450) f.savefig(outpath.replace('.png', '.pdf'), bbox_inches='tight') print('made {}'.format(outpath))
def calculate_pdots(signifiant_trends=1): if signifiant_trends: datapath = '../data/Knutson_2014_tables7_and_8_joined.csv' else: datapath = '../data/Knutson_2014_tables7_and_8_joined_limits.csv' df = pd.read_csv(datapath) k14_plnames = nparr(df.planet) gamma_dot_value = nparr(df.gammadot) * (u.m / u.s) / u.day gamma_dot_perr = nparr(df.gammadot_pluserr) * (u.m / u.s) / u.day gamma_dot_merr = nparr(df.gammadot_minuserr) * (u.m / u.s) / u.day gamma_dot_upper_limit = (gamma_dot_value + 1 * gamma_dot_perr) gamma_dot_lower_limit = (gamma_dot_value - 1 * gamma_dot_merr) # # get orbital periods for all the planets # manual periods: # * XO-2b fails because host star is binary; planets are known around both # components. # * HAT-P-10 = WASP-11 # t = NasaExoplanetArchive.get_confirmed_planets_table(all_columns=False) ea_df = t.to_pandas() selcols = ['pl_name', 'pl_orbper'] ea_seldf = ea_df[selcols] mdf = df.merge(ea_seldf, left_on='planet', right_on='pl_name', how='left') if signifiant_trends: mdf.loc[mdf['planet'] == 'XO-2 b', 'pl_orbper'] = 2.615862 mdf.loc[mdf['planet'] == 'HAT-P-10 b', 'pl_orbper'] = 3.7224690 else: badnames = ['GJ436 b', 'HD149026 b'] badnameperiods = [2.643904, '2.87588874'] for n, per in zip(badnames, badnameperiods): mdf.loc[mdf['planet'] == n, 'pl_orbper'] = per # # calculate Pdot # P = nparr(mdf['pl_orbper']) * u.day dP_dt_value = gamma_dot_value * P / c.c dP_dt_upper_limit = gamma_dot_upper_limit * P / c.c dP_dt_lower_limit = gamma_dot_lower_limit * P / c.c # # insert into data frame and save # mdf['Pdot'] = dP_dt_value.to(u.millisecond / u.year) mdf['Pdot_upper_limit'] = dP_dt_upper_limit.to(u.millisecond / u.year) mdf['Pdot_lower_limit'] = dP_dt_lower_limit.to(u.millisecond / u.year) mdf['Pdot_perr'] = (dP_dt_upper_limit.to(u.millisecond / u.year) - dP_dt_value.to(u.millisecond / u.year)) mdf['Pdot_merr'] = (dP_dt_value.to(u.millisecond / u.year) - dP_dt_lower_limit.to(u.millisecond / u.year)) if signifiant_trends: outpath = '../results/knutson_significant_population_pdots.csv' else: outpath = '../results/knutson_limit_population_pdots.csv' mdf.to_csv(outpath, sep=';', index=False) print('made {}'.format(outpath)) return mdf
def get_data(self, by_method: bool = True, by_class: bool = True, cache: bool = True): """ Get the current total number of confirmed exoplanets from the NASA Exoplanet Archive. Additionally, also get the number of exoplanets grouped by detection method or by planet class (if desired). Args: by_method: Whether or not to also return the exoplanet count grouped by detection method. by_class: Whether or not to also return the exoplanet count grouped by (approximate) planet class. cache: Whether or not to cache results or use cached results. Returns: A dictionary with keys `{"total", "by_method", "by_class"}` which holds the respective count of exoplanets. """ # Instantiate the dictionary that will hold the results exoplanet_count = dict() # Get the confirmed exoplanets form the NASA Exoplanet Archive. # In case we do not have internet access (and thus get an URLError), # the function ends here already (i.e., self.data will remain None). try: confirmed_exoplanets = \ NasaExoplanetArchive.get_confirmed_planets_table(cache=cache) except URLError: return # Get the total count of all confirmed planets exoplanet_count['total'] = len(confirmed_exoplanets) # Get count by detection method if by_method: exoplanet_count['by_method'] = \ dict(Counter(list(confirmed_exoplanets['pl_discmethod']))) # Get count by planet class (by looping over all confirmed exoplanets # and classifying each of them based on its respective mass and radius) if by_class: # Initialize the sub-dictionary that will hold the counts per class exoplanet_count['by_class'] = dict() # Loop over all confirmed exoplanets and classify them individually for i in range(len(confirmed_exoplanets)): # Get the mass and radius and cast to a astropy.units.Quantity # Note: The NASA Exoplanet Archive usually returns values in # Jupiter units. mass = float( str(confirmed_exoplanets[i]['pl_bmassj']).split()[0]) mass = u.Quantity(mass, u.jupiterMass) radius = float( str(confirmed_exoplanets[i]['pl_radj']).split()[0]) radius = u.Quantity(radius, u.jupiterRad) # Classify the exoplanet based on these values planet_class = get_exoplanet_class(mass=mass, radius=radius) # Increase the count for the planet class if planet_class in exoplanet_count['by_class'].keys(): exoplanet_count['by_class'][planet_class] += 1 else: exoplanet_count['by_class'][planet_class] = 1 # Store away the data retrieved by this method self.data = exoplanet_count
def plot_population(): """This plots the exoplanet population to create a plot of selectable planets in the exoplanet population It is based off a Gist by Brett Morris (github bmorris3), pulling it from Notebook form and adding an interactive plot. Jens Hoeijmakers, 04-05-2020""" import numpy as np import matplotlib.pyplot as plt import astropy.units as u from astroquery.nasa_exoplanet_archive import NasaExoplanetArchive #First establish the rules that a planet must satisfy in order to be printed / highlighted. teq_min = 1000 * u.K teq_max = 1300 * u.K rad_min = 2 * u.R_earth rad_max = 4 * u.R_earth gaia_mag_limit = 13 P_min = 0.0 * u.day P_max = 1.0 * u.day #Read the archive and compute the equilibrium temperature. #TO DO: SOME PLANETS FALL OUT BECAUSE THEY DONT HAVE A STELLAR EFFECTIVE TEMPERATURE AND/OR STELLAR RADIUS. #HOWEVER THESE CAN BE APPROXIMATED FROM THE SPECTRAL TYPE. FOR EACH MISSING VALUE, I NEED TO LOOK UP WHAT A STAR WITH #THAT SPECTRAL TYPE TYPICALLY HAS FOR VALUES OF R_S AND T_EFF, AND REPLACE THOSE. table = NasaExoplanetArchive.get_confirmed_planets_table(all_columns=True)#This is an astropy table. transiting = table[(table['pl_tranflag'].data).astype(bool)]#Select only the transiting ones, and put them in a new table. rp = transiting['pl_radj']#Short-hand for planet radii. equilibrium_temperature = (transiting['st_teff'] * np.sqrt(transiting['st_rad'] / 2 / transiting['pl_orbsmax'])).decompose()#Compute T_eq. g = transiting['gaia_gmag'].quantity#Short-hand for the Gaia magnitude. P = transiting['pl_orbper'] transiting['teq'] = equilibrium_temperature #Create boolean arrays for selecting the rows in the table, based on the above rules. temp_constraints = (equilibrium_temperature < teq_max) & (equilibrium_temperature > teq_min) rad_constraints = (rp < rad_max) & (rp > rad_min) gmag_constaints = (g < gaia_mag_limit) P_constraints = (P > P_min) & (P < P_max) targets = transiting[temp_constraints & rad_constraints & gmag_constaints]#These are the highlighted planets. targets = transiting[P_constraints] targets.sort('gaia_gmag') targets['r_earth'] = targets['pl_radj'].to(u.R_earth) targets[['pl_name', 'gaia_gmag', 'teq', 'r_earth', 'pl_orbper','st_rad','st_teff','st_spstr']].pprint(max_lines=1000) #Now we move on to plotting the population #These are rules for the planets that will be plotted as gray background points. has_rp = (rp > 0.0)#There needs to be a radius has_rs = (transiting['st_rad'] > 0)#...a stellar radius has_teff = (transiting['st_teff'] > 0)#... a stellar T_eff # is_spt = (transiting['st_spstr'].astype(str) == 'K2 V')#Test for being a particular spectral type. Will be needed to fill in systems with missing effective temperatures. systems_to_plot = transiting[has_rp & has_rs & has_teff]#Only transiting planets here. fig,ax = plt.subplots() sc = plt.scatter(systems_to_plot['teq'],systems_to_plot['pl_radj'].to(u.R_earth),c='gray',s=20,alpha=0.5) sct=plt.scatter(targets['teq'],targets['pl_radj'].to(u.R_earth),c='orange',s=20,alpha=0.5) ax.set_ylabel('Radius ($R_E$)') ax.set_xlabel('Equilibrium temperature (K)') ax.set_title('Temperature versus Radius') ax.set_xlim(ax.get_xlim()[::-1]) #And this is all annotation, taken from : annot = ax.annotate("", xy=(0,0), xytext=(20,20),textcoords="offset points",bbox=dict(boxstyle="round", fc="w"),arrowprops=dict(arrowstyle="->")) annot.set_visible(False) names = systems_to_plot['pl_name'] gmags = systems_to_plot['gaia_gmag'] Ps = systems_to_plot['pl_orbper'] def update_annot_new(ind): pos = sc.get_offsets()[ind["ind"][0]] annot.xy = pos text='' n_in = len(ind["ind"]) prefix=''#This becomes a newline if the forloop is run through more than once. for n in ind["ind"]: text+=prefix+names[n]+'\n' text+=' G = %s \n'%np.round(gmags[n],2) text+=' P = %s'%np.round(Ps[n],2) prefix='\n' # text = "{}, {}".format(" ".join(list(map(str,ind["ind"])))," ".join([names[n] for n in ind["ind"]])) annot.set_text(text) annot.get_bbox_patch().set_alpha(0.4) def newhover(event): vis = annot.get_visible() if event.inaxes == ax: cont, ind = sc.contains(event) if cont: update_annot_new(ind) annot.set_visible(True) fig.canvas.draw_idle() else: if vis: annot.set_visible(False) fig.canvas.draw_idle() fig.canvas.mpl_connect("motion_notify_event", newhover) plt.show()
from astropy.visualization import astropy_mpl_style, quantity_support plt.style.use(astropy_mpl_style) quantity_support() from astropy.coordinates import get_sun from astroquery.nasa_exoplanet_archive import NasaExoplanetArchive from astroquery.exoplanet_orbit_database import ExoplanetOrbitDatabase #primary_eclipse_time = Time(2452826.628514, format='jd') #orbital_period = 3.52474859 * u.day #eclipse_duration = 0.1277 * u.day # #hd209458 = EclipsingSystem(primary_eclipse_time=primary_eclipse_time, # orbital_period=orbital_period, duration=eclipse_duration, # name='HD 209458 b') planet_properties = NasaExoplanetArchive.query_planet('TRAPPIST-1 b', all_columns=True) # get relevant planet properties epoch = Time(planet_properties['pl_tranmid'], format='jd') period = planet_properties['pl_orbper'] transit_duration = planet_properties['pl_trandur'] * u.day # Create an EclipsingSystem object for HD 209458 #from astroplan import EclipsingSystem trappist1b = astroplan.EclipsingSystem(primary_eclipse_time=epoch, orbital_period=period, duration=transit_duration) # Calculate next three mid-transit times which occur after ``obs_time`` obs_time = Time('2017-01-01 12:00') trappist1b.next_primary_eclipse_time(obs_time, n_eclipses=3)
def plot_rp_vs_age_scatter(active_targets=0): # columns described at # https://exoplanetarchive.ipac.caltech.edu/docs/API_exoplanet_columns.html ea_tab = NasaExoplanetArchive.get_confirmed_planets_table( all_columns=True, show_progress=True) # get systems with finite ages (has a value, and +/- error bar) has_age_value = ~ea_tab['st_age'].mask has_age_errs = (~ea_tab['st_ageerr1'].mask) & (~ea_tab['st_ageerr2'].mask) has_rp_value = ~ea_tab['pl_rade'].mask has_rp_errs = (~ea_tab['pl_radeerr1'].mask) & (~ea_tab['pl_radeerr2'].mask) transits = (ea_tab['pl_tranflag'] == 1) sel = (has_age_value & has_age_errs & has_rp_value & has_rp_errs & transits) t = ea_tab[sel] # # read params # age = t['st_age'] age_perr = t['st_ageerr1'] age_merr = np.abs(t['st_ageerr2']) age_errs = np.array([age_perr, age_merr]).reshape(2, len(age)) rp = t['pl_rade'] rp_perr = t['pl_radeerr1'] rp_merr = t['pl_radeerr2'] rp_errs = np.array([rp_perr, rp_merr]).reshape(2, len(age)) # plot age vs all "good cols". (age is on y axis b/c it has the error bars, and # I at least skimmed the footnotes of Hogg 2010) f, ax = plt.subplots(figsize=(4, 3)) # squares label = ('NASA Exoplanet Archive, ' + r"$\langle \sigma_{{\mathrm{{age}}}} \rangle$ = " + "{:.1f} Gyr".format(np.median(age_errs))) ax.scatter(age, rp, color='gray', s=3, zorder=1, marker='o', linewidth=0, label=label, alpha=1) # targets tdf = pd.read_csv( os.path.join( os.path.expanduser("~"), 'Dropbox/proj/cdips_followup/results/20190926_2020A_targets_age_rp.csv' )) badids = [ 4827527233363019776, 2919143383943171200, 3340674976430098688, 5561614350584396800, 5618515825371166464 ] tdf = tdf[~tdf['source_id'].isin(badids)] target_age = 10**(np.array(tdf['age'])) / (1e9) target_rp = np.array(tdf['rplanet']) target_rp_unc = np.array(tdf['rplanet_unc']) if active_targets: ax.scatter( target_age, target_rp, color='black', s=25, zorder=3, marker='*', linewidth=0, label= r'Active targets, $\langle \sigma_{{\mathrm{{age}}}} \rangle$ < 0.1 Gyr' ) target_rp_rel_unc = target_rp_unc / target_rp ########## # HACK: force to 30% relative uncertainty for TOI-520, b/c fits did not # converge sel = target_rp_rel_unc > 0.5 target_rp_unc[sel] = target_rp[sel] * 0.3 ########## ax.errorbar(target_age, target_rp, yerr=target_rp_unc, elinewidth=0.3, ecolor='k', capsize=0, capthick=0, linewidth=0, fmt='*', ms=0, zorder=2, color='black', alpha=0.5) ## error bars #ax.errorbar(age, rp, yerr=age_errs, xerr=rp_errs, # elinewidth=0.3, ecolor='k', capsize=0, capthick=0, linewidth=0, # fmt='s', ms=0, zorder=2, alpha=0.05) # flip default legend order handles, labels = ax.get_legend_handles_labels() ax.legend(handles[::-1], labels[::-1], loc='lower left', borderpad=0.1, handletextpad=0.1, fontsize='small', framealpha=1) ax.set_xlabel('Age [Gyr]') ax.set_ylabel('Planet radius [R$_\oplus$]') ax.get_yaxis().set_tick_params(which='both', direction='in') ax.get_xaxis().set_tick_params(which='both', direction='in') ax.set_ylim([0.13, 85]) ax.set_xscale('log') ax.set_yscale('log') ax.tick_params(top=True, bottom=True, left=True, right=True, which='both') f.tight_layout() savstr = '_no_overplot' if not active_targets else '_active_targets' outpath = '../results/rp_vs_age_scatter{}.png'.format(savstr) f.savefig(outpath, bbox_inches='tight', dpi=450) f.savefig(outpath.replace('.png', '.pdf'), bbox_inches='tight') print('made {}'.format(outpath))