Example #1
0
 def connect_scope(self):
     # choose configuration file
     try:
         self.config_file = QFileDialog.getOpenFileName(self, 
             "Choose config file")
         pico_serial_num, params_dict = read_config(self.config_file)
         file_found = True
     except:
         QMessageBox.about(self, "File error", "File not in expected format")
         return 0
     # Open picoscope
     try:
         # picoscope = TestPs3000a(pico_serial_num) #ps3000a.PS3000a(pico_serial_num)
         picoscope = ps3000a.PS3000a(pico_serial_num)
     except:
         msg = "Could not connect to PicoScope " + pico_serial_num
         QMessageBox.about(self, "Connection error", msg)
         return 0
     # self.radar_scope = TestRadarScope(picoscope, **params_dict)
     self.radar_scope = RadarScope(picoscope, **params_dict)
     self.data_q = Queue.Queue()
     self.acq_thread = DataAcquisitionThread(self.data_q, self.radar_scope)
     self.proc_thread = DataProcessingThread(self.data_q, self.radar_scope, self)
     self.acq_thread.setDaemon(True)
     self.proc_thread.setDaemon(True)
     self.acq_thread.start()
     self.proc_thread.start()
     self.status_text.setText("Connected")
     return 1
Example #2
0
class RadarConsole(QMainWindow):
    def __init__(self, parent=None):
        QMainWindow.__init__(self, parent)
        self.setWindowTitle("Radar Console")
        self.create_menu()
        self.create_main_frame()
        self.create_status_bar()
        # self.connect_scope()
        # self.update_ppi()
        self.radar_scope = None
        self.data = None
        self.timestamp = None
        self.cmap = cm.jet
        self.output_dir = os.getcwd()
        self.file_text.setText(self.output_dir)
        self.timer = QTimer(self)
        self.timer.timeout.connect(self.update_clock)
        self.timer.start(1000)
        self.recording = False

    def on_about(self):
        msg = """
        WE'VE GOT A THING THAT'S CALLED RADAR LOVE\nWE'VE GOT A LINE IN THE SKY\nRADAR LOVE
        """
        QMessageBox.about(self, "ABOUT", msg.strip())

    def update_clock(self):
        self.time_text.setText(time.strftime(CLOCK_FMT))

    def update_ppi(self):
        """
        Redraws the figure
        """
        # if self.data is None:
        #     self.data = self.radar_scope.get_trimmed_sweep()
        sub_R = 1
        sub_theta = 5
        data_to_plot = self.data[::sub_theta, ::sub_R]
        theta = sp.linspace(2 * sp.pi, 0.0, data_to_plot.shape[0])
        # theta = sp.hstack((theta[100:400], theta[0:100]))
        R = sp.arange(data_to_plot.shape[1])

        # clear the axes and redraw the plot
        self.axes.clear()        
        self.axes.pcolormesh(theta, R, data_to_plot.T, vmin=self.vmin_spin_box.value(),
            vmax=self.vmax_spin_box.value(), cmap=self.cmap)
        self.canvas.draw()
    
    def create_main_frame(self):
        self.main_frame = QWidget()
        # Create the mpl Figure and FigCanvas objects.
        self.fig = Figure()
        self.canvas = FigureCanvas(self.fig)
        self.canvas.setParent(self.main_frame)
        self.axes = self.fig.add_subplot(111, polar=True)   
        # Create the navigation toolbar, tied to the canvas
        self.mpl_toolbar = NavigationToolbar(self.canvas, self.main_frame)

        # control panel
        self.recordBtn = QPushButton("&Record", self)
        self.recordBtn.setCheckable(True)
        self.recordBtn.clicked[bool].connect(self.setRecording)

        self.capture_button = QPushButton("&Capture")
        self.capture_button.setCheckable(True)
        self.capture_button.clicked[bool].connect(self.capture_sweep) 

        self.colormap_combo_box = QComboBox()
        for cmap in ["jet", "spectral", "copper"]:
            self.colormap_combo_box.addItem(cmap)
        self.connect(self.colormap_combo_box, SIGNAL("activated(QString)"), 
            self.set_cmap)

        self.vmin_spin_box = QDoubleSpinBox()
        self.vmax_spin_box = QDoubleSpinBox()
        for w in [self.vmin_spin_box, self.vmax_spin_box]:
            w.setMinimum(-1000.0)
            w.setMaximum(30000.0)
            self.connect(w, SIGNAL("valueChanged(double)"), self.set_cmap_range)
        self.vmin_spin_box.setValue(0.0)
        self.vmax_spin_box.setValue(28000.0)
        vmin_label = QLabel("Scale min")
        vmax_label = QLabel("Scale max")
        colormap_layout = QGridLayout()
        colormap_layout.addWidget(vmin_label, 0, 0)
        colormap_layout.addWidget(vmax_label, 0, 1)
        colormap_layout.addWidget(self.vmin_spin_box, 1, 0)
        colormap_layout.addWidget(self.vmax_spin_box, 1, 1)


        # Layout with box sizers
        controlbox = QVBoxLayout()
        for w in [self.recordBtn, self.capture_button, self.colormap_combo_box]:
            w.setFixedWidth(200)
            controlbox.addWidget(w)
        controlbox.addLayout(colormap_layout)
        controlbox.addStretch(1)

        plotbox = QVBoxLayout()
        plotbox.addWidget(self.canvas)
        plotbox.addWidget(self.mpl_toolbar)

        hbox = QHBoxLayout()
        hbox.addLayout(plotbox)
        hbox.addLayout(controlbox)

        self.main_frame.setLayout(hbox)
        self.setCentralWidget(self.main_frame)
    
    def create_status_bar(self):
        self.status_text = QLabel("Not connected")
        self.file_text = QLabel("some file")
        self.time_text = QLabel(time.strftime(CLOCK_FMT))
        self.statusBar().addWidget(self.status_text, 0.5)
        self.statusBar().addWidget(self.file_text, 1)
        self.statusBar().addWidget(self.time_text)
        
    def create_menu(self):        
        self.file_menu = self.menuBar().addMenu("&File")
        
        set_output_dir_action = self.create_action("&Set output directory",
            shortcut="Ctrl+S", slot=self.set_output_dir, 
            tip="Save the plot")
        connect_scope_action = self.create_action("&Connect scope",
            shortcut="Ctrl+c", slot=self.connect_scope, 
            tip="Connect to digitizing oscilloscope")
        disconnect_scope_action = self.create_action("&Disconnect scope",
            shortcut="Ctrl+d", slot=self.disconnect_scope, 
            tip="Connect to digitizing oscilloscope")
        quit_action = self.create_action("&Quit", slot=self.close, 
            shortcut="Ctrl+Q", tip="Close the application")
        
        self.add_actions(self.file_menu, 
            (set_output_dir_action, connect_scope_action, disconnect_scope_action,
             None, quit_action))
        
        self.help_menu = self.menuBar().addMenu("&Help")
        about_action = self.create_action("&About", 
            shortcut='F1', slot=self.on_about, 
            tip='About the demo')
        
        self.add_actions(self.help_menu, (about_action,))

    def add_actions(self, target, actions):
        for action in actions:
            if action is None:
                target.addSeparator()
            else:
                target.addAction(action)

    def create_action(self, text, slot=None, shortcut=None, 
        icon=None, tip=None, checkable=False, signal="triggered()"):
        action = QAction(text, self)
        if icon is not None:
            action.setIcon(QIcon(":/%s.png" % icon))
        if shortcut is not None:
            action.setShortcut(shortcut)
        if tip is not None:
            action.setToolTip(tip)
            action.setStatusTip(tip)
        if slot is not None:
            self.connect(action, SIGNAL(signal), slot)
        if checkable:
            action.setCheckable(True)
        return action

    def connect_scope(self):
        # choose configuration file
        try:
            self.config_file = QFileDialog.getOpenFileName(self, 
                "Choose config file")
            pico_serial_num, params_dict = read_config(self.config_file)
            file_found = True
        except:
            QMessageBox.about(self, "File error", "File not in expected format")
            return 0
        # Open picoscope
        try:
            # picoscope = TestPs3000a(pico_serial_num) #ps3000a.PS3000a(pico_serial_num)
            picoscope = ps3000a.PS3000a(pico_serial_num)
        except:
            msg = "Could not connect to PicoScope " + pico_serial_num
            QMessageBox.about(self, "Connection error", msg)
            return 0
        # self.radar_scope = TestRadarScope(picoscope, **params_dict)
        self.radar_scope = RadarScope(picoscope, **params_dict)
        self.data_q = Queue.Queue()
        self.acq_thread = DataAcquisitionThread(self.data_q, self.radar_scope)
        self.proc_thread = DataProcessingThread(self.data_q, self.radar_scope, self)
        self.acq_thread.setDaemon(True)
        self.proc_thread.setDaemon(True)
        self.acq_thread.start()
        self.proc_thread.start()
        self.status_text.setText("Connected")
        return 1

    def disconnect_scope(self):
        if self.acq_thread is not None:
            self.acq_thread.join(0.01)
            self.proc_thread.join(0.01)       
            self.acq_thread = None
            self.proc_thread = None
            self.stopRecording()
            self.status_text.setText("Not connected")
        self.radar_scope.disconnect()
        self.radar_scope = None

    def set_output_dir(self):
        self.output_dir = QFileDialog.getExistingDirectory(self, 
            "Set output directory")
        self.file_text.setText(self.output_dir)

    def set_cmap(self):
        self.cmap = cm.get_cmap(str(self.colormap_combo_box.currentText()))

    def set_cmap_range(self):
        self.vmin_spin_box.setMaximum(self.vmax_spin_box.value())
        self.vmax_spin_box.setMinimum(self.vmin_spin_box.value())
        self.vmin = self.vmin_spin_box.value()
        self.vmax = self.vmax_spin_box.value()

    def save_file(self):
        filename = "sweep_" + self.timestamp + ".swp"
        filename = os.path.join(self.output_dir, filename)
        self.file_text.setText(filename)
        # output_file = open(filename, "wb")
        # # Should have more metadata in here
        # output_file.write(self.data)
        # output_file.close()

    def capture_sweep(self, on):
        if on:
            if self.radar_scope is None:
                connection_success = self.connect_scope()
                if not connection_success:
                    self.capture_button.setChecked(False)
                    return
            self.save_file()
            self.capture_button.setChecked(False)
        else:
            if self.recording:
                self.capture_button.setChecked(True)

    def setRecording(self, on):
        if on:
            self.startRecording()
        else:
            self.stopRecording()

    def startRecording(self):
        if self.radar_scope is None:
            connection_success = self.connect_scope()
            if not connection_success:
                self.recordBtn.setChecked(False)
                return
        self.recording = True
        self.capture_button.setChecked(True)
        self.status_text.setText("Recording")
        self.status_text.setStyleSheet('color: red')
        
    def stopRecording(self):
        self.status_text.setText("Ready")
        self.status_text.setStyleSheet('color: black')
        self.recording = False
        self.recordBtn.setChecked(False)
        self.capture_button.setChecked(False)