#!/usr/bin/env python
#-*- coding: utf-8 -*-
"""Distributions
.. topic:: distribution.py summary
Provides standard distributions
:Code status: mature
:Documentation status: to be completed
:Author: Thomas Cokelaer <Thomas.Cokelaer@sophia.inria.fr>
:Revision: $Id$
"""
__version__ = "$Id$"
from . import interface
from . import error
from openalea.stat_tool._stat_tool import *
from openalea.stat_tool._stat_tool import (
_DiscreteParametricModel,
_DiscreteDistributionData,
_Distribution,
I_DEFAULT,
D_DEFAULT,
D_INF,
MAX_DIFF_BOUND,
MAX_MEAN,
VariableType,
VariableTypeBis,
RestorationAlgorithm,
_SetSeed
)
_SetSeedInstance = _SetSeed()
set_seed = _SetSeedInstance.set_seed
from .enums import distribution_identifier_type
__all__ = ["_Distribution",
"_DiscreteParametricModel",
"Distribution",
"Binomial",
"Poisson",
"Uniform",
"NegativeBinomial",
"Multinomial",
"ToHistogram",
"ToDistribution",
"set_seed"]
[docs]
def Distribution(utype, *args):
"""
Construction of a parametric discrete distribution (either binomial,
Poisson, negative binomial or uniform) from the name and the parameters
of the distribution or from an ASCII file.
A supplementary shift parameter (argument inf_bound) is required with
respect to the usual definitions of these discrete distributions.
Constraints over parameters are given in the file syntax corresponding
to the type distribution(cf. File Syntax).
:Parameters:
* `inf_bound` (int) : lower bound to the range of possible values
(shift parameter),
* `sup_bound` (int) : upper bound to the range of possible values \
(only relevant for binomial or uniform distributions),
* `param` (int, real) : parameter of either the Poisson distribution or \
the negative binomial distribution.
* `proba` (int, float) : probability of success \
(only relevant for binomial or negative binomial distributions),
* `file_name` (string).
.. note:: the names of the parametric discrete distributions can be
summarized by their first letters:
* "B" ("BINOMIAL"),
* "P" ("POISSON"),
* "NB" ("NEGATIVE_BINOMIAL"),
* "U" ("UNIFORM"),
* "M" ("MULTINOMIAL"),
:Returns:
If the construction succeeds, an object of type distribution is
returned, otherwise no object is returned.
:Examples:
.. doctest::
:options: +SKIP
>>> Distribution("BINOMIAL", inf_bound, sup_bound, proba)
>>> Distribution("POISSON", inf_bound, param)
>>> Distribution("NEGATIVE_BINOMIAL", inf_bound, param, proba)
>>> Distribution("UNIFORM", inf_bound, sup_bound)
>>> Distribution(file_name)
.. seealso::
:func:`~openalea.stat_tool.output.Save`,
:func:`~openalea.stat_tool.estimate.Estimate`
:func:`~openalea.stat_tool.simulate.Simulate`.
"""
# Constructor from Filename or Histogram or parametricmodel
if(len(args) == 0):
error.CheckType([utype],
[[str, _DiscreteDistributionData, _DiscreteParametricModel]],
arg_id=[1])
result = _DiscreteParametricModel(utype)
# from parameters
if len(args)>0:
error.CheckArgumentsLength(args, 1)
if utype in ["B", "BINOMIAL"]:
result = Binomial(*args)
elif utype in ["P", "POISSON"]:
result = Poisson(*args)
elif utype in ["M", "MULTINOMIAL"]:
result = Multinomial(*args)
elif utype in ["NB", "NEGATIVE_BINOMIAL"]:
result = NegativeBinomial(*args)
elif utype in ["U", "UNIFORM"]:
result = Uniform(*args)
else:
raise KeyError(" %s not found. Allowed keys are %s"
% (utype, list(distribution_identifier_type.keys())))
return result
[docs]
def Binomial(inf_bound, sup_bound=I_DEFAULT,
proba=D_DEFAULT):
"""
Construction of a binomial distribution
:param float inf_bound: lower bound to the range of possible values (shift parameter)
:param float sup_bound: upper bound to the range of possible values
:param float proba: probability of `success`
.. plot::
:width: 50%
:include-source:
from openalea.stat_tool.distribution import Binomial
b = Binomial(0,10,0.5)
b.plot(legend_size=8)
"""
# todo: seg fault when passing -1 as first arguments if there
# is no assert here below
# memory leak ?
# todo: returns error if ((inf_bound < min_inf_bound) ||
# (inf_bound > MAX_INF_BOUND)) {
error.CheckType([inf_bound, sup_bound, proba], [int, int, [int, float]])
assert inf_bound >= 0
assert inf_bound < sup_bound
assert (sup_bound - inf_bound) <= MAX_DIFF_BOUND
assert proba <= 1. and proba > 0
param = D_DEFAULT
return(_DiscreteParametricModel(BINOMIAL.real,
inf_bound, sup_bound, param, proba))
[docs]
def Poisson(inf_bound, param=D_DEFAULT):
"""
Construction of a Poisson distribution
:Parameters:
* `inf_bound` (int) : lower bound to the range of possible values
(shift parameter)
* `param` (int, float) : parameter of the Poisson distribution
.. plot::
:width: 50%
:include-source:
from openalea.stat_tool.distribution import Poisson
b = Poisson(1,1.5)
b.plot(legend_size=8)
"""
assert inf_bound >= 0
assert param > inf_bound
assert param > 0. and param < MAX_MEAN
sup_bound = I_DEFAULT
proba = D_DEFAULT
return _DiscreteParametricModel(POISSON,
inf_bound, sup_bound, param, proba)
[docs]
def NegativeBinomial(inf_bound, param=D_DEFAULT,
proba=D_DEFAULT):
r"""
Construction of a negative binomial distribution
The negative binomial distribution has the following parameterization:
.. math::
P(X-inf\_bound=i) = \frac{\Gamma(param+i)}{i! \Gamma(param)} p^{param} (1-p)^i
:Parameters:
* inf_bound (int) : lower bound to the range of possible values
(shift parameter)
* param (int, float) : parameter of the Negative Binomial distribution
* proba (int, float) : probability of 'success'
.. plot::
:width: 50%
:include-source:
from openalea.stat_tool.distribution import NegativeBinomial
b = NegativeBinomial(1,2,.5)
b.plot(legend_size=12)
"""
# Check parameters
assert inf_bound >= 0
assert param > 0
assert proba <= 1. and proba > 0
assert (param * (1. - proba) / proba) <= MAX_MEAN
sup_bound = I_DEFAULT
return _DiscreteParametricModel(NEGATIVE_BINOMIAL,
inf_bound, sup_bound, param, proba)
[docs]
def Multinomial(probabilities):
r"""
Construction of a categorical distribution.
A categorical distribution is implemented as a particular case
of the multinomial distribution :math:`{\mathcal{M}}(1; p_1, \ldots, p_K)`
:Parameters:
* probabilities (list): list of probabilities :math:`p_1,\ldots,p_K`
.. plot::
:width: 50%
:include-source:
from openalea.stat_tool.distribution import Multinomial
m = Multinomial([0.1, 0.6, .3])
from openalea.stat_tool import Histogram
Histogram([m.simulation() for i in range(100)]).plot()
"""
return _Distribution(probabilities)
# Extend _DiscreteParametricModel
interface.extend_class( _DiscreteParametricModel, interface.StatInterface)
# Cast Functions
[docs]
def ToDistribution(histo):
""" Cast an object of type `_DiscreteDistributionData` into an object
of type `_Distribution`.
:Parameters:
* `histo` (DiscreteDistributionData)
:Returns:
If the object histo contains a 'model' part, an object
of type `_Distribution` is returned, otherwise no object
is returned.
:Examples:
.. doctest::
:options: +SKIP
>>> ToDistribution(histo)
.. seealso::
:func:`~openalea.stat_tool.distribution.ToHistogram`
"""
return histo.extract_model()
[docs]
def ToHistogram(dist):
"""Cast an object of type `_Distribution` into an object of
type `_DiscreteDistributionData`.
:Parameters:
* dist (distribution).
:Returns:
If the object dist contains a 'data' part, an object of
type `_DiscreteDistributionData` is returned, otherwise no object
is returned.
:Examples:
.. doctest::
:options: +SKIP
>>> ToHistogram(dist)
.. seealso::
:func:`~openalea.stat_tool.distribution.ToDistribution`
"""
return dist.extract_data()