def get_LS(time, flux,freq): def get_hist(t, len_bin): ###将输入的time信息,按照len_bin的长度输出为lc t_test = t - t[0] a = [0 for i in range(int(t_test[-1] / len_bin) + 1)] for i in range(len(t_test)): a[int(t_test[i] / len_bin)] += 1 a = np.array(a) x = np.arange(bin_len / 2., (time[-1] - time[0]) + bin_len / 2., bin_len) y = flux LS = LombScargle(x, y,normalization = 'standard') # LS = LombScargle(x, y, dy, normalization='psd') power = LS.power(freq) FP=LS.false_alarm_probability(power.max(),samples_per_peak=5, nyquist_factor=5,minimum_frequency = freq[0], maximum_frequency = freq[-1],method='baluev') FP_99 = LS.false_alarm_level(0.01, samples_per_peak=10, nyquist_factor=5,minimum_frequency = freq[0], maximum_frequency = freq[-1],method='naive') FP_90 = LS.false_alarm_level(0.1, samples_per_peak=10, nyquist_factor=5, minimum_frequency=freq[0], maximum_frequency=freq[-1], method='naive') FP_68 = LS.false_alarm_level(0.32, samples_per_peak=10, nyquist_factor=5, minimum_frequency=freq[0], maximum_frequency=freq[-1], method='naive') plt.title('{0},FP={1}'.format('test',FP)) plt.plot(freq, power) print(1./freq[np.where(power==np.max(power))]) plt.plot([freq[0], freq[-1]], [FP_99, FP_99], '--') plt.plot([freq[0], freq[-1]], [FP_90, FP_90], '--') plt.plot([freq[0], freq[-1]], [FP_68, FP_68], '--') plt.show()
def periodogram(self): dt = [self.t[i + 1] - self.t[i - 1] for i in range(1, len(self.t) - 1)] fmax = 1.0 / np.median(dt) fmin = 2.0 / (max(self.t)) ls = LombScargle(self.t, self.flux, self.flux_err) #Oversampling a factor of 10 to achieve frequency resolution freq, power = ls.autopower(minimum_frequency=fmin, maximum_frequency=fmax, samples_per_peak=10) # Find the dominant peak best_f = freq[np.argmax(power)] period = 1.0 / best_f #period from the LS periodogram fap_p = ls.false_alarm_probability(power.max()) fap_001 = ls.false_alarm_level(0.01) if (period > 30.0): # Long periods are often spurious, search for a shorter minimum one # Calculates treshold using a running median every 2000 points mean_freq = avg_array(freq, 2000) mean_power = avg_array(power, 2000) treshold = np.interp(freq, mean_freq, mean_power) # Finds the period looking for the local maximum max_loc = np.argmax(power / treshold) best_f = freq[max_loc] period = 1.0 / best_f fap_p = ls.false_alarm_probability(power[max_loc]) fap_001 = ls.false_alarm_level(0.01) self.freq = np.array(freq) self.power = np.array(power) self.period = period self.fap_p = fap_p self.fap_001 = fap_001
def plot(self, periodogram=False): ncols = 2 if periodogram else 1 fig, axs = plt.subplots(3 + 1, ncols,) #sharex=False, sharey=False, # constrained_layout=True) axs = axs.ravel() if periodogram: indices_plots = np.arange(0, 8, 2) else: indices_plots = np.arange(0, 4) kw = dict(fmt='o', ms=3) axs[indices_plots[0]].errorbar(self.time, self.fullRV - self.fullRV.mean(), self.fullRVerror, color='k', **kw) axs[indices_plots[1]].errorbar(self.time, self.blueRV - self.blueRV.mean(), self._blueRVerror, color='b', **kw) axs[indices_plots[2]].errorbar(self.time, self.midRV - self.midRV.mean(), self._midRVerror, color='g', **kw) axs[indices_plots[3]].errorbar(self.time, self.redRV - self.redRV.mean(), self._redRVerror, color='r', **kw) if periodogram: from astropy.timeseries import LombScargle model = LombScargle(self.time, self.fullRV, self.fullRVerror) f, p = model.autopower() axs[1].semilogx(1 / f, p, color='k') axs[1].hlines(model.false_alarm_level([0.1, 0.01]), *axs[1].get_xlim(), alpha=0.2, ls='--') model = LombScargle(self.time, self.blueRV, self._blueRVerror) f, p = model.autopower() axs[3].semilogx(1 / f, p, color='b') axs[3].hlines(model.false_alarm_level([0.1, 0.01]), *axs[3].get_xlim(), alpha=0.2, ls='--') model = LombScargle(self.time, self.midRV, self._midRVerror) f, p = model.autopower() axs[5].semilogx(1 / f, p, color='g') axs[5].hlines(model.false_alarm_level([0.1, 0.01]), *axs[5].get_xlim(), alpha=0.2, ls='--') model = LombScargle(self.time, self.redRV, self._redRVerror) f, p = model.autopower() axs[7].semilogx(1 / f, p, color='r') axs[7].hlines(model.false_alarm_level([0.1, 0.01]), *axs[7].get_xlim(), alpha=0.2, ls='--') return fig, axs
def get_LS(time, flux, freq, outpath=None, outname=None, save=False, show=True): x = time y = flux LS = LombScargle(x, y, normalization='standard') power = LS.power(freq) max_NormLSP = np.max(power) period_peak = 1. / freq[np.where(power == np.max(power))][0] FP = LS.false_alarm_probability(power.max(), minimum_frequency=freq[0], maximum_frequency=freq[-1], method='baluev') FP_99 = LS.false_alarm_level(0.0027, minimum_frequency=freq[0], maximum_frequency=freq[-1], method='baluev') FP_95 = LS.false_alarm_level(0.05, minimum_frequency=freq[0], maximum_frequency=freq[-1], method='baluev') FP_68 = LS.false_alarm_level(0.32, minimum_frequency=freq[0], maximum_frequency=freq[-1], method='baluev') plt.figure(1, (6, 6)) # plt.title('Period={0:.2f}'.format(period_peak), font1) plt.text(freq[np.where(power == np.max(power))][0] * 1.3, max_NormLSP * 0.95, 'P={0:.2f}s'.format(period_peak), fontsize=18, fontweight='semibold') plt.plot(freq, power) plt.semilogx() out_period = 1. / freq[np.where(power == np.max(power))][0] plt.plot([freq[0], freq[-1]], [FP_99, FP_99], '--') plt.plot([freq[0], freq[-1]], [FP_95, FP_95], '--') plt.plot([freq[0], freq[-1]], [FP_68, FP_68], '--') plt.text(freq[0], FP_99, '1-FAP 99.73%', font1) plt.text(freq[0], FP_95, '95%', font1) plt.text(freq[0], FP_68, '68%', font1) plt.xlabel('Frequency (Hz)', font1) plt.ylabel('Normalized LS Periodogram', font1) plt.tick_params(labelsize=16) if save: plt.savefig(outpath + outname + '_LS.pdf', bbox_inches='tight', pad_inches=0.01) if show: plt.show() else: plt.close() return [FP, out_period, max_NormLSP]
def get_LS(time, flux, freq, outpath, outname, save=False, show=True): x = time y = flux LS = LombScargle(x, y, normalization='standard') # LS = LombScargle(x, y, normalization='psd') power = LS.power(freq) max_NormLSP = np.max(power) period_peak = 1. / freq[np.where(power == np.max(power))][0] FP = LS.false_alarm_probability(power.max(), minimum_frequency=freq[0], maximum_frequency=freq[-1], method='baluev') FP_99 = LS.false_alarm_level(0.0027, minimum_frequency=freq[0], maximum_frequency=freq[-1], method='baluev') FP_95 = LS.false_alarm_level(0.05, minimum_frequency=freq[0], maximum_frequency=freq[-1], method='baluev') FP_68 = LS.false_alarm_level(0.32, minimum_frequency=freq[0], maximum_frequency=freq[-1], method='baluev') # if FP<0.01:print(dataname) # plt.title('Epoch {2}: XID={0},FAP={1}'.format(dataname,np.round(FP,4),k),font1) plt.figure(1, (15, 6)) plt.title('Period={0:.2f}'.format(period_peak), font1) # plt.semilogx() # print(freq) plt.plot(freq, power) plt.semilogx() out_period = 1. / freq[np.where(power == np.max(power))][0] # plt.plot([1/period_peak,1/period_peak],[0,np.max(power)],'--') plt.plot([freq[0], freq[-1]], [FP_99, FP_99], '--') plt.plot([freq[0], freq[-1]], [FP_95, FP_95], '--') plt.plot([freq[0], freq[-1]], [FP_68, FP_68], '--') plt.text(freq[0], FP_99, '1-FAP 99.73%', font1) plt.text(freq[0], FP_95, '95%', font1) plt.text(freq[0], FP_68, '68%', font1) plt.xlabel('Frequency (Hz)', font1) plt.ylabel('Normalized LS Periodogram', font1) plt.tick_params(labelsize=16) # plt.show() if save: plt.savefig(outpath + outname + '.eps', bbox_inches='tight', pad_inches=0.0) if show: plt.show() else: plt.close() return [FP, out_period, max_NormLSP]
def get_LS(time, flux,freq,dataname,k,save=0,show=0): x = time y = flux # dy=np.sqrt(y) # plt.scatter(x,y) # plt.show() FP=1.0 LS = LombScargle(x, y,dy=None,normalization = 'standard') # print(len(freq)) # LS = LombScargle(x, y, normalization='psd') power = LS.power(freq) # print(power.max()) FP=LS.false_alarm_probability(power.max(),minimum_frequency = freq[0],maximum_frequency = freq[-1],method='naive') FP_99 = LS.false_alarm_level(0.0027,minimum_frequency = freq[0], maximum_frequency = freq[-1],method='naive') FP_95 = LS.false_alarm_level(0.05, minimum_frequency=freq[0], maximum_frequency=freq[-1], method='naive') FP_68 = LS.false_alarm_level(0.32,minimum_frequency=freq[0], maximum_frequency=freq[-1], method='naive') # if FP<0.01:print(dataname) plt.figure(1, (10, 8)) # plt.title('Epoch {2}: XID={0},FAP={1}'.format(dataname,np.round(FP,4),k),font1) plt.title('Epoch {1}: XID={0}'.format(dataname, k), font1) # plt.title('XID={0},FAP={1}'.format(dataname, np.round(FP, 4)), font1) # plt.semilogx() plt.plot(freq, power) # plt.plot([1/2492.73,1/2492.73],[0,np.max(power)],'--',linewidth=1) plt.semilogx() # plt.ylim(0,0.00012) print(1. / freq[np.where(power == np.max(power))]) # print(np.where(power == np.max(power))) # if FP<0.01:print(1./freq[np.where(power==np.max(power))]);print(np.where(power==np.max(power))) out_period=1./freq[np.where(power==np.max(power))] plt.plot([freq[0], freq[-1]], [FP_99, FP_99], '--') plt.plot([freq[0], freq[-1]], [FP_95, FP_95], '--') plt.plot([freq[0], freq[-1]], [FP_68, FP_68], '--') plt.text(freq[int(len(freq)*0.32)], FP_99, '1-FAP 99.73%',font1) plt.text(freq[int(len(freq)*0.7)], FP_95, '95%',font1) plt.text(freq[int(len(freq)*0.7)], FP_68, '68%',font1) plt.xlabel('Frequency (Hz)',font1) plt.ylabel('Normalized LS Periodogram',font1) plt.tick_params(labelsize=16) # plt.savefig(func.figurepath + '643_epoch4.pdf', bbox_inches='tight', pad_inches=0.0) if save: plt.savefig(func.figurepath+'{0}_epoch{1}.pdf'.format(dataname,k),bbox_inches='tight', pad_inches=0.0) if show: plt.show() else: plt.close() # plt.savefig('/Users/baotong/Desktop/CDFS/fig_LS_ep{0}_ovsamp_5_baluev/{1}_bin250.eps'.format(k,dataname)) # plt.savefig('/Users/baotong/Desktop/CDFS/fig_LS_ep{0}_samp_1_baluev/{1}_bin250.eps'.format(k,dataname)) # plt.close() return [FP,out_period]
def get_LS(time, flux, freq, dataname='default', outpath='/Users/baotong/Desktop/'): x = time y = flux # dy=np.sqrt(y) # plt.scatter(x,y) # plt.show() FP = 1.0 # LS = LombScargle(x, y, dy = 1, normalization = 'standard', fit_mean = True, # center_data = True).power(freq, method = 'cython') LS = LombScargle(x, y, normalization='standard') # LS = LombScargle(x, y, normalization='psd') power = LS.power(freq) FP = LS.false_alarm_probability(power.max(), minimum_frequency=freq[0], maximum_frequency=freq[-1], method='baluev') FP_99 = LS.false_alarm_level(0.01, minimum_frequency=freq[0], maximum_frequency=freq[-1], method='baluev') FP_95 = LS.false_alarm_level(0.05, minimum_frequency=freq[0], maximum_frequency=freq[-1], method='baluev') FP_68 = LS.false_alarm_level(0.32, minimum_frequency=freq[0], maximum_frequency=freq[-1], method='baluev') # # if FP<0.01:print(dataname) plt.title('{0},FP={1}'.format(dataname, FP)) # plt.semilogx() plt.plot(freq, power) plt.semilogx() # print(1. / freq[np.where(power == np.max(power))]) # print(np.where(power == np.max(power))) # if FP<0.01:print(1./freq[np.where(power==np.max(power))]);print(np.where(power==np.max(power))) out_period = 1. / freq[np.where(power == np.max(power))[0]] plt.plot([freq[0], freq[-1]], [FP_99, FP_99], '--') plt.plot([freq[0], freq[-1]], [FP_95, FP_95], '--') plt.plot([freq[0], freq[-1]], [FP_68, FP_68], '--') plt.text(freq[0], FP_99, '99%') plt.text(freq[0], FP_95, '95%') plt.text(freq[0], FP_68, '68%') plt.show() # plt.savefig(outpath+'{0}_15sec.eps'.format(dataname)) # plt.close() return [FP, out_period]
def APFAP(self, P): #FAP from LombScargle, not entierly accurate as I'd want because my LombScargle #returns worse estimations than theirs AstroLS = LombScargle(self.time, self.RV, self.Munc) FAP = AstroLS.false_alarm_level(P) return (FAP)
def get_LS(time, flux, error, freq): x = time y = flux dy = error FP = 1.0 LS = LombScargle(x, y, normalization='standard') # LS = LombScargle(x, y, normalization='psd') power = LS.power(freq) FP = LS.false_alarm_probability(power.max(), minimum_frequency=freq[0], maximum_frequency=freq[-1], method='baluev') FP_99 = LS.false_alarm_level(0.0027, minimum_frequency=freq[0], maximum_frequency=freq[-1], method='baluev') FP_95 = LS.false_alarm_level(0.05, minimum_frequency=freq[0], maximum_frequency=freq[-1], method='baluev') FP_68 = LS.false_alarm_level(0.32, minimum_frequency=freq[0], maximum_frequency=freq[-1], method='baluev') # if FP<0.01:print(dataname) plt.figure(1, (9, 6)) plt.title('Lomb-Scargle Periodogram') plt.plot(freq, power) plt.semilogx() # print(1. / freq[np.where(power == np.max(power))]) # print(np.where(power == np.max(power))) out_period = 1. / freq[np.where(power == np.max(power))] plt.plot([freq[0], freq[-1]], [FP_99, FP_99], '--') plt.plot([freq[0], freq[-1]], [FP_95, FP_95], '--') plt.plot([freq[0], freq[-1]], [FP_68, FP_68], '--') plt.text(freq[0], FP_99, '99%') plt.text(freq[0], FP_95, '95%') plt.text(freq[0], FP_68, '68%') plt.xlabel('Frequency (1/day)', font1) plt.ylabel('Normalized LSP', font1) plt.tick_params(labelsize=16) plt.show() return [FP, out_period]
def get_LS(time, flux, freq): ## Lomb-Scagrle周期图算法,参考VanderPlas J. T., 2018, ApJS, 236, 16 ## x = time y = flux plt.figure(1, (9, 6)) # LS = LombScargle(x, y, dy = 1, normalization = 'standard', fit_mean = True, # center_data = True).power(freq, method = 'cython') LS = LombScargle(x, y, normalization='standard') power = LS.power(freq) FP = LS.false_alarm_probability(power.max(), minimum_frequency=freq[0], maximum_frequency=freq[-1], method='baluev') FP_99 = LS.false_alarm_level(0.0027, minimum_frequency=freq[0], maximum_frequency=freq[-1], method='baluev') FP_90 = LS.false_alarm_level(0.05, minimum_frequency=freq[0], maximum_frequency=freq[-1], method='baluev') FP_68 = LS.false_alarm_level(0.32, minimum_frequency=freq[0], maximum_frequency=freq[-1], method='baluev') plt.plot([freq[0], freq[-1]], [FP_99, FP_99], '--') plt.plot([freq[0], freq[-1]], [FP_90, FP_90], '--') plt.plot([freq[0], freq[-1]], [FP_68, FP_68], '--') plt.title('FP={0}'.format(FP), font1) plt.semilogx() plt.xlabel('frequency (Hz)') plt.ylabel('Normalized Lomb-Scargle power') plt.plot(freq, power) print(1. / freq[np.where(power == np.max(power))]) plt.xlabel('frequency', font1) plt.ylabel('normalized LSP', font1) plt.tick_params(labelsize=16) plt.show() res = 1e5 * power res = np.round(res, 2) return [ FP, 1. / freq[np.where(power == np.max(power))], np.max(power), res ]
def get_LS(time, flux, freq): x = time y = flux # LS = LombScargle(x, y, dy = 1, normalization = 'standard', fit_mean = True, # center_data = True).power(freq, method = 'cython') LS = LombScargle(x, y, normalization='standard') FP = 0 power = LS.power(freq) FP = LS.false_alarm_probability(power.max(), minimum_frequency=freq[0], maximum_frequency=freq[-1], method='baluev') FP_99 = LS.false_alarm_level(0.0027, minimum_frequency=freq[0], maximum_frequency=freq[-1], method='baluev') FP_90 = LS.false_alarm_level(0.05, minimum_frequency=freq[0], maximum_frequency=freq[-1], method='baluev') FP_68 = LS.false_alarm_level(0.32, minimum_frequency=freq[0], maximum_frequency=freq[-1], method='baluev') plt.figure(1, (9, 6)) plt.plot([freq[0], freq[-1]], [FP_99, FP_99], '--') plt.plot([freq[0], freq[-1]], [FP_90, FP_90], '--') plt.plot([freq[0], freq[-1]], [FP_68, FP_68], '--') # plt.plot([1 /950.7, 1 / 950.7], [0, np.max(power)], '--', linewidth=1) plt.title('FP={0}'.format(FP)) plt.semilogx() # plt.xlim(1000.,1500.) plt.plot(freq, power) print(1. / freq[np.where(power == np.max(power))]) plt.show() res = 1e5 * power res = np.round(res, 2) return [ FP, 1. / freq[np.where(power == np.max(power))], np.max(power), res ]
def get_LS(time, flux, freq): x = time y = flux LS = LombScargle(x, y, normalization='standard') # LS = LombScargle(x, y, normalization='psd') power = LS.power(freq) max_NormLSP = np.max(power) FP = LS.false_alarm_probability(power.max(), minimum_frequency=freq[0], maximum_frequency=freq[-1], method='baluev') FP_99 = LS.false_alarm_level(0.0027, minimum_frequency=freq[0], maximum_frequency=freq[-1], method='baluev') FP_95 = LS.false_alarm_level(0.05, minimum_frequency=freq[0], maximum_frequency=freq[-1], method='baluev') FP_68 = LS.false_alarm_level(0.32, minimum_frequency=freq[0], maximum_frequency=freq[-1], method='baluev') # if FP<0.01:print(dataname) # plt.title('Epoch {2}: XID={0},FAP={1}'.format(dataname,np.round(FP,4),k),font1) # plt.semilogx() plt.plot(freq, power) plt.semilogx() out_period = 1. / freq[np.where(power == np.max(power))][0] plt.plot([freq[0], freq[-1]], [FP_99, FP_99], '--') plt.plot([freq[0], freq[-1]], [FP_95, FP_95], '--') plt.plot([freq[0], freq[-1]], [FP_68, FP_68], '--') plt.text(freq[0], FP_99, '1-FAP 99%', font1) plt.text(freq[0], FP_95, '95%', font1) plt.text(freq[0], FP_68, '68%', font1) plt.xlabel('Frequency (Hz)', font1) plt.ylabel('Normalized LS Periodogram', font1) plt.tick_params(labelsize=16) # plt.show() # plt.savefig('/Users/baotong/Desktop/CDFS/fig_LS_ep{0}_ovsamp_5_baluev/{1}.eps'.format(k,dataname)) plt.close() return [FP, out_period, max_NormLSP]
def get_LS(time, flux,freq,dataname,k): x = time y = flux # dy=np.sqrt(y) # plt.scatter(x,y) # plt.show() FP=1.0 LS = LombScargle(x, y,dy=None,normalization = 'standard') # print(len(freq)) # LS = LombScargle(x, y, normalization='psd') power = LS.power(freq) # print(power.max()) FP=LS.false_alarm_probability(power.max(),minimum_frequency = freq[0],maximum_frequency = freq[-1],method='baluev') FP_99 = LS.false_alarm_level(0.01,minimum_frequency = freq[0], maximum_frequency = freq[-1],method='baluev') FP_95 = LS.false_alarm_level(0.05, minimum_frequency=freq[0], maximum_frequency=freq[-1], method='baluev') FP_68 = LS.false_alarm_level(0.32,minimum_frequency=freq[0], maximum_frequency=freq[-1], method='baluev') # if FP<0.01:print(dataname) plt.title('Epoch {2}: XID={0},FAP={1}'.format(dataname,np.round(FP,4),k),font1) # plt.semilogx() plt.plot(freq, power) # plt.plot([1/2492.73,1/2492.73],[0,np.max(power)],'--',linewidth=1) plt.semilogx() print(1. / freq[np.where(power == np.max(power))]) # print(np.where(power == np.max(power))) # if FP<0.01:print(1./freq[np.where(power==np.max(power))]);print(np.where(power==np.max(power))) out_period=1./freq[np.where(power==np.max(power))] plt.plot([freq[0], freq[-1]], [FP_99, FP_99], '--') plt.plot([freq[0], freq[-1]], [FP_95, FP_95], '--') plt.plot([freq[0], freq[-1]], [FP_68, FP_68], '--') plt.text(freq[0], FP_99, 'FAP 99%',font1) plt.text(freq[0], FP_95, '95%',font1) plt.text(freq[0], FP_68, '68%',font1) plt.xlabel('Frequency (Hz)',font1) plt.ylabel('Normalized LS Periodogram',font1) plt.tick_params(labelsize=16) plt.show() # plt.savefig('/Users/baotong/Desktop/CDFS/fig_LS_ep{0}_ovsamp_5_baluev/{1}.eps'.format(k,dataname)) # plt.savefig('/Users/baotong/Desktop/CDFS/fig_LS_ep{0}_samp_1_baluev/{1}.eps'.format(k,dataname)) # plt.close() return [FP,out_period]
def get_LS(time, flux,freq): path='/Users/baotong/xmm/0201290301/txt/' x = time y = flux # dy=np.sqrt(y) # plt.scatter(x,y) # plt.show() # LS = LombScargle(x, y, dy = 1, normalization = 'standard', fit_mean = True, # center_data = True).power(freq, method = 'cython') LS = LombScargle(x, y,normalization = 'standard') # LS = LombScargle(x, y, dy, normalization='psd') power = LS.power(freq) # print('freq_num={0}'.format(len(freq))) FP=LS.false_alarm_probability(power.max(),minimum_frequency = freq[0], maximum_frequency = freq[-1],method='baluev') FP_99 = LS.false_alarm_level(0.0027, minimum_frequency = freq[0], maximum_frequency = freq[-1],method='baluev') FP_90 = LS.false_alarm_level(0.05, minimum_frequency=freq[0], maximum_frequency=freq[-1], method='baluev') FP_68 = LS.false_alarm_level(0.32, minimum_frequency=freq[0], maximum_frequency=freq[-1], method='baluev') plt.title('FP={0}'.format(FP)) plt.semilogx() # plt.xlim(1000.,1500.) plt.plot(1/freq, power) print(1./freq[np.where(power==np.max(power))]) # plt.plot([freq[0], freq[-1]], [FP_99, FP_99], '--') # plt.plot([freq[0], freq[-1]], [FP_90, FP_90], '--') # plt.plot([freq[0], freq[-1]], [FP_68, FP_68], '--') # plt.plot([1/(20.3*60),1/(20.3*60)],[0,0.08],'--',color='green') # plt.plot([1 / (22.5 * 60), 1 / (22.5 * 60)], [0, 0.08], '--', color='yellow') # plt.plot([1 / (18.6 * 60), 1 / (18.6 * 60)], [0, 0.08], '--', color='blue') plt.plot([20.3*60,20.3*60],[0,0.08],'--',color='green') plt.plot([22.5 * 60, 22.5 * 60], [0, 0.08], '--', color='yellow') plt.plot([18.6 * 60, 18.6 * 60], [0, 0.08], '--', color='blue') plt.show() res=1e5*power res=np.round(res,2) # res=res[::smooth] # np.savetxt(path+'LS_simres_{0}.txt'.format(trial+1),res,fmt='%10.5f') return [FP, 1. / freq[np.where(power == np.max(power))],np.max(power),res]
def get_LS(time, flux, freq): x = time y = flux LS = LombScargle(x, y, normalization='standard') # LS = LombScargle(x, y, dy, normalization='psd') power = LS.power(freq) FP = LS.false_alarm_probability(power.max(), minimum_frequency=freq[0], maximum_frequency=freq[-1], method='baluev') FP_99 = LS.false_alarm_level(0.0027, minimum_frequency=freq[0], maximum_frequency=freq[-1], method='baluev') FP_90 = LS.false_alarm_level(0.05, minimum_frequency=freq[0], maximum_frequency=freq[-1], method='baluev') FP_68 = LS.false_alarm_level(0.32, minimum_frequency=freq[0], maximum_frequency=freq[-1], method='baluev') # if FP<0.01:print(dataname) # plt.title('{0},FP={1}'.format(dataname,FP)) # plt.semilogx() # plt.title('XID 19') plt.plot(freq, power) plt.semilogx() print(1. / freq[np.where(power == np.max(power))]) print(np.where(power == np.max(power))) # if FP<0.01:print(1./freq[np.where(power==np.max(power))]);print(np.where(power==np.max(power))) out_period = 1. / freq[np.where(power == np.max(power))] plt.plot([freq[0], freq[-1]], [FP_99, FP_99], '--') plt.plot([freq[0], freq[-1]], [FP_90, FP_90], '--') plt.plot([freq[0], freq[-1]], [FP_68, FP_68], '--') plt.show() # plt.savefig('/Users/baotong/Desktop/CDFS/fig_LS_ep{0}_ovsamp_5_baluev/{1}.eps'.format(k,dataname)) # plt.close() return [FP, out_period]
def get_LS(time, flux, freq): x = time y = flux LS = LombScargle(x, y, normalization='standard') # LS = LombScargle(x, y, dy, normalization='psd') power = LS.power(freq) FP = LS.false_alarm_probability(power.max(), samples_per_peak=5, nyquist_factor=5, minimum_frequency=freq[0], maximum_frequency=freq[-1], method='baluev') FP_99 = LS.false_alarm_level(0.01, samples_per_peak=10, nyquist_factor=5, minimum_frequency=freq[0], maximum_frequency=freq[-1], method='naive') FP_90 = LS.false_alarm_level(0.1, samples_per_peak=10, nyquist_factor=5, minimum_frequency=freq[0], maximum_frequency=freq[-1], method='naive') FP_68 = LS.false_alarm_level(0.32, samples_per_peak=10, nyquist_factor=5, minimum_frequency=freq[0], maximum_frequency=freq[-1], method='naive') plt.plot(freq, power) print(1. / freq[np.where(power == np.max(power))]) plt.plot([freq[0], freq[-1]], [FP_99, FP_99], '--') plt.plot([freq[0], freq[-1]], [FP_90, FP_90], '--') plt.plot([freq[0], freq[-1]], [FP_68, FP_68], '--') plt.show()
def periodogram(ax, t, sig): alpha = 0.001 baseline = max(t) - min(t) ls = LombScargle(t, sig) frequency, power = ls.autopower(minimum_frequency=1 / baseline, maximum_frequency=1 / 2) periods = 1 / frequency ax.plot(periods, power, 'k-') ax.set(xlim=(min(periods), max(periods)), ylim=min(power), xlabel='Period (JD)', ylabel='Lomb-Scargle Power', xscale='log') # Add line to periodogram representing FAP = alpha n = 100 x_values = [1.3**i for i in range(n)] + [1.11] y_values_alpha = [ls.false_alarm_level(alpha) for i in range(n + 1)] ax.plot(x_values, y_values_alpha, 'b_') ax.legend(["{0} FAP".format(alpha)], loc="upper right", frameon=False, handlelength=0) best_period = find_best_period(t, sig) # Plot aliases, harmonics and sampling periods on the periodogram as vertical lines. f_sampling = [1 / 1, 1 / 29.5, 1 / 365] aliases, harmonics = find_aliases(1 / best_period, [-1, 1], f_sampling) for alias in aliases: ax.axvline(alias, c="grey", lw=0.8) for harmonic in harmonics: ax.axvline(harmonic, c="blue", lw=0.8) for f in f_sampling: ax.axvline(1 / f, c="green", lw=0.8)
def lombscargle(t, x, dx=None, f0=None, fmax=None, n=5, fap_method=None, fap_level=None, psd=False): """Computes the generalized Lomb-Scargle periodogram of a discrete signal. Parameters ---------- t: array-like Time array. x: array-like Signal array. dx: array-like, optional Measurement uncertainties for each sample. f0: float, optional Minimum frequency. If not given, it will be determined from the time baseline. fmax: float, optional Maximum frequency. If not given, defaults to the pseudo-Nyquist limit. n: float, optional Samples per peak (default is 5). fap_method: {None, 'baluev', 'bootstrap'} The approximation method to use for the highest peak FAP and false alarm levels. The default is None, in which case the FAP is not calculated. fap_level: array-like, optional List of false alarm probabilities for which you want to calculate approximate levels. Can also be passed as a single scalar value. psd: bool, optional Whether to leave periodogram non-normalized (Fourier Spectral Density). Returns ------- ls: astropy.timeseries.LombScargle object The full object for the given data. f: ndarray Frequency array. a: ndarray Power array. fap: float If `fap_method` is given, the False Alarm Probability of highest peak. fal: float If `fap_level` is given, the power level for the given probabilities. """ if psd: ls = LombScargle(t, x, dy=dx, normalization='psd') else: ls = LombScargle(t, x, dy=dx) if fmax is None: ts = float(np.median(np.diff(t))) fs = 1 / ts fmax = fs / 2 f, a = ls.autopower(samples_per_peak=n, minimum_frequency=f0, maximum_frequency=fmax) if fap_method is not None: if fap_method not in ['baluev', 'bootstrap']: raise ValueError(f"Unknown FAP method {fap_method}.") fap = ls.false_alarm_probability(a.max(), method=fap_method, minimum_frequency=f0, maximum_frequency=fmax, samples_per_peak=n) if fap_level is not None: fal = ls.false_alarm_level(fap_level, method=fap_method, minimum_frequency=f0, maximum_frequency=fmax, samples_per_peak=n) return ls, f, a, fap, fal return ls, f, a, fap return ls, f, a
def genLS(self, show_plot='y', compute_fap='n', use_detrend='n', minP=None, maxP=None, LSquarters=None): print("calling _mp_visuals.py/genLS().") ### this function generates a Lomb-Scargle Periodogram! LSperiods = [] LSmaxpower_periods = [] LSpowers = [] LSfaps = [] nquarters = len(self.quarters) if type(LSquarters) == type(None): LSquarters = self.quarters for qidx in np.arange(0, nquarters, 1): this_quarter = self.quarters[qidx] if this_quarter not in LSquarters: ### use this in case you've only specified select quarters. continue print("processing LS for ", this_quarter) if nquarters != 1: if use_detrend == 'n': qtimes, qfluxes, qerrors = self.times[qidx], self.fluxes[ qidx], self.errors[qidx] elif use_detrend == 'y': qtimes, qfluxes, qerrors = self.times[ qidx], self.fluxes_detrend[qidx], self.errors_detrend[qidx] else: if use_detrend == 'n': qtimes, qfluxes, qerrors = self.times, self.fluxes, self.errors elif use_use_detrend == 'y': qtimes, qfluxes, qerrors = self.times, self.fluxes_detrend, self.errors_detrend if maxP == None: maxperiod = 0.5 * (np.nanmax(qtimes) - np.nanmin(qtimes)) else: maxperiod = maxP if minP == None: minperiod = 0.5 else: minperiod = minP minfreq, maxfreq = 1 / maxperiod, 1 / minperiod qls = LombScargle(qtimes, qfluxes, qerrors) qfreq, qpower = qls.autopower(minimum_frequency=minfreq, maximum_frequency=maxfreq) qperiods = 1 / qfreq if compute_fap == 'y': qfap = qls.false_alarm_probability(qpower.max(), method='bootstrap') probabilities = [0.1, 0.05, 0.01] quarter_FALs = qls.false_alarm_level(probabilities) if show_plot == 'y': random_color = np.random.rand(3) plt.plot(qperiods[::-1], qpower[::-1], c=random_color) if compute_fap == 'y': plt.plot(qperiods[::-1], np.linspace(quarter_FALs[1], quarter_FALs[1], len(qperiods[::-1])), c=random_color) LSperiods.append(qperiods) max_power_period = qperiods[np.nanargmax(qpower)] LSmaxpower_periods.append(max_power_period) LSpowers.append(qpower) if compute_fap == 'y': LSfaps.append(qfap) if show_plot == 'y': plt.xscale('log') plt.xlabel('Period [days]') plt.ylabel('Power') plt.title(self.target) plt.show() LSperiods, LSpowers, LSfaps = np.array(LSperiods), np.array( LSpowers), np.array(LSfaps) print('LS max power periods = ', LSmaxpower_periods) LSperiod_median = np.nanmedian(LSmaxpower_periods) LSperiod_std = np.nanstd(LSmaxpower_periods) print('median(LS max power periods) = ', LSperiod_median) print('std(LS max power periods) = ', LSperiod_std) self.LSperiods = LSperiods self.LSpowers = LSpowers self.LSfaps = LSfaps self.LSmaxperiods = LSmaxpower_periods
def plot_periodograms(activityFile, plot_dir, results): """ Produce periodograms of RV and activity indices @author: Melissa Hobson adapted by Martin Schlecker Parameters ------------ activityFile : string file containing the reduced time series plot_dir : string directory for the created plots results : results object a results object returned by juliet.fit() Returns -------- fig : matplotlib figure figure containing the plot ax : matplotlib axis axis object with the plot """ font = {'size': 15} mpl.rc('font', **font) bbox_props = { 'boxstyle': "round", 'fc': "w", 'edgecolor': "w", # 'ec':0.5, 'alpha': 0.9 } # ============================================================================= # Read data in # FEROS data feros_dat = np.genfromtxt(activityFile, names=True) feros_dat = pd.DataFrame(feros_dat).replace(-999, np.nan) transit_per = np.median(results.posteriors['posterior_samples']['P_p1']) # ============================================================================= # Periodograms - FEROS f_min = 1 / (feros_dat['BJD_OUT'].max() - feros_dat['BJD_OUT'].min()) f_max = None #RV # variables bjd_feros = feros_dat['BJD_OUT'] RV_feros = feros_dat['RV'] RV_E_feros = feros_dat['RV_E'] # create periodogram rv_ls = LombScargle(bjd_feros, RV_feros, RV_E_feros) rv_frequency, rv_power = rv_ls.autopower(minimum_frequency=f_min, maximum_frequency=f_max) # Get FAP levels probabilities = [0.01, 0.005, 0.001] labels = ['1.00% FAP', '0.50% FAP', '0.01% FAP'] ltype = ['solid', 'dashed', 'dotted'] rv_faps = rv_ls.false_alarm_level(probabilities, method='bootstrap') # H alpha # variables ha_feros = feros_dat['HALPHA'] ha_e_feros = feros_dat['HALPHA_E'] # create periodogram ha_ls = LombScargle(bjd_feros, ha_feros, ha_e_feros) ha_frequency, ha_power = ha_ls.autopower(minimum_frequency=f_min, maximum_frequency=f_max) # Get FAP levels ha_faps = ha_ls.false_alarm_level(probabilities, method='bootstrap') # log Rhk # variables rhk_feros = feros_dat['LOG_RHK'].dropna() rhk_e_feros = feros_dat['LOGRHK_E'].dropna() bjd_rhk = bjd_feros.iloc[rhk_feros.index] # create periodogram rhk_ls = LombScargle(bjd_rhk, rhk_feros, rhk_e_feros) rhk_frequency, rhk_power = rhk_ls.autopower(minimum_frequency=f_min, maximum_frequency=f_max) # Get FAP levels rhk_faps = rhk_ls.false_alarm_level(probabilities, method='bootstrap') # Na II # variables na_feros = feros_dat['NA_II'] na_e_feros = feros_dat['NA_II_E'] # create periodogram na_ls = LombScargle(bjd_feros, na_feros, na_e_feros) na_frequency, na_power = na_ls.autopower(minimum_frequency=f_min, maximum_frequency=f_max) # Get FAP levels na_faps = na_ls.false_alarm_level(probabilities, method='bootstrap') # He I # variables he_feros = feros_dat['HE_I'] he_e_feros = feros_dat['HE_I_E'] # create periodogram he_ls = LombScargle(bjd_feros, he_feros, he_e_feros) he_frequency, he_power = he_ls.autopower(minimum_frequency=f_min, maximum_frequency=f_max) # Get FAP levels he_faps = he_ls.false_alarm_level(probabilities, method='bootstrap') # ============================================================================= # Plot the data # figsize = plotstyle.set_size(subplot=[5,1]) # (11, 21) figsize = (8, 10) fig, axs = plt.subplots(5, 1, figsize=figsize, sharex=True, sharey=True, gridspec_kw={ 'wspace': 0, 'hspace': 0.08 }) # # RV timeseries # axs[0].errorbar(bjd_feros, RV_feros, yerr=RV_E_feros, fmt='o') # axs[0].set_xlabel('BJD') # axs[0].set_ylabel('RV [km/s]') # RV periodogram annotOffsets = [-.12, 0, .12] axs[0].plot(rv_frequency, rv_power) for ind in range(len(rv_faps)): axs[0].axhline(rv_faps[ind], xmax=0.81, label=labels[ind], lw=1.5, linestyle=ltype[ind], c='black') axs[0].annotate(labels[ind], xy=[.815, rv_faps[ind]], va='center', xytext=[.86, rv_faps[1] + annotOffsets[ind]], size=10, xycoords=('axes fraction', 'data'), arrowprops=dict(arrowstyle="-")) axs[0].axvline(1 / transit_per, lw=1.5, linestyle='dashed', color='C1') # axs[0].set_xscale('log') # axs[0].set_xlabel('Frequency [1/d]') axs[0].set_ylabel('power') axs[0].annotate('P = {:.2f} d'.format(transit_per), [1 / transit_per, 1.05], color='C1', ha='center', xycoords=('data', 'axes fraction')) axs[0].annotate('RV', xy=(0, 1.01), xytext=(.02, .84), size=15, bbox=bbox_props, ha='left', va='center', xycoords='axes fraction', textcoords='axes fraction') # # Halpha timeseries # plt.subplot(4, 3, 2) # plt.errorbar(bjd_feros, ha_feros, yerr=ha_e_feros, fmt='o') # plt.set_xlabel('BJD') # plt.set_ylabel('H ALPHA') # Halpha periodogram axs[1].plot(ha_frequency, ha_power) for ind in range(len(ha_faps)): axs[1].axhline(ha_faps[ind], label=labels[ind], lw=1.5, linestyle=ltype[ind], c='black') axs[1].axvline(1 / transit_per, lw=1.5, linestyle='dashed', color='C1') # axs[1].set_xscale('log') # axs[1].set_xlabel('Period [d]') axs[1].set_ylabel('power') axs[1].annotate(r'H$_\alpha$', xy=(0, 1.01), xytext=(.02, .84), size=15, bbox=bbox_props, ha='left', va='center', xycoords='axes fraction', textcoords='axes fraction') # # log RHK timeseries # plt.subplot(4, 3, 3) # plt.errorbar(bjd_feros, rhk_feros, yerr=rhk_e_feros, fmt='o') # plt.set_xlabel('BJD'HKk) # plt.set_ylabel('LOG RHK') # log Rhk periodogram axs[2].plot(rhk_frequency, rhk_power) for ind in range(len(rhk_faps)): axs[2].axhline(rhk_faps[ind], label=labels[ind], lw=1.5, linestyle=ltype[ind], c='black') axs[2].axvline(1 / transit_per, lw=1.5, linestyle='dashed', color='C1') # axs[2].set_xscale('log') # axs[2].set_xlabel('Period [d]') axs[2].set_ylabel('power') axs[2].annotate(r'log($R^\prime_{HK}$)', xy=(0, 1.01), xytext=(.02, .84), size=15, bbox=bbox_props, ha='left', va='center', xycoords='axes fraction', textcoords='axes fraction') # # Na II timeseries # plt.subplot(4, 3, 8) # plt.errorbar(bjd_feros, na_feros, yerr=na_e_feros, fmt='o') # plt.set_xlabel('BJD') # plt.set_ylabel('NA II') # Na II periodogram axs[3].plot(na_frequency, na_power) for ind in range(len(na_faps)): axs[3].axhline(na_faps[ind], label=labels[ind], lw=1.5, linestyle=ltype[ind], c='black') axs[3].axvline(1 / transit_per, lw=1.5, linestyle='dashed', color='C1') # axs[3].set_xscale('log') # axs[3].set_xlabel('Period [d]') axs[3].set_ylabel('power') axs[3].annotate(r'Na II', xy=(0, 1.01), xytext=(.02, .84), size=15, bbox=bbox_props, ha='left', va='center', xycoords='axes fraction', textcoords='axes fraction') # # HeI timeseries # plt.subplot(4, 3, 9) # plt.errorbar(bjd_feros, he_feros, yerr=he_e_feros, fmt='o') # plt.set_xlabel('BJD') # plt.set_ylabel('HE I') # HeI periodogram axs[4].plot(he_frequency, he_power) for ind in range(len(he_faps)): axs[4].axhline(he_faps[ind], label=labels[ind], lw=1.5, linestyle=ltype[ind], c='black') axs[4].axvline(1 / transit_per, lw=1.5, linestyle='dashed', color='C1') # axs[4].set_xscale('log') # axs[4].set_xlabel('Period [d]') axs[4].set_xlabel('Frequency [1/d]') axs[4].set_ylabel('power') axs[4].annotate(r'He I', xy=(0, 1.01), xytext=(.02, .84), size=15, bbox=bbox_props, ha='left', va='center', xycoords='axes fraction', textcoords='axes fraction') # some eye candy [ax.set_xlim([0.005, 0.3]) for ax in axs] # [ax.set_ylim([0,.9]) for ax in axs] [ax.tick_params(direction='in', top=True, right=True) for ax in axs] # fig.subplots_adjust(hspace = .03, wspace=0.4) plt.show() fig.savefig(plot_dir + 'periodograms.pdf') return fig, ax # import pickle # out_folder = 'out/27_tess+chat+feros+GP' # priors, params = get_priors(GP=True) # times_lc, fluxes, fluxes_error, gp_times_lc = read_photometry(datafolder, # plotPhot=False, outlierIndices=outlierIndices) # times_rv, rvs, rvs_error = read_rv(datafolder) # # dataset = juliet.load( # priors=priors, t_lc=times_lc, y_lc=fluxes, yerr_lc=fluxes_error, # t_rv=times_rv, y_rv=rvs, yerr_rv=rvs_error, # GP_regressors_lc=gp_times_lc, # out_folder=out_folder, verbose=True) # results = pickle.load(open(out_folder + '/results.pkl', 'rb')) # plot_periodograms(activityFile, plot_dir, results) # sys.exit(0)
def lombScargle(mjd, mag, magerr, dv, min_per, max_per, false_alarm_levels, out_type): #Import(s) from astropy.timeseries import LombScargle from pandas import Series, concat, date_range, to_datetime import numpy as np import matplotlib.pyplot as plt from matplotlib.ticker import AutoMinorLocator #Action JD = mjd + 2400000.5 # Generate a Dirac Comb, our window function time = to_datetime(JD, unit="D", origin="julian") time_not_obs = date_range(time.min(), time.max(), periods=1000) base = Series(np.zeros(len(time_not_obs)), index=time_not_obs) teeth = Series(np.ones(len(time)), index=time) dirac_comb = concat([base, teeth]).sort_index() minf = 1 / max_per maxf = 1 / min_per # First, the periodogram of the window function JD_W = dirac_comb.index.to_julian_date() mag_W = dirac_comb.values periodogram_W = LombScargle(JD_W, mag_W) freq_W, power_W = periodogram_W.autopower(method='fastchi2', minimum_frequency=minf, maximum_frequency=maxf) # Periodogram of original light curve periodogram = LombScargle(JD, mag, magerr) ls_freqs, ls_powers = periodogram.autopower(method='fastchi2', minimum_frequency=minf, maximum_frequency=maxf) # Mask out peak window-function frequencies from the data with a notch # width of dv (default should be 0.03) Hz on either side. high_power_W = power_W.mean() + 2 * power_W.std() pwf = freq_W[np.argwhere( power_W > high_power_W)] # pwf = Peak Window Frequencies for f in pwf: good_idx = np.invert( np.logical_and((ls_freqs + dv) > f, (ls_freqs - dv) < f)) # Phew that is clean cleaned_powers = ls_powers[good_idx] cleaned_freqs = ls_freqs[good_idx] # Calculate FAPs faps = periodogram.false_alarm_level(false_alarm_levels) cleaned_periods = 1 / cleaned_freqs mask_lunar = np.invert( np.logical_and(cleaned_periods > 26, cleaned_periods < 30)) cleaned_freqs = np.array(cleaned_freqs)[mask_lunar] cleaned_powers = np.array(cleaned_powers)[mask_lunar] best_index = np.argmax(cleaned_powers) best_power = cleaned_powers[best_index] best_freq = cleaned_freqs[best_index] # Fold the light curve T = 1 / (float(best_freq)) phased_dates = np.mod( mjd, T) / T # Got this from the feets package documentation phased_dates_cycle_2 = phased_dates + 1 # Plot plt.rcParams['font.family'] = 'serif' ax1 = plt.subplot(222) periods = 1 / cleaned_freqs ax1.plot(periods[np.argwhere(periods < 26)], cleaned_powers[np.argwhere(periods < 26)]) ax1.plot(periods[np.argwhere(periods > 30)], cleaned_powers[np.argwhere(periods > 30)], color='C0') #Plot FAP Levels colors = ['lightgrey', 'silver', 'darkgray', 'gray', 'dimgray'] for i in range( len(false_alarm_levels) - 1, -1, -1 ): # Plot them in reverse order so the highest confidence label is confidence_label = str(100 * (1 - false_alarm_levels[i])) + '% FAP' ax1.hlines(y=(false_alarm_levels[i]), xmin=min_per, xmax=max_per, color=colors[i], linestyles='--', label=confidence_label) # Periodogram plot ax1.set_xscale('log') ax1.set_xlabel('Period d') ax1.set_xscale('log') ax1.set_ylabel('Power') ax1.set_yticks([0.1, 0.3, 0.5, 0.7, 0.9]) ax1.yaxis.set_minor_locator(AutoMinorLocator()) ax1.set_ylim(0, 1) ax1.set_xlim(1.5, 250) ax1.set_title('Periodogram', fontsize=10) box = ax1.get_position() ax1.set_position([box.x0, box.y0, box.width * 0.5, box.height]) ax1.legend(bbox_to_anchor=(1.15, 0.5), loc='center', fontsize=4) # Folded light curve plot ax2 = plt.subplot(221) xlabel = 'Phase (P = ' + str(round((1 / best_freq), 3)) + ' d)' ax2.set_xlabel(xlabel) ax2.set_ylabel('Mag') ax2.scatter(phased_dates, mag, s=2) ax2.scatter(phased_dates_cycle_2, mag, s=2, c='C0') ax2.xaxis.set_minor_locator(AutoMinorLocator()) ax2.yaxis.set_minor_locator(AutoMinorLocator()) ax2.invert_yaxis() ax2.set_title("Folded Light Curve", fontsize=10) ax2.locator_params(axis='y', nbins=5) # Unfolded light curve plot ax3 = plt.subplot(212) ax3.errorbar(mjd, mag, yerr=magerr, lw=0, elinewidth=0.5) ax3.scatter(mjd, mag, s=2) ax3.invert_yaxis() ax3.xaxis.set_minor_locator(AutoMinorLocator()) ax3.yaxis.set_minor_locator(AutoMinorLocator()) ax3.set_ylabel('Mag') ax3.set_xlabel('MJD') ax3.set_title('Light Curve', fontsize=10) ax3.locator_params(axis='y', nbins=5) plt.subplots_adjust(wspace=0.4, hspace=0.45) if out_type == 'show' or out_type == 'Show': plt.show() plt.clf() else: plt.savefig( out_type, dpi=200, format=out_type[-3:]) # Flexible save type (svg, png, etc.) plt.clf() out_list = [best_power, 1 / best_freq] for fap in faps: out_list.append(fap) return out_list
def q_diagnostic(id, mjd, mag, magerr, dv, min_per, max_per, false_alarm_levels, out_type): ''' Create diagnostic plot for lomb-scargle periodogram as well as q-analysis. Incorporates the best working version of our period search and quasi-periodicty routines. ''' # Import(s) from astropy.timeseries import LombScargle from pandas import Series, concat, date_range, to_datetime import numpy as np import matplotlib.pyplot as plt from matplotlib.ticker import AutoMinorLocator #Action JD = mjd + 2400000.5 # Generate a Dirac Comb, our window function time = to_datetime(JD, unit="D", origin="julian") time_not_obs = date_range(time.min(), time.max(), periods=1000) base = Series(np.zeros(len(time_not_obs)), index=time_not_obs) teeth = Series(np.ones(len(time)), index=time) dirac_comb = concat([base, teeth]).sort_index() minf = 1 / max_per maxf = 1 / min_per # Periodogram of the window function JD_W = dirac_comb.index.to_julian_date() mag_W = dirac_comb.values periodogram_W = LombScargle(JD_W, mag_W) freq_W, power_W = periodogram_W.autopower(method='fastchi2', minimum_frequency=minf, maximum_frequency=maxf) # Periodogram of original light curve periodogram = LombScargle(JD, mag, magerr) ls_freqs, ls_powers = periodogram.autopower(method='fastchi2', minimum_frequency=minf, maximum_frequency=maxf) # Mask out peak window-function frequencies from the data with a notch # width of dv (default should be 0.03) Hz on either side. high_power_W = power_W.mean() + 2 * power_W.std() pwff = freq_W[np.where( power_W > high_power_W)] # pwff = Peak Window Function Frequencies wffitr = np.array( []) # wfftr = Window Function Frequency Indices To Remove ls_pers = 1 / ls_freqs for f in pwff: per = 1 / f #print((per-0.02),per,(per+0.02)) #good_idx = np.invert(np.logical_and((ls_freqs<(f+dv)), (ls_freqs>(f-dv)))) # Phew that is clean good_idx = np.invert( np.logical_and(ls_pers < per + dv, ls_pers > per - dv)) bap = np.where(good_idx == False) wffitr = np.append(wffitr, bap) #.astype(int) wffitr = np.unique(wffitr).astype(int) cleaned_powers = np.delete(ls_powers, wffitr) cleaned_freqs = np.delete(ls_freqs, wffitr) ''' cleaned_powers = ls_powers[good_idx] cleaned_freqs = ls_freqs[good_idx] ''' # Calculate FAPs faps = periodogram.false_alarm_level(false_alarm_levels) # Mask known aliase ranges (Lunar, etc.) cleaned_periods = 1 / cleaned_freqs mask_lunar = np.invert( np.logical_and(cleaned_periods > 26, cleaned_periods < 30)) cleaned_freqs = np.array(cleaned_freqs)[mask_lunar] cleaned_powers = np.array(cleaned_powers)[mask_lunar] # Find best results best_index = np.argmax(cleaned_powers) best_power = cleaned_powers[best_index] best_freq = cleaned_freqs[best_index] best_per = 1 / best_freq # Fold the light curve T = 1 / (float(best_freq)) phased_dates = np.mod( mjd, T) / T # Got this from the feets package documentation phased_dates_cycle_2 = phased_dates + 1 # Calculate Q and get residuals plot qp_results = quas_per(mjd=mjd, mag=mag, magerr=magerr, per=best_per) q = qp_results[0] residuals = qp_results[1] # Calculate m m = codyM(x=mag) def create_plot(): # Plot plt.rcParams['font.family'] = 'serif' fig, axs = plt.subplots(2, 2) fig.suptitle('Q: ' + str(round(q, 3)) + '; M: ' + str(round(m, 3)), fontsize='medium') # Periodogram plot periods = 1 / cleaned_freqs axs[1, 1].plot(periods[np.argwhere(periods < 26)], cleaned_powers[np.argwhere(periods < 26)]) axs[1, 1].plot(periods[np.argwhere(periods > 30)], cleaned_powers[np.argwhere(periods > 30)], color='C0') #Plot FAP Levels colors = ['lightgrey', 'silver', 'darkgray', 'gray', 'dimgray'] for i in range( len(false_alarm_levels) - 1, -1, -1 ): # Plot them in reverse order so the highest confidence label is confidence_label = str(100 * (1 - false_alarm_levels[i])) + '% FAP' axs[1, 1].hlines(y=(faps[i]), xmin=min_per, xmax=max_per, color=colors[i], linestyles='--', label=confidence_label) axs[1, 1].set_xscale('log') axs[1, 1].set_xlabel('Period d') axs[1, 1].set_xscale('log') axs[1, 1].set_ylabel('Power') axs[1, 1].set_yticks([0.1, 0.3, 0.5, 0.7, 0.9]) axs[1, 1].yaxis.set_minor_locator(AutoMinorLocator()) axs[1, 1].set_ylim(0, 1) axs[1, 1].set_xlim(0.5, 250) axs[1, 1].set_title('Periodogram', fontsize=10) box = axs[1, 1].get_position() axs[1, 1].set_position([box.x0, box.y0, box.width * 0.5, box.height]) axs[1, 1].legend(bbox_to_anchor=(1.15, 0.5), loc='center', fontsize=4) # Folded light curve plot xlabel = 'Phase (P = ' + str(round((1 / best_freq), 3)) + ' d)' axs[0, 1].set_xlabel(xlabel) axs[0, 1].set_ylabel('Mag') axs[0, 1].scatter(phased_dates, mag, s=2) axs[0, 1].scatter(phased_dates_cycle_2, mag, s=2, c='C0') axs[0, 1].xaxis.set_minor_locator(AutoMinorLocator()) axs[0, 1].yaxis.set_minor_locator(AutoMinorLocator()) axs[0, 1].invert_yaxis() axs[0, 1].set_title("Folded Light Curve", fontsize=10) axs[0, 1].locator_params(axis='y', nbins=5) # Unfolded light curve plot axs[0, 0].errorbar(mjd, mag, yerr=magerr, lw=0, elinewidth=0.5) axs[0, 0].scatter(mjd, mag, s=2) axs[0, 0].invert_yaxis() axs[0, 0].xaxis.set_minor_locator(AutoMinorLocator()) axs[0, 0].yaxis.set_minor_locator(AutoMinorLocator()) axs[0, 0].set_ylabel('Mag') axs[0, 0].set_xlabel('MJD') axs[0, 0].set_title('Light Curve', fontsize=10) axs[0, 0].locator_params(axis='y', nbins=5) # Residuals plot axs[1, 0].scatter(mjd, residuals, s=2) axs[1, 0].axhline(y=0, xmin=0, xmax=1, color='black', lw=0.75) axs[1, 0].set_title('Residual Plot') axs[1, 0].xaxis.set_minor_locator(AutoMinorLocator()) axs[1, 0].yaxis.set_minor_locator(AutoMinorLocator()) axs[1, 0].set_xlabel('MJD') axs[1, 0].set_ylabel('Residual Mag', fontsize=10) plt.subplots_adjust(wspace=0.4, hspace=0.50) if out_type == 'show' or out_type == 'Show': create_plot() plt.show() plt.clf() elif out_type == 'None' or out_type == 'none': plt.clf() else: create_plot() q_str = str(q) q_str_split = q_str.split('.') decimal_portion = q_str_split[1] decimal_portion = decimal_portion[0:3] q_str = q_str_split[0] + '.' + decimal_portion actual_path = out_type.replace('***', q_str) actual_path = actual_path.replace('+++', id) plt.savefig( actual_path, dpi=200, format=out_type[-3:]) # Flexible save type (svg, png, etc.) plt.clf() plt.close() out_list = [best_power, 1 / best_freq, q, m] for fap in faps: out_list.append(fap) return out_list
def LSP(x, y, dy, fVal=[0, 1, 5, 1], norm='standard', figout=None, label=None, freq_set=None): ''' 周期分析 https://docs.astropy.org/en/stable/timeseries/lombscargle.html#periodogram-algorithms 参数: x,y,dy: arrays 时间,星等,误差 figout: str 图片保存名称 fVal: list minimum_frequency,maximum_frequency,samples_per_peak(default 5),nterms(default 1) return: frequency, power, residuals, x_range, y_fit, theta if nterms=1: theta=[off_set,amplitude,phi,best_frequency] y=off_set+amplitude*np.sin(2*np.pi*best_frequency*x+phi) ''' import numpy as np import matplotlib.pyplot as plt from astropy.timeseries import LombScargle if not isinstance(x, np.ndarray): x = np.array(x) y = np.array(y) dy = np.array(dy) fVal[0] = 10**-5 if fVal[0] == 0 else fVal[0] ls = LombScargle(x, y, dy, nterms=fVal[-1], normalization=norm) frequency, power = ls.autopower(minimum_frequency=fVal[0], maximum_frequency=fVal[1], samples_per_peak=fVal[2]) fig, ax = plt.subplots(3) fig.set_size_inches(20, 27) #ax[0].invert_yaxis();ax[2].invert_yaxis(); ax[0].grid() ax[1].grid() ax[2].grid() ax[0].errorbar(x, y, dy, fmt='bo-', label=label) ax[1].set_xlim((frequency[0], frequency[-1])) ax[1].plot(frequency, power, 'b-') ax11 = ax[1].twiny() ax11.set_xlim(ax[1].get_xlim()) x_side = np.linspace(0.001 + frequency[0], frequency[-1], 10) x_side_var = np.round(24 * 60 / x_side, 2) plt.xticks(x_side, x_side_var, rotation=0) best_frequency = frequency[np.argmax(power)] peak_power = power.max() ax[1].plot(best_frequency, peak_power, 'ro') ax[1].legend([ 'spectrum distribution', 'peak frequency ' + str(round(best_frequency, 4)) + 'c/d is period ' + str(round(24 / best_frequency, 4)) + 'h' ], loc='upper right', fontsize=15, frameon=False) if fVal[-1] == 1: for cutoff in ls.false_alarm_level([0.1, 0.05, 0.01]): ax[1].axhline(cutoff, color='black', linestyle='dotted') if freq_set != None: best_frequency = freq_set phase = (x * best_frequency) % 1 y_fit = ls.model(x, best_frequency) residuals = y - y_fit y_fit = y_fit[np.argsort(phase)] ax[2].plot(np.sort(phase), y_fit, 'r-', linewidth=5) ax[2].errorbar(phase, y, dy, fmt='b.', alpha=1) ax[2].legend( ['best fitted curve is ' + str(best_frequency), 'folded data'], loc='upper right', fontsize=15, frameon=False) x_range = np.linspace(x.min(), x.max(), 100) y_fit = ls.model(x_range, best_frequency) ax[0].plot(x_range, y_fit, 'r-', label='fitting curve', linewidth=5) ax[0].legend(loc='upper right', fontsize=15, frameon=False) if figout: plt.savefig(figout, dpi=100) plt.show() if fVal[-1] == 1: print('the false alarm probability for %0.2f (%0.2f min) is %0.2e' % (best_frequency, 24 * 60 / best_frequency, ls.false_alarm_probability(peak_power, method='davies'))) theta = ls.model_parameters(best_frequency) theta[0] = ls.offset() + theta[0] if len(theta) == 3: K = (theta[1]**2 + theta[2]**2)**0.5 phi = np.arcsin(theta[2] / K) theta = [theta[0], K, phi, best_frequency] return frequency, power, residuals, x_range, y_fit, theta
def main(): names = [ "d-abc_f.by", "d-abc_f.by.001", "d-abc_f.by.002", "d-ab_f.by", "d-ac_f.by", "d-ab_f.by", "c-ab_f.by", "d-bc_f.by", "c-a_f.by", "d-b_f.by", "d-a_f.by" ] names_index = 0 while (names_index < 15): filename = names[names_index] try: file = open(filename) break except: names_index += 1 continue season_lengths = [] last_day = 0 curr_season_length = 0 for line in file.readlines(): words = line.split() day = float(words[0]) if (day - last_day > 1000): #first line last_day = day curr_season_length += 1 continue if (day - last_day > 50): #fix season_lengths.append(curr_season_length) curr_season_length = 0 last_day = day curr_season_length += 1 season_lengths.append(curr_season_length) file.close() newfile = open("seasons.by", "w") file = open(filename) for season_length in season_lengths: times = [] fluxes = [] for n in range(season_length): words = file.readline().split() times.append(float(words[0])) fluxes.append(float(words[1])) times, fluxes = residuals(times, fluxes, 2) for n in range(season_length): newfile.write(str(times[n]) + " " + str(fluxes[n]) + "\n") newfile.write("\n") newfile.close() file.close() # make residual plot data = ascii.read("seasons.by") fig = plt.plot(data["col1"], data["col2"], 'k.') plt.xlabel("Day", fontsize=10) plt.ylabel("Res. Flux", fontsize=10) plt.title("Residuals of Relative Flux", fontsize=15) plt.savefig("residuals.png") # make periodogram t = data["col1"] mag = data["col2"] dmag = 1 #arbitrary, doesn't affect anything baseline = max(t) - min(t) cwd = os.getcwd() starname = cwd.split('/')[-1] ls = LombScargle(t, mag) frequency, power = ls.autopower(minimum_frequency=1 / baseline, maximum_frequency=1 / 2) periods = 1 / frequency best_power = power.max() best_period = periods[list(power).index(best_power)] probabilities = [0.1, 0.05, 0.01] fa_levels = ls.false_alarm_level(probabilities) alpha = 0.01 file = open("/Users/Ilya/Desktop/SURF/best_periods_using_fap.txt", "a") if (best_power > ls.false_alarm_level(alpha)): file.write("{0} {1}\n".format(starname, best_period)) else: file.write("{0}\n".format(starname)) file.close() # make phased data if (best_power > ls.false_alarm_level(alpha)): data = ascii.read(filename) phased_t = [] for element in t: phased_t.append(element % best_period) y_fit = ls.model(phased_t, 1 / best_period) fig, ax = plt.subplots() ax.plot(phased_t, mag, 'k.') ax.plot(phased_t, y_fit, 'b.') plt.savefig("phased.png") plt.show() length = 100 x_values = [1.3**n for n in range(length)] + [1.11] y_values_10 = [fa_levels[0] for n in range(length + 1)] y_values_05 = [fa_levels[1] for n in range(length + 1)] y_values_01 = [fa_levels[2] for n in range(length + 1)] fig, ax = plt.subplots() ax.plot(periods, power, 'k-') ax.plot(x_values, y_values_01, 'b*', markersize=4) ax.plot(x_values, y_values_05, 'b.', markersize=4) ax.plot(x_values, y_values_10, 'b_') ax.set( xlim=(2, baseline * 5), ylim=min(power), xlabel='period (days)', ylabel='Lomb-Scargle Power', xscale='log', title='{0}'.format(starname), ) ax.legend([ "Best Period: {0:.3f} days".format(best_period), "0.01 FAP", "0.05 FAP", "0.10 FAP" ], loc="center right", frameon=False, handlelength=0) plt.savefig("adjusted_periodogram.png")
def main(): names = [ "d-abc_f.by", "d-abc_f.by.001", "d-abc_f.by.002", "d-ab_f.by", "d-ac_f.by", "d-ab_f.by", "c-ab_f.by", "d-bc_f.by", "c-a_f.by", "d-b_f.by", "d-a_f.by" ] names_index = 0 while (names_index < 15): filename = names[names_index] try: file = open(filename) break except: names_index += 1 continue season_lengths = [] last_day = 0 curr_season_length = 0 for line in file.readlines(): words = line.split() day = float(words[0]) if (day - last_day > 1000): #first line last_day = day curr_season_length += 1 continue if (day - last_day > 50): #fix season_lengths.append(curr_season_length) curr_season_length = 0 last_day = day curr_season_length += 1 season_lengths.append(curr_season_length) file.close() newfile = open("seasons.by", "w") file = open(filename) print("Season\tn\tBest Period\tFAP\tp < 0.05 ?") print("-" * 50) t = [] mag = [] for season_number, season_length in enumerate(season_lengths): times = [] fluxes = [] for n in range(season_length): words = file.readline().split() times.append(float(words[0])) fluxes.append(float(words[1])) times, fluxes = residuals(times, fluxes, 2) # fluxes = bandpass.band_pass_filter(times, fluxes, 1/100, 1/4) for n in range(season_length): newfile.write(str(times[n]) + " " + str(fluxes[n]) + "\n") newfile.write("\n") # group seasons groups_of = 6 t += list(times) mag += list(fluxes) if ((season_number + 1) % groups_of == 0 or season_number + 1 == len(season_lengths)): pass else: continue first_season = season_number - groups_of + 2 if (season_number + 1 == len(season_lengths)): first_season = season_number - (season_number % groups_of) + 1 dmag = 1 #arbitrary, doesn't affect anything baseline = max(t) - min(t) ls = LombScargle(t, mag) frequency, power = ls.autopower(minimum_frequency=1 / baseline, maximum_frequency=1 / 2) periods = 1 / frequency best_power = power.max() best_period = periods[list(power).index(best_power)] alpha = 0.05 print("{0}-{4}\t{1}\t{2:.3f}\t\t{3:.4f}\t".format( first_season, len(t), best_period, ls.false_alarm_probability(best_power), season_number + 1), end="") if (best_power > ls.false_alarm_level(alpha)): print("True") else: print("False") t = [] mag = [] newfile.close() file.close() data = ascii.read("seasons.by") # fig = plt.plot(data["col1"], data["col2"], 'k.') # plt.xlabel("Day", fontsize=10) # plt.ylabel("Res. Flux", fontsize=10) # plt.title("Residuals of Relative Flux", fontsize=15) # plt.savefig("residuals.png") # make periodogram t = data["col1"] mag = data["col2"] dmag = 1 #arbitrary, doesn't affect anything baseline = max(t) - min(t) cwd = os.getcwd() starname = cwd.split('/')[-1] ls = LombScargle(t, mag) frequency, power = ls.autopower(minimum_frequency=1 / baseline, maximum_frequency=1 / 2) periods = 1 / frequency best_power = power.max() best_period = periods[list(power).index(best_power)] probabilities = [0.1, 0.05, 0.01] fa_levels = ls.false_alarm_level(probabilities) print("1-{0}\t{1}\t{2:.3f}\t\t{3:.4f}\t".format( len(season_lengths), len(t), best_period, ls.false_alarm_probability(best_power)), end="") alpha = 0.01 if (best_power > ls.false_alarm_level(alpha)): print("True") else: print("False") # file = open("/Users/Ilya/Desktop/SURF/best_periods_using_fap.txt", "a") # if (best_power > ls.false_alarm_level(alpha)): # file.write("{0} {1}\n".format(starname, best_period)) # else: # file.write("{0}\n".format(starname)) # file.close() # make phased data # if (best_power > ls.false_alarm_level(alpha)): # data = ascii.read(filename) # phased_t = [] # for element in t: # phased_t.append(element % best_period) # y_fit = ls.model(phased_t, 1/best_period) # fig, ax = plt.subplots() # ax.plot(phased_t, mag, 'k.') # ax.plot(phased_t, y_fit, 'b.') # plt.savefig("phased.png") # plt.show() length = 100 x_values = [1.3**n for n in range(length)] + [1.11] y_values_10 = [fa_levels[0] for n in range(length + 1)] y_values_05 = [fa_levels[1] for n in range(length + 1)] y_values_01 = [fa_levels[2] for n in range(length + 1)] fig, ax = plt.subplots() ax.plot(periods, power, 'k-') ax.plot(x_values, y_values_01, 'b*', markersize=4) ax.plot(x_values, y_values_05, 'b.', markersize=4) ax.plot(x_values, y_values_10, 'b_') ax.set( xlim=(2, baseline * 5), ylim=min(power), xlabel='period (days)', ylabel='Lomb-Scargle Power', xscale='log', title='{0}'.format(starname), ) ax.legend([ "Best Period: {0:.3f} days".format(best_period), "0.01 FAP", "0.05 FAP", "0.10 FAP" ], loc="center right", frameon=False, handlelength=0) plt.show()
def main(): megafile = pandas.read_csv("../halpha.csv") ids = list(megafile["observation_id"]) times = list(megafile["time"]) starnames = list(megafile["star"]) Ha = list(megafile["Ha"]) C1 = list(megafile["C1"]) # Convert times from UTC into float times = [utc_to_jd(datetime.strptime(time, '%Y-%m-%d %H:%M:%S.%f')) for time in times] # Create list of all star names starlist = [] for starname in starnames: if starname not in starlist: starlist.append(starname) #145675, 201092, 221354 for star in (217107,): print(star) # Create lists of all observations of the star. # Keep the two instruments separate. star_times_a, star_times_h = [], [] star_Ha_a, star_Ha_h = [], [] for i in range(len(Ha)): if (starnames[i] == star): if (ids[i][1] == 'j'): star_times_h.append(times[i]) star_Ha_h.append(Ha[i]) else: star_times_a.append(times[i]) star_Ha_a.append(Ha[i]) # # # # # # # # # # # # # # # # # Data Processing Begins Here # # # # # # # # # # # # # # # # # # Remove data points that are obviously errors star_times_a, star_Ha_a = remove_outliers(star_times_a, star_Ha_a) star_times_h, star_Ha_h = remove_outliers(star_times_h, star_Ha_h) # Apply filter before combining data. Applying the filter will remove long-term # trends that may have affected the two sets separately. star_times_a, star_Ha_a = bandpass.band_pass_filter(star_times_a, star_Ha_a, 1/100, 1/4) star_times_h, star_Ha_h = bandpass.band_pass_filter(star_times_h, star_Ha_h, 1/100, 1/4) # Combine the sets from the two instruments. star_times = star_times_a + star_times_h star_Ha = star_Ha_a + star_Ha_h # Create Lomb-Scargle Periodogram model ls = LombScargle(star_times, star_Ha) baseline = max(star_times) - min(star_times) frequency, power = ls.autopower(minimum_frequency=1/baseline, maximum_frequency=1/2) periods = 1 / frequency # Find the best period within a reasonable range best_power = 0 best_period = 1 for i, p in enumerate(power): if (periods[i] > 4 and periods[i] < 80): if (p > best_power): best_power = p best_period = periods[i] # # # # # # # # # # # # # # # # Data Processing Ends Here # # # # # # # # # # # # # # # # FAP = ls.false_alarm_probability(best_power) alpha = 0.001 # Record best period in a file # if (FAP < 1): # file = open("/Users/Ilya/Desktop/SURF/halpha_periods_catalog.txt", "a") # file.write("hd{0}\t{1}\t{2}\n".format(star, str(best_period), str(FAP))) # file.close() # Make plot fig, axs = plt.subplots(3, 1, sharex=False) # Plot filtered data axs[0].plot(star_times, star_Ha, 'k.') axs[0].set(title="hd{0}".format(star)) # Plot periodogram axs[1].plot(periods, power, 'k-') axs[1].set(xlim=(min(periods), max(periods)), ylim=min(power), xlabel='Period (JD)', ylabel='Lomb-Scargle Power', xscale='log') # Plot phased data phased_t = [time % float(best_period) for time in star_times] axs[2].plot(phased_t, star_Ha, 'k.') # Plot best-fit model on top of phased data n = 300 model_t = [i / n * float(best_period) for i in range(n)] y_fit = ls.model(model_t, 1/best_period) axs[2].plot(model_t, y_fit, 'b.') # Add line to periodogram representing FAP = alpha n = 100 x_values = [1.3**i for i in range(n)] + [1.11] y_values_alpha = [ls.false_alarm_level(alpha) for i in range(n + 1)] axs[1].plot(x_values, y_values_alpha, 'b_') axs[1].legend(["{0} FAP".format(alpha)], loc="upper right", frameon=False, handlelength=0) # Plot aliases, harmonics and sampling periods on the periodogram as vertical lines. f_sampling = [1/1, 1/29.5, 1/365] aliases, harmonics = find_aliases(1 / best_period, [-2, -1, 1, 2], f_sampling) for alias in aliases: axs[1].axvline(alias, c="grey") for harmonic in harmonics: axs[1].axvline(harmonic, c="blue") for f in f_sampling: axs[1].axvline(1/f, c="green") plt.show()
def pixel_by_pixel(self, colrange=None, rowrange=None, cmap='viridis', data_type="corrected", mask=None, xlim=None, ylim=None, color_by_pixel=False, color_by_aperture=True, freq_range=[1 / 20., 1 / 0.1], FAP=None, aperture=None, ap_color='r', ap_linewidth=2): """ Creates a pixel-by-pixel light curve using the corrected flux. Contribution from Oliver Hall. Parameters ---------- colrange : np.array, optional A list of start column and end column you're interested in zooming in on. rowrange : np.array, optional A list of start row and end row you're interested in zooming in on. cmap : str, optional Name of a matplotlib colormap. Default is 'viridis'. data_type : str, optional The type of flux used. Either: 'raw', 'corrected', 'amplitude', or 'periodogram'. If not, default set to 'corrected'. mask : np.array, optional Specifies the cadences used in the light curve. If not, default set to good quality cadences. xlim : np.array, optional Specifies the xlim on the subplots. If not, default is set to the entire light curve. ylim : np.array, optional Specifies the ylim on the subplots, If not, default is set to the entire light curve flux range. color_by_pixel : bool, optional Colors the light curve given the color of the pixel. If not, default is set to False. freq_range : list, optional List of minimum and maximum frequency to search in Lomb Scargle periodogram. Only used if data_type = 'periodogram'. If None, default = [1/20., 1/0.1]. FAP: np.array, optional. False Alarm Probability levels to include in periodogram. Ensure that the values are < 1. For example: FAP = np.array([0.1, 0.01]), will plot the 10% and 1% FAP levels. """ if self.obj.lite: print( 'This is an eleanor-lite object. No pixel_by_pixel visualization can be created.' ) print( 'Please create a regular eleanor.TargetData object (lite=False) to use this tool.' ) return if colrange is None: colrange = [0, self.dimensions[1]] if rowrange is None: rowrange = [0, self.dimensions[0]] nrows = int(np.round(colrange[1] - colrange[0])) ncols = int(np.round(rowrange[1] - rowrange[0])) if (colrange[1] > self.dimensions[1]) or (rowrange[1] > self.dimensions[0]): raise ValueError( "Asking for more pixels than available in the TPF.") figure = plt.figure(figsize=(20, 8)) outer = gridspec.GridSpec(1, 2, width_ratios=[1, 4]) inner = gridspec.GridSpecFromSubplotSpec(ncols, nrows, hspace=0.1, wspace=0.1, subplot_spec=outer[1]) i, j = rowrange[0], colrange[0] if mask is None: q = self.obj.quality == 0 else: q = mask == 0 ## PLOTS TARGET PIXEL FILE ## ax = plt.subplot(outer[0]) if aperture is None: aperture = self.obj.aperture plotflux = np.nanmedian(self.flux[:, rowrange[0]:rowrange[1], colrange[0]:colrange[1]], axis=0) c = ax.imshow(plotflux, origin='lower', vmax=np.percentile(plotflux, 95), cmap=cmap) divider = make_axes_locatable(ax) cax = divider.append_axes('right', size='5%', pad=0.15) plt.colorbar(c, cax=cax, orientation='vertical') f = lambda x, y: aperture[int(y), int(x)] g = np.vectorize(f) x = np.linspace(colrange[0], colrange[1], nrows * 100) y = np.linspace(rowrange[0], rowrange[1], ncols * 100) X, Y = np.meshgrid(x[:-1], y[:-1]) Z = g(X[:-1], Y[:-1]) ax.contour(Z, [0.05], colors=ap_color, linewidths=[ap_linewidth], extent=[0 - 0.5, nrows - 0.5, 0 - 0.5, ncols - 0.5]) ## PLOTS PIXEL LIGHT CURVES ## for ind in range(int(nrows * ncols)): if ind == 0: ax = plt.Subplot(figure, inner[ind]) origax = ax else: ax = plt.Subplot(figure, inner[ind], sharex=origax) flux = self.flux[:, i, j] time = self.obj.time corr_flux = self.obj.corrected_flux(flux=flux) if data_type.lower() == 'corrected': y = corr_flux[q] / np.nanmedian(corr_flux[q]) x = time[q] elif data_type.lower() == 'amplitude': lc = lk.LightCurve(time=time, flux=corr_flux) pg = lc.normalize().to_periodogram() x = pg.frequency.value y = pg.power.value elif data_type.lower() == 'raw': y = flux[q] / np.nanmedian(flux[q]) x = time[q] elif data_type.lower() == 'periodogram': LS = LombScargle(time, corr_flux) freq, power = LS.autopower(minimum_frequency=freq_range[0], maximum_frequency=freq_range[1], method='fast') y = power x = 1 / freq if (FAP is not None): if np.all(FAP < 1 ): # Ensure that the probabilities are all < 1 if type(FAP) == list: FAP = np.array(FAP) FAPlevel = LS.false_alarm_level(FAP, method='baluev') if color_by_pixel is False: color = 'k' else: rgb = c.cmap(c.norm(self.flux[100, i, j])) color = matplotlib.colors.rgb2hex(rgb) ax.plot(x, y, c=color) if (data_type.lower() == 'periodogram') & (FAP is not None): if np.all(FAP < 1): _ = [ ax.axhline(f, color='k', ls='--', alpha=0.3) for f in FAPlevel ] if color_by_aperture and aperture[i, j] > 0: for iax in ['top', 'bottom', 'left', 'right']: ax.spines[iax].set_color(ap_color) ax.spines[iax].set_linewidth(ap_linewidth) j += 1 if j == colrange[1]: i += 1 j = colrange[0] if ylim is None: ax.set_ylim(np.percentile(y, 1), np.percentile(y, 99)) else: ax.set_ylim(ylim[0], ylim[1]) if xlim is None: ax.set_xlim(np.min(x) - 0.1, np.max(x) + 0.1) else: ax.set_xlim(xlim[0], xlim[1]) if data_type.lower() == 'amplitude': ax.set_yscale('log') ax.set_xscale('log') ax.set_ylim(y.min(), y.max()) ax.set_xlim(np.min(x), np.max(x)) ax.set_xticks([]) ax.set_yticks([]) figure.add_subplot(ax) return figure
def estimate_period_old(time, y, y_err, periodogram_kwargs=None, astropy_kwargs=None, wotan_kwargs=None, options=None): ''' Parameters ---------- time : TYPE DESCRIPTION. y : TYPE DESCRIPTION. y_err : TYPE DESCRIPTION. periodogram_kwargs : TYPE, optional DESCRIPTION. The default is None. astropy_kwargs : TYPE, optional DESCRIPTION. The default is None. wotan_kwargs : TYPE, optional DESCRIPTION. The default is None. options : None or dictionary, optional The default is None, which will evaluate to: options = {} options['show_plot'] = True #show a plot in the terminal? options['save_plot'] = True #save a plot? options['fname_plot'] = 'periodogram' #filenmae of the plot options['outdir'] = '.' #output directory for the plot If a dictionary is given, it may contain and overwrite all these keys. Returns ------- None. ''' #========================================================================== #::: handle inputs #========================================================================== cadence = np.nanmedian(np.diff(time)) if periodogram_kwargs is None: periodogram_kwargs = {} if 'minperiod' not in periodogram_kwargs: periodogram_kwargs['minperiod'] = 10. * cadence if 'maxperiod' not in periodogram_kwargs: periodogram_kwargs['maxperiod'] = time[-1] - time[0] if astropy_kwargs is None: astropy_kwargs = {} if 'sigma' not in astropy_kwargs: astropy_kwargs['sigma'] = 5 if wotan_kwargs is None: wotan_kwargs = {} if 'slide_clip' not in wotan_kwargs: wotan_kwargs['slide_clip'] = {} if 'window_length' not in wotan_kwargs['slide_clip']: wotan_kwargs['slide_clip']['window_length'] = 1. if 'low' not in wotan_kwargs['slide_clip']: wotan_kwargs['slide_clip']['low'] = 5 if 'high' not in wotan_kwargs['slide_clip']: wotan_kwargs['slide_clip']['high'] = 5 if options is None: options = {} if 'show_plot' not in options: options['show_plot'] = False if 'save_plot' not in options: options['save_plot'] = False if 'return_plot' not in options: options['return_plot'] = False if 'fname_plot' not in options: options['fname_plot'] = 'periodogram' if 'outdir' not in options: options['outdir'] = '.' minfreq = 1. / periodogram_kwargs['maxperiod'] maxfreq = 1. / periodogram_kwargs['minperiod'] #========================================================================== #::: first, a global 5 sigma clip #========================================================================== ff = sigma_clip(time, np.ma.masked_invalid(y), low=astropy_kwargs['sigma'], high=astropy_kwargs['sigma']) #astropy wants masked arrays # ff = np.array(ff.filled(np.nan)) #use NaN instead of masked arrays, because masked arrays drive me crazy #========================================================================== #::: fast slide clip (1 day, 5 sigma) [replaces Wotan's slow slide clip] #========================================================================== try: ff = slide_clip(time, ff, **wotan_kwargs['slide_clip']) except: print('Fast slide clip failed and was skipped.') #========================================================================== #::: now do the periodogram #========================================================================== ind_notnan = np.where(~np.isnan(time * ff * y_err)) ls = LombScargle( time[ind_notnan], ff[ind_notnan] ) #Analyze our dates and s-index data using the AstroPy Lomb Scargle module frequency, power = ls.autopower( minimum_frequency=minfreq, maximum_frequency=maxfreq) #Determine the LS periodogram best_power = np.nanmax(power) best_frequency = frequency[np.argmax(power)] FAP = ls.false_alarm_probability( best_power) #Calculate the FAP for the highest peak in the power array #========================================================================== #::: plots #========================================================================== if options['show_plot'] or options['save_plot'] or options['return_plot']: peak_loc = round(float(1. / best_frequency), 2) FAP_probabilities = [0.5, 0.1, 0.01] #Enter FAP values you want to determine FAP_levels = ls.false_alarm_level( FAP_probabilities) #Get corresponding LS Power values fig, axes = plt.subplots(4, 1, figsize=[10, 15], tight_layout=True) # axes = np.atleast_1d(axes) # ax = axes[0] # ind_clipped = np.where(np.isnan(ff))[0] # ax.plot(time[ind_clipped], flux[ind_clipped], 'r.', rasterized=True) # ax.plot(time, ff, 'b.', rasterized=True) # ax.set(xlabel='Time (BJD)', ylabel='Flux') # ax = axes[1] # ax.plot(time, ff, 'b.', rasterized=True) # ax.set(xlabel='Time (BJD)', ylabel='Flux (clipped)') ax = axes[0] ax.semilogx(1. / frequency, power, color='b') ax.plot(peak_loc, best_power, marker='d', markersize=12, color='r') ax.text(peak_loc * 1.2, best_power * 0.95, 'Peak Period: ' + str(peak_loc) + ' days') ax.text(peak_loc * 1.2, best_power * 0.85, 'FAP: ' + str(FAP)) ax.hlines(FAP_levels, periodogram_kwargs['minperiod'], periodogram_kwargs['maxperiod'], color='grey', lw=1) ax.text(periodogram_kwargs['maxperiod'], FAP_levels[0], '0.5% FAP ', ha='right') ax.text(periodogram_kwargs['maxperiod'], FAP_levels[1], '0.1% FAP ', ha='right') ax.text(periodogram_kwargs['maxperiod'], FAP_levels[2], '0.01% FAP ', ha='right') ax.set(xlabel='Period (days)', ylabel='L-S power') ax.tick_params(axis='both', which='major') # ax.text(peak_loc*1.2,best_power*0.75,'std_old:'+str(std_old*1e3)[0:4]+' --> '+'std_new:'+str(std_new*1e3)[0:4]) ax = axes[1] plot_phase_folded_lightcurve(time, ff, period=1. / best_frequency, epoch=0, ax=ax) ax.set(ylim=[np.nanmin(ff), np.nanmax(ff)], ylabel='Data (clipped; phased)') ax = axes[2] plot_phase_folded_lightcurve(time, ff, period=1. / best_frequency, epoch=0, ax=ax) ax.set(ylabel='Data (clipped; phased; y-zoom)') #::: plot the autocorrelation of the data ax = axes[3] plot_acf(pd.Series(ff[ind_notnan], index=time[ind_notnan]), ax=ax, lags=np.linspace(start=1, stop=2000, num=100, dtype=int)) ax.set(xlabel='Lag', ylabel='Autocorrelation', title='') if options['save_plot']: if not os.path.exists(options['outdir']): os.makedirs(options['outdir']) fig.savefig(os.path.join(options['outdir'], options['fname_plot'] + '.pdf'), bbox_inches='tight') if options['show_plot']: plt.show(fig) else: plt.close(fig) if options['return_plot'] is True: return 1. / best_frequency, FAP, axes else: return 1. / best_frequency, FAP
def LS_estimator(x, y, fsamp=None, fap=0.1, return_levels=False, max_peaks=2): """ Generates a Lomb-Scargle periodogram and identifies significant frequencies from a data series Assumes that data are nearly evenly sampled Optimized for finding marginal periodic TTV signals in OMC data; may not perform well for other applications Parameters ---------- x : array-like 1D array of x data values; should be monotonically increasing y : array-like 1D array of corresponding y data values, len(x) fsamp: float nominal sampling frequency; if not provided it will be calculated from the data fap : float false alarm probability threshold to consider a frequency significant (default=0.1) Returns ------- xf : ndarray 1D array of frequencies yf : ndarray 1D array of corresponding response freqs : list signficant frequencies faps : list corresponding false alarm probabilities """ # get sampling frequency if fsamp is None: fsamp = 1 / np.min(x[1:] - x[:-1]) # Hann window to reduce ringing hann = sig.windows.hann(len(x)) hann /= np.sum(hann) # identify any egregious outliers out = np.abs(y - np.median(y)) / astropy.stats.mad_std(y) > 5.0 xt = x[~out] yt = y[~out] freqs = [] faps = [] loop = True while loop: lombscargle = LombScargle(xt, yt * hann[~out]) xf, yf = lombscargle.autopower(minimum_frequency=2.0/(xt.max()-xt.min()), \ maximum_frequency=0.25*fsamp, \ samples_per_peak=10) peak_freq = xf[np.argmax(yf)] peak_fap = lombscargle.false_alarm_probability(yf.max(), method='bootstrap') # output first iteration of LS periodogram if len(freqs) == 0: xf_out = xf.copy() yf_out = yf.copy() levels = lombscargle.false_alarm_level([0.1, 0.01, 0.001]) if peak_fap < fap: yt -= lombscargle.model(xt, peak_freq) * len(xt) freqs.append(peak_freq) faps.append(peak_fap) else: loop = False if len(freqs) >= max_peaks: loop = False if return_levels: return xf_out, yf_out, freqs, faps, levels else: return xf_out, yf_out, freqs, faps
def estimate_period(time, flux, flux_err, periodogram_kwargs=None, astropy_kwargs=None, wotan_kwargs=None, options=None): #========================================================================== #::: handle inputs #========================================================================== cadence = np.nanmedian(np.diff(time)) if periodogram_kwargs is None: periodogram_kwargs = {} if 'minperiod' not in periodogram_kwargs: periodogram_kwargs['minperiod'] = 10. * cadence if 'maxperiod' not in periodogram_kwargs: periodogram_kwargs['maxperiod'] = time[-1] - time[0] if astropy_kwargs is None: astropy_kwargs = {} if 'sigma' not in astropy_kwargs: astropy_kwargs['sigma'] = 5 if wotan_kwargs is None: wotan_kwargs = {} if 'slide_clip' not in wotan_kwargs: wotan_kwargs['slide_clip'] = {} if 'window_length' not in wotan_kwargs['slide_clip']: wotan_kwargs['slide_clip']['window_length'] = 1. if 'low' not in wotan_kwargs['slide_clip']: wotan_kwargs['slide_clip']['low'] = 5 if 'high' not in wotan_kwargs['slide_clip']: wotan_kwargs['slide_clip']['high'] = 5 if options is None: options = {} if 'show_plot' not in options: options['show_plot'] = False if 'save_plot' not in options: options['save_plot'] = False if 'fname_plot' not in options: options['fname_plot'] = 'periodogram' if 'outdir' not in options: options['outdir'] = '.' minfreq = 1. / periodogram_kwargs['maxperiod'] maxfreq = 1. / periodogram_kwargs['minperiod'] #========================================================================== #::: first, a global 5 sigma clip #========================================================================== ff = sigma_clip( np.ma.masked_invalid(flux), sigma=astropy_kwargs['sigma']) #astropy wants masked arrays ff = np.array( ff.filled(np.nan) ) #use NaN instead of masked arrays, because masked arrays drive me crazy #========================================================================== #::: fast slide clip (1 day, 5 sigma) [replaces Wotan's slow slide clip] #========================================================================== try: ff = fast_slide_clip(time, ff, **wotan_kwargs['slide_clip']) except: print('Fast slide clip failed and was skipped.') #========================================================================== #::: now do the periodogram #========================================================================== ind_notnan = np.where(~np.isnan(time * ff * flux_err)) ls = LombScargle( time[ind_notnan], ff[ind_notnan] ) #Analyze our dates and s-index data using the AstroPy Lomb Scargle module frequency, power = ls.autopower( minimum_frequency=minfreq, maximum_frequency=maxfreq) #Determine the LS periodogram best_power = np.nanmax(power) best_frequency = frequency[np.argmax(power)] FAP = ls.false_alarm_probability( best_power) #Calculate the FAP for the highest peak in the power array #========================================================================== #::: plots #========================================================================== if options['show_plot'] or options['save_plot']: peak_loc = round(float(1. / best_frequency), 2) FAP_probabilities = [0.5, 0.1, 0.01] #Enter FAP values you want to determine FAP_levels = ls.false_alarm_level( FAP_probabilities) #Get corresponding LS Power values fig, axes = plt.subplots(5, 1, figsize=[10, 15], tight_layout=True) axes = np.atleast_1d(axes) ax = axes[0] ind_clipped = np.where(np.isnan(ff))[0] ax.plot(time[ind_clipped], flux[ind_clipped], 'r.', rasterized=True) ax.plot(time, ff, 'b.', rasterized=True) ax.set(xlabel='Time (BJD)', ylabel='Flux') ax = axes[1] ax.plot(time, ff, 'b.', rasterized=True) ax.set(xlabel='Time (BJD)', ylabel='Flux (clipped)') ax = axes[2] ax.semilogx(1. / frequency, power, color='b') ax.plot(peak_loc, best_power, marker='d', markersize=12, color='r') ax.text(peak_loc * 1.2, best_power * 0.95, 'Peak Period: ' + str(peak_loc) + ' days') ax.text(peak_loc * 1.2, best_power * 0.85, 'FAP: ' + str(FAP)) ax.hlines(FAP_levels, periodogram_kwargs['minperiod'], periodogram_kwargs['maxperiod'], color='grey', lw=1) ax.text(periodogram_kwargs['maxperiod'], FAP_levels[0], '0.5% FAP ', ha='right') ax.text(periodogram_kwargs['maxperiod'], FAP_levels[1], '0.1% FAP ', ha='right') ax.text(periodogram_kwargs['maxperiod'], FAP_levels[2], '0.01% FAP ', ha='right') ax.set(xlabel='Period (days)', ylabel='L-S power') ax.tick_params(axis='both', which='major') # ax.text(peak_loc*1.2,best_power*0.75,'std_old:'+str(std_old*1e3)[0:4]+' --> '+'std_new:'+str(std_new*1e3)[0:4]) ax = axes[3] plot_phase_folded_lightcurve(time, ff, period=1. / best_frequency, epoch=0, ax=ax) ax.set(ylim=[np.nanmin(ff), np.nanmax(ff)], ylabel='Flux (clipped)', xticklabels=[]) ax = axes[4] plot_phase_folded_lightcurve(time, ff, period=1. / best_frequency, epoch=0, ax=ax) ax.set(ylabel='Flux (clipped; y-zoom)') if options['save_plot']: if not os.path.exists(options['outdir']): os.makedirs(options['outdir']) fig.savefig(os.path.join(options['outdir'], options['fname_plot'] + '.pdf'), bbox_inches='tight') if options['show_plot']: plt.show(fig) else: plt.close(fig) return 1. / best_frequency, FAP