HOWTO · SciPy
SciPy signal.butter
Entwerfen und wenden Sie einen Butterworth-Bandpassfilter in Python an – mit scipy.signal.butter, Sektionen zweiter Ordnung und einer Signaldarstellung.
Auf dieser Seite
Entwerfen Sie mit scipy.signal.butter einen Butterworth-Filter und wenden Sie anschließend die resultierenden Sektionen zweiter Ordnung auf ein abgetastetes Signal an. Dieses Beispiel erhält eine Komponente mit 50 Hz, während es eine Komponente mit 250 Hz abschwächt, und stellt das Eingangssignal dem gefilterten Ergebnis gegenüber. Für die Vorwärts-Rückwärts-Filterung kommt sosfiltfilt zum Einsatz; dadurch entsteht keine Phasenverschiebung wie bei einem einzelnen Vorwärtsdurchlauf.
Die Funktion entwirft digitale oder analoge Butterworth-Filter, filtert aber nicht selbst die Daten. Die offizielle SciPy-Referenz zur Signalverarbeitung dokumentiert die Funktionen zum Filterentwurf.
Mit scipy.signal.butter einen Butterworth-Filter entwerfen
Ein Butterworth-Filter weist im Durchlassbereich einen maximal flachen Amplitudenfrequenzgang auf. Die Funktion scipy.signal.butter gibt Filterkoeffizienten zurück. Für die praktische digitale Filterung sollten Sie mit output="sos" Sektionen zweiter Ordnung anfordern. Bei Filtern höherer Ordnung ist diese Darstellung in der Regel numerisch robuster als ein einzelner Zähler und Nenner.
Das Argument N gibt die Filterordnung an. Bei einem Bandpass hat die resultierende Übertragungsfunktion die Ordnung 2 * N; der Parameter N bezeichnet weiterhin die an die Entwurfsfunktion übergebene Ordnung. Das Argument Wn gibt die kritische Frequenz an oder bei einem Bandpass einen Bereich mit zwei Werten in aufsteigender Reihenfolge. Dabei handelt es sich um Entwurfsfrequenzen, nicht um getrennte Vorgaben für Durchlass- und Sperrbereich. An jeder kritischen Frequenz beträgt die Verstärkung eines Butterworth-Filters ungefähr 1/√2 (−3 dB).
Filtertyp, Ordnung und kritische Frequenzen auswählen
Mit btype="bandpass" lassen Sie Frequenzen zwischen zwei Grenzwerten passieren. Für einen Tiefpass verwenden Sie "lowpass", für einen Hochpass "highpass" und für einen Bandsperrfilter "bandstop". Die Grenzwerte müssen positiv, aufsteigend und kleiner als die Hälfte der Abtastrate sein.
Wenn Sie fs angeben, müssen Wn und fs dieselbe Einheit verwenden, zum Beispiel Hertz. Ohne fs interpretiert SciPy digitale kritische Frequenzen in Einheiten, bei denen 1 der Nyquist-Frequenz entspricht, also der Hälfte der Abtastrate. Beispielsweise entspricht eine kritische Frequenz von 100 Hz bei fs=1000 Hz dem Wert Wn=0.2, wenn fs nicht angegeben wird.
Wählen Sie die Ordnung entsprechend der benötigten Flankensteilheit und dem Rechenaufwand Ihrer Anwendung. Eine höhere Ordnung macht den Übergang steiler, erhöht aber den Rechenaufwand und kann den Entwurf empfindlicher gegenüber numerischen Effekten machen. Sie garantiert nicht für jedes Signal ein besseres Ergebnis. Wenn Ihre Vorgaben Angaben zur Welligkeit im Durchlassbereich oder zur Dämpfung im Sperrbereich enthalten, verwenden Sie ein Entwurfsverfahren, das solche Vorgaben berücksichtigt, beispielsweise scipy.signal.iirdesign.
Den Filter auf ein Signal anwenden
Dieses ausführbare Beispiel tastet ein Signal mit 1000 Hz ab. Seine Komponente mit 50 Hz liegt im Durchlassbereich von 40–100 Hz, die Komponente mit 250 Hz dagegen außerhalb. sosfiltfilt verarbeitet die Sektionen vorwärts und rückwärts; daher hat das Ergebnis keine Phasenverschiebung durch einen einseitigen kausalen Filter. Installieren Sie SciPy, NumPy und Matplotlib in Ihrer Python-Umgebung, bevor Sie das Beispiel ausführen. Die Vergleichsgrafik wird im aktuellen Verzeichnis unter butterworth_filter.png gespeichert.
import matplotlib.pyplot as plt
import numpy as np
from scipy.signal import butter, sosfiltfilt
fs = 1000.0
duration = 1.0
t = np.arange(0.0, duration, 1.0 / fs)
signal = np.sin(2.0 * np.pi * 50.0 * t) + 0.6 * np.sin(2.0 * np.pi * 250.0 * t)
sos = butter(4, [40.0, 100.0], btype="bandpass", fs=fs, output="sos")
filtered = sosfiltfilt(sos, signal)
fig, axes = plt.subplots(2, 1, sharex=True, figsize=(9, 5))
axes[0].plot(t, signal, label="Input")
axes[0].set_ylabel("Amplitude")
axes[0].legend()
axes[1].plot(t, filtered, label="Filtered", color="tab:orange")
axes[1].set_xlabel("Time (s)")
axes[1].set_ylabel("Amplitude")
axes[1].legend()
fig.tight_layout()
fig.savefig("butterworth_filter.png", dpi=150)
plt.close(fig)
Das Eingangssignal ist die Summe zweier bekannter Sinuskurven. Das Beispiel ist daher reproduzierbar und hängt nicht von zufälligem Rauschen ab. Um eigene Messwerte zu verwenden, ersetzen Sie signal und setzen Sie fs auf deren Abtastrate. Signalarray und Filtereinstellungen müssen dabei zueinander passende Einheiten verwenden. Für Streaming oder Echtzeitverarbeitung eignet sich ein einseitiger Filter wie sosfilt; berücksichtigen Sie dabei seine Phasenverschiebung und sein Einschwingverhalten.
Gefiltertes Signal darstellen und interpretieren
Öffnen Sie butterworth_filter.png, um im ersten Diagramm das zusammengesetzte Eingangssignal und im zweiten die gefilterten Abtastwerte über denselben Zeitbereich zu vergleichen. Die Schwingung mit 50 Hz bleibt deutlich sichtbar, während die Komponente mit 250 Hz abgeschwächt wird. Die Grafik veranschaulicht den qualitativen Unterschied, garantiert aber keine exakten Amplituden: In der Nähe der kritischen Frequenzen verläuft der Frequenzgang allmählich, und das Ergebnis hängt außerdem von den Daten und der Filterordnung ab.
Das dargestellte Beispiel verwendet eine Vorwärts-Rückwärts-Filterung, bei der die Daten in beide Richtungen verarbeitet werden. Das beseitigt die Phasenverzögerung, macht das Verfahren jedoch nichtkausal. Es eignet sich daher für Offline-Daten, nicht für einen laufenden Datenstrom. Bei endlichen Datensätzen kann die Vorwärts-Rückwärts-Filterung außerdem am Anfang und Ende Einschwingeffekte erzeugen. Prüfen Sie diese Bereiche, bevor Sie dort Messwerte interpretieren. Für Live-Daten sollten Sie stattdessen einen kausalen Filter verwenden und dessen Verzögerung sowie Verhalten beim Anfangszustand berücksichtigen.
Häufige Fallstricke: Abtastrate, Filterordnung und Einschwingeffekte
- Abtastrate:
fsmuss die tatsächliche Abtastrate Ihrer Daten angeben. Ein falscher Wert verändert die physikalische Bedeutung jeder Frequenz im Entwurf. Frequenzen ab der Nyquist-Frequenz lassen sich in abgetasteten Daten nicht zuverlässig darstellen. Verwenden Sie vor der Abtastung eine geeignete Erfassungsrate und einen Anti-Aliasing-Filter. - Filterordnung:
Nist keine Stärkeangabe. Eine höhere Ordnung macht den Übergang steiler und erhöht den Rechenaufwand sowie die numerischen Kosten. Vergleichen Sie den resultierenden Frequenzgang mit den Anforderungen Ihrer Aufgabe, statt anzunehmen, dass die höchstmögliche praktikable Ordnung am besten ist. - Frequenzargumente: Wenn Sie
fsangeben, müssenWnundfsdieselbe Einheit verwenden. Ohnefsnormalisieren Sie digitale Frequenzen auf die Nyquist-Frequenz. Bei einem Bandpass enthältWndie untere und obere kritische Frequenz; Sperrbereichsgrenzen oder Dämpfungsziele sind darin nicht festgelegt. - Einschwingeffekte und Filterrichtung:
sosfiltfiltist ein praktisches, phasenfreies Verfahren für die Offline-Verarbeitung.sosfiltarbeitet kausal in einer Richtung und eignet sich für Streaming. Bei beiden Verfahren können Einschwing- oder Randeffekte auftreten. Lassen Sie daher rund um den zu analysierenden Bereich genügend Daten und prüfen Sie die Endpunkte.