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
@@ -0,0 +1,41 @@
1
+ # Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.
2
+
3
+ """
4
+ Testing image format handling based on the `imageio_formats` option.
5
+ """
6
+
7
+ # Note about the modules imported outside top-level:
8
+ #
9
+ # We want to keep the import order under control, so we import the modules only when
10
+ # they are needed, especially for the dynamically defined image formats in the `formats`
11
+ # module. This way, we can ensure that the formats are defined just before we use them
12
+ # in the tests. This is particularly useful for testing the `imageio_formats` option
13
+ # that allows users to set custom image I/O formats.
14
+
15
+
16
+ def get_image_formats():
17
+ """Get image formats"""
18
+ # pylint: disable=import-outside-toplevel
19
+ from sigima.io.image import formats
20
+
21
+ return [clname for clname in dir(formats) if clname.endswith("ImageFormat")]
22
+
23
+
24
+ def test_imageio_formats_option():
25
+ """Set other image I/O formats"""
26
+ # pylint: disable=import-outside-toplevel
27
+ from sigima.config import options
28
+ from sigima.io.image import formats
29
+
30
+ # Set custom image I/O formats
31
+ options.imageio_formats.set((("*.rec", "PCO Camera REC"),))
32
+ # Check if the formats are set correctly
33
+ assert hasattr(formats, "RECImageFormat"), "RECImageFormat not found in formats"
34
+
35
+
36
+ if __name__ == "__main__":
37
+ from pprint import pprint
38
+
39
+ pprint(get_image_formats())
40
+ test_imageio_formats_option()
41
+ pprint(get_image_formats())
@@ -0,0 +1,69 @@
1
+ # Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.
2
+
3
+ """
4
+ I/O registry unit test
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ from sigima.io import ImageIORegistry, SignalIORegistry
10
+ from sigima.io.base import IOAction, get_file_extensions
11
+ from sigima.tests.env import execenv
12
+
13
+
14
+ def test_get_file_extensions() -> None:
15
+ """Test function `get_file_extensions` for I/O registries"""
16
+ extensions = "*.bmp *.jpg *.jpeg *.png *.tif *.tiff *.jp2"
17
+ assert get_file_extensions(extensions) == [
18
+ "bmp",
19
+ "jp2",
20
+ "jpeg",
21
+ "jpg",
22
+ "png",
23
+ "tif",
24
+ "tiff",
25
+ ], "get_file_extensions did not return expected list of extensions"
26
+
27
+
28
+ def __test_io_registry(registry: SignalIORegistry | ImageIORegistry) -> None:
29
+ """Test I/O registry functionality
30
+
31
+ Args:
32
+ registry: I/O registry to test
33
+ """
34
+ execenv.print("*" * 80)
35
+ execenv.print(f"Testing I/O registry: {registry.__name__}")
36
+ execenv.print("*" * 80)
37
+ formats = registry.get_formats()
38
+ execenv.print(f"Supported formats: {len(formats)}")
39
+ execenv.print(registry.get_format_info(mode="text"))
40
+ load_filters = registry.get_filters(IOAction.LOAD)
41
+ assert (
42
+ len(load_filters.splitlines())
43
+ == len([fmt for fmt in formats if fmt.info.readable]) + 1
44
+ ), "Number of load filters does not match number of formats"
45
+ save_filters = registry.get_filters(IOAction.SAVE)
46
+ assert (
47
+ len(save_filters.splitlines())
48
+ == len([fmt for fmt in formats if fmt.info.writeable]) + 1
49
+ ), "Number of save filters does not match number of formats"
50
+ execenv.print(f"Readable formats: {load_filters}")
51
+ assert load_filters == registry.get_read_filters()
52
+ execenv.print(f"Writable formats: {save_filters}")
53
+ assert save_filters == registry.get_write_filters()
54
+
55
+
56
+ def test_signal_io_registry() -> None:
57
+ """Test Signal I/O registry functionality"""
58
+ __test_io_registry(SignalIORegistry)
59
+
60
+
61
+ def test_image_io_registry() -> None:
62
+ """Test Image I/O registry functionality"""
63
+ __test_io_registry(ImageIORegistry)
64
+
65
+
66
+ if __name__ == "__main__":
67
+ test_signal_io_registry()
68
+ test_image_io_registry()
69
+ test_get_file_extensions()
@@ -0,0 +1,87 @@
1
+ # Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.
2
+
3
+ """
4
+ I/O metadata and ROI functions
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ import os.path as osp
10
+
11
+ from sigima.io.common.objmeta import (
12
+ read_metadata,
13
+ read_roi,
14
+ write_metadata,
15
+ write_roi,
16
+ )
17
+ from sigima.tests.data import (
18
+ create_multigaussian_image,
19
+ create_paracetamol_signal,
20
+ create_test_image_rois,
21
+ create_test_metadata,
22
+ create_test_signal_rois,
23
+ )
24
+ from sigima.tests.env import execenv
25
+ from sigima.tests.helpers import WorkdirRestoringTempDir, compare_metadata
26
+
27
+
28
+ def test_signal_roi_io():
29
+ """Test reading and writing of signal ROIs."""
30
+ execenv.print("==============================================")
31
+ execenv.print("Testing signal ROI I/O")
32
+ execenv.print("==============================================")
33
+ with WorkdirRestoringTempDir() as temp_dir:
34
+ obj = create_paracetamol_signal()
35
+ for orig_roi in create_test_signal_rois(obj):
36
+ fname = osp.join(temp_dir, "test_signal_roi.json")
37
+ write_roi(fname, orig_roi)
38
+ roi = read_roi(fname)
39
+ try:
40
+ compare_metadata(roi.to_dict(), orig_roi.to_dict(), raise_on_diff=True)
41
+ except AssertionError as exc:
42
+ raise AssertionError(
43
+ "Signal ROI read from file does not match original"
44
+ ) from exc
45
+
46
+
47
+ def test_image_roi_io():
48
+ """Test reading and writing of image ROIs."""
49
+ execenv.print("==============================================")
50
+ execenv.print("Testing image ROI I/O")
51
+ execenv.print("==============================================")
52
+ with WorkdirRestoringTempDir() as temp_dir:
53
+ obj = create_multigaussian_image()
54
+ for orig_roi in create_test_image_rois(obj):
55
+ fname = osp.join(temp_dir, "test_image_roi.json")
56
+ write_roi(fname, orig_roi)
57
+ roi = read_roi(fname)
58
+ try:
59
+ compare_metadata(roi.to_dict(), orig_roi.to_dict(), raise_on_diff=True)
60
+ except AssertionError as exc:
61
+ raise AssertionError(
62
+ "Image ROI read from file does not match original"
63
+ ) from exc
64
+
65
+
66
+ def test_metadata_io():
67
+ """Test reading and writing of metadata."""
68
+ execenv.print("==============================================")
69
+ execenv.print("Testing metadata I/O")
70
+ execenv.print("==============================================")
71
+ with WorkdirRestoringTempDir() as temp_dir:
72
+ orig_metadata = create_test_metadata()
73
+ fname = osp.join(temp_dir, "test_metadata.json")
74
+ write_metadata(fname, orig_metadata)
75
+ metadata = read_metadata(fname)
76
+ try:
77
+ compare_metadata(metadata, orig_metadata, raise_on_diff=True)
78
+ except AssertionError as exc:
79
+ raise AssertionError(
80
+ "Metadata read from file does not match original"
81
+ ) from exc
82
+
83
+
84
+ if __name__ == "__main__":
85
+ test_signal_roi_io()
86
+ test_image_roi_io()
87
+ test_metadata_io()
@@ -0,0 +1,130 @@
1
+ # Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.
2
+
3
+ """
4
+ I/O test
5
+
6
+ Testing `sigima` specific formats.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ import numpy as np
12
+ import pytest
13
+
14
+ from sigima.io import read_images, read_signals
15
+ from sigima.io.ftlab import FTLabImageFile, imread_ftlabima, sigread_ftlabsig
16
+ from sigima.objects import ImageObj, SignalObj
17
+ from sigima.tests import guiutils, helpers
18
+ from sigima.tests.env import execenv
19
+
20
+
21
+ def __read_objs(fname: str) -> list[ImageObj] | list[SignalObj]:
22
+ """Read objects from a file"""
23
+ if "curve" in fname:
24
+ objs = read_signals(fname)
25
+ else:
26
+ objs = read_images(fname)
27
+ for obj in objs:
28
+ if np.all(np.isnan(obj.data)):
29
+ raise ValueError("Data is all NaNs")
30
+ for obj in objs:
31
+ execenv.print(obj)
32
+ return objs
33
+
34
+
35
+ def __read_and_view_objs(
36
+ fname: str | None = None, title: str | None = None
37
+ ) -> list[ImageObj]:
38
+ """Read and view objects from a file
39
+
40
+ Args:
41
+ fname: Name of the file to open.
42
+ title: Title for the view.
43
+
44
+ Returns:
45
+ List of ImageObj or SignalObj read from the file.
46
+ """
47
+ objs = __read_objs(fname)
48
+ guiutils.view_curves_and_images_if_gui(objs, title=f"{title} - {fname}")
49
+ return objs
50
+
51
+
52
+ @helpers.try_open_test_data("Testing TXT file reader", "*.txt")
53
+ def test_open_txt(fname: str | None = None, title: str | None = None) -> None:
54
+ """Testing TXT files."""
55
+ __read_and_view_objs(fname, title)
56
+
57
+
58
+ @helpers.try_open_test_data("Testing CSV file reader", "*.csv")
59
+ def test_open_csv(fname: str | None = None, title: str | None = None) -> None:
60
+ """Testing CSV files."""
61
+ __read_and_view_objs(fname, title)
62
+
63
+
64
+ @helpers.try_open_test_data("Testing FTLab signal file reader", "*.sig")
65
+ def test_open_sigdata(fname: str | None = None, title: str | None = None) -> None:
66
+ """Testing FTLab signal files."""
67
+ __read_and_view_objs(fname, title)
68
+
69
+ # Read the FTLab signal file and compare the data with the reference
70
+ data = sigread_ftlabsig(fname)
71
+ ref = read_signals(fname.replace(".sig", ".npy"))[0]
72
+ helpers.check_array_result(f"{fname}", data, ref.xydata)
73
+
74
+
75
+ @helpers.try_open_test_data("Testing MCA file reader", "*.mca")
76
+ def test_open_mca(fname: str | None = None, title: str | None = None) -> None:
77
+ """Testing MCA files."""
78
+ __read_and_view_objs(fname, title)
79
+
80
+
81
+ @helpers.try_open_test_data("Testing MAT-File reader", "*.mat")
82
+ def test_open_mat(fname: str | None = None, title: str | None = None) -> None:
83
+ """Testing MAT files."""
84
+ __read_and_view_objs(fname, title)
85
+
86
+
87
+ @helpers.try_open_test_data("Testing SIF file handler", "*.sif")
88
+ def test_open_sif(fname: str | None = None, title: str | None = None) -> None:
89
+ """Testing SIF files."""
90
+ __read_and_view_objs(fname, title)
91
+
92
+
93
+ @helpers.try_open_test_data("Testing SCOR-DATA file handler", "*.scor-data")
94
+ def test_open_scordata(fname: str | None = None, title: str | None = None) -> None:
95
+ """Testing SCOR-DATA files."""
96
+ __read_and_view_objs(fname, title)
97
+
98
+
99
+ @helpers.try_open_test_data("Testing FTLab image file handler", "*.ima")
100
+ def test_open_imadata(fname: str | None = None, title: str | None = None) -> None:
101
+ """Testing FTLab image files."""
102
+ __read_and_view_objs(fname, title)
103
+
104
+ # Read the FTLab image file and show the data
105
+ ftlab_file = FTLabImageFile(fname)
106
+ ftlab_file.read()
107
+ execenv.print(ftlab_file)
108
+
109
+ # Read the FTLab image file and compare the data with the reference
110
+ data = imread_ftlabima(fname)
111
+ ref = read_images(fname.replace(".ima", ".npy"))[0]
112
+ helpers.check_array_result(f"{fname}", data, ref.data)
113
+
114
+
115
+ @pytest.mark.gui
116
+ def test_read_obj_interactive() -> None:
117
+ """Interactive test for I/O: read and view objects from various formats."""
118
+ guiutils.enable_gui()
119
+ test_open_txt()
120
+ test_open_csv()
121
+ test_open_sigdata()
122
+ test_open_mca()
123
+ test_open_mat()
124
+ test_open_sif()
125
+ test_open_scordata()
126
+ test_open_imadata()
127
+
128
+
129
+ if __name__ == "__main__":
130
+ test_read_obj_interactive()
@@ -0,0 +1,67 @@
1
+ # Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.
2
+
3
+ """
4
+ I/O test
5
+
6
+ Testing `sigima` specific formats.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ import os.path as osp
12
+
13
+ from sigima.io.image import ImageIORegistry
14
+ from sigima.io.signal import SignalIORegistry
15
+ from sigima.tests.env import execenv
16
+ from sigima.tests.helpers import WorkdirRestoringTempDir, read_test_objects, reduce_path
17
+
18
+
19
+ def __testfunc(
20
+ title: str,
21
+ registry: SignalIORegistry | ImageIORegistry,
22
+ pattern: str = "*.*",
23
+ in_folder: str | None = None,
24
+ ) -> None:
25
+ """Test I/O features: read and write objects, and check registry functionality
26
+
27
+ Args:
28
+ title: Title of the test
29
+ registry: I/O registry to use
30
+ pattern: File name pattern to match
31
+ in_folder: Folder to search for test files
32
+
33
+ Raises:
34
+ NotImplementedError: if format is not supported
35
+ """
36
+ execenv.print(f" {title}:")
37
+ with WorkdirRestoringTempDir() as tmpdir:
38
+ # os.startfile(tmpdir)
39
+ objects = {}
40
+ for fname, obj in read_test_objects(registry, pattern, in_folder):
41
+ label = f" Opening {reduce_path(fname)}"
42
+ execenv.print(label + ": ", end="")
43
+ if obj is None:
44
+ execenv.print("Skipped (not implemented)")
45
+ else:
46
+ execenv.print("OK")
47
+ objects[fname] = obj
48
+ execenv.print(" Saving:")
49
+ for fname, obj in objects.items():
50
+ path = osp.join(tmpdir, osp.basename(fname))
51
+ try:
52
+ execenv.print(f" {path}: ", end="")
53
+ registry.write(path, obj)
54
+ execenv.print("OK")
55
+ except NotImplementedError:
56
+ execenv.print("Skipped (not implemented)")
57
+
58
+
59
+ def test_read_write_obj():
60
+ """I/O test: read and write objects, check registry functionality"""
61
+ execenv.print("I/O unit test:")
62
+ __testfunc("Signals", SignalIORegistry)
63
+ __testfunc("Images", ImageIORegistry)
64
+
65
+
66
+ if __name__ == "__main__":
67
+ test_read_write_obj()
File without changes
@@ -0,0 +1,135 @@
1
+ # Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.
2
+
3
+ """
4
+ Unit tests for signal analysis features
5
+ ---------------------------------------
6
+
7
+ Features from the "Analysis" menu are covered by this test.
8
+ The "Analysis" menu contains functions to compute signal properties like
9
+ bandwidth, ENOB, etc.
10
+ """
11
+
12
+ # pylint: disable=invalid-name # Allows short reference names like x, y, ...
13
+ # pylint: disable=duplicate-code
14
+
15
+ from __future__ import annotations
16
+
17
+ import numpy as np
18
+ import pytest
19
+
20
+ import sigima.objects
21
+ import sigima.params
22
+ import sigima.proc.signal
23
+ from sigima.tests import guiutils
24
+ from sigima.tests.data import get_test_signal
25
+ from sigima.tests.helpers import check_scalar_result
26
+
27
+
28
+ @pytest.mark.validation
29
+ def test_signal_bandwidth_3db() -> None:
30
+ """Validation test for the bandwidth computation."""
31
+ obj = get_test_signal("bandwidth.txt")
32
+ geometry = sigima.proc.signal.bandwidth_3db(obj)
33
+ assert geometry is not None, "Bandwidth computation failed."
34
+ with guiutils.lazy_qt_app_context() as qt_app:
35
+ if qt_app is not None:
36
+ # pylint: disable=import-outside-toplevel
37
+ from plotpy.builder import make
38
+
39
+ from sigima.tests import vistools
40
+
41
+ x0, y0, x1, y1 = geometry.coords[0]
42
+ x, y = obj.xydata
43
+ vistools.view_curve_items(
44
+ [
45
+ make.mcurve(x.real, y.real, label=obj.title),
46
+ vistools.create_signal_segment(x0, y0, x1, y1, "Bandwidth@-3dB"),
47
+ ],
48
+ title="Bandwidth@-3dB",
49
+ )
50
+ length = geometry.segments_lengths()[0]
51
+ check_scalar_result("Bandwidth@-3dB", length, 38.99301975103714)
52
+ p1 = sigima.params.AbscissaParam.create(x=length)
53
+ table = sigima.proc.signal.y_at_x(obj, p1)
54
+ check_scalar_result("Value@cutoff", table["y@x"][0], np.max(obj.y) - 3.0)
55
+
56
+
57
+ @pytest.mark.validation
58
+ def test_dynamic_parameters() -> None:
59
+ """Validation test for dynamic parameters computation."""
60
+ obj = get_test_signal("dynamic_parameters.txt")
61
+ param = sigima.params.DynamicParam.create(full_scale=1.0)
62
+ table = sigima.proc.signal.dynamic_parameters(obj, param)
63
+ assert table is not None, "Dynamic parameters computation failed"
64
+ tdict = table.as_dict()
65
+ check_scalar_result("ENOB", tdict["enob"], 5.1, rtol=0.001)
66
+ check_scalar_result("SINAD", tdict["sinad"], 32.49, rtol=0.001)
67
+ check_scalar_result("THD", tdict["thd"], -30.18, rtol=0.001)
68
+ check_scalar_result("SFDR", tdict["sfdr"], 34.03, rtol=0.001)
69
+ check_scalar_result("Freq", tdict["freq"], 49998377.464, rtol=0.001)
70
+ check_scalar_result("SNR", tdict["snr"], 101.52, rtol=0.001)
71
+
72
+
73
+ @pytest.mark.validation
74
+ def test_signal_sampling_rate_period() -> None:
75
+ """Validation test for the sampling rate and period computation."""
76
+ obj = get_test_signal("dynamic_parameters.txt")
77
+ table = sigima.proc.signal.sampling_rate_period(obj)
78
+ assert table is not None, "Sampling rate and period computation failed"
79
+ check_scalar_result("Sampling rate", table["fs"][0], 1.0e10, rtol=0.001)
80
+ check_scalar_result("Period", table["T"][0], 1.0e-10, rtol=0.001)
81
+
82
+
83
+ @pytest.mark.validation
84
+ def test_signal_contrast() -> None:
85
+ """Validation test for the contrast computation."""
86
+ obj = get_test_signal("fw1e2.txt")
87
+ table = sigima.proc.signal.contrast(obj)
88
+ assert table is not None, "Contrast computation failed"
89
+ check_scalar_result("Contrast", table["contrast"][0], 0.825, rtol=0.001)
90
+
91
+
92
+ @pytest.mark.validation
93
+ def test_signal_x_at_minmax() -> None:
94
+ """Validation test for the x value at min/max computation."""
95
+ obj = get_test_signal("fw1e2.txt")
96
+ table = sigima.proc.signal.x_at_minmax(obj)
97
+ assert table is not None, "X at min/max computation failed"
98
+ check_scalar_result("X@Ymin", table["X@Ymin"][0], 0.803, rtol=0.001)
99
+ check_scalar_result("X@Ymax", table["X@Ymax"][0], 5.184, rtol=0.001)
100
+
101
+
102
+ @pytest.mark.validation
103
+ def test_signal_x_at_y() -> None:
104
+ """Validation test for the abscissa finding computation."""
105
+ obj = sigima.objects.create_signal_from_param(sigima.objects.StepParam.create())
106
+ if obj is None:
107
+ raise ValueError("Failed to create test signal")
108
+ param = sigima.proc.signal.OrdinateParam.create(y=0.5)
109
+ table = sigima.proc.signal.x_at_y(obj, param)
110
+ assert table is not None, "X at Y computation failed"
111
+ check_scalar_result("x|y=0.5", table["x@y"][0], 0.0)
112
+
113
+
114
+ @pytest.mark.validation
115
+ def test_signal_y_at_x() -> None:
116
+ """Validation test for the ordinate finding computation."""
117
+ param = sigima.objects.TriangleParam.create(xmin=0.0, xmax=10.0, size=101)
118
+ obj = sigima.objects.create_signal_from_param(param)
119
+ if obj is None:
120
+ raise ValueError("Failed to create test signal")
121
+ param = sigima.proc.signal.AbscissaParam.create(x=2.5)
122
+ table = sigima.proc.signal.y_at_x(obj, param)
123
+ assert table is not None, "Y at X computation failed"
124
+ check_scalar_result("y|x=2.5", table["y@x"][0], 1.0)
125
+
126
+
127
+ if __name__ == "__main__":
128
+ guiutils.enable_gui()
129
+ test_signal_bandwidth_3db()
130
+ test_dynamic_parameters()
131
+ test_signal_sampling_rate_period()
132
+ test_signal_contrast()
133
+ test_signal_x_at_minmax()
134
+ test_signal_x_at_y()
135
+ test_signal_y_at_x()