timelined_array 0.0.5__tar.gz → 0.0.7__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.5
3
+ Version: 0.0.7
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.5"
13
+ version = "0.0.7"
14
14
 
15
15
  [project.license]
16
16
  text = "MIT"
@@ -1,3 +1,3 @@
1
- __version__ = "0.0.5"
1
+ __version__ = "0.0.7"
2
2
 
3
3
  from .time import TimelinedArray, MaskedTimelinedArray, Seconds, Boundary
@@ -21,7 +21,7 @@ class TimeCompatibleProtocol(Protocol):
21
21
  def __array__(self) -> np.ndarray: ...
22
22
 
23
23
  @property
24
- def shape(self) -> Tuple[int]: ...
24
+ def shape(self) -> Tuple[int, ...]: ...
25
25
 
26
26
  @property
27
27
  def ndim(self) -> int: ...
@@ -347,11 +347,11 @@ class TimeMixin:
347
347
  time_dimension: int
348
348
  timeline: Timeline
349
349
 
350
- def _time_dimension_in_axis(self, axis: int | Tuple[int] | None) -> bool:
350
+ def _time_dimension_in_axis(self, axis: int | Tuple[int, ...] | None) -> bool:
351
351
  """Check if the time dimension is present in the specified axis.
352
352
 
353
353
  Args:
354
- axis (int | Tuple[int] | None): The axis to check for the time dimension.
354
+ axis (int | Tuple[int, ...] | None): The axis to check for the time dimension.
355
355
 
356
356
  Returns:
357
357
  bool: True if the time dimension is present in the axis, False otherwise.
@@ -502,11 +502,11 @@ class TimeMixin:
502
502
 
503
503
  return index, final_timeline, final_time_dimension
504
504
 
505
- def _get_indexed_times(self, index: int | Tuple[int] | slice | Tuple[slice] | List | np.ndarray):
505
+ def _get_indexed_times(self, index: int | Tuple[int, ...] | slice | Tuple[slice] | List | np.ndarray):
506
506
  """Get indexed times based on the provided index.
507
507
 
508
508
  Args:
509
- index (int | Tuple[int] | slice | Tuple[slice] | List | np.ndarray): The index to retrieve times from.
509
+ index (int | Tuple[int, ...] | slice | Tuple[slice] | List | np.ndarray): The index to retrieve times from.
510
510
 
511
511
  Returns:
512
512
  np.ndarray: The indexed times based on the provided index.
@@ -531,12 +531,12 @@ class TimeMixin:
531
531
 
532
532
  return obj.shape == ()
533
533
 
534
- def _finish_axis_removing_operation(self, result: TimeCompatibleProtocol, axis: int | Tuple[int] | None):
534
+ def _finish_axis_removing_operation(self, result: TimeCompatibleProtocol, axis: int | Tuple[int, ...] | None):
535
535
  """Finish axis removing operation.
536
536
 
537
537
  Args:
538
538
  result (TimeCompatibleProtocol): The result of the operation.
539
- axis (int | Tuple[int] | None): The axis or axes to remove.
539
+ axis (int | Tuple[int, ...] | None): The axis or axes to remove.
540
540
 
541
541
  Returns:
542
542
  TimeCompatibleProtocol: The result after finishing the axis removing operation.
@@ -544,7 +544,7 @@ class TimeMixin:
544
544
 
545
545
  if not isinstance(result, np.ndarray):
546
546
  return result
547
- if not self._is_single_element(result):
547
+ if self._is_single_element(result):
548
548
  return result.item()
549
549
  if self._time_dimension_in_axis(axis):
550
550
  return np.asarray(result)
@@ -641,6 +641,40 @@ class TimeMixin:
641
641
 
642
642
  return self.itime[start:][:element_nb] # type: ignore
643
643
 
644
+ def shift_values(
645
+ self,
646
+ period: int | Tuple[int, ...] | slice | Tuple[slice, ...] | List | np.ndarray = 0,
647
+ axis=None,
648
+ time_period=True,
649
+ ):
650
+ """Shifts the values of the array along the specified axis by the given period.
651
+
652
+ Args:
653
+ period (int): The period by which to shift the values.
654
+ axis (int, optional): The axis along which to shift the values. Defaults to None.
655
+ time_period (bool, optional): If True, the shift is applied based on time. Defaults to True.
656
+
657
+ Returns:
658
+ numpy.ndarray: The array with shifted values.
659
+ """
660
+
661
+ if axis is None:
662
+ axis = self.time_dimension
663
+
664
+ indexer = []
665
+ for dim in range(len(self.shape)):
666
+ if dim == axis:
667
+ # make a new axis to account fo the axis loss of the .mean later
668
+ indexer.append(np.newaxis)
669
+ else:
670
+ # select all with slice(None) equivalent to ":"
671
+ indexer.append(slice(None))
672
+ indexer = tuple(indexer)
673
+
674
+ shift_area = self.itime.__getitem__(period) if time_period else self.__getitem__(period)
675
+
676
+ return self - np.repeat(shift_area.mean(axis=axis).__getitem__(tuple(indexer)), self.shape[axis], axis=axis)
677
+
644
678
  def swapaxes(self: TimeCompatibleProtocol, axis1: int, axis2: int):
645
679
  """Swap the two specified axes of the TimelinedArray.
646
680
 
@@ -701,12 +735,12 @@ class TimeMixin:
701
735
 
702
736
  return self.transpose()
703
737
 
704
- def moveaxis(self: TimeCompatibleProtocol, source: int | Tuple[int], destination: int | Tuple[int]):
738
+ def moveaxis(self: TimeCompatibleProtocol, source: int | Tuple[int, ...], destination: int | Tuple[int, ...]):
705
739
  """Move the axis of the array to new positions.
706
740
 
707
741
  Args:
708
- source (int or Tuple[int]): The source position(s) of the axis to move.
709
- destination (int or Tuple[int]): The destination position(s) to move the axis to.
742
+ source (int or Tuple[int, ...]): The source position(s) of the axis to move.
743
+ destination (int or Tuple[int, ...]): The destination position(s) to move the axis to.
710
744
 
711
745
  Returns:
712
746
  TimeCompatibleProtocol: A new array with the axis moved to the specified destination.
@@ -777,11 +811,14 @@ class TimeMixin:
777
811
  # TimelinedArray.time_dimension and TimelinedArray.timeline are set. good to go
778
812
  return rolled_array
779
813
 
780
- def mean(self: TimeCompatibleProtocol, axis: int | Tuple[int] | None = None, dtype=None, out=None, keepdims=False):
814
+ def mean(
815
+ self: TimeCompatibleProtocol, axis: int | Tuple[int, ...] | None = None, dtype=None, out=None, keepdims=False
816
+ ):
781
817
  """Calculates the mean along the specified axis.
782
818
 
783
819
  Args:
784
- axis (int | Tuple[int] | None): Axis or axes along which to perform the mean operation. Default is None.
820
+ axis (int | Tuple[int, ...] | None): Axis or axes along which to perform the mean operation.
821
+ Default is None.
785
822
  dtype: Data-type to use in the computation.
786
823
  out: Output array where the result is stored.
787
824
  keepdims (bool): If True, the reduced dimensions are retained in the output array.
@@ -794,11 +831,13 @@ class TimeMixin:
794
831
  return self._finish_axis_removing_operation(result, axis)
795
832
 
796
833
  # Override other reduction methods similarly if needed
797
- def sum(self: TimeCompatibleProtocol, axis: int | Tuple[int] | None = None, dtype=None, out=None, keepdims=False):
834
+ def sum(
835
+ self: TimeCompatibleProtocol, axis: int | Tuple[int, ...] | None = None, dtype=None, out=None, keepdims=False
836
+ ):
798
837
  """Calculate the sum along the specified axis.
799
838
 
800
839
  Args:
801
- axis (int | Tuple[int] | None): Axis or axes along which a sum is performed.
840
+ axis (int | Tuple[int, ...] | None): Axis or axes along which a sum is performed.
802
841
  The default is to sum over all the dimensions of the input array.
803
842
  dtype: The type of the returned array and of the accumulator in which the elements are summed.
804
843
  If dtype is not specified, it defaults to the dtype of a, unless a has an integer dtype
@@ -818,12 +857,17 @@ class TimeMixin:
818
857
  return self._finish_axis_removing_operation(result, axis)
819
858
 
820
859
  def std(
821
- self: TimeCompatibleProtocol, axis: int | Tuple[int] | None = None, dtype=None, out=None, ddof=0, keepdims=False
860
+ self: TimeCompatibleProtocol,
861
+ axis: int | Tuple[int, ...] | None = None,
862
+ dtype=None,
863
+ out=None,
864
+ ddof=0,
865
+ keepdims=False,
822
866
  ):
823
867
  """Calculate the standard deviation along the specified axis.
824
868
 
825
869
  Args:
826
- axis (int or Tuple[int] or None): Axis or axes along which the standard deviation is computed.
870
+ axis (int or Tuple[int, ...] or None): Axis or axes along which the standard deviation is computed.
827
871
  The default is to compute the standard deviation of the flattened array.
828
872
  dtype: Data-type of the result. If not provided, the data-type of the input is used.
829
873
  out: Output array with the same shape as input array, placed with the result.
@@ -841,13 +885,18 @@ class TimeMixin:
841
885
  return self._finish_axis_removing_operation(result, axis)
842
886
 
843
887
  def var(
844
- self: TimeCompatibleProtocol, axis: int | Tuple[int] | None = None, dtype=None, out=None, ddof=0, keepdims=False
888
+ self: TimeCompatibleProtocol,
889
+ axis: int | Tuple[int, ...] | None = None,
890
+ dtype=None,
891
+ out=None,
892
+ ddof=0,
893
+ keepdims=False,
845
894
  ):
846
895
  """Calculate the variance along the specified axis.
847
896
 
848
897
  Args:
849
898
  self (TimeCompatibleProtocol): The input data.
850
- axis (int | Tuple[int] | None): Axis or axes along which the variance is computed.
899
+ axis (int | Tuple[int, ...] | None): Axis or axes along which the variance is computed.
851
900
  The default is to compute the variance of the flattened array.
852
901
  dtype: Data-type of the result. If not provided, the data-type of the input is used.
853
902
  out: Alternative output array in which to place the result.
@@ -958,7 +1007,10 @@ class TimeMixin:
958
1007
  # +1 (a.k.a. shifted one dimension deeper)
959
1008
 
960
1009
  for element in data:
961
- time_dimension = getattr(element, "time_dimension", None) + 1
1010
+ time_dimension = getattr(element, "time_dimension", None)
1011
+ if time_dimension is None:
1012
+ break
1013
+ time_dimension = time_dimension + 1
962
1014
  _unpacking = True
963
1015
  break
964
1016
  else:
@@ -1114,12 +1166,12 @@ class TimelinedArray(TimeMixin, np.ndarray, TimeCompatibleProtocol):
1114
1166
  return super().__array_function__(func, types, args, kwargs)
1115
1167
 
1116
1168
  def __getitem__(
1117
- self, index: int | Tuple[int] | slice | Tuple[slice] | List | np.ndarray
1169
+ self, index: int | Tuple[int, ...] | slice | Tuple[slice, ...] | List | np.ndarray
1118
1170
  ) -> "TimelinedArray | np.ndarray":
1119
1171
  """Get item from TimelinedArray based on index or slice.
1120
1172
 
1121
1173
  Args:
1122
- index (int | Tuple[int] | slice | Tuple[slice] | List | np.ndarray): Index or slice to retrieve item.
1174
+ index (int | Tuple[int, ...] | slice | Tuple[slice] | List | np.ndarray): Index or slice to retrieve item.
1123
1175
 
1124
1176
  Returns:
1125
1177
  TimelinedArray | np.ndarray: Indexed result based on the provided index.
@@ -1145,13 +1197,14 @@ class TimelinedArray(TimeMixin, np.ndarray, TimeCompatibleProtocol):
1145
1197
  def __repr__(self):
1146
1198
  """Return a string representation of the object with the class name and the array representation."""
1147
1199
 
1148
- return type(self).__name__ + np.array(self).__repr__()[5:]
1200
+ # [5:] serves to remove the 'array' part for the original array repr string
1201
+ return type(self).__name__ + np.asarray(self).__repr__()[5:]
1149
1202
 
1150
1203
  def __str__(self):
1151
1204
  """Return a string representation of the object by concatenating the class name with the string
1152
1205
  representation of the object as a NumPy array."""
1153
1206
 
1154
- return type(self).__name__ + np.array(self).__str__()
1207
+ return type(self).__name__ + np.asarray(self).__str__()
1155
1208
 
1156
1209
  @staticmethod
1157
1210
  def align_from_iterable(iterable) -> "TimelinedArray":
@@ -1249,12 +1302,12 @@ class MaskedTimelinedArray(TimeMixin, np.ma.MaskedArray, TimeCompatibleProtocol)
1249
1302
  self.time_dimension = getattr(obj, "time_dimension", 0)
1250
1303
 
1251
1304
  def __getitem__(
1252
- self, index: int | Tuple[int] | slice | Tuple[slice] | List | np.ndarray
1305
+ self, index: int | Tuple[int, ...] | slice | Tuple[slice] | List | np.ndarray
1253
1306
  ) -> "MaskedTimelinedArray | np.ma.MaskedArray":
1254
1307
  """Get item from the MaskedTimelinedArray based on the provided index.
1255
1308
 
1256
1309
  Args:
1257
- index (int | Tuple[int] | slice | Tuple[slice] | List | np.ndarray): The index or slice to retrieve.
1310
+ index (int | Tuple[int, ...] | slice | Tuple[slice] | List | np.ndarray): The index or slice to retrieve.
1258
1311
 
1259
1312
  Returns:
1260
1313
  MaskedTimelinedArray | np.ma.MaskedArray: The masked array or MaskedTimelinedArray based on the index.
File without changes