diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..78f73a7 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,15 @@ +files: "giddy\/" +repos: + - repo: https://github.com/psf/black + rev: "23.9.1" + hooks: + - id: black + language_version: python3 + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: "v0.0.292" + hooks: + - id: ruff + +ci: + autofix_prs: false + autoupdate_schedule: quarterly diff --git a/giddy/directional.py b/giddy/directional.py index f3999d4..6136881 100644 --- a/giddy/directional.py +++ b/giddy/directional.py @@ -6,7 +6,7 @@ __all__ = ["Rose"] -import warnings + import numpy as np from libpysal import weights from libpysal.common import requires as _requires @@ -27,7 +27,8 @@ class Rose(object): Parameters ---------- Y : array (n,2) - Columns correspond to end-point time periods to calculate LISA vectors for n object. + Columns correspond to end-point time periods to + calculate LISA vectors for n object. w : PySAL W Spatial weights object. k : int @@ -349,10 +350,8 @@ def plot_origin(self): # TODO add attribute option to color vectors Plot vectors of positional transition of LISA values starting from the same origin. """ - import matplotlib.cm as cm import matplotlib.pyplot as plt - ax = plt.subplot(111) xlim = [self._dx.min(), self._dx.max()] ylim = [self._dy.min(), self._dy.max()] for x, y in zip(self._dx, self._dy): diff --git a/giddy/ergodic.py b/giddy/ergodic.py index 73d91ff..12497ae 100644 --- a/giddy/ergodic.py +++ b/giddy/ergodic.py @@ -201,17 +201,17 @@ def _mfpt_ergodic(P): k = P.shape[0] A = np.zeros_like(P) ss = _steady_state_ergodic(P) - for i in range(k): - A[:, i] = ss + for j in range(k): + A[:, j] = ss A = A.transpose() - I = np.identity(k) - Z = la.inv(I - P + A) + i = np.identity(k) + Z = la.inv(i - P + A) E = np.ones_like(Z) A_diag = np.diag(A) A_diag = A_diag + (A_diag == 0) D = np.diag(1.0 / A_diag) Zdg = np.diag(np.diag(Z)) - M = (I - Z + E.dot(Zdg)).dot(D) + M = (i - Z + E.dot(Zdg)).dot(D) return M @@ -353,7 +353,10 @@ def mfpt(P, fill_empty_classes=False): def var_fmpt_ergodic(p): warn( - "var_fmpt_ergodic is deprecated. It will be replaced in giddy 2.5 with var_fmpt_ergodic", + ( + "var_fmpt_ergodic is deprecated. It will be " + "replaced in giddy 2.5 with var_fmpt_ergodic" + ), DeprecationWarning, stacklevel=2, ) @@ -398,13 +401,13 @@ def var_mfpt_ergodic(p): k = P.shape[0] A = _steady_state_ergodic(P) A = np.tile(A, (k, 1)) - I = np.identity(k) - Z = la.inv(I - P + A) + i = np.identity(k) + Z = la.inv(i - P + A) E = np.ones_like(Z) D = np.diag(1.0 / np.diag(A)) Zdg = np.diag(np.diag(Z)) - M = (I - Z + E.dot(Zdg)).dot(D) + M = (i - Z + E.dot(Zdg)).dot(D) ZM = Z.dot(M) ZMdg = np.diag(np.diag(ZM)) - W = M.dot(2 * Zdg.dot(D) - I) + 2 * (ZM - E.dot(ZMdg)) + W = M.dot(2 * Zdg.dot(D) - i) + 2 * (ZM - E.dot(ZMdg)) return np.array(W - np.multiply(M, M)) diff --git a/giddy/markov.py b/giddy/markov.py index 6876613..6166d9f 100644 --- a/giddy/markov.py +++ b/giddy/markov.py @@ -19,7 +19,6 @@ from .ergodic import steady_state, mfpt from .util import fill_empty_diagonals from .components import Graph -from warnings import warn from scipy import stats from scipy.stats import rankdata from operator import gt @@ -282,13 +281,6 @@ def __init__(self, class_ids, classes=None, fill_empty_classes=False, summary=Tr ) print(*self.astates_indices, sep=", ") - @property - def mfpt(self): - warn("self._mfpt is deprecated. Please use self._mfpt") - if not hasattr(self, "_mfpt"): - self._mfpt = mfpt(self.p, fill_empty_classes=True) - return self._mfpt - @property def mfpt(self): if not hasattr(self, "_mfpt"): @@ -708,7 +700,9 @@ class Spatial_Markov(object): We can easily adjust this assigning `fill_empty_classes = True` when initializing `Spatial_Markov`. - >>> sm = Spatial_Markov(rpci, w, cutoffs=cc, lag_cutoffs=cc, fill_empty_classes=True) + >>> sm = Spatial_Markov( + ... rpci, w, cutoffs=cc, lag_cutoffs=cc, fill_empty_classes=True + ... ) >>> for p in sm.P: ... print(p) [[0.96703297 0.03296703 0. 0. 0. ] @@ -1075,7 +1069,7 @@ def _maybe_classify(self, y, k, cutoffs): def chi2(T1, T2): - """ + r""" chi-squared test of difference between two transition matrices. Parameters @@ -1849,14 +1843,14 @@ def summary(self, file_name=None, title="Markov Homogeneity Test"): lead = "-" * width head = title.center(width) contents = [lead, head, lead] - l = "Number of regimes: %d" % int(self.m) + L = "Number of regimes: %d" % int(self.m) k = "Number of classes: %d" % int(self.k) r = "Regime names: " r += ", ".join(regime_names) t = "Number of transitions: %d" % int(self.t_total) contents.append(k) contents.append(t) - contents.append(l) + contents.append(L) contents.append(r) contents.append(lead) h = "%7s %20s %20s" % ("Test", "LR", "Chi-2") @@ -2091,7 +2085,7 @@ def sojourn_time(p, summary=True): if (p.sum(axis=1) == 0).sum() > 0: p = fill_empty_diagonals(p) - markovchain = qe.MarkovChain(p) + # markovchain = qe.MarkovChain(p) pii = p.diagonal() if not (1 - pii).all(): @@ -2213,7 +2207,8 @@ class GeoRank_Markov(Markov): def __init__(self, y, fill_empty_classes=False, summary=True): y = np.asarray(y) - n = y.shape[0] + # n = y.shape[0] + # resolve ties: All values are given a distinct rank, corresponding # to the order that the values occur in each cross section. ranks = np.array([rankdata(col, method="ordinal") for col in y.T]).T diff --git a/giddy/rank.py b/giddy/rank.py index d89fff9..efb6cf2 100644 --- a/giddy/rank.py +++ b/giddy/rank.py @@ -16,7 +16,6 @@ from scipy.stats.mstats import rankdata from scipy.special import erfc import numpy as np -import scipy as sp from libpysal import weights @@ -184,7 +183,6 @@ def _calc(self, x, y): n = len(y) perm = list(range(n)) perm.sort(key=lambda a: (x[a], y[a])) - vals = y[perm] ExtraY = 0 ExtraX = 0 ACount = 0 @@ -315,8 +313,9 @@ class SpatialTau(object): taus : float spatial tau values for permuted samples (if permutations>0). tau_spatial_psim : float - one-sided pseudo p-value for observed tau_spatial under the null - of spatial randomness of rank exchanges (if permutations>0). + one-sided pseudo p-value for observed tau_spatial + under the null of spatial randomness of rank exchanges + (if permutations>0). Notes ----- diff --git a/giddy/sequence.py b/giddy/sequence.py index 4eb3ccd..8d9d481 100644 --- a/giddy/sequence.py +++ b/giddy/sequence.py @@ -84,7 +84,14 @@ class Sequence(object): 1.2 User-defined substitution cost matrix and indel cost - >>> subs_mat = np.array([[0, 0.76, 0.29, 0.05],[0.30, 0, 0.40, 0.60],[0.16, 0.61, 0, 0.26],[0.38, 0.20, 0.12, 0]]) + >>> subs_mat = np.array( + ... [ + ... [0, 0.76, 0.29, 0.05], + ... [0.30, 0, 0.40, 0.60], + ... [0.16, 0.61, 0, 0.26], + ... [0.38, 0.20, 0.12, 0] + ... ] + ... ) >>> indel = subs_mat.max() >>> seqAna = Sequence([seq1,seq2,seq3], subs_mat=subs_mat, indel=indel) >>> seqAna.seq_dis_mat @@ -117,7 +124,14 @@ class Sequence(object): between different types is always 1 and indel cost is 2) - give the same sequence distance matrix as "hamming" distance - >>> subs_mat = np.array([[0., 1., 1., 1.],[1., 0., 1., 1.],[1., 1., 0., 1.],[1., 1., 1., 0.]]) + >>> subs_mat = np.array( + ... [ + ... [0., 1., 1., 1.], + ... [1., 0., 1., 1.], + ... [1., 1., 0., 1.], + ... [1., 1., 1., 0.] + ... ] + ... ) >>> indel = 2 >>> seqAna = Sequence([seq1,seq2,seq3], subs_mat=subs_mat, indel=indel) >>> seqAna.seq_dis_mat @@ -130,7 +144,14 @@ class Sequence(object): slightly different sequence distance matrix from "hamming" distance since insertion and deletion is happening - >>> subs_mat = np.array([[0., 1., 1., 1.],[1., 0., 1., 1.],[1., 1., 0.,1.],[1., 1., 1., 0.]]) + >>> subs_mat = np.array( + ... [ + ... [0., 1., 1., 1.], + ... [1., 0., 1., 1.], + ... [1., 1., 0., 1.], + ... [1., 1., 1., 0.] + ... ] + ... ) >>> indel = 1 >>> seqAna = Sequence([seq1,seq2,seq3], subs_mat=subs_mat, indel=indel) >>> seqAna.seq_dis_mat diff --git a/giddy/tests/test_sequence.py b/giddy/tests/test_sequence.py index 8c2ae05..02426f5 100644 --- a/giddy/tests/test_sequence.py +++ b/giddy/tests/test_sequence.py @@ -1,4 +1,3 @@ -import unittest import numpy as np import pytest from ..sequence import Sequence