I have three functions for building, applying, and plotting filters:
Build a filter:
def filter_build(frequency, sample_rate, filter_type, filter_order):
nyq = 0.5 * sample_rate
if filter_type == 'bandpass':
try:
normal_cutoff = (frequency[0] / nyq, frequency[1] / nyq)
except Exception as e:
print("Must provide tuple of frequency ranges for a bandpass filter")
raise
else:
try:
normal_cutoff = frequency / nyq
except Exception as e:
print("Must provide a single frequency value for this filter type")
raise
b, a = butter(filter_order, normal_cutoff, btype=filter_type, analog=False)
return b, a
Apply filter:
def filter(signal, frequency, sample_rate, filter_type, filter_order=2):
try:
b, a = filter_build(frequency, sample_rate, filter_type, filter_order)
except:
print("Error when creating filter")
return None
filtered = filtfilt(b, a, signal)
return filtered
Plotting the filter response:
def plot_filter_response(frequency, sample_rate, filter_type, filter_order=2):
try:
b, a = filter_build(frequency, sample_rate, filter_type, filter_order)
except:
print("Error when creating filter")
return None
w, h = freqz(b, a, worN=8000)
plt.subplot(2, 1, 1)
plt.plot(0.5*sample_rate*w/np.pi, np.abs(h), 'b')
plt.xlim(0, 0.5*sample_rate)
plt.title("Filter Frequency Response")
plt.xlabel('Frequency (Hz)')
plt.grid()
if filter_type == 'bandpass':
for i in range(len(frequency)):
plt.axvline(frequency[i], color='k')
plt.plot(frequency[i], 0.5*np.sqrt(2), 'ko')
else:
plt.axvline(frequency, color='k')
plt.plot(frequency, 0.5*np.sqrt(2), 'ko')
plt.show()
Everything appears to be working, but I dont think I'm handling exceptions correctly/efficiently.
For example, in filter()
and plot_filter_response()
I have the exact same try
block, which feels redundant
The purpose of the try
blocks (in all 3 functions) is to provide an easily understood error message if building a filter fails. The primary reason for this happening (that I can foresee) is if someone specifies a bandpass filter and only provides a single frequency cutoff, or if someone wants a lowpass filter but accidentally provides a tuple of 2 frequencies
Is there a way to remove the redundant try
blocks, so that if a filter is mis-specified, then filter_build()
will raise the error and stop any other lines of code from running?
A related issue is my inclusion of Return None
in the latter 2 functions. Is there a way to remove those? If I remove them, then currently if filter_build()
fails, the rest of the plotting code (or filtfilt
) still gets executed, which runs into more problems. Ideally I want the functions to just exit if filter_build()
doesn't return correctly