From d1dd5e499a6d7c266e11fa3594b0557a17ec137e Mon Sep 17 00:00:00 2001 From: Leonardo Robol Date: Tue, 2 Mar 2010 18:44:00 +0100 Subject: [PATCH] Added FilterBank class. --- Filtering/Filtering.py | 132 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 131 insertions(+), 1 deletion(-) diff --git a/Filtering/Filtering.py b/Filtering/Filtering.py index fe0ed71..b046372 100644 --- a/Filtering/Filtering.py +++ b/Filtering/Filtering.py @@ -2,7 +2,7 @@ # -*- coding: utf-8 -*- # -from numpy import array, zeros, convolve, dot +from numpy import array, zeros, convolve, dot, roll class AbstractFilter(): @@ -49,3 +49,133 @@ def UpSample(samples): s = zeros(2 * len(samples)) s[::2] = samples return array(s) + + +class FilterBank(): + + def __init__(self): + """Create a new empty filter bank""" + self.lowPassFilter = None + self.highPassFilter = None + self.highPassInverseFilter = None + self.lowPassInverseFilter = None + + self.depth = 1 + + def SetFilterMatrix(self, filter_matrix): + """ + Set the filter matrix for the filter bank. + It must have this shape: + + [ h0 , h1, f0, f1 ] + + Where h0 is the lowPass coefficients vector, + h1 the high pass one, f0 the inverse low pass + and f1 the inverse high pass. + This method can only use FIR filters, if you are + looking for more freedom use SetLowPassFilter () + and similar. + """ + self.lowPassFilter = FIR (filter_matrix[0]) + self.highPassFilter = FIR (filter_matrix[1]) + self.lowPassInverseFilter = FIR (filter_matrix[2]) + self.highPassInverseFilter = FIR (filter_matrix[3]) + + def _Truncate(self, samples): + """ + Returns the samples truncated to make + recursive split possibile + (i.e. len(samples) % 2^depth = 0) + """ + toRemove = len(samples) % pow(2,self.depth) + if toRemove is 0: + return samples + else: + return samples[:-1 * toRemove] + + def SetDepth(self, depth): + """ + Set the depth of the filter, i.e. how many recursion + will be done when filtering and downsampling + """ + self.depth = depth + + def SetLowPassFilter(self, lowpass): + """ + Set the LowPassFilter for the filterbank. + It has to be a callable that transform the + samples. It will usually be a FIR + """ + self.lowPassFilter = lowpass + + def SetHighPassFilter(self, highpass): + """ + Set the High pass filter. It is usually + a FIR but can be a generic callable that + returns the filtered samples + """ + self.highPassFilter = highpass + + def SetLowPassInverseFilter(self, lowpass): + """ + Set the LowPass inverse filter to be used + in reconstruction. + """ + self.lowPassInverseFilter = lowpass + + def SetHighPassInverseFilter(self, highpass): + """ + Set the HighPass inverse filter to be used + in signal reconstruction + """ + self.highPassInverseFilter = highpass + + def Split(self, samples): + """ + Split the samples using the filter provided + by the user. It returns an array of samples similar + to this: + + [ high, high, high , ... , high, low ] + + that contains the details and the last average. + The original signal can be rebuilt collapsing + all these downsamples signals with the Rebuild + method. + """ + + samplesArray = [] + low = self._Truncate(samples) + + # Do the real filtering and downsampling. Store the downsampled + # details in the array. + for recursion in xrange(1, self.depth): + samplesArray.append (DownSample (self.highPassFilter (low))) + low = DownSample (self.lowPassFilter (low)) + + # In the end append the low downsampled data to the array + samplesArray.append (low) + + return samplesArray + + def Rebuild(self, sampleArray): + """ + Rebuild an array of samples obtained by the Split() + method. + """ + + low = sampleArray.pop () + + # Iterate over the reversed array + for high in sampleArray[::-1]: + low = self.lowPassInverseFilter (UpSample (low)) + low += self.highPassInverseFilter (UpSample (high)) + low = roll(low, -1) + + return low + + + + + + -- 2.1.4