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.connect(self.gui.nfftEdit,
43 Qt.SIGNAL("textEdited(QString)"),
44 self.nfft_edit_changed)
46 self.gui.designButton.setShortcut("Return")
49 self.nfftpts = int(10000)
50 self.gui.nfftEdit.setText(Qt.QString("%1").arg(self.nfftpts))
52 self.gui.lpfPassBandRippleLabel.setVisible(False)
53 self.gui.lpfPassBandRippleEdit.setVisible(False)
54 self.gui.bpfPassBandRippleLabel.setVisible(False)
55 self.gui.bpfPassBandRippleEdit.setVisible(False)
56 self.gui.hpfPassBandRippleLabel.setVisible(False)
57 self.gui.hpfPassBandRippleEdit.setVisible(False)
60 self.gui.filterTypeWidget.setCurrentWidget(self.gui.firlpfPage)
63 self.rcurve = Qwt.QwtPlotCurve("Real")
64 self.rcurve.attach(self.gui.timePlot)
66 self.freqcurve = Qwt.QwtPlotCurve("PSD")
67 self.freqcurve.attach(self.gui.freqPlot)
69 # Create zoom functionality for the plots
70 self.timeZoomer = Qwt.QwtPlotZoomer(self.gui.timePlot.xBottom,
71 self.gui.timePlot.yLeft,
72 Qwt.QwtPicker.PointSelection,
73 Qwt.QwtPicker.AlwaysOn,
74 self.gui.timePlot.canvas())
76 self.freqZoomer = Qwt.QwtPlotZoomer(self.gui.freqPlot.xBottom,
77 self.gui.freqPlot.yLeft,
78 Qwt.QwtPicker.PointSelection,
79 Qwt.QwtPicker.AlwaysOn,
80 self.gui.freqPlot.canvas())
82 self.phaseZoomer = Qwt.QwtPlotZoomer(self.gui.phasePlot.xBottom,
83 self.gui.phasePlot.yLeft,
84 Qwt.QwtPicker.PointSelection,
85 Qwt.QwtPicker.AlwaysOn,
86 self.gui.phasePlot.canvas())
88 self.groupZoomer = Qwt.QwtPlotZoomer(self.gui.groupPlot.xBottom,
89 self.gui.groupPlot.yLeft,
90 Qwt.QwtPicker.PointSelection,
91 Qwt.QwtPicker.AlwaysOn,
92 self.gui.groupPlot.canvas())
94 # Set up pen for colors and line width
95 blue = QtGui.qRgb(0x00, 0x00, 0xFF)
96 blueBrush = Qt.QBrush(Qt.QColor(blue))
97 self.freqcurve.setPen(Qt.QPen(blueBrush, 2))
98 self.rcurve.setPen(Qt.QPen(blueBrush, 2))
100 self.filterWindows = {"Hamming Window" : gr.firdes.WIN_HAMMING,
101 "Hann Window" : gr.firdes.WIN_HANN,
102 "Blackman Window" : gr.firdes.WIN_BLACKMAN,
103 "Rectangular Window" : gr.firdes.WIN_RECTANGULAR,
104 "Kaiser Window" : gr.firdes.WIN_KAISER,
105 "Blackman-harris Window" : gr.firdes.WIN_BLACKMAN_hARRIS}
109 def changed_filter_type(self, ftype):
110 strftype = str(ftype.toAscii())
111 if(ftype == "Low Pass"):
112 self.gui.filterTypeWidget.setCurrentWidget(self.gui.firlpfPage)
113 elif(ftype == "Band Pass"):
114 self.gui.filterTypeWidget.setCurrentWidget(self.gui.firbpfPage)
115 elif(ftype == "High Pass"):
116 self.gui.filterTypeWidget.setCurrentWidget(self.gui.firhpfPage)
120 def changed_filter_design_type(self, design):
121 if(design == "Equiripple"):
122 self.set_equiripple()
128 def set_equiripple(self):
129 self.equiripple = True
130 self.gui.lpfPassBandRippleLabel.setVisible(True)
131 self.gui.lpfPassBandRippleEdit.setVisible(True)
132 self.gui.bpfPassBandRippleLabel.setVisible(True)
133 self.gui.bpfPassBandRippleEdit.setVisible(True)
134 self.gui.hpfPassBandRippleLabel.setVisible(True)
135 self.gui.hpfPassBandRippleEdit.setVisible(True)
137 def set_windowed(self):
138 self.equiripple = False
139 self.gui.lpfPassBandRippleLabel.setVisible(False)
140 self.gui.lpfPassBandRippleEdit.setVisible(False)
141 self.gui.bpfPassBandRippleLabel.setVisible(False)
142 self.gui.bpfPassBandRippleEdit.setVisible(False)
143 self.gui.hpfPassBandRippleLabel.setVisible(False)
144 self.gui.hpfPassBandRippleEdit.setVisible(False)
148 fs,r = self.gui.sampleRateEdit.text().toDouble()
150 gain,r = self.gui.filterGainEdit.text().toDouble()
154 winstr = str(self.gui.filterDesignTypeComboBox.currentText().toAscii())
155 ftype = str(self.gui.filterTypeComboBox.currentText().toAscii())
157 if(winstr == "Equiripple"):
158 designer = {"Low Pass" : self.design_opt_lpf,
159 "Band Pass" : self.design_opt_bpf,
160 "High Pass" : self.design_opt_hpf}
161 taps,r = designer[ftype](fs, gain)
164 designer = {"Low Pass" : self.design_win_lpf,
165 "Band Pass" : self.design_win_bpf,
166 "High Pass" : self.design_win_hpf}
167 wintype = self.filterWindows[winstr]
168 taps,r = designer[ftype](fs, gain, wintype)
171 self.update_time_curves(taps)
172 self.update_freq_curves(taps, self.nfftpts)
175 # Filter design functions using a window
176 def design_win_lpf(self, fs, gain, wintype):
178 pb,r = self.gui.endofLpfPassBandEdit.text().toDouble()
180 sb,r = self.gui.startofLpfStopBandEdit.text().toDouble()
182 atten,r = self.gui.lpfStopBandAttenEdit.text().toDouble()
188 taps = gr.firdes.low_pass_2(gain, fs, pb, tb,
194 def design_win_bpf(self, fs, gain, wintype):
196 pb1,r = self.gui.startofBpfPassBandEdit.text().toDouble()
198 pb2,r = self.gui.endofBpfPassBandEdit.text().toDouble()
200 tb,r = self.gui.bpfTransitionEdit.text().toDouble()
202 atten,r = self.gui.bpfStopBandAttenEdit.text().toDouble()
206 taps = gr.firdes.band_pass_2(gain, fs, pb1, pb2, tb,
212 def design_win_hpf(self, fs, gain, wintype):
214 sb,r = self.gui.endofHpfStopBandEdit.text().toDouble()
216 pb,r = self.gui.startofHpfPassBandEdit.text().toDouble()
218 atten,r = self.gui.hpfStopBandAttenEdit.text().toDouble()
223 taps = gr.firdes.high_pass_2(gain, fs, pb, tb,
231 # Design Functions for Equiripple Filters
232 def design_opt_lpf(self, fs, gain, wintype=None):
234 pb,r = self.gui.endofLpfPassBandEdit.text().toDouble()
236 sb,r = self.gui.startofLpfStopBandEdit.text().toDouble()
238 atten,r = self.gui.lpfStopBandAttenEdit.text().toDouble()
240 ripple,r = self.gui.lpfPassBandRippleEdit.text().toDouble()
244 taps = blks2.optfir.low_pass(gain, fs, pb, sb,
250 def design_opt_bpf(self, fs, gain, wintype=None):
252 pb1,r = self.gui.startofBpfPassBandEdit.text().toDouble()
254 pb2,r = self.gui.endofBpfPassBandEdit.text().toDouble()
256 tb,r = self.gui.bpfTransitionEdit.text().toDouble()
258 atten,r = self.gui.bpfStopBandAttenEdit.text().toDouble()
260 ripple,r = self.gui.bpfPassBandRippleEdit.text().toDouble()
266 taps = blks2.optfir.band_pass(gain, fs, sb1, pb1, pb2, sb2,
272 def design_opt_hpf(self, fs, gain, wintype=None):
274 sb,r = self.gui.endofHpfStopBandEdit.text().toDouble()
276 pb,r = self.gui.startofHpfPassBandEdit.text().toDouble()
278 atten,r = self.gui.hpfStopBandAttenEdit.text().toDouble()
280 ripple,r = self.gui.hpfPassBandRippleEdit.text().toDouble()
284 taps = blks2.optfir.high_pass(gain, fs, sb, pb,
290 def nfft_edit_changed(self, nfft):
291 infft,r = nfft.toInt()
292 if(r and (infft != self.nfftpts)):
294 self.update_freq_curves(self.taps, self.nfftpts)
296 def tab_changed(self, tab):
298 self.update_freq_curves(self.taps, self.nfftpts)
300 self.update_time_curves(self.taps)
302 def update_time_curves(self, taps):
306 self.rcurve.setData(scipy.arange(ntaps), taps)
308 # Reset the x-axis to the new time scale
309 ymax = 1.5 * max(taps)
310 ymin = 1.5 * min(taps)
311 self.gui.timePlot.setAxisScale(self.gui.timePlot.xBottom,
313 self.gui.timePlot.setAxisScale(self.gui.timePlot.yLeft,
316 # Set the zoomer base to unzoom to the new axis
317 self.timeZoomer.setZoomBase()
319 self.gui.timePlot.replot()
321 def update_freq_curves(self, taps, Npts=1000):
323 fftpts = fftpack.fft(taps, Npts)
324 freq = scipy.arange(0, Npts)
326 fftdB = 20.0*scipy.log10(abs(fftpts))
328 self.freqcurve.setData(freq, fftdB)
330 # Reset the x-axis to the new time scale
331 ymax = 1.5 * max(fftdB)
332 ymin = 1.5 * min(fftdB)
333 self.gui.freqPlot.setAxisScale(self.gui.freqPlot.xBottom,
335 self.gui.timePlot.setAxisScale(self.gui.timePlot.yLeft,
338 # Set the zoomer base to unzoom to the new axis
339 self.freqZoomer.setZoomBase()
341 self.gui.freqPlot.replot()
345 usage="%prog: [options] (input_filename)"
348 parser = OptionParser(conflict_handler="resolve",
349 usage=usage, description=description)
353 parser = setup_options()
354 (options, args) = parser.parse_args ()
356 app = Qt.QApplication(args)
357 gplt = gr_plot_filter(app, options)
360 if __name__ == '__main__':