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,260 @@
|
|
|
1
|
+
# Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
Fourier analysis module
|
|
5
|
+
-----------------------
|
|
6
|
+
|
|
7
|
+
This module provides 2D Fourier transform utilities and frequency domain operations
|
|
8
|
+
for image processing.
|
|
9
|
+
|
|
10
|
+
Features include:
|
|
11
|
+
|
|
12
|
+
- 2D FFT/IFFT functions with optional shifting
|
|
13
|
+
- Spectral analysis (magnitude spectrum, phase spectrum, power spectral density)
|
|
14
|
+
- Frequency domain filtering and deconvolution
|
|
15
|
+
- Zero padding utilities for FFT operations
|
|
16
|
+
|
|
17
|
+
These tools support various frequency domain image processing operations
|
|
18
|
+
including filtering, spectral analysis, and deconvolution.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
from __future__ import annotations
|
|
22
|
+
|
|
23
|
+
import warnings
|
|
24
|
+
|
|
25
|
+
import numpy as np
|
|
26
|
+
import scipy.signal as sps
|
|
27
|
+
|
|
28
|
+
from sigima.tools.checks import check_2d_array, normalize_kernel
|
|
29
|
+
|
|
30
|
+
# pylint: disable=invalid-name # Allows short reference names like x, y, ...
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
@check_2d_array
|
|
34
|
+
def fft2d(z: np.ndarray, shift: bool = True) -> np.ndarray:
|
|
35
|
+
"""Compute FFT of complex array `z`
|
|
36
|
+
|
|
37
|
+
Args:
|
|
38
|
+
z: Input data
|
|
39
|
+
shift: Shift zero frequency to center (default: True)
|
|
40
|
+
|
|
41
|
+
Returns:
|
|
42
|
+
FFT of input data
|
|
43
|
+
"""
|
|
44
|
+
z1 = np.fft.fft2(z)
|
|
45
|
+
if shift:
|
|
46
|
+
z1 = np.fft.fftshift(z1)
|
|
47
|
+
return z1
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
@check_2d_array
|
|
51
|
+
def ifft2d(z: np.ndarray, shift: bool = True) -> np.ndarray:
|
|
52
|
+
"""Compute inverse FFT of complex array `z`
|
|
53
|
+
|
|
54
|
+
Args:
|
|
55
|
+
z: Input data
|
|
56
|
+
shift: Shift zero frequency to center (default: True)
|
|
57
|
+
|
|
58
|
+
Returns:
|
|
59
|
+
Inverse FFT of input data
|
|
60
|
+
"""
|
|
61
|
+
if shift:
|
|
62
|
+
z = np.fft.ifftshift(z)
|
|
63
|
+
z1 = np.fft.ifft2(z)
|
|
64
|
+
return z1
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
@check_2d_array
|
|
68
|
+
def magnitude_spectrum(z: np.ndarray, log_scale: bool = False) -> np.ndarray:
|
|
69
|
+
"""Compute magnitude spectrum of complex array `z`
|
|
70
|
+
|
|
71
|
+
Args:
|
|
72
|
+
z: Input data
|
|
73
|
+
log_scale: Use log scale (default: False)
|
|
74
|
+
|
|
75
|
+
Returns:
|
|
76
|
+
Magnitude spectrum of input data
|
|
77
|
+
"""
|
|
78
|
+
z1 = np.abs(fft2d(z))
|
|
79
|
+
if log_scale:
|
|
80
|
+
z1 = 20 * np.log10(z1.clip(1e-10))
|
|
81
|
+
return z1
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
@check_2d_array
|
|
85
|
+
def phase_spectrum(z: np.ndarray) -> np.ndarray:
|
|
86
|
+
"""Compute phase spectrum of complex array `z`
|
|
87
|
+
|
|
88
|
+
Args:
|
|
89
|
+
z: Input data
|
|
90
|
+
|
|
91
|
+
Returns:
|
|
92
|
+
Phase spectrum of input data (in degrees)
|
|
93
|
+
"""
|
|
94
|
+
return np.rad2deg(np.angle(fft2d(z)))
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
@check_2d_array
|
|
98
|
+
def psd(z: np.ndarray, log_scale: bool = False) -> np.ndarray:
|
|
99
|
+
"""Compute power spectral density of complex array `z`
|
|
100
|
+
|
|
101
|
+
Args:
|
|
102
|
+
z: Input data
|
|
103
|
+
log_scale: Use log scale (default: False)
|
|
104
|
+
|
|
105
|
+
Returns:
|
|
106
|
+
Power spectral density of input data
|
|
107
|
+
"""
|
|
108
|
+
z1 = np.abs(fft2d(z)) ** 2
|
|
109
|
+
if log_scale:
|
|
110
|
+
z1 = 10 * np.log10(z1.clip(1e-10))
|
|
111
|
+
return z1
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
@check_2d_array
|
|
115
|
+
def gaussian_freq_filter(
|
|
116
|
+
data: np.ndarray, f0: float = 0.1, sigma: float = 0.05
|
|
117
|
+
) -> np.ndarray:
|
|
118
|
+
"""
|
|
119
|
+
Apply a 2D Gaussian bandpass filter in the frequency domain to an image.
|
|
120
|
+
|
|
121
|
+
This function performs a 2D Fast Fourier Transform (FFT) on the input image,
|
|
122
|
+
applies a Gaussian filter centered at frequency `f0` with standard deviation `sigma`
|
|
123
|
+
(both expressed in cycles per pixel), and then transforms the result back to the
|
|
124
|
+
spatial domain.
|
|
125
|
+
|
|
126
|
+
Args:
|
|
127
|
+
data: Input image data.
|
|
128
|
+
f0: Center frequency of the Gaussian filter (cycles/pixel).
|
|
129
|
+
sigma: Standard deviation of the Gaussian filter (cycles/pixel).
|
|
130
|
+
|
|
131
|
+
Returns:
|
|
132
|
+
The filtered image.
|
|
133
|
+
"""
|
|
134
|
+
n, m = data.shape
|
|
135
|
+
fx = np.fft.fftshift(np.fft.fftfreq(m, d=1))
|
|
136
|
+
fy = np.fft.fftshift(np.fft.fftfreq(n, d=1))
|
|
137
|
+
fx_grid, fy_grid = np.meshgrid(fx, fy)
|
|
138
|
+
freq_radius = np.hypot(fx_grid, fy_grid)
|
|
139
|
+
|
|
140
|
+
# Create the 2D Gaussian bandpass filter
|
|
141
|
+
gaussian_filter = np.exp(-0.5 * ((freq_radius - f0) / sigma) ** 2)
|
|
142
|
+
|
|
143
|
+
# Apply FFT, filter in frequency domain, and inverse FFT
|
|
144
|
+
fft_data = fft2d(data, shift=True)
|
|
145
|
+
filtered_fft = fft_data * gaussian_filter
|
|
146
|
+
zout = ifft2d(filtered_fft, shift=True)
|
|
147
|
+
return zout.real
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
@check_2d_array(non_constant=True)
|
|
151
|
+
def convolve(
|
|
152
|
+
data: np.ndarray,
|
|
153
|
+
kernel: np.ndarray,
|
|
154
|
+
normalize_kernel_flag: bool = True,
|
|
155
|
+
) -> np.ndarray:
|
|
156
|
+
"""
|
|
157
|
+
Perform 2D convolution with a kernel using scipy.signal.convolve.
|
|
158
|
+
|
|
159
|
+
This function adds optional kernel normalization to the standard scipy convolution.
|
|
160
|
+
|
|
161
|
+
Args:
|
|
162
|
+
data: Input image (2D array).
|
|
163
|
+
kernel: Convolution kernel.
|
|
164
|
+
normalize_kernel_flag: If True, normalize kernel so that ``kernel.sum() == 1``
|
|
165
|
+
to preserve image brightness.
|
|
166
|
+
|
|
167
|
+
Returns:
|
|
168
|
+
Convolved image (same shape as input).
|
|
169
|
+
|
|
170
|
+
Raises:
|
|
171
|
+
ValueError: If kernel is empty or null.
|
|
172
|
+
"""
|
|
173
|
+
if kernel.size == 0 or not np.any(kernel):
|
|
174
|
+
raise ValueError("Convolution kernel cannot be null.")
|
|
175
|
+
|
|
176
|
+
# Optionally normalize the kernel
|
|
177
|
+
if normalize_kernel_flag:
|
|
178
|
+
kernel = normalize_kernel(kernel)
|
|
179
|
+
|
|
180
|
+
# Use scipy.signal.convolve with 'same' mode to preserve image size
|
|
181
|
+
return sps.convolve(data, kernel, mode="same", method="auto")
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
@check_2d_array(non_constant=True)
|
|
185
|
+
def deconvolve(
|
|
186
|
+
data: np.ndarray,
|
|
187
|
+
kernel: np.ndarray,
|
|
188
|
+
reg: float = 0.0,
|
|
189
|
+
boundary: str = "edge",
|
|
190
|
+
normalize_kernel_flag: bool = True,
|
|
191
|
+
) -> np.ndarray:
|
|
192
|
+
"""
|
|
193
|
+
Perform 2D FFT deconvolution with correct 'same' geometry (no shift).
|
|
194
|
+
|
|
195
|
+
The kernel (PSF) must be centered (impulse at center for identity kernel).
|
|
196
|
+
Odd kernel sizes are recommended.
|
|
197
|
+
|
|
198
|
+
Args:
|
|
199
|
+
data: Input image (2D array).
|
|
200
|
+
kernel: Point Spread Function (PSF), centered.
|
|
201
|
+
reg: Regularization parameter (if >0, Wiener/Tikhonov inverse:
|
|
202
|
+
``H* / (|H|^2 + reg))``.
|
|
203
|
+
boundary: Padding mode ('edge' for constant plateau,
|
|
204
|
+
'reflect' for symmetric mirror).
|
|
205
|
+
normalize_kernel_flag: If True, normalize kernel so that ``kernel.sum() == 1``
|
|
206
|
+
to preserve image brightness.
|
|
207
|
+
|
|
208
|
+
Returns:
|
|
209
|
+
Deconvolved image (same shape as input).
|
|
210
|
+
|
|
211
|
+
Raises:
|
|
212
|
+
ValueError: If kernel is empty or null.
|
|
213
|
+
"""
|
|
214
|
+
if kernel.size == 0 or not np.any(kernel):
|
|
215
|
+
raise ValueError("Deconvolution kernel cannot be null.")
|
|
216
|
+
|
|
217
|
+
# Optionally normalize the kernel
|
|
218
|
+
if normalize_kernel_flag:
|
|
219
|
+
kernel = normalize_kernel(kernel)
|
|
220
|
+
|
|
221
|
+
H, W = data.shape
|
|
222
|
+
kh, kw = kernel.shape
|
|
223
|
+
|
|
224
|
+
if kh % 2 == 0 or kw % 2 == 0:
|
|
225
|
+
# Warning for even-sized kernels (off-by-one in centered FFT)
|
|
226
|
+
warnings.warn(
|
|
227
|
+
"Deconvolution kernel should have odd dimensions for centered FFT."
|
|
228
|
+
)
|
|
229
|
+
|
|
230
|
+
# Symmetric padding for centered 'same' convolution
|
|
231
|
+
top = kh // 2
|
|
232
|
+
bottom = kh - 1 - top
|
|
233
|
+
left = kw // 2
|
|
234
|
+
right = kw - 1 - left
|
|
235
|
+
data_pad = np.pad(data, ((top, bottom), (left, right)), mode=boundary)
|
|
236
|
+
Hp, Wp = data_pad.shape # = H+kh-1, W+kw-1
|
|
237
|
+
|
|
238
|
+
# Centered PSF to OTF conversion (avoid off-by-one for even sizes)
|
|
239
|
+
kernel_pad = np.zeros_like(data_pad, dtype=float)
|
|
240
|
+
r0 = Hp // 2 - kh // 2
|
|
241
|
+
c0 = Wp // 2 - kw // 2
|
|
242
|
+
kernel_pad[r0 : r0 + kh, c0 : c0 + kw] = kernel
|
|
243
|
+
H_otf = np.fft.fft2(np.fft.ifftshift(kernel_pad)) # center → (0,0)
|
|
244
|
+
|
|
245
|
+
# FFT of padded image (no shift)
|
|
246
|
+
Z = np.fft.fft2(data_pad)
|
|
247
|
+
|
|
248
|
+
# Frequency domain inversion
|
|
249
|
+
if reg > 0.0:
|
|
250
|
+
Hc = np.conj(H_otf)
|
|
251
|
+
X = Z * Hc / (np.abs(H_otf) ** 2 + float(reg))
|
|
252
|
+
else:
|
|
253
|
+
eps = 1e-12
|
|
254
|
+
X = Z / (H_otf + eps)
|
|
255
|
+
|
|
256
|
+
data_true_pad = np.fft.ifft2(X).real
|
|
257
|
+
|
|
258
|
+
# Central crop to restore original geometry
|
|
259
|
+
out = data_true_pad[top : top + H, left : left + W]
|
|
260
|
+
return out
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
# Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
Geometric analysis module
|
|
5
|
+
-------------------------
|
|
6
|
+
|
|
7
|
+
This module provides functions for geometric analysis of images, including
|
|
8
|
+
centroid detection, shape fitting, and spatial measurements.
|
|
9
|
+
|
|
10
|
+
Features include:
|
|
11
|
+
|
|
12
|
+
- Various centroid detection algorithms (Fourier-based, projected profile,
|
|
13
|
+
automatic selection)
|
|
14
|
+
- Enclosing circle calculation for thresholded regions
|
|
15
|
+
- Radial profile extraction around specified centers
|
|
16
|
+
- Absolute level calculation from relative thresholds
|
|
17
|
+
|
|
18
|
+
These tools support precise geometric measurements and shape analysis
|
|
19
|
+
for scientific and technical image analysis applications.
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
from __future__ import annotations
|
|
23
|
+
|
|
24
|
+
from typing import Literal
|
|
25
|
+
|
|
26
|
+
import numpy as np
|
|
27
|
+
from skimage import measure
|
|
28
|
+
|
|
29
|
+
from sigima.tools.checks import check_2d_array
|
|
30
|
+
from sigima.tools.image.preprocessing import get_absolute_level
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
@check_2d_array
|
|
34
|
+
def get_centroid_fourier(data: np.ndarray) -> tuple[float, float]:
|
|
35
|
+
"""Return image centroid using Fourier algorithm
|
|
36
|
+
|
|
37
|
+
Args:
|
|
38
|
+
data: Input data
|
|
39
|
+
|
|
40
|
+
Returns:
|
|
41
|
+
Centroid coordinates (row, col)
|
|
42
|
+
"""
|
|
43
|
+
# Fourier transform method as discussed by Weisshaar et al.
|
|
44
|
+
# (http://www.mnd-umwelttechnik.fh-wiesbaden.de/pig/weisshaar_u5.pdf)
|
|
45
|
+
rows, cols = data.shape
|
|
46
|
+
if rows == 1 or cols == 1:
|
|
47
|
+
return 0, 0
|
|
48
|
+
|
|
49
|
+
i = np.arange(0, rows).reshape(1, rows)
|
|
50
|
+
sin_a = np.sin((i - 1) * 2 * np.pi / (rows - 1)).T
|
|
51
|
+
cos_a = np.cos((i - 1) * 2 * np.pi / (rows - 1)).T
|
|
52
|
+
|
|
53
|
+
j = np.arange(0, cols).reshape(cols, 1)
|
|
54
|
+
sin_b = np.sin((j - 1) * 2 * np.pi / (cols - 1)).T
|
|
55
|
+
cos_b = np.cos((j - 1) * 2 * np.pi / (cols - 1)).T
|
|
56
|
+
|
|
57
|
+
a = np.nansum((cos_a * data))
|
|
58
|
+
b = np.nansum((sin_a * data))
|
|
59
|
+
c = np.nansum((data * cos_b))
|
|
60
|
+
d = np.nansum((data * sin_b))
|
|
61
|
+
|
|
62
|
+
rphi = (0 if b > 0 else 2 * np.pi) if a > 0 else np.pi
|
|
63
|
+
cphi = (0 if d > 0 else 2 * np.pi) if c > 0 else np.pi
|
|
64
|
+
|
|
65
|
+
if a * c == 0.0:
|
|
66
|
+
return 0, 0
|
|
67
|
+
|
|
68
|
+
row = (np.arctan(b / a) + rphi) * (rows - 1) / (2 * np.pi) + 1
|
|
69
|
+
col = (np.arctan(d / c) + cphi) * (cols - 1) / (2 * np.pi) + 1
|
|
70
|
+
|
|
71
|
+
row = np.nan if row is np.ma.masked else row
|
|
72
|
+
col = np.nan if col is np.ma.masked else col
|
|
73
|
+
|
|
74
|
+
return row, col
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
@check_2d_array
|
|
78
|
+
def get_projected_profile_centroid(
|
|
79
|
+
data: np.ndarray, smooth_ratio: float = 1 / 40, method: str = "median"
|
|
80
|
+
) -> tuple[float, float]:
|
|
81
|
+
"""
|
|
82
|
+
Estimate centroid from smoothed 1D projections.
|
|
83
|
+
|
|
84
|
+
Args:
|
|
85
|
+
data: 2D image array
|
|
86
|
+
smooth_ratio: Ratio of smoothing window size (default: 1/40)
|
|
87
|
+
method: 'median' (default) or 'barycenter'
|
|
88
|
+
|
|
89
|
+
Returns:
|
|
90
|
+
(y, x) coordinates
|
|
91
|
+
"""
|
|
92
|
+
x_profile = data.sum(axis=0)
|
|
93
|
+
y_profile = data.sum(axis=1)
|
|
94
|
+
window_size = max(1, int(min(data.shape) * smooth_ratio))
|
|
95
|
+
kernel = np.ones(window_size) / window_size
|
|
96
|
+
x_profile = np.convolve(x_profile, kernel, mode="same")
|
|
97
|
+
y_profile = np.convolve(y_profile, kernel, mode="same")
|
|
98
|
+
x_profile -= np.min(x_profile)
|
|
99
|
+
y_profile -= np.min(y_profile)
|
|
100
|
+
|
|
101
|
+
if method == "median":
|
|
102
|
+
x_integral = np.cumsum(x_profile)
|
|
103
|
+
y_integral = np.cumsum(y_profile)
|
|
104
|
+
x_center = np.interp(
|
|
105
|
+
0.5 * x_integral[-1], x_integral, np.arange(len(x_integral))
|
|
106
|
+
)
|
|
107
|
+
y_center = np.interp(
|
|
108
|
+
0.5 * y_integral[-1], y_integral, np.arange(len(y_integral))
|
|
109
|
+
)
|
|
110
|
+
elif method == "barycenter": # pragma: no cover
|
|
111
|
+
# (ignored for coverage because median gives better results)
|
|
112
|
+
x_center = np.sum(np.arange(len(x_profile)) * x_profile) / np.sum(x_profile)
|
|
113
|
+
y_center = np.sum(np.arange(len(y_profile)) * y_profile) / np.sum(y_profile)
|
|
114
|
+
else:
|
|
115
|
+
raise ValueError("Unknown method: choose 'median' or 'barycenter'")
|
|
116
|
+
|
|
117
|
+
return float(y_center), float(x_center)
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
@check_2d_array
|
|
121
|
+
def get_centroid_auto(
|
|
122
|
+
data: np.ndarray,
|
|
123
|
+
return_method: bool = False,
|
|
124
|
+
) -> tuple[float, float] | tuple[float, float, Literal["fourier", "skimage"]]:
|
|
125
|
+
"""
|
|
126
|
+
Automatically select the most reliable centroid estimation method:
|
|
127
|
+
- Prefer Fourier if it is more consistent with the projected median.
|
|
128
|
+
- Fallback to scikit-image centroid if Fourier is less coherent.
|
|
129
|
+
|
|
130
|
+
Args:
|
|
131
|
+
data: 2D image array.
|
|
132
|
+
return_method: If True, also return the name of the selected method.
|
|
133
|
+
|
|
134
|
+
Returns:
|
|
135
|
+
(row, col): Estimated centroid coordinates (float).
|
|
136
|
+
Optionally, the selected method as string: "fourier" or "skimage".
|
|
137
|
+
"""
|
|
138
|
+
try:
|
|
139
|
+
row_f, col_f = get_centroid_fourier(data)
|
|
140
|
+
except Exception: # pylint: disable=broad-except
|
|
141
|
+
row_f, col_f = float("nan"), float("nan")
|
|
142
|
+
|
|
143
|
+
row_m, col_m = get_projected_profile_centroid(data, method="median")
|
|
144
|
+
row_s, col_s = measure.centroid(data)
|
|
145
|
+
|
|
146
|
+
dist_f = np.hypot(row_f - row_m, col_f - col_m)
|
|
147
|
+
dist_s = np.hypot(row_s - row_m, col_s - col_m)
|
|
148
|
+
|
|
149
|
+
if not (np.isnan(row_f) or np.isnan(col_f)) and dist_f < dist_s:
|
|
150
|
+
result = (row_f, col_f)
|
|
151
|
+
method = "fourier"
|
|
152
|
+
else:
|
|
153
|
+
result = (row_s, col_s)
|
|
154
|
+
method = "skimage"
|
|
155
|
+
|
|
156
|
+
return result + (method,) if return_method else result
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
@check_2d_array(non_constant=True)
|
|
160
|
+
def get_enclosing_circle(
|
|
161
|
+
data: np.ndarray, level: float = 0.5
|
|
162
|
+
) -> tuple[int, int, float]:
|
|
163
|
+
"""Return (x, y, radius) for the circle contour enclosing image
|
|
164
|
+
values above threshold relative level (.5 means FWHM)
|
|
165
|
+
|
|
166
|
+
Args:
|
|
167
|
+
data: Input data
|
|
168
|
+
level: Relative level (default: 0.5)
|
|
169
|
+
|
|
170
|
+
Returns:
|
|
171
|
+
A tuple (x, y, radius)
|
|
172
|
+
|
|
173
|
+
Raises:
|
|
174
|
+
ValueError: No contour was found
|
|
175
|
+
"""
|
|
176
|
+
data_th = data.copy()
|
|
177
|
+
data_th[data <= get_absolute_level(data, level)] = 0.0
|
|
178
|
+
contours = measure.find_contours(data_th)
|
|
179
|
+
model = measure.CircleModel()
|
|
180
|
+
result = None
|
|
181
|
+
max_radius = 1.0
|
|
182
|
+
for contour in contours:
|
|
183
|
+
if model.estimate(contour):
|
|
184
|
+
yc, xc, radius = model.params
|
|
185
|
+
if radius > max_radius:
|
|
186
|
+
result = (int(xc), int(yc), radius)
|
|
187
|
+
max_radius = radius
|
|
188
|
+
if result is None:
|
|
189
|
+
raise ValueError("No contour was found")
|
|
190
|
+
return result
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Signal/Image Preprocessing
|
|
3
|
+
--------------------------
|
|
4
|
+
|
|
5
|
+
This module contains utility functions for preprocessing and transforming image data:
|
|
6
|
+
|
|
7
|
+
- Binning and scaling operations
|
|
8
|
+
- Zero padding for Fourier analysis
|
|
9
|
+
- Utility functions for data transformation
|
|
10
|
+
|
|
11
|
+
.. note::
|
|
12
|
+
All functions in this module are also available directly in the parent
|
|
13
|
+
`sigima.tools.image` package.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
from __future__ import annotations
|
|
17
|
+
|
|
18
|
+
from typing import Literal
|
|
19
|
+
|
|
20
|
+
import numpy as np
|
|
21
|
+
import scipy.spatial as spt
|
|
22
|
+
from numpy import ma
|
|
23
|
+
|
|
24
|
+
from sigima.enums import BinningOperation
|
|
25
|
+
from sigima.tools.checks import check_2d_array
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def get_absolute_level(data: np.ndarray, level: float) -> float:
|
|
29
|
+
"""Get absolute level from relative level
|
|
30
|
+
|
|
31
|
+
Args:
|
|
32
|
+
data: Input data
|
|
33
|
+
level: Relative level (0.0 to 1.0)
|
|
34
|
+
|
|
35
|
+
Returns:
|
|
36
|
+
Absolute level
|
|
37
|
+
|
|
38
|
+
Raises:
|
|
39
|
+
ValueError: If level is not a float between 0.0 and 1.0
|
|
40
|
+
"""
|
|
41
|
+
if not isinstance(level, (int, float)) or level < 0.0 or level > 1.0:
|
|
42
|
+
raise ValueError("Level must be a number between 0.0 and 1.0")
|
|
43
|
+
return np.nanmin(data) + level * (np.nanmax(data) - np.nanmin(data))
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def distance_matrix(coords: list) -> np.ndarray:
|
|
47
|
+
"""Return distance matrix from coords
|
|
48
|
+
|
|
49
|
+
Args:
|
|
50
|
+
coords: List of coordinates
|
|
51
|
+
|
|
52
|
+
Returns:
|
|
53
|
+
Distance matrix
|
|
54
|
+
"""
|
|
55
|
+
return np.triu(spt.distance.cdist(coords, coords, "euclidean"))
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
@check_2d_array
|
|
59
|
+
def binning(
|
|
60
|
+
data: np.ndarray,
|
|
61
|
+
sx: int,
|
|
62
|
+
sy: int,
|
|
63
|
+
operation: BinningOperation | str,
|
|
64
|
+
dtype=None,
|
|
65
|
+
) -> np.ndarray:
|
|
66
|
+
"""Perform image pixel binning
|
|
67
|
+
|
|
68
|
+
Args:
|
|
69
|
+
data: Input data
|
|
70
|
+
sx: Binning size along x (number of pixels to bin together)
|
|
71
|
+
sy: Binning size along y (number of pixels to bin together)
|
|
72
|
+
operation: Binning operation
|
|
73
|
+
dtype: Output data type (default: None, i.e. same as input)
|
|
74
|
+
|
|
75
|
+
Returns:
|
|
76
|
+
Binned data
|
|
77
|
+
"""
|
|
78
|
+
# Convert enum to string value if needed
|
|
79
|
+
if isinstance(operation, BinningOperation):
|
|
80
|
+
operation = operation.value
|
|
81
|
+
|
|
82
|
+
ny, nx = data.shape
|
|
83
|
+
shape = (ny // sy, sy, nx // sx, sx)
|
|
84
|
+
try:
|
|
85
|
+
bdata = data[: ny - ny % sy, : nx - nx % sx].reshape(shape)
|
|
86
|
+
except ValueError as err:
|
|
87
|
+
raise ValueError("Binning is not a multiple of image dimensions") from err
|
|
88
|
+
if operation == "sum":
|
|
89
|
+
bdata = np.array(bdata, dtype=float).sum(axis=(-1, 1))
|
|
90
|
+
elif operation == "average":
|
|
91
|
+
bdata = bdata.mean(axis=(-1, 1))
|
|
92
|
+
elif operation == "median":
|
|
93
|
+
bdata = ma.median(bdata, axis=(-1, 1))
|
|
94
|
+
elif operation == "min":
|
|
95
|
+
bdata = bdata.min(axis=(-1, 1))
|
|
96
|
+
elif operation == "max":
|
|
97
|
+
bdata = bdata.max(axis=(-1, 1))
|
|
98
|
+
else:
|
|
99
|
+
valid = ", ".join(op.value for op in BinningOperation)
|
|
100
|
+
raise ValueError(f"Invalid operation {operation} (valid values: {valid})")
|
|
101
|
+
return np.array(bdata, dtype=data.dtype if dtype is None else np.dtype(dtype))
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
@check_2d_array(non_constant=True)
|
|
105
|
+
def scale_data_to_min_max(
|
|
106
|
+
data: np.ndarray, zmin: float | int, zmax: float | int
|
|
107
|
+
) -> np.ndarray:
|
|
108
|
+
"""Scale array `data` to fit [zmin, zmax] dynamic range
|
|
109
|
+
|
|
110
|
+
Args:
|
|
111
|
+
data: Input data
|
|
112
|
+
zmin: Minimum value of output data
|
|
113
|
+
zmax: Maximum value of output data
|
|
114
|
+
|
|
115
|
+
Returns:
|
|
116
|
+
Scaled data
|
|
117
|
+
"""
|
|
118
|
+
dmin, dmax = np.nanmin(data), np.nanmax(data)
|
|
119
|
+
if dmin == zmin and dmax == zmax:
|
|
120
|
+
return data
|
|
121
|
+
fdata = np.array(data, dtype=float)
|
|
122
|
+
fdata -= dmin
|
|
123
|
+
fdata *= float(zmax - zmin) / (dmax - dmin)
|
|
124
|
+
fdata += float(zmin)
|
|
125
|
+
return np.array(fdata, data.dtype)
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
@check_2d_array
|
|
129
|
+
def zero_padding(
|
|
130
|
+
data: np.ndarray,
|
|
131
|
+
rows: int = 0,
|
|
132
|
+
cols: int = 0,
|
|
133
|
+
position: Literal["bottom-right", "around"] = "bottom-right",
|
|
134
|
+
) -> np.ndarray:
|
|
135
|
+
"""
|
|
136
|
+
Zero-pad a 2D image by adding rows and/or columns.
|
|
137
|
+
|
|
138
|
+
Args:
|
|
139
|
+
data: 2D input image (grayscale)
|
|
140
|
+
rows: Number of rows to add in total (default: 0)
|
|
141
|
+
cols: Number of columns to add in total (default: 0)
|
|
142
|
+
position: Padding placement strategy:
|
|
143
|
+
- "bottom-right": all padding is added to the bottom and right
|
|
144
|
+
- "around": padding is split equally on top/bottom and left/right
|
|
145
|
+
|
|
146
|
+
Returns:
|
|
147
|
+
The padded 2D image as a NumPy array.
|
|
148
|
+
|
|
149
|
+
Raises:
|
|
150
|
+
ValueError: If the input is not a 2D array or if padding values are negative.
|
|
151
|
+
"""
|
|
152
|
+
if rows < 0 or cols < 0:
|
|
153
|
+
raise ValueError("Padding values must be non-negative")
|
|
154
|
+
|
|
155
|
+
if position == "bottom-right":
|
|
156
|
+
pad_width = ((0, rows), (0, cols))
|
|
157
|
+
elif position == "around":
|
|
158
|
+
pad_width = (
|
|
159
|
+
(rows // 2, rows - rows // 2),
|
|
160
|
+
(cols // 2, cols - cols // 2),
|
|
161
|
+
)
|
|
162
|
+
else:
|
|
163
|
+
raise ValueError(f"Invalid position: {position}")
|
|
164
|
+
|
|
165
|
+
return np.pad(data, pad_width, mode="constant", constant_values=0)
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Signal Processing Tools (:mod:`sigima.tools.signal`)
|
|
3
|
+
----------------------------------------------------
|
|
4
|
+
|
|
5
|
+
This package contains signal processing tools, which are organized into subpackages
|
|
6
|
+
according to their purpose:
|
|
7
|
+
|
|
8
|
+
- :mod:`sigima.tools.signal.dynamic`: Dynamic parameter extraction
|
|
9
|
+
- :mod:`sigima.tools.signal.features`: Feature extraction algorithms
|
|
10
|
+
- :mod:`sigima.tools.signal.pulse`: Curve fitting models
|
|
11
|
+
- :mod:`sigima.tools.signal.fourier`: Fourier analysis algorithms
|
|
12
|
+
- :mod:`sigima.tools.signal.interpolation`: Interpolation algorithms
|
|
13
|
+
- :mod:`sigima.tools.signal.peakdetection`: Peak detection algorithms
|
|
14
|
+
- :mod:`sigima.tools.signal.pulse`: Pulse analysis algorithms
|
|
15
|
+
- :mod:`sigima.tools.signal.scaling`: Scaling algorithms
|
|
16
|
+
- :mod:`sigima.tools.signal.stability`: Stability analysis algorithms
|
|
17
|
+
- :mod:`sigima.tools.signal.windowing`: Windowing algorithms
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
Dynamic Parameter Extraction
|
|
21
|
+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
22
|
+
|
|
23
|
+
.. automodule:: sigima.tools.signal.dynamic
|
|
24
|
+
:members:
|
|
25
|
+
|
|
26
|
+
Feature Extraction Algorithms
|
|
27
|
+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
28
|
+
|
|
29
|
+
.. automodule:: sigima.tools.signal.features
|
|
30
|
+
:members:
|
|
31
|
+
|
|
32
|
+
Filtering Functions
|
|
33
|
+
^^^^^^^^^^^^^^^^^^^
|
|
34
|
+
|
|
35
|
+
.. automodule:: sigima.tools.signal.filtering
|
|
36
|
+
:members:
|
|
37
|
+
|
|
38
|
+
Curve Fitting Models
|
|
39
|
+
^^^^^^^^^^^^^^^^^^^^
|
|
40
|
+
|
|
41
|
+
.. automodule:: sigima.tools.signal.fitting
|
|
42
|
+
:members:
|
|
43
|
+
|
|
44
|
+
Fourier Analysis Algorithms
|
|
45
|
+
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
46
|
+
|
|
47
|
+
.. automodule:: sigima.tools.signal.fourier
|
|
48
|
+
:members:
|
|
49
|
+
|
|
50
|
+
Interpolation Algorithms
|
|
51
|
+
^^^^^^^^^^^^^^^^^^^^^^^^
|
|
52
|
+
|
|
53
|
+
.. automodule:: sigima.tools.signal.interpolation
|
|
54
|
+
:members:
|
|
55
|
+
|
|
56
|
+
Peak Detection Algorithms
|
|
57
|
+
^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
58
|
+
|
|
59
|
+
.. automodule:: sigima.tools.signal.peakdetection
|
|
60
|
+
:members:
|
|
61
|
+
|
|
62
|
+
Pulse Analysis Algorithms
|
|
63
|
+
^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
64
|
+
|
|
65
|
+
.. automodule:: sigima.tools.signal.pulse
|
|
66
|
+
:members:
|
|
67
|
+
|
|
68
|
+
Scaling Algorithms
|
|
69
|
+
^^^^^^^^^^^^^^^^^^
|
|
70
|
+
|
|
71
|
+
.. automodule:: sigima.tools.signal.scaling
|
|
72
|
+
:members:
|
|
73
|
+
|
|
74
|
+
Stability Analysis Algorithms
|
|
75
|
+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
76
|
+
|
|
77
|
+
.. automodule:: sigima.tools.signal.stability
|
|
78
|
+
:members:
|
|
79
|
+
|
|
80
|
+
Windowing Algorithms
|
|
81
|
+
^^^^^^^^^^^^^^^^^^^^
|
|
82
|
+
|
|
83
|
+
.. automodule:: sigima.tools.signal.windowing
|
|
84
|
+
:members:
|
|
85
|
+
|
|
86
|
+
"""
|