示例#1
0
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
示例#2
0
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
示例#3
0
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
示例#4
0
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)
示例#6
0
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
示例#7
0
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])
示例#8
0
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