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.
- sigima/__init__.py +142 -2
- sigima/client/__init__.py +105 -0
- sigima/client/base.py +780 -0
- sigima/client/remote.py +469 -0
- sigima/client/stub.py +814 -0
- sigima/client/utils.py +90 -0
- sigima/config.py +444 -0
- sigima/data/logo/Sigima.svg +135 -0
- sigima/data/tests/annotations.json +798 -0
- sigima/data/tests/curve_fitting/exponential_fit.txt +511 -0
- sigima/data/tests/curve_fitting/gaussian_fit.txt +100 -0
- sigima/data/tests/curve_fitting/piecewiseexponential_fit.txt +1022 -0
- sigima/data/tests/curve_fitting/polynomial_fit.txt +100 -0
- sigima/data/tests/curve_fitting/twohalfgaussian_fit.txt +1000 -0
- sigima/data/tests/curve_formats/bandwidth.txt +201 -0
- sigima/data/tests/curve_formats/boxcar.npy +0 -0
- sigima/data/tests/curve_formats/datetime.txt +1001 -0
- sigima/data/tests/curve_formats/dynamic_parameters.txt +4000 -0
- sigima/data/tests/curve_formats/fw1e2.txt +301 -0
- sigima/data/tests/curve_formats/fwhm.txt +319 -0
- sigima/data/tests/curve_formats/multiple_curves.csv +29 -0
- sigima/data/tests/curve_formats/noised_saw.mat +0 -0
- sigima/data/tests/curve_formats/oscilloscope.csv +111 -0
- sigima/data/tests/curve_formats/other/other2/recursive2.txt +5 -0
- sigima/data/tests/curve_formats/other/recursive1.txt +5 -0
- sigima/data/tests/curve_formats/paracetamol.npy +0 -0
- sigima/data/tests/curve_formats/paracetamol.txt +1010 -0
- sigima/data/tests/curve_formats/paracetamol_dx_dy.csv +1000 -0
- sigima/data/tests/curve_formats/paracetamol_dy.csv +1001 -0
- sigima/data/tests/curve_formats/pulse1.npy +0 -0
- sigima/data/tests/curve_formats/pulse2.npy +0 -0
- sigima/data/tests/curve_formats/simple.txt +5 -0
- sigima/data/tests/curve_formats/spectrum.mca +2139 -0
- sigima/data/tests/curve_formats/square2.npy +0 -0
- sigima/data/tests/curve_formats/step.npy +0 -0
- sigima/data/tests/fabry-perot1.jpg +0 -0
- sigima/data/tests/fabry-perot2.jpg +0 -0
- sigima/data/tests/flower.npy +0 -0
- sigima/data/tests/image_formats/NF 180338201.scor-data +11003 -0
- sigima/data/tests/image_formats/binary_image.npy +0 -0
- sigima/data/tests/image_formats/binary_image.png +0 -0
- sigima/data/tests/image_formats/centroid_test.npy +0 -0
- sigima/data/tests/image_formats/coordinated_text/complex_image.txt +10011 -0
- sigima/data/tests/image_formats/coordinated_text/complex_ref_image.txt +10010 -0
- sigima/data/tests/image_formats/coordinated_text/image.txt +15 -0
- sigima/data/tests/image_formats/coordinated_text/image2.txt +14 -0
- sigima/data/tests/image_formats/coordinated_text/image_no_unit_no_label.txt +14 -0
- sigima/data/tests/image_formats/coordinated_text/image_with_nan.txt +15 -0
- sigima/data/tests/image_formats/coordinated_text/image_with_unit.txt +14 -0
- sigima/data/tests/image_formats/fiber.csv +480 -0
- sigima/data/tests/image_formats/fiber.jpg +0 -0
- sigima/data/tests/image_formats/fiber.png +0 -0
- sigima/data/tests/image_formats/fiber.txt +480 -0
- sigima/data/tests/image_formats/gaussian_spot_with_noise.npy +0 -0
- sigima/data/tests/image_formats/mr-brain.dcm +0 -0
- sigima/data/tests/image_formats/noised_gaussian.mat +0 -0
- sigima/data/tests/image_formats/sif_reader/nd_lum_image_no_glue.sif +0 -0
- sigima/data/tests/image_formats/sif_reader/raman1.sif +0 -0
- sigima/data/tests/image_formats/tiling.txt +10 -0
- sigima/data/tests/image_formats/uint16.tiff +0 -0
- sigima/data/tests/image_formats/uint8.tiff +0 -0
- sigima/data/tests/laser_beam/TEM00_z_13.jpg +0 -0
- sigima/data/tests/laser_beam/TEM00_z_18.jpg +0 -0
- sigima/data/tests/laser_beam/TEM00_z_23.jpg +0 -0
- sigima/data/tests/laser_beam/TEM00_z_30.jpg +0 -0
- sigima/data/tests/laser_beam/TEM00_z_35.jpg +0 -0
- sigima/data/tests/laser_beam/TEM00_z_40.jpg +0 -0
- sigima/data/tests/laser_beam/TEM00_z_45.jpg +0 -0
- sigima/data/tests/laser_beam/TEM00_z_50.jpg +0 -0
- sigima/data/tests/laser_beam/TEM00_z_55.jpg +0 -0
- sigima/data/tests/laser_beam/TEM00_z_60.jpg +0 -0
- sigima/data/tests/laser_beam/TEM00_z_65.jpg +0 -0
- sigima/data/tests/laser_beam/TEM00_z_70.jpg +0 -0
- sigima/data/tests/laser_beam/TEM00_z_75.jpg +0 -0
- sigima/data/tests/laser_beam/TEM00_z_80.jpg +0 -0
- sigima/enums.py +195 -0
- sigima/io/__init__.py +123 -0
- sigima/io/base.py +311 -0
- sigima/io/common/__init__.py +5 -0
- sigima/io/common/basename.py +164 -0
- sigima/io/common/converters.py +189 -0
- sigima/io/common/objmeta.py +181 -0
- sigima/io/common/textreader.py +58 -0
- sigima/io/convenience.py +157 -0
- sigima/io/enums.py +17 -0
- sigima/io/ftlab.py +395 -0
- sigima/io/image/__init__.py +9 -0
- sigima/io/image/base.py +177 -0
- sigima/io/image/formats.py +1016 -0
- sigima/io/image/funcs.py +414 -0
- sigima/io/signal/__init__.py +9 -0
- sigima/io/signal/base.py +129 -0
- sigima/io/signal/formats.py +290 -0
- sigima/io/signal/funcs.py +723 -0
- sigima/objects/__init__.py +260 -0
- sigima/objects/base.py +937 -0
- sigima/objects/image/__init__.py +88 -0
- sigima/objects/image/creation.py +556 -0
- sigima/objects/image/object.py +524 -0
- sigima/objects/image/roi.py +904 -0
- sigima/objects/scalar/__init__.py +57 -0
- sigima/objects/scalar/common.py +215 -0
- sigima/objects/scalar/geometry.py +502 -0
- sigima/objects/scalar/table.py +784 -0
- sigima/objects/shape.py +290 -0
- sigima/objects/signal/__init__.py +133 -0
- sigima/objects/signal/constants.py +27 -0
- sigima/objects/signal/creation.py +1428 -0
- sigima/objects/signal/object.py +444 -0
- sigima/objects/signal/roi.py +274 -0
- sigima/params.py +405 -0
- sigima/proc/__init__.py +96 -0
- sigima/proc/base.py +381 -0
- sigima/proc/decorator.py +330 -0
- sigima/proc/image/__init__.py +513 -0
- sigima/proc/image/arithmetic.py +335 -0
- sigima/proc/image/base.py +260 -0
- sigima/proc/image/detection.py +519 -0
- sigima/proc/image/edges.py +329 -0
- sigima/proc/image/exposure.py +406 -0
- sigima/proc/image/extraction.py +458 -0
- sigima/proc/image/filtering.py +219 -0
- sigima/proc/image/fourier.py +147 -0
- sigima/proc/image/geometry.py +661 -0
- sigima/proc/image/mathops.py +340 -0
- sigima/proc/image/measurement.py +195 -0
- sigima/proc/image/morphology.py +155 -0
- sigima/proc/image/noise.py +107 -0
- sigima/proc/image/preprocessing.py +182 -0
- sigima/proc/image/restoration.py +235 -0
- sigima/proc/image/threshold.py +217 -0
- sigima/proc/image/transformations.py +393 -0
- sigima/proc/signal/__init__.py +376 -0
- sigima/proc/signal/analysis.py +206 -0
- sigima/proc/signal/arithmetic.py +551 -0
- sigima/proc/signal/base.py +262 -0
- sigima/proc/signal/extraction.py +60 -0
- sigima/proc/signal/features.py +310 -0
- sigima/proc/signal/filtering.py +484 -0
- sigima/proc/signal/fitting.py +276 -0
- sigima/proc/signal/fourier.py +259 -0
- sigima/proc/signal/mathops.py +420 -0
- sigima/proc/signal/processing.py +580 -0
- sigima/proc/signal/stability.py +175 -0
- sigima/proc/title_formatting.py +227 -0
- sigima/proc/validation.py +272 -0
- sigima/tests/__init__.py +7 -0
- sigima/tests/common/__init__.py +0 -0
- sigima/tests/common/arithmeticparam_unit_test.py +26 -0
- sigima/tests/common/basename_unit_test.py +126 -0
- sigima/tests/common/client_unit_test.py +412 -0
- sigima/tests/common/converters_unit_test.py +77 -0
- sigima/tests/common/decorator_unit_test.py +176 -0
- sigima/tests/common/examples_unit_test.py +104 -0
- sigima/tests/common/kernel_normalization_unit_test.py +242 -0
- sigima/tests/common/roi_basic_unit_test.py +73 -0
- sigima/tests/common/roi_geometry_unit_test.py +171 -0
- sigima/tests/common/scalar_builder_unit_test.py +142 -0
- sigima/tests/common/scalar_unit_test.py +991 -0
- sigima/tests/common/shape_unit_test.py +183 -0
- sigima/tests/common/stat_unit_test.py +138 -0
- sigima/tests/common/title_formatting_unit_test.py +338 -0
- sigima/tests/common/tools_coordinates_unit_test.py +60 -0
- sigima/tests/common/transformations_unit_test.py +178 -0
- sigima/tests/common/validation_unit_test.py +205 -0
- sigima/tests/conftest.py +129 -0
- sigima/tests/data.py +998 -0
- sigima/tests/env.py +280 -0
- sigima/tests/guiutils.py +163 -0
- sigima/tests/helpers.py +532 -0
- sigima/tests/image/__init__.py +28 -0
- sigima/tests/image/binning_unit_test.py +128 -0
- sigima/tests/image/blob_detection_unit_test.py +312 -0
- sigima/tests/image/centroid_unit_test.py +170 -0
- sigima/tests/image/check_2d_array_unit_test.py +63 -0
- sigima/tests/image/contour_unit_test.py +172 -0
- sigima/tests/image/convolution_unit_test.py +178 -0
- sigima/tests/image/datatype_unit_test.py +67 -0
- sigima/tests/image/edges_unit_test.py +155 -0
- sigima/tests/image/enclosingcircle_unit_test.py +88 -0
- sigima/tests/image/exposure_unit_test.py +223 -0
- sigima/tests/image/fft2d_unit_test.py +189 -0
- sigima/tests/image/filtering_unit_test.py +166 -0
- sigima/tests/image/geometry_unit_test.py +654 -0
- sigima/tests/image/hough_circle_unit_test.py +147 -0
- sigima/tests/image/imageobj_unit_test.py +737 -0
- sigima/tests/image/morphology_unit_test.py +71 -0
- sigima/tests/image/noise_unit_test.py +57 -0
- sigima/tests/image/offset_correction_unit_test.py +72 -0
- sigima/tests/image/operation_unit_test.py +518 -0
- sigima/tests/image/peak2d_limits_unit_test.py +41 -0
- sigima/tests/image/peak2d_unit_test.py +133 -0
- sigima/tests/image/profile_unit_test.py +159 -0
- sigima/tests/image/projections_unit_test.py +121 -0
- sigima/tests/image/restoration_unit_test.py +141 -0
- sigima/tests/image/roi2dparam_unit_test.py +53 -0
- sigima/tests/image/roi_advanced_unit_test.py +588 -0
- sigima/tests/image/roi_grid_unit_test.py +279 -0
- sigima/tests/image/spectrum2d_unit_test.py +40 -0
- sigima/tests/image/threshold_unit_test.py +91 -0
- sigima/tests/io/__init__.py +0 -0
- sigima/tests/io/addnewformat_unit_test.py +125 -0
- sigima/tests/io/convenience_funcs_unit_test.py +470 -0
- sigima/tests/io/coordinated_text_format_unit_test.py +495 -0
- sigima/tests/io/datetime_csv_unit_test.py +198 -0
- sigima/tests/io/imageio_formats_test.py +41 -0
- sigima/tests/io/ioregistry_unit_test.py +69 -0
- sigima/tests/io/objmeta_unit_test.py +87 -0
- sigima/tests/io/readobj_unit_test.py +130 -0
- sigima/tests/io/readwriteobj_unit_test.py +67 -0
- sigima/tests/signal/__init__.py +0 -0
- sigima/tests/signal/analysis_unit_test.py +135 -0
- sigima/tests/signal/check_1d_arrays_unit_test.py +169 -0
- sigima/tests/signal/convolution_unit_test.py +404 -0
- sigima/tests/signal/datetime_unit_test.py +176 -0
- sigima/tests/signal/fft1d_unit_test.py +303 -0
- sigima/tests/signal/filters_unit_test.py +403 -0
- sigima/tests/signal/fitting_unit_test.py +929 -0
- sigima/tests/signal/fwhm_unit_test.py +111 -0
- sigima/tests/signal/noise_unit_test.py +128 -0
- sigima/tests/signal/offset_correction_unit_test.py +34 -0
- sigima/tests/signal/operation_unit_test.py +489 -0
- sigima/tests/signal/peakdetection_unit_test.py +145 -0
- sigima/tests/signal/processing_unit_test.py +657 -0
- sigima/tests/signal/pulse/__init__.py +112 -0
- sigima/tests/signal/pulse/crossing_times_unit_test.py +123 -0
- sigima/tests/signal/pulse/plateau_detection_unit_test.py +102 -0
- sigima/tests/signal/pulse/pulse_unit_test.py +1824 -0
- sigima/tests/signal/roi_advanced_unit_test.py +392 -0
- sigima/tests/signal/signalobj_unit_test.py +603 -0
- sigima/tests/signal/stability_unit_test.py +431 -0
- sigima/tests/signal/uncertainty_unit_test.py +611 -0
- sigima/tests/vistools.py +1030 -0
- sigima/tools/__init__.py +59 -0
- sigima/tools/checks.py +290 -0
- sigima/tools/coordinates.py +308 -0
- sigima/tools/datatypes.py +26 -0
- sigima/tools/image/__init__.py +97 -0
- sigima/tools/image/detection.py +451 -0
- sigima/tools/image/exposure.py +77 -0
- sigima/tools/image/extraction.py +48 -0
- sigima/tools/image/fourier.py +260 -0
- sigima/tools/image/geometry.py +190 -0
- sigima/tools/image/preprocessing.py +165 -0
- sigima/tools/signal/__init__.py +86 -0
- sigima/tools/signal/dynamic.py +254 -0
- sigima/tools/signal/features.py +135 -0
- sigima/tools/signal/filtering.py +171 -0
- sigima/tools/signal/fitting.py +1171 -0
- sigima/tools/signal/fourier.py +466 -0
- sigima/tools/signal/interpolation.py +70 -0
- sigima/tools/signal/peakdetection.py +126 -0
- sigima/tools/signal/pulse.py +1626 -0
- sigima/tools/signal/scaling.py +50 -0
- sigima/tools/signal/stability.py +258 -0
- sigima/tools/signal/windowing.py +90 -0
- sigima/worker.py +79 -0
- sigima-1.0.0.dist-info/METADATA +233 -0
- sigima-1.0.0.dist-info/RECORD +262 -0
- {sigima-0.0.1.dev0.dist-info → sigima-1.0.0.dist-info}/licenses/LICENSE +29 -29
- sigima-0.0.1.dev0.dist-info/METADATA +0 -60
- sigima-0.0.1.dev0.dist-info/RECORD +0 -6
- {sigima-0.0.1.dev0.dist-info → sigima-1.0.0.dist-info}/WHEEL +0 -0
- {sigima-0.0.1.dev0.dist-info → sigima-1.0.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
# Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.
|
|
2
|
+
|
|
3
|
+
"""Test ROI geometry transformations"""
|
|
4
|
+
|
|
5
|
+
import numpy as np
|
|
6
|
+
|
|
7
|
+
from sigima.objects.image import ImageObj, ImageROI, RectangularROI
|
|
8
|
+
from sigima.proc.image import fliph, flipv, rotate90, rotate270, transpose
|
|
9
|
+
from sigima.tests.env import execenv
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def test_roi_rotate90() -> None:
|
|
13
|
+
"""Test ROI transformation with 90° rotation."""
|
|
14
|
+
# Create test image
|
|
15
|
+
data = np.random.rand(100, 80) # Height=100, Width=80
|
|
16
|
+
img = ImageObj(title="Test Image")
|
|
17
|
+
img.data = data
|
|
18
|
+
|
|
19
|
+
# Create rectangular ROI
|
|
20
|
+
roi_obj = ImageROI()
|
|
21
|
+
single_roi = RectangularROI([10, 20, 20, 20], indices=False) # x0, y0, dx, dy
|
|
22
|
+
roi_obj.add_roi(single_roi)
|
|
23
|
+
img.roi = roi_obj
|
|
24
|
+
|
|
25
|
+
# Apply rotation
|
|
26
|
+
img_rotated = rotate90(img)
|
|
27
|
+
roi_rotated = img_rotated.roi.single_rois[0]
|
|
28
|
+
|
|
29
|
+
# Verify ROI is properly transformed and dimensions change
|
|
30
|
+
assert img_rotated.roi is not None, "90° rotation should preserve ROI object"
|
|
31
|
+
assert len(img_rotated.roi.single_rois) == 1, (
|
|
32
|
+
"90° rotation should preserve ROI count"
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
# The exact coordinates depend on the transformation, but the ROI should be valid
|
|
36
|
+
coords_rotated = roi_rotated.get_physical_coords(img_rotated)
|
|
37
|
+
assert len(coords_rotated) == 4, "Rectangular ROI should have 4 coordinates"
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def test_roi_rotate270() -> None:
|
|
41
|
+
"""Test ROI transformation with 270° rotation."""
|
|
42
|
+
# Create test image
|
|
43
|
+
data = np.random.rand(100, 80)
|
|
44
|
+
img = ImageObj(title="Test Image")
|
|
45
|
+
img.data = data
|
|
46
|
+
|
|
47
|
+
# Create rectangular ROI
|
|
48
|
+
roi_obj = ImageROI()
|
|
49
|
+
single_roi = RectangularROI([10, 20, 20, 20], indices=False)
|
|
50
|
+
roi_obj.add_roi(single_roi)
|
|
51
|
+
img.roi = roi_obj
|
|
52
|
+
|
|
53
|
+
# Apply rotation
|
|
54
|
+
img_rotated = rotate270(img)
|
|
55
|
+
|
|
56
|
+
# Verify ROI is properly transformed
|
|
57
|
+
assert img_rotated.roi is not None, "270° rotation should preserve ROI object"
|
|
58
|
+
assert len(img_rotated.roi.single_rois) == 1, (
|
|
59
|
+
"270° rotation should preserve ROI count"
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def test_roi_fliph() -> None:
|
|
64
|
+
"""Test ROI transformation with horizontal flip."""
|
|
65
|
+
# Create test image
|
|
66
|
+
data = np.random.rand(100, 80)
|
|
67
|
+
img = ImageObj(title="Test Image")
|
|
68
|
+
img.data = data
|
|
69
|
+
|
|
70
|
+
# Create rectangular ROI
|
|
71
|
+
roi_obj = ImageROI()
|
|
72
|
+
single_roi = RectangularROI([10, 20, 20, 20], indices=False)
|
|
73
|
+
roi_obj.add_roi(single_roi)
|
|
74
|
+
img.roi = roi_obj
|
|
75
|
+
|
|
76
|
+
# Apply flip
|
|
77
|
+
img_flipped = fliph(img)
|
|
78
|
+
|
|
79
|
+
# Verify ROI is properly transformed
|
|
80
|
+
assert img_flipped.roi is not None, "Horizontal flip should preserve ROI object"
|
|
81
|
+
assert len(img_flipped.roi.single_rois) == 1, (
|
|
82
|
+
"Horizontal flip should preserve ROI count"
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def test_roi_flipv() -> None:
|
|
87
|
+
"""Test ROI transformation with vertical flip."""
|
|
88
|
+
# Create test image
|
|
89
|
+
data = np.random.rand(100, 80)
|
|
90
|
+
img = ImageObj(title="Test Image")
|
|
91
|
+
img.data = data
|
|
92
|
+
|
|
93
|
+
# Create rectangular ROI
|
|
94
|
+
roi_obj = ImageROI()
|
|
95
|
+
single_roi = RectangularROI([10, 20, 20, 20], indices=False)
|
|
96
|
+
roi_obj.add_roi(single_roi)
|
|
97
|
+
img.roi = roi_obj
|
|
98
|
+
|
|
99
|
+
# Apply flip
|
|
100
|
+
img_flipped = flipv(img)
|
|
101
|
+
|
|
102
|
+
# Verify ROI is properly transformed
|
|
103
|
+
assert img_flipped.roi is not None, "Vertical flip should preserve ROI object"
|
|
104
|
+
assert len(img_flipped.roi.single_rois) == 1, (
|
|
105
|
+
"Vertical flip should preserve ROI count"
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def test_roi_transpose() -> None:
|
|
110
|
+
"""Test ROI transformation with transpose."""
|
|
111
|
+
# Create test image
|
|
112
|
+
data = np.random.rand(100, 80)
|
|
113
|
+
img = ImageObj(title="Test Image")
|
|
114
|
+
img.data = data
|
|
115
|
+
|
|
116
|
+
# Create rectangular ROI
|
|
117
|
+
roi_obj = ImageROI()
|
|
118
|
+
single_roi = RectangularROI([10, 20, 20, 20], indices=False)
|
|
119
|
+
roi_obj.add_roi(single_roi)
|
|
120
|
+
img.roi = roi_obj
|
|
121
|
+
|
|
122
|
+
# Apply transpose
|
|
123
|
+
img_transposed = transpose(img)
|
|
124
|
+
|
|
125
|
+
# Verify ROI is properly transformed
|
|
126
|
+
assert img_transposed.roi is not None, "Transpose should preserve ROI object"
|
|
127
|
+
assert len(img_transposed.roi.single_rois) == 1, (
|
|
128
|
+
"Transpose should preserve ROI count"
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def test_roi_comprehensive() -> None:
|
|
133
|
+
"""Comprehensive test for all ROI transformations."""
|
|
134
|
+
execenv.print("Testing ROI geometry transformations:")
|
|
135
|
+
|
|
136
|
+
# Create test image
|
|
137
|
+
data = np.random.rand(100, 80) # Height=100, Width=80
|
|
138
|
+
img = ImageObj(title="Test Image")
|
|
139
|
+
img.data = data
|
|
140
|
+
|
|
141
|
+
# Create rectangular ROI
|
|
142
|
+
roi_obj = ImageROI()
|
|
143
|
+
single_roi = RectangularROI([10, 20, 20, 20], indices=False)
|
|
144
|
+
roi_obj.add_roi(single_roi)
|
|
145
|
+
img.roi = roi_obj
|
|
146
|
+
|
|
147
|
+
coords_original = single_roi.get_physical_coords(img)
|
|
148
|
+
execenv.print(f" Original ROI: {coords_original}")
|
|
149
|
+
|
|
150
|
+
# Test all transformations
|
|
151
|
+
transformations = [
|
|
152
|
+
(rotate90, "rotate90"),
|
|
153
|
+
(rotate270, "rotate270"),
|
|
154
|
+
(fliph, "fliph"),
|
|
155
|
+
(flipv, "flipv"),
|
|
156
|
+
(transpose, "transpose"),
|
|
157
|
+
]
|
|
158
|
+
|
|
159
|
+
for transform_func, name in transformations:
|
|
160
|
+
img_transformed = transform_func(img)
|
|
161
|
+
roi_transformed = img_transformed.roi.single_rois[0]
|
|
162
|
+
coords_transformed = roi_transformed.get_physical_coords(img_transformed)
|
|
163
|
+
execenv.print(f" {name}: {coords_transformed}")
|
|
164
|
+
|
|
165
|
+
# Verify ROI is properly transformed
|
|
166
|
+
assert img_transformed.roi is not None, f"{name} should preserve ROI object"
|
|
167
|
+
assert len(img_transformed.roi.single_rois) == 1, (
|
|
168
|
+
f"{name} should preserve ROI count"
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
execenv.print(" ✅ All ROI transformations working correctly")
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
Unit tests for TableResultBuilder (sigima.objects.scalar).
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from numpy import ma
|
|
8
|
+
|
|
9
|
+
from sigima.objects.scalar import TableResultBuilder
|
|
10
|
+
from sigima.objects.signal import SignalObj
|
|
11
|
+
from sigima.tests.data import create_paracetamol_signal, create_test_signal_rois
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def create_dummy_signal() -> SignalObj:
|
|
15
|
+
"""Create a simple SignalObj with a single ROI."""
|
|
16
|
+
sig = create_paracetamol_signal()
|
|
17
|
+
roi = list(create_test_signal_rois(sig))[0]
|
|
18
|
+
sig.roi = roi
|
|
19
|
+
return sig
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class TestTableResultBuilder:
|
|
23
|
+
"""Test class for TableResultBuilder basic functionality."""
|
|
24
|
+
|
|
25
|
+
def test_basic_functionality(self) -> None:
|
|
26
|
+
"""Test basic TableResultBuilder API with a SignalObj."""
|
|
27
|
+
sig = create_dummy_signal()
|
|
28
|
+
|
|
29
|
+
builder = TableResultBuilder("Signal Stats")
|
|
30
|
+
builder.add(ma.min, "min")
|
|
31
|
+
builder.add(ma.max, "max")
|
|
32
|
+
builder.add(ma.mean, "mean")
|
|
33
|
+
|
|
34
|
+
table = builder.compute(sig)
|
|
35
|
+
|
|
36
|
+
assert table.title == "Signal Stats"
|
|
37
|
+
# [None, ROI_0] x 3 stats
|
|
38
|
+
assert len(table.data) == 2 and len(table.data[0]) == 3
|
|
39
|
+
assert list(table.headers) == ["min", "max", "mean"]
|
|
40
|
+
assert table.roi_indices[0] == -1 # NO_ROI
|
|
41
|
+
assert table.roi_indices[1] == 0
|
|
42
|
+
|
|
43
|
+
# Check actual values
|
|
44
|
+
row_none = table.data[0]
|
|
45
|
+
row_roi = table.data[1]
|
|
46
|
+
assert isinstance(row_none[0], float)
|
|
47
|
+
assert isinstance(row_roi[1], float)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class TestTableResultBuilderHideColumns:
|
|
51
|
+
"""Test class for TableResultBuilder hide_columns functionality."""
|
|
52
|
+
|
|
53
|
+
def setup_method(self) -> None:
|
|
54
|
+
"""Set up test data for each test method."""
|
|
55
|
+
# pylint: disable=attribute-defined-outside-init
|
|
56
|
+
self.sig = create_dummy_signal()
|
|
57
|
+
|
|
58
|
+
def _create_basic_builder(self) -> TableResultBuilder:
|
|
59
|
+
"""Helper method to create a basic builder with standard columns."""
|
|
60
|
+
builder = TableResultBuilder("Signal Stats")
|
|
61
|
+
builder.add(ma.min, "min")
|
|
62
|
+
builder.add(ma.max, "max")
|
|
63
|
+
builder.add(ma.mean, "mean")
|
|
64
|
+
builder.add(ma.std, "std")
|
|
65
|
+
return builder
|
|
66
|
+
|
|
67
|
+
def _assert_display_preferences(
|
|
68
|
+
self, table, expected_prefs: dict[str, bool]
|
|
69
|
+
) -> None:
|
|
70
|
+
"""Helper method to check display preferences and visible headers."""
|
|
71
|
+
prefs = table.get_display_preferences()
|
|
72
|
+
assert prefs == expected_prefs
|
|
73
|
+
|
|
74
|
+
expected_visible = [name for name, visible in expected_prefs.items() if visible]
|
|
75
|
+
visible_headers = table.get_visible_headers()
|
|
76
|
+
assert set(visible_headers) == set(expected_visible)
|
|
77
|
+
|
|
78
|
+
def test_hide_some_columns(self) -> None:
|
|
79
|
+
"""Test hiding some columns."""
|
|
80
|
+
builder = self._create_basic_builder()
|
|
81
|
+
builder.hide_columns(["max", "std"])
|
|
82
|
+
|
|
83
|
+
table = builder.compute(self.sig)
|
|
84
|
+
|
|
85
|
+
assert table.title == "Signal Stats"
|
|
86
|
+
# All headers still present
|
|
87
|
+
assert list(table.headers) == ["min", "max", "mean", "std"]
|
|
88
|
+
|
|
89
|
+
self._assert_display_preferences(
|
|
90
|
+
table, {"min": True, "max": False, "mean": True, "std": False}
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
def test_hide_nonexistent_columns(self) -> None:
|
|
94
|
+
"""Test hiding non-existent columns."""
|
|
95
|
+
builder = TableResultBuilder("Signal Stats")
|
|
96
|
+
builder.add(ma.min, "min")
|
|
97
|
+
builder.add(ma.max, "max")
|
|
98
|
+
|
|
99
|
+
# Try to hide non-existent column - should not cause error
|
|
100
|
+
builder.hide_columns(["nonexistent", "min"])
|
|
101
|
+
|
|
102
|
+
table = builder.compute(self.sig)
|
|
103
|
+
|
|
104
|
+
self._assert_display_preferences(table, {"min": False, "max": True})
|
|
105
|
+
|
|
106
|
+
def test_hide_empty_list(self) -> None:
|
|
107
|
+
"""Test hiding empty list of columns."""
|
|
108
|
+
builder = TableResultBuilder("Signal Stats")
|
|
109
|
+
builder.add(ma.min, "min")
|
|
110
|
+
builder.add(ma.max, "max")
|
|
111
|
+
|
|
112
|
+
builder.hide_columns([])
|
|
113
|
+
|
|
114
|
+
table = builder.compute(self.sig)
|
|
115
|
+
|
|
116
|
+
self._assert_display_preferences(table, {"min": True, "max": True})
|
|
117
|
+
|
|
118
|
+
def test_hide_multiple_calls(self) -> None:
|
|
119
|
+
"""Test multiple hide_columns calls accumulate."""
|
|
120
|
+
builder = self._create_basic_builder()
|
|
121
|
+
|
|
122
|
+
# Hide columns in multiple calls
|
|
123
|
+
builder.hide_columns(["max"])
|
|
124
|
+
builder.hide_columns(["std"])
|
|
125
|
+
|
|
126
|
+
table = builder.compute(self.sig)
|
|
127
|
+
|
|
128
|
+
self._assert_display_preferences(
|
|
129
|
+
table, {"min": True, "max": False, "mean": True, "std": False}
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
def test_hide_all_columns(self) -> None:
|
|
133
|
+
"""Test hiding all columns."""
|
|
134
|
+
builder = TableResultBuilder("Signal Stats")
|
|
135
|
+
builder.add(ma.min, "min")
|
|
136
|
+
builder.add(ma.max, "max")
|
|
137
|
+
|
|
138
|
+
builder.hide_columns(["min", "max"])
|
|
139
|
+
|
|
140
|
+
table = builder.compute(self.sig)
|
|
141
|
+
|
|
142
|
+
self._assert_display_preferences(table, {"min": False, "max": False})
|