pymodaq_data 5.2.10__tar.gz → 5.3.0a0__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.10 → pymodaq_data-5.3.0a0}/PKG-INFO +12 -12
  2. {pymodaq_data-5.2.10 → pymodaq_data-5.3.0a0}/README.rst +11 -11
  3. {pymodaq_data-5.2.10 → pymodaq_data-5.3.0a0}/src/pymodaq_data/data.py +30 -8
  4. {pymodaq_data-5.2.10 → pymodaq_data-5.3.0a0}/src/pymodaq_data/h5modules/backends.py +45 -7
  5. {pymodaq_data-5.2.10 → pymodaq_data-5.3.0a0}/src/pymodaq_data/h5modules/data_saving.py +42 -15
  6. {pymodaq_data-5.2.10 → pymodaq_data-5.3.0a0}/src/pymodaq_data/h5modules/saving.py +21 -5
  7. {pymodaq_data-5.2.10 → pymodaq_data-5.3.0a0}/src/pymodaq_data/plotting/plotter/plotters/matplotlib_plotters.py +14 -3
  8. {pymodaq_data-5.2.10 → pymodaq_data-5.3.0a0}/src/pymodaq_data/plotting/utils.py +2 -1
  9. {pymodaq_data-5.2.10 → pymodaq_data-5.3.0a0}/src/pymodaq_data/resources/config_template.toml +1 -0
  10. {pymodaq_data-5.2.10 → pymodaq_data-5.3.0a0}/.gitignore +0 -0
  11. {pymodaq_data-5.2.10 → pymodaq_data-5.3.0a0}/LICENSE +0 -0
  12. {pymodaq_data-5.2.10 → pymodaq_data-5.3.0a0}/pyproject.toml +0 -0
  13. {pymodaq_data-5.2.10 → pymodaq_data-5.3.0a0}/src/pymodaq_data/__init__.py +0 -0
  14. {pymodaq_data-5.2.10 → pymodaq_data-5.3.0a0}/src/pymodaq_data/config.py +0 -0
  15. {pymodaq_data-5.2.10 → pymodaq_data-5.3.0a0}/src/pymodaq_data/h5modules/__init__.py +0 -0
  16. {pymodaq_data-5.2.10 → pymodaq_data-5.3.0a0}/src/pymodaq_data/h5modules/browsing.py +0 -0
  17. {pymodaq_data-5.2.10 → pymodaq_data-5.3.0a0}/src/pymodaq_data/h5modules/exporter.py +0 -0
  18. {pymodaq_data-5.2.10 → pymodaq_data-5.3.0a0}/src/pymodaq_data/h5modules/exporters/__init__.py +0 -0
  19. {pymodaq_data-5.2.10 → pymodaq_data-5.3.0a0}/src/pymodaq_data/h5modules/exporters/base.py +0 -0
  20. {pymodaq_data-5.2.10 → pymodaq_data-5.3.0a0}/src/pymodaq_data/h5modules/exporters/flimj.py +0 -0
  21. {pymodaq_data-5.2.10 → pymodaq_data-5.3.0a0}/src/pymodaq_data/h5modules/exporters/hyperspy.py +0 -0
  22. {pymodaq_data-5.2.10 → pymodaq_data-5.3.0a0}/src/pymodaq_data/h5modules/swmr.py +0 -0
  23. {pymodaq_data-5.2.10 → pymodaq_data-5.3.0a0}/src/pymodaq_data/h5modules/utils.py +0 -0
  24. {pymodaq_data-5.2.10 → pymodaq_data-5.3.0a0}/src/pymodaq_data/icon.ico +0 -0
  25. {pymodaq_data-5.2.10 → pymodaq_data-5.3.0a0}/src/pymodaq_data/numpy_func.py +0 -0
  26. {pymodaq_data-5.2.10 → pymodaq_data-5.3.0a0}/src/pymodaq_data/plotting/__init__.py +0 -0
  27. {pymodaq_data-5.2.10 → pymodaq_data-5.3.0a0}/src/pymodaq_data/plotting/plotter/plotter.py +0 -0
  28. {pymodaq_data-5.2.10 → pymodaq_data-5.3.0a0}/src/pymodaq_data/plotting/plotter/plotters/__init__.py +0 -0
  29. {pymodaq_data-5.2.10 → pymodaq_data-5.3.0a0}/src/pymodaq_data/post_treatment/__init__.py +0 -0
  30. {pymodaq_data-5.2.10 → pymodaq_data-5.3.0a0}/src/pymodaq_data/post_treatment/process_to_scalar.py +0 -0
  31. {pymodaq_data-5.2.10 → pymodaq_data-5.3.0a0}/src/pymodaq_data/resources/__init__.py +0 -0
  32. {pymodaq_data-5.2.10 → pymodaq_data-5.3.0a0}/src/pymodaq_data/slicing.py +0 -0
  33. {pymodaq_data-5.2.10 → pymodaq_data-5.3.0a0}/src/pymodaq_data/splash.png +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: pymodaq_data
3
- Version: 5.2.10
3
+ Version: 5.3.0a0
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
@@ -71,11 +71,11 @@ PyMoDAQ Data
71
71
  :target: https://pypi.org/project/pymodaq_data/
72
72
  :alt: Latest Version
73
73
 
74
- .. image:: https://readthedocs.org/projects/pymodaq/badge/?version=malik-irain-patch-2
75
- :target: https://pymodaq.readthedocs.io/en/stable/?badge=malik-irain-patch-2
74
+ .. image:: https://readthedocs.org/projects/pymodaq/badge/?version=state-machine-simplify
75
+ :target: https://pymodaq.readthedocs.io/en/stable/?badge=state-machine-simplify
76
76
  :alt: Documentation Status
77
77
 
78
- .. image:: https://codecov.io/gh/PyMoDAQ/PyMoDAQ/branch/malik-irain-patch-2/graph/badge.svg?token=IQNJRCQDM2
78
+ .. image:: https://codecov.io/gh/PyMoDAQ/PyMoDAQ/branch/state-machine-simplify/graph/badge.svg?token=IQNJRCQDM2
79
79
  :target: https://codecov.io/gh/PyMoDAQ/PyMoDAQ
80
80
 
81
81
  +-------------+-------------+---------------+
@@ -94,28 +94,28 @@ PyMoDAQ Data
94
94
 
95
95
 
96
96
 
97
- .. |310-linux| image:: https://raw.githubusercontent.com/PyMoDAQ/PyMoDAQ/badges/pymodaq_data/malik-irain-patch-2/tests_Linux_3.10.svg
97
+ .. |310-linux| image:: https://raw.githubusercontent.com/PyMoDAQ/PyMoDAQ/badges/pymodaq_data/state-machine-simplify/tests_Linux_3.10.svg
98
98
  :target: https://github.com/PyMoDAQ/PyMoDAQ/actions/workflows/tests-data.yml
99
99
 
100
- .. |311-linux| image:: https://raw.githubusercontent.com/PyMoDAQ/PyMoDAQ/badges/pymodaq_data/malik-irain-patch-2/tests_Linux_3.11.svg
100
+ .. |311-linux| image:: https://raw.githubusercontent.com/PyMoDAQ/PyMoDAQ/badges/pymodaq_data/state-machine-simplify/tests_Linux_3.11.svg
101
101
  :target: https://github.com/PyMoDAQ/PyMoDAQ/actions/workflows/tests-data.yml
102
102
 
103
- .. |312-linux| image:: https://raw.githubusercontent.com/PyMoDAQ/PyMoDAQ/badges/pymodaq_data/malik-irain-patch-2/tests_Linux_3.12.svg
103
+ .. |312-linux| image:: https://raw.githubusercontent.com/PyMoDAQ/PyMoDAQ/badges/pymodaq_data/state-machine-simplify/tests_Linux_3.12.svg
104
104
  :target: https://github.com/PyMoDAQ/PyMoDAQ/actions/workflows/tests-data.yml
105
105
 
106
- .. |313-linux| image:: https://raw.githubusercontent.com/PyMoDAQ/PyMoDAQ/badges/pymodaq_data/malik-irain-patch-2/tests_Linux_3.13.svg
106
+ .. |313-linux| image:: https://raw.githubusercontent.com/PyMoDAQ/PyMoDAQ/badges/pymodaq_data/state-machine-simplify/tests_Linux_3.13.svg
107
107
  :target: https://github.com/PyMoDAQ/PyMoDAQ/actions/workflows/tests-data.yml
108
108
 
109
- .. |310-windows| image:: https://raw.githubusercontent.com/PyMoDAQ/PyMoDAQ/badges/pymodaq_data/malik-irain-patch-2/tests_Windows_3.10.svg
109
+ .. |310-windows| image:: https://raw.githubusercontent.com/PyMoDAQ/PyMoDAQ/badges/pymodaq_data/state-machine-simplify/tests_Windows_3.10.svg
110
110
  :target: https://github.com/PyMoDAQ/PyMoDAQ/actions/workflows/tests-data.yml
111
111
 
112
- .. |311-windows| image:: https://raw.githubusercontent.com/PyMoDAQ/PyMoDAQ/badges/pymodaq_data/malik-irain-patch-2/tests_Windows_3.11.svg
112
+ .. |311-windows| image:: https://raw.githubusercontent.com/PyMoDAQ/PyMoDAQ/badges/pymodaq_data/state-machine-simplify/tests_Windows_3.11.svg
113
113
  :target: https://github.com/PyMoDAQ/PyMoDAQ/actions/workflows/tests-data.yml
114
114
 
115
- .. |312-windows| image:: https://raw.githubusercontent.com/PyMoDAQ/PyMoDAQ/badges/pymodaq_data/malik-irain-patch-2/tests_Windows_3.12.svg
115
+ .. |312-windows| image:: https://raw.githubusercontent.com/PyMoDAQ/PyMoDAQ/badges/pymodaq_data/state-machine-simplify/tests_Windows_3.12.svg
116
116
  :target: https://github.com/PyMoDAQ/PyMoDAQ/actions/workflows/tests-data.yml
117
117
 
118
- .. |313-windows| image:: https://raw.githubusercontent.com/PyMoDAQ/PyMoDAQ/badges/pymodaq_data/malik-irain-patch-2/tests_Windows_3.13.svg
118
+ .. |313-windows| image:: https://raw.githubusercontent.com/PyMoDAQ/PyMoDAQ/badges/pymodaq_data/state-machine-simplify/tests_Windows_3.13.svg
119
119
  :target: https://github.com/PyMoDAQ/PyMoDAQ/actions/workflows/tests-data.yml
120
120
 
121
121
 
@@ -11,11 +11,11 @@ PyMoDAQ Data
11
11
  :target: https://pypi.org/project/pymodaq_data/
12
12
  :alt: Latest Version
13
13
 
14
- .. image:: https://readthedocs.org/projects/pymodaq/badge/?version=malik-irain-patch-2
15
- :target: https://pymodaq.readthedocs.io/en/stable/?badge=malik-irain-patch-2
14
+ .. image:: https://readthedocs.org/projects/pymodaq/badge/?version=state-machine-simplify
15
+ :target: https://pymodaq.readthedocs.io/en/stable/?badge=state-machine-simplify
16
16
  :alt: Documentation Status
17
17
 
18
- .. image:: https://codecov.io/gh/PyMoDAQ/PyMoDAQ/branch/malik-irain-patch-2/graph/badge.svg?token=IQNJRCQDM2
18
+ .. image:: https://codecov.io/gh/PyMoDAQ/PyMoDAQ/branch/state-machine-simplify/graph/badge.svg?token=IQNJRCQDM2
19
19
  :target: https://codecov.io/gh/PyMoDAQ/PyMoDAQ
20
20
 
21
21
  +-------------+-------------+---------------+
@@ -34,28 +34,28 @@ PyMoDAQ Data
34
34
 
35
35
 
36
36
 
37
- .. |310-linux| image:: https://raw.githubusercontent.com/PyMoDAQ/PyMoDAQ/badges/pymodaq_data/malik-irain-patch-2/tests_Linux_3.10.svg
37
+ .. |310-linux| image:: https://raw.githubusercontent.com/PyMoDAQ/PyMoDAQ/badges/pymodaq_data/state-machine-simplify/tests_Linux_3.10.svg
38
38
  :target: https://github.com/PyMoDAQ/PyMoDAQ/actions/workflows/tests-data.yml
39
39
 
40
- .. |311-linux| image:: https://raw.githubusercontent.com/PyMoDAQ/PyMoDAQ/badges/pymodaq_data/malik-irain-patch-2/tests_Linux_3.11.svg
40
+ .. |311-linux| image:: https://raw.githubusercontent.com/PyMoDAQ/PyMoDAQ/badges/pymodaq_data/state-machine-simplify/tests_Linux_3.11.svg
41
41
  :target: https://github.com/PyMoDAQ/PyMoDAQ/actions/workflows/tests-data.yml
42
42
 
43
- .. |312-linux| image:: https://raw.githubusercontent.com/PyMoDAQ/PyMoDAQ/badges/pymodaq_data/malik-irain-patch-2/tests_Linux_3.12.svg
43
+ .. |312-linux| image:: https://raw.githubusercontent.com/PyMoDAQ/PyMoDAQ/badges/pymodaq_data/state-machine-simplify/tests_Linux_3.12.svg
44
44
  :target: https://github.com/PyMoDAQ/PyMoDAQ/actions/workflows/tests-data.yml
45
45
 
46
- .. |313-linux| image:: https://raw.githubusercontent.com/PyMoDAQ/PyMoDAQ/badges/pymodaq_data/malik-irain-patch-2/tests_Linux_3.13.svg
46
+ .. |313-linux| image:: https://raw.githubusercontent.com/PyMoDAQ/PyMoDAQ/badges/pymodaq_data/state-machine-simplify/tests_Linux_3.13.svg
47
47
  :target: https://github.com/PyMoDAQ/PyMoDAQ/actions/workflows/tests-data.yml
48
48
 
49
- .. |310-windows| image:: https://raw.githubusercontent.com/PyMoDAQ/PyMoDAQ/badges/pymodaq_data/malik-irain-patch-2/tests_Windows_3.10.svg
49
+ .. |310-windows| image:: https://raw.githubusercontent.com/PyMoDAQ/PyMoDAQ/badges/pymodaq_data/state-machine-simplify/tests_Windows_3.10.svg
50
50
  :target: https://github.com/PyMoDAQ/PyMoDAQ/actions/workflows/tests-data.yml
51
51
 
52
- .. |311-windows| image:: https://raw.githubusercontent.com/PyMoDAQ/PyMoDAQ/badges/pymodaq_data/malik-irain-patch-2/tests_Windows_3.11.svg
52
+ .. |311-windows| image:: https://raw.githubusercontent.com/PyMoDAQ/PyMoDAQ/badges/pymodaq_data/state-machine-simplify/tests_Windows_3.11.svg
53
53
  :target: https://github.com/PyMoDAQ/PyMoDAQ/actions/workflows/tests-data.yml
54
54
 
55
- .. |312-windows| image:: https://raw.githubusercontent.com/PyMoDAQ/PyMoDAQ/badges/pymodaq_data/malik-irain-patch-2/tests_Windows_3.12.svg
55
+ .. |312-windows| image:: https://raw.githubusercontent.com/PyMoDAQ/PyMoDAQ/badges/pymodaq_data/state-machine-simplify/tests_Windows_3.12.svg
56
56
  :target: https://github.com/PyMoDAQ/PyMoDAQ/actions/workflows/tests-data.yml
57
57
 
58
- .. |313-windows| image:: https://raw.githubusercontent.com/PyMoDAQ/PyMoDAQ/badges/pymodaq_data/malik-irain-patch-2/tests_Windows_3.13.svg
58
+ .. |313-windows| image:: https://raw.githubusercontent.com/PyMoDAQ/PyMoDAQ/badges/pymodaq_data/state-machine-simplify/tests_Windows_3.13.svg
59
59
  :target: https://github.com/PyMoDAQ/PyMoDAQ/actions/workflows/tests-data.yml
60
60
 
61
61
 
@@ -86,7 +86,9 @@ def dimensionless_aware_reduce_units(q: Type[Q_]) -> Type[Q_]:
86
86
  -------
87
87
  The reduced quantity
88
88
  """
89
-
89
+ # this may fire a pint.errors.UndefinedBehavior warning when the magnitude is a numpy array
90
+ # but pint https://github.com/hgrecco/pint/issues/2274 fixed this in July 2026
91
+ # at the moment, it just returns the same quantity layout
90
92
  return q.to_compact() if q.dimensionless else q.to_reduced_units()
91
93
 
92
94
  def check_units(units: str):
@@ -529,6 +531,16 @@ class Axis(SerializableBase):
529
531
  if self._data is None:
530
532
  self._size = _size
531
533
 
534
+ @property
535
+ def axis_width(self) -> Q_:
536
+ """get the width of the axis in axis unit
537
+
538
+ That is the difference between the max value and the min value of the axis
539
+ """
540
+ if self.scaling is not None:
541
+ return Q_(self.size * self.scaling, self.units)
542
+ else:
543
+ return Q_(self.get_data().max() - self.get_data().min(), self.units)
532
544
  @staticmethod
533
545
  def _check_index_valid(index: int):
534
546
  if not isinstance(index, int):
@@ -653,10 +665,10 @@ class Axis(SerializableBase):
653
665
  """find the index of the threshold value within the axis"""
654
666
  if isinstance(threshold, Q_):
655
667
  threshold = threshold.m_as(self.units)
656
- if threshold < self.min():
668
+ if threshold <= self.min():
657
669
  return 0
658
- elif threshold > self.max():
659
- return len(self) - 1
670
+ elif threshold >= self.max():
671
+ return len(self)
660
672
  elif self._data is not None:
661
673
  return mutils.find_index(self._data, threshold)[0][0]
662
674
  else:
@@ -702,7 +714,7 @@ class DataLowLevel:
702
714
 
703
715
  @name.setter
704
716
  def name(self, other_name: str):
705
- self._name = other_name
717
+ self._name = str(other_name)
706
718
 
707
719
  @property
708
720
  def timestamp(self):
@@ -2141,6 +2153,10 @@ class DataWithAxes(DataBase, SerializableBase):
2141
2153
  dwa.timestamp = timestamp
2142
2154
  return dwa, remaining_bytes
2143
2155
 
2156
+ def get_axes_sizes(self) -> Iterable[Q_]:
2157
+ self.create_missing_axes()
2158
+ return [self.get_axis_from_index(index)[0].axis_width for index in range(len(self.axes))]
2159
+
2144
2160
  def check_axes_linear(self, axes: List[Axis] = None) -> bool:
2145
2161
  """ Check if any axis may be non linear
2146
2162
 
@@ -3747,9 +3763,16 @@ class DataToExport(DataLowLevel, SerializableBase):
3747
3763
  data, _ = find_objects_in_list_from_attr_name_val(self.data, 'name', name, return_first=True)
3748
3764
  return data
3749
3765
 
3750
- def get_data_from_names(self, names: List[str]) -> DataToExport:
3766
+ def get_data_from_names(self, names: List[str] | str) -> DataToExport:
3767
+ if isinstance(names, str):
3768
+ names = [names]
3751
3769
  return DataToExport(self.name, data=[dwa for dwa in self if dwa.name in names])
3752
3770
 
3771
+ def get_data_from_origins(self, origins: list[str] | str) -> DataToExport:
3772
+ if isinstance(origins, str):
3773
+ origins = [origins]
3774
+ return DataToExport(self.name, data=[dwa for dwa in self if dwa.origin in origins])
3775
+
3753
3776
  def get_data_from_name_origin(self, name: str, origin: str = '') -> DataWithAxes:
3754
3777
  """Get the data matching the given name and the given origin"""
3755
3778
  if origin == '':
@@ -3771,9 +3794,8 @@ class DataToExport(DataLowLevel, SerializableBase):
3771
3794
  return ind
3772
3795
  raise ValueError
3773
3796
 
3774
- def index_from_name_origin(self, name: str, origin: str = '') -> List[DataWithAxes]:
3797
+ def index_from_name_origin(self, name: str, origin: str = '') -> int:
3775
3798
  """Get the index of a given DataWithAxes within the list of data"""
3776
- """Get the data matching the given name and the given origin"""
3777
3799
  if origin == '':
3778
3800
  _, index = find_objects_in_list_from_attr_name_val(self.data, 'name', name, return_first=True)
3779
3801
  else:
@@ -242,7 +242,7 @@ class Node(object):
242
242
  return self.attrs['TITLE']
243
243
 
244
244
  @property
245
- def path(self):
245
+ def path(self) -> str:
246
246
  """return node path
247
247
  Parameters
248
248
  ----------
@@ -575,6 +575,11 @@ class H5Backend:
575
575
  self._swmr_enabled = False
576
576
  self.set_backend(backend)
577
577
 
578
+ @property
579
+ def swmr_mode(self) -> bool:
580
+ return self._swmr_mode
581
+
582
+
578
583
  def set_backend(self, backend: str):
579
584
  """Switch the active backend, closing any open file first.
580
585
 
@@ -977,7 +982,7 @@ class H5Backend:
977
982
  else:
978
983
  return self.get_node(node.parent)
979
984
 
980
- def get_children(self, where):
985
+ def get_children(self, where) -> dict[str, Node]:
981
986
  """Get a dict containing all children node hanging from where with their name as keys and types among Node,
982
987
  CARRAY, EARRAY, VLARRAY or StringARRAY
983
988
 
@@ -1023,12 +1028,45 @@ class H5Backend:
1023
1028
  children[child_name] = _cls(child, self.backend)
1024
1029
  return children
1025
1030
 
1026
- def walk_nodes(self, where):
1031
+ def walk_nodes(self, where: str| Node, depth: int = None, only_groups=False):
1032
+ """ Node Generator recursively iterating in the tree starting from where down to the specified depth
1033
+ (counted from where).
1034
+
1035
+
1036
+ Parameters
1037
+ ----------
1038
+ where: str | Node
1039
+ The starting node of the iteration
1040
+ depth: int
1041
+ The depth of the iteration in the h5 tree
1042
+ only_groups: bool
1043
+ if False (default) return all nodes otherwise retruns only GROUP instances
1044
+
1045
+ Yields
1046
+ ------
1047
+ Node
1048
+ """
1027
1049
  where = self.get_node(where) # return a node object in case where is a string
1028
- yield where
1029
- for gr in self.walk_groups(where):
1030
- for child in self.get_children(gr).values():
1031
- yield child
1050
+ if only_groups and where.attrs['CLASS'] != 'GROUP':
1051
+ pass
1052
+ else:
1053
+ yield where
1054
+
1055
+ if depth == 0:
1056
+ return
1057
+ else:
1058
+ for gr in self.walk_groups(where):
1059
+ for child in self.get_children(gr).values():
1060
+ node_path = child.path[len(where.path):]
1061
+ if node_path[0] == '/':
1062
+ node_path = node_path[1:]
1063
+ if depth is not None and node_path.count('/') == depth:
1064
+ return
1065
+ else:
1066
+ if only_groups and child.attrs['CLASS'] != 'GROUP':
1067
+ pass
1068
+ else:
1069
+ yield child
1032
1070
 
1033
1071
  def walk_groups(self, where):
1034
1072
  where = self.get_node(where) # return a node object in case where is a string
@@ -297,12 +297,17 @@ class DataSaverLoader(DataManagement):
297
297
  data_type = DataType['data']
298
298
 
299
299
  def __init__(self, h5saver: Union[H5SaverLowLevel, Path],
300
- new_file: bool = False, metadata: dict = None, save_type=SaveType.custom):
300
+ new_file: bool = False,
301
+ metadata: dict = None,
302
+ save_type=SaveType.custom,
303
+ swmr_mode=False):
301
304
  self.data_type = enum_checker(DataType, self.data_type)
302
305
 
303
306
  if isinstance(h5saver, (Path, str)):
304
307
  h5saver = H5SaverLowLevel.from_file(h5saver, save_type,
305
- new_file=new_file, metadata=metadata)
308
+ new_file=new_file,
309
+ metadata=metadata,
310
+ swmr_mode=swmr_mode)
306
311
 
307
312
  self._h5saver = h5saver
308
313
  self._axis_saver = AxisSaverLoader(self._h5saver)
@@ -708,7 +713,7 @@ class DataExtendedSaver(DataSaverLoader):
708
713
  Parameters
709
714
  ----------
710
715
  h5saver: H5SaverLowLevel
711
- extended_shape: Tuple[int]
716
+ extended_shape: Iterable[int]
712
717
  the extra shape compared to the data the h5array will have
713
718
 
714
719
  Attributes
@@ -718,7 +723,9 @@ class DataExtendedSaver(DataSaverLoader):
718
723
  """
719
724
  data_type = DataType['data']
720
725
 
721
- def __init__(self, h5saver: H5SaverLowLevel, extended_shape: Tuple[int], fill_value=None):
726
+ def __init__(self, h5saver: H5SaverLowLevel,
727
+ extended_shape: Iterable[int],
728
+ fill_value=None):
722
729
  super().__init__(h5saver)
723
730
  self.extended_shape = extended_shape
724
731
  self.fill_value = fill_value
@@ -784,7 +791,9 @@ class DataExtendedSaver(DataSaverLoader):
784
791
  # because there will be len(self.extended_shape) extra navigation axes
785
792
  self._axis_saver.add_axis(where, axis)
786
793
 
787
- def add_data(self, where: Union[Node, str], data: DataWithAxes, indexes: List[int],
794
+ def add_data(self, where: Union[Node, str],
795
+ data: DataWithAxes,
796
+ indexes: Iterable[int],
788
797
  distribution=DataDistribution['uniform']):
789
798
  """Adds given DataWithAxes at a location within the initialized h5 array
790
799
 
@@ -1035,7 +1044,10 @@ class DataToExportExtendedSaver(DataToExportSaver):
1035
1044
  the extra shape compared to the data the h5array will have
1036
1045
  """
1037
1046
 
1038
- def __init__(self, h5saver: H5SaverLowLevel, extended_shape: Tuple[int], fill_value=None):
1047
+ def __init__(self,
1048
+ h5saver: H5SaverLowLevel,
1049
+ extended_shape: Iterable[int],
1050
+ fill_value=None):
1039
1051
  super().__init__(h5saver)
1040
1052
  self._data_saver = DataExtendedSaver(h5saver, extended_shape, fill_value=fill_value)
1041
1053
  self._nav_axis_saver = AxisSaverLoader(h5saver)
@@ -1054,7 +1066,9 @@ class DataToExportExtendedSaver(DataToExportSaver):
1054
1066
  for axis in axes:
1055
1067
  self._nav_axis_saver.add_axis(nav_group, axis)
1056
1068
 
1057
- def add_data(self, where: Union[Node, str], data: DataToExport, indexes: Iterable[int],
1069
+ def add_data(self, where: Union[Node, str],
1070
+ data: DataToExport,
1071
+ indexes: Iterable[int],
1058
1072
  distribution=DataDistribution.uniform,
1059
1073
  settings_as_xml='', **kwargs):
1060
1074
 
@@ -1095,7 +1109,7 @@ class DataToExportExtendedSaver(DataToExportSaver):
1095
1109
 
1096
1110
 
1097
1111
  class DataLoader:
1098
- """Specialized Object to load DataWithAxes object from a h5file
1112
+ """Specialized Object to load DataWithAxes / DataToExport objects from a h5file
1099
1113
 
1100
1114
  On the contrary to DataSaverLoader, does include navigation axes stored elsewhere in the h5file
1101
1115
  (for instance if saved from the DAQ_Scan)
@@ -1105,12 +1119,15 @@ class DataLoader:
1105
1119
  h5saver: H5SaverLowLevel or Path
1106
1120
  """
1107
1121
 
1108
- def __init__(self, h5saver: Union[H5SaverLowLevel, Path]):
1122
+ def __init__(self, h5saver: Union[H5SaverLowLevel, Path],
1123
+ swmr_mode = False):
1109
1124
  self._axis_loader: AxisSaverLoader = None
1110
1125
  self._data_loader: DataSaverLoader = None
1111
1126
 
1112
1127
  if isinstance(h5saver, (Path, str)):
1113
- h5saver = H5SaverLowLevel.from_file(h5saver)
1128
+ h5saver = H5SaverLowLevel.from_file(h5saver,
1129
+ swmr_mode=swmr_mode,
1130
+ mode='r')
1114
1131
 
1115
1132
  self.h5saver = h5saver
1116
1133
 
@@ -1129,8 +1146,8 @@ class DataLoader:
1129
1146
 
1130
1147
  def __exit__(self, exc_type, exc_val, exc_tb):
1131
1148
  self.close_file()
1132
- @property
1133
1149
 
1150
+ @property
1134
1151
  def raw_group(self) -> Node:
1135
1152
  """ Get the base RawGroup where raw data should be saved
1136
1153
 
@@ -1141,9 +1158,11 @@ class DataLoader:
1141
1158
  def close_file(self):
1142
1159
  self._h5saver.close_file()
1143
1160
 
1144
- def walk_nodes(self, where: Union[str, Node] = '/'):
1161
+ def walk_nodes(self, where: Union[str, Node] = '/', depth: int = None,
1162
+ only_groups=False) -> Iterable[Node]:
1145
1163
  """Return a Node generator iterating over the h5file content"""
1146
- return self.h5saver.walk_nodes(where)
1164
+ return self.h5saver.walk_nodes(where, depth=depth,
1165
+ only_groups=only_groups)
1147
1166
 
1148
1167
  def get_node(self, where: Union[Node, str], name: str = None) -> Node:
1149
1168
  """ Convenience method to get node"""
@@ -1198,17 +1217,25 @@ class DataLoader:
1198
1217
  if nav_group is not None:
1199
1218
  nav_axes = self._axis_loader.get_axes(nav_group)
1200
1219
  axes = data.axes[:]
1220
+ # in swmr mode, if at the time where the axis is read, a writer added stuff
1221
+ # then the axis and the data may not be consistent. Below is an attempt to correct this
1222
+ for ind_nav, nav_axe in enumerate(nav_axes):
1223
+ if nav_axe.size > data.shape[data.nav_indexes[ind_nav]]:
1224
+ nav_axe.data = nav_axe.get_data()[:data.shape[data.nav_indexes[ind_nav]]]
1201
1225
  axes.extend(nav_axes)
1202
1226
  data.axes = axes
1203
1227
  data.get_dim_from_data_axes()
1204
1228
  data.create_missing_axes()
1205
1229
  return data
1206
1230
 
1207
- def load_all(self, where: GROUP, data: DataToExport = None, with_bkg=False) -> DataToExport:
1231
+ def load_all(self, where: GROUP | str, data: DataToExport = None, with_bkg=False) -> DataToExport:
1208
1232
  if data is None:
1209
1233
  data = DataToExport('Loaded data')
1210
1234
  where = self._h5saver.get_node(where)
1211
- children_dict = where.children()
1235
+ try:
1236
+ children_dict = where.children()
1237
+ except AttributeError:
1238
+ children_dict = {where.name: where}
1212
1239
  data_list = []
1213
1240
  for child in children_dict:
1214
1241
  if isinstance(children_dict[child], GROUP):
@@ -92,7 +92,9 @@ class H5SaverLowLevel(H5Backend):
92
92
 
93
93
  @classmethod
94
94
  def from_file(cls, path: Union[Path, str], save_type: SaveType = 'scan',
95
- new_file: bool = False, metadata: dict = None) -> 'H5SaverLowLevel':
95
+ new_file: bool = False, metadata: dict = None,
96
+ swmr_mode: bool = False,
97
+ mode='a') -> 'H5SaverLowLevel':
96
98
  """Create and initialise an H5SaverLowLevel from a file path.
97
99
 
98
100
  Convenience factory that combines the constructor and :meth:`init_file`
@@ -108,6 +110,11 @@ class H5SaverLowLevel(H5Backend):
108
110
  opened for appending.
109
111
  metadata: dict or None
110
112
  Extra attributes written to the raw-data group on creation.
113
+ swmr_mode: bool
114
+ If True, prepare the file for SWMR (h5py backend only)
115
+ mode: str
116
+ valid if new_file is False. Then could be 'r' for readonly or 'a' to append data
117
+
111
118
 
112
119
  Returns
113
120
  -------
@@ -115,7 +122,11 @@ class H5SaverLowLevel(H5Backend):
115
122
  A fully initialised instance ready for reading/writing.
116
123
  """
117
124
  h5saver = cls(save_type)
118
- h5saver.init_file(file_name=Path(path), new_file=new_file, metadata=metadata)
125
+ h5saver.init_file(file_name=Path(path),
126
+ new_file=new_file,
127
+ metadata=metadata,
128
+ swmr_mode=swmr_mode,
129
+ mode=mode)
119
130
  return h5saver
120
131
 
121
132
  def set_swmr_flush_interval(self, interval: int):
@@ -149,8 +160,11 @@ class H5SaverLowLevel(H5Backend):
149
160
  def h5_file(self):
150
161
  return self._h5file
151
162
 
152
- def init_file(self, file_name: Path, raw_group_name='RawData', new_file=False,
153
- metadata: dict = None, swmr_mode: bool = False):
163
+ def init_file(self, file_name: Path, raw_group_name='RawData',
164
+ new_file=False,
165
+ metadata: dict = None,
166
+ swmr_mode: bool = False,
167
+ mode: str = 'a'):
154
168
  """Initializes a new h5 file,
155
169
 
156
170
  Should have an extension with h5 in it.
@@ -167,6 +181,8 @@ class H5SaverLowLevel(H5Backend):
167
181
  A dictionary to be saved as attributes
168
182
  swmr_mode: bool
169
183
  If True, prepare the file for SWMR (h5py backend only)
184
+ mode: str
185
+ valid if new_file is False. Then could be 'r' for readonly or 'a' to append data
170
186
 
171
187
  Returns
172
188
  -------
@@ -200,7 +216,7 @@ class H5SaverLowLevel(H5Backend):
200
216
  return
201
217
 
202
218
  self.close_file()
203
- self.open_file(self.h5_file_path.joinpath(self.h5_file_name), 'w' if new_file else 'a',
219
+ self.open_file(self.h5_file_path.joinpath(self.h5_file_name), 'w' if new_file else mode,
204
220
  title='PyMoDAQ file', swmr_mode=swmr_mode)
205
221
 
206
222
  self._raw_group = self.get_set_group(self.root(), raw_group_name, title='Data from PyMoDAQ modules')
@@ -20,7 +20,10 @@ logger = set_logger(get_module_name(__file__))
20
20
  config = configmod.GlobalConfig()
21
21
 
22
22
  PLOT_COLORS = PlotColors()
23
- PLOT_COLORS.remove((255, 255, 255)) # remove white color as plotted on white background
23
+ try:
24
+ PLOT_COLORS.remove((255, 255, 255))# remove white color as plotted on white background
25
+ except ValueError:
26
+ pass # this color is not in PLOT_COLORS (maybe because light style is used)
24
27
  PLOT_COLORS = PlotColors([(np.array(color) / 255).tolist() for color in PLOT_COLORS]) # translation to matplotlib
25
28
 
26
29
 
@@ -38,18 +41,26 @@ class Plotter(PlotterBase):
38
41
  def plot(self, data: Union[DataWithAxes, DataToExport], *args, viewer=None,
39
42
  **kwargs) -> plt.Figure:
40
43
  fig = plt.figure()
44
+ if 'linewidth' in kwargs:
45
+ linewidth = kwargs['linewidth']
46
+ else:
47
+ linewidth = self.linewidth
41
48
 
42
49
  if isinstance(data, DataWithAxes):
43
50
  self.n_columns = len(data) if data.dim.name == 'Data2D' else 1
44
- self.plot_dwa(data, *args, **kwargs)
51
+ self.plot_dwa(data, *args, linewidth=linewidth, **kwargs)
45
52
  elif isinstance(data, DataToExport):
46
53
  self.n_columns = max([len(dwa) if dwa.dim.name == 'Data2D' else 1 for dwa in data])
47
54
  self.n_lines = len(data)
48
- self.plot_dte(data, *args, **kwargs)
55
+ self.plot_dte(data, *args, linewidth=linewidth, **kwargs)
49
56
  plt.tight_layout()
50
57
  fig.suptitle(f'{data.name} taken the {datetime.datetime.fromtimestamp(data.timestamp)}')
51
58
  return fig
52
59
 
60
+ @property
61
+ def linewidth(self) -> int:
62
+ return config('data', 'plotting', 'linewidth')
63
+
53
64
  def plot_dwa(self, dwa: DataWithAxes, *args, **kwargs):
54
65
  if dwa.dim.name == 'Data1D':
55
66
  if len(dwa.axes) == 0:
@@ -1,7 +1,8 @@
1
1
  import copy
2
2
  from typing import Iterable as IterableType, Iterable
3
3
 
4
- from pymodaq_utils.utils import config
4
+ from pymodaq_utils.config import GlobalConfig
5
+ config = GlobalConfig()
5
6
 
6
7
 
7
8
  class PlotColors:
@@ -26,3 +26,4 @@ backend = ['h5py', 'tables', 'h5pyd'] # first element is the default, mostly te
26
26
  backend = ['matplotlib'] # either 'matplotlib' or 'qt' or any other custom backend
27
27
  plot_colors = [[255, 255, 255], [255, 0, 0], [0, 255, 0], [0, 0, 255], [14, 207, 189], [207, 14, 166], [207, 204, 14]]
28
28
  process_roi = true # if True subdata is extracted from the ROI in the data viewers
29
+ linewidth = 1 # default linewidth of the plots
File without changes
File without changes