Exemplo n.º 1
0
def fit_sine(time, flux, unc, period):
    """Fit a simple sine model fixed to the best-fit period."""
    def _sine_model(t, amp, yoffset, tshift):
        return amp * np.sin(2 * np.pi * t / period + tshift) + yoffset

    # Phase by the period, then extend the arrays
    # To fit two cycles instead of one
    phased_time = utils.phase(time, period)
    fit_time = np.append(phased_time, phased_time + period)
    fit_flux = np.append(flux, flux)
    fit_unc = np.append(unc, unc)

    # initial amplitude and yoffset are stdev and median, respectively
    p0 = np.append(utils.stats(flux, unc), 0.0)

    popt, pcov = opt.curve_fit(_sine_model,
                               fit_time,
                               fit_flux,
                               sigma=fit_unc,
                               p0=p0)
    perr = np.sqrt(np.diag(pcov))

    logging.debug("amplitude, yoffset, tshift")
    logging.debug(popt)
    logging.debug(perr)

    return phased_time, _sine_model(phased_time, *popt)
Exemplo n.º 2
0
def fit_sine(time, flux, unc, period):
    """Fit a simple sine model fixed to the best-fit period."""

    def _sine_model(t, amp, yoffset, tshift):
        return amp * np.sin(2 * np.pi * t / period + tshift) + yoffset

    # Phase by the period, then extend the arrays
    # To fit two cycles instead of one
    phased_time = utils.phase(time, period)
    fit_time = np.append(phased_time, phased_time + period)
    fit_flux = np.append(flux, flux)
    fit_unc = np.append(unc, unc)

    # initial amplitude and yoffset are stdev and median, respectively
    p0 = np.append(utils.stats(flux, unc), 0.0)

    popt, pcov = opt.curve_fit(_sine_model, fit_time, fit_flux, sigma=fit_unc, p0=p0)
    perr = np.sqrt(np.diag(pcov))

    logging.debug("amplitude, yoffset, tshift")
    logging.debug(popt)
    logging.debug(perr)

    return phased_time, _sine_model(phased_time, *popt)
Exemplo n.º 3
0
def pre_whiten(time, flux, unc_flux, period, kind="supersmoother",
               which="phased",phaser=None):
    """Phase a lightcurve and then smooth it.

    Inputs
    ------
    time, flux, unc_flux: array_like

    period: float
        period to whiten by

    kind: string, optional
        type of smoothing to use. Defaults to "supersmoother."
        Other types are "boxcar", "linear" 

    which: string, optional
        whether to smooth the "phased" lightcurve (default) or the "full" 
        lightcurve. 

    phaser: Float, optional (default=None)
        if kind="boxcar", phaser is the Half-width of the smoothing window.
        if kind="supersmoother", phaser is alpha (the "bass enhancement").

    Outputs
    -------
    white_flux, white_unc, smoothed_flux: arrays

    """

    # phase the LC by the period
    if period is not None:
        phased_time = utils.phase(time, period)
    else:
        phased_time = time

    if kind.lower()=="supersmoother":

        if phaser is None:
            logging.info("Phaser not set! "
                         "Set phaser=alpha (bass-enhancement value "
                         "for supersmoother) if desired.")

        if which.lower()=="phased":
            # Instantiate the supersmoother model object with the input period
            model = supersmoother.SuperSmoother(period=period)

            # Set up base arrays for phase for the fit
            x_vals = np.linspace(0,max(phased_time),1000)

            # Run a fit for the y phase
            y_fit = model.fit(phased_time, flux, unc_flux).predict(x_vals)

        elif which.lower()=="full":
            # Instantiate the supersmoother model object with the input period
            model = supersmoother.SuperSmoother(alpha=phaser)

            # Set up base arrays for time for the fit
            x_vals = np.linspace(min(time),max(time),1000)

            # run a fit for the y values
            y_fit = model.fit(time, flux, unc_flux).predict(x_vals)

        else:
            logging.warning("unknown which %s !!!",which)


    elif kind.lower()=="boxcar":

        if phaser is None:
            logging.info("Phaser not set! "
                         "Set phaser to the width of the smoothing "
                         "box in pixels!")

        if which.lower()=="phased":
            # sort the phases
            sort_locs = np.argsort(phased_time)
            x_vals = phased_time[sort_locs]
            flux_to_fit = flux[sort_locs]

        elif which.lower()=="full":
            x_vals = time
            flux_to_fit = flux
        else:
            logging.warning("unknown which %s !!!",which)

        # Use astropy's convolution function!
        boxcar_kernel = convolution.Box1DKernel(width=phaser,
                                                mode="linear_interp")
        y_fit = convolution.convolve(flux_to_fit, boxcar_kernel,
                                     boundary="wrap")

    elif kind=="linear":

         if which!="full":
             logging.warning("Linear smoothing only allowed for full "
                             "lightcurve! Switching to full mode.")
             which = "full"

         # Fit a line to the data
         pars = np.polyfit(time, flux, deg=1)
         m, b = pars
         smoothed_flux = m * time + b

    else:
        logging.warning("unknown kind %s !!!",kind)

    if (kind=="supersmoother") or (kind=="boxcar"):
        # Interpolate back onto the original time array
        interp_func = interpolate.interp1d(x_vals, y_fit)

        if which.lower()=="phased":
            smoothed_flux = interp_func(phased_time)
        elif which.lower()=="full":
            smoothed_flux = interp_func(time)
        else:
            logging.warning("unknown which %s !!!",which)

    # Whiten the input flux by subtracting the smoothed version
    # The smoothed flux represents the "bulk trend"
    white_flux = flux - smoothed_flux
    white_unc = unc_flux

    return white_flux, white_unc, smoothed_flux
Exemplo n.º 4
0
def plot_one(lightcurve,
             periodogram,
             best_period,
             power_threshold,
             data_label,
             residuals=None,
             aliases=None,
             axes_list=None,
             plot_title=None,
             phase_by=None,
             **plot_kwargs):
    """Plot input lightcurve, input periodogram, and input phased lightcurve
    INPUTS ARE DIFFERENT FROM REST OF CODE

    inputs
    ------
    lightcurve: arraylike (3, num_points)
        time, flux, unc_flux

    periodogram: arraylike (2, num_periods)
        periods_to_test, periodogram

    best_period: float

    power_threshold: float

    data_label: string
        name for the dataset being plotted

    residuals: array-like (default None)
        if provided, will be plotted in the bottom panel

    aliases: array-like (default None)
        if provided, will be plotted as vertical dotted lines on the 
        periodogram

    axes_list: optional, length=4
        if not provided, a new figure will be created.
        Axes should correspond to lightcurve, periodogram, phased lightcurve, 
        and phased residuals

    phase_by: float (default=None)
        if not None, the phased lightcurve will use this period 
        instead of best_period
    """

    # If axes_list is None, create the figure and axes with setup_plots
    if axes_list is None:
        fig, axes_list = setup_plots()
        plot_color, plot_marker = color1, shape1
    elif len(axes_list) != 4:
        logging.warning("Incorrect number of axes! Setting up new figure")
        fig, axes_list = setup_plots()
        plot_color, plot_marker = color1, shape1
    else:
        fig = plt.gcf()
        plot_color, plot_marker = color2, shape2

    # Top panel: lightcurve
    axes_list[0].plot(lightcurve[0],
                      lightcurve[1],
                      lw=0,
                      marker=plot_marker,
                      mec=plot_color,
                      mfc=plot_color,
                      ms=2,
                      label=data_label)
    # Also plot vertical lines for the period if it's longer than 2 days
    # (shorter than that isn't really comprehensible)
    if best_period >= 2.0:
        phase_mult = np.arange(min(lightcurve[0]), max(lightcurve[0]),
                               best_period)
        for pm in phase_mult:
            axes_list[0].axvline(pm,
                                 color=plot_color,
                                 linestyle="--",
                                 zorder=-100,
                                 alpha=0.75)

    # Middle panel: periodogram
    logging.debug("plot periodograms")
    axes_list[1].plot(periodogram[0], periodogram[1], color=plot_color)
    axes_list[1].axvline(best_period, color=plot_color, linestyle="--")

    axes_list[1].set_xlim(xmin=0.1)

    # Plot the power threshold, if it would be visible
    ymax = axes_list[1].get_ylim()[1]
    logging.debug("ymax %f", ymax)
    if (((type(power_threshold) == float) or (type(power_threshold) == int))
            and power_threshold < ymax):
        # Only one threshold
        axes_list[1].axhline(power_threshold, color="Grey", ls="-.")
    elif (type(power_threshold) == float and power_threshold >= ymax):
        logging.debug("peak lower than threshold")
    else:
        for threshold in power_threshold:
            logging.debug(threshold)
            axes_list[1].axhline(threshold, color=plot_color, ls="-.")

    # Plot aliases, if provided
    if aliases is not None:
        for alias in aliases:
            axes_list[1].axvline(alias, color=plot_color, linestyle=":")

    # Plot harmonics of the best period
    harmonics = np.array([0.5, 2]) * best_period
    for harm in harmonics:
        axes_list[1].axvline(harm, color=plot_color, linestyle="--", alpha=0.5)

    # Plot harmonics of the thruster firing time
    harmonics = np.append(0.125, np.arange(0.25, 2.1, 0.25))
    for harm in harmonics:
        axes_list[1].axvline(harm,
                             color="LightGrey",
                             linestyle="-",
                             alpha=0.5,
                             zorder=-111)

    # Bottom panels: phased lightcurve
    if phase_by is None:
        phase_by = best_period
    phased = utils.phase(lightcurve[0], phase_by)
    axes_list[2].plot(phased,
                      lightcurve[1],
                      lw=0,
                      marker=plot_marker,
                      mec=plot_color,
                      mfc=plot_color,
                      ms=2)
    axes_list[2].set_xlim(0, phase_by)
    if residuals is not None:
        axes_list[3].plot(phased,
                          residuals,
                          lw=0,
                          marker=plot_marker,
                          mec=plot_color,
                          mfc=plot_color,
                          ms=2)
        axes_list[3].set_xlim(0, phase_by)


#    plt.tight_layout()

    return fig, axes_list
Exemplo n.º 5
0
def plot_one(lightcurve, periodogram, best_period, power_threshold, data_label,
             residuals=None, aliases=None, axes_list=None,plot_title=None,
             phase_by=None, **plot_kwargs):
    """Plot input lightcurve, input periodogram, and input phased lightcurve
    INPUTS ARE DIFFERENT FROM REST OF CODE

    inputs
    ------
    lightcurve: arraylike (3, num_points)
        time, flux, unc_flux

    periodogram: arraylike (2, num_periods)
        periods_to_test, periodogram

    best_period: float

    power_threshold: float

    data_label: string
        name for the dataset being plotted

    residuals: array-like (default None)
        if provided, will be plotted in the bottom panel

    aliases: array-like (default None)
        if provided, will be plotted as vertical dotted lines on the 
        periodogram

    axes_list: optional, length=4
        if not provided, a new figure will be created.
        Axes should correspond to lightcurve, periodogram, phased lightcurve, 
        and phased residuals

    phase_by: float (default=None)
        if not None, the phased lightcurve will use this period 
        instead of best_period
    """

    # If axes_list is None, create the figure and axes with setup_plots
    if axes_list is None:
        fig, axes_list = setup_plots()
        plot_color, plot_marker = color1, shape1
    elif len(axes_list)!=4:
        logging.warning("Incorrect number of axes! Setting up new figure")
        fig, axes_list = setup_plots()
        plot_color, plot_marker = color1, shape1
    else:
        fig = plt.gcf()
        plot_color, plot_marker = color2, shape2

    # Top panel: lightcurve
    axes_list[0].plot(lightcurve[0], lightcurve[1], lw=0, 
                      marker=plot_marker,  mec=plot_color,
                      mfc=plot_color, ms=2, label=data_label)
    # Also plot vertical lines for the period if it's longer than 2 days
    # (shorter than that isn't really comprehensible)
    if best_period>=2.0:
        phase_mult = np.arange(min(lightcurve[0]), max(lightcurve[0]), 
                               best_period)
        for pm in phase_mult:
            axes_list[0].axvline(pm, color=plot_color, linestyle="--",
                                     zorder=-100, alpha=0.75)

    # Middle panel: periodogram
    logging.debug("plot periodograms")
    axes_list[1].plot(periodogram[0], periodogram[1], color=plot_color)
    axes_list[1].axvline(best_period, color=plot_color, linestyle="--")

    axes_list[1].set_xlim(xmin=0.1)

    # Plot the power threshold, if it would be visible
    ymax = axes_list[1].get_ylim()[1]
    logging.debug("ymax %f", ymax)
    if (((type(power_threshold)==float) or (type(power_threshold)==int))
        and power_threshold<ymax):
        # Only one threshold
        axes_list[1].axhline(power_threshold,color="Grey",ls="-.")
    elif (type(power_threshold)==float and 
          power_threshold>=ymax):
        logging.debug("peak lower than threshold")
    else:
        for threshold in power_threshold:
            logging.debug(threshold)
            axes_list[1].axhline(threshold,color=plot_color,ls="-.")

    # Plot aliases, if provided
    if aliases is not None:
        for alias in aliases:
            axes_list[1].axvline(alias, color=plot_color, linestyle=":")

    # Plot harmonics of the best period
    harmonics = np.array([0.5, 2])*best_period
    for harm in harmonics:
        axes_list[1].axvline(harm, color=plot_color, linestyle="--",
                             alpha=0.5)

    # Plot harmonics of the thruster firing time
    harmonics = np.append(0.125,np.arange(0.25,2.1,0.25))
    for harm in harmonics:
        axes_list[1].axvline(harm, color="LightGrey", linestyle="-",
                             alpha=0.5, zorder=-111)

    # Bottom panels: phased lightcurve
    if phase_by is None:
        phase_by = best_period
    phased = utils.phase(lightcurve[0], phase_by)
    axes_list[2].plot(phased, lightcurve[1], lw=0, marker=plot_marker, 
                      mec=plot_color, mfc=plot_color, ms=2)
    axes_list[2].set_xlim(0,phase_by)
    if residuals is not None:
        axes_list[3].plot(phased, residuals, lw=0, marker=plot_marker, 
                          mec=plot_color, mfc=plot_color, ms=2)
        axes_list[3].set_xlim(0,phase_by)

#    plt.tight_layout()

    return fig, axes_list