"""

biogeme.results
===============

Examples of use of several functions.

This is designed for programmers who need examples of use of the
functions of the module. The examples are designed to illustrate the
syntax. They do not correspond to any meaningful model.

:author: Michel Bierlaire
:date: Wed Nov 29 09:44:41 2023
"""
import pandas as pd
from biogeme.version import getText
import biogeme.biogeme as bio
import biogeme.database as db
import biogeme.results as res
from biogeme.expressions import Beta, Variable, exp


# %%
# Version of Biogeme.
print(getText())

# %%
# Definition of a database
df = pd.DataFrame(
    {
        'Person': [1, 1, 1, 2, 2],
        'Exclude': [0, 0, 1, 0, 1],
        'Variable1': [1, 2, 3, 4, 5],
        'Variable2': [10, 20, 30, 40, 50],
        'Choice': [1, 2, 3, 1, 2],
        'Av1': [0, 1, 1, 1, 1],
        'Av2': [1, 1, 1, 1, 1],
        'Av3': [0, 1, 1, 1, 1],
    }
)
df

# %%
my_data = db.Database('test', df)

# %%
# Definition of various expressions
Variable1 = Variable('Variable1')
Variable2 = Variable('Variable2')
beta1 = Beta('beta1', -1.0, -3, 3, 0)
beta2 = Beta('beta2', 2.0, -3, 10, 0)
likelihood = -(beta1**2) * Variable1 - exp(beta2 * beta1) * Variable2 - beta2**4
simul = beta1 / Variable1 + beta2 / Variable2
dict_of_expressions = {'loglike': likelihood, 'beta1': beta1, 'simul': simul}

# %%
# Creation of the BIOGEME object
my_biogeme = bio.BIOGEME(my_data, dict_of_expressions)
my_biogeme.modelName = 'simple_example'
my_biogeme.bootstrap_samples = 10
results = my_biogeme.estimate(run_bootstrap=True)
print(results)

# %%
# Dump results on a file
the_pickle_file = results.writePickle()
print(the_pickle_file)

# %%
# Results can be imported from a file previously generated
read_results = res.bioResults(pickleFile=the_pickle_file)
print(read_results)

# %%
# Results can be formatted in LaTeX
print(read_results.getLaTeX())

# %%
# Results can be formatted in HTML
print(read_results.getHtml())

# %%
# General statistics, including a suggested format.
statistics = read_results.getGeneralStatistics()
statistics

# %%
# The suggested format can be used as follows
for k, (v, p) in statistics.items():
    print(f'{k}:\t{v:{p}}')

# %%
# This result can be generated directly with the following function
print(results.printGeneralStatistics())

# %%
# Estimated parameters as pandas dataframe
read_results.getEstimatedParameters()

# %%
# Correlation results
read_results.getCorrelationResults()

# %%
# Obtain the values of the parameters
read_results.getBetaValues()

# %%
# Obtain the value of one or several specific parameters
read_results.getBetaValues(myBetas=['beta2'])

# %%
# Variance-covariance matrix (Rao-Cramer)
read_results.getVarCovar()

# %%
# Variance-covariance matrix (robust)
read_results.getRobustVarCovar()

# %%
# Variance-covaraince matrix (bootstrap)
read_results.getBootstrapVarCovar()

# %%
# Draws for sensitivity analysis are generated using
# bootstrapping. Any indicator can be generated by the model for each
# draw, and its empirical distribution can be investigate .
read_results.getBetasForSensitivityAnalysis(['beta1', 'beta2'], size=10)

# %%
# Results can be produced in the ALOGIT F12 format
print(read_results.getF12())

# %%
# Miscellaneous functions

# %%
# Likelihood ratio test. Let's first estimate a constrained model

# %%
beta2_constrained = Beta('beta2_constrained', 2.0, -3, 10, 1)
likelihood_constrained = (
    -(beta1**2) * Variable1
    - exp(beta2_constrained * beta1) * Variable2
    - beta2_constrained**4
)
my_biogeme_constrained = bio.BIOGEME(my_data, likelihood_constrained)
my_biogeme_constrained.modelName = 'simple_example_constrained'
results_constrained = my_biogeme_constrained.estimate()
print(results_constrained.short_summary())

# %%
# We can now perform a likelihood ratio test.
test_results = results.likelihood_ratio_test(results_constrained, 0.95)
print(test_results.message)
print(f'Statistic: {test_results.statistic}')
print(f'Threshold: {test_results.threshold}')

# %%
# Calculation of the :math:`p`-value
res.calcPValue(1.96)

# %%
# Compilation of results
dict_of_results = {'Model A': read_results, 'Model B': the_pickle_file}

# %%
df = res.compile_estimation_results(dict_of_results)
df
