def lomb_scargle(t, y, dy=None, minfreq=1. / 365, maxfreq=1 / 2, npeaks=0, peaktol=0.05): # periodogram if isinstance(dy, np.ndarray): ls = LombScargle(t, y, dy) else: ls = LombScargle(t, y) frequency, power = ls.autopower(minimum_frequency=minfreq, maximum_frequency=maxfreq, samples_per_peak=10) probabilities = [0.1, 0.05, 0.01] try: pp = ls.false_alarm_level(probabilities) except: pp = [-1, -1, -1] # power probabilities # This tells us that to attain a 10% false alarm probability requires the highest periodogram peak to be approximately XX; 5% requires XX, and 1% requires XX. if npeaks > 0: # find peaks in periodogram peaks, amps = find_peaks(power, height=peaktol) Nterms = npeaks #min(npeaks,len(peaks)) fdata = np.zeros((Nterms, 3)) # frequency, amplitude, shift # fit amplitudes to each peak frequency if Nterms > 0 and npeaks > 0: # sort high to low peaks = peaks[np.argsort(amps['peak_heights'])[::-1]] # estimate priors for i in range(min(npeaks, len(peaks))): fdata[i, 0] = frequency[int(peaks[i])] fdata[i, 1] = np.sort(amps['peak_heights'])[::-1][i] * maxavg( y) #amplitude estimate fdata[i, 2] = 0 # phase shift estimate # ignore fitting frequencies priors = fdata.flatten() bounds = np.array([[0, 1], [0, max(y) * 1.5], [0, 2 * np.pi]] * Nterms).T def fit_wave(pars): wave = make_sin(t, pars) return (y - wave) / y res = least_squares(fit_wave, x0=priors, bounds=bounds) fdata = res.x.reshape(Nterms, -1) return frequency, power, fdata else: return frequency, power
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 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 plot_LombScargle(Planet, Observations): LS = LombScargle(Observations.t.value, Observations.RV.value, Observations.errRV.value) frequency, power = LS.autopower() plt.plot(frequency, power) plt.xlabel('frequency') plt.ylabel('Lomb-Scargle Power') plt.axvline(1. / Planet.P.value, lw=2, color='red', alpha=0.4) plt.axhline(LS.false_alarm_level(0.1, method='bootstrap'), linestyle=':', lw=2, color='black', alpha=0.4) plt.axhline(LS.false_alarm_level(0.01, method='bootstrap'), linestyle='-', lw=2, color='black', alpha=0.4) plt.ylim([0., 1.])
def bootstrap(time,flux,error,size,min_freq,max_freq): """ Function that performs the bootstraping :params: time: time series array (x value) :params: flux: time series array (y value) :params: error: error on the y :parms: size: :params: min_freq: minimum frequency to search :params: min_freq: maximum frequency to search :out: per_sum: array with the sum of all the Periodograms :out: peaks: array with frequency of each peak """ flux_distributions = np.zeros((len(flux),size)) for i in range(0,len(flux)): flux_distributions[i] = np.random.normal(flux[i],error[i],size) peaks = [] per_sum = 0 peaks_len = 0 for i in range(size): ls = LombScargle(time, flux_distributions[:,i], error) threshold = ls.false_alarm_level(0.99) freq, PLS = ls.autopower(minimum_frequency=min_freq,maximum_frequency=max_freq,samples_per_peak=1000) if type(per_sum) is int: per_sum = PLS else: per_sum += PLS peaks.append(freq[argrelextrema(PLS,np.greater)]) if i%(size/100) == 0: print("Progress: %i %%"%(i/size*100)) peaks = np.concatenate(peaks) return(per_sum,peaks)
def QPO_detect(tf_path, output=-1, df_path=-1, minfreq=0, maxfreq=1, sinterms=1, saveimage=True, savetext=False, is_window=False, norm='standard', renorm=False, poisson=True, FALs=True, plottitle="Lomb-Scargle Periodogram", plotcolor='black', probs=[0.95, 0.5, 0.05]): """ Input: many, many arguments. All but the first are optional. tf_path: path to data file output: path to output image (default ~/lomb_scargle.png) df_path: path to output text file (default ~/lomb_scargle.txt) minfreq: minimum allowed frequency (default 0 Hz) maxfreq: maximum allowed frequency (default 1 Hz) sinterms: no. of sin terms to be used in Lomb-Scargle fit (default 1) saveimage: whether or not to save the plot (default True) savetext: whether or not to save results to text file (default True) is_window: whether or not to show LS periodogram for the window of the input data (default False) norm: normalization to use (default 'standard') renorm: if True, set min. power to 0 and max. to 1 (default False) poisson: whether or not to apply correction to Poisson noise (default True) FALs: whether or not to plot false-alarm probability levels (default True, unless poisson=True, in which case they are not) plottitle: a title for the plot (default "Lomb-Scargle Periodogram") plotcolor: color of plot (default black) probs: false alarm probability levels to plot if plotted (defaults are 95%, 50%, and 5% chance of data being a result of random Gaussian noise) Output: a LombScargle object, frequency in the given interval, error on frequency, power in the given interval, and false alarm probability levels ** Plots show frequency in mHz, but all frequency outputs are in Hz Assumes data reduction is complete and that the textfile at tf_path is populated as one row per reduced image and tab-delimited columns: (0) stack, (1) exp avg [ms], (2) exp stdev [ms], (3) time avg [s], (4) time stdev [s], (5) centroid x_min, (6) centroid y_min, (7) pixel area, (8) photon counts, (9) photon count error If renormalized, every power p obtained from the LS is divided by the maximum power before plotting. If poisson is True (default), a decaying exponential is fit to the local minima of the powers obtained from the LS periodogram, which is then used to correct all powers. """ from astropy.stats import LombScargle import matplotlib.pyplot as plt import numpy as np # acquire the data for the Lomb-Scargle (LS) periodogram tf = open(tf_path, "r") contents = tf.readlines() tf.close() time = [] time_err = [] photon = [] photon_err = [] for line in contents: data = line.split("\t") time.append(float(data[3])) time_err.append(float(data[4])) photon.append(float(data[8])) photon_err.append(float(data[9])) # normalization of photon count with first count = 0 first_count = photon[0] photon_normed = [p - first_count for p in photon] # normalization of time with t1 = 0 first_time = time[0] time_normed = [t - first_time for t in time] # edit the center data and fit mean depending on whether the data is to be # viewed in window mode (i.e., if the periodogram is to show the window # which is convoluted with the raw data ) cd_opt = True fm_opt = True if is_window: photon_normed = [1.0] * len(photon_normed) photon_err = None cd_opt = False fm_opt = False # if fit_mean is true, then (from LS documentation): # "Include a constant offset as part of the model at each frequency. # This can lead to more accurate results, especially in the case of # incomplete phase coverage." # if center_data is True, then (from LS documentation): # "Pre-center the data by subtracting the weighted mean of the input data. # This is especially important if fit_mean = False" # create the LS object using autopower to generate a frequency sweep limbo = LombScargle(time_normed, photon_normed, photon_err, center_data=cd_opt, fit_mean=fm_opt, nterms=sinterms) # determine the error on the general frequency sweep to use in the # restricted frequencies error frequency, power = limbo.autopower(normalization=norm) frequency_rebin = np.histogram(frequency, len(time))[1].tolist() while (len(time) < len(frequency_rebin)): frequency_rebin.pop() frequency_err = [0] for i in range(1, len(frequency_rebin)): # start at 1 to avoid t=0 frequency_err.append(frequency_rebin[i] * time_err[i] / time[i]) frequency_err[0] = frequency_err[1] frequency_err = np.histogram(frequency_err, len(frequency))[1].tolist() while (len(frequency) < len(frequency_err)): frequency_err.pop() # set the frequencies and powers using autopower to generate a frequency # sweep which is restricted to a given frequency interval frequency_strict, power_strict = limbo.autopower(minimum_frequency=minfreq, maximum_frequency=maxfreq, normalization=norm) # determine the error on the resticted frequencies sweeped frequency_strict_rebin = np.histogram(frequency_strict, len(time))[1].tolist() while (len(time) < len(frequency_strict_rebin)): frequency_strict_rebin.pop() frequency_strict_err = [0] for i in range(1, len(frequency_strict_rebin)): # start at 1 to avoid t=0 frequency_strict_err.append(frequency_strict_rebin[i] * time_err[i] / time[i]) frequency_strict_err[0] = frequency_err[1] frequency_strict_err = np.histogram(frequency_strict_err, len(frequency_strict))[1].tolist() while (len(frequency_strict) < len(frequency_strict_err)): frequency_strict_err.pop() # enforce a renormalization of min power = 0, max power = 1 if desired if renorm: m = max(power) power = [p / m for p in power] ms = max(power_strict) power_strict = [ps / ms for ps in power_strict] # create the plot if image is to be saved, with mHz frequency units. # if FALs are to be added, calculate those and add to background. # if no output location is given, store as home/lomb_scargle.png frequency_strict_milli = [f * 1000.0 for f in frequency_strict] frequency_strict_milli_err = [f * 1000.0 for f in frequency_strict_err] # compute false alarm probabilities heights = limbo.false_alarm_level(probs) if poisson: # if we want to apply correction to Poisson noise power_strict = correct_poisson(frequency_strict_milli, power_strict, fit_lows=True) if not (power_strict): # if poisson corrections fails and returns None print("\nPoisson correction failed, breaking QPO detection.\n") return print("\nNote: FALs not plotted as Poisson noise is corrected for.\n") FALs = False if saveimage: # if the image is to be saved if output == -1: from os.path import expanduser output = expanduser("~") output = output + "lomb_scargle.png" if not FALs: # if false alarm probabilities should be plotted plt.switch_backend('agg') fig, ax0 = plt.subplots(figsize=(6, 2), nrows=1, sharex=False) else: plt.switch_backend('agg') fig, ax0 = plt.subplots(figsize=(6, 2), nrows=1, sharex=False) for i in range(len(heights)): ax0.axhline(y=heights[i], color='#d3d3d3') ax0.plot(frequency_strict_milli, power_strict, color=plotcolor) #mHz ax0.set_title(plottitle) ax0.set_ylabel('Power') ax0.set_xlabel('Frequency [mHz]') plt.savefig(output, bbox_inches='tight') # create the text file if data is to be saved. # if no output location is given, store as ~/lomb_scargle.txt if savetext: # if we want to save the results to a text file if df_path == -1: from os.path import expanduser df_path = expanduser("~") df_path = df_path + "lomb_scargle.txt" df = open(df_path, 'w+') for i in range(len(frequency)): #Hz if (i < len(frequency_strict)): line = str(frequency[i]) + "\t" + str(power[i]) + "\t" line += str(frequency_strict[i]) + "\t" + str( power_strict[i]) + "\n" df.write(line) else: line = str(frequency[i]) + "\t" + str(power[i]) + "\t \t \n" df.write(line) df.close() return limbo, frequency_strict, frequency_strict_err, power_strict, heights
def main(csvname, makeplot, w_pgram=1, w_expt=.2, w_WS=.30, w_magfit=.25, comment=False): ###Path assertions### catalogpath = ("/home/dmrowan/WhiteDwarfs/" + "Catalogs/MainCatalog_reduced_simbad_asassn.csv") sigmamag_path_NUV = "Catalog/SigmaMag_NUV.csv" sigmamag_path_FUV = "Catalog/SigmaMag_FUV.csv" assert (os.path.isfile(csvname)) assert (os.path.isfile(catalogpath)) assert (os.path.isfile(sigmamag_path_NUV)) assert (os.path.isfile(sigmamag_path_FUV)) assert (os.path.isdir('PDFs')) assert (os.path.isdir('Output')) #Find source name from csvpath csvpath = csvname for i in range(len(csvpath)): character = csvpath[i] if character == 'c': endidx = i - 5 break source = csvpath[0:endidx] #Grab the band (also checks we have source csv) if csvpath[-7] == 'N': band = 'NUV' band_other = 'FUV' elif csvpath[-7] == 'F': band = 'FUV' band_other = 'NUV' else: print("Not source csv, skipping") return assert (band is not None) bandcolors = {'NUV': 'red', 'FUV': 'blue'} alldata = pd.read_csv(csvpath) ###Alldata table corrections### alldata = WDutils.df_reduce(alldata) #Fix rows with incorrecct t_means by averaging t0 and t1 alldata = WDutils.tmean_correction(alldata) ###Apparent Magnitude### m_ab = np.nanmedian(alldata['mag_bgsub']) sigma_mag_all = median_absolute_deviation(alldata['mag_bgsub']) magdic = {"mag": [m_ab], "sigma": [sigma_mag_all], "weight": [1]} #c_magfit_all = find_cRMS(m_ab, sigma_mag_all, band) ###See if we have any data in the other band### if band == 'NUV': csvpath_other = csvpath.replace('NUV', 'FUV') else: csvpath_other = csvpath.replace('FUV', 'NUV') #Look for file in GALEXphot/LCs csvpath_other = f"/home/dmrowan/WhiteDwarfs/GALEXphot/LCs/{csvpath_other}" if os.path.isfile(csvpath_other): other_band_exists = True alldata_other = pd.read_csv(csvpath_other) else: other_band_exists = False if other_band_exists: #print(f"Generating additional LC data for {band_other} band") alldata_other = pd.read_csv(csvpath_other) alldata_other = WDutils.df_fullreduce(alldata_other) #Fix rows with weird t_mean time alldata_other = WDutils.tmean_correction(alldata_other) #Make correction for relative scales relativetup_other = WDutils.relativescales(alldata_other) alldata_tmean_other = relativetup_other.t_mean alldata_flux_bgsub_other = relativetup_other.flux alldata_flux_bgsub_err_other = relativetup_other.err ###Query Catalogs### bigcatalog = pd.read_csv(catalogpath) bigcatalog_idx = WDutils.catalog_match(source, bigcatalog) if len(bigcatalog_idx) == 0: print(f"{source} not in catalog") with open("../brokensources.txt", 'a') as f: f.write(f"source \n") return else: bigcatalog_idx = bigcatalog_idx[0] spectype = bigcatalog['spectype'][bigcatalog_idx] variability = bigcatalog['variability'][bigcatalog_idx] binarity = bigcatalog['binarity'][bigcatalog_idx] hasdisk = bigcatalog['hasdisk'][bigcatalog_idx] simbad_name = bigcatalog['SimbadName'][bigcatalog_idx] simbad_types = bigcatalog['SimbadTypes'][bigcatalog_idx] gmag = bigcatalog['gaia_g_mean_mag'][bigcatalog_idx] ###Break the alldata table into exposure groups### data = WDutils.dfsplit(alldata, 100) print(f"Dividing {source} {band} data into {len(data)} exposure groups") #Initialize Lists df_number = 1 c_vals = [] c_ws_vals = [] c_magfit_vals = [] c_exp_vals = [] c_pgram_vals = [] df_numbers_run = [] biglc_time = [] biglc_counts = [] biglc_err = [] strongest_periods_list = [] fap_list = [] ditherperiod_exists = False ###Loop through each exposure group### for df in data: if len(df['t1']) == 0: df_number += 1 continue ###Dataframe corrections### #Reset first time in t_mean to be 0 firsttime_mean = df['t_mean'][df.index[0]] df['t_mean'] = df['t_mean'] - firsttime_mean #Find exposure, c_exposure exposuretup = find_cEXP(df) firsttime = exposuretup.firsttime lasttime = exposuretup.lasttime exposure = exposuretup.exposure c_exposure = exposuretup.c_exposure c_exp_vals.append(c_exposure) #Filter for red and blue points coloredtup = WDutils.ColoredPoints(df) redpoints = coloredtup.redpoints bluepoints = coloredtup.bluepoints droppoints = np.unique(np.concatenate([redpoints, bluepoints])) #Corrections for relative scales relativetup = WDutils.relativescales(df) t_mean = relativetup.t_mean flux_bgsub = relativetup.flux flux_bgsub_err = relativetup.err if len(redpoints) != 0: t_mean_red = [t_mean[ii] for ii in redpoints] flux_bgsub_red = [flux_bgsub[ii] for ii in redpoints] flux_bgsub_err_red = [flux_bgsub_err[ii] for ii in redpoints] if len(bluepoints) != 0: t_mean_blue = [t_mean[ii] for ii in bluepoints] flux_bgsub_blue = [flux_bgsub[ii] for ii in bluepoints] flux_bgsub_err_blue = [flux_bgsub_err[ii] for ii in bluepoints] #Drop red and blue points df_reduced = df.drop(index=droppoints) df_reduced = df_reduced.reset_index(drop=True) if df_reduced.shape[0] < 10: df_number += 1 continue #Drop bad first and last points df_reduced = WDutils.df_firstlast(df_reduced) #Have to do this again to get the reduced indicies relativetup_reduced = WDutils.relativescales(df_reduced) t_mean = relativetup_reduced.t_mean flux_bgsub = relativetup_reduced.flux flux_bgsub_err = relativetup_reduced.err #Math points in other band if other_band_exists: idx_exposuregroup_other = np.where( (alldata_tmean_other > firsttime) & (alldata_tmean_other < lasttime))[0] t_mean_other = np.array( alldata_tmean_other[idx_exposuregroup_other] - firsttime_mean) flux_bgsub_other = np.array( alldata_flux_bgsub_other[idx_exposuregroup_other]) flux_bgsub_err_other = np.array( alldata_flux_bgsub_err_other[idx_exposuregroup_other]) ###Periodogram Creation### #Fist do the periodogram of the data ls = LombScargle(t_mean, flux_bgsub) freq, amp = ls.autopower(nyquist_factor=1) #Periodogram for dither information detrad = df_reduced['detrad'] ls_detrad = LombScargle(t_mean, detrad) freq_detrad, amp_detrad = ls_detrad.autopower(nyquist_factor=1) #Periodogram for expt information exptime = df_reduced['exptime'] ls_expt = LombScargle(t_mean, exptime) freq_expt, amp_expt = ls_expt.autopower(nyquist_factor=1) #Periodogram metric pgram_tup = find_cPGRAM(ls, amp_detrad, exposure) c_periodogram = pgram_tup.c ditherperiod_exists = pgram_tup.ditherperiod_exists strongest_period_tup = pgram_tup.strongest_period_tup if strongest_period_tup[0] != -1: strongest_periods_list.append(strongest_period_tup) fap_list.append(strongest_period_tup[2]) c_pgram_vals.append(c_periodogram) sspeaks = pgram_tup.sspeaks #Welch Stetson Variability Metric. if other_band_exists: c_ws = find_cWS(t_mean, t_mean_other, flux_bgsub, flux_bgsub_other, flux_bgsub_err, flux_bgsub_err_other, ditherperiod_exists, other_band_exists) else: c_ws = find_cWS(t_mean, None, flux_bgsub, None, flux_bgsub_err, None, ditherperiod_exists, other_band_exists) c_ws_vals.append(c_ws) #Sigma Mag Metric ###Grab magnitude information### df_sigma_mag = median_absolute_deviation(df_reduced['mag_bgsub']) magdic["mag"].append(m_ab) magdic["sigma"].append(df_sigma_mag) magdic["weight"].append(.25) c_magfit = find_cRMS(m_ab, df_sigma_mag, band) c_magfit_vals.append(c_magfit) ###Autocorrelation results### autocorr_result = selfcorrelation(flux_bgsub) #####GENERATE RATING##### print(c_periodogram, c_exposure, c_magfit, c_ws) C = ((w_pgram * c_periodogram) + (w_expt * c_exposure) + (w_magfit * c_magfit) + (w_WS * c_ws)) print(f"Exposure group {df_number} ranking: {C}") c_vals.append(C) if makeplot: ###Generate plot/subplot information### fig = plt.figure(df_number, figsize=(16, 12)) gs.GridSpec(4, 4) fig.tight_layout(rect=[0, 0.03, 1, 0.95]) fig.suptitle(f"Exposure group {df_number} with {exposure}s \n" f"Ranking: {C}") #Subplot for LC plt.subplot2grid((4, 4), (0, 0), colspan=4, rowspan=2) #Convert to JD here as well jd_t_mean = [ gphoton_utils.calculate_jd(t + firsttime_mean) for t in t_mean ] plt.errorbar(jd_t_mean, flux_bgsub, yerr=flux_bgsub_err, color=bandcolors[band], marker='.', ls='', zorder=4, label=band) plt.axhline(alpha=.3, ls='dotted', color=bandcolors[band]) if len(redpoints) != 0: jd_t_mean_red = [ gphoton_utils.calculate_jd(t + firsttime_mean) for t in t_mean_red ] plt.errorbar(jd_t_mean_red, flux_bgsub_red, yerr=flux_bgsub_err_red, color='#808080', marker='.', ls='', zorder=2, alpha=.5, label='Flagged') if len(bluepoints) != 0: jd_t_mean_blue = [ gphoton_utils.calculate_jd(t + firsttime_mean) for t in t_mean_blue ] plt.errorbar(jd_t_mean_blue, flux_bgsub_blue, yerr=flux_bgsub_err_blue, color='green', marker='.', ls='', zorder=3, alpha=.5, label='SigmaClip') if other_band_exists: jd_t_mean_other = [ gphoton_utils.calculate_jd(t + firsttime_mean) for t in t_mean_other ] plt.errorbar(jd_t_mean_other, flux_bgsub_other, yerr=flux_bgsub_err_other, color=bandcolors[band_other], marker='.', ls='', zorder=1, label=band_other, alpha=.25) ax = plt.gca() ax = WDutils.plotparams(ax) plt.title(f"{band} light curve") plt.xlabel('Time JD') plt.ylabel('Flux mmi') plt.legend(loc=1) plt.tight_layout(rect=[0, 0.03, 1, 0.95]) #Subplot for autocorr plt.subplot2grid((4, 4), (2, 2), colspan=1, rowspan=2) plt.plot(autocorr_result, 'b-', label='data') plt.title('Autocorrelation') plt.xlabel('Delay') plt.tight_layout(rect=[0, 0.03, 1, 0.95]) ax = plt.gca() ax = WDutils.plotparams(ax) #Subplot for periodogram plt.subplot2grid((4, 4), (2, 0), colspan=2, rowspan=2) ax = plt.gca() ax = WDutils.plotparams(ax) ax.plot(freq, amp, 'g-', label='Data') ax.plot(freq_detrad, amp_detrad, 'r-', label="Detrad", alpha=.25) ax.plot(freq_expt, amp_expt, 'b-', label="Exposure", alpha=.25) ax.set_title(f"{band} Periodogram") ax.set_xlabel('Freq [Hz]') ax.set_ylabel('Amplitude') ax.set_xlim(0, np.max(freq)) try: ax.set_ylim(0, np.max(amp) * 2) except: print("Issue with periodogram axes") top5amp_detrad = heapq.nlargest(5, amp_detrad) bad_detrad = pgram_tup.bad_detrad if any(np.isnan(x) for x in top5amp_detrad): print(f"No detrad peaks for exposure group {df_number}") else: for tup in bad_detrad: ax.axvspan(tup[0], tup[1], alpha=.1, color='black') #ax[0][1].axvline(x=nyquistfreq, color='r', ls='--') for level in [.05]: ax.axhline(ls.false_alarm_level(level), color='black', alpha=.5, ls='--', label=f"FAP: {level}") ax.axhline(ls.false_alarm_level(.25), color='black', alpha=.5, ls=':', label='FAP: 0.25') ax.legend() plt.tight_layout(rect=[0, 0.03, 1, 0.95]) #Subplot for png image plt.subplot2grid((4, 4), (2, 3), colspan=1, rowspan=2) pngfile = ( f"/home/dmrowan/WhiteDwarfs/GALEXphot/pngs/{source}.png") img1 = mpimg.imread(pngfile) plt.imshow(img1) #Turn of axes #ax[1][1].axis('off') plt.axis('off') plt.tight_layout(rect=[0, 0.03, 1, 0.95]) saveimagepath = f"PDFs/{source}-{band}qlp{df_number}.pdf" fig.savefig(saveimagepath) #Close figure fig.clf() plt.close('all') #Information for big light curve biglc_time.append(np.nanmean(t_mean + firsttime_mean)) biglc_counts.append(np.nanmean(flux_bgsub)) biglc_err.append(np.std(flux_bgsub_err) / np.sqrt(df_reduced.shape[0])) df_numbers_run.append(df_number) df_number += 1 ###Find the total rank, best rank, and best group### totalrank = np.sum(c_vals) if len(c_vals) != 0: bestrank = max(c_vals) idx_best = np.where(np.array(c_vals) == bestrank)[0][0] best_expt_group = df_numbers_run[idx_best] c_ws_best = c_ws_vals[idx_best] c_magfit_best = c_magfit_vals[idx_best] c_ws_max = max(c_ws_vals) c_exp_max = max(c_exp_vals) c_pgram_max = max(c_pgram_vals) else: bestrank = 0 idx_best = 0 best_expt_group = 0 c_ws_best = 0 c_magfit_best = 0 c_ws_max = 0 c_exp_max = 0 c_pgram_max = 0 print(f"{source} Best Rank: {bestrank} in group {best_expt_group}") ###Get most prevalent period from strongest_periods_list### all_periods = [tup[0] for tup in strongest_periods_list] all_ratios = [tup[1] for tup in strongest_periods_list] if len(all_periods) > 1: period_to_save = all_periods[np.where( np.asarray(all_ratios) == max(all_ratios))[0][0]] best_fap = min(fap_list) elif len(all_periods) == 1: period_to_save = all_periods[0] period_to_save = round(period_to_save, 3) best_fap = min(fap_list) else: period_to_save = '' best_fap = '' #Generate output csv with pandas outputdic = { "SourceName": [source], "Band": [band], "TotalRank": [round(totalrank, 3)], "BestRank": [round(bestrank, 3)], "Comment": [""], "ABmag": [round(m_ab, 2)], "StrongestPeriod": [period_to_save], "False Alarm Prob.": [best_fap], "WS metric": [c_ws_best], "c_magfit": [c_magfit_best], "SimbadName": [simbad_name], "SimbadTypes": [simbad_types], "Spectype": [spectype], "KnownVariable": [variability], "Binarity": [binarity], "Hasdisk": [hasdisk], "c_ws_max": [c_ws_max], "c_exp_max": [c_exp_max], "c_pgram_max": [c_pgram_max], } dfoutput = pd.DataFrame(outputdic) dfoutput.to_csv(f"Output/{source}-{band}-output.csv", index=False) if makeplot: #####Generate multiplage pdf##### ###Page 1### #Drop flagged rows from alldata alldata_flag_bool_vals = [ WDutils.badflag_bool(x) for x in alldata['flags'] ] alldata_flag_idx = np.where( np.array(alldata_flag_bool_vals) == True)[0] alldata = alldata.drop(index=alldata_flag_idx) alldata = alldata.reset_index(drop=True) #Make the correction for relative scales alldata_tmean = alldata['t_mean'] alldata_flux_bgsub = alldata['flux_bgsub'] alldata_medianflux = np.nanmedian(alldata_flux_bgsub) alldata_flux_bgsub = (alldata_flux_bgsub / alldata_medianflux) - 1.0 alldata_flux_bgsub_err = (alldata['flux_bgsub_err'] / alldata_medianflux) #Convert to JD alldata_jd_tmean = [ gphoton_utils.calculate_jd(t) for t in alldata_tmean ] biglc_jd_time = [gphoton_utils.calculate_jd(t) for t in biglc_time] if other_band_exists: alldata_jd_tmean_other = [ gphoton_utils.calculate_jd(t) for t in alldata_tmean_other ] #See if ASASSN data exists: if type(bigcatalog['ASASSNname'][bigcatalog_idx]) != str: asassn_exists = False else: asassn_exists = True asassn_name = bigcatalog['ASASSNname'][bigcatalog_idx] #Plot ASASSN data if asassn_exists: print("ASASSN data exists") figall = plt.figure(figsize=(16, 12)) gs.GridSpec(2, 2) figall.tight_layout(rect=[0, .03, 1, .95]) #Plot total light curve plt.subplot2grid((2, 2), (0, 0), colspan=2, rowspan=1) plt.errorbar(biglc_jd_time, biglc_counts, yerr=biglc_err, color=bandcolors[band], marker='.', ls='-', zorder=3, ms=15, label=band) plt.errorbar(alldata_jd_tmean, alldata_flux_bgsub, yerr=alldata_flux_bgsub_err, color='black', marker='.', zorder=2, ls='', alpha=.125) plt.xlabel('Time [s]') plt.ylabel('Relative Counts per Second') #Plot data in other band if other_band_exists: print(f"Plotting additional LC data for {band_other} band") plt.errorbar(alldata_jd_tmean_other, alldata_flux_bgsub_other, yerr=alldata_flux_bgsub_err_other, color=bandcolors[band_other], marker='.', ls='', zorder=1, alpha=.25, label=band_other) plt.xlabel('Time [s]') plt.ylabel('Flux MMI') plt.legend() #Plot ASASSN data plt.subplot2grid((2, 2), (1, 0), colspan=1, rowspan=1) axASASSN_LC = plt.gca() axASASSN_LC = WDutils.plotASASSN_LC(axASASSN_LC, asassn_name) axASASSN_LC = WDutils.plotparams(axASASSN_LC) plt.subplot2grid((2, 2), (1, 1), colspan=1, rowspan=1) axASASSN_pgram = plt.gca() axASASSN_pgram = WDutils.plotASASSN_pgram(axASASSN_pgram, asassn_name) axASASSN_pgram = WDutils.plotparams(axASASSN_pgram) else: figall, axall = plt.subplots(1, 1, figsize=(16, 12)) figall.tight_layout(rect=[0, 0.03, 1, 0.95]) #Plot total light curve axall.errorbar(biglc_jd_time, biglc_counts, yerr=biglc_err, color=bandcolors[band], marker='.', ls='-', zorder=3, ms=15, label=band) axall.errorbar(alldata_jd_tmean, alldata_flux_bgsub, yerr=alldata_flux_bgsub_err, color='black', marker='.', zorder=2, ls='', alpha=.125) #Plot data in other band if other_band_exists: print(f"Plotting additional LC data for {band_other} band") axall.errorbar(alldata_jd_tmean_other, alldata_flux_bgsub_other, yerr=alldata_flux_bgsub_err_other, color=bandcolors[band_other], marker='.', ls='', zorder=1, alpha=.25, label=band_other) axall.set_xlabel('Time [s]') axall.set_ylabel('Flux MMI') axall.legend() #Supertitle figall.suptitle( f"Combined Light curve for {source} in {band} \n" f"Best rank {round(bestrank, 2)} in df {best_expt_group} \n" f"Total rank {round(totalrank, 2)} in {len(data)} groups") all1saveimagepath = f"PDFs/{source}-{band}all1.pdf" figall.savefig(all1saveimagepath) #Clear figure figall.clf() plt.close('all') ###Page 2### Magnitude sigma plot and Source information #Get info from sigmamag csv file (from WDsigmamag) figall2, axall2 = plt.subplots(2, 1, figsize=(16, 12)) figall2.tight_layout(rect=[0, 0.03, 1, 0.95]) if band == 'NUV': df_sigmamag = pd.read_csv(sigmamag_path_NUV) else: assert (band == 'FUV') df_sigmamag = pd.read_csv(sigmamag_path_FUV) #Pull values, weights allmags = df_sigmamag['m_ab'] allsigma = df_sigmamag['sigma_m'] df_alphas = df_sigmamag['weight'] rgb_1 = np.zeros((len(df_alphas), 4)) rgb_1[:, 3] = df_alphas #Create magnitude bins using np.digitize axall2[0].scatter(allmags, allsigma, color=rgb_1, zorder=1, s=5) #Get information from magdic sourcemags = np.array(magdic['mag']) sourcesigmas = np.array(magdic['sigma']) sourcealphas = np.array(magdic['weight']) #Make lists for arrow points (above .3 sigma) arrow_mag = [] arrow_sigma = [] arrow_alpha = [] idx_arrow = np.where(sourcesigmas > .3)[0] for idx in idx_arrow: arrow_mag.append(sourcemags[idx]) arrow_sigma.append(.29) arrow_alpha.append(sourcealphas[idx]) #Drop these indicies from the source arrays sourcemags = np.delete(sourcemags, idx_arrow) sourcesigmas = np.delete(sourcesigmas, idx_arrow) sourcealphas = np.delete(sourcealphas, idx_arrow) #Make color code information rgb_2 = np.zeros((len(sourcealphas), 4)) rgb_2[:, 0] = 1.0 rgb_2[:, 3] = sourcealphas #Make color code information for arrow rgb_arrow = np.zeros((len(arrow_alpha), 4)) rgb_arrow[:, 0] = .3 rgb_arrow[:, 1] = .7 rgb_arrow[:, 2] = 1.0 rgb_arrow[:, 3] = arrow_alpha axall2[0].scatter(sourcemags, sourcesigmas, color=rgb_2, zorder=2) axall2[0].scatter(arrow_mag, arrow_sigma, color=rgb_arrow, marker="^", zorder=3) axall2[0].set_title("Sigma as a function of AB mag") axall2[0].set_xlabel("AB mag") axall2[0].set_ylabel("Sigma") axall2[0].set_ylim(ymin=0) axall2[0].set_ylim(ymax=.3) axall2[0].set_xlim(xmin=13) axall2[0].set_xlim(xmax=23) ###Information for text subplot axall2[1].set_ylim(ymin=0, ymax=1) information1 = """ Source name: \n Band: \n ABMagnitude: \n g Magitude: \n Spectral Type: \n SIMBAD Designation: \n SIMBAD Type list: \n Known Variability: \n Known Binarity: \n Has Disk: \n Strongest Period: \n """ information2 = (f"{source} \n" f"{band} \n" f"{round(m_ab, 4)} \n" f"{round(gmag, 4)} \n" f"{spectype} \n" f"{simbad_name} \n" f"{simbad_types}" f"{variability} \n" f"{binarity} \n" f"{hasdisk} \n" f"{period_to_save} \n") axall2[1].text(.2, 1, information1, size=15, ha='left', va='top') axall2[1].text(.7, 1, information2, size=15, ha='right', va='top') axall2[1].axis('off') all2saveimagepath = f"PDFs/{source}-{band}all2.pdf" figall2.savefig(all2saveimagepath) #Clear figure figall.clf() plt.close('all') #Generate PDF subprocess.run(['PDFcreator', '-s', source, '-b', band])
import numpy as np from astropy.stats import LombScargle rand = np.random.RandomState(42) t = 100 * rand.rand(60) dy = 1.0 y = np.sin(2 * np.pi * t) + dy * rand.randn(60) ls = LombScargle(t, y, dy) freq, power = ls.autopower() print(power.max()) print(ls.false_alarm_probability(power.max())) probabilities = [0.1, 0.05, 0.01] print(ls.false_alarm_level(probabilities)) #print(ls.false_alarm_probability(power.max(), method='bootstrap')) frequency, power = LombScargle(t, y).autopower(method='fastchi2') print(power)
#Plot the raw data ax[0].errorbar(star_time, star_flux, star_flux_err, fmt='.', elinewidth=1.5, capsize=0) ax[0].set(xlim=(np.min(star_time) -20, np.max(star_time)+20), xlabel='Observation time (days)', ylabel='Observed Flux') #Plot the periodogram ax[1].plot(1. / freq, PLS) ax[1].set(xlabel='period (days)', ylabel='Lomb-Scargle Power', xlim=(0.1, 50.0), ylim=(0, 1)); #Plot the false-alarm levels z_false = ls.false_alarm_level(0.001) ax[1].axhline(z_false, linestyle='dotted', color='black') print("Peak at: " + str(best_freq) + "\nFAP: " + str(ls.false_alarm_probability(PLS.max()))) #Plot the phased data & model in the inset inset.errorbar(phase, star_flux, star_flux_err, fmt='.k', capsize=0) inset.plot(phase_fit, mag_fit) inset.invert_yaxis() inset.set_xlabel('phase') inset.set_ylabel('Normalized Flux [Counts]') plt.savefig(DIR_SAVE+'filename to save') plt.show() #Plot the periodogram in a single figure fig, ax = plt.subplots() ax.plot(1. / freq, PLS)
def main(): """ Main function """ DIR = #Direcotry to load the input light curve DIR_SAVE = #Directory to save the out files pip = 'b' #Season of the data (based on the pipeline b (BANZAI - 2nd Season) or o (ORAC - 1st Season)) star_time, star_flux, star_flux_err = np.load(DIR+'Residuals_r_best_8_55555555-0208391.npy') time = star_time flux = star_flux error = star_flux_err if len(sys.argv) > 2: min_freq = 1/float(sys.argv[2]) max_freq = 1/float(sys.argv[1]) min_per = sys.argv[1] max_per = sys.argv[2] else: print("Please provide the limits as arguments [min] [max] \n Default is being used [0:10]") min_freq = 1/10.0 max_freq = 1/0.01 min_per = 1.0 max_per = 10.0 nproc = mp.cpu_count() nproc = max(1, nproc) - 1 logger = mp.log_to_stderr() logger.setLevel(logging.INFO) ntasks = 3 #Number of cores to use n_samples = 33000 #Number of samples to use inputs = [[time,flux,error,n_samples,min_freq,max_freq],[time,flux,error,n_samples,min_freq,max_freq],[time,flux,error,n_samples,min_freq,max_freq]] #inputs = [(,) for i in xrange(ntasks)] #Tuple with inputs for each worker in_q = mp.Queue() out_q = mp.Queue() procs = [mp.Process(target=worker, args=(in_q, out_q)) for i in range(nproc)] for i in range(ntasks): in_q.put(inputs[i]) for i in range(nproc): in_q.put('STOP') for p in procs: p.start() allout = [] peaks = np.array([]) per_sum = 0 while ntasks > 0: result = out_q.get() #Get data from workers peaks = np.concatenate((peaks,result[1])) if type(per_sum) is int: per_sum = result[0] else: per_sum += result[0] ntasks -= 1 for p in procs: p.join() ls = LombScargle(time, flux, error) fal = ls.false_alarm_level(0.5) freq, PLS = ls.autopower(minimum_frequency=min_freq, maximum_frequency=max_freq,samples_per_peak=1000) plot(freq,per_sum/(n_samples*3),ls) plt.hist(1/peaks,200) plt.show() np.save(DIR_SAVE+"bootstrap_"+str(min_per)+"_"+str(max_per)+"_"+str(pip)+"_samp_"+str(n_samples*3)+".npy",(freq,per_sum,fal,peaks)) return 0