changes from running bootstrap and then make maintainer-clean
[debian/gnuradio] / gr-utils / src / python / gr_filter_design.py
index 2d0c72c7621e73dd16ad83db52ddcadb6ba24d7f..bf83cf69f6c9e4185263b84025445ba93d66dd6e 100755 (executable)
@@ -1,5 +1,9 @@
 #!/usr/bin/env python
 
+import sys, os
+from optparse import OptionParser
+from gnuradio import gr, blks2, eng_notation
+
 try:
     import scipy
     from scipy import fftpack
@@ -7,16 +11,24 @@ except ImportError:
     print "Please install SciPy to run this script (http://www.scipy.org/)"
     raise SystemExit, 1
 
-import sys, os
-from PyQt4 import Qt, QtCore, QtGui
-import PyQt4.Qwt5 as Qwt
-from optparse import OptionParser
-from gnuradio import gr, blks2, eng_notation
-from scipy import fftpack
+try:
+    from PyQt4 import Qt, QtCore, QtGui
+except ImportError:
+    print "Please install PyQt4 to run this script (http://www.riverbankcomputing.co.uk/software/pyqt/download)"
+    raise SystemExit, 1
+
+try:
+    import PyQt4.Qwt5 as Qwt
+except ImportError:
+    print "Please install PyQwt5 to run this script (http://pyqwt.sourceforge.net/)"
+    raise SystemExit, 1
+
+try:
+    from pyqt_filter import Ui_MainWindow
+except ImportError:
+    print "Could not import from pyqt_filter. Please build with \"pyuic4 pyqt_filter.ui -o pyqt_filter.py\""
+    raise SystemExit, 1
 
-from pyqt_filter import Ui_MainWindow
-from pyqt_filter_firlpf import Ui_firlpfForm
-from pyqt_filter_firhpf import Ui_firhpfForm
 
 class gr_plot_filter(QtGui.QMainWindow):
     def __init__(self, qapp, options):
@@ -43,7 +55,7 @@ class gr_plot_filter(QtGui.QMainWindow):
                      Qt.SIGNAL("textEdited(QString)"),
                      self.nfft_edit_changed)
 
-        self.gui.designButton.setShortcut("Return")
+        self.gui.designButton.setShortcut(QtCore.Qt.Key_Return)
 
         self.taps = []
         self.fftdB = []
@@ -52,12 +64,12 @@ class gr_plot_filter(QtGui.QMainWindow):
         self.nfftpts = int(10000)
         self.gui.nfftEdit.setText(Qt.QString("%1").arg(self.nfftpts))
 
-        self.gui.lpfPassBandRippleLabel.setVisible(False)
-        self.gui.lpfPassBandRippleEdit.setVisible(False)
-        self.gui.bpfPassBandRippleLabel.setVisible(False)
-        self.gui.bpfPassBandRippleEdit.setVisible(False)
-        self.gui.hpfPassBandRippleLabel.setVisible(False)
-        self.gui.hpfPassBandRippleEdit.setVisible(False)
+        self.firFilters = ("Low Pass", "Band Pass", "Complex Band Pass", "Band Notch",
+                           "High Pass", "Root Raised Cosine", "Gaussian")
+        self.optFilters = ("Low Pass", "Band Pass", "Complex Band Pass",
+                           "Band Notch", "High Pass")
+        
+        self.set_windowed()
                 
         # Initialize to LPF
         self.gui.filterTypeWidget.setCurrentWidget(self.gui.firlpfPage)
@@ -123,11 +135,47 @@ class gr_plot_filter(QtGui.QMainWindow):
         # Set up pen for colors and line width
         blue = QtGui.qRgb(0x00, 0x00, 0xFF)
         blueBrush = Qt.QBrush(Qt.QColor(blue))
+        red = QtGui.qRgb(0xFF, 0x00, 0x00)
+        redBrush = Qt.QBrush(Qt.QColor(red))
         self.freqcurve.setPen(Qt.QPen(blueBrush, 2))
         self.rcurve.setPen(Qt.QPen(blueBrush, 2))
+        self.icurve.setPen(Qt.QPen(redBrush, 2))
         self.phasecurve.setPen(Qt.QPen(blueBrush, 2))
         self.groupcurve.setPen(Qt.QPen(blueBrush, 2))
-        
+
+        # Set up validators for edit boxes
+        self.intVal = Qt.QIntValidator(None)
+        self.dblVal = Qt.QDoubleValidator(None)
+        self.gui.nfftEdit.setValidator(self.intVal)
+        self.gui.sampleRateEdit.setValidator(self.dblVal)
+        self.gui.filterGainEdit.setValidator(self.dblVal)
+        self.gui.endofLpfPassBandEdit.setValidator(self.dblVal)
+        self.gui.startofLpfStopBandEdit.setValidator(self.dblVal)
+        self.gui.lpfStopBandAttenEdit.setValidator(self.dblVal)
+        self.gui.lpfPassBandRippleEdit.setValidator(self.dblVal)
+        self.gui.startofBpfPassBandEdit.setValidator(self.dblVal)
+        self.gui.endofBpfPassBandEdit.setValidator(self.dblVal)
+        self.gui.bpfTransitionEdit.setValidator(self.dblVal)
+        self.gui.bpfStopBandAttenEdit.setValidator(self.dblVal)
+        self.gui.bpfPassBandRippleEdit.setValidator(self.dblVal)
+        self.gui.startofBnfStopBandEdit.setValidator(self.dblVal)
+        self.gui.endofBnfStopBandEdit.setValidator(self.dblVal)
+        self.gui.bnfTransitionEdit.setValidator(self.dblVal)
+        self.gui.bnfStopBandAttenEdit.setValidator(self.dblVal)
+        self.gui.bnfPassBandRippleEdit.setValidator(self.dblVal)
+        self.gui.endofHpfStopBandEdit.setValidator(self.dblVal)
+        self.gui.startofHpfPassBandEdit.setValidator(self.dblVal)
+        self.gui.hpfStopBandAttenEdit.setValidator(self.dblVal)
+        self.gui.hpfPassBandRippleEdit.setValidator(self.dblVal)
+        self.gui.rrcSymbolRateEdit.setValidator(self.dblVal)
+        self.gui.rrcAlphaEdit.setValidator(self.dblVal)
+        self.gui.rrcNumTapsEdit.setValidator(self.dblVal)
+        self.gui.gausSymbolRateEdit.setValidator(self.dblVal)
+        self.gui.gausBTEdit.setValidator(self.dblVal)
+        self.gui.gausNumTapsEdit.setValidator(self.dblVal)
+
+        self.gui.nTapsEdit.setText("0")
+
         self.filterWindows = {"Hamming Window" : gr.firdes.WIN_HAMMING,
                               "Hann Window" : gr.firdes.WIN_HANN,
                               "Blackman Window" : gr.firdes.WIN_BLACKMAN,
@@ -151,6 +199,8 @@ class gr_plot_filter(QtGui.QMainWindow):
             self.gui.filterTypeWidget.setCurrentWidget(self.gui.firhpfPage)
         elif(ftype == "Root Raised Cosine"):
             self.gui.filterTypeWidget.setCurrentWidget(self.gui.rrcPage)
+        elif(ftype == "Gaussian"):
+            self.gui.filterTypeWidget.setCurrentWidget(self.gui.gausPage)
 
         self.design()
         
@@ -163,23 +213,71 @@ class gr_plot_filter(QtGui.QMainWindow):
         self.design()
 
     def set_equiripple(self):
+        # Stop sending the signal for this function
+        self.gui.filterTypeComboBox.blockSignals(True)
+        
         self.equiripple = True
         self.gui.lpfPassBandRippleLabel.setVisible(True)
         self.gui.lpfPassBandRippleEdit.setVisible(True)
         self.gui.bpfPassBandRippleLabel.setVisible(True)
         self.gui.bpfPassBandRippleEdit.setVisible(True)
+        self.gui.bnfPassBandRippleLabel.setVisible(True)
+        self.gui.bnfPassBandRippleEdit.setVisible(True)
         self.gui.hpfPassBandRippleLabel.setVisible(True)
         self.gui.hpfPassBandRippleEdit.setVisible(True)
+
+        # Save current type and repopulate the combo box for
+        # filters this window type can handle
+        currenttype = self.gui.filterTypeComboBox.currentText()
+        items = self.gui.filterTypeComboBox.count()
+        for i in xrange(items):
+            self.gui.filterTypeComboBox.removeItem(0)
+        self.gui.filterTypeComboBox.addItems(self.optFilters)
+
+        # If the last filter type was valid for this window type,
+        # go back to it; otherwise, reset
+        try:
+            index = self.optFilters.index(currenttype)
+            self.gui.filterTypeComboBox.setCurrentIndex(index)
+        except ValueError:
+            pass
+
+        # Tell gui its ok to start sending this signal again
+        self.gui.filterTypeComboBox.blockSignals(False)
         
     def set_windowed(self):
+        # Stop sending the signal for this function
+        self.gui.filterTypeComboBox.blockSignals(True)
+        
         self.equiripple = False
         self.gui.lpfPassBandRippleLabel.setVisible(False)
         self.gui.lpfPassBandRippleEdit.setVisible(False)
         self.gui.bpfPassBandRippleLabel.setVisible(False)
         self.gui.bpfPassBandRippleEdit.setVisible(False)
+        self.gui.bnfPassBandRippleLabel.setVisible(False)
+        self.gui.bnfPassBandRippleEdit.setVisible(False)
         self.gui.hpfPassBandRippleLabel.setVisible(False)
         self.gui.hpfPassBandRippleEdit.setVisible(False)
-        
+
+        # Save current type and repopulate the combo box for
+        # filters this window type can handle
+        currenttype = self.gui.filterTypeComboBox.currentText()
+        items = self.gui.filterTypeComboBox.count()
+        for i in xrange(items):
+            self.gui.filterTypeComboBox.removeItem(0)
+        self.gui.filterTypeComboBox.addItems(self.firFilters)
+
+        # If the last filter type was valid for this window type,
+        # go back to it; otherwise, reset
+        try:
+            index = self.optFilters.index(currenttype)
+            self.gui.filterTypeComboBox.setCurrentIndex(index)
+        except ValueError:
+            pass
+
+        # Tell gui its ok to start sending this signal again
+        self.gui.filterTypeComboBox.blockSignals(False)
+
     def design(self):
         ret = True
         fs,r = self.gui.sampleRateEdit.text().toDouble()
@@ -194,7 +292,9 @@ class gr_plot_filter(QtGui.QMainWindow):
             if(winstr == "Equiripple"):
                 designer = {"Low Pass" : self.design_opt_lpf,
                             "Band Pass" : self.design_opt_bpf,
-                            "High Pass" :  self.design_opt_hpf}        
+                            "Complex Band Pass" : self.design_opt_cbpf,
+                            "Band Notch" : self.design_opt_bnf,
+                            "High Pass" :  self.design_opt_hpf}
                 taps,r = designer[ftype](fs, gain)
 
             else:
@@ -203,7 +303,8 @@ class gr_plot_filter(QtGui.QMainWindow):
                             "Complex Band Pass" : self.design_win_cbpf,
                             "Band Notch" : self.design_win_bnf,
                             "High Pass" :  self.design_win_hpf,
-                            "Root Raised Cosine" :  self.design_win_rrc}
+                            "Root Raised Cosine" :  self.design_win_rrc,
+                            "Gaussian" :  self.design_win_gaus}
                 wintype = self.filterWindows[winstr]
                 taps,r = designer[ftype](fs, gain, wintype)
 
@@ -215,6 +316,9 @@ class gr_plot_filter(QtGui.QMainWindow):
                 self.update_phase_curves()
                 self.update_group_curves()
 
+                self.gui.nTapsEdit.setText(Qt.QString("%1").arg(self.taps.size))
+
+
     # Filter design functions using a window
     def design_win_lpf(self, fs, gain, wintype):
         ret = True
@@ -321,8 +425,24 @@ class gr_plot_filter(QtGui.QMainWindow):
         else:
             return ([],r)
 
+    def design_win_gaus(self, fs, gain, wintype):
+        ret = True
+        sr,r = self.gui.gausSymbolRateEdit.text().toDouble()
+        ret = r and ret
+        bt,r = self.gui.gausBTEdit.text().toDouble()
+        ret = r and ret
+        ntaps,r = self.gui.gausNumTapsEdit.text().toInt()
+        ret = r and ret
+
+        if(r):
+            spb = fs / sr
+            taps = gr.firdes.gaussian(gain, spb, bt, ntaps)
+            return (taps,r)
+        else:
+            return ([],r)
+
     # Design Functions for Equiripple Filters
-    def design_opt_lpf(self, fs, gain, wintype=None):
+    def design_opt_lpf(self, fs, gain):
         ret = True
         pb,r = self.gui.endofLpfPassBandEdit.text().toDouble()
         ret = r and ret
@@ -340,7 +460,7 @@ class gr_plot_filter(QtGui.QMainWindow):
         else:
             return ([], ret)
     
-    def design_opt_bpf(self, fs, gain, wintype=None):
+    def design_opt_bpf(self, fs, gain):
         ret = True
         pb1,r = self.gui.startofBpfPassBandEdit.text().toDouble()
         ret = r and ret
@@ -362,7 +482,51 @@ class gr_plot_filter(QtGui.QMainWindow):
         else:
             return ([],r)
 
-    def design_opt_hpf(self, fs, gain, wintype=None):
+    def design_opt_cbpf(self, fs, gain):
+        ret = True
+        pb1,r = self.gui.startofBpfPassBandEdit.text().toDouble()
+        ret = r and ret
+        pb2,r = self.gui.endofBpfPassBandEdit.text().toDouble()
+        ret = r and ret
+        tb,r  = self.gui.bpfTransitionEdit.text().toDouble()
+        ret = r and ret
+        atten,r = self.gui.bpfStopBandAttenEdit.text().toDouble()
+        ret = r and ret
+        ripple,r = self.gui.bpfPassBandRippleEdit.text().toDouble()
+        ret = r and ret
+
+        if(r):
+            sb1 = pb1 - tb
+            sb2 = pb2 + tb
+            taps = blks2.optfir.complex_band_pass(gain, fs, sb1, pb1, pb2, sb2,
+                                                  ripple, atten)
+            return (taps,r)
+        else:
+            return ([],r)
+
+    def design_opt_bnf(self, fs, gain):
+        ret = True
+        sb1,r = self.gui.startofBnfStopBandEdit.text().toDouble()
+        ret = r and ret
+        sb2,r = self.gui.endofBnfStopBandEdit.text().toDouble()
+        ret = r and ret
+        tb,r  = self.gui.bnfTransitionEdit.text().toDouble()
+        ret = r and ret
+        atten,r = self.gui.bnfStopBandAttenEdit.text().toDouble()
+        ret = r and ret
+        ripple,r = self.gui.bnfPassBandRippleEdit.text().toDouble()
+        ret = r and ret
+
+        if(r):
+            pb1 = sb1 - tb
+            pb2 = sb2 + tb
+            taps = blks2.optfir.band_reject(gain, fs, pb1, sb1, sb2, pb2,
+                                            ripple, atten)
+            return (taps,r)
+        else:
+            return ([],r)
+
+    def design_opt_hpf(self, fs, gain):
         ret = True
         sb,r = self.gui.endofHpfStopBandEdit.text().toDouble()
         ret = r and ret