示例#1
0
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()
示例#2
0
    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
示例#3
0
    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
示例#4
0
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]
示例#5
0
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]
示例#6
0
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]
示例#7
0
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]
示例#8
0
    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)
示例#9
0
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]
示例#10
0
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
    ]
示例#11
0
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
    ]
示例#12
0
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]
示例#13
0
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]
示例#14
0
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]
示例#15
0
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]
示例#16
0
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()
示例#17
0
    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)
示例#18
0
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
示例#19
0
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)
示例#21
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
示例#22
0
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
示例#23
0
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
示例#24
0
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")
示例#25
0
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()
示例#27
0
    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
示例#28
0
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
示例#29
0
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
示例#30
0
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