def __init__(self, fg, parent=None):
        QtGui.QMainWindow.__init__(self, parent)

        self.gui = Ui_MainWindow()
        self.gui.setupUi(self)

        self.fg = fg
        self.first_run = 0

        # Set up plot
        self.gui.plot.setTitle("Spectrum Estimate")
        self.gui.plot.setAxisTitle(Qwt.QwtPlot.xBottom, "Frequency (MHz)")
        self.gui.plot.setAxisTitle(Qwt.QwtPlot.yLeft, "Spectral Power Density (dB)")
        # Grid
        grid = Qwt.QwtPlotGrid()
        pen = Qt.QPen(Qt.Qt.DotLine)
        pen.setColor(Qt.Qt.black)
        pen.setWidth(0)
        grid.setPen(pen)
        grid.attach(self.gui.plot)
        #Curve
        pen_curve = Qt.QPen(Qt.Qt.SolidLine)
        pen_curve.setColor(Qt.Qt.blue)
        pen_curve.setWidth(1)
        self.curve = Qwt.QwtPlotCurve("Power Density")
        self.curve.attach(self.gui.plot)
        self.curve.setPen(pen_curve)

        # Set data in UI
        # General Settings
        self.set_input_selector(self.fg.input_selector())
        self.set_input_tab(self.fg.input_selector())
        self.set_method_selector(self.fg.method_selector())
        self.set_method_tab(self.fg.method_selector())
        self.set_center_f(self.fg.center_frequency())
        self.set_scale(self.fg.get_scale())
        # File Input Settings
        self.set_file_rec_samp_rate(self.fg.file_rec_samp_rate())
        self.set_file_file_to_open(self.fg.file_file_to_open())
        self.set_file_samp_type(self.fg.file_samp_type())
        # UHD Input Settings
        self.set_uhd_samp_type(self.fg.uhd_samp_type())
        self.set_uhd_board_num(self.fg.uhd_board_num())
        self.set_uhd_samp_rate(self.fg.uhd_samp_rate())
        self.set_uhd_gain(self.fg.uhd_gain())
        self.set_uhd_ant(self.fg.uhd_ant())
        self.set_uhd_subdev_spec(self.fg.uhd_subdev_spec())

        # Connect control signals
        self.connect(self.gui.pause_button, QtCore.SIGNAL("clicked()"),
                                 self.pause_flow_graph)
        self.connect(self.gui.run_button, QtCore.SIGNAL("clicked()"),
                                 self.run_flow_graph)
        self.connect(self.gui.close_button, QtCore.SIGNAL("clicked()"),
                                 self.stop_flow_graph)
        # Connect general signals
        self.connect(self.gui.input_selector, QtCore.SIGNAL("currentIndexChanged(int)"),
                                 self.input_selector_text)
        self.connect(self.gui.tabWidget_2, QtCore.SIGNAL("currentChanged(int)"),
                                 self.input_tab_text)
        self.connect(self.gui.method_selector, QtCore.SIGNAL("currentIndexChanged(int)"),
                                 self.method_selector_text)
        self.connect(self.gui.tabWidget, QtCore.SIGNAL("currentChanged(int)"),
                                 self.method_tab_text)
        self.connect(self.gui.center_f, QtCore.SIGNAL("valueChanged(double)"),
                                 self.center_f_text)
        self.connect(self.gui.scale, QtCore.SIGNAL("currentIndexChanged(int)"),
                                 self.scale_text)
        # File Input Signals
        self.connect(self.gui.file_rec_samp_rate, QtCore.SIGNAL("editingFinished()"),
                     self.file_rec_samp_rate_text)
        self.connect(self.gui.file_file_to_open, QtCore.SIGNAL("editingFinished()"),
                     self.file_file_to_open_text)
        self.connect(self.gui.file_samp_type, QtCore.SIGNAL("currentIndexChanged(int)"),
                     self.file_samp_type_text)
        # UHD Input Signals
        self.connect(self.gui.uhd_samp_type, QtCore.SIGNAL("currentIndexChanged(int)"),
                     self.uhd_samp_type_text)
        self.connect(self.gui.uhd_gain, QtCore.SIGNAL("editingFinished()"),
                     self.uhd_gain_text)
        self.connect(self.gui.uhd_samp_rate, QtCore.SIGNAL("editingFinished()"),
                     self.uhd_samp_rate_text)
        self.connect(self.gui.uhd_board_num, QtCore.SIGNAL("editingFinished()"),
                     self.uhd_board_num_text)
        self.connect(self.gui.uhd_ant, QtCore.SIGNAL("editingFinished()"),
                     self.uhd_ant_text)
        self.connect(self.gui.uhd_subdev_spec, QtCore.SIGNAL("editingFinished()"),
                     self.uhd_subdev_spec_text)
        for estimator_name in estimators:
            estimators[estimator_name].connect_gui(self)
        self.__initTracking()
        self.__initZooming()
class SpecEstGUI(QtGui.QMainWindow):
    """ All of this controls the actual GUI. """
    def __init__(self, fg, parent=None):
        QtGui.QMainWindow.__init__(self, parent)

        self.gui = Ui_MainWindow()
        self.gui.setupUi(self)

        self.fg = fg
        self.first_run = 0

        # Set up plot
        self.gui.plot.setTitle("Spectrum Estimate")
        self.gui.plot.setAxisTitle(Qwt.QwtPlot.xBottom, "Frequency (MHz)")
        self.gui.plot.setAxisTitle(Qwt.QwtPlot.yLeft, "Spectral Power Density (dB)")
        # Grid
        grid = Qwt.QwtPlotGrid()
        pen = Qt.QPen(Qt.Qt.DotLine)
        pen.setColor(Qt.Qt.black)
        pen.setWidth(0)
        grid.setPen(pen)
        grid.attach(self.gui.plot)
        #Curve
        pen_curve = Qt.QPen(Qt.Qt.SolidLine)
        pen_curve.setColor(Qt.Qt.blue)
        pen_curve.setWidth(1)
        self.curve = Qwt.QwtPlotCurve("Power Density")
        self.curve.attach(self.gui.plot)
        self.curve.setPen(pen_curve)

        # Set data in UI
        # General Settings
        self.set_input_selector(self.fg.input_selector())
        self.set_input_tab(self.fg.input_selector())
        self.set_method_selector(self.fg.method_selector())
        self.set_method_tab(self.fg.method_selector())
        self.set_center_f(self.fg.center_frequency())
        self.set_scale(self.fg.get_scale())
        # File Input Settings
        self.set_file_rec_samp_rate(self.fg.file_rec_samp_rate())
        self.set_file_file_to_open(self.fg.file_file_to_open())
        self.set_file_samp_type(self.fg.file_samp_type())
        # UHD Input Settings
        self.set_uhd_samp_type(self.fg.uhd_samp_type())
        self.set_uhd_board_num(self.fg.uhd_board_num())
        self.set_uhd_samp_rate(self.fg.uhd_samp_rate())
        self.set_uhd_gain(self.fg.uhd_gain())
        self.set_uhd_ant(self.fg.uhd_ant())
        self.set_uhd_subdev_spec(self.fg.uhd_subdev_spec())

        # Connect control signals
        self.connect(self.gui.pause_button, QtCore.SIGNAL("clicked()"),
                                 self.pause_flow_graph)
        self.connect(self.gui.run_button, QtCore.SIGNAL("clicked()"),
                                 self.run_flow_graph)
        self.connect(self.gui.close_button, QtCore.SIGNAL("clicked()"),
                                 self.stop_flow_graph)
        # Connect general signals
        self.connect(self.gui.input_selector, QtCore.SIGNAL("currentIndexChanged(int)"),
                                 self.input_selector_text)
        self.connect(self.gui.tabWidget_2, QtCore.SIGNAL("currentChanged(int)"),
                                 self.input_tab_text)
        self.connect(self.gui.method_selector, QtCore.SIGNAL("currentIndexChanged(int)"),
                                 self.method_selector_text)
        self.connect(self.gui.tabWidget, QtCore.SIGNAL("currentChanged(int)"),
                                 self.method_tab_text)
        self.connect(self.gui.center_f, QtCore.SIGNAL("valueChanged(double)"),
                                 self.center_f_text)
        self.connect(self.gui.scale, QtCore.SIGNAL("currentIndexChanged(int)"),
                                 self.scale_text)
        # File Input Signals
        self.connect(self.gui.file_rec_samp_rate, QtCore.SIGNAL("editingFinished()"),
                     self.file_rec_samp_rate_text)
        self.connect(self.gui.file_file_to_open, QtCore.SIGNAL("editingFinished()"),
                     self.file_file_to_open_text)
        self.connect(self.gui.file_samp_type, QtCore.SIGNAL("currentIndexChanged(int)"),
                     self.file_samp_type_text)
        # UHD Input Signals
        self.connect(self.gui.uhd_samp_type, QtCore.SIGNAL("currentIndexChanged(int)"),
                     self.uhd_samp_type_text)
        self.connect(self.gui.uhd_gain, QtCore.SIGNAL("editingFinished()"),
                     self.uhd_gain_text)
        self.connect(self.gui.uhd_samp_rate, QtCore.SIGNAL("editingFinished()"),
                     self.uhd_samp_rate_text)
        self.connect(self.gui.uhd_board_num, QtCore.SIGNAL("editingFinished()"),
                     self.uhd_board_num_text)
        self.connect(self.gui.uhd_ant, QtCore.SIGNAL("editingFinished()"),
                     self.uhd_ant_text)
        self.connect(self.gui.uhd_subdev_spec, QtCore.SIGNAL("editingFinished()"),
                     self.uhd_subdev_spec_text)
        for estimator_name in estimators:
            estimators[estimator_name].connect_gui(self)
        self.__initTracking()
        self.__initZooming()

    def plot_data(self, data_x, data_y, rescale_at_sample_num):
        """ Update the plot. """
        self.x = data_x
        self.y = data_y
        self.curve.setData(self.x, self.y)
        if(self.first_run == (rescale_at_sample_num + 1)):
            scale_div = self.gui.plot.axisScaleDiv(Qwt.QwtPlot.yLeft)
            self.gui.plot.setAxisScaleDiv(Qwt.QwtPlot.yLeft, scale_div)
            self.zoomer.setZoomBase()
            self.first_run = self.first_run + 1
        elif(self.first_run == 0):
            self.gui.plot.setAxisAutoScale(Qwt.QwtPlot.yLeft)
            self.gui.plot.setAxisScale(Qwt.QwtPlot.xBottom, self.x.item(1), self.x.item(data_x.size -1))
            self.first_run = 1
        elif(self.first_run == rescale_at_sample_num):
            self.gui.plot.setAxisAutoScale(Qwt.QwtPlot.yLeft)
            self.gui.plot.setAxisScale(Qwt.QwtPlot.xBottom, self.x.item(1), self.x.item(data_x.size -1))
            self.first_run = self.first_run + 1
        elif(self.first_run > 0 and self.first_run < rescale_at_sample_num):
            self.first_run = self.first_run + 1
        self.gui.plot.replot()

    def pause_flow_graph(self):
        """ Pause and unpause the flow graph. """
        if(self.gui.pause_button.text() == "Pause"):
            self.fg.stop()
            self.fg.wait()
            self.gui.pause_button.setText("Unpause")
        else:
            self.fg.start()
            self.gui.pause_button.setText("Pause")

    def run_flow_graph(self):
        """ Init and start the flow graph. """
        self.fg.cpu_watcher = CPUUsageWatcherThread(self)
        self.fg.set_head()
        self.fg.set_decimator()
        self.fg.set_body()
        self.fg.set_decimator()
        self.fg.start()

    def stop_flow_graph(self):
        self.fg.stop()

    # Functions to manipulate parameters in GUI
    def set_input_selector(self, src_type):
        self.gui.input_selector.setCurrentIndex({'File': 0, 'UHD': 1}[src_type])

    def set_input_tab(self, src_type):
        self.gui.tabWidget_2.setCurrentIndex({'File': 0, 'UHD': 1}[src_type])

    def set_method_selector(self, method):
        method_idx = {'Welch': 0, 'Burg': 1, 'fcov': 2, 'fmcov': 3, 'MTM': 4, 'Music': 5, 'Esprit': 6}
        self.gui.method_selector.setCurrentIndex(method_idx[method])

    def set_method_tab(self, method):
        self.gui.tabWidget.setCurrentIndex(ESTIM_TAB_NAMES[method])

    def set_center_f(self, center_f):
        self.gui.center_f.setValue(center_f)

    def set_scale(self, scale):
        self.gui.scale.setCurrentIndex({'Logarithmic': 0, 'Linear': 1}[scale])

    def set_file_rec_samp_rate(self, samp_rate):
        self.gui.file_rec_samp_rate.setText(QtCore.QString("%1").arg(samp_rate))

    def set_file_file_to_open(self, file_to_open):
        self.gui.file_file_to_open.setText(QtCore.QString("%1").arg(file_to_open))

    def set_file_samp_type(self, samp_type):
        if(samp_type == gr.sizeof_gr_complex):
            self.gui.file_samp_type.setCurrentIndex(0)
        elif(samp_type == gr.sizeof_float):
            self.gui.file_samp_type.setCurrentIndex(1)
        else:
            print "Wrong sample-type set!"

    def set_uhd_samp_type(self, samp_type):
        if(samp_type == gr.sizeof_gr_complex):
            self.gui.uhd_samp_type.setCurrentIndex(0)
        elif(samp_type == gr.sizeof_float):
            self.gui.uhd_samp_type.setCurrentIndex(1)
        else:
            print "Wrong sample-type set!"

    def set_uhd_gain(self, gain):
        self.gui.uhd_gain.setValue(gain)

    def set_uhd_board_num(self, board_num):
        self.gui.uhd_board_num.setValue(board_num)

    def set_uhd_samp_rate(self, samp_rate):
        self.gui.uhd_samp_rate.setValue(samp_rate)

    def set_uhd_ant(self, ant):
        self.gui.uhd_ant.setText(QtCore.QString("%1").arg(ant))

    def set_uhd_subdev_spec(self, subdev_spec):
        self.gui.uhd_subdev_spec.setText(QtCore.QString("%1").arg(subdev_spec))

    # Functions to change parameters in flowgraph
    def input_selector_text(self):
        try:
            src_type = str(self.gui.input_selector.currentText())
            self.fg.set_src_type(src_type)
            self.set_input_tab(src_type)
        except RuntimeError:
            pass

    def input_tab_text(self, tab):
        # FIXME Add code to execute, when input-tab changes!
        pass

    def method_selector_text(self):
        try:
            method = str(self.gui.method_selector.currentText())
            self.fg.set_method(method)
            self.set_method_tab(method)
        except RuntimeError:
            pass

    def method_tab_text(self, tab):
        # FIXME Add code to execute, when method-tab changes!
        pass

    def center_f_text(self):
        try:
            center_f = self.gui.center_f.value()
            self.fg.set_center_f(center_f)
        except RuntimeError:
            pass

    def scale_text(self):
        try:
            scale = str(self.gui.scale.currentText())
            self.fg.set_scale(scale)
        except RuntimeError:
            pass

    def file_rec_samp_rate_text(self):
        try:
            rec_samp_rate = self.gui.file_rec_samp_rate.text().toLong()[0]
            self.fg.set_file_rec_samp_rate(rec_samp_rate)
        except RuntimeError:
            pass

    def file_file_to_open_text(self):
        try:
            file_to_open = str(self.gui.file_file_to_open.text())
            self.fg.set_file_to_open(file_to_open)
        except RuntimeError:
            pass

    def file_samp_type_text(self):
        try:
            samp_type = str(self.gui.file_samp_type.currentText())
            self.fg.set_file_samp_type(samp_type)
        except RuntimeError:
            pass

    def uhd_samp_type_text(self):
        try:
            samp_type = str(self.gui.uhd_samp_type.currentText())
            self.fg.set_uhd_samp_type(samp_type)
        except RuntimeError:
            pass

    def uhd_gain_text(self):
        try:
            gain = self.gui.uhd_gain.text().toLong()[0]
            self.fg.set_uhd_gain(gain)
        except RuntimeError:
            pass

    def uhd_board_num_text(self):
        try:
            board_num = self.gui.uhd_board_num.text().toLong()[0]
            self.fg.set_uhd_board_num(board_num)
        except RuntimeError:
            pass

    def uhd_samp_rate_text(self):
        try:
            samp_rate = self.gui.uhd_samp_rate.text().toLong()[0]
            self.fg.set_uhd_samp_rate(samp_rate)
        except RuntimeError:
            pass

    def uhd_ant_text(self):
        try:
            ant = str(self.gui.uhd_ant.text())
            self.fg.set_uhd_ant(ant)
        except RuntimeError:
            pass

    def uhd_subdev_spec_text(self):
        try:
            subdev_spec = str(self.gui.uhd_subdev_spec.text())
            self.fg.set_uhd_subdev_spec(subdev_spec)
        except RuntimeError:
            pass

    # Functions needed for zooming
    def __initTracking(self):
        self.connect(Spy(self.gui.plot.canvas()),
                     Qt.SIGNAL("MouseMove"),
                     self.showCoordinates)

    def showCoordinates(self, position):
        self.statusBar().showMessage(
            'f = %.6g MHz | P = %.6g (dB)'
            % (self.gui.plot.invTransform(Qwt.QwtPlot.xBottom, position.x()),
               self.gui.plot.invTransform(Qwt.QwtPlot.yLeft, position.y())))

    def __initZooming(self):
        self.zoomer = Qwt.QwtPlotZoomer(Qwt.QwtPlot.xBottom,
                                        Qwt.QwtPlot.yLeft,
                                        Qwt.QwtPicker.DragSelection,
                                        Qwt.QwtPicker.ActiveOnly,
                                        self.gui.plot.canvas())
        self.zoomer.setRubberBandPen(Qt.QPen(Qt.Qt.black))
        self.zoomer.initMousePattern(0)