def plot_korbpost(outpath, truth=None, xlabel='K$_\mathrm{orb}$ [m$\,$s$^{-1}$]'): Nobs = [20, 30, 45, 90] Korb_d = {} from betty.paths import BETTYDIR for N in Nobs: pklpath = os.path.join( BETTYDIR, f'test_HIP67522_rvspotorbit_Nobs{N}.pkl' ) with open(pklpath, 'rb') as f: d = pickle.load(f) trace = d['trace'] samples = trace['K_orb'] Korb_d[N] = samples # make plot set_style() plt.close('all') f, ax = plt.subplots(figsize=(4,3)) for N in Nobs: ls = ':' if N in [30, 90] else '-' ax.hist(Korb_d[N], bins=np.arange(0,220,20), weights=np.ones_like(Korb_d[N])*1/len(Korb_d[N]), zorder=-1, histtype='step', alpha=1, ls=ls, label='N$_\mathrm{obs}$='+f'{N}') from matplotlib.lines import Line2D handles, labels = ax.get_legend_handles_labels() new_handles = [] for ix, h in enumerate(handles): ls = ':' if ix in [1, 3] else '-' new_handles.append(Line2D([], [], c=h.get_edgecolor(), ls=ls)) ax.legend(loc='best', fontsize='small', handles=new_handles, labels=labels) if isinstance(xlabel, str): ax.set_xlabel(xlabel) if truth is not None: ymin, ymax = ax.get_ylim() ax.vlines( truth, ymin, ymax, colors='k', alpha=0.8, linestyles='--', zorder=-2, linewidths=1 ) ax.set_ylim((ymin, ymax)) ax.set_ylabel('Posterior probability') savefig(f, outpath, writepdf=0)
def plot_spec_Prot_hist(Prot_source='M15', spec_source='cks'): """ Prot_source (str): M13 or M15 spec_source (str): always 'cks', because that's the only vsini source. [nb. this is the vsini dataset from J. Winn, received 2 Aug 2020] """ if spec_source != 'cks': raise NotImplementedError mdf, cdf = _get_spec_vsini_phot_Prot_overlap(Prot_source=Prot_source) sel = cdf['id_kic'].isin(arr(mdf['id_kic'])) scdf = cdf[~sel] print(f'{len(cdf)} with vsini') print(f'{len(mdf[(~pd.isnull(mdf.spec_Prot)) & (~pd.isnull(mdf.Prot))])} with vsini & M15 prot') print(f'{len(scdf)} with vsini & and no M15 prot') outdir = join(RESULTSDIR, 'spec_rot') set_style() f, ax = plt.subplots(figsize=(4,3)) bins = np.arange(0, 52.5, 2.5) N_m = len(mdf) N_n = len(scdf) ax.hist(scdf.spec_Prot, bins=bins, cumulative=False, fill=False, density=False, weights=np.ones(N_n)/N_n, histtype='step', label=f'No M15 match ({len(scdf)})') ax.hist(mdf.spec_Prot, bins=bins, cumulative=False, fill=False, density=False, weights=np.ones(N_m)/N_m, histtype='step', label=f'Has M15 match ({len(mdf)})') # Create new legend handles but use the colors from the existing ones handles, labels = ax.get_legend_handles_labels() new_handles = [Line2D([], [], c=h.get_edgecolor()) for h in handles] ax.legend(handles=new_handles, labels=labels, fontsize='small') txt = ( r'$\mu_{T_{\mathrm{eff}}} \pm \sigma_{T_{\mathrm{eff}}}$ '+' for P$_{\mathrm{rot}}^{\mathrm{spec}} < 25$ d:\n' 'No M15: '+f'{int(scdf[scdf.spec_Prot<25].cks_steff.mean())} $\pm$ {int(scdf[scdf.spec_Prot<25].cks_steff.std())}\n' 'Has M15: '+f'{int(mdf[mdf.spec_Prot<25].VIIs_Teff.mean())} $\pm$ {int(mdf[mdf.spec_Prot<25].VIIs_Teff.std())}\n' ) ax.text(0.95, 0.50, txt, transform=ax.transAxes, ha='right', va='center', fontsize='small') ax.set_ylabel('Fraction per bin') ax.set_xlabel('CKS-VII P$_{\mathrm{rot}}^{\mathrm{spec}}$ [day]') outpath = join( outdir, f'spec_Prot_hist_prot{Prot_source}.png' ) savefig(f, outpath, writepdf=0)
def backintegrate( icrs = coord.SkyCoord(ra=coord.Angle('17h 20m 12.4s'), dec=coord.Angle('+57° 54′ 55″'), distance=76*u.kpc, pm_ra_cosdec=0.0569*u.mas/u.yr, pm_dec=-0.1673*u.mas/u.yr, radial_velocity=-291*u.km/u.s), dt=-0.1*u.Myr, n_steps=int(1e3), outpath=None ): """ Note: this is a thin wrapper to Gala's "integrate_orbit" method. Args: icrs (SkyCoord). Default is Draco. Note however that you can pass many ICRS coordinates to a coord.SkyCoord instance, via a construct like: ``` icrs_samples = coord.SkyCoord(ra=ra, dec=dec, distance=dist, pm_ra_cosdec=pm_ra_cosdec, pm_dec=pm_dec, radial_velocity=rv) ``` where ra, dec, etc are correctly unit-ed arrays. dt (Quantity): timestep. (Default: 1e5 yr) n_steps (int): how many steps. (Default: 1e3, so total 1e8 years back). outpath (str): if passed, makes a plot of the orbit here. Returns: gala orbit object. """ # Transform the measured values to a Galactocentric reference frame so we # can integrate an orbit in our Milky Way model. gc_frame = coord.Galactocentric() # Transform the mean observed kinematics to this frame. galcen = icrs.transform_to(gc_frame) # Turn the `Galactocentric` object into orbital initial conditions, and # integrate. Timestep: 0.5 Myr, and integrate back for 1e4 steps (5 Gyr). w0 = gd.PhaseSpacePosition(galcen.data) orbit = potential.integrate_orbit(w0, dt=dt, n_steps=n_steps) if isinstance(outpath, str): fig = orbit.plot() savefig(fig, outpath) return orbit
def plot_stsnr_vs_gyroage(Prot_source='M15', gyro_source='A19', cdpp_id='rms3'): """ Prot_source: M13 or M15 gyro_source: MH08 or A19 cdpp_id: rms3, rms6, or rms12 Makes a Berger+2020 style single-transit SNR vs age plot. The method is identical to Berger+2020. CDPP is taken from Christiansen 2012. Single-transit SNR is calculated by doing (Rp/R*)^2 * (1/CDPP). This was cited as being from Petigura+2018. [.....] """ mdf = get_merged_gyroage_CKS(Prot_source=Prot_source, gyro_source=gyro_source) mdf = _add_Christiansen12_CDPP(mdf) Rp = 1*u.Rearth Rstar = arr(mdf.VIIs_R)*u.Rsun Rp_Rs = (Rp/Rstar).cgs.value mdf['stsnr'] = ( Rp_Rs**2 * (1/arr(1e-6*mdf[cdpp_id])) ) scols = ['gyroage_yr', 'stsnr'] sdf = mdf[scols] outdir = join( RESULTSDIR, f'singletransitSNR_{Prot_source}rot_{gyro_source}age' ) if not os.path.exists(outdir): os.mkdir(outdir) set_style() f, ax = plt.subplots(figsize=(4,3)) ax.scatter(sdf.gyroage_yr, sdf.stsnr, s=2, c='k', zorder=3) agelabel = (f'Gyro-Age [{Prot_source} '+'P$_\mathrm{rot}$ +' +f'{gyro_source}; yr]') ax.set_xlabel(agelabel, fontsize='small') ax.set_ylabel(f'Single-transit SNR [C12 CDPP{cdpp_id.replace("rms","")}]', fontsize='small') ax.set_xscale('log'); ax.set_yscale('log') outpath = join(outdir, f'singletransitsnr_{cdpp_id}_rot{Prot_source}_gyro{gyro_source}.png') savefig(f, outpath, writepdf=0)
def plot_spec_vs_phot_Prot(Prot_source='M15', spec_source='cks'): """ Prot_source (str): M13 or M15 spec_source (str): always 'cks', because that's the only vsini source. [nb. this is the vsini dataset from J. Winn, received 2 Aug 2020] """ if spec_source != 'cks': raise NotImplementedError mdf, _ = _get_spec_vsini_phot_Prot_overlap(Prot_source=Prot_source) outdir = join(RESULTSDIR, 'spec_rot') if not os.path.exists(outdir): os.mkdir(outdir) set_style() f, ax = plt.subplots(figsize=(4,3)) ax.scatter(mdf.Prot, mdf.spec_Prot, s=2, c='k', zorder=3) _, xmax = ax.get_xlim() span = np.linspace(2, xmax, 100) ax.plot(span, span, zorder=-1, lw=1, ls='--', c='lightgray', label='$i=90^\circ$') ax.plot(span, span/np.sin(np.deg2rad(45)), zorder=-1, lw=1, ls=':', c='lightgray', label='$i=45^\circ$') ax.legend(fontsize='small') ax.set_xscale('log'); ax.set_yscale('log') ax.set_xlabel(f'{Prot_source} phot '+'P$_\mathrm{rot}$ [day]') ax.set_ylabel(f'CKS-VII spec '+'P$_\mathrm{rot}$ [day]') outpath = join(outdir, f'cks-VII_specrot_vs_{Prot_source}_prot.png') savefig(f, outpath, writepdf=0) sel = (mdf.Prot < 10) sdf = mdf[sel] sdf['specProt/photProt'] = sdf.spec_Prot/sdf.Prot sdf = sdf.sort_values(by='specProt/photProt', ascending=False) selcols = ['VIIp_KOI', 'Prot', 'spec_Prot'] print(sdf[selcols][:20].to_string(index=False))
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 numpy as np, matplotlib.pyplot as plt from aesthetic.plot import (savefig, set_style, set_style_scatter, set_style_grid, format_ax) x = np.linspace(0, 10, 1000) y = (x / 100)**3 + 5 * np.sin(x) set_style() fig, ax = plt.subplots() ax.plot(x, y) ax.plot(x, y + 3) ax.plot(x, y + 6) ax.set_xlabel('x') ax.set_ylabel('y') savefig(fig, '../results/plot_standard.png') set_style_scatter() fig, ax = plt.subplots() ax.scatter(x[::50], y[::50]) ax.scatter(x[::50], y[::50] + 3) ax.scatter(x[::50], y[::50] + 6) ax.set_xlabel('x') ax.set_ylabel('y') savefig(fig, '../results/plot_scatter.png') set_style_grid() fig, ax = plt.subplots() ax.plot(x, y) ax.plot(x, y + 3) ax.plot(x, y + 6) ax.set_xlabel('x')
zorder=-1, lw=1, c='gray', ls=':') ax.set_xlabel('LS Period [days]') ax.set_ylabel('SPDM Period [days]') ax.set_xlim([0, 30]) ax.set_ylim([0, 30]) format_ax(ax) outpath = '../results/rotation/NGC_2516/NGC_2516_LS_vs_SPDM_periods.png' savefig( f, outpath, ) ########## sel_match = ((0.9 < (df.spdmperiod / df.period)) & (1.1 > (df.spdmperiod / df.period))) sel_spdm2x = ((1.9 < (df.spdmperiod / df.period)) & (2.1 > (df.spdmperiod / df.period))) sel_spdmpt5x = ((0.4 < (df.spdmperiod / df.period)) & (0.6 > (df.spdmperiod / df.period))) sel_spdm3x = ((2.9 < (df.spdmperiod / df.period)) & (3.1 > (df.spdmperiod / df.period)))
def plot_S21_prot_vs_teff(koiflag, ylim=None): # koiflag: 0 is confirmed. 1 is candidate. set_style() outdir = join(RESULTSDIR, f'S21_prot_vs_teff') if not os.path.exists(outdir): os.mkdir(outdir) Prot_source = 'S21' df = _get_Santos21_data() sel = np.zeros(len(df)).astype(bool) for f in koiflag: sel |= (df.flag4 == f) df = df[sel] reference_clusters = ['Pleiades', 'Praesepe'] for scale in ['linear','log']: plt.close('all') f, ax = plt.subplots(figsize=(4,3)) ax.scatter(df.Teff, df.Prot, s=2, c='k', label=f'{Prot_source}', zorder=10) for ix, c in enumerate(reference_clusters): cdf = _get_Curtis20_data(c.lower()) # data ax.scatter(cdf.Teff, cdf.Prot, s=1, c=f'C{ix}', label=c) # interpolated model InterpModel = ( PleiadesInterpModel if c == 'Pleiades' else PraesepeInterpModel ) _teff = np.linspace(4500, 6400, 300) _prot = InterpModel(_teff) ax.plot(_teff, _prot, lw=1, c=f'C{ix}') ax.legend(fontsize='x-small', loc='best') ax.set_xlabel('T$_\mathrm{eff}$ [K]') ax.set_ylabel(f'{Prot_source} '+'P$_\mathrm{rot}$ [day]') ax.set_xlim(ax.get_xlim()[::-1]) ax.set_xlim([7000,4000]) if isinstance(ylim, list): ax.set_ylim(ylim) ax.set_xscale('linear'); ax.set_yscale(scale) if koiflag == [0]: titlestr = 'Confirmed KOIs only' elif koiflag == [0,1]: titlestr = 'Confirmed + candidate KOIs' ax.set_title(titlestr) kstr = '_'.join(np.array(koiflag).astype(str)) s = '' if isinstance(ylim, list): s += 'ylim'+'_'.join(np.array(ylim).astype(str)) outpath = join( outdir, f'teff_vs_{Prot_source}_prot_{scale}_koiflag{kstr}{s}.png' ) savefig(f, outpath, writepdf=0) # # print any KOIs below the cutoffs # sel = (df.Teff > 4500) & (df.Teff < 6400) sdf = df[sel] pleiades_model_prot = PleiadesInterpModel(sdf.Teff) praesepe_model_prot = PraesepeInterpModel(sdf.Teff) below_Pleiades = (sdf.Prot < pleiades_model_prot) below_Praesepe = (sdf.Prot < praesepe_model_prot) PRINT = 0 if scale == 'linear' and isinstance(ylim, list): PRINT = 1 if PRINT: print(42*'-') print(f'Below Pleaides, KOI flags {kstr}. N={len(sdf[below_Pleiades])}') print(sdf[below_Pleiades].sort_values(by='Prot')) print(11*'#') print(f'Below Praesepe, KOI flags {kstr}. N={len(sdf[below_Praesepe])}') print(sdf[below_Praesepe].sort_values(by='Prot')) print(42*'-') sdf['is_below_Praesepe'] = below_Praesepe.astype(int) sdf['is_below_Pleiades'] = below_Pleiades.astype(int) outcsvpath = join( DATADIR, f'Santos21_koiflag{kstr}_below_Praesepe_in_Prot_Teff_Teff_btwn_4500_6400.csv' ) if not os.path.exists(outcsvpath): outdf = sdf[below_Praesepe].sort_values(by='Prot') outdf.to_csv(outcsvpath, index=False) print(f"Made {outcsvpath}") else: print(f"Found {outcsvpath} and did not overwrite.")
def plot_cks_rp_vs_prot(Prot_source='M15'): """ Prot_source: M13 or M15 Make scatter plots of {plantet radius, orbital period} against rotation periods in a few different projections. """ mdf, fp18_df = get_merged_rot_CKS(Prot_source=Prot_source) Prot_key = 'Prot' if Prot_source in ['M13','M15','S21'] else 'spec_Prot' set_style() outdir = join(RESULTSDIR, f'cks_{Prot_source}_rotation_period') if not os.path.exists(outdir): os.mkdir(outdir) for scale in ['linear','log']: f, ax = plt.subplots(figsize=(4,3)) ax.scatter(mdf.VIIp_Rp, mdf[Prot_key], s=2, c='k', zorder=3) ax.set_xlabel('CKS-VII R$_\mathrm{p}$ [R$_\oplus$]') ax.set_ylabel(f'{Prot_source} '+'P$_\mathrm{rot}$ [day]') ax.set_xscale(scale); ax.set_yscale(scale) outpath = join(outdir, f'cks-VII_rp_vs_{Prot_source}_prot_{scale}.png') savefig(f, outpath, writepdf=0) for scale in ['linear','log']: plt.close('all') f, ax = plt.subplots(figsize=(4,3)) ax.scatter(mdf.VIIs_Teff, mdf[Prot_key], s=2, c='k', label=f'CKS-VII $\otimes$ {Prot_source}', zorder=10) for ix, c in enumerate(['Pleiades', 'Praesepe']): cdf = _get_Curtis20_data(c.lower()) ax.scatter(cdf.Teff, cdf.Prot, s=1, c=f'C{ix}', label=c) ax.legend(fontsize='x-small', loc='best') ax.set_xlabel('CKS-VII T$_\mathrm{eff}$ [K]') ax.set_ylabel(f'{Prot_source} '+'P$_\mathrm{rot}$ [day]') ax.set_xlim(ax.get_xlim()[::-1]) ax.set_xlim([7000,4000]) ax.set_xscale('linear'); ax.set_yscale(scale) outpath = join(outdir, f'cks-VII_teff_vs_{Prot_source}_prot_{scale}.png') savefig(f, outpath, writepdf=0) plt.close('all') f, ax = plt.subplots(figsize=(4,3)) ax.scatter(mdf.VIIp_Per, mdf[Prot_key], s=2, c='k') ax.set_xlabel('CKS-VII P$_\mathrm{orb}$ [day]') ax.set_ylabel(f'{Prot_source} '+'P$_\mathrm{rot}$ [day]') ax.set_xscale('log'); ax.set_yscale('log') outpath = join(outdir, f'cks-VII_period_vs_{Prot_source}_prot.png') savefig(f, outpath, writepdf=0) plt.close('all') f, ax = plt.subplots(figsize=(4,3)) sel = ~pd.isnull(mdf[Prot_key]) N_withProt = len(mdf[sel]) N_noProt = len(fp18_df) - N_withProt ax.scatter(mdf[sel].VIIp_Per, mdf[sel].VIIp_Rp, s=1.5, c='k', zorder=3, label=f'Yes {Prot_source} '+'P$_\mathrm{rot}$ '+f'({N_withProt})') ax.scatter(fp18_df.VIIp_Per, fp18_df.VIIp_Rp, s=1.5, c='darkgray', zorder=2, label=f'No {Prot_source} '+'P$_\mathrm{rot}$ '+f'({N_noProt})') ax.legend(fontsize='small') ax.set_xlabel('CKS-VII P$_\mathrm{orb}$ [day]') ax.set_ylabel('CKS-VII R$_\mathrm{p}$ [R$_\oplus$]') ax.set_xscale('log'); ax.set_yscale('log') outpath = join(outdir, f'cks-VII_period_vs_cks-VII_prad_{Prot_source}_match.png') savefig(f, outpath, writepdf=0) plt.close('all') f, ax = plt.subplots(figsize=(4,3)) sel = ~pd.isnull(mdf[Prot_key]) N_withProt = len(mdf[sel]) N_noProt = len(fp18_df) - N_withProt hasrot = (fp18_df['VIIp_SimbadName'].isin(mdf[sel]['VIIp_SimbadName'])) norot = ~hasrot ax.scatter(fp18_df[hasrot].VIIp_Per, fp18_df[hasrot].VIIp_Rp, s=1.5, c='darkgray', zorder=2, label=f'Yes {Prot_source} '+'P$_\mathrm{rot}$ '+f'({N_withProt})') ax.scatter(fp18_df[norot].VIIp_Per, fp18_df[norot].VIIp_Rp, s=1.5, c='k', zorder=3, label=f'No {Prot_source} '+'P$_\mathrm{rot}$ '+f'({N_noProt})') ax.legend(fontsize='small') ax.set_xlabel('CKS-VII P$_\mathrm{orb}$ [day]') ax.set_ylabel('CKS-VII R$_\mathrm{p}$ [R$_\oplus$]') ax.set_xscale('log'); ax.set_yscale('log') outpath = join( outdir, f'cks-VII_period_vs_cks-VII_prad_{Prot_source}_match_inverted.png' ) savefig(f, outpath, writepdf=0) plt.close('all') f, ax = plt.subplots(figsize=(4.3,3)) sel = ~pd.isnull(mdf[Prot_key]) N_withProt = len(mdf[sel]) N_noProt = len(fp18_df) - N_withProt l = f'Yes {Prot_source}'+' P$_\mathrm{rot}$ '+f'({N_withProt})' norm = mpl.colors.Normalize(vmin=5, vmax=25) cax = ax.scatter(mdf[sel].VIIp_Per, mdf[sel].VIIp_Rp, s=7, c=mdf[sel][Prot_key], cmap='plasma_r', zorder=3, label=l, norm=norm, edgecolors='k', linewidths=0.2) ax.set_xlabel('CKS-VII P$_\mathrm{orb}$ [day]') ax.set_ylabel('CKS-VII R$_\mathrm{p}$ [R$_\oplus$]') ax.set_xscale('log'); ax.set_yscale('log') cbar = f.colorbar(cax, extend='both') cbar.set_label(f'{Prot_source}'+' P$_\mathrm{rot}$ [day]') cbar.minorticks_off() outpath = join(outdir, f'cks-VII_period_vs_cks-VII_prad_{Prot_source}-Protcolors.png') savefig(f, outpath, writepdf=0)
import numpy as np, matplotlib.pyplot as plt, pandas as pd from astropy import units as u, constants as const from aesthetic.plot import set_style, savefig from timmy.priors import RSTAR, MSTAR sma = np.logspace(-1, 3, 100) * u.AU Mtot = (MSTAR) * u.Msun v_kep = ((const.G * Mtot / sma)**(1 / 2)).to(u.km / u.s) set_style() f, ax = plt.subplots() ax.plot(sma, v_kep, label=f'Mtot={MSTAR:.2f}M$_\odot$') ax.plot(sma, v_kep * np.sqrt(2), label=f'Mtot={2*MSTAR:.2f}M$_\odot$') ax.set_xlabel('semi-major axis [AU]') ax.set_ylabel('$v_{\mathrm{Kep}}$ [km/s]') ax.set_xscale('log') ax.set_yscale('log') ax.hlines([10, 15], 1e-1, 1e3, label='SB2 sep limits') ax.set_xlim((1e-1, 1e3)) ax.legend() figpath = '../../results/fpscenarios/velocity_separation_check.png' savefig(f, figpath, writepdf=False, dpi=300)
def plot_TIC268_nbhd_small(outdir=RESULTSDIR): set_style() df = get_cdips_catalog(ver=0.4) kc19_sel = ((df.cluster.str.contains('NGC_2516')) & (df.reference.str.contains('Kounkel_2019'))) cg18_sel = ((df.cluster.str.contains('NGC_2516')) & (df.reference.str.contains('CantatGaudin_2018'))) target_df = df[df.source_id == 5489726768531119616] # TIC 2683... kc19_df = df[kc19_sel] cg18_df = df[cg18_sel] kc19_df = kc19_df[~(kc19_df.source_id.isin(cg18_df.source_id))] ########## # NGC 2516 rough bounds = { 'parallax_lower': 1.5, 'parallax_upper': 4.0, 'ra_lower': 108, 'ra_upper': 132, 'dec_lower': -76, 'dec_upper': -45 } groupname = 'customngc2516' nbhd_df = query_neighborhood(bounds, groupname, n_max=6000, overwrite=False, manual_gmag_limit=17) sel_nbhd = ((~nbhd_df.source_id.isin(kc19_df.source_id)) & (~nbhd_df.source_id.isin(cg18_df.source_id))) from copy import deepcopy orig_nbhd_df = deepcopy(nbhd_df) nbhd_df = nbhd_df[sel_nbhd] print(f'Got {len(nbhd_df)} neighbors') print(f'Got {len(cg18_df)} in core') print(f'Got {len(kc19_df)} in corona') ########## plt.close('all') f, axs = plt.subplots(figsize=(4, 3), ncols=2) xv, yv = 'ra', 'dec' axs[0].scatter(nbhd_df[xv], nbhd_df[yv], c='gray', alpha=0.5, zorder=2, s=7, rasterized=True, linewidths=0, label='Field', marker='.') axs[0].scatter(kc19_df[xv], kc19_df[yv], c='lightskyblue', alpha=0.9, zorder=3, s=7, rasterized=True, linewidths=0.15, label='Corona', marker='.', edgecolors='k') axs[0].scatter(cg18_df[xv], cg18_df[yv], c='k', alpha=0.9, zorder=4, s=7, rasterized=True, label='Core', marker='.') axs[0].plot(target_df[xv], target_df[yv], alpha=1, mew=0.5, zorder=8, label='TOI 1937', markerfacecolor='lightskyblue', markersize=14, marker='*', color='black', lw=0) axs[0].set_xlabel(r'$\alpha$ [deg]') axs[0].set_ylabel(r'$\delta$ [deg]') axs[0].set_xlim([108, 132]) axs[0].set_ylim([-76, -45]) ########## get_yval = (lambda _df: np.array(_df['phot_g_mean_mag'] + 5 * np.log10(_df[ 'parallax'] / 1e3) + 5)) get_xval = (lambda _df: np.array(_df['phot_bp_mean_mag'] - _df[ 'phot_rp_mean_mag'])) axs[1].scatter(get_xval(nbhd_df), get_yval(nbhd_df), c='gray', alpha=0.8, zorder=2, s=7, rasterized=True, linewidths=0, label='Field', marker='.') axs[1].scatter(get_xval(kc19_df), get_yval(kc19_df), c='lightskyblue', alpha=1, zorder=3, s=7, rasterized=True, linewidths=0.15, label='Corona', marker='.', edgecolors='k') axs[1].scatter(get_xval(cg18_df), get_yval(cg18_df), c='k', alpha=0.9, zorder=4, s=7, rasterized=True, linewidths=0, label='Core', marker='.') axs[1].plot(get_xval(target_df), get_yval(target_df), alpha=1, mew=0.5, zorder=8, label='TOI 1937', markerfacecolor='lightskyblue', markersize=14, marker='*', color='black', lw=0) axs[1].set_ylim(axs[1].get_ylim()[::-1]) axs[1].set_xlabel('Bp - Rp [mag]') axs[1].set_ylabel('Absolute G [mag]', labelpad=-6) ########## words = ['Field', 'Corona', 'Core', 'TOI1937'][::-1] colors = ['gray', 'lightskyblue', 'k', 'lightskyblue'][::-1] rainbow_text(0.98, 0.02, words, colors, size='medium', ax=axs[0]) f.tight_layout(w_pad=2) outpath = os.path.join(outdir, 'small_ngc2516.png') savefig(f, outpath)
def plot_Prot_vs_eps(includefit=False, xscale=None): # # make the plot! # set_style() f, ax = plt.subplots(figsize=(4, 3)) Porb_1937 = 0.947 Prot_1937 = 6.5 MpMs_1937 = ((1.79 * u.Mjup) / (1.045 * u.Msun)).cgs.value Rs_a_1937 = (1 / 4.26) # from MIT report eps_1937 = MpMs_1937 * Rs_a_1937**5 ax.scatter(df['epsilon'], df['P_rot'], zorder=2, c='k', alpha=0.9, s=9, linewidths=0, label='HJs (phot P$_\mathrm{rot}$)') # ax.scatter( # d['Per'][sel1], d['SPer'][sel1], zorder=2, c='gray', alpha=0.9, s=9, # linewidths=0, # label='HJs ($\mathrm{R}_{\star} \geq 1.2 \mathrm{R}_{\odot}$)' # ) ax.plot(eps_1937, Prot_1937, mew=0.5, zorder=3, markerfacecolor='yellow', markersize=18, marker='*', color='k', lw=0, label='TOI 1937b') # if includefit: # x = np.hstack([d['Per'][sel0], Porb_1937]) # y = np.hstack([d['SPer'][sel0], Prot_1937]) # slope, intercept, rvalue, pvalue, stderr = linregress(x, y) # label = f'Slope={slope:.1f}$\pm${stderr:.1f}, p={pvalue:.1e}' # ax.plot(x, intercept + slope*x, label=label) # Shrink current axis by 20% box = ax.get_position() ax.set_position([box.x0, box.y0, box.width * 0.8, box.height]) # Put a legend to the right of the current axis ax.legend(loc='center left', bbox_to_anchor=(1, 0.5), handletextpad=0.1) ax.set_xlabel('$\epsilon \equiv (M_\mathrm{p}/M_{\star})(R_{\star}/a)^5$') ax.set_ylabel('Stellar spin period [days]') # ax.set_xlim([0.5, 4.2]) ax.set_ylim([2, 28]) extrastr = '_withfit' if includefit else '_nofit' if isinstance(xscale, str): ax.set_xscale(xscale) extrastr += f'_{xscale}' figpath = (f'../results/Prot_vs_eps/Prot_vs_eps_snrcut{extrastr}.png') savefig(f, figpath)
def plot_hist_rp_agecut(agecut=1e9, Prot_source='M15', gyro_source='A19', fix_ylim=None): """ Prot_source (str): M13 or M15 gyro_source (str): MH08 or A19 agecut (float): Age cut in years Plot histogram. $$$? """ mdf = get_merged_gyroage_CKS(Prot_source=Prot_source, gyro_source=gyro_source) odf = mdf[(mdf.gyroage_yr > agecut) & (mdf.VIIp_Rp < 6)] # old ydf = mdf[(mdf.gyroage_yr <= agecut) & (mdf.VIIp_Rp < 6)] # young N_o = len(odf) N_y = len(ydf) # Following Fulton et al 2017, we define a “super-Earth” as a # planet with a radius of 1–1.75 Re, and a “sub-Neptune” as # having a radius of 1.75–4.0 Re. # old: number of superNeptunes / number of super Earths o_NsN = len(odf[(odf.VIIp_Rp > 1.75) & (odf.VIIp_Rp <= 4.00)]) o_NsE = len(odf[(odf.VIIp_Rp > 1.00) & (odf.VIIp_Rp <= 1.75)]) unc_o_NsN = np.sqrt(len(odf[(odf.VIIp_Rp > 1.75) & (odf.VIIp_Rp <= 4.00)])) unc_o_NsE = np.sqrt(len(odf[(odf.VIIp_Rp > 1.00) & (odf.VIIp_Rp <= 1.75)])) o_NsN_div_NsE = o_NsN / o_NsE unc_o_div = o_NsN_div_NsE * np.sqrt( (unc_o_NsN/o_NsN)**2 + (unc_o_NsE/o_NsE)**2 ) # ditto for young y_NsN = len(ydf[(ydf.VIIp_Rp > 1.75) & (ydf.VIIp_Rp <= 4.00)]) y_NsE = len(ydf[(ydf.VIIp_Rp > 1.00) & (ydf.VIIp_Rp <= 1.75)]) unc_y_NsN = np.sqrt(len(ydf[(ydf.VIIp_Rp > 1.75) & (ydf.VIIp_Rp <= 4.00)])) unc_y_NsE = np.sqrt(len(ydf[(ydf.VIIp_Rp > 1.00) & (ydf.VIIp_Rp <= 1.75)])) y_NsN_div_NsE = y_NsN / y_NsE unc_y_div = y_NsN_div_NsE * np.sqrt( (unc_y_NsN/y_NsN)**2 + (unc_y_NsE/y_NsE)**2 ) txt = ( 'N$_{\mathrm{subNeptune}}$/N$_{\mathrm{superEarth}}$:' + f'\nOld: {o_NsN_div_NsE:.2f} $\pm$ {unc_o_div:.2f}' + f'\nYoung: {y_NsN_div_NsE:.2f} $\pm$ {unc_y_div:.2f}' ) # # make the plot! # outdir = join( RESULTSDIR, f'hist_rp_agecut' ) if not os.path.exists(outdir): os.mkdir(outdir) set_style() f, ax = plt.subplots(figsize=(4,3)) bins = np.arange(0, 6.25, 0.25) ax.hist(odf.VIIp_Rp, bins=bins, cumulative=False, fill=False, density=False, weights=np.ones(N_o)/N_o, histtype='step', label=f'Age > {agecut/1e9:.1f} Gyr ({N_o})') ax.hist(ydf.VIIp_Rp, bins=bins, cumulative=False, fill=False, density=False, weights=np.ones(N_y)/N_y, histtype='step', label=f'Age < {agecut/1e9:.1f} Gyr ({N_y})') if fix_ylim: ax.set_ylim([0,0.28]) ymin, ymax = ax.get_ylim() ax.vlines( 1.74, ymin, ymax, colors='darkgray', alpha=1, linestyles='--', zorder=-2, linewidths=0.5 ) ax.set_ylim((ymin, ymax)) # Create new legend handles but use the colors from the existing ones handles, labels = ax.get_legend_handles_labels() new_handles = [Line2D([], [], c=h.get_edgecolor()) for h in handles] ax.legend(handles=new_handles, labels=labels, fontsize='small') ax.text(0.95, 0.50, txt, transform=ax.transAxes, ha='right', va='center', fontsize='small') ax.set_ylabel('Fraction per bin') ax.set_xlabel('CKS-VII R$_\mathrm{p}$ [R$_\oplus$]') outpath = join( outdir, f'hist_Rp_cut{agecut/1e9:.1f}_prot{Prot_source}_gyro{gyro_source}.png' ) savefig(f, outpath, writepdf=0)
def plot_cdf_rp_agecut_KS_test(agecut=1e9, Prot_source='M15', gyro_source='A19'): """ Prot_source (str): M13 or M15 gyro_source (str): MH08 or A19 agecut (float): Age cut in years Plot CDF, do KS test, calculate p-values. """ mdf = get_merged_gyroage_CKS(Prot_source=Prot_source, gyro_source=gyro_source) odf = mdf[(mdf.gyroage_yr > agecut) & (mdf.VIIp_Rp < 6)] # old ydf = mdf[(mdf.gyroage_yr <= agecut) & (mdf.VIIp_Rp < 6)] # young N_o = len(odf) N_y = len(ydf) # # make the plot! # outdir = join( RESULTSDIR, f'cdf_rp_agecut_KS_test' ) if not os.path.exists(outdir): os.mkdir(outdir) set_style() f, ax = plt.subplots(figsize=(4,3)) bins = np.linspace(mdf.VIIp_Rp.min(), mdf.VIIp_Rp.max(), 1000) cnt, bin_edges = np.histogram(arr(odf.VIIp_Rp), bins=bins, normed=True) cdf = np.cumsum(cnt) ax.plot(bin_edges[:-1], cdf/cdf[-1], label=f'Age > {agecut/1e9:.1f} Gyr ({N_o})') cnt, bin_edges = np.histogram(arr(ydf.VIIp_Rp), bins=bins, normed=True) cdf = np.cumsum(cnt) ax.plot(bin_edges[:-1], cdf/cdf[-1], label=f'Age < {agecut/1e9:.1f} Gyr ({N_y})') ax.set_xscale('log') from scipy.stats import ks_2samp D, p_value = ks_2samp(arr(odf.VIIp_Rp), arr(ydf.VIIp_Rp)) txt = f'D={D:.2e}, p={p_value:.2e}' ax.text(0.05, 0.95, txt, transform=ax.transAxes, ha='left', va='top', fontsize='small') ax.legend(fontsize='small', loc='lower right') ax.set_xlabel('CKS-VII R$_\mathrm{p}$ [R$_\oplus$]') outpath = join( outdir, f'cdf_Rp_KS_cut{agecut/1e9:.1f}_prot{Prot_source}_gyro{gyro_source}.png' ) savefig(f, outpath, writepdf=0)
def calc_semiamplitude_period_recovery(N_samples, gammadot_limit, delta_time, t_observed, do_serial=0): np.random.seed(42) log_semiamplitude = np.random.uniform(np.log(1e1), np.log(1e7), size=N_samples) log_period = np.random.uniform(np.log(1e0), np.log(1e15), size=N_samples) cosi = np.random.uniform(0, 1, N_samples) i = np.arccos(cosi) sini = np.sin(i) phase = np.random.uniform(0, 1, N_samples) t_start = t_observed.min() t0s = t_start + phase * np.exp(log_period) outpath = os.path.join(rdir, f'semiamplitude_period_recovery_{N_samples}.csv') if not os.path.exists(outpath): if do_serial: slopes, detectables = [], [] ix = 0 for logK, logP, t0, si in zip(log_semiamplitude, log_period, t0s, sini): if ix % 10 == 0: print(f'{ix}/{N_samples}') task = (logK, logP, t0, si, t_observed, gammadot_limit) slope, isdetectable = rv_injection_worker(task) slopes.append(slope) detectables.append(isdetectable) ix += 1 else: print(f'{datetime.now().isoformat()}: Beginning injection workers') tasks = [(logK, logP, t0, si, t_observed, gammadot_limit) for logK, logP, t0, si in zip(log_semiamplitude, log_period, t0s, sini)] nworkers = mp.cpu_count() maxworkertasks = 1000 pool = mp.Pool(nworkers, maxtasksperchild=maxworkertasks) result = pool.map(rv_injection_worker, tasks) pool.close() pool.join() print(f'{datetime.now().isoformat()}: Finished injection workers') out = np.array(result, dtype=np.dtype('float,bool')) out.dtype.names = ['slopes', 'detectables'] slopes = out['slopes'] detectables = out['detectables'] df = pd.DataFrame({ 'logK': log_semiamplitude, 'logP': log_period, 'phase': phase, 'slope': slopes, 'detectable': detectables }) df.to_csv(outpath, index=False) print(f'saved {outpath}') else: df = pd.read_csv(outpath) # # make plots; convert to desired mass vs semimajor axis contours # from aesthetic.plot import set_style, savefig set_style() f, ax = plt.subplots() ax.scatter(df.logP, df.logK, c=df.detectable.astype(int), s=0.2) ax.set_xlabel('logP') ax.set_ylabel('logK') figpath = os.path.join(rdir, 'logP_vs_logK_detectable_check.png') savefig(f, figpath, writepdf=False, dpi=300) # NOTE: assuming log[k (m/s)] # NOTE: this is the Mstar >> Mcomp approximation. If this doesn't hold, it's an # implicit equation (the "binary mass function"). So in the large semimajor # axis regime, your resulting converted contours are slightly wrong. e = 0 sini = 1 Mstar = MSTAR * u.Msun msini_msun = sini * (( (np.exp(np.array(df.logK)) / (28.4329)) * (1 - e**2)**(1 / 2) * (Mstar.to(u.Msun).value)**(2 / 3) * ((np.exp(np.array(df.logP)) * u.day).to(u.yr).value)**(1 / 3)) * u.Mjup).to(u.Msun).value log10msini = np.log10(msini_msun) per1 = np.exp(np.array(df.logP)) * u.day sma1 = ((per1**2 * const.G * (Mstar + msini_msun * u.Msun) / (4 * np.pi**2))**(1 / 3)).to(u.au).value log10sma1 = np.log10(sma1) plt.close('all') f, ax = plt.subplots() ax.scatter(log10sma1, log10msini, c=df.detectable.astype(int), s=0.2) ax.set_xlabel('log$_{10}$(semi-major axis [AU])') ax.set_ylabel('log$_{10}$(M$\sin i$ [M$_\odot$])') ax.set_xlim([-2, 5]) ax.set_ylim([np.log10(0.001), np.log10(2)]) figpath = os.path.join(rdir, 'log10sma_vs_log10msini_detectable_check.png') savefig(f, figpath, writepdf=False, dpi=300)
def get_simulated_rvs(sigma_obs, N_obs, start_time, end_time, xoparams, xo_df, makeplot=True): # # a GP model is not defined without data. so _time, _rv, and _rv_err are # fake data, got by multiplying the photometry by the expected spot-induced # RV amplitude. # eps = 1e-5 _time = np.ascontiguousarray(xo_df.time, dtype=np.float64) _rv = np.ascontiguousarray(xo_df.rv, dtype=np.float64) _rv_err = np.ones_like(_rv)*30 t_train = np.linspace(_time.min(), _time.max(), int(1e4)) t_true = np.linspace(start_time.jd, end_time.jd, int(1e4)) t_long = np.linspace(_time.min(), end_time.jd, int(1e4)) np.random.seed(42) t_obs = np.sort(np.random.uniform(start_time.jd, end_time.jd, N_obs)) assert np.all(np.diff(t_obs) > 0) with pm.Model() as model: mean = pm.Normal('mean', mu=np.mean(_rv), sd=np.std(_rv)) upper_amp = 13.8 # 14 works log_amp = pm.Bound(pm.Normal, lower=10, upper=upper_amp)( 'log_amp', mu=xoparams['log_amp'], sd=10 ) P_rot = pm.Normal('P_rot', mu=xoparams['P_rot'], sd=0.01) log_Q0 = pm.Bound(pm.Normal, upper=7, lower=0.7)( 'log_Q0', mu=xoparams['log_Q0'], sd=2 ) log_deltaQ = pm.Normal('log_deltaQ', mu=xoparams['log_deltaQ'], sd=0.1) mix = pm.Uniform('mix', lower=1e-4, upper=1) kernel = xo.gp.terms.RotationTerm( log_amp=log_amp, period=P_rot, log_Q0=log_Q0, log_deltaQ=log_deltaQ, mix=mix ) gp = xo.gp.GP(kernel, _time, _rv_err**2, mean=mean) gp.marginal('gp', observed=_rv) pm.Deterministic('pred_train', gp.predict(t_train)) pm.Deterministic('pred_long', gp.predict(t_long)) pm.Deterministic('pred_obs', gp.predict(t_obs)) pm.Deterministic('pred_true', gp.predict(t_true)) map_soln = xo.optimize(start=model.test_point) # gp model doesn't really work because i don't understand it. period etc # are fine; scale is wonky. rv_train = map_soln['pred_train'] rv_long = map_soln['pred_long'] rv_obs_spot = map_soln['pred_obs'] rv_true_spot = map_soln['pred_true'] print(map_soln) orbit = xo.orbits.KeplerianOrbit( period=xoparams['period'], b=xoparams['b'], t0=xoparams['t0'], ecc=xoparams['ecc'], omega=xoparams['omega'], m_star=xoparams['m_star'], r_star=xoparams['r_star'] ) np.random.seed(42) rv_true_kep = orbit.get_radial_velocity(t_true, K=xoparams['K_orb']).eval() rv_obs_kep = orbit.get_radial_velocity(t_obs, K=xoparams['K_orb']).eval() rv_obs_noise = np.random.normal(loc=0, scale=sigma_obs, size=len(t_obs)) rv_true = rv_true_spot + rv_true_kep rv_obs = rv_obs_spot + rv_obs_kep + rv_obs_noise rv_err_obs = np.ones_like(t_obs)*sigma_obs if makeplot: #################### # plot #1: training data from cdips_followup.paths import RESULTSDIR set_style() plt.close('all') f, ax = plt.subplots(figsize=(8,3)) ax.scatter(_time, _rv, s=0.5, c='k', label='train data', zorder=3) ax.plot(t_train, rv_train, label='gp fit', lw=0.3, zorder=1) ax.legend() ax.set_xlabel('time') ax.set_ylabel('RV [m/s]') figpath = os.path.join(RESULTSDIR, 'HIP_67522', f'training_data_short_Nobs{N_obs}.png') savefig(f, figpath, writepdf=0) #################### # plot #2: training + predict set_style() plt.close('all') f, ax = plt.subplots(figsize=(4,3)) ax.scatter(_time, _rv, s=1, c='k', label='train data', zorder=3) ax.plot(t_long, rv_long, label='gp fit', lw=0.5, zorder=1) ax.legend() ax.set_xlabel('time') ax.set_ylabel('RV [m/s]') figpath = os.path.join(RESULTSDIR, 'HIP_67522', f'training_data_long_Nobs{N_obs}.png') savefig(f, figpath, writepdf=0) #################### # plot #3: generated data plt.close('all') t0 = t_true.min() f, axs = plt.subplots(nrows=3, figsize=(4,3), sharex=True) axs[0].plot(t_true-t0, rv_true_spot, c='C0', lw=1) axs[1].plot(t_true-t0, rv_true_kep, c='C1', lw=1) axs[2].errorbar(t_obs-t0, rv_obs, yerr=sigma_obs, fmt='none', ecolor='k', alpha=1, elinewidth=1, capsize=1, zorder=12) axs[2].plot(t_true-t0, rv_true, c='C2', lw=1) axs[2].plot(t_true-t0, rv_true_kep, c='C1', lw=1) props = dict(boxstyle='square', facecolor='white', alpha=0.95, pad=0.1, linewidth=0) axs[0].text(0.03, 0.05, 'Star', ha='left', va='bottom', transform=axs[0].transAxes, bbox=props, zorder=2, color='C0') axs[1].text(0.03, 0.05, 'Planet', ha='left', va='bottom', transform=axs[1].transAxes, bbox=props, zorder=2, color='C1') axs[2].text(0.03, 0.05, 'Sum', ha='left', va='bottom', transform=axs[2].transAxes, bbox=props, zorder=15, color='C2') axs[2].set_xlabel('Days from 2021-Apr-28') axs[0].set_ylim([-600, 600]) axs[1].set_ylim([-120, 120]) axs[2].set_ylim([-600, 600]) f.text(-0.02,0.5, 'Radial velocity [m/s]', va='center', rotation=90) figpath = os.path.join(RESULTSDIR, 'HIP_67522', f'sim_spot_Nobs{N_obs}.png') savefig(f, figpath, writepdf=0) obs_df = pd.DataFrame({ 't_obs':t_obs, 'rv_obs':rv_obs, 'rv_err_obs':rv_err_obs }) true_df = pd.DataFrame({ 'rv_true_spot':rv_true_spot, 'rv_true_kep':rv_true_kep, 'rv_true':rv_true, 't_true':t_true }) return obs_df, true_df
def plot_dilution_histogram(ap=None): ''' Make the plot of log10(dilution [2px aperture]) vs log10(distance [pc]) for T<16 mag, d<2kpc cluster members. ''' df = pd.read_csv('../../data/cg18_cdips_table1_subset_with_dilution.csv') sel = (df.parallax > 0.5) & (df.Tmag_pred < 16) # d < 2kpc, T<16 df = df[sel] dil_n_px = np.array(df['dilution_ap{:.2f}'.format(ap)]) # y dil_n_px[dil_n_px > 0.999] = 0.999 set_style() plt.close('all') fig, ax = plt.subplots(figsize=(3, 3)) ax.set_xscale('log') ax.set_xlabel('(Target flux)/(Total flux in aperture)'.format(ap)) ax.set_ylabel('Relative probability') ax.set_xlim((10**(-2.05), 1.1)) ax.tick_params(which='both', direction='in', zorder=0) xmin, xmax = 10**(-3), 10**1 log_dil_n_px_bins = np.linspace(np.log10(xmin), np.log10(xmax), 17) x = 10**log_dil_n_px_bins y = np.histogram(np.log10(dil_n_px), log_dil_n_px_bins)[0] x = np.array(list(zip(x[:-1], x[1:]))).flatten() y = np.array(list(zip(y, y))).flatten() ax.plot(x, y, lw=1, color='black') inds = (x <= 0.1) ax.fill_between(x[inds], y[inds], np.zeros_like(y[inds]), facecolor='none', hatch='/', edgecolor='gray', lw=0) frac_not_ok = np.sum(y[inds]) / np.sum(y) nonrecov_str = r'$\approx$' + '{:d}%\ntoo crowded'.format( int(100 * frac_not_ok)) recov_str = r'$\approx$' + '{:d}%\nrecoverable'.format( int(round(100 * (1 - frac_not_ok)))) t = ax.text(10**(-0.5), 11500, recov_str, verticalalignment='center', horizontalalignment='center', fontsize='medium') t.set_bbox(dict(facecolor='white', alpha=1, edgecolor='gray')) t = ax.text(10**(-1.5), 11500, nonrecov_str, verticalalignment='center', horizontalalignment='center', fontsize='medium') t.set_bbox(dict(facecolor='white', alpha=1, edgecolor='gray')) #ax.set_xticklabels([]) ax.set_yticklabels([]) ax.yaxis.set_major_locator(plt.MaxNLocator(5)) format_ax(ax) # ax.yaxis.set_ticks_position('both') # ax.xaxis.set_ticks_position('both') # ax.get_yaxis().set_tick_params(which='both', direction='in') # ax.get_xaxis().set_tick_params(which='both', direction='in') # ax.xaxis.set_tick_params(labelsize='small') # ax.yaxis.set_tick_params(labelsize='small') # ax.tick_params(which='both', direction='in', zorder=0) # ax.spines['right'].set_visible(False) # ax.spines['top'].set_visible(False) ax.set_ylim((0, max(ax.get_ylim()))) outname = ('../../results/dilution_histogram/' 'dil_Tmaglt16_dlt2kpc_cg18_ap{:.2f}px.png'.format(ap)) savefig(fig, outname)
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_period_scatter(active_targets=1, specialyoung=1, show_legend=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 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, 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] target_period = (np.array([8.3]) * u.day) if active_targets: label = ('TOI$\,$837') mfc = 'yellow' if not deemph837 else 'white' ms = 15 if not deemph837 else 8 ax.plot(target_period, target_rp, mew=0.5, markerfacecolor=mfc, markersize=ms, 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! 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(_period, _rp, mew=0.5, markerfacecolor='lightskyblue', markersize=8, marker='*', color='k', lw=0, label=l, zorder=1) # 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 size [Earth radii]') ax.set_xlim([0.1, 1100]) format_ax(ax) ax.set_xscale('log') savstr = '_no_overplot' if not active_targets else '_toi837' if show_legend: savstr += '_yeslegend' else: savstr += '_nolegend' if showcandidates: savstr += '_showcandidates' if deemph837: savstr += '_deemph837' outpath = ( '../results/rp_vs_period_scatter/rp_vs_period_scatter_{}{}.png'.format( today_YYYYMMDD(), savstr)) savefig(fig, outpath, writepdf=1, dpi=400)
def plot_TIC268_nbhd_full(outdir=RESULTSDIR): set_style() df = get_cdips_catalog(ver=0.4) kc19_sel = ((df.cluster.str.contains('NGC_2516')) & (df.reference.str.contains('Kounkel_2019'))) cg18_sel = ((df.cluster.str.contains('NGC_2516')) & (df.reference.str.contains('CantatGaudin_2018'))) target_df = df[df.source_id == 5489726768531119616] # TIC 2683... kc19_df = df[kc19_sel] cg18_df = df[cg18_sel] ########## plt.close('all') params = ['ra', 'dec', 'parallax', 'pmra', 'pmdec'] nparams = len(params) qlimd = { 'ra': 0, 'dec': 0, 'parallax': 0, 'pmra': 0, 'pmdec': 0, 'radial_velocity': 0 } # whether to limit axis by quantile ldict = { 'ra': r'$\alpha$ [deg]', 'dec': r'$\delta$ [deg]', 'parallax': r'$\pi$ [mas]', 'pmra': r'$\mu_{{\alpha}} \cos\delta$ [mas/yr]', 'pmdec': r'$\mu_{{\delta}}$ [mas/yr]', 'radial_velocity': 'RV [km/s]' } f, axs = plt.subplots(figsize=(6, 6), nrows=nparams - 1, ncols=nparams - 1) for i in range(nparams): for j in range(nparams): print(i, j) if j == nparams - 1 or i == nparams - 1: continue if j > i: axs[i, j].set_axis_off() continue xv = params[j] yv = params[i + 1] print(i, j, xv, yv) axs[i, j].scatter(kc19_df[xv], kc19_df[yv], c='gray', alpha=0.9, zorder=2, s=5, rasterized=True, linewidths=0, label='Core', marker='.') axs[i, j].scatter(cg18_df[xv], cg18_df[yv], c='k', alpha=0.9, zorder=3, s=5, rasterized=True, linewidths=0, label='Corona') axs[i, j].plot(target_df[xv], target_df[yv], alpha=1, mew=0.5, zorder=8, label='TOI 1937', markerfacecolor='yellow', markersize=14, marker='*', color='black', lw=0) # set the axis limits as needed if qlimd[xv]: xlim = (np.nanpercentile(kc19_df[xv], 25), np.nanpercentile(kc19_df[xv], 75)) axs[i, j].set_xlim(xlim) if qlimd[yv]: ylim = (np.nanpercentile(kc19_df[yv], 25), np.nanpercentile(kc19_df[yv], 75)) axs[i, j].set_ylim(ylim) # fix labels if j == 0: axs[i, j].set_ylabel(ldict[yv]) if not i == nparams - 2: # hide xtick labels labels = [ item.get_text() for item in axs[i, j].get_xticklabels() ] empty_string_labels = [''] * len(labels) axs[i, j].set_xticklabels(empty_string_labels) if i == nparams - 2: axs[i, j].set_xlabel(ldict[xv]) if not j == 0: # hide ytick labels labels = [ item.get_text() for item in axs[i, j].get_yticklabels() ] empty_string_labels = [''] * len(labels) axs[i, j].set_yticklabels(empty_string_labels) if (not (j == 0)) and (not (i == nparams - 2)): # hide ytick labels labels = [ item.get_text() for item in axs[i, j].get_yticklabels() ] empty_string_labels = [''] * len(labels) axs[i, j].set_yticklabels(empty_string_labels) # hide xtick labels labels = [ item.get_text() for item in axs[i, j].get_xticklabels() ] empty_string_labels = [''] * len(labels) axs[i, j].set_xticklabels(empty_string_labels) # axs[2,2].legend(loc='best', handletextpad=0.1, fontsize='medium', framealpha=0.7) # leg = axs[2,2].legend(bbox_to_anchor=(0.8,0.8), loc="upper right", # handletextpad=0.1, fontsize='medium', # bbox_transform=f.transFigure) for ax in axs.flatten(): format_ax(ax) f.tight_layout(h_pad=0.1, w_pad=0.1) outpath = os.path.join(outdir, 'full_kinematics.png') savefig(f, outpath)
def SpadaLanzafame20_gyro(BmV=None, Prot=None, makeplot=True): """ Spada & Lanzafame 2020 give gyrochrones in B-V (and mass) vs age space. Will need to interpolate between them on a 2D grid. """ sl20path = os.path.join(DATADIR, 'Spada_Lanzafame_2020_BmV_table.csv') df = pd.read_csv(sl20path, sep='&') from scipy.interpolate import interp2d, interp1d from scipy.optimize import newton df = df.sort_values(by='BmV') BmV_arr = np.array(df.BmV).astype(float) age_gyr = np.array(df.columns[1:-1]).astype(float) Prot_array = np.array(df[[ c for c in df.columns if (c != 'BmV' and c != '4.57') ]]).astype(float) fn = interp2d(age_gyr, BmV_arr, Prot_array, kind='cubic', bounds_error=False, fill_value=0) N_pts = 100 BmV_new = np.linspace(min(BmV_arr), max(BmV_arr), N_pts) age_new = np.linspace(min(age_gyr), max(age_gyr), 2 * N_pts) Prot_new = fn(age_new, BmV_new) if makeplot: from aesthetic.plot import set_style, savefig set_style() fig, ax = plt.subplots(figsize=(4, 3)) X, Y = np.meshgrid(BmV_new, age_new) #cmap = plt.cm.viridis cmap = plt.cm.Paired norm = mpl.colors.Normalize(vmin=np.nanmin(Prot_new), vmax=np.nanmax(Prot_new)) im = ax.pcolormesh(X, Y, Prot_new.T, cmap=cmap, norm=norm, shading='flat') # vs 'gouraud' ax.set_xlabel('B-V') ax.set_ylabel('Age [Gyr]') cbar = fig.colorbar(im, orientation='vertical', extend='min', label='Prot [day]') cbar.ax.tick_params(labelsize=6, direction='out') outpath = os.path.join(RESULTSDIR, 'SpadaLanzafame2020', 'interpolation_check.png') savefig(fig, outpath, writepdf=False) age_gyrs = [] for _prot, _bmv in zip(Prot, BmV): nearest_BmV, idx = find_nearest(BmV_new, _bmv, verbose=True, return_index=True) # now it's a 1-dimensional optimization problem fn_1d = interp1d(age_new, Prot_new[idx, :], kind='quadratic', bounds_error=False, fill_value=0) interp_fn2 = lambda x: fn_1d(x) - _prot age_init_gyr = 2 try: root_age_gyr = newton(interp_fn2, age_init_gyr) except: if _prot > max(Prot_new[idx, :]): root_age_gyr = 10 else: root_age_gyr = 0 age_gyrs.append(root_age_gyr) t_yr = np.array(age_gyrs) * 1e9 return t_yr
def plot_cks_rp_vs_gyroage(Prot_source='M15', gyro_source='A19'): """ Prot_source: M13 or M15 gyro_source: MH08 or A19 or SL20 Make scatter plots of {plantet radius, orbital period} against gyrochronology ages in a few different projections. """ mdf = get_merged_gyroage_CKS(Prot_source=Prot_source, gyro_source=gyro_source) outdir = join(RESULTSDIR, f'{Prot_source}rot_{gyro_source}gyroage') if not os.path.exists(outdir): os.mkdir(outdir) set_style() agelabel = (f'Gyro-Age [{Prot_source} '+'P$_\mathrm{rot}$ +' +f'{gyro_source}; yr]') for scale in ['linear','log']: f, ax = plt.subplots(figsize=(4,3)) ax.scatter(mdf.VIIp_Rp, mdf.gyroage_yr, s=2, c='k', zorder=3) ax.set_xlabel('CKS-VII R$_\mathrm{p}$ [R$_\oplus$]') ax.set_ylabel(agelabel) ax.set_xscale(scale); ax.set_yscale('log') ylim = ax.get_ylim() ymax = 1.5e10 ax.set_ylim([1e8, ymax]) print(f'WRN! {len(mdf[mdf.gyroage_yr > ymax])} older than max plotted gyroage') outpath = join(outdir, f'cks-VII_rp_vs_gyroage_{scale}.png') savefig(f, outpath, writepdf=0) plt.close('all') f, ax = plt.subplots(figsize=(4,3)) ax.scatter(mdf.VIIp_Per, mdf.gyroage_yr, s=2, c='k') ax.set_xlabel('CKS-VII P$_\mathrm{orb}$ [day]') ax.set_ylabel(agelabel) ax.set_xscale('log'); ax.set_yscale('log') ylim = ax.get_ylim() ymax = 1.5e10 ax.set_ylim([ylim[0], ymax]) outpath = join(outdir, 'cks-VII_period_vs_gyroage.png') savefig(f, outpath, writepdf=0) plt.close('all') f, ax = plt.subplots(figsize=(4.3,3)) Prot_key = 'Prot' if Prot_source in ['M13','M15','S21'] else 'spec_Prot' sel = ~pd.isnull(mdf[Prot_key]) norm = mpl.colors.Normalize(vmin=8.5, vmax=10) cax = ax.scatter(mdf[sel].VIIp_Per, mdf[sel].VIIp_Rp, s=7, c=np.log10(mdf[sel].gyroage_yr), cmap='plasma_r', zorder=3, norm=norm, edgecolors='k', linewidths=0.2) ax.set_xlabel('CKS-VII P$_\mathrm{orb}$ [day]') ax.set_ylabel('CKS-VII R$_\mathrm{p}$ [R$_\oplus$]') ax.set_xscale('log'); ax.set_yscale('log') cbar = f.colorbar(cax, extend='both') cbar.set_label('log$_{10}$'+agelabel, fontsize='small') cbar.minorticks_off() outpath = join(outdir, 'cks-VII_period_vs_cks-VII_prad_gyroagecolors.png') savefig(f, outpath, writepdf=0)
def plot_mass_vs_age_scatter(active_targets=1, specialyoung=1, showcandidates=0, show_legend=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) m_gt_0 = (ea_tab['pl_bmassj'] > 0) & (np.abs(ea_tab['pl_bmassjerr1']) > 0) has_m_errs = (~ea_tab['pl_bmassjerr1'].mask) & ( ~ea_tab['pl_bmassjerr2'].mask) transits = (ea_tab['pl_tranflag'] == 1) sel = (has_age_value & has_age_errs & has_rp_value & has_rp_errs & transits & rp_gt_0 & m_gt_0 & has_m_errs) 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 mass = t['pl_bmassj'] ########################################## 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 700 Myr:') _t = t[(t['st_age'] < 0.7 * 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, mass, 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') ax.plot(target_age, target_mass, 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! 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)) ax.plot(_age, _rp, mew=0.5, markerfacecolor='lightskyblue', markersize=8, marker='*', color='k', lw=0, label='New Planet Candidates', zorder=1) # 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('Age [billion years]') ax.set_ylabel(r'Planet mass [M$_\mathrm{Jup}$]') ax.set_xlim([6e-3, 17]) ax.set_ylim([0.001, 1e2]) format_ax(ax) ax.set_xscale('log') ax.set_yscale('log') savstr = '_no_overplot' if not active_targets else '_toi837' if showcandidates: savstr += '_showcandidates' if show_legend: savstr += '_yeslegend' else: savstr += '_nolegend' outpath = ( '../results/mass_vs_age_scatter/mass_vs_age_scatter_{}{}.png'.format( today_YYYYMMDD(), savstr)) savefig(fig, outpath, writepdf=1, dpi=400)
def plot_Porb_Prot(snr_cutoff=2, includefit=False): sel = (((d['SPer'] / d['E_SPer']) > snr_cutoff) & (d['SPer'] < 30)) sel0 = (((d['SPer'] / d['E_SPer']) > snr_cutoff) & (d['R_'] < 1.2) & (d['SPer'] < 30)) sel1 = (((d['SPer'] / d['E_SPer']) > snr_cutoff) & (d['R_'] >= 1.2) & (d['SPer'] < 30)) sel2 = (((d['SPer'] / d['E_SPer']) > snr_cutoff) & (d['R_'] < 1.2) & (d['SPer'] < 8)) sel3 = (((d['SPer'] / d['E_SPer']) > snr_cutoff) & (d['R_'] < 1.2) & (d['Per'] < 1)) print(d['ID'][sel2]) print(d['ID'][sel3]) # # make the plot! # set_style() f, ax = plt.subplots(figsize=(4, 3)) Porb_1937 = 0.947 Prot_1937 = 6.5 ax.scatter(d['Per'][sel0], d['SPer'][sel0], zorder=2, c='k', alpha=0.9, s=9, linewidths=0, label='HJs ($\mathrm{R}_{\star} < 1.2 \mathrm{R}_{\odot}$)') ax.scatter(d['Per'][sel1], d['SPer'][sel1], zorder=2, c='gray', alpha=0.9, s=9, linewidths=0, label='HJs ($\mathrm{R}_{\star} \geq 1.2 \mathrm{R}_{\odot}$)') ax.plot(Porb_1937, Prot_1937, mew=0.5, zorder=3, markerfacecolor='yellow', markersize=18, marker='*', color='k', lw=0, label='TOI 1937b (1.1$\mathrm{R}_{\odot}$)') if includefit: x = np.hstack([d['Per'][sel0], Porb_1937]) y = np.hstack([d['SPer'][sel0], Prot_1937]) slope, intercept, rvalue, pvalue, stderr = linregress(x, y) label = f'Slope={slope:.1f}$\pm${stderr:.1f}, p={pvalue:.1e}' ax.plot(x, intercept + slope * x, label=label) # Shrink current axis by 20% box = ax.get_position() ax.set_position([box.x0, box.y0, box.width * 0.8, box.height]) # Put a legend to the right of the current axis ax.legend(loc='center left', bbox_to_anchor=(1, 0.5), handletextpad=0.1) ax.set_xlabel('Planet orbital period [days]') ax.set_ylabel('Stellar spin period [days]') ax.set_xlim([0.5, 4.2]) ax.set_ylim([2, 28]) extrastr = '_withfit' if includefit else '_nofit' figpath = ( f'../results/Porb_Prot/Porb_Prot_snrcut{snr_cutoff}{extrastr}.png') savefig(f, figpath)