def spike(time, flux): """ Function to calculate the metric called "spike" for K2 objects. When spike > 1.0, the object is said to have bad arc drift. args time : time reference for light curve (seconds) flux : flux of light curve returns spike : spike metric """ # get fit for below the 5 day noise floor freq, power = LS_PSD(time, flux, f=k2_freq) # noise floor are freqencies > X days, convert to Hz noise_floor_days = 5 noise_floor_mask = freq > (2 * np.pi / (noise_floor_days * 86400)) m_noise, b_noise = np.polyfit( np.log10(freq)[noise_floor_mask], np.log10(power)[noise_floor_mask], 1) freq_six_hour = (2 * np.pi / (0.5 * 86400) ) # frequency for 2*6 hour thurster fire # Compute the LS based power for single frequency model = LombScargle(time, flux) freq_temp = k2_freq[320] # a very particular frequency power_temp = model.power(freq_temp, method="fast", normalization="psd") power_temp /= len(time) spike = np.log10(power_temp / (10**(np.log10(freq_six_hour) * m_noise + b_noise))) return spike
def multiterm_periodogram(t, y, dy, omega, n_terms=3): """Perform a multiterm periodogram at each omega This calculates the chi2 for the best-fit least-squares solution for each frequency omega. Parameters ---------- t : array_like sequence of times y : array_like sequence of observations dy : array_like sequence of observational errors omega : float or array_like frequencies at which to evaluate p(omega) Returns ------- power : ndarray P = 1. - chi2 / chi2_0 where chi2_0 is the chi-square for a simple mean fit to the data """ # TODO: deprecate this ls = LombScargle(t, y, dy, nterms=n_terms) frequency = np.asarray(omega) / (2 * np.pi) return ls.power(frequency)
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
def run_GLS_process(self): ''' This function runs the GLS calculation process. ''' # , normalization='psd' if isinstance(self.time_series.vals[0], float): self.GLS_power = LombScargle(self.time_series.times, self.time_series.vals).power( self.GLS_frequency) else: if self.time_series.calculated_vrad_list != []: self.GLS_power = LombScargle( self.time_series.times, self.time_series.calculated_vrad_list).power( self.GLS_frequency) else: assert 'GLS is possible for scalar time-series only' return self.GLS_flag = True self.results_frequency.update({"GLS": self.GLS_frequency}) self.results_power.update({"GLS": self.GLS_power}) return self.GLS_frequency, self.GLS_power
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
def replace_lightcurve(self, lightcurve): # Create LombScargle object of timeseries, where time is in seconds: indx = np.isfinite(lightcurve.flux) self.ls = LombScargle(lightcurve.time[indx] * 86400, lightcurve.flux[indx], center_data=True, fit_mean=self.fit_mean)
def windowfunction(self, width=None, oversampling=10): """Spectral window function. Parameters: width (float, optional): The width in Hz on either side of zero to calculate spectral window. oversampling (float, optional): Oversampling factor. Default=10. """ if width is None: width = 100 * self.df freq_cen = 0.5 * self.nyquist Nfreq = int(oversampling * width / self.df) freq = freq_cen + (self.df / oversampling) * np.arange( -Nfreq, Nfreq, 1) x = 0.5 * np.sin(2 * np.pi * freq_cen * self.ls.t) + 0.5 * np.cos( 2 * np.pi * freq_cen * self.ls.t) # Calculate power spectrum for the given frequency range: ls = LombScargle(self.ls.t, x, center_data=True, fit_mean=self.fit_mean) power = ls.power(freq, method='fast', normalization='psd', assume_regular_frequency=True) power /= power[int(len(power) / 2)] # Normalize to have maximum of one freq -= freq_cen freq *= 1e6 return freq, power
def APFAP(self, P): #FAP from LombScargle, not entierly accurate as I'd want because my LombScargle #returns worse estimations than theirs AstroLS = LombScargle(self.time, self.RV, self.Munc) FAP = AstroLS.false_alarm_level(P) return (FAP)
def amplitude_spectrum( self, t, y, fmin: float = None, fmax: float = None, oversample_factor: float = 5.0, ) -> tuple: """Calculates the amplitude spectrum at a given time and flux input Args: t (np.ndarray): Time values y (np.ndarray): Flux values fmin (float, optional): Minimum frequency. Defaults to None. fmax (float, optional): Maximum frequency. Defaults to None. oversample_factor (float, optional): Amount by which to oversample the light curve. Defaults to 5.0. Returns: tuple: Frequency and amplitude arrays """ # t, y = self.time, self.residual tmax = t.max() tmin = t.min() df = 1.0 / (tmax - tmin) if fmin is None: fmin = df if fmax is None: fmax = 0.5 / np.median(np.diff(t)) # *nyq_mult freq = np.arange(fmin, fmax, df / oversample_factor) model = LombScargle(t, y) sc = model.power(freq, method="fast", normalization="psd") fct = np.sqrt(4.0 / len(t)) amp = np.sqrt(sc) * fct return freq, amp
def LS_PSD(t, y, f=None): """ Normalized Lomb Scargle Power Spectrum Density args t : time array y : flux array f(optional) : frequency range returns f : frequency range with first and last entry removed power_ls: lomb-scargle power """ N = len(t) # number of datapoints #f = np.fft.rfftfreq(N**2, (t[-1] - t[0])) # frequency range (from Uttley et al. 2002) if f is None: f = np.fft.rfftfreq(N, (t[1] - t[0])) # frequency range # Compute the LS based power spectrum estimates model = LombScargle(t, y) power_ls = model.power(f[1:-1], method="fast", normalization="psd") # >>> To get the LS based PSD in the correct units, normalize by N <<< power_ls /= N return f[1:-1], power_ls
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
def get_period(t, y, dy, frequencies=None): if frequencies == None: frequencies = get_range_freqs(t) ls = LombScargle(t, y, dy) power = ls.power(frequencies) best_freq = frequencies[np.argmax(power)] period = round(1 / best_freq, 3) return period
def make_lsp(time, flux, flux_err, p_min=1/24.0, p_max=1.0, oversampling=5, lsp_kwargs={}, nterms=1, use_gatspy=False): """ Compute the Lomb-Scargle periodogram using the astropy LombScargle class. Parameters ---------- time : numpy.ndarray The time stamps of the time series **IN DAYS** flux : numpy.ndarray Flux measurements corresponding to the time stamps flux_err : numpy.ndarray The flux uncertainties corresponding to the data. p_min, p_max : float, float The minimum and maximum period to search, **IN DAYS** oversampling : int The oversampling factor; default is 5 lsp_kwargs : dict Optional keyword arguments for astropy.stats.LombScargle Returns ------- freq : numpy.ndarray The frequencies for which the Lomb-Scargle periodogram was computed power : numpy.ndarray Normalized Lomb-Scargle power """ # number of frequencies to sample nfreq = int(oversampling*(p_max - p_min)/p_min) # number of frequencies # make a list of frequencies freq = np.linspace(1/p_max, 1/p_min, nfreq) if use_gatspy: model = periodic.LombScargle(fit_period=True, center_data=True, fit_offset=True, Nterms=nterms) model.optimizer.period_range = (p_min, p_max) model.fit(time, flux, flux_err) periods = 1/freq power = model.periodogram(periods) power = power else: # initialize the lomb-scargle periodogram ls = LombScargle(time, flux, dy=flux_err, **lsp_kwargs, nterms=nterms) # compute the power at each given frequency power = ls.power(freq) return freq, power
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
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
def get_fig_LS(): plt.scatter(time, rate) plt.show() border = 10000 vary = np.array([i for i in range(0, border)]) freq = 1 / 50000. + vary * 1.e-8 x = time y = rate LS = LombScargle(x, y, dy=1, normalization='standard', fit_mean=True, center_data=True).power(freq, method='cython') FP_99 = LombScargle(x, y, dy=1, normalization='standard', fit_mean=True, center_data=True).false_alarm_level( 0.01, minimum_frequency=freq[0], maximum_frequency=freq[-1]) FP_90 = LombScargle(x, y, dy=1, normalization='standard', fit_mean=True, center_data=True).false_alarm_level( 0.1, minimum_frequency=freq[0], maximum_frequency=freq[-1]) FP_68 = LombScargle(x, y, dy=1, normalization='standard', fit_mean=True, center_data=True).false_alarm_level( 0.32, minimum_frequency=freq[0], maximum_frequency=freq[-1]) plt.semilogx() plt.step(freq, LS) print(max(LS)) print() plt.plot([freq[0], freq[-1]], [FP_99, FP_99], '--') plt.plot([freq[0], freq[-1]], [FP_90, FP_90], '--') plt.plot([freq[0], freq[-1]], [FP_68, FP_68], '--') plt.show()
def circadian_movement_energies(locationData): time = (locationData["timestamp"].values / 1000.0) # seconds ylat = locationData["double_latitude"].values ylong = locationData["double_longitude"].values hours_intervals = np.arange(23.5, 24.51, 0.01) # hours seconds_intervals = hours_intervals * 60 * 60 # seconds frequency = 1 / seconds_intervals power_latitude = LombScargle(time, ylat).power(frequency=frequency, normalization='psd') power_longitude = LombScargle(time, ylong).power(frequency=frequency, normalization='psd') energy_latitude = np.sum(power_latitude) energy_longitude = np.sum(power_longitude) return (energy_latitude, energy_longitude)
def frequency_alarm(df_d: pd.DataFrame) -> float: """Function that returns the false alarm probability for a given detector, for use in groupbys Args: df_d: dataframe for single detector Returns: false alarm probability as float""" X = df_d.reset_index() X = X.drop(columns=["detector_id", "measurement_end_utc"]) x = X.index.to_numpy() y = X.to_numpy().flatten() ls = LombScargle(x, y) period = np.linspace(15, 30, 300) pmax = ls.power(1 / period).max() return ls.false_alarm_probability(pmax)
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)
def LS_periodogram(times, signal, dy=None, f0=None, fn=None, oversample_factor=10.0, normalisation='amplitude'): """ Calculates the amplitude spectrum of a given signal Parameters ---------- t : `array` Time values y : `array` Flux or magnitude measurements This is not automatically mean-substracted!!! f0 : float (default None) Minimum frequency to calculate spectrum. Defaults to df fn : float Maximum frequency to calculate spectrum. Defaults to Nyquist. oversample_factor : float Amount by which to oversample the spectrum. Defaults to 10. normalisation : str (default amplitude) Normalise the periodogram. Options are 'distribution', 'ampliude', 'power_density', 'power' """ df = 1.0 / (times.max() - times.min()) if f0 is None: f0 = df if fn is None: fn = 0.5 / np.median(np.diff(times)) # *nyq_mult freq = np.arange(f0, fn, df / oversample_factor) ls_ = LombScargle(times, signal, dy=dy) sc = ls_.power(freq, method="fast", normalization="psd") if dy is None: dy = np.array([1.]) #np.ones_like(signal) w = (dy**-2.0).sum() power = (1. * sc) / w ## Normalised to return desired output units noramlise_str = 'normalise_{}'.format(normalisation) LS_out = eval(noramlise_str + '(power,times)') return freq, LS_out
def calPower(code, df): tt = df.index.values dfD = df[df[code].notna().values] t = dfD.index.values x = (t.astype('datetime64[D]') - np.datetime64('1979-01-01')).astype( np.float) y = dfD[code].values nt = len(tt) freq = np.fft.fftfreq(nt)[1:] ind = np.where((1 / freq >= 0) & (1 / freq < 1000))[0] freq = freq[ind] ls = LombScargle(x, y) power = ls.power(freq) p = ls.false_alarm_probability(power) return freq, power, 1 - p
def __call__(self): self.logger = getLogger( f"{self.name}:{self.ts.name.lower().replace('_','-')}") self.logger.info("Running Lomb-Scargle periodogram") self._periods = 1 / linspace(1 / self.ts.pmax, 1 / self.ts.pmin, 1000) self.ls = LombScargle(self.ts.time, self.ts.flux) self._powers = self.ls.power(1 / self._periods) self._faps = self.ls.false_alarm_probability(self._powers) i = argmax(self._powers) self.period = self._periods[i] self.power = self._powers[i] self.fap = self._faps[i] self.logger.info( f"LS period {self.period:.2f}, power {self.power:.4f}, FAP {self.fap:.4f}" )
def get_LS(time, flux): x = time y = flux freq = 1. / np.linspace(50, 400, 350) LS = LombScargle(x, y, dy=1, normalization='standard', fit_mean=True, center_data=True).power(freq, method='cython') FP_99 = LombScargle(x, y, dy=1, normalization='standard', fit_mean=True, center_data=True).false_alarm_level( 0.01, minimum_frequency=freq[0], maximum_frequency=freq[-1]) FP_90 = LombScargle(x, y, dy=1, normalization='standard', fit_mean=True, center_data=True).false_alarm_level( 0.1, minimum_frequency=freq[0], maximum_frequency=freq[-1]) FP_68 = LombScargle(x, y, dy=1, normalization='standard', fit_mean=True, center_data=True).false_alarm_level( 0.32, minimum_frequency=freq[0], maximum_frequency=freq[-1]) plt.semilogx() plt.step(freq, LS) print(max(LS)) print() 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.savefig('/Volumes/pulsar/WR/1671/LS_4_8.eps') plt.show()
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()
def LS(t, y): f, p = LombScargle(t, y).autopower(normalization='psd', nyquist_factor=1, samples_per_peak=1) f = f * 1e6 # to uHz p = p * np.var(y) / np.trapz(p, x=f) # Bill's normalization return f, p
def plotLombScargle(time, flux): """Finding the period of the selected data with astropy's Lombscargle package. *** Interpolation coefficients and truncated arrays are hardcoded, may need to be altered. *** Args: time (List): Time values from processed data file. flux (List): Flux values from processed data file. """ tot_time = np.max(time) - np.min(time) # Plotting the period with the Lomb-Scargle method. frequency, power = LombScargle(time, flux).autopower() # Estimate of noise based on the std of power values. noise = np.std(np.diff(power)) # Truncate arrays to only view the first peak of the periodogram. frequency = frequency[:int(len(frequency) * .25)] power = power[:int(len(power) * .25)] period = np.max(power) # Values used when creating interpolated values in uncertainty function. interp_coeff = [0.5, 2] peak_index = np.where(power == period)[0][0] # Finds lower and upper uncertainties. Values are saved and placed on the plot. plt_text = find_uncertainty(frequency, power, tot_time, noise, peak_index, interp_coeff) # Temporary box coordinates, will have to be changed*** output.plot_graph(frequency, power, "Frequency - Cycles/Day", "Power", "Lomb-Scargle Periods", plt_text, .2, max(power))
def getLGpeak(t, sig, sig_err): """Calculates the location of the highest peak and the maximum power of the hightest peak Args: t: Time [days] sig: Flux sig_err: Flux error Returns: :LG_Prot ([float]): The period calculated from Lomb-Scargle :LG_peaks ([float]): The maximum peak height """ # lomb-scargle # get frequencies freq = np.linspace(1. / abs(t[-1] - t[0]), 1. / abs(t[1] - t[0]) * 0.5, 100000) # periods ps = 1. / freq power = LombScargle(t, sig, sig_err).power(freq) peaks = np.array([ i for i in range(1, len(ps) - 1) if power[i - 1] < power[i] and power[i + 1] < power[i] ]) return ps[power == max(power[peaks])][0], max(power[peaks])
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
def update_hidden(contents, filename): x = [] y = [] xx = [] yy = [] xxx = [] yyy = [] frequency = [] power = [] bf = 1.0 if contents: contents = contents[0] filename = filename[0] df = parse_data(contents, filename) x = df[df.columns[0]] x = np.asarray(x) y = df[df.columns[1]] y = np.asarray(y) yerr = df[df.columns[2]] yerr = np.asarray(yerr) t_days = x * u.day y_mags = y * u.mag dy_mags = yerr * u.mag frequency, power = LombScargle(t_days, y_mags, dy_mags).autopower(nyquist_factor=10) bf = 1.0 / frequency[np.argmax(power)] return "Best Period: " + str(bf), "Best Period: " + str(bf)
def lomb_scargle(self): ''' The LombScargle module from astropy.timeseries is used to compute the period of the given data. ''' t, y = self.jd, self.light self.freq, self.power = LombScargle(t, y).autopower( minimum_frequency=0.037, maximum_frequency=10) # false_alarm = LombScargle(t,y).false_alarm_probability(power=self.power) # # print('''False alarm probability''') # print(false_alarm) if self.noise is not None: idx = [ np.where(np.round(self.freq, 5) == round(i, 5))[0][0] for i in self.noise if round(i, 5) in np.round(self.freq, 5) ] self.freq = np.delete(self.freq, idx) # / # self.power = np.delete(self.power, idx) else: pass self.period = 1 / self.freq[np.argmax(self.power)] self.phase = np.remainder(self.jd, self.period) / self.period self.phase2 = np.concatenate((self.phase, self.phase + 1)) self.magx2 = np.concatenate((self.mag, self.mag)) return self.period
def lomb_scargle(t, y, dy, omega, generalized=True, subtract_mean=True, significance=None): """ (Generalized) Lomb-Scargle Periodogram with Floating Mean Parameters ---------- t : array_like sequence of times y : array_like sequence of observations dy : array_like sequence of observational errors omega : array_like frequencies at which to evaluate p(omega) generalized : bool if True (default) use generalized lomb-scargle method otherwise, use classic lomb-scargle. subtract_mean : bool if True (default) subtract the sample mean from the data before computing the periodogram. Only referenced if generalized is False significance : None or float or ndarray if specified, then this is a list of significances to compute for the results. Returns ------- p : array_like Lomb-Scargle power associated with each frequency omega z : array_like if significance is specified, this gives the levels corresponding to the desired significance (using the Scargle 1982 formalism) Notes ----- The algorithm is based on reference [1]_. The result for generalized=False is given by equation 4 of this work, while the result for generalized=True is given by equation 20. Note that the normalization used in this reference is different from that used in other places in the literature (e.g. [2]_). For a discussion of normalization and false-alarm probability, see [1]_. To recover the normalization used in Scargle [3]_, the results should be multiplied by (N - 1) / 2 where N is the number of data points. References ---------- .. [1] M. Zechmeister and M. Kurster, A&A 496, 577-584 (2009) .. [2] W. Press et al, Numerical Recipes in C (2002) .. [3] Scargle, J.D. 1982, ApJ 263:835-853 """ # delegate to astropy's Lomb-Scargle ls = LombScargle(t, y, dy, fit_mean=generalized, center_data=subtract_mean) frequency = np.asarray(omega) / (2 * np.pi) p_omega = ls.power(frequency, method='cython') if significance is not None: N = t.size M = 2 * N z = (-2.0 / (N - 1.) * np.log(1 - (1 - np.asarray(significance)) ** (1. / M))) return p_omega, z else: return p_omega