def get_period(t,f_t,outputpath='',starname=''): # here we use a BLS algorithm to create a periodogram and find the best periods. The BLS is implemented in Python by Ruth Angus and Dan Foreman-Mackey outputfolder = os.path.join(outputpath,str(starname)) fmin = 2.0/((t[len(t)-1]-t[0])) # minimum frequency. we can't find anything longer than 90 days obviously nf = 1e5 # amount of frequencies to try df = 1e-4#0.00001 # frequency step qmi = 0.0005 # min relative length of transit (in phase unit) qma = 0.1 # max relative length of transit (in phase unit) nb = 200 # number of bins in folded LC u = np.linspace(fmin,fmin + nf*df,nf) v = np.array(0) t = np.array(t) f_t = np.array(f_t) t_orig = np.copy(t) f_t_orig = f_t results = bls.eebls(t,f_t,t,f_t,nf,fmin,df,nb,qmi,qma) freqlist = u powers = results[0] period = results[1] folded,f_t_folded = fold_data(t,f_t,period) np.savetxt(os.path.join(outputfolder, 'PhaseFolded.txt'),np.transpose([folded,f_t_folded]),header='Time, Flux') t_foldbin,f_t_foldbin,stdv_foldbin = rebin_dataset(folded,f_t_folded,15) f_t_smooth = savitzky_golay(f_t_folded,29,1) pl.figure('my data folded bls') pl.plot(folded,f_t_folded+1.,'.',color='black',label='K2 photometry') pl.xlabel('Time [d]') pl.ylabel('Relative Flux') pl.savefig(os.path.join(outputfolder, 'PhaseFolded.png')) pl.close('all') # unravel again n_start = int(np.round(t[0] / period)) n_end = np.round(t[-1] / period) + 1 i = n_start t_unravel = [] f_t_unravel = [] while i < n_end: t_unravel.append(np.array(folded) + i*period + t_orig[0]) f_t_unravel.append(np.array(f_t_smooth)) pl.plot(t_unravel[i],f_t_unravel[i],color='black',lw='1.5') i = i + 1 if abs(period-0.24)<0.01: freqlist,powers = maskout_freqs(freqlist,powers,freq=0.245) # spacecraft freqs Location = np.where(powers==max(powers)) period = freqlist[Location[0]][0] print "The best period is: ", period return folded,f_t_folded,period,freqlist,powers
def BLS(self,time, lc, df = 0.0001, nf = 500, nb = 200, qmi = 0.01,\ qma = 0.8, fmin = (1./(400.0*1.1))): diffs = time[1:] - time[:-1] u = np.ones(len(time)) v = np.ones(len(time)) BLS = bls.eebls(time, lc, u, v, nf, fmin, df, nb, qmi, qma) f = fmin + (np.arange(len(BLS[0])))*df return BLS, 1/f, nb
def BLS(time, lc, df=0.0001, nf=500, nb=200, qmi=0.01, qma=0.8, fmin=(1.0 / (400.0 * 1.1))): u = numpy.ones(len(time)) v = numpy.ones(len(time)) BLS = bls.eebls(time, lc, u, v, nf, fmin, df, nb, qmi, qma) f = fmin + (numpy.arange(len(BLS[0]))) * df return BLS, 1 / f, nb
def process_lightcurve(lc, lc_duration): time = lc.times flux = lc.fluxes # Run this light curve through original FORTRAN implementation of BLS u = np.zeros_like(time) v = np.zeros_like(time) qmi = 0.25 qma = lc_duration / 2 results = bls.eebls(time, flux, u, v, nf, fmin, df, nb, qmi, qma) # Return results return results
def run_bls(file, nf=10000, a_logP = math.log(8000), b_logP = math.log(20000), nb=1500, qmi=0.0005, qma=0.005, verbose=True): if verbose: print "Reading data..." flux = np.loadtxt(file, delimiter=",") if verbose: print "Setting up arrays..." time = range(len(flux)) n = len(flux) u = np.empty(n) v = np.empty(n) if verbose: print "Setting up BLS specs..." #Most of this are set through the function call, so I commented this out. For use later, perhaps. # Prior for period: min_period = math.exp(a_logP) max_period = math.exp(b_logP) ### Email Specs #### fmin = 1 / max_period fmax = 1 / min_period df = (fmax - fmin) / nf if verbose: print "EEBLS parameters:" print "nf=" + str(nf) print "fmin=" + str(fmin) print "fmax=" + str(fmax) print "df=" + str(df) print "nb=" + str(nb) print "qmi=" + str(qmi) print "qma=" + str(qma) print "Running EEBLS..." results = bls.eebls(time, flux, u, v, nf, fmin, df, nb, qmi, qma) #f = fmin + (np.arange(len(results[0])))*df if verbose: print "Done. Results:" print results return results
def compute(self, verbose=True): """ Compute using bls.eebls() """ self.results = bls.eebls(self.t, self.f, self.u, self.v, self.nf, self.fmin, self.df, self.nb, self.qmi, self.qma) self._power = self.results[0] self._freq = self.fmin + np.arange(self.nf) * self.df self._best_period = self.results[1] self._best_freq = 1.0 / self._best_period self._best_power = self.results[2] self._depth = self.results[3] self._q = self.results[4] self._fraqdur = self.results[4] self._in1 = self.results[5] self._in2 = self.results[6] # Taking a look at https://github.com/dfm/python-bls/blob/master/ruth_bls2.py self._duration = self._best_period * self._q self._phase1 = self._in1 / float(self.nb) self._phase2 = self._in2 / float(self.nb) self._transit_number = int( (max(self.t) - min(self.t)) / self._best_period) self._epoch = self.t[ 0] + self._phase1 * self._best_period + self._duration / 2. self._ingresses = np.zeros(self._transit_number) self._egresses = np.zeros(self._transit_number) for n in range(0, self._transit_number): self._ingresses[n] = (self._epoch + self._best_period * n) #- 0.2 self._egresses[ n] = self._epoch + self._best_period * n + self._duration # + 0.2 # add a margin each side self._duration_approx = self._egresses[0] - self._ingresses[0] if verbose == True: print("=====Results====") print("Best period:", self._best_period) print("Best freq:", self._best_freq) print("Depth:", self._depth) print("Epoch:", self._epoch) print("Number of transits:", self._transit_number)
def BLS(time, mergedfluxD): #time array, detrended flux arr (with transits injected) u = [0.0] * len(time) v = [0.0] * len(time) u = np.array(u) v = np.array(v) #time, flux, u, v, number of freq bins (nf), min freq to test (fmin), freq spacing (df), number of bins (nb), min transit dur (qmi), max transit dur (qma) nf = 1000.0 fmin = .035 df = 0.001 nbins = 300 qmi = 0.001 qma = 0.3 results = bls.eebls(time, mergedfluxD, u, v, nf, fmin, df, nbins, qmi, qma) #RESULTS: #power, best_period, best_power, depth, q, in1, in2 #0 1 2 3 4 5 6 SR_array = results[0] max_SR = max(SR_array) avg_SR = np.mean(SR_array) sd_SR = np.std(SR_array) #normaze SR_array between 0 and 1 SR_array = [i / max_SR for i in SR_array] freq = fmin + np.arange(nf) * df #Signal Detection Efficiency SDE = (max_SR - avg_SR) / sd_SR #depth high = results[3] * results[4] low = high - results[3] fit = np.zeros(nbins) + high # H fit[results[5]:results[6] + 1] = low # L depth = high - low return results, SR_array, freq, SDE, depth
def blswrap(epicid, campaign, initial_time): global nbin try: start = time.time() initial_time = float(initial_time) t, f = data.retrieve(epicid, campaign, directory=directory) if initial_time != 0: t, f = t[t>initial_time], f[t>initial_time] u, v = np.zeros(len(t)), np.zeros(len(f)) #minfreq, dfreq, nfreq = 1/70., 4.082799167108228e-06, 1000000 minfreq, dfreq, nfreq = 0.015, 2.0437359493152146e-05,100000 #nbin = 100 minduration, maxduration = 0.01, 0.05 results = bls.eebls(t, f, u, v, nfreq, minfreq, dfreq, nbin, minduration, maxduration) end = time.time() print(epicid, end - start) return epicid, results[1:] except: print("SKIPPING " + str(epicid))
def calc_bls(t, f, nf=10000, nb=1500, verbose=False, **bls_kwargs): """Main work-function, calculates the bls spectrum of an array. Uses EEBLS, programmed by Dan Foreman-Mackey, see: https://github.com/dfm/python-bls From the algorithm by Kovacs Zucker & Mazeh (2002) For a possible improvement, see: https://github.com/hpparvi/PyBLS Args: t (np.array-like): array of times f (np.array-like): array of fluxes (same len as t) nf (int): nb (int): verbose (bool): print information such as run-time **bls_kwargs: can contain qmi, qma, fmin, fmax etc... Returns: df_result, best_period, t0, duration, depth, (bls_output**) bls_result: pd.DataFrame with columns [f, period, power] bls_output**: the output values from the bls (power, best_period, best_power, depth, fractional_duration, in1, in2) Exceptions: """ # This is a temporary fix and shouldn't be relied on if np.nanmedian(f) < 0.1: f = f - 1.0 # Blocks the run if it would cause a FORTRAN error. if len(t) < 10: raise InvalidLightcurveError("Lightcurve has less then 10 points.") # Prepare parameters. # Observation duration: T = max(t) - min(t) assert T > 0 # Try to catch this earlier # Default frequency limits: fmax = 2. # 12h period is minimum/maximum fmin = 2./T # Require two transits currently # TODO: What happens if fmin is too low? Does BLS raise an error? # YES. # Unpack kwargs and replace the main values if 'qmi' in bls_kwargs.keys(): qmi = bls_kwargs['qmi'] if 'qma' in bls_kwargs.keys(): qma = bls_kwargs['qma'] if 'fmin' in bls_kwargs.keys(): fmin = bls_kwargs['fmin'] if 'fmax' in bls_kwargs.keys(): fmax = bls_kwargs['fmax'] # Frequency step. df = (fmax - fmin)/nf # Transit ratios/durations: qmi = (0.5/24)*fmin # assume half hour transit at minimum frequency qma = 0.1 # Run checks on the parameters. # Skip all lightcurves that are less than 4 days currently. if T < min_light_curve: raise ShortLightcurveError("Skipping shortened lightcurve (T = {}).".format(T)) # fmin must be greater than fmax. if fmin > fmax: raise ValueError("fmin > fmax - Observation period may be less than a day.") assert len(t) == len(f) # Period (1/fmin) greater than T if fmin < 1/T: raise InvalidLightcurveError("Max period (1/fmin) greater than" "lightcurve timescale.") # Run the BLS # ----------- # The work arrays. u = np.empty(len(t), dtype=float) v = np.empty(len(t), dtype=float) start_time = time.time() power, best_period, best_power, depth, fractional_duration, in1, in2 = bls.eebls(t, f, u, v, nf, fmin, df, nb, qmi, qma) run_time = time.time() - start_time # Brief explanation of output: # ---------------------------- # best_period is best-fit period in same units as time # best_power is the fit at best_period # depth is the depth of transit at best_period # in1 is the bin index at the start of the transit # in2 is the bin index at the end of transit if verbose: print("BLS running time: {}".format(run_time)) # Package results. frequencies = fmin + np.arange(nf) * df periods = 1./frequencies assert len(frequencies) == len(power) df_result = pd.DataFrame({'frequency':frequencies, 'period':periods, 'power':power}) # Convert in1 and in2 to t0 and duration perhaps duration = fractional_duration * best_period t0 = min(t) + best_period * (in1 + in2)/(2*nb) #tt0 = 0 return df_result, best_period, t0, duration, depth, (power, best_period, best_power, depth, fractional_duration, in1, in2)
def calc_smart_bls(t, f, split_info=None, verbose=False, **split_kwargs): """Main work-function, calculates the bls spectrum of an array. Uses EEBLS, programmed by Dan Foreman-Mackey, see: https://github.com/dfm/python-bls From the algorithm by Kovacs Zucker & Mazeh (2002) For a possible improvement, see: https://github.com/hpparvi/PyBLS NOTE BUG: Current issue is that fractional_duration can be greater than the maximum fractional_duration (qma) Args: t (np.array-like): array of times f (np.array-like): array of fluxes (same len as t) split_info (pd.DataFrame): the information DataFrame controlling the runs. If not given, parameters must be input into split_kwargs verbose (bool): print information such as run-time, nf **split_kwargs: if split_info not given P_min, P_max, T, R_star, M_star, P_step, nf_tol, nb_tol, qms_tol Returns: bls_spectrum, best_period, t0, duration, depth, split_info bls_spectrum: pd.DataFrame with columns [frequency, period, power] split_info: the output values from the bls (best_period, best_power, depth, fractional_duration, in1, in2) Exceptions: """ # This is a temporary fix and shouldn't be relied on if abs(np.nanmedian(f)) > 0.1: print("WARNING: f is not normalised with median at 0.0.", "Subtracting median. Median:", np.nanmedian(f)) f = f - np.nanmedian(f) elif abs(np.nanmedian(f)) > 0.005: f = f - np.nanmedian(f) assert len(t) == len(f) # Prepare parameters # ------------------ T = max(t) - min(t) if split_info is not None: split_info = split_info.copy() elif all(key in split_kwargs for key in ('R_star', 'M_star')): if 'P_min' not in split_kwargs: split_kwargs['P_min'] = 0.5 if 'P_max' not in split_kwargs: split_kwargs['P_max'] = 0.5 + T/2 split_info = get_split_info(T=T, **split_kwargs) else: raise ValueError("split_info not given, and split_kwargs doesn't " "contain enough arguments: {}".format(split_kwargs)) # Block the run if it would cause a FORTRAN error if len(t) < 10: raise InvalidLightcurveError("Lightcurve has less than 10 points.") if T < min_light_curve: raise ShortLightcurveError("Skipping shortened lightcurve " "(T = {}).".format(T)) if (split_info.fmin < 1/T).any(): raise InvalidLightcurveError("Max period (1/fmin) greater than " "lightcurve timescale for one of the " "splits.") if verbose: print("Total nf: {}\n".format(split_info.nf.sum())) # Perform the distributed BLS fitting # ----------------------------------- # Holds the combined bls information bls_spectrum = pd.DataFrame(columns=['frequency', 'period', 'power']) for i in split_info.index: # The work arrays u = np.empty(len(t), dtype=float) v = np.empty(len(t), dtype=float) # Quick bullshit filter if split_info.loc[i, 'nf'] < 1: # TODO BUG: what to do here? make args None? Or what? # Will have to add a spectrum, if not a fake one # Ok, no spectrum addition needed print("negative nf") t_start = time.time() try: (power, best_period, best_power, depth, fractional_duration, in1, in2) = bls.eebls( t, f, u, v, nf=split_info.loc[i, 'nf'], fmin=split_info.loc[i, 'fmin'], df=split_info.loc[i, 'df'], nb=split_info.loc[i, 'nb'], qmi=split_info.loc[i, 'qmi'], qma=split_info.loc[i, 'qma']) except ValueError as e: print("ValueError when running bls.eebls.", split_info.loc[i]) raise IntentValueError( "ValueError when running bls.eebls." + str(e), split_info.loc[i]) t_end = time.time() split_info.loc[i, 'run_time'] = t_end - t_start split_info.loc[i, 'best_power'] = best_power split_info.loc[i, 'best_period'] = best_period split_info.loc[i, 'depth'] = depth split_info.loc[i, 'fractional_duration'] = fractional_duration split_info.loc[i, 'in1'] = in1 split_info.loc[i, 'in2'] = in2 # Package results frequencies = split_info.loc[i, 'fmin'] \ + np.arange(split_info.loc[i, 'nf']) * split_info.loc[i, 'df'] add_spectrum = pd.DataFrame({'frequency':frequencies, 'period':1./frequencies, 'power':power}) bls_spectrum = bls_spectrum.append(add_spectrum, ignore_index=True) if verbose: print("Individual run times:", split_info.run_time) print("Total run time:", split_info.run_time.sum()) # Order the total bls spectrum bls_spectrum.drop_duplicates(subset='frequency', keep='first', inplace=True) bls_spectrum.sort_values(by='frequency', inplace=True) bls_spectrum.index = range(len(bls_spectrum)) # Select the strongest peak across the stitched spectrum imax = split_info.best_power.idxmax() best_period = split_info.loc[imax, 'best_period'] best_power = split_info.loc[imax, 'best_power'] depth = split_info.loc[imax, 'depth'] fractional_duration = split_info.loc[imax, 'fractional_duration'] in1 = split_info.loc[imax, 'in1'] in2 = split_info.loc[imax, 'in2'] nb = split_info.loc[imax, 'nb'] # in1 is the bin index at the start of the transit # in2 is the bin index at the end of transit # Convert in1 and in2 to t0 and duration duration = fractional_duration * best_period t0 = min(t) + best_period * (in1 + in2)/(2*nb) # TODO: turn this into an automatic discarding of any 25% duration # dips **in split_info**, so that it never removes such a large fraction if fractional_duration >= 0.25: pd.set_option('display.max_rows', 10) pd.set_option('display.max_columns', 20) print(split_info, "\nduration = {}".format(fractional_duration), "\nsplit_kwargs = {}".format(split_kwargs)) return (bls_spectrum, best_period, best_power, t0, duration, depth, split_info)
def get_period(t, f_t, outputpath='', starname=''): # here we use a BLS algorithm to create a periodogram and find the best periods. The BLS is implemented in Python by Ruth Angus and Dan Foreman-Mackey outputfolder = os.path.join(outputpath, str(starname)) fmin = 2.0 / ( (t[len(t) - 1] - t[0]) ) # minimum frequency. we can't find anything longer than 90 days obviously nf = 3e6 # amount of frequencies to try df = 1e-5 #0.00001 # frequency step qmi = 0.0005 # min relative length of transit (in phase unit) qma = 0.1 # max relative length of transit (in phase unit) nb = 200 # number of bins in folded LC u = np.linspace(fmin, fmin + nf * df, nf) v = np.array(0) t = np.array(t) f_t = np.array(f_t) t_orig = np.copy(t) f_t_orig = f_t results = bls.eebls(t, f_t, t, f_t, nf, fmin, df, nb, qmi, qma) freqlist = u powers = results[0] period = results[1] #print(results[2], results[3]) depth = results[2] duration = results[3] folded, f_t_folded = fold_data(t, f_t, period) try: np.savetxt(os.path.join(outputfolder, 'Flattened.txt'), np.transpose([t, f_t]), header='Time, Flux') np.savetxt(os.path.join(outputfolder, 'PhaseFolded.txt'), np.transpose([folded, f_t_folded]), header='Time, Flux') np.savetxt(os.path.join(outputfolder, 'OptimalDepth.txt'), [depth], header='Depth') np.savetxt(os.path.join(outputfolder, 'OptimalDuration.txt'), [duration], header='Fractional Duration') except: os.mkdir(outputfolder) np.savetxt(os.path.join(outputfolder, 'Flattened.txt'), np.transpose([t, f_t]), header='Time, Flux') np.savetxt(os.path.join(outputfolder, 'PhaseFolded.txt'), np.transpose([folded, f_t_folded]), header='Time, Flux') np.savetxt(os.path.join(outputfolder, 'OptimalDepth.txt'), [depth], header='Depth') np.savetxt(os.path.join(outputfolder, 'OptimalDuration.txt'), [duration], header='Fractional Duration') t_foldbin, f_t_foldbin, stdv_foldbin = rebin_dataset( folded, f_t_folded, 15) f_t_smooth = savitzky_golay(f_t_folded, 101, 1) # unravel again n_start = int(np.round(t[0] / period)) n_end = np.round(t[-1] / period) + 1 i = n_start t_unravel = [] f_t_unravel = [] while i < n_end: t_unravel.append(np.array(folded) + i * period + t_orig[0]) f_t_unravel.append(np.array(f_t_smooth)) #pl.plot(t_unravel[i],f_t_unravel[i],color='black',lw='1.5') i = i + 1 if abs(period - 0.24) < 0.01: freqlist, powers = maskout_freqs(freqlist, powers, freq=0.245) # spacecraft freqs Location = np.where(powers == max(powers)) period = freqlist[Location[0]][0] print("The best period is: ", period) return folded, f_t_folded, period, freqlist, powers
def get_period(t,f_t,get_mandelagolmodel=True,outputpath='',starname=''): # # here we use a BLS algorithm to create a periodogram and find the best periods. The BLS is implemented in Python by Ruth Angus and Dan Foreman-Macey # outputfolder = os.path.join(outputpath,str(starname)) fmin = 0.03 # minimum frequency. we can't find anything longer than 90 days obviously nf = 60000 # amount of frequencies to try df = 0.00001 # frequency step qmi = 0.0005 # min relative length of transit (in phase unit) qma = 0.1 # max relative length of transit (in phase unit) nb = 200 # number of bins in folded LC u = np.linspace(fmin,fmin + nf*df,nf) v = np.array(0) t = np.array(t) print t[0] f_t = np.array(f_t) t_orig = np.copy(t) f_t_orig = f_t results = bls.eebls(t,f_t,t,f_t,nf,fmin,df,nb,qmi,qma) freqlist = u powers = results[0] period = results[1] folded,f_t_folded = fold_data(t,f_t,period) np.savetxt(os.path.join(outputfolder, 'folded_P' + str(period) + 'star_' + str(starname) + '.txt'),np.transpose([folded,f_t_folded]),header='Time, Flux') t_foldbin,f_t_foldbin,stdv_foldbin = rebin_dataset(folded,f_t_folded,15) f_t_smooth = savitzky_golay(f_t_folded,29,1) pl.figure('my data folded bls') pl.plot(folded,f_t_folded+1.,'.',color='black',label='K2 photometry') pl.xlabel('Time [d]') pl.ylabel('Relative Flux') if get_mandelagolmodel: # this is not a core part of the module and uses a transit model by Mandel & Agol, implemented in Python by Ian Crossfield. #[T0,b,R_over_a,Rp_over_Rstar,flux_star,gamma1,gamma2] transit_params = np.array([4.11176,0.9,0.104,np.sqrt(0.0036),1.,0.2,0.2]) import model_transits times_full = np.linspace(0.,period,10000) model = model_transits.modeltransit(transit_params,model_transits.occultquad,period,times_full) pl.figure('Transit model') pl.scatter((folded-transit_params[0])*24.,f_t_folded+1.,color='black',label='K2 photometry',s=10.) pl.plot((times_full-transit_params[0])*24.,model,color='grey',lw=4,label='Transit model') pl.xlabel('Time from mid-transit [hr]',fontsize=17) pl.ylabel('Relative flux',fontsize=17) legend = pl.legend(loc='upper center',numpoints=1,scatterpoints=1,fontsize=15,prop={'size':15},title='EPIC 205071984') pl.tick_params(labelsize=17) pl.tick_params(axis='both', which='major', width=1.5) pl.tight_layout() pl.setp(legend.get_title(),fontsize=17) pl.savefig(os.path.join(outputfolder, 'folded_P_' + 'star_' + str(starname) +str(period) + '.png')) # unravel again n_start = int(np.round(t[0] / period)) n_end = np.round(t[-1] / period) + 1 i = n_start pl.figure() pl.plot(t_orig,f_t,'*') t_unravel = [] f_t_unravel = [] while i < n_end: t_unravel.append(np.array(folded) + i*period + t_orig[0]) f_t_unravel.append(np.array(f_t_smooth)) pl.plot(t_unravel[i],f_t_unravel[i],color='black',lw='1.5') i = i + 1 print 'best period is ' print period return folded,f_t_folded,period,freqlist,powers
def getBLS(lc, TIC, filename, t0=0, multirunthresh=5.): '''Runs BLS search for transits on lightcurve. Returns 3-column array (detns) with the position and height of any peaks, and the 2-column spectrum''' #Using custom timerange across full lightcurve/1.1 to 0.4d min_freq = 1.1 / (lc[-1, 0] - lc[0, 0]) max_freq = 1. / 0.4 freq_spacing = 1e-5 nfb = int(np.floor((max_freq - min_freq) / freq_spacing)) nb = 400 count = 0 while True: #remove transit for all but first run if count > 0: lccut = CutTransits(lccut, epoch, bper, phase1, phase2) else: lccut = lc.copy() powOut = bls.eebls(lccut[:, 0], lccut[:, 1], np.zeros(len(lccut[:, 0])), np.zeros(len(lccut[:, 0])), nfb, fmin=min_freq, df=freq_spacing, nb=nb, qmi=0.005, qma=0.15) PowArr = np.column_stack( (1 / (np.arange(min_freq, (min_freq + nfb * freq_spacing), freq_spacing))[0:nfb], powOut[0])) PowArr = PowArr[PowArr[:, 0].argsort(), :] #Rescaling both BLS and LS such that the median (of values <0.3*the max value ) is at 1 and the position of a peak gives the height above the median PowArr[:, 1] = PowArr[:, 1] / np.median( PowArr[:, 1][PowArr[:, 1] < np.percentile(PowArr[:, 1], 95)]) if count == 0: blsoutfile = filename[:-4] + '_' + str(TIC) + '_' + str( count ) + '_pgram.txt' #includes count in case we want to save the others later np.savetxt(blsoutfile, PowArr) detnsOut_lccut = getPeaks(PowArr) detnsOut_lccut = detnsOut_lccut[(-detnsOut_lccut[:, 1]).argsort(), :] detnsOut_lccut = np.hstack( (detnsOut_lccut, np.ones([len(detnsOut_lccut[:, 0]), 1]) + count)) detnmax = np.max(detnsOut_lccut[:, 2]) bper = powOut[1] bpow = powOut[2] depth = powOut[3] qtran = powOut[4] duration = bper * qtran in1 = powOut[5] in2 = powOut[6] phase1 = in1 / float(nb) phase2 = in2 / float(nb) epoch = lccut[0, 0] epoch_array = np.zeros([ len(detnsOut_lccut[:, 0]), 1 ]) #hard to easily extract epoch etc for more than just main peak epoch_array[0] = (epoch + phase1 * bper) + t0 #check if only one transit in middle of lc if epoch + (phase1 + 1) * bper > lccut[-1, 0]: detnmax = multirunthresh + 1 #force another run, unless we hit max via count detnsOut_lccut[0, 0] = -10. #set peak period to -10 if count == 0: detnsOut = np.hstack((detnsOut_lccut, epoch_array)) else: detnsOut = np.vstack( (detnsOut, np.hstack((detnsOut_lccut, epoch_array)))) count += 1 if detnmax < multirunthresh: break if count > 2: break return detnsOut
u = [0.0] * len(time) v = [0.0] * len(time) u = np.array(u) v = np.array(v) #time, flux, u, v, number of freq bins (nf), min freq to test (fmin), freq spacing (df), number of bins (nb), min transit dur (qmi), max transit dur (qma) nf = 1000.0 fmin = .035 df = 0.001 nbins = 300 qmi = 0.001 qma = 0.3 results = bls.eebls(time, mergedfluxDetrend, u, v, nf, fmin, df, nbins, qmi, qma) #RESULTS: #power, best_period, best_power, depth, q, in1, in2 #0 1 2 3 4 5 6 print('DEPTH: ' + str(results[3])) print('BLS period: ' + str(results[1])) ################################################################################### SR_array = results[0] max_SR = max(SR_array) avg_SR = np.mean(SR_array) sd_SR = np.std(SR_array)
def compute(self): time = self.target.light_curve.time flux = self.target.light_curve.flux ferr = self.target.light_curve.ferr u = np.ones(len(time)) v = np.ones(len(time)) nf = 50 fmin = 1 / (time[-1] - time[0]) * 1.01 df = 0.00541570 nb = 50 qmi = 0.01000 qma = 0.10000 self.f = fmin + np.arange(nf) * df f_1 = 1/self.f results = bls.eebls(time, flux, u, v, nf, fmin, df, nb, qmi, qma) self.power = results[0] self.best_period = results[1] self.best_power = results[2] self.depth = results[3] q = results[4] in1 = results[5] in2 = results[6] ## Mimic what the python-bls demo code does to get all the information we need to calculate system parameters # Compute duration self.duration = self.best_period * q phase1 = in1 / float(nb) phase2 = in2 / float(nb) # Find peaks convolved_bls = scipy.ndimage.filters.gaussian_filter(self.power, 2.0) peak = np.r_[True, convolved_bls[1:] > convolved_bls[:-1]] & np.r_[convolved_bls[:-1] > convolved_bls[1:], True] sel_peaks = np.sort(convolved_bls[peak]) sel_peaks = sel_peaks[-1:] self.all_periods = f_1[np.where(convolved_bls == sel_peaks)] # Calculate # of transits, epoch, ingress ,egress times t_number = int((np.max(time) - np.min(time)) / self.best_period) self.epoch = time[0] + phase1 * self.best_period ingresses = np.zeros(t_number) egresses = np.zeros(t_number) for n in xrange(0, t_number): # Compute w/ a margin on each side ingresses[n] = (self.epoch + self.best_period * n) - 0.2 egresses[n] = self.epoch + self.best_period*n + self.duration + 0.2 self.ingresses = ingresses self.egresses = egresses self.approx_duration = egresses[0] - ingresses[0] # Stuff only useful for sample calculation self.values = { 'in1': in1, 'phase1': phase1, 'nb': nb, 'q': q }
def get_BLS_2 (time, flux, starname, outputfolder, Pmin, Pmax, nP, qmin, qmax, nb): """ Find Box-fitting Least Squares (BLS) frequency spectrum. Input: time = array containing data points of the time series flux = array containing data points of the flux series Pmin = minimal oribtal period Pmax = maximal orbital period nP = number of oribtal periods to compute qmin = minimal fractional transit length (duration = q * period) qmax = maximal fractional transit length nb = number of bins in which the data should be binned Output: BLS = BLS frequency spectrum P = array containing periods best_params = parameters of interest correpsonding to the maximal value in the BLS and two candidate periods ([period, power, fractional transit length, transitdepth, transitcenter]) """ # calculate the weight for all datapoints flux = flux - np.median(flux) # make average signal zero P = np.linspace(Pmin,Pmax,nP) nf = nP fmin = 1./Pmax fmax = 1./Pmin df = np.diff(P)[0] u = np.linspace(fmin,fmin + nf*df,nf) v = np.linspace(fmin,fmin + nf*df,nf) # best period parameters results = bls.eebls(time, flux, time, flux, nf, fmin, df, nb, qmin, qmax) BLS, best_period, best_power, depth, q, in1, in2 = results P = 1./u time_f, flux_f = fold_data(time, flux, best_period) # Pbest time_f_b = bin_data(time_f, nb, median = False) flux_f_b = bin_data(flux_f, nb, median = False) center = time_f_b[np.argmin(flux_f_b)] params_Pbest = np.array([best_period, best_power, q, depth, center]) # get best three periods and other relevant parameters Pbest, P2, P3, best_power_Pbest, best_power_P2, best_power_P3 = find_candidate_periods_2(P, BLS) time_f, flux_f = fold_data(time, flux, P2) # P2 time_f_b = bin_data(time_f, nb, median = False) flux_f_b = bin_data(flux_f, nb, median = False) center = time_f_b[np.argmin(flux_f_b)] depth = np.min(flux_f_b) params_P2 = np.array([P2, best_power_P2, q, depth, center]) time_f, flux_f = fold_data(time, flux, P3) # P3 time_f_b = bin_data(time_f, nb, median = False) flux_f_b = bin_data(flux_f, nb, median = False) center = time_f_b[np.argmin(flux_f_b)] depth = np.min(flux_f_b) params_P3 = np.array([P3, best_power_P3, q, depth, center]) # combine all the parameters params = np.vstack((params_Pbest, params_P2, params_P3)) # save as txt file data = np.array(zip(P, BLS)) data_header = '#0 period, 1 SR' np.savetxt(os.path.join(outputfolder,'bls_' + str(starname) + '.txt'), data, header=data_header, fmt='%s') data = np.copy(params) data_header = '#0 best period 1 corresponding SR 2 q 3 transitdepth 4 index at start of transit 5 index at end of transit' np.savetxt(os.path.join(outputfolder,'blsparams_' + str(starname) + '.txt'), data, header=data_header, fmt='%s') # Calculate Signal Detection Efficiency value for best period SRbest = params[0,1] SDE = (SRbest - np.mean(BLS) )/np.std(BLS) return P, BLS, params, Pbest, SDE
def main(rad_min, rad_max, rad_step, per_min, per_max, per_step): detect_count = 0 detect_SDE = []*18905 detect_per = []*18905 detect_rad = []*18905 detect_BLS_per = []*18905 undetect_count = 0 undetect_SDE = []*18905 undetect_per = []*18905 undetect_rad = []*18905 detect_diff = []*18905 undetect_diff = []*18905 diff = [[0 for x in range(96)] for y in range(200)] #Limits and step size can be changed rad_range = numpy.arange(rad_min, rad_max, rad_step) per_range = numpy.arange(per_min, per_max, per_step) rindex = -1 pindex = -1 for r in rad_range: rindex += 1 pindex = 0 for p in per_range: pindex += 1 currentdir = makedir("/Users/sheilasagear/OneDrive/K2_Research/bls-ktransit/Pipeline/EPIC229227250-2sigclip", r, p) time, flux = importLC('/Users/sheilasagear/OneDrive/K2_Research/Corrected Light Curve by EPIC ID (.txt)/hlsp_k2sff_k2_lightcurve_229227254-c06_kepler_v1_llc-default-aper.txt') flux = sigma_clip(flux, sigma=2, iters=1) ktflux = createktransit(time, p, r) savektransitLC(currentdir, time, ktflux, p, r) merged_flux = injecttransit(ktflux, flux) savemergedLC(currentdir, "EPICX", time, merged_flux, p, r) ########################## #BLS routine ########################## u = [0.0]*len(time) v = [0.0]*len(time) u = numpy.array(u) v = numpy.array(v) nbins = 200 results = bls.eebls(time, merged_flux, u, v, 1000.0, .3, .001, nbins, .001, .3) #RESULTS: #power, best_period, best_power, depth, q, in1, in2 #0 1 2 3 4 5 6 print('Planet radius/star radius:' + str(r)) print('Period from BLS is: ' + str(results[1])) print('Set period is: ' + str(p)) max_SR, avg_SR, sd_SR = saveSRplot(currentdir, 'EPICX', results[0], p, r) SDE, detect_count, detect_SDE, detect_per, detect_rad, detect_BLS_per, detect_diff, undetect_count, undetect_SDE, undetect_per, undetect_rad, undetect_diff = SDEcount(max_SR, avg_SR, sd_SR, p, r, detect_count, detect_SDE, detect_per, detect_rad, detect_BLS_per, detect_diff, undetect_count, undetect_SDE, undetect_per, undetect_rad, undetect_diff, results[1]) savefoldbin(currentdir, SDE, time, nbins, results[1], results[3], results[4], results[5], results[6], u, v, p, r) ########################## #END LOOP ########################## savetext('/Users/sheilasagear/OneDrive/K2_Research/bls-ktransit/SDE_text/data213244700.txt', detect_diff, detect_SDE, detect_BLS_per, detect_per, detect_rad) #deletes extras from arrays for i in range(len(detect_SDE)): if detect_SDE[i] == 0: del detect_SDE[i] for i in range(len(detect_per)): if detect_per[i] == 0: del detect_per[i] for i in range(len(detect_rad)): if detect_rad[i] == 0: del detect_rad[i] for i in range(len(undetect_SDE)): if undetect_SDE[i] == 0: del undetect_SDE[i] for i in range(len(undetect_per)): if undetect_per[i] == 0: del undetect_per[i] for i in range(len(undetect_rad)): if undetect_rad[i] == 0: del undetect_rad[i] showinitialLC(time, flux) show2Dscatter(detect_per, detect_rad, rad_max, per_max) show3Dscatter(detect_per, detect_rad, detect_diff, detect_SDE)
def process_lightcurve(lc: LightcurveArbitraryRaster, lc_duration: float, search_settings: dict): """ Perform a transit search on a light curve, using the bls_kovacs code. :param lc: The lightcurve object containing the input lightcurve. :type lc: LightcurveArbitraryRaster :param lc_duration: The duration of the lightcurve, in units of days. :type lc_duration: float :param search_settings: Dictionary of settings which control how we search for transits. :type search_settings: dict :return: dict containing the results of the transit search. """ time = lc.times # Unit of days flux = lc.fluxes # Median subtract lightcurve median = np.median(flux) flux -= median # Run this light curve through original FORTRAN implementation of BLS u = np.zeros(len(time)) v = np.zeros(len(time)) # Minimum transit length qmi = 0.05 # Maximum transit length qma = 0.2 # Minimum transit period, days minimum_period = float(search_settings.get('period_min', 0.5)) fmax = 1 / minimum_period # Maximum transit period, seconds # Arithmetic here based on <https://docs.astropy.org/en/stable/api/astropy.timeseries.BoxLeastSquares.html#astropy.timeseries.BoxLeastSquares.autoperiod> minimum_n_transits = 2 maximum_period = float( search_settings.get('period_max', lc_duration / minimum_n_transits)) fmin = 1 / maximum_period # Frequency spacing frequency_factor = 2 df = frequency_factor * qmi / lc_duration**2 nf = (fmax - fmin) / df # Number of bins (maximum 2000) # For large number of bins, the FORTRAN code seems to segfault, which limits usefulness of this code # See issue described here <https://github.com/dfm/python-bls/issues/4> nb = 10 # results = {} results = bls.eebls(time, flux, u, v, nf, fmin, df, nb, qmi, qma) # Unpack results power, best_period, best_power, depth, q, in1, in2 = results results = {"period": best_period, "power": best_power, "depth": depth} # Extended results to save to disk results_extended = results # Return results return results, results_extended
u = [0.0] * len(time) v = [0.0] * len(time) u = np.array(u) v = np.array(v) #time, flux, u, v, number of freq bins (nf), min freq to test (fmin), freq spacing (df), number of bins (nb), min transit dur (qmi), max transit dur (qma) nf = 1000.0 fmin = .02 df = 0.001 nbins = 700 qmi = 0.001 qma = 0.3 results = bls.eebls(time, flux, u, v, nf, fmin, df, nbins, qmi, qma) #RESULTS: #power, best_period, best_power, depth, q, in1, in2 #0 1 2 3 4 5 6 print('BLS period: ' + str(results[1])) SR_array = results[0] max_SR = max(SR_array) avg_SR = np.mean(SR_array) sd_SR = np.std(SR_array) #normalize SR_array between 0 and 1 SR_array = [i / max_SR for i in SR_array]
#plt.show(merged_LC) ########################## #BLS routine ########################## u = [0.0]*len(time) v = [0.0]*len(time) u = np.array(u) v = np.array(v) nbins = 200 results = bls.eebls(time, merged_flux, u, v, 1000.0, .3, .001, nbins, .001, .3) #RESULTS: #power, best_period, best_power, depth, q, in1, in2 #0 1 2 3 4 5 6 print('Planet radius/star radius:' + str(r)) print('Period from BLS is: ' + str(results[1])) print('Set period is: ' + str(p)) ########################## #SR plot ########################## SR_array = results[0]
pylab.savefig("/Users/sheilasagear/OneDrive/K2_Research/bls-ktransit/LC_5/Period" + str(p) + "Radius" + str(r) + "/merged_fluxPer" + str(p) + "Rad" + str(r) + '.png') """ #plt.show(merged_LC) ########################## #BLS routine ########################## u = [0.0] * len(time) v = [0.0] * len(time) u = numpy.array(u) v = numpy.array(v) results = bls.eebls(time, merged_flux, u, v, 1000.0, .3, .001, 500.0, .01, .1) #print(results) #RESULTS: #power, best_period, best_power, depth, q, in1, in2 #0 1 2 3 4 5 6 print('Planet radius/star radius:' + str(r)) print('Period from BLS is: ' + str(results[1])) print('Set period is: ' + str(p)) ########################## #SR plot ##########################
########################## u = [0.0] * len(time) v = [0.0] * len(flux) u = np.array(u) v = np.array(v) nf = 1000.0 fmin = .035 df = 0.001 nb = 300 qmi = 0.001 qma = 0.3 results = bls.eebls(time, merged_flux, u, v, nf, fmin, df, nb, qmi, qma) #RESULTS: #power, best_period, best_power, depth, q, in1, in2 #0 1 2 3 4 5 6 print('BLS period: ' + str(results[1])) ########################## #Power Spectrum ########################## SR_array = results[0] max_SR = max(SR_array) avg_SR = np.mean(SR_array) sd_SR = np.std(SR_array)