पायथन में सैंपल सिग्नल के लिए लोपास फ़िल्टर कैसे लिखें?


16

मेरे पास कुछ संकेत हैं जो प्रत्येक 1 एनएस (1e-9 सेकंड) का नमूना लेते हैं और कहते हैं, 1e4 अंक। मुझे इस सिग्नल से उच्च आवृत्तियों को फ़िल्टर करने की आवश्यकता है। मान लीजिए कि मुझे 10 मेगाहर्ट्ज से अधिक आवृत्तियों को फ़िल्टर करने की आवश्यकता है। मैं चाहता हूं कि कटऑफ फ्रीक्वेंसी सिग्नल की तुलना में कम आवृत्तियों को अपरिवर्तित पारित किया जाएगा। इसका मतलब है कि फिल्टर का लाभ कटऑफ आवृत्ति की तुलना में कम आवृत्तियों के लिए 1 होगा। मैं फ़िल्टर ऑर्डर निर्दिष्ट करने में सक्षम होना चाहूंगा। मेरा मतलब है, पहले ऑर्डर फिल्टर में कटऑफ आवृत्ति के बाद 20 डीबी / दशक ढलान (पावर रोल ऑफ) है, दूसरे ऑर्डर फिल्टर में कटऑफ आवृत्ति के बाद 40 डीबी / डेसी ढलान है। कोड का उच्च प्रदर्शन महत्वपूर्ण है।

जवाबों:


19

मक्खन फ़ंक्शन का उपयोग करके डिज़ाइन किए गए फ़िल्टर के लिए आवृत्ति प्रतिक्रिया है:

बटरवर्थ फ़िल्टर रिस्पांस

लेकिन फ़िल्टर को निरंतर मोनोटोनिक फ़िल्टर डिज़ाइन तक सीमित करने का कोई कारण नहीं है। यदि आप स्टॉपबैंड और स्टेपर ट्रांज़िशन बैंड में उच्च क्षीणन की इच्छा रखते हैं, तो अन्य विकल्प मौजूद हैं। का उपयोग कर एक फिल्टर निर्दिष्ट करने के बारे में अधिक जानकारी के लिए iirdesing देखना यह । जैसा कि मक्खन डिजाइन के लिए आवृत्ति प्रतिक्रिया भूखंडों द्वारा दिखाया गया है कटऑफ आवृत्ति (-3 डीबी बिंदु) लक्ष्य से बहुत दूर है। इसे फ़िल्टर करने से पहले डाउन-सैंपलिंग द्वारा कम किया जा सकता है (डिजाइन फ़ंक्शंस में इस तरह के एक संकीर्ण फिल्टर के साथ मुश्किल समय होगा, 2% बैंडविड्थ)। निर्दिष्ट कटऑफ के साथ मूल नमूना दर को फ़िल्टर करने पर ध्यान दें।

import numpy as np
from scipy import signal
from matplotlib import pyplot as plt

from scipy.signal import fir_filter_design as ffd
from scipy.signal import filter_design as ifd

# setup some of the required parameters
Fs = 1e9           # sample-rate defined in the question, down-sampled

# remez (fir) design arguements
Fpass = 10e6       # passband edge
Fstop = 11.1e6     # stopband edge, transition band 100kHz
Wp = Fpass/(Fs)    # pass normalized frequency
Ws = Fstop/(Fs)    # stop normalized frequency

# iirdesign agruements
Wip = (Fpass)/(Fs/2)
Wis = (Fstop+1e6)/(Fs/2)
Rp = 1             # passband ripple
As = 42            # stopband attenuation

# Create a FIR filter, the remez function takes a list of 
# "bands" and the amplitude for each band.
taps = 4096
br = ffd.remez(taps, [0, Wp, Ws, .5], [1,0], maxiter=10000) 

# The iirdesign takes passband, stopband, passband ripple, 
# and stop attenuation.
bc, ac = ifd.iirdesign(Wip, Wis, Rp, As, ftype='ellip')  
bb, ab = ifd.iirdesign(Wip, Wis, Rp, As, ftype='cheby2') 

मूल नमूना दर फ़िल्टर

जैसा कि उल्लेख किया गया है, क्योंकि हम बैंडविड्थ के इतने छोटे प्रतिशत को फ़िल्टर करने की कोशिश कर रहे हैं, फ़िल्टर में तेज कटऑफ नहीं होगा। इस मामले में, फ़िल्टर को कम करें, हम बेहतर दिखने वाले फ़िल्टर प्राप्त करने के लिए बैंडविड्थ को कम कर सकते हैं। अजगर / scipy.signal resample फ़ंक्शन का उपयोग बैंडविड्थ को कम करने के लिए किया जा सकता है।

ध्यान दें रेज़लूशन फंक्शन अलियासिंग को रोकने के लिए फ़िल्टरिंग करेगा। प्रीफ़िल्टरिंग को भी सुगंधित किया जा सकता है (एलियासिंग को कम करने के लिए) और इस मामले में हम बस 100 से फिर से तैयार कर सकते हैं और किया जा सकता है , लेकिन सवाल फिल्टर बनाने के बारे में पूछा गया। इस उदाहरण के लिए हम 25 से घटाएंगे और एक नया फ़िल्टर बनाएंगे

R = 25;            # how much to down sample by
Fsr = Fs/25.       # down-sampled sample rate
xs = signal.resample(x, len(x)/25.)

यदि हम एफआईआर फ़िल्टर के लिए डिज़ाइन मापदंडों को अपडेट करते हैं तो नई प्रतिक्रिया होती है।

# Down sampled version, create new filter and plot spectrum
R = 25.             # how much to down sample by
Fsr = Fs/R          # down-sampled sample rate
Fstop = 11.1e6      # modified stopband
Wp = Fpass/(Fsr)    # pass normalized frequency
Ws = Fstop/(Fsr)    # stop normalized frequency
taps = 256
br = ffd.remez(taps, [0, Wp, Ws, .5], [1,0], maxiter=10000) 

डाउनसम्पल्ड फ़िल्टर रिस्पॉन्स

डाउनसम्पल्ड डेटा पर काम करने वाले फ़िल्टर की बेहतर प्रतिक्रिया होती है। एफआईआर फिल्टर का उपयोग करने का एक और लाभ यह है कि आपके पास रैखिक चरण प्रतिक्रिया होगी।


1
धन्यवाद। आप सिग्नल स्पेक्ट्रम का ग्राफ कैसे बनाते हैं?
एलेक्स

एक उत्कृष्ट उत्तर के लिए बहुत बहुत धन्यवाद! मुझे आश्चर्य है कि यदि आप संभवतः समझा सकते हैं कि रिमेज़ का उपयोग करके गणना किए गए गुणांक के आधार पर एफआईआर फ़िल्टर कैसे लागू किया जाए? मुझे यह समझने में परेशानी हो रही है कि पैरामीटर के filtfiltलिए क्या चाहिए a
अली_म

एक बार फ़िल्टर डिजाइन, (से गुणांक है प्राथमिकी के लिए और एक IIR के लिए) आप एक जोड़े को विभिन्न कार्यों के लिए इस्तेमाल किया फ़िल्टर करना कर सकते हैं: lfilter , convolve , filtfilt । आमतौर पर ये सभी फ़ंक्शन समान होते हैं: y = filtfilt (b, a, x) यदि आपके पास एक एफआईआर फिल्टर है तो बस एक = 1 सेट करें , एक्स इनपुट सिग्नल है, बी एफआई ​​गुणांक है। इस पोस्ट के रूप में अच्छी तरह से मदद कर सकता है।
क्रिस्टोफर फेल्टन

5

क्या यह काम करता है?

from __future__ import division
from scipy.signal import butter, lfilter

fs = 1E9 # 1 ns -> 1 GHz
cutoff = 10E6 # 10 MHz
B, A = butter(1, cutoff / (fs / 2), btype='low') # 1st order Butterworth low-pass
filtered_signal = lfilter(B, A, signal, axis=0)

आप सही हैं, हालांकि, प्रलेखन बहुत पूरा नहीं है। ऐसा लगता है butterकि एक रैपर है iirfilter, जो बेहतर प्रलेखित है :

N: int फ़िल्टर का क्रम। Wn: array_like महत्वपूर्ण आवृत्तियों को देते हुए एक स्केलर या लंबाई -2 अनुक्रम।

इस सामान का अधिकांश हिस्सा मटलबाल से लिया गया है, हालाँकि, आप उनके प्रलेखन को भी देख सकते हैं:

सामान्यीकृत कटऑफ आवृत्ति Wn 0 और 1 के बीच की संख्या होनी चाहिए, जहां 1 Nyquist आवृत्ति, प्रति नमूने। रेडियन से मेल खाती है।

अपडेट करें:

मैंने इन कार्यों के लिए प्रलेखन जोड़ा । :) Github यह आसान बनाता है।


1

निश्चित नहीं है कि आपका आवेदन क्या है, लेकिन आप Gnuradio की जांच कर सकते हैं: http://gnuradio.org/doc/doxygen/classgr__firdes.html

सिग्नल प्रोसेसिंग ब्लॉक C ++ में लिखे गए हैं (हालांकि ग्नूरडिओ प्रवाह ग्राफ़ पायथन में हैं), लेकिन आपने कहा था कि उच्च प्रदर्शन महत्वपूर्ण है।


1

मुझे इस एफआईआर फ़िल्टर के साथ अच्छे परिणाम मिल रहे हैं। सूचनाएँ दो बार फ़िल्टर को लागू करती हैं, "फॉरवर्ड" और "रिवर्स", ताकि सिग्नल ऑफ़सेट की भरपाई हो सके ( filtfiltफ़ंक्शन काम नहीं करता, पता नहीं क्यों):

def firfilt(interval, freq, sampling_rate):
    nfreq = freq/(0.5*sampling_rate)
    taps =  sampling_rate + 1
    a = 1
    b = scipy.signal.firwin(taps, cutoff=nfreq)
    firstpass = scipy.signal.lfilter(b, a, interval)
    secondpass = scipy.signal.lfilter(b, a, firstpass[::-1])[::-1]
    return secondpass

डिज़ाइन और उपयोग को फ़िल्टर करने के लिए एक महान संसाधन, जहाँ से मैंने यह कोड लिया था, और जहाँ से बैंड-पास और हाई-पास फ़िल्टर के उदाहरण लिए जा सकते हैं, यह है


मुझे विश्वास नहीं है कि एफआईआर फ़िल्टर को आगे और पीछे फ़िल्टर करने में बहुत लाभ है। IIR फ़िल्टर आगे / रिवर्स (फिल्टफिल्ट) से लाभान्वित हो सकता है क्योंकि आप स्ट्रेचिंग द्वारा गैर-रैखिक चरण फ़िल्टर से रैखिक चरण प्राप्त कर सकते हैं।
क्रिस्टोफर फेल्टन

2
@ChristopherFelton मैं स्वयं के चिकने संस्करण के साथ रॉ इलेक्ट्रोमोग्राफिक सिग्नल को सिंक्रनाइज़ करने के लिए बस रिवर्स करता हूं। मुझे पता है कि मैं सिर्फ सिग्नल को शिफ्ट कर सकता था, लेकिन दो बार फ़िल्टर करने से परेशानी कम होती है। यह ध्यान देने योग्य है कि दूसरा पास लगभग पहले से फ़िल्टर किए गए पहले पास को नहीं बदलता है ... ध्यान देने योग्य है!
हेलटनबिकर

आह, हाँ। देरी (समूह विलंब) को हटाने के लिए, अच्छी बात है।
क्रिस्टोफर फेल्टन

1

मेरे पास टिप्पणी अधिकार नहीं हैं ...

@endolith: मैं आपको scipy.signal.filtfilt (B, A, x) का उपयोग करने के अलावा उसी का उपयोग करता हूं जहां x फ़िल्टर किए जाने वाला इनपुट वेक्टर है - जैसे numpy.random.normal (size = (N))filtfilt सिग्नल का फॉरवर्ड और रिवर्स पास बनाता है। पूर्णता के लिए (सबसे ज्यादा @endolith के समान है):

import numpy as np
import scipy.signal as sps

input = np.random.normal(size=(N)) # Random signal as example
bz, az = sps.butter(FiltOrder, Bandwidth/(SamplingFreq/2)) # Gives you lowpass Butterworth as default
output = sps.filtfilt(bz, az, input) # Makes forward/reverse filtering (linear phase filter)

filtfilt जैसा कि @heltonbiker ने भी सुझाव दिया है कि मुझे विश्वास है कि गुणांक के सरणियों की आवश्यकता है। यदि आपको जटिल बेसबैंड पर बैंडपास फ़िल्टरिंग करने की आवश्यकता होती है, तो अधिक सम्मिलित कॉन्फ़िगरेशन की आवश्यकता होती है, लेकिन यह यहां एक समस्या नहीं है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.