def multi_search(self, to_plot=False): """Search a lightcurve for a secondary signal.""" # Start with the corrected lightcurve and its associated period # Phase on that period and remove it white_out = detrend.pre_whiten(self.time, self.corrected_flux, self.corrected_unc, self.corr_prot, which="phased") detrended_flux = self.corrected_flux / white_out[2] self.corr_trend = white_out[2] self.sec_flux = detrended_flux self.sec_unc = self.corrected_unc # Run lomb-scargle again and re-measure the period fit_out = self._run_fit([self.time, self.sec_flux, self.sec_unc]) self.sec_prot = fit_out[0] self.sec_power = fit_out[1] self.sec_periods = fit_out[2] self.sec_pgram = fit_out[3] self.sec_sigmas = fit_out[5] eval_out = evaluate.test_pgram(self.sec_periods, self.sec_pgram, self.power_threshold) plot_aliases = [None, eval_out[2]] white_out2 = detrend.pre_whiten(self.time, self.sec_flux, self.sec_unc, self.sec_prot, which="phased") self.sec_trend = white_out2[2] # Plot! if to_plot: # Plot them up lcs = [[self.time, self.corrected_flux, self.corrected_unc], [self.time, self.sec_flux, self.sec_unc]] pgrams = [[self.corr_periods, self.corr_pgram], [self.sec_periods, self.sec_pgram]] best_periods = [self.corr_prot, self.sec_prot] data_labels = ["Corrected", "Fund. Prot=" "{0:.2f}d Removed".format(self.corr_prot)] sigmas = [self.corr_sigmas, self.sec_sigmas] rd_fig, rd_axes = plot.compare_multiple(lcs, pgrams, best_periods, sigmas, aliases=plot_aliases, data_labels=data_labels, phase_by=self.sec_prot) rd_fig.suptitle(self.name, fontsize="large", y=0.99) rd_fig.delaxes(rd_axes[3]) rd_axes[0].plot(self.time, white_out[2], 'b-', lw=2) plt.savefig("{0}plot_outputs/{1}_second_period.png".format( base_path,self.name))
def choose_initial(self, to_plot=False): """Search raw and detrended LCs for periods, and decide whether there's a period there. """ # Run a fit on the raw lc r_out = self._run_fit("raw") raw_fp, raw_power, raw_prots, raw_pgram, raw_alias, raw_sigma = r_out logging.debug("Ran raw fit") # Run a fit on the detrended lc d_out = self._run_fit("detrended") det_fp, det_power, det_prots, det_pgram, det_alias, det_sigma = d_out logging.debug("Ran detrended fit") # Only consider peaks less than ~half the length of the lightcurve # max_peak_loc = 0.75 * (self.time[-1] - self.time[0]) max_peak_loc = 40 logging.info("Max Prot = %f", max_peak_loc) raw_loc2 = np.argmax(raw_pgram[raw_prots<max_peak_loc]) raw_power2 = raw_pgram[raw_prots<max_peak_loc][raw_loc2] raw_prot2 = raw_prots[raw_prots<max_peak_loc][raw_loc2] logging.info("raw %d FP %f Power %f", raw_loc2, raw_prot2, raw_power2) det_loc2 = np.argmax(det_pgram[det_prots<max_peak_loc]) det_power2 = det_pgram[det_prots<max_peak_loc][det_loc2] det_prot2 = det_prots[det_prots<max_peak_loc][det_loc2] logging.info("det %d FP %f Power %f", det_loc2, det_prot2, det_power2) # Compare them lc_to_use = self._pick_lc(raw_power2, det_power2) if lc_to_use<=1: logging.info("Using raw lightcurve") self.init_prot , self.init_power = raw_prot2, raw_power2 self.init_periods_to_test, self.init_pgram = raw_prots, raw_pgram self.use_flux = self.flux / self.med self.use_unc = self.unc_flux / self.med self.init_sigmas = raw_sigma self.use = "raw" data_labels = ["Raw (Selected)", "Detrended"] elif lc_to_use==2: logging.info("Using detrended lightcurve") self.init_prot , self.init_power = det_prot2, det_power2 self.init_periods_to_test, self.init_pgram = det_prots, det_pgram self.use_flux = self.det_flux self.use_unc = self.unc_flux self.init_sigmas = det_sigma self.use = "det" data_labels = ["Raw", "Detrended (Selected)"] logging.info("Initial Prot %f Power %f", self.init_prot, self.init_power) # get power at harmonics self.init_harmonics = self._harmonics(self.init_prot, self.init_periods_to_test, self.init_pgram) # Get aliases for selected period eval_out = evaluate.test_pgram(self.init_periods_to_test, self.init_pgram, self.power_threshold) # Get phase-folded, smoothed trend white_out2 = detrend.pre_whiten(self.time, self.use_flux, self.use_unc, self.init_prot, which="phased") self.init_trend = white_out2[2] if eval_out[-1]==False: logging.warning("Selected lightcurve is not clean") else: logging.debug("Selected lightcurve is clean") plot_aliases = [None, eval_out[2]] if to_plot: # Plot them up lcs = [[self.time, self.flux/self.med, abs(self.unc_flux/self.med)], [self.time, self.det_flux, self.det_unc]] pgrams = [[raw_prots, raw_pgram], [det_prots, det_pgram]] best_periods = [raw_prot2, det_prot2] sigmas = [raw_sigma, det_sigma] logging.debug(sigmas) rd_fig, rd_axes = plot.compare_multiple(lcs, pgrams, best_periods, sigmas, aliases=plot_aliases, data_labels=data_labels, phase_by=self.init_prot) rd_fig.suptitle(self.name, fontsize="large", y=0.99) rd_fig.delaxes(rd_axes[3]) plt.savefig("{0}plot_outputs/{1}_raw_detrend.png".format(base_path, self.name)) plt.close("all")
def run_ls(time, flux, unc_flux, threshold, prot_lims=None, run_bootstrap=False): """Run a periodogram and return it. Inputs ------ time, flux, unc_flux: array_like prot_lims: list-like, length=2 minimum and maximum rotation periods to search num_prot: integer How many rotation periods to search Outputs ------- fund_period, fund_power, periods_to_test, periodogram, aliases sigmas only if run_bootstrap=True """ logging.debug("run ls t %d f %d u %d", len(time), len(flux), len(unc_flux)) # Define range of period space to search # Using real frequencies not angular frequencies freq_term = 1.0 # 2.0 * np.pi set_f0 = freq_term / prot_lims[1] set_fmax = freq_term / prot_lims[0] n_freqs = 3e4 set_df = (set_fmax - set_f0) / n_freqs freqs_to_test = set_f0 + set_df * np.arange(n_freqs) # Search for a period model = lomb_scargle_fast.LombScargleFast().fit(time, flux, unc_flux) periodogram = model.score_frequency_grid(f0=set_f0, df=set_df, N=n_freqs) logging.debug("pgram count %d", len(periodogram)) periods_to_test = freq_term / freqs_to_test ls_out = evaluate.test_pgram(periods_to_test, periodogram, threshold) fund_period, fund_power, aliases, is_clean = ls_out # Now bootstrap to find the typical height of the highest peak # (Use the same time points, but redraw the corresponding flux points # at random, allowing replacement) if run_bootstrap: N_bootstraps = 500 n_points = len(flux) ind = np.random.randint(0, n_points, (N_bootstraps, n_points)) bs_periods, bs_powers = np.zeros(N_bootstraps), np.zeros(N_bootstraps) for i, f_index in enumerate(ind): bs_model = lomb_scargle_fast.LombScargleFast().fit( time, flux[f_index], unc_flux[f_index]) bs_pgram = bs_model.score_frequency_grid(f0=set_f0, df=set_df, N=n_freqs) max_loc = np.argmax(bs_pgram) bs_periods[i] = periods_to_test[max_loc] bs_powers[i] = bs_pgram[max_loc] # logging.debug("Periods and Powers") # logging.debug(bs_periods) # logging.debug(bs_powers) sigmas = np.percentile(bs_powers, [99.9, 99, 95]) logging.debug("Fund power: %f 99p %f 95p %f", fund_power, sigmas[1], sigmas[2]) else: sigmas = None return (fund_period, fund_power, periods_to_test, periodogram, aliases, sigmas)
def correct_and_fit(self, to_plot=False, n_closest=21): """Position-correct and perform a fit.""" logging.debug("Fitting corrected lightcurve") cl_flux, cl_unc = self._clean_it(self.use) self._xy_correct(correct_with=cl_flux, n_closest=n_closest) fit_out = self._run_fit([self.time, self.corrected_flux, self.corrected_unc]) fund_prot, fund_power, periods_to_test, periodogram = fit_out[:4] aliases, sigmas = fit_out[4:] eval_out = evaluate.test_pgram(periods_to_test, periodogram, self.power_threshold) self.corr_prot = fund_prot self.corr_power = fund_power self.corr_sigmas = sigmas self.corr_periods = periods_to_test self.corr_pgram = periodogram self.corr_harmonics = self._harmonics(self.corr_prot, self.corr_periods, self.corr_pgram) if eval_out[-1]==False: logging.warning("Corrected lightcurve is not clean") else: logging.debug("Corrected lightcurve is clean") plot_aliases = [None, eval_out[2]] if to_plot: # Plot them up lcs = [[self.time, self.use_flux, self.use_unc], [self.time, self.corrected_flux, self.corrected_unc]] pgrams = [[self.init_periods_to_test, self.init_pgram], [periods_to_test, periodogram]] best_periods = [self.init_prot, fund_prot] data_labels = ["Initial", "Corrected"] sigmas = [self.init_sigmas, sigmas] rd_fig, rd_axes = plot.compare_multiple(lcs, pgrams, best_periods, sigmas, aliases=plot_aliases, data_labels=data_labels, phase_by=fund_prot) rd_fig.suptitle(self.name, fontsize="large", y=0.99) ptime, fsine = evaluate.fit_sine(self.time, self.corrected_flux, self.corrected_unc, self.corr_prot) plotx = np.argsort(ptime) rd_axes[2].plot(ptime[plotx], fsine[plotx], color="lightgrey", lw=2) # rd_axes[2].set_ylim(min(fsine)*0.9, max(fsine)*1.1) use_residuals = self.use_flux - fsine cor_residuals = self.corrected_flux - fsine logging.debug("RESIDUALS") logging.debug(use_residuals[:10]) logging.debug(cor_residuals[:10]) rd_axes[3].errorbar(self.time % fund_prot, use_residuals, np.zeros_like(self.time), #self.use_unc, fmt=plot.shape1, ms=2, capsize=0, ecolor=plot.color1, color=plot.color1, mec=plot.color1) rd_axes[3].errorbar(self.time % fund_prot, cor_residuals, np.zeros_like(self.time), #self.corrected_unc, fmt=plot.shape2, ms=2, capsize=0, ecolor=plot.color2, color=plot.color2, mec=plot.color2) rd_axes[3].set_xlim(0, fund_prot) plt.savefig("{0}plot_outputs/{1}_corrected.png".format(base_path, self.name)) # plt.show() plt.close("all")
def run_ls(time, flux, unc_flux, threshold, prot_lims=None, run_bootstrap=False): """Run a periodogram and return it. Inputs ------ time, flux, unc_flux: array_like prot_lims: list-like, length=2 minimum and maximum rotation periods to search num_prot: integer How many rotation periods to search Outputs ------- fund_period, fund_power, periods_to_test, periodogram, aliases sigmas only if run_bootstrap=True """ logging.debug("run ls t %d f %d u %d", len(time), len(flux), len(unc_flux)) # Define range of period space to search # Using real frequencies not angular frequencies freq_term = 1.0 # 2.0 * np.pi set_f0 = freq_term / prot_lims[1] set_fmax = freq_term / prot_lims[0] n_freqs = 3e4 set_df = (set_fmax - set_f0) / n_freqs freqs_to_test = set_f0 + set_df * np.arange(n_freqs) # Search for a period model = lomb_scargle_fast.LombScargleFast().fit(time, flux, unc_flux) periodogram = model.score_frequency_grid(f0=set_f0, df=set_df, N=n_freqs) logging.debug("pgram count %d", len(periodogram)) periods_to_test = freq_term / freqs_to_test ls_out = evaluate.test_pgram(periods_to_test, periodogram, threshold) fund_period, fund_power, aliases, is_clean = ls_out # Now bootstrap to find the typical height of the highest peak # (Use the same time points, but redraw the corresponding flux points # at random, allowing replacement) if run_bootstrap: N_bootstraps = 500 n_points = len(flux) ind = np.random.randint(0, n_points, (N_bootstraps, n_points)) bs_periods, bs_powers = np.zeros(N_bootstraps), np.zeros(N_bootstraps) for i, f_index in enumerate(ind): bs_model = lomb_scargle_fast.LombScargleFast().fit(time, flux[f_index], unc_flux[f_index]) bs_pgram = bs_model.score_frequency_grid(f0=set_f0, df=set_df, N=n_freqs) max_loc = np.argmax(bs_pgram) bs_periods[i] = periods_to_test[max_loc] bs_powers[i] = bs_pgram[max_loc] # logging.debug("Periods and Powers") # logging.debug(bs_periods) # logging.debug(bs_powers) sigmas = np.percentile(bs_powers, [99.9, 99, 95]) logging.debug("Fund power: %f 99p %f 95p %f", fund_power, sigmas[1], sigmas[2]) else: sigmas=None return (fund_period, fund_power, periods_to_test, periodogram, aliases, sigmas)