timelined_array 0.0.8__tar.gz → 0.0.10__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.0.8
3
+ Version: 0.0.10
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 <timothe.jost@wanadoo.fr>
6
6
  License: MIT
@@ -10,7 +10,7 @@ dependencies = [
10
10
  requires-python = ">=3.11"
11
11
  readme = "README.md"
12
12
  dynamic = []
13
- version = "0.0.8"
13
+ version = "0.0.10"
14
14
 
15
15
  [project.license]
16
16
  text = "MIT"
@@ -0,0 +1,3 @@
1
+ __version__ = "0.0.10"
2
+
3
+ from .time import TimelinedArray, MaskedTimelinedArray
@@ -2,10 +2,13 @@
2
2
 
3
3
  import numpy as np
4
4
  from logging import getLogger
5
- from typing import Tuple, List, Protocol, Type
6
5
  from enum import Enum
7
6
  import operator
8
7
 
8
+ from typing import Tuple, List, Protocol, Type, Callable, Any
9
+
10
+ OperatorType = Callable[[Any, Any], bool]
11
+
9
12
  # class syntax
10
13
 
11
14
  logger = getLogger("timelined_array")
@@ -149,56 +152,39 @@ class Timeline(np.ndarray):
149
152
  return self._max_step * self.max_step_mult
150
153
 
151
154
 
152
- class Boundary(Enum):
153
- inclusive = 0
154
- exclusive = 1
155
- inc = 0
156
- exc = 1
155
+ class StartBoundary(Enum):
156
+ inclusive = operator.ge
157
+ exclusive = operator.gt
158
+ inc = operator.ge
159
+ exc = operator.gt
157
160
 
158
- @staticmethod
159
- def get_operation(boundary, setting):
160
- """Return the appropriate comparison operator based on the boundary and setting.
161
161
 
162
- Args:
163
- boundary (str): The boundary type, either "start" or "stop".
164
- setting (Boundary): The setting for the boundary, either inclusive or exclusive.
162
+ class StoptBoundary(Enum):
163
+ inclusive = operator.le
164
+ exclusive = operator.lt
165
+ inc = operator.le
166
+ exc = operator.lt
165
167
 
166
- Returns:
167
- function: The comparison operator based on the boundary and setting.
168
168
 
169
- Raises:
170
- ValueError: If the boundary or setting is invalid.
171
- """
172
-
173
- if boundary == "start":
174
- if setting == Boundary.inclusive:
175
- return operator.ge
176
- elif setting == Boundary.exclusive:
177
- return operator.gt
178
- else:
179
- raise ValueError
180
- elif boundary == "stop":
181
- if setting == Boundary.inclusive:
182
- return operator.le
183
- elif setting == Boundary.exclusive:
184
- return operator.lt
185
- else:
186
- raise ValueError
187
- else:
188
- raise ValueError
169
+ class EdgePolicy(Enum):
170
+ start = StartBoundary
171
+ stop = StoptBoundary
189
172
 
190
173
 
191
174
  class TimeIndexer:
192
175
  """The time indexer indexes by default from >= to the time start, and strictly < to time stop"""
193
176
 
194
- start_mode = Boundary.inclusive
195
- stop_mode = Boundary.exclusive
196
-
197
- _start_operation = Boundary.get_operation("start", start_mode)
198
- _stop_operation = Boundary.get_operation("stop", stop_mode)
177
+ _start_operation: OperatorType
178
+ _stop_operation: OperatorType
199
179
 
200
- def __init__(self, array: TimeCompatibleProtocol):
180
+ def __init__(self, array: TimeCompatibleProtocol, start="inclusive", stop="exclusive"):
201
181
  self.array = array
182
+ self.set_edge_policy(start, stop)
183
+
184
+ def set_edge_policy(self, start="inclusive", stop="exclusive"):
185
+ self._start_operation = EdgePolicy["start"].value[start].value
186
+ self._stop_operation = EdgePolicy["stop"].value[stop].value
187
+ return self
202
188
 
203
189
  def time_to_index(
204
190
  self, time: float | int | slice | Tuple[int | float] | List[float | int | slice | Tuple[int | float]]
@@ -229,7 +215,7 @@ class TimeIndexer:
229
215
  elif isinstance(time, (int, float)):
230
216
  return self.get_iindex(sec_start=time).start
231
217
  else:
232
- raise ValueError("Cannot process time to index ")
218
+ raise ValueError("Cannot process time to index")
233
219
 
234
220
  seconds_to_index = time_to_index
235
221
 
@@ -333,17 +319,16 @@ class TimeIndexer:
333
319
  step = 1
334
320
  return slice(start, stop, step)
335
321
 
336
- def __call__(self, start=None, stop=None):
337
- if start is not None:
338
- self._start_operation = Boundary.get_operation("start", start)
339
- if stop is not None:
340
- self._stop_operation = Boundary.get_operation("stop", stop)
322
+ def __call__(self, start="inclusive", stop="exclusive"):
323
+ return self.set_edge_policy(start, stop)
341
324
 
342
325
 
343
326
  class TimeMixin:
344
327
 
345
328
  time_dimension: int
346
329
  timeline: Timeline
330
+ start_policy = "inclusive"
331
+ stop_policy = "exclusive"
347
332
 
348
333
  def _time_dimension_in_axis(self, axis: int | Tuple[int, ...] | None) -> bool:
349
334
  """Check if the time dimension is present in the specified axis.
@@ -622,7 +607,7 @@ class TimeMixin:
622
607
  def itime(self: TimeCompatibleProtocol):
623
608
  """Return a TimeIndexer object based on the given TimeCompatibleProtocol object."""
624
609
 
625
- return TimeIndexer(self)
610
+ return TimeIndexer(self, self.start_policy, self.stop_policy)
626
611
 
627
612
  isec = itime
628
613
 
@@ -1184,7 +1169,7 @@ class TimelinedArray(TimeMixin, np.ndarray, TimeCompatibleProtocol):
1184
1169
  index, final_timeline, final_time_dimension = self._get_indexed_times(index)
1185
1170
 
1186
1171
  if final_timeline is None or final_time_dimension is None:
1187
- return np.array(self).__getitem__(index)
1172
+ return np.asarray(self).__getitem__(index)
1188
1173
 
1189
1174
  indexed_result = super().__getitem__(index)
1190
1175
 
@@ -1,3 +0,0 @@
1
- __version__ = "0.0.8"
2
-
3
- from .time import TimelinedArray, MaskedTimelinedArray, Seconds, Boundary