xai4tsc.utils.fourier_transforms

Domain transforms (Fourier / short-time Fourier) used by frequency-domain XAI.

A DomainTransform maps a time-domain signal to a target domain (frequency or time-frequency) and back. Explainers use the forward direction to express relevance in the target domain; perturbation metrics use the inverse to return a perturbed representation to the time domain before re-querying the model. Transform objects are stateful (they may cache expensive setup) and are meant to be built once and shared via xai4tsc.Explanation.transform.

Mixing Fourier implementations from different libraries (e.g. torch and scipy) has historically produced inconsistent results, so this module standardises on torch.fft / torch.stft.

Classes

DomainTransform

Abstract base for invertible time-domain ↔ target-domain transforms.

FourierTransform

Discrete Fourier transform and its inverse.

RFFTransform

One-sided real Fourier transform and its inverse.

STFTransform

Short-time Fourier transform and its inverse.

Functions

get_transform(→ DomainTransform | None)

Build a DomainTransform from a config dict.

resolve_transform(→ DomainTransform | None)

Normalise a transform argument to a DomainTransform or None.

Module Contents

class xai4tsc.utils.fourier_transforms.DomainTransform

Bases: abc.ABC

Abstract base for invertible time-domain ↔ target-domain transforms.

Subclasses implement forward() (to the target domain) and inverse() (back to the time domain). Instances are stateful and may cache setup between calls; build once and reuse.

abstractmethod forward(x: torch.Tensor, **kwargs: object) torch.Tensor

Transform x from the time domain to the target domain.

abstractmethod inverse(x: torch.Tensor, **kwargs: object) torch.Tensor

Transform x from the target domain back to the time domain.

class xai4tsc.utils.fourier_transforms.FourierTransform(n: int | None = None)

Bases: DomainTransform

Discrete Fourier transform and its inverse.

Wraps torch.fft.fft() / torch.fft.ifft() (full complex FFT).

Parameters:

n (int, optional) – Signal length passed to the underlying FFT (None uses the input length).

n = None
forward(x: torch.Tensor, **kwargs: object) torch.Tensor

Apply the Fourier transform.

Parameters:
  • x (torch.Tensor) – Input of shape (B, ..., T) where B is the batch dimension. Higher-dimensional inputs are flattened so every series is transformed independently.

  • **kwargs (object) – Extra keyword arguments forwarded to torch.fft.fft().

Returns:

Complex frequencies of shape (B, -1, n_freq).

Return type:

torch.Tensor

inverse(x: torch.Tensor, **kwargs: object) torch.Tensor

Apply the inverse Fourier transform.

Parameters:
  • x (torch.Tensor) – Frequencies of shape (B, ..., n_freq). Higher-dimensional inputs are flattened so every spectrum is transformed independently.

  • **kwargs (object) – Extra keyword arguments forwarded to torch.fft.ifft().

Returns:

Reconstructed signals of shape (B, -1, T).

Return type:

torch.Tensor

class xai4tsc.utils.fourier_transforms.RFFTransform(n: int | None = None)

Bases: DomainTransform

One-sided real Fourier transform and its inverse.

Wraps torch.fft.rfft() / torch.fft.irfft(). For a length-T real signal the forward yields T // 2 + 1 complex bins. irfft needs the original length to invert exactly (it otherwise assumes an even length), so this transform is stateful: forward() records the signal length and inverse() reuses it (overridable via the length keyword). Used by FFT-mode FreqRISE so its explanation carries a usable transform.

Parameters:

n (int, optional) – Signal length for the inverse. If None it is captured on the first forward() call.

n = None
forward(x: torch.Tensor, **kwargs: object) torch.Tensor

Apply the one-sided real Fourier transform.

Parameters:
  • x (torch.Tensor) – Input of shape (B, ..., T). Records T as the inverse length.

  • **kwargs (object) – Extra keyword arguments forwarded to torch.fft.rfft().

Returns:

Complex coefficients of shape (B, -1, T // 2 + 1).

Return type:

torch.Tensor

inverse(x: torch.Tensor, length: int | None = None, **kwargs: object) torch.Tensor

Apply the inverse one-sided real Fourier transform.

Parameters:
  • x (torch.Tensor) – One-sided coefficients of shape (B, ..., T // 2 + 1).

  • length (int, optional) – Output signal length. Defaults to the length recorded by forward() (self.n).

  • **kwargs (object) – Extra keyword arguments forwarded to torch.fft.irfft().

Returns:

Real signals of shape (B, -1, length).

Return type:

torch.Tensor

class xai4tsc.utils.fourier_transforms.STFTransform(n_fft: int, win_length: int, hop_length: int | None = None, window: str = 'hann')

Bases: DomainTransform

Short-time Fourier transform and its inverse.

Wraps torch.stft() / torch.istft().

Parameters:
  • n_fft (int) – Size of the Fourier transform.

  • win_length (int) – Size of the window frame and STFT filter.

  • hop_length (int, optional) – Distance between neighbouring sliding window frames. Defaults to floor(win_length / 2).

  • window (str) – Window function name (see _get_window()). Default "hann".

n_fft
win_length
hop_length
window
signal_length: int | None = None
forward(x: torch.Tensor, return_complex: bool = True, **kwargs: object) torch.Tensor

Apply the short-time Fourier transform.

Parameters:
  • x (torch.Tensor) – Input of shape (B, ..., T) where B is the batch dimension. Higher-dimensional inputs are flattened so every series is transformed independently.

  • return_complex (bool) – Whether to return a complex spectrogram. Default True.

  • **kwargs (object) – Extra keyword arguments forwarded to torch.stft().

Returns:

Spectrograms of shape (B, -1, n_freq, n_time).

Return type:

torch.Tensor

inverse(x: torch.Tensor, length: int | None = None, **kwargs: object) torch.Tensor

Apply the inverse short-time Fourier transform.

Parameters:
  • x (torch.Tensor) – Spectrograms of shape (B, ..., n_freq, n_time). Higher-dimensional inputs are flattened so every spectrogram is transformed independently.

  • length (int, optional) – Output signal length. Defaults to the length recorded by forward() (self.signal_length); istft otherwise returns a frame-derived length that may not equal the original.

  • **kwargs (object) – Extra keyword arguments forwarded to torch.istft().

Returns:

Reconstructed signals of shape (B, -1, T).

Return type:

torch.Tensor

xai4tsc.utils.fourier_transforms.get_transform(transform_config: dict | None) DomainTransform | None

Build a DomainTransform from a config dict.

Parameters:

transform_config (dict or None) – Mapping with a "name" key ("fft" or "stft") and a "params" mapping forwarded to the transform constructor. None yields None (time-domain, no transform).

Returns:

The constructed transform, or None when transform_config is None.

Return type:

DomainTransform or None

Raises:

ValueError – If transform_config["name"] is not a supported transform name.

xai4tsc.utils.fourier_transforms.resolve_transform(transform: DomainTransform | dict | None) DomainTransform | None

Normalise a transform argument to a DomainTransform or None.

Accepts an already-built transform (returned as-is), a config dict (built via get_transform()), or None. Lets explainer constructors take either a Python object (package use) or a YAML config mapping (runner use).

Parameters:

transform (DomainTransform or dict or None) – The transform, a get_transform config dict, or None.

Returns:

The resolved transform.

Return type:

DomainTransform or None

Raises:

TypeError – If transform is not a DomainTransform, dict, or None.