Investment Studio > Expressions > Functions > DSP > LOPASS

Short fom: float array[*][data_columns] lopass(float array[*][4] filter_parameters, float amplification, float array[*][data_columns] data)

Returns the data array, with all columns passed through the filter specified by the filter_parameters and multiplied by the amplification factor. Each data column is filtered separately.

Range form: float array[*][data_columns] lopass(float array[*][4] filter_parameters, float amplification, float array[*][data_columns] data, integer first_column, integer last_column = data_columns)

Returns the data array, with columns first_column through last_column passed through the filter specified by the filter_parameters and multiplied by the amplification factor. Each data column in the specified range is filtered separately.

If last_column is omitted, it defaults to first_column (i.e. only first_column is filtered).

All arguments (including all array elements) are converted to float. If conversion fails, the default value 0.0 is used.

Each row in filter_parameters describes a second order IIR (Infinite Impulse Response) filter implementing the difference equation

y[n] = b0 * x[n] + b1 * x[n - 1] + a1 * y[n - 1] + a2 * y[n - 2]

where x[n] is the input sequence and y[n] is the filter's output. The filter coefficients are listed in the order {b0, b1, a1, a2}.

All second order filters are applied to the input sequence in parallell. The function result is obtained by summing their outputs and multiplying the sum with the factor amplification.

Filter parameters can be specified manually or created with make_ema and make_lopass (recommended).

Tip: The frequency response of any linear, time-invariant filter is just the Fourier transform of the filter's impulse response (the filter's output when the input sequence is a unit impulse, i.e. a single 1 followed by zeros) so to visualize the filter's frequency response, all you have to do is pass a unit impulse through the filter, apply fftp to the output and plot the result. See the example below.

Example (see also the lopass example in make_ema and the example in notch)

The 100-point column vector

_data = mop("sin()", makevector(100, 0, 4 * PI / 100)) + mop("sin()", makevector(100, 0, 32 * PI / 100))

contains a sine wave with period 50 (normalized frequency 0.5) mixed with a sine wave with period 100 / 16 (normalized frequency 0.16). To filter out the shorter wave, we can use a low pass filter with normalized cut-off frequency 0.25:

=lopass(make_lopass(2, 0.25), 1, array(_data))

Plugged into graph sources and plotted together, the above expressions look like this:

The input is in black, the high-pass output in blue. Both wave components can be seen to have suffered some amplitude loss, but the shorter waves much more so than the longer ones.

To improve the result, we can reduce the width of the transition band by adding more poles to our filter. With 8 poles,

=lopass(make_lopass(8, 0.25), 1, array(_data))

the result looks like this:

The shorter wave component is now almost completely gone, while the amplitude of the longer component is almost unaffected.

Tip: In cases like this, with a sharply defined, narrow frequency range to filter out, the notch function is usually a better choice than a generic low pass filter.

We can visualize the difference in frequency response between the two filters by passing a unit impulse through both and computing the Fourier transforms of their output.

With the definitions

_impulse = index(m1(128), 0, 1)

_2_poles = fftp(lopass(make_lopass(2, 0.25), 1, array(_impulse)))

_8_poles = fftp(lopass(make_lopass(8, 0.25), 1, array(_impulse)))

the graph sources

=128 * index(array(_2_poles), x + 1, 1)

=128 * index(array(_8_poles), x + 1, 1)

(where the "+ 1" is to skip the zeroth, constant "harmonic") yield the following amplitude responses (blue for 2 poles, red for 8 poles):

It should be noted that the better frequency resolution of the higher order filter comes at the price of larger phase delays at the lower frequencies frequencies which we are trying to isolate (clearly visible as a shift to the right of the filtered wave). With the graph sources

=index(array(_2_poles), x + 1, 2)

=index(array(_8_poles), x + 1, 2)

we get the following phase responses:

See also hipass, make_ema, make_lopass, notch, resonate.