def test_predictions_with_additional_regressors(sample_data):
    '''
        TODO: update
    '''

    my_chronos = Chronos(n_changepoints=0, max_iter=100)
    my_chronos.add_regressors("reg1", "mul")
    my_chronos.add_regressors("reg2", "mul")

    # Check not including the regressor throws an error
    with pytest.raises(KeyError):
        my_chronos.fit(sample_data)

    # Now check with the regressor
    sample_data['reg1'] = [1] * sample_data.shape[0]
    sample_data['reg2'] = [1] * sample_data.shape[0]
    my_chronos.fit(sample_data)

    future_df = my_chronos.make_future_dataframe(include_history=False)

    # Check not including the regressor throws an error
    with pytest.raises(KeyError):
        predictions = my_chronos.predict(future_df)

    # Now check with the regressor
    future_df['reg1'] = [1] * future_df.shape[0]
    future_df['reg2'] = [1] * future_df.shape[0]
    predictions = my_chronos.predict(future_df)

    predictions.drop('y', axis=1, inplace=True)

    assert (predictions.isna().sum().sum() == 0)
def test_plotting_no_history(capsys, monkeypatch, sample_data):
    '''
        Test the plotting of data when no history is provided.
        This was an issue raised in issue #2.
    '''
    for distribution in chronos_utils.SUPPORTED_DISTRIBUTIONS:
        my_chronos = Chronos(n_changepoints=0, max_iter=100, distribution=distribution)
        my_chronos.fit(sample_data)

        future_df = my_chronos.make_future_dataframe(include_history=False)
        predictions = my_chronos.predict(future_df)

        
        fig = plt.figure(figsize=(15,5))
        gs = gridspec.GridSpec(1,1, figure=fig)
        gs_section = gs[0,0]
        ax = fig.add_subplot(gs_section)

        #chronos_plotting.plot_predictions(predictions, my_chronos, fig=fig, gs_section=gs_section)
        chronos_plotting.plot_predictions(predictions, my_chronos, axs=ax)
        plt.savefig("test_prediction_no_history.png")

        std_error = capsys.readouterr().err
        assert(std_error == "")

    os.remove("test_prediction_no_history.png")
def test_error_for_nan_values(sample_data):
    '''
        Tests that Chronos complains when given
        nan values to fit on, but not to predict on
    '''
    def add_dummy_regressors(data):

        z = data.index.values
        y = 0.01 * z + np.sin(z / 30)
        data['y'] = y

        # should be easy since the target is just dummy1 + dummy2
        dummy1 = 0.01 * z
        dummy2 = np.sin(z / 30)
        data['dummy1'] = dummy1
        data['dummy2'] = dummy2

        return data

    sample_data = add_dummy_regressors(sample_data)

    my_chronos = Chronos(max_iter=200)

    # add dummies
    my_chronos.add_regressors("dummy1")
    my_chronos.add_regressors("dummy2")

    # check nan values fail for all columns
    for col in ['ds', 'y', 'dummy1', 'dummy2']:
        sample_data_with_nans = sample_data.copy()
        sample_data_with_nans.loc[0, col] = np.nan

        with pytest.raises(ValueError):
            my_chronos.fit(sample_data_with_nans)

    # check original data works
    my_chronos.fit(sample_data)

    future_df = my_chronos.make_future_dataframe()
    future_df = add_dummy_regressors(future_df)

    # check nan values fail for all columns EXCEPT
    # the target column when making predictions
    for col in ['ds', 'y', 'dummy1', 'dummy2']:
        future_df_with_nans = future_df.copy()
        future_df_with_nans.loc[0, col] = np.nan
        if (col == 'y'):
            predictions = my_chronos.predict(future_df_with_nans)
        else:
            with pytest.raises(ValueError):
                predictions = my_chronos.predict(future_df_with_nans)
def test_prediction_with_easy_extra_regressors(sample_data):
    '''
        Test that when the size of the data is too small, the
        number of changepoints gets adjusted
    '''

    z = sample_data.index.values
    y = 0.01 * z + np.sin(z / 30)
    sample_data['y'] = y

    # should be easy since the target is just dummy1 + dummy2
    dummy1 = 0.01 * z
    dummy2 = np.sin(z / 30)
    sample_data['dummy1'] = dummy1
    sample_data['dummy2'] = dummy2

    for distribution in chronos_utils.SUPPORTED_DISTRIBUTIONS:

        # Student t distribution has issues with the long tails
        if (distribution != chronos_utils.StudentT_dist_code):
            my_chronos = Chronos(max_iter=200, distribution=distribution)

            # add dummies
            my_chronos.add_regressors("dummy1")
            my_chronos.add_regressors("dummy2")

            my_chronos.fit(sample_data)

            future_df = my_chronos.make_future_dataframe()

            # Add dummies to future df
            z = future_df.index.values

            y = 0.01 * z + np.sin(z / 30)
            future_df['y'] = y

            dummy1 = 0.01 * z
            dummy2 = np.sin(z / 30)
            future_df['dummy1'] = dummy1
            future_df['dummy2'] = dummy2

            # Make predictions
            predictions = my_chronos.predict(future_df)

            # The predictions should be almost the same as the target
            assert (np.mean(np.abs(predictions['y'] - predictions['yhat'])) <
                    0.1)
def test_predictions_not_nan(sample_data):
    '''
        Make sure no nans are returned during the prediction process
    '''
    for method in ["MAP", "MLE"]:
        for distribution in chronos_utils.SUPPORTED_DISTRIBUTIONS:
            my_chronos = Chronos(n_changepoints=0,
                                 max_iter=100,
                                 distribution=distribution,
                                 method=method)
            my_chronos.fit(sample_data)

            future_df = my_chronos.make_future_dataframe(include_history=False)
            predictions = my_chronos.predict(future_df)

            predictions.drop('y', axis=1, inplace=True)
            #print(predictions)

            assert (predictions.isna().sum().sum() == 0)
def test_prediction_too_small_for_default_changepoints(sample_data):
    '''
        Test that when the size of the data is too small, the
        number of changepoints gets adjusted
    '''
    for distribution in chronos_utils.SUPPORTED_DISTRIBUTIONS:
        my_chronos = Chronos(max_iter=100,
                             n_changepoints=20,
                             distribution=distribution)

        # This should raise a warning about the size of the data and changepoint number
        with pytest.warns(RuntimeWarning):
            my_chronos.fit(sample_data.iloc[:10])

        future_df = my_chronos.make_future_dataframe()
        predictions = my_chronos.predict(future_df)

        assert (my_chronos._Chronos__number_of_changepoints <
                sample_data.shape[0])
def test_plotting(capsys, monkeypatch, sample_data):
    '''
        Test the plotting of data when no history is provided.
        This was an issue raised in issue #2.
    '''
    for distribution in chronos_utils.SUPPORTED_DISTRIBUTIONS:
        my_chronos = Chronos(n_changepoints=0, max_iter=100, distribution=distribution)
        my_chronos.fit(sample_data)

        future_df = my_chronos.make_future_dataframe(include_history=True)
        predictions = my_chronos.predict(future_df)


        with pytest.warns(UserWarning):
            chronos_plotting.plot_components(predictions, my_chronos, figure_name="test_prediction.png")

        std_error = capsys.readouterr().err
        assert(std_error == "")

    os.remove("test_prediction.png")