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,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()
|