Esempio n. 1
0
def sample_carma(p, q):
    """
    Randomly generate a stationary CARMA model given the orders (p and q).

    Args:
        p (int): The p order of a CARMA(p, q) model.
        q (int): The q order of a CARMA(p, q) model.

    Returns:
        AR and MA coefficients in two separate arrays.
    """
    init_log_fcoeffs = carma_log_fcoeff_init(p, q)
    logAR, logMA = CARMA_term.fcoeffs2carma_log(init_log_fcoeffs, p)
    return np.exp(logAR), np.exp(logMA)
Esempio n. 2
0
def pred_lc(t, y, yerr, params, p, t_pred, return_var=True):
    """
    Generate predicted values at particular time stamps given the initial
    time series and a best-fit model.

    Args:
        t (array(float)): Time stamps of the initial time series.
        y (array(float)): y values (i.e., flux) of the initial time series.
        yerr (array(float)): Measurement errors of the initial time series.
        params (array(float)): Best-fit CARMA parameters
        p (int): The AR order (p) of the given best-fit model.
        t_pred (array(float)): Time stamps to generate predicted time series.
        return_var (bool, optional): Whether to return uncertainties in the mean
            prediction. Defaults to True.

    Returns:
        (array(float), array(float), array(float)): t_pred, mean prediction at t_pred
        and uncertainties (variance) of the mean prediction.
    """

    assert p >= len(
        params) - p, "The dimension of AR must be greater than that of MA"

    # get ar, ma
    ar = params[:p]
    ma = params[p:]

    # reposition lc
    y_aln = y - np.median(y)

    # init kernel, gp and compute matrix
    kernel = CARMA_term(np.log(ar), np.log(ma))
    gp = celerite.GP(kernel, mean=0)
    gp.compute(t, yerr)

    try:
        mu, var = gp.predict(y_aln, t_pred, return_var=return_var)
    except FloatingPointError as e:
        print(e)
        print("No (super small) variance will be returned")
        return_var = False
        mu, var = gp.predict(y_aln, t_pred, return_var=return_var)

    return t_pred, mu + np.median(y), var
Esempio n. 3
0
def carma_fit(
    t,
    y,
    yerr,
    p,
    q,
    init_func=None,
    neg_lp_func=None,
    optimizer_func=None,
    n_opt=20,
    user_bounds=None,
    scipy_opt_kwargs={},
    scipy_opt_options={},
    debug=False,
):
    """
    Fit an arbitrary CARMA model

    The default settings are optimized for normalized LCs.

    Args:
        t (array(float)): Time stamps of the input time series (the default unit is day).
        y (array(float)): y values of the input time series.
        yerr (array(float)): Measurement errors for y values.
        p (int): The p order of a CARMA(p, q) model.
        q (int): The q order of a CARMA(p, q) model.
        init_func (object, optional): A user-provided function to generate initial
            guesses for the optimizer. Defaults to None.
        neg_lp_func (object, optional): A user-provided function to compute negative
            probability given an array of parameters, an array of time series values and
            a celerite GP instance. Defaults to None.
        optimizer_func (object, optional): A user-provided optimizer function.
            Defaults to None.
        n_opt (int, optional): Number of optimizers to run.
            Defaults to 20.
        user_bounds (array(float), optional): Parameter boundaries for the default
            optimizer. If p > 2, these are boundaries for the coefficients of the
            factored polynomial. Defaults to None.
        scipy_opt_kwargs (dict, optional): Keyword arguments for scipy.optimize.minimize.
            Defaults to {}.
        scipy_opt_options (dict, optional): "options" argument for scipy.optimize.minimize.
            Defaults to {}.
        debug (bool, optional): Turn on/off debug mode. Defaults to False.

    Raises:
        celerite.solver.LinAlgError: For non-positive definite autocovariance matrices.

    Returns:
        array(float): Best-fit parameters
    """
    # set core config
    dim = int(p + q + 1)
    mode = "fcoeff" if p > 2 else "param"

    # init bounds for fitting
    if user_bounds is not None and (len(user_bounds) == dim):
        bounds = user_bounds
    else:
        bounds = [(-15, 15)] * dim
        bounds[p:-1] = [(a[0] - 5, a[1] - 5) for a in bounds[p:-1]]
        bounds[-1] = (-15, 5)

    # re-position lc
    t = t - t[0]
    y = y - np.median(y)
    y_std = mad(y) * 1.4826
    y = y / y_std
    yerr = yerr / y_std

    # initialize parameter and kernel
    ARpars, MApars = sample_carma(p, q)
    kernel = CARMA_term(np.log(ARpars), np.log(MApars))
    gp = GP(kernel, mean=0)
    gp.compute(t, yerr)

    # determine/set init func
    if init_func is not None:
        init = init_func
    else:
        init = partial(carma_log_fcoeff_init, p, q)

    # determine/set negative log probability function
    if neg_lp_func is None:
        neg_lp = partial(neg_lp_flat, bounds=np.array(bounds), mode=mode)
    else:
        neg_lp = neg_lp_func

    # determine/set optimizer function
    if optimizer_func is None:
        scipy_opt_kwargs.update({"method": "L-BFGS-B", "bounds": bounds})
        opt = partial(
            scipy_opt,
            mode=mode,
            opt_kwargs=scipy_opt_kwargs,
            opt_options=scipy_opt_options,
            debug=debug,
        )
    else:
        opt = optimizer_func

    # get best-fit solution & adjust MA params (multiply by y_std)
    best_fit_return = opt(y, gp, init, neg_lp, n_opt)
    best_fit_return[p:] = best_fit_return[p:] * y_std

    return best_fit_return
Esempio n. 4
0
def scipy_opt(
    y,
    gp,
    init_func,
    neg_lp_func,
    n_opt,
    mode="fcoeff",
    debug=False,
    opt_kwargs={},
    opt_options={},
):
    """
    A wrapper for scipy.optimize.minimize method.

    Args:
        y (array(float)): y values of the input time series.
        gp (object): celerite GP object with a proper CARMA kernel.
        init_func (object): A user-provided function to generate initial
            guesses for the optimizer. Defaults to None.
        neg_lp_func (object): A user-provided function to compute negative
            probability given an array of parameters, an array of time series values and
            a celerite GP instance. Defaults to None.
        n_opt (int): Number of iterations to run the optimizer.
        mode (str, optional): The parameter space in which to make proposals, this
            should be determined in the "_fit" functions based on the value of the p
            order. Defaults to "fcoeff".
        debug (bool, optional): Turn on/off debug mode. Defaults to False.
        opt_kwargs (dict, optional): Keyword arguments for scipy.optimize.minimize.
            Defaults to {}.
        opt_options (dict, optional): "options" argument for scipy.optimize.minimize.
            Defaults to {}.

    Returns:
        Best-fit parameters if "debug" is False, an array of scipy.optimize.OptimizeResult objects otherwise.
    """

    initial_params = init_func(size=n_opt)
    dim = gp.kernel.p + gp.kernel.q + 1

    rs = []
    for i in range(n_opt):
        r = minimize(
            neg_lp_func,
            initial_params[i],
            args=(y, gp),
            **opt_kwargs,
            options=opt_options,
        )

        rs.append(r)

    if debug:
        return rs
    else:
        good_rs = [r for r in rs if r.success and r.fun != -np.inf]

        if len(good_rs) == 0:
            return [np.nan] * dim
        else:
            lls = [-r.fun for r in good_rs]
            log_sols = [r.x for r in good_rs]
            best_sol = log_sols[np.argmax(lls)]

            if mode == "fcoeff":
                return np.concatenate(CARMA_term.fcoeffs2carma(best_sol, gp.kernel.p))
            else:
                return np.exp(best_sol)
Esempio n. 5
0
def carma_fit(t,
              y,
              yerr,
              p,
              q,
              de=True,
              debug=False,
              mode="coeff",
              user_bounds=None,
              n_iter=10):
    """Fit time series to any CARMA model.

    Args:
        t (object): An array of time stamps in days.
        y (object): An array of y values.
        yerr (object): An array of the errors in y values.
        p (int): P order of a CARMA(p, q) model.
        q (int): Q order of a CARMA(p, q) model.
        de (bool, optional): Whether to use differential_evolution as the
            optimizer. Defaults to True.
        debug (bool, optional): Turn on/off debug mode. Defaults to False.
        mode (str, optional): Specify which space to sample, 'param' or 'coeff'.
            Defaults to 'coeff'.
        user_bounds (list, optional): Factorized polynomial coefficient boundaries
            for the optimizer. Defaults to None.
        n_iter (int, optional): Number of iterations to run the optimizer if de==False.
            Defaults to 10.

    Raises:
        celerite.solver.LinAlgError: For non-positive definite matrices.

    Returns:
        object: An array of best-fit CARMA parameters
    """
    dim = int(p + q + 1)
    best_fit = np.empty(dim)

    # init bounds for fitting
    if user_bounds is not None and (len(user_bounds) == dim):
        bounds = user_bounds
    elif p == 2 and q == 1:
        bounds = [(-10, 13), (-14, 7), (-10, 6), (-12, 3)]
    elif p == 2 and q == 0:
        bounds = [(-10, 16), (-14, 16), (-13, 15)]
    else:
        ARbounds = [(-6, 3)] * p
        MAbounds = [(-6, 1)] * (q + 1)
        bounds = ARbounds + MAbounds

    # re-position lc
    t = t - t[0]
    y = y - np.median(y)

    # initialize parameter and kernel
    ARpars, MApars = sample_carma(p, q)
    kernel = CARMA_term(np.log(ARpars), np.log(MApars))
    gp = GP(kernel, mean=np.median(y))
    gp.compute(t, yerr)

    if p > 2:
        mode = "coeff"

    if mode == "coeff":
        init_func = lambda: carma_log_fcoeff_init(dim)
    else:
        init_func = lambda: carma_log_param_init(dim)

    if de:
        best_fit_return = _de_opt(
            y,
            best_fit,
            gp,
            init_func,
            mode,
            debug,
            bounds,
        )
    else:
        best_fit_return = _min_opt(
            y,
            best_fit,
            gp,
            init_func,
            mode,
            debug,
            bounds,
            n_iter,
        )

    return best_fit_return
Esempio n. 6
0
def carma_fit(
    t,
    y,
    yerr,
    p,
    q,
    debug=False,
    user_bounds=None,
    init_ranges=None,
    n_iter=15,
):
    """
    Fit time series to an arbitrary CARMA model.

    Args:
        t (array(float)): Time stamps of the input time series (the default unit is day).
        y (array(float)): y values of the input time series.
        yerr (array(float)): Measurement errors for y values.
        p (int): The p order of a CARMA(p, q) model.
        q (int): The q order of a CARMA(p, q) model.
        debug (bool, optional): Turn on/off debug mode. Defaults to False.
        user_bounds (list, optional): Parameter boundaries for the optimizer. If p > 2,
            these are boundaries for the coefficients of the factored polynomial.
            Defaults to None.
        init_ranges (list, optional): Tuples of custom ranges to draw initial
            parameter proposals from. If p > 2, same as for the user_bounds. Defaults to
            None.
        n_iter (int, optional): Number of iterations to run the optimizer if de==False.
            Defaults to 15.

    Raises:
        celerite.solver.LinAlgError: For non-positive definite autocovariance matrices.

    Returns:
        array(float): Best-fit parameters
    """
    dim = int(p + q + 1)
    best_fit = np.empty(dim)

    # init bounds for fitting
    if user_bounds is not None and (len(user_bounds) == dim):
        bounds = user_bounds
    else:
        bounds = [(-15, 15)] * dim

    # re-position lc
    t = t - t[0]
    y = y - np.median(y)

    # determine shift due amp too large/small
    shift = np.array(0)
    if np.std(y) < 1e-4 or np.std(y) > 1e4:
        shift = np.log(np.std(y))

    # initialize parameter and kernel
    ARpars, MApars = sample_carma(p, q, shift=float(shift))
    kernel = CARMA_term(np.log(ARpars), np.log(MApars))
    gp = GP(kernel, mean=0)
    gp.compute(t, yerr)

    if p > 2:
        mode = "coeff"
        init_func = lambda: carma_log_fcoeff_init(
            p, q, ranges=init_ranges, size=n_iter, shift=float(shift))
        bounds[-1] += shift
    else:
        mode = "param"
        init_func = lambda: carma_log_param_init(
            p, q, ranges=init_ranges, size=n_iter, shift=float(shift))
        bounds[p:] += shift

    best_fit_return = _min_opt(
        y,
        best_fit,
        gp,
        init_func,
        mode,
        debug,
        bounds,
        n_iter,
    )

    return best_fit_return