antropy 0.2.2__tar.gz → 0.2.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {antropy-0.2.2/src/antropy.egg-info → antropy-0.2.3}/PKG-INFO +1 -1
- {antropy-0.2.2 → antropy-0.2.3}/src/antropy/__init__.py +1 -1
- {antropy-0.2.2 → antropy-0.2.3}/src/antropy/entropy.py +51 -31
- {antropy-0.2.2 → antropy-0.2.3/src/antropy.egg-info}/PKG-INFO +1 -1
- {antropy-0.2.2 → antropy-0.2.3}/tests/test_entropy.py +106 -10
- {antropy-0.2.2 → antropy-0.2.3}/tests/test_fractal.py +5 -5
- {antropy-0.2.2 → antropy-0.2.3}/LICENSE +0 -0
- {antropy-0.2.2 → antropy-0.2.3}/MANIFEST.in +0 -0
- {antropy-0.2.2 → antropy-0.2.3}/README.rst +0 -0
- {antropy-0.2.2 → antropy-0.2.3}/pyproject.toml +0 -0
- {antropy-0.2.2 → antropy-0.2.3}/setup.cfg +0 -0
- {antropy-0.2.2 → antropy-0.2.3}/src/antropy/fractal.py +0 -0
- {antropy-0.2.2 → antropy-0.2.3}/src/antropy/utils.py +0 -0
- {antropy-0.2.2 → antropy-0.2.3}/src/antropy.egg-info/SOURCES.txt +0 -0
- {antropy-0.2.2 → antropy-0.2.3}/src/antropy.egg-info/dependency_links.txt +0 -0
- {antropy-0.2.2 → antropy-0.2.3}/src/antropy.egg-info/requires.txt +0 -0
- {antropy-0.2.2 → antropy-0.2.3}/src/antropy.egg-info/top_level.txt +0 -0
- {antropy-0.2.2 → antropy-0.2.3}/tests/test_utils.py +0 -0
|
@@ -31,12 +31,11 @@ __all__ = [
|
|
|
31
31
|
# the ordinal index from a small pre-computed table. This avoids the O(m
|
|
32
32
|
# log m) sort and replaces it with O(m) bitwise operations.
|
|
33
33
|
#
|
|
34
|
-
#
|
|
35
|
-
#
|
|
36
|
-
# case of continuous data this never occurs in practice.
|
|
34
|
+
# Comparisons use '<=' because the left column always has the earlier
|
|
35
|
+
# position. This breaks ties by position, matching stable argsort.
|
|
37
36
|
# ---------------------------------------------------------------------------
|
|
38
37
|
|
|
39
|
-
# order=3 — key bits: bit2=(a
|
|
38
|
+
# order=3 — key bits: bit2=(a<=b), bit1=(a<=c), bit0=(b<=c)
|
|
40
39
|
# The 8-entry _PE3_LOOKUP maps the 3-bit key to the hashmult hash value
|
|
41
40
|
# (sum of argsort * [1,3,9]) used by the general path; _PE3_REMAP then
|
|
42
41
|
# compresses those 6 sparse hash values to the dense range 0..5.
|
|
@@ -52,8 +51,8 @@ for _i, _v in enumerate([5, 7, 11, 15, 19, 21]):
|
|
|
52
51
|
_PE3_REMAP[_v] = _i
|
|
53
52
|
del _i, _v
|
|
54
53
|
|
|
55
|
-
# order=4 — key bits: bit5=(a
|
|
56
|
-
# bit1=(b
|
|
54
|
+
# order=4 — key bits: bit5=(a<=b), bit4=(a<=c), bit3=(a<=d), bit2=(b<=c),
|
|
55
|
+
# bit1=(b<=d), bit0=(c<=d)
|
|
57
56
|
# The 64-entry table directly maps each valid 6-bit key to ordinal 0..23.
|
|
58
57
|
# Invalid keys (impossible comparison patterns) keep the sentinel value -1.
|
|
59
58
|
_PE4_LOOKUP = np.full(64, -1, dtype=np.int64)
|
|
@@ -87,24 +86,26 @@ def _perm_entropy_fast(x, order, delay, normalize):
|
|
|
87
86
|
n, m = x.shape
|
|
88
87
|
n_embed = m - (order - 1) * delay
|
|
89
88
|
|
|
90
|
-
#
|
|
91
|
-
#
|
|
92
|
-
#
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
89
|
+
# NaN comparisons do not define an ordering and can produce invalid keys.
|
|
90
|
+
# Process valid epochs separately so a missing sample cannot affect them.
|
|
91
|
+
# Self-comparison detects NaN without requiring a float dtype.
|
|
92
|
+
valid_epochs = (x == x).all(axis=1)
|
|
93
|
+
if not valid_epochs.all():
|
|
94
|
+
result = np.full(n, np.nan)
|
|
95
|
+
result[valid_epochs] = _perm_entropy_fast(x[valid_epochs], order, delay, normalize)
|
|
96
|
+
return float(result[0]) if is_1d else result
|
|
97
|
+
|
|
98
|
+
# Keep the original values: a numeric jitter can reorder close values,
|
|
99
|
+
# and conversion to float64 can lose differences between large integers.
|
|
100
|
+
cols = [x[:, i * delay : i * delay + n_embed] for i in range(order)]
|
|
100
101
|
|
|
101
102
|
if order == 3:
|
|
102
103
|
col0, col1, col2 = cols
|
|
103
104
|
# Encode the 3 pairwise comparisons as bits of an integer key
|
|
104
105
|
bit_key = (
|
|
105
|
-
((col0
|
|
106
|
-
| ((col0
|
|
107
|
-
| (col1
|
|
106
|
+
((col0 <= col1).astype(np.uint8) << 2)
|
|
107
|
+
| ((col0 <= col2).astype(np.uint8) << 1)
|
|
108
|
+
| (col1 <= col2).astype(np.uint8)
|
|
108
109
|
)
|
|
109
110
|
keys = _PE3_REMAP[_PE3_LOOKUP[bit_key]] # ordinal indices 0..5
|
|
110
111
|
n_perms = 6
|
|
@@ -113,12 +114,12 @@ def _perm_entropy_fast(x, order, delay, normalize):
|
|
|
113
114
|
col0, col1, col2, col3 = cols
|
|
114
115
|
# Encode the 6 pairwise comparisons as bits of an integer key
|
|
115
116
|
bit_key = (
|
|
116
|
-
((col0
|
|
117
|
-
| ((col0
|
|
118
|
-
| ((col0
|
|
119
|
-
| ((col1
|
|
120
|
-
| ((col1
|
|
121
|
-
| (col2
|
|
117
|
+
((col0 <= col1).astype(np.uint8) << 5)
|
|
118
|
+
| ((col0 <= col2).astype(np.uint8) << 4)
|
|
119
|
+
| ((col0 <= col3).astype(np.uint8) << 3)
|
|
120
|
+
| ((col1 <= col2).astype(np.uint8) << 2)
|
|
121
|
+
| ((col1 <= col3).astype(np.uint8) << 1)
|
|
122
|
+
| (col2 <= col3).astype(np.uint8)
|
|
122
123
|
)
|
|
123
124
|
keys = _PE4_LOOKUP[bit_key] # ordinal indices 0..23
|
|
124
125
|
n_perms = 24
|
|
@@ -150,10 +151,11 @@ def perm_entropy(x, order=3, delay=1, normalize=False):
|
|
|
150
151
|
2D input is only supported for ``order=3`` or ``order=4``.
|
|
151
152
|
order : int
|
|
152
153
|
Order of permutation entropy. Default is 3.
|
|
153
|
-
delay : int, list, np.ndarray or range
|
|
154
|
+
delay : int, list, tuple, np.ndarray or range
|
|
154
155
|
Time delay (lag). Default is 1. If multiple values are passed
|
|
155
156
|
(e.g. ``[1, 2, 3]``), AntroPy will calculate the average permutation
|
|
156
|
-
entropy across all these delays.
|
|
157
|
+
entropy across all these delays. For 2D input, the average is taken
|
|
158
|
+
separately for each epoch. Delay sequences must be nonempty and 1D.
|
|
157
159
|
normalize : bool
|
|
158
160
|
If True, divide by log2(order!) to normalize the entropy between 0
|
|
159
161
|
and 1. Otherwise, return the permutation entropy in bits.
|
|
@@ -162,7 +164,8 @@ def perm_entropy(x, order=3, delay=1, normalize=False):
|
|
|
162
164
|
-------
|
|
163
165
|
pe : float or np.array
|
|
164
166
|
Permutation entropy. Returns a scalar for 1D input, or an array of
|
|
165
|
-
shape ``(n_epochs,)`` for 2D input.
|
|
167
|
+
shape ``(n_epochs,)`` for 2D input. For orders 3 and 4, an epoch
|
|
168
|
+
containing NaN returns NaN without affecting other epochs.
|
|
166
169
|
|
|
167
170
|
Notes
|
|
168
171
|
-----
|
|
@@ -245,15 +248,32 @@ def perm_entropy(x, order=3, delay=1, normalize=False):
|
|
|
245
248
|
(4,)
|
|
246
249
|
>>> print(np.round(pe, 4))
|
|
247
250
|
[0.9997 0.9991 0.9988 0.9988]
|
|
251
|
+
|
|
252
|
+
Multiple delays retain one average per epoch:
|
|
253
|
+
|
|
254
|
+
>>> pe_delays = ant.perm_entropy(x2d, delay=(1, 2, 3), normalize=True)
|
|
255
|
+
>>> pe_delays.shape
|
|
256
|
+
(4,)
|
|
257
|
+
>>> single_delays = [ant.perm_entropy(x2d, delay=d, normalize=True) for d in (1, 2, 3)]
|
|
258
|
+
>>> np.allclose(pe_delays, np.mean(single_delays, axis=0))
|
|
259
|
+
True
|
|
248
260
|
"""
|
|
249
|
-
# If multiple delays are passed, return the average across all of them
|
|
250
|
-
if isinstance(delay, (list, np.ndarray, range)):
|
|
251
|
-
return np.mean([perm_entropy(x, order=order, delay=d, normalize=normalize) for d in delay])
|
|
252
261
|
x = np.asarray(x)
|
|
253
262
|
if x.ndim not in (1, 2):
|
|
254
263
|
raise ValueError("x must be 1D or 2D.")
|
|
255
264
|
if order < 2:
|
|
256
265
|
raise ValueError("Order has to be at least 2.")
|
|
266
|
+
# If multiple delays are passed, return the average across all of them
|
|
267
|
+
delays = np.asarray(delay)
|
|
268
|
+
if delays.ndim > 1:
|
|
269
|
+
raise ValueError("delay must be a scalar or a 1D sequence.")
|
|
270
|
+
if delays.ndim == 1:
|
|
271
|
+
if not delays.size:
|
|
272
|
+
raise ValueError("delay sequence must not be empty.")
|
|
273
|
+
return np.mean(
|
|
274
|
+
[perm_entropy(x, order=order, delay=d, normalize=normalize) for d in delays], axis=0
|
|
275
|
+
)
|
|
276
|
+
delay = delays.item()
|
|
257
277
|
if delay < 1:
|
|
258
278
|
raise ValueError("delay must be greater than zero.")
|
|
259
279
|
delay = int(delay)
|
|
@@ -4,7 +4,7 @@ import unittest
|
|
|
4
4
|
|
|
5
5
|
import numpy as np
|
|
6
6
|
from numpy import apply_along_axis as aal
|
|
7
|
-
from numpy.testing import assert_equal
|
|
7
|
+
from numpy.testing import assert_allclose, assert_equal
|
|
8
8
|
from utils import ARANGE, NORMAL_TS, PURE_SINE, RANDOM_TS, RANDOM_TS_LONG, TEST_DTYPES
|
|
9
9
|
|
|
10
10
|
from antropy import (
|
|
@@ -27,8 +27,8 @@ def _perm_entropy_orig(x, order=3, delay=1, normalize=False):
|
|
|
27
27
|
"""Original argsort-based implementation with no fast path, used as reference.
|
|
28
28
|
|
|
29
29
|
Uses kind='stable' so that ties are broken by position (earlier index ranks
|
|
30
|
-
lower), matching the
|
|
31
|
-
|
|
30
|
+
lower), matching the position-based comparisons in the fast path.
|
|
31
|
+
For tie-free data stable and quicksort give identical results.
|
|
32
32
|
"""
|
|
33
33
|
from math import factorial
|
|
34
34
|
|
|
@@ -82,8 +82,7 @@ class TestEntropy(unittest.TestCase):
|
|
|
82
82
|
def test_perm_entropy_ties(self):
|
|
83
83
|
"""Fast path must agree with the original argsort implementation on signals with ties.
|
|
84
84
|
|
|
85
|
-
|
|
86
|
-
by column index, exactly matching argsort's position-based tiebreaking.
|
|
85
|
+
Ties are broken by column index, matching stable argsort.
|
|
87
86
|
This applies to integer arrays, float arrays with duplicate values,
|
|
88
87
|
zero-padded signals, and quantized data stored as float.
|
|
89
88
|
"""
|
|
@@ -94,8 +93,7 @@ class TestEntropy(unittest.TestCase):
|
|
|
94
93
|
perm_entropy(x_const, order=3), _perm_entropy_orig(x_const, order=3)
|
|
95
94
|
)
|
|
96
95
|
|
|
97
|
-
# Ties at different window positions
|
|
98
|
-
# collapse both tied windows to the same pattern; with jitter it matches argsort.
|
|
96
|
+
# Ties at different window positions must remain distinct patterns.
|
|
99
97
|
# x = [3, 2, 2, 1, 3]:
|
|
100
98
|
# window [3,2,2] → argsort [1,2,0] (b<c<a, tie broken by position)
|
|
101
99
|
# window [2,2,1] → argsort [2,0,1] (c<a<b, tie broken by position)
|
|
@@ -106,7 +104,7 @@ class TestEntropy(unittest.TestCase):
|
|
|
106
104
|
atol=1e-12,
|
|
107
105
|
)
|
|
108
106
|
|
|
109
|
-
# Same signal stored as float
|
|
107
|
+
# Same signal stored as float: tie handling is independent of dtype.
|
|
110
108
|
x_ties_float = x_ties.astype(float)
|
|
111
109
|
np.testing.assert_allclose(
|
|
112
110
|
perm_entropy(x_ties_float, order=3),
|
|
@@ -145,6 +143,66 @@ class TestEntropy(unittest.TestCase):
|
|
|
145
143
|
err_msg=f"Mismatch on quantized float signal for order={order}",
|
|
146
144
|
)
|
|
147
145
|
|
|
146
|
+
def test_perm_entropy_preserves_ordering(self):
|
|
147
|
+
x = np.array([2, 0, 3, 1, 4, 1, 5, 2, 3, 0, 1, 4], dtype=np.int64)
|
|
148
|
+
examples = [
|
|
149
|
+
x,
|
|
150
|
+
x + 2**60,
|
|
151
|
+
x.astype(np.uint64) + 2**63,
|
|
152
|
+
np.array([int(value) + 2**100 for value in x], dtype=object),
|
|
153
|
+
x * 1e-18,
|
|
154
|
+
1.0 + x * np.finfo(float).eps,
|
|
155
|
+
]
|
|
156
|
+
for order in [3, 4]:
|
|
157
|
+
for delay in [1, 2, 3]:
|
|
158
|
+
for normalize in [False, True]:
|
|
159
|
+
# All examples preserve x's ordinal patterns. The original
|
|
160
|
+
# embedding helper casts integers to float64, so use x as
|
|
161
|
+
# the reference before adding large offsets.
|
|
162
|
+
reference = _perm_entropy_orig(x, order, delay, normalize)
|
|
163
|
+
for values in examples:
|
|
164
|
+
np.testing.assert_allclose(
|
|
165
|
+
perm_entropy(values, order, delay, normalize),
|
|
166
|
+
reference,
|
|
167
|
+
rtol=0,
|
|
168
|
+
atol=1e-14,
|
|
169
|
+
)
|
|
170
|
+
batch = np.vstack([x, x + 2**60])
|
|
171
|
+
np.testing.assert_allclose(
|
|
172
|
+
perm_entropy(batch, order, delay, normalize),
|
|
173
|
+
[reference, reference],
|
|
174
|
+
rtol=0,
|
|
175
|
+
atol=1e-14,
|
|
176
|
+
)
|
|
177
|
+
|
|
178
|
+
def test_perm_entropy_nan_epoch_isolation(self):
|
|
179
|
+
values = np.array([1, 0, 2, 3, 5, 4, 1, 2.0])
|
|
180
|
+
missing = values.copy()
|
|
181
|
+
missing[1] = np.nan
|
|
182
|
+
for order in [3, 4]:
|
|
183
|
+
for normalize in [False, True]:
|
|
184
|
+
self.assertTrue(np.isnan(perm_entropy(missing, order, normalize=normalize)))
|
|
185
|
+
self.assertTrue(
|
|
186
|
+
np.isnan(perm_entropy(missing.astype(object), order, normalize=normalize))
|
|
187
|
+
)
|
|
188
|
+
self.assertTrue(np.isnan(perm_entropy(np.vstack([missing, missing]), order)).all())
|
|
189
|
+
expected = _perm_entropy_orig(values, order, normalize=normalize)
|
|
190
|
+
for position in [0, 1, 2]:
|
|
191
|
+
batch = np.vstack([values, values, values])
|
|
192
|
+
batch[position] = missing
|
|
193
|
+
before = batch.copy()
|
|
194
|
+
actual = perm_entropy(batch, order, normalize=normalize)
|
|
195
|
+
self.assertTrue(np.isnan(actual[position]))
|
|
196
|
+
np.testing.assert_allclose(np.delete(actual, position), expected)
|
|
197
|
+
np.testing.assert_array_equal(batch, before)
|
|
198
|
+
|
|
199
|
+
infinite = values.copy()
|
|
200
|
+
infinite[:2] = [-np.inf, np.inf]
|
|
201
|
+
np.testing.assert_allclose(
|
|
202
|
+
perm_entropy(infinite, order, normalize=normalize),
|
|
203
|
+
_perm_entropy_orig(infinite, order, normalize=normalize),
|
|
204
|
+
)
|
|
205
|
+
|
|
148
206
|
def test_perm_entropy_fast_path(self):
|
|
149
207
|
"""Fast paths (order=3/4) must match the original argsort implementation for 1D input."""
|
|
150
208
|
rng = np.random.default_rng(0)
|
|
@@ -186,6 +244,44 @@ class TestEntropy(unittest.TestCase):
|
|
|
186
244
|
err_msg=f"2D mismatch: order={order}, delay={delay}, normalize={normalize}",
|
|
187
245
|
)
|
|
188
246
|
|
|
247
|
+
def test_perm_entropy_delay_shapes(self):
|
|
248
|
+
batch = np.random.default_rng(0).random((3, 30))
|
|
249
|
+
for values in [batch[0], batch]:
|
|
250
|
+
np.testing.assert_allclose(
|
|
251
|
+
perm_entropy(values, delay=np.array(2)), perm_entropy(values, delay=2)
|
|
252
|
+
)
|
|
253
|
+
for empty in [[], (), range(0), np.array([])]:
|
|
254
|
+
with self.assertRaisesRegex(ValueError, "delay sequence must not be empty"):
|
|
255
|
+
perm_entropy(values, delay=empty)
|
|
256
|
+
with self.assertRaisesRegex(ValueError, "scalar or a 1D sequence"):
|
|
257
|
+
perm_entropy(values, delay=np.array([[1, 2]]))
|
|
258
|
+
|
|
259
|
+
def test_perm_entropy_2d_multiple_delays(self):
|
|
260
|
+
x = np.array(
|
|
261
|
+
[
|
|
262
|
+
[3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5, 8],
|
|
263
|
+
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11],
|
|
264
|
+
]
|
|
265
|
+
)
|
|
266
|
+
for order in [3, 4]:
|
|
267
|
+
for normalize in [False, True]:
|
|
268
|
+
for delays in [[1, 2, 3], (1, 2, 3), np.array([1, 2, 3]), range(1, 4)]:
|
|
269
|
+
reference = [
|
|
270
|
+
np.mean(
|
|
271
|
+
[_perm_entropy_orig(row, order, delay, normalize) for delay in delays]
|
|
272
|
+
)
|
|
273
|
+
for row in x
|
|
274
|
+
]
|
|
275
|
+
result = perm_entropy(x, order, delays, normalize)
|
|
276
|
+
self.assertEqual(result.shape, (2,))
|
|
277
|
+
np.testing.assert_allclose(result, reference)
|
|
278
|
+
single_epoch = perm_entropy(x[:1], order, delays, normalize)
|
|
279
|
+
self.assertEqual(single_epoch.shape, (1,))
|
|
280
|
+
np.testing.assert_allclose(single_epoch, reference[:1])
|
|
281
|
+
scalar = perm_entropy(x[0], order, delays, normalize)
|
|
282
|
+
self.assertEqual(np.ndim(scalar), 0)
|
|
283
|
+
np.testing.assert_allclose(scalar, reference[0])
|
|
284
|
+
|
|
189
285
|
def test_spectral_entropy(self):
|
|
190
286
|
spectral_entropy(RANDOM_TS, SF_TS, method="fft")
|
|
191
287
|
spectral_entropy(RANDOM_TS, SF_TS, method="welch")
|
|
@@ -194,7 +290,7 @@ class TestEntropy(unittest.TestCase):
|
|
|
194
290
|
self.assertEqual(np.round(spectral_entropy(PURE_SINE, 100), 2), 0.0)
|
|
195
291
|
# 2D data
|
|
196
292
|
params = dict(sf=SF_TS, normalize=True, method="welch", nperseg=100)
|
|
197
|
-
|
|
293
|
+
assert_allclose(
|
|
198
294
|
aal(spectral_entropy, axis=1, arr=data, **params),
|
|
199
295
|
spectral_entropy(data, **params),
|
|
200
296
|
)
|
|
@@ -310,7 +406,7 @@ class TestEntropy(unittest.TestCase):
|
|
|
310
406
|
assert mob_sine < mob
|
|
311
407
|
assert com_sine < com
|
|
312
408
|
# 2D data (avoid warning with flat line variance)
|
|
313
|
-
|
|
409
|
+
assert_allclose(
|
|
314
410
|
aal(hjorth_params, axis=-1, arr=data[:-1, :]).T,
|
|
315
411
|
hjorth_params(data[:-1, :], axis=-1),
|
|
316
412
|
)
|
|
@@ -4,7 +4,7 @@ import unittest
|
|
|
4
4
|
|
|
5
5
|
import numpy as np
|
|
6
6
|
from numpy import apply_along_axis as aal
|
|
7
|
-
from numpy.testing import
|
|
7
|
+
from numpy.testing import assert_allclose
|
|
8
8
|
from utils import ARANGE, NORMAL_TS, PURE_COSINE, PURE_SINE, RANDOM_TS, TEST_DTYPES
|
|
9
9
|
|
|
10
10
|
from antropy import detrended_fluctuation, higuchi_fd, katz_fd, petrosian_fd
|
|
@@ -49,16 +49,16 @@ class TestEntropy(unittest.TestCase):
|
|
|
49
49
|
petrosian_fd(list(RANDOM_TS))
|
|
50
50
|
self.assertEqual(np.round(pfd, 3), 1.030)
|
|
51
51
|
# 2D data
|
|
52
|
-
|
|
53
|
-
|
|
52
|
+
assert_allclose(aal(petrosian_fd, axis=1, arr=data), petrosian_fd(data))
|
|
53
|
+
assert_allclose(aal(petrosian_fd, axis=0, arr=data), petrosian_fd(data, axis=0))
|
|
54
54
|
|
|
55
55
|
def test_katz_fd(self):
|
|
56
56
|
x_k = [0.0, 0.0, 2.0, -2.0, 0.0, -1.0, -1.0, 0.0]
|
|
57
57
|
self.assertEqual(np.round(katz_fd(x_k), 3), 5.783)
|
|
58
58
|
# 2D data
|
|
59
59
|
data_kfd = np.vstack((RANDOM_TS, NORMAL_TS, PURE_SINE, PURE_COSINE, ARANGE))
|
|
60
|
-
|
|
61
|
-
|
|
60
|
+
assert_allclose(aal(katz_fd, axis=1, arr=data_kfd), katz_fd(data_kfd))
|
|
61
|
+
assert_allclose(aal(katz_fd, axis=0, arr=data_kfd), katz_fd(data_kfd, axis=0))
|
|
62
62
|
|
|
63
63
|
def test_higuchi_fd(self):
|
|
64
64
|
"""Test for function `higuchi_fd`.
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|