sigima 0.0.1.dev0__py3-none-any.whl → 1.0.0__py3-none-any.whl

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 (264) hide show
  1. sigima/__init__.py +142 -2
  2. sigima/client/__init__.py +105 -0
  3. sigima/client/base.py +780 -0
  4. sigima/client/remote.py +469 -0
  5. sigima/client/stub.py +814 -0
  6. sigima/client/utils.py +90 -0
  7. sigima/config.py +444 -0
  8. sigima/data/logo/Sigima.svg +135 -0
  9. sigima/data/tests/annotations.json +798 -0
  10. sigima/data/tests/curve_fitting/exponential_fit.txt +511 -0
  11. sigima/data/tests/curve_fitting/gaussian_fit.txt +100 -0
  12. sigima/data/tests/curve_fitting/piecewiseexponential_fit.txt +1022 -0
  13. sigima/data/tests/curve_fitting/polynomial_fit.txt +100 -0
  14. sigima/data/tests/curve_fitting/twohalfgaussian_fit.txt +1000 -0
  15. sigima/data/tests/curve_formats/bandwidth.txt +201 -0
  16. sigima/data/tests/curve_formats/boxcar.npy +0 -0
  17. sigima/data/tests/curve_formats/datetime.txt +1001 -0
  18. sigima/data/tests/curve_formats/dynamic_parameters.txt +4000 -0
  19. sigima/data/tests/curve_formats/fw1e2.txt +301 -0
  20. sigima/data/tests/curve_formats/fwhm.txt +319 -0
  21. sigima/data/tests/curve_formats/multiple_curves.csv +29 -0
  22. sigima/data/tests/curve_formats/noised_saw.mat +0 -0
  23. sigima/data/tests/curve_formats/oscilloscope.csv +111 -0
  24. sigima/data/tests/curve_formats/other/other2/recursive2.txt +5 -0
  25. sigima/data/tests/curve_formats/other/recursive1.txt +5 -0
  26. sigima/data/tests/curve_formats/paracetamol.npy +0 -0
  27. sigima/data/tests/curve_formats/paracetamol.txt +1010 -0
  28. sigima/data/tests/curve_formats/paracetamol_dx_dy.csv +1000 -0
  29. sigima/data/tests/curve_formats/paracetamol_dy.csv +1001 -0
  30. sigima/data/tests/curve_formats/pulse1.npy +0 -0
  31. sigima/data/tests/curve_formats/pulse2.npy +0 -0
  32. sigima/data/tests/curve_formats/simple.txt +5 -0
  33. sigima/data/tests/curve_formats/spectrum.mca +2139 -0
  34. sigima/data/tests/curve_formats/square2.npy +0 -0
  35. sigima/data/tests/curve_formats/step.npy +0 -0
  36. sigima/data/tests/fabry-perot1.jpg +0 -0
  37. sigima/data/tests/fabry-perot2.jpg +0 -0
  38. sigima/data/tests/flower.npy +0 -0
  39. sigima/data/tests/image_formats/NF 180338201.scor-data +11003 -0
  40. sigima/data/tests/image_formats/binary_image.npy +0 -0
  41. sigima/data/tests/image_formats/binary_image.png +0 -0
  42. sigima/data/tests/image_formats/centroid_test.npy +0 -0
  43. sigima/data/tests/image_formats/coordinated_text/complex_image.txt +10011 -0
  44. sigima/data/tests/image_formats/coordinated_text/complex_ref_image.txt +10010 -0
  45. sigima/data/tests/image_formats/coordinated_text/image.txt +15 -0
  46. sigima/data/tests/image_formats/coordinated_text/image2.txt +14 -0
  47. sigima/data/tests/image_formats/coordinated_text/image_no_unit_no_label.txt +14 -0
  48. sigima/data/tests/image_formats/coordinated_text/image_with_nan.txt +15 -0
  49. sigima/data/tests/image_formats/coordinated_text/image_with_unit.txt +14 -0
  50. sigima/data/tests/image_formats/fiber.csv +480 -0
  51. sigima/data/tests/image_formats/fiber.jpg +0 -0
  52. sigima/data/tests/image_formats/fiber.png +0 -0
  53. sigima/data/tests/image_formats/fiber.txt +480 -0
  54. sigima/data/tests/image_formats/gaussian_spot_with_noise.npy +0 -0
  55. sigima/data/tests/image_formats/mr-brain.dcm +0 -0
  56. sigima/data/tests/image_formats/noised_gaussian.mat +0 -0
  57. sigima/data/tests/image_formats/sif_reader/nd_lum_image_no_glue.sif +0 -0
  58. sigima/data/tests/image_formats/sif_reader/raman1.sif +0 -0
  59. sigima/data/tests/image_formats/tiling.txt +10 -0
  60. sigima/data/tests/image_formats/uint16.tiff +0 -0
  61. sigima/data/tests/image_formats/uint8.tiff +0 -0
  62. sigima/data/tests/laser_beam/TEM00_z_13.jpg +0 -0
  63. sigima/data/tests/laser_beam/TEM00_z_18.jpg +0 -0
  64. sigima/data/tests/laser_beam/TEM00_z_23.jpg +0 -0
  65. sigima/data/tests/laser_beam/TEM00_z_30.jpg +0 -0
  66. sigima/data/tests/laser_beam/TEM00_z_35.jpg +0 -0
  67. sigima/data/tests/laser_beam/TEM00_z_40.jpg +0 -0
  68. sigima/data/tests/laser_beam/TEM00_z_45.jpg +0 -0
  69. sigima/data/tests/laser_beam/TEM00_z_50.jpg +0 -0
  70. sigima/data/tests/laser_beam/TEM00_z_55.jpg +0 -0
  71. sigima/data/tests/laser_beam/TEM00_z_60.jpg +0 -0
  72. sigima/data/tests/laser_beam/TEM00_z_65.jpg +0 -0
  73. sigima/data/tests/laser_beam/TEM00_z_70.jpg +0 -0
  74. sigima/data/tests/laser_beam/TEM00_z_75.jpg +0 -0
  75. sigima/data/tests/laser_beam/TEM00_z_80.jpg +0 -0
  76. sigima/enums.py +195 -0
  77. sigima/io/__init__.py +123 -0
  78. sigima/io/base.py +311 -0
  79. sigima/io/common/__init__.py +5 -0
  80. sigima/io/common/basename.py +164 -0
  81. sigima/io/common/converters.py +189 -0
  82. sigima/io/common/objmeta.py +181 -0
  83. sigima/io/common/textreader.py +58 -0
  84. sigima/io/convenience.py +157 -0
  85. sigima/io/enums.py +17 -0
  86. sigima/io/ftlab.py +395 -0
  87. sigima/io/image/__init__.py +9 -0
  88. sigima/io/image/base.py +177 -0
  89. sigima/io/image/formats.py +1016 -0
  90. sigima/io/image/funcs.py +414 -0
  91. sigima/io/signal/__init__.py +9 -0
  92. sigima/io/signal/base.py +129 -0
  93. sigima/io/signal/formats.py +290 -0
  94. sigima/io/signal/funcs.py +723 -0
  95. sigima/objects/__init__.py +260 -0
  96. sigima/objects/base.py +937 -0
  97. sigima/objects/image/__init__.py +88 -0
  98. sigima/objects/image/creation.py +556 -0
  99. sigima/objects/image/object.py +524 -0
  100. sigima/objects/image/roi.py +904 -0
  101. sigima/objects/scalar/__init__.py +57 -0
  102. sigima/objects/scalar/common.py +215 -0
  103. sigima/objects/scalar/geometry.py +502 -0
  104. sigima/objects/scalar/table.py +784 -0
  105. sigima/objects/shape.py +290 -0
  106. sigima/objects/signal/__init__.py +133 -0
  107. sigima/objects/signal/constants.py +27 -0
  108. sigima/objects/signal/creation.py +1428 -0
  109. sigima/objects/signal/object.py +444 -0
  110. sigima/objects/signal/roi.py +274 -0
  111. sigima/params.py +405 -0
  112. sigima/proc/__init__.py +96 -0
  113. sigima/proc/base.py +381 -0
  114. sigima/proc/decorator.py +330 -0
  115. sigima/proc/image/__init__.py +513 -0
  116. sigima/proc/image/arithmetic.py +335 -0
  117. sigima/proc/image/base.py +260 -0
  118. sigima/proc/image/detection.py +519 -0
  119. sigima/proc/image/edges.py +329 -0
  120. sigima/proc/image/exposure.py +406 -0
  121. sigima/proc/image/extraction.py +458 -0
  122. sigima/proc/image/filtering.py +219 -0
  123. sigima/proc/image/fourier.py +147 -0
  124. sigima/proc/image/geometry.py +661 -0
  125. sigima/proc/image/mathops.py +340 -0
  126. sigima/proc/image/measurement.py +195 -0
  127. sigima/proc/image/morphology.py +155 -0
  128. sigima/proc/image/noise.py +107 -0
  129. sigima/proc/image/preprocessing.py +182 -0
  130. sigima/proc/image/restoration.py +235 -0
  131. sigima/proc/image/threshold.py +217 -0
  132. sigima/proc/image/transformations.py +393 -0
  133. sigima/proc/signal/__init__.py +376 -0
  134. sigima/proc/signal/analysis.py +206 -0
  135. sigima/proc/signal/arithmetic.py +551 -0
  136. sigima/proc/signal/base.py +262 -0
  137. sigima/proc/signal/extraction.py +60 -0
  138. sigima/proc/signal/features.py +310 -0
  139. sigima/proc/signal/filtering.py +484 -0
  140. sigima/proc/signal/fitting.py +276 -0
  141. sigima/proc/signal/fourier.py +259 -0
  142. sigima/proc/signal/mathops.py +420 -0
  143. sigima/proc/signal/processing.py +580 -0
  144. sigima/proc/signal/stability.py +175 -0
  145. sigima/proc/title_formatting.py +227 -0
  146. sigima/proc/validation.py +272 -0
  147. sigima/tests/__init__.py +7 -0
  148. sigima/tests/common/__init__.py +0 -0
  149. sigima/tests/common/arithmeticparam_unit_test.py +26 -0
  150. sigima/tests/common/basename_unit_test.py +126 -0
  151. sigima/tests/common/client_unit_test.py +412 -0
  152. sigima/tests/common/converters_unit_test.py +77 -0
  153. sigima/tests/common/decorator_unit_test.py +176 -0
  154. sigima/tests/common/examples_unit_test.py +104 -0
  155. sigima/tests/common/kernel_normalization_unit_test.py +242 -0
  156. sigima/tests/common/roi_basic_unit_test.py +73 -0
  157. sigima/tests/common/roi_geometry_unit_test.py +171 -0
  158. sigima/tests/common/scalar_builder_unit_test.py +142 -0
  159. sigima/tests/common/scalar_unit_test.py +991 -0
  160. sigima/tests/common/shape_unit_test.py +183 -0
  161. sigima/tests/common/stat_unit_test.py +138 -0
  162. sigima/tests/common/title_formatting_unit_test.py +338 -0
  163. sigima/tests/common/tools_coordinates_unit_test.py +60 -0
  164. sigima/tests/common/transformations_unit_test.py +178 -0
  165. sigima/tests/common/validation_unit_test.py +205 -0
  166. sigima/tests/conftest.py +129 -0
  167. sigima/tests/data.py +998 -0
  168. sigima/tests/env.py +280 -0
  169. sigima/tests/guiutils.py +163 -0
  170. sigima/tests/helpers.py +532 -0
  171. sigima/tests/image/__init__.py +28 -0
  172. sigima/tests/image/binning_unit_test.py +128 -0
  173. sigima/tests/image/blob_detection_unit_test.py +312 -0
  174. sigima/tests/image/centroid_unit_test.py +170 -0
  175. sigima/tests/image/check_2d_array_unit_test.py +63 -0
  176. sigima/tests/image/contour_unit_test.py +172 -0
  177. sigima/tests/image/convolution_unit_test.py +178 -0
  178. sigima/tests/image/datatype_unit_test.py +67 -0
  179. sigima/tests/image/edges_unit_test.py +155 -0
  180. sigima/tests/image/enclosingcircle_unit_test.py +88 -0
  181. sigima/tests/image/exposure_unit_test.py +223 -0
  182. sigima/tests/image/fft2d_unit_test.py +189 -0
  183. sigima/tests/image/filtering_unit_test.py +166 -0
  184. sigima/tests/image/geometry_unit_test.py +654 -0
  185. sigima/tests/image/hough_circle_unit_test.py +147 -0
  186. sigima/tests/image/imageobj_unit_test.py +737 -0
  187. sigima/tests/image/morphology_unit_test.py +71 -0
  188. sigima/tests/image/noise_unit_test.py +57 -0
  189. sigima/tests/image/offset_correction_unit_test.py +72 -0
  190. sigima/tests/image/operation_unit_test.py +518 -0
  191. sigima/tests/image/peak2d_limits_unit_test.py +41 -0
  192. sigima/tests/image/peak2d_unit_test.py +133 -0
  193. sigima/tests/image/profile_unit_test.py +159 -0
  194. sigima/tests/image/projections_unit_test.py +121 -0
  195. sigima/tests/image/restoration_unit_test.py +141 -0
  196. sigima/tests/image/roi2dparam_unit_test.py +53 -0
  197. sigima/tests/image/roi_advanced_unit_test.py +588 -0
  198. sigima/tests/image/roi_grid_unit_test.py +279 -0
  199. sigima/tests/image/spectrum2d_unit_test.py +40 -0
  200. sigima/tests/image/threshold_unit_test.py +91 -0
  201. sigima/tests/io/__init__.py +0 -0
  202. sigima/tests/io/addnewformat_unit_test.py +125 -0
  203. sigima/tests/io/convenience_funcs_unit_test.py +470 -0
  204. sigima/tests/io/coordinated_text_format_unit_test.py +495 -0
  205. sigima/tests/io/datetime_csv_unit_test.py +198 -0
  206. sigima/tests/io/imageio_formats_test.py +41 -0
  207. sigima/tests/io/ioregistry_unit_test.py +69 -0
  208. sigima/tests/io/objmeta_unit_test.py +87 -0
  209. sigima/tests/io/readobj_unit_test.py +130 -0
  210. sigima/tests/io/readwriteobj_unit_test.py +67 -0
  211. sigima/tests/signal/__init__.py +0 -0
  212. sigima/tests/signal/analysis_unit_test.py +135 -0
  213. sigima/tests/signal/check_1d_arrays_unit_test.py +169 -0
  214. sigima/tests/signal/convolution_unit_test.py +404 -0
  215. sigima/tests/signal/datetime_unit_test.py +176 -0
  216. sigima/tests/signal/fft1d_unit_test.py +303 -0
  217. sigima/tests/signal/filters_unit_test.py +403 -0
  218. sigima/tests/signal/fitting_unit_test.py +929 -0
  219. sigima/tests/signal/fwhm_unit_test.py +111 -0
  220. sigima/tests/signal/noise_unit_test.py +128 -0
  221. sigima/tests/signal/offset_correction_unit_test.py +34 -0
  222. sigima/tests/signal/operation_unit_test.py +489 -0
  223. sigima/tests/signal/peakdetection_unit_test.py +145 -0
  224. sigima/tests/signal/processing_unit_test.py +657 -0
  225. sigima/tests/signal/pulse/__init__.py +112 -0
  226. sigima/tests/signal/pulse/crossing_times_unit_test.py +123 -0
  227. sigima/tests/signal/pulse/plateau_detection_unit_test.py +102 -0
  228. sigima/tests/signal/pulse/pulse_unit_test.py +1824 -0
  229. sigima/tests/signal/roi_advanced_unit_test.py +392 -0
  230. sigima/tests/signal/signalobj_unit_test.py +603 -0
  231. sigima/tests/signal/stability_unit_test.py +431 -0
  232. sigima/tests/signal/uncertainty_unit_test.py +611 -0
  233. sigima/tests/vistools.py +1030 -0
  234. sigima/tools/__init__.py +59 -0
  235. sigima/tools/checks.py +290 -0
  236. sigima/tools/coordinates.py +308 -0
  237. sigima/tools/datatypes.py +26 -0
  238. sigima/tools/image/__init__.py +97 -0
  239. sigima/tools/image/detection.py +451 -0
  240. sigima/tools/image/exposure.py +77 -0
  241. sigima/tools/image/extraction.py +48 -0
  242. sigima/tools/image/fourier.py +260 -0
  243. sigima/tools/image/geometry.py +190 -0
  244. sigima/tools/image/preprocessing.py +165 -0
  245. sigima/tools/signal/__init__.py +86 -0
  246. sigima/tools/signal/dynamic.py +254 -0
  247. sigima/tools/signal/features.py +135 -0
  248. sigima/tools/signal/filtering.py +171 -0
  249. sigima/tools/signal/fitting.py +1171 -0
  250. sigima/tools/signal/fourier.py +466 -0
  251. sigima/tools/signal/interpolation.py +70 -0
  252. sigima/tools/signal/peakdetection.py +126 -0
  253. sigima/tools/signal/pulse.py +1626 -0
  254. sigima/tools/signal/scaling.py +50 -0
  255. sigima/tools/signal/stability.py +258 -0
  256. sigima/tools/signal/windowing.py +90 -0
  257. sigima/worker.py +79 -0
  258. sigima-1.0.0.dist-info/METADATA +233 -0
  259. sigima-1.0.0.dist-info/RECORD +262 -0
  260. {sigima-0.0.1.dev0.dist-info → sigima-1.0.0.dist-info}/licenses/LICENSE +29 -29
  261. sigima-0.0.1.dev0.dist-info/METADATA +0 -60
  262. sigima-0.0.1.dev0.dist-info/RECORD +0 -6
  263. {sigima-0.0.1.dev0.dist-info → sigima-1.0.0.dist-info}/WHEEL +0 -0
  264. {sigima-0.0.1.dev0.dist-info → sigima-1.0.0.dist-info}/top_level.txt +0 -0
sigima/client/base.py ADDED
@@ -0,0 +1,780 @@
1
+ # Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.
2
+
3
+ """
4
+ DataLab Client base proxy module
5
+ --------------------------------
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import abc
11
+ from collections.abc import Callable
12
+ from typing import TYPE_CHECKING
13
+
14
+ import guidata.dataset as gds
15
+ import numpy as np
16
+
17
+ if TYPE_CHECKING:
18
+ from collections.abc import Iterator
19
+
20
+ from sigima.client.remote import ServerProxy
21
+ from sigima.objects import ImageObj, SignalObj
22
+
23
+
24
+ class SimpleAbstractDLControl(abc.ABC):
25
+ """Simple abstract base class for controlling DataLab
26
+
27
+ This is a subset of DataLab's AbstractDLControl, with only the methods that do not
28
+ require DataLab object model to be implemented."""
29
+
30
+ def __len__(self) -> int:
31
+ """Return number of objects"""
32
+ return len(self.get_object_uuids())
33
+
34
+ def __getitem__(
35
+ self,
36
+ nb_id_title: int | str | None = None,
37
+ ) -> SignalObj | ImageObj:
38
+ """Return object"""
39
+ return self.get_object(nb_id_title)
40
+
41
+ def __iter__(self) -> Iterator[SignalObj | ImageObj]:
42
+ """Iterate over objects"""
43
+ uuids = self.get_object_uuids()
44
+ for uuid in uuids:
45
+ yield self.get_object(uuid)
46
+
47
+ def __str__(self) -> str:
48
+ """Return object string representation"""
49
+ return super().__repr__()
50
+
51
+ def __repr__(self) -> str:
52
+ """Return object representation"""
53
+ titles = self.get_object_titles()
54
+ uuids = self.get_object_uuids()
55
+ text = f"{str(self)} (DataLab, {len(titles)} items):\n"
56
+ for uuid, title in zip(uuids, titles):
57
+ text += f" {uuid}: {title}\n"
58
+ return text
59
+
60
+ def __bool__(self) -> bool:
61
+ """Return True if model is not empty"""
62
+ return bool(self.get_object_uuids())
63
+
64
+ def __contains__(self, id_title: str) -> bool:
65
+ """Return True if object (UUID or title) is in model"""
66
+ return id_title in (self.get_object_titles() + self.get_object_uuids())
67
+
68
+ @classmethod
69
+ def get_public_methods(cls) -> list[str]:
70
+ """Return all public methods of the class, except itself.
71
+
72
+ Returns:
73
+ list[str]: List of public methods
74
+ """
75
+ return [
76
+ method
77
+ for method in dir(cls)
78
+ if not method.startswith("_") and method != "get_public_methods"
79
+ ]
80
+
81
+ @abc.abstractmethod
82
+ def get_version(self) -> str:
83
+ """Return DataLab version.
84
+
85
+ Returns:
86
+ str: DataLab version
87
+ """
88
+
89
+ @abc.abstractmethod
90
+ def close_application(self) -> None:
91
+ """Close DataLab application"""
92
+
93
+ @abc.abstractmethod
94
+ def raise_window(self) -> None:
95
+ """Raise DataLab window"""
96
+
97
+ @abc.abstractmethod
98
+ def get_current_panel(self) -> str:
99
+ """Return current panel name.
100
+
101
+ Returns:
102
+ str: Panel name (valid values: "signal", "image", "macro"))
103
+ """
104
+
105
+ @abc.abstractmethod
106
+ def set_current_panel(self, panel: str) -> None:
107
+ """Switch to panel.
108
+
109
+ Args:
110
+ panel (str): Panel name (valid values: "signal", "image", "macro"))
111
+ """
112
+
113
+ @abc.abstractmethod
114
+ def reset_all(self) -> None:
115
+ """Reset all application data"""
116
+
117
+ @abc.abstractmethod
118
+ def toggle_auto_refresh(self, state: bool) -> None:
119
+ """Toggle auto refresh state.
120
+
121
+ Args:
122
+ state (bool): Auto refresh state
123
+ """
124
+
125
+ @abc.abstractmethod
126
+ def toggle_show_titles(self, state: bool) -> None:
127
+ """Toggle show titles state.
128
+
129
+ Args:
130
+ state (bool): Show titles state
131
+ """
132
+
133
+ @abc.abstractmethod
134
+ def save_to_h5_file(self, filename: str) -> None:
135
+ """Save to a DataLab HDF5 file.
136
+
137
+ Args:
138
+ filename (str): HDF5 file name
139
+ """
140
+
141
+ @abc.abstractmethod
142
+ def open_h5_files(
143
+ self,
144
+ h5files: list[str] | None = None,
145
+ import_all: bool | None = None,
146
+ reset_all: bool | None = None,
147
+ ) -> None:
148
+ """Open a DataLab HDF5 file or import from any other HDF5 file.
149
+
150
+ Args:
151
+ h5files (list[str] | None): List of HDF5 files to open. Defaults to None.
152
+ import_all (bool | None): Import all objects from HDF5 files.
153
+ Defaults to None.
154
+ reset_all (bool | None): Reset all application data. Defaults to None.
155
+ """
156
+
157
+ @abc.abstractmethod
158
+ def import_h5_file(self, filename: str, reset_all: bool | None = None) -> None:
159
+ """Open DataLab HDF5 browser to Import HDF5 file.
160
+
161
+ Args:
162
+ filename (str): HDF5 file name
163
+ reset_all (bool | None): Reset all application data. Defaults to None.
164
+ """
165
+
166
+ @abc.abstractmethod
167
+ def load_from_files(self, filenames: list[str]) -> None:
168
+ """Open objects from files in current panel (signals/images).
169
+
170
+ Args:
171
+ filenames: list of file names
172
+ """
173
+
174
+ @abc.abstractmethod
175
+ def add_signal(
176
+ self,
177
+ title: str,
178
+ xdata: np.ndarray,
179
+ ydata: np.ndarray,
180
+ xunit: str | None = None,
181
+ yunit: str | None = None,
182
+ xlabel: str | None = None,
183
+ ylabel: str | None = None,
184
+ ) -> bool: # pylint: disable=too-many-arguments
185
+ """Add signal data to DataLab.
186
+
187
+ Args:
188
+ title (str): Signal title
189
+ xdata (numpy.ndarray): X data
190
+ ydata (numpy.ndarray): Y data
191
+ xunit (str | None): X unit. Defaults to None.
192
+ yunit (str | None): Y unit. Defaults to None.
193
+ xlabel (str | None): X label. Defaults to None.
194
+ ylabel (str | None): Y label. Defaults to None.
195
+
196
+ Returns:
197
+ bool: True if signal was added successfully, False otherwise
198
+
199
+ Raises:
200
+ ValueError: Invalid xdata dtype
201
+ ValueError: Invalid ydata dtype
202
+ """
203
+
204
+ @abc.abstractmethod
205
+ # pylint: disable=too-many-arguments
206
+ def add_image(
207
+ self,
208
+ title: str,
209
+ data: np.ndarray,
210
+ xunit: str | None = None,
211
+ yunit: str | None = None,
212
+ zunit: str | None = None,
213
+ xlabel: str | None = None,
214
+ ylabel: str | None = None,
215
+ zlabel: str | None = None,
216
+ ) -> bool:
217
+ """Add image data to DataLab.
218
+
219
+ Args:
220
+ title (str): Image title
221
+ data (numpy.ndarray): Image data
222
+ xunit (str | None): X unit. Defaults to None.
223
+ yunit (str | None): Y unit. Defaults to None.
224
+ zunit (str | None): Z unit. Defaults to None.
225
+ xlabel (str | None): X label. Defaults to None.
226
+ ylabel (str | None): Y label. Defaults to None.
227
+ zlabel (str | None): Z label. Defaults to None.
228
+
229
+ Returns:
230
+ bool: True if image was added successfully, False otherwise
231
+
232
+ Raises:
233
+ ValueError: Invalid data dtype
234
+ """
235
+
236
+ @abc.abstractmethod
237
+ def add_object(
238
+ self, obj: SignalObj | ImageObj, group_id: str = "", set_current: bool = True
239
+ ) -> None:
240
+ """Add object to DataLab.
241
+
242
+ Args:
243
+ obj: Signal or image object
244
+ group_id: group id in which to add the object. Defaults to ""
245
+ set_current: if True, set the added object as current
246
+
247
+ Returns:
248
+ True if object was added successfully, False otherwise
249
+ """
250
+
251
+ @abc.abstractmethod
252
+ def load_from_directory(self, path: str) -> None:
253
+ """Open objects from directory in current panel (signals/images).
254
+
255
+ Args:
256
+ path: directory path
257
+ """
258
+
259
+ @abc.abstractmethod
260
+ def add_group(
261
+ self, title: str, panel: str | None = None, select: bool = False
262
+ ) -> None:
263
+ """Add group to DataLab.
264
+
265
+ Args:
266
+ title: Group title
267
+ panel: Panel name (valid values: "signal", "image"). Defaults to None.
268
+ select: Select the group after creation. Defaults to False.
269
+ """
270
+
271
+ @abc.abstractmethod
272
+ def get_sel_object_uuids(self, include_groups: bool = False) -> list[str]:
273
+ """Return selected objects uuids.
274
+
275
+ Args:
276
+ include_groups: If True, also return objects from selected groups.
277
+
278
+ Returns:
279
+ List of selected objects uuids.
280
+ """
281
+
282
+ @abc.abstractmethod
283
+ def select_objects(
284
+ self,
285
+ selection: list[int | str],
286
+ panel: str | None = None,
287
+ ) -> None:
288
+ """Select objects in current panel.
289
+
290
+ Args:
291
+ selection: List of object numbers (1 to N) or uuids to select
292
+ panel: panel name (valid values: "signal", "image").
293
+ If None, current panel is used. Defaults to None.
294
+ """
295
+
296
+ @abc.abstractmethod
297
+ def select_groups(
298
+ self, selection: list[int | str] | None = None, panel: str | None = None
299
+ ) -> None:
300
+ """Select groups in current panel.
301
+
302
+ Args:
303
+ selection: List of group numbers (1 to N), or list of group uuids,
304
+ or None to select all groups. Defaults to None.
305
+ panel (str | None): panel name (valid values: "signal", "image").
306
+ If None, current panel is used. Defaults to None.
307
+ """
308
+
309
+ @abc.abstractmethod
310
+ def delete_metadata(
311
+ self, refresh_plot: bool = True, keep_roi: bool = False
312
+ ) -> None:
313
+ """Delete metadata of selected objects
314
+
315
+ Args:
316
+ refresh_plot: Refresh plot. Defaults to True.
317
+ keep_roi: Keep ROI. Defaults to False.
318
+ """
319
+
320
+ @abc.abstractmethod
321
+ def get_group_titles_with_object_info(
322
+ self,
323
+ ) -> tuple[list[str], list[list[str]], list[list[str]]]:
324
+ """Return groups titles and lists of inner objects uuids and titles.
325
+
326
+ Returns:
327
+ Tuple: groups titles, lists of inner objects uuids and titles
328
+ """
329
+
330
+ @abc.abstractmethod
331
+ def get_object_titles(self, panel: str | None = None) -> list[str]:
332
+ """Get object (signal/image) list for current panel.
333
+ Objects are sorted by group number and object index in group.
334
+
335
+ Args:
336
+ panel: panel name (valid values: "signal", "image", "macro").
337
+ If None, current data panel is used (i.e. signal or image panel).
338
+
339
+ Returns:
340
+ List of object titles
341
+
342
+ Raises:
343
+ ValueError: if panel not found
344
+ """
345
+
346
+ @abc.abstractmethod
347
+ def get_object(
348
+ self,
349
+ nb_id_title: int | str | None = None,
350
+ panel: str | None = None,
351
+ ) -> SignalObj | ImageObj:
352
+ """Get object (signal/image) from index.
353
+
354
+ Args:
355
+ nb_id_title: Object number, or object id, or object title.
356
+ Defaults to None (current object).
357
+ panel: Panel name. Defaults to None (current panel).
358
+
359
+ Returns:
360
+ Object
361
+
362
+ Raises:
363
+ KeyError: if object not found
364
+ """
365
+
366
+ @abc.abstractmethod
367
+ def get_object_uuids(
368
+ self, panel: str | None = None, group: int | str | None = None
369
+ ) -> list[str]:
370
+ """Get object (signal/image) uuid list for current panel.
371
+ Objects are sorted by group number and object index in group.
372
+
373
+ Args:
374
+ panel: panel name (valid values: "signal", "image").
375
+ If None, current panel is used.
376
+ group: Group number, or group id, or group title.
377
+ Defaults to None (all groups).
378
+
379
+ Returns:
380
+ List of object uuids
381
+
382
+ Raises:
383
+ ValueError: if panel not found
384
+ """
385
+
386
+ @abc.abstractmethod
387
+ def get_object_shapes(
388
+ self,
389
+ nb_id_title: int | str | None = None,
390
+ panel: str | None = None,
391
+ ) -> list:
392
+ """Get plot item shapes associated to object (signal/image).
393
+
394
+ Args:
395
+ nb_id_title: Object number, or object id, or object title.
396
+ Defaults to None (current object).
397
+ panel: Panel name. Defaults to None (current panel).
398
+
399
+ Returns:
400
+ List of plot item shapes
401
+ """
402
+
403
+ @abc.abstractmethod
404
+ def add_annotations_from_items(
405
+ self, items: list, refresh_plot: bool = True, panel: str | None = None
406
+ ) -> None:
407
+ """Add object annotations (annotation plot items).
408
+
409
+ Args:
410
+ items (list): annotation plot items
411
+ refresh_plot (bool | None): refresh plot. Defaults to True.
412
+ panel (str | None): panel name (valid values: "signal", "image").
413
+ If None, current panel is used.
414
+ """
415
+
416
+ @abc.abstractmethod
417
+ def add_label_with_title(
418
+ self, title: str | None = None, panel: str | None = None
419
+ ) -> None:
420
+ """Add a label with object title on the associated plot
421
+
422
+ Args:
423
+ title (str | None): Label title. Defaults to None.
424
+ If None, the title is the object title.
425
+ panel (str | None): panel name (valid values: "signal", "image").
426
+ If None, current panel is used.
427
+ """
428
+
429
+ @abc.abstractmethod
430
+ def run_macro(self, number_or_title: int | str | None = None) -> None:
431
+ """Run macro.
432
+
433
+ Args:
434
+ number: Number of the macro (starting at 1). Defaults to None (run
435
+ current macro, or does nothing if there is no macro).
436
+ """
437
+
438
+ @abc.abstractmethod
439
+ def stop_macro(self, number_or_title: int | str | None = None) -> None:
440
+ """Stop macro.
441
+
442
+ Args:
443
+ number: Number of the macro (starting at 1). Defaults to None (stop
444
+ current macro, or does nothing if there is no macro).
445
+ """
446
+
447
+ @abc.abstractmethod
448
+ def import_macro_from_file(self, filename: str) -> None:
449
+ """Import macro from file
450
+
451
+ Args:
452
+ filename: Filename.
453
+ """
454
+
455
+ @abc.abstractmethod
456
+ def calc(self, name: str, param: gds.DataSet | None = None) -> None:
457
+ """Call compute function ``name`` in current panel's processor.
458
+
459
+ Args:
460
+ name: Compute function name
461
+ param: Compute function parameter. Defaults to None.
462
+
463
+ Raises:
464
+ ValueError: unknown function
465
+ """
466
+
467
+ def __getattr__(self, name: str) -> Callable:
468
+ """Return compute function ``name`` in current panel's processor.
469
+
470
+ Args:
471
+ name (str): Compute function name
472
+
473
+ Returns:
474
+ Callable: Compute function
475
+
476
+ Raises:
477
+ AttributeError: If compute function ``name`` does not exist
478
+ """
479
+
480
+ def compute_func(param: gds.DataSet | None = None) -> gds.DataSet:
481
+ """Compute function.
482
+
483
+ Args:
484
+ param (guidata.dataset.DataSet | None): Compute function
485
+ parameter. Defaults to None.
486
+
487
+ Returns:
488
+ guidata.dataset.DataSet: Compute function result
489
+ """
490
+ return self.calc(name, param)
491
+
492
+ if name.startswith("compute_"):
493
+ return compute_func
494
+ raise AttributeError(f"DataLab has no compute function '{name}'")
495
+
496
+
497
+ class SimpleBaseProxy(SimpleAbstractDLControl, metaclass=abc.ABCMeta):
498
+ """Simple common base class for DataLab proxies
499
+
500
+ This is a subset of DataLab's BaseProxy, with only the methods that do not require
501
+ DataLab object model to be implemented.
502
+
503
+ Args:
504
+ datalab (DLMainWindow | ServerProxy | None): DLMainWindow instance or
505
+ ServerProxy instance. If None, then the proxy implementation will
506
+ have to set it later (e.g. see SimpleRemoteProxy).
507
+ """
508
+
509
+ def __init__(self, datalab: ServerProxy | None = None) -> None:
510
+ self._datalab = datalab
511
+
512
+ def get_version(self) -> str:
513
+ """Return DataLab version.
514
+
515
+ Returns:
516
+ str: DataLab version
517
+ """
518
+ return self._datalab.get_version()
519
+
520
+ def close_application(self) -> None:
521
+ """Close DataLab application"""
522
+ self._datalab.close_application()
523
+
524
+ def raise_window(self) -> None:
525
+ """Raise DataLab window"""
526
+ self._datalab.raise_window()
527
+
528
+ def get_current_panel(self) -> str:
529
+ """Return current panel name.
530
+
531
+ Returns:
532
+ str: Panel name (valid values: "signal", "image", "macro"))
533
+ """
534
+ return self._datalab.get_current_panel()
535
+
536
+ def set_current_panel(self, panel: str) -> None:
537
+ """Switch to panel.
538
+
539
+ Args:
540
+ panel (str): Panel name (valid values: "signal", "image", "macro"))
541
+ """
542
+ self._datalab.set_current_panel(panel)
543
+
544
+ def reset_all(self) -> None:
545
+ """Reset all application data"""
546
+ self._datalab.reset_all()
547
+
548
+ def toggle_auto_refresh(self, state: bool) -> None:
549
+ """Toggle auto refresh state.
550
+
551
+ Args:
552
+ state (bool): Auto refresh state
553
+ """
554
+ self._datalab.toggle_auto_refresh(state)
555
+
556
+ # Returns a context manager to temporarily disable autorefresh
557
+ def context_no_refresh(self) -> Callable:
558
+ """Return a context manager to temporarily disable auto refresh.
559
+
560
+ Returns:
561
+ Context manager
562
+
563
+ Example:
564
+
565
+ >>> with proxy.context_no_refresh():
566
+ ... proxy.add_image("image1", data1)
567
+ ... proxy.compute_fft()
568
+ ... proxy.compute_wiener()
569
+ ... proxy.compute_ifft()
570
+ ... # Auto refresh is disabled during the above operations
571
+ """
572
+
573
+ class NoRefreshContextManager:
574
+ """Context manager to temporarily disable auto refresh"""
575
+
576
+ def __init__(self, datalab: SimpleAbstractDLControl) -> None:
577
+ self._datalab = datalab
578
+
579
+ def __enter__(self) -> None:
580
+ self._datalab.toggle_auto_refresh(False)
581
+
582
+ def __exit__(self, exc_type, exc_value, traceback) -> None:
583
+ self._datalab.toggle_auto_refresh(True)
584
+
585
+ return NoRefreshContextManager(self)
586
+
587
+ def toggle_show_titles(self, state: bool) -> None:
588
+ """Toggle show titles state.
589
+
590
+ Args:
591
+ state (bool): Show titles state
592
+ """
593
+ self._datalab.toggle_show_titles(state)
594
+
595
+ def save_to_h5_file(self, filename: str) -> None:
596
+ """Save to a DataLab HDF5 file.
597
+
598
+ Args:
599
+ filename (str): HDF5 file name
600
+ """
601
+ self._datalab.save_to_h5_file(filename)
602
+
603
+ def open_h5_files(
604
+ self,
605
+ h5files: list[str] | None = None,
606
+ import_all: bool | None = None,
607
+ reset_all: bool | None = None,
608
+ ) -> None:
609
+ """Open a DataLab HDF5 file or import from any other HDF5 file.
610
+
611
+ Args:
612
+ h5files (list[str] | None): List of HDF5 files to open. Defaults to None.
613
+ import_all (bool | None): Import all objects from HDF5 files.
614
+ Defaults to None.
615
+ reset_all (bool | None): Reset all application data. Defaults to None.
616
+ """
617
+ self._datalab.open_h5_files(h5files, import_all, reset_all)
618
+
619
+ def import_h5_file(self, filename: str, reset_all: bool | None = None) -> None:
620
+ """Open DataLab HDF5 browser to Import HDF5 file.
621
+
622
+ Args:
623
+ filename (str): HDF5 file name
624
+ reset_all (bool | None): Reset all application data. Defaults to None.
625
+ """
626
+ self._datalab.import_h5_file(filename, reset_all)
627
+
628
+ def load_from_files(self, filenames: list[str]) -> None:
629
+ """Open objects from files in current panel (signals/images).
630
+
631
+ Args:
632
+ filenames: list of file names
633
+ """
634
+ self._datalab.load_from_files(filenames)
635
+
636
+ def add_group(
637
+ self, title: str, panel: str | None = None, select: bool = False
638
+ ) -> None:
639
+ """Add group to DataLab.
640
+
641
+ Args:
642
+ title: Group title
643
+ panel: Panel name (valid values: "signal", "image"). Defaults to None.
644
+ select: Select the group after creation. Defaults to False.
645
+ """
646
+ self._datalab.add_group(title, panel, select)
647
+
648
+ def get_sel_object_uuids(self, include_groups: bool = False) -> list[str]:
649
+ """Return selected objects uuids.
650
+
651
+ Args:
652
+ include_groups: If True, also return objects from selected groups.
653
+
654
+ Returns:
655
+ List of selected objects uuids.
656
+ """
657
+ return self._datalab.get_sel_object_uuids(include_groups)
658
+
659
+ def select_objects(
660
+ self,
661
+ selection: list[int | str],
662
+ panel: str | None = None,
663
+ ) -> None:
664
+ """Select objects in current panel.
665
+
666
+ Args:
667
+ selection: List of object numbers (1 to N) or uuids to select
668
+ panel: panel name (valid values: "signal", "image").
669
+ If None, current panel is used. Defaults to None.
670
+ """
671
+ self._datalab.select_objects(selection, panel)
672
+
673
+ def select_groups(
674
+ self, selection: list[int | str] | None = None, panel: str | None = None
675
+ ) -> None:
676
+ """Select groups in current panel.
677
+
678
+ Args:
679
+ selection: List of group numbers (1 to N), or list of group uuids,
680
+ or None to select all groups. Defaults to None.
681
+ panel (str | None): panel name (valid values: "signal", "image").
682
+ If None, current panel is used. Defaults to None.
683
+ """
684
+ self._datalab.select_groups(selection, panel)
685
+
686
+ def delete_metadata(
687
+ self, refresh_plot: bool = True, keep_roi: bool = False
688
+ ) -> None:
689
+ """Delete metadata of selected objects
690
+
691
+ Args:
692
+ refresh_plot: Refresh plot. Defaults to True.
693
+ keep_roi: Keep ROI. Defaults to False.
694
+ """
695
+ self._datalab.delete_metadata(refresh_plot, keep_roi)
696
+
697
+ def get_group_titles_with_object_info(
698
+ self,
699
+ ) -> tuple[list[str], list[list[str]], list[list[str]]]:
700
+ """Return groups titles and lists of inner objects uuids and titles.
701
+
702
+ Returns:
703
+ Tuple: groups titles, lists of inner objects uuids and titles
704
+ """
705
+ return self._datalab.get_group_titles_with_object_info()
706
+
707
+ def get_object_titles(self, panel: str | None = None) -> list[str]:
708
+ """Get object (signal/image) list for current panel.
709
+ Objects are sorted by group number and object index in group.
710
+
711
+ Args:
712
+ panel: panel name (valid values: "signal", "image", "macro").
713
+ If None, current data panel is used (i.e. signal or image panel).
714
+
715
+ Returns:
716
+ List of object titles
717
+
718
+ Raises:
719
+ ValueError: if panel not found
720
+ """
721
+ return self._datalab.get_object_titles(panel)
722
+
723
+ def get_object_uuids(
724
+ self, panel: str | None = None, group: int | str | None = None
725
+ ) -> list[str]:
726
+ """Get object (signal/image) uuid list for current panel.
727
+ Objects are sorted by group number and object index in group.
728
+
729
+ Args:
730
+ panel: panel name (valid values: "signal", "image").
731
+ If None, current panel is used.
732
+ group: Group number, or group id, or group title.
733
+ Defaults to None (all groups).
734
+
735
+ Returns:
736
+ List of object uuids
737
+
738
+ Raises:
739
+ ValueError: if panel not found
740
+ """
741
+ return self._datalab.get_object_uuids(panel, group)
742
+
743
+ def add_label_with_title(
744
+ self, title: str | None = None, panel: str | None = None
745
+ ) -> None:
746
+ """Add a label with object title on the associated plot
747
+
748
+ Args:
749
+ title (str | None): Label title. Defaults to None.
750
+ If None, the title is the object title.
751
+ panel (str | None): panel name (valid values: "signal", "image").
752
+ If None, current panel is used.
753
+ """
754
+ self._datalab.add_label_with_title(title, panel)
755
+
756
+ def run_macro(self, number_or_title: int | str | None = None) -> None:
757
+ """Run macro.
758
+
759
+ Args:
760
+ number: Number of the macro (starting at 1). Defaults to None (run
761
+ current macro, or does nothing if there is no macro).
762
+ """
763
+ self._datalab.run_macro(number_or_title)
764
+
765
+ def stop_macro(self, number_or_title: int | str | None = None) -> None:
766
+ """Stop macro.
767
+
768
+ Args:
769
+ number: Number of the macro (starting at 1). Defaults to None (stop
770
+ current macro, or does nothing if there is no macro).
771
+ """
772
+ self._datalab.stop_macro(number_or_title)
773
+
774
+ def import_macro_from_file(self, filename: str) -> None:
775
+ """Import macro from file
776
+
777
+ Args:
778
+ filename: Filename.
779
+ """
780
+ return self._datalab.import_macro_from_file(filename)