コード例 #1
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
コード例 #2
0
    def set_power_period(self, nt=5, min_p=1, max_p=100, n_f=10000, auto=True, method='LS_astropy'):
        self.pmin = min_p
        self.pmax = max_p
        self.method = method
        if self.method == 'LS_astropy':
            if auto:
                ls = LombScargle(self.df.t.values, self.df.m.values, self.df.dflux.values, nterms=nt)
                self.frequency, self.power = ls.autopower(minimum_frequency=1. / self.pmax,
                                                          maximum_frequency=1. / self.pmin)
            else:
                self.frequency = np.linspace(1. / self.pmax, 1. / self.pmin, n_f)
                self.power = LombScargle(self.df.t.values, self.df.m.values, self.df.dflux.values).power(self.frequency)

        elif self.method == 'BLS_astropy':
            model = BoxLeastSquares(self.df.t.values, self.df.m.values, dy=self.df.dflux.values)
            if auto:
                periodogram = model.autopower(0.2)
                self.frequency = 1. / periodogram.period
                self.power = periodogram.power
            else:
                periods = np.linspace(self.pmin, self.pmax, 10)
                periodogram = model.power(periods, 0.2)
                self.frequency = 1. / periodogram.period
                self.power = periodogram.power
        else:
            print('Method should be chosen between these options:')
            print('LS_astropy, BLS_astropy')
            sys.exit()
        # setting_period
        period = (1. / self.frequency[np.argmax(self.power)])
        print("p f p-f", period, np.fix(period), period-np.fix(period))
        if period - np.fix(period) < 0.009:
            self.period = (1. / self.frequency[(np.asarray(self.power).argsort()[-2])])
        else:
            self.period = period
コード例 #3
0
ファイル: sf_active.py プロジェクト: l631768226/cal
    def period_mining(self, user_df: pd.DataFrame):
        """设置用户初始时间为0将时间转化为时间序列(0,1,2,...)(小时), 得到单个用户全部活动的周期"""

        def get_time_intervals(t, base_t):
            """返回 t减去base_t的小时数"""
            diff = pd.to_datetime(t) - pd.to_datetime(base_t)
            return diff.days * 24 + diff.seconds / 3600

        x = np.array(user_df['localtime'].apply(lambda t: get_time_intervals(t, user_df['localtime'].min())))
        y = user_df['placeID'].to_numpy()
        # 遍历全部的placeID对某个单独的placeID进行周期提取
        for place_id in np.unique(y):
            y_copy = y.copy()
            # 将其他place_id设为 -1
            y_copy[y_copy != place_id] = -1
            # 控制最大频率(频率范围),因为知道周期不会小于1小时,则频率必定落在(0, 1)中
            ls = LombScargle(x, y_copy)
            frequency, power = ls.autopower(minimum_frequency=0.0001, maximum_frequency=1)
            try:
                period = 1 / frequency[np.where(power > power.max() * 0.5)]
                # period = 1 / frequency[np.where(power == power.max())]
                self.periods[str(place_id)] = round(period.max()[0], 2)
            except (ValueError, IndexError):
                # 没有周期性的时候将周期设置为-1表示没有周期性
                self.periods[str(place_id)] = -1
        return self.periods
コード例 #4
0
ファイル: TESSutils.py プロジェクト: ipelisoli/TESS-LS
    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
コード例 #5
0
def lombscargle(time, relFlux):
    LS = LombScargle(time, relFlux)
    frequency, power = LS.autopower(minimum_frequency=1 / 27, maximum_frequency=1 / .1)
    bestPeriod = 1 / frequency[np.argmax(power)]
    maxPower = np.max(power)
    period = 1 / frequency

    return period, power, bestPeriod, maxPower
コード例 #6
0
ファイル: lc_preparation.py プロジェクト: mar-ses/lcnm
def find_periodicity_peak(t, f, plims=None, plot=False):
    """Calculates the Lomb-Scargle periodogram of a timeseries.

    Default threshold for the false-alarm probability is now
    set to 10**-30 (k2sc is 1e-50). Perhaps a more
    specific metric should be used (i.e amplitude of wave
    vs white noise).

    Args:
        t
        f
        plims (tuple): upper and lower bound for periods
            to calculate the periodogram on. Default: [0.5, 15]

    Returns:
        max_period (float): value of the most valid peak
        threshhold_flag (bool): True if passes the threshold
        pfa (float): probability of false alarm
            P(peak max | gaussian noise)
        lsp (pd.DataFrame): 'frequency', 'period', 'power'
    """

    threshold_fa = 1e-30

    plims = plims if plims is not None else (0.5, 15)

    ls = LombScargle(t, f)

    freqs, power = ls.autopower(minimum_frequency=1 / max(plims),
                                maximum_frequency=1 / min(plims))
    periods = 1.0 / freqs
    lsp = pd.DataFrame({'frequency': freqs, 'period': periods, 'power': power})

    max_period = periods[np.argmax(power)]

    pfa = ls.false_alarm_probability(power.max())

    threshhold_flag = True if pfa < threshold_fa else False

    if plot:
        fig, ax = plt.subplots(3)

        ax[0].plot(t, f, 'k.')
        ax[0].set_xlabel('t')
        ax[0].set_ylabel('f')

        ax[1].plot(lc_utils.fold_on_first(t, max_period), f, 'k.')
        ax[1].set_xlabel('t')
        ax[1].set_ylabel('f')

        ax[2].plot(periods, power, 'k-')
        ax[2].set_xlabel('period')
        ax[2].set_ylabel('power')
        fig.show()

    return max_period, threshhold_flag, pfa, lsp
コード例 #7
0
def computeperiod(npjdmag):
    JDtime = npjdmag[:, 0]
    targetflux = npjdmag[:, 1]
    ls = LombScargle(JDtime, targetflux, normalization='model')
    frequency, power = ls.autopower(minimum_frequency=0.025,
                                    maximum_frequency=20)
    index = np.argmax(power)
    maxpower = np.max(power)
    period = 1 / frequency[index]
    wrongP = ls.false_alarm_probability(power.max())
    return period, wrongP, maxpower
コード例 #8
0
ファイル: estimators.py プロジェクト: emilygilbert/exoplanet
def lomb_scargle_estimator(
    x,
    y,
    yerr=None,
    min_period=None,
    max_period=None,
    filter_period=None,
    max_peaks=2,
    **kwargs,
):
    """Estimate period of a time series using the periodogram

    Args:
        x (ndarray[N]): The times of the observations
        y (ndarray[N]): The observations at times ``x``
        yerr (Optional[ndarray[N]]): The uncertainties on ``y``
        min_period (Optional[float]): The minimum period to consider
        max_period (Optional[float]): The maximum period to consider
        filter_period (Optional[float]): If given, use a high-pass filter to
            down-weight period longer than this
        max_peaks (Optional[int]): The maximum number of peaks to return
            (default: 2)

    Returns:
        A dictionary with the computed ``periodogram`` and the parameters for
        up to ``max_peaks`` peaks in the periodogram.

    """
    if min_period is not None:
        kwargs["maximum_frequency"] = 1.0 / min_period
    if max_period is not None:
        kwargs["minimum_frequency"] = 1.0 / max_period

    # Estimate the power spectrum
    model = LombScargle(x, y, yerr)
    freq, power = model.autopower(method="fast", normalization="psd", **kwargs)
    power /= len(x)
    power_est = np.array(power)

    # Filter long periods
    if filter_period is not None:
        freq0 = 1.0 / filter_period
        filt = 1.0 / np.sqrt(1 + (freq0 / freq)**(2 * 3))
        power *= filt

    # Find and fit peaks
    peaks = find_peaks(freq, power, max_peaks=max_peaks)

    return dict(periodogram=(freq, power_est), peaks=peaks, ls=model)
コード例 #9
0
    def period_finder(self,
                      nt=5,
                      min_p=1,
                      max_p=100,
                      n_f=10000,
                      auto=True,
                      method='LS_astropy'):

        self.pmin = min_p
        self.pmax = max_p
        self.method = method

        if self.method == 'LS_astropy':
            if auto:
                ls = LombScargle(self.df.t.values,
                                 self.df.m.values,
                                 self.df.e.values,
                                 nterms=nt)
                self.frequency, self.power = ls.autopower(
                    minimum_frequency=1. / self.pmax,
                    maximum_frequency=1. / self.pmin)
            else:
                self.frequency = np.linspace(1. / self.pmax, 1. / self.pmin,
                                             n_f)
                self.power = LombScargle(self.df.t.values, self.df.m.values,
                                         self.df.e.values).power(
                                             self.frequency)

        elif self.method == 'BLS_astropy':
            model = BoxLeastSquares(self.df.t.values * u.day,
                                    self.df.m.values,
                                    dy=self.df.e.values)
            if auto:
                periodogram = model.autopower(0.2)
                self.frequency = 1. / periodogram.period
                self.power = periodogram.power
            else:
                periods = np.linspace(self.pmin, self.pmax, 10)
                periodogram = model.power(periods, 0.2)
                self.frequency = 1. / periodogram.period
                self.power = periodogram.power
        else:
            print('Method should be chosen between these options:')
            print('LS_astropy, BLS_astropy')
            sys.exit()

        self.set_period()
        self.plot_ls()
コード例 #10
0
def get_GLS(t, rv, rv_error):
    """ compute the Generalized Lomb-Scargle periodogram.

    Notes
    -----
    The irregularly-sampled data enables frequencies much higher than the
    average Nyquist frequency.
    """
    ls = LombScargle(t, rv, rv_error, fit_mean=True)
    frequency, power = ls.autopower(
    )  # minimum_frequency=f_min, maximum_frequency = f_max) ### automated f limits from baseline and Nyquist factor
    i_peak = np.argmax(power)
    peakFrequency = frequency[i_peak]
    peakPower = power[i_peak]
    FAP = ls.false_alarm_probability(peakPower, method='bootstrap')
    return peakFrequency, peakPower, FAP, ls
コード例 #11
0
ファイル: backup.py プロジェクト: l631768226/cal
    def period_mining(user_df: pd.DataFrame):
        """设置用户初始时间为0将时间转化为时间序列(0,1,2,...)(小时), 得到单个用户全部活动的周期"""
        def get_time_intervals(t, base_t):
            """返回 t减去base_t的小时数"""
            diff = pd.to_datetime(t) - pd.to_datetime(base_t)
            return round(diff.days * 24 + diff.seconds / 3600)

        checkin_time = np.array(user_df['localtime'].apply(
            lambda t: get_time_intervals(t, user_df['localtime'].min())))
        checkin_id = user_df['placeID'].to_numpy()
        periods = {}
        # 遍历全部的placeID对某个单独的placeID进行周期提取
        for cur_id in np.unique(checkin_id):
            # print("打卡地点:", cur_id)
            # 选择出当前id的打卡时间列表
            cur_checkin_time = checkin_time[checkin_id == cur_id]
            # 以最大打卡时间范围为x轴,最小为y轴, 间隔1建立横轴
            x = np.arange(cur_checkin_time.min(), cur_checkin_time.max())
            y = []
            # 在打卡时间内的设置为cur_id值,其余的设置为0,建立y轴
            for i in range(cur_checkin_time.min(), cur_checkin_time.max()):
                y.append(cur_id if i in list(cur_checkin_time) else 0)
            y = np.array(y)
            ls = LombScargle(x, y)
            # 控制最大频率(频率范围),因为知道周期不会小于3/24小时,则频率必定落在(0, 1)中, 最大频率设置为8个月至少访问5次,8/5 * 30 * 24
            frequency = None
            try:
                frequency, power = ls.autopower(minimum_frequency=1 /
                                                ((8 / 5) * 30 * 24),
                                                maximum_frequency=3 / 24)
                # 如果没有符合条件的说明没有周期性
                if frequency.size:
                    # 选取满足条件的周期中最大的,并保留两位小数
                    periods[str(cur_id)] = [
                        round(1 /
                              frequency[np.where(power == power.max())][0]),
                        round(ls.false_alarm_probability(power.max()), 3)
                    ]
                else:
                    # 没有周期性的时候将周期设置为-1表示没有周期性
                    periods[str(cur_id)] = [-1, 1]
            except Exception as e:
                print(e, frequency)
                periods[str(cur_id)] = [-1, 1]
                continue
        return periods
コード例 #12
0
    def gls(self,
            col_x='Julian Date',
            col_y='Radial Velocity (m/s)',
            err_col='Error (m/s)'):
        """
        Computes a generalized lomb-scargle periodogram on the object time series, as
        described by Zechmeister et al. (2009). The default format for col1 and col2 is
        the HiRES publicly available radial velocity data (Butler, Vogt, Laughlin et al. 2017).

        :param col_x: a string, the name of the column containing the x-values (time stamps).
        :param col_y: a string, the name of the column containing the y-values (radial velocities).
        :param err_col: a string, the name of the columm containing the radial velocity errors.
        :return: the period, power, and false alarm probability for each signal detected with the periodogram.
        Moreover, the lsdf pandas DataFrame is updated with the contents of the period, power, and FAP arrays.
        """

        # Compute Generalized Lomb-Scargle periodogram (Zechmeister et al. 2009)
        ls = LombScargle(self.df[col_x],
                         self.df[col_y],
                         self.df[err_col],
                         fit_mean=True)

        frequency, power = ls.autopower(method="slow")

        # Compute false alarm probability for each signal.
        fap = []
        print("Starting Bootstrap FAP extrapolation process...")
        for pow_ in power:
            # append(ls.false_alarm_probability(pow_, method='bootstrap'))
            fap.append(ls.false_alarm_probability(pow_))
        print("Finished Bootstrap FAP extrapolation process.")
        fap = np.array(fap)
        period_ = 1 / frequency
        df = pd.DataFrame({'Period': period_, 'Power': power, 'FAP': fap})
        self.lsdf = df

        print(
            "Saving the Period, Power, and FAP dataset to a csv at the directory "
            + self.dir + "...")
        self.lsdf.to_csv(self.dir + '_LombScarglePeriodogramResults.csv')
        print("Done!")
        self.lsdf = self.lsdf.reset_index(drop=True)
        return period_, power, fap
コード例 #13
0
def window(t, n=5):
    """Computes the periodogram of the window function.

    Parameters
    ----------
    t: array-like
        Timestamps of the sampling comb window.
    n: float, optional
        Samples per peak (default is 5).
    Returns
    -------
    f: ndarray
        Frequency array.
    a: ndarray
        Power array.
    """
    ls = LombScargle(t, 1, fit_mean=False, center_data=False)
    f, a = ls.autopower(minimum_frequency=0, samples_per_peak=n)
    return f, a
コード例 #14
0
ファイル: bandpass.py プロジェクト: ilyasher/star-rotation
def find_best_period(t, y, FAP=False, return_model=False):
    baseline = max(t) - min(t)
    ls = LombScargle(t, y)
    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)]
    if (FAP):
        FAP = ls.false_alarm_probability(best_power)
        if (return_model):
            return (best_period, FAP, ls)
        else:
            return (best_period, FAP)
    else:
        if (return_model):
            return (best_period, ls)
        else:
            return best_period
コード例 #15
0
def periodogram(times, data):

    # Create Lomb-Scargle Periodogram model
    ls = LombScargle(times, data)
    baseline = max(times) - min(times)
    frequency, power = ls.autopower(minimum_frequency=1/baseline, maximum_frequency=1/(1/10))
    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] < 70):
            if (p > best_power):
                best_power = p
                best_period = periods[i]

    FAP = ls.false_alarm_probability(best_power)

    return ls, periods, power, best_period, FAP
コード例 #16
0
ファイル: bandpass.py プロジェクト: ilyasher/star-rotation
    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)
コード例 #17
0
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)
コード例 #18
0
def estimate_period(time, y, y_err, clip=True, plot=True, **kwargs):
    """
    Run a Lomb-Scargle Periodogram to find periodic signals. It's recommended 
    to use the allesfitter.time_series functions sigma_clip and slide_clip beforehand.

    Parameters
    ----------
    time : array of float
        e.g. time array (usually in days)
    y : array of float
        e.g. flux or RV array (usually as normalized flux or RV in km/s)
    yerr : array of float
        e.g. flux or RV error array (usually as normalized flux or RV in km/s)
    clip : bool, optional
        Automatically clip the input data with sigma_clip(low=4, high=4)
        and slide_clip(window_length=1, low=4, high=4). The default is True.
    plot : bool, optional
        To plot or not, that is the question. The default is False.
    **kwargs : collection of keyword arguments
        Any keyword arguments will be passed onto the astropy periodogram class.

    Returns
    -------
    best_period : float
        The best period found.
    FAP : float
        The false alarm probability for the best period.
    fig : matplotlib.figure object, optional
        The summary figure. Only returned if plot is True.
    """

    #==========================================================================
    #::: clean the inputs
    #==========================================================================
    time, y, y_err = clean(time, y, y_err)
    plot_bool = plot

    if clip:
        y = sigma_clip(time, y, low=4, high=4)
        y = slide_clip(time, y, window_length=1, low=4, high=4)
        time, y, y_err = clean(time, y, y_err)

    #==========================================================================
    #::: handle inputs
    #==========================================================================
    cadence = np.nanmedian(np.diff(time))
    if kwargs is None: kwargs = {}
    if 'minperiod' not in kwargs: kwargs['minperiod'] = 10. * cadence
    if 'maxperiod' not in kwargs: kwargs['maxperiod'] = time[-1] - time[0]
    minfreq = 1. / kwargs['maxperiod']
    maxfreq = 1. / kwargs['minperiod']

    #==========================================================================
    #::: now do the periodogram
    #==========================================================================
    ls = LombScargle(
        time, y
    )  #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)]
    best_period = 1. / best_frequency
    FAP = ls.false_alarm_probability(
        best_power)  #Calculate the FAP for the highest peak in the power array

    #==========================================================================
    #::: plot
    #==========================================================================
    def 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)

        #::: plot the periodogram
        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,
                  kwargs['minperiod'],
                  kwargs['maxperiod'],
                  color='grey',
                  lw=1)
        ax.text(kwargs['maxperiod'], FAP_levels[0], '0.5% FAP ', ha='right')
        ax.text(kwargs['maxperiod'], FAP_levels[1], '0.1% FAP ', ha='right')
        ax.text(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')

        #::: plot the phase-folded data
        ax = axes[1]
        plot_phase_folded_lightcurve(time,
                                     y,
                                     period=1. / best_frequency,
                                     epoch=0,
                                     ax=ax)
        ax.set(ylim=[np.nanmin(y), np.nanmax(y)],
               ylabel='Data (clipped; phased)')

        #::: plot the phase-folded data, zoomed
        ax = axes[2]
        plot_phase_folded_lightcurve(time,
                                     y,
                                     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(y, index=time),
                 ax=ax,
                 lags=np.linspace(start=1,
                                  stop=2 * best_period / cadence,
                                  num=100,
                                  dtype=int))
        ax.set(xlabel='Lag', ylabel='Autocorrelation', title='')

        return fig

    #==========================================================================
    #::: return
    #==========================================================================
    if plot_bool:
        fig = plot()
        return best_period, FAP, fig
    else:
        return best_period, FAP
コード例 #19
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
コード例 #20
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
コード例 #21
0
def lombscargle_periodogram(time,
                            flux,
                            error,
                            dt=0,
                            min_period=0.1,
                            max_period=4,
                            peak_points=10,
                            height=0,
                            peak_ind=0,
                            plot=True,
                            xlim=(0, 1)):
    '''
    this function determines the peak period of a given light curve, allows
    one to choose which peak to select, then plots the periodogram and the
    folded light curve
    
    Parameters
    ----------
    time : array of float
        contains time data for the light curve
    flux : array of float
        contains flux data for the light curve
    error : array of float
        contains error data for the light curve
    dt : float
        time shift [default = 0]
    min_period : float
        minimum period to investigate [default = 0.1 days]
    max_period : float
        maximum period to investigate [default = 4 days]
    peak_points : int
        number of points around peaks [default = 10]
    height : float
        minimum height to consider peaks [default = 0]
    peak_ind : ind
        choose a peak number, maximum is default [peak_ind = 0]
    plot : bool
        plot a periodogram and the folded lightcurve with best fit sinusoid
    xlim : tuple
        x-limits of the folded plot [default = (0, 1)]

    Returns
    -------
    Pb : tuple
        contains the best fit parameters for the sine wave (amplitude,
        period, phase)
    residuals : array of float
        contains the residuals between the best fit model and the data
    '''
    time_fixed = time - dt
    # create the periodogram
    model = LombScargle(time_fixed, flux, error)
    frequencies, power = model.autopower(minimum_frequency=(1. / max_period),
                                         maximum_frequency=(1 / min_period),
                                         samples_per_peak=peak_points)
    # convert to periods
    periods = 1 / frequencies
    # identify and extract peaks
    inds, peaks = find_peaks(power, height=height)
    peaks = peaks['peak_heights']
    sort_peaks = np.argsort(peaks)
    inds = inds[sort_peaks]
    peaks = peaks[sort_peaks]
    # select peak
    period = periods[inds[-1 - peak_ind]]
    # fit the sinusoid
    flux_fit = model.model(time_fixed, 1 / period)
    residuals = flux - flux_fit
    t0, t1, t2 = model.model_parameters(1 / period)
    # convert theta parameters to amplitude and phase
    amplitude = np.hypot(t1, t2) * np.sign(flux_fit[0])
    phase = -np.arctan(t1 / t2) + np.pi / 2
    Pb = (amplitude, period, phase)
    # plot the periodogram and folded light curve
    if plot == True:
        # periodogram
        fig = plt.figure(figsize=(16, 8))
        plt.title('Lomb-Scargle Periodogram of Stellar Variations')
        plt.xlabel('Period [days]')
        plt.ylabel('Power [-]')
        plt.plot(periods, power, 'b-')
        plt.gca().axvline(x=period, color='k', ls=':')
        plt.show()
        # folded light curve
        plot_folded(time_fixed, flux, error, Pb, flux_fit, dt, xlim)
        print('%.6f sin(2 pi time / %.4f + %.4f)' % Pb)
    return Pb, residuals
コード例 #22
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
コード例 #23
0
ファイル: period_plot.py プロジェクト: davidjwilson/gj1132
from astropy.modeling import models, fitting
from astropy.time import Time
from datetime import date
from astropy.timeseries import LombScargle
import matplotlib.gridspec as gridspec


data = Table.read('gj1132_lya_lc.ecsv')
times, flux, error = np.array(data['MJD']), np.array(data['FLUX']), np.array(data['ERROR'])

fitter = fitting.LevMarLSQFitter()

plt.figure(figsize=(16, 6))
gs = gridspec.GridSpec(1,7)
ls =  LombScargle(times, flux, dy=np.array(error), normalization='model')
frequency, power = ls.autopower(maximum_frequency = 1/100, minimum_frequency=1/1500, samples_per_peak=10)
plt.subplot(gs[0:3])

plt.plot(1/frequency, power)
period = 1/frequency[np.argmax(power)]
print(period)
plt.xlabel('Period (d)')
plt.ylabel('LS Power')
#plt.annotate('P\_max = {0:10.1f} d'.format(period), (0.6, 0.9), xycoords ='axes fraction' )
#plt.axhline(ls.false_alarm_level(0.01))
plt.xlim(101, 1399)


plt.subplot(gs[3:])
plt.errorbar(times, flux, yerr=error, ls='none', marker='o')
コード例 #24
0
ファイル: by_season.py プロジェクト: ilyasher/star-rotation
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()
コード例 #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)

    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")
コード例 #26
0
def plot_graph(data, out_filepath, to_display=False, save_to_disk=True):
    '''
    Plot grapth and return its data

    Params
    data - input data in list of lists with pair value and time
    out_filepath - out file name path for create
    to_display - if set to true then graph will be shown on the display
    save_to_disk - if set to true then graph will be saved on the disk

    Return
    List of lists of graph values in form [freq, period, pgram_value, time_value]
    '''

    output_data = list()

    x = list()
    y = list()

    # Get first time value as constant time value for all window
    time_value = data[0][1]

    for val_pair in data:
        if val_pair[0] != None:
            x.append(val_pair[1])
            y.append(val_pair[0])

    # Calculate Lomb-Scargle periodogram Astropy
    astropy_pgram = LombScargle(x, y, normalization='psd')
    astropy_freq, astropy_power = astropy_pgram.autopower()
    astropy_false_alarm_probability = astropy_pgram.false_alarm_probability(astropy_power.max(), method='baluev')

    # Create figure with 2 subplots
    fig = plt.figure()
    source_ax = fig.add_subplot(211)
    astropy_pgram_ax = fig.add_subplot(212)

    #Now make a plot of the input data:
    source_ax.plot(x, y, 'b+')

    # astropy periodogram
    astropy_pgram_ax.plot(astropy_freq, astropy_power,'g')
    astropy_pgram_ax.text(0.95, 0.95, "FAP(first_peak) = {:.4f}%".format(astropy_false_alarm_probability),
        verticalalignment='top', horizontalalignment='right',
        transform=astropy_pgram_ax.transAxes,
        color='green', fontsize=15)

    if to_display:
        plt.show()

    if save_to_disk:
        plt.savefig(out_filepath)

    # Generate output
    for idx, freq in enumerate(astropy_freq):
        period = 1 / freq
        output_data.append([freq, period, astropy_power[idx], time_value])

    plt.cla()
    plt.clf()
    plt.close(fig)

    return output_data
コード例 #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
ファイル: TESStools.py プロジェクト: tzdwi/TESS
def make_WWZ_plot(wwz, wwa, omegas, taus, t, y, lombscargle=True, **kwargs):
    """
    Makes a pretty plot with the WWZ info
    
    Parameters
    ----------
    wwz : array-like
        `(len(omegas),len(taus))` Weighted Wavelet Z-transform array
    wwa : array-like
        `(len(omegas),len(taus))` Weighted Wavelet Amplitude array
    omegas : array-like
        1-D array of angular frequencies
    taus : array-like
        1-D array of time-shifts
    t : array-like
        1-D array of time observations
    y : array-like
        1-D array of flux or magnitude observations
    lombscargle : bool
        Whether or not to plot the Lomb-Scargle periodogram to compare with the WWZ spectrum. 
        Default True.
    **kwargs
        Passed to `matplotlib.pyplot.figure()`
        
    Returns
    -------
    fig : `matplotlib.pyplot.Figure`
        Figure object
    ax : list
        List of `matplotlib.pyplot.Axes` objects
    
    """
    if lombscargle:
        ls = LombScargle(t, y)
        freq, power = ls.autopower(
            minimum_frequency=np.min(omegas) / 2 / np.pi,
            maximum_frequency=np.max(omegas) / 2 / np.pi)

    fig = plt.figure(constrained_layout=True, **kwargs)

    gs = GridSpec(5, 4, figure=fig)
    lcax = fig.add_subplot(gs[0, :3])
    wwzax = fig.add_subplot(gs[1:3, :3])
    wwaax = fig.add_subplot(gs[3:, :3])
    zsumax = fig.add_subplot(gs[1:3, 3])
    asumax = fig.add_subplot(gs[3:, 3])

    lcax.scatter(t, y, s=1, c='k')
    lcax.set(ylabel='Normalized Flux', xlim=(np.min(t), np.max(t)))

    wwzax.contourf(taus, omegas / 2.0 / np.pi, wwz, levels=100, cmap='cividis')
    wwzax.fill_between(2 * np.pi / omegas + np.min(t),
                       0,
                       omegas / 2 / np.pi,
                       alpha=0.5,
                       facecolor='white')
    #fill the whole axis below this
    wwzax.fill_between(
        [np.min(t), np.min(2 * np.pi / omegas + np.min(t))],
        0,
        wwzax.get_ylim()[-1],
        alpha=0.5,
        facecolor='white')
    wwzax.fill_between(np.max(t) - 2 * np.pi / omegas,
                       0,
                       omegas / 2 / np.pi,
                       alpha=0.5,
                       facecolor='white')
    #fill the whole axis above this
    wwzax.fill_between([np.max(np.max(t) - 2 * np.pi / omegas),
                        np.max(t)],
                       0,
                       wwzax.get_ylim()[-1],
                       alpha=0.5,
                       facecolor='white')
    wwzax.set(ylabel=r'Frequency [d$^{-1}$]',
              ylim=(np.min(omegas) / 2 / np.pi, np.max(omegas / 2 / np.pi)),
              xlim=(np.min(t), np.max(t)))

    wwaax.contourf(taus, omegas / 2.0 / np.pi, wwa, levels=100, cmap='cividis')
    wwaax.fill_between(2 * np.pi / omegas + np.min(t),
                       0,
                       omegas / 2 / np.pi,
                       alpha=0.5,
                       facecolor='white')
    wwaax.fill_between(
        [np.min(t), np.min(2 * np.pi / omegas + np.min(t))],
        0,
        wwzax.get_ylim()[-1],
        alpha=0.5,
        facecolor='white')
    wwaax.fill_between(np.max(t) - 2 * np.pi / omegas,
                       0,
                       omegas / 2 / np.pi,
                       alpha=0.5,
                       facecolor='white')
    wwaax.fill_between([np.max(np.max(t) - 2 * np.pi / omegas),
                        np.max(t)],
                       0,
                       wwzax.get_ylim()[-1],
                       alpha=0.5,
                       facecolor='white')
    wwaax.set(xlabel='Time [d]',
              ylabel=r'Frequency [d$^{-1}$]',
              ylim=(np.min(omegas) / 2 / np.pi, np.max(omegas / 2 / np.pi)),
              xlim=(np.min(t), np.max(t)))

    zsumax.plot(np.mean(wwz, axis=1), omegas / 2.0 / np.pi)
    if lombscargle:
        scale = np.max(np.mean(wwz, axis=1)) / np.max(power)
        zsumax.plot(power * scale, freq, c='k')
    zsumax.set(yticks=[],
               xlabel=r'$\langle WWZ \rangle$',
               ylim=(np.min(omegas) / 2 / np.pi, np.max(omegas / 2 / np.pi)),
               xlim=(0, zsumax.get_xlim()[-1]))

    asumax.plot(np.mean(wwa, axis=1), omegas / 2.0 / np.pi)
    asumax.set(yticks=[],
               xlabel=r'$\langle WWA \rangle$',
               ylim=(np.min(omegas) / 2 / np.pi, np.max(omegas / 2 / np.pi)),
               xlim=(0, asumax.get_xlim()[-1]))
    if lombscargle:
        scale = np.max(np.mean(wwa, axis=1)) / np.max(power)
        asumax.plot(power * scale, freq, c='k')

    return fig, [lcax, wwzax, wwaax, zsumax, asumax]
コード例 #29
0
ファイル: utilities.py プロジェクト: fallingelf/Phoebe
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
コード例 #30
0
ファイル: TESStools.py プロジェクト: tzdwi/TESS
def prewhiten(time, flux, err, verbose=True, red_noise=True, max_freq=np.inf):
    """
    Runs through a prewhitening procedure to reproduce the variability as sin functions. Now encorporates an optional
    way of fitting for red noise in the periodograms!
    
    Parameters
    ----------
    time : array-like
        times
    flux : array-like
        fluxes
    err : array-like
        corresponding errors.
    verbose : bool
        If set, will print out every 10th stage of prewhitening, as well as some other diagnostics
    red_noise : bool
        If set, will fit for a red noise background model before finding the highest peak
    max_freq : numeric
        Determines the number of frequencies to fit for if given. Default `np.inf`
        
    Returns
    -------
    good_fs : `~numpy.ndarray`
        Nx2 array with first dimension frequencies, and the second errors
    good_amps :`~numpy.ndarray`
        Nx2 array with first dimension amplitudes, and the second errors
    good_amps :`~numpy.ndarray`
        Nx2 array with first dimension amplitudes, and the second errors
    good_snrs :`~numpy.ndarray`
        1D array with signal to noise, calculated directly from the periodogram
    good_amps :`~numpy.ndarray`
        1D array with the heights of the extracted peaks.
    
    """

    pseudo_NF = 0.5 / (np.mean(np.diff(time)))
    rayleigh = 1.0 / (np.max(time) - np.min(time))

    #Step 1: subtract off the mean, save original arrays for later
    flux -= np.mean(flux)
    time -= np.mean(time)

    original_flux = flux.copy()
    original_err = err.copy()
    original_time = time.copy()

    found_fs = []
    err_fs = []
    found_amps = []
    err_amps = []
    found_phases = []
    err_phases = []
    found_peaks = []
    found_snrs = []

    #Step 2: Calculate the Lomb Scargle periodogram
    ls = LombScargle(time, flux, normalization='psd')
    frequency, power = ls.autopower(minimum_frequency=1.0 / 30.0,
                                    maximum_frequency=pseudo_NF)
    power /= len(time)  #putting into the right units

    #Step 2.5: Normaling by the red noise!
    if red_noise:
        try:
            popt, pcov, resid = fit_red_noise(frequency, power)
        except RuntimeError:
            popt, pcov, resid = fit_red_noise(frequency[frequency < 50],
                                              power[frequency < 50])

        power = resid

    #Step 3: Find frequency of max residual power, and the SNR of that peak
    f_0 = frequency[np.argmax(power)]
    noise_region = (np.abs(frequency - f_0) / rayleigh <
                    7) & (np.abs(frequency - f_0) / rayleigh > 2)
    found_peaks.append(power.max())
    found_snrs.append(power.max() / np.std(power[noise_region]))

    #Step 4: Fit the sin. Initial guess is that frequency, the max flux point, and no phase
    # Then save the fit params
    p0 = [f_0, np.max(flux), 0]
    bounds = ([f_0 - rayleigh, 0, -np.inf], [f_0 + rayleigh, np.inf, np.inf])

    popt, pcov = curve_fit(parametrized_sin, time, flux, bounds=bounds, p0=p0)

    found_fs.append(popt[0])
    found_amps.append(popt[1])
    phase = popt[2]
    while phase >= np.pi:
        phase -= 2.0 * np.pi
    while phase <= -np.pi:
        phase += 2.0 * np.pi
    found_phases.append(phase)

    #Calculate the errors
    err_fs.append(
        np.sqrt(6.0 / len(time)) * rayleigh * np.std(flux) / (np.pi * popt[1]))
    err_amps.append(np.sqrt(2.0 / len(time)) * np.std(flux))
    err_phases.append(np.sqrt(2.0 / len(time)) * np.std(flux) / popt[1])

    #Calculate the BIC up to a constant: -2 log L + m log (N)
    log_like_ish = np.sum(
        np.power(((original_flux - np.sum([
            parametrized_sin(time, f, amp, phase)
            for f, amp, phase in zip(found_fs, found_amps, found_phases)
        ],
                                          axis=0)) / original_err), 2.0))

    bic = log_like_ish + 3.0 * len(found_fs) * np.log(len(time))
    #bic with no fit is:
    old_bic = np.sum(np.power((original_flux / original_err), 2.0))
    bic_dif = bic - old_bic

    #subtract off the fit
    flux -= parametrized_sin(time, *popt)

    #now loop until BIC hits a minimum
    j = 0
    while (bic_dif <= 0) and (len(found_fs) <= max_freq):
        #Reset old_bic
        old_bic = bic
        #Lomb Scargle
        ls = LombScargle(time, flux, normalization='psd')
        frequency, power = ls.autopower(minimum_frequency=1.0 / 30.0,
                                        maximum_frequency=pseudo_NF)

        power /= len(time)  #putting into the right units

        #fit
        if red_noise:
            try:
                popt, pcov, resid = fit_red_noise(frequency, power)
            except RuntimeError:
                popt, pcov, resid = fit_red_noise(frequency[frequency < 50],
                                                  power[frequency < 50])

            power = resid

        #Highest peak
        f_0 = frequency[np.argmax(power)]
        noise_region = (np.abs(frequency - f_0) / rayleigh <
                        7) & (np.abs(frequency - f_0) / rayleigh > 2)
        found_peaks.append(power.max())
        found_snrs.append(power.max() / np.std(power[noise_region]))

        #Fit
        p0 = [f_0, np.max(flux), 0]
        bounds = ([f_0 - rayleigh, 0,
                   -np.inf], [f_0 + rayleigh, np.inf, np.inf])
        popt, pcov = curve_fit(parametrized_sin,
                               time,
                               flux,
                               bounds=bounds,
                               p0=p0)

        found_fs.append(popt[0])
        found_amps.append(popt[1])
        phase = popt[2]
        while phase >= np.pi:
            phase -= 2.0 * np.pi
        while phase <= -np.pi:
            phase += 2.0 * np.pi
        found_phases.append(phase)

        #Calculate the errors
        err_fs.append(
            np.sqrt(6.0 / len(time)) * rayleigh * np.std(flux) /
            (np.pi * popt[1]))
        err_amps.append(np.sqrt(2.0 / len(time)) * np.std(flux))
        err_phases.append(np.sqrt(2.0 / len(time)) * np.std(flux) / popt[1])

        #Calculate BIC
        log_like_ish = np.sum(
            np.power(((original_flux - np.sum([
                parametrized_sin(time, f, amp, phase)
                for f, amp, phase in zip(found_fs, found_amps, found_phases)
            ],
                                              axis=0)) / original_err), 2.0))
        bic = log_like_ish + 3.0 * len(found_fs) * np.log(len(time))
        bic_dif = bic - old_bic
        #subtract off the fit
        flux -= parametrized_sin(time, *popt)
        j += 1
        if (j % 10 == 0) and verbose:
            print(j)
    if verbose:
        print('Found {} frequencies'.format(len(found_fs) - 1))
    #if we didn't find any GOOD frequencies, get rid of that ish
    if len(found_fs) - 1 == 0:
        return np.array([]), np.array([]), np.array([]), np.array(
            []), np.array([])
    #pop the last from each array, as it made the fit worse, then turn into numpy arrays
    found_fs = np.array(found_fs[:-1])
    found_amps = np.array(found_amps[:-1])
    found_phases = np.array(found_phases[:-1])
    found_snrs = np.array(found_snrs[:-1])
    found_peaks = np.array(found_peaks[:-1])
    err_fs = np.array(err_fs[:-1])
    err_amps = np.array(err_amps[:-1])
    err_phases = np.array(err_phases[:-1])

    #Now loop through frequencies. If any of the less-strong peaks are within 1.5/T,
    #get rid of it.
    good_fs = np.array([[found_fs[0], err_fs[0]]])
    good_amps = np.array([[found_amps[0], err_amps[0]]])
    good_phases = np.array([[found_phases[0], err_phases[0]]])
    good_snrs = np.array([found_snrs[0]])
    good_peaks = np.array([found_peaks[0]])

    for f, ef, a, ea, p, ep, s, pk in zip(found_fs[1:], err_fs[1:],
                                          found_amps[1:], err_amps[1:],
                                          found_phases[1:], err_phases[1:],
                                          found_snrs[1:], found_peaks[1:]):
        if ~np.any(np.abs(good_fs[:, 0] - f) <= 1.5 * rayleigh):
            good_fs = np.append(good_fs, [[f, ef]], axis=0)
            good_amps = np.append(good_amps, [[a, ea]], axis=0)
            good_phases = np.append(good_phases, [[p, ep]], axis=0)
            good_snrs = np.append(good_snrs, [s], axis=0)
            good_peaks = np.append(good_peaks, [pk], axis=0)
    if verbose:
        print('{} unique frequencies'.format(len(good_fs)))

    return good_fs, good_amps, good_phases, good_snrs, good_peaks