Skip to content

Commit 6416365

Browse files
committed
v2: Additional probability distributions
Add additional probability distributions as required for PEtab-dev/PEtab#595. See #374.
1 parent b43f5b8 commit 6416365

File tree

1 file changed

+110
-4
lines changed

1 file changed

+110
-4
lines changed

petab/v1/distributions.py

Lines changed: 110 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import abc
66

77
import numpy as np
8-
from scipy.stats import laplace, norm, uniform
8+
from scipy.stats import cauchy, chi2, laplace, norm, uniform
99

1010
__all__ = [
1111
"Distribution",
@@ -366,7 +366,12 @@ def __init__(
366366
super().__init__(log=log)
367367

368368
def __repr__(self):
369-
log = f", log={self._logbase}" if self._logbase else ""
369+
if self._logbase is False:
370+
log = ""
371+
if self._logbase == np.exp(1):
372+
log = ", log=True"
373+
else:
374+
log = f", log={self._logbase}"
370375
return f"Uniform(low={self._low}, high={self._high}{log})"
371376

372377
def _sample(self, shape=None) -> np.ndarray | float:
@@ -411,9 +416,16 @@ def __init__(
411416
super().__init__(log=log, trunc=trunc)
412417

413418
def __repr__(self):
419+
if self._logbase is False:
420+
log = ""
421+
if self._logbase == np.exp(1):
422+
log = ", log=True"
423+
else:
424+
log = f", log={self._logbase}"
425+
414426
trunc = f", trunc={self._trunc}" if self._trunc else ""
415-
log = f", log={self._logbase}" if self._logbase else ""
416-
return f"Laplace(loc={self._loc}, scale={self._scale}{trunc}{log})"
427+
428+
return f"Laplace(loc={self._loc}, scale={self._scale}{log}{trunc})"
417429

418430
def _sample(self, shape=None) -> np.ndarray | float:
419431
return np.random.laplace(loc=self._loc, scale=self._scale, size=shape)
@@ -436,3 +448,97 @@ def loc(self) -> float:
436448
def scale(self) -> float:
437449
"""The scale parameter of the underlying distribution."""
438450
return self._scale
451+
452+
453+
class Cauchy(Distribution):
454+
"""A Cauchy distribution."""
455+
456+
def __init__(
457+
self,
458+
loc: float,
459+
scale: float,
460+
trunc: tuple[float, float] | None = None,
461+
log: bool | float = False,
462+
):
463+
self._loc = loc
464+
self._scale = scale
465+
super().__init__(log=log, trunc=trunc)
466+
467+
def __repr__(self):
468+
if self._logbase is False:
469+
log = ""
470+
if self._logbase == np.exp(1):
471+
log = ", log=True"
472+
else:
473+
log = f", log={self._logbase}"
474+
475+
trunc = f", trunc={self._trunc}" if self._trunc else ""
476+
477+
cls = self.__class__.__name__
478+
return f"{cls}(loc={self._loc}, scale={self._scale}{log}{trunc})"
479+
480+
def _pdf_untransformed_untruncated(self, x) -> np.ndarray | float:
481+
return cauchy.pdf(x, loc=self._loc, scale=self._scale)
482+
483+
def _cdf_untransformed_untruncated(self, x) -> np.ndarray | float:
484+
return cauchy.cdf(x, loc=self._loc, scale=self._scale)
485+
486+
def _ppf_untransformed_untruncated(self, q) -> np.ndarray | float:
487+
return cauchy.ppf(q, loc=self._loc, scale=self._scale)
488+
489+
@property
490+
def loc(self) -> float:
491+
"""The location parameter of the underlying distribution."""
492+
return self._loc
493+
494+
@property
495+
def scale(self) -> float:
496+
"""The scale parameter of the underlying distribution."""
497+
return self._scale
498+
499+
500+
class ChiSquare(Distribution):
501+
"""A chi-squared distribution.
502+
503+
:param k: Degrees of freedom.
504+
"""
505+
506+
def __init__(
507+
self,
508+
k: int,
509+
trunc: tuple[float, float] | None = None,
510+
):
511+
if not k.is_integer() or k < 1:
512+
raise ValueError("k must be a positive integer.")
513+
514+
self._k = k
515+
super().__init__(log=False, trunc=trunc)
516+
517+
def __repr__(self):
518+
trunc = f", trunc={self._trunc}" if self._trunc else ""
519+
520+
cls = self.__class__.__name__
521+
return f"{cls}(k={self._k}, {trunc})"
522+
523+
def _pdf_untransformed_untruncated(self, x) -> np.ndarray | float:
524+
return chi2.pdf(x, df=self._k)
525+
526+
def _cdf_untransformed_untruncated(self, x) -> np.ndarray | float:
527+
return chi2.cdf(x, df=self._k)
528+
529+
def _ppf_untransformed_untruncated(self, q) -> np.ndarray | float:
530+
return chi2.ppf(q, df=self._k)
531+
532+
@property
533+
def k(self) -> int:
534+
"""The degrees of freedom parameter."""
535+
return self._k
536+
537+
538+
class Exponential(Distribution): ...
539+
540+
541+
class Gamma(Distribution): ...
542+
543+
544+
class Rayleigh(Distribution): ...

0 commit comments

Comments
 (0)