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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: timelined_array
3
- Version: 0.1.0
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
- ![Python](https://img.shields.io/badge/python-3.11-blue.svg)
16
- [![PyPI version](https://badge.fury.io/py/timelined_array.svg)](https://badge.fury.io/py/timelined_array)
17
- ![Publish Status](https://github.com/JostTim/timelined_array/actions/workflows/publish.yml/badge.svg)
18
- ![Test Status](https://github.com/JostTim/timelined_array/actions/workflows/test.yml/badge.svg)
19
- [![codecov](https://codecov.io/gh/JostTim/timelined_array/branch/main/graph/badge.svg)](https://codecov.io/gh/JostTim/timelined_array)
15
+ ![Python Version from PEP 621 TOML](https://img.shields.io/python/required-version-toml?tomlFilePath=https%3A%2F%2Fraw.githubusercontent.com%2FJostTim%2Ftimelined_array%2Frefs%2Fheads%2Fmain%2Fpyproject.toml)
16
+ ![PyPI - Version](https://img.shields.io/pypi/v/timelined_array)
17
+ ![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/JostTim/timelined_array/publish.yml?label=Publishing)
18
+ ![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/JostTim/timelined_array/test.yml?label=Testing)
19
+ [![Codecov](https://img.shields.io/codecov/c/github/JostTim/timelined_array)](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
- ![Python](https://img.shields.io/badge/python-3.11-blue.svg)
4
- [![PyPI version](https://badge.fury.io/py/timelined_array.svg)](https://badge.fury.io/py/timelined_array)
5
- ![Publish Status](https://github.com/JostTim/timelined_array/actions/workflows/publish.yml/badge.svg)
6
- ![Test Status](https://github.com/JostTim/timelined_array/actions/workflows/test.yml/badge.svg)
7
- [![codecov](https://codecov.io/gh/JostTim/timelined_array/branch/main/graph/badge.svg)](https://codecov.io/gh/JostTim/timelined_array)
3
+ ![Python Version from PEP 621 TOML](https://img.shields.io/python/required-version-toml?tomlFilePath=https%3A%2F%2Fraw.githubusercontent.com%2FJostTim%2Ftimelined_array%2Frefs%2Fheads%2Fmain%2Fpyproject.toml)
4
+ ![PyPI - Version](https://img.shields.io/pypi/v/timelined_array)
5
+ ![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/JostTim/timelined_array/publish.yml?label=Publishing)
6
+ ![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/JostTim/timelined_array/test.yml?label=Testing)
7
+ [![Codecov](https://img.shields.io/codecov/c/github/JostTim/timelined_array)](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.0"
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
@@ -1,3 +1,3 @@
1
- __version__ = "0.1.0"
1
+ __version__ = "0.1.2"
2
2
 
3
3
  from .time import TimelinedArray, MaskedTimelinedArray, Timeline
@@ -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:][:element_nb] # type: ignore
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