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 main(): df = pd.read_fwf(data_url, colspecs=((0, 6), (7, 27)), header=1, names=('orbnum', 'utc'), parse_dates=[1], date_parser=_dp) sec_of_day = 86400.0 df['period'] = df.utc.diff(periods=1).astype('timedelta64[s]')/sec_of_day ax = plt.axes() plt.plot(df.utc, df.period, marker='+') plt.xlabel('date/time') plt.ylabel('period') plt.ylim(10.0, 14.0) ax.xaxis.set_major_locator(mdates.MonthLocator(interval=4)) ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m')) plt.show() date0 = pd.datetime.strptime('2016-04-17', '%Y-%m-%d') df_m = df[ df.utc > date0 ].copy() df_m['delta'] = df_m['utc'] - date0 df_m['et'] = df_m['delta'].dt.total_seconds()/sec_of_day from astropy.stats import LombScargle ls = LombScargle(df_m.et, df_m.period, fit_mean=True) freq, power = ls.autopower() fmax = freq[np.argmax(power)] print('frequency(Lomb-Scargle): ', 1/fmax) print('frequency(rev/2): ', 224.701/2.0)
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 peak_inds = (power[1:-1] > power[:-2]) & (power[1:-1] > power[2:]) peak_inds = np.arange(1, len(power)-1)[peak_inds] peak_inds = peak_inds[np.argsort(power[peak_inds])][::-1] peaks = [] for i in peak_inds[:max_peaks]: A = np.vander(freq[i-1:i+2], 3) w = np.linalg.solve(A, np.log(power[i-1:i+2])) sigma2 = -0.5 / w[0] freq0 = w[1] * sigma2 peaks.append(dict( log_power=w[2] + 0.5*freq0**2 / sigma2, period=1.0 / freq0, period_uncert=np.sqrt(sigma2 / freq0**4), )) return dict( periodogram=(freq, power_est), peaks=peaks, )
def periodcheck(thistime, thisflux, mflags): #dates,flux,flux_pcor,flux_ptcor,mflags = readpsfk2cor(k2name) ig = (mflags == 0) # # k2sc documentation: # https://github.com/OxES/k2sc/blob/master/relase_readme.txt # indicates that mflags ==0 would be good data. # # This section, not used, shows how to do sigma clipping. Unncessary since mgflags already # applies a ~4-5 sigma clip. #sigma clipping stuff ; see http://docs.astropy.org/en/stable/stats/robust.html#sigma-clipping #from astropy.stats import sigma_clip #filtered_data = sigma_clip(flux_ptcor, sigma=3, iters=10) # that would be a mask # # DISCOVERY: WILL CRASH IF ALL DATA FLAGGED AS BAD!!! # SOLUTION: DON'T GIVE IT THOSE FILES! # # Periodogram stuff # search good data only in period range 1 hour to 10 days ls = LombScargle(thistime[ig], thisflux[ig]) frequency, power = ls.autopower(maximum_frequency=24.0, minimum_frequency=0.1) # best_frequency = frequency[np.argmax(power)] best_fap = ls.false_alarm_probability(power.max()) # # Calculate the model if desired #y_fit = ls.model(dates, best_frequency) #plt.plot(t_fit,y_fit,'k-') # return frequency, power, best_frequency, best_fap
def compute_periodogram(data: np.ndarray, kwargs: Dict = None) -> np.ndarray: """ Computes a given periodogram from the lightcurve :param data: Lightcurve dataset :return: Periodogram from the dataset """ indx = np.isfinite(data[1]) df = 1 / (86400 * (np.amax(data[0][indx]) - np.amin(data[0][indx]))) # Hz ls = LombScargle(data[0][indx] * 86400, data[1][indx], center_data=True) nyq = 1 / (2 * 86400 * np.median(np.diff(data[0][indx]))) df = fundamental_spacing_integral(df, nyq, ls) freq = np.arange(df, nyq, df) power = ls.power(freq, normalization='psd', method='fast', assume_regular_frequency=True) N = len(ls.t) tot_MS = np.sum((ls.y - np.mean(ls.y))**2) / N tot_lomb = np.sum(power) normfactor = tot_MS / tot_lomb freq *= 10**6 power *= normfactor / (df * 10**6) return np.array((rebin(freq, 1), rebin(power, 1)))
def box_ls_pspec(cube, L, r_mpc, Nkbins=100, error=False, kz=None,cosmo=False): """ Estimate the 1D power spectrum for square regions with non-uniform distances using Lomb-Scargle periodogram in the radial direction.""" Nx,Ny,Nz = cube.shape try: Lx, Ly, Lz = L except TypeError: Lx = L; Ly = L; Lz = L # Assume L is a single side length, same for all dx, dy, dz = Lx/float(Nx), Ly/float(Ny), Lz/float(Nz) kx = np.fft.fftfreq(Nx,d=dx)*2*np.pi #Mpc^-1 ky = np.fft.fftfreq(Ny,d=dy)*2*np.pi #Mpc^-1 assert len(r_mpc) == Nz if kz is None: kz, powtest = LombScargle(r_mpc,cube[0,0,:]).autopower(nyquist_factor=1,normalization="psd") _cube = np.zeros((Nx,Ny,kz.size)) for i in range(cube.shape[0]): for j in range(cube.shape[1]): if kz is None: kz, power = LombScargle(r_mpc,cube[i,j,:]).autopower(nyquist_factor=1,normalization="psd") else: power = LombScargle(r_mpc, cube[i,j,:]).power(kz,normalization="psd") _cube[i,j] = np.sqrt(power) kz *= 2*np.pi _d = np.fft.fft2(_cube,axes=(0,1)) kx = kx[kx>0] ky = ky[ky>0] Nx = np.sum(kx>0) Ny = np.sum(ky>0) _d = _d[1:Nx+1,1:Ny+1,:] #Remove the nonpositive k-terms from the 2D FFT pk3d = np.abs(_d)**2/(Nx*Ny) results = bin_1d(pk3d,(kx,ky,kz),Nkbins=Nkbins, error=error) return results
def visibility(Planet, Observations): LS = LombScargle(Observations.t.value, Observations.RV.value) frequency, power = LS.autopower() false_alarm = LS.false_alarm_level(0.01, method='bootstrap') prob = LS.power(1. / Planet.P.value) if power.max() > false_alarm: return True else: return False
def visibility_MC(P, RV, t): LS = LombScargle(t.value, RV.value) frequency, power = LS.autopower() false_alarm = LS.false_alarm_level(0.01, method='bootstrap') prob = LS.power(1. / P.value) if power.max() > false_alarm: return True else: return False
def getLombScarglePeriodogram(peaks, tachogram, minFreq=0, maxFreq=.4, norm='standard'): ls = LombScargle(peaks, tachogram) freq, power = ls.autopower(minimum_frequency=minFreq, maximum_frequency=maxFreq, normalization=norm) print(sumWithNan(power)) return (freq, power)
def power_spectrum(t,y,freqs,idx_cut): 'compute power spectrum and integrate' model = LombScargle(t, y, dy=None, fit_mean=True, center_data=True, nterms=1, normalization='psd') ps = model.power(freqs) # integrate the entire power spectrum E = sintegrate.simps(ps, x=freqs, even='avg') if len(idx_cut) == 0: idx_cut = np.ones(freqs.size).astype(bool) # integrate only frequencies above cut-off Ec = sintegrate.simps(ps[idx_cut], x=freqs[idx_cut], even='avg') return ps, E, Ec
def periodogram(self, N=100000): """ Calculates the periodogram of the lightcurve """ fmin, fmax = self.fmin, self.fmax freq = np.linspace(fmin, fmax, N) model = LombScargle(self.times, self.mags) power = model.power(freq, method="fast", normalization="psd") # Convert to amplitude fct = np.sqrt(4. / len(self.times)) amp = np.sqrt(np.abs(power)) * fct return freq, amp
def circadian_movement_energies(g): t = (g["timestamp"].values / 1000.0) # seconds ylat = g["latitude"].values ylong = g["longitude"].values pHrs = np.arange(23.5, 24.51, 0.01) # hours pSecs = pHrs * 60 * 60 # seconds f = 1 / pSecs pgram_lat = LombScargle(t, ylat).power(frequency=f, normalization='psd') pgram_long = LombScargle(t, ylong).power(frequency=f, normalization='psd') E_lat = np.sum(pgram_lat) E_long = np.sum(pgram_long) return (E_lat, E_long)
def get_pgram(time,flux, min_p=1./24., max_p = 20.): finite = np.isfinite(flux) ls = LombScargle(time[finite],flux[finite],normalization='psd') frequency, power = ls.autopower(minimum_frequency=1./max_p,maximum_frequency=1./min_p,samples_per_peak=5) norm = np.nanstd(flux * 1e6)**2 / np.sum(power) # normalize according to Parseval's theorem - same form used by Oliver Hall in lightkurve fs = np.mean(np.diff(frequency*11.57)) # ppm^/muHz power *= norm/fs spower = gaussfilt(power,15) return frequency, power, spower
def lomb_scargle_periodogram(self, test_frequencies: (np.ndarray, u.Quantity)): times = self.flare_times if self._weighted: correlators = np.transpose(self.weighted_correlation_matrix) else: correlators = np.transpose(self.correlation_matrix) result_array = np.zeros((len(correlators), len(test_frequencies))) for lag_index in range(len(correlators)): ls_obj = LombScargle(times, correlators[lag_index]) result_array[lag_index] = ls_obj.power(test_frequencies) return result_array
def hybrid_periodogram(times, magnitudes, errors, give_ls=False): """ computes the power or periodicity (a hybrid method which uses both the Lomb-Scargle method and the Laffler Kinnman method) of a set of magnitude data (in one filter) over a series of periods. Parameters --------- times : numpy array or list the list of times for the data magnitudes : numpy array or list the list of magnitudes for the data errors : numpy array or list the list of errors for the data Returns ------- period : list a list of periods for which periodicity was computed menorah : list a list of periodicities based on both the periodicities returned by the Lomb-Scargle and Laffler-Kinnman methods at each period. Called menorah because the symbol used to represent this value is an upper-case psi, which I believe looks like a menorah with most of the candle holders broken off. """ # Lomb-Scargle LS = LombScargle(times, magnitudes) LS_frequency, LS_power = LS.autopower() # Converts frequency to period period = 1 / LS_frequency # Laffler-Kinman theta_list = [] # for each period that was used in LombScargle, this computes Theta for p in period: theta_list.append(Theta(p, times, magnitudes, errors)) theta_array = np.array(theta_list) # Finding Menorah (otherwise known as upper-case psi) menorah = (2 * LS_power) / theta_array if give_ls == True: return(period, menorah, LS) else: return period, menorah
def wavelet(self, fmin, fmax, windows=500, nfreq=1000, gwidth=1, ax=None, cmap='jet'): """ Calculates a simple Gaussian based wavelet to check the stability of the frequency over the LC""" t, y = self.times, self.mags def gaussian(x, mu, sig): return 1. / (np.sqrt(2. * np.pi) * sig) * np.exp(-np.power( (x - mu) / sig, 2.) / 2) num_days = t[-1] - t[0] ds = num_days / windows freq = np.linspace(fmin, fmax, nfreq) dynam, btime = [], [] # Loop over windows for i, n in enumerate(tqdm(range(windows))): window = gaussian(t, t[0] + i * ds, gwidth) btime.append(t[0] + i * ds) # determine FT power model = LombScargle(t, window * y) power = model.power(freq, method="fast", normalization="psd") for j in range(len(power)): dynam.append(power[j]) if ax is None: fig, ax = plt.subplots() # define shape of results array dynam = np.array(dynam, dtype='float64') dynam.shape = len(btime), len(power) ax.imshow(dynam.T, origin='lower', aspect='auto', cmap=cmap, extent=[btime[0], btime[-1], fmin, fmax], interpolation='bicubic') return ax
def ls(t, c, lowf=.01, highf=1, spp=10, ylim=(0, .5), xlow=0): ''' Plots Lomb-Scargle Periodogram and return top 10 highest-powered periods Inputs: ------- t: c: lowf: minimum_frequency to search highf: maximum frequency to search spp: samples per peak ylim: tuple of limits of plot xlow: int or float of lower end of x limit of plot Outputs: -------- first 10 values of DataFrame containing frequencies, periods, and power in descending order by power ''' fig = plt.figure(figsize=(10, 3)) gs = plt.GridSpec(2, 2) dy = np.sqrt(c) ax = fig.add_subplot(gs[:, 0]) ax.errorbar(t, c, dy, fmt='ok', ecolor='gray', markersize=3, capsize=0) ax.set(xlabel='time', ylabel='signal', title='Data and Model') ls = LombScargle(t, c) freq, power = ls.autopower(normalization='standard', minimum_frequency=lowf, maximum_frequency=highf, samples_per_peak=spp) plt.plot(1. / freq, power, color='rebeccapurple') plt.xlabel('Period (s)') plt.ylabel('Power') plt.xlim(xlow, 1 / lowf) plt.ylim(ylim) best_freq = freq[np.argmax(power)] print(1. / best_freq) frame = pd.DataFrame(columns=['f', 'pow', 'pd']) frame['f'] = freq frame['pow'] = power frame['pd'] = 1. / freq return (frame.sort_values(by='pow', ascending=False)[:10])
def psd_scargle(time, flux, Nsample=10.): """ Calculate the power spectral density using the Lomb-Scargle (L-S) periodogram Parameters: time (numpy array, float): time stamps of the light curve flux (numpy array, float): the flux variations of the light curve Nsample (optional, float): oversampling rate for the periodogram. Default value = 10. Returns: fr (numpy array, float): evaluated frequency values in the domain of the periodogram sc (numpy array, float): the PSD values of the L-S periodogram .. codeauthor:: Timothy Van Reeth <*****@*****.**> """ ndata = len(time) # The number of data points fnyq = 0.5 / np.median(time[1:] - time[:-1]) # the Nyquist frequency fres = 1. / (time[-1] - time[0]) # the frequency resolution fr = np.arange(0., fnyq, fres / float(Nsample)) # the frequencies sc1 = LombScargle(time, flux).power( fr, normalization='psd') # The non-normalized Lomb-Scargle "power" # Computing the appropriate rescaling factors (to convert to astrophysical units) fct = m.sqrt(4. / ndata) T = time.ptp() sc = fct**2. * sc1 * T # Ensuring the output does not contain nans if (np.isnan(sc).any()): fr = fr[~np.isnan(sc)] sc = sc[~np.isnan(sc)] return fr, sc
def fold(t, y, periodogram=False): """Folds data on pattern frequency if periodogram = True then returns T, frequency, power otherwise by default returns T only""" frequency, power = LombScargle( t, y).autopower() #find frequencies that contribute to describe data fpat = frequency[np.argmax( power )] #find the most important frequency, this will likely be the period of the orbit #create array of folded times T T = t * 0 #initialize array for folded times T c = 0 #initialize c the multiplication factor to choose the bin in which each datapoint goes for i in range(len(t)): #iterate over all numbers in t while ( t[i] >= c / fpat ): #if the time t[i] is larger than the current multiple of the period (=1/pattern frequency) c = c + 1 # then add 1 to the multiplication factor c until t[i] is smaller than c*period T[i] = t[i] - c / fpat #remove c-1 periods from the time if periodogram == True: return T, frequency, power else: return T
def getPeriod2(values): frequency, power = LombScargle(range(1, len(values) + 1), values).autopower() #plt.plot(frequency, power) #plt.show() # print power #power = abs(power) #max_pwr, max_f = sorted(zip(power,frequency),key=lambda x: x[0])[-1] #max_pwr2, max_f2 = sorted(zip(power,frequency),key=lambda x: x[0])[-2] p = 99.5 while True: threshold = np.percentile(power, p) #print threshold #print(np.where(abs(power)>threshold)[0]) #idx = np.where(abs(power)>threshold)[0] #threshold idx = np.where(abs(power) > threshold)[0] #print idx if (len(idx) > 3 and (idx[1] - idx[0]) == 1 and (idx[2] - idx[1]) == 1 and (idx[3] - idx[2]) == 1): break p -= 0.1 max_f = abs(frequency[idx][1]) max_f2 = abs(frequency[idx][2]) return [1 / max_f, 1 / max_f2]
def __init__(self, t, y, dy=None, show_progress=False, progress_bar=None, model=None, freq=None, **kwargs): self.model = model self.t = t self.y = y self.dy = dy self.freq = freq self.show_progress = show_progress self.progress_bar = progress_bar if self.show_progress and self.progress_bar is None: self.progress_bar = tqdm elif self.progress_bar is None: self.progress_bar = lambda x: x if self.dy is None: self.dy = np.ones_like(t) if self.freq is None: freqs, powers = LombScargle(t, y, dy).autopower(minimum_frequency=0.5, maximum_frequency=10, samples_per_peak=10) self.freq = freqs[np.argmax(powers)]
def __get_freq_psd_from_nn_intervals(nn_intervals, method, sampling_frequency, interpolation_method, vlf_band, hf_band): timestamp_list = __create_timestamp_list(nn_intervals) if method == "welch": funct = interpolate.interp1d(x=timestamp_list, y=nn_intervals, kind=interpolation_method) timestamps_interpolation = __create_interpolated_timestamp_list( nn_intervals, sampling_frequency) nni_interpolation = funct(timestamps_interpolation) nni_normalized = nni_interpolation - np.mean(nni_interpolation) freq, psd = signal.welch(x=nni_normalized, fs=sampling_frequency, window='hann', nfft=4096) elif method == "lomb": freq, psd = LombScargle(timestamp_list, nn_intervals, normalization='psd').autopower( minimum_frequency=vlf_band[0], maximum_frequency=hf_band[1]) else: raise ValueError( "Not a valid method. Choose between 'lomb' and 'welch'") return freq, psd
def Gen_flsp(time, flux, NyFreq, s): if len(time) != 1: frequency = np.linspace(0, NyFreq, s) power = LombScargle(time, flux).power(frequency, method='fast') return {'Freq': frequency, 'Amp': power} else: return {'Freq': np.linspace(0, 1, s), 'Amp': np.ones(s)}
def LS(t, y): f, p = LombScargle(t, y).autopower(normalization='psd', nyquist_factor=1.0, samples_per_peak=1) f = f * 1e6 # to uHz p = p * np.mean(y**2) / np.sum(p) / (f[1] - f[0]) # Bill's normalization return f, p
def fft(time, flux, kepler=False): import numpy as np from astropy.stats import LombScargle fr, f = LombScargle(time, flux).autopower(minimum_frequency=1e-9, maximum_frequency=10000e-6, samples_per_peak=50, normalization='standard', method='fast') # f = np.ma.masked_where(fr <= 3160e-6, f) # f = np.ma.masked_where(fr >= 3170e-6, f) f = np.ma.masked_where(fr <= 1.1574074074074074e-6, f) if kepler == True: hm = np.array([n * 47.2042e-6 for n in np.arange(50)]) for h in hm: f = np.ma.masked_where((h - 0.25e-6 <= fr) & (fr <= h + 0.25e-6), f) mfq = fr[f.argmax()] # print(f.argmax()) p = 1 / mfq / 86400. return fr, p, mfq, f, hm else: mfq = fr[f.argmax()] p = 1 / mfq / 86400. return fr, p, mfq, f
def estimate_frequencies(x, y, fmin=None, fmax=None, max_peaks=9, oversample=4.0, optimize_f=True): tmax = x.max() tmin = x.min() dt = np.median(np.diff(x)) df = 1.0 / (tmax - tmin) ny = 0.5 / dt if fmin is None: fmin = df if fmax is None: fmax = ny freq = np.arange(fmin, fmax, df / oversample) power = LombScargle(x, y).power(freq) # Find peaks peak_inds = (power[1:-1] > power[:-2]) & (power[1:-1] > power[2:]) peak_inds = np.arange(1, len(power) - 1)[peak_inds] peak_inds = peak_inds[np.argsort(power[peak_inds])][::-1] peaks = [] for j in range(max_peaks): i = peak_inds[0] freq0 = freq[i] alias = 2.0 * ny - freq0 m = np.abs(freq[peak_inds] - alias) > 25 * df m &= np.abs(freq[peak_inds] - freq0) > 25 * df peak_inds = peak_inds[m] peaks.append(freq0) peaks = np.array(peaks) if optimize_f: def chi2(nu): arg = 2 * np.pi * nu[None, :] * x[:, None] D = np.concatenate( [np.cos(arg), np.sin(arg), np.ones((len(x), 1))], axis=1) # Solve for the amplitudes and phases of the oscillations DTD = np.matmul(D.T, D) DTy = np.matmul(D.T, y[:, None]) w = np.linalg.solve(DTD, DTy) model = np.squeeze(np.matmul(D, w)) chi2_val = np.sum(np.square(y - model)) return chi2_val res = optimize.minimize(chi2, [peaks], method="L-BFGS-B") return res.x else: return peaks
def get_periodogram(t, amp=0, clip=80): time = t['t (sec)'] y = t['Amp {} Val'.format(amp)] pts = np.abs(y) < clip psd = LombScargle(time[pts], y[pts]).power(frequency=freqGrid) return psd
def perform_and_return_lombs(x, y): import numpy as np import matplotlib.pyplot as plt from scipy import signal from astropy.stats import LombScargle f = np.linspace(0.01, 3, 10_000) lombS = LombScargle(x, y) power = lombS.power(f) fmax = f[list(power).index(power.max())] period = 1/fmax pval = lombS.false_alarm_probability(max(list(power)), method='bootstrap') return power, f, period, pval, fmax
def periodogram(filenam): """Takes file filename and outputs best period with automatically determined frequency grid.""" time, magnitude, err = np.loadtxt(filenam, dtype='float', comments='%').T frequency, power = LombScargle(time, magnitude, err).autopower(minimum_frequency=0.01, maximum_frequency=20) period = 1 / frequency[np.argmax(power)] print period return period
def bootstrap(time, signal, fmin, fmax, n, noise_sdev, R, K, L): R_max = [] N = len(time) freq = np.linspace(fmin,fmax,n) for i in xrange(R): print 'iteration ', i+1, 'out of ', R L_list = [] signal_temp = signal[np.random.randint(N, size=N)] list_temp = np.random.randint(n, size=L) for g in xrange(L): center = list_temp[g] L_list.append((np.linspace(center - K/2, center + K/2, K+1)).tolist()) L_list = [item for sublist in L_list for item in sublist] L_list = (np.asarray(L_list)).astype(int) L_freq = freq[(L_list > 0) & (L_list < n)] power = LombScargle(time, signal_temp, noise_sdev).power(L_freq) R_max.append(power.max()) return R_max
def _get_freq_psd_from_nn_intervals(nn_intervals: List[float], method: str = WELCH_METHOD, sampling_frequency: int = 4, interpolation_method: str = "linear", vlf_band: namedtuple = VlfBand(0.003, 0.04), hf_band: namedtuple = HfBand(0.15, 0.40)) -> Tuple: """ Returns the frequency and power of the signal. Parameters --------- nn_intervals : list list of Normal to Normal Interval method : str Method used to calculate the psd. Choice are Welch's FFT or Lomb method. sampling_frequency : int Frequency at which the signal is sampled. Common value range from 1 Hz to 10 Hz, by default set to 7 Hz. No need to specify if Lomb method is used. interpolation_method : str Kind of interpolation as a string, by default "linear". No need to specify if Lomb method is used. vlf_band : tuple Very low frequency bands for features extraction from power spectral density. hf_band : tuple High frequency bands for features extraction from power spectral density. Returns --------- freq : list Frequency of the corresponding psd points. psd : list Power Spectral Density of the signal. """ timestamp_list = _create_timestamp_list(nn_intervals) if method == WELCH_METHOD: # ---------- Interpolation of signal ---------- # funct = interpolate.interp1d(x=timestamp_list, y=nn_intervals, kind=interpolation_method) timestamps_interpolation = _create_interpolated_timestamp_list(nn_intervals, sampling_frequency) nni_interpolation = funct(timestamps_interpolation) # ---------- Remove DC Component ---------- # nni_normalized = nni_interpolation - np.mean(nni_interpolation) # --------- Compute Power Spectral Density --------- # freq, psd = signal.welch(x=nni_normalized, fs=sampling_frequency, window='hann', nfft=4096) elif method == LOMB_METHOD: freq, psd = LombScargle(timestamp_list, nn_intervals, normalization='psd').autopower(minimum_frequency=vlf_band[0], maximum_frequency=hf_band[1]) else: raise ValueError("Not a valid method. Choose between 'lomb' and 'welch'") return freq, psd
def periodogram(bjd, flux, flux_err): t = (bjd - bjd[0])*24.0 mean = np.mean(flux) flux = flux - mean dt = [ t[i+1] - t[i-1] for i in range(1,len(t)-1)] fmax = 1.0/np.median(dt) fmin = 2.0/(max(t)) ls = LombScargle(t, flux, 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) best_f = freq[np.argmax(power)] period = 1.0/best_f #period from the LS periodogram fap_p = ls.false_alarm_probability(power.max()) amp = np.sqrt(power)/mean return np.array(freq), np.array(amp), period, fap_p
# mask_sig[chunck_pts*i:chunck_pts*(i+1)] = filtered_data_temp.mask # #print chunck_pts*(i+1) #mask_sig[-(len(time) % chunck_pts):] = 1 #mask_tot = time_temp.mask + mask_sig mask_tot = time_temp.mask + filtered_data.mask mask_tot[mask_tot == 2] = 1 time = np.ma.array(time, mask = mask_tot) print len(time), len(PDCSAP_FLUX) PDCSAP_FLUX = PDCSAP_FLUX[~time.mask] PDCSAP_FLUX_err = PDCSAP_FLUX_err[~time.mask] time = time[~time.mask] print len(time), len(PDCSAP_FLUX) frequency, power = LombScargle(time, PDCSAP_FLUX, PDCSAP_FLUX_err).autopower(minimum_frequency = 10.**(-0.05)*orbital_frequency, maximum_frequency = 10.**(0.8)*orbital_frequency) print 'freq lenght:', len(frequency) print 'freq bounds:', frequency.min(), 'to ', frequency.max() #Phase folding for illustrative purposes time = np.ma.mod(time +1,planet_period) data = np.ma.column_stack((time,PDCSAP_FLUX)) #2D array of t,signal data = data[np.lexsort((data[:,1],data[:,0]))] #we sort it fig = plt.figure() ax1 = fig.add_subplot(2, 1, 1) ax1.set_xlabel('Time (days)') ax1.set_ylabel('Flux') ax1.set_xlim([0,planet_period]) ax1.grid()
time_temp = np.ma.masked_inside(time_temp, sec_transit_right, sec_transit_left) time_temp = np.ma.masked_inside(time_temp, left_boundary, planet_period) print len(time) filtered_data = sigma_clip(flux, sigma=5, iters=None) mask_tot = time_temp.mask + filtered_data.mask mask_tot[mask_tot == 2] = 1 time = np.ma.array(time, mask = mask_tot) flux = flux[~time.mask] time = time[~time.mask] print len(time) frequency, power = LombScargle(time, flux).autopower(minimum_frequency=10.**(-0.05)*orbital_frequency, maximum_frequency=10.**(0.8)*orbital_frequency) print 'freq lenght:', len(frequency) time = np.ma.mod(time - 0.9,planet_period) data = np.ma.column_stack((time,flux)) data = data[np.lexsort((data[:,1],data[:,0]))] fig = plt.figure() ax1 = fig.add_subplot(2, 1, 1) ax1.set_xlabel('Time (days)') ax1.set_ylabel('Flux') ax1.set_xlim([0,planet_period]) ax1.grid() ax1.set_ylim([0.98,1.02]) ax1.get_yaxis().get_major_formatter().set_useOffset(False)
#####Comment these lines if you dont want to remove the transits time_temp1 = np.ma.masked_inside(time_temp, left_boundary, right_boundary) time_temp2 = np.ma.masked_inside(time_temp, left_boundary, right_boundary) time_temp2 = np.ma.masked_inside(time_temp2, sec_transit_left, planet_period) time_temp2 = np.ma.masked_inside(time_temp2, sec_transit_right, 0.) time_eclipse = np.ma.masked_inside(time_temp, sec_transit_left, planet_period) time_eclipse = np.ma.masked_inside(time_eclipse, sec_transit_right, 0.) time1 = time[~time_temp1.mask] time2 = time[~time_temp2.mask] signal1 = signal[~time_temp1.mask] signal2 = signal[~time_temp2.mask] print len(time), len(time1), len(time2) frequency, power = LombScargle(time, signal, noise_sdev).autopower() frequency1, power1 = LombScargle(time1, signal1, noise_sdev).autopower() frequency2, power2 = LombScargle(time2, signal2, noise_sdev).autopower() R, K, L = 300, 10, 40 fmin, fmax, n = frequency.min(), frequency.max(), len(frequency) N = len(time) print len(frequency) start_time = timer.time() R_max = bootstrap(time, signal, fmin, fmax, n, noise_sdev, R, K, L) R_max1 = bootstrap(time1, signal1, fmin, fmax, n, noise_sdev, R, K, L) R_max2 = bootstrap(time2, signal2, fmin, fmax, n, noise_sdev, R, K, L) print 'time: ', timer.time() - start_time, 'seconds' print (np.asarray(R_max)).max() fap_percentage = FAP(R_max, K, L, n, 0.001)
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 Recipies 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
mask_tot = time_temp.mask + filtered_data.mask mask_tot[mask_tot == 2] = 1 time = np.ma.array(time, mask = mask_tot) print len(time), len(PDCSAP_FLUX) PDCSAP_FLUX = PDCSAP_FLUX[~time.mask] PDCSAP_FLUX_err = PDCSAP_FLUX_err[~time.mask] time = time[~time.mask] print len(time), len(PDCSAP_FLUX) if LS_idx == 0: normval = len(time) pgram = diag.lombscargle(time, PDCSAP_FLUX - PDCSAP_FLUX.mean(), frequency) power, z = lomb_scargle(time, PDCSAP_FLUX, PDCSAP_FLUX_err, frequency, significance = [1.-0.682689492,1.-0.999999426697]) else: frequency, power = LombScargle(time, PDCSAP_FLUX, PDCSAP_FLUX_err).autopower(minimum_frequency=10.**(-0.05)*orbital_frequency, maximum_frequency=10.**(0.8)*orbital_frequency) print 'freq lenght:', len(frequency) #Phase folding for illustrative purposes ##centering## offset = ((first_transit%planet_period) - planet_period/2.) time = np.ma.mod(time - offset,planet_period) data = np.ma.column_stack((time,PDCSAP_FLUX)) #2D array of t,signal data = data[np.lexsort((data[:,1],data[:,0]))] #we sort it fig = plt.figure() ax1 = fig.add_subplot(2, 1, 1) ax1.set_xlabel('Time (days)') ax1.set_ylabel('Flux')
#####Comment these lines if you dont want to remove the transits time_temp1 = np.ma.masked_inside(time_temp, left_boundary, right_boundary) time_temp2 = np.ma.masked_inside(time_temp, left_boundary, right_boundary) time_temp2 = np.ma.masked_inside(time_temp2, sec_transit_left, planet_period) time_temp2 = np.ma.masked_inside(time_temp2, sec_transit_right, 0.) time_eclipse = np.ma.masked_inside(time_temp, sec_transit_left, planet_period) time_eclipse = np.ma.masked_inside(time_eclipse, sec_transit_right, 0.) time1 = time[~time_temp1.mask] time2 = time[~time_temp2.mask] signal1 = signal[~time_temp1.mask] signal2 = signal[~time_temp2.mask] print len(time), len(time1), len(time2) frequency, power = LombScargle(time, signal, noise_sdev).autopower() frequency1, power1 = LombScargle(time1, signal1, noise_sdev).autopower() frequency2, power2 = LombScargle(time2, signal2, noise_sdev).autopower() R, K, L = 500, 10, 100 fmin, fmax, n = frequency.min(), frequency.max(), len(frequency) fmin1, fmax1, n1 = frequency1.min(), frequency1.max(), len(frequency1) fmin2, fmax2, n2 = frequency2.min(), frequency2.max(), len(frequency2) print len(frequency) start_time = timer.time() R_max, R_max1, R_max2 = np.loadtxt('R_maxs_ellipsoid.txt', unpack=True) fap_percentage = np.percentile(R_max, 99.9) #FAP(R_max, K, L, n, 0.9, 0.02, 3.e-4, 1e-5) fap_percentage1 = np.percentile(R_max1, 99.9) #FAP(R_max1, K, L, n, 0.9, 0.02, 3.e-4, 1e-5) fap_percentage2 = np.percentile(R_max2, 99.9) #FAP(R_max2, K, L, n, 0.9, -1, 3.e-4, 1e-4)
# n = len(df) # # # Determine first and last Julian dates of data # t1 = df.ix[:0,'jd'] # t2 = df.ix[n-1:,'jd'] # t2 = t2.reset_index(drop=True) # tj = t2-t1 # Iterate over each observation within each star file jd = df['jd'] dmag = df['dmag'] var = df['dmag'].var() # periodogram(jd, dmag, t1, t2) # Periodogram frequency, power = LombScargle(jd, dmag).autopower() # power = power/var cols_out = np.column_stack((frequency.flatten(), power.flatten())) # hdr = 'frequency, power' np.savetxt('p3_' + h, cols_out, delimiter = ',', fmt = '%.3e', header = 'frequency,power', comments='') plt.plot(1/frequency, power)
print len(time), len(PDCSAP_FLUX) PDCSAP_FLUX = PDCSAP_FLUX[~time.mask] PDCSAP_FLUX_err = PDCSAP_FLUX_err[~time.mask] time = time[~time.mask] print len(time), len(PDCSAP_FLUX) #We compute the periodograms if LS_idx == 0: normval = len(time) pgram = diag.lombscargle(time, PDCSAP_FLUX - PDCSAP_FLUX.mean(), f) power, z = lomb_scargle(time, PDCSAP_FLUX, PDCSAP_FLUX_err, f, significance = [1.-0.682689492,1.-0.999999426697]) print z elif LS_idx == 1: pgram = LombScargle(time, PDCSAP_FLUX) power = pgram.score(2.*np.pi/f) elif LS_idx == 2: #print time power, z = lomb_scargle(time, PDCSAP_FLUX, PDCSAP_FLUX_err, f, significance = [1.-0.682689492,1.-0.999999426697]) print z #plt.plot(time, PDCSAP_FLUX) #plt.show() #Phase folding for illustrative purposes offset = ((first_transit%planet_period) - planet_period/2.) time = np.ma.mod(time - offset,planet_period) data = np.ma.column_stack((time,PDCSAP_FLUX)) #2D array of t,signal data = data[np.lexsort((data[:,1],data[:,0]))] #we sort it