"""
* `new` - Constructor for Hybrid/Inner GP
* `predict_mean` - Predict GP interpolation mean on sample array
* `predict_mean_sgl` - Predict GP interpolation mean on single sample
* `predict_var` - Predict GP interpolation variance on sample array
* `predict_var_sgl` - Predict GP interpolation variance on single sample
* `predict_cov_sgl` - Predict GP covariance between two sample points
* `retrain` - Retrain GP with new hyperparameters
* `log_marginal_likelihood` - Evaluate the log marginal likelihood of the model
* `ndim` - Return the number of dimensions for the GP model
* `whitenoise` - Return the whitenoise hyperparameter for the GP model
* `to_hdf5` - Save the GP to HDF5
* `from_hdf5` - Load a GP from HDF5
* `generate_ldl` - Generate the LDL decomposition for a loaded model
"""
def test_sine():
    #### Imports #### 
    import time
    import numpy as np
    import matplotlib
    from matplotlib import pyplot as plt
    from csrk import HybridGP
    #### Setup ####
    xmin, xmax = 0, 16*np.pi
    ntrain = 100
    neval = 101
    X = np.atleast_2d(np.linspace(xmin,xmax,ntrain)).T
    Y = np.sin(X.flatten())
    Y_err = np.zeros_like(Y)
    scale = np.asarray([1.])
    whitenoise = 1e-9
    order = 3

    #### Train the GP ####
    gp = HybridGP(X, Y, Y_err, scale, whitenoise, order)
    #### Sample the GP ####
    x = np.atleast_2d(np.linspace(xmin,xmax,neval)).T
    # Test predict mean and get values
    y = gp.predict_mean(x)
    # Test predict_mean_sgl
    assert np.isclose(y[0], gp.predict_mean_sgl(x[0]))
    # Test predict_var
    var = gp.predict_var(x)
    # Test predict_var_sgl
    assert np.isclose(var[0], gp.predict_var_sgl(x[0]))
    # Test predict_cov_sgl
    cov_0_1 = gp.predict_cov_sgl(x[0], x[1])
    # Test retrain
    gp.retrain(2*scale,2*whitenoise,order)
    y2 = gp(x)
    # Estimate difference
    diff = np.abs(y - y2)
    assert diff.max() < 0.2

    #### Serialization ####
    gp.to_hdf5("test_serialization.hdf5", "sine_gp")
    gp2 = HybridGP.from_hdf5("test_serialization.hdf5", "sine_gp")
    assert gp2.whitenoise == gp.whitenoise
    assert gp2.ndim == 1
    assert np.allclose(gp2.scale, gp.scale)
    assert np.allclose(gp2.predict_mean(x), y2)
    #### Plot the result ####
    plt.plot(X.flatten(),Y, label="training")
    plt.plot(x,y, label="eval", linestyle='dashed')
    plt.legend()
    plt.savefig("test_csrk_sine.png")

if __name__ == "__main__":
    test_sine()
