pymodaq_data 5.2.7__tar.gz → 5.2.9__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.
Files changed (33) hide show
  1. {pymodaq_data-5.2.7 → pymodaq_data-5.2.9}/PKG-INFO +2 -2
  2. {pymodaq_data-5.2.7 → pymodaq_data-5.2.9}/src/pymodaq_data/data.py +27 -4
  3. {pymodaq_data-5.2.7 → pymodaq_data-5.2.9}/src/pymodaq_data/h5modules/data_saving.py +59 -5
  4. {pymodaq_data-5.2.7 → pymodaq_data-5.2.9}/src/pymodaq_data/post_treatment/process_to_scalar.py +20 -4
  5. {pymodaq_data-5.2.7 → pymodaq_data-5.2.9}/.gitignore +0 -0
  6. {pymodaq_data-5.2.7 → pymodaq_data-5.2.9}/LICENSE +0 -0
  7. {pymodaq_data-5.2.7 → pymodaq_data-5.2.9}/README.rst +0 -0
  8. {pymodaq_data-5.2.7 → pymodaq_data-5.2.9}/pyproject.toml +0 -0
  9. {pymodaq_data-5.2.7 → pymodaq_data-5.2.9}/src/pymodaq_data/__init__.py +0 -0
  10. {pymodaq_data-5.2.7 → pymodaq_data-5.2.9}/src/pymodaq_data/config.py +0 -0
  11. {pymodaq_data-5.2.7 → pymodaq_data-5.2.9}/src/pymodaq_data/h5modules/__init__.py +0 -0
  12. {pymodaq_data-5.2.7 → pymodaq_data-5.2.9}/src/pymodaq_data/h5modules/backends.py +0 -0
  13. {pymodaq_data-5.2.7 → pymodaq_data-5.2.9}/src/pymodaq_data/h5modules/browsing.py +0 -0
  14. {pymodaq_data-5.2.7 → pymodaq_data-5.2.9}/src/pymodaq_data/h5modules/exporter.py +0 -0
  15. {pymodaq_data-5.2.7 → pymodaq_data-5.2.9}/src/pymodaq_data/h5modules/exporters/__init__.py +0 -0
  16. {pymodaq_data-5.2.7 → pymodaq_data-5.2.9}/src/pymodaq_data/h5modules/exporters/base.py +0 -0
  17. {pymodaq_data-5.2.7 → pymodaq_data-5.2.9}/src/pymodaq_data/h5modules/exporters/flimj.py +0 -0
  18. {pymodaq_data-5.2.7 → pymodaq_data-5.2.9}/src/pymodaq_data/h5modules/exporters/hyperspy.py +0 -0
  19. {pymodaq_data-5.2.7 → pymodaq_data-5.2.9}/src/pymodaq_data/h5modules/saving.py +0 -0
  20. {pymodaq_data-5.2.7 → pymodaq_data-5.2.9}/src/pymodaq_data/h5modules/swmr.py +0 -0
  21. {pymodaq_data-5.2.7 → pymodaq_data-5.2.9}/src/pymodaq_data/h5modules/utils.py +0 -0
  22. {pymodaq_data-5.2.7 → pymodaq_data-5.2.9}/src/pymodaq_data/icon.ico +0 -0
  23. {pymodaq_data-5.2.7 → pymodaq_data-5.2.9}/src/pymodaq_data/numpy_func.py +0 -0
  24. {pymodaq_data-5.2.7 → pymodaq_data-5.2.9}/src/pymodaq_data/plotting/__init__.py +0 -0
  25. {pymodaq_data-5.2.7 → pymodaq_data-5.2.9}/src/pymodaq_data/plotting/plotter/plotter.py +0 -0
  26. {pymodaq_data-5.2.7 → pymodaq_data-5.2.9}/src/pymodaq_data/plotting/plotter/plotters/__init__.py +0 -0
  27. {pymodaq_data-5.2.7 → pymodaq_data-5.2.9}/src/pymodaq_data/plotting/plotter/plotters/matplotlib_plotters.py +0 -0
  28. {pymodaq_data-5.2.7 → pymodaq_data-5.2.9}/src/pymodaq_data/plotting/utils.py +0 -0
  29. {pymodaq_data-5.2.7 → pymodaq_data-5.2.9}/src/pymodaq_data/post_treatment/__init__.py +0 -0
  30. {pymodaq_data-5.2.7 → pymodaq_data-5.2.9}/src/pymodaq_data/resources/__init__.py +0 -0
  31. {pymodaq_data-5.2.7 → pymodaq_data-5.2.9}/src/pymodaq_data/resources/config_template.toml +0 -0
  32. {pymodaq_data-5.2.7 → pymodaq_data-5.2.9}/src/pymodaq_data/slicing.py +0 -0
  33. {pymodaq_data-5.2.7 → pymodaq_data-5.2.9}/src/pymodaq_data/splash.png +0 -0
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.4
1
+ Metadata-Version: 2.5
2
2
  Name: pymodaq_data
3
- Version: 5.2.7
3
+ Version: 5.2.9
4
4
  Summary: Modular Data Acquisition with Python
5
5
  Project-URL: Homepage, http://pymodaq.cnrs.fr
6
6
  Project-URL: Source, https://github.com/PyMoDAQ/PyMoDAQ
@@ -949,8 +949,12 @@ class DataBase(DataLowLevel, NDArrayOperatorsMixin):
949
949
  if isinstance(epsilon, numbers.Number):
950
950
  epsilon = Q_(epsilon, self.units)
951
951
  try:
952
+ # using below epsilon - Q_(0, self.units) to handle units with offset/scaling like
953
+ # °C and °F where the diff produce a derived unit (delta_degree_Celsius) that do
954
+ # not compare well to epsilon itself. While epsilon - Q_(0, self.units) is not changing
955
+ # the value but produce similar delta units!
952
956
  return bool(np.all([np.abs(self.quantities[ind] - other.quantities[ind])
953
- <= epsilon for ind in range(len(self))]))
957
+ <= (epsilon - Q_(0, self.units)) for ind in range(len(self))]))
954
958
  except pint.errors.DimensionalityError as e:
955
959
  return False
956
960
 
@@ -2795,6 +2799,10 @@ class DataWithAxes(DataBase, SerializableBase):
2795
2799
 
2796
2800
  do_squeeze = self.check_squeeze(total_slices, is_navigation)
2797
2801
  new_arrays_data = [squeeze(dat[total_slices], do_squeeze) for dat in self.data]
2802
+ if self.errors is not None:
2803
+ new_errors_data = [squeeze(dat[total_slices], do_squeeze) for dat in self.errors]
2804
+ else:
2805
+ new_errors_data = None
2798
2806
  tmp_axes = self._am.get_signal_axes() if is_navigation else self._am.get_nav_axes()
2799
2807
  axes_to_append = [copy.deepcopy(axis) for axis in tmp_axes]
2800
2808
 
@@ -2843,17 +2851,22 @@ class DataWithAxes(DataBase, SerializableBase):
2843
2851
  else:
2844
2852
  distribution = DataDistribution.uniform
2845
2853
 
2846
- data = DataWithAxes(self.name, data=new_arrays_data, nav_indexes=tuple(nav_indexes),
2854
+ data = DataWithAxes(self.name,
2855
+ data=new_arrays_data,
2856
+ errors=new_errors_data,
2857
+ nav_indexes=tuple(nav_indexes),
2847
2858
  axes=axes,
2848
2859
  source=DataSource.calculated, origin=self.origin,
2849
2860
  labels=self.labels[:],
2850
2861
  distribution=distribution)
2851
2862
  return data
2852
2863
 
2853
- def deepcopy_with_new_data(self, data: List[np.ndarray] = None,
2864
+ def deepcopy_with_new_data(self,
2865
+ data: List[np.ndarray] = None,
2854
2866
  remove_axes_index: Union[int, List[int]] = None,
2855
2867
  source: DataSource = DataSource.calculated,
2856
- keep_dim=False) -> DataWithAxes:
2868
+ keep_dim=False,
2869
+ errors: List[np.ndarray] = None,) -> DataWithAxes:
2857
2870
  """deepcopy without copying the initial data (saving memory)
2858
2871
 
2859
2872
  The new data, may have some axes stripped as specified in remove_axes_index
@@ -2868,16 +2881,26 @@ class DataWithAxes(DataBase, SerializableBase):
2868
2881
  keep_dim: bool
2869
2882
  if False (the default) will calculate the new dim based on the data shape
2870
2883
  else keep the same (be aware it could lead to issues)
2884
+ errors: list of numpy ndarray
2885
+ The new errors corresponding to the new data
2871
2886
 
2872
2887
  Returns
2873
2888
  -------
2874
2889
  DataWithAxes
2875
2890
  """
2891
+ def check_errors(data: list[np.ndarray], errors: list[np.ndarray]) -> bool:
2892
+ for data_array, error_array in zip(data, errors):
2893
+ if data_array.shape != error_array.shape:
2894
+ return False
2895
+ return True
2876
2896
  try:
2897
+ if errors is not None and check_errors(data, errors):
2898
+ errors = None
2877
2899
  old_data = self.data
2878
2900
  self._data = None
2879
2901
  new_data = self.deepcopy()
2880
2902
  new_data._data = data
2903
+ new_data.errors = errors
2881
2904
  new_data.get_dim_from_data(data)
2882
2905
 
2883
2906
  if source is not None:
@@ -441,7 +441,11 @@ class DataSaverLoader(DataManagement):
441
441
  parent_node = data_node.parent_node
442
442
  data_nodes = self._get_nodes_from_data_type(parent_node)
443
443
  data_node = data_nodes[0]
444
- error_node = data_node
444
+ error_nodes = self._error_saver._get_nodes_from_data_type(parent_node)
445
+ if len(error_nodes) > 0:
446
+ error_node = error_nodes[0]
447
+ else:
448
+ error_node = None
445
449
  else:
446
450
  parent_node = data_node.parent_node
447
451
  if not isinstance(data_node, CARRAY):
@@ -463,7 +467,7 @@ class DataSaverLoader(DataManagement):
463
467
  else:
464
468
  ndarrays = self.get_data_arrays(data_node, with_bkg=with_bkg, load_all=load_all)
465
469
  axes = self.get_axes(parent_node)
466
- if error_node is not None:
470
+ if error_node is not None and self.data_type != DataType.error:
467
471
  error_arrays = self._error_saver.get_data_arrays(error_node, load_all=load_all)
468
472
  if len(error_arrays) == 0:
469
473
  error_arrays = None
@@ -591,7 +595,9 @@ class DataEnlargeableSaver(DataSaverLoader):
591
595
  nav_indexes = ([0] +
592
596
  list(np.array(nav_indexes, dtype=int) + 1))
593
597
 
594
- self._h5saver.add_array(where, self._get_next_node_name(where), self.data_type,
598
+ self._h5saver.add_array(where,
599
+ self._get_next_node_name(where),
600
+ self.data_type,
595
601
  title=data.name,
596
602
  array_to_save=data[ind_data],
597
603
  data_shape=data[ind_data].shape,
@@ -604,6 +610,24 @@ class DataEnlargeableSaver(DataSaverLoader):
604
610
  distribution='spread',
605
611
  origin=data.origin,
606
612
  nav_indexes=tuple(nav_indexes)))
613
+ if data.errors is not None:
614
+ error_dwa = data.errors_as_dwa()
615
+ self._h5saver.add_array(where,
616
+ self._error_saver._get_next_node_name(where),
617
+ self._error_saver.data_type,
618
+ title=error_dwa.name,
619
+ array_to_save=error_dwa[ind_data],
620
+ data_shape=error_dwa[ind_data].shape,
621
+ array_type=error_dwa[ind_data].dtype,
622
+ enlargeable=True,
623
+ data_dimension=error_dwa.dim.name,
624
+ metadata=dict(timestamp=error_dwa.timestamp,
625
+ label=error_dwa.labels[ind_data],
626
+ source=error_dwa.source.name,
627
+ distribution='spread',
628
+ origin=error_dwa.origin,
629
+ nav_indexes=tuple(nav_indexes)))
630
+
607
631
  if add_enl_axes:
608
632
  for ind_enl_axis in range(self._n_enl_axes):
609
633
  self._axis_saver.add_axis(where,
@@ -661,6 +685,12 @@ class DataEnlargeableSaver(DataSaverLoader):
661
685
  for ind_data in range(len(data)):
662
686
  array: EARRAY = self.get_node_from_index(where, ind_data)
663
687
  array.append(data[ind_data])
688
+
689
+ if data.errors is not None:
690
+ error_array: EARRAY = self._error_saver.get_node_from_index(where, ind_data)
691
+ error_array.append(data.errors[ind_data])
692
+
693
+
664
694
  if add_enl_axes:
665
695
  for ind_axis in range(self._n_enl_axes):
666
696
  axis_array: EARRAY = self._axis_saver.get_node_from_index(where, ind_axis)
@@ -715,7 +745,10 @@ class DataExtendedSaver(DataSaverLoader):
715
745
  nav_indexes = [ind for ind in range(len(self.extended_shape))] +\
716
746
  list(np.array(nav_indexes, dtype=int) + len(self.extended_shape))
717
747
 
718
- self._h5saver.add_array(where, self._get_next_node_name(where), self.data_type, title=data.name,
748
+ self._h5saver.add_array(where,
749
+ self._get_next_node_name(where),
750
+ self.data_type,
751
+ title=data.name,
719
752
  data_shape=data[ind_data].shape,
720
753
  array_type=data[ind_data].dtype,
721
754
  fill_value=self.fill_value,
@@ -727,6 +760,24 @@ class DataExtendedSaver(DataSaverLoader):
727
760
  origin=data.origin,
728
761
  nav_indexes=tuple(nav_indexes)))
729
762
 
763
+ if data.errors is not None:
764
+ error_dwa = data.errors_as_dwa()
765
+ self._h5saver.add_array(where,
766
+ self._error_saver._get_next_node_name(where),
767
+ self._error_saver.data_type,
768
+ title=error_dwa.name,
769
+ data_shape=error_dwa[ind_data].shape,
770
+ array_type=error_dwa[ind_data].dtype,
771
+ fill_value=self.fill_value,
772
+ scan_shape=self.extended_shape,
773
+ add_scan_dim=True,
774
+ data_dimension=error_dwa.dim.name,
775
+ metadata=dict(timestamp=error_dwa.timestamp, label=error_dwa.labels[ind_data],
776
+ source=error_dwa.source.name, distribution=distribution.name,
777
+ origin=error_dwa.origin,
778
+ nav_indexes=tuple(nav_indexes)))
779
+
780
+
730
781
  if save_axes:
731
782
  for axis in data.axes:
732
783
  axis.index += len(self.extended_shape)
@@ -756,10 +807,13 @@ class DataExtendedSaver(DataSaverLoader):
756
807
  self._create_data_arrays(where, data, save_axes=True, distribution=distribution)
757
808
 
758
809
  for ind_data in range(len(data)):
759
- #todo check that getting with index is safe...
810
+
760
811
  array: CARRAY = self.get_node_from_index(where, ind_data)
761
812
  array[tuple(indexes)] = data[ind_data]
762
813
  # maybe use array.__setitem__(indexes, data[ind_data]) if it's not working
814
+ if data.errors is not None:
815
+ error_array: CARRAY = self._error_saver.get_node_from_index(where, ind_data)
816
+ error_array[tuple(indexes)] = data.errors[ind_data]
763
817
 
764
818
 
765
819
  class DataToExportSaver:
@@ -84,7 +84,11 @@ class StdProcessor(DataProcessorBase):
84
84
 
85
85
  def operate(self, sub_data: DataWithAxes):
86
86
  data_arrays = [np.atleast_1d(np.std(data, axis=sub_data.sig_indexes)) for data in sub_data]
87
- return sub_data.deepcopy_with_new_data(data_arrays, sub_data.sig_indexes)
87
+ if sub_data.errors is not None:
88
+ error_arrays = [np.atleast_1d(np.std(data, axis=sub_data.sig_indexes)) for data in sub_data.errors]
89
+ else:
90
+ error_arrays = None
91
+ return sub_data.deepcopy_with_new_data(data_arrays, sub_data.sig_indexes, errors=error_arrays)
88
92
 
89
93
 
90
94
  @DataProcessorFactory.register('sum')
@@ -93,7 +97,11 @@ class SumProcessor(DataProcessorBase):
93
97
 
94
98
  def operate(self, sub_data: DataWithAxes):
95
99
  data_arrays = [np.atleast_1d(np.sum(data, axis=sub_data.sig_indexes)) for data in sub_data]
96
- return sub_data.deepcopy_with_new_data(data_arrays, sub_data.sig_indexes)
100
+ if sub_data.errors is not None:
101
+ error_arrays = [np.atleast_1d(np.sum(data, axis=sub_data.sig_indexes)) for data in sub_data.errors]
102
+ else:
103
+ error_arrays = None
104
+ return sub_data.deepcopy_with_new_data(data_arrays, sub_data.sig_indexes, errors=error_arrays)
97
105
 
98
106
 
99
107
  @DataProcessorFactory.register('max')
@@ -102,7 +110,11 @@ class MaxProcessor(DataProcessorBase):
102
110
 
103
111
  def operate(self, sub_data: DataWithAxes):
104
112
  data_arrays = [np.atleast_1d(np.max(data, axis=sub_data.sig_indexes)) for data in sub_data]
105
- return sub_data.deepcopy_with_new_data(data_arrays, sub_data.sig_indexes)
113
+ if sub_data.errors is not None:
114
+ error_arrays = [np.atleast_1d(np.max(data, axis=sub_data.sig_indexes)) for data in sub_data.errors]
115
+ else:
116
+ error_arrays = None
117
+ return sub_data.deepcopy_with_new_data(data_arrays, sub_data.sig_indexes, errors=error_arrays)
106
118
 
107
119
 
108
120
  @DataProcessorFactory.register('min')
@@ -111,7 +123,11 @@ class MinProcessor(DataProcessorBase):
111
123
 
112
124
  def operate(self, sub_data: DataWithAxes):
113
125
  data_arrays = [np.atleast_1d(np.min(data, axis=sub_data.sig_indexes)) for data in sub_data]
114
- return sub_data.deepcopy_with_new_data(data_arrays, sub_data.sig_indexes)
126
+ if sub_data.errors is not None:
127
+ error_arrays = [np.atleast_1d(np.min(data, axis=sub_data.sig_indexes)) for data in sub_data.errors]
128
+ else:
129
+ error_arrays = None
130
+ return sub_data.deepcopy_with_new_data(data_arrays, sub_data.sig_indexes, errors=error_arrays)
115
131
 
116
132
 
117
133
  @DataProcessorFactory.register('argmax')
File without changes
File without changes
File without changes