def make_plot(days_ago, dates, mag): print('Making plot...') time_span = np.max(dates) - np.min(dates) flatten_lc, trend_lc = flatten( days_ago, mag, method='lowess', window_length=time_span/3, return_trend=True, ) plt.scatter(days_ago, mag, s=5, color='blue', alpha=0.5) plt.scatter(days_ago1, all_mags1, s=10, color='black', alpha=0.8, marker="x") plt.xlabel('Days before today') plt.ylabel('Visual magnitude') #mid = biweight_location(mag) mid = 1.10 plt.ylim(mid-1, mid+1) plt.xlim(-1, 20) plt.plot(days_ago, trend_lc, color='red', linewidth=1) plt.gca().invert_yaxis() plt.gca().invert_xaxis() date_text = datetime.datetime.now().strftime("%d %b %Y") data_last24hrs = np.where(days_ago<1) mean_last24hrs = biweight_location(mag[data_last24hrs]) lumi = str(format(mean_last24hrs, '.2f')) plt.text(19.5, mid+1-0.25, "AAVSO observations visual (by-eye) in blue", color='blue') plt.text(19.5, mid+1-0.15, "AAVSO observations from CCDs in black", color='black') plt.text(19.5, mid+1-0.05, "LOESS trend in red", color='red') plt.text(19.5, mid-1+0.1, '#Betelgeuse brightness ' + lumi + " mag on " + date_text + " by @betelbot") plt.savefig(plot_file, bbox_inches='tight', dpi=300) print('Done.')
def flatten_gp(self, flatten_input): flatten_lc, trend = wotan.flatten(flatten_input.time, flatten_input.flux, method="gp", kernel='matern', kernel_size=flatten_input.wl, return_trend=True, break_tolerance=0.5) flatten_lc = sigma_clip(flatten_lc, sigma_lower=20, sigma_upper=3) bin_centers_i, bin_means_i, bin_width_i, bin_edges_i, bin_stds_i = \ self.__compute_flatten_stats(flatten_input.time, flatten_lc, flatten_input.bin_minutes) return flatten_lc, trend, bin_centers_i, bin_means_i, flatten_input.wl
def flatten_bw(self, flatten_input): flatten_lc, trend = wotan.flatten(flatten_input.time, flatten_input.flux, window_length=flatten_input.wl, return_trend=True, method="biweight", break_tolerance=0.5) flatten_lc = sigma_clip(flatten_lc, sigma_lower=20, sigma_upper=3) bin_centers_i, bin_means_i, bin_width_i, bin_edges_i, bin_stds_i = \ self.__compute_flatten_stats(flatten_input.time, flatten_lc, flatten_input.bin_minutes) return flatten_lc, trend, bin_centers_i, bin_means_i, flatten_input.wl
def SNR(alltimes, lc, dip, x0): ''' Calculates SNR for event Takes in: alltimes: array - Time series lc: array - light curve dip: float - depth of transit x0: tuple - best fit parameters Returns: SNR: float - Signal to noise ratio ''' (tmid, dur) = x0[:2] lc = np.array(lc) if np.all(np.isnan(lc)): return np.nan #To find SNR - take detrended curve to find overall stddev - wotan preserves SNR (I think ...) lc_flat = flatten(alltimes, lc, window_length = 0.5, method = 'biweight', return_trend = False) masked_lc = lc_flat masked_lc[int(tmid - dur*0.5):int(tmid+dur*0.5)]=np.nan sigma_oot = np.nanstd(masked_lc) return dip/sigma_oot
def __detrend_by_period(self, method, time, flux, period_window): if method == 'gp': flatten_lc, lc_trend = flatten(time, flux, method=method, kernel='matern', kernel_size=period_window, return_trend=True, break_tolerance=0.5) else: flatten_lc, lc_trend = flatten(time, flux, window_length=period_window, return_trend=True, method=method, break_tolerance=0.5) return flatten_lc, lc_trend
def get_numax(self): # use 2d ACF to get a rough estimation on numax freqRanges = np.logspace( min(np.log10(15.), np.log10(np.min(self.freq))), np.log10(np.max(self.freq)), 250) # freqRanges = np.linspace(15., np.max(freq), 200.) freqCenters = (freqRanges[1:] + freqRanges[:-1]) / 2. spacings = np.diff(freqRanges) widths = 0.263 * freqCenters**0.772 * 4. # # crude background estimation cacf = np.zeros(len(spacings)) acf2d = np.zeros([140, len(spacings)]) for isp, width in enumerate(widths): idx = (self.freq >= freqRanges[isp]) & (self.freq <= freqRanges[isp] + width) if np.sum(idx) > 100: # powerbg = percentile_filter(self.power[idx], 15, size=int(width/np.median(np.diff(self.freq[idx])))) # powerbg = np.percentile(self.power[idx], 20) lag, rho = a_correlate( self.freq[idx], self.power[idx]) # return the acf at this freqRange acf = np.interp( np.arange(30, 170) / 200 * np.max(lag), lag, rho) # switch to the scale of width acf2d[:, isp] = np.abs(detrend(acf)) # store the 2D acf cacf[isp] = np.sum(np.abs( detrend(acf))) # store the max acf power (collapsed acf) else: acf2d[:, isp] = 0. cacf[isp] = np.nan # detrend the data to find the peak idx = np.isfinite(cacf) cacfDetrend = np.zeros(len(cacf)) cacfDetrend[idx] = flatten(np.arange(np.sum(idx)), cacf[idx], method='biweight', window_length=50, edge_cutoff=10) # The highest value of the cacf (smoothed) corresponds to numax cacf_numax = freqCenters[np.nanargmax(cacfDetrend)] # create and return the object containing the result self.numax_diagnostics = { 'cacf': cacf, 'acf2d': acf2d, 'freqCenters': freqCenters, 'spacings': spacings, 'widths': widths, 'freqRanges': freqRanges, 'cacfDetrend': cacfDetrend, 'cacf_numax': cacf_numax } return self.numax_diagnostics
def get_flat_lc( self, lc=None, period=None, epoch=None, duration=None, window_length=None, method="biweight", sigma_upper=None, sigma_lower=None, return_trend=False, ): """ """ lc = self.lc if lc is None else lc period = self.period if period is None else period epoch = self.epoch if epoch is None else epoch duration = self.duration if duration is None else duration duration_hours = duration * 24 if duration_hours < 1: raise ValueError("Duration should be in hours.") if window_length is None: window_length = 0.5 if duration is None else duration * 3 if self.verbose: print( f"Using {method} filter with window_length={window_length:.2f} day" ) if (period is not None) & (epoch is not None) & (duration is not None): tmask = get_transit_mask(lc.time, period=period, t0=epoch, dur=duration_hours / 24) else: tmask = np.zeros_like(lc.time, dtype=bool) # dummy holder flat, trend = lc.flatten(return_trend=True) # flatten using wotan wflat, wtrend = flatten( lc.time, lc.flux, method=method, window_length=window_length, mask=tmask, return_trend=True, ) # overwrite flat.flux = wflat trend.flux = wtrend # clean lc sigma_upper = 5 if sigma_upper is None else sigma_upper sigma_lower = 10 if sigma_lower is None else sigma_lower flat = ( flat.remove_nans() ) # .remove_outliers(sigma_upper=sigma_upper, sigma_lower=sigma_lower) if return_trend: return flat, trend else: return flat
def __detrend_by_period(self, lc, period_window, detrend_method): if detrend_method == 'gp': flatten_lc, lc_trend = flatten(lc.time.value, lc.flux.value, method=detrend_method, kernel='matern', kernel_size=period_window, return_trend=True, break_tolerance=0.5) else: flatten_lc, lc_trend = flatten(lc.time.value, lc.flux.value, window_length=period_window, return_trend=True, method=detrend_method, break_tolerance=0.5) flatten_lc = sigma_clip(flatten_lc, sigma_lower=20, sigma_upper=3) return flatten_lc, lc_trend
def __tls_search(self, time, flux, rstar, rstar_min, rstar_max, mass, mstar_min, mstar_max, ab, intransit, epoch, period, min_period, max_period, min_snr, cores, transit_template, ws, transits_min_count, run_limit): snr = 1e12 found_signal = False time = time[~intransit] flux = flux[~intransit] time, flux = cleaned_array(time, flux) run = 0 if ws > 0: flux = wotan.flatten(time, flux, window_length=ws, return_trend=False, method='biweight', break_tolerance=0.5) while snr >= min_snr and not found_signal and (run_limit > 0 and run < run_limit): model = transitleastsquares(time, flux) # R_starx = rstar / u.R_sun results = model.power( u=ab, R_star=rstar, # rstar/u.R_sun, R_star_min=rstar_min, # rstar_min/u.R_sun, R_star_max=rstar_max, # rstar_max/u.R_sun, M_star=mass, # mstar/u.M_sun, M_star_min=mstar_min, # mstar_min/u.M_sun, M_star_max=mstar_max, # mstar_max/u.M_sun, period_min=min_period, period_max=max_period, n_transits_min=transits_min_count, show_progress_bar=True, use_threads=cores, transit_template=transit_template) snr = results.snr if results.snr >= min_snr: intransit_result = transit_mask(time, results.period, 2 * results.duration, results.T0) time = time[~intransit_result] flux = flux[~intransit_result] time, flux = cleaned_array(time, flux) right_period = self.__is_multiple_of(results.period, period / 2.) right_epoch = False for tt in results.transit_times: for i in range(-5, 5): right_epoch = right_epoch or ( np.abs(tt - epoch + i * period) < (1. / 24.)) # right_depth = (np.abs(np.sqrt(1.-results.depth)*rstar - rplanet)/rplanet < 0.05) #check if the depth matches if right_period and right_epoch: found_signal = True break run = run + 1 return found_signal, results.snr, results.SDE, run
def __tls_search(self, time, flux, rstar, rstar_min, rstar_max, mass, mstar_min, mstar_max, ab, intransit, epoch, period, min_period, max_period, min_snr, cores, transit_template): SNR = 1e12 FOUND_SIGNAL = False time = time[~intransit] flux = flux[~intransit] time, flux = cleaned_array(time, flux) run = 0 flux = wotan.flatten(time, flux, window_length=0.5, return_trend=False, method='biweight', break_tolerance=0.5) #::: search for the rest while (SNR >= min_snr) and (not FOUND_SIGNAL): model = transitleastsquares(time, flux) # R_starx = rstar / u.R_sun results = model.power( u=ab, R_star=rstar, # rstar/u.R_sun, R_star_min=rstar_min, # rstar_min/u.R_sun, R_star_max=rstar_max, # rstar_max/u.R_sun, M_star=mass, # mstar/u.M_sun, M_star_min=mstar_min, # mstar_min/u.M_sun, M_star_max=mstar_max, # mstar_max/u.M_sun, period_min=min_period, period_max=max_period, n_transits_min=2, show_progress_bar=False, use_threads=cores, transit_template=transit_template) SNR = results.snr if results.snr >= min_snr: intransit_result = transit_mask(time, results.period, 2 * results.duration, results.T0) time = time[~intransit_result] flux = flux[~intransit_result] time, flux = cleaned_array(time, flux) right_period = self.__is_multiple_of(results.period, period / 2.) right_epoch = False for tt in results.transit_times: for i in range(-5, 5): right_epoch = right_epoch or ( np.abs(tt - epoch + i * period) < (1. / 24.) ) # check if any epochs matches to within 1 hour # right_depth = (np.abs(np.sqrt(1.-results.depth)*rstar - rplanet)/rplanet < 0.05) #check if the depth matches if right_period and right_epoch: FOUND_SIGNAL = True break run = run + 1 return FOUND_SIGNAL, results.snr, results.SDE, run
def _get_flat_lc( self, lc, period=None, epoch=None, duration=None, window_length=None, method="biweight", return_trend=False, **wotan_kwargs, ): """ TODO: migrate self in class method; See plot_hrd in cluster.py """ period = self.toi_period if period is None else period epoch = self.toi_epoch - TESS_TIME_OFFSET if epoch is None else epoch duration = self.toi_duration if duration is None else duration if duration is not None: if duration < 1: print("Duration should be in hours.") if window_length is None: window_length = 0.5 if duration is None else duration / 24 * 3 if self.verbose: print( f"Using {method} filter with window_length={window_length:.2f} day." ) if (period is not None) & (epoch is not None) & (duration is not None): tmask = get_transit_mask(lc.time, period=period, t0=epoch, dur=duration / 24) else: tmask = np.zeros_like(lc.time, dtype=bool) # dummy holder flat, trend = lc.flatten(return_trend=True) # flatten using wotan # import pdb; pdb.set_trace() wflat, wtrend = flatten( lc.time, lc.flux, method=method, mask=tmask, window_length=window_length, return_trend=True, **wotan_kwargs, ) # overwrite flat.flux = wflat trend.flux = wtrend if return_trend: return flat, trend else: return flat
def eigvec_smooth_fn(time, eigenvec): _, smoothed = flatten(time - np.nanmin(time), 1 + eigenvec, break_tolerance=0.5, method='biweight', window_length=1, cval=6, edge_cutoff=0, return_trend=True) return smoothed
def make_plot(days_ago, dates, mag): print('Making plot...') time_span = np.max(dates) - np.min(dates) flatten_lc, trend_lc = flatten( days_ago, mag, method='lowess', window_length=time_span / 5, return_trend=True, ) #mpl.rcParams['font.sans-serif']=['Times New Roman'] #指定默认字体 SimHei为黑体 mpl.rcParams['font.sans-serif'] = ['SimHei'] mpl.rcParams['axes.unicode_minus'] = False #用来正常显示负号 #fontcn = {'family': 'Droid Sans Fallback'} # 1pt = 4/3px fontcn = {'family': 'SimHei'} # 1pt = 4/3px fonten = {'family': 'Times New Roman'} plt.scatter(days_ago, mag, s=5, color='blue', alpha=0.5) plt.scatter(days_ago1, all_mags1, s=10, color='black', alpha=0.8, marker="x") plt.xlabel(u'从今天往回数的天数', fontdict=fontcn) #plt.xlabel('从今天往回数的天数') plt.ylabel(u'视星等', fontdict=fontcn) mid = 0.6 plt.ylim(mid - 1, mid + 1) plt.xlim(-1, 20) plt.plot(days_ago, trend_lc, color='red', linewidth=1) plt.gca().invert_yaxis() plt.gca().invert_xaxis() date_text = datetime.datetime.now().strftime("%Y-%m-%d") data_last24hrs = np.where(days_ago < 1) mean_last24hrs = biweight_location(mag[data_last24hrs]) lumi = str(format(mean_last24hrs, '.2f')) plt.text(19.5, mid + 1 - 0.25, u"裸眼 ", color='blue', fontdict=fontcn) plt.text(18, mid + 1 - 0.25, u"观测星等 蓝色", color='blue', fontdict=fontcn) plt.text(14, mid + 1 - 0.25, u"○", color='blue', fontdict=fonten) plt.text(19.5, mid + 1 - 0.15, u"CCD ", color='black', fontdict=fonten) plt.text(18, mid + 1 - 0.15, u"观测星等 黑色", color='black', fontdict=fontcn) plt.text(14, mid + 1 - 0.15, u"×", color='black', fontdict=fonten) plt.text(19.5, mid + 1 - 0.05, u"局部加权拟合 红色线", color='red', fontdict=fontcn) plt.text(7.5, mid - 1 + 0.1, u'目前参宿四的星等为 ', fontdict=fontcn) plt.text(2, mid - 1 + 0.1, lumi, fontdict=fonten) plt.text(7.5, mid - 1 + 0.2, u"由 天文通 译制于", fontdict=fontcn) plt.text(3, mid - 1 + 0.2, date_text, fontdict=fonten) plt.savefig(plot_file, bbox_inches='tight', dpi=300) print('Done.')
def __clean(self, lc, detrend_period, detrend_period_method, custom_clean_algorithm): clean_flux = lc.flux.value time = lc.time.value if custom_clean_algorithm is not None: clean_flux = custom_clean_algorithm.clean(time, clean_flux) elif detrend_period: periodogram = lc.to_periodogram(minimum_period=0.05, maximum_period=15, oversample_factor=10) ws = self.__calculate_max_significant_period(lc, periodogram) clean_flux = wotan.flatten(time, clean_flux, window_length=ws, return_trend=False, method=detrend_period_method, break_tolerance=0.5) return clean_flux
def detrend_tessphot(x_obs, y_obs, y_err): from wotan import flatten flat_flux, trend_flux = flatten(x_obs, y_obs, method='hspline', window_length=0.3, break_tolerance=0.4, return_trend=True) # flat_flux, trend_flux = flatten(time, flux, method='pspline', # break_tolerance=0.4, return_trend=True) # flat_flux, trend_flux = flatten(time, flux, method='biweight', # window_length=0.3, edge_cutoff=0.5, # break_tolerance=0.4, return_trend=True, # cval=2.0) return flat_flux, trend_flux
def wotan_detrend(time, flux, window_length=0.1, method='biweight', edge_cutoff=0.5, break_tolerance=0.5, cval=5.0): """ Detrends the light curve using methods in wotan.flatten(). Parameters ---------- time : np.ndarray flux : np.ndarray window_length : str, optional The window length used for the robust estimator. Default = 0.1. For the biweight filter, window_length is given in unit days. For the savgol filter, window_length is given in unit cadences. method : str, optional. The type of detrending to use on the light curve. Default is 'biweight'. edge_cutoff: float, optional Trims data near the edges of the light curve. Default = 0.5. Only available for the biweight detrending method. break_tolerance : float, optional Breaks the light curve into segments to help alleviate gap issues. Default = 0.5. cval : float, optional Tuning parameter for robust M-estimators. Defined as multiples in units of median absolute deviation from central location. Default = 5.0. Only available for the biweight detrending method. Returns ---------- detrend : detranded flux """ detrend = wotan.flatten(time, flux, window_length=window_length, method=method, edge_cutoff=edge_cutoff, break_tolerance=break_tolerance, cval=cval) return detrend
def fast_slide_clip(time, flux, window_length=1, low=5, high=5): """ A much faster alternative to Wotan's build-in slide clip Returns ------- Clipped flux (outliers replaced with NaN) """ flux2 = 1. * flux flux_flat = flatten(time, flux, method='biweight', window_length=window_length) flux_flat = sigma_clip(np.ma.masked_invalid(flux_flat), sigma_lower=low, sigma_upper=high) #astropy wants masked arrays flux2[ flux_flat. mask] = np.nan #use NaN instead of masked arrays, because masked arrays drive me crazy return flux2
def test_wotan_fake_data(t0): # t0: time system offset delta_t = 0.5/24 # TESS FFI cadence time = t0+np.arange(0, 28.5, delta_t) rotation_period = 2 rotation_semiamplitude = 10 # units: part per thousdand. 10 <-> 1% flux = 1 + (( 30*np.sin(2*np.pi*(time-t0)/rotation_period) + (time-t0) / 10 + (time-t0)**1.5 / 100) / 1000 ) noise = np.random.normal(0, 0.0001, len(time)) flux += noise for i in range(len(time)): if i % 75 == 0: flux[i:i+5] -= 5e-3 # Add some transits flux[i+50:i+52] += 5e-3 # and flares flux[300:400] = np.nan # and a gap flatten_lc, trend_lc = flatten( time, # Array of time values flux, # Array of flux values method='biweight', window_length=0.5, # The length of the filter window in units of ``time`` edge_cutoff=0.5, # length (in units of time) to be cut off each edge. break_tolerance=0.5, # Split into segments at breaks longer than that return_trend=True, # Return trend and flattened light curve cval=6 # Tuning parameter for the robust estimators ) f,ax = plt.subplots(nrows=2, ncols=1, figsize=(16,8)) ax[0].scatter(time, flux, color='black', s=3, zorder=5) ax[0].plot(time, trend_lc, color='red', lw=1, zorder=3) ax[1].scatter(time, flatten_lc, s=1, color='black') f.savefig('test_wotan_plots/test_wotan_fake_data_t0_{}.png'.format(t0), bbox_inches='tight')
def slide_clip(time, y, window_length=1, low=4, high=4, return_mask=False): """ Slide clip outliers from a non-stationary time series; a much faster alternative to Wotan's built-in slide clip. Parameters ---------- time : array of flaot Time stamps. y : array of float Any data corresponding to the time stamps.\ window_length : float, optional The length of the sliding window (in time's units). The default is 1. low : float, optional The lower sigma. The default is 5. high : float, optional The upper sigma. The default is 5. return_mask : bool, optional Return the masks or only the clipped time series. The default is False. Returns ------- Clipped y (outliers replaced with NaN). """ y_flat = flatten(time, y, method='biweight', window_length=window_length) y2, mask, mask_upper, mask_lower = sigma_clip(time, y_flat, low=low, high=high, return_mask=True) y3 = 1 * y y3[mask] = np.nan if not return_mask: return y3 else: return y3, mask, mask_upper, mask_lower
def analyse(det_met, time_i, flatten_i, n_tra, ab, mass, mass_min, mass_max, radius, radius_min, radius_max, id_run): # --------------------------------------------------------------------------------------------------------------------------------------------------------- # Detrending of the data using WOTAN # --------------------------------------------------------------------------------------------------------------------------------------------------------- # By default is used a 'biweight' method. # It will detrend the lightcurve 'N_detrends' independent times from wotan import flatten if det_met == 2: wl_min = 1 wl_max = 12 else: tdur = t14( R_s=radius, M_s=mass, P=P_protec, small_planet=True ) # we define the typical duration of a small planet in this star wl_min = 3 * tdur # minimum transit duration wl_max = 20 * tdur # maximum transit duration wl_step = (wl_max - wl_min) / N_detrends wl = np.arange( wl_min, wl_max, wl_step) # we define all the posibles window_length that we apply global_flatten_lc = np.zeros((len(wl), len(flatten_i))) global_trend_lc = np.zeros((len(wl), len(flatten_i))) for i in range(0, len(wl)): if det_met == 2: flatten_lc, trend_lc = flatten(time_i, flatten_i, method='gp', kernel='matern', kernel_size=wl[i], return_trend=True, break_tolerance=0.5) else: flatten_lc, trend_lc = flatten(time_i, flatten_i, window_length=wl[i], return_trend=True, method='biweight', break_tolerance=0.5) global_flatten_lc[i] = flatten_lc global_trend_lc[i] = trend_lc ## save in the log file all the information concerning the detrendins applied warnings.filterwarnings("ignore") global_final = np.zeros((len(wl), len(flatten_i))) logprint('\n MODELS IN THE DETRENDING - Run ' + str(id_run)) logprint('========================================\n') if det_met == 2: det_model = 'kernel_size:' else: det_model = 'window_size:' bins = len(time_i) * 2 / minutes bin_means, bin_edges, binnumber = stats.binned_statistic(time_i, flatten_i, statistic='mean', bins=bins) bin_stds, _, _ = stats.binned_statistic(time_i, flatten_i, statistic='std', bins=bins) bin_width = (bin_edges[1] - bin_edges[0]) bin_centers = bin_edges[1:] - bin_width / 2 logprint('PDCSAP_FLUX_' + str(id_run), '\t ', ' ------ ', '\t', '------', '\t', '\t', 'RMS (ppm):', np.std(flatten_i) * 1e6, '\t', 'RMS_10min (ppm):', np.std(bin_means[~np.isnan(bin_means)]) * 1e6) for i in range(len(wl)): flatten = sigma_clip(global_flatten_lc[i], sigma_lower=20, sigma_upper=3) global_final[i] = flatten bins_i = len(time_i) * 2 / minutes bin_means_i, bin_edges_i, binnumber_i = stats.binned_statistic( time_i, flatten, statistic='mean', bins=bins_i) bin_stds_i, _, _ = stats.binned_statistic(time_i, flatten, statistic='std', bins=bins_i) bin_width_i = (bin_edges_i[1] - bin_edges_i[0]) bin_centers_i = bin_edges_i[1:] - bin_width_i / 2 logprint('flatten_lc%s' % i, '\t ', 'trend_lc%s' % i, '\t', det_model, format(wl[i], '0.4f'), '\t', 'RMS (ppm):', np.std(flatten) * 1e6, '\t', 'RMS_10min (ppm):', np.std(bin_means_i[~np.isnan(bin_means_i)]) * 1e6) ## save in a plot all the detrendings and all the data to inspect visually. cases = np.zeros((len(wl), 1)) for i in range(len(wl)): cases[i] = wl[i] figsize = (8, 8) #x,y cols = 3 rows = len(cases) // cols shift = 2 * (1.0 - (np.min(flatten_i)) ) #shift in the between the raw and detrended data ylim_max = 1.0 + 3 * (np.max(flatten_i) - 1.0 ) #shift in the between the raw and detrended data ylim_min = 1.0 - 2.0 * shift #shift in the between the raw and detrended data fig1, axs = plt.subplots(rows, cols, figsize=figsize, constrained_layout=True) axs = trim_axs(axs, len(cases)) for ax, case in zip(axs, cases): if det_met == 2: ax.set_title('ks=%s' % str(np.around(case, decimals=4))) else: ax.set_title('ws=%s' % str(np.around(case, decimals=4))) bins_i = len(time_i) * 2 / minutes bin_means_i, bin_edges_i, binnumber_i = stats.binned_statistic( time_i, global_final[np.nonzero(cases == case)[0][0]], statistic='mean', bins=bins_i) bin_stds_i, _, _ = stats.binned_statistic( time_i, global_final[np.nonzero(cases == case)[0][0]], statistic='std', bins=bins_i) bin_width_i = (bin_edges_i[1] - bin_edges_i[0]) bin_centers_i = bin_edges_i[1:] - bin_width_i / 2 ax.plot(time_i, flatten_i, linewidth=0.05, color='black', alpha=0.75, rasterized=True) ax.plot(time_i, global_trend_lc[np.nonzero(cases == case)[0][0]], linewidth=1, color='orange', alpha=1.0) ax.plot(time_i, global_final[np.nonzero(cases == case)[0][0]] - shift, linewidth=0.05, color='teal', alpha=0.75, rasterized=True) ax.plot(bin_centers_i, bin_means_i - shift, marker='.', markersize=2, color='firebrick', alpha=0.5, linestyle='none', rasterized=True) ax.set_ylim(ylim_min, ylim_max) plt.savefig('Detrends_' + 'run_' + str(id_run) + '_TIC' + str(TIC_ID) + '.png', dpi=200) # --------------------------------------------------------------------------------------------------------------------------------------------------------- # Search of signals in the raw data # --------------------------------------------------------------------------------------------------------------------------------------------------------- logprint('\n SEARCH OF SIGNALS - Run', id_run) logprint('=================================\n') logprint('PDCSAP_FLUX_' + str(id_run), '\t', 'Period', '\t', 'Per_err', '\t', 'N.Tran', '\t', 'Mean Depth(ppt)', '\t', 'T. dur(min)', '\t', 'T0', '\t', 'SNR', '\t', 'SDE', '\t', 'FAP\n') model = transitleastsquares(time_i, flatten_i) results_pdcsap = model.power(u=ab, M_star=mass, M_star_min=mass_min, M_star_max=mass_max, R_star=radius, R_star_min=radius_min, R_star_max=radius_max, period_min=Pmin, period_max=Pmax, n_transits_min=n_tra, show_progress_bar=False) x = [] if results_pdcsap.T0 != 0: for j in range(0, len(results_pdcsap.transit_depths)): # print (results.transit_depths[i]) x = np.append(x, results_pdcsap.transit_depths[j]) x = x[~np.isnan(x)] depth = (1. - np.mean(x)) * 100 / 0.1 #we change to ppt units else: depth = results_pdcsap.transit_depths logprint('-----', '\t ', format(results_pdcsap.period, '.5f'), '\t ', format(results_pdcsap.period_uncertainty, '.6f'), '\t ', results_pdcsap.distinct_transit_count, '\t', format(depth, '.3f'), '\t', format(results_pdcsap.duration * 24 * 60, '.1f'), '\t', results_pdcsap.T0, '\t ', format(results_pdcsap.snr, '.3f'), '\t ', format(results_pdcsap.SDE, '.3f'), '\t ', results_pdcsap.FAP) logprint('\n') # --------------------------------------------------------------------------------------------------------------------------------------------------------- # Saving a plot of the best signal from raw data # --------------------------------------------------------------------------------------------------------------------------------------------------------- fig = save_plot(time_i, global_final, results_pdcsap, i) fig.suptitle('PDCSAP_FLUX_' + str(id_run) + ' ## SNR:' + str(format(results_pdcsap.snr, '.3f')) + ' ## SDE:' + str(format(results_pdcsap.SDE, '.3f')) + ' ## FAP:' + str(results_pdcsap.FAP)) plt.savefig('Run_' + str(id_run) + '_PDCSAP-FLUX_' + 'TIC' + str(TIC_ID) + '.png', bbox_inches='tight', dpi=200) # --------------------------------------------------------------------------------------------------------------------------------------------------------- # Search of signals in the detrended data # --------------------------------------------------------------------------------------------------------------------------------------------------------- if det_met == 2: logprint('Kernel_size', '\t', 'Period', '\t', 'Per_err', '\t', 'N.Tran', '\t', 'Mean Depth(ppt)', '\t', 'T. dur(min)', '\t', 'T0', '\t', 'SNR', '\t', 'SDE', '\t', 'FAP\n') else: logprint('Window_size', '\t', 'Period', '\t', 'Per_err', '\t', 'N.Tran', '\t', 'Mean Depth(ppt)', '\t', 'T. dur(min)', '\t', 'T0', '\t', 'SNR', '\t', 'SDE', '\t', 'FAP\n') SNR = np.zeros((len(wl), 1)) SDE = np.zeros((len(wl), 1)) FAP = np.zeros((len(wl), 1)) periods = np.zeros((len(wl), 1)) per_err = np.zeros((len(wl), 1)) durations = np.zeros((len(wl), 1)) tos = np.zeros((len(wl), 1)) for i in range(len(wl)): print(i) model = transitleastsquares(time_i, global_final[i]) results = model.power(u=ab, M_star=mass, M_star_min=mass_min, M_star_max=mass_max, R_star=radius, R_star_min=radius_min, R_star_max=radius_max, period_min=Pmin, period_max=Pmax, n_transits_min=n_tra, show_progress_bar=False) SNR[i] = results.snr SDE[i] = results.SDE FAP[i] = results.FAP periods[i] = results.period per_err[i] = results.period_uncertainty durations[i] = results.duration tos[i] = results.T0 x = [] if results.T0 != 0: for j in range(0, len(results.transit_depths)): # print (results.transit_depths[i]) x = np.append(x, results.transit_depths[j]) x = x[~np.isnan(x)] depth = (1. - np.mean(x)) * 100 / 0.1 #we change to ppt units else: depth = results.transit_depths logprint(format(wl[i], '.4f'), '\t ', format(results.period, '.5f'), '\t ', format(results.period_uncertainty, '.6f'), '\t ', results.distinct_transit_count, '\t', format(depth, '.3f'), '\t', format(results.duration * 24 * 60, '.1f'), '\t', results.T0, '\t ', format(results.snr, '.3f'), '\t ', format(results.SDE, '.3f'), '\t ', results.FAP) # ----------------------------------------------------------------------------------------------------------------------------------------------------- # Saving a plot of the best signal from detrended data # ----------------------------------------------------------------------------------------------------------------------------------------------------- fig = save_plot(time_i, global_final, results, i) if det_met == 2: fig.suptitle('Run ' + str(id_run) + ' ## kernel_size:' + str(format(wl[i], '.4f')) + ' ## SNR:' + str(format(results.snr, '.3f')) + ' ## SDE:' + str(format(results.SDE, '.3f')) + ' ## FAP:' + str(results.FAP)) #plt.savefig('TIC'+str(TIC_ID)+'_ks='+str(format(wl[i],'.4f'))+'_run_'+str(id_run)+'.png', bbox_inches='tight', dpi=200) plt.savefig('Run_' + str(id_run) + '_ks=' + str(format(wl[i], '.4f')) + '_TIC' + str(TIC_ID) + '.png', bbox_inches='tight', dpi=200) else: fig.suptitle('Run ' + str(id_run) + ' ## window_size:' + str(format(wl[i], '.4f')) + ' ## SNR:' + str(format(results.snr, '.3f')) + ' ## SDE:' + str(format(results.SDE, '.3f')) + ' ## FAP:' + str(results.FAP)) #plt.savefig('TIC'+str(TIC_ID)+'_ws='+str(format(wl[i],'.4f'))+'_run_'+str(id_run)+'.png', bbox_inches='tight', dpi=200) plt.savefig('Run_' + str(id_run) + '_ws=' + str(format(wl[i], '.4f')) + '_TIC' + str(TIC_ID) + '.png', bbox_inches='tight', dpi=200) SNR = np.nan_to_num(SNR) a = np.nanargmax(SNR) #check the maximum SRN if results_pdcsap.snr > SNR[a]: logprint('\nBest Signal -->', '\t', 'PDCSAP_FLUX', '\t', 'SNR:', format(results_pdcsap.snr, '.3f')) if ( results_pdcsap.snr > SNR_min ): # and results_pdcsap.SDE > SDE_min and results_pdcsap.FAP < FAP_max): logprint( '\nBest Signal is good enough to keep searching. Going to the next run.' ) key = 1 else: logprint('\nBest Signal does not look very promising. End') key = 0 else: if det_met == 2: logprint('\nBest Signal -->', '\t', 'flatten_lc' + str(a), '\t', 'kernel_size:', format(wl[a], '0.4f'), '\t', 'SNR:', format(SNR[a][0], '.3f')) else: logprint('\nBest Signal -->', '\t', 'flatten_lc' + str(a), '\t', 'window_size:', format(wl[a], '0.4f'), '\t', 'SNR:', format(SNR[a][0], '.3f')) if (SNR[a] > SNR_min): #and SDE[a] > SDE_min and FAP[a] < FAP_max): logprint( '\nBest Signal is good enough to keep searching. Going to the next run.' ) key = 1 else: logprint('\nBest Signal does not look very promising. End') key = 0 print("### SNR :", str(format(results.snr, '.3f')), " SDE :", str(format(results.SDE, '.3f')), " FAP :", str(results.FAP)) return results_pdcsap, SNR, key, periods, durations, tos
#ax.axvline(params.t0+2*params.per+lc_30min.time[index], ymin = 0.1, ymax = 0.2, lw=1, c = 'r') #ax.axvline(params.t0-params.per+lc_30min.time[index], ymin = 0.1, ymax = 0.2, lw=1, c = 'r') peak_cut_fig.savefig(save_path + "{} - Peak cut fig.png".format(target_ID)) #peak_cut_fig.show() plt.close(peak_cut_fig) else: t_cut = lc_30min.time flux_cut = combined_flux print('else clause completed') #################################### Wotan #################################### if detrending == 'wotan': flatten_lc_before, trend_before = flatten(lc_30min.time, combined_flux, window_length=0.3, method='hspline', return_trend=True) flatten_lc_after, trend_after = flatten(t_cut, flux_cut, window_length=0.3, method='hspline', return_trend=True) # Plot before peak removal wotan_original_lc_fig = plt.figure() plt.scatter(lc_30min.time, flatten_lc_before, c='k', s=2) plt.xlabel('Time - 2457000 [BTJD days]') plt.ylabel("Relative flux") plt.title( '{} lc after standard wotan detrending - before peak removal'.
def tls_search(time, flux, epoch, period, rplanet, min_snr, transit_template): SNR = 1e12 FOUND_SIGNAL = False #::: mask out the first detection at 6.2 days, with a duration of 2.082h, and T0=1712.54922 # intransit = transit_mask(time, 6.26391, 2*2.082/24., 1712.54922) # time = time[~intransit] # flux = flux[~intransit] time, flux = cleaned_array(time, flux) run = 0 flux = wotan.flatten(time, flux, window_length=0.25, return_trend=False, method='biweight', break_tolerance=0.5) #::: search for the rest while (SNR >= min_snr) and (not FOUND_SIGNAL): model = transitleastsquares(time, flux) R_starx = rstar / u.R_sun results = model.power(u=ab, R_star=radius, # rstar/u.R_sun, R_star_min=rstar_min, # rstar_min/u.R_sun, R_star_max=rstar_max, # rstar_max/u.R_sun, M_star=mass, # mstar/u.M_sun, M_star_min=mstar_min, # mstar_min/u.M_sun, M_star_max=mstar_max, # mstar_max/u.M_sun, period_min=0.5, period_max=14, n_transits_min=2, show_progress_bar=False, use_threads=20, transit_template=transit_template ) # mass and radius for the TLS # rstar=radius ##mstar=mass # mstar_min = mass-massmin # mstar_max = mass+massmax # rstar_min = radius-radiusmin # rstar_max = radius+raduismax SNR = results.snr if results.snr >= min_snr: intransit = transit_mask(time, results.period, 2 * results.duration, results.T0) time = time[~intransit] flux = flux[~intransit] time, flux = cleaned_array(time, flux) #::: check if it found the right signal right_period = IsMultipleOf(results.period, period / 2.) # check if it is a multiple of half the period to within 5% right_epoch = False for tt in results.transit_times: for i in range(-5, 5): right_epoch = right_epoch or (np.abs(tt - epoch + i * period) < ( 1. / 24.)) # check if any epochs matches to within 1 hour # right_depth = (np.abs(np.sqrt(1.-results.depth)*rstar - rplanet)/rplanet < 0.05) #check if the depth matches if right_period and right_epoch: FOUND_SIGNAL = True break run = run + 1 return FOUND_SIGNAL, results.snr, run
def main(): print("Starting tests for wotan...") numpy.testing.assert_almost_equal(t14(R_s=1, M_s=1, P=365), 0.6490025258902046) numpy.testing.assert_almost_equal( t14(R_s=1, M_s=1, P=365, small_planet=True), 0.5403690143737738) print("Transit duration correct.") numpy.random.seed(seed=0) # reproducibility print("Slide clipper...") points = 1000 time = numpy.linspace(0, 30, points) flux = 1 + numpy.sin(time) / points noise = numpy.random.normal(0, 0.0001, points) flux += noise for i in range(points): if i % 75 == 0: flux[i:i + 5] -= 0.0004 # Add some transits flux[i + 50:i + 52] += 0.0002 # and flares clipped = slide_clip(time, flux, window_length=0.5, low=3, high=2, method='mad', center='median') numpy.testing.assert_almost_equal(numpy.nansum(clipped), 948.9926368754939) """ import matplotlib.pyplot as plt plt.scatter(time, flux, s=3, color='black') plt.scatter(time, clipped, s=3, color='orange') plt.show() """ # TESS test print('Loading TESS data from archive.stsci.edu...') path = 'https://archive.stsci.edu/hlsps/tess-data-alerts/' filename = "hlsp_tess-data-alerts_tess_phot_00062483237-s01_tess_v1_lc.fits" #path = 'P:/P/Dok/tess_alarm/' #filename = "hlsp_tess-data-alerts_tess_phot_00062483237-s01_tess_v1_lc.fits" #filename = 'P:/P/Dok/tess_alarm/hlsp_tess-data-alerts_tess_phot_00077031414-s02_tess_v1_lc.fits' #filename = 'tess2018206045859-s0001-0000000201248411-111-s_llc.fits' time, flux = load_file(path + filename) window_length = 0.5 print("Detrending 1 (biweight)...") flatten_lc, trend_lc = flatten(time, flux, window_length, edge_cutoff=1, break_tolerance=0.1, return_trend=True, cval=5.0) numpy.testing.assert_equal(len(trend_lc), 20076) numpy.testing.assert_almost_equal(numpy.nanmax(trend_lc), 28754.985299070882) numpy.testing.assert_almost_equal(numpy.nanmin(trend_lc), 28615.108124724477) numpy.testing.assert_almost_equal(trend_lc[500], 28671.686308143515) numpy.testing.assert_equal(len(flatten_lc), 20076) numpy.testing.assert_almost_equal(numpy.nanmax(flatten_lc), 1.0034653549250616) numpy.testing.assert_almost_equal(numpy.nanmin(flatten_lc), 0.996726610702177) numpy.testing.assert_almost_equal(flatten_lc[500], 1.000577429565131) print("Detrending 2 (andrewsinewave)...") flatten_lc, trend_lc = flatten(time, flux, window_length, method='andrewsinewave', return_trend=True) numpy.testing.assert_almost_equal(numpy.nansum(flatten_lc), 18119.15471987987, decimal=2) print("Detrending 3 (welsch)...") flatten_lc, trend_lc = flatten(time, flux, window_length, method='welsch', return_trend=True) numpy.testing.assert_almost_equal(numpy.nansum(flatten_lc), 18119.16764691235, decimal=2) print("Detrending 4 (hodges)...") flatten_lc, trend_lc = flatten(time[:1000], flux[:1000], window_length, method='hodges', return_trend=True) numpy.testing.assert_almost_equal(numpy.nansum(flatten_lc), 994.0110525909206, decimal=2) print("Detrending 5 (median)...") flatten_lc, trend_lc = flatten(time, flux, window_length, method='median', return_trend=True) numpy.testing.assert_almost_equal(numpy.nansum(flatten_lc), 18119.122065014355, decimal=2) print("Detrending 6 (mean)...") flatten_lc, trend_lc = flatten(time, flux, window_length, method='mean', return_trend=True) numpy.testing.assert_almost_equal(numpy.nansum(flatten_lc), 18119.032473037714, decimal=2) print("Detrending 7 (trim_mean)...") flatten_lc, trend_lc = flatten(time, flux, window_length, method='trim_mean', return_trend=True) numpy.testing.assert_almost_equal(numpy.nansum(flatten_lc), 18119.095164910334, decimal=2) print("Detrending 8 (supersmoother)...") flatten_lc, trend_lc = flatten(time, flux, window_length, method='supersmoother', return_trend=True) numpy.testing.assert_almost_equal(numpy.nansum(flatten_lc), 18123.00632204841, decimal=2) print("Detrending 9 (hspline)...") flatten_lc, trend_lc = flatten(time, flux, window_length, method='hspline', return_trend=True) numpy.testing.assert_almost_equal(numpy.nansum(flatten_lc), 18123.07625225313, decimal=2) print("Detrending 10 (cofiam)...") flatten_lc, trend_lc = flatten(time[:2000], flux[:2000], window_length, method='cofiam', return_trend=True) numpy.testing.assert_almost_equal(numpy.nansum(flatten_lc), 1948.9999999987976, decimal=2) print("Detrending 11 (savgol)...") flatten_lc, trend_lc = flatten(time, flux, window_length=301, method='savgol', return_trend=True) numpy.testing.assert_almost_equal(numpy.nansum(flatten_lc), 18123.003465539354, decimal=2) print("Detrending 12 (medfilt)...") flatten_lc, trend_lc = flatten(time, flux, window_length=301, method='medfilt', return_trend=True) numpy.testing.assert_almost_equal(numpy.nansum(flatten_lc), 18123.22609806557, decimal=2) print("Detrending 12 (gp squared_exp)...") flatten_lc, trend_lc1 = flatten(time[:2000], flux[:2000], method='gp', kernel='squared_exp', kernel_size=10, return_trend=True) numpy.testing.assert_almost_equal(numpy.nansum(flatten_lc), 1948.99958552324, decimal=2) print("Detrending 13 (gp squared_exp robust)...") flatten_lc, trend_lc1 = flatten(time[:2000], flux[:2000], method='gp', kernel='squared_exp', kernel_size=10, robust=True, return_trend=True) numpy.testing.assert_almost_equal(numpy.nansum(flatten_lc), 1948.8820772313468, decimal=2) print("Detrending 14 (gp matern)...") flatten_lc, trend_lc2 = flatten(time[:2000], flux[:2000], method='gp', kernel='matern', kernel_size=10, return_trend=True) numpy.testing.assert_almost_equal(numpy.nansum(flatten_lc), 1949.0001583058202, decimal=2) print("Detrending 15 (gp periodic)...") flatten_lc, trend_lc2 = flatten(time[:2000], flux[:2000], method='gp', kernel='periodic', kernel_size=1, kernel_period=10, return_trend=True) numpy.testing.assert_almost_equal(numpy.nansum(flatten_lc), 1948.9999708985608, decimal=2) time_synth = numpy.linspace(0, 30, 200) flux_synth = numpy.sin(time_synth) + numpy.random.normal(0, 0.1, 200) flux_synth = 1 + flux_synth / 100 time_synth *= 1.5 print("Detrending 16 (gp periodic_auto)...") flatten_lc, trend_lc2 = flatten(time_synth, flux_synth, method='gp', kernel='periodic_auto', kernel_size=1, return_trend=True) numpy.testing.assert_almost_equal(numpy.nansum(flatten_lc), 200, decimal=1) print("Detrending 17 (rspline)...") flatten_lc, trend_lc2 = flatten(time, flux, method='rspline', window_length=1, return_trend=True) numpy.testing.assert_almost_equal(numpy.nansum(flatten_lc), 18121.812790732245, decimal=2) print("Detrending 18 (huber)...") flatten_lc, trend_lc = flatten(time[:1000], flux[:1000], method='huber', window_length=0.5, edge_cutoff=0, break_tolerance=0.4, return_trend=True) numpy.testing.assert_almost_equal(numpy.nansum(flatten_lc), 994.01102, decimal=2) print("Detrending 19 (winsorize)...") flatten_lc, trend_lc2 = flatten(time, flux, method='winsorize', window_length=0.5, edge_cutoff=0, break_tolerance=0.4, proportiontocut=0.1, return_trend=True) numpy.testing.assert_almost_equal(numpy.nansum(flatten_lc), 18119.064587196448, decimal=2) print("Detrending 20 (pspline)...") flatten_lc, trend_lc = flatten(time, flux, method='pspline', return_trend=True) numpy.testing.assert_almost_equal(numpy.nansum(flatten_lc), 18121.832133916843, decimal=2) print("Detrending 21 (hampelfilt)...") flatten_lc, trend_lc5 = flatten(time, flux, method='hampelfilt', window_length=0.5, cval=3, return_trend=True) numpy.testing.assert_almost_equal(numpy.nansum(flatten_lc), 18119.158072498867, decimal=2) print("Detrending 22 (lowess)...") flatten_lc, trend_lc1 = flatten(time, flux, method='lowess', window_length=1, return_trend=True) numpy.testing.assert_almost_equal(numpy.nansum(flatten_lc), 18123.08085676265, decimal=2) print("Detrending 23 (huber_psi)...") flatten_lc, trend_lc1 = flatten(time, flux, method='huber_psi', window_length=0.5, return_trend=True) numpy.testing.assert_almost_equal(numpy.nansum(flatten_lc), 18119.122065014355, decimal=2) print("Detrending 24 (tau)...") flatten_lc, trend_lc2 = flatten(time, flux, method='tau', window_length=0.5, return_trend=True) numpy.testing.assert_almost_equal(numpy.nansum(flatten_lc), 18119.02772621119, decimal=2) import numpy as np points = 1000 time = np.linspace(0, 30, points) flux = 1 + np.sin(time) / points noise = np.random.normal(0, 0.0001, points) flux += noise for i in range(points): if i % 75 == 0: flux[i:i + 5] -= 0.0004 # Add some transits flux[i + 50:i + 52] += 0.0002 # and flares print("Detrending 25a (hampel 17A)...") flatten_lc, trend_lc1 = flatten(time, flux, method='hampel', cval=(1.7, 3.4, 8.5), window_length=0.5, return_trend=True) print("Detrending 25b (hampel 25A)...") flatten_lc, trend_lc2 = flatten(time, flux, method='hampel', cval=(2.5, 4.5, 9.5), window_length=0.5, return_trend=True) numpy.testing.assert_almost_equal(numpy.nansum(flatten_lc), 997.9994362858843, decimal=2) print("Detrending 26 (ramsay)...") flatten_lc, trend_lc3 = flatten(time, flux, method='ramsay', cval=0.3, window_length=0.5, return_trend=True) numpy.testing.assert_almost_equal(numpy.nansum(flatten_lc), 997.9974021484584, decimal=2) """ import matplotlib.pyplot as plt plt.scatter(time, flux, s=1, color='black') plt.plot(time[:len(trend_lc1)], trend_lc1, color='blue', linewidth=2) plt.plot(time[:len(trend_lc1)], trend_lc2, color='red', linewidth=2, linestyle='dashed') plt.show() plt.close() #plt.scatter(time, flatten_lc, s=1, color='black') #plt.show() """ print('All tests completed.')
def prepare_ttv_fit(datadir, ax=None): ''' this must be run *after* reduce_phot_data() ''' ax0 = ax alles = allesfitter.allesclass(datadir) window = alles.settings['fast_fit_width'] if not os.path.exists( os.path.join(datadir,'ttv_preparation') ): os.makedirs(os.path.join(datadir,'ttv_preparation')) with open(os.path.join(datadir,'ttv_preparation','ttv_initial_guess_params.csv'),'w') as f: f.write('') def plot_all_transits_color_coded(): for inst in alles.settings['inst_phot']: time = alles.data[inst]['time'] for companion in alles.settings['companions_phot']: ind = [] for i, t in enumerate(alles.data[companion+'_tmid_observed_transits']): ind += list( np.where((time >= (t - window/2.)) & (time <= (t + window/2.)))[0] ) ax.plot( alles.data[inst]['time'][ind], alles.data[inst]['flux'][ind], ls='none', marker='.', label=companion ) for companion in alles.settings['companions_phot']: with open(os.path.join(datadir,'ttv_preparation','ttv_initial_guess_params.csv'),'a') as f: f.write('#TTV companion '+companion+',,,,,\n') #---------------------------------------------------------------------- #::: get combined data from all instruments #---------------------------------------------------------------------- all_times = [] all_flux = [] for inst in alles.settings['inst_phot']: all_times += list(alles.data[inst]['time']) all_flux += list(alles.data[inst]['flux']) ind_sort = np.argsort(all_times) all_times = np.array(all_times)[ind_sort] all_flux = np.array(all_flux)[ind_sort] #---------------------------------------------------------------------- #::: get eclipse window #---------------------------------------------------------------------- alles.initial_guess_params_median[companion+'_epoch'] eclipse_width = eclipse_width_smart(alles.initial_guess_params_median[companion+'_period'], alles.initial_guess_params_median[companion+'_rr'], alles.initial_guess_params_median[companion+'_rsuma'], alles.initial_guess_params_median[companion+'_cosi'], alles.initial_guess_params_median[companion+'_f_s'], alles.initial_guess_params_median[companion+'_f_c'], )[0] #---------------------------------------------------------------------- #::: compute tmid, ttv_guess and make per-transit-plots #---------------------------------------------------------------------- tmids = [] alles.data[companion+'_tmid_observed_transits'] = get_tmid_observed_transits(all_times,alles.initial_guess_params_median[companion+'_epoch'],alles.initial_guess_params_median[companion+'_period'],alles.settings['fast_fit_width']) N = len(alles.data[companion+'_tmid_observed_transits']) fig, axes = plt.subplots(N, 1, figsize=(6,4*N), sharey=True, tight_layout=True) for i, t in enumerate(alles.data[companion+'_tmid_observed_transits']): ind_tr1 = np.where((all_times >= (t - window/2.)) & (all_times <= (t + window/2.)))[0] tr_times = all_times[ind_tr1] tr_flux = all_flux[ind_tr1] t_exp = np.median(np.diff(tr_times)) N_points_in_eclipse = int(eclipse_width/t_exp) try: trend = flatten(tr_times, tr_flux, window_length=eclipse_width/2., method='biweight', return_trend=True)[1] tmid = np.median( tr_times[ np.argsort(trend)[0:int(N_points_in_eclipse/2.)] ] ) except: warnings.warn('Install wotan for improved performance of prepare_ttv_fit().') trend = None tmid = np.median( tr_times[ np.argsort(tr_times)[0:int(N_points_in_eclipse/2.)] ] ) ttv_guess = tmid - t tmids.append(tmid) ax = axes[i] ax.plot(tr_times, tr_flux, 'b.', rasterized=True) if trend is not None: ax.plot(tr_times, trend, 'r-') ax.axvline(t,c='grey',ls='--',label='linear prediction') ax.axvline(tmid,c='r',ls='--',label='flux minimum') ax.set(xlabel='Time', ylabel='Flux', xlim=[t-window/2., t+window/2.]) ax.text(0.95,0.95,'Transit '+str(i+1), va='top', ha='right', transform=ax.transAxes) with open(os.path.join(datadir,'ttv_preparation','ttv_initial_guess_params.csv'),'a') as f: f.write(companion+'_ttv_transit_'+str(i+1)+','+np.format_float_positional(ttv_guess,4)+',1,uniform '+np.format_float_positional(ttv_guess-0.01,4)+' '+np.format_float_positional(ttv_guess+0.01,4)+',TTV$_\mathrm{'+companion+';'+str(i+1)+'}$,d\n') axes[0].legend() fig.savefig(os.path.join(datadir,'ttv_preparation','ttv_preparation_'+companion+'_per_transit.pdf'), bbox_inches='tight') plt.close(fig) tmids = np.array(tmids) #---------------------------------------------------------------------- #::: ttv guess 0-C plot #---------------------------------------------------------------------- nr = np.array([ int(np.round( (t-tmids[0]) / alles.initial_guess_params_median[companion+'_period'] )) for t in tmids ]) #get corresponding transit number nr -= int(nr[-1]/2.) #shift into the middle of the data set period_mean, epoch_mean = np.polyfit(nr, tmids, 1) fig, axes = plt.subplots(2,1,figsize=(6,8),tight_layout=True,sharex=True) axes[0].plot(nr, tmids, 'bo', label='Companion '+companion) axes[0].plot(nr, epoch_mean + nr * period_mean, 'b-') axes[0].set(xlabel='Nr.', ylabel='Transit mid-time') axes[0].legend() axes[1].plot(nr, tmids-(epoch_mean + nr * period_mean), 'bo') axes[1].axhline(0,c='grey',ls='--') fig.savefig(os.path.join(datadir,'ttv_preparation','ttv_preparation_'+companion+'_oc.pdf'), bbox_inches='tight') period_dev = np.abs( (period_mean-alles.initial_guess_params_median[companion+'_period'])/alles.initial_guess_params_median[companion+'_period'] ) epoch_dev = np.abs( (epoch_mean-alles.initial_guess_params_median[companion+'_epoch'])/alles.initial_guess_params_median[companion+'_epoch'] ) print('\nCompanion', companion) print('Initial guess for mean period and epoch:') print(np.format_float_positional(alles.initial_guess_params_median[companion+'_period']), np.format_float_positional(alles.initial_guess_params_median[companion+'_epoch'])) print('New estimate for mean period and epoch:') print(np.format_float_positional(period_mean,4), np.format_float_positional(epoch_mean,4)) # print('Deviation from another:') # print(np.format_float_positional(period_dev,4), # np.format_float_positional(epoch_dev,4)) if (period_dev > 0.01) or (epoch_dev > 0.01): print('\n! Consider updating your initial guess to these new estimated mean values.') print('\n! If you do, then you must rerun this code.') else: print('\n! Looks great! You are ready to fit.') #---------------------------------------------------------------------- #::: full lightcurve plot #---------------------------------------------------------------------- flux_min = np.nanmin(all_flux) flux_max = np.nanmax(all_flux) if ax0 is None: days = np.max(all_times) - np.min(all_times) figsizex = np.max( [5, 5*(days/10.)] ) fig, ax = plt.subplots(figsize=(figsizex, 4)) #figsize * 5 for every 20 days for inst in alles.settings['inst_phot']: ax.plot(alles.fulldata[inst]['time'], alles.fulldata[inst]['flux'],ls='none',marker='.',color='silver') # ax.plot(alles.data[inst]['time'], alles.data[inst]['flux'],ls='none',marker='.',label=inst) #color code by instrument plot_all_transits_color_coded() #color code by companion ax.plot( alles.data[companion+'_tmid_observed_transits'], np.ones_like(alles.data[companion+'_tmid_observed_transits'])*0.997*flux_min, 'k^', zorder=12 ) for i, tmid in enumerate(alles.data[companion+'_tmid_observed_transits']): ax.text( tmid, 0.992*flux_min, str(i+1), ha='center', zorder=12 ) ax.axvline( tmid, color='grey', zorder=11 ) ax.set(ylim=[0.99*flux_min, 1.002*flux_max], xlabel='Time (BJD)', ylabel='Realtive Flux', title='Companion '+companion) ax.legend(loc='best') fname = os.path.join(datadir,'ttv_preparation','ttv_preparation_'+companion+'.jpg') fig = plt.gcf() fig.savefig(fname, bbox_inches='tight' ) plt.close(fig)
def calculate(self): if self.ui.radio_remove_median.isChecked(): flatten_lc1 = self.flux/np.median(self.flux) trend_lc1 = np.ones(len(self.flux))*np.median(self.flux) elif self.ui.radio_remove_mean.isChecked(): flatten_lc1 = self.flux/np.mean(self.flux) trend_lc1 = np.ones(len(self.flux))*np.mean(self.flux) elif self.ui.radio_timeW.isChecked(): flatten_lc1, trend_lc1 = flatten( self.t, # Array of time values self.flux , # Array of flux values method=str(self.ui.comboBox_sliders.currentText()), window_length=self.ui.sliders_wl.value(), # The length of the filter window in units of ``time`` # break_tolerance=self.ui.spline_bt.value(), # Split into segments at breaks longer than that return_trend=True, # Return trend and flattened light curve ) elif self.ui.radio_Splines.isChecked(): flatten_lc1, trend_lc1 = flatten( self.t, # Array of time values self.flux , # Array of flux values method=str(self.ui.comboBox_splines.currentText()), window_length=self.ui.spline_wl.value(), # The length of the filter window in units of ``time`` break_tolerance=self.ui.spline_bt.value(), # Split into segments at breaks longer than that return_trend=True, # Return trend and flattened light curve ) elif self.ui.radio_Polynomials.isChecked(): flatten_lc1, trend_lc1 = flatten( self.t, # Array of time values self.flux , # Array of flux values method=str(self.ui.comboBox_poly.currentText()), window_length=self.ui.poly_wl.value(), # The length of the filter window in units of ``time`` break_tolerance=self.ui.poly_bt.value(), # Split into segments at breaks longer than that return_trend=True, # Return trend and flattened light curve ) elif self.ui.radio_Regressions.isChecked(): flatten_lc1, trend_lc1 = flatten( self.t, # Array of time values self.flux , # Array of flux values method=str(self.ui.comboBox_regs.currentText()), window_length=self.ui.regres_wl.value(), # The length of the filter window in units of ``time`` break_tolerance=self.ui.regres_bt.value(), # Split into segments at breaks longer than that return_trend=True, # Return trend and flattened light curve ) elif self.ui.radio_GPs.isChecked(): flatten_lc1, trend_lc1 = flatten( self.t, # Array of time values self.flux , # Array of flux values method='gp', kernel = str(self.ui.comboBox_GP.currentText()), kernel_size=self.ui.kernel_size.value(), break_tolerance=self.ui.regres_bt.value(), # Split into segments at breaks longer than that kernel_period = self.ui.GP_period.value(), robust = self.ui.checkBox_GP_robust.isChecked(), return_trend=True # Return trend and flattened light curve ) else: flatten_lc1 = self.flux trend_lc1 = np.ones(len(self.flux))*np.median(self.flux) self.flux_o_c = flatten_lc1 self.trend = trend_lc1 self.flux_err_o_c = self.flux_err/trend_lc1
def main(): print("Starting tests for wotan...") numpy.testing.assert_almost_equal(t14(R_s=1, M_s=1, P=365), 0.6490025258902046) numpy.testing.assert_almost_equal( t14(R_s=1, M_s=1, P=365, small_planet=True), 0.5403690143737738 ) print("Transit duration correct.") numpy.random.seed(seed=0) # reproducibility print("Slide clipper...") points = 1000 time = numpy.linspace(0, 30, points) flux = 1 + numpy.sin(time) / points noise = numpy.random.normal(0, 0.0001, points) flux += noise for i in range(points): if i % 75 == 0: flux[i : i + 5] -= 0.0004 # Add some transits flux[i + 50 : i + 52] += 0.0002 # and flares clipped = slide_clip( time, flux, window_length=0.5, low=3, high=2, method="mad", center="median" ) numpy.testing.assert_almost_equal(numpy.nansum(clipped), 948.9926368754939) """ import matplotlib.pyplot as plt plt.scatter(time, flux, s=3, color='black') plt.scatter(time, clipped, s=3, color='orange') plt.show() """ # TESS test print("Loading TESS data from archive.stsci.edu...") path = "https://archive.stsci.edu/hlsps/tess-data-alerts/" # path = 'P:/P/Dok/tess_alarm/' filename = "hlsp_tess-data-alerts_tess_phot_00062483237-s01_tess_v1_lc.fits" time, flux = load_file(path + filename) window_length = 0.5 print("Detrending 1 (biweight)...") flatten_lc, trend_lc = flatten( time, flux, window_length, edge_cutoff=1, break_tolerance=0.1, return_trend=True, cval=5.0, ) numpy.testing.assert_equal(len(trend_lc), 20076) numpy.testing.assert_almost_equal( numpy.nanmax(trend_lc), 28755.03811866676, decimal=2 ) numpy.testing.assert_almost_equal( numpy.nanmin(trend_lc), 28615.110229935075, decimal=2 ) numpy.testing.assert_almost_equal(trend_lc[500], 28671.650565730513, decimal=2) numpy.testing.assert_equal(len(flatten_lc), 20076) numpy.testing.assert_almost_equal( numpy.nanmax(flatten_lc), 1.0034653549250616, decimal=2 ) numpy.testing.assert_almost_equal( numpy.nanmin(flatten_lc), 0.996726610702177, decimal=2 ) numpy.testing.assert_almost_equal(flatten_lc[500], 1.000577429565131, decimal=2) print("Detrending 2 (andrewsinewave)...") flatten_lc, trend_lc = flatten( time, flux, window_length, method="andrewsinewave", return_trend=True ) numpy.testing.assert_almost_equal( numpy.nansum(flatten_lc), 18123.15456308313, decimal=2 ) print("Detrending 3 (welsch)...") flatten_lc, trend_lc = flatten( time, flux, window_length, method="welsch", return_trend=True ) numpy.testing.assert_almost_equal( numpy.nansum(flatten_lc), 18123.16770590837, decimal=2 ) print("Detrending 4 (hodges)...") flatten_lc, trend_lc = flatten( time[:1000], flux[:1000], window_length, method="hodges", return_trend=True ) numpy.testing.assert_almost_equal( numpy.nansum(flatten_lc), 996.0113241694287, decimal=2 ) print("Detrending 5 (median)...") flatten_lc, trend_lc = flatten( time, flux, window_length, method="median", return_trend=True ) numpy.testing.assert_almost_equal( numpy.nansum(flatten_lc), 18123.12166552401, decimal=2 ) print("Detrending 6 (mean)...") flatten_lc, trend_lc = flatten( time, flux, window_length, method="mean", return_trend=True ) numpy.testing.assert_almost_equal( numpy.nansum(flatten_lc), 18123.032058753546, decimal=2 ) print("Detrending 7 (trim_mean)...") flatten_lc, trend_lc = flatten( time, flux, window_length, method="trim_mean", return_trend=True ) numpy.testing.assert_almost_equal( numpy.nansum(flatten_lc), 18123.094751124332, decimal=2 ) print("Detrending 8 (supersmoother)...") flatten_lc, trend_lc = flatten( time, flux, window_length, method="supersmoother", return_trend=True ) numpy.testing.assert_almost_equal( numpy.nansum(flatten_lc), 18123.00632204841, decimal=2 ) print("Detrending 9 (hspline)...") flatten_lc, trend_lc = flatten( time, flux, window_length, method="hspline", return_trend=True ) numpy.testing.assert_almost_equal( numpy.nansum(flatten_lc), 18123.082601463717, decimal=1 ) print("Detrending 10 (cofiam)...") flatten_lc, trend_lc = flatten( time[:2000], flux[:2000], window_length, method="cofiam", return_trend=True ) numpy.testing.assert_almost_equal( numpy.nansum(flatten_lc), 1948.9999999987976, decimal=1 ) print("Detrending 11 (savgol)...") flatten_lc, trend_lc = flatten( time, flux, window_length=301, method="savgol", return_trend=True ) numpy.testing.assert_almost_equal( numpy.nansum(flatten_lc), 18123.003465539354, decimal=1 ) print("Detrending 12 (medfilt)...") flatten_lc, trend_lc = flatten( time, flux, window_length=301, method="medfilt", return_trend=True ) numpy.testing.assert_almost_equal( numpy.nansum(flatten_lc), 18123.22609806557, decimal=1 ) print("Detrending 12 (gp squared_exp)...") flatten_lc, trend_lc1 = flatten( time[:2000], flux[:2000], method="gp", kernel="squared_exp", kernel_size=10, return_trend=True, ) numpy.testing.assert_almost_equal( numpy.nansum(flatten_lc), 1948.9672036416687, decimal=2 ) print("Detrending 13 (gp squared_exp robust)...") flatten_lc, trend_lc1 = flatten( time[:2000], flux[:2000], method="gp", kernel="squared_exp", kernel_size=10, robust=True, return_trend=True, ) numpy.testing.assert_almost_equal( numpy.nansum(flatten_lc), 1948.8820772313468, decimal=2 ) print("Detrending 14 (gp matern)...") flatten_lc, trend_lc2 = flatten( time[:2000], flux[:2000], method="gp", kernel="matern", kernel_size=10, return_trend=True, ) numpy.testing.assert_almost_equal( numpy.nansum(flatten_lc), 1948.9672464898367, decimal=2 ) print("Detrending 15 (gp periodic)...") flatten_lc, trend_lc2 = flatten( time[:2000], flux[:2000], method="gp", kernel="periodic", kernel_size=1, kernel_period=10, return_trend=True, ) numpy.testing.assert_almost_equal( numpy.nansum(flatten_lc), 1948.9999708985608, decimal=2 ) time_synth = numpy.linspace(0, 30, 200) flux_synth = numpy.sin(time_synth) + numpy.random.normal(0, 0.1, 200) flux_synth = 1 + flux_synth / 100 time_synth *= 1.5 print("Detrending 16 (gp periodic_auto)...") flatten_lc, trend_lc2 = flatten( time_synth, flux_synth, method="gp", kernel="periodic_auto", kernel_size=1, return_trend=True, ) numpy.testing.assert_almost_equal(numpy.nansum(flatten_lc), 200, decimal=1) print("Detrending 17 (rspline)...") flatten_lc, trend_lc2 = flatten( time, flux, method="rspline", window_length=1, return_trend=True ) numpy.testing.assert_almost_equal( numpy.nansum(flatten_lc), 18121.812790732245, decimal=2 ) """ print("Detrending 18 (huber)...") flatten_lc, trend_lc = flatten( time[:1000], flux[:1000], method='huber', window_length=0.5, edge_cutoff=0, break_tolerance=0.4, return_trend=True) numpy.testing.assert_almost_equal(numpy.nansum(flatten_lc), 996.0112964009066, decimal=2) """ print("Detrending 19 (winsorize)...") flatten_lc, trend_lc2 = flatten( time, flux, method="winsorize", window_length=0.5, edge_cutoff=0, break_tolerance=0.4, proportiontocut=0.1, return_trend=True, ) numpy.testing.assert_almost_equal( numpy.nansum(flatten_lc), 18123.064149766662, decimal=2 ) print("Detrending 20 (pspline)...") flatten_lc, trend_lc = flatten(time, flux, method="pspline", return_trend=True) # import matplotlib.pyplot as plt # plt.scatter(time, flux, s=3, color='black') # plt.plot(time, trend_lc) # plt.show() numpy.testing.assert_almost_equal( numpy.nansum(flatten_lc), 18122.740535799767, decimal=2 ) print("Detrending 21 (hampelfilt)...") flatten_lc, trend_lc5 = flatten( time, flux, method="hampelfilt", window_length=0.5, cval=3, return_trend=True ) numpy.testing.assert_almost_equal( numpy.nansum(flatten_lc), 18123.157973016467, decimal=2 ) print("Detrending 22 (lowess)...") flatten_lc, trend_lc1 = flatten( time, flux, method="lowess", window_length=1, return_trend=True ) numpy.testing.assert_almost_equal( numpy.nansum(flatten_lc), 18123.039744125545, decimal=2 ) print("Detrending 23 (huber_psi)...") flatten_lc, trend_lc1 = flatten( time, flux, method="huber_psi", window_length=0.5, return_trend=True ) numpy.testing.assert_almost_equal( numpy.nansum(flatten_lc), 18123.110893063527, decimal=2 ) print("Detrending 24 (tau)...") flatten_lc, trend_lc2 = flatten( time, flux, method="tau", window_length=0.5, return_trend=True ) numpy.testing.assert_almost_equal( numpy.nansum(flatten_lc), 18123.026005725977, decimal=2 ) print("Detrending 25 (cosine)...") flatten_lc, trend_lc2 = flatten( time, flux, method="cosine", window_length=0.5, return_trend=True ) numpy.testing.assert_almost_equal( numpy.nansum(flatten_lc), 18122.999999974905, decimal=2 ) print("Detrending 25 (cosine robust)...") flatten_lc, trend_lc2 = flatten( time, flux, method="cosine", robust=True, window_length=0.5, return_trend=True ) numpy.testing.assert_almost_equal( numpy.nansum(flatten_lc), 18122.227938535038, decimal=2 ) import numpy as np points = 1000 time = numpy.linspace(0, 30, points) flux = 1 + numpy.sin(time) / points noise = numpy.random.normal(0, 0.0001, points) flux += noise for i in range(points): if i % 75 == 0: flux[i : i + 5] -= 0.0004 # Add some transits flux[i + 50 : i + 52] += 0.0002 # and flares print("Detrending 26 (hampel 17A)...") flatten_lc, trend_lc1 = flatten( time, flux, method="hampel", cval=(1.7, 3.4, 8.5), window_length=0.5, return_trend=True, ) print("Detrending 27 (hampel 25A)...") flatten_lc, trend_lc2 = flatten( time, flux, method="hampel", cval=(2.5, 4.5, 9.5), window_length=0.5, return_trend=True, ) numpy.testing.assert_almost_equal( numpy.nansum(flatten_lc), 999.9992212031945, decimal=2 ) print("Detrending 28 (ramsay)...") flatten_lc, trend_lc3 = flatten( time, flux, method="ramsay", cval=0.3, window_length=0.5, return_trend=True ) numpy.testing.assert_almost_equal( numpy.nansum(flatten_lc), 999.9970566765148, decimal=2 ) print("Detrending 29 (ridge)...") flatten_lc, trend_lc1 = flatten( time, flux, window_length=0.5, method="ridge", return_trend=True, cval=1 ) numpy.testing.assert_almost_equal( numpy.nansum(flatten_lc), 999.9999958887022, decimal=1 ) print("Detrending 30 (lasso)...") flatten_lc, trend_lc2 = flatten( time, flux, window_length=0.5, method="lasso", return_trend=True, cval=1 ) numpy.testing.assert_almost_equal( numpy.nansum(flatten_lc), 999.9999894829843, decimal=1 ) print("Detrending 31 (elasticnet)...") flatten_lc, trend_lc3 = flatten( time, flux, window_length=0.5, method="elasticnet", return_trend=True, cval=1 ) numpy.testing.assert_almost_equal( numpy.nansum(flatten_lc), 999.9999945063338, decimal=1 ) # Test of transit mask print("Testing transit_mask") filename = "hlsp_tess-data-alerts_tess_phot_00207081058-s01_tess_v1_lc.fits" time, flux = load_file(path + filename) from wotan import transit_mask mask = transit_mask(time=time, period=14.77338, duration=0.21060, T0=1336.141095) numpy.testing.assert_almost_equal(numpy.sum(mask), 302, decimal=1) print("Detrending 32 (transit_mask cosine)") flatten_lc1, trend_lc1 = flatten( time, flux, method="cosine", window_length=0.4, return_trend=True, robust=True, mask=mask, ) numpy.testing.assert_almost_equal( numpy.nansum(flatten_lc1), 18119.281265446625, decimal=1 ) print("Detrending 33 (transit_mask lowess)") flatten_lc2, trend_lc2 = flatten( time, flux, method="lowess", window_length=0.8, return_trend=True, robust=True, mask=mask, ) # print(numpy.nansum(flatten_lc2)) numpy.testing.assert_almost_equal( numpy.nansum(flatten_lc2), 18119.30865711536, decimal=1 ) print("Detrending 34 (transit_mask GP)") mask = transit_mask(time=time[:2000], period=100, duration=0.3, T0=1327.4) flatten_lc2, trend_lc2 = flatten( time[:2000], flux[:2000], method="gp", kernel="matern", kernel_size=0.8, return_trend=True, robust=True, mask=mask, ) # print(numpy.nansum(flatten_lc2)) numpy.testing.assert_almost_equal( numpy.nansum(flatten_lc2), 1948.9000170463796, decimal=1 ) print("Detrending 35 (pspline full features)") flatten_lc, trend_lc, nsplines = flatten( time, flux, method="pspline", max_splines=100, edge_cutoff=0.5, return_trend=True, return_nsplines=True, verbose=True, ) # print('lightcurve was split into', len(nsplines), 'segments') # print('chosen number of splines', nsplines) """ import matplotlib.pyplot as plt plt.scatter(time, flux, s=3, color='black') plt.plot(time, trend_lc) plt.show() plt.scatter(time, flatten_lc, s=3, color='black') plt.show() """ numpy.testing.assert_almost_equal( numpy.nansum(flatten_lc), 16678.312693036027, decimal=1 ) print("Detrending 36 (pspline variable PSPLINES_STDEV_CUT)") flatten_lc, trend_lc, nsplines = flatten( time, flux, method="pspline", max_splines=100, edge_cutoff=0.5, stdev_cut=3, return_trend=True, return_nsplines=True, verbose=True, ) numpy.testing.assert_almost_equal( numpy.nansum(flatten_lc), 16678.292210380347, decimal=2 ) """ import matplotlib.pyplot as plt plt.scatter(time, flux, s=1, color='black') plt.plot(time, trend_lc, color='red', linewidth=2, linestyle='dashed') plt.show() plt.close() """ print("All tests completed.")
cumulative_residuals = np.full(len(lc_time), np.nan) residual_calculation = np.full((len(model_samples), len(lc_time)), np.nan) depth_calculation = np.full((len(model_samples), len(lc_time)), np.nan) for model_index, model_sample in enumerate(model_samples): model_duration_days = duration_grid[model_index] * cadence / 60 / 24 first_valid_time = lc_time[lc_time > lc_time[0] + model_duration_days * 3][0] time_without_tail = lc_time[lc_time < lc_time[len(lc_time) - 1] - model_duration_days * 3] last_valid_time = time_without_tail[len(time_without_tail) - 1] first_valid_time = lc_time[0] last_valid_time = lc_time[len(lc_time) - 1 - len(model_sample)] dt_flux = wotan.flatten(lc_time, flux, model_duration_days * 4, method="biweight") dt_flux = flux for flux_index, flux_value in enumerate( lc_time[(lc_time >= first_valid_time) & (lc_time <= last_valid_time)]): residual, depth = calculate_residuals(lc_time, dt_flux, model_sample, flux_index) residual_calculation[model_index][flux_index] = residual depth_calculation[model_index][flux_index] = depth local_residual_minima = argrelextrema(residual_calculation[model_index], np.less)[0] minima_mask = np.full(len(residual_calculation[model_index]), False) minima_mask[local_residual_minima] = True max_allowed_residual = np.nanmax(residual_calculation[model_index]) residual_calculation[model_index][np.where(
def flatten(lc, t0=None, period=None, duration=1. / 24., window_length=3. / 24., **kwargs): """ Flatten a light curve using the `wotan` package. Parameters ---------- lc : `~lightkurve.LightCurve` A light curve object with the data. t0 : float or iterable, optional Mid-transit time of transit signal(s) to mask. period : float or iterable, optional Period of transit signal(s) to mask. duration : float, optional Duration of transit signal to mask. Defaults to 1 hr. window_length : float, optional Length of the filter window for `wotan.flatten()`. Defaults to 3 hr. kwargs : dict, optional Any extra keyword arguments to pass to `wotan.flatten()`. Returns ------- lc : `~lightkurve.LightCurve` A light curve object with the flattened light curve. trend : ndarray The removed flux trend. Only returned if ``return_trend`` is `True`. """ # Mask transits if any ephemerides are given mask = np.zeros_like(lc.time, dtype=bool) if t0 is not None: t0s = np.array(t0).flatten() periods = np.array(period).flatten() for t0, period in zip(t0s, periods): mask += wotan.transit_mask(time=lc.time, T0=t0, period=period, duration=duration) # Flatten the light curve flux_flat = wotan.flatten(lc.time, lc.flux, window_length=window_length, mask=mask, **kwargs) # Return trend if return_trend=True return_trend = False if isinstance(flux_flat, tuple): return_trend = True flux_flat, trend = flux_flat lcflat = lc.copy() lcflat.flux = flux_flat if return_trend: return (lcflat, trend) else: return lcflat
def detrend_lightcurve_wotan(data, window_length=0.25, iscdips=True): #NOTE: junky. doesnt work. # try two simple harmonic oscillators with periods separated by a factor of # two... if iscdips: sector_data = data[0] time = sector_data['TMID_BJD'] flux = vp._given_mag_get_flux(sector_data['IRM1']) else: d = data[0] time = d['TIME'] flux = d['PDCSAP_FLUX'] / np.nanmedian(d['PDCSAP_FLUX']) from wotan import flatten _, trend_lc2 = flatten( time, # Array of time values flux, # Array of flux values method='biweight', robust=True, # Iteratively clip 2-sigma outliers until convergence window_length= window_length, # The length of the filter window in units of ``time`` break_tolerance=0.5, # Split into segments at breaks longer than that return_trend=True, # Return trend and flattened light curve ) if window_length == 99: trend_lc2 = np.ones_like(flux) * np.nanmedian(flux) # flatten_lc2, trend_lc2 = flatten( # time, # Array of time values # flux, # Array of flux values # method='gp', # kernel='periodic', # GP kernel choice # kernel_period=0.498818, # GP kernel period # kernel_size=50, # GP kernel length # break_tolerance=0.5, # Split into segments at breaks longer than # return_trend=True, # Return trend and flattened light curve # ) # plot! plt.close('all') if iscdips: f, axs = plt.subplots(nrows=2, ncols=1, figsize=(16, 7)) else: f, axs = plt.subplots(nrows=2, ncols=1, figsize=(32, 7)) axs[0].scatter(time, flux, c='k', s=5, zorder=2) axs[0].plot(time, trend_lc2, c='orange', lw=1, zorder=3) dtr_flux = flux - trend_lc2 sel = ~np.isnan(dtr_flux) axs[1].scatter(time[sel], dtr_flux[sel], c='k', s=5) axs[1].set_xlabel('time [bjdtdb]') axs[0].set_ylabel('IRM1 flux') axs[1].set_ylabel('residual') axs[0].set_title('biweight detrend, {}d'.format(window_length)) if not iscdips: axs[1].set_ylim([-0.1, 0.05]) if window_length == 99: axs[1].set_ylim([-0.1, 0.1]) isspoc = '' if iscdips else '_spoc2min' savpath = '../../results/quicklooklc/PTFO_8-8695/detrend_lc{}_{:.2f}d.png'.format( isspoc, window_length) f.savefig(savpath, dpi=300, bbox_inches='tight') print('made {}'.format(savpath)) if not iscdips: from transitleastsquares import transitleastsquares model = transitleastsquares( time[sel], 1 + dtr_flux[sel] + np.nanmedian(dtr_flux[sel])) results = model.power(period_min=0.3, period_max=0.6, M_star_min=0.1, M_star_max=5, R_star=0.5, M_star=0.5) print(42 * '-') print('t0: {}'.format(results.T0) + '\nperiod: {}'.format(results.period) + '\nperiod_unc: {}'.format(results.period_uncertainty)) print(42 * '-') plt.close('all') fig = plt.figure() ax = plt.gca() ax.axvline(results.period, alpha=0.4, lw=3) plt.xlim(np.min(results.periods), np.max(results.periods)) for n in range(2, 10): ax.axvline(n * results.period, alpha=0.4, lw=1, linestyle="dashed") ax.axvline(results.period / n, alpha=0.4, lw=1, linestyle="dashed") plt.ylabel(r'SDE') plt.xlabel('Period (days)') plt.plot(results.periods, results.power, color='black', lw=0.5) plt.xlim(0, max(results.periods)) savpath = '../../results/quicklooklc/PTFO_8-8695/detrend_lc{}_{:.2f}d_periodogram.png'.format( isspoc, window_length) fig.savefig(savpath, dpi=300, bbox_inches='tight') print('made {}'.format(savpath)) plt.close('all') fig = plt.figure() # plt.plot(results.model_folded_phase, results.model_folded_model, # color='orange', zorder=3) plt.scatter(results.folded_phase, results.folded_y, color='gray', s=2, alpha=0.8, zorder=4, linewidths=0) pd = phase_bin_magseries(results.folded_phase, results.folded_y, binsize=0.01) plt.scatter(pd['binnedphases'], pd['binnedmags'], color='black', s=8, alpha=1, zorder=5, linewidths=0) #plt.xlim(0.35, 0.65) rstr = '(on residual)' if window_length <= 0.2 else '(on raw)' plt.title('{} period {:.8f}d'.format(rstr, results.period)) plt.xlabel('Phase') plt.ylabel('Relative flux') plt.xticks([0, 0.25, 0.5, 0.75, 1]) plt.grid(which='major', axis='both', linestyle='--', zorder=-3, alpha=0.5, color='gray') pct_80 = np.percentile(results.model_folded_model, 80) pct_20 = np.percentile(results.model_folded_model, 20) center = np.nanmedian(results.model_folded_model) delta_y = (10 / 6) * np.abs(pct_80 - pct_20) plt.ylim((center - 0.7 * delta_y, center + 0.7 * delta_y)) savpath = '../../results/quicklooklc/PTFO_8-8695/detrend_lc{}_{:.2f}d_phasefold.png'.format( isspoc, window_length) fig.savefig(savpath, dpi=300, bbox_inches='tight') print('made {}'.format(savpath))
#::: 2) prepare data flux = sigma_clip(time, flux, high=3, low=20) flux = slide_clip(time, flux, high=3, low=20) flux = mask_regions(time, flux, regions=[(2458865.5, 2458866), (2458990, 2458990.5)]) tessplot(time, flux) #::: 3) estimate variability period period = estimate_period(time, flux, flux_err)[0] #::: 4) detrend data flux = slide_clip(time, flux, high=3, low=20) flux_flat, trend = flatten(time, flux, method='biweight', window_length=1, return_trend=True) tessplot(time, flux, trend=trend) tessplot(time, flux_flat) period = estimate_period(time, flux_flat, flux_err)[0] #::: 5) search transits kwargs = get_tls_kwargs_by_tic(tic_id) #390651552 #459837008 results_all, fig_all = tls_search(time, flux_flat, flux_err, plot=True, period_min=1, period_max=20, **kwargs)