Qu

butter

Builtin index · Signal processing

result = butter(order, kind, cutoff, fs)

Input: order, kind, cutoff, fs · Output: result

What it is

order: number (filter order); kind: string; cutoff: number or length-2 vector (Hz); fs: number (Hz).

Overloads

cutoff can be number or vector.

2 forms. Each carries its own inputs, outputs and worked example — pick the tab for the one you are calling.

CodeInputOutputDescription
result = butter(order, "low"/"high", cutoff, fs)
order numberorder: number (filter order).
"low"/"high" —not documented yet
cutoff number or vectorcutoff: number or length-2 vector (Hz).
fs numberfs: number (Hz).
result number
A single Hz number — the low-pass or high-pass edge.

Examples

From the documentation, and run by the build -- the output and the figure below are what the engine actually produced. Simplest first.

fs = 1000
lp = butter(4, "low", 100, fs)          # 4th-order lowpass, 100 Hz cutoff

notch = butter(2, "notch", [45, 55], fs)  # removes 45-55 Hz (mains hum)

from numerics-dsp

print(zeros(3))                              # [0, 0, 0]

print(zeros(2, 3))                           # [0, 0, 0; 0, 0, 0]

filt = butter(4, "low", 100, 1000)
print(zeros(filt))                           # [-1, -1, -1, -1] -- a CVec, not a fresh zero-fill

output
[0, 0, 0]
[0, 0, 0; 0, 0, 0]
[-1, -1, -1, -1]

from core-math

fs = 1000
iir = butter(2, "low", 100, fs)
print("IIR poles: {poles(iir)}")
# IIR poles: [0.57149 + 0.293599i, 0.57149 - 0.293599i]

output
IIR poles: [0.57149 + 0.293599j, 0.57149 - 0.293599j]

from signal-processing

fs = 1000
lp = butter(4, "low", 100, fs)
bp = butter(4, "band", [80, 120], fs)
print("lowpass sections: {shape(lp.sos)[0]}")    # lowpass sections: 2

print("bandpass sections: {shape(bp.sos)[0]}")   # bandpass sections: 4

output
lowpass sections: 2
bandpass sections: 4

from signal-processing

CodeInputOutputDescription
result = butter(order, "band"/"stop", cutoff, fs)
order numberorder: number (filter order).
"band"/"stop" —not documented yet
cutoff number or vectorcutoff: number or length-2 vector (Hz).
fs numberfs: number (Hz).
result vector
A length-2 [low, high] Hz vector — the passband/stopband edges ("stop"/"notch" cuts that band out instead of keeping it).

Examples

From the documentation, and run by the build -- the output and the figure below are what the engine actually produced. Simplest first.

fs = 1000
lp = butter(4, "low", 100, fs)          # 4th-order lowpass, 100 Hz cutoff

notch = butter(2, "notch", [45, 55], fs)  # removes 45-55 Hz (mains hum)

from numerics-dsp

print(zeros(3))                              # [0, 0, 0]

print(zeros(2, 3))                           # [0, 0, 0; 0, 0, 0]

filt = butter(4, "low", 100, 1000)
print(zeros(filt))                           # [-1, -1, -1, -1] -- a CVec, not a fresh zero-fill

output
[0, 0, 0]
[0, 0, 0; 0, 0, 0]
[-1, -1, -1, -1]

from core-math

fs = 1000
iir = butter(2, "low", 100, fs)
print("IIR poles: {poles(iir)}")
# IIR poles: [0.57149 + 0.293599i, 0.57149 - 0.293599i]

output
IIR poles: [0.57149 + 0.293599j, 0.57149 - 0.293599j]

from signal-processing

fs = 1000
lp = butter(4, "low", 100, fs)
bp = butter(4, "band", [80, 120], fs)
print("lowpass sections: {shape(lp.sos)[0]}")    # lowpass sections: 2

print("bandpass sections: {shape(bp.sos)[0]}")   # bandpass sections: 4

output
lowpass sections: 2
bandpass sections: 4

from signal-processing

How it works

butter(order, kind, cutoff, fs) — designs a digital Butterworth filter as a cascade of second-order sections (SOS), the numerically stable representation used no matter the order. kind is "low"/"high"/"band"/ "stop" ("bandpass"/"lowpass"/"highpass"/ "bandstop"/"notch" all accepted as more readable aliases). cutoff is one frequency in Hz for low/high, or [low, high] for band/stop. Model kind "filter", field sos (a matrix, one section per row: [b0,b1,b2,a1,a2]).

From the note above this builtin in the interpreter, where the reasoning was written down as it was built.