FreqFilterSpec#

class hypercoil.init.freqfilter.FreqFilterSpec(*, Wn: float | Tuple[float, float] | Tuple[float, ...] | Tuple[Tuple[float, float], ...] | None = None, N: int | Tuple[int, ...] = 1, ftype: Literal['ideal', 'butter', 'cheby1', 'cheby2', 'ellip', 'bessel', 'randn'] = 'ideal', btype: Literal['lowpass', 'highpass', 'bandpass', 'bandstop'] = 'bandpass', fs: float | None = None, rp: float = 0.1, rs: float = 0.1, norm: Literal['phase', 'amplitude', 'delay'] = 'phase', ampl_loc: float = 0.5, ampl_scale: float = 0.1, phase_loc: float = 0.0, phase_scale: float = 0.02, clamps: Sequence[Dict[float, float]] | None = None, bound: float = 3.0)[source]#

Specification for an approximate frequency response curve for various filter classes.

Danger

Note that this provides only an emulation for IIR filters. Thus, for instance, using the butterworth filter initialisation will not in any sense initialise a Butterworth filter. It will return a spectrum that approximately emulates the action of a Butterworth filter in the frequency domain. In practice, the results are not even close to a true IIR filter. For a true differentiable IIR filter, use the IIRFilter class instead (when it’s operational).

Parameters:
Filter class to emulate: Butterworth, Chebyshev I, Chebyshev II,

elliptic, Bessel-Thompson, ideal, or filter weights sampled randomly from a normal distribution.

Note

Because it cannot be overstated: IIR filter spectra (Butterworth, Chebyshev, elliptic, Bessel) are strictly emulations and do not remotely follow the actual behaviour of the filter. These filters are recursive and cannot be implemented as frequency products. By contrast, the ideal initialisation is exact.

Nint or tuple of int

Filter order. If this is a tuple, then a separate filter will be created for each entry in the tuple. Wn must be shaped to match or of length 1.

Wnfloat or tuple(float, float) or tuple thereof

Critical or cutoff frequency. If this is a band-pass filter, then this should be a tuple, with the first entry specifying the high-pass cutoff and the second entry specifying the low-pass frequency. This should be specified relative to the Nyquist frequency if fs is not provided, and should be in the same units as fs if it is provided. To create multiple filters, specify a tuple (of floats or tuples) containing the critical frequencies for each filter in a single entry. N must be shaped to match or of length 1.

worNint

Number of frequency bins to include in the computed spectrum.

btype‘lowpass’, ‘highpass’, or ‘bandpass’ (default ‘bandpass’)

Filter type to emulate: low-pass, high-pass, or band-pass. The interpretation of the critical frequency changes depending on the filter type.

fsfloat or None (default None)

Sampling frequency.

rsfloat

Stop-band ripple parameter. Used only for Chebyshev II and elliptic filter response emulation.

rpfloat

Pass-band ripple parameter. Used only for Chebyshev I and elliptic filter response emulation.

norm'phase', 'delay', or 'amplitude'

Critical frequency normalisation. Used only for Bessel-Thompson filter response emulation. Consult the scipy.signal.bessel documentation for details.

ampl_locfloat

Mean of the normal distribution used to initialise the amplitudes. Used only for random initialisation.

ampl_scalefloat

Standard deviation of the normal distribution used to initialise the amplitudes. Used only for random initialisation.

phase_locfloat

Mean of the normal distribution used to initialise the phases. Used only for random initialisation.

phase_scalefloat

Standard deviation of the normal distribution used to initialise the phases. Used only for random initialisation.

clampslist(dict)

Frequencies whose responses should be clampable to particular values. Each element of the list is a dictionary corresponding to a single filter; the list should therefore have a length of F. Each key/value pair in each dictionary should correspond to a frequency (relative to Nyquist or fs if provided) and the clampable response at that frequency. For instance {0.1: 0, 0.5: 1} enables clamping of the frequency bin closest to 0.1 to 0 (full stop) and the bin closest to 0.5 to 1 (full pass). Note that the clamp must be applied using the get_clamps method.

Methods

get_clamps(*, worN)

Returns a mask and a set of values that can be used to clamp each filter's transfer function at a specified set of frequencies.

initialise_spectrum(*, worN, key)

Initialises a frequency spectrum or transfer function approximation for the specified filter with worN frequency bins between 0 and Nyquist, inclusive.

initialise_spectrum(*, worN: int, key: PRNGKey) Tensor[source]#

Initialises a frequency spectrum or transfer function approximation for the specified filter with worN frequency bins between 0 and Nyquist, inclusive.

Parameters:
worNint

Number of frequency bins between 0 and Nyquist, inclusive.

Returns:
Tensor

A tensor of shape (F, worN) where F is the number of filters.

get_clamps(*, worN: int)[source]#

Returns a mask and a set of values that can be used to clamp each filter’s transfer function at a specified set of frequencies.

To apply the clamp, use:

`jnp.where(points, values, spectrum)`

Parameters:
worNint

Number of frequency bins between 0 and Nyquist, inclusive.

Returns:
pointsTensor

Boolean mask indicating the frequency bins that are clampable.

valuesTensor

Values to which the response function is clampable at the specified frequencies.