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,406 @@
1
+ # Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.
2
+
3
+ """
4
+ Exposure computation module
5
+ ---------------------------
6
+
7
+ This module provides tools for adjusting and analyzing image exposure and contrast.
8
+
9
+ Main features include:
10
+
11
+ - Histogram computation and equalization
12
+ - Contrast adjustment and normalization
13
+ - Logarithmic and gamma correction
14
+
15
+ Exposure processing improves the visual quality and interpretability of images,
16
+ especially under variable lighting conditions.
17
+ """
18
+
19
+ # pylint: disable=invalid-name # Allows short reference names like x, y, ...
20
+
21
+ # Note:
22
+ # ----
23
+ # - All `guidata.dataset.DataSet` parameter classes must also be imported
24
+ # in the `sigima.params` module.
25
+ # - All functions decorated by `computation_function` must be imported in the upper
26
+ # level `sigima.proc.image` module.
27
+
28
+ from __future__ import annotations
29
+
30
+ import guidata.dataset as gds
31
+ import numpy as np
32
+ from skimage import exposure
33
+
34
+ import sigima.enums
35
+ import sigima.tools.image
36
+ from sigima.config import _
37
+ from sigima.objects.base import BaseProcParam
38
+ from sigima.objects.image import ImageObj, ROI2DParam
39
+ from sigima.objects.signal import SignalObj
40
+ from sigima.proc.base import (
41
+ ClipParam,
42
+ HistogramParam,
43
+ NormalizeParam,
44
+ dst_1_to_1,
45
+ dst_2_to_1,
46
+ new_signal_result,
47
+ )
48
+ from sigima.proc.decorator import computation_function
49
+ from sigima.proc.image.base import Wrap1to1Func, restore_data_outside_roi
50
+
51
+ # NOTE: Only parameter classes DEFINED in this module should be included in __all__.
52
+ # Parameter classes imported from other modules (like sigima.proc.base) should NOT
53
+ # be re-exported to avoid Sphinx cross-reference conflicts. The sigima.params module
54
+ # serves as the central API point that imports and re-exports all parameter classes.
55
+ __all__ = [
56
+ "AdjustGammaParam",
57
+ "AdjustLogParam",
58
+ "AdjustSigmoidParam",
59
+ "EqualizeAdaptHistParam",
60
+ "EqualizeHistParam",
61
+ "FlatFieldParam",
62
+ "RescaleIntensityParam",
63
+ "adjust_gamma",
64
+ "adjust_log",
65
+ "adjust_sigmoid",
66
+ "clip",
67
+ "equalize_adapthist",
68
+ "equalize_hist",
69
+ "flatfield",
70
+ "histogram",
71
+ "normalize",
72
+ "offset_correction",
73
+ "rescale_intensity",
74
+ ]
75
+
76
+
77
+ class AdjustGammaParam(gds.DataSet):
78
+ """Gamma adjustment parameters"""
79
+
80
+ gamma = gds.FloatItem(
81
+ _("Gamma"),
82
+ default=1.0,
83
+ min=0.0,
84
+ help=_("Gamma correction factor (higher values give more contrast)."),
85
+ )
86
+ gain = gds.FloatItem(
87
+ _("Gain"),
88
+ default=1.0,
89
+ min=0.0,
90
+ help=_("Gain factor (higher values give more contrast)."),
91
+ )
92
+
93
+
94
+ @computation_function()
95
+ def adjust_gamma(src: ImageObj, p: AdjustGammaParam) -> ImageObj:
96
+ """Gamma correction with :py:func:`skimage.exposure.adjust_gamma`
97
+
98
+ Args:
99
+ src: input image object
100
+ p: parameters
101
+
102
+ Returns:
103
+ Output image object
104
+ """
105
+ dst = dst_1_to_1(src, "adjust_gamma", f"gamma={p.gamma}, gain={p.gain}")
106
+ dst.data = exposure.adjust_gamma(src.data, gamma=p.gamma, gain=p.gain)
107
+ restore_data_outside_roi(dst, src)
108
+ return dst
109
+
110
+
111
+ class AdjustLogParam(gds.DataSet):
112
+ """Logarithmic adjustment parameters"""
113
+
114
+ gain = gds.FloatItem(
115
+ _("Gain"),
116
+ default=1.0,
117
+ min=0.0,
118
+ help=_("Gain factor (higher values give more contrast)."),
119
+ )
120
+ inv = gds.BoolItem(
121
+ _("Inverse"),
122
+ default=False,
123
+ help=_("If True, apply inverse logarithmic transformation."),
124
+ )
125
+
126
+
127
+ @computation_function()
128
+ def adjust_log(src: ImageObj, p: AdjustLogParam) -> ImageObj:
129
+ """Compute log correction with :py:func:`skimage.exposure.adjust_log`
130
+
131
+ Args:
132
+ src: input image object
133
+ p: parameters
134
+
135
+ Returns:
136
+ Output image object
137
+ """
138
+ dst = dst_1_to_1(src, "adjust_log", f"gain={p.gain}, inv={p.inv}")
139
+ dst.data = exposure.adjust_log(src.data, gain=p.gain, inv=p.inv)
140
+ restore_data_outside_roi(dst, src)
141
+ return dst
142
+
143
+
144
+ class AdjustSigmoidParam(gds.DataSet):
145
+ """Sigmoid adjustment parameters"""
146
+
147
+ cutoff = gds.FloatItem(
148
+ _("Cutoff"),
149
+ default=0.5,
150
+ min=0.0,
151
+ max=1.0,
152
+ help=_("Cutoff value (higher values give more contrast)."),
153
+ )
154
+ gain = gds.FloatItem(
155
+ _("Gain"),
156
+ default=10.0,
157
+ min=0.0,
158
+ help=_("Gain factor (higher values give more contrast)."),
159
+ )
160
+ inv = gds.BoolItem(
161
+ _("Inverse"),
162
+ default=False,
163
+ help=_("If True, apply inverse sigmoid transformation."),
164
+ )
165
+
166
+
167
+ @computation_function()
168
+ def adjust_sigmoid(src: ImageObj, p: AdjustSigmoidParam) -> ImageObj:
169
+ """Compute sigmoid correction with :py:func:`skimage.exposure.adjust_sigmoid`
170
+
171
+ Args:
172
+ src: input image object
173
+ p: parameters
174
+
175
+ Returns:
176
+ Output image object
177
+ """
178
+ dst = dst_1_to_1(
179
+ src, "adjust_sigmoid", f"cutoff={p.cutoff}, gain={p.gain}, inv={p.inv}"
180
+ )
181
+ dst.data = exposure.adjust_sigmoid(
182
+ src.data, cutoff=p.cutoff, gain=p.gain, inv=p.inv
183
+ )
184
+ restore_data_outside_roi(dst, src)
185
+ return dst
186
+
187
+
188
+ class RescaleIntensityParam(gds.DataSet):
189
+ """Intensity rescaling parameters"""
190
+
191
+ _dtype_list = ["image", "dtype"] + ImageObj.get_valid_dtypenames()
192
+ in_range = gds.ChoiceItem(
193
+ _("Input range"),
194
+ list(zip(_dtype_list, _dtype_list)),
195
+ default="image",
196
+ help=_(
197
+ "Min and max intensity values of input image ('image' refers to input "
198
+ "image min/max levels, 'dtype' refers to input image data type range)."
199
+ ),
200
+ )
201
+ out_range = gds.ChoiceItem(
202
+ _("Output range"),
203
+ list(zip(_dtype_list, _dtype_list)),
204
+ default="dtype",
205
+ help=_(
206
+ "Min and max intensity values of output image ('image' refers to input "
207
+ "image min/max levels, 'dtype' refers to input image data type range).."
208
+ ),
209
+ )
210
+
211
+
212
+ @computation_function()
213
+ def rescale_intensity(src: ImageObj, p: RescaleIntensityParam) -> ImageObj:
214
+ """Rescale image intensity levels
215
+ with :py:func:`skimage.exposure.rescale_intensity`
216
+
217
+ Args:
218
+ src: input image object
219
+ p: parameters
220
+
221
+ Returns:
222
+ Output image object
223
+ """
224
+ dst = dst_1_to_1(
225
+ src,
226
+ "rescale_intensity",
227
+ f"in_range={p.in_range}, out_range={p.out_range}",
228
+ )
229
+ dst.data = exposure.rescale_intensity(
230
+ src.data, in_range=p.in_range, out_range=p.out_range
231
+ )
232
+ restore_data_outside_roi(dst, src)
233
+ return dst
234
+
235
+
236
+ class EqualizeHistParam(gds.DataSet):
237
+ """Histogram equalization parameters"""
238
+
239
+ nbins = gds.IntItem(
240
+ _("Number of bins"),
241
+ min=1,
242
+ default=256,
243
+ help=_("Number of bins for image histogram."),
244
+ )
245
+
246
+
247
+ @computation_function()
248
+ def equalize_hist(src: ImageObj, p: EqualizeHistParam) -> ImageObj:
249
+ """Histogram equalization with :py:func:`skimage.exposure.equalize_hist`
250
+
251
+ Args:
252
+ src: input image object
253
+ p: parameters
254
+
255
+ Returns:
256
+ Output image object
257
+ """
258
+ dst = dst_1_to_1(src, "equalize_hist", f"nbins={p.nbins}")
259
+ dst.data = exposure.equalize_hist(src.data, nbins=p.nbins)
260
+ restore_data_outside_roi(dst, src)
261
+ return dst
262
+
263
+
264
+ class EqualizeAdaptHistParam(EqualizeHistParam):
265
+ """Adaptive histogram equalization parameters"""
266
+
267
+ clip_limit = gds.FloatItem(
268
+ _("Clipping limit"),
269
+ default=0.01,
270
+ min=0.0,
271
+ max=1.0,
272
+ help=_("Clipping limit (higher values give more contrast)."),
273
+ )
274
+
275
+
276
+ @computation_function()
277
+ def equalize_adapthist(src: ImageObj, p: EqualizeAdaptHistParam) -> ImageObj:
278
+ """Adaptive histogram equalization
279
+ with :py:func:`skimage.exposure.equalize_adapthist`
280
+
281
+ Args:
282
+ src: input image object
283
+ p: parameters
284
+
285
+ Returns:
286
+ Output image object
287
+ """
288
+ dst = dst_1_to_1(
289
+ src, "equalize_adapthist", f"nbins={p.nbins}, clip_limit={p.clip_limit}"
290
+ )
291
+ dst.data = exposure.equalize_adapthist(
292
+ src.data, clip_limit=p.clip_limit, nbins=p.nbins
293
+ )
294
+ restore_data_outside_roi(dst, src)
295
+ return dst
296
+
297
+
298
+ class FlatFieldParam(BaseProcParam):
299
+ """Flat-field parameters"""
300
+
301
+ threshold = gds.FloatItem(_("Threshold"), default=0.0)
302
+
303
+ def update_from_obj(self, obj: ImageObj) -> None:
304
+ """Update parameters from image"""
305
+ self.set_from_datatype(obj.data.dtype)
306
+
307
+
308
+ @computation_function()
309
+ def flatfield(src1: ImageObj, src2: ImageObj, p: FlatFieldParam) -> ImageObj:
310
+ """Compute flat field correction with :py:func:`sigima.tools.image.flatfield`
311
+
312
+ Args:
313
+ src1: raw data image object
314
+ src2: flat field image object
315
+ p: flat field parameters
316
+
317
+ Returns:
318
+ Output image object
319
+ """
320
+ dst = dst_2_to_1(src1, src2, "flatfield", f"threshold={p.threshold}")
321
+ dst.data = sigima.tools.image.flatfield(src1.data, src2.data, p.threshold)
322
+ restore_data_outside_roi(dst, src1)
323
+ return dst
324
+
325
+
326
+ # MARK: compute_1_to_1 functions -------------------------------------------------------
327
+ # Functions with 1 input image and 1 output image
328
+ # --------------------------------------------------------------------------------------
329
+
330
+
331
+ @computation_function()
332
+ def normalize(src: ImageObj, p: NormalizeParam) -> ImageObj:
333
+ """
334
+ Normalize image data depending on its maximum,
335
+ with :py:func:`sigima.tools.image.normalize`
336
+
337
+ Args:
338
+ src: input image object
339
+
340
+ Returns:
341
+ Output image object
342
+ """
343
+ method: sigima.enums.NormalizationMethod = p.method
344
+ dst = dst_1_to_1(src, "normalize", suffix=f"ref={method.value}")
345
+ dst.data = sigima.tools.image.normalize(src.data, method)
346
+ restore_data_outside_roi(dst, src)
347
+ return dst
348
+
349
+
350
+ @computation_function()
351
+ def histogram(src: ImageObj, p: HistogramParam) -> SignalObj:
352
+ """Compute histogram of the image data, with :py:func:`numpy.histogram`
353
+
354
+ Args:
355
+ src: input image object
356
+ p: parameters
357
+
358
+ Returns:
359
+ Signal object with the histogram
360
+ """
361
+ data = src.get_masked_view().compressed()
362
+ suffix = p.get_suffix(data) # Also updates p.lower and p.upper
363
+ y, bin_edges = np.histogram(data, bins=p.bins, range=(p.lower, p.upper))
364
+ x = (bin_edges[:-1] + bin_edges[1:]) / 2
365
+ dst = new_signal_result(
366
+ src,
367
+ "histogram",
368
+ suffix=suffix,
369
+ units=(src.zunit, ""),
370
+ labels=(src.zlabel, _("Counts")),
371
+ )
372
+ dst.set_xydata(x, y)
373
+ dst.set_metadata_option("shade", 0.5)
374
+ dst.set_metadata_option("curvestyle", "Steps")
375
+ return dst
376
+
377
+
378
+ @computation_function()
379
+ def clip(src: ImageObj, p: ClipParam) -> ImageObj:
380
+ """Apply clipping with :py:func:`numpy.clip`
381
+
382
+ Args:
383
+ src: input image object
384
+ p: parameters
385
+
386
+ Returns:
387
+ Output image object
388
+ """
389
+ return Wrap1to1Func(np.clip, a_min=p.lower, a_max=p.upper)(src)
390
+
391
+
392
+ @computation_function()
393
+ def offset_correction(src: ImageObj, p: ROI2DParam) -> ImageObj:
394
+ """Apply offset correction
395
+
396
+ Args:
397
+ src: input image object
398
+ p: parameters
399
+
400
+ Returns:
401
+ Output image object
402
+ """
403
+ dst = dst_1_to_1(src, "offset_correction", p.get_suffix())
404
+ dst.data = src.data - np.nanmean(p.get_data(src))
405
+ restore_data_outside_roi(dst, src)
406
+ return dst