def _compute_sigrp(frac_sigRs=.1): ''' Use the TESS parameters to estimate the measurement uncertainty on the planet's radius. See http://adsabs.harvard.edu/abs/2008ApJ...689..499C for equations. ''' # Get the 3sigma results starnums, Nharps, Nnirps, Nspirou, texpharps, texpnirps, texpspirou, tobsharps, tobsnirps, tobsspirou, min_Nrv, bestspectrograph_Nrv, min_tobs, bestspectrograph_tobs = np.loadtxt( 'Results/median_results_3sigma_mp.dat', delimiter=',').T # Get TESS parameters including photometric uncertainty inds = np.array([2, 3, 5, 6, 14]) rp, P, K, Rs, logsigV = np.ascontiguousarray(get_TESS_data())[inds] # Compute transit depth uncertainty depth = compute_depth(rp, Rs) Gamma = compute_Gamma() T = compute_transit_duration(rp, P, K, Rs) Q = compute_Q(Gamma, T, depth, logsigV) sigdepth = compute_sigdepth(depth, Q) # compute corresponding planet radius uncertainty depth = unp.uarray(depth, sigdepth) Rs2 = rvs.m2Rearth(rvs.Rsun2m(unp.uarray(Rs, frac_sigRs * Rs))) rp2 = unp.sqrt(depth) * Rs2 return rp, unp.std_devs(rp2)
def _P2h(P, Ps, T, mu=28.97): ''' Convert the atmospheric pressure to a depth in Earth radii. Parameters ---------- `P': array-like Atmospheric pressure as a function of depth in Pascals `T': array-like 4D atmospheric temperature in kelvin ''' # reshape arrays Ntime, NP, Nlat, Nlon = T.shape P4 = np.repeat(np.repeat(np.repeat(P[np.newaxis, :], Ntime, axis=0)[:, :, np.newaxis], Nlat, axis=2)[:, :, :, np.newaxis], Nlon, axis=3) assert P4.shape == T.shape Ps4 = np.repeat(Ps[:, np.newaxis, :, :], NP, axis=1) assert Ps4.shape == T.shape # compute depth vs pressure H = kb * T / (g * mu * mp) return rvs.m2Rearth(H * np.log(Ps4 / P4))
def depth2rp(P_days, depth, duration_days, Ms, Rs): '''Compute the planet radius from the transit depth and duration using the analtyical treatment from Mandel & Agol 2002''' assert 0 < depth < 1 # compute distance from centres at T0 sma = rvs.semimajoraxis(P_days, Ms, 0) a_Rs = rvs.AU2m(sma) / rvs.Rsun2m(Rs) assert a_Rs > 1 b = rvs.impactparam_T(P_days, Ms, Rs, duration_days) assert abs(b) <= 1 inc = float(rvs.inclination(P_days, Ms, Rs, b)) z = compute_distance_center(a_Rs, inc) # compute size ratio (p=rp/Rs) p_simple = unp.sqrt(depth) if z <= 1 - p_simple: p = p_simple else: ps = np.logspace(-6, 0, 1000) depths = p2depth_grazing(ps, z) if (np.nanmax(depths) < z) or (np.nanmin(depths) > z): p = p_simple else: fint = interp1d(ps, depths) p = float(fint(depth)) # compute planet radius rp = rvs.m2Rearth(rvs.Rsun2m(p * Rs)) return rp
def estimate_box_transit_model(P, T0, Rs, t, f, ef): '''Estimate the transit depth and duration given P and T0. Return the box transit model.''' phase = foldAt(t, P, T0) phase[phase > .5] -= 1 intransit_approx = (phase * P <= 15. / 60 / 24) & (phase * P >= -15. / 60 / 24) depth = np.median(f[intransit_approx]) duration = rvs.transit_width(P, Rs, Rs, rvs.m2Rearth(np.sqrt(depth) * rvs.Rsun2m(Rs)), 0) model = llnl.box_transit_model((P, T0, depth, duration), t) return model
def rpRs2rp(rpRs, Rs): rp = rvs.m2Rearth(rvs.Rsun2m(rpRs * Rs)) return unp.nominal_values(rp), unp.std_devs(rp)
def sample_planet_params(self, index, postGAIA=True): '''sample distribution of planet parameters from observables and stellar pdfs''' # get stellar parameters PDFs either from derived from GAIA distances # or from original Kepler parameters (approximate distributions as skewnormal) g = int(index) print self.KepIDs[g] if postGAIA: path = '../GAIAMdwarfs/Gaia-DR2-distances_custom/DistancePosteriors/' try: samp_Rs, samp_Teff, samp_Ms = np.loadtxt('%s/KepID_allpost_%i' % (path, self.KepIDs[g]), delimiter=',', usecols=(9, 10, 11)).T except IOError: samp_Rs, samp_Teff, samp_Ms = np.zeros(1000), np.zeros( 1000), np.zeros(1000) if np.all(np.isnan(samp_Rs)) or np.all(np.isnan(samp_Teff)) or np.all( np.isnan(samp_Ms)): samp_Rs, samp_Teff, samp_Ms = np.zeros(1000), np.zeros( 1000), np.zeros(1000) samp_Rs = resample_PDF(samp_Rs[np.isfinite(samp_Rs)], samp_Rs.size, sig=1e-3) samp_Teff = resample_PDF(samp_Teff[np.isfinite(samp_Teff)], samp_Teff.size, sig=5) samp_Ms = resample_PDF(samp_Ms[np.isfinite(samp_Ms)], samp_Ms.size, sig=1e-3) else: _, _, samp_Rs = get_samples_from_percentiles(self.Rss1[g], self.ehi_Rss1[g], self.elo_Rss1[g], Nsamp=1e3) _, _, samp_Teff = get_samples_from_percentiles(self.Teffs1[g], self.ehi_Teffs1[g], self.elo_Teffs1[g], Nsamp=1e3) _, _, samp_Ms = get_samples_from_percentiles(self.Mss1[g], self.ehi_Mss1[g], self.elo_Mss1[g], Nsamp=1e3) # sample rp/Rs distribution from point estimates _, _, samp_rpRs = get_samples_from_percentiles(self.rpRs[g], self.ehi_rpRs[g], self.elo_rpRs[g], Nsamp=samp_Rs.size) # compute planet radius PDF samp_rp = rvs.m2Rearth(rvs.Rsun2m(samp_rpRs * samp_Rs)) v = np.percentile(samp_rp, (16, 50, 84)) rps = v[1], v[2] - v[1], v[1] - v[0] # compute semi-major axis PDF samp_Ps = np.random.normal(self.Ps[g], self.e_Ps[g], samp_Ms.size) samp_as = rvs.semimajoraxis(samp_Ps, samp_Ms, 0) v = np.percentile(samp_as, (16, 50, 84)) smas = v[1], v[2] - v[1], v[1] - v[0] # compute equilibrium T PDF (Bond albedo=0) samp_Teq = samp_Teff * np.sqrt( .5 * rvs.Rsun2m(samp_Rs) / rvs.AU2m(samp_as)) v = np.percentile(samp_Teq, (16, 50, 84)) Teqs = v[1], v[2] - v[1], v[1] - v[0] # compute insolation samp_F = samp_Rs**2 * (samp_Teff / 5778.)**4 / samp_as**2 v = np.percentile(samp_F, (16, 50, 84)) Fs = v[1], v[2] - v[1], v[1] - v[0] return rps, smas, Teqs, Fs
def get_data(self): self.fs = np.array( glob.glob('%s/%s_%i/*LC*' % (self.folder, self.prefix, self.epicnum))) # remove planet search result (i.e. with index -99) if np.any( np.in1d( self.fs, '%s/%s_%i/%sLC_-00099' % (self.folder, self.prefix, self.epicnum, self.prefix))): g = np.where( np.in1d( self.fs, '%s/%s_%i/LC_-00099' % (self.folder, self.prefix, self.epicnum)))[0][0] self.fs = np.delete(self.fs, g) if self.fs.size == 0: return None self.Nsim = 0 d = loadpickle(self.fs[0]) self.Kepmag, self.logg, self.Ms, self.Rs, self.Teff = d.Kepmag, \ d.logg, \ d.Ms, d.Rs, \ d.Teff self.e_logg, self.e_Ms, self.e_Rs, self.e_Teff = d.e_logg, \ d.e_Ms, d.e_Rs, \ d.e_Teff Nmax = 20 self.Nplanets_true, self.Nplanets_found = np.zeros(0), np.zeros(0) self.Ps, self.rps, self.isdet = np.zeros((0, Nmax)), np.zeros( (0, Nmax)), np.zeros((0, Nmax)) self.Psfound, self.rpsfound, self.isFP = np.zeros((0, Nmax)), np.zeros( (0, Nmax)), np.zeros((0, Nmax)) for i in range(self.fs.size): print float(i) / self.fs.size d = loadpickle(self.fs[i]) if d.DONE: self.Nsim += 1 self.Nplanets_true = np.append(self.Nplanets_true, d.Ptrue.size) filler = np.repeat(np.nan, Nmax - self.Nplanets_true[-1]) Pin = np.append(d.Ptrue, filler) rpin = np.append(d.rptrue, filler) isdetin = np.append(d.is_detected, filler) self.Ps = np.append(self.Ps, Pin.reshape(1, Nmax), axis=0) self.rps = np.append(self.rps, rpin.reshape(1, Nmax), axis=0) self.isdet = np.append(self.isdet, isdetin.reshape(1, Nmax), axis=0) # get false positives TEMP because d.is_FP doesnt exist yet until # the simulation is rerun params = d.params_guess self.Nplanets_found = np.append(self.Nplanets_found, params.shape[0]) filler2 = np.repeat(np.nan, Nmax - self.Nplanets_found[-1]) Pinfound = np.append(params[:, 0], filler2) rpinfound = np.append( rvs.m2Rearth(rvs.Rsun2m(np.sqrt(params[:, 2]) * d.Rs)), filler2) self.Psfound = np.append(self.Psfound, Pinfound.reshape(1, Nmax), axis=0) self.rpsfound = np.append(self.rpsfound, rpinfound.reshape(1, Nmax), axis=0) is_FPin = np.array([ int( np.invert( np.any(np.isclose(d.Ptrue, params[i, 0], rtol=.02)))) for i in range(params.shape[0]) ]).astype(bool) self.isFP = np.append(self.isFP, np.append(is_FPin, filler2).reshape(1, Nmax), axis=0) # trim excess planets end = np.where(np.all(np.isnan(self.Ps), axis=0))[0][0] self.Ps = self.Ps[:, :end] self.rps = self.rps[:, :end] self.isdet = self.isdet[:, :end] #end2 = np.where(np.all(np.isnan(self.PsFP), axis=0))[0][0] self.Psfound = self.Psfound[:, :end] self.rpsfound = self.rpsfound[:, :end] self.isFP = self.isFP[:, :end]
def identify_EBs(params, bjd, fcorr, ef, Ms, Rs, Teff, SNRthresh=3., rpmax=30, detthresh=5, Kep=False, TESS=False): '''For each proposed planet in params, run through a variety of checks to vetting the planetary candidates and identify EB false positives.''' assert len(params.shape) == 2 Nplanets = params.shape[0] paramsout, isEB, maybeEB = np.zeros_like(params), np.zeros(Nplanets), \ np.zeros(Nplanets) EBconditions = np.zeros((Nplanets, 5)).astype(bool) EBcondition_labels = np.array([ 'rpRs > 0.5', 'rp>%.1f' % rpmax, 'secondary eclipse detected', 'transit is V-shaped', 'transit duration is too long for a planet' ]) for i in range(Nplanets): # get best fit parameters paramsout[i] = _fit_params(params[i], bjd, fcorr, ef, Ms, Rs, Teff, Kep=Kep, TESS=TESS) # ensure the planet is not too big rpRs = np.sqrt(params[i, 2]) isEB[i] = 1 if rpRs > .5 else isEB[i] EBconditions[i, 0] = True if rpRs > .5 else False rp = rvs.m2Rearth(rvs.Rsun2m(rpRs * Rs)) isEB[i] = 1 if rp > rpmax else isEB[i] EBconditions[i, 1] = True if rp > rpmax else False # check for secondary eclipse eclipse = _is_eclipse(params[i], bjd, fcorr, ef, detthresh) isEB[i] = 1 if eclipse else isEB[i] EBconditions[i, 2] = True if eclipse else False # check for ellipsoidal variations #ellipsoidal = _is_ellipsoidal() #isEB[i] = 1 if ellipsoidal else isEB[i] # how can I do this without knowing the parameters of the binary? # flag V-shaped transits (does not implies an EB) Vshaped, duration = _is_Vshaped(params[i], bjd, fcorr, ef, Ms, Rs, Teff, Kep, TESS) maybeEB[i] = 1 if Vshaped else maybeEB[i] EBconditions[i, 3] = True if Vshaped else False # is duration reasonable? # Gunther+2016 EBduration = _is_EB_duration(duration, paramsout[i, 0], Ms, Rs) isEB[i] = 1 if EBduration else isEB[i] EBconditions[i, 4] = True if EBduration else False # save planet and EB parameters maybeEB[isEB == 1] = 1 isEB, maybeEB = isEB.astype(bool), maybeEB.astype(bool) params, EBparams, maybeEBparams = params[np.invert(isEB)], params[isEB], \ params[maybeEB] return params, EBparams, maybeEBparams, EBconditions, EBcondition_labels