# -*- coding: utf-8 -*-
from setuptools import setup

packages = \
['pykelihood', 'pykelihood.visualisation']

package_data = \
{'': ['*']}

install_requires = \
['cachetools>=4.2.1,<5.0.0',
 'numpy>=1.16.5,<2.0.0',
 'pandas>=1.2.1,<2.0.0',
 'scipy>=1.5.3,<2.0.0']

setup_kwargs = {
    'name': 'pykelihood',
    'version': '0.2.0',
    'description': 'Intuitive syntax for complex statistical model fitting and parameter sensitivity analysis.',
    'long_description': 'pykelihood\n==========\n\n\n.. image:: https://badge.fury.io/py/pykelihood.svg\n    :target: https://pypi.org/project/pykelihood/\n\n.. image:: https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit&logoColor=white\n   :target: https://github.com/pre-commit/pre-commit\n   :alt: pre-commit\n\n-----\nAbout\n-----\n\nPykelihood is a Python package for statistical analysis designed to give more flexibility to likelihood-based inference\nthan is possible with **scipy.stats**. Distributions are designed from an Object Oriented Programming (OOP) point of\nview.\n\nMain features include:\n\n- use any **scipy.stats** distribution, or make your own,\n- fit distributions of arbitrary complexity to your data,\n- add trends of different forms in the parameters of any distribution,\n- condition the likelihood with any form of penalty,\n- profile parameters with a penalised likelihood,\n- fit joint distributions and point processes with self exciting or time dependent intensity,\n- more to come...\n\n\n------------\nInstallation\n------------\n\nUsing pip\n------------------\n\n.. code::\n\n    pip install pykelihood\n\n\nFrom sources\n------------\n\n.. code::\n\n    git clone https://www.github.com/OpheliaMiralles/pykelihood\n\nor\n\n.. code::\n\n    gh repo clone OpheliaMiralles/pykelihood\n\n\n-----\nUsage\n-----\n\nBasics\n------\n\nThe most basic thing you can use ``pykelihood`` for is creating and manipulating distributions as objects.\n\n>>> from pykelihood.distributions import Normal\n>>> n = Normal(1, 2)\n>>> n\nNormal(loc=1.0, scale=2.0)\n\n``n`` is an *object* of type ``Normal``. It has 2 parameters, ``loc`` and ``scale``. They can be accessed like standard\nPython attributes:\n\n>>> n.loc\n1.0\n\nUsing the ``Normal`` object, you can calculate standard values using the same semantics as **scipy.stats**:\n\n>>> n.pdf([0, 1, 2])\narray([0.17603266, 0.19947114, 0.17603266])\n>>> n.cdf([0, 1, 2])\narray([0.30853754, 0.5       , 0.69146246])\n\nOr you can also generate random values according to this distribution:\n\n>>> n.rvs(10)\narray([ 3.31370986,  5.02699468, -0.3573229 ,  1.00460378, -3.26044871,\n        1.86362711, -0.84192901,  0.81132182, -2.03266978,  1.48079944])\n\n\nFitting\n-------\n\nLet\'s generate a larger sample from our previous object:\n\n>>> data = n.rvs(1000)\n>>> data.mean()\n1.025039359276458\n>>> data.std()\n1.9376460645596842\n\nWe can fit a ``Normal`` distribution to this data, which will return another ``Normal`` object:\n\n>>> n.fit(data)\nNormal(loc=1.0250822420920338, scale=1.9376400770300832)\n\nAs you can see, the values are slightly different from the moments in the data.\nThis is due to the fact that the ``fit`` method returns the Maximum Likelihood Estimator (MLE)\nfor the data, and is thus the result of an optimisation (using **scipy.optimize**).\n\nWe can also fix the value for some parameters if we know them:\n\n>>> n.fit(data, loc=1)\nNormal(loc=1.0, scale=1.9377929687500024)\n\nTrend fitting\n*************\n\nOne of the most powerful features of ``pykelihood`` is the ability to fit arbitrary distributions.\nFor instance, say our data has a linear trend with a very little gaussian noise we would like to capture:\n\n>>> import numpy as np\n>>> data = np.linspace(-1, 1, 365) + np.random.normal(0, 0.001, 365)\n>>> data[:10]\narray([-0.99802364, -0.99503679, -0.98900434, -0.98277981, -0.979487  ,\n       -0.97393519, -0.96853445, -0.96149152, -0.95564004, -0.95054887])\n\nIf we try to fit this without a trend, the resulting distribution will miss out on most of the information:\n\n>>> n.fit(data)\nNormal(loc=-3.6462053656578005e-05, scale=0.5789668679237372)\n\nLet\'s fit a ``Normal`` distribution with a trend in the loc parameter:\n\n>>> from pykelihood import kernels\n>>> n.fit(data, loc=kernels.linear(np.arange(365)))\nNormal(loc=linear(a=-1.0000458359290572, b=0.005494714384381866), scale=0.0010055323717468906)\n\n``kernels.linear(X)`` builds a linear model in the form *a + bX* where *a* and *b* are parameters to\nbe optimised for, and *X* is some covariate used to fit the data. If we assume the data were daily observations,\nthen we find all the values we expected: *-1* was the value on the first day, *0.05* was the daily increment\n(*2 / 365 = 0.05*), and there was a noise with std deviation *0.001*.\n\n\nParameter profiling\n*******************\n\nLikelihood based inference relies on parameter estimation. This is why it\'s important to quantify the sensitivity of a\nchosen model to each of those parameters. The ``stats_utils`` module in ``pykelihood`` includes the ``Likelihood``\nclass that allows to link a model to a set of observations by providing goodness of fit metrics and profiles for all\nparameters.\n\n>>> from pykelihood.stats_utils import Likelihood\n>>> from pykelihood.distributions import GEV\n>>> fitted_gev = GEV.fit(data, loc=kernels.linear(np.linspace(-1, 1, len(data))))\n>>> ll = Likelihood(fitted_gev, data, inference_confidence=0.99) # level of confidence for tests\n>>> ll.AIC  # the standard fit is without trend\n{\'AIC MLE\': -359.73533182968777, \'AIC Standard MLE Fit\': 623.9896838880583}\n>>> ll.profiles.keys()\ndict_keys([\'loc_a\', \'loc_b\', \'scale\', \'shape\'])\n>>> ll.profiles["shape"].head(5)\n      loc_a     loc_b     scale     shape   likelihood\n0 -0.000122  1.000812  0.002495 -0.866884  1815.022132\n1 -0.000196  1.000795  0.001964 -0.662803  1882.043541\n2 -0.000283  1.000477  0.001469 -0.458721  1954.283256\n3 -0.000439  1.000012  0.000987 -0.254640  2009.740282\n4 -0.000555  1.000016  0.000948 -0.050558  1992.812843\n\nConfidence intervals can be computed for specified metrics:\n\n>>> def metric(gev): return gev.loc()\n>>> ll.confidence_interval(metric)\n[-4.160287666875364, 4.7039931595123825]\n\n\n------------\nContributing\n------------\n\n`Poetry <http://python-poetry.org>`_ is used to manage ``pykelihood``\'s dependencies and build system. To install\nPoetry, you can refer to the `installation instructions <https://python-poetry.org/docs/#installation>`_, but it boils\ndown to running:\n\n.. code::\n\n    curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py | python\n\n\n\nTo configure your environment to work on pykelihood, run:\n\n.. code-block::\n\n    git clone https://www.github.com/OpheliaMiralles/pykelihood  # or any other clone method\n    cd pykelihood\n    poetry install\n\nThis will create a virtual environment for the project and install the required dependencies. To activate the virtual\nenvironment, be sure to run :code:`poetry shell` prior to executing any code.\n\nWe also use the `pre-commit <https://pre-commit.com>`_ library which adds git hooks to the repository. These must be installed with:\n\n.. code::\n\n   pre-commit install\n\nSome parts of the code base use the `matplotlib <https://matplotlib.org/>`_ and\n`hawkeslib <https://hawkeslib.readthedocs.io/en/latest/index.html>`_ package, but are for now not required to run most\nof the code, including the tests.\n\nTests\n-----\n\nTests are run using `pytest <https://docs.pytest.org/en/stable/>`_. To run all tests, navigate to the root folder or the\n``tests`` folder and type :code:`pytest`.\n',
    'author': 'Ophélia Miralles',
    'author_email': 'ophelia.miralles@epfl.ch',
    'maintainer': None,
    'maintainer_email': None,
    'url': 'https://github.com/OpheliaMiralles/pykelihood',
    'packages': packages,
    'package_data': package_data,
    'install_requires': install_requires,
    'python_requires': '>=3.7.1,<4.0.0',
}


setup(**setup_kwargs)
