Tools (sigima.tools)#

This package contains functions operating on NumPy arrays that are intended to be used in Sigima computation functions. These functions are complementary to the algorithms provided by external libraries such as SciPy, NumPy, and scikit-image.

Even though these functions are primarily designed to be used in the Sigima pipeline, they can also be used independently. They provide a wide range of features but are not exhaustive due to the vast number of algorithms already available in the scientific Python ecosystem.

See also

The sigima.proc module contains the Sigima computation functions that operate on signal and image objects (i.e. sigima.objects.SignalObj and sigima.objects.ImageObj, defined in the sigima.objects package).

These tools are organized in subpackages according to their purpose. The following subpackages are available:

Check functions#

class sigima.tools.checks.ArrayValidationRules(label: str, require_1d: bool = True, min_size: int | None = None, dtype: type | None = None, finite_only: bool = False, sorted_: bool = False, evenly_spaced: bool = False, rtol: float = 1e-05)[source]#

Hold 1-D array validation rules.

label: str#

Label used in error messages (e.g., “x” or “y”)

require_1d: bool = True#

Whether to enforce 1-D.

min_size: int | None = None#

Check minimum size

dtype: type | None = None#

Expected dtype (np.issubdtype). Use None to skip.

finite_only: bool = False#

Whether to enforce finite values only.

sorted_: bool = False#

Whether to enforce non-decreasing order.

evenly_spaced: bool = False#

Whether to enforce constant spacing (within rtol).

rtol: float = 1e-05#

Relative tolerance for regular spacing.

sigima.tools.checks.check_1d_array(func: ~typing.Callable[[...], ~typing.Any] | None = None, *, require_1d: bool = True, min_size: int | None = None, dtype: type | None = <class 'numpy.inexact'>, finite_only: bool = False, sorted_: bool = False, evenly_spaced: bool = False, rtol: float = 1e-05, label: str = 'array') Callable[source]#

Decorator to check a single 1D NumPy array.

Can be used with or without parentheses.

Parameters:
  • require_1d – Whether to check if the array is 1-D.

  • min_size – Minimum size of the array.

  • dtype – Expected dtype of the array (np.issubdtype). Use None to skip.

  • finite_only – Whether to check if the array contains only finite values.

  • sorted – Whether to check if the array is sorted in ascending order.

  • evenly_spaced – Whether to check if the array is evenly spaced.

  • rtol – Relative tolerance for regular spacing.

  • label – Label for error messages (e.g., “x”, “y”).

Returns:

Decorated function with pre-checks on the single array.

sigima.tools.checks.check_1d_arrays(func: ~typing.Callable[[...], ~typing.Any] | None = None, *, x_require_1d: bool = True, x_min_size: int | None = None, x_dtype: type | None = <class 'numpy.floating'>, x_finite_only: bool = False, x_sorted: bool = False, x_evenly_spaced: bool = False, y_require_1d: bool = True, y_min_size: int | None = None, y_dtype: type | None = <class 'numpy.inexact'>, y_finite_only: bool = False, same_size: bool = True, rtol: float = 1e-05) Callable[source]#

Decorator to check paired 1D NumPy arrays (x, y).

Can be used with or without parentheses.

Parameters:
  • func – Function to decorate.

  • x_require_1d – Whether to check if x is 1-D.

  • x_min_size – Minimum size of x.

  • x_dtype – Expected dtype of x (np.issubdtype). Use None to skip.

  • x_finite_only – Whether to check if x contains only finite values.

  • x_sorted – Whether to check if x is sorted in ascending order.

  • x_evenly_spaced – Whether to check if x is evenly spaced.

  • y_require_1d – Whether to check if y is 1-D.

  • y_min_size – Minimum size of y.

  • y_dtype – Expected dtype of y (np.issubdtype). Use None to skip.

  • y_finite_only – Whether to check if y contains only finite values.

  • same_size – Whether to check that x and y have the same size.

  • rtol – Relative tolerance for regular spacing (used for x).

Returns:

Decorated function with pre-checks on x/y.

sigima.tools.checks.check_2d_array(func: Callable[[...], Any] | None = None, *, ndim: int = 2, dtype: type | None = None, non_constant: bool = False, finite_only: bool = False) Callable[source]#

Decorator to check input for functions operating on 2D NumPy arrays (e.g. images).

Can be used with parentheses:

@check_2d_array(ndim=3, dtype=np.uint8)
def process_image(image: np.ndarray) -> np.ndarray:
    # Process the image
    return image

Or without parentheses (default arguments):

@check_2d_array
def process_image(image: np.ndarray) -> np.ndarray:
    # Process the image
    return image
Parameters:
  • ndim – Expected number of dimensions.

  • dtype – Expected dtype.

  • non_constant – Whether to check that the array has dynamic range.

  • finite_only – Whether to check that all values are finite.

Returns:

Decorated function with pre-checks on data.

sigima.tools.checks.normalize_kernel(kernel: ndarray) ndarray[source]#

Normalize a convolution/deconvolution kernel if needed.

This utility function can normalize the kernel to sum to 1.0.

Parameters:

kernel – The kernel array to normalize.

Returns:

The normalized kernel if it’s not already normalized and if its sum is not zero, otherwise the original kernel.

Note

A kernel is considered normalized if np.isclose(sum(kernel), 1.0).

Signal Processing Tools#

Signal Processing Tools (sigima.tools.signal)#

This package contains signal processing tools, which are organized into subpackages according to their purpose:

Dynamic Parameter Extraction#

sigima.tools.signal.dynamic.sinusoidal_model(x: ndarray, a: float, f: float, phi: float, offset: float) ndarray[source]#

Sinusoidal model function.

sigima.tools.signal.dynamic.sinusoidal_fit(x: ndarray, y: ndarray) tuple[tuple[float, float, float, float], float][source]#

Fit a sinusoidal model to the input data.

Parameters:
  • x – X data

  • y – Y data

Returns:

A tuple containing the fit parameters (amplitude, frequency, phase, offset) and the residuals

sigima.tools.signal.dynamic.sinus_frequency(x: ndarray, y: ndarray) float[source]#

Compute the frequency of a sinusoidal signal.

Parameters:
  • x – x signal data

  • y – y signal data

Returns:

Frequency of the sinusoidal signal

sigima.tools.signal.dynamic.enob(x: ndarray, y: ndarray, full_scale: float = 1.0) float[source]#

Compute Effective Number of Bits (ENOB).

Parameters:
  • x – x signal data

  • y – y signal data

  • full_scale – Full scale(V). Defaults to 1.0.

Returns:

Effective Number of Bits (ENOB)

sigima.tools.signal.dynamic.sinad(x: ndarray, y: ndarray, full_scale: float = 1.0, unit: PowerUnit = 'dBc') float[source]#

Compute Signal-to-Noise and Distortion Ratio (SINAD).

Parameters:
  • x – x signal data

  • y – y signal data

  • full_scale – Full scale(V). Defaults to 1.0.

  • unit – Unit of the input data. Defaults to PowerUnit.DBC.

Returns:

Signal-to-Noise and Distortion Ratio (SINAD)

sigima.tools.signal.dynamic.thd(x: ndarray, y: ndarray, full_scale: float = 1.0, unit: PowerUnit = 'dBc', nb_harm: int = 5) float[source]#

Compute Total Harmonic Distortion (THD).

Parameters:
  • x – x signal data

  • y – y signal data

  • full_scale – Full scale(V). Defaults to 1.0.

  • unit – Unit of the input data. Defaults to PowerUnit.DBC.

  • nb_harm – Number of harmonics to consider. Defaults to 5.

Returns:

Total Harmonic Distortion (THD)

sigima.tools.signal.dynamic.sfdr(x: ndarray, y: ndarray, full_scale: float = 1.0, unit: PowerUnit = 'dBc') float[source]#

Compute Spurious-Free Dynamic Range (SFDR).

Parameters:
  • x – x signal data

  • y – y signal data

  • full_scale – Full scale(V). Defaults to 1.0.

  • unit – Unit of the input data. Defaults to PowerUnit.DBC.

Returns:

Spurious-Free Dynamic Range (SFDR)

sigima.tools.signal.dynamic.snr(x: ndarray, y: ndarray, full_scale: float = 1.0, unit: PowerUnit = 'dBc') float[source]#

Compute Signal-to-Noise Ratio (SNR).

Parameters:
  • x – x signal data

  • y – y signal data

  • full_scale – Full scale(V). Defaults to 1.0.

  • unit – Unit of the input data. Defaults to PowerUnit.DBC.

Returns:

Signal-to-Noise Ratio (SNR)

sigima.tools.signal.dynamic.sampling_period(x: ndarray) float[source]#

Compute sampling period

Parameters:

x – X data

Returns:

Sampling period

sigima.tools.signal.dynamic.sampling_rate(x: ndarray) float[source]#

Compute mean sampling rate

Parameters:

x – X data

Returns:

Sampling rate

Feature Extraction Algorithms#

sigima.tools.signal.features.find_zero_crossings(y: ndarray) ndarray[source]#

Find the left indices of the zero-crossing intervals in the given array.

A zero crossing is detected when consecutive non-zero samples have opposite signs. Samples exactly equal to zero are skipped: a contiguous run of zero samples that bridges samples of opposite sign counts as a single crossing, located at the index of the last non-zero sample before the run; a run of zeros that does not change the sign (e.g. [1, 0, 1]) is not reported as a crossing.

Parameters:

y – Input array.

Returns:

An array of indices where zero-crossings occur.

sigima.tools.signal.features.find_x_axis_crossings(x: ndarray, y: ndarray) ndarray[source]#

Find the \(x_n\) values where \(y = f(x)\) intercepts the x-axis.

This function uses zero-crossing detection and interpolation to find the x values where \(y = 0\).

Parameters:
  • x – X data.

  • y – Y data.

Returns:

Array of x-intercepts. The array is empty if no intercept is found.

sigima.tools.signal.features.find_y_at_x_value(x: ndarray, y: ndarray, x_target: float) float[source]#

Return the y value at a specified x value using linear interpolation.

Parameters:
  • x – X data.

  • y – Y data.

  • x_target – Input x value.

Returns:

Interpolated y value at x_target, or nan if input value is not within the interpolation range.

sigima.tools.signal.features.find_x_values_at_y(x: ndarray, y: ndarray, y_target: float) ndarray[source]#

Find all x values where \(y = f(x)\) equals the value \(y_target\).

Parameters:
  • x – X data.

  • y – Y data.

  • y_target – Target value.

Returns:

Array of x values where \(y = f(x)\) equals \(y_target\).

sigima.tools.signal.features.find_bandwidth_coordinates(x: ndarray, y: ndarray, threshold: float = -3.0) tuple[float, float, float, float] | None[source]#

Compute the bandwidth of the signal at a given threshold relative to the maximum.

Parameters:
  • x – X data.

  • y – Y data.

  • threshold – Threshold in decibel (relative to the maximum) at which the bandwidth is computed. Defaults to -3.0 dB.

Returns:

Segment coordinates of the bandwidth of the signal at the given threshold. Returns None if the bandwidth cannot be determined.

sigima.tools.signal.features.contrast(y: ndarray) float[source]#

Compute contrast.

The contrast is defined as (max - min) / (|max| + |min|). For non-negative signals this matches the standard Michelson contrast (max - min) / (max + min). For signals containing negative samples, the absolute values in the denominator keep the result well-defined and bounded in [0, 1]. If both max and min are zero, nan is returned.

Parameters:

y – Input array

Returns:

Contrast value in [0, 1], or nan if undefined.

Filtering Functions#

This module provides denoising and filtering tools, such as Savitzky-Golay.

class sigima.tools.signal.filtering.SimilarityResult(ok: bool, rel_dc_diff: float, corr: float)[source]#

Result of signal similarity validation.

sigima.tools.signal.filtering.signal_similarity(y: ndarray, y_filtered: ndarray, max_dc_diff: float = 0.01, min_corr: float = 0.99) SimilarityResult[source]#

Check global similarity between two signals.

Criteria:
  • DC level (mean value) must not drift more than max_dc_diff (relative).

  • Correlation (cosine similarity) must stay above min_corr.

Parameters:
  • y – Original 1D signal.

  • y_filtered – Filtered 1D signal (same length as y).

  • max_dc_diff – Maximum allowed relative change in mean value.

  • min_corr – Minimum allowed correlation between signals.

Returns:

A result object containing the similarity metrics.

sigima.tools.signal.filtering.savgol_filter(y: ndarray, window_length: int = 11, polyorder: int = 3, mode: str = 'interp') ndarray[source]#

Smooth a 1D signal using the Savitzky-Golay filter.

Parameters:
  • y – Input signal values.

  • window_length – Length of the filter window (must be odd and > polyorder).

  • polyorder – Order of the polynomial used to fit the samples.

  • mode – Padding mode passed to scipy.signal.savgol_filter.

Returns:

Smoothed signal values.

sigima.tools.signal.filtering.choose_savgol_window_auto(y: ndarray, target_reduction: float = 0.3, polyorder: int = 3, min_len: int = 5, max_len: int = 101) int[source]#

Choose the smallest Savitzky-Golay window that sufficiently reduces noise.

Strategy: measure noise on first differences of y, then increase the window until noise is reduced by target_reduction.

Parameters:
  • y – 1D signal values.

  • target_reduction – Desired reduction factor in diff-std (e.g. 0.3 → ÷3).

  • polyorder – Polynomial order.

  • min_len – Minimum allowed window length.

  • max_len – Maximum allowed window length.

Returns:

Odd integer window length.

sigima.tools.signal.filtering.denoise_preserve_shape(y: ndarray, polyorder: int = 3, target_reduction: float = 0.3, max_dc_diff: float = 0.01, min_corr: float = 0.99, min_len: int = 5, max_len: int = 101) tuple[ndarray, SimilarityResult][source]#

Denoise a signal while preserving slow variations.

Strategy:
  1. Estimate noise on first differences.

  2. Choose the smallest Savitzky-Golay window that reduces noise by at least target_reduction.

  3. Apply the filter.

  4. Check similarity with the original signal (DC and correlation).

  5. Return filtered signal if ok, otherwise return original.

Parameters:
  • y – Input signal values.

  • polyorder – Polynomial order of Savitzky-Golay filter.

  • target_reduction – Desired noise reduction factor (0.3 → ÷3).

  • max_dc_diff – Maximum allowed relative change in mean value.

  • min_corr – Minimum allowed correlation between signals.

  • min_len – Minimum window length.

  • max_len – Maximum window length.

Returns:

A tuple (y_denoised, result) where y_denoised is either the filtered signal or the original if similarity criteria are not met, and result contains the details of the similarity check.

Curve Fitting Models#

Curve Fitting Algorithms#

This module provides curve fitting functions without GUI dependencies. The functions take x,y data and return fitted curves and parameters.

These functions are designed to be used programmatically and in tests, providing the core fitting algorithms without PlotPy GUI components.

class sigima.tools.signal.fitting.FitComputer(x: ndarray, y: ndarray)[source]#

Base class for fit computers

get_params_names() tuple[str][source]#

Return the names of the parameters used in this fit.

check_params(**params) None[source]#

Check that all required parameters are provided.

classmethod args_kwargs_to_list(*args, **kwargs) list[float][source]#

Convert args and kwargs to a parameter list.

classmethod infer_param_names_from_kwargs(kwargs: dict) tuple[str, ...][source]#

Infer parameter names from kwargs. Override in subclasses if needed.

classmethod evaluate(x: ndarray, *args, **kwargs) ndarray[source]#

Evaluate the fit function at given x values.

compute_initial_params() dict[str, float][source]#

Compute initial parameters for fitting. To be implemented by subclasses.

compute_bounds(**initial_params) list[tuple[float, float]] | None[source]#

Compute parameter bounds for fitting.

create_params(y_fitted: ndarray, **params) dict[str, float][source]#

Create a fit parameters dictionary from given parameters.

fit() tuple[ndarray, dict[str, float]][source]#

Fit the model to the data.

optimize_fit_with_scipy() tuple[ndarray, ndarray][source]#

Generic fitting function using scipy.optimize.curve_fit

Returns:

(fitted_y_values, fitted_parameters)

Return type:

tuple

class sigima.tools.signal.fitting.LinearFitComputer(x: ndarray, y: ndarray)[source]#

Linear fit computer

classmethod evaluate(x: ndarray, *args, **kwargs) ndarray[source]#

Evaluate linear function at given x values.

compute_initial_params() dict[str, float][source]#

Compute initial parameters for linear fitting using numpy polyfit.

class sigima.tools.signal.fitting.PolynomialFitComputer(x: ndarray, y: ndarray, degree: int = 2)[source]#

Polynomial fit computer of given degree

get_params_names() tuple[str][source]#

Return the names of the parameters used in this fit.

classmethod infer_param_names_from_kwargs(kwargs: dict) tuple[str, ...][source]#

Infer parameter names for polynomial from kwargs.

classmethod evaluate(x: ndarray, *args, **kwargs) ndarray[source]#

Evaluate polynomial function at given x values.

compute_initial_params() dict[str, float][source]#

Compute initial parameters for polynomial fitting using numpy polyfit.

class sigima.tools.signal.fitting.GaussianFitComputer(x: ndarray, y: ndarray)[source]#

Gaussian fit computer

classmethod evaluate(x: ndarray, *args, **kwargs) ndarray[source]#

Evaluate Gaussian function at given x values.

compute_initial_params() dict[str, float][source]#

Compute initial parameters for Gaussian fitting.

compute_bounds(**initial_params) list[tuple[float, float]] | None[source]#

Compute parameter bounds for Gaussian fitting.

class sigima.tools.signal.fitting.LorentzianFitComputer(x: ndarray, y: ndarray)[source]#

Lorentzian fit computer

classmethod evaluate(x: ndarray, *args, **kwargs) ndarray[source]#

Evaluate Lorentzian function at given x values.

compute_initial_params() dict[str, float][source]#

Compute initial parameters for Lorentzian fitting.

compute_bounds(**initial_params) list[tuple[float, float]] | None[source]#

Compute parameter bounds for Lorentzian fitting.

class sigima.tools.signal.fitting.VoigtFitComputer(x: ndarray, y: ndarray)[source]#

Voigt fit computer

classmethod evaluate(x: ndarray, *args, **kwargs) ndarray[source]#

Evaluate Voigt function at given x values.

compute_initial_params() dict[str, float][source]#

Compute initial parameters for Voigt fitting.

compute_bounds(**initial_params) list[tuple[float, float]] | None[source]#

Compute parameter bounds for Voigt fitting.

class sigima.tools.signal.fitting.ExponentialFitComputer(x: ndarray, y: ndarray)[source]#

Exponential fit computer: y = a * exp(b * x) + y0

classmethod evaluate(x: ndarray, *args, **kwargs) ndarray[source]#

Evaluate exponential function at given x values.

compute_initial_params() dict[str, float][source]#

Compute initial parameters for exponential fitting.

compute_bounds(**initial_params) list[tuple[float, float]] | None[source]#

Compute parameter bounds for exponential fitting.

class sigima.tools.signal.fitting.PlanckianFitComputer(x: ndarray, y: ndarray)[source]#

Planckian fit computer

classmethod evaluate(x: ndarray, *args, **kwargs) ndarray[source]#

Return Planckian fitting function

Parameters:
  • x – wavelength values (in nm or other units)

  • amp – amplitude scaling factor

  • x0 – peak wavelength (Wien’s displacement law)

  • sigma – width parameter (larger sigma = wider peak)

  • y0 – baseline offset

compute_initial_params() dict[str, float][source]#

Compute initial parameters for Planckian fitting.

compute_bounds(**initial_params) list[tuple[float, float]] | None[source]#

Compute parameter bounds for Planckian fitting.

class sigima.tools.signal.fitting.TwoHalfGaussianFitComputer(x: ndarray, y: ndarray)[source]#

Two Half-Gaussian fit computer

classmethod evaluate(x: ndarray, *args, **kwargs) ndarray[source]#

Return two half-Gaussian with separate left/right amplitudes

Parameters:
  • x – x values

  • amp_left – amplitude for left side (x < x0)

  • amp_right – amplitude for right side (x >= x0)

  • sigma_left – standard deviation for x < x0

  • sigma_right – standard deviation for x > x0

  • x0 – center position

  • y0_left – baseline offset for x < x0

  • y0_right – baseline offset for x >= x0

compute_initial_params() dict[str, float][source]#

Compute initial parameters for Two Half-Gaussian fitting.

class sigima.tools.signal.fitting.DoubleExponentialFitComputer(x: ndarray, y: ndarray)[source]#

Piecewise exponential (raise-decay) fit computer.

classmethod evaluate(x: ndarray, *args, **kwargs) ndarray[source]#

Return piecewise exponential (raise-decay) fitting function

Parameters:
  • x – time values

  • x_center – center position (boundary between left and right components)

  • a_left – left component amplitude coefficient

  • b_left – left component time constant coefficient

  • a_right – right component amplitude coefficient

  • b_right – right component time constant coefficient

  • y0 – baseline offset

compute_initial_params() dict[str, float][source]#

Compute initial parameters for piecewise exponential (raise-decay) fitting.

class sigima.tools.signal.fitting.BaseMultiPeakFitComputer(x: ndarray, y: ndarray, peak_indices: list[int] | None = None)[source]#

Base class for multi-peak fit computers

get_params_names() tuple[str][source]#

Return the names of the parameters used in this fit.

classmethod infer_param_names_from_kwargs(kwargs: dict) tuple[str, ...][source]#

Infer parameter names for multi-gaussian from kwargs.

classmethod evaluate(x: ndarray, *args, **kwargs) ndarray[source]#

Evaluate the fit function at given x values.

compute_initial_params() dict[str, float][source]#

Compute initial parameters for Multi Gaussian fitting.

compute_bounds(**initial_params) list[tuple[float, float]] | None[source]#

Compute parameter bounds for Multi Lorentzian fitting.

create_params(y_fitted: ndarray, **params) dict[str, float][source]#

Create a flat fit parameters dictionary.

class sigima.tools.signal.fitting.MultiGaussianFitComputer(x: ndarray, y: ndarray, peak_indices: list[int] | None = None)[source]#

Multi Gaussian fit computer

PULSE_MODEL#

alias of GaussianModel

class sigima.tools.signal.fitting.MultiLorentzianFitComputer(x: ndarray, y: ndarray, peak_indices: list[int] | None = None)[source]#

Multi Lorentzian fit computer

PULSE_MODEL#

alias of LorentzianModel

class sigima.tools.signal.fitting.SinusoidalFitComputer(x: ndarray, y: ndarray)[source]#

Sinusoidal fit computer.

classmethod evaluate(x: ndarray, *args, **kwargs) ndarray[source]#

Evaluate sinusoidal function at given x values.

compute_initial_params() dict[str, float][source]#

Compute initial parameters for sinusoidal fitting.

compute_bounds(**initial_params) list[tuple[float, float]] | None[source]#

Compute parameter bounds for sinusoidal fitting.

class sigima.tools.signal.fitting.CDFFitComputer(x: ndarray, y: ndarray)[source]#

Cumulative Distribution Function (CDF) fit computer

classmethod evaluate(x: ndarray, *args, **kwargs) ndarray[source]#

Evaluate CDF function at given x values.

compute_initial_params() dict[str, float][source]#

Compute initial parameters for CDF fitting.

compute_bounds(**initial_params) list[tuple[float, float]] | None[source]#

Compute parameter bounds for CDF fitting.

class sigima.tools.signal.fitting.SigmoidFitComputer(x: ndarray, y: ndarray)[source]#

Sigmoid fit computer.

classmethod evaluate(x: ndarray, *args, **kwargs) ndarray[source]#

Evaluate Sigmoid function at given x values.

compute_initial_params() dict[str, float][source]#

Compute initial parameters for Sigmoid fitting.

compute_bounds(**initial_params) list[tuple[float, float]] | None[source]#

Compute parameter bounds for Sigmoid fitting.

sigima.tools.signal.fitting.linear_fit(x: ndarray, y: ndarray) tuple[ndarray, dict[str, float]][source]#

Compute linear fit: y = a*x + b.

Parameters:
  • x – x data array

  • y – y data array

Returns:

A tuple containing the fitted y values and a dictionary of fit parameters.

sigima.tools.signal.fitting.polynomial_fit(x: ndarray, y: ndarray, degree: int = 2) tuple[ndarray, dict[str, float]][source]#

Compute polynomial fit.

Parameters:
  • x – x data array

  • y – y data array

  • degree – polynomial degree

Returns:

A tuple containing the fitted y values and a dictionary of fit parameters.

sigima.tools.signal.fitting.gaussian_fit(x: ndarray, y: ndarray) tuple[ndarray, dict[str, float]][source]#

Compute Gaussian fit.

Parameters:
  • x – x data array

  • y – y data array

Returns:

A tuple containing the fitted y values and a dictionary of fit parameters.

sigima.tools.signal.fitting.lorentzian_fit(x: ndarray, y: ndarray) tuple[ndarray, dict][source]#

Compute Lorentzian fit.

Parameters:
  • x – x data array

  • y – y data array

Returns:

A tuple containing the fitted y values and a dictionary of fit parameters.

sigima.tools.signal.fitting.exponential_fit(x: ndarray, y: ndarray) tuple[ndarray, dict[str, float]][source]#

Compute exponential fit: y = a * exp(b * x) + y0.

Parameters:
  • x – x data array

  • y – y data array

Returns:

A tuple containing the fitted y values and a dictionary of fit parameters.

sigima.tools.signal.fitting.planckian_fit(x: ndarray, y: ndarray) tuple[ndarray, dict[str, float]][source]#

Compute Planckian (blackbody radiation) fit.

Parameters:
  • x – wavelength data array

  • y – intensity data array

Returns:

A tuple containing the fitted y values and a dictionary of fit parameters.

sigima.tools.signal.fitting.twohalfgaussian_fit(x: ndarray, y: ndarray) tuple[ndarray, dict[str, float]][source]#

Compute two half-Gaussian fit for asymmetric peaks with separate baselines.

Now supports separate amplitudes for even better asymmetric peak fitting.

Parameters:
  • x – x data array

  • y – y data array

Returns:

A tuple containing the fitted y values and a dictionary of fit parameters.

sigima.tools.signal.fitting.piecewiseexponential_fit(x: ndarray, y: ndarray) tuple[ndarray, dict[str, float]][source]#

Compute piecewise exponential fit (raise-decay).

Parameters:
  • x – time data array

  • y – intensity data array

Returns:

A tuple containing the fitted y values and a dictionary of fit parameters.

sigima.tools.signal.fitting.multilorentzian_fit(x: ndarray, y: ndarray, peak_indices: list[int]) tuple[ndarray, dict[str, float]][source]#

Compute multi-Lorentzian fit for multiple peaks.

Parameters:
  • x – x data array

  • y – y data array

  • peak_indices – list of peak indices

Returns:

A tuple containing the fitted y values and a dictionary of fit parameters.

sigima.tools.signal.fitting.multigaussian_fit(x: ndarray, y: ndarray, peak_indices: list[int]) tuple[ndarray, dict[str, float]][source]#

Compute multi-Gaussian fit for multiple peaks.

Parameters:
  • x – x data array

  • y – y data array

  • peak_indices – list of peak indices

Returns:

A tuple containing the fitted y values and a dictionary of fit parameters.

sigima.tools.signal.fitting.sinusoidal_fit(x: ndarray, y: ndarray) tuple[ndarray, dict[str, float]][source]#

Compute sinusoidal fit.

Parameters:
  • x – x data array

  • y – y data array

Returns:

A tuple containing the fitted y values and a dictionary of fit parameters.

sigima.tools.signal.fitting.voigt_fit(x: ndarray, y: ndarray) tuple[ndarray, dict[str, float]][source]#

Compute Voigt fit.

Parameters:
  • x – x data array

  • y – y data array

Returns:

A tuple containing the fitted y values and a dictionary of fit parameters.

sigima.tools.signal.fitting.cdf_fit(x: ndarray, y: ndarray) tuple[ndarray, dict[str, float]][source]#

Compute Cumulative Distribution Function (CDF) fit.

Parameters:
  • x – x data array

  • y – y data array

Returns:

A tuple containing the fitted y values and a dictionary of fit parameters.

sigima.tools.signal.fitting.sigmoid_fit(x: ndarray, y: ndarray) tuple[ndarray, dict[str, float]][source]#

Compute Sigmoid (Logistic) fit.

Parameters:
  • x – x data array

  • y – y data array

Returns:

A tuple containing the fitted y values and a dictionary of fit parameters.

sigima.tools.signal.fitting.evaluate_fit(x: ndarray, **fit_params) ndarray[source]#

Evaluate fit function with given parameters at x values.

Parameters:
  • x – X values to evaluate at

  • **fit_params – Fit parameters (any of the *Params dataclasses)

Returns:

Y values computed from the fit function

Fourier Analysis Algorithms#

sigima.tools.signal.fourier.zero_padding(x: ndarray, y: ndarray, n_prepend: int = 0, n_append: int = 0) tuple[ndarray, ndarray][source]#

Prepend and append zeros.

This function pads the input signal with zeros at the beginning and end.

Parameters:
  • x – X data.

  • y – Y data.

  • n_prepend – Number of zeros to prepend.

  • n_append – Number of zeros to append.

Returns:

Padded x and y.

Return type:

Tuple (xnew, ynew)

sigima.tools.signal.fourier.fft1d(x: ndarray, y: ndarray, shift: bool = True) tuple[ndarray, ndarray][source]#

Compute the Fast Fourier Transform (FFT) of a 1D real signal.

Parameters:
  • x – Time domain axis (evenly spaced).

  • y – Signal values.

  • shift – If True, shift zero frequency and its corresponding FFT component to the

  • center.

Returns:

Frequency axis and corresponding FFT values.

Return type:

Tuple (f, sp)

sigima.tools.signal.fourier.ifft1d(f: ndarray, sp: ndarray, initial: float = 0.0) tuple[ndarray, ndarray][source]#

Compute the inverse Fast Fourier Transform (FFT) of a 1D complex spectrum.

Parameters:
  • f – Frequency axis (evenly spaced).

  • sp – FFT values.

  • initial – Starting value for the time axis.

Returns:

Time axis and real signal.

Return type:

Tuple (x, y)

Raises:

ValueError – If frequency array is not evenly spaced or has fewer than 2 points.

sigima.tools.signal.fourier.magnitude_spectrum(x: ndarray, y: ndarray, decibel: bool = False) tuple[ndarray, ndarray][source]#

Compute magnitude spectrum.

Parameters:
  • x – X data.

  • y – Y data.

  • decibel – Compute the magnitude spectrum root-power level in decibel (dB).

Returns:

Frequency values and magnitude spectrum.

Return type:

Tuple (f, mag_spectrum)

sigima.tools.signal.fourier.phase_spectrum(x: ndarray, y: ndarray) tuple[ndarray, ndarray][source]#

Compute phase spectrum.

Parameters:
  • x – X data.

  • y – Y data.

Returns:

Frequency values and phase spectrum in degrees.

Return type:

Tuple (f, phase)

sigima.tools.signal.fourier.psd(x: ndarray, y: ndarray, decibel: bool = False) tuple[ndarray, ndarray][source]#

Estimate the Power Spectral Density (PSD) using Welch’s method.

Parameters:
  • x – X data.

  • y – Y data.

  • decibel – Compute the power spectral density power level in decibel (dB).

Returns:

Frequency values and PSD.

Return type:

Tuple (f, welch_psd)

sigima.tools.signal.fourier.convolve(x: ndarray, y: ndarray, h: ndarray, boundary: Literal['reflect', 'symmetric', 'edge', 'wrap'] = 'reflect', normalize_kernel_flag: bool = True, method: Literal['auto', 'direct', 'fft'] = 'auto', correct_group_delay: bool = True) ndarray[source]#

Convolve a 1D signal with a kernel, avoiding border artifacts and x-shift.

The input signal is padded before convolution, then a ‘valid’ extraction is used to return exactly len(y) samples. Non-zero padding (e.g. “reflect”) prevents the typical edge attenuation caused by implicit zero-padding. If the kernel is asymmetric, an optional group-delay correction recenters the output on the same x-grid (no shift), using sub-sample interpolation.

Parameters:
  • x – 1D monotonically increasing and uniformly spaced axis (same length as y).

  • y – 1D input signal.

  • h – 1D convolution kernel (impulse response).

  • boundary – Padding mode passed to np.pad (“reflect” recommended).

  • normalize_kernel_flag – If True, normalize kernel so that h.sum() == 1 to preserve DC level.

  • method – Convolution method for scipy.signal.convolve.

  • correct_group_delay – If True, compensate the kernel center-of-mass shift (group delay) to avoid any x-shift in the output.

Returns:

Convolved signal with the same length as y, aligned on x.

Raises:

ValueError – If inputs are not 1D, empty, or shapes are inconsistent.

Notes

Precondition: x is strictly increasing with constant spacing. This is required for standard discrete convolution to represent a physical LTI filtering on the given grid.

sigima.tools.signal.fourier.deconvolve(x: ndarray, y: ndarray, h: ndarray, *, boundary: Literal['reflect', 'symmetric', 'edge', 'wrap'] = 'reflect', normalize_kernel_flag: bool = True, method: Literal['wiener', 'fft'] = 'wiener', reg: float = 0.05, gain_max: float | None = 10.0, dc_lock: bool = True, auto_scale: bool = True) ndarray[source]#

Deconvolve a 1D signal with frequency-dependent regularization and DC lock.

Strategy:
  1. Pad y with the same geometry as the convolve step (x-uniform grid).

  2. Build OTF H(f) from the centered PSF h.

  3. Compute inverse filter:
    • wiener (recommended): H*(f) / (|H|^2 + reg * |D|^2), with |D|^2 = (2 sin(ω/2))^2 (1st-derivative prior).

    • fft: bare inverse 1/H(f) (unstable; only for noise-free data).

    • Optionally clamp |G(f)| gain_max and lock DC gain.

  4. IFFT, then extract the central unpadded segment (len == len(y)).

  5. Optionally auto-scale the result to correct amplitude bias from regularization.

Parameters:
  • x – Strictly increasing, uniformly spaced axis (same length as y).

  • y – Observed signal (result of y_true h, plus noise).

  • h – Centered convolution kernel (PSF).

  • boundary – Padding mode (should match your convolution).

  • normalize_kernel_flag – If True, normalize h to preserve DC.

  • method"wiener" (regularized inverse) or "fft" (bare inverse).

  • reg – Regularization strength for the derivative prior.

  • gain_max – Optional clamp on |G(f)| to avoid wild amplification.

  • dc_lock – If True, enforce exact DC gain (preserve mean/plateau).

  • auto_scale – If True, auto-correct amplitude scaling after deconvolution.

Returns:

Deconvolved signal with the same length as y, x-aligned.

sigima.tools.signal.fourier.brickwall_filter(x: ndarray, y: ndarray, mode: Literal['lowpass', 'highpass', 'bandpass', 'bandstop'], cut0: float, cut1: float | None = None) tuple[ndarray, ndarray][source]#

Apply an ideal frequency filter (“brick wall” filter) to a signal.

Parameters:
  • x – Time domain axis (evenly spaced).

  • y – Signal values (same length as x).

  • mode – Type of filter to apply.

  • cut0 – First cutoff frequency.

  • cut1 – Second cutoff frequency, required for band-pass and band-stop filters.

Returns:

Tuple (x, y_filtered), where y_filtered is the filtered signal.

Raises:
  • ValueError – If mode is unknown.

  • ValueError – If cut0 is not positive.

  • ValueError – If cut1 is missing for band-pass and band-stop filters.

  • ValueError – If cut0 > cut1 for band-pass and band-stop filters.

Interpolation Algorithms#

sigima.tools.signal.interpolation.interpolate(x: ndarray, y: ndarray, xnew: ndarray, method: Interpolation1DMethod, fill_value: float | None = None) ndarray[source]#

Interpolate data.

Parameters:
  • x – X data

  • y – Y data

  • xnew – New X data

  • method – Interpolation method

  • fill_value – Fill value. Defaults to None. This value is used to fill in for requested points outside of the X data range. It is only used if the method argument is ‘linear’, ‘cubic’ or ‘pchip’.

Returns:

Interpolated Y data

Peak Detection Algorithms#

sigima.tools.signal.peakdetection.peak_indices(y, thres: float = 0.3, min_dist: int = 1, thres_abs: bool = False) ndarray[source]#

Peak detection routine.

Finds the numeric index of the peaks in y by taking its first order difference. By using thres and min_dist parameters, it is possible to reduce the number of detected peaks. y must be signed.

Parameters:
  • y (ndarray (signed)) – 1D amplitude data to search for peaks.

  • thres (float between [0., 1.]) – Normalized threshold. Only the peaks with amplitude higher than the threshold will be detected.

  • min_dist (int) – Minimum distance between each detected peak. The peak with the highest amplitude is preferred to satisfy this constraint.

  • thres_abs (boolean) – If True, the thres value will be interpreted as an absolute value, instead of a normalized threshold.

Returns:

Array containing the numeric indices of the peaks that were detected

Return type:

ndarray

sigima.tools.signal.peakdetection.xpeak(x: ndarray, y: ndarray) float[source]#

Return default peak X-position (assuming a single peak).

Parameters:
  • x – X data

  • y – Y data

Returns:

Peak X-position

Pulse Analysis Algorithms#

class sigima.tools.signal.pulse.PulseFitModel[source]#

Base class for 1D pulse fit models

abstractmethod classmethod func(x, amp, sigma, x0, y0)[source]#

Return fitting function

classmethod get_amp_from_amplitude(amplitude, sigma)[source]#

Return amp from function amplitude and sigma

classmethod amplitude(amp, sigma)[source]#

Return function amplitude

abstractmethod classmethod fwhm(amp, sigma)[source]#

Return function FWHM

classmethod half_max_segment(amp, sigma, x0, y0)[source]#

Return segment coordinates for y=half-maximum intersection

class sigima.tools.signal.pulse.GaussianModel[source]#

1-dimensional Gaussian fit model

classmethod func(x, amp, sigma, x0, y0)[source]#

Return fitting function

classmethod get_amp_from_amplitude(amplitude, sigma)[source]#

Return amp from function amplitude and sigma

classmethod amplitude(amp, sigma)[source]#

Return function amplitude

classmethod fwhm(amp, sigma)[source]#

Return function FWHM

class sigima.tools.signal.pulse.LorentzianModel[source]#

1-dimensional Lorentzian fit model

classmethod func(x, amp, sigma, x0, y0)[source]#

Return fitting function

classmethod get_amp_from_amplitude(amplitude, sigma)[source]#

Return amp from function amplitude and sigma

classmethod amplitude(amp, sigma)[source]#

Return function amplitude

classmethod fwhm(amp, sigma)[source]#

Return function FWHM

class sigima.tools.signal.pulse.VoigtModel[source]#

1-dimensional Voigt fit model

classmethod func(x, amp, sigma, x0, y0)[source]#

Return fitting function

classmethod fwhm(amp, sigma)[source]#

Return function FWHM

exception sigima.tools.signal.pulse.PulseAnalysisError[source]#

Base exception for pulse analysis errors.

exception sigima.tools.signal.pulse.InvalidSignalError[source]#

Raised when signal data is invalid or insufficient.

exception sigima.tools.signal.pulse.PolarityDetectionError[source]#

Raised when polarity cannot be determined.

sigima.tools.signal.pulse.heuristically_recognize_shape(x: ndarray, y: ndarray, start_range: tuple[float, float] | None = None, end_range: tuple[float, float] | None = None, step_threshold_ratio: float = 0.5) SignalShape[source]#

Heuristically determine the shape of the signal: ‘step’ or ‘square’.

Parameters:
  • x – 1D array of x values (e.g., time or position).

  • y – 1D array of y values corresponding to x.

  • start_range – Range for the start baseline.

  • end_range – Range for the end baseline.

  • step_threshold_ratio – Threshold ratio to distinguish step from square pulse. If step amplitude > threshold_ratio * total_amplitude, classify as step.

Returns:

Signal shape, either SignalShape.STEP or SignalShape.SQUARE.

Raises:

InvalidSignalError – If signal data is invalid.

sigima.tools.signal.pulse.detect_polarity(x: ndarray, y: ndarray, start_range: tuple[float, float] | None = None, end_range: tuple[float, float] | None = None, plateau_range: tuple[float, float] | None = None, signal_shape: SignalShape | None = None, fraction: float = 0.05) int[source]#

Get step curve polarity.

Parameters:
  • x – Array of x-values (abscisse).

  • y – Array of y-values (ordinate).

  • start_range – Range for the start baseline.

  • end_range – Range for the end baseline.

  • plateau_range – Range for the plateau.

  • signal_shape – Shape of the signal.

  • fraction – Fraction of the x-range to use for baseline and plateau calculations.

Returns:

Polarity of the step (1 for positive, -1 for negative).

Raises:
sigima.tools.signal.pulse.get_start_range(x: ndarray, fraction: float = 0.05) tuple[float, float][source]#

Get start range based on fraction of x-range.

Parameters:
  • x – 1D array of x values.

  • fraction – Fraction of the x-range to use for the start range.

Returns:

Tuple representing the start range (min, max).

sigima.tools.signal.pulse.get_end_range(x: ndarray, fraction: float = 0.05) tuple[float, float][source]#

Get end range based on fraction of x-range.

Parameters:
  • x – 1D array of x values.

  • fraction – Fraction of the x-range to use for the end range.

Returns:

Tuple representing the end range (min, max).

sigima.tools.signal.pulse.get_plateau_range(x: ndarray, y: ndarray, polarity: int, fraction: float = 0.05, start_range: tuple[float, float] | None = None, end_range: tuple[float, float] | None = None) tuple[float, float][source]#

Get plateau range around the max y-value based on fraction of x-range.

The plateau is identified as the longest continuous region with values >= 90% of the maximum, constrained to be after the start baseline and before the end baseline. This ensures the plateau is detected in the correct temporal region of the signal, avoiding isolated spikes.

Parameters:
  • x – 1D array of x values.

  • y – 1D array of y values.

  • polarity – Polarity of the signal (1 for positive, -1 for negative).

  • fraction – Fraction of the x-range to use for the plateau range.

  • start_range – Start baseline range (optional, for constraining search).

  • end_range – End baseline range (optional, for constraining search).

Returns:

Tuple representing the plateau range (min, max).

sigima.tools.signal.pulse.get_range_mean_y(x: ndarray, y: ndarray, value_range: tuple[float, float]) float[source]#

Get mean y-value in a given x-range.

Parameters:
  • x – 1D array of x values.

  • y – 1D array of y values.

  • value_range – Tuple representing the x-range (min, max).

Returns:

Mean y-value in the specified x-range, or NaN if no points in range.

sigima.tools.signal.pulse.get_amplitude(x: ndarray, y: ndarray, start_range: tuple[float, float] | None = None, end_range: tuple[float, float] | None = None, plateau_range: tuple[float, float] | None = None, signal_shape: SignalShape | str | None = None, fraction: float = 0.05) float[source]#

Get curve amplitude.

This function uses plateau-mean detection which is robust to noise but introduces a systematic error (~2-3%) for smooth pulse shapes (Gaussian, Lorentzian, etc.). This is an acceptable trade-off for robustness across all signal types.

Parameters:
  • x – 1D array of x values.

  • y – 1D array of y values.

  • start_range – Range for the start baseline.

  • end_range – Range for the end baseline.

  • plateau_range – Range for the plateau.

  • signal_shape – Shape of the signal.

  • fraction – Fraction of the x-range to use for baseline and plateau calculations if start, end, or plateau are None.

Returns:

Amplitude of the step.

Warning

For noise-free smooth peaks (Gaussian, Lorentzian), this method introduces a systematic offset of approximately +2-3% due to plateau-mean detection. For accurate results with known signal shapes, use fitting methods instead (e.g., fwhm with method=’gauss’ for Gaussian signals).

sigima.tools.signal.pulse.find_crossing_at_ratio(x: ndarray, y: ndarray, ratio: float = 0.1, start_range: tuple[float, float] | None = None, end_range: tuple[float, float] | None = None, signal_shape: SignalShape | str | None = None, fraction: float = 0.05, warn_multiple_crossings: bool = False) float | None[source]#

Find the x-value at which the signal crosses a specified fractional amplitude.

Calculates the x-value at which a normalized step signal crosses a specified fractional amplitude.

This function normalizes the input signal y relative to the baseline level defined by start and the amplitude between start and end. It accounts for the polarity of the step (rising or falling) and then finds the x-position where the normalized signal crosses the specified ratio fraction of the step height.

Parameters:
  • x – 1D array of x values (e.g., time).

  • y – 1D array of y values corresponding to x.

  • ratio – The fractional amplitude (between 0 and 1) at which to find the crossing time. For example, 0.5 corresponds to the half-maximum crossing.

  • start_range – Tuple defining the start baseline region (initial plateau).

  • end_range – Tuple defining the end baseline region (final plateau).

  • signal_shape – Shape of the signal. If None, it will be heuristically determined.

  • fraction – Fraction of the x-range to use for baseline calculations if start_range or end_range are None.

  • warn_multiple_crossings – If True, a warning is issued when multiple crossings are found.

Returns:

The x-value where the normalized signal crosses the specified fractional amplitude.

Raises:
sigima.tools.signal.pulse.get_rise_time_estimated(x: ndarray, y: ndarray, start_range: tuple[float, float] | None = None, end_range: tuple[float, float] | None = None, start_ratio: float = 0.1, stop_ratio: float = 0.9) float | None[source]#

Calculates rise time using heuristic foot detection and 50% crossing estimation.

This method uses a more robust approach: 1. Find the true start of the systematic rise (foot end time) 2. Find the 50% amplitude crossing 3. Estimate the full rise duration from these two points 4. Calculate the requested ratio-based rise time from the estimated parameters

Parameters:
  • x – 1D array of x values (e.g., time).

  • y – 1D array of y values corresponding to x.

  • start_range – Tuple defining the start plateau region (before the rise).

  • end_range – Tuple defining the end plateau region (after the rise).

  • start_ratio – Fraction of the step height at which the rise starts.

  • stop_ratio – Fraction of the step height at which the rise ends.

Returns:

The estimated rise time between the specified ratios.

sigima.tools.signal.pulse.get_rise_time(x: ndarray, y: ndarray, start_ratio: float = 0.1, stop_ratio: float = 0.9, start_range: tuple[float, float] | None = None, end_range: tuple[float, float] | None = None) float | None[source]#

Calculates the rise time of a step-like signal between two defined plateaus.

The rise time is defined as the time it takes for the signal to increase from start_ratio to stop_ratio of the total amplitude change.

For rise time calculations (stop_ratio > start_ratio), this function automatically uses an improved estimation method that combines heuristic foot detection with 50% crossing analysis for better accuracy in noisy signals.

For fall time calculations (stop_ratio < start_ratio), it uses the traditional ratio-based method.

Parameters:
  • x – 1D array of x values (e.g., time).

  • y – 1D array of y values corresponding to x.

  • start_ratio – Fraction of the step height at which the rise starts. Default is 0.1 (i.e., 10% of the step height).

  • stop_ratio – Fraction of the step height at which the rise ends. Default is 0.9 (i.e., 90% of the step height).

  • start_range – Tuple defining the start plateau region (before the rise).

  • end_range – Tuple defining the end plateau region (after the rise).

Returns:

The rise time (difference between the stop and start ratio crossings).

Raises:

ValueError – If ratios are not between 0 and 1.

sigima.tools.signal.pulse.get_fall_time(x: ndarray, y: ndarray, start_ratio: float = 0.9, stop_ratio: float = 0.1, plateau_range: tuple[float, float] | None = None, end_range: tuple[float, float] | None = None, fraction: float = 0.05) float | None[source]#

Calculates the fall time of a step-like signal between two defined plateaus.

The fall time is defined as the time it takes for the signal to decrease from start_ratio to stop_ratio of the total amplitude change.

This function internally reverses the signal and applies the rise time calculation to determine the fall time.

Parameters:
  • x – 1D array of x values (e.g., time).

  • y – 1D array of y values corresponding to x.

  • start_ratio – Fraction of the step height at which the fall starts. Default is 0.9 (i.e., 90% of the step height).

  • stop_ratio – Fraction of the step height at which the fall ends. Default is 0.1 (i.e., 10% of the step height).

  • plateau_range – Tuple defining the plateau region (top of the step). If None, uses the peak y-value.

  • end_range – Tuple defining the end plateau region (after the fall).

  • fraction – Fraction of the x-range to use for baseline calculations if plateau_range is None.

Returns:

The fall time (difference between the stop and start ratio crossings).

Raises:

ValueError – If start_ratio is not greater than stop_ratio or if ratios are not between 0 and 1.

sigima.tools.signal.pulse.heuristically_find_rise_start_time(x: ndarray, y: ndarray, start_range: tuple[float, float]) float | None[source]#

Finds the point where a step signal begins its systematic rise from baseline.

This function uses multiple strategies to detect the true start of a step transition: 1. Trend analysis to identify sustained directional change 2. Moving window statistics to detect consistent deviations 3. Gradient analysis for backup detection

Parameters:
  • x – 1D array of x values (e.g., time).

  • y – 1D array of y values corresponding to x.

  • start_range – Tuple defining the lower plateau region (start of the step).

Returns:

The x-value of the first systematic rise, or None if no such value is found.

Raises:

InvalidSignalError – If insufficient data is provided.

sigima.tools.signal.pulse.get_rise_start_time(x: ndarray, y: ndarray, start_range: tuple[float, float], end_range: tuple[float, float], threshold: float | None = None) float[source]#

Find the rise start time of a step signal using multiple strategies.

This function tries multiple approaches to find the rise start time: 1. Uses threshold crossing if threshold is provided 2. Uses heuristic detection as fallback 3. Validates results to ensure they make physical sense

Parameters:
  • x – 1D array of x values (e.g., time or position).

  • y – 1D array of y values (same size as x).

  • start_range – A range (min, max) representing the initial flat region (“foot”).

  • end_range – A range (min, max) representing the final high region after the rise.

  • threshold – If provided, use this fractional amplitude (0-1) to determine the end of the foot. If None, use heuristic detection.

Returns:

The rise start time (foot end time).

Raises:

InvalidSignalError – If rise start time cannot be determined.

sigima.tools.signal.pulse.full_width_at_y(x: ndarray, y: ndarray, level: float) tuple[float, float, float, float][source]#

Compute the full width at a given y level of a square shaped signal using zero-crossing method.

Parameters:
  • x – 1D array of x values.

  • y – 1D array of y values.

  • level – The Y level at which to compute the width

Returns:

Full width segment coordinates (x1, level, x2, level)

sigima.tools.signal.pulse.full_width_at_ratio(x: ndarray, y: ndarray, ratio: float, start_range: tuple[float, float] | None = None, end_range: tuple[float, float] | None = None, fraction: float = 0.05) tuple[float, float, float, float][source]#

Calculate the full width at a specified ratio of the amplitude for a pulse signal.

This function determines the two crossing points (x1, x2) where the normalized signal crosses a given ratio of its amplitude, and returns these points along with the corresponding y-level.

Parameters:
  • x – 1D array of x-values.

  • y – 1D array of y-values.

  • ratio – Ratio (between 0 and 1) of the amplitude at which to measure the width.

  • start_range – Range of x-values to estimate the start baseline.

  • end_range – Range of x-values to estimate the end baseline.

  • fraction – Fraction of the x-range to use for baseline calculations if start_range or end_range are None.

Returns:

Full width segment coordinates (x1, level, x2, level), where x1 and x2 are the

crossing points at the specified ratio, and level is the corresponding y-value.

Raises:
  • ValueError – If the amplitude of the signal is zero.

  • RuntimeWarning – If the polarity cannot be determined, returns NaN for crossing times.

Notes

  • The function normalizes the signal based on the detected amplitude and polarity.

  • The crossing times are computed using features.find_first_x_at_y_value function.

sigima.tools.signal.pulse.fwhm(x: ndarray, y: ndarray, method: Literal['zero-crossing', 'gauss', 'lorentz', 'voigt'] = 'zero-crossing', xmin: float | None = None, xmax: float | None = None) tuple[float, float, float, float][source]#

Compute Full Width at Half Maximum (FWHM) of the input data.

Two types of methods are supported:

  • “zero-crossing”: Fast interpolation-based method that works directly with signal values (no normalization). Shape-independent and robust.

  • “gauss”, “lorentz”, “voigt”: Curve fitting methods for specific signal shapes. Very accurate when the signal matches the model.

Parameters:
  • x – 1D array of x-values.

  • y – 1D array of y-values.

  • method – Calculation method.

  • xmin – Lower X bound for the fitting. Defaults to None (no lower bound, i.e. the fitting starts from the first point).

  • xmax – Upper X bound for the fitting. Defaults to None (no upper bound, i.e. the fitting ends at the last point)

Returns:

FWHM segment coordinates (x1, y1, x2, y2)

Warning

The zero-crossing method uses amplitude normalization via get_amplitude(), which introduces a small systematic offset (~2-3%) for smooth peaks (Gaussian, Lorentzian, etc.) but is robust to noise. For accurate results with known signal shapes, use fitting methods (e.g., method=’gauss’).

sigima.tools.signal.pulse.fw1e2(x: ndarray, y: ndarray) tuple[float, float, float, float][source]#

Compute Full Width at 1/e² of the input data (using a Gaussian model fitting).

Parameters:
  • x – 1D array of x-values.

  • y – 1D array of y-values.

Returns:

FW at 1/e² segment coordinates

class sigima.tools.signal.pulse.PulseFeatures(signal_shape: SignalShape = 'step', polarity: int = 1, amplitude: float = 0.0, offset: float = 0.0, foot_duration: float = 0.0, xstartmin: float = 0.0, xstartmax: float = 0.0, xendmin: float = 0.0, xendmax: float = 0.0, xplateaumin: float | None = None, xplateaumax: float | None = None, rise_time: float | None = None, fall_time: float | None = None, fwhm: float | None = None, x0: float | None = None, x50: float | None = None, x100: float | None = None)[source]#

Extracted features from a pulse signal.

signal_shape#

The shape of the signal (step or square).

Type:

sigima.enums.SignalShape

polarity#

The polarity of the signal (1 for positive, -1 for negative).

Type:

int

amplitude#

The amplitude of the signal.

Type:

float

offset#

The baseline offset of the signal.

Type:

float

foot_duration#

The duration of the foot (flat region before rise) of the signal.

Type:

float

xstartmin#

The minimum x-value of the start baseline region.

Type:

float

xstartmax#

The maximum x-value of the start baseline region.

Type:

float

xendmin#

The minimum x-value of the end baseline region.

Type:

float

xendmax#

The maximum x-value of the end baseline region.

Type:

float

xplateaumin#

The minimum x-value of the plateau region (if applicable).

Type:

float | None

xplateaumax#

The maximum x-value of the plateau region (if applicable).

Type:

float | None

rise_time#

The rise time of the signal (time from start_ratio to stop_ratio).

Type:

float | None

fall_time#

The fall time of the signal (time from stop_ratio to start_ratio).

Type:

float | None

fwhm#

The full width at half maximum of the signal.

Type:

float | None

x50#

The time at which the signal reaches 50% of its amplitude.

Type:

float | None

x100#

The time at which the signal reaches its maximum amplitude.

Type:

float | None

sigima.tools.signal.pulse.extract_pulse_features(x: ndarray, y: ndarray, start_range: tuple[float, float], end_range: tuple[float, float], start_ratio: float = 0.1, stop_ratio: float = 0.9, signal_shape: SignalShape | None = None, fraction: float = 0.05, denoise: bool = True) PulseFeatures[source]#

Extract various pulse features from the input signal.

Parameters:
  • x – 1D array of x values (e.g., time).

  • y – 1D array of y values (signal).

  • start_range – Interval for the first plateau (baseline).

  • end_range – Interval for the second plateau (peak).

  • signal_shape – Signal type (None for auto-detection).

  • start_ratio – Fraction for rise start.

  • stop_ratio – Fraction for rise end.

  • fraction – Fraction of the x-range to use for baseline calculations if start_range or end_range are None.

  • denoise – If True, apply a denoising filter to the signal before analysis.

Returns:

Pulse features.

Raises:

ValueError – If input parameters are invalid.

Scaling Algorithms#

sigima.tools.signal.scaling.normalize(yin: ndarray, parameter: NormalizationMethod = 'maximum') ndarray[source]#

Normalize input array to a given parameter.

Parameters:
  • yin – Input array

  • parameter – Normalization parameter. Defaults to MAXIMUM

Returns:

Normalized array

Stability Analysis Algorithms#

sigima.tools.signal.stability.allan_variance(x: ndarray, y: ndarray, tau_values: ndarray) ndarray[source]#

Calculate the Allan variance for given time and measurement values at specified tau values.

Parameters:
  • x – Time array

  • y – Measured values array

  • tau_values – Allan deviation time values

Returns:

Allan variance values

sigima.tools.signal.stability.allan_deviation(x: ndarray, y: ndarray, tau_values: ndarray) ndarray[source]#

Calculate the Allan deviation for given time and measurement values at specified tau values.

Parameters:
  • x – Time array

  • y – Measured values array

  • tau_values – Allan deviation time values

Returns:

Allan deviation values

sigima.tools.signal.stability.overlapping_allan_variance(x: ndarray, y: ndarray, tau_values: ndarray) ndarray[source]#

Calculate the Overlapping Allan variance for given time and measurement values.

Parameters:
  • x – Time array

  • y – Measured values array

  • tau_values – Allan deviation time values

Returns:

Overlapping Allan variance values

sigima.tools.signal.stability.modified_allan_variance(x: ndarray, y: ndarray, tau_values: ndarray) ndarray[source]#

Calculate the Modified Allan variance for given time and measurement values.

Parameters:
  • x – Time array

  • y – Measured values array

  • tau_values – Modified Allan deviation time values

Returns:

Modified Allan variance values

sigima.tools.signal.stability.hadamard_variance(x: ndarray, y: ndarray, tau_values: ndarray) ndarray[source]#

Calculate the Hadamard variance for given time and measurement values.

Parameters:
  • x – Time array

  • y – Measured values array

  • tau_values – Hadamard deviation time values

Returns:

Hadamard variance values

sigima.tools.signal.stability.total_variance(x: ndarray, y: ndarray, tau_values: ndarray) ndarray[source]#

Calculate the Total variance for given time and measurement values.

Parameters:
  • x – Time array

  • y – Measured values array

  • tau_values – Total variance time values

Returns:

Total variance values

sigima.tools.signal.stability.time_deviation(x: ndarray, y: ndarray, tau_values: ndarray) ndarray[source]#

Calculate the Time Deviation (TDEV) for given time and measurement values.

Parameters:
  • x – Time array

  • y – Measured values array

  • tau_values – Time deviation time values

Returns:

Time deviation values

Windowing Algorithms#

sigima.tools.signal.windowing.apply_window(y: ndarray, method: WindowingMethod = 'hamming', alpha: float = 0.5, beta: float = 14.0, sigma: float = 7.0) ndarray[source]#

Apply windowing to the input data.

Parameters:
  • x – X data.

  • y – Y data.

  • method – Windowing function. Defaults to “HAMMING”.

  • alpha – Tukey window parameter. Defaults to 0.5.

  • beta – Kaiser window parameter. Defaults to 14.0.

  • sigma – Gaussian window parameter. Defaults to 7.0.

Returns:

Windowed Y data.

Raises:

ValueError – If the method is not recognized.

Image Processing Tools#

Image Processing Tools (sigima.tools.image)#

This package contains image processing tools, which are organized into subpackages according to their purpose:

  • sigima.tools.image.detection: Object detection algorithms (blob detection, peak detection, contour fitting)

  • sigima.tools.image.exposure: Exposure and level adjustment functions, including flat-field correction

  • sigima.tools.image.extraction: Data extraction and analysis functions (radial profiles, feature extraction)

  • sigima.tools.image.fourier: 2D Fourier transform operations and spectral analysis

  • sigima.tools.image.geometry: Geometric analysis and transformations

  • sigima.tools.image.preprocessing: Data preprocessing and transformation utilities (scaling, normalization, binning, padding)

All functions are re-exported at the subpackage level for backward compatibility. Existing imports like from sigima.tools.image import fft2d will continue to work.

sigima.tools.image.binning(data: ndarray, sx: int, sy: int, operation: BinningOperation | str, dtype=None) ndarray[source]#

Perform image pixel binning

Parameters:
  • data – Input data

  • sx – Binning size along x (number of pixels to bin together)

  • sy – Binning size along y (number of pixels to bin together)

  • operation – Binning operation

  • dtype – Output data type (default: None, i.e. same as input)

Returns:

Binned data

sigima.tools.image.convolve(data: ndarray, kernel: ndarray, normalize_kernel_flag: bool = True) ndarray[source]#

Perform 2D convolution with a kernel using scipy.signal.convolve.

This function adds optional kernel normalization to the standard scipy convolution.

Parameters:
  • data – Input image (2D array).

  • kernel – Convolution kernel.

  • normalize_kernel_flag – If True, normalize kernel so that kernel.sum() == 1 to preserve image brightness.

Returns:

Convolved image (same shape as input).

Raises:

ValueError – If kernel is empty or null.

sigima.tools.image.deconvolve(data: ndarray, kernel: ndarray, reg: float = 0.0, boundary: str = 'edge', normalize_kernel_flag: bool = True) ndarray[source]#

Perform 2D FFT deconvolution with correct ‘same’ geometry (no shift).

The kernel (PSF) must be centered (impulse at center for identity kernel). Odd kernel sizes are recommended.

Parameters:
  • data – Input image (2D array).

  • kernel – Point Spread Function (PSF), centered.

  • reg – Regularization parameter (if >0, Wiener/Tikhonov inverse: H* / (|H|^2 + reg)).

  • boundary – Padding mode (‘edge’ for constant plateau, ‘reflect’ for symmetric mirror).

  • normalize_kernel_flag – If True, normalize kernel so that kernel.sum() == 1 to preserve image brightness.

Returns:

Deconvolved image (same shape as input).

Raises:

ValueError – If kernel is empty or null.

sigima.tools.image.distance_matrix(coords: list) ndarray[source]#

Return distance matrix from coords

Parameters:

coords – List of coordinates

Returns:

Distance matrix

sigima.tools.image.fft2d(z: ndarray, shift: bool = True) ndarray[source]#

Compute FFT of complex array z

Parameters:
  • z – Input data

  • shift – Shift zero frequency to center (default: True)

Returns:

FFT of input data

sigima.tools.image.find_blobs_dog(data: ndarray, min_sigma: float = 1, max_sigma: float = 30, overlap: float = 0.5, threshold_rel: float = 0.2, exclude_border: bool = True) ndarray[source]#

Finds blobs in the given grayscale image using the Difference of Gaussians (DoG) method.

Parameters:
  • data – The grayscale input image.

  • min_sigma – The minimum blob radius in pixels.

  • max_sigma – The maximum blob radius in pixels.

  • overlap – The minimum overlap between two blobs in pixels. For instance, if two blobs are detected with radii of 10 and 12 respectively, and the overlap is set to 0.5, then the area of the smaller blob will be ignored and only the area of the larger blob will be returned.

  • threshold_rel – The absolute lower bound for scale space maxima. Local maxima smaller than threshold_rel are ignored. Reduce this to detect blobs with less intensities.

  • exclude_border – If True, exclude blobs from detection if they are too close to the border of the image. Border size is min_sigma.

Returns:

Coordinates of blobs

sigima.tools.image.find_blobs_doh(data: ndarray, min_sigma: float = 1, max_sigma: float = 30, overlap: float = 0.5, log_scale: bool = False, threshold_rel: float = 0.2) ndarray[source]#

Finds blobs in the given grayscale image using the Determinant of Hessian (DoH) method.

Parameters:
  • data – The grayscale input image.

  • min_sigma – The minimum blob radius in pixels.

  • max_sigma – The maximum blob radius in pixels.

  • overlap – The minimum overlap between two blobs in pixels. For instance, if two blobs are detected with radii of 10 and 12 respectively, and the overlap is set to 0.5, then the area of the smaller blob will be ignored and only the area of the larger blob will be returned.

  • log_scale – If True, the radius of each blob is returned as sqrt(sigma) for each detected blob.

  • threshold_rel – The absolute lower bound for scale space maxima. Local maxima smaller than threshold_rel are ignored. Reduce this to detect blobs with less intensities.

Returns:

Coordinates of blobs

sigima.tools.image.find_blobs_log(data: ndarray, min_sigma: float = 1, max_sigma: float = 30, overlap: float = 0.5, log_scale: bool = False, threshold_rel: float = 0.2, exclude_border: bool = True) ndarray[source]#

Finds blobs in the given grayscale image using the Laplacian of Gaussian (LoG) method.

Parameters:
  • data – The grayscale input image.

  • min_sigma – The minimum blob radius in pixels.

  • max_sigma – The maximum blob radius in pixels.

  • overlap – The minimum overlap between two blobs in pixels. For instance, if two blobs are detected with radii of 10 and 12 respectively, and the overlap is set to 0.5, then the area of the smaller blob will be ignored and only the area of the larger blob will be returned.

  • log_scale – If True, the radius of each blob is returned as sqrt(sigma) for each detected blob.

  • threshold_rel – The absolute lower bound for scale space maxima. Local maxima smaller than threshold_rel are ignored. Reduce this to detect blobs with less intensities.

  • exclude_border – If True, exclude blobs from detection if they are too close to the border of the image. Border size is min_sigma.

Returns:

Coordinates of blobs

sigima.tools.image.find_blobs_opencv(data: ndarray, min_threshold: float | None = None, max_threshold: float | None = None, min_repeatability: int | None = None, min_dist_between_blobs: float | None = None, filter_by_color: bool | None = None, blob_color: int | None = None, filter_by_area: bool | None = None, min_area: float | None = None, max_area: float | None = None, filter_by_circularity: bool | None = None, min_circularity: float | None = None, max_circularity: float | None = None, filter_by_inertia: bool | None = None, min_inertia_ratio: float | None = None, max_inertia_ratio: float | None = None, filter_by_convexity: bool | None = None, min_convexity: float | None = None, max_convexity: float | None = None) ndarray[source]#

Finds blobs in the given grayscale image using OpenCV’s SimpleBlobDetector.

Parameters:
  • data – The grayscale input image.

  • min_threshold – The minimum blob intensity.

  • max_threshold – The maximum blob intensity.

  • min_repeatability – The minimum number of times a blob is detected before it is reported.

  • min_dist_between_blobs – The minimum distance between blobs.

  • filter_by_color – If True, blobs are filtered by color.

  • blob_color – The color of the blobs to filter by.

  • filter_by_area – If True, blobs are filtered by area.

  • min_area – The minimum blob area.

  • max_area – The maximum blob area.

  • filter_by_circularity – If True, blobs are filtered by circularity.

  • min_circularity – The minimum blob circularity.

  • max_circularity – The maximum blob circularity.

  • filter_by_inertia – If True, blobs are filtered by inertia.

  • min_inertia_ratio – The minimum blob inertia ratio.

  • max_inertia_ratio – The maximum blob inertia ratio.

  • filter_by_convexity – If True, blobs are filtered by convexity.

  • min_convexity – The minimum blob convexity.

  • max_convexity – The maximum blob convexity.

Returns:

Coordinates of blobs

sigima.tools.image.flatfield(rawdata: ndarray, flatdata: ndarray, threshold: float | None = None) ndarray[source]#

Compute flat-field correction

Parameters:
  • rawdata – Raw data

  • flatdata – Flat-field data

  • threshold – Threshold for flat-field correction (default: None)

Returns:

Flat-field corrected data

sigima.tools.image.gaussian_freq_filter(data: ndarray, f0: float = 0.1, sigma: float = 0.05) ndarray[source]#

Apply a 2D Gaussian bandpass filter in the frequency domain to an image.

This function performs a 2D Fast Fourier Transform (FFT) on the input image, applies a Gaussian filter centered at frequency f0 with standard deviation sigma (both expressed in cycles per pixel), and then transforms the result back to the spatial domain.

Parameters:
  • data – Input image data.

  • f0 – Center frequency of the Gaussian filter (cycles/pixel).

  • sigma – Standard deviation of the Gaussian filter (cycles/pixel).

Returns:

The filtered image.

sigima.tools.image.get_2d_peaks_coords(data: ndarray, size: int | None = None, level: float = 0.5) ndarray[source]#

Detect peaks in image data, return coordinates.

If neighborhoods size is None, default value is the highest value between 50 pixels and the 1/40th of the smallest image dimension.

Detection threshold level is relative to difference between data maximum and minimum values.

Parameters:
  • data – Input data

  • size – Neighborhood size (default: None)

  • level – Relative level (default: 0.5)

Returns:

Coordinates of peaks

sigima.tools.image.get_absolute_level(data: ndarray, level: float) float[source]#

Get absolute level from relative level

Parameters:
  • data – Input data

  • level – Relative level (0.0 to 1.0)

Returns:

Absolute level

Raises:

ValueError – If level is not a float between 0.0 and 1.0

sigima.tools.image.get_centroid_auto(data: ndarray, return_method: bool = False) tuple[float, float] | tuple[float, float, Literal['fourier', 'skimage']][source]#

Automatically select the most reliable centroid estimation method: - Prefer Fourier if it is more consistent with the projected median. - Fallback to scikit-image centroid if Fourier is less coherent.

Parameters:
  • data – 2D image array.

  • return_method – If True, also return the name of the selected method.

Returns:

Estimated centroid coordinates (float). Optionally, the selected method as string: “fourier” or “skimage”.

Return type:

(row, col)

sigima.tools.image.get_centroid_fourier(data: ndarray) tuple[float, float][source]#

Return image centroid using Fourier algorithm

Parameters:

data – Input data

Returns:

Centroid coordinates (row, col)

sigima.tools.image.get_contour_shapes(data: ndarray | MaskedArray, shape: ContourShape = 'ellipse', level: float = 0.5) ndarray[source]#

Find iso-valued contours in a 2D array, above relative level (.5 means FWHM).

Parameters:
  • data – Input data

  • shape – Shape to fit. Default is ELLIPSE

  • level – Relative level (default: 0.5)

Returns:

Coordinates of shapes fitted to contours

sigima.tools.image.get_enclosing_circle(data: ndarray, level: float = 0.5) tuple[int, int, float][source]#

Return (x, y, radius) for the circle contour enclosing image values above threshold relative level (.5 means FWHM)

Parameters:
  • data – Input data

  • level – Relative level (default: 0.5)

Returns:

A tuple (x, y, radius)

Raises:

ValueError – No contour was found

sigima.tools.image.get_hough_circle_peaks(data: ndarray, min_radius: float | None = None, max_radius: float | None = None, nb_radius: int | None = None, min_distance: int = 1) ndarray[source]#

Detect peaks in image from circle Hough transform, return circle coordinates.

Parameters:
  • data – Input data

  • min_radius – Minimum radius (default: None)

  • max_radius – Maximum radius (default: None)

  • nb_radius – Number of radii (default: None)

  • min_distance – Minimum distance between circles (default: 1)

Returns:

Coordinates of circles

sigima.tools.image.get_projected_profile_centroid(data: ndarray, smooth_ratio: float = 0.025, method: str = 'median') tuple[float, float][source]#

Estimate centroid from smoothed 1D projections.

Parameters:
  • data – 2D image array

  • smooth_ratio – Ratio of smoothing window size (default: 1/40)

  • method – ‘median’ (default) or ‘barycenter’

Returns:

(y, x) coordinates

sigima.tools.image.get_radial_profile(data: ndarray, center: tuple[int, int]) tuple[ndarray, ndarray][source]#

Return radial profile of image data

Parameters:
  • data – Input data (2D array)

  • center – Coordinates of the center of the profile (x, y)

Returns:

Radial profile (X, Y) where X is the distance from the center (1D array) and Y is the average value of pixels at this distance (1D array)

sigima.tools.image.ifft2d(z: ndarray, shift: bool = True) ndarray[source]#

Compute inverse FFT of complex array z

Parameters:
  • z – Input data

  • shift – Shift zero frequency to center (default: True)

Returns:

Inverse FFT of input data

sigima.tools.image.magnitude_spectrum(z: ndarray, log_scale: bool = False) ndarray[source]#

Compute magnitude spectrum of complex array z

Parameters:
  • z – Input data

  • log_scale – Use log scale (default: False)

Returns:

Magnitude spectrum of input data

sigima.tools.image.normalize(data: ndarray, parameter: NormalizationMethod = 'maximum') ndarray[source]#

Normalize input array to a given parameter.

Parameters:
  • data – Input data

  • parameter – Normalization parameter (default: MAXIMUM)

Returns:

Normalized array

sigima.tools.image.phase_spectrum(z: ndarray) ndarray[source]#

Compute phase spectrum of complex array z

Parameters:

z – Input data

Returns:

Phase spectrum of input data (in degrees)

sigima.tools.image.psd(z: ndarray, log_scale: bool = False) ndarray[source]#

Compute power spectral density of complex array z

Parameters:
  • z – Input data

  • log_scale – Use log scale (default: False)

Returns:

Power spectral density of input data

sigima.tools.image.remove_overlapping_disks(coords: ndarray) ndarray[source]#

Remove overlapping disks among coordinates

Parameters:

coords – The coordinates of the disks

Returns:

The coordinates of the disks with overlapping disks removed

sigima.tools.image.scale_data_to_min_max(data: ndarray, zmin: float | int, zmax: float | int) ndarray[source]#

Scale array data to fit [zmin, zmax] dynamic range

Parameters:
  • data – Input data

  • zmin – Minimum value of output data

  • zmax – Maximum value of output data

Returns:

Scaled data

sigima.tools.image.zero_padding(data: ndarray, rows: int = 0, cols: int = 0, position: Literal['bottom-right', 'around'] = 'bottom-right') ndarray[source]#

Zero-pad a 2D image by adding rows and/or columns.

Parameters:
  • data – 2D input image (grayscale)

  • rows – Number of rows to add in total (default: 0)

  • cols – Number of columns to add in total (default: 0)

  • position – Padding placement strategy: - “bottom-right”: all padding is added to the bottom and right - “around”: padding is split equally on top/bottom and left/right

Returns:

The padded 2D image as a NumPy array.

Raises:

ValueError – If the input is not a 2D array or if padding values are negative.

Data Type Conversion Tools#

sigima.tools.datatypes.datetime64_to_seconds(dt_values: ndarray) ndarray[source]#

Convert numpy datetime64 array to float seconds (Unix timestamps).

This function handles different datetime resolutions (ns, us, ms, s) correctly, providing compatibility with both older pandas versions (using nanoseconds) and pandas 3.0+ (using microseconds by default).

Parameters:

dt_values – NumPy array of datetime64 values (from pandas Series.values or DatetimeIndex.values)

Returns:

NumPy array of float64 Unix timestamps (seconds since 1970-01-01)

Example

>>> import pandas as pd
>>> dt_series = pd.to_datetime(['2025-01-01 10:00:00'])
>>> seconds = datetime64_to_seconds(dt_series.values)
>>> seconds[0] > 1.7e9  # Year 2025
True
sigima.tools.datatypes.clip_astype(data: ndarray, dtype: dtype) ndarray[source]#

Convert array to a new data type, after having clipped values to the new data type’s range if it is an integer type. If data type is not integer, this is equivalent to data.astype(dtype).

Parameters:
  • data – Array to convert

  • dtype – Data type to convert to

Returns:

Array converted to new data type

Coordinate Conversion Tools#

sigima.tools.coordinates.circle_to_diameter(xc: float, yc: float, r: float) tuple[float, float, float, float][source]#

Convert circle center and radius to X diameter coordinates

Parameters:
  • xc – Circle center X coordinate

  • yc – Circle center Y coordinate

  • r – Circle radius

Returns:

Circle X diameter coordinates

Return type:

tuple

sigima.tools.coordinates.array_circle_to_diameter(data: ndarray) ndarray[source]#

Convert circle center and radius to X diameter coordinates (array version)

Parameters:

data – Circle center and radius, in the form of a 2D array (N, 3)

Returns:

Circle X diameter coordinates, in the form of a 2D array (N, 4)

sigima.tools.coordinates.circle_to_center_radius(x0: float, y0: float, x1: float, y1: float) tuple[float, float, float][source]#

Convert circle X diameter coordinates to center and radius

Parameters:
  • x0 – Diameter start X coordinate

  • y0 – Diameter start Y coordinate

  • x1 – Diameter end X coordinate

  • y1 – Diameter end Y coordinate

Returns:

Circle center and radius

Return type:

tuple

sigima.tools.coordinates.array_circle_to_center_radius(data: ndarray) ndarray[source]#

Convert circle X diameter coordinates to center and radius (array version)

Parameters:

data – Circle X diameter coordinates, in the form of a 2D array (N, 4)

Returns:

Circle center and radius, in the form of a 2D array (N, 3)

sigima.tools.coordinates.ellipse_to_diameters(xc: float, yc: float, a: float, b: float, theta: float) tuple[float, float, float, float, float, float, float, float][source]#

Convert ellipse center, axes and angle to X/Y diameters coordinates

Parameters:
  • xc – Ellipse center X coordinate

  • yc – Ellipse center Y coordinate

  • a – Ellipse half larger axis

  • b – Ellipse half smaller axis

  • theta – Ellipse angle

Returns:

Ellipse X/Y diameters (major/minor axes) coordinates

sigima.tools.coordinates.array_ellipse_to_diameters(data: ndarray) ndarray[source]#

Convert ellipse center, axes and angle to X/Y diameters coordinates (array version)

Parameters:

data – Ellipse center, axes and angle, in the form of a 2D array (N, 5)

Returns:

Ellipse X/Y diameters (major/minor axes) coordinates,

in the form of a 2D array (N, 8)

sigima.tools.coordinates.ellipse_to_center_axes_angle(x0: float, y0: float, x1: float, y1: float, x2: float, y2: float, x3: float, y3: float) tuple[float, float, float, float, float][source]#

Convert ellipse X/Y diameters coordinates to center, axes and angle

Parameters:
  • x0 – major axis start X coordinate

  • y0 – major axis start Y coordinate

  • x1 – major axis end X coordinate

  • y1 – major axis end Y coordinate

  • x2 – minor axis start X coordinate

  • y2 – minor axis start Y coordinate

  • x3 – minor axis end X coordinate

  • y3 – minor axis end Y coordinate

Returns:

Ellipse center, axes and angle

sigima.tools.coordinates.array_ellipse_to_center_axes_angle(data: ndarray) ndarray[source]#

Convert ellipse X/Y diameters coordinates to center, axes and angle (array version)

Parameters:

data – Ellipse X/Y diameters coordinates, in the form of a 2D array (N, 8)

Returns:

Ellipse center, axes and angle, in the form of a 2D array (N, 5)

sigima.tools.coordinates.to_polar(x: ndarray, y: ndarray, unit: Literal['°', 'rad'] = 'rad') tuple[ndarray, ndarray][source]#

Convert Cartesian coordinates to polar coordinates.

Parameters:
  • x – Cartesian x-coordinate.

  • y – Cartesian y-coordinate.

  • unit – Unit of the angle (”°” or “rad”).

Returns:

Polar coordinates (r, theta) where r is the radius and theta is the angle.

Raises:

ValueError – If the unit is not “°” or “rad”.

sigima.tools.coordinates.to_cartesian(r: ndarray, theta: ndarray, unit: Literal['°', 'rad'] = 'rad') tuple[ndarray, ndarray][source]#

Convert polar coordinates to Cartesian coordinates.

Parameters:
  • r – Polar radius.

  • theta – Polar angle.

  • unit – Unit of the angle (”°” or “rad”).

Returns:

Cartesian coordinates (x, y) where x is the x-coordinate and y is the y-coordinate.

Raises:
  • ValueError – If the unit is not “°” or “rad”.

  • ValueError – If any value of the radius is negative.

sigima.tools.coordinates.rotate(angle: float) ndarray[source]#

Return rotation matrix

Parameters:

angle – Rotation angle (in radians)

Returns:

Rotation matrix

sigima.tools.coordinates.colvector(x: float, y: float) ndarray[source]#

Return vector from coordinates

Parameters:
  • x – x-coordinate

  • y – y-coordinate

Returns:

Vector

sigima.tools.coordinates.vector_rotation(theta: float, dx: float, dy: float) tuple[float, float][source]#

Compute theta-rotation on vector

Parameters:
  • theta – Rotation angle

  • dx – x-coordinate of vector

  • dy – y-coordinate of vector

Returns:

Tuple of (x, y) coordinates of rotated vector

sigima.tools.coordinates.polar_to_complex(r: ndarray, theta: ndarray, unit: Literal['°', 'rad'] = 'rad') ndarray[source]#

Convert polar coordinates to complex number.

Parameters:
  • r – Polar radius.

  • theta – Polar angle.

  • unit – Unit of the angle (”°” or “rad”).

Returns:

Complex numbers corresponding to the polar coordinates.

Raises:
  • ValueError – If the unit is not “°” or “rad”.

  • ValueError – If any value of the radius is negative.