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,175 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the terms of the BSD 3-Clause
|
|
4
|
+
# (see sigima/LICENSE for details)
|
|
5
|
+
|
|
6
|
+
"""
|
|
7
|
+
Stability analysis functions
|
|
8
|
+
============================
|
|
9
|
+
|
|
10
|
+
This module provides stability analysis functions for signal objects:
|
|
11
|
+
|
|
12
|
+
- Allan variance and deviation
|
|
13
|
+
- Overlapping Allan variance
|
|
14
|
+
- Modified Allan variance
|
|
15
|
+
- Hadamard variance
|
|
16
|
+
- Total variance
|
|
17
|
+
|
|
18
|
+
.. note::
|
|
19
|
+
|
|
20
|
+
All operations use functions from :mod:`sigima.tools.signal.stability` for
|
|
21
|
+
actual computations.
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
from __future__ import annotations
|
|
25
|
+
|
|
26
|
+
import guidata.dataset as gds
|
|
27
|
+
import numpy as np
|
|
28
|
+
|
|
29
|
+
from sigima.config import _
|
|
30
|
+
from sigima.objects import SignalObj
|
|
31
|
+
from sigima.proc.decorator import computation_function
|
|
32
|
+
from sigima.tools.signal import stability
|
|
33
|
+
|
|
34
|
+
from .base import dst_1_to_1
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class AllanVarianceParam(gds.DataSet, title=_("Allan variance")):
|
|
38
|
+
"""Allan variance parameters"""
|
|
39
|
+
|
|
40
|
+
max_tau = gds.IntItem("Max τ", default=100, min=1, unit="pts")
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
@computation_function()
|
|
44
|
+
def allan_variance(src: SignalObj, p: AllanVarianceParam) -> SignalObj:
|
|
45
|
+
"""Compute Allan variance with
|
|
46
|
+
:py:func:`sigima.tools.signal.stability.allan_variance`.
|
|
47
|
+
|
|
48
|
+
Args:
|
|
49
|
+
src: source signal
|
|
50
|
+
p: parameters
|
|
51
|
+
|
|
52
|
+
Returns:
|
|
53
|
+
Result signal object
|
|
54
|
+
"""
|
|
55
|
+
dst = dst_1_to_1(src, "allan_variance", f"max_tau={p.max_tau}")
|
|
56
|
+
x, y = src.get_data()
|
|
57
|
+
tau_values = np.arange(1, p.max_tau + 1)
|
|
58
|
+
avar = stability.allan_variance(x, y, tau_values)
|
|
59
|
+
dst.set_xydata(tau_values, avar)
|
|
60
|
+
return dst
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
@computation_function()
|
|
64
|
+
def allan_deviation(src: SignalObj, p: AllanVarianceParam) -> SignalObj:
|
|
65
|
+
"""Compute Allan deviation with
|
|
66
|
+
:py:func:`sigima.tools.signal.stability.allan_deviation`
|
|
67
|
+
|
|
68
|
+
Args:
|
|
69
|
+
src: source signal
|
|
70
|
+
p: parameters
|
|
71
|
+
|
|
72
|
+
Returns:
|
|
73
|
+
Result signal object
|
|
74
|
+
"""
|
|
75
|
+
dst = dst_1_to_1(src, "allan_deviation", f"max_tau={p.max_tau}")
|
|
76
|
+
x, y = src.get_data()
|
|
77
|
+
tau_values = np.arange(1, p.max_tau + 1)
|
|
78
|
+
adev = stability.allan_deviation(x, y, tau_values)
|
|
79
|
+
dst.set_xydata(tau_values, adev)
|
|
80
|
+
return dst
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
@computation_function()
|
|
84
|
+
def overlapping_allan_variance(src: SignalObj, p: AllanVarianceParam) -> SignalObj:
|
|
85
|
+
"""Compute Overlapping Allan variance.
|
|
86
|
+
|
|
87
|
+
Args:
|
|
88
|
+
src: source signal
|
|
89
|
+
p: parameters
|
|
90
|
+
|
|
91
|
+
Returns:
|
|
92
|
+
Result signal object
|
|
93
|
+
"""
|
|
94
|
+
dst = dst_1_to_1(src, "overlapping_allan_variance", f"max_tau={p.max_tau}")
|
|
95
|
+
x, y = src.get_data()
|
|
96
|
+
tau_values = np.arange(1, p.max_tau + 1)
|
|
97
|
+
oavar = stability.overlapping_allan_variance(x, y, tau_values)
|
|
98
|
+
dst.set_xydata(tau_values, oavar)
|
|
99
|
+
return dst
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
@computation_function()
|
|
103
|
+
def modified_allan_variance(src: SignalObj, p: AllanVarianceParam) -> SignalObj:
|
|
104
|
+
"""Compute Modified Allan variance.
|
|
105
|
+
|
|
106
|
+
Args:
|
|
107
|
+
src: source signal
|
|
108
|
+
p: parameters
|
|
109
|
+
|
|
110
|
+
Returns:
|
|
111
|
+
Result signal object
|
|
112
|
+
"""
|
|
113
|
+
dst = dst_1_to_1(src, "modified_allan_variance", f"max_tau={p.max_tau}")
|
|
114
|
+
x, y = src.get_data()
|
|
115
|
+
tau_values = np.arange(1, p.max_tau + 1)
|
|
116
|
+
mavar = stability.modified_allan_variance(x, y, tau_values)
|
|
117
|
+
dst.set_xydata(tau_values, mavar)
|
|
118
|
+
return dst
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
@computation_function()
|
|
122
|
+
def hadamard_variance(src: SignalObj, p: AllanVarianceParam) -> SignalObj:
|
|
123
|
+
"""Compute Hadamard variance.
|
|
124
|
+
|
|
125
|
+
Args:
|
|
126
|
+
src: source signal
|
|
127
|
+
p: parameters
|
|
128
|
+
|
|
129
|
+
Returns:
|
|
130
|
+
Result signal object
|
|
131
|
+
"""
|
|
132
|
+
dst = dst_1_to_1(src, "hadamard_variance", f"max_tau={p.max_tau}")
|
|
133
|
+
x, y = src.get_data()
|
|
134
|
+
tau_values = np.arange(1, p.max_tau + 1)
|
|
135
|
+
hvar = stability.hadamard_variance(x, y, tau_values)
|
|
136
|
+
dst.set_xydata(tau_values, hvar)
|
|
137
|
+
return dst
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
@computation_function()
|
|
141
|
+
def total_variance(src: SignalObj, p: AllanVarianceParam) -> SignalObj:
|
|
142
|
+
"""Compute Total variance.
|
|
143
|
+
|
|
144
|
+
Args:
|
|
145
|
+
src: source signal
|
|
146
|
+
p: parameters
|
|
147
|
+
|
|
148
|
+
Returns:
|
|
149
|
+
Result signal object
|
|
150
|
+
"""
|
|
151
|
+
dst = dst_1_to_1(src, "total_variance", f"max_tau={p.max_tau}")
|
|
152
|
+
x, y = src.get_data()
|
|
153
|
+
tau_values = np.arange(1, p.max_tau + 1)
|
|
154
|
+
tvar = stability.total_variance(x, y, tau_values)
|
|
155
|
+
dst.set_xydata(tau_values, tvar)
|
|
156
|
+
return dst
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
@computation_function()
|
|
160
|
+
def time_deviation(src: SignalObj, p: AllanVarianceParam) -> SignalObj:
|
|
161
|
+
"""Compute Time Deviation (TDEV).
|
|
162
|
+
|
|
163
|
+
Args:
|
|
164
|
+
src: source signal
|
|
165
|
+
p: parameters
|
|
166
|
+
|
|
167
|
+
Returns:
|
|
168
|
+
Result signal object
|
|
169
|
+
"""
|
|
170
|
+
dst = dst_1_to_1(src, "time_deviation", f"max_tau={p.max_tau}")
|
|
171
|
+
x, y = src.get_data()
|
|
172
|
+
tau_values = np.arange(1, p.max_tau + 1)
|
|
173
|
+
tdev = stability.time_deviation(x, y, tau_values)
|
|
174
|
+
dst.set_xydata(tau_values, tdev)
|
|
175
|
+
return dst
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
# Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
Title formatting system for computation results
|
|
5
|
+
-----------------------------------------------
|
|
6
|
+
|
|
7
|
+
This module provides a configurable title formatting system for computation results.
|
|
8
|
+
It allows different applications (Sigima vs DataLab) to use different title formatting
|
|
9
|
+
strategies while maintaining compatibility.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
from typing import TYPE_CHECKING, Protocol, runtime_checkable
|
|
15
|
+
|
|
16
|
+
if TYPE_CHECKING:
|
|
17
|
+
from sigima.objects.base import BaseObj
|
|
18
|
+
|
|
19
|
+
__all__ = [
|
|
20
|
+
"PlaceholderTitleFormatter",
|
|
21
|
+
"SimpleTitleFormatter",
|
|
22
|
+
"TitleFormatter",
|
|
23
|
+
"get_default_title_formatter",
|
|
24
|
+
"set_default_title_formatter",
|
|
25
|
+
]
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
@runtime_checkable
|
|
29
|
+
class TitleFormatter(Protocol):
|
|
30
|
+
"""Protocol for title formatting strategies used in computation functions.
|
|
31
|
+
|
|
32
|
+
This protocol allows different title formatting approaches:
|
|
33
|
+
- Simple descriptive titles for Sigima-only usage
|
|
34
|
+
- Placeholder-based titles for DataLab integration
|
|
35
|
+
- Custom formatting for specific use cases
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
def format_1_to_1_title(self, name: str, suffix: str | None = None) -> str:
|
|
39
|
+
"""Format title for 1-to-1 computation (single input → single output).
|
|
40
|
+
|
|
41
|
+
Args:
|
|
42
|
+
name: Name of the computation function
|
|
43
|
+
suffix: Optional suffix to add to the title
|
|
44
|
+
|
|
45
|
+
Returns:
|
|
46
|
+
Formatted title string
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
def format_n_to_1_title(
|
|
50
|
+
self, name: str, n_inputs: int, suffix: str | None = None
|
|
51
|
+
) -> str:
|
|
52
|
+
"""Format title for n-to-1 computation (multiple inputs → single output).
|
|
53
|
+
|
|
54
|
+
Args:
|
|
55
|
+
name: Name of the computation function
|
|
56
|
+
n_inputs: Number of input objects
|
|
57
|
+
suffix: Optional suffix to add to the title
|
|
58
|
+
|
|
59
|
+
Returns:
|
|
60
|
+
Formatted title string
|
|
61
|
+
"""
|
|
62
|
+
|
|
63
|
+
def format_2_to_1_title(self, name: str, suffix: str | None = None) -> str:
|
|
64
|
+
"""Format title for 2-to-1 computation (two inputs → single output).
|
|
65
|
+
|
|
66
|
+
Args:
|
|
67
|
+
name: Name of the computation function
|
|
68
|
+
suffix: Optional suffix to add to the title
|
|
69
|
+
|
|
70
|
+
Returns:
|
|
71
|
+
Formatted title string
|
|
72
|
+
"""
|
|
73
|
+
|
|
74
|
+
def resolve_placeholder_title(
|
|
75
|
+
self,
|
|
76
|
+
title: str,
|
|
77
|
+
source_objects: list[BaseObj],
|
|
78
|
+
) -> str:
|
|
79
|
+
"""Resolve placeholder title with actual object references.
|
|
80
|
+
|
|
81
|
+
This method takes a title with placeholders (e.g., "wiener({0})")
|
|
82
|
+
and replaces them with actual object identifiers.
|
|
83
|
+
|
|
84
|
+
Args:
|
|
85
|
+
title: Title containing placeholders
|
|
86
|
+
source_objects: List of source objects to use for replacement
|
|
87
|
+
|
|
88
|
+
Returns:
|
|
89
|
+
Title with placeholders resolved
|
|
90
|
+
"""
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
class SimpleTitleFormatter:
|
|
94
|
+
"""Simple descriptive title formatter for Sigima-only usage.
|
|
95
|
+
|
|
96
|
+
Creates human-readable titles without placeholders, suitable for
|
|
97
|
+
standalone Sigima usage where object relationships are less critical.
|
|
98
|
+
"""
|
|
99
|
+
|
|
100
|
+
def format_1_to_1_title(self, name: str, suffix: str | None = None) -> str:
|
|
101
|
+
"""Format title for 1-to-1 computation."""
|
|
102
|
+
if len(name) == 1: # This is an operator
|
|
103
|
+
base_title = f"operator_{name}"
|
|
104
|
+
else:
|
|
105
|
+
# Convert function names to human-readable format
|
|
106
|
+
readable_name = name.replace("_", " ").title()
|
|
107
|
+
base_title = f"{readable_name} Result"
|
|
108
|
+
|
|
109
|
+
if suffix:
|
|
110
|
+
base_title += f" ({suffix})"
|
|
111
|
+
return base_title
|
|
112
|
+
|
|
113
|
+
def format_n_to_1_title(
|
|
114
|
+
self, name: str, n_inputs: int, suffix: str | None = None
|
|
115
|
+
) -> str:
|
|
116
|
+
"""Format title for n-to-1 computation."""
|
|
117
|
+
readable_name = name.replace("_", " ").title()
|
|
118
|
+
base_title = f"{readable_name} of {n_inputs} Objects"
|
|
119
|
+
|
|
120
|
+
if suffix:
|
|
121
|
+
base_title += f" ({suffix})"
|
|
122
|
+
return base_title
|
|
123
|
+
|
|
124
|
+
def format_2_to_1_title(self, name: str, suffix: str | None = None) -> str:
|
|
125
|
+
"""Format title for 2-to-1 computation."""
|
|
126
|
+
if len(name) == 1: # This is an operator
|
|
127
|
+
base_title = f"Binary Operation {name}"
|
|
128
|
+
else:
|
|
129
|
+
readable_name = name.replace("_", " ").title()
|
|
130
|
+
base_title = f"{readable_name} Result"
|
|
131
|
+
|
|
132
|
+
if suffix:
|
|
133
|
+
base_title += f" ({suffix})"
|
|
134
|
+
return base_title
|
|
135
|
+
|
|
136
|
+
def resolve_placeholder_title(
|
|
137
|
+
self,
|
|
138
|
+
title: str,
|
|
139
|
+
source_objects: list[BaseObj], # pylint: disable=unused-argument
|
|
140
|
+
) -> str:
|
|
141
|
+
"""For simple formatter, just return the title as-is."""
|
|
142
|
+
return title
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
class PlaceholderTitleFormatter:
|
|
146
|
+
"""Placeholder-based title formatter compatible with DataLab.
|
|
147
|
+
|
|
148
|
+
Creates titles with placeholders that can be resolved later by DataLab's
|
|
149
|
+
patch_title_with_ids() function.
|
|
150
|
+
"""
|
|
151
|
+
|
|
152
|
+
def format_1_to_1_title(self, name: str, suffix: str | None = None) -> str:
|
|
153
|
+
"""Format title for 1-to-1 computation with placeholder."""
|
|
154
|
+
if len(name) == 1: # This is an operator
|
|
155
|
+
title = f"{{0}}{name}"
|
|
156
|
+
else:
|
|
157
|
+
title = f"{name}({{0}})"
|
|
158
|
+
if suffix: # suffix may be None or an empty string
|
|
159
|
+
title += "|"
|
|
160
|
+
if suffix: # suffix may be None or an empty string
|
|
161
|
+
title += suffix
|
|
162
|
+
return title
|
|
163
|
+
|
|
164
|
+
def format_n_to_1_title(
|
|
165
|
+
self, name: str, n_inputs: int, suffix: str | None = None
|
|
166
|
+
) -> str:
|
|
167
|
+
"""Format title for n-to-1 computation with placeholders."""
|
|
168
|
+
placeholders = ", ".join(f"{{{i}}}" for i in range(n_inputs))
|
|
169
|
+
title = f"{name}({placeholders})"
|
|
170
|
+
if suffix:
|
|
171
|
+
title += "|" + suffix
|
|
172
|
+
return title
|
|
173
|
+
|
|
174
|
+
def format_2_to_1_title(self, name: str, suffix: str | None = None) -> str:
|
|
175
|
+
"""Format title for 2-to-1 computation with placeholders."""
|
|
176
|
+
if len(name) == 1: # This is an operator
|
|
177
|
+
title = f"{{0}}{name}{{1}}"
|
|
178
|
+
else:
|
|
179
|
+
title = f"{name}({{0}}, {{1}})"
|
|
180
|
+
if suffix:
|
|
181
|
+
title += "|" + suffix
|
|
182
|
+
return title
|
|
183
|
+
|
|
184
|
+
def resolve_placeholder_title(
|
|
185
|
+
self,
|
|
186
|
+
title: str,
|
|
187
|
+
source_objects: list[BaseObj],
|
|
188
|
+
) -> str:
|
|
189
|
+
"""Resolve placeholder title with object short IDs (if available)."""
|
|
190
|
+
# For basic Sigima usage, use simple indexing
|
|
191
|
+
# DataLab will override this with its own patch_title_with_ids logic
|
|
192
|
+
try:
|
|
193
|
+
# Try to use short_id if available (for DataLab compatibility)
|
|
194
|
+
ids = []
|
|
195
|
+
for i, obj in enumerate(source_objects):
|
|
196
|
+
short_id = getattr(obj, "short_id", None)
|
|
197
|
+
if short_id is not None:
|
|
198
|
+
ids.append(short_id)
|
|
199
|
+
else:
|
|
200
|
+
ids.append(f"obj{i + 1}")
|
|
201
|
+
return title.format(*ids)
|
|
202
|
+
except (IndexError, AttributeError):
|
|
203
|
+
# Fallback: use simple object indices
|
|
204
|
+
return title.format(*[f"obj{i + 1}" for i in range(len(source_objects))])
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
# Global default title formatter
|
|
208
|
+
_default_title_formatter: TitleFormatter = SimpleTitleFormatter()
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
def get_default_title_formatter() -> TitleFormatter:
|
|
212
|
+
"""Get the current default title formatter.
|
|
213
|
+
|
|
214
|
+
Returns:
|
|
215
|
+
Current default title formatter
|
|
216
|
+
"""
|
|
217
|
+
return _default_title_formatter
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
def set_default_title_formatter(formatter: TitleFormatter) -> None:
|
|
221
|
+
"""Set the default title formatter.
|
|
222
|
+
|
|
223
|
+
Args:
|
|
224
|
+
formatter: Title formatter to use as default
|
|
225
|
+
"""
|
|
226
|
+
global _default_title_formatter # pylint: disable=global-statement
|
|
227
|
+
_default_title_formatter = formatter
|
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
# Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
.. Validation statistics module
|
|
5
|
+
(see parent package :mod:`sigima.computation`)
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import csv
|
|
11
|
+
import dataclasses
|
|
12
|
+
import importlib
|
|
13
|
+
import inspect
|
|
14
|
+
import os.path as osp
|
|
15
|
+
import pkgutil
|
|
16
|
+
import re
|
|
17
|
+
|
|
18
|
+
from _pytest.mark import Mark
|
|
19
|
+
|
|
20
|
+
import sigima.tests as tests_pkg
|
|
21
|
+
from sigima import __version__
|
|
22
|
+
from sigima.proc.decorator import find_computation_functions
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def generate_valid_test_names_for_function(
|
|
26
|
+
module_name: str, func_name: str
|
|
27
|
+
) -> list[str]:
|
|
28
|
+
"""Generate all valid test names for a computation function.
|
|
29
|
+
|
|
30
|
+
Args:
|
|
31
|
+
module_name: Module name containing the computation function
|
|
32
|
+
(e.g., "sigima.proc.image")
|
|
33
|
+
func_name: Function name (e.g., "compute_add_gaussian_noise")
|
|
34
|
+
|
|
35
|
+
Returns:
|
|
36
|
+
List of valid test names that could test this computation function
|
|
37
|
+
"""
|
|
38
|
+
family = module_name.split(".")[-1] # "signal" or "image"
|
|
39
|
+
shortname = func_name.removeprefix("compute_")
|
|
40
|
+
endings = [shortname, shortname + "_unit", shortname + "_validation"]
|
|
41
|
+
beginnings = ["test", f"test_{family}", f"test_{family[:3]}", f"test_{family[0]}"]
|
|
42
|
+
names = [f"{beginning}_{ending}" for beginning in beginnings for ending in endings]
|
|
43
|
+
return names
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def check_for_validation_test(
|
|
47
|
+
full_function_name: str, validation_tests: list[tuple[str, str]]
|
|
48
|
+
) -> str:
|
|
49
|
+
"""Check if a validation test exists for a compute function
|
|
50
|
+
|
|
51
|
+
Args:
|
|
52
|
+
full_function_name: Compute function name
|
|
53
|
+
validation_tests: List of validation tests
|
|
54
|
+
|
|
55
|
+
Returns:
|
|
56
|
+
Text to be included in the CSV file or None if it doesn't exist
|
|
57
|
+
"""
|
|
58
|
+
# Extract module name and function name from full function name
|
|
59
|
+
module_parts = full_function_name.split(".")
|
|
60
|
+
module_name = ".".join(module_parts[:-1]) # e.g., "sigima.proc.image"
|
|
61
|
+
func_name = module_parts[-1] # e.g., "compute_add_gaussian_noise"
|
|
62
|
+
|
|
63
|
+
# Generate all valid test names for this computation function
|
|
64
|
+
names = generate_valid_test_names_for_function(module_name, func_name)
|
|
65
|
+
|
|
66
|
+
stable_version = re.sub(r"\.?(post|dev|rc|b|a)\S*", "", __version__)
|
|
67
|
+
for test, path, line_number in validation_tests:
|
|
68
|
+
if test in names:
|
|
69
|
+
# Path relative to the `datalab` package:
|
|
70
|
+
path = osp.relpath(path, start=osp.dirname(osp.join(tests_pkg.__file__)))
|
|
71
|
+
name = "/".join(path.split(osp.sep))
|
|
72
|
+
link = (
|
|
73
|
+
f"https://github.com/DataLab-Platform/Sigima/blob/"
|
|
74
|
+
f"v{stable_version}/sigima/tests/{name}#L{line_number}"
|
|
75
|
+
)
|
|
76
|
+
return f"`{test} <{link}>`_"
|
|
77
|
+
return None
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def get_validation_tests(package: str) -> list:
|
|
81
|
+
"""Retrieve list of validation tests from a package and its submodules
|
|
82
|
+
|
|
83
|
+
Args:
|
|
84
|
+
package: Python package
|
|
85
|
+
|
|
86
|
+
Returns:
|
|
87
|
+
List of tuples containing the test name, module path and line number
|
|
88
|
+
"""
|
|
89
|
+
validation_tests = []
|
|
90
|
+
package_path = package.__path__
|
|
91
|
+
for _, module_name, _ in pkgutil.walk_packages(
|
|
92
|
+
package_path, package.__name__ + "."
|
|
93
|
+
):
|
|
94
|
+
try:
|
|
95
|
+
module = importlib.import_module(module_name)
|
|
96
|
+
except ImportError as exc:
|
|
97
|
+
if "vistools" in module_name:
|
|
98
|
+
# This is expected as vistools requires a GUI
|
|
99
|
+
continue
|
|
100
|
+
raise ImportError(
|
|
101
|
+
f"Failed to import module {module_name}. "
|
|
102
|
+
"Ensure the module is correctly installed and accessible."
|
|
103
|
+
) from exc
|
|
104
|
+
for name, obj in inspect.getmembers(module, inspect.isfunction):
|
|
105
|
+
if hasattr(obj, "pytestmark"):
|
|
106
|
+
for mark in obj.pytestmark:
|
|
107
|
+
if isinstance(mark, Mark) and mark.name == "validation":
|
|
108
|
+
module_path = inspect.getfile(obj)
|
|
109
|
+
try:
|
|
110
|
+
line_number = inspect.getsourcelines(obj)[1]
|
|
111
|
+
except OSError as exc:
|
|
112
|
+
raise RuntimeError(
|
|
113
|
+
f"Failed to get source line for {name} in {module_name}"
|
|
114
|
+
) from exc
|
|
115
|
+
validation_tests.append((name, module_path, line_number))
|
|
116
|
+
return validation_tests
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def shorten_docstring(docstring: str) -> str:
|
|
120
|
+
"""Shorten a docstring to a single line
|
|
121
|
+
|
|
122
|
+
Args:
|
|
123
|
+
docstring: Docstring
|
|
124
|
+
|
|
125
|
+
Returns:
|
|
126
|
+
Shortened docstring
|
|
127
|
+
"""
|
|
128
|
+
shorter = docstring.split("\n")[0].strip() if docstring else "-"
|
|
129
|
+
for suffix in (".", ":", ",", "using", "with"):
|
|
130
|
+
shorter = shorter.removesuffix(suffix)
|
|
131
|
+
shorter = shorter.split(" with :py:func:")[0] # Remove function references
|
|
132
|
+
return shorter
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
@dataclasses.dataclass
|
|
136
|
+
class ValidationStatus:
|
|
137
|
+
"""Data class to hold validation status of a compute function"""
|
|
138
|
+
|
|
139
|
+
module_name: str
|
|
140
|
+
function_name: str
|
|
141
|
+
description: str
|
|
142
|
+
test_script: str
|
|
143
|
+
|
|
144
|
+
def get_pyfunc_link(self) -> str:
|
|
145
|
+
"""Get the reStructuredText link to the compute function"""
|
|
146
|
+
return (
|
|
147
|
+
f":py:func:`{self.function_name} <{self.module_name}.{self.function_name}>`"
|
|
148
|
+
)
|
|
149
|
+
|
|
150
|
+
def __str__(self) -> str:
|
|
151
|
+
"""String representation of the validation status"""
|
|
152
|
+
return f"{self.get_pyfunc_link()} - {self.description} - {self.test_script}"
|
|
153
|
+
|
|
154
|
+
def to_csv_row(self) -> list[str]:
|
|
155
|
+
"""Convert the validation status to a CSV row"""
|
|
156
|
+
return [self.get_pyfunc_link(), self.description, self.test_script]
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
class ValidationStatistics:
|
|
160
|
+
"""Data class to hold validation statistics of compute functions"""
|
|
161
|
+
|
|
162
|
+
def __init__(self):
|
|
163
|
+
self.submodules: dict[str, list[tuple[str, str, str]]] = {}
|
|
164
|
+
self.t_count: dict[str, int] = {}
|
|
165
|
+
self.v_count: dict[str, int] = {}
|
|
166
|
+
self.signal_pct: int = 0
|
|
167
|
+
self.image_pct: int = 0
|
|
168
|
+
self.total_pct: int = 0
|
|
169
|
+
self.validations: dict[str, list[ValidationStatus]] = {}
|
|
170
|
+
self.validation_info_list: list[str] = []
|
|
171
|
+
|
|
172
|
+
def collect_validation_status(self, verbose: bool = False) -> None:
|
|
173
|
+
"""Populate the statistics from the validation status"""
|
|
174
|
+
compute_functions = find_computation_functions()
|
|
175
|
+
validation_tests = get_validation_tests(tests_pkg)
|
|
176
|
+
|
|
177
|
+
self.submodules = {"signal": [], "image": []}
|
|
178
|
+
for modname, funcname, docstring in compute_functions:
|
|
179
|
+
if "signal" in modname:
|
|
180
|
+
self.submodules["signal"].append((modname, funcname, docstring))
|
|
181
|
+
elif "image" in modname:
|
|
182
|
+
self.submodules["image"].append((modname, funcname, docstring))
|
|
183
|
+
|
|
184
|
+
self.t_count = t_count = {"signal": 0, "image": 0, "total": 0}
|
|
185
|
+
self.v_count = v_count = {"signal": 0, "image": 0, "total": 0}
|
|
186
|
+
|
|
187
|
+
self.validations = {"signal": [], "image": []}
|
|
188
|
+
for submodule, functions in self.submodules.items():
|
|
189
|
+
for modname, funcname, docstring in functions:
|
|
190
|
+
full_funcname = f"{modname}.{funcname}"
|
|
191
|
+
test_link = check_for_validation_test(full_funcname, validation_tests)
|
|
192
|
+
if test_link:
|
|
193
|
+
v_count[submodule] += 1
|
|
194
|
+
v_count["total"] += 1
|
|
195
|
+
t_count[submodule] += 1
|
|
196
|
+
t_count["total"] += 1
|
|
197
|
+
status = ValidationStatus(
|
|
198
|
+
module_name=modname,
|
|
199
|
+
function_name=funcname,
|
|
200
|
+
description=shorten_docstring(docstring),
|
|
201
|
+
test_script=test_link if test_link else "N/A",
|
|
202
|
+
)
|
|
203
|
+
self.validations[submodule].append(status)
|
|
204
|
+
|
|
205
|
+
self.signal_pct = signal_pct = (
|
|
206
|
+
int((v_count["signal"] / t_count["signal"]) * 100)
|
|
207
|
+
if t_count["signal"] > 0
|
|
208
|
+
else 0
|
|
209
|
+
)
|
|
210
|
+
self.image_pct = image_pct = (
|
|
211
|
+
int((v_count["image"] / t_count["image"]) * 100)
|
|
212
|
+
if t_count["image"] > 0
|
|
213
|
+
else 0
|
|
214
|
+
)
|
|
215
|
+
self.total_pct = total_pct = (
|
|
216
|
+
int((v_count["total"] / t_count["total"]) * 100)
|
|
217
|
+
if t_count["total"] > 0
|
|
218
|
+
else 0
|
|
219
|
+
)
|
|
220
|
+
|
|
221
|
+
self.validation_info_list = [
|
|
222
|
+
f"Validation statistics for Sigima {__version__}:",
|
|
223
|
+
f" Signal: {v_count['signal']}/{t_count['signal']} ({signal_pct}%)",
|
|
224
|
+
f" Image : {v_count['image']}/{t_count['image']} ({image_pct}%)",
|
|
225
|
+
f" Total : {v_count['total']}/{t_count['total']} ({total_pct}%)",
|
|
226
|
+
]
|
|
227
|
+
|
|
228
|
+
if verbose:
|
|
229
|
+
print("\n".join(self.validation_info_list))
|
|
230
|
+
print()
|
|
231
|
+
|
|
232
|
+
def get_validation_info(self) -> list[str]:
|
|
233
|
+
"""Get the validation information as a list of strings"""
|
|
234
|
+
if not self.validation_info_list:
|
|
235
|
+
self.collect_validation_status(verbose=False)
|
|
236
|
+
return self.validation_info_list
|
|
237
|
+
|
|
238
|
+
def generate_csv_files(self, path: str) -> None:
|
|
239
|
+
"""Generate CSV files for each submodule's validation status"""
|
|
240
|
+
for submodule, validation_status_list in self.validations.items():
|
|
241
|
+
rows = [status.to_csv_row() for status in validation_status_list]
|
|
242
|
+
fname = osp.join(path, f"validation_status_{submodule}.csv")
|
|
243
|
+
with open(fname, "w", newline="", encoding="utf-8") as csvfile:
|
|
244
|
+
writer = csv.writer(csvfile)
|
|
245
|
+
writer.writerows(rows)
|
|
246
|
+
|
|
247
|
+
def generate_statistics_csv(self, path: str) -> None:
|
|
248
|
+
"""Generate a CSV file with the validation statistics"""
|
|
249
|
+
statistics_rows = [
|
|
250
|
+
[
|
|
251
|
+
"Number of compute functions",
|
|
252
|
+
self.t_count["signal"],
|
|
253
|
+
self.t_count["image"],
|
|
254
|
+
self.t_count["total"],
|
|
255
|
+
],
|
|
256
|
+
[
|
|
257
|
+
"Number of validated compute functions",
|
|
258
|
+
self.v_count["signal"],
|
|
259
|
+
self.v_count["image"],
|
|
260
|
+
self.v_count["total"],
|
|
261
|
+
],
|
|
262
|
+
[
|
|
263
|
+
"Percentage of validated compute functions",
|
|
264
|
+
f"{self.signal_pct}%",
|
|
265
|
+
f"{self.image_pct}%",
|
|
266
|
+
f"{self.total_pct}%",
|
|
267
|
+
],
|
|
268
|
+
]
|
|
269
|
+
fname = osp.join(path, "validation_statistics.csv")
|
|
270
|
+
with open(fname, "w", newline="", encoding="utf-8") as csvfile:
|
|
271
|
+
writer = csv.writer(csvfile)
|
|
272
|
+
writer.writerows(statistics_rows)
|
sigima/tests/__init__.py
ADDED
|
File without changes
|