scipy.fft — Fast Fourier Transforms¶
The scipy_fft module wraps scipy.fft as Clausal predicates. It covers 1-D, 2-D, and N-D forward and inverse DFTs, real-input transforms, discrete cosine transforms, and frequency/shift utilities.
Import¶
Or via the canonical py.* path:
Tier¶
All predicates are Tier 1 — pure functions: NumPy array in, NumPy array (or scalar array) directly in RESULT. No result dicts, no ResultGet needed.
Bidirectionality¶
The core transform predicates are bidirectional relations: they dispatch on argument groundness, running forward or backward depending on which arguments are bound.
| Bidirectional predicate | Forward | Backward |
|---|---|---|
FFTransform(X, Y) |
fft(x) |
ifft(y) |
FFTransform2D(X, Y) |
fft2(x) |
ifft2(y) |
FFTransformND(X, Y) |
fftn(x) |
ifftn(y) |
RealFFT(X, Y) |
rfft(x) |
irfft(y) |
DiscreteCosineTransform(X, Y) |
dct(x) |
idct(y) |
DiscreteSineTransform(X, Y) |
dst(x) |
idst(y) |
FFTShift(X, Y) |
fftshift(x) |
ifftshift(y) |
# skip
FFTransform(++(np.array([1,0,0,0])), RESULT),
% RESULT is unified with the complex spectrum array
Naming conventions¶
Abbreviations that are the universal name are kept as-is; others are spelled out:
| scipy function | Clausal predicate |
|---|---|
fft |
FFTransform forward |
ifft |
FFTransform backward |
fft2 |
FFTransform2D forward |
ifft2 |
FFTransform2D backward |
fftn |
FFTransformND forward |
ifftn |
FFTransformND backward |
rfft |
RealFFT forward |
irfft |
RealFFT backward |
dct |
DiscreteCosineTransform forward |
idct |
DiscreteCosineTransform backward |
dst |
DiscreteSineTransform forward |
idst |
DiscreteSineTransform backward |
fftfreq |
FFTFrequencies |
rfftfreq |
RealFFTFrequencies |
fftshift |
FFTShift forward |
ifftshift |
FFTShift backward |
Why FFTransform instead of FFT?
In .clausal source, any identifier whose alphabetic characters are all uppercase is parsed as a logic variable, not a predicate name. FFT, FFT2D, and FFTND are entirely uppercase, so they would be treated as unbound variables rather than callable predicates. Spelling them as FFTransform, FFTransform2D, and FFTransformND introduces lowercase letters, making them unambiguously predicate names.
All other predicates in this module (RealFFT, FFTShift, FFTFrequencies, etc.) already contain lowercase letters from their prefixes and suffixes, so they work without this adjustment.
Predicate catalogue¶
1-D transforms¶
# skip
FFTransform(X, Y) # bidirectional
X ground, Y unbound → Y = fft(x) # forward DFT
Y ground, X unbound → X = ifft(y) # backward (inverse DFT)
Both ground → consistency check: succeeds iff fft(x) ≈ y
X: real or complex 1-D array
Y: complex array of length len(X)
FFTransform(X, N, Y) # bidirectional; N always ground
N: output length (zero-pads or truncates).
Example — frequency analysis of a sine wave:
-import_from(scipy_fft, [FFTransform, FFTFrequencies])
FrequencySpectrum(SIGNAL, FREQS, SPECTRUM) <- (
FFTransform(SIGNAL, SPECTRUM),
LEN is ++(len(SIGNAL)),
FFTFrequencies(LEN, FREQS)
)
2-D transforms¶
# skip
FFTransform2D(X, Y) # bidirectional
X ground, Y unbound → Y = fft2(x) # 2-D forward DFT over last two axes
Y ground, X unbound → X = ifft2(y) # backward (2-D inverse DFT)
Both ground → consistency check: succeeds iff fft2(x) ≈ y
X: 2-D real or complex array
Y: complex array of the same shape
FFTransform2D(X, S, Y) # bidirectional; S always ground
S: output shape as (rows, cols); zero-pads or truncates X to this shape.
Example — round-trip:
-import_from(scipy_fft, [FFTransform2D])
RoundTrip2D(IMAGE, RECOVERED) <- (
FFTransform2D(IMAGE, SPECTRUM),
FFTransform2D(RECOVERED, SPECTRUM)
)
N-D transforms¶
# skip
FFTransformND(X, Y) # bidirectional
X ground, Y unbound → Y = fftn(x) # N-D forward DFT over all axes
Y ground, X unbound → X = ifftn(y) # backward (N-D inverse DFT)
Both ground → consistency check: succeeds iff fftn(x) ≈ y
Y: complex array of the same shape as X
FFTransformND(X, S, Y) # bidirectional; S always ground
S: list of output lengths, one per axis.
Real-input transforms¶
RealFFT exploits conjugate symmetry to halve storage for real signals. The output of RealFFT has length N//2 + 1.
# skip
RealFFT(X, Y) # bidirectional
X ground, Y unbound → Y = rfft(x) forward: complex half-spectrum of length N//2 + 1
Y ground, X unbound → X = irfft(y) backward: real array of length 2*(len(Y)-1)
Both ground → consistency check: succeeds iff rfft(x) ≈ y
Note: assumes even-length original signal when going backward without N.
RealFFT(X, N, Y) # bidirectional; N always ground
N: explicit length for unambiguous round-trips of odd-length originals.
Example — filter a 1-D signal in the frequency domain:
-import_from(scipy_fft, [RealFFT])
LowPassFilter(SIGNAL, CUTOFF_BIN, FILTERED) <- (
RealFFT(SIGNAL, SPECTRUM),
ZEROED is ++(
[SPECTRUM[i] if i < int(CUTOFF_BIN) else 0.0
for i in range(len(SPECTRUM))]),
RealFFT(FILTERED, ++ZEROED)
)
Cosine and sine transforms¶
# skip
DiscreteCosineTransform(X, Y) # bidirectional
X ground, Y unbound → Y = dct(x) (type-2 default)
Y ground, X unbound → X = idct(y)
Both ground → consistency check: succeeds iff dct(x) ≈ y
DiscreteCosineTransform(X, TYPE, Y) # bidirectional; TYPE always ground
TYPE: integer 1–4 selecting the DCT variant.
DiscreteSineTransform(X, Y) # bidirectional
X ground, Y unbound → Y = dst(x) (type-2 default)
Y ground, X unbound → X = idst(y)
Both ground → consistency check: succeeds iff dst(x) ≈ y
DiscreteSineTransform(X, TYPE, Y) # bidirectional; TYPE always ground
DCT types:
| TYPE | Description |
|---|---|
| 1 | DCT-I: symmetric boundary conditions |
| 2 | DCT-II: default; used in JPEG compression |
| 3 | DCT-III: inverse of DCT-II (up to a scale) |
| 4 | DCT-IV: symmetric half-sample |
Utility¶
# skip
FFTFrequencies(N, RESULT)
DFT sample frequencies for a length-N transform with unit sample spacing.
RESULT: real array of length N
Layout: [0, 1/N, 2/N, ..., -k/N, ..., -1/N]
where k = N//2
FFTFrequencies(N, D, RESULT)
D: sample spacing in seconds (reciprocal of sample rate).
Frequencies are in cycles per unit time (Hz if D is in seconds).
RealFFTFrequencies(N, RESULT)
Sample frequencies for a length-N real FFT output.
RESULT: real array of length N//2 + 1 (all non-negative)
RealFFTFrequencies(N, D, RESULT)
D: sample spacing.
FFTShift(X, Y) # bidirectional
X ground, Y unbound → Y = fftshift(x) (DC to centre)
Y ground, X unbound → X = ifftshift(y) (DC back to index 0)
Both ground → consistency check: succeeds iff fftshift(x) ≈ y
Example — plot-ready spectrum:
-import_from(scipy_fft, [FFTransform, FFTFrequencies, FFTShift])
CentredSpectrum(SIGNAL, FREQS_CENTRED, SPECTRUM_CENTRED) <- (
LEN is ++(len(SIGNAL)),
FFTransform(SIGNAL, SPECTRUM),
FFTFrequencies(LEN, FREQS),
FFTShift(SPECTRUM, SPECTRUM_CENTRED),
FFTShift(FREQS, FREQS_CENTRED)
)
Complete examples¶
Round-trip: 1-D signal¶
# skip
-import_from(scipy_fft, [FFTransform])
TestRoundTrip(SIGNAL) <- (
FFTransform(SIGNAL, SPECTRUM),
FFTransform(RECOVERED, SPECTRUM),
% check first element recovered correctly
ERR is ++(abs(float(RECOVERED[0].real) - float(SIGNAL[0]))),
ERR < 1e-10
)
Convolution via FFT¶
# skip
-import_from(scipy_fft, [FFTransform])
% Linear convolution of two equal-length signals (circular; pad as needed)
FFTConvolve(A, B, RESULT) <- (
FFTransform(A, FA),
FFTransform(B, FB),
PRODUCT is ++(FA * FB),
FFTransform(RESULT, ++PRODUCT)
)
Image spectrum (2-D)¶
-import_from(scipy_fft, [FFTransform2D, FFTShift])
ImageSpectrum(IMAGE, CENTRED_SPECTRUM) <- (
FFTransform2D(IMAGE, SPECTRUM),
FFTShift(SPECTRUM, CENTRED_SPECTRUM)
)
Notes¶
- Array inputs: pass Python lists or NumPy arrays via
++(). - Complex output:
FFTransform,FFTransform2D,FFTransformND,RealFFTall return complex128 arrays. Use++(x.real)to extract the real part. - RealFFT backward output length: by default, output length is
2 * (len(X) - 1), which assumes the original signal had even length. PassNexplicitly for odd-length originals. - Normalisation: the default (un-normalised) convention is
fftfollowed byifftrecovers the original signal. PassNORM='ortho'for the orthonormal convention — but this requires the 3-arity form which is not yet exposed; use the++()escape directly for that case. - Predicates fail (no solution) when scipy raises an exception, or when a
bound
RESULTdoes not unify with the computed value.