timelined_array 0.1.0__tar.gz → 0.1.2__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.
- {timelined_array-0.1.0 → timelined_array-0.1.2}/PKG-INFO +7 -6
- {timelined_array-0.1.0 → timelined_array-0.1.2}/README.md +6 -5
- {timelined_array-0.1.0 → timelined_array-0.1.2}/pyproject.toml +8 -2
- {timelined_array-0.1.0 → timelined_array-0.1.2}/src/timelined_array/__init__.py +1 -1
- {timelined_array-0.1.0 → timelined_array-0.1.2}/src/timelined_array/time.py +8 -4
- {timelined_array-0.1.0 → timelined_array-0.1.2}/tests/test_timelined_array.py +98 -4
- {timelined_array-0.1.0 → timelined_array-0.1.2}/LICENSE +0 -0
- {timelined_array-0.1.0 → timelined_array-0.1.2}/tests/__init__.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: timelined_array
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.2
|
|
4
4
|
Summary: Manage easily 1 or multidimensionnal samples numpy arrays that are time related. Extends numpy without removing any of it's abilities on such arrays.
|
|
5
5
|
Author-Email: Timothe Jost <44769559+JostTim@users.noreply.github.com>
|
|
6
6
|
License: MIT
|
|
@@ -12,11 +12,12 @@ Description-Content-Type: text/markdown
|
|
|
12
12
|
|
|
13
13
|
# timelined_array
|
|
14
14
|
|
|
15
|
-

|
|
16
|
+

|
|
17
|
+

|
|
18
|
+

|
|
19
|
+
[](https://codecov.io/gh/JostTim/timelined_array)
|
|
20
|
+
|
|
20
21
|
|
|
21
22
|
<!-- eventually, add ?cache-bust=1 to badges url above, and update the value of cache-bust randomly at git commits (or based on the commit name) so that we always see the latest badge produced, and not the cached badge in the browser.-->
|
|
22
23
|
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
# timelined_array
|
|
2
2
|
|
|
3
|
-

|
|
4
|
+

|
|
5
|
+

|
|
6
|
+

|
|
7
|
+
[](https://codecov.io/gh/JostTim/timelined_array)
|
|
8
|
+
|
|
8
9
|
|
|
9
10
|
<!-- eventually, add ?cache-bust=1 to badges url above, and update the value of cache-bust randomly at git commits (or based on the commit name) so that we always see the latest badge produced, and not the cached badge in the browser.-->
|
|
10
11
|
|
|
@@ -10,7 +10,7 @@ dependencies = [
|
|
|
10
10
|
requires-python = ">=3.11"
|
|
11
11
|
readme = "README.md"
|
|
12
12
|
dynamic = []
|
|
13
|
-
version = "0.1.
|
|
13
|
+
version = "0.1.2"
|
|
14
14
|
|
|
15
15
|
[project.license]
|
|
16
16
|
text = "MIT"
|
|
@@ -39,11 +39,17 @@ dev = [
|
|
|
39
39
|
]
|
|
40
40
|
|
|
41
41
|
[tool.pytest.ini_options]
|
|
42
|
-
addopts = "--pdbcls=IPython.terminal.debugger:TerminalPdb --cov-report xml --cov --junitxml=pytest_results.xml"
|
|
42
|
+
addopts = "--pdbcls=IPython.terminal.debugger:TerminalPdb --cov-report xml --cov=timelined_array --junitxml=pytest_results.xml --cov-config=pyproject.toml"
|
|
43
43
|
testpaths = [
|
|
44
44
|
"tests",
|
|
45
45
|
]
|
|
46
46
|
|
|
47
|
+
[tool.coverage.run]
|
|
48
|
+
omit = [
|
|
49
|
+
".vscode/*",
|
|
50
|
+
".tests/*",
|
|
51
|
+
]
|
|
52
|
+
|
|
47
53
|
[tool.black]
|
|
48
54
|
preview = true
|
|
49
55
|
line-length = 120
|
|
@@ -7,7 +7,9 @@ import operator
|
|
|
7
7
|
|
|
8
8
|
from numpy.typing import NDArray
|
|
9
9
|
from types import MethodType
|
|
10
|
-
from typing import Tuple, List, Protocol, Type, Callable, Any, Optional
|
|
10
|
+
from typing import Tuple, List, Protocol, Type, Callable, Any, Optional, TypeVar, Sequence
|
|
11
|
+
|
|
12
|
+
Tp = TypeVar("Tp", bound="TimelinedArray")
|
|
11
13
|
|
|
12
14
|
OperatorType = Callable[[Any, Any], bool]
|
|
13
15
|
|
|
@@ -635,8 +637,10 @@ class BaseTimeArray(TimeMixin, np.ndarray):
|
|
|
635
637
|
Returns:
|
|
636
638
|
TimelinedArray: The synchronized and cut arrray.
|
|
637
639
|
"""
|
|
640
|
+
# this slice is to select the number of elements, on the time_dimension
|
|
641
|
+
slices = tuple(slice(None) if i != self.time_dimension else slice(None, element_nb) for i in range(self.ndim))
|
|
638
642
|
|
|
639
|
-
return self.itime[start:][
|
|
643
|
+
return self.itime[start:][slices] # type: ignore
|
|
640
644
|
|
|
641
645
|
def shift_values(
|
|
642
646
|
self,
|
|
@@ -829,7 +833,7 @@ class BaseTimeArray(TimeMixin, np.ndarray):
|
|
|
829
833
|
def all_axes(self):
|
|
830
834
|
return tuple([i for i in range(self.ndim)])
|
|
831
835
|
|
|
832
|
-
def mean(self, axis: int | Tuple[int, ...] | None = None, dtype=None, out=None, keepdims=False):
|
|
836
|
+
def mean(self: Tp, axis: int | Tuple[int, ...] | None = None, dtype=None, out=None, keepdims=False) -> Tp:
|
|
833
837
|
"""Calculates the mean along the specified axis.
|
|
834
838
|
|
|
835
839
|
Args:
|
|
@@ -1238,7 +1242,7 @@ class TimelinedArray(BaseTimeArray):
|
|
|
1238
1242
|
return type(self).__name__ + np.asarray(self).__str__()
|
|
1239
1243
|
|
|
1240
1244
|
@staticmethod
|
|
1241
|
-
def align_from_iterable(iterable) -> "TimelinedArray":
|
|
1245
|
+
def align_from_iterable(iterable: "Sequence[TimelinedArray]") -> "TimelinedArray":
|
|
1242
1246
|
"""Aligns arrays from an iterable based on their timelines.
|
|
1243
1247
|
|
|
1244
1248
|
Args:
|
|
@@ -25,6 +25,13 @@ def timelined_array_3D():
|
|
|
25
25
|
return TimelinedArray(np.random.rand(25, 50, 75), timeline=np.arange(50), time_dimension=1)
|
|
26
26
|
|
|
27
27
|
|
|
28
|
+
@pytest.fixture
|
|
29
|
+
def masked_timelined_array_1D():
|
|
30
|
+
data = np.random.rand(50)
|
|
31
|
+
mask = data > 0.5
|
|
32
|
+
return MaskedTimelinedArray(data, mask=mask, timeline=np.arange(50), time_dimension=0)
|
|
33
|
+
|
|
34
|
+
|
|
28
35
|
@pytest.fixture
|
|
29
36
|
def pickle_path():
|
|
30
37
|
file_path = Path("serialized_test_3D_ta_array.pickle")
|
|
@@ -33,6 +40,38 @@ def pickle_path():
|
|
|
33
40
|
file_path.unlink(missing_ok=True)
|
|
34
41
|
|
|
35
42
|
|
|
43
|
+
def test_timelined_array_1D_properties(timelined_array_1D):
|
|
44
|
+
assert timelined_array_1D.time_dimension == 0
|
|
45
|
+
assert timelined_array_1D.timeline.shape == (50,)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def test_timelined_array_3D_properties(timelined_array_3D):
|
|
49
|
+
assert timelined_array_3D.time_dimension == 1
|
|
50
|
+
assert timelined_array_3D.timeline.shape == (50,)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def test_masked_timelined_array_1D_properties(masked_timelined_array_1D):
|
|
54
|
+
assert masked_timelined_array_1D.time_dimension == 0
|
|
55
|
+
assert np.all(masked_timelined_array_1D.mask == (masked_timelined_array_1D.data > 0.5))
|
|
56
|
+
assert masked_timelined_array_1D.timeline.shape == (50,)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def test_timelined_array_indexing(timelined_array_1D):
|
|
60
|
+
sub_array = timelined_array_1D[10:20]
|
|
61
|
+
assert isinstance(sub_array, TimelinedArray)
|
|
62
|
+
assert sub_array.shape == (10,)
|
|
63
|
+
assert np.array_equal(sub_array.timeline, np.arange(10, 20))
|
|
64
|
+
assert timelined_array_1D[[1]] == timelined_array_1D[1]
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def test_masked_timelined_array_indexing(masked_timelined_array_1D):
|
|
68
|
+
sub_array = masked_timelined_array_1D[10:20]
|
|
69
|
+
assert isinstance(sub_array, MaskedTimelinedArray)
|
|
70
|
+
assert sub_array.shape == (10,)
|
|
71
|
+
assert np.array_equal(sub_array.timeline, np.arange(10, 20))
|
|
72
|
+
assert np.all(sub_array.mask == (sub_array.data > 0.5))
|
|
73
|
+
|
|
74
|
+
|
|
36
75
|
def get_axis_parameters_3D():
|
|
37
76
|
# affected_axis, time_dimension, shape
|
|
38
77
|
# if None, we expect an AttributeError
|
|
@@ -54,12 +93,23 @@ def test_timeline_creation():
|
|
|
54
93
|
assert isinstance(timeline, Timeline)
|
|
55
94
|
assert timeline.max() == 9
|
|
56
95
|
assert timeline.min() == 0
|
|
96
|
+
assert 5 in timeline
|
|
97
|
+
assert timeline.step == 1
|
|
57
98
|
|
|
58
99
|
with pytest.raises(NotImplementedError):
|
|
59
100
|
timeline = Timeline(np.random.rand(10), uniform_space=True)
|
|
60
101
|
# assert np.unique(np.diff(timeline)).size == 1
|
|
61
102
|
|
|
62
103
|
|
|
104
|
+
def test_timelined_array_creation(timelined_array_1D):
|
|
105
|
+
|
|
106
|
+
with pytest.raises(ValueError):
|
|
107
|
+
array = TimelinedArray(np.array(timelined_array_1D))
|
|
108
|
+
|
|
109
|
+
with pytest.raises(ValueError):
|
|
110
|
+
array = TimelinedArray(np.array(timelined_array_1D), time_dimension=5.5)
|
|
111
|
+
|
|
112
|
+
|
|
63
113
|
def test_pickle_unpickle(timelined_array_3D, pickle_path):
|
|
64
114
|
# Pickle the numpy array
|
|
65
115
|
with open(pickle_path, "wb") as f:
|
|
@@ -76,13 +126,13 @@ def test_pickle_unpickle(timelined_array_3D, pickle_path):
|
|
|
76
126
|
|
|
77
127
|
|
|
78
128
|
def test_start_boundary():
|
|
79
|
-
assert StartBoundary.inclusive.value(5, 5)
|
|
80
|
-
assert not StartBoundary.exclusive.value(5, 5)
|
|
129
|
+
assert StartBoundary.inclusive.value(5, 5) # 5 is => than 5
|
|
130
|
+
assert not StartBoundary.exclusive.value(5, 5) # 5 is not > than 5
|
|
81
131
|
|
|
82
132
|
|
|
83
133
|
def test_stop_boundary():
|
|
84
|
-
assert StoptBoundary.inclusive.value(5, 5)
|
|
85
|
-
assert not StoptBoundary.exclusive.value(5, 5)
|
|
134
|
+
assert StoptBoundary.inclusive.value(5, 5) # 5 is =< than 5
|
|
135
|
+
assert not StoptBoundary.exclusive.value(5, 5) # 5 is not < than 5
|
|
86
136
|
|
|
87
137
|
|
|
88
138
|
def test_edge_policy():
|
|
@@ -106,6 +156,10 @@ def test_ta_transpose(timelined_array_3D):
|
|
|
106
156
|
assert transposed.shape == (75, 25, 50)
|
|
107
157
|
assert transposed.time_dimension == 2
|
|
108
158
|
|
|
159
|
+
transposed = timelined_array_3D.T
|
|
160
|
+
assert transposed.shape == (75, 50, 25)
|
|
161
|
+
assert transposed.time_dimension == 1
|
|
162
|
+
|
|
109
163
|
|
|
110
164
|
def test_ta_swapaxes(timelined_array_3D):
|
|
111
165
|
swapped = timelined_array_3D.swapaxes(1, 2)
|
|
@@ -171,3 +225,43 @@ def test_masked_ta_creation():
|
|
|
171
225
|
def test_seconds_to_index():
|
|
172
226
|
sec = Seconds(10)
|
|
173
227
|
assert sec.to_index(2) == 20
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
def test_timelined_array_from_iterable(timelined_array_3D):
|
|
231
|
+
array = TimelinedArray.align_from_iterable(timelined_array_3D)
|
|
232
|
+
assert np.all(array == timelined_array_3D)
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
def test_rebase_timelined_array(timelined_array_1D):
|
|
236
|
+
|
|
237
|
+
array = timelined_array_1D.rebase_timeline(at=16)
|
|
238
|
+
assert array.timeline[16] == 0
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
def test_offset_timeline(timelined_array_1D):
|
|
242
|
+
array = timelined_array_1D.offset_timeline(offset=84)
|
|
243
|
+
assert array.timeline[22] == (22 + 84)
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
def test_shift_period(timelined_array_1D):
|
|
247
|
+
|
|
248
|
+
with pytest.raises(NotImplementedError):
|
|
249
|
+
array = timelined_array_1D.shift_values(period=slice(8, 10))
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
def test_moveaxis(timelined_array_3D):
|
|
253
|
+
|
|
254
|
+
array = timelined_array_3D.moveaxis(1, 2)
|
|
255
|
+
assert array.time_dimension == 2
|
|
256
|
+
assert array.shape[2] == 50
|
|
257
|
+
|
|
258
|
+
array = timelined_array_3D.moveaxis(0, 2)
|
|
259
|
+
assert array.time_dimension == 0
|
|
260
|
+
assert array.shape[1] == 75
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
def test_pack(timelined_array_1D):
|
|
264
|
+
|
|
265
|
+
timeline, array = timelined_array_1D.pack
|
|
266
|
+
assert timeline is timelined_array_1D.timeline
|
|
267
|
+
assert np.all(array == timelined_array_1D)
|
|
File without changes
|
|
File without changes
|