scikit-diveMove 1.0.0__tar.gz → 1.0.1__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.
- {scikit_divemove-1.0.0 → scikit_divemove-1.0.1}/PKG-INFO +4 -4
- {scikit_divemove-1.0.0 → scikit_divemove-1.0.1}/pyproject.toml +28 -5
- {scikit_divemove-1.0.0 → scikit_divemove-1.0.1}/skdiveMove/__init__.py +1 -1
- {scikit_divemove-1.0.0 → scikit_divemove-1.0.1}/skdiveMove/bouts/__init__.py +1 -1
- {scikit_divemove-1.0.0 → scikit_divemove-1.0.1}/skdiveMove/bouts/boutsnls.py +9 -6
- {scikit_divemove-1.0.0 → scikit_divemove-1.0.1}/skdiveMove/calibspeed.py +1 -1
- {scikit_divemove-1.0.0 → scikit_divemove-1.0.1}/skdiveMove/tdr.py +53 -27
- {scikit_divemove-1.0.0 → scikit_divemove-1.0.1}/skdiveMove/tdrphases.py +7 -7
- {scikit_divemove-1.0.0 → scikit_divemove-1.0.1}/skdiveMove/tdrsource.py +2 -2
- scikit_divemove-1.0.1/skdiveMove/tests/conftest.py +18 -0
- scikit_divemove-1.0.0/skdiveMove/tests/__init__.py → scikit_divemove-1.0.1/skdiveMove/tests/get_sample_data.py +44 -2
- scikit_divemove-1.0.1/skdiveMove/tests/scenarios.py +135 -0
- scikit_divemove-1.0.1/skdiveMove/tests/test_BoutsMLE.py +296 -0
- scikit_divemove-1.0.1/skdiveMove/tests/test_BoutsNLS.py +307 -0
- scikit_divemove-1.0.1/skdiveMove/tests/test_TDR.py +214 -0
- scikit_divemove-1.0.1/skdiveMove/tests/test_TDRPhases.py +162 -0
- scikit_divemove-1.0.1/skdiveMove/tests/test_TDRSource.py +46 -0
- scikit_divemove-1.0.1/skdiveMove/tests/test_ZOC.py +94 -0
- scikit_divemove-1.0.1/skdiveMove/tests/test_calibrate.py +42 -0
- {scikit_divemove-1.0.0 → scikit_divemove-1.0.1}/skdiveMove/zoc.py +8 -4
- scikit_divemove-1.0.0/skdiveMove/tests/get_sample_data.py +0 -45
- scikit_divemove-1.0.0/skdiveMove/tests/test_BoutsMLE.py +0 -294
- scikit_divemove-1.0.0/skdiveMove/tests/test_BoutsNLS.py +0 -303
- scikit_divemove-1.0.0/skdiveMove/tests/test_TDR.py +0 -246
- scikit_divemove-1.0.0/skdiveMove/tests/test_TDRPhases.py +0 -205
- scikit_divemove-1.0.0/skdiveMove/tests/test_TDRSource.py +0 -48
- scikit_divemove-1.0.0/skdiveMove/tests/test_ZOC.py +0 -94
- scikit_divemove-1.0.0/skdiveMove/tests/test_calibrate.py +0 -48
- {scikit_divemove-1.0.0 → scikit_divemove-1.0.1}/LICENSE +0 -0
- {scikit_divemove-1.0.0 → scikit_divemove-1.0.1}/skdiveMove/__main__.py +0 -0
- {scikit_divemove-1.0.0 → scikit_divemove-1.0.1}/skdiveMove/bouts/bouts.py +0 -0
- {scikit_divemove-1.0.0 → scikit_divemove-1.0.1}/skdiveMove/bouts/boutsmle.py +0 -0
- {scikit_divemove-1.0.0 → scikit_divemove-1.0.1}/skdiveMove/calibconfig.py +0 -0
- {scikit_divemove-1.0.0 → scikit_divemove-1.0.1}/skdiveMove/config_examples/ag_mk7_2002_022_config.json +0 -0
- {scikit_divemove-1.0.0 → scikit_divemove-1.0.1}/skdiveMove/core.py +0 -0
- {scikit_divemove-1.0.0 → scikit_divemove-1.0.1}/skdiveMove/helpers.py +0 -0
- {scikit_divemove-1.0.0 → scikit_divemove-1.0.1}/skdiveMove/metadata.py +0 -0
- {scikit_divemove-1.0.0 → scikit_divemove-1.0.1}/skdiveMove/plotting.py +0 -0
- {scikit_divemove-1.0.0 → scikit_divemove-1.0.1}/skdiveMove/tests/data/ag_mk7_2002_022.nc +0 -0
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: scikit-diveMove
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.1
|
|
4
4
|
Summary: Python interface to R package diveMove
|
|
5
5
|
License: AGPL-3.0-or-later
|
|
6
6
|
License-File: LICENSE
|
|
7
7
|
Keywords: animal behaviour,biology,behavioural ecology,diving,diving behaviour
|
|
8
8
|
Author: Sebastian Luque
|
|
9
|
-
Requires-Python: >=3.
|
|
9
|
+
Requires-Python: >=3.13
|
|
10
10
|
Classifier: Development Status :: 4 - Beta
|
|
11
11
|
Classifier: Programming Language :: Python :: 3
|
|
12
12
|
Classifier: Intended Audience :: Developers
|
|
@@ -15,14 +15,14 @@ Classifier: License :: OSI Approved :: GNU Affero General Public License v3 or l
|
|
|
15
15
|
Classifier: Topic :: Scientific/Engineering
|
|
16
16
|
Classifier: Topic :: Scientific/Engineering :: Instrument Drivers
|
|
17
17
|
Requires-Dist: bottleneck (>=1.6.0,<2.0.0)
|
|
18
|
-
Requires-Dist: docutils (>=0.
|
|
18
|
+
Requires-Dist: docutils (>=0.23,<0.24)
|
|
19
19
|
Requires-Dist: matplotlib (>=3.10.8,<4.0.0)
|
|
20
20
|
Requires-Dist: netcdf4 (>=1.7.4,<2.0.0)
|
|
21
21
|
Requires-Dist: numpy (>=2.4.3,<3.0.0)
|
|
22
22
|
Requires-Dist: pandas (>=3.0.1,<4.0.0)
|
|
23
23
|
Requires-Dist: rpy2 (>=3.6.5,<4.0.0)
|
|
24
24
|
Requires-Dist: scipy (>=1.17.1,<2.0.0)
|
|
25
|
-
Requires-Dist: statsmodels (>=0.
|
|
25
|
+
Requires-Dist: statsmodels (>=0.15.0,<0.16.0)
|
|
26
26
|
Requires-Dist: xarray (>=2026.2.0,<2027.0.0)
|
|
27
27
|
Project-URL: Documentation, https://spluque.github.io/scikit-diveMove
|
|
28
28
|
Project-URL: Repository, https://github.com/spluque/scikit-diveMove
|
|
@@ -6,17 +6,17 @@ authors = [
|
|
|
6
6
|
{name = "Sebastian Luque"}
|
|
7
7
|
]
|
|
8
8
|
license = {text = "AGPL-3.0-or-later"}
|
|
9
|
-
requires-python = ">=3.
|
|
9
|
+
requires-python = ">=3.13"
|
|
10
10
|
dependencies = [
|
|
11
11
|
"bottleneck (>=1.6.0,<2.0.0)",
|
|
12
|
-
"docutils (>=0.
|
|
12
|
+
"docutils (>=0.23,<0.24)",
|
|
13
13
|
"matplotlib (>=3.10.8,<4.0.0)",
|
|
14
14
|
"netcdf4 (>=1.7.4,<2.0.0)",
|
|
15
15
|
"numpy (>=2.4.3,<3.0.0)",
|
|
16
16
|
"pandas (>=3.0.1,<4.0.0)",
|
|
17
17
|
"rpy2 (>=3.6.5,<4.0.0)",
|
|
18
18
|
"scipy (>=1.17.1,<2.0.0)",
|
|
19
|
-
"statsmodels (>=0.
|
|
19
|
+
"statsmodels (>=0.15.0,<0.16.0)",
|
|
20
20
|
"xarray (>=2026.2.0,<2027.0.0)"
|
|
21
21
|
]
|
|
22
22
|
classifiers = [
|
|
@@ -34,7 +34,7 @@ keywords = ["animal behaviour",
|
|
|
34
34
|
"diving",
|
|
35
35
|
"diving behaviour"
|
|
36
36
|
]
|
|
37
|
-
version = "1.0.
|
|
37
|
+
version = "1.0.1"
|
|
38
38
|
|
|
39
39
|
[project.urls]
|
|
40
40
|
repository = "https://github.com/spluque/scikit-diveMove"
|
|
@@ -44,7 +44,7 @@ documentation = "https://spluque.github.io/scikit-diveMove"
|
|
|
44
44
|
docs = [
|
|
45
45
|
"ipykernel (>=7.2.0,<8.0.0)",
|
|
46
46
|
"myst-nb (>=1.4.0,<2.0.0)",
|
|
47
|
-
"pydata-sphinx-theme (>=0.
|
|
47
|
+
"pydata-sphinx-theme (>=0.24.0,<0.25.0)"
|
|
48
48
|
]
|
|
49
49
|
test = [
|
|
50
50
|
"pytest (>=9.0.2,<10.0.0)",
|
|
@@ -77,6 +77,29 @@ enable = false
|
|
|
77
77
|
source = "skdiveMove/__init__.py"
|
|
78
78
|
pattern = "^__version__\\s*=\\s*['\"](?P<version>.+?)['\"]"
|
|
79
79
|
|
|
80
|
+
[tool.pytest]
|
|
81
|
+
minversion = "9.0"
|
|
82
|
+
testpaths = ["skdiveMove"]
|
|
83
|
+
addopts = [
|
|
84
|
+
"--doctest-modules",
|
|
85
|
+
"--ignore-glob=skdiveMove/config_examples/*.json",
|
|
86
|
+
"-v",
|
|
87
|
+
"--tb=short",
|
|
88
|
+
"--strict-markers"
|
|
89
|
+
]
|
|
90
|
+
doctest_optionflags = ["NORMALIZE_WHITESPACE", "IGNORE_EXCEPTION_DETAIL"]
|
|
91
|
+
markers = [
|
|
92
|
+
"integration: integration tests (deselect with '-m \"not integration\"')",
|
|
93
|
+
"slow: slow tests (deselect with '-m \"not slow\"')",
|
|
94
|
+
"plotting: tests that generate plots"
|
|
95
|
+
]
|
|
96
|
+
filterwarnings = [
|
|
97
|
+
"ignore:.*ABCs.+:DeprecationWarning",
|
|
98
|
+
"ignore:.*tostring.+:DeprecationWarning"
|
|
99
|
+
]
|
|
100
|
+
log_format = "%(asctime)s[%(levelname)s] %(name)s:%(lineno)d: %(message)s"
|
|
101
|
+
log_date_format = "%Y-%m-%dT%H:%M:%S%z"
|
|
102
|
+
|
|
80
103
|
[build-system]
|
|
81
104
|
requires = [
|
|
82
105
|
"poetry-core>=2.0.0,<3.0.0",
|
|
@@ -107,7 +107,7 @@ Methods summary
|
|
|
107
107
|
from .bouts import Bouts, label_bouts
|
|
108
108
|
from .boutsnls import BoutsNLS
|
|
109
109
|
from .boutsmle import BoutsMLE
|
|
110
|
-
from skdiveMove.tests import random_mixexp
|
|
110
|
+
from skdiveMove.tests.get_sample_data import random_mixexp
|
|
111
111
|
|
|
112
112
|
__all__ = ["Bouts", "BoutsNLS", "BoutsMLE", "label_bouts",
|
|
113
113
|
"random_mixexp"]
|
|
@@ -26,7 +26,7 @@ class BoutsNLS(bouts.Bouts):
|
|
|
26
26
|
:math:`p < 0.7` and the second process occurs with the remaining
|
|
27
27
|
probability.
|
|
28
28
|
|
|
29
|
-
>>> from skdiveMove.tests import random_mixexp
|
|
29
|
+
>>> from skdiveMove.tests.get_sample_data import random_mixexp
|
|
30
30
|
>>> rng = np.random.default_rng(123)
|
|
31
31
|
>>> x2 = random_mixexp(1000, p=0.7, lda=np.array([0.05, 0.005]),
|
|
32
32
|
... rng=rng)
|
|
@@ -48,13 +48,16 @@ class BoutsNLS(bouts.Bouts):
|
|
|
48
48
|
|
|
49
49
|
Plot observed and predicted data:
|
|
50
50
|
|
|
51
|
-
>>>
|
|
52
|
-
|
|
51
|
+
>>> from matplotlib.pyplot import Axes
|
|
52
|
+
>>> ax = xbouts2.plot_fit(coefs)
|
|
53
|
+
>>> isinstance(ax, Axes)
|
|
54
|
+
True
|
|
53
55
|
|
|
54
56
|
Plot ECDF:
|
|
55
57
|
|
|
56
|
-
>>> xbouts2.plot_ecdf(coefs)
|
|
57
|
-
|
|
58
|
+
>>> ax = xbouts2.plot_ecdf(coefs)
|
|
59
|
+
>>> isinstance(ax, Axes)
|
|
60
|
+
True
|
|
58
61
|
|
|
59
62
|
"""
|
|
60
63
|
def fit(self, start, **kwargs):
|
|
@@ -156,7 +159,7 @@ class BoutsNLS(bouts.Bouts):
|
|
|
156
159
|
|
|
157
160
|
|
|
158
161
|
if __name__ == '__main__':
|
|
159
|
-
from skdiveMove.tests import diveMove2skd
|
|
162
|
+
from skdiveMove.tests.get_sample_data import diveMove2skd
|
|
160
163
|
import pandas as pd
|
|
161
164
|
|
|
162
165
|
tdrX = diveMove2skd()
|
|
@@ -48,13 +48,18 @@ class TDR(TDRPhases):
|
|
|
48
48
|
--------
|
|
49
49
|
Construct an instance from diveMove example dataset
|
|
50
50
|
|
|
51
|
-
>>>
|
|
51
|
+
>>> import matplotlib.pyplot as plt
|
|
52
|
+
>>> from skdiveMove.tests.get_sample_data import diveMove2skd
|
|
53
|
+
|
|
52
54
|
>>> tdrX = diveMove2skd()
|
|
53
55
|
|
|
54
56
|
Plot the `TDR` object
|
|
55
57
|
|
|
56
|
-
>>> tdrX.plot()
|
|
57
|
-
(
|
|
58
|
+
>>> fig, ax = tdrX.plot()
|
|
59
|
+
>>> isinstance(fig, plt.Figure)
|
|
60
|
+
True
|
|
61
|
+
>>> ax is not None
|
|
62
|
+
True
|
|
58
63
|
|
|
59
64
|
"""
|
|
60
65
|
|
|
@@ -131,7 +136,7 @@ class TDR(TDRPhases):
|
|
|
131
136
|
|
|
132
137
|
Examples
|
|
133
138
|
--------
|
|
134
|
-
>>> from skdiveMove.tests import diveMove2skd
|
|
139
|
+
>>> from skdiveMove.tests.get_sample_data import diveMove2skd
|
|
135
140
|
>>> tdrX = diveMove2skd(has_speed=True)
|
|
136
141
|
>>> tdrX.zoc("offset", offset=3)
|
|
137
142
|
>>> tdrX.calibrate_speed(z=2)
|
|
@@ -210,7 +215,7 @@ class TDR(TDRPhases):
|
|
|
210
215
|
--------
|
|
211
216
|
ZOC using the "filter" method
|
|
212
217
|
|
|
213
|
-
>>> from skdiveMove.tests import diveMove2skd
|
|
218
|
+
>>> from skdiveMove.tests.get_sample_data import diveMove2skd
|
|
214
219
|
>>> tdrX = diveMove2skd(has_speed=True)
|
|
215
220
|
|
|
216
221
|
>>> # Window lengths and probabilities
|
|
@@ -285,7 +290,7 @@ class TDR(TDRPhases):
|
|
|
285
290
|
ones_list.append(res)
|
|
286
291
|
|
|
287
292
|
ones_df = pd.concat(ones_list, ignore_index=True)
|
|
288
|
-
ones_df.set_index(dive_ids[ok].unique()
|
|
293
|
+
ones_df = ones_df.set_index(dive_ids[ok].unique())
|
|
289
294
|
ones_df.index.rename("dive_id", inplace=True)
|
|
290
295
|
ones_df["postdive_dur"] = postdive_dur[idx_name]
|
|
291
296
|
|
|
@@ -355,11 +360,16 @@ class TDR(TDRPhases):
|
|
|
355
360
|
|
|
356
361
|
Examples
|
|
357
362
|
--------
|
|
358
|
-
>>>
|
|
363
|
+
>>> import matplotlib.pyplot as plt
|
|
364
|
+
>>> from skdiveMove.tests.get_sample_data import diveMove2skd
|
|
359
365
|
>>> tdrX = diveMove2skd()
|
|
360
|
-
>>> tdrX.plot(
|
|
361
|
-
...
|
|
362
|
-
|
|
366
|
+
>>> fig, ax = tdrX.plot(
|
|
367
|
+
... xlim=["2002-01-05 21:00:00", "2002-01-06 04:10:00"],
|
|
368
|
+
... depth_lim=[95, -1])
|
|
369
|
+
>>> isinstance(fig, plt.Figure)
|
|
370
|
+
True
|
|
371
|
+
>>> ax is not None
|
|
372
|
+
True
|
|
363
373
|
|
|
364
374
|
"""
|
|
365
375
|
try:
|
|
@@ -419,7 +429,9 @@ class TDR(TDRPhases):
|
|
|
419
429
|
|
|
420
430
|
Examples
|
|
421
431
|
--------
|
|
422
|
-
>>>
|
|
432
|
+
>>> import matplotlib.pyplot as plt
|
|
433
|
+
>>> from skdiveMove.tests.get_sample_data import diveMove2skd
|
|
434
|
+
|
|
423
435
|
>>> tdrX = diveMove2skd()
|
|
424
436
|
>>> # Window lengths and probabilities
|
|
425
437
|
>>> DB = [-2, 5]
|
|
@@ -430,9 +442,11 @@ class TDR(TDRPhases):
|
|
|
430
442
|
>>> tdrX.detect_dives(3)
|
|
431
443
|
>>> tdrX.detect_dive_phases("unimodal", descent_crit_q=0.01,
|
|
432
444
|
... ascent_crit_q=0, knot_factor=20)
|
|
433
|
-
>>> tdrX.plot_zoc()
|
|
434
|
-
|
|
435
|
-
|
|
445
|
+
>>> fig, axs = tdrX.plot_zoc()
|
|
446
|
+
>>> isinstance(fig, plt.Figure)
|
|
447
|
+
True
|
|
448
|
+
>>> len(axs) == 3
|
|
449
|
+
True
|
|
436
450
|
|
|
437
451
|
"""
|
|
438
452
|
zoc_method = self.zoc_method
|
|
@@ -497,16 +511,21 @@ class TDR(TDRPhases):
|
|
|
497
511
|
|
|
498
512
|
Examples
|
|
499
513
|
--------
|
|
500
|
-
>>>
|
|
514
|
+
>>> import matplotlib.pyplot as plt
|
|
515
|
+
>>> from skdiveMove.tests.get_sample_data import diveMove2skd
|
|
516
|
+
|
|
501
517
|
>>> tdrX = diveMove2skd()
|
|
502
518
|
>>> tdrX.zoc("offset", offset=3)
|
|
503
519
|
>>> tdrX.detect_wet()
|
|
504
520
|
>>> tdrX.detect_dives(3)
|
|
505
521
|
>>> tdrX.detect_dive_phases("unimodal", descent_crit_q=0.01,
|
|
506
522
|
... ascent_crit_q=0, knot_factor=20)
|
|
507
|
-
>>> tdrX.plot_phases(list(range(250, 300)),
|
|
508
|
-
...
|
|
509
|
-
(
|
|
523
|
+
>>> fig, ax = tdrX.plot_phases(list(range(250, 300)),
|
|
524
|
+
... surface=True)
|
|
525
|
+
>>> isinstance(fig, plt.Figure)
|
|
526
|
+
True
|
|
527
|
+
>>> ax is not None
|
|
528
|
+
True
|
|
510
529
|
|
|
511
530
|
"""
|
|
512
531
|
row_ids = self.get_dives_details("row_ids")
|
|
@@ -595,16 +614,21 @@ class TDR(TDRPhases):
|
|
|
595
614
|
|
|
596
615
|
Examples
|
|
597
616
|
--------
|
|
598
|
-
>>>
|
|
617
|
+
>>> import matplotlib.pyplot as plt
|
|
618
|
+
>>> from skdiveMove.tests.get_sample_data import diveMove2skd
|
|
619
|
+
|
|
599
620
|
>>> tdrX = diveMove2skd()
|
|
600
621
|
>>> tdrX.zoc("offset", offset=3)
|
|
601
622
|
>>> tdrX.detect_wet()
|
|
602
623
|
>>> tdrX.detect_dives(3)
|
|
603
624
|
>>> tdrX.detect_dive_phases("unimodal", descent_crit_q=0.01,
|
|
604
625
|
... ascent_crit_q=0, knot_factor=20)
|
|
605
|
-
>>> tdrX.plot_dive_model(diveNo=20,
|
|
606
|
-
...
|
|
607
|
-
|
|
626
|
+
>>> fig, axs = tdrX.plot_dive_model(diveNo=20,
|
|
627
|
+
... figsize=(10, 10))
|
|
628
|
+
>>> isinstance(fig, plt.Figure)
|
|
629
|
+
True
|
|
630
|
+
>>> len(axs) == 2
|
|
631
|
+
True
|
|
608
632
|
|
|
609
633
|
"""
|
|
610
634
|
dive_ids = self.get_dives_details("row_ids", "dive_id")
|
|
@@ -776,16 +800,18 @@ class TDR(TDRPhases):
|
|
|
776
800
|
|
|
777
801
|
Examples
|
|
778
802
|
--------
|
|
779
|
-
>>> from skdiveMove.tests import diveMove2skd
|
|
803
|
+
>>> from skdiveMove.tests.get_sample_data import diveMove2skd
|
|
804
|
+
>>> from xarray import Dataset
|
|
805
|
+
|
|
780
806
|
>>> tdrX = diveMove2skd()
|
|
781
807
|
>>> tdrX.zoc("offset", offset=3)
|
|
782
808
|
>>> tdrX.detect_wet()
|
|
783
809
|
>>> tdrX.detect_dives(3)
|
|
784
810
|
>>> tdrX.detect_dive_phases("unimodal", descent_crit_q=0.01,
|
|
785
811
|
... ascent_crit_q=0, knot_factor=20)
|
|
786
|
-
>>> tdrX.extract_dives(diveNo=20)
|
|
787
|
-
|
|
788
|
-
|
|
812
|
+
>>> dives_ds = tdrX.extract_dives(diveNo=20)
|
|
813
|
+
>>> isinstance(dives_ds, Dataset)
|
|
814
|
+
True
|
|
789
815
|
|
|
790
816
|
"""
|
|
791
817
|
dive_ids = self.get_dives_details("row_ids", "dive_id")
|
|
@@ -832,7 +858,7 @@ def calibrate(tdr_file, config_file=None):
|
|
|
832
858
|
|
|
833
859
|
"""
|
|
834
860
|
if config_file is None:
|
|
835
|
-
config = calibconfig._DEFAULT_CONFIG
|
|
861
|
+
config = calibconfig._DEFAULT_CONFIG.copy()
|
|
836
862
|
else:
|
|
837
863
|
config = calibconfig.read_config(config_file)
|
|
838
864
|
|
|
@@ -148,7 +148,7 @@ class TDRPhases(ZOC):
|
|
|
148
148
|
--------
|
|
149
149
|
ZOC using the "offset" method for convenience
|
|
150
150
|
|
|
151
|
-
>>> from skdiveMove.tests import diveMove2skd
|
|
151
|
+
>>> from skdiveMove.tests.get_sample_data import diveMove2skd
|
|
152
152
|
>>> tdrX = diveMove2skd("TDRPhases")
|
|
153
153
|
>>> tdrX.zoc("offset", offset=3)
|
|
154
154
|
|
|
@@ -180,7 +180,7 @@ class TDRPhases(ZOC):
|
|
|
180
180
|
dry_thr=dry_thr,
|
|
181
181
|
wet_thr=wet_thr,
|
|
182
182
|
wet_cond=(robjs.vectors
|
|
183
|
-
.BoolVector(
|
|
183
|
+
.BoolVector(wet_cond)),
|
|
184
184
|
interval=dtime))
|
|
185
185
|
with (robjs.default_converter + pandas2ri.converter).context():
|
|
186
186
|
phases = pd.DataFrame({'phase_id': phases_l.rx2("phase.id"),
|
|
@@ -234,7 +234,7 @@ class TDRPhases(ZOC):
|
|
|
234
234
|
--------
|
|
235
235
|
ZOC using the ``offset`` method for convenience
|
|
236
236
|
|
|
237
|
-
>>> from skdiveMove.tests import diveMove2skd
|
|
237
|
+
>>> from skdiveMove.tests.get_sample_data import diveMove2skd
|
|
238
238
|
>>> tdrX = diveMove2skd("TDRPhases")
|
|
239
239
|
>>> tdrX.zoc("offset", offset=3)
|
|
240
240
|
|
|
@@ -256,7 +256,7 @@ class TDRPhases(ZOC):
|
|
|
256
256
|
# Replace dots with underscore
|
|
257
257
|
phases_df.columns = (phases_df.columns.str
|
|
258
258
|
.replace(".", "_", regex=False))
|
|
259
|
-
phases_df.set_index(depth_py.index
|
|
259
|
+
phases_df = phases_df.set_index(depth_py.index)
|
|
260
260
|
dive_activity = phases_df.pop("dive_activity")
|
|
261
261
|
# Dive and post-dive ID should be integer
|
|
262
262
|
phases_df = phases_df.astype(int)
|
|
@@ -383,7 +383,7 @@ class TDRPhases(ZOC):
|
|
|
383
383
|
--------
|
|
384
384
|
ZOC using the "offset" method for convenience
|
|
385
385
|
|
|
386
|
-
>>> from skdiveMove.tests import diveMove2skd
|
|
386
|
+
>>> from skdiveMove.tests.get_sample_data import diveMove2skd
|
|
387
387
|
>>> tdrX = diveMove2skd("TDRPhases")
|
|
388
388
|
>>> tdrX.zoc("offset", offset=3)
|
|
389
389
|
|
|
@@ -664,7 +664,7 @@ class TDRPhases(ZOC):
|
|
|
664
664
|
|
|
665
665
|
Examples
|
|
666
666
|
--------
|
|
667
|
-
>>> from skdiveMove.tests import diveMove2skd
|
|
667
|
+
>>> from skdiveMove.tests.get_sample_data import diveMove2skd
|
|
668
668
|
>>> tdrX = diveMove2skd("TDRPhases")
|
|
669
669
|
>>> tdrX.zoc("offset", offset=3)
|
|
670
670
|
>>> tdrX.detect_wet()
|
|
@@ -712,7 +712,7 @@ class TDRPhases(ZOC):
|
|
|
712
712
|
|
|
713
713
|
Examples
|
|
714
714
|
--------
|
|
715
|
-
>>> from skdiveMove.tests import diveMove2skd
|
|
715
|
+
>>> from skdiveMove.tests.get_sample_data import diveMove2skd
|
|
716
716
|
>>> tdrX = diveMove2skd("TDRPhases")
|
|
717
717
|
>>> tdrX.zoc("offset", offset=3)
|
|
718
718
|
>>> tdrX.detect_wet()
|
|
@@ -31,7 +31,7 @@ class TDRSource:
|
|
|
31
31
|
|
|
32
32
|
Examples
|
|
33
33
|
--------
|
|
34
|
-
>>> from skdiveMove.tests import diveMove2skd
|
|
34
|
+
>>> from skdiveMove.tests.get_sample_data import diveMove2skd
|
|
35
35
|
>>> tdrX = diveMove2skd()
|
|
36
36
|
>>> print(tdrX) # doctest: +ELLIPSIS
|
|
37
37
|
Time-Depth Recorder -- Class TDR object ...
|
|
@@ -66,7 +66,7 @@ class TDRSource:
|
|
|
66
66
|
for vname, da in self.tdr.data_vars.items():
|
|
67
67
|
da.attrs["sampling_rate"] = (1.0 /
|
|
68
68
|
pd.to_timedelta(subsample)
|
|
69
|
-
.
|
|
69
|
+
.total_seconds())
|
|
70
70
|
da.attrs["sampling_rate_units"] = "Hz"
|
|
71
71
|
_append_xr_attr(da, "history",
|
|
72
72
|
"Resampled to {}\n".format(subsample))
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"""Shared pytest fixtures for scikit-diveMove tests.
|
|
2
|
+
|
|
3
|
+
Provides reusable fixtures for test data, directory management, matplotlib
|
|
4
|
+
backend configuration, and sample data loading.
|
|
5
|
+
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import pytest
|
|
9
|
+
import matplotlib as mpl
|
|
10
|
+
mpl.use("Agg")
|
|
11
|
+
import matplotlib.pyplot as plt # noqa: E402
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@pytest.fixture(autouse=True)
|
|
15
|
+
def close_matplotlib_figures():
|
|
16
|
+
"""Close all matplotlib figures after each test."""
|
|
17
|
+
yield
|
|
18
|
+
plt.close("all")
|
|
@@ -1,7 +1,49 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""Helper function to load sample data onto a TDR object
|
|
2
2
|
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import importlib.resources as rsrc
|
|
3
6
|
import numpy as np
|
|
4
|
-
from .
|
|
7
|
+
from skdiveMove.tdr import TDR
|
|
8
|
+
from skdiveMove.tdrsource import TDRSource
|
|
9
|
+
from skdiveMove.tdrphases import TDRPhases
|
|
10
|
+
from skdiveMove.zoc import ZOC
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def diveMove2skd(oclass="TDR", **kwargs):
|
|
14
|
+
"""Create a `TDRSource` instance from `diveMove` example data set
|
|
15
|
+
|
|
16
|
+
The sample data set has been converted to NetCDF4 format, to include
|
|
17
|
+
all necessary metadata.
|
|
18
|
+
|
|
19
|
+
Parameters
|
|
20
|
+
----------
|
|
21
|
+
oclass : {"TDRSource", "ZOC", "TDRPhases", "TDR"}
|
|
22
|
+
The class to return.
|
|
23
|
+
**kwargs
|
|
24
|
+
Optional keyword arguments passed to class instantiator.
|
|
25
|
+
|
|
26
|
+
Returns
|
|
27
|
+
-------
|
|
28
|
+
`TDR`
|
|
29
|
+
|
|
30
|
+
"""
|
|
31
|
+
class_names = ["TDRSource", "ZOC", "TDRPhases", "TDR"]
|
|
32
|
+
|
|
33
|
+
if oclass in class_names:
|
|
34
|
+
ifile = (rsrc.files("skdiveMove") / "tests" /
|
|
35
|
+
"data" / "ag_mk7_2002_022.nc")
|
|
36
|
+
|
|
37
|
+
classes = [TDRSource, ZOC, TDRPhases, TDR]
|
|
38
|
+
class_map = dict(zip(class_names, classes))
|
|
39
|
+
tdrX = class_map[oclass].read_netcdf(ifile, depth_name="depth",
|
|
40
|
+
time_name="date_time",
|
|
41
|
+
**kwargs)
|
|
42
|
+
else:
|
|
43
|
+
raise LookupError(("Requested class ({}) does not exist"
|
|
44
|
+
.format(oclass)))
|
|
45
|
+
|
|
46
|
+
return tdrX
|
|
5
47
|
|
|
6
48
|
|
|
7
49
|
def random_mixexp(n, p, lda, rng=None):
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
"""Meta classes for flexible testing of TDR and bout analysis classes
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
import numpy as np
|
|
5
|
+
import pandas as pd
|
|
6
|
+
|
|
7
|
+
from abc import ABC, abstractmethod
|
|
8
|
+
from skdiveMove.tests.get_sample_data import (
|
|
9
|
+
diveMove2skd, random_mixexp) # noqa: E402
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class TDRScenario:
|
|
13
|
+
"""Test `TDR` class.
|
|
14
|
+
|
|
15
|
+
Parameters
|
|
16
|
+
----------
|
|
17
|
+
oclass : {"TDRSource", "ZOC", "TDRPhases", "TDR"}
|
|
18
|
+
The class to retrieve from sample data.
|
|
19
|
+
**kwargs
|
|
20
|
+
Optional keyword arguments passed to class instantiator.
|
|
21
|
+
|
|
22
|
+
Attributes
|
|
23
|
+
----------
|
|
24
|
+
tdrX : TDR
|
|
25
|
+
TDR instance.
|
|
26
|
+
default_pars : dict
|
|
27
|
+
Calibrate parameters.
|
|
28
|
+
tdr_calib : TDRPhases
|
|
29
|
+
Calibrated TDR instance.
|
|
30
|
+
diveNo_seq : ndarray of shape (N,)
|
|
31
|
+
Sequence of dive numbers in the time series.
|
|
32
|
+
|
|
33
|
+
"""
|
|
34
|
+
def __init__(self, oclass, **kwargs) -> None:
|
|
35
|
+
# An instance to work with
|
|
36
|
+
self.tdrX = diveMove2skd(oclass, **kwargs)
|
|
37
|
+
zoc_offset = 3
|
|
38
|
+
dry_thr = 70
|
|
39
|
+
wet_thr = 3610
|
|
40
|
+
dive_thr = 3
|
|
41
|
+
dive_model = "unimodal"
|
|
42
|
+
smooth_par = 0.1
|
|
43
|
+
knot_factor = 3
|
|
44
|
+
descent_crit_q = 0
|
|
45
|
+
ascent_crit_q = 0
|
|
46
|
+
self.default_pars = {"zoc_offset": zoc_offset,
|
|
47
|
+
"dry_thr": dry_thr,
|
|
48
|
+
"wet_thr": wet_thr,
|
|
49
|
+
"dive_thr": dive_thr,
|
|
50
|
+
"dive_model": dive_model,
|
|
51
|
+
"smooth_par": smooth_par,
|
|
52
|
+
"knot_factor": knot_factor,
|
|
53
|
+
"descent_crit_q": descent_crit_q,
|
|
54
|
+
"ascent_crit_q": ascent_crit_q}
|
|
55
|
+
self.diveNo_seq = None
|
|
56
|
+
|
|
57
|
+
def zoc(self):
|
|
58
|
+
tdrX = self.tdrX
|
|
59
|
+
default_pars = self.default_pars
|
|
60
|
+
tdrX.zoc(method="offset", offset=default_pars["zoc_offset"])
|
|
61
|
+
|
|
62
|
+
def detect_wet(self):
|
|
63
|
+
default_pars = self.default_pars
|
|
64
|
+
self.zoc()
|
|
65
|
+
self.tdrX.detect_wet(dry_thr=default_pars["dry_thr"],
|
|
66
|
+
wet_thr=default_pars["wet_thr"])
|
|
67
|
+
|
|
68
|
+
def detect_dives(self):
|
|
69
|
+
default_pars = self.default_pars
|
|
70
|
+
self.detect_wet()
|
|
71
|
+
self.tdrX.detect_dives(dive_thr=default_pars["dive_thr"])
|
|
72
|
+
diveNo_max = (self.tdrX.get_dives_details("row_ids", "dive_id")
|
|
73
|
+
.max())
|
|
74
|
+
self.diveNo_seq = np.arange(diveNo_max) + 1
|
|
75
|
+
|
|
76
|
+
def detect_dive_phases(self):
|
|
77
|
+
default_pars = self.default_pars
|
|
78
|
+
self.detect_dives()
|
|
79
|
+
self.tdrX.detect_dive_phases(
|
|
80
|
+
dive_model=default_pars["dive_model"],
|
|
81
|
+
smooth_par=default_pars["smooth_par"],
|
|
82
|
+
knot_factor=default_pars["knot_factor"],
|
|
83
|
+
descent_crit_q=default_pars["descent_crit_q"],
|
|
84
|
+
ascent_crit_q=default_pars["ascent_crit_q"])
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
class BoutsBaseScenario(ABC):
|
|
88
|
+
"""Common base scenario for testing
|
|
89
|
+
|
|
90
|
+
Subclasses must implement their own __init__ method.
|
|
91
|
+
|
|
92
|
+
Attributes
|
|
93
|
+
----------
|
|
94
|
+
nsamp : int
|
|
95
|
+
Number of samples to draw from the mixed distributions.
|
|
96
|
+
x : array_like
|
|
97
|
+
1D array with samples from mixed distribution.
|
|
98
|
+
pars_true : dict
|
|
99
|
+
Dictionary with true parameters used to generate `x`, with keys:
|
|
100
|
+
`p`, `lambda0`, and `lambda1`, if it is a 2-process scenario, or
|
|
101
|
+
`p0`, `p1`, `lambda0`, `lambda1`, and `lambda2`, if it is a
|
|
102
|
+
3-process scenario.
|
|
103
|
+
nls_opts, mle_opts1, mle_opts2 : dict
|
|
104
|
+
Dictionary with keys and values passed to optimization routine for
|
|
105
|
+
first and second fits.
|
|
106
|
+
|
|
107
|
+
"""
|
|
108
|
+
|
|
109
|
+
@abstractmethod
|
|
110
|
+
def __init__(self, nsamp: int) -> None:
|
|
111
|
+
self.nsamp = nsamp
|
|
112
|
+
self.rng = np.random.default_rng()
|
|
113
|
+
self.pars_true = None
|
|
114
|
+
self.nls_opts = None
|
|
115
|
+
self.mle_opts1 = None
|
|
116
|
+
self.mle_opts2 = None
|
|
117
|
+
self.x = None
|
|
118
|
+
|
|
119
|
+
def generate_proc2(self, pars_true):
|
|
120
|
+
# Generate samples for 2-process case
|
|
121
|
+
x2 = random_mixexp(self.nsamp,
|
|
122
|
+
pars_true.loc["p"],
|
|
123
|
+
(pars_true.loc[["lambda0", "lambda1"]]
|
|
124
|
+
.to_numpy()), rng=self.rng)
|
|
125
|
+
|
|
126
|
+
return pd.Series(x2)
|
|
127
|
+
|
|
128
|
+
def generate_proc3(self, pars_true):
|
|
129
|
+
# Generate samples for 3-process case
|
|
130
|
+
x3 = random_mixexp(self.nsamp,
|
|
131
|
+
pars_true.loc[["p0", "p1"]].to_numpy(),
|
|
132
|
+
(pars_true.loc[
|
|
133
|
+
["lambda0", "lambda1", "lambda2"]]
|
|
134
|
+
.to_numpy()), rng=self.rng)
|
|
135
|
+
return pd.Series(x3)
|