Transforms

Signal transforms including Fourier, short-time Fourier, and wavelet transforms.

Transform utilities.

This module provides signal transforms for time-frequency analysis: - Fourier transforms (FFT, RFFT, 2D FFT) - Short-Time Fourier Transform (STFT) and spectrograms - Wavelet transforms (CWT and DWT)

class pytcl.mathematical_functions.transforms.PowerSpectrum(frequencies, psd)[source]

Bases: NamedTuple

Result of power spectrum estimation.

frequencies

Frequency values in Hz.

Type:

ndarray

psd

Power spectral density estimate.

Type:

ndarray

frequencies: ndarray[tuple[Any, ...], dtype[floating]]

Alias for field number 0

psd: ndarray[tuple[Any, ...], dtype[floating]]

Alias for field number 1

class pytcl.mathematical_functions.transforms.CrossSpectrum(frequencies, csd)[source]

Bases: NamedTuple

Result of cross-spectrum estimation.

frequencies

Frequency values in Hz.

Type:

ndarray

csd

Cross-spectral density estimate (complex).

Type:

ndarray

frequencies: ndarray[tuple[Any, ...], dtype[floating]]

Alias for field number 0

csd: ndarray[tuple[Any, ...], dtype[complexfloating]]

Alias for field number 1

class pytcl.mathematical_functions.transforms.CoherenceResult(frequencies, coherence)[source]

Bases: NamedTuple

Result of coherence estimation.

frequencies

Frequency values in Hz.

Type:

ndarray

coherence

Magnitude-squared coherence, values between 0 and 1.

Type:

ndarray

frequencies: ndarray[tuple[Any, ...], dtype[floating]]

Alias for field number 0

coherence: ndarray[tuple[Any, ...], dtype[floating]]

Alias for field number 1

pytcl.mathematical_functions.transforms.fft(x, n=None, axis=-1, norm=None)[source]

Compute the one-dimensional discrete Fourier Transform.

Parameters:
  • x (array_like) – Input array, can be complex.

  • n (int, optional) – Length of the transformed axis of the output. If n is smaller than the length of the input, the input is cropped. If it is larger, the input is padded with zeros.

  • axis (int, optional) – Axis over which to compute the FFT. Default is -1.

  • norm ({None, "ortho", "forward", "backward"}, optional) – Normalization mode. Default is None (backward).

Returns:

out – The truncated or zero-padded input, transformed along the axis.

Return type:

ndarray

Examples

>>> import numpy as np
>>> x = np.array([1.0, 2.0, 1.0, -1.0])
>>> X = fft(x)
>>> np.allclose(X, [3.+0.j, 0.-2.j, 1.+0.j, 0.+2.j])
True
pytcl.mathematical_functions.transforms.ifft(X, n=None, axis=-1, norm=None)[source]

Compute the one-dimensional inverse discrete Fourier Transform.

Parameters:
  • X (array_like) – Input array, can be complex.

  • n (int, optional) – Length of the transformed axis of the output.

  • axis (int, optional) – Axis over which to compute the inverse FFT. Default is -1.

  • norm ({None, "ortho", "forward", "backward"}, optional) – Normalization mode. Default is None (backward).

Returns:

out – The truncated or zero-padded input, transformed along the axis.

Return type:

ndarray

Examples

>>> import numpy as np
>>> X = np.array([3.+0.j, 0.-2.j, 1.+0.j, 0.+2.j])
>>> x = ifft(X)
>>> np.allclose(x, [1.0, 2.0, 1.0, -1.0])
True
pytcl.mathematical_functions.transforms.rfft(x, n=None, axis=-1, norm=None)[source]

Compute the one-dimensional FFT for real input.

This function computes the one-dimensional n-point discrete Fourier Transform (DFT) of a real-valued array by means of an efficient algorithm called the Fast Fourier Transform (FFT).

Parameters:
  • x (array_like) – Input array, must be real.

  • n (int, optional) – Number of points to use. If n is smaller than the length of the input, the input is cropped. If it is larger, the input is padded with zeros.

  • axis (int, optional) – Axis over which to compute the FFT. Default is -1.

  • norm ({None, "ortho", "forward", "backward"}, optional) – Normalization mode.

Returns:

out – The FFT of the input along the indicated axis. Only the non-negative frequency terms are returned (n//2 + 1 points).

Return type:

ndarray

Examples

>>> import numpy as np
>>> x = np.array([0., 1., 0., 0.])
>>> X = rfft(x)
>>> len(X)  # Only positive frequencies
3
pytcl.mathematical_functions.transforms.irfft(X, n=None, axis=-1, norm=None)[source]

Compute the inverse FFT for real output.

Parameters:
  • X (array_like) – Input array (typically from rfft).

  • n (int, optional) – Length of the output (along the transformed axis). If not given, n = 2*(len(X)-1).

  • axis (int, optional) – Axis over which to compute the inverse FFT. Default is -1.

  • norm ({None, "ortho", "forward", "backward"}, optional) – Normalization mode.

Returns:

out – Real-valued inverse FFT result.

Return type:

ndarray

Examples

>>> import numpy as np
>>> X = rfft([0., 1., 0., 0.])
>>> x = irfft(X)
>>> np.allclose(x, [0., 1., 0., 0.])
True
pytcl.mathematical_functions.transforms.fft2(x, s=None, axes=(-2, -1), norm=None)[source]

Compute the 2-dimensional discrete Fourier Transform.

Parameters:
  • x (array_like) – Input array, can be complex.

  • s (tuple of ints, optional) – Shape (length of each transformed axis) of the output.

  • axes (tuple of ints, optional) – Axes over which to compute the FFT. Default is (-2, -1).

  • norm ({None, "ortho", "forward", "backward"}, optional) – Normalization mode.

Returns:

out – The 2D FFT of the input.

Return type:

ndarray

Examples

>>> import numpy as np
>>> x = np.array([[1, 0], [0, 1]], dtype=float)
>>> X = fft2(x)
>>> X.shape
(2, 2)
pytcl.mathematical_functions.transforms.ifft2(X, s=None, axes=(-2, -1), norm=None)[source]

Compute the 2-dimensional inverse discrete Fourier Transform.

Parameters:
  • X (array_like) – Input array, can be complex.

  • s (tuple of ints, optional) – Shape (length of each transformed axis) of the output.

  • axes (tuple of ints, optional) – Axes over which to compute the inverse FFT. Default is (-2, -1).

  • norm ({None, "ortho", "forward", "backward"}, optional) – Normalization mode.

Returns:

out – The 2D inverse FFT of the input.

Return type:

ndarray

pytcl.mathematical_functions.transforms.fftshift(x, axes=None)[source]

Shift the zero-frequency component to the center of the spectrum.

Parameters:
  • x (array_like) – Input array.

  • axes (int or tuple of ints, optional) – Axes over which to shift. Default is all axes.

Returns:

y – The shifted array.

Return type:

ndarray

Examples

>>> import numpy as np
>>> freqs = np.fft.fftfreq(10, 0.1)
>>> freqs
array([ 0.,  1.,  2.,  3.,  4., -5., -4., -3., -2., -1.])
>>> fftshift(freqs)
array([-5., -4., -3., -2., -1.,  0.,  1.,  2.,  3.,  4.])
pytcl.mathematical_functions.transforms.ifftshift(x, axes=None)[source]

Inverse of fftshift. Shift zero-frequency back to beginning.

Parameters:
  • x (array_like) – Input array.

  • axes (int or tuple of ints, optional) – Axes over which to shift. Default is all axes.

Returns:

y – The shifted array.

Return type:

ndarray

pytcl.mathematical_functions.transforms.frequency_axis(n, fs, shift=False)[source]

Generate frequency axis values for FFT output.

Parameters:
  • n (int) – Number of FFT points.

  • fs (float) – Sampling frequency in Hz.

  • shift (bool, optional) – If True, return frequencies in centered (fftshift) order. Default is False.

Returns:

freqs – Frequency values in Hz.

Return type:

ndarray

Examples

>>> frequency_axis(8, 100.0)
array([  0. ,  12.5,  25. ,  37.5, -50. , -37.5, -25. , -12.5])
>>> frequency_axis(8, 100.0, shift=True)
array([-50. , -37.5, -25. , -12.5,   0. ,  12.5,  25. ,  37.5])
pytcl.mathematical_functions.transforms.rfft_frequency_axis(n, fs)[source]

Generate frequency axis values for rfft output.

Parameters:
  • n (int) – Number of points in the original signal.

  • fs (float) – Sampling frequency in Hz.

Returns:

freqs – Non-negative frequency values in Hz.

Return type:

ndarray

Examples

>>> rfft_frequency_axis(8, 100.0)
array([ 0. , 12.5, 25. , 37.5, 50. ])
pytcl.mathematical_functions.transforms.power_spectrum(x, fs=1.0, window='hann', nperseg=None, noverlap=None, nfft=None, detrend='constant', scaling='density')[source]

Estimate power spectral density using Welch’s method.

Parameters:
  • x (array_like) – Time series data.

  • fs (float, optional) – Sampling frequency in Hz. Default is 1.0.

  • window (str, optional) – Window function to use. Default is ‘hann’.

  • nperseg (int, optional) – Length of each segment. Default is 256.

  • noverlap (int, optional) – Number of points to overlap between segments. Default is nperseg//2.

  • nfft (int, optional) – Length of the FFT used. Default is nperseg.

  • detrend (str or bool, optional) – Detrending method: ‘constant’, ‘linear’, or False. Default is ‘constant’.

  • scaling ({'density', 'spectrum'}, optional) – ‘density’ for power spectral density (V^2/Hz), ‘spectrum’ for power spectrum (V^2). Default is ‘density’.

Returns:

result – Named tuple with frequencies and power spectral density.

Return type:

PowerSpectrum

Examples

>>> import numpy as np
>>> fs = 1000  # 1 kHz
>>> t = np.arange(0, 1, 1/fs)
>>> x = np.sin(2 * np.pi * 100 * t)  # 100 Hz sine
>>> result = power_spectrum(x, fs=fs)
>>> peak_freq = result.frequencies[np.argmax(result.psd)]
>>> abs(peak_freq - 100) < 5  # Peak near 100 Hz
True

Notes

Uses Welch’s method which averages modified periodograms of overlapping segments to reduce variance of the spectral estimate.

pytcl.mathematical_functions.transforms.cross_spectrum(x, y, fs=1.0, window='hann', nperseg=None, noverlap=None, nfft=None, detrend='constant')[source]

Estimate cross-spectral density between two signals.

Parameters:
  • x (array_like) – First time series.

  • y (array_like) – Second time series.

  • fs (float, optional) – Sampling frequency in Hz. Default is 1.0.

  • window (str, optional) – Window function. Default is ‘hann’.

  • nperseg (int, optional) – Length of each segment. Default is 256.

  • noverlap (int, optional) – Number of points to overlap between segments. Default is nperseg//2.

  • nfft (int, optional) – Length of FFT. Default is nperseg.

  • detrend (str or bool, optional) – Detrending method. Default is ‘constant’.

Returns:

result – Named tuple with frequencies and cross-spectral density.

Return type:

CrossSpectrum

Examples

>>> import numpy as np
>>> fs = 1000
>>> t = np.arange(0, 1, 1/fs)
>>> x = np.sin(2 * np.pi * 50 * t)
>>> y = np.sin(2 * np.pi * 50 * t + np.pi/4)  # Same freq, phase shifted
>>> result = cross_spectrum(x, y, fs=fs)
>>> len(result.frequencies) > 0
True
pytcl.mathematical_functions.transforms.coherence(x, y, fs=1.0, window='hann', nperseg=None, noverlap=None, nfft=None, detrend='constant')[source]

Estimate magnitude-squared coherence between two signals.

The coherence measures the linear correlation between two signals as a function of frequency. Values range from 0 (no correlation) to 1 (perfect correlation).

Parameters:
  • x (array_like) – First time series.

  • y (array_like) – Second time series.

  • fs (float, optional) – Sampling frequency in Hz. Default is 1.0.

  • window (str, optional) – Window function. Default is ‘hann’.

  • nperseg (int, optional) – Length of each segment. Default is 256.

  • noverlap (int, optional) – Number of overlap points. Default is nperseg//2.

  • nfft (int, optional) – Length of FFT. Default is nperseg.

  • detrend (str or bool, optional) – Detrending method. Default is ‘constant’.

Returns:

result – Named tuple with frequencies and coherence values.

Return type:

CoherenceResult

Examples

>>> import numpy as np
>>> fs = 1000
>>> t = np.arange(0, 1, 1/fs)
>>> x = np.sin(2 * np.pi * 50 * t)
>>> y = 2 * x + 0.1 * np.random.randn(len(t))  # Correlated
>>> result = coherence(x, y, fs=fs)
>>> np.max(result.coherence) > 0.9  # High coherence at 50 Hz
True

Notes

Coherence is defined as:

C_xy = |S_xy|^2 / (S_xx * S_yy)

where S_xy is the cross-spectral density and S_xx, S_yy are the power spectral densities.

pytcl.mathematical_functions.transforms.periodogram(x, fs=1.0, window=None, nfft=None, detrend='constant', scaling='density')[source]

Estimate power spectral density using a periodogram.

Unlike Welch’s method, the periodogram uses the entire signal without segmentation and averaging. This gives higher frequency resolution but higher variance.

Parameters:
  • x (array_like) – Time series data.

  • fs (float, optional) – Sampling frequency in Hz. Default is 1.0.

  • window (str, optional) – Window function. Default is None (rectangular).

  • nfft (int, optional) – Length of FFT. Default is len(x).

  • detrend (str or bool, optional) – Detrending method. Default is ‘constant’.

  • scaling ({'density', 'spectrum'}, optional) – Scaling mode. Default is ‘density’.

Returns:

result – Named tuple with frequencies and power spectral density.

Return type:

PowerSpectrum

Examples

>>> import numpy as np
>>> fs = 1000
>>> t = np.arange(0, 1, 1/fs)
>>> x = np.sin(2 * np.pi * 100 * t)
>>> result = periodogram(x, fs=fs)
>>> len(result.frequencies) == len(result.psd)
True
pytcl.mathematical_functions.transforms.magnitude_spectrum(X, scale='linear')[source]

Compute magnitude spectrum from FFT coefficients.

Parameters:
  • X (array_like) – Complex FFT coefficients.

  • scale ({'linear', 'dB'}, optional) – Output scale. Default is ‘linear’.

Returns:

mag – Magnitude spectrum.

Return type:

ndarray

Examples

>>> import numpy as np
>>> X = np.array([4+0j, 0-2j, 0+0j, 0+2j])
>>> magnitude_spectrum(X)
array([4., 2., 0., 2.])
>>> magnitude_spectrum(X, scale='dB')
array([12.04..., 6.02..., -inf, 6.02...])
pytcl.mathematical_functions.transforms.phase_spectrum(X, unwrap=False)[source]

Compute phase spectrum from FFT coefficients.

Parameters:
  • X (array_like) – Complex FFT coefficients.

  • unwrap (bool, optional) – If True, unwrap the phase to remove discontinuities. Default is False.

Returns:

phase – Phase spectrum in radians.

Return type:

ndarray

Examples

>>> import numpy as np
>>> X = np.array([1+0j, 0+1j, -1+0j, 0-1j])
>>> phase = phase_spectrum(X)
>>> np.allclose(phase, [0, np.pi/2, np.pi, -np.pi/2])
True
class pytcl.mathematical_functions.transforms.STFTResult(frequencies, times, Zxx)[source]

Bases: NamedTuple

Result of Short-Time Fourier Transform.

frequencies

Frequency values in Hz.

Type:

ndarray

times

Time values in seconds (segment centers).

Type:

ndarray

Zxx

STFT matrix (complex), shape (n_frequencies, n_times).

Type:

ndarray

frequencies: ndarray[tuple[Any, ...], dtype[floating]]

Alias for field number 0

times: ndarray[tuple[Any, ...], dtype[floating]]

Alias for field number 1

Zxx: ndarray[tuple[Any, ...], dtype[complexfloating]]

Alias for field number 2

class pytcl.mathematical_functions.transforms.Spectrogram(frequencies, times, power)[source]

Bases: NamedTuple

Result of spectrogram computation.

frequencies

Frequency values in Hz.

Type:

ndarray

times

Time values in seconds.

Type:

ndarray

power

Power spectrogram (|STFT|^2).

Type:

ndarray

frequencies: ndarray[tuple[Any, ...], dtype[floating]]

Alias for field number 0

times: ndarray[tuple[Any, ...], dtype[floating]]

Alias for field number 1

power: ndarray[tuple[Any, ...], dtype[floating]]

Alias for field number 2

pytcl.mathematical_functions.transforms.stft(x, fs=1.0, window='hann', nperseg=256, noverlap=None, nfft=None, detrend=False, return_onesided=True, boundary='zeros', padded=True)[source]

Compute the Short-Time Fourier Transform.

Parameters:
  • x (array_like) – Input time-domain signal.

  • fs (float, optional) – Sampling frequency in Hz. Default is 1.0.

  • window (str, tuple, or array_like, optional) – Window function. Default is ‘hann’.

  • nperseg (int, optional) – Length of each segment. Default is 256.

  • noverlap (int, optional) – Number of points to overlap between segments. Default is nperseg // 2.

  • nfft (int, optional) – Length of the FFT used. Default is nperseg.

  • detrend (str or bool, optional) – Detrending: ‘constant’, ‘linear’, or False. Default is False.

  • return_onesided (bool, optional) – If True, return only non-negative frequencies for real input. Default is True.

  • boundary (str or None, optional) – Boundary extension: ‘zeros’, ‘even’, ‘odd’, or None. Default is ‘zeros’.

  • padded (bool, optional) – Whether to pad the signal. Default is True.

Returns:

result – Named tuple with frequencies, times, and STFT matrix.

Return type:

STFTResult

Examples

>>> import numpy as np
>>> fs = 1000
>>> t = np.arange(0, 1, 1/fs)
>>> x = np.sin(2 * np.pi * 50 * t)  # 50 Hz sine
>>> result = stft(x, fs=fs, nperseg=128)
>>> result.Zxx.shape  # (n_freq, n_time)
(65, 16)

Notes

The STFT provides a time-frequency representation where: - Time resolution = nperseg / fs - Frequency resolution = fs / nfft

There is a trade-off between time and frequency resolution (uncertainty principle): better time resolution requires shorter segments, which reduces frequency resolution, and vice versa.

pytcl.mathematical_functions.transforms.istft(Zxx, fs=1.0, window='hann', nperseg=None, noverlap=None, nfft=None, input_onesided=True, boundary=True)[source]

Compute the inverse Short-Time Fourier Transform.

Parameters:
  • Zxx (array_like) – STFT matrix from stft function.

  • fs (float, optional) – Sampling frequency in Hz. Default is 1.0.

  • window (str, tuple, or array_like, optional) – Window function (should match the one used in stft). Default is ‘hann’.

  • nperseg (int, optional) – Length of each segment. Default is inferred from Zxx.

  • noverlap (int, optional) – Overlap between segments. Default is nperseg // 2.

  • nfft (int, optional) – FFT length. Default is inferred from Zxx.

  • input_onesided (bool, optional) – If True, interpret Zxx as one-sided. Default is True.

  • boundary (bool, optional) – Whether boundary extension was used. Default is True.

Returns:

  • times (ndarray) – Time values in seconds.

  • x (ndarray) – Reconstructed time-domain signal.

Return type:

tuple[ndarray[tuple[Any, …], dtype[floating]], ndarray[tuple[Any, …], dtype[floating]]]

Examples

>>> import numpy as np
>>> fs = 1000
>>> t = np.arange(0, 1, 1/fs)
>>> x = np.sin(2 * np.pi * 50 * t)
>>> result = stft(x, fs=fs, nperseg=128)
>>> t_rec, x_rec = istft(result.Zxx, fs=fs, nperseg=128)
>>> np.allclose(x, x_rec[:len(x)], atol=1e-10)
True

Notes

The inverse STFT uses the overlap-add method. For perfect reconstruction, the window function and overlap must satisfy the constant overlap-add (COLA) constraint.

pytcl.mathematical_functions.transforms.spectrogram(x, fs=1.0, window='hann', nperseg=256, noverlap=None, nfft=None, detrend='constant', scaling='density', mode='psd')[source]

Compute a spectrogram (power spectral density over time).

Parameters:
  • x (array_like) – Input time-domain signal.

  • fs (float, optional) – Sampling frequency in Hz. Default is 1.0.

  • window (str, tuple, or array_like, optional) – Window function. Default is ‘hann’.

  • nperseg (int, optional) – Length of each segment. Default is 256.

  • noverlap (int, optional) – Overlap between segments. Default is nperseg // 8.

  • nfft (int, optional) – FFT length. Default is nperseg.

  • detrend (str or bool, optional) – Detrending: ‘constant’, ‘linear’, or False. Default is ‘constant’.

  • scaling ({'density', 'spectrum'}, optional) – ‘density’ for PSD (V^2/Hz), ‘spectrum’ for power (V^2). Default is ‘density’.

  • mode ({'psd', 'complex', 'magnitude', 'angle', 'phase'}, optional) – Return type. Default is ‘psd’.

Returns:

result – Named tuple with frequencies, times, and power spectrogram.

Return type:

Spectrogram

Examples

>>> import numpy as np
>>> fs = 1000
>>> t = np.arange(0, 2, 1/fs)
>>> # Chirp from 50 to 200 Hz
>>> x = np.sin(2 * np.pi * (50 + 75*t) * t)
>>> result = spectrogram(x, fs=fs, nperseg=128)
>>> result.power.shape  # (n_freq, n_time)
(65, 31)

Notes

The spectrogram is computed by taking the magnitude squared of the STFT. It shows how the spectral content of the signal evolves over time.

pytcl.mathematical_functions.transforms.get_window(window, length, fftbins=True)[source]

Generate a window function.

Parameters:
  • window (str, tuple, or array_like) – Window type. Can be: - String: ‘hann’, ‘hamming’, ‘blackman’, ‘bartlett’, ‘kaiser’, etc. - Tuple: (window_name, parameter) for parameterized windows - Array: Custom window values

  • length (int) – Length of the window.

  • fftbins (bool, optional) – If True, create a periodic window for FFT use. Default is True.

Returns:

window – Window function values.

Return type:

ndarray

Examples

>>> w = get_window('hann', 256)
>>> len(w)
256
>>> w[0], w[-1]  # Near-zero at edges
(0.0, 0.0038...)
>>> w = get_window(('kaiser', 8.0), 256)  # Kaiser with beta=8
>>> len(w)
256

Notes

Common window functions: - ‘rectangular’: No tapering (unity) - ‘hann’: Good frequency resolution, low leakage - ‘hamming’: Similar to Hann, slightly different sidelobes - ‘blackman’: Very low sidelobes, wider main lobe - ‘kaiser’: Parameterized trade-off between resolution and leakage

pytcl.mathematical_functions.transforms.window_bandwidth(window, length)[source]

Compute the equivalent noise bandwidth of a window.

The equivalent noise bandwidth (ENBW) is the width of an ideal rectangular filter that would pass the same amount of white noise power.

Parameters:
  • window (str or array_like) – Window function.

  • length (int) – Window length.

Returns:

enbw – Equivalent noise bandwidth in bins.

Return type:

float

Examples

>>> enbw = window_bandwidth('hann', 256)
>>> 1.4 < enbw < 1.6  # Hann window ENBW is about 1.5 bins
True
pytcl.mathematical_functions.transforms.reassigned_spectrogram(x, fs=1.0, window='hann', nperseg=256, noverlap=None, nfft=None)[source]

Compute reassigned spectrogram for improved time-frequency resolution.

The reassigned spectrogram sharpens the time-frequency representation by moving energy to the center of gravity of each analysis frame.

Parameters:
  • x (array_like) – Input signal.

  • fs (float, optional) – Sampling frequency in Hz. Default is 1.0.

  • window (str, tuple, or array_like, optional) – Window function. Default is ‘hann’.

  • nperseg (int, optional) – Segment length. Default is 256.

  • noverlap (int, optional) – Overlap. Default is nperseg - 1.

  • nfft (int, optional) – FFT length. Default is nperseg.

Returns:

  • frequencies (ndarray) – Frequency values in Hz.

  • times (ndarray) – Time values in seconds.

  • Sxx (ndarray) – Reassigned spectrogram power.

Return type:

tuple[ndarray[tuple[Any, …], dtype[floating]], ndarray[tuple[Any, …], dtype[floating]], ndarray[tuple[Any, …], dtype[floating]]]

Notes

The reassignment method improves readability of the spectrogram by concentrating the spectral energy, making it easier to track frequency components. However, it requires more computation than a standard spectrogram.

pytcl.mathematical_functions.transforms.mel_spectrogram(x, fs, n_mels=128, fmin=0.0, fmax=None, window='hann', nperseg=2048, noverlap=None)[source]

Compute mel-scaled spectrogram.

The mel scale is a perceptual scale of pitches that approximates human auditory perception. Mel spectrograms are widely used in audio analysis and speech recognition.

Parameters:
  • x (array_like) – Input audio signal.

  • fs (float) – Sampling frequency in Hz.

  • n_mels (int, optional) – Number of mel bands. Default is 128.

  • fmin (float, optional) – Minimum frequency in Hz. Default is 0.0.

  • fmax (float, optional) – Maximum frequency in Hz. Default is fs/2.

  • window (str, optional) – Window function. Default is ‘hann’.

  • nperseg (int, optional) – Segment length. Default is 2048.

  • noverlap (int, optional) – Overlap. Default is nperseg // 4.

Returns:

  • mel_freqs (ndarray) – Mel frequency band centers in Hz.

  • times (ndarray) – Time values in seconds.

  • mel_spec (ndarray) – Mel spectrogram (n_mels, n_times).

Return type:

tuple[ndarray[tuple[Any, …], dtype[floating]], ndarray[tuple[Any, …], dtype[floating]], ndarray[tuple[Any, …], dtype[floating]]]

Examples

>>> import numpy as np
>>> fs = 22050
>>> x = np.random.randn(fs)  # 1 second of noise
>>> mel_freqs, times, mel_spec = mel_spectrogram(x, fs, n_mels=64)
>>> mel_spec.shape[0]
64
class pytcl.mathematical_functions.transforms.CWTResult(coefficients, scales, frequencies)[source]

Bases: NamedTuple

Result of Continuous Wavelet Transform.

coefficients

CWT coefficient matrix (complex), shape (n_scales, n_samples).

Type:

ndarray

scales

Scale values used.

Type:

ndarray

frequencies

Approximate frequencies corresponding to each scale.

Type:

ndarray

coefficients: ndarray[tuple[Any, ...], dtype[complexfloating]]

Alias for field number 0

scales: ndarray[tuple[Any, ...], dtype[floating]]

Alias for field number 1

frequencies: ndarray[tuple[Any, ...], dtype[floating]]

Alias for field number 2

class pytcl.mathematical_functions.transforms.DWTResult(cA, cD, levels, wavelet)[source]

Bases: NamedTuple

Result of Discrete Wavelet Transform.

cA

Approximation coefficients at the coarsest level.

Type:

ndarray

cD

Detail coefficients at each level (finest to coarsest).

Type:

list of ndarray

levels

Number of decomposition levels.

Type:

int

wavelet

Wavelet name used.

Type:

str

cA: ndarray[tuple[Any, ...], dtype[floating]]

Alias for field number 0

cD: List[ndarray[tuple[Any, ...], dtype[floating]]]

Alias for field number 1

levels: int

Alias for field number 2

wavelet: str

Alias for field number 3

pytcl.mathematical_functions.transforms.morlet_wavelet(M, w=5.0, s=1.0, complete=True)[source]

Generate a Morlet wavelet.

The Morlet wavelet is a sinusoid windowed by a Gaussian, commonly used for time-frequency analysis.

Parameters:
  • M (int) – Length of the wavelet.

  • w (float, optional) – Omega0, the central frequency parameter. Default is 5.0.

  • s (float, optional) – Scaling factor. Default is 1.0.

  • complete (bool, optional) – If True, use the complete Morlet wavelet with correction term. Default is True.

Returns:

wavelet – Complex Morlet wavelet.

Return type:

ndarray

Examples

>>> wav = morlet_wavelet(128, w=5.0)
>>> len(wav)
128
>>> np.abs(wav[len(wav)//2]) > 0  # Peak in center
True

Notes

The Morlet wavelet is defined as:

psi(t) = exp(i*w*t) * exp(-t^2/2)

With the complete correction:

psi(t) = (exp(i*w*t) - exp(-w^2/2)) * exp(-t^2/2)

pytcl.mathematical_functions.transforms.ricker_wavelet(points, a=1.0)[source]

Generate a Ricker wavelet (Mexican hat wavelet).

The Ricker wavelet is the negative normalized second derivative of a Gaussian function. It is real-valued and commonly used in seismology.

Parameters:
  • points (int) – Number of points in the wavelet.

  • a (float, optional) – Width parameter. Default is 1.0.

Returns:

wavelet – Ricker wavelet.

Return type:

ndarray

Examples

>>> wav = ricker_wavelet(128, a=4.0)
>>> len(wav)
128
>>> wav[len(wav)//2]  # Peak at center
1.0

Notes

The Ricker wavelet is defined as:

psi(t) = (1 - 2*(pi*f*t)^2) * exp(-(pi*f*t)^2)

where f = 1/(sqrt(2)*pi*a) is the central frequency.

pytcl.mathematical_functions.transforms.gaussian_wavelet(M, order=1, sigma=1.0)[source]

Generate a Gaussian derivative wavelet.

Parameters:
  • M (int) – Length of the wavelet.

  • order (int, optional) – Order of the derivative. Default is 1.

  • sigma (float, optional) – Standard deviation of the Gaussian. Default is 1.0.

Returns:

wavelet – Gaussian derivative wavelet.

Return type:

ndarray

Examples

>>> wav = gaussian_wavelet(128, order=1)
>>> len(wav)
128
pytcl.mathematical_functions.transforms.cwt(signal, scales, wavelet='morlet', fs=1.0, method='fft')[source]

Compute the Continuous Wavelet Transform.

Parameters:
  • signal (array_like) – Input signal.

  • scales (array_like) – Scale values to use.

  • wavelet (str or callable, optional) – Wavelet to use. Options: ‘morlet’, ‘ricker’, ‘gaussian1’, ‘gaussian2’, or a callable. Default is ‘morlet’.

  • fs (float, optional) – Sampling frequency in Hz. Default is 1.0.

  • method ({'fft', 'conv'}, optional) – Computation method. ‘fft’ is faster for long signals. Default is ‘fft’.

Returns:

result – Named tuple with coefficients, scales, and frequencies.

Return type:

CWTResult

Examples

>>> import numpy as np
>>> fs = 1000
>>> t = np.arange(0, 1, 1/fs)
>>> x = np.sin(2 * np.pi * 50 * t)
>>> scales = np.arange(1, 128)
>>> result = cwt(x, scales, wavelet='morlet', fs=fs)
>>> result.coefficients.shape
(127, 1000)

Notes

The CWT is computed as:

W(a, b) = integral s(t) * (1/sqrt(a)) * psi*((t-b)/a) dt

where a is the scale, b is the translation, and psi is the wavelet.

pytcl.mathematical_functions.transforms.scales_to_frequencies(scales, wavelet='morlet', fs=1.0)[source]

Convert CWT scales to approximate frequencies.

Parameters:
  • scales (array_like) – Scale values.

  • wavelet (str, optional) – Wavelet name. Default is ‘morlet’.

  • fs (float, optional) – Sampling frequency in Hz. Default is 1.0.

Returns:

frequencies – Approximate frequencies in Hz.

Return type:

ndarray

Examples

>>> scales = np.array([1, 2, 4, 8, 16])
>>> freqs = scales_to_frequencies(scales, wavelet='morlet', fs=1000)
>>> len(freqs)
5
>>> freqs[0] > freqs[-1]  # Smaller scale = higher frequency
True
pytcl.mathematical_functions.transforms.frequencies_to_scales(frequencies, wavelet='morlet', fs=1.0)[source]

Convert desired frequencies to CWT scales.

Parameters:
  • frequencies (array_like) – Desired frequencies in Hz.

  • wavelet (str, optional) – Wavelet name. Default is ‘morlet’.

  • fs (float, optional) – Sampling frequency in Hz. Default is 1.0.

Returns:

scales – Scale values.

Return type:

ndarray

pytcl.mathematical_functions.transforms.dwt(signal, wavelet='db4', level=None, mode='symmetric')[source]

Compute the Discrete Wavelet Transform.

The DWT decomposes a signal into approximation and detail coefficients at multiple resolution levels.

Parameters:
  • signal (array_like) – Input signal.

  • wavelet (str, optional) – Wavelet to use (e.g., ‘db4’, ‘haar’, ‘sym8’, ‘coif3’). Default is ‘db4’.

  • level (int, optional) – Decomposition level. Default is max level for signal length.

  • mode (str, optional) – Signal extension mode. Default is ‘symmetric’.

Returns:

result – Named tuple with approximation and detail coefficients.

Return type:

DWTResult

Examples

>>> import numpy as np
>>> x = np.random.randn(256)
>>> result = dwt(x, wavelet='db4', level=4)
>>> len(result.cD)  # 4 levels of detail
4

Notes

Requires the pywavelets package. Install with: pip install pywavelets

Common wavelet families: - ‘haar’: Simplest wavelet - ‘dbN’: Daubechies wavelets (N=1..38) - ‘symN’: Symlets (N=2..20) - ‘coifN’: Coiflets (N=1..17) - ‘biorN.M’: Biorthogonal wavelets

pytcl.mathematical_functions.transforms.idwt(coeffs, mode='symmetric')[source]

Compute the inverse Discrete Wavelet Transform.

Parameters:
  • coeffs (DWTResult) – DWT coefficients from dwt function.

  • mode (str, optional) – Signal extension mode. Default is ‘symmetric’.

Returns:

signal – Reconstructed signal.

Return type:

ndarray

Examples

>>> import numpy as np
>>> x = np.random.randn(256)
>>> result = dwt(x, wavelet='db4', level=4)
>>> x_rec = idwt(result)
>>> np.allclose(x, x_rec)
True
pytcl.mathematical_functions.transforms.dwt_single_level(signal, wavelet='db4', mode='symmetric')[source]

Compute single-level DWT decomposition.

Parameters:
  • signal (array_like) – Input signal.

  • wavelet (str, optional) – Wavelet name. Default is ‘db4’.

  • mode (str, optional) – Signal extension mode. Default is ‘symmetric’.

Returns:

  • cA (ndarray) – Approximation coefficients.

  • cD (ndarray) – Detail coefficients.

Return type:

tuple[ndarray[tuple[Any, …], dtype[floating]], ndarray[tuple[Any, …], dtype[floating]]]

pytcl.mathematical_functions.transforms.idwt_single_level(cA, cD, wavelet='db4', mode='symmetric')[source]

Compute single-level inverse DWT.

Parameters:
  • cA (array_like) – Approximation coefficients.

  • cD (array_like) – Detail coefficients.

  • wavelet (str, optional) – Wavelet name. Default is ‘db4’.

  • mode (str, optional) – Signal extension mode. Default is ‘symmetric’.

Returns:

signal – Reconstructed signal.

Return type:

ndarray

pytcl.mathematical_functions.transforms.wpt(signal, wavelet='db4', level=None, mode='symmetric')[source]

Compute the Wavelet Packet Transform.

The WPT provides a more flexible time-frequency decomposition than DWT by also decomposing the detail coefficients.

Parameters:
  • signal (array_like) – Input signal.

  • wavelet (str, optional) – Wavelet name. Default is ‘db4’.

  • level (int, optional) – Decomposition level. Default is 3.

  • mode (str, optional) – Signal extension mode. Default is ‘symmetric’.

Returns:

nodes – Dictionary mapping node paths to coefficients. Path format: ‘a’ for approximation, ‘d’ for detail. Example: ‘aad’ means approx->approx->detail.

Return type:

dict

Examples

>>> import numpy as np
>>> x = np.random.randn(256)
>>> nodes = wpt(x, wavelet='db4', level=2)
>>> 'aa' in nodes  # Level 2 approximation
True
>>> 'dd' in nodes  # Level 2 detail of detail
True
pytcl.mathematical_functions.transforms.available_wavelets()[source]

List available wavelet families for DWT.

Returns:

wavelets – Available wavelet names.

Return type:

list of str

pytcl.mathematical_functions.transforms.wavelet_info(wavelet)[source]

Get information about a wavelet.

Parameters:

wavelet (str) – Wavelet name.

Returns:

info – Dictionary with wavelet properties.

Return type:

dict

pytcl.mathematical_functions.transforms.threshold_coefficients(coeffs, threshold='soft', value=None)[source]

Threshold DWT coefficients for denoising.

Parameters:
  • coeffs (DWTResult) – DWT coefficients.

  • threshold (float or {'soft', 'hard'}, optional) – Threshold type or value. Default is ‘soft’.

  • value (float, optional) – Threshold value. If None, uses universal threshold.

Returns:

result – Thresholded coefficients.

Return type:

DWTResult

Examples

>>> import numpy as np
>>> from pytcl.mathematical_functions.transforms import dwt, threshold_coefficients, idwt
>>> # Create noisy signal
>>> t = np.linspace(0, 1, 256)
>>> signal = np.sin(2 * np.pi * 5 * t)
>>> noise = 0.5 * np.random.randn(256)
>>> noisy_signal = signal + noise
>>> # Denoise using wavelet thresholding
>>> coeffs = dwt(noisy_signal, wavelet='db4', level=3)
>>> # Apply soft threshold (default automatic threshold value)
>>> coeffs_denoised = threshold_coefficients(coeffs, threshold='soft')
>>> # Reconstruct signal from thresholded coefficients
>>> signal_denoised = idwt(coeffs_denoised)
>>> len(signal_denoised) == len(noisy_signal)
True

Notes

When value is None, the universal threshold is computed as:

sigma * sqrt(2 * log(n))

where sigma is estimated from the finest detail coefficients and n is the total number of coefficients.

Fourier Transforms

FFT, power spectrum, and frequency analysis functions.

Fourier transform utilities.

This module provides wrappers and utilities for Discrete Fourier Transform operations, power spectral density estimation, and spectral analysis.

Functions

  • fft, ifft: Complex FFT and inverse

  • rfft, irfft: Real-signal FFT and inverse

  • fftshift, ifftshift: Shift zero-frequency to center

  • power_spectrum: Power spectral density estimation

  • cross_spectrum: Cross-spectral density

  • coherence: Magnitude-squared coherence

  • frequency_axis: Generate frequency axis for FFT

References

class pytcl.mathematical_functions.transforms.fourier.PowerSpectrum(frequencies, psd)[source]

Bases: NamedTuple

Result of power spectrum estimation.

frequencies

Frequency values in Hz.

Type:

ndarray

psd

Power spectral density estimate.

Type:

ndarray

frequencies: ndarray[tuple[Any, ...], dtype[floating]]

Alias for field number 0

psd: ndarray[tuple[Any, ...], dtype[floating]]

Alias for field number 1

class pytcl.mathematical_functions.transforms.fourier.CrossSpectrum(frequencies, csd)[source]

Bases: NamedTuple

Result of cross-spectrum estimation.

frequencies

Frequency values in Hz.

Type:

ndarray

csd

Cross-spectral density estimate (complex).

Type:

ndarray

frequencies: ndarray[tuple[Any, ...], dtype[floating]]

Alias for field number 0

csd: ndarray[tuple[Any, ...], dtype[complexfloating]]

Alias for field number 1

class pytcl.mathematical_functions.transforms.fourier.CoherenceResult(frequencies, coherence)[source]

Bases: NamedTuple

Result of coherence estimation.

frequencies

Frequency values in Hz.

Type:

ndarray

coherence

Magnitude-squared coherence, values between 0 and 1.

Type:

ndarray

frequencies: ndarray[tuple[Any, ...], dtype[floating]]

Alias for field number 0

coherence: ndarray[tuple[Any, ...], dtype[floating]]

Alias for field number 1

pytcl.mathematical_functions.transforms.fourier.fft(x, n=None, axis=-1, norm=None)[source]

Compute the one-dimensional discrete Fourier Transform.

Parameters:
  • x (array_like) – Input array, can be complex.

  • n (int, optional) – Length of the transformed axis of the output. If n is smaller than the length of the input, the input is cropped. If it is larger, the input is padded with zeros.

  • axis (int, optional) – Axis over which to compute the FFT. Default is -1.

  • norm ({None, "ortho", "forward", "backward"}, optional) – Normalization mode. Default is None (backward).

Returns:

out – The truncated or zero-padded input, transformed along the axis.

Return type:

ndarray

Examples

>>> import numpy as np
>>> x = np.array([1.0, 2.0, 1.0, -1.0])
>>> X = fft(x)
>>> np.allclose(X, [3.+0.j, 0.-2.j, 1.+0.j, 0.+2.j])
True
pytcl.mathematical_functions.transforms.fourier.ifft(X, n=None, axis=-1, norm=None)[source]

Compute the one-dimensional inverse discrete Fourier Transform.

Parameters:
  • X (array_like) – Input array, can be complex.

  • n (int, optional) – Length of the transformed axis of the output.

  • axis (int, optional) – Axis over which to compute the inverse FFT. Default is -1.

  • norm ({None, "ortho", "forward", "backward"}, optional) – Normalization mode. Default is None (backward).

Returns:

out – The truncated or zero-padded input, transformed along the axis.

Return type:

ndarray

Examples

>>> import numpy as np
>>> X = np.array([3.+0.j, 0.-2.j, 1.+0.j, 0.+2.j])
>>> x = ifft(X)
>>> np.allclose(x, [1.0, 2.0, 1.0, -1.0])
True
pytcl.mathematical_functions.transforms.fourier.rfft(x, n=None, axis=-1, norm=None)[source]

Compute the one-dimensional FFT for real input.

This function computes the one-dimensional n-point discrete Fourier Transform (DFT) of a real-valued array by means of an efficient algorithm called the Fast Fourier Transform (FFT).

Parameters:
  • x (array_like) – Input array, must be real.

  • n (int, optional) – Number of points to use. If n is smaller than the length of the input, the input is cropped. If it is larger, the input is padded with zeros.

  • axis (int, optional) – Axis over which to compute the FFT. Default is -1.

  • norm ({None, "ortho", "forward", "backward"}, optional) – Normalization mode.

Returns:

out – The FFT of the input along the indicated axis. Only the non-negative frequency terms are returned (n//2 + 1 points).

Return type:

ndarray

Examples

>>> import numpy as np
>>> x = np.array([0., 1., 0., 0.])
>>> X = rfft(x)
>>> len(X)  # Only positive frequencies
3
pytcl.mathematical_functions.transforms.fourier.irfft(X, n=None, axis=-1, norm=None)[source]

Compute the inverse FFT for real output.

Parameters:
  • X (array_like) – Input array (typically from rfft).

  • n (int, optional) – Length of the output (along the transformed axis). If not given, n = 2*(len(X)-1).

  • axis (int, optional) – Axis over which to compute the inverse FFT. Default is -1.

  • norm ({None, "ortho", "forward", "backward"}, optional) – Normalization mode.

Returns:

out – Real-valued inverse FFT result.

Return type:

ndarray

Examples

>>> import numpy as np
>>> X = rfft([0., 1., 0., 0.])
>>> x = irfft(X)
>>> np.allclose(x, [0., 1., 0., 0.])
True
pytcl.mathematical_functions.transforms.fourier.fft2(x, s=None, axes=(-2, -1), norm=None)[source]

Compute the 2-dimensional discrete Fourier Transform.

Parameters:
  • x (array_like) – Input array, can be complex.

  • s (tuple of ints, optional) – Shape (length of each transformed axis) of the output.

  • axes (tuple of ints, optional) – Axes over which to compute the FFT. Default is (-2, -1).

  • norm ({None, "ortho", "forward", "backward"}, optional) – Normalization mode.

Returns:

out – The 2D FFT of the input.

Return type:

ndarray

Examples

>>> import numpy as np
>>> x = np.array([[1, 0], [0, 1]], dtype=float)
>>> X = fft2(x)
>>> X.shape
(2, 2)
pytcl.mathematical_functions.transforms.fourier.ifft2(X, s=None, axes=(-2, -1), norm=None)[source]

Compute the 2-dimensional inverse discrete Fourier Transform.

Parameters:
  • X (array_like) – Input array, can be complex.

  • s (tuple of ints, optional) – Shape (length of each transformed axis) of the output.

  • axes (tuple of ints, optional) – Axes over which to compute the inverse FFT. Default is (-2, -1).

  • norm ({None, "ortho", "forward", "backward"}, optional) – Normalization mode.

Returns:

out – The 2D inverse FFT of the input.

Return type:

ndarray

pytcl.mathematical_functions.transforms.fourier.fftshift(x, axes=None)[source]

Shift the zero-frequency component to the center of the spectrum.

Parameters:
  • x (array_like) – Input array.

  • axes (int or tuple of ints, optional) – Axes over which to shift. Default is all axes.

Returns:

y – The shifted array.

Return type:

ndarray

Examples

>>> import numpy as np
>>> freqs = np.fft.fftfreq(10, 0.1)
>>> freqs
array([ 0.,  1.,  2.,  3.,  4., -5., -4., -3., -2., -1.])
>>> fftshift(freqs)
array([-5., -4., -3., -2., -1.,  0.,  1.,  2.,  3.,  4.])
pytcl.mathematical_functions.transforms.fourier.ifftshift(x, axes=None)[source]

Inverse of fftshift. Shift zero-frequency back to beginning.

Parameters:
  • x (array_like) – Input array.

  • axes (int or tuple of ints, optional) – Axes over which to shift. Default is all axes.

Returns:

y – The shifted array.

Return type:

ndarray

pytcl.mathematical_functions.transforms.fourier.frequency_axis(n, fs, shift=False)[source]

Generate frequency axis values for FFT output.

Parameters:
  • n (int) – Number of FFT points.

  • fs (float) – Sampling frequency in Hz.

  • shift (bool, optional) – If True, return frequencies in centered (fftshift) order. Default is False.

Returns:

freqs – Frequency values in Hz.

Return type:

ndarray

Examples

>>> frequency_axis(8, 100.0)
array([  0. ,  12.5,  25. ,  37.5, -50. , -37.5, -25. , -12.5])
>>> frequency_axis(8, 100.0, shift=True)
array([-50. , -37.5, -25. , -12.5,   0. ,  12.5,  25. ,  37.5])
pytcl.mathematical_functions.transforms.fourier.rfft_frequency_axis(n, fs)[source]

Generate frequency axis values for rfft output.

Parameters:
  • n (int) – Number of points in the original signal.

  • fs (float) – Sampling frequency in Hz.

Returns:

freqs – Non-negative frequency values in Hz.

Return type:

ndarray

Examples

>>> rfft_frequency_axis(8, 100.0)
array([ 0. , 12.5, 25. , 37.5, 50. ])
pytcl.mathematical_functions.transforms.fourier.power_spectrum(x, fs=1.0, window='hann', nperseg=None, noverlap=None, nfft=None, detrend='constant', scaling='density')[source]

Estimate power spectral density using Welch’s method.

Parameters:
  • x (array_like) – Time series data.

  • fs (float, optional) – Sampling frequency in Hz. Default is 1.0.

  • window (str, optional) – Window function to use. Default is ‘hann’.

  • nperseg (int, optional) – Length of each segment. Default is 256.

  • noverlap (int, optional) – Number of points to overlap between segments. Default is nperseg//2.

  • nfft (int, optional) – Length of the FFT used. Default is nperseg.

  • detrend (str or bool, optional) – Detrending method: ‘constant’, ‘linear’, or False. Default is ‘constant’.

  • scaling ({'density', 'spectrum'}, optional) – ‘density’ for power spectral density (V^2/Hz), ‘spectrum’ for power spectrum (V^2). Default is ‘density’.

Returns:

result – Named tuple with frequencies and power spectral density.

Return type:

PowerSpectrum

Examples

>>> import numpy as np
>>> fs = 1000  # 1 kHz
>>> t = np.arange(0, 1, 1/fs)
>>> x = np.sin(2 * np.pi * 100 * t)  # 100 Hz sine
>>> result = power_spectrum(x, fs=fs)
>>> peak_freq = result.frequencies[np.argmax(result.psd)]
>>> abs(peak_freq - 100) < 5  # Peak near 100 Hz
True

Notes

Uses Welch’s method which averages modified periodograms of overlapping segments to reduce variance of the spectral estimate.

pytcl.mathematical_functions.transforms.fourier.cross_spectrum(x, y, fs=1.0, window='hann', nperseg=None, noverlap=None, nfft=None, detrend='constant')[source]

Estimate cross-spectral density between two signals.

Parameters:
  • x (array_like) – First time series.

  • y (array_like) – Second time series.

  • fs (float, optional) – Sampling frequency in Hz. Default is 1.0.

  • window (str, optional) – Window function. Default is ‘hann’.

  • nperseg (int, optional) – Length of each segment. Default is 256.

  • noverlap (int, optional) – Number of points to overlap between segments. Default is nperseg//2.

  • nfft (int, optional) – Length of FFT. Default is nperseg.

  • detrend (str or bool, optional) – Detrending method. Default is ‘constant’.

Returns:

result – Named tuple with frequencies and cross-spectral density.

Return type:

CrossSpectrum

Examples

>>> import numpy as np
>>> fs = 1000
>>> t = np.arange(0, 1, 1/fs)
>>> x = np.sin(2 * np.pi * 50 * t)
>>> y = np.sin(2 * np.pi * 50 * t + np.pi/4)  # Same freq, phase shifted
>>> result = cross_spectrum(x, y, fs=fs)
>>> len(result.frequencies) > 0
True
pytcl.mathematical_functions.transforms.fourier.coherence(x, y, fs=1.0, window='hann', nperseg=None, noverlap=None, nfft=None, detrend='constant')[source]

Estimate magnitude-squared coherence between two signals.

The coherence measures the linear correlation between two signals as a function of frequency. Values range from 0 (no correlation) to 1 (perfect correlation).

Parameters:
  • x (array_like) – First time series.

  • y (array_like) – Second time series.

  • fs (float, optional) – Sampling frequency in Hz. Default is 1.0.

  • window (str, optional) – Window function. Default is ‘hann’.

  • nperseg (int, optional) – Length of each segment. Default is 256.

  • noverlap (int, optional) – Number of overlap points. Default is nperseg//2.

  • nfft (int, optional) – Length of FFT. Default is nperseg.

  • detrend (str or bool, optional) – Detrending method. Default is ‘constant’.

Returns:

result – Named tuple with frequencies and coherence values.

Return type:

CoherenceResult

Examples

>>> import numpy as np
>>> fs = 1000
>>> t = np.arange(0, 1, 1/fs)
>>> x = np.sin(2 * np.pi * 50 * t)
>>> y = 2 * x + 0.1 * np.random.randn(len(t))  # Correlated
>>> result = coherence(x, y, fs=fs)
>>> np.max(result.coherence) > 0.9  # High coherence at 50 Hz
True

Notes

Coherence is defined as:

C_xy = |S_xy|^2 / (S_xx * S_yy)

where S_xy is the cross-spectral density and S_xx, S_yy are the power spectral densities.

pytcl.mathematical_functions.transforms.fourier.periodogram(x, fs=1.0, window=None, nfft=None, detrend='constant', scaling='density')[source]

Estimate power spectral density using a periodogram.

Unlike Welch’s method, the periodogram uses the entire signal without segmentation and averaging. This gives higher frequency resolution but higher variance.

Parameters:
  • x (array_like) – Time series data.

  • fs (float, optional) – Sampling frequency in Hz. Default is 1.0.

  • window (str, optional) – Window function. Default is None (rectangular).

  • nfft (int, optional) – Length of FFT. Default is len(x).

  • detrend (str or bool, optional) – Detrending method. Default is ‘constant’.

  • scaling ({'density', 'spectrum'}, optional) – Scaling mode. Default is ‘density’.

Returns:

result – Named tuple with frequencies and power spectral density.

Return type:

PowerSpectrum

Examples

>>> import numpy as np
>>> fs = 1000
>>> t = np.arange(0, 1, 1/fs)
>>> x = np.sin(2 * np.pi * 100 * t)
>>> result = periodogram(x, fs=fs)
>>> len(result.frequencies) == len(result.psd)
True
pytcl.mathematical_functions.transforms.fourier.magnitude_spectrum(X, scale='linear')[source]

Compute magnitude spectrum from FFT coefficients.

Parameters:
  • X (array_like) – Complex FFT coefficients.

  • scale ({'linear', 'dB'}, optional) – Output scale. Default is ‘linear’.

Returns:

mag – Magnitude spectrum.

Return type:

ndarray

Examples

>>> import numpy as np
>>> X = np.array([4+0j, 0-2j, 0+0j, 0+2j])
>>> magnitude_spectrum(X)
array([4., 2., 0., 2.])
>>> magnitude_spectrum(X, scale='dB')
array([12.04..., 6.02..., -inf, 6.02...])
pytcl.mathematical_functions.transforms.fourier.phase_spectrum(X, unwrap=False)[source]

Compute phase spectrum from FFT coefficients.

Parameters:
  • X (array_like) – Complex FFT coefficients.

  • unwrap (bool, optional) – If True, unwrap the phase to remove discontinuities. Default is False.

Returns:

phase – Phase spectrum in radians.

Return type:

ndarray

Examples

>>> import numpy as np
>>> X = np.array([1+0j, 0+1j, -1+0j, 0-1j])
>>> phase = phase_spectrum(X)
>>> np.allclose(phase, [0, np.pi/2, np.pi, -np.pi/2])
True

Short-Time Fourier Transform

STFT, spectrogram, and time-frequency analysis.

Short-Time Fourier Transform (STFT) and spectrogram computation.

The STFT provides time-frequency analysis of signals by computing the Fourier transform of short, overlapping segments of the signal. This reveals how the frequency content of a signal changes over time.

Functions

  • stft: Compute Short-Time Fourier Transform

  • istft: Inverse Short-Time Fourier Transform

  • spectrogram: Compute power spectrogram

  • get_window: Generate window functions

References

class pytcl.mathematical_functions.transforms.stft.STFTResult(frequencies, times, Zxx)[source]

Bases: NamedTuple

Result of Short-Time Fourier Transform.

frequencies

Frequency values in Hz.

Type:

ndarray

times

Time values in seconds (segment centers).

Type:

ndarray

Zxx

STFT matrix (complex), shape (n_frequencies, n_times).

Type:

ndarray

frequencies: ndarray[tuple[Any, ...], dtype[floating]]

Alias for field number 0

times: ndarray[tuple[Any, ...], dtype[floating]]

Alias for field number 1

Zxx: ndarray[tuple[Any, ...], dtype[complexfloating]]

Alias for field number 2

class pytcl.mathematical_functions.transforms.stft.Spectrogram(frequencies, times, power)[source]

Bases: NamedTuple

Result of spectrogram computation.

frequencies

Frequency values in Hz.

Type:

ndarray

times

Time values in seconds.

Type:

ndarray

power

Power spectrogram (|STFT|^2).

Type:

ndarray

frequencies: ndarray[tuple[Any, ...], dtype[floating]]

Alias for field number 0

times: ndarray[tuple[Any, ...], dtype[floating]]

Alias for field number 1

power: ndarray[tuple[Any, ...], dtype[floating]]

Alias for field number 2

pytcl.mathematical_functions.transforms.stft.get_window(window, length, fftbins=True)[source]

Generate a window function.

Parameters:
  • window (str, tuple, or array_like) – Window type. Can be: - String: ‘hann’, ‘hamming’, ‘blackman’, ‘bartlett’, ‘kaiser’, etc. - Tuple: (window_name, parameter) for parameterized windows - Array: Custom window values

  • length (int) – Length of the window.

  • fftbins (bool, optional) – If True, create a periodic window for FFT use. Default is True.

Returns:

window – Window function values.

Return type:

ndarray

Examples

>>> w = get_window('hann', 256)
>>> len(w)
256
>>> w[0], w[-1]  # Near-zero at edges
(0.0, 0.0038...)
>>> w = get_window(('kaiser', 8.0), 256)  # Kaiser with beta=8
>>> len(w)
256

Notes

Common window functions: - ‘rectangular’: No tapering (unity) - ‘hann’: Good frequency resolution, low leakage - ‘hamming’: Similar to Hann, slightly different sidelobes - ‘blackman’: Very low sidelobes, wider main lobe - ‘kaiser’: Parameterized trade-off between resolution and leakage

pytcl.mathematical_functions.transforms.stft.window_bandwidth(window, length)[source]

Compute the equivalent noise bandwidth of a window.

The equivalent noise bandwidth (ENBW) is the width of an ideal rectangular filter that would pass the same amount of white noise power.

Parameters:
  • window (str or array_like) – Window function.

  • length (int) – Window length.

Returns:

enbw – Equivalent noise bandwidth in bins.

Return type:

float

Examples

>>> enbw = window_bandwidth('hann', 256)
>>> 1.4 < enbw < 1.6  # Hann window ENBW is about 1.5 bins
True
pytcl.mathematical_functions.transforms.stft.stft(x, fs=1.0, window='hann', nperseg=256, noverlap=None, nfft=None, detrend=False, return_onesided=True, boundary='zeros', padded=True)[source]

Compute the Short-Time Fourier Transform.

Parameters:
  • x (array_like) – Input time-domain signal.

  • fs (float, optional) – Sampling frequency in Hz. Default is 1.0.

  • window (str, tuple, or array_like, optional) – Window function. Default is ‘hann’.

  • nperseg (int, optional) – Length of each segment. Default is 256.

  • noverlap (int, optional) – Number of points to overlap between segments. Default is nperseg // 2.

  • nfft (int, optional) – Length of the FFT used. Default is nperseg.

  • detrend (str or bool, optional) – Detrending: ‘constant’, ‘linear’, or False. Default is False.

  • return_onesided (bool, optional) – If True, return only non-negative frequencies for real input. Default is True.

  • boundary (str or None, optional) – Boundary extension: ‘zeros’, ‘even’, ‘odd’, or None. Default is ‘zeros’.

  • padded (bool, optional) – Whether to pad the signal. Default is True.

Returns:

result – Named tuple with frequencies, times, and STFT matrix.

Return type:

STFTResult

Examples

>>> import numpy as np
>>> fs = 1000
>>> t = np.arange(0, 1, 1/fs)
>>> x = np.sin(2 * np.pi * 50 * t)  # 50 Hz sine
>>> result = stft(x, fs=fs, nperseg=128)
>>> result.Zxx.shape  # (n_freq, n_time)
(65, 16)

Notes

The STFT provides a time-frequency representation where: - Time resolution = nperseg / fs - Frequency resolution = fs / nfft

There is a trade-off between time and frequency resolution (uncertainty principle): better time resolution requires shorter segments, which reduces frequency resolution, and vice versa.

pytcl.mathematical_functions.transforms.stft.istft(Zxx, fs=1.0, window='hann', nperseg=None, noverlap=None, nfft=None, input_onesided=True, boundary=True)[source]

Compute the inverse Short-Time Fourier Transform.

Parameters:
  • Zxx (array_like) – STFT matrix from stft function.

  • fs (float, optional) – Sampling frequency in Hz. Default is 1.0.

  • window (str, tuple, or array_like, optional) – Window function (should match the one used in stft). Default is ‘hann’.

  • nperseg (int, optional) – Length of each segment. Default is inferred from Zxx.

  • noverlap (int, optional) – Overlap between segments. Default is nperseg // 2.

  • nfft (int, optional) – FFT length. Default is inferred from Zxx.

  • input_onesided (bool, optional) – If True, interpret Zxx as one-sided. Default is True.

  • boundary (bool, optional) – Whether boundary extension was used. Default is True.

Returns:

  • times (ndarray) – Time values in seconds.

  • x (ndarray) – Reconstructed time-domain signal.

Return type:

tuple[ndarray[tuple[Any, …], dtype[floating]], ndarray[tuple[Any, …], dtype[floating]]]

Examples

>>> import numpy as np
>>> fs = 1000
>>> t = np.arange(0, 1, 1/fs)
>>> x = np.sin(2 * np.pi * 50 * t)
>>> result = stft(x, fs=fs, nperseg=128)
>>> t_rec, x_rec = istft(result.Zxx, fs=fs, nperseg=128)
>>> np.allclose(x, x_rec[:len(x)], atol=1e-10)
True

Notes

The inverse STFT uses the overlap-add method. For perfect reconstruction, the window function and overlap must satisfy the constant overlap-add (COLA) constraint.

pytcl.mathematical_functions.transforms.stft.spectrogram(x, fs=1.0, window='hann', nperseg=256, noverlap=None, nfft=None, detrend='constant', scaling='density', mode='psd')[source]

Compute a spectrogram (power spectral density over time).

Parameters:
  • x (array_like) – Input time-domain signal.

  • fs (float, optional) – Sampling frequency in Hz. Default is 1.0.

  • window (str, tuple, or array_like, optional) – Window function. Default is ‘hann’.

  • nperseg (int, optional) – Length of each segment. Default is 256.

  • noverlap (int, optional) – Overlap between segments. Default is nperseg // 8.

  • nfft (int, optional) – FFT length. Default is nperseg.

  • detrend (str or bool, optional) – Detrending: ‘constant’, ‘linear’, or False. Default is ‘constant’.

  • scaling ({'density', 'spectrum'}, optional) – ‘density’ for PSD (V^2/Hz), ‘spectrum’ for power (V^2). Default is ‘density’.

  • mode ({'psd', 'complex', 'magnitude', 'angle', 'phase'}, optional) – Return type. Default is ‘psd’.

Returns:

result – Named tuple with frequencies, times, and power spectrogram.

Return type:

Spectrogram

Examples

>>> import numpy as np
>>> fs = 1000
>>> t = np.arange(0, 2, 1/fs)
>>> # Chirp from 50 to 200 Hz
>>> x = np.sin(2 * np.pi * (50 + 75*t) * t)
>>> result = spectrogram(x, fs=fs, nperseg=128)
>>> result.power.shape  # (n_freq, n_time)
(65, 31)

Notes

The spectrogram is computed by taking the magnitude squared of the STFT. It shows how the spectral content of the signal evolves over time.

pytcl.mathematical_functions.transforms.stft.reassigned_spectrogram(x, fs=1.0, window='hann', nperseg=256, noverlap=None, nfft=None)[source]

Compute reassigned spectrogram for improved time-frequency resolution.

The reassigned spectrogram sharpens the time-frequency representation by moving energy to the center of gravity of each analysis frame.

Parameters:
  • x (array_like) – Input signal.

  • fs (float, optional) – Sampling frequency in Hz. Default is 1.0.

  • window (str, tuple, or array_like, optional) – Window function. Default is ‘hann’.

  • nperseg (int, optional) – Segment length. Default is 256.

  • noverlap (int, optional) – Overlap. Default is nperseg - 1.

  • nfft (int, optional) – FFT length. Default is nperseg.

Returns:

  • frequencies (ndarray) – Frequency values in Hz.

  • times (ndarray) – Time values in seconds.

  • Sxx (ndarray) – Reassigned spectrogram power.

Return type:

tuple[ndarray[tuple[Any, …], dtype[floating]], ndarray[tuple[Any, …], dtype[floating]], ndarray[tuple[Any, …], dtype[floating]]]

Notes

The reassignment method improves readability of the spectrogram by concentrating the spectral energy, making it easier to track frequency components. However, it requires more computation than a standard spectrogram.

pytcl.mathematical_functions.transforms.stft.mel_spectrogram(x, fs, n_mels=128, fmin=0.0, fmax=None, window='hann', nperseg=2048, noverlap=None)[source]

Compute mel-scaled spectrogram.

The mel scale is a perceptual scale of pitches that approximates human auditory perception. Mel spectrograms are widely used in audio analysis and speech recognition.

Parameters:
  • x (array_like) – Input audio signal.

  • fs (float) – Sampling frequency in Hz.

  • n_mels (int, optional) – Number of mel bands. Default is 128.

  • fmin (float, optional) – Minimum frequency in Hz. Default is 0.0.

  • fmax (float, optional) – Maximum frequency in Hz. Default is fs/2.

  • window (str, optional) – Window function. Default is ‘hann’.

  • nperseg (int, optional) – Segment length. Default is 2048.

  • noverlap (int, optional) – Overlap. Default is nperseg // 4.

Returns:

  • mel_freqs (ndarray) – Mel frequency band centers in Hz.

  • times (ndarray) – Time values in seconds.

  • mel_spec (ndarray) – Mel spectrogram (n_mels, n_times).

Return type:

tuple[ndarray[tuple[Any, …], dtype[floating]], ndarray[tuple[Any, …], dtype[floating]], ndarray[tuple[Any, …], dtype[floating]]]

Examples

>>> import numpy as np
>>> fs = 22050
>>> x = np.random.randn(fs)  # 1 second of noise
>>> mel_freqs, times, mel_spec = mel_spectrogram(x, fs, n_mels=64)
>>> mel_spec.shape[0]
64

Wavelet Transforms

Continuous and discrete wavelet transforms.

Wavelet transform utilities.

This module provides continuous and discrete wavelet transform functions, wavelet generation, and time-frequency analysis tools.

Functions

  • cwt: Continuous Wavelet Transform

  • dwt: Discrete Wavelet Transform (requires pywavelets)

  • idwt: Inverse Discrete Wavelet Transform

  • morlet_wavelet: Generate Morlet wavelet

  • ricker_wavelet: Generate Ricker (Mexican hat) wavelet

  • scales_to_frequencies: Convert wavelet scales to frequencies

References

class pytcl.mathematical_functions.transforms.wavelets.CWTResult(coefficients, scales, frequencies)[source]

Bases: NamedTuple

Result of Continuous Wavelet Transform.

coefficients

CWT coefficient matrix (complex), shape (n_scales, n_samples).

Type:

ndarray

scales

Scale values used.

Type:

ndarray

frequencies

Approximate frequencies corresponding to each scale.

Type:

ndarray

coefficients: ndarray[tuple[Any, ...], dtype[complexfloating]]

Alias for field number 0

scales: ndarray[tuple[Any, ...], dtype[floating]]

Alias for field number 1

frequencies: ndarray[tuple[Any, ...], dtype[floating]]

Alias for field number 2

class pytcl.mathematical_functions.transforms.wavelets.DWTResult(cA, cD, levels, wavelet)[source]

Bases: NamedTuple

Result of Discrete Wavelet Transform.

cA

Approximation coefficients at the coarsest level.

Type:

ndarray

cD

Detail coefficients at each level (finest to coarsest).

Type:

list of ndarray

levels

Number of decomposition levels.

Type:

int

wavelet

Wavelet name used.

Type:

str

cA: ndarray[tuple[Any, ...], dtype[floating]]

Alias for field number 0

cD: List[ndarray[tuple[Any, ...], dtype[floating]]]

Alias for field number 1

levels: int

Alias for field number 2

wavelet: str

Alias for field number 3

pytcl.mathematical_functions.transforms.wavelets.morlet_wavelet(M, w=5.0, s=1.0, complete=True)[source]

Generate a Morlet wavelet.

The Morlet wavelet is a sinusoid windowed by a Gaussian, commonly used for time-frequency analysis.

Parameters:
  • M (int) – Length of the wavelet.

  • w (float, optional) – Omega0, the central frequency parameter. Default is 5.0.

  • s (float, optional) – Scaling factor. Default is 1.0.

  • complete (bool, optional) – If True, use the complete Morlet wavelet with correction term. Default is True.

Returns:

wavelet – Complex Morlet wavelet.

Return type:

ndarray

Examples

>>> wav = morlet_wavelet(128, w=5.0)
>>> len(wav)
128
>>> np.abs(wav[len(wav)//2]) > 0  # Peak in center
True

Notes

The Morlet wavelet is defined as:

psi(t) = exp(i*w*t) * exp(-t^2/2)

With the complete correction:

psi(t) = (exp(i*w*t) - exp(-w^2/2)) * exp(-t^2/2)

pytcl.mathematical_functions.transforms.wavelets.ricker_wavelet(points, a=1.0)[source]

Generate a Ricker wavelet (Mexican hat wavelet).

The Ricker wavelet is the negative normalized second derivative of a Gaussian function. It is real-valued and commonly used in seismology.

Parameters:
  • points (int) – Number of points in the wavelet.

  • a (float, optional) – Width parameter. Default is 1.0.

Returns:

wavelet – Ricker wavelet.

Return type:

ndarray

Examples

>>> wav = ricker_wavelet(128, a=4.0)
>>> len(wav)
128
>>> wav[len(wav)//2]  # Peak at center
1.0

Notes

The Ricker wavelet is defined as:

psi(t) = (1 - 2*(pi*f*t)^2) * exp(-(pi*f*t)^2)

where f = 1/(sqrt(2)*pi*a) is the central frequency.

pytcl.mathematical_functions.transforms.wavelets.gaussian_wavelet(M, order=1, sigma=1.0)[source]

Generate a Gaussian derivative wavelet.

Parameters:
  • M (int) – Length of the wavelet.

  • order (int, optional) – Order of the derivative. Default is 1.

  • sigma (float, optional) – Standard deviation of the Gaussian. Default is 1.0.

Returns:

wavelet – Gaussian derivative wavelet.

Return type:

ndarray

Examples

>>> wav = gaussian_wavelet(128, order=1)
>>> len(wav)
128
pytcl.mathematical_functions.transforms.wavelets.cwt(signal, scales, wavelet='morlet', fs=1.0, method='fft')[source]

Compute the Continuous Wavelet Transform.

Parameters:
  • signal (array_like) – Input signal.

  • scales (array_like) – Scale values to use.

  • wavelet (str or callable, optional) – Wavelet to use. Options: ‘morlet’, ‘ricker’, ‘gaussian1’, ‘gaussian2’, or a callable. Default is ‘morlet’.

  • fs (float, optional) – Sampling frequency in Hz. Default is 1.0.

  • method ({'fft', 'conv'}, optional) – Computation method. ‘fft’ is faster for long signals. Default is ‘fft’.

Returns:

result – Named tuple with coefficients, scales, and frequencies.

Return type:

CWTResult

Examples

>>> import numpy as np
>>> fs = 1000
>>> t = np.arange(0, 1, 1/fs)
>>> x = np.sin(2 * np.pi * 50 * t)
>>> scales = np.arange(1, 128)
>>> result = cwt(x, scales, wavelet='morlet', fs=fs)
>>> result.coefficients.shape
(127, 1000)

Notes

The CWT is computed as:

W(a, b) = integral s(t) * (1/sqrt(a)) * psi*((t-b)/a) dt

where a is the scale, b is the translation, and psi is the wavelet.

pytcl.mathematical_functions.transforms.wavelets.scales_to_frequencies(scales, wavelet='morlet', fs=1.0)[source]

Convert CWT scales to approximate frequencies.

Parameters:
  • scales (array_like) – Scale values.

  • wavelet (str, optional) – Wavelet name. Default is ‘morlet’.

  • fs (float, optional) – Sampling frequency in Hz. Default is 1.0.

Returns:

frequencies – Approximate frequencies in Hz.

Return type:

ndarray

Examples

>>> scales = np.array([1, 2, 4, 8, 16])
>>> freqs = scales_to_frequencies(scales, wavelet='morlet', fs=1000)
>>> len(freqs)
5
>>> freqs[0] > freqs[-1]  # Smaller scale = higher frequency
True
pytcl.mathematical_functions.transforms.wavelets.frequencies_to_scales(frequencies, wavelet='morlet', fs=1.0)[source]

Convert desired frequencies to CWT scales.

Parameters:
  • frequencies (array_like) – Desired frequencies in Hz.

  • wavelet (str, optional) – Wavelet name. Default is ‘morlet’.

  • fs (float, optional) – Sampling frequency in Hz. Default is 1.0.

Returns:

scales – Scale values.

Return type:

ndarray

pytcl.mathematical_functions.transforms.wavelets.dwt(signal, wavelet='db4', level=None, mode='symmetric')[source]

Compute the Discrete Wavelet Transform.

The DWT decomposes a signal into approximation and detail coefficients at multiple resolution levels.

Parameters:
  • signal (array_like) – Input signal.

  • wavelet (str, optional) – Wavelet to use (e.g., ‘db4’, ‘haar’, ‘sym8’, ‘coif3’). Default is ‘db4’.

  • level (int, optional) – Decomposition level. Default is max level for signal length.

  • mode (str, optional) – Signal extension mode. Default is ‘symmetric’.

Returns:

result – Named tuple with approximation and detail coefficients.

Return type:

DWTResult

Examples

>>> import numpy as np
>>> x = np.random.randn(256)
>>> result = dwt(x, wavelet='db4', level=4)
>>> len(result.cD)  # 4 levels of detail
4

Notes

Requires the pywavelets package. Install with: pip install pywavelets

Common wavelet families: - ‘haar’: Simplest wavelet - ‘dbN’: Daubechies wavelets (N=1..38) - ‘symN’: Symlets (N=2..20) - ‘coifN’: Coiflets (N=1..17) - ‘biorN.M’: Biorthogonal wavelets

pytcl.mathematical_functions.transforms.wavelets.idwt(coeffs, mode='symmetric')[source]

Compute the inverse Discrete Wavelet Transform.

Parameters:
  • coeffs (DWTResult) – DWT coefficients from dwt function.

  • mode (str, optional) – Signal extension mode. Default is ‘symmetric’.

Returns:

signal – Reconstructed signal.

Return type:

ndarray

Examples

>>> import numpy as np
>>> x = np.random.randn(256)
>>> result = dwt(x, wavelet='db4', level=4)
>>> x_rec = idwt(result)
>>> np.allclose(x, x_rec)
True
pytcl.mathematical_functions.transforms.wavelets.dwt_single_level(signal, wavelet='db4', mode='symmetric')[source]

Compute single-level DWT decomposition.

Parameters:
  • signal (array_like) – Input signal.

  • wavelet (str, optional) – Wavelet name. Default is ‘db4’.

  • mode (str, optional) – Signal extension mode. Default is ‘symmetric’.

Returns:

  • cA (ndarray) – Approximation coefficients.

  • cD (ndarray) – Detail coefficients.

Return type:

tuple[ndarray[tuple[Any, …], dtype[floating]], ndarray[tuple[Any, …], dtype[floating]]]

pytcl.mathematical_functions.transforms.wavelets.idwt_single_level(cA, cD, wavelet='db4', mode='symmetric')[source]

Compute single-level inverse DWT.

Parameters:
  • cA (array_like) – Approximation coefficients.

  • cD (array_like) – Detail coefficients.

  • wavelet (str, optional) – Wavelet name. Default is ‘db4’.

  • mode (str, optional) – Signal extension mode. Default is ‘symmetric’.

Returns:

signal – Reconstructed signal.

Return type:

ndarray

pytcl.mathematical_functions.transforms.wavelets.wpt(signal, wavelet='db4', level=None, mode='symmetric')[source]

Compute the Wavelet Packet Transform.

The WPT provides a more flexible time-frequency decomposition than DWT by also decomposing the detail coefficients.

Parameters:
  • signal (array_like) – Input signal.

  • wavelet (str, optional) – Wavelet name. Default is ‘db4’.

  • level (int, optional) – Decomposition level. Default is 3.

  • mode (str, optional) – Signal extension mode. Default is ‘symmetric’.

Returns:

nodes – Dictionary mapping node paths to coefficients. Path format: ‘a’ for approximation, ‘d’ for detail. Example: ‘aad’ means approx->approx->detail.

Return type:

dict

Examples

>>> import numpy as np
>>> x = np.random.randn(256)
>>> nodes = wpt(x, wavelet='db4', level=2)
>>> 'aa' in nodes  # Level 2 approximation
True
>>> 'dd' in nodes  # Level 2 detail of detail
True
pytcl.mathematical_functions.transforms.wavelets.available_wavelets()[source]

List available wavelet families for DWT.

Returns:

wavelets – Available wavelet names.

Return type:

list of str

pytcl.mathematical_functions.transforms.wavelets.wavelet_info(wavelet)[source]

Get information about a wavelet.

Parameters:

wavelet (str) – Wavelet name.

Returns:

info – Dictionary with wavelet properties.

Return type:

dict

pytcl.mathematical_functions.transforms.wavelets.threshold_coefficients(coeffs, threshold='soft', value=None)[source]

Threshold DWT coefficients for denoising.

Parameters:
  • coeffs (DWTResult) – DWT coefficients.

  • threshold (float or {'soft', 'hard'}, optional) – Threshold type or value. Default is ‘soft’.

  • value (float, optional) – Threshold value. If None, uses universal threshold.

Returns:

result – Thresholded coefficients.

Return type:

DWTResult

Examples

>>> import numpy as np
>>> from pytcl.mathematical_functions.transforms import dwt, threshold_coefficients, idwt
>>> # Create noisy signal
>>> t = np.linspace(0, 1, 256)
>>> signal = np.sin(2 * np.pi * 5 * t)
>>> noise = 0.5 * np.random.randn(256)
>>> noisy_signal = signal + noise
>>> # Denoise using wavelet thresholding
>>> coeffs = dwt(noisy_signal, wavelet='db4', level=3)
>>> # Apply soft threshold (default automatic threshold value)
>>> coeffs_denoised = threshold_coefficients(coeffs, threshold='soft')
>>> # Reconstruct signal from thresholded coefficients
>>> signal_denoised = idwt(coeffs_denoised)
>>> len(signal_denoised) == len(noisy_signal)
True

Notes

When value is None, the universal threshold is computed as:

sigma * sqrt(2 * log(n))

where sigma is estimated from the finest detail coefficients and n is the total number of coefficients.