Skip to content

Commit

Permalink
improved formating
Browse files Browse the repository at this point in the history
  • Loading branch information
Andrew McCluskey committed May 19, 2020
1 parent 36c985a commit 2ce8916
Show file tree
Hide file tree
Showing 6 changed files with 83 additions and 197 deletions.
42 changes: 23 additions & 19 deletions uravu/axis.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""
The Axis class controls the organisation of axes in the uravu code.
The :py:class:`~uravu.axis.Axis` class controls the organisation of axes in the uravu code, including the evaluation of an axis-level multidimensional kernal density estimate.
"""

# Copyright (c) Andrew R. McCluskey
Expand All @@ -8,18 +8,17 @@


import numpy as np
from uravu import UREG
from uravu.distribution import Distribution
from scipy.stats import gaussian_kde
from uravu.distribution import Distribution


class Axis:
"""
The Axes class is a flexible storage option for both numerical (:py:class:`numpy.ndarray`) and distribution (:py:class:`uravu.distribution.Distribution`) arrays.
The Axes class is a flexible storage option for both numerical (:py:class:`numpy.ndarray`) and distribution (:py:class:`uravu.distribution.Distribution`) arrays.
Attributes:
values (:py:attr:`list` or :py:class:`uravu.distribution.Distribution` or :py:attr:`array_like`): Array of values.
kde (:py:class:`scipy.stats.kde.gaussian_kde`): Multi-dimensional kernal density approximation for the axes.
kde (:py:class:`scipy.stats.kde.gaussian_kde`): Multi-dimensional kernel density approximation for the axes.
Args:
values (:py:attr:`list` or :py:class:`uravu.distribution.Distribution` or :py:attr:`array_like`): Array of values.
Expand Down Expand Up @@ -47,10 +46,9 @@ def n(self):
if isinstance(self.values[0], Distribution):
for i, o in enumerate(self.values):
v[i] = o.n
return v
else:
return self.values

return v
return self.values

@property
def s(self):
"""
Expand All @@ -63,9 +61,8 @@ def s(self):
dv = np.zeros((2, self.size))
for i, o in enumerate(self.values):
dv[:, i] = np.abs(o.con_int - o.n)
return dv
else:
return np.zeros(self.shape)
return dv
return np.zeros(self.shape)

@property
def size(self):
Expand All @@ -77,8 +74,7 @@ def size(self):
"""
if isinstance(self.values[0], Distribution):
return len(self.values)
else:
return self.values.size
return self.values.size

@property
def shape(self):
Expand All @@ -90,16 +86,15 @@ def shape(self):
"""
if isinstance(self.values[0], Distribution):
return len(self.values)
else:
return self.values.shape
return self.values.shape

def pdf(self, x):
""""
Get the probability density function for all of the distributions in the axes.
Args:
x (:py:attr:`array_like`): Values to return probability of.
Return:
:py:attr:`array_like`: Probability.
"""
Expand All @@ -111,17 +106,26 @@ def logpdf(self, x):
Args:
x (:py:attr:`array_like`): Values to return natural log probability of.
Return:
:py:attr:`array_like`: Natural log probability.
"""
return self.kde.logpdf(x)


def _get_kde(values):
"""
Determine the kernel density estimate for a given set of values.
Args:
values (:py:attr:`array_like`): Sample for kde.
Returns:
:py:class:`scipy.stats.kde.gaussian_kde`: Kernel density estimate for samples.
"""
min_size = values[0].size
for v in values:
if v.size < min_size:
min_size = v.size
random_list = [np.random.choice(v.samples, size=min_size) for v in values]
return gaussian_kde(np.vstack(random_list))
return gaussian_kde(np.vstack(random_list))
41 changes: 14 additions & 27 deletions uravu/distribution.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
"""
The storage and manipulation of probability distributions is fundamental to the operation of ``uravu`` and Bayesian inference.
The :py:class:`~uravu.distribution.Distribution` class oversees these operations.
The storage and manipulation of probability distributions is fundamental to the operation of ``uravu`` and Bayesian inference.
The :py:class:`~uravu.distribution.Distribution` class oversees these operations.
"""

# Copyright (c) Andrew R. McCluskey
# Distributed under the terms of the MIT License
# author: Andrew R. McCluskey

import numpy as np
from scipy.stats import normaltest, gaussian_kde, norm
from uncertainties import ufloat
from scipy.stats import normaltest, gaussian_kde
from uravu import UREG


Expand All @@ -23,6 +22,7 @@ class Distribution:
ci_points (:py:attr:`array_like`): The percentiles at which confidence intervals should be found.
unit (:py:class:`~pint.unit.Unit`): The unit of the values in the Distribution.
normal (:py:attr:`bool`): Are the samples normally distributed?
kde (:py:class:`scipy.stats.kde.gaussian_kde`): Kernel density approximation for the distribution.
Args:
samples (:py:attr:`array_like`): Sample for the distribution.
Expand All @@ -33,9 +33,7 @@ class Distribution:
.. _FAQ: ./faq.html
"""

def __init__(
self, samples, name="Distribution", ci_points=None, unit=UREG.dimensionless,
):
def __init__(self, samples, name="Distribution", ci_points=None, unit=UREG.dimensionless):
"""
Initialisation function for a :py:class:`~uravu.distribution.Distribution` object.
"""
Expand All @@ -46,9 +44,7 @@ def __init__(
self.ci_points = np.array([2.5, 97.5])
else:
if len(ci_points) != 2:
raise ValueError(
"The ci_points must be an array of length two."
)
raise ValueError("The ci_points must be an array of length two.")
self.ci_points = np.array(ci_points)
self.normal = False
self.add_samples(np.array(samples))
Expand Down Expand Up @@ -83,7 +79,7 @@ def pdf(self, x):
Args:
x (:py:attr:`float`): Value to return probability of.
Return:
:py:attr:`float`: Probability.
"""
Expand All @@ -95,7 +91,7 @@ def logpdf(self, x):
Args:
x (:py:attr:`float`): Value to return natural log probability of.
Return:
:py:attr:`float`: Natural log probability.
"""
Expand Down Expand Up @@ -131,37 +127,28 @@ def n(self):
"""
return np.percentile(self.samples, [50])[0]

@property
def s(self, ddof=1):
def s(self):
"""
Get the standard deviation of the distribution. For a non-normal distribution, this will return :py:attr:`None`.
Args:
ddof (:py:attr:`int`): Degrees of freedom to be included in calculation.
Returns:
:py:attr:`float` or :py:attr:`None`: Standard deviation of the distribution.
"""
if self.normal:
return np.std(self.samples, ddof=ddof)
else:
return None
return np.std(self.samples, ddof=1)
return None

@property
def v(self, ddof=1):
def v(self):
"""
Get the variance of the distribution. For a non-normal distribution, this will return :py:attr:`None`.
Args:
ddof (:py:attr:`int`): Degrees of freedom to be included in calculation.
Returns:
:py:attr:`float` or :py:attr:`None`: Standard deviation of the distribution.
"""
if self.normal:
return np.var(self.samples, ddof=ddof)
else:
return None
return np.var(self.samples, ddof=1)
return None

@property
def con_int(self):
Expand Down
45 changes: 8 additions & 37 deletions uravu/optimize.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""
The optimize module includes the functionality necessary for maximum likelihood determination.
The optimize module includes the functionality necessary for maximum likelihood determination.
Furthermore, the natural log likelihood function used in the :func:`~uravu.sampling.mcmc()` and :func:`~uravu.sampling.nested_sampling()` methods may be found here.
"""

Expand All @@ -9,8 +9,6 @@

import numpy as np
from scipy.optimize import minimize, differential_evolution
from uncertainties import unumpy as unp
import sys


def max_ln_likelihood(relationship, method, x0=None, **kwargs):
Expand All @@ -26,35 +24,15 @@ def max_ln_likelihood(relationship, method, x0=None, **kwargs):
"""
if x0 is None:
x0 = relationship.variable_medians
args = (relationship.function, relationship.abscissa, relationship.ordinate)
if method == 'diff_evo':
res = differential_evolution(
negative_lnl,
relationship.bounds,
args=(
relationship.function,
relationship.abscissa,
relationship.ordinate,
),
**kwargs,
)
res = differential_evolution(negative_lnl, relationship.bounds, args=args, **kwargs)
elif method == 'mini':
res = minimize(
negative_lnl,
x0,
args=(
relationship.function,
relationship.abscissa,
relationship.ordinate,
),
bounds=relationship.bounds,
**kwargs,
)
res = minimize(negative_lnl, x0, args=args, bounds=relationship.bounds, **kwargs)
return res.x


def negative_lnl(
variables, function, abscissa, ordinate,
):
def negative_lnl(variables, function, abscissa, ordinate):
"""
Calculate the negative natural logarithm of the likelihood given a set of variables, when there is no uncertainty in the abscissa.
Expand All @@ -67,17 +45,10 @@ def negative_lnl(
Returns:
:py:attr:`float`: Negative natural log-likelihood between model and data.
"""
return -ln_likelihood(
variables,
function,
abscissa,
ordinate,
)
return -ln_likelihood(variables, function, abscissa, ordinate)


def ln_likelihood(
variables, function, abscissa, ordinate,
):
def ln_likelihood(variables, function, abscissa, ordinate):
"""
Calculate the natural logarithm of the likelihood given a set of variables, when there is no uncertainty in the abscissa.
Expand All @@ -92,4 +63,4 @@ def ln_likelihood(
"""
model = function(abscissa, *variables)
ln_l = ordinate.logpdf(model)
return np.sum(ln_l)
return np.sum(ln_l)
Loading

0 comments on commit 2ce8916

Please sign in to comment.