From 52e27b48265566231cffa5afb11c609e4c94034a Mon Sep 17 00:00:00 2001 From: Bina Ansari Date: Tue, 18 Jan 2022 10:05:42 -0700 Subject: [PATCH 1/6] changes to distr and stats --- lmoments3/distr.py | 28 +++++++++++++++------------- lmoments3/stats.py | 4 ++-- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/lmoments3/distr.py b/lmoments3/distr.py index b372614..d9a90b3 100644 --- a/lmoments3/distr.py +++ b/lmoments3/distr.py @@ -683,7 +683,8 @@ class WakebyGen(LmomDistrMixin, scipy.stats.rv_continuous): """ - def _argcheck(self, b, c, d): + def _argcheck(self, b, c, d, xi, a): + a = np.asarray(a) b = np.asarray(b) c = np.asarray(c) d = np.asarray(d) @@ -692,26 +693,27 @@ def _argcheck(self, b, c, d): (b == c) & (c == d) & (d == 0)) np.putmask(check, c > 0, d > 0) np.putmask(check, c < 0, False) + np.putmask(check, a + c < 0, False) return check - def _ppf(self, q, b, c, d): + def _ppf(self, q, b, c, d, xi, a): z = -np.log(1. - q) u = np.where(b == 0, z, (1. - np.exp(-b * z)) / b) v = np.where(d == 0, z, (1. - np.exp(d * z)) / d) - return u - c * v + return a * u - c * v + xi - def _cdf(self, x, b, c, d): + def _cdf(self, x, b, c, d, xi, a): if hasattr(x, '__iter__'): if hasattr(b, '__iter__'): # Assume x, b, c, d are arrays with matching length result = np.array([self._cdfwak(_, parameters) - for (_, parameters) in zip(x, zip(b, c, d))]) + for (_, parameters) in zip(x, zip(b, c, d, xi, a))]) else: # Only x is an array, paras are scalars - result = np.array([self._cdfwak(_, [b, c, d]) + result = np.array([self._cdfwak(_, [b, c, d, xi, a]) for _ in x]) else: - result = self._cdfwak(x, (b, c, d)) + result = self._cdfwak(x, (b, c, d, xi, a)) return result def _cdfwak(self, x, para): @@ -722,9 +724,9 @@ def _cdfwak(self, x, para): ZINCMX = 3 ZMULT = 0.2 UFL = -170 - XI = 0 # stats.rv_continuous deals with scaling - A = 1 # stats.rv_continuous deals with scaling - B, C, D = para + # XI = # stats.rv_continuous deals with scaling + # A = # stats.rv_continuous deals with scaling + B, C, D, XI, A = para CDFWAK = 0 if x <= XI: @@ -810,9 +812,9 @@ def _cdfwak(self, x, para): CDFWAK = 1 - math.exp(-Z) return CDFWAK - def _pdf(self, x, b, c, d): - t = (1. - self._cdf(x, b, c, d)) - f = t ** (d + 1) / (t ** (b + d) + c) + def _pdf(self, x, b, c, d, xi, a): + t = (1. - self._cdf(x, b, c, d, xi, a)) + f = t ** (d + 1) / (a * t ** (b + d) + c) return f def _lmom_fit(self, lmom_ratios): diff --git a/lmoments3/stats.py b/lmoments3/stats.py index 640fe8a..ce425e3 100644 --- a/lmoments3/stats.py +++ b/lmoments3/stats.py @@ -31,7 +31,7 @@ def AIC(data, distr_name, distr_paras): def AICc(data, distr_name, distr_paras): - distr_f = getattr(distr, distr_name.lower()) # scipy rv_continous class + distr_f = getattr(distr, distr_name.lower()) # scipy rv_continuous class AICbase = AIC(data, distr_name, distr_paras) k = distr_f.numargs + 2 # Include location and scale in addition to shape parameters @@ -41,7 +41,7 @@ def AICc(data, distr_name, distr_paras): def BIC(data, distr_name, distr_paras): - distr_f = getattr(distr, distr_name.lower()) # scipy rv_continous class + distr_f = getattr(distr, distr_name.lower()) # scipy rv_continuous class NLL = distr_f.nnlf(data, **distr_paras) k = distr_f.numargs + 2 # Include location and scale in addition to shape parameters From 64d109e8fe8287f94daef447ba0ec375faf38e1f Mon Sep 17 00:00:00 2001 From: Bina Ansari Date: Thu, 27 Jan 2022 11:32:22 -0700 Subject: [PATCH 2/6] modified a bunch of functions --- .travis.yml | 24 ------------------------ 1 file changed, 24 deletions(-) delete mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index cfd1b8d..0000000 --- a/.travis.yml +++ /dev/null @@ -1,24 +0,0 @@ -language: python -python: - - 3.3 - - 3.4 - - 3.5 - -sudo: false - -before_install: - - wget https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda.sh - - bash miniconda.sh -b -p $HOME/miniconda - - export PATH="$HOME/miniconda/bin:$PATH" - - hash -r - - conda config --set always_yes yes --set changeps1 no - - conda update -q conda - - conda info -a - - conda create -q -n pyenv python=$TRAVIS_PYTHON_VERSION nose numpy scipy - - source activate pyenv - -install: - - python setup.py install - -script: - - nosetests From a8706a959dad8cf656fc6b946a24d79d51e7c535 Mon Sep 17 00:00:00 2001 From: Bina Ansari Date: Thu, 27 Jan 2022 11:33:03 -0700 Subject: [PATCH 3/6] modified a bunch of functions --- lmoments3/distr.py | 62 +++++++++++++++++++++++----------------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/lmoments3/distr.py b/lmoments3/distr.py index d9a90b3..2247cd1 100644 --- a/lmoments3/distr.py +++ b/lmoments3/distr.py @@ -460,7 +460,7 @@ def _lmom_fit(self, lmom_ratios): T3 = lmom_ratios[2] T4 = lmom_ratios[3] if lmom_ratios[1] <= 0 or abs(T3) >= 1 or abs(T4) >= 1 or T4 <= (5 * T3 * T3 - 1) / 4 or \ - T4 >= (5 * T3 * T3 + 1) / 6: + T4 >= (5 * T3 * T3 + 1) / 6: raise ValueError("L-Moments invalid") G = (1 - 3 * T3) / (1 + T3) @@ -683,37 +683,37 @@ class WakebyGen(LmomDistrMixin, scipy.stats.rv_continuous): """ - def _argcheck(self, b, c, d, xi, a): - a = np.asarray(a) - b = np.asarray(b) - c = np.asarray(c) - d = np.asarray(d) - check = np.where(b + d > 0, - np.where(c == 0, d == 0, True), - (b == c) & (c == d) & (d == 0)) - np.putmask(check, c > 0, d > 0) - np.putmask(check, c < 0, False) - np.putmask(check, a + c < 0, False) + def _argcheck(self, b, c, d, a): + alpha = np.asarray(a) + beta = np.asarray(b) + gamma = np.asarray(c) + delta = np.asarray(d) + cond1 = alpha + beta >= 0 + cond2 = (alpha + beta) > 0 or (b == 0 and gamma == 0 and delta == 0) + cond3 = np.where(gamma == 0, delta == 0, True) + cond4 = gamma >= 0 + cond5 = alpha + gamma >= 0 + check = cond1 and cond2 and cond3 and cond4 and cond5 return check - def _ppf(self, q, b, c, d, xi, a): + def _ppf(self, q, b, c, d, a): z = -np.log(1. - q) u = np.where(b == 0, z, (1. - np.exp(-b * z)) / b) v = np.where(d == 0, z, (1. - np.exp(d * z)) / d) - return a * u - c * v + xi + return a * u - c * v - def _cdf(self, x, b, c, d, xi, a): + def _cdf(self, x, b, c, d, a): if hasattr(x, '__iter__'): - if hasattr(b, '__iter__'): + if hasattr(b, '__iter__') and (np.size(b) == np.size(x)): # Assume x, b, c, d are arrays with matching length result = np.array([self._cdfwak(_, parameters) - for (_, parameters) in zip(x, zip(b, c, d, xi, a))]) + for (_, parameters) in zip(x, zip(b, c, d, a))]) else: # Only x is an array, paras are scalars - result = np.array([self._cdfwak(_, [b, c, d, xi, a]) + result = np.array([self._cdfwak(_, [b, c, d, a]) for _ in x]) else: - result = self._cdfwak(x, (b, c, d, xi, a)) + result = self._cdfwak(x, (b, c, d, a)) return result def _cdfwak(self, x, para): @@ -724,9 +724,8 @@ def _cdfwak(self, x, para): ZINCMX = 3 ZMULT = 0.2 UFL = -170 - # XI = # stats.rv_continuous deals with scaling - # A = # stats.rv_continuous deals with scaling - B, C, D, XI, A = para + XI = 0 # stats.rv_continuous deals with location + B, C, D, A = para CDFWAK = 0 if x <= XI: @@ -812,8 +811,8 @@ def _cdfwak(self, x, para): CDFWAK = 1 - math.exp(-Z) return CDFWAK - def _pdf(self, x, b, c, d, xi, a): - t = (1. - self._cdf(x, b, c, d, xi, a)) + def _pdf(self, x, b, c, d, a): + t = (1. - self._cdf(x, b, c, d, a)) f = t ** (d + 1) / (a * t ** (b + d) + c) return f @@ -866,18 +865,19 @@ def _lmom_fit(self, lmom_ratios): para = OrderedDict([('beta', B), ('gamma', C), ('delta', D), - ('loc', XI), - ('scale', A)]) + ('alpha', A), + ('loc', XI)] + ) return para - def _lmom_ratios(self, beta, gamma, delta, loc, scale, nmom): + def _lmom_ratios(self, beta, gamma, delta, alpha, loc, scale, nmom): if (delta >= 1) \ or (beta + delta <= 0 and (beta != 0 or gamma != 0 or delta != 0)) \ - or (scale == 0 and beta != 0) \ + or (alpha == 0 and beta != 0) \ or (gamma == 0 and delta != 0) \ or (gamma < 0) \ - or (scale + gamma < 0) \ - or (scale == 0 and gamma == 0): + or (alpha + gamma < 0) \ + or (alpha == 0 and gamma == 0): raise ValueError("Invalid parameters") Y = scale / (1 + beta) @@ -900,7 +900,7 @@ def _lmom_ratios(self, beta, gamma, delta, loc, scale, nmom): return xmom -wak = WakebyGen(name='wakeby', shapes='beta, gamma, delta') +wak = WakebyGen(name='wakeby', shapes='beta, gamma, delta, alpha') """ The following distributions are available in `scipy.stats` and are redefined here with an `LmomDistrMixin` to extend the From eecbda230be21d49a6015e6830c4a5b7123c9506 Mon Sep 17 00:00:00 2001 From: Bina Ansari Date: Thu, 27 Jan 2022 11:34:10 -0700 Subject: [PATCH 4/6] added back yml --- .travis.yml | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..cfd1b8d --- /dev/null +++ b/.travis.yml @@ -0,0 +1,24 @@ +language: python +python: + - 3.3 + - 3.4 + - 3.5 + +sudo: false + +before_install: + - wget https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda.sh + - bash miniconda.sh -b -p $HOME/miniconda + - export PATH="$HOME/miniconda/bin:$PATH" + - hash -r + - conda config --set always_yes yes --set changeps1 no + - conda update -q conda + - conda info -a + - conda create -q -n pyenv python=$TRAVIS_PYTHON_VERSION nose numpy scipy + - source activate pyenv + +install: + - python setup.py install + +script: + - nosetests From 89ea2e6f7d2dca4d4e485d0fbc50caaa548ca30c Mon Sep 17 00:00:00 2001 From: Bina Ansari Date: Thu, 27 Jan 2022 15:56:44 -0700 Subject: [PATCH 5/6] bug fix in _lmom_ratios + test update --- lmoments3/distr.py | 5 +++-- lmoments3/tests/test_lmoments.py | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/lmoments3/distr.py b/lmoments3/distr.py index 2247cd1..6a7936c 100644 --- a/lmoments3/distr.py +++ b/lmoments3/distr.py @@ -866,7 +866,8 @@ def _lmom_fit(self, lmom_ratios): ('gamma', C), ('delta', D), ('alpha', A), - ('loc', XI)] + ('loc', XI), + ('scale', 1)] ) return para @@ -880,7 +881,7 @@ def _lmom_ratios(self, beta, gamma, delta, alpha, loc, scale, nmom): or (alpha == 0 and gamma == 0): raise ValueError("Invalid parameters") - Y = scale / (1 + beta) + Y = alpha / (1 + beta) Z = gamma / (1 - delta) xmom = [loc + Y + Z] if nmom == 1: diff --git a/lmoments3/tests/test_lmoments.py b/lmoments3/tests/test_lmoments.py index ab05661..e70b004 100644 --- a/lmoments3/tests/test_lmoments.py +++ b/lmoments3/tests/test_lmoments.py @@ -150,7 +150,7 @@ class TestPe3(DistributionTestCase): class TestWak(DistributionTestCase): dist = 'wak' - paras = {'loc': 0.7928727, 'scale': 2.7855796, 'beta': 0.14, 'gamma': 0, 'delta': 0} + paras = {'loc': 0.7928727, 'scale': 1, 'alpha': 2.7855796, 'beta': 0.14, 'gamma': 0, 'delta': 0} correct_fit = [0.7928727, 2.7855796, 0.1400000, 0.0000000, 0.0000000] correct_qua = [1.404848, 2.632964, 4.806899] correct_lmr = [3.2363636, 1.1418182, 0.2738854, 0.1230499] From 58ea757560ca59253ba61ecd7c5cb741c6b28a1a Mon Sep 17 00:00:00 2001 From: Pascal Bourgault Date: Mon, 29 Aug 2022 16:02:49 -0400 Subject: [PATCH 6/6] Adapt to changes in scipy 1.9 --- lmoments3/distr.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/lmoments3/distr.py b/lmoments3/distr.py index b372614..df77d14 100644 --- a/lmoments3/distr.py +++ b/lmoments3/distr.py @@ -26,6 +26,14 @@ import lmoments3 as lm +try: + # Scipy >= 1.9 + from scipy.stats._distn_infrastructure import rv_continuous_frozen +except ImportError: + # Scipy < 1.9 + from scipy.stats._distn_infrastructure import rv_frozen as rv_continuous_frozen + + class LmomDistrMixin(object): """ Mixin class to add L-moment methods to :class:`scipy.stats.rv_continous` distribution functions. Distributions using @@ -123,7 +131,7 @@ def freeze(self, *args, **kwds): return LmomFrozenDistr(self, *args, **kwds) -class LmomFrozenDistr(scipy.stats.distributions.rv_frozen): +class LmomFrozenDistr(rv_continuous_frozen): """ Frozen version of the distribution returned by :class:`LmomDistrMixin`. Simply provides additional methods supported by the mixin.