def scipy_example(self, time, data, sample_rate=None): """ Example from the SciPy Cookboock, see http://www.scipy.org/Cookbook/FIRFilter """ chk.array_1d(time) chk.array_1d(data) if not sample_rate: sample_rate = calc_sample_rate(time) # ------------------------------------------------ # Create a FIR filter and apply it to data[:,channel] # ------------------------------------------------ # The Nyquist rate of the signal. nyq_rate = sample_rate / 2.0 # The desired width of the transition from pass to stop, # relative to the Nyquist rate. We'll design the filter # with a 5 Hz transition width. width = 5.0 / nyq_rate # The desired attenuation in the stop band, in dB. ripple_db = 60.0 # Compute the order and Kaiser parameter for the FIR filter. N, beta = sp.signal.kaiserord(ripple_db, width) # The cutoff frequency of the filter. cutoff_hz = 10.0 # Use firwin with a Kaiser window to create a lowpass FIR filter. taps = sp.signal.firwin(N, cutoff_hz / nyq_rate, window=("kaiser", beta)) # Use lfilter to filter x with the FIR filter. filtered_x = sp.signal.lfilter(taps, 1.0, data) # ------------------------------------------------ # Setup the figure parameters # ------------------------------------------------ figpath = "processing/" figfile = "filterdesign" plot = plotting.A4Tuned() plot.setup(figpath + figfile, nr_plots=3, grandtitle=figfile, figsize_y=20, wsleft_cm=2.0) # ------------------------------------------------ # Plot the FIR filter coefficients. # ------------------------------------------------ plot_nr = 1 ax1 = plot.fig.add_subplot(plot.nr_rows, plot.nr_cols, plot_nr) ax1.plot(taps, "bo-", linewidth=2) ax1.set_title("Filter Coefficients (%d taps)" % N) ax1.grid(True) # ------------------------------------------------ # Plot the magnitude response of the filter. # ------------------------------------------------ plot_nr += 1 ax2 = plot.fig.add_subplot(plot.nr_rows, plot.nr_cols, plot_nr) w, h = sp.signal.freqz(taps, worN=8000) ax2.plot((w / np.pi) * nyq_rate, np.absolute(h), linewidth=2) ax2.set_xlabel("Frequency (Hz)") ax2.set_ylabel("Gain") ax2.set_title("Frequency Response") ax2.set_ylim(-0.05, 1.05) # ax2.grid(True) # in order to place the nex axes inside following figure, first # determine the ax2 bounding box # points: a 2x2 numpy array of the form [[x0, y0], [x1, y1]] ax2box = ax2.get_window_extent().get_points() # seems to be expressed in pixels so convert to relative coordinates # print ax2box # figure size in pixels figsize_x_pix = plot.figsize_x * plot.dpi figsize_y_pix = plot.figsize_y * plot.dpi # ax2 box in relative coordinates ax2box[:, 0] = ax2box[:, 0] / figsize_x_pix ax2box[:, 1] = ax2box[:, 1] / figsize_y_pix # print ax2box[0,0], ax2box[1,0], ax2box[0,1], ax2box[1,1] # left position new box at 10% of x1 left = ax2box[0, 0] + ((ax2box[1, 0] - ax2box[0, 0]) * 0.15) bottom = ax2box[0, 1] + ((ax2box[1, 1] - ax2box[0, 1]) * 0.30) # x2 width = (ax2box[1, 0] - ax2box[0, 0]) * 0.35 height = (ax2box[1, 1] - ax2box[0, 1]) * 0.6 # print [left, bottom, width, height] # left inset plot. # [left, bottom, width, height] # ax2a = plot.fig.add_axes([0.42, 0.6, .45, .25]) ax2a = plot.fig.add_axes([left, bottom, width, height]) ax2a.plot((w / np.pi) * nyq_rate, np.absolute(h), linewidth=2) ax2a.set_xlim(0, 8.0) ax2a.set_ylim(0.9985, 1.001) ax2a.grid(True) # right inset plot left = ax2box[0, 0] + ((ax2box[1, 0] - ax2box[0, 0]) * 0.62) bottom = ax2box[0, 1] + ((ax2box[1, 1] - ax2box[0, 1]) * 0.30) # x2 width = (ax2box[1, 0] - ax2box[0, 0]) * 0.35 height = (ax2box[1, 1] - ax2box[0, 1]) * 0.6 # Lower inset plot # ax2b = plot.fig.add_axes([0.42, 0.25, .45, .25]) ax2b = plot.fig.add_axes([left, bottom, width, height]) ax2b.plot((w / np.pi) * nyq_rate, np.absolute(h), linewidth=2) ax2b.set_xlim(12.0, 20.0) ax2b.set_ylim(0.0, 0.0025) ax2b.grid(True) # ------------------------------------------------ # Plot the original and filtered signals. # ------------------------------------------------ # The phase delay of the filtered signal. delay = 0.5 * (N - 1) / sample_rate plot_nr += 1 ax3 = plot.fig.add_subplot(plot.nr_rows, plot.nr_cols, plot_nr) # Plot the original signal. ax3.plot(time, data, label="original signal") # Plot the filtered signal, shifted to compensate for the phase delay. ax3.plot(time - delay, filtered_x, "r-", label="filtered signal") # Plot just the "good" part of the filtered signal. The first N-1 # samples are "corrupted" by the initial conditions. ax3.plot(time[N - 1 :] - delay, filtered_x[N - 1 :], "g", linewidth=4) ax3.set_xlabel("t") ax3.grid(True) plot.save_fig()
def fir(self, time, data, **kwargs): """ Based on the xxample from the SciPy cook boock, see http://www.scipy.org/Cookbook/FIRFilter Parameters ---------- time : ndarray(n) data : ndarray(n) plot : boolean, default=False figpath : str, default=False figfile : str, default=False sample_rate : int, default=None If None, sample rate will be calculated from the given signal freq_trans_width : float, default=1 The desired width of the transition from pass to stop, relative to the Nyquist rate. ripple_db : float, default=10 The desired attenuation in the stop band, in dB. cutoff_hz : float, default=10 Frequencies above cutoff_hz are filtered out Returns ------- filtered_x : ndarray(n - (N-1)) filtered signal N : float order of the firwin filter delay : float phase delay due to the filtering process """ plot = kwargs.get("plot", False) figpath = kwargs.get("figpath", False) figfile = kwargs.get("figfile", False) sample_rate = kwargs.get("sample_rate", None) # The desired width of the transition from pass to stop, # relative to the Nyquist rate. We'll design the filter # with a 5 Hz transition width. freq_trans_width = kwargs.get("freq_trans_width", 1) # The desired attenuation in the stop band, in dB. ripple_db = kwargs.get("ripple_db", 10) # The cutoff frequency of the filter. cutoff_hz = kwargs.get("cutoff_hz", 10) chk.array_1d(time) chk.array_1d(data) if not sample_rate: sample_rate = calc_sample_rate(time) # ------------------------------------------------ # Create a FIR filter and apply it to data[:,channel] # ------------------------------------------------ # The Nyquist rate of the signal. nyq_rate = sample_rate / 2.0 # The desired width of the transition from pass to stop, # relative to the Nyquist rate. We'll design the filter # with a 5 Hz transition width. width = freq_trans_width / nyq_rate # Compute the order and Kaiser parameter for the FIR filter. N, beta = sp.signal.kaiserord(ripple_db, width) # Use firwin with a Kaiser window to create a lowpass FIR filter. taps = sp.signal.firwin(N, cutoff_hz / nyq_rate, window=("kaiser", beta)) # Use lfilter to filter x with the FIR filter. filtered_x = sp.signal.lfilter(taps, 1.0, data) # The phase delay of the filtered signal. delay = 0.5 * (N - 1) / sample_rate # # the filtered signal, shifted to compensate for the phase delay. # time_shifted = time-delay # # the "good" part of the filtered signal. The first N-1 # # samples are "corrupted" by the initial conditions. # time_good = time[N-1:] - delay if plot: self.plot_fir(figpath, figfile, time, data, filtered_x, N, delay, sample_rate, taps, nyq_rate) return filtered_x, N, delay