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,290 @@
1
+ # Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.
2
+
3
+ """
4
+ Coordinates objects module
5
+ ==========================
6
+
7
+ Coordinate objects are 2D geometric entities that are used to represent and manipulate
8
+ shapes in a two-dimensional space. Coordinates are typically defined in the physical
9
+ coordinate system (as opposed to the image pixel coordinate system).
10
+ Geometric transformations, such as translation, rotation, and scaling, can be applied
11
+ to those objects to manipulate their position and size.
12
+
13
+ Applications
14
+ ------------
15
+
16
+ Coordinate objects have two main applications:
17
+
18
+ 1. ROIs (Regions of Interest) for image processing tasks.
19
+ 2. Geometry results of signal and image processing tasks.
20
+
21
+ In both cases, geometric transformations can be applied to coordinate objects (rotation,
22
+ translation, horizontal flipping, vertical flipping, transposition, and scaling), in
23
+ order to apply the same transformation as the one applied to the image or signal data.
24
+
25
+ .. note::
26
+
27
+ Geometric transformations currently support only the necessary transformations
28
+ for image processing (not for signal processing).
29
+
30
+ Design choices
31
+ --------------
32
+
33
+ Coordinate objects are built around a `data` attribute that holds the characteristics
34
+ defining the shape in the form of a 1D array:
35
+
36
+ - (x, y) coordinates are stored in a flattened format: (x1, y1, x2, y2, ..., xn, yn)
37
+ - Point coordinates are represented as (x, y).
38
+ - Segment coordinates are represented as (x1, y1, x2, y2),
39
+ where (x1, y1) is the start point and (x2, y2) is the end point.
40
+ - Rectangle coordinates are represented as (x0, y0, dx, dy),
41
+ where (x0, y0) is the top-left corner and (dx, dy) are the width and height.
42
+ - Circle coordinates are represented as (x, y, r),
43
+ where (x, y) is the center and r is the radius.
44
+ - Ellipse coordinates are represented as (x, y, a, b),
45
+ where (x, y) is the center, a is the semi-major axis, and b is the semi-minor axis.
46
+ - Polygon coordinates are represented as a flattened array of (x, y) pairs:
47
+ (x1, y1, x2, y2, ..., xn, yn).
48
+
49
+ At construction, the coordinates are validated to ensure they conform to the expected
50
+ format for each shape type.
51
+ """
52
+
53
+ from __future__ import annotations
54
+
55
+ import abc
56
+
57
+ import numpy as np
58
+
59
+
60
+ class BaseCoordinates(abc.ABC):
61
+ """Base class for 2D coordinates representation of shapes.
62
+
63
+ Args:
64
+ data: 1D array or list of characteristics defining the shape.
65
+ """
66
+
67
+ VALID_SHAPE: tuple[int, int] | None = None # To be defined by subclasses
68
+ REQUIRES_EVEN_NUMBER_OF_VALUES: bool = False
69
+
70
+ def __init__(self, points: np.ndarray | list[int] | list[float]):
71
+ self.data = np.array(points, dtype=float)
72
+ self.validate()
73
+
74
+ def validate(self) -> None:
75
+ """Validate the coordinates.
76
+
77
+ Raises:
78
+ ValueError: If the coordinates are invalid.
79
+ """
80
+ if self.data.ndim != 1:
81
+ raise ValueError(
82
+ f"Invalid {self.__class__.__name__} coordinates ndim: "
83
+ f"{self.data.ndim} (expected 1)"
84
+ )
85
+ if self.VALID_SHAPE is not None and self.data.shape != self.VALID_SHAPE:
86
+ raise ValueError(
87
+ f"Invalid {self.__class__.__name__} coordinates shape: "
88
+ f"{self.data.shape} (expected {self.VALID_SHAPE})"
89
+ )
90
+ if self.REQUIRES_EVEN_NUMBER_OF_VALUES and self.data.size % 2 != 0:
91
+ raise ValueError(
92
+ f"Invalid {self.__class__.__name__} coordinates: "
93
+ f"even number of values expected (got {self.data.size})"
94
+ )
95
+
96
+ def transform_affine(self, matrix: np.ndarray) -> None:
97
+ """Apply a 2D affine transformation to the coordinates inplace.
98
+
99
+ Args:
100
+ matrix: 3x3 affine transformation matrix.
101
+ """
102
+ coords = self.data
103
+ if coords.size % 2 == 0:
104
+ pts = coords.reshape(-1, 2)
105
+ homo = np.c_[pts, np.ones(len(pts))]
106
+ out = (homo @ matrix.T)[:, :2].reshape(-1)
107
+ self.data[:] = out
108
+ else:
109
+ pts = coords[:2].reshape(1, 2)
110
+ homo = np.c_[pts, np.ones(1)]
111
+ out = (homo @ matrix.T)[:, :2].reshape(-1)
112
+ self.data[:2] = out
113
+
114
+ def copy(self) -> BaseCoordinates:
115
+ """Return a copy of the coordinate object.
116
+
117
+ Returns:
118
+ BaseCoordinates: A new object with the same data.
119
+ """
120
+ return self.__class__(self.data.copy())
121
+
122
+ def rotate(self, angle: float, center: tuple[float, float] = (0, 0)) -> None:
123
+ """Rotate coordinates by a given angle around a center inplace.
124
+
125
+ Args:
126
+ angle: Rotation angle in radians (counterclockwise).
127
+ center: Center of rotation (x, y). Defaults to (0, 0).
128
+ """
129
+ cx, cy = center
130
+ c, s = np.cos(angle), np.sin(angle)
131
+ t1 = np.array([[1, 0, -cx], [0, 1, -cy], [0, 0, 1]], float)
132
+ r = np.array([[c, -s, 0], [s, c, 0], [0, 0, 1]], float)
133
+ t2 = np.array([[1, 0, cx], [0, 1, cy], [0, 0, 1]], float)
134
+ matrix = t2 @ r @ t1
135
+ self.transform_affine(matrix)
136
+
137
+ def translate(self, dx: float, dy: float) -> None:
138
+ """Translate coordinates by (dx, dy) inplace.
139
+
140
+ Args:
141
+ dx: Translation along x-axis.
142
+ dy: Translation along y-axis.
143
+ """
144
+ matrix = np.array([[1, 0, dx], [0, 1, dy], [0, 0, 1]], float)
145
+ self.transform_affine(matrix)
146
+
147
+ def fliph(self, cx: float = 0.0) -> None:
148
+ """Flip coordinates horizontally around a vertical line x=cx inplace.
149
+
150
+ Args:
151
+ cx: x-coordinate of the vertical axis. Defaults to 0.0.
152
+ """
153
+ matrix = np.array([[-1, 0, 2 * cx], [0, 1, 0], [0, 0, 1]], float)
154
+ self.transform_affine(matrix)
155
+
156
+ def flipv(self, cy: float = 0.0) -> None:
157
+ """Flip coordinates vertically around a horizontal line y=cy inplace.
158
+
159
+ Args:
160
+ cy: y-coordinate of the horizontal axis. Defaults to 0.0.
161
+ """
162
+ matrix = np.array([[1, 0, 0], [0, -1, 2 * cy], [0, 0, 1]], float)
163
+ self.transform_affine(matrix)
164
+
165
+ def transpose(self) -> None:
166
+ """Transpose coordinates (swap x and y) inplace."""
167
+ matrix = np.array([[0, 1, 0], [1, 0, 0], [0, 0, 1]], float)
168
+ self.transform_affine(matrix)
169
+
170
+ def scale(self, sx: float, sy: float, center: tuple[float, float] = (0, 0)) -> None:
171
+ """Scale coordinates by (sx, sy) around a center inplace.
172
+
173
+ Args:
174
+ sx: Scaling factor along x-axis.
175
+ sy: Scaling factor along y-axis.
176
+ center: Center of scaling (x, y). Defaults to (0, 0).
177
+ """
178
+ cx, cy = center
179
+ t1 = np.array([[1, 0, -cx], [0, 1, -cy], [0, 0, 1]], float)
180
+ s = np.array([[sx, 0, 0], [0, sy, 0], [0, 0, 1]], float)
181
+ t2 = np.array([[1, 0, cx], [0, 1, cy], [0, 0, 1]], float)
182
+ matrix = t2 @ s @ t1
183
+ self.transform_affine(matrix)
184
+
185
+
186
+ class PointCoordinates(BaseCoordinates):
187
+ """Class for point coordinates.
188
+
189
+ Args:
190
+ data: 1D array point coordinates (x, y).
191
+ """
192
+
193
+ VALID_SHAPE = (2,)
194
+
195
+
196
+ class SegmentCoordinates(BaseCoordinates):
197
+ """Class for segment coordinates.
198
+
199
+ Args:
200
+ data: 1D array point coordinates (x1, y1, x2, y2).
201
+ """
202
+
203
+ VALID_SHAPE = (4,)
204
+
205
+
206
+ class RectangleCoordinates(BaseCoordinates):
207
+ """Class for a rectangle coordinates.
208
+
209
+ Args:
210
+ data: 1D array point coordinates (x0, y0, dx, dy).
211
+ """
212
+
213
+ VALID_SHAPE = (4,)
214
+
215
+ def transform_affine(self, matrix: np.ndarray) -> None:
216
+ """
217
+ Apply 2D affine transformation to rectangle coordinates.
218
+
219
+ For rectangles in (x0, y0, dx, dy) format, we transform the corner points
220
+ and then convert back to (x0, y0, dx, dy) format.
221
+
222
+ Args:
223
+ matrix: 3x3 affine transformation matrix.
224
+ """
225
+ x0, y0, dx, dy = self.data
226
+
227
+ # Convert to corner coordinates
228
+ x1, y1 = x0, y0
229
+ x2, y2 = x0 + dx, y0 + dy
230
+
231
+ # Transform both corners
232
+ corners = np.array([[x1, y1], [x2, y2]])
233
+ homo = np.c_[corners, np.ones(2)]
234
+ transformed = (homo @ matrix.T)[:, :2]
235
+
236
+ # Get the new bounding box
237
+ x_min, y_min = transformed.min(axis=0)
238
+ x_max, y_max = transformed.max(axis=0)
239
+
240
+ # Update data with new (x0, y0, dx, dy)
241
+ self.data[:] = [x_min, y_min, x_max - x_min, y_max - y_min]
242
+
243
+ def rotate(self, angle: float, center: tuple[float, float] = (0, 0)) -> None:
244
+ """Rotate rectangle by a given angle around a center.
245
+
246
+ For rectangles, rotation may change the bounding box, so we transform
247
+ all corners and compute the new axis-aligned bounding rectangle.
248
+
249
+ Args:
250
+ angle: Rotation angle in radians (counterclockwise).
251
+ center: Center of rotation (x, y). Defaults to (0, 0).
252
+ """
253
+ cx, cy = center
254
+ c, s = np.cos(angle), np.sin(angle)
255
+ t1 = np.array([[1, 0, -cx], [0, 1, -cy], [0, 0, 1]], float)
256
+ r = np.array([[c, -s, 0], [s, c, 0], [0, 0, 1]], float)
257
+ t2 = np.array([[1, 0, cx], [0, 1, cy], [0, 0, 1]], float)
258
+ matrix = t2 @ r @ t1
259
+ self.transform_affine(matrix)
260
+
261
+
262
+ class CircleCoordinates(BaseCoordinates):
263
+ """Class for a circle coordinates.
264
+
265
+ Args:
266
+ data: 1D array point coordinates (x, y, r).
267
+ """
268
+
269
+ VALID_SHAPE = (3,)
270
+
271
+
272
+ class EllipseCoordinates(BaseCoordinates):
273
+ """Class for an ellipse coordinates.
274
+
275
+ Args:
276
+ data: 1D array point coordinates (x, y, a, b).
277
+ """
278
+
279
+ VALID_SHAPE = (4,)
280
+
281
+
282
+ class PolygonCoordinates(BaseCoordinates):
283
+ """Class for a polygon coordinates.
284
+
285
+ Args:
286
+ data: 1D array point coordinates (x1, y1, x2, y2, ..., xn, yn).
287
+ """
288
+
289
+ VALID_SHAPE = None
290
+ REQUIRES_EVEN_NUMBER_OF_VALUES = True
@@ -0,0 +1,133 @@
1
+ # Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.
2
+
3
+ """
4
+ Signal objects subpackage
5
+ =========================
6
+
7
+ This subpackage provides signal data structures and utilities.
8
+
9
+ The subpackage is organized into the following modules:
10
+
11
+ - `roi`: Region of Interest (ROI) classes and parameters for 1D signals
12
+ - `object`: Main SignalObj class for handling 1D signal data
13
+ - `creation`: Signal creation utilities and parameter classes
14
+
15
+ All classes and functions are re-exported at the subpackage level for backward
16
+ compatibility. Existing imports like `from sigima.objects.signal import SignalObj`
17
+ will continue to work.
18
+ """
19
+
20
+ # Import all public classes and functions from submodules
21
+ from .creation import (
22
+ # Constants
23
+ DEFAULT_TITLE,
24
+ # Mathematical function parameter classes
25
+ BaseGaussLorentzVoigtParam,
26
+ BasePeriodicParam,
27
+ BasePulseParam,
28
+ CosineParam,
29
+ CustomSignalParam,
30
+ # Pulse signal classes
31
+ ExpectedFeatures,
32
+ ExponentialParam,
33
+ FeatureTolerances,
34
+ # Periodic function parameter classes
35
+ FreqUnits,
36
+ GaussParam,
37
+ # Other signal types
38
+ LinearChirpParam,
39
+ LogisticParam,
40
+ LorentzParam,
41
+ # Base parameter classes
42
+ NewSignalParam,
43
+ NormalDistribution1DParam,
44
+ PlanckParam,
45
+ PoissonDistribution1DParam,
46
+ # Polynomial and custom signals
47
+ PolyParam,
48
+ PulseParam,
49
+ SawtoothParam,
50
+ # Enums
51
+ SignalTypes,
52
+ SincParam,
53
+ SineParam,
54
+ SquareParam,
55
+ SquarePulseParam,
56
+ StepParam,
57
+ StepPulseParam,
58
+ TriangleParam,
59
+ UniformDistribution1DParam,
60
+ VoigtParam,
61
+ # Distribution parameter classes
62
+ ZeroParam,
63
+ check_all_signal_parameters_classes,
64
+ # Core creation functions
65
+ create_signal,
66
+ create_signal_from_param,
67
+ # Factory and utility functions
68
+ create_signal_parameters,
69
+ get_next_signal_number,
70
+ # Registration functions
71
+ register_signal_parameters_class,
72
+ triangle_func,
73
+ )
74
+ from .object import (
75
+ # Main signal class
76
+ SignalObj,
77
+ )
78
+ from .roi import (
79
+ # ROI classes
80
+ ROI1DParam,
81
+ SegmentROI,
82
+ SignalROI,
83
+ # ROI functions
84
+ create_signal_roi,
85
+ )
86
+
87
+ # Define __all__ for explicit public API
88
+ __all__ = [
89
+ "DEFAULT_TITLE",
90
+ "BaseGaussLorentzVoigtParam",
91
+ "BasePeriodicParam",
92
+ "BasePulseParam",
93
+ "CosineParam",
94
+ "CustomSignalParam",
95
+ "ExpectedFeatures",
96
+ "ExponentialParam",
97
+ "FeatureTolerances",
98
+ "FreqUnits",
99
+ "GaussParam",
100
+ "LinearChirpParam",
101
+ "LogisticParam",
102
+ "LorentzParam",
103
+ "NewSignalParam",
104
+ "NormalDistribution1DParam",
105
+ "PlanckParam",
106
+ "PoissonDistribution1DParam",
107
+ "PolyParam",
108
+ "PulseParam",
109
+ "ROI1DParam",
110
+ "SawtoothParam",
111
+ "SegmentROI",
112
+ "SignalObj",
113
+ "SignalROI",
114
+ "SignalTypes",
115
+ "SincParam",
116
+ "SineParam",
117
+ "SquareParam",
118
+ "SquarePulseParam",
119
+ "StepParam",
120
+ "StepPulseParam",
121
+ "TriangleParam",
122
+ "UniformDistribution1DParam",
123
+ "VoigtParam",
124
+ "ZeroParam",
125
+ "check_all_signal_parameters_classes",
126
+ "create_signal",
127
+ "create_signal_from_param",
128
+ "create_signal_parameters",
129
+ "create_signal_roi",
130
+ "get_next_signal_number",
131
+ "register_signal_parameters_class",
132
+ "triangle_func",
133
+ ]
@@ -0,0 +1,27 @@
1
+ # Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.
2
+
3
+ """
4
+ Signal I/O constants - especially for datetime metadata handling
5
+ """
6
+
7
+ # Datetime metadata keys
8
+ # These keys are used to store datetime-related information in SignalObj.metadata
9
+ DATETIME_X_KEY = "x_datetime" # Boolean: True if x represents datetime data
10
+ DATETIME_X_FORMAT_KEY = "x_datetime_format" # String: format for display
11
+
12
+ # Time unit conversion factors (to seconds)
13
+ # Used to convert datetime values to float timestamps
14
+ TIME_UNIT_FACTORS = {
15
+ "ns": 1e-9, # nanoseconds
16
+ "us": 1e-6, # microseconds
17
+ "ms": 1e-3, # milliseconds
18
+ "s": 1.0, # seconds (base unit)
19
+ "min": 60.0, # minutes
20
+ "h": 3600.0, # hours
21
+ }
22
+
23
+ # Valid time units (ordered from smallest to largest)
24
+ VALID_TIME_UNITS = list(TIME_UNIT_FACTORS.keys())
25
+
26
+ # Default datetime format string
27
+ DEFAULT_DATETIME_FORMAT = "%Y-%m-%d %H:%M:%S"