5 from scipy import fftpack
7 print "Please install SciPy to run this script (http://www.scipy.org/)"
11 from PyQt4 import Qt, QtCore, QtGui
12 import PyQt4.Qwt5 as Qwt
13 from optparse import OptionParser
14 from gnuradio import gr, blks2, eng_notation
15 from scipy import fftpack
17 from pyqt_filter import Ui_MainWindow
18 from pyqt_filter_firlpf import Ui_firlpfForm
19 from pyqt_filter_firhpf import Ui_firhpfForm
21 class gr_plot_filter(QtGui.QMainWindow):
22 def __init__(self, qapp, options):
23 QtGui.QWidget.__init__(self, None)
24 self.gui = Ui_MainWindow()
25 self.gui.setupUi(self)
27 self.connect(self.gui.filterTypeComboBox,
28 Qt.SIGNAL("currentIndexChanged(const QString&)"),
29 self.changed_filter_type)
30 self.connect(self.gui.filterDesignTypeComboBox,
31 Qt.SIGNAL("currentIndexChanged(const QString&)"),
32 self.changed_filter_design_type)
34 self.connect(self.gui.designButton,
35 Qt.SIGNAL("released()"),
38 self.connect(self.gui.tabGroup,
39 Qt.SIGNAL("currentChanged(int)"),
42 self.gui.designButton.setShortcut("Return")
46 self.gui.lpfPassBandRippleLabel.setVisible(False)
47 self.gui.lpfPassBandRippleEdit.setVisible(False)
48 self.gui.bpfPassBandRippleLabel.setVisible(False)
49 self.gui.bpfPassBandRippleEdit.setVisible(False)
50 self.gui.hpfPassBandRippleLabel.setVisible(False)
51 self.gui.hpfPassBandRippleEdit.setVisible(False)
54 self.gui.filterTypeWidget.setCurrentWidget(self.gui.firlpfPage)
57 self.rcurve = Qwt.QwtPlotCurve("Real")
58 self.rcurve.attach(self.gui.timePlot)
60 self.freqcurve = Qwt.QwtPlotCurve("PSD")
61 self.freqcurve.attach(self.gui.freqPlot)
63 # Create zoom functionality for the plots
64 self.timeZoomer = Qwt.QwtPlotZoomer(self.gui.timePlot.xBottom,
65 self.gui.timePlot.yLeft,
66 Qwt.QwtPicker.PointSelection,
67 Qwt.QwtPicker.AlwaysOn,
68 self.gui.timePlot.canvas())
70 self.freqZoomer = Qwt.QwtPlotZoomer(self.gui.freqPlot.xBottom,
71 self.gui.freqPlot.yLeft,
72 Qwt.QwtPicker.PointSelection,
73 Qwt.QwtPicker.AlwaysOn,
74 self.gui.freqPlot.canvas())
76 # Set up pen for colors and line width
77 blue = QtGui.qRgb(0x00, 0x00, 0xFF)
78 blueBrush = Qt.QBrush(Qt.QColor(blue))
79 self.freqcurve.setPen(Qt.QPen(blueBrush, 2))
80 self.rcurve.setPen(Qt.QPen(blueBrush, 2))
82 self.filterWindows = {"Hamming Window" : gr.firdes.WIN_HAMMING,
83 "Hann Window" : gr.firdes.WIN_HANN,
84 "Blackman Window" : gr.firdes.WIN_BLACKMAN,
85 "Rectangular Window" : gr.firdes.WIN_RECTANGULAR,
86 "Kaiser Window" : gr.firdes.WIN_KAISER,
87 "Blackman-harris Window" : gr.firdes.WIN_BLACKMAN_hARRIS}
91 def changed_filter_type(self, ftype):
92 strftype = str(ftype.toAscii())
93 if(ftype == "Low Pass"):
94 self.gui.filterTypeWidget.setCurrentWidget(self.gui.firlpfPage)
95 elif(ftype == "Band Pass"):
96 self.gui.filterTypeWidget.setCurrentWidget(self.gui.firbpfPage)
97 elif(ftype == "High Pass"):
98 self.gui.filterTypeWidget.setCurrentWidget(self.gui.firhpfPage)
102 def changed_filter_design_type(self, design):
103 if(design == "Equiripple"):
104 self.set_equiripple()
110 def set_equiripple(self):
111 self.equiripple = True
112 self.gui.lpfPassBandRippleLabel.setVisible(True)
113 self.gui.lpfPassBandRippleEdit.setVisible(True)
114 self.gui.bpfPassBandRippleLabel.setVisible(True)
115 self.gui.bpfPassBandRippleEdit.setVisible(True)
116 self.gui.hpfPassBandRippleLabel.setVisible(True)
117 self.gui.hpfPassBandRippleEdit.setVisible(True)
119 def set_windowed(self):
120 self.equiripple = False
121 self.gui.lpfPassBandRippleLabel.setVisible(False)
122 self.gui.lpfPassBandRippleEdit.setVisible(False)
123 self.gui.bpfPassBandRippleLabel.setVisible(False)
124 self.gui.bpfPassBandRippleEdit.setVisible(False)
125 self.gui.hpfPassBandRippleLabel.setVisible(False)
126 self.gui.hpfPassBandRippleEdit.setVisible(False)
130 fs,r = self.gui.sampleRateEdit.text().toDouble()
132 gain,r = self.gui.filterGainEdit.text().toDouble()
136 winstr = str(self.gui.filterDesignTypeComboBox.currentText().toAscii())
137 ftype = str(self.gui.filterTypeComboBox.currentText().toAscii())
139 if(winstr == "Equiripple"):
140 designer = {"Low Pass" : self.design_opt_lpf,
141 "Band Pass" : self.design_opt_bpf,
142 "High Pass" : self.design_opt_hpf}
143 taps,r = designer[ftype](fs, gain)
146 designer = {"Low Pass" : self.design_win_lpf,
147 "Band Pass" : self.design_win_bpf,
148 "High Pass" : self.design_win_hpf}
149 wintype = self.filterWindows[winstr]
150 taps,r = designer[ftype](fs, gain, wintype)
153 self.update_time_curves(taps)
154 self.update_freq_curves(taps)
157 # Filter design functions using a window
158 def design_win_lpf(self, fs, gain, wintype):
160 pb,r = self.gui.endofLpfPassBandEdit.text().toDouble()
162 sb,r = self.gui.startofLpfStopBandEdit.text().toDouble()
164 atten,r = self.gui.lpfStopBandAttenEdit.text().toDouble()
170 taps = gr.firdes.low_pass_2(gain, fs, pb, tb,
176 def design_win_bpf(self, fs, gain, wintype):
178 pb1,r = self.gui.startofBpfPassBandEdit.text().toDouble()
180 pb2,r = self.gui.endofBpfPassBandEdit.text().toDouble()
182 tb,r = self.gui.bpfTransitionEdit.text().toDouble()
184 atten,r = self.gui.bpfStopBandAttenEdit.text().toDouble()
188 taps = gr.firdes.band_pass_2(gain, fs, pb1, pb2, tb,
194 def design_win_hpf(self, fs, gain, wintype):
196 sb,r = self.gui.endofHpfStopBandEdit.text().toDouble()
198 pb,r = self.gui.startofHpfPassBandEdit.text().toDouble()
200 atten,r = self.gui.hpfStopBandAttenEdit.text().toDouble()
205 taps = gr.firdes.high_pass_2(gain, fs, pb, tb,
213 # Design Functions for Equiripple Filters
214 def design_opt_lpf(self, fs, gain, wintype=None):
216 pb,r = self.gui.endofLpfPassBandEdit.text().toDouble()
218 sb,r = self.gui.startofLpfStopBandEdit.text().toDouble()
220 atten,r = self.gui.lpfStopBandAttenEdit.text().toDouble()
222 ripple,r = self.gui.lpfPassBandRippleEdit.text().toDouble()
226 taps = blks2.optfir.low_pass(gain, fs, pb, sb,
232 def design_opt_bpf(self, fs, gain, wintype=None):
234 pb1,r = self.gui.startofBpfPassBandEdit.text().toDouble()
236 pb2,r = self.gui.endofBpfPassBandEdit.text().toDouble()
238 tb,r = self.gui.bpfTransitionEdit.text().toDouble()
240 atten,r = self.gui.bpfStopBandAttenEdit.text().toDouble()
242 ripple,r = self.gui.bpfPassBandRippleEdit.text().toDouble()
248 taps = blks2.optfir.band_pass(gain, fs, sb1, pb1, pb2, sb2,
254 def design_opt_hpf(self, fs, gain, wintype=None):
256 sb,r = self.gui.endofHpfStopBandEdit.text().toDouble()
258 pb,r = self.gui.startofHpfPassBandEdit.text().toDouble()
260 atten,r = self.gui.hpfStopBandAttenEdit.text().toDouble()
262 ripple,r = self.gui.hpfPassBandRippleEdit.text().toDouble()
266 taps = blks2.optfir.high_pass(gain, fs, sb, pb,
272 def tab_changed(self, tab):
274 self.update_freq_curves(self.taps)
276 self.update_time_curves(self.taps)
278 def update_time_curves(self, taps):
282 self.rcurve.setData(scipy.arange(ntaps), taps)
284 # Reset the x-axis to the new time scale
285 ymax = 1.5 * max(taps)
286 ymin = 1.5 * min(taps)
287 self.gui.timePlot.setAxisScale(self.gui.timePlot.xBottom,
289 self.gui.timePlot.setAxisScale(self.gui.timePlot.yLeft,
292 # Set the zoomer base to unzoom to the new axis
293 rect = Qt.QRectF(0, ymin, (ntaps-0), (ymax-ymin))
294 self.timeZoomer.setZoomBase(rect)
296 self.gui.timePlot.replot()
298 def update_freq_curves(self, taps, Npts=1000):
300 fftpts = fftpack.fft(taps, Npts)
301 freq = scipy.arange(0, Npts)
303 fftdB = 20.0*scipy.log10(abs(fftpts))
305 self.freqcurve.setData(freq, fftdB)
307 # Reset the x-axis to the new time scale
308 ymax = 1.5 * max(fftdB)
309 ymin = 1.5 * min(fftdB)
310 self.gui.freqPlot.setAxisScale(self.gui.freqPlot.xBottom,
312 self.gui.timePlot.setAxisScale(self.gui.timePlot.yLeft,
315 # Set the zoomer base to unzoom to the new axis
316 self.freqZoomer.setZoomBase()
318 self.gui.freqPlot.replot()
322 usage="%prog: [options] (input_filename)"
325 parser = OptionParser(conflict_handler="resolve",
326 usage=usage, description=description)
330 parser = setup_options()
331 (options, args) = parser.parse_args ()
333 app = Qt.QApplication(args)
334 gplt = gr_plot_filter(app, options)
337 if __name__ == '__main__':