Added FilterBank class.
Leonardo Robol [2010-03-02 17:44]
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
+
+
+
+
+
+