def mask(time, flux, flux_err, period, duration, T0): intransit = transit_mask(time, period, duration, T0) time = time[~intransit] flux = flux[~intransit] if flux_err is not None: flux_err = flux_err[~intransit] time, flux, flux_err = cleaned_array(time, flux, flux_err) else: time, flux = cleaned_array(time, flux) return time, flux, flux_err
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 loadfile(EPIC_id): star = everest.Everest(EPIC_id) t = numpy.delete(star.time, star.badmask) y = numpy.delete(star.fcor, star.badmask) t = numpy.array(t[~numpy.isnan(y)], dtype='float32') y = numpy.array(y[~numpy.isnan(y)], dtype='float32') return cleaned_array(t, y)
def loadkoi(koi): print('Getting LC for KOI', koi) client = kplr.API() koi = client.koi(koi) lcs = koi.get_light_curves(short_cadence=False) # Loop over the datasets and read in the data time, flux, ferr, quality = [], [], [], [] for lc in lcs: with lc.open() as f: # The lightcurve data are in the first FITS HDU hdu_data = f[1].data time.append(hdu_data["time"]) flux_segment = hdu_data["pdcsap_flux"] quality.append(hdu_data["sap_quality"]) # Normalize each segment by its median flux_segment = flux_segment / numpy.nanmedian(flux_segment) flux.append(flux_segment.tolist()) time = numpy.hstack(time) flux = numpy.hstack(flux) # Reject data points of non-zero quality quality = numpy.hstack(quality) m = numpy.any(numpy.isfinite(flux)) & (quality == 0) time = time[m] flux = flux[m] time, flux = cleaned_array(time, flux) print('Data points:', len(time)) return time, flux
def add_mask(time_i, flatten_i, results_pdcsap, periods, durations, tos, a): if results_pdcsap.snr > SNR[a]: intransit = transit_mask(time_i, results_pdcsap.period, 2 * results_pdcsap.duration, results_pdcsap.T0) else: intransit = transit_mask(time_i, periods[a], 2 * durations[a], tos[a]) flatten_i[intransit] = np.nan time_j, flatten_j = cleaned_array(time_i, flatten_i) return time_j, flatten_j
def load_file(filename): """Loads a TESS *spoc* FITS file and returns cleaned arrays TIME, PDCSAP_FLUX""" print(filename) hdu = fits.open(filename) t = hdu[1].data['TIME'] y = hdu[1].data[ 'PDCSAP_FLUX'] # values with non-zero quality are nan or zero'ed #y = hdu[1].data['FLUX'] # values with non-zero quality are nan or zero'ed #t = t[64:] #y = y[64:] #t = t[:-64] #y = y[:-64] t, y = cleaned_array( t, y) # remove invalid values such as nan, inf, non, negative print('Time series from', format(min(t), '.1f'), 'to', format(max(t), '.1f'), 'with a duration of', format(max(t) - min(t), '.1f'), 'days') return t, y, hdu[0].header['TICID'] # filename[36:45] "trappist"
def seach_one_koi(KOI): # Check if vetting file exists already figure_out_path = '_FAIL0-5d_' + str(KOI) figure_out_path2 = 'GOOD0-5d_' + str(KOI) if figure_out_path in " ".join( glob.glob("*.png")) or figure_out_path2 in " ".join( glob.glob("*.png")): print('Vetting sheet for this KOI exists already, skipping KOI', KOI) else: print('Working on file', KOI) time, flux = loadkoi(str(KOI)) row = numpy.argmax(catalog["KOI"].astype(int) == int(float(KOI))) KIC = catalog["KIC"][row] print('row', row) print('KIC', KIC) max_t14 = T14(R_s=catalog["R_star"][row], M_s=catalog["mass"][row], P=period_max) window = 3 * max_t14 print('R_star, mass, max_t14, window', catalog["R_star"][row], catalog["mass"][row], max_t14, window) if time is not None: # Remove known planets periods, t0s, tdurs = get_planets(KIC) print('periods', periods) for no in range(len(periods)): print('Removing planet', no + 1, periods[no], t0s[no], tdurs[no]) intransit = transit_mask(time, periods[no], 2 * tdurs[no], t0s[no]) flux = flux[~intransit] time = time[~intransit] time, flux = cleaned_array(time, flux) print('Next planet is number', no + 2) # Detrend data and remove high outliers print('Detrending with window...', window) #print(time) #print(flux) trend1 = trend(time, flux, window=window, c=5) #plt.scatter(time, flux, s=1, color='black') #plt.plot(time, trend1, color='red') #plt.show() #trend = scipy.signal.medfilt(flux, 31) #trend = scipy.signal.savgol_filter(trend, 25, 2) rawflux = flux.copy() rawtime = time.copy() y_filt = flux / trend1 y_filt = sigma_clip(y_filt, sigma_upper=3, sigma_lower=1e10) time, y_filt = cleaned_array(time, y_filt) #plt.close() #plt.scatter(time, y_filt, s=1, color='black') #plt.show() a = catalog["ld1"][row] b = catalog["ld2"][row] print('LD ab = ', a, b) try: model = transitleastsquares(time, y_filt) results = model.power( #n_transits_min=1, u=(a, b), R_star=catalog["R_star"][row], R_star_max=catalog["R_star"][row] + 2 * catalog["rad_up"][row], # sign is OK, is negative in catalog: R_star_min=catalog["R_star"][row] + 2 * catalog["rad_down"][row], M_star=catalog["mass"][row], M_star_max=catalog["mass"][row] + 2 * catalog["mass_up"][row], M_star_min=catalog["mass"][row] + 2 * catalog["mass_down"][row], oversampling_factor=5, duration_grid_step=1.05, use_threads=1, period_min=period_min, period_max=period_max, show_progress_bar=False, T0_fit_margin=0.1) tls_worked = True #except ValueError: # tls_worked = False valid = True if tls_worked: # Check if phase space has gaps bins = numpy.linspace(0, 1, 100) digitized = numpy.digitize(results.folded_phase, bins) bin_means = [ results.folded_phase[digitized == i].mean() for i in range(1, len(bins)) ] #print('bin_means', bin_means) if numpy.isnan(bin_means).any(): print('Vetting fail! Phase bins contain NaNs') valid = False if results.distinct_transit_count == 1 and results.transit_count >= 2: valid = False print( 'Vetting fail! results.distinct_transit_count==1 and results.transit_count == 2' ) if results.distinct_transit_count == 2 and results.transit_count >= 3: valid = False print( 'Vetting fail! results.distinct_transit_count==2 and results.transit_count == 3' ) if results.SDE < 8: valid = False print('Vetting fail! results.SDE < 8', results.SDE) if results.snr < 7: valid = False print('Vetting fail! results.snr < 7', results.snr) upper_transit_depths = results.transit_depths + results.transit_depths_uncertainties if results.transit_count == 2 and max( upper_transit_depths) > 1: valid = False print('Vetting fail! 2 transits, only 1 significant') upper_transit_depths = results.transit_depths + results.transit_depths_uncertainties if results.transit_count == 3 and max( upper_transit_depths) > 1: valid = False print( 'Vetting fail! 3 transits, not all 3 significant') upper_transit_depths = results.transit_depths + results.transit_depths_uncertainties if results.transit_count == 4 and max( upper_transit_depths) > 1: valid = False print( 'Vetting fail! 4 transits, not all 4 significant') if results.depth < 0.95: valid = False print('Vetting fail! Transit depth < 0.95', results.depth) print('Signal detection efficiency (SDE):', format(results.SDE, '.1f')) print('SNR:', format(results.snr, '.1f')) print('Search completed') #if valid: print('Attempting figure...') make_figure(KOI=str(KOI), planet_number=no + 2, results=results, t=time, y=flux, y_filt=y_filt, trend=trend1, rawtime=rawtime, rawflux=rawflux, catalog=catalog, row=row, valid=valid) #else: # print('No figure made, vetting failed!') else: print('TLS failed') process = psutil.Process(os.getpid()) ram_mb = process.memory_info().rss / 2**20 print('RAM (MB)', ram_mb) if ram_mb > 25000: sys.exit() except: pass
def tls_search(*args, tic=None, shape='default', star_params=None, rms_calc=True, norm_val=1., clean_lc=False, starparams_out=False, del_dur=1., verbose=False, nthreads=6, **kwargs): #!!Change if flux_err is all nans to replace it with rms flux_err!! """ Function to perform a search for periodic signals using the Transit Least Squares (TLS) algorithm developed by Hippke & Heller 2018. While slower than Box Least Squares, the transit shape used in the search is more realistic. Parameters ---------- *args : `lightkurve.LightCurve` object or multiple numpy array arguments If the len = 1, then the argument is assumed to be a `lightkurve.LightCurve` object with at least two columns, labeled ``'time'`` and ``'flux'``, respectively, with an optional ``'flux_err'`` column as the third column. If the len of > 1, then it is assumed the user is passing ``time``, ``flux``, and ``flux_err`` (optional), respectively. These columns or arguments should be arrays of equal length. tic : int or None TIC ID of the source that the light curve comes from. This will be used to query the TIC for the stellar parameters of the system. May be set to ``None`` if a full dictionary of stellar params are provided to the ``star_params`` keyword. shape : str The shape used by TLS to search for periodic signals. The user may specify ``'default'``, ``'grazing'``, or ``'box'``. See Hippke & Heller 2018 for an in-depth description of these shapes. star_params : dict or None A dictionary containing stellar parameters to be used in the TLS search. The dictionary can contain an array of limb-darkening parameters, stellar radius, lower radius error, upper radius error, stellar mass, lower mass error, and upper mass error labeled ``'ab'``, ``'rstar'``, ``'rlow'``, ``'rhigh'``, ``'mstar'``, ``'mlow'``, and ``'mhigh'``, respectively. The error values are the errors themselves and not the upper and lower values for each of the parameters. A partial list may be included, but in this case, the TIC must also be given. rms_calc : bool A flag to denote whether the root mean square error will be applied in the case that error values are not provided. norm_val : float Value that the light curve is normalized to. Default is 1. Only 1 or 0 are valid normalizations for TLS. clean_lc : bool Flag to indicate whether or not to output a cleaned lightcurve with the recovered periodic signal masked out. Results in an additional expected output. Default ``False``. starparams_out : bool Flag to indicate whether or not to output the dictionary of stellar parameters used in the TLS search. Results in an additional expected output. del_dur : float How many durations worth of data points should be excluded from cleaned light curve centered on the transit center. Default is 1. Values < 1 will result in some in-transit points remaining while values > 1 will remove some points outside the transit. verbose : bool Flag to have function print more while it runs. nthreads : int Number of threads to be used for running the signal search. Many times, cores have the capability to run multiple threads, so be sure to check your machine to optimize this parameter. **kwargs : dict Optional arguments passed to the ``transitleastsquares.power`` function. Returns ------- results : dict Results of the TLS fit. See TLS documentation for the contents of this dictionary and descriptions of each element. cleaned_lc : ``lightkurve.LightCurve`` object, optional A light curve with the transits masked out based on the results of the TLS search. """ dy = None #processing inputs if not tic and (not star_params or len(star_params) != 7): raise ValueError('Either tic or full star_params dictionary must' + ' be given!') if len(args) == 1: lc = args[0] time = lc.time flux = lc.flux try: if lc.flux_err is None: print('No flux errors provided') else: dy = lc.flux_err except: print('No flux errors provided') elif len(args) > 1: time = args[0] flux = args[1] if len(args) == 3: if args[2] is not None: dy = args[2] else: print('No flux_errors provided') else: print('No flux errors provided') if rms_calc == True and not isinstance(dy, np.ndarray): dy = np.ones(len(flux)) * rms(flux, norm_val=norm_val) print('RMS will be used for errors') #get catalog info and/or parse user-provided values if tic and (not star_params or len(star_params) != 7): print(f'Gathering stellar params that were not provided...', end='\r') ab, R_star, R_star_lowe, R_star_highe, M_star, M_star_lowe, M_star_highe = tls.catalog_info(TIC_ID=int(tic)) cat = {'ab' : ab, 'rstar' : R_star, 'rlow' : R_star_lowe, 'rhigh' : R_star_highe, 'mstar' : M_star, 'mlow' : M_star_lowe, 'mhigh' : M_star_highe} if not star_params: star_params = {} missing = list(set(cat) - set(star_params)) star_params.update({k: cat[k] for k in missing}) print('Gathering stellar params that were not provided... Done!') #quality control for stellar params dc = star_params dc['rstar'] = 1.0 if math.isnan(dc['rstar']) else dc['rstar'] dc['mstar'] = 1.0 if math.isnan(dc['mstar']) else dc['mstar'] dc['mlow'] = 0.1 if math.isnan(dc['mlow']) else dc['mlow'] dc['mhigh'] = 0.1 if math.isnan(dc['mhigh']) else dc['mhigh'] dc['rlow'] = 0.1 if math.isnan(dc['rlow']) else dc['rlow'] dc['rhigh'] = 0.1 if math.isnan(dc['rhigh']) else dc['rhigh'] rmax = dc['rstar'] + dc['rhigh'] rmin = dc['rstar'] - dc['rlow'] mmax = dc['mstar'] + dc['mhigh'] mmin = dc['mstar'] - dc['mlow'] if verbose: print('Stellar params used:') for i in list(dc.keys()): print(str(i) + ' = ' + str(dc[i])) print('(defaults are solar and 0.1 for errors)') #beginning TLS search print('Searching using TLS using %s shape...' % shape) model = tls.transitleastsquares(t=time, y=flux, dy=dy) results = model.power(R_star=dc['rstar'], R_star_min=rmin, R_star_max=rmax, M_star=dc['mstar'], M_star_min=mmin, M_star_max=mmax, u=dc['ab'], transit_template=shape, use_threads=nthreads, **kwargs) #cleaning light curve if clean_lc flag if clean_lc: intransit = tls.transit_mask(time, results.period, del_dur * results.duration, results.T0) time2 = time[~intransit] flux2 = flux[~intransit] dy2 = dy[~intransit] time2, flux2, dy2 = tls.cleaned_array(time2, flux2, dy2) lc_clean = LightCurve(time=time2, flux=flux2, flux_err=dy2) if clean_lc and not starparams_out: return results, lc_clean elif not clean_lc and starparams_out: return results, dc elif clean_lc and starparams_out: return results, lc_clean, dc else: return results
def seach_one_koi(KOI): print('Working on file', KOI) time, flux = loadkoi(str(KOI)) #KOI = 1206.01 #print(catalog["KOI"]) #catalog_KOIs = #catalog_KOIs = round(catalog_KOIs, 0) #print(catalog_KOIs) #print(int(float(KOI))) #print(catalog["KOI"].astype(int)[:20]) row = numpy.argmax(catalog["KOI"].astype(int) == int(float(KOI))) KIC = catalog["KIC"][row] print('row', row) print('KIC', KIC) max_t14 = T14(R_s=catalog["R_star"][row], M_s=catalog["mass"][row], P=period_max) window = 3 * max_t14 print('R_star, mass, max_t14, window', catalog["R_star"][row], catalog["mass"][row], max_t14, window) #"KIC","KOI","KepName","Period","T0","T14","ld1","ld2","R_star","rad_up","rad_down","mass","mass_up","mass_down" #10337517,1165.01,,7.053934488,136.357253,0.07185,0.1959,0.5086,0.863,0.073,-0.065,0.854,0.054,-0.045 #plt.scatter(time, flux, s=1) #plt.show() #print(time) #print(flux) if time is not None: # Remove known planets periods, t0s, tdurs = get_planets(KIC) print('periods', periods) for no in range(len(periods)): print('Removing planet', no + 1, periods[no], t0s[no], tdurs[no]) intransit = transit_mask(time, periods[no], 2 * tdurs[no], t0s[no]) flux = flux[~intransit] time = time[~intransit] time, flux = cleaned_array(time, flux) print('Next planet is number', no + 2) # Detrend data and remove high outliers print('Detrending...') #print(time) #print(flux) trend1 = trend(time, flux, window=window, c=5) #plt.scatter(time, flux, s=1, color='black') #plt.plot(time, trend1, color='red') #plt.show() #trend = scipy.signal.medfilt(flux, 31) #trend = scipy.signal.savgol_filter(trend, 25, 2) rawflux = flux.copy() rawtime = time.copy() y_filt = flux / trend1 y_filt = sigma_clip(y_filt, sigma_upper=3, sigma_lower=1e10) time, y_filt = cleaned_array(time, y_filt) #plt.close() #plt.scatter(time, y_filt, s=1, color='black') #plt.show() a = catalog["ld1"][row] b = catalog["ld2"][row] print('LD ab = ', a, b) model = transitleastsquares(time, y_filt) results = model.power( #n_transits_min=1, u=(a, b), R_star=catalog["R_star"][row], R_star_max=catalog["R_star"][row] + 2 * catalog["rad_up"][row], # sign is OK, is negative in catalog: R_star_min=catalog["R_star"][row] + 2 * catalog["rad_down"][row], M_star=catalog["mass"][row], M_star_max=catalog["mass"][row] + 2 * catalog["mass_up"][row], M_star_min=catalog["mass"][row] + 2 * catalog["mass_down"][row], oversampling_factor=5, duration_grid_step=1.05, use_threads=1, #period_min=4.9, #period_max=5.0, show_progress_bar=False, period_max=period_max, T0_fit_margin=0.1) tls_worked = True #except ValueError: # tls_worked = False valid = True if tls_worked: # Check if phase space has gaps bins = numpy.linspace(0, 1, 100) digitized = numpy.digitize(results.folded_phase, bins) bin_means = [ results.folded_phase[digitized == i].mean() for i in range(1, len(bins)) ] #print('bin_means', bin_means) if numpy.isnan(bin_means).any(): print('Vetting fail! Phase bins contain NaNs') valid = False if results.distinct_transit_count == 1 and results.transit_count >= 2: valid = False print( 'Vetting fail! results.distinct_transit_count==1 and results.transit_count == 2' ) if results.distinct_transit_count == 2 and results.transit_count >= 3: valid = False print( 'Vetting fail! results.distinct_transit_count==2 and results.transit_count == 3' ) if results.SDE < 8: valid = False print('Vetting fail! results.SDE < 8', results.SDE) if results.snr < 7: valid = False print('Vetting fail! results.snr < 7', results.snr) upper_transit_depths = results.transit_depths + results.transit_depths_uncertainties if results.transit_count == 2 and max(upper_transit_depths) > 1: valid = False print('Vetting fail! 2 transits, only 1 significant') upper_transit_depths = results.transit_depths + results.transit_depths_uncertainties if results.transit_count == 3 and max(upper_transit_depths) > 1: valid = False print('Vetting fail! 3 transits, not all 3 significant') upper_transit_depths = results.transit_depths + results.transit_depths_uncertainties if results.transit_count == 4 and max(upper_transit_depths) > 1: valid = False print('Vetting fail! 4 transits, not all 4 significant') if results.depth < 0.95: valid = False print('Vetting fail! Transit depth < 0.95', results.depth) #if results.SDE > 9: # 9 print('Signal detection efficiency (SDE):', format(results.SDE, '.1f')) print('SNR:', format(results.snr, '.1f')) print('Search completed') # Make figure #ttime.sleep(1) #valid = True if valid: print('Valid result, attempting figure...') make_figure(KOI=str(KOI), planet_number=no + 2, results=results, t=time, y=flux, y_filt=y_filt, trend=trend1, rawtime=rawtime, rawflux=rawflux) #ttime.sleep(1) #print('Figure made') else: print('No figure made, vetting failed!') else: print('TLS failed') process = psutil.Process(os.getpid()) ram_mb = process.memory_info().rss / 2**20 print('RAM (MB)', ram_mb) if ram_mb > 25000: sys.exit()
from astropy.stats import sigma_clip import matplotlib.pyplot as plt from astropy.io import fits from astropy import units as u from transitleastsquares import cleaned_array if __name__ == "__main__": file = 'hlsp_tess-data-alerts_tess_phot_00012862099-s03_tess_v1_lc.fits' hdu = fits.open(file) t = hdu[1].data['TIME'] y = hdu[1].data['PDCSAP_FLUX'] t, y = cleaned_array(t, y) average_cadence = numpy.median(numpy.diff(t)) print('average_cadence (days)', average_cadence) y = sigma_clip(y, sigma_upper=10, sigma_lower=100) t, y = cleaned_array(t, y) window = 1 # day kernel = int(window / average_cadence) if kernel % 2 == 0: kernel = kernel + 1 print('kernel window (days)', window) print('kernel window (cadences)', kernel) from transitleastsquares.helpers import running_median y = y / numpy.mean(y)
def make_plot(days_ago, dates, mag): print('Making plot...') time_span = np.max(dates) - np.min(dates) min_plot = 0.0 max_plot = 2 x_days = -120 # Make daily bins nights = np.arange(0, 120, 1) daily_mags = [] errors = [] for night in nights: selector = np.where((days_ago < night + 1) & (days_ago > night)) n_obs = np.size(mag[selector]) flux = biweight_location(mag[selector]) error = np.std(mag[selector]) / np.sqrt(n_obs) if error > 0.75: error = 0 daily_mags.append(flux) errors.append(error) print(night, flux, error, n_obs, np.std(mag[selector])) nights_all = nights.copy() daily_mags_all = daily_mags.copy() errors_all = errors.copy() lookback = np.arange(1, 20, 1) for missing_days in lookback: nights = nights_all.copy()[missing_days:] daily_mags = daily_mags_all.copy()[missing_days:] errors = errors_all.copy()[missing_days:] plt.errorbar(-(nights + 0.5), daily_mags, yerr=errors, fmt='.k', alpha=0.5) plt.xlabel('Days from today') plt.ylabel('Visual magnitude') mid = biweight_location(mag) plt.ylim(min_plot, max_plot) plt.xlim(x_days, 120) plt.gca().invert_yaxis() date_text = datetime.datetime.now().strftime("%d %b %Y") plt.text(-x_days - 2, min_plot + 0.1, 'AAVSO visual (by-eye) daily bins', ha='right') plt.text(-x_days - 2, min_plot + 0.2, 'Gaussian process regression, Matern 3/2 kernel', ha='right') plt.text(-x_days - 2, min_plot + 0.3, '@betelbot update ' + date_text, ha='right') use_days = 30 - missing_days X = np.array(nights + 0.5) X = X[:use_days] y = np.array(daily_mags) y = y[:use_days] X, y = cleaned_array(X, y) length_scale = 1 kernel = ConstantKernel() + Matern( length_scale=length_scale, nu=3 / 2) + WhiteKernel(noise_level=1) X = X.reshape(-1, 1) gp = gaussian_process.GaussianProcessRegressor(kernel=kernel) gp.fit(X, y) GaussianProcessRegressor(alpha=1e-10, copy_X_train=True, kernel=1**2 + Matern(length_scale=length_scale, nu=1.5) + WhiteKernel(noise_level=1), n_restarts_optimizer=0, normalize_y=False, optimizer='fmin_l_bfgs_b', random_state=None) x_pred = np.linspace(30, -120, 250).reshape(-1, 1) y_pred, sigma = gp.predict(x_pred, return_std=True) plt.plot(-x_pred, y_pred, linestyle='dashed', color='blue') plt.fill_between(-x_pred.ravel(), y_pred + sigma, y_pred - sigma, alpha=0.5) idx = 20 - missing_days if idx < 10: filename = "0" + str(idx) + '.png' else: filename = str(idx) + '.png' plt.savefig(filename, bbox_inches='tight', dpi=100) print('Plot made', filename) plt.clf()
from __future__ import division, print_function import numpy from transitleastsquares import cleaned_array if __name__ == "__main__": print("Starting test: cleaned_array...", end="") dirty_array = numpy.ones(10, dtype=object) time_array = numpy.linspace(1, 10, 10) dy_array = numpy.ones(10, dtype=object) dirty_array[1] = None dirty_array[2] = numpy.inf dirty_array[3] = -numpy.inf dirty_array[4] = numpy.nan dirty_array[5] = -99 time_array[8] = numpy.nan dy_array[9] = numpy.inf t, y, dy = cleaned_array(time_array, dirty_array, dy_array) numpy.testing.assert_equal(t, [1, 7, 8]) numpy.testing.assert_equal(y, [1, 1, 1]) numpy.testing.assert_equal(dy, [1, 1, 1]) print("passed")
numpy.testing.assert_almost_equal(min(b), 0.99) numpy.testing.assert_almost_equal(max(b), 1.01) numpy.testing.assert_almost_equal(numpy.mean(b), 1) print('Test passed: Resampling') # Clean array test dirty_array = numpy.ones(10, dtype=object) time_array = numpy.linspace(1, 10, 10) dy_array = numpy.ones(10, dtype=object) dirty_array[1] = None dirty_array[2] = numpy.inf dirty_array[3] = -numpy.inf dirty_array[4] = numpy.nan dirty_array[5] = -99 t, y, dy = cleaned_array(time_array, dirty_array, dy_array) numpy.testing.assert_equal(len(t), 5) numpy.testing.assert_equal(numpy.sum(t), 35) numpy.testing.assert_equal(FAP(SDE=2), numpy.nan) numpy.testing.assert_equal(FAP(SDE=7), 0.009443778) numpy.testing.assert_equal(FAP(SDE=99), 8.0032e-05) print("Test passed: FAP table") periods = period_grid(R_star=1, M_star=1, time_span=0.1) # R_sun # M_sun # days numpy.testing.assert_almost_equal(max(periods), 2.4999999999999987) numpy.testing.assert_almost_equal(min(periods), 0.6002621413799498) numpy.testing.assert_equal(len(periods), 179) periods = period_grid(R_star=1, M_star=1,
def tls_search(time, flux, epoch, period, rplanet): SNR = 1e12 SNR_threshold = 5. 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) #::: search for the rest while (SNR >= SNR_threshold) and (FOUND_SIGNAL==False): logprint('\n====================================================================') model = transitleastsquares(time, flux) R_starx=rstar/u.R_sun #print(rstar_min/u.R_sun) #print(rstar_max/u.R_sun) #print(mstar/u.M_sun) #print(mstar_min/u.M_sun) #print(mstar_max/u.M_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=20, n_transits_min=1, show_progress_bar=False ) #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 if results.snr >= SNR_threshold: logprint('\nPeriod:', format(results.period, '.5f'), 'd') logprint(len(results.transit_times), 'transit times in time series:', ['{0:0.5f}'.format(i) for i in results.transit_times]) logprint('Transit depth:', format(1.-results.depth, '.5f')) logprint('Best duration (days):', format(results.duration, '.5f')) logprint('Signal detection efficiency (SDE):', results.SDE) logprint('Signal-to-noise ratio (SNR):', results.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: logprint('*** SUCCESFULLY FOUND THE TRANSIT ***') with open( os.path.join('tls_table/tls_table.csv'), 'a' ) as f: f.write(str(period)+','+str(rplanet/u.R_earth)+','+'1\n') FOUND_SIGNAL = True else: logprint('No other signals detected with SNR >= ' + str(SNR_threshold)) if FOUND_SIGNAL == False: logprint('*** FAILED FINDING THE TRANSIT ***') with open( os.path.join('tls_table/tls_table.csv'), 'a' ) as f: f.write(str(period)+','+str(rplanet)+','+'0\n') SNR = results.snr
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
names=["EPIC_id", "period", "t0", "tdur"]) rows = range(len(catalog["EPIC_id"])) for row in rows: EPIC_id = catalog["EPIC_id"][row] print('New planet EPIC_id', EPIC_id) time, flux = loadfile(EPIC_id) # Remove known planets periods, t0s, tdurs = get_planets(EPIC_id) for no in range(len(periods)): print('Removing planet', periods[no], t0s[no], tdurs[no]) intransit = transit_mask(time, periods[no], 2 * tdurs[no], t0s[no]) flux = flux[~intransit] time = time[~intransit] time, flux = cleaned_array(time, flux) # Detrend data and remove high outliers trend = scipy.signal.medfilt(flux, MEDIAN_KERNEL_WINDOW) flux = flux / trend flux = sigma_clip(flux, sigma_upper=3, sigma_lower=6) # Search flushed data for additional planets ab, mass, mass_min, mass_max, radius, radius_min, radius_max = catalog_info( EPIC_id) model = transitleastsquares(time, flux) results = model.power(n_transits_min=1, u=ab, oversampling_factor=5, duration_grid_step=1.05) print('Signal detection efficiency (SDE):', format(results.SDE, '.1f'))
def make_plot(days_ago, dates, mag): #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'} print('Making plot...') time_span = np.max(dates) - np.min(dates) min_plot = 0.0 max_plot = 2 x_days = -120 # Make daily bins nights = np.arange(0, 120, 1) daily_mags = [] errors = [] for night in nights: selector = np.where((days_ago < night + 1) & (days_ago > night)) n_obs = np.size(mag[selector]) flux = biweight_location(mag[selector]) error = np.std(mag[selector]) / np.sqrt(n_obs) if error > 0.75: error = 0 daily_mags.append(flux) errors.append(error) print(night, flux, error, n_obs, np.std(mag[selector])) nights_all = nights.copy() daily_mags_all = daily_mags.copy() errors_all = errors.copy() lookback = np.arange(1, 20, 1) for missing_days in lookback: nights = nights_all.copy()[missing_days:] daily_mags = daily_mags_all.copy()[missing_days:] errors = errors_all.copy()[missing_days:] plt.errorbar(-(nights + 0.5), daily_mags, yerr=errors, fmt='.k', alpha=0.5) plt.xlabel(u'从今天算起的天数', fontdict=fontcn) plt.ylabel(u'视星等', fontdict=fontcn) #plt.ylabel('视星等') mid = biweight_location(mag) plt.ylim(min_plot, max_plot) plt.xlim(-100, 100) plt.gca().invert_yaxis() date_text = datetime.datetime.now().strftime("%Y-%m-%d") plt.text(95, min_plot + 0.1, u'每日观测数据合成', ha='right', fontdict=fontcn) plt.text(60, min_plot + 0.2, u'由 天文通 译制于', ha='right', fontdict=fontcn) plt.text(95, min_plot + 0.2, date_text, ha='right', fontdict=fonten) use_days = 60 - missing_days X = np.array(nights + 0.5) X = X[:use_days] y = np.array(daily_mags) y = y[:use_days] X, y = cleaned_array(X, y) length_scale = 1 kernel = ConstantKernel() + Matern( length_scale=length_scale, nu=3 / 2) + WhiteKernel(noise_level=1) X = X.reshape(-1, 1) gp = gaussian_process.GaussianProcessRegressor(kernel=kernel) gp.fit(X, y) GaussianProcessRegressor(alpha=1e-10, copy_X_train=True, kernel=1**2 + Matern(length_scale=length_scale, nu=1.5) + WhiteKernel(noise_level=1), n_restarts_optimizer=0, normalize_y=False, optimizer='fmin_l_bfgs_b', random_state=None) x_pred = np.linspace(60, -120, 250).reshape(-1, 1) y_pred, sigma = gp.predict(x_pred, return_std=True) plt.plot(-x_pred, y_pred, linestyle='dashed', color='blue') plt.fill_between(-x_pred.ravel(), y_pred + sigma, y_pred - sigma, alpha=0.5) idx = 20 - missing_days if idx < 10: filename = "0" + str(idx) + '.png' else: filename = str(idx) + '.png' plt.savefig(filename, bbox_inches='tight', dpi=100) print('Plot made', filename) plt.clf()
def main(): # test higher: alles oder ohne low outlier? using "all, 3x": # 0.032 235037 mit ? # 0.1 140068425 mit # 0.1 14901 ohne low slight over # 0.1 100100827 ohne low slight under, ok # 0.1 7079 mit? # 0.1 2760710 mit # bad 0.01 1546 path = 'P:/P/Dok/tess_alarm/' #path = 'P:/P/Dok/k2fits/' #path = '/home/michael/Downloads/tess-data-alerts/' os.chdir(path) for file in glob.glob("*.fits"): #if "ktwo200164267-c12_llc" in file: if 1 == 1: converged = False t, y, TIC_ID = load_file(path + file) y = y / numpy.median(y) y = sigma_clip(y, sigma_lower=20, sigma_upper=3) t, y = cleaned_array(t, y) y_clipped = y.copy() #no_knots = 30 duration = max(t) - min(t) no_knots = int(duration / 0.75) print('no_knots', no_knots) #if no_knots > 50: # # print('Final run') #no_knots = no_knots#*3 while converged == False: y_detrended, trend = spline_detrender(t, y, no_knots) #y_detrended = sigma_clip(y_detrended, sigma_lower=10, sigma_upper=3) #t, y_detrended = cleaned_array(t, y_detrended) std = numpy.std(y_detrended) plt.figure() fig, axes = plt.subplots(5, 1, figsize=(6, 10)) ax = axes[0] #ax.plot(X[:, 0]-t.min(), y_clipped, 'o', ms=1, c='black', alpha=0.5) ax.plot(t - t.min(), y_clipped, 'o', ms=1, c='black', alpha=0.5) ax.plot(t - t.min(), trend, '--', lw=1, ms=1, color='red') ax.plot(t - t.min(), trend + std, '--', lw=1, ms=1, color='orange') ax.plot(t - t.min(), trend - std, '--', lw=1, ms=1, color='orange') ax.set_ylabel("Raw flux") ax = axes[1] ax.plot(t - t.min(), y_detrended, 'o', ms=1, c='black', alpha=0.5) ax.set_xlabel("Time (days)") ax.set_ylabel("Normalized flux") ax = axes[2] core_t = [] core_y = [] upper_cut = 1 + numpy.std(y_detrended) lower_cut = 1 - numpy.std(y_detrended) for i in range(len(y_detrended)): if y_detrended[i] < upper_cut and y_detrended[ i] > lower_cut: core_t.append(t[i]) core_y.append(y_detrended[i]) ax.plot(core_t - min(core_t), core_y, 'o', ms=1, c='black', alpha=0.5) ax = axes[3] period_grid = numpy.linspace(0.01, max(t) - min(t), 10000) frequency_grid = 1 / period_grid ls = LombScargle(core_t - min(core_t), core_y) power = ls.power(frequency_grid) #print(max(power)) if max(power) < 0.02: converged = True print('Fine, quitting. max(power)=', max(power)) else: print('no_knots old', no_knots) print('max(power)=', max(power)) no_knots = int(no_knots * 1.5) print('no_knots new', no_knots) if no_knots > 100: converged = True print('Quitting because no_knows > 100') ax.plot(1 / frequency_grid, power, color='black') #print(ls.false_alarm_probability(power.max())) #if max(power) > 0.05: #ls.false_alarm_probability(power.max()) < 0.05: # color='red' #else: # color='black' #text = "{:10.4f}".format(ls.false_alarm_probability(power.max())) ax.text(5, 0.04, str(no_knots), color='black') ax.plot((0, 20), (0.05, 0.05), color='red', linestyle='dashed') ax.set_ylim(0, 0.06) ax.set_xlabel("Period (days)") ax.set_ylabel("Power") #plt.show() ax = axes[4] #from scipy.stats import norm #x_d = np.linspace(-4, 8, 1000) #density = sum(norm(xi).pdf(x_d) for xi in y_detrended) #plt.fill_between(x_d, density, alpha=0.5) #plt.plot(y_detrended, np.full_like(y_detrended, -0.1), '|k', markeredgewidth=1) #bins = 50 from scipy.stats import norm import matplotlib.mlab as mlab #(mu, sigma) = norm.fit(y_detrended) n, bins, patches = ax.hist(y_detrended, int(len(t) / 200)) plt.plot((numpy.mean(y_detrended), numpy.mean(y_detrended)), (0, max(n)), color='orange') plt.plot( (numpy.median(y_detrended), numpy.median(y_detrended)), (0, max(n)), linestyle='dashed', color='red') #ax.plot(bins, mlab.normpdf(bins, mu, sigma), 'r--', linewidth=2) plt.savefig(str(TIC_ID) + ".png", bbox_inches='tight') plt.clf() plt.close('all')
def find_planets(time, raw_flux, cor_flux, campaign_no, star_id, provenance, summary_log, max_planets=1, plotno=1, interactive=False): """ Find one or more planet transits given input time, raw flux and corrected flux series. Save the results to the log files and display plots of light curves and folded light curves from TLS. Parameters ---------- time: numpy.ndarray Time series. raw_flux: numpy.ndarray Raw flux series. cor_flux: numpy.ndarray Corrected flux series. campaign_no: int, str Campaign number or "sequence number". Can be a wildcard character `'*'` to indicate that all campaigns should be searched. Used for logging. star_id: int, str EPIC ID of the star. Used for logging. provenance: str Provenance name in MAST archive, e.g., ``'K2'``, ``'EVEREST'``, ``'K2SFF'``. Used for logging. summary_log: file object File object of the summary log file with write access and initialized with appropriate column names. max_planets: int Maximum number of planets to find. plotno: int Plot number to be passed directly to `~matplotlib.pyplot.figure`. If `None`, a new figure will be created. interactive: bool Indicates whether or not to draw figures on screen. When ``interactive`` is `False`, figures are saved to files in the ``'Graphs/tls/'`` and ``'Graphs/lc/'`` sub-directories. Figure's file names will be constructed using the following pattern: ``star_id + '_' + provenance + '_tls.log'`` ``star_id + '_' + provenance + '_lc.log'`` """ planet_id = 1 while (max_planets and planet_id <= max_planets) or max_planets is None: lmask, umask = detect_outliers(cor_flux) # lmask indicates lower outliers and possible transits # umask indicates indicates outliers above the trend # remove upper outliers: umask = np.logical_not(umask) lmask = lmask[umask] time = time[umask] raw_flux = raw_flux[umask] cor_flux = cor_flux[umask] # "detrend" corrected flux: normalized_cor_flux, trend = normalize_lc(cor_flux, lmask) # run TLS: tls_results, valid = run_tls(time, normalized_cor_flux) if not valid: break # if the detection is significant, plot it and log it: if _calc_stats(tls_results): if isinstance(tls_results.transit_times, list): plot_lc(time, raw_flux, cor_flux, normalized_cor_flux, trend, star_id, planet_id, provenance, tls_results, interactive=interactive) plotno += 1 plot_tls(star_id, planet_id, provenance, plotno, tls_results, interactive=interactive) plotno += 1 log_results(star_id, planet_id, provenance, tls_results) append_summary_log(summary_log, star_id, campaign_no, planet_id, provenance, tls_results) # Remove detected transit and remove it from the data series: intransit = transit_mask(time, tls_results.period, 2 * tls_results.duration, tls_results.T0) raw_flux = raw_flux[~intransit] cor_flux = cor_flux[~intransit] time = time[~intransit] time, cor_flux = cleaned_array(time, cor_flux) planet_id += 1
44.00867236551441, decimal=5) numpy.testing.assert_almost_equal(min(results.power), -0.620153987656165, decimal=5) numpy.testing.assert_almost_equal(min(results.power_raw), -0.29015390864908414, decimal=5) print("Detrending of power spectrum from power_raw passed") # Mask of the first planet intransit = transit_mask(t, results.period, 2 * results.duration, results.T0) y_second_run = y_filt[~intransit] t_second_run = t[~intransit] t_second_run, y_second_run = cleaned_array(t_second_run, y_second_run) # Search for second planet model_second_run = transitleastsquares(t_second_run, y_second_run) results_second_run = model_second_run.power() numpy.testing.assert_almost_equal(results_second_run.duration, 0.1478628403227008, decimal=5) numpy.testing.assert_almost_equal(results_second_run.SDE, 34.98291056410117, decimal=5) numpy.testing.assert_almost_equal(results_second_run.rp_rs, 0.025852178872027086, decimal=5) print("Passed")
def mask(time, flux, period, duration, T0): intransit = transit_mask(time, period, duration, T0) time = time[~intransit] flux = flux[~intransit] time, flux = cleaned_array(time, flux) return time, flux