Ejemplo n.º 1
0
    def __init__(self):
        QMainWindow.__init__(self)
        self.setWindowIcon(get_icon(os.path.join(APP_RESOURCES, 'icons',
                                                  'python.png')))
        self.setupUi(self)
        
        # Redirect output to GUI's QTextEdit
        sys.stdout = OutLog(self.outputTextEdit, sys.stdout)
        sys.stderr = OutLog(self.outputTextEdit, sys.stderr, QColor(255,0,0) )
        
        settings = QSettings()
        size = settings.value("MainWindow/Size",
                              QVariant(QSize(600, 500))).toSize()
        self.resize(size)
        position = settings.value("MainWindow/Position",
                                  QVariant(QPoint(0, 0))).toPoint()
        self.move(position)
        self.restoreState(
        settings.value("MainWindow/State").toByteArray())
    
        self.logger = Logger('Zupport.GUIloader')
        self.logger.debugging = settings.value("Logging/debugging").toBool()
         
        # Set up a ZupportManager to deal with the plugins
        self.manager = Manager(self)
        self.plugins = {}

        # Set up the extents menu
        self.extent = ExtentContainer()
        self.menuExtent = QMenu("Extent")
        resolutions = self.extent.resolutions
        self.extenactiongroup = QActionGroup(self.menuExtent)  
        noneaction = QAction("None", self.menuExtent)
        self.extenactiongroup.addAction(noneaction)
        self.menuExtent.addAction(noneaction)
        for resolution in resolutions:
            resolution_text = str(resolution)
            submenu = self.menuExtent.addMenu(resolution_text) 
            self.menuExtent.addMenu(submenu)
            for area in self.extent.get_names(resolution):
                subaction = QAction(str(area) + ": %s" % resolution_text, 
                                    submenu)
                subaction.setCheckable(True)
                self.extenactiongroup.addAction(subaction)
                submenu.addAction(subaction)
        
        noneaction.isChecked()
        self.menuSettings.addMenu(self.menuExtent)
        
        self.actionDebugging_messages.setChecked(self.logger.debugging)

        self.setWindowTitle("Zupport GUI")
        
        self.load_tools()
        
        self.toolTreeWidget.itemSelectionChanged.connect(self.update_ui)
        self.actionDebugging_messages.toggled.connect(self._set_debugging)
        self.menuExtent.triggered.connect(self.update_ui)
        self.actionLoad_tool.triggered.connect(self.show_tool_gui)
        self.toolTreeWidget.doubleClicked.connect(self.show_tool_gui)
Ejemplo n.º 2
0
Archivo: gui.py Proyecto: cbig/zupport
    def __init__(self):
        QMainWindow.__init__(self)
        self.setWindowIcon(get_icon(os.path.join(APP_RESOURCES, 'icons',
                                                  'python.png')))
        self.setupUi(self)
        
        # Redirect output to GUI's QTextEdit
        sys.stdout = OutLog(self.outputTextEdit, sys.stdout)
        sys.stderr = OutLog(self.outputTextEdit, sys.stderr, QColor(255,0,0) )
        
        settings = QSettings()
        size = settings.value("MainWindow/Size",
                              QVariant(QSize(600, 500))).toSize()
        self.resize(size)
        position = settings.value("MainWindow/Position",
                                  QVariant(QPoint(0, 0))).toPoint()
        self.move(position)
        self.restoreState(
        settings.value("MainWindow/State").toByteArray())
    
        self.logger = Logger('Zupport.GUIloader')
        self.logger.debugging = settings.value("Logging/debugging").toBool()
         
        # Set up a ZupportManager to deal with the plugins
        self.manager = Manager(self)
        self.plugins = {}

        # Set up the extents menu
        self.extent = ExtentContainer()
        self.menuExtent = QMenu("Extent")
        resolutions = self.extent.resolutions
        self.extenactiongroup = QActionGroup(self.menuExtent)  
        noneaction = QAction("None", self.menuExtent)
        self.extenactiongroup.addAction(noneaction)
        self.menuExtent.addAction(noneaction)
        for resolution in resolutions:
            resolution_text = str(resolution)
            submenu = self.menuExtent.addMenu(resolution_text) 
            self.menuExtent.addMenu(submenu)
            for area in self.extent.get_names(resolution):
                subaction = QAction(str(area) + ": %s" % resolution_text, 
                                    submenu)
                subaction.setCheckable(True)
                self.extenactiongroup.addAction(subaction)
                submenu.addAction(subaction)
        
        noneaction.isChecked()
        self.menuSettings.addMenu(self.menuExtent)
        
        self.actionDebugging_messages.setChecked(self.logger.debugging)

        self.setWindowTitle("Zupport GUI")
        
        self.load_tools()
        
        self.toolTreeWidget.itemSelectionChanged.connect(self.update_ui)
        self.actionDebugging_messages.toggled.connect(self._set_debugging)
        self.menuExtent.triggered.connect(self.update_ui)
        self.actionLoad_tool.triggered.connect(self.show_tool_gui)
        self.toolTreeWidget.doubleClicked.connect(self.show_tool_gui)
Ejemplo n.º 3
0
    def _setup_menu(self):
        # File menu
        file_menu = self.menuBar().addMenu(_("File"))
        settings_action = create_action(self, _("Settings"),
                                   icon=get_icon('settings.png'),
                                   tip=_("Settings"),
                                   triggered=self.edit_settings)
        quit_action = create_action(self, _("Quit"),
                                    shortcut="Ctrl+Q",
                                    icon=get_std_icon("DialogCloseButton"),
                                    tip=_("Quit application"),
                                    triggered=self.close)
        add_actions(file_menu, (settings_action, None, quit_action))

        # View menu
        view_menu = self.createPopupMenu()
        view_menu.setTitle(_(u"&View"))
        self.menuBar().addMenu(view_menu)

        # Help menu
        help_menu = self.menuBar().addMenu("?")
        about_action = create_action(self, _("About..."),
                                     icon=get_std_icon('MessageBoxInformation'),
                                     triggered=self.about)
        add_actions(help_menu, (about_action,))

        # Base toolbar
        self.connectAction = QAction(QIcon('common/disconnected.png'), 'Connect', self)
        self.connectAction.triggered.connect( self.connect_button )
        self.playAction = QAction(QIcon('common/play.png'), 'Play free', self)
        self.playAction.triggered.connect( self.start_free_session_button )
        self.stopAction = QAction(QIcon('common/stop.png'), 'Stop', self)
        self.stopAction.triggered.connect( self.stop_button )
        self.timedAction = QAction(QIcon('common/timed.png'), 'Start', self)
        self.timedAction.triggered.connect( self.start_timed_session_button )

        self.toolbar = self.addToolBar('Controls')
        self.toolbar.addAction( self.connectAction )
        self.toolbar.addAction( self.playAction )
        self.toolbar.addAction( self.stopAction )
        self.toolbar.addAction( self.timedAction )
        self.toolbar.setObjectName('Controls')

        # Time toolbar
        self.timer = Timer( self )
        self.connect( self.timer, SIGNAL( 'SessionStop' ), self.session_stop )
Ejemplo n.º 4
0
def create_action(parent, title, triggered=None, toggled=None,
                  shortcut=None, icon=None, tip=None, checkable=None,
                  context=Qt.WindowShortcut, enabled=None):
    """
    Create a new QAction
    """
    action = QAction(title, parent)
    if triggered:
        parent.connect(action, SIGNAL("triggered(bool)"), triggered)
    if checkable is not None:
        # Action may be checkable even if the toggled signal is not connected
        action.setCheckable(checkable)
    if toggled:
        parent.connect(action, SIGNAL("toggled(bool)"), toggled)
        action.setCheckable(True)
    if icon is not None:
        assert isinstance(icon, QIcon)
        action.setIcon( icon )
    if shortcut is not None:
        action.setShortcut(shortcut)
    if tip is not None:
        action.setToolTip(tip)
        action.setStatusTip(tip)
    if enabled is not None:
        action.setEnabled(enabled)
    action.setShortcutContext(context)
    return action
Ejemplo n.º 5
0
class MainWindow( QMainWindow ):
    def __init__(self):
        QMainWindow.__init__(self)
        self.setWindowTitle(APP_NAME)
        self.setWindowIcon(get_icon('python.png'))
        self.timeout = None

        # used to recognise the checkbox in settings
        self.bhpacketname = {
            'RR':0,
            'BREATHING':1,
            'ECG':2,
            'SUMMARY':3,
            'ACC':4,
        }

        # Welcome message in statusbar:
        status = self.statusBar()
        status.showMessage(_("Zephyr BioHarness 3.0"), 5000)

        self._setup_layout()
        self._setup_menu()
        self._load_settings()
        self._init_objects()
        self.show()

    def _setup_menu(self):
        # File menu
        file_menu = self.menuBar().addMenu(_("File"))
        settings_action = create_action(self, _("Settings"),
                                   icon=get_icon('settings.png'),
                                   tip=_("Settings"),
                                   triggered=self.edit_settings)
        quit_action = create_action(self, _("Quit"),
                                    shortcut="Ctrl+Q",
                                    icon=get_std_icon("DialogCloseButton"),
                                    tip=_("Quit application"),
                                    triggered=self.close)
        add_actions(file_menu, (settings_action, None, quit_action))

        # View menu
        view_menu = self.createPopupMenu()
        view_menu.setTitle(_(u"&View"))
        self.menuBar().addMenu(view_menu)

        # Help menu
        help_menu = self.menuBar().addMenu("?")
        about_action = create_action(self, _("About..."),
                                     icon=get_std_icon('MessageBoxInformation'),
                                     triggered=self.about)
        add_actions(help_menu, (about_action,))

        # Base toolbar
        self.connectAction = QAction(QIcon('common/disconnected.png'), 'Connect', self)
        self.connectAction.triggered.connect( self.connect_button )
        self.playAction = QAction(QIcon('common/play.png'), 'Play free', self)
        self.playAction.triggered.connect( self.start_free_session_button )
        self.stopAction = QAction(QIcon('common/stop.png'), 'Stop', self)
        self.stopAction.triggered.connect( self.stop_button )
        self.timedAction = QAction(QIcon('common/timed.png'), 'Start', self)
        self.timedAction.triggered.connect( self.start_timed_session_button )

        self.toolbar = self.addToolBar('Controls')
        self.toolbar.addAction( self.connectAction )
        self.toolbar.addAction( self.playAction )
        self.toolbar.addAction( self.stopAction )
        self.toolbar.addAction( self.timedAction )
        self.toolbar.setObjectName('Controls')

        # Time toolbar
        self.timer = Timer( self )
        self.connect( self.timer, SIGNAL( 'SessionStop' ), self.session_stop )

    def _setup_layout(self):
        # Allow dockable widgets to be side by side
        self.setDockOptions(QMainWindow.AnimatedDocks | QMainWindow.AllowNestedDocks)
        self.setGeometry(300,100,1500,900)

        self.rrplot         = RealTimePlot( self, 'RR-Interval', 'ms', QColor( 255, 0, 0 ) )
        self.bwplot         = RealTimePlot( self, 'Breathing','', QColor( 0, 0, 255 ) )
        self.ecgplot        = RealTimePlot( self, 'ECG Waveform','', QColor( 0, 0, 255 ) )
        self.logarea        = myDockableWidget(self, QTextEdit)
        self.bwpsd          = RealTimePSD( self, 'Breathing PSD', inity=25000 )
        self.rrpsd          = RealTimePSD( self, 'RR-Interval PSD')

        self.logarea.widget.setReadOnly( True )
        self.logarea.widget.setFont( QFont("Courier", 8) )
        self.logarea.widget.setMinimumHeight(150)

        # Add the DockWidget to the main window
        self.ecgplot_dock = self.add_dockwidget( self.ecgplot.dockwidget, _("ECG Waveform") )
        self.rrcurve_dock = self.add_dockwidget( self.rrplot.dockwidget, _("RR-Intervals Plot") )
        self.rrpsd_dock = self.add_dockwidget( self.rrpsd.dockwidget, _("RRI PSD"))
        self.bwcurve_dock = self.add_dockwidget( self.bwplot.dockwidget, _("Breathing Plot") )
        self.bwpsd_dock = self.add_dockwidget( self.bwpsd.dockwidget, _("Breathing PSD (not implemented)") )
        self.splitDockWidget(self.rrcurve_dock, self.rrpsd_dock, Qt.Horizontal)
        self.splitDockWidget(self.bwcurve_dock, self.bwpsd_dock, Qt.Horizontal)
        self.log_dock = self.add_dockwidget( self.logarea, _("Messages"),  position=Qt.BottomDockWidgetArea)

        #self.splitDockWidget(self.rrcurve_dock, self.ecgplot_dock, Qt.Horizontal)

        # setting the name of the dock widget is required to save correclty
        # the postion of the widget when the application close
        self.rrcurve_dock.setObjectName('rrcurve_dock')
        self.rrpsd_dock.setObjectName('rrpsd_dock')
        self.bwcurve_dock.setObjectName('bwcurve_dock')
        self.bwpsd_dock.setObjectName('bwpsd_dock')
        self.log_dock.setObjectName('log_dock')
        self.ecgplot_dock.setObjectName('ecgplot_dock')

        #self.log_dock.setMinimumHeight( 20 )


        self.rrcurve_dock.setMinimumSize( 400, 200 )
        self.bwcurve_dock.setMinimumSize( 400, 200 )
        self.rrpsd_dock.setMinimumSize( 400, 200 )
        self.bwpsd_dock.setMinimumSize( 400, 200 )
        self.log_dock.setMinimumSize( 400, 100 )
        self.log_dock.setMaximumHeight( 250 )

    def _load_settings(self):
        self.appsettings = DataSetShowGroupBox("Settings",
                                             AppSettings, comment='',
                                             title=_("Application settings"))

        self.settings_storage = QSettings('settings.ini', QSettings.IniFormat)

        self.restoreGeometry( self.settings_storage.value('docksGeometry').toByteArray() )
        self.restoreState( self.settings_storage.value('docksState').toByteArray() )

        # load settings:
        self.settings_storage.beginGroup('BioHarnessPackets')
        rrdata = self.settings_storage.value('rrdata', True).toBool()
        breathing = self.settings_storage.value('breathing', True).toBool()
        ecg = self.settings_storage.value('ecg', False).toBool()
        summary = self.settings_storage.value('summary', False).toBool()
        accelerometer = self.settings_storage.value('accelerometer', False).toBool()
        self.settings_storage.endGroup()
        self.appsettings.dataset.bh_packets = []
        if rrdata: self.appsettings.dataset.bh_packets.append(0)
        if breathing: self.appsettings.dataset.bh_packets.append(1)
        if ecg: self.appsettings.dataset.bh_packets.append(2)
        if summary: self.appsettings.dataset.bh_packets.append(3)
        if accelerometer: self.appsettings.dataset.bh_packets.append(4)

        self.settings_storage.beginGroup('Misc')
        self.appsettings.dataset.timedsession = self.settings_storage.value('TimedDuration', 5).toInt()[0]
        # handle windows and linux serial port name
        portname = self.settings_storage.value('Serial_Port').toString()
        if str(portname).isdigit() is True:
            self.appsettings.dataset.serialport = int(portname)
        else:
             self.appsettings.dataset.serialport = str(portname)
        self.appsettings.dataset.use_virtual_serial = self.settings_storage.value('Use_Virtual_Serial_Port', False).toBool()
        self.settings_storage.endGroup()

        self.settings_storage.beginGroup('Storage')
        self.appsettings.dataset.enable_database = self.settings_storage.value('db_enable', False).toBool()
        self.appsettings.dataset.db_url = self.settings_storage.value('db_url').toString()
        self.appsettings.dataset.db_port = self.settings_storage.value('db_port').toString()
        self.appsettings.dataset.db_user = self.settings_storage.value('db_user').toString()
        self.appsettings.dataset.db_pwd = self.settings_storage.value('db_pwd').toString()
        self.appsettings.dataset.db_dbname = self.settings_storage.value('db_dbname').toString()
        self.appsettings.dataset.enable_files = self.settings_storage.value('files_enable', False).toBool()
        self.appsettings.dataset.directory_storage = self.settings_storage.value('directory').toString()
        self.settings_storage.endGroup()

    def _init_objects(self):
        # The time series container hold the data of the heart beat and breathing signal
        self.timeseriescontainer = TimeSeriesContainer()

        self.sessiontype = 'free'   # either free or timed

        self.zephyr_connect = ZephyrDevice()
        self.connect( self.zephyr_connect, SIGNAL( 'Message' ), self.printmessage )
        self.connect( self.zephyr_connect, SIGNAL( 'rrinterval' ), self.update_RR_plot )
        self.connect( self.zephyr_connect, SIGNAL( 'breathing_wave' ), self.update_BW_plot )
        self.connect( self.zephyr_connect, SIGNAL( 'ecg' ), self.update_ECG_plot )
        self.connect( self.zephyr_connect, SIGNAL( 'heart_rate' ), self.add_heart_rate )
        self.connect( self.zephyr_connect, SIGNAL( 'respiration_rate' ), self.add_respiration_rate )
        self.connect( self.zephyr_connect, SIGNAL( 'breathing_wave_amplitude' ), self.add_breathing_wave_amplitude )
        self.connect( self.zephyr_connect, SIGNAL( 'activity' ), self.add_activity )
        self.connect( self.zephyr_connect, SIGNAL( 'posture' ), self.add_posture )
        self.zephyr_connect.virtual_serial = self.appsettings.dataset.use_virtual_serial

        # the button are disabled by default
        # they are enabled if the connection to the device is successfull
        self.stopAction.setEnabled( False )
        self.playAction.setEnabled( False )
        self.timedAction.setEnabled( False )

        # InfluxDB storage configuration
        # Data storage need the application settings for db credentials
        self.datastorage = DataStorage()
        if self.appsettings.dataset.enable_database is True:
            self.datastorage.db_init( self.appsettings.dataset )
            self._test_database_connection()

        # size for the ecg window is different that the default value
        # of 60' set at the creation of the real time plot
        self.ecgplot.window_length = 6

    def sendbhcmd( self ):
        cmd =  int(str(self.bhcmdinput.text()), 16)
        self.zephyr_connect.sendmessage(cmd, [])

    #------?
    def about( self ):
        QMessageBox.about( self, _("About ")+APP_NAME,
              """<b>%s</b> v%s<p>%s Darko Petrovic
              <br>(Lisence goes here)
              <p>Python %s, Qt %s, PyQt %s %s %s""" % \
              (APP_NAME, VERSION, _("Developped by"), platform.python_version(),
               QT_VERSION_STR, PYQT_VERSION_STR, _("on"), platform.system()) )

    def edit_settings( self ):
        ok = self.appsettings.dataset.edit()

        # save settings in the .ini file
        if ok == 1:
            # Application settings (window position, view, ...):
            # ...
            # User settings:
            rrdata = breathing = ecg = summary = accelerometer = False
            for a in self.appsettings.dataset.bh_packets:
                if a == 0: rrdata = True
                elif a == 1: breathing = True
                elif a == 2: ecg = True
                elif a == 3: summary = True
                elif a == 4: accelerometer = True

            self.settings_storage.beginGroup('BioHarnessPackets')
            self.settings_storage.setValue('rrdata', str(rrdata) )
            self.settings_storage.setValue('breathing', str(breathing) )
            self.settings_storage.setValue('ecg', str(ecg) )
            self.settings_storage.setValue('summary', str(summary) )
            self.settings_storage.setValue('accelerometer', str(accelerometer) )
            self.settings_storage.endGroup()

            self.settings_storage.beginGroup('Misc')
            self.settings_storage.setValue('TimedDuration', self.appsettings.dataset.timedsession )
            self.settings_storage.setValue('Serial_Port', self.appsettings.dataset.serialport )
            self.settings_storage.setValue('Use_Virtual_Serial_Port', self.appsettings.dataset.use_virtual_serial )
            self.settings_storage.endGroup()

            self.settings_storage.beginGroup('Storage')
            self.settings_storage.setValue('db_enable', str(self.appsettings.dataset.enable_database) )
            self.settings_storage.setValue('db_url', self.appsettings.dataset.db_url )
            self.settings_storage.setValue('db_port', self.appsettings.dataset.db_port )
            self.settings_storage.setValue('db_user', str(self.appsettings.dataset.db_user) )
            self.settings_storage.setValue('db_pwd', str(self.appsettings.dataset.db_pwd) )
            self.settings_storage.setValue('db_dbname', str(self.appsettings.dataset.db_dbname) )
            self.settings_storage.setValue('files_enable', str(self.appsettings.dataset.enable_files) )
            self.settings_storage.setValue('directory', str(self.appsettings.dataset.directory_storage) )
            self.settings_storage.endGroup()

        if ok==1 and self.appsettings.dataset.enable_database:
            self.datastorage.db_init( self.appsettings.dataset )
            self._test_database_connection()

        if ok==1:
            self.zephyr_connect.virtual_serial = self.appsettings.dataset.use_virtual_serial

    def _test_database_connection(self):
        result, message = self.datastorage.db_connection()
        if result:
            self.logmessage(message)
        else:
            self.logmessage("Connection to the database failed: %s" % message, 'error')

    #------GUI refresh/setup
    def add_dockwidget( self, child, title, orientation = Qt.Vertical, position=None ):
        """Add a QDockWidget to the main window."""
        dockwidget, location = child.create_dockwidget( title )
        if position is not None:
            location = position
        self.addDockWidget( location, dockwidget, orientation )
        return dockwidget

    def logmessage( self, text, msgtype='info' ):
        """ Print a message in the message window
        """
        if msgtype == 'error':
            self.logarea.widget.setTextColor( QColor( 255, 0, 0 ) )
        else:
            self.logarea.widget.setTextColor( QColor( 0, 0, 0 ) )

        self.logarea.widget.insertPlainText( text + "\n" )
        sb = self.logarea.widget.verticalScrollBar()
        sb.setValue( sb.maximum() )

    def update_RR_plot( self, value ):
        # Store value in the data-set. We store every value in the dataset
        # but we display only a certain duration specified by 'self.rrplot.window_length'
        self.timeseriescontainer.ts_rri.add_rrinterval( value )
        if self.appsettings.dataset.enable_database is True:
            self.datastorage.write_points('rrintervals', value, self.timeseriescontainer.ts_rri.realtime[-1]*1000, 'm')
        # Set the data to the curve with values from the time series and update the plot
        self.rrplot.startIdx = self.timeseriescontainer.ts_rri.getSampleIndex( self.rrplot.window_length )
        self.rrplot.update( self.timeseriescontainer.ts_rri.realtime, self.timeseriescontainer.ts_rri.series )

        # Wait minimum 10 samples
        if len(self.timeseriescontainer.ts_rri.series) > 10:
            self.timeseriescontainer.ts_rri.computeLombPeriodogram()
            self.rrpsd.update(self.timeseriescontainer.ts_rri.psd_freq, self.timeseriescontainer.ts_rri.psd_mag)

    def update_BW_plot( self, values ):
        # Store value in the data-set. We store every value in the dataset
        # but we display only a certain duration specified by 'self.rrplot.window_length'
        self.timeseriescontainer.ts_bw.add_breath( values )
        if self.appsettings.dataset.enable_database is True:
            self.datastorage.write_points('breathing_wave', values, self.timeseriescontainer.ts_bw.realtime[-len(values):]*1000, 'm')
        # Set the data to the curve with values from the data-set and update the plot
        self.bwplot.startIdx = self.timeseriescontainer.ts_bw.getSampleIndex( self.bwplot.window_length )
        self.bwplot.update( self.timeseriescontainer.ts_bw.realtime, self.timeseriescontainer.ts_bw.series )

        if len(self.timeseriescontainer.ts_bw.series) > 50:
            # ---- Compute and display the Power Spectral Density of breathing signal
            self.timeseriescontainer.ts_bw.computeWelchPeriodogram()
            self.bwpsd.update(self.timeseriescontainer.ts_bw.psd_freq, self.timeseriescontainer.ts_bw.psd_mag)

    def update_ECG_plot( self, values ):
        self.timeseriescontainer.ts_ecg.add_ecg( values )
        if self.appsettings.dataset.enable_database is True:
            self.datastorage.write_points('ecg', values, self.timeseriescontainer.ts_ecg.realtime[-len(values):]*1000, 'm')

        self.ecgplot.startIdx = self.timeseriescontainer.ts_ecg.getSampleIndex( self.ecgplot.window_length )
        self.ecgplot.update( self.timeseriescontainer.ts_ecg.realtime, self.timeseriescontainer.ts_ecg.series )

    def add_heart_rate(self, value):
        self.timeseriescontainer.heart_rate = np.append(self.timeseriescontainer.heart_rate, value)
        if self.appsettings.dataset.enable_database is True:
            self.datastorage.write_points('heart_rate', value)

    def add_respiration_rate(self, value):
        self.timeseriescontainer.respiration_rate = np.append(self.timeseriescontainer.respiration_rate, value)
        if self.appsettings.dataset.enable_database is True:
            self.datastorage.write_points('respiration_rate', value)

    def add_breathing_wave_amplitude(self, value):
        self.timeseriescontainer.breathwave_ampltitude = np.append(self.timeseriescontainer.breathwave_ampltitude,value)
        if self.appsettings.dataset.enable_database is True:
            self.datastorage.write_points('breathing_wave_amplitude', value)

    def add_activity(self, value):
        self.timeseriescontainer.activity = np.append(self.timeseriescontainer.activity, value)
        if self.appsettings.dataset.enable_database is True:
            self.datastorage.write_points('activity', value)

    def add_posture(self, value):
        self.timeseriescontainer.posture = np.append(self.timeseriescontainer.posture, value)
        if self.appsettings.dataset.enable_database is True:
            self.datastorage.write_points('posture', value)

    def printmessage( self, message ):
        if message == 'connected':
            self.logmessage( "Successfully connected to the device %s." % self.zephyr_connect.SerialNumber )
            self._toggle_connect_button()
            if self.timeout:
                self.timeout.stop()
                self.timeout = None

        if isinstance(message, zephyr.message.BatteryStatus):
            self.logmessage("Battery charge is %d%%" % message.Charge )

    def _toggle_connect_button(self):
        if self.zephyr_connect.connected is True:
            self.connectAction.setIcon(QIcon('common/connected.png'))
            self.connectAction.setToolTip("Disconnect")
            self.connectAction.triggered.disconnect( self.connect_button )
            self.connectAction.triggered.connect( self.disconnect_button )
            self.playAction.setEnabled( True )
            self.timedAction.setEnabled( True )
        else:
            self.connectAction.setIcon(QIcon('common/disconnected.png'))
            self.connectAction.setToolTip("Connect")
            self.connectAction.triggered.disconnect( self.disconnect_button )
            self.connectAction.triggered.connect( self.connect_button )
            self.playAction.setEnabled( False )
            self.timedAction.setEnabled( False )

    def connect_button(self):
        # The connect button is first trying to open the com port. If the port can be opened,
        # the zephyr protocol functions are instancied and a message is send to the device
        # (the thread is started for this purpose and to let the reception of the response).
        # The device has 3 seconds to respond (a timeout is started to close the serial
        # and terminate the thread in case of no response). When the device responds a signal 'Message'
        # is sent to the GUI (the message is the Serial Number of the device).
        if self.zephyr_connect.connectTo( self.appsettings.dataset.serialport,
                                          self.appsettings.dataset.use_virtual_serial):
            self.zephyr_connect.start()
            if self.appsettings.dataset.use_virtual_serial is False:
                self.timeout = QTimer( self )
                self.connect( self.timeout, SIGNAL( 'timeout()' ), self.connectionTimeout )
                self.timeout.setSingleShot(True)
                self.timeout.start(3000)
            else:
                self.logmessage("Serial virtualization in use.")
                self._toggle_connect_button()
        else:
            self.logmessage( "Fail to open port '%s' !" % self.appsettings.dataset.serialport, 'error' )

    def disconnect_button(self):
        self.zephyr_connect.terminate()
        if self.zephyr_connect.wait():
            self._toggle_connect_button()
            if self.appsettings.dataset.use_virtual_serial is False:
                self.logmessage( "Successfully disconnected from the device." )
            else:
                self.logmessage( "Virtual serial stopped." )

    def connectionTimeout(self):
        self.logmessage("Unable to connected to the device on %s." % self.appsettings.dataset.serialport, 'error' )
        self.zephyr_connect.terminate()
        if self.timeout:
            self.timeout = None

    def start_free_session_button( self ):
        self.sessiontype = 'free'
        self.timer.initialize( 0 )
        self.session_start()

    def start_timed_session_button(self):

        if not self.timeout:
            self.sessiontype = 'timed'
            self.timer.initialize( self.appsettings.dataset.timedsession * 60 )
            # the session will start after 'X' seconds
            X = 20
            self.timeout = QTimer( self )
            self.connect( self.timeout, SIGNAL( 'timeout()' ), self.session_start )
            self.timeout.setSingleShot(True)
            self.timeout.start(X*1000)
            self.logmessage('The session will start in %d seconds.' % X)
        else:
             # the button is pressed a second time
            self.timeout.stop()
            self.timeout = None
            self.session_start()

    def stop_button( self ):
        sel = 0
        if self.sessiontype == 'timed':
            sel = QMessageBox.warning( self, "Timed Session",
                                       "A Timed Session is currently active!\nIf you stop the session "
                                       "the session will be stored as a free session.", "OK", "Cancel")
        if sel == 0:
            self.session_stop()

    def session_start( self ):
        if self.timeout:
            self.timeout.stop()
            self.timeout = None

        # empty all arrays
        self.timeseriescontainer.clearContainer()

        if self.appsettings.dataset.use_virtual_serial is True:
            self.zephyr_connect.resume()

        for a in self.appsettings.dataset.bh_packets:
            if a == 0:
                self.zephyr_connect.enablePacket('RRDATA')
                self.timeseriescontainer.ts_rri.setStartTime()
            elif a == 1:
                self.zephyr_connect.enablePacket('BREATHING')
                self.timeseriescontainer.ts_bw.setStartTime()
            elif a == 2:
                self.zephyr_connect.enablePacket('ECG')
                self.timeseriescontainer.ts_ecg.setStartTime()
            elif a == 3:
                self.zephyr_connect.enablePacket('SUMMARY')

        self.timer.start()

        # handle graphical change:
        self.playAction.setEnabled( False )
        self.timedAction.setEnabled( False )
        self.stopAction.setEnabled( True )
        self.connectAction.setEnabled( False )

        # in any case, we create the new session in database because the
        # data are written in real time
        if self.appsettings.dataset.enable_database is True:
            self.datastorage.create_session()

    def session_stop(self):
        if self.appsettings.dataset.use_virtual_serial is True:
            self.zephyr_connect.pause()

        for a in self.appsettings.dataset.bh_packets:
            if a == 0: self.zephyr_connect.disablePacket('RRDATA')
            elif a == 1: self.zephyr_connect.disablePacket('BREATHING')
            elif a == 2: self.zephyr_connect.disablePacket('ECG')
            elif a == 3: self.zephyr_connect.disablePacket('SUMMARY')

        self.timer.stop()
        # handle graphical change:
        self.playAction.setEnabled( True )
        self.timedAction.setEnabled( True )
        self.stopAction.setEnabled( False )
        self.connectAction.setEnabled( True )

        # update session with the duration
        if self.appsettings.dataset.enable_database is True:
            self.datastorage.update_duration(self.timer.getRunningTime())

        # store more info for the current session?
        if self.appsettings.dataset.enable_database or self.appsettings.dataset.enable_files:
            self.infosdialog = SessionInfos( self, self.datastorage )
            self.connect(self.infosdialog, SIGNAL('accepted()'), self.add_more_infos )
            self.infosdialog.exec_()

    def add_more_infos(self):
        sessiontype = 0
        for i, r in enumerate(self.infosdialog.sessiontypes):
            if r.isChecked():
                sessiontype = i+1

        breathing_zone = self.infosdialog.breathzone.currentIndex()
        infos = {   'session_type': sessiontype,
                    'breathing_zone': '' if breathing_zone == 0 else breathing_zone,
                    'note': str(self.infosdialog.note.toPlainText()),
                }

        if self.appsettings.dataset.enable_database is True:
            self.datastorage.add_informations( infos )
        self.logmessage("The information was stored in the database for this session.")

    def closeEvent(self, event):
        self.settings_storage.setValue( 'docksGeometry', self.saveGeometry() )
        self.settings_storage.setValue( 'docksState', self.saveState() )
        QMainWindow.closeEvent(self, event)
Ejemplo n.º 6
0
def create_action(parent,
                  title,
                  triggered=None,
                  toggled=None,
                  shortcut=None,
                  icon=None,
                  tip=None,
                  checkable=None,
                  context=Qt.WindowShortcut,
                  enabled=None):
    """
    Create a new QAction
    """
    action = QAction(title, parent)
    if triggered:
        action.triggered.connect(triggered)
    if checkable is not None:
        # Action may be checkable even if the toggled signal is not connected
        action.setCheckable(checkable)
    if toggled:
        action.toggled.connect(toggled)
        action.setCheckable(True)
    if icon is not None:
        assert isinstance(icon, QIcon)
        action.setIcon(icon)
    if shortcut is not None:
        action.setShortcut(shortcut)
    if tip is not None:
        action.setToolTip(tip)
        action.setStatusTip(tip)
    if enabled is not None:
        action.setEnabled(enabled)
    action.setShortcutContext(context)
    return action
Ejemplo n.º 7
0
    def __init__(self):
        QMainWindow.__init__(self)
        self.setWindowIcon(get_icon('python.png'))
        self.setWindowTitle("Electric motor simulator")

        # Dataset for editing motor parameters
        self.groupbox1 = DataSetShowGroupBox("Motor parameters",
                                             ExampleDataSet,
                                             comment='')
        self.groupbox2 = DataSetShowGroupBox("Controller parameters",
                                             AnotherDataSet,
                                             comment='')
        self.groupbox3 = DataSetEditGroupBox("Standard dataset",
                                             OtherDataSet,
                                             comment='')
        self.groupbox4 = DataSetEditGroupBox("Standard dataset",
                                             ExampleMultiGroupDataSet,
                                             comment='')
        #self.groupbox3.SIG_APPLY_BUTTON_CLICKED.connect(self.update_window)
        self.update_groupboxes()

        splitter = QSplitter(self)
        splitter.addWidget(self.groupbox1)
        splitter.addWidget(self.groupbox2)
        #splitter.addWidget(self.groupbox3)
        #splitter.addWidget(self.groupbox4)
        self.setCentralWidget(splitter)
        self.setContentsMargins(10, 5, 10, 5)

        # File menu
        file_menu = self.menuBar().addMenu("File")
        quit_action = create_action(self,
                                    "Quit",
                                    shortcut="Ctrl+Q",
                                    icon=get_std_icon("DialogCloseButton"),
                                    tip="Quit application",
                                    triggered=self.close)
        add_actions(file_menu, (quit_action, ))

        # Edit menu
        edit_menu = self.menuBar().addMenu("Edit")
        editparam1_action = create_action(self,
                                          "Edit dataset 1",
                                          triggered=self.edit_dataset1)
        editparam2_action = create_action(self,
                                          "Edit dataset 2",
                                          triggered=self.edit_dataset2)
        editparam4_action = create_action(self,
                                          "Edit dataset 4",
                                          triggered=self.edit_dataset4)
        add_actions(edit_menu,
                    (editparam1_action, editparam2_action, editparam4_action))

        # Toolbar
        tb = self.addToolBar("Tools")
        reset = QAction("Reset", self)
        tb.addAction(reset)
        pause = QAction("Pause", self)
        tb.addAction(pause)
        step = QAction("Step", self)
        tb.addAction(step)
        go = QAction("Go", self)
        tb.addAction(go)
Ejemplo n.º 8
0
    def __init__(self, parent):
        QSplitter.__init__(self, parent)
        # List Widget
        self.arraylist = QListWidget(self)
        self.arraylist.setContextMenuPolicy(Qt.ActionsContextMenu)

        newArray = QAction(self)
        newArray.setText("Paste Array (no header name)")
        newArray.triggered.connect(self.pasteArray)
        newArrayWithName = QAction(self)
        newArrayWithName.setText("Paste Array (with header name)")
        newArrayWithName.triggered.connect(self.pasteArrayWithName)
        plotArray = QAction(self)
        plotArray.setText("Plot Array")
        plotArray.triggered.connect(self.plotArray)
        modifyArray = QAction(self)
        modifyArray.setText("Modify Array(Calibration)")
        modifyArray.triggered.connect(self.modifyArray)
        plotScatter = QAction(self)
        plotScatter.setText("Plot Scatter")
        plotScatter.triggered.connect(self.plotScatter)
        plotHist = QAction(self)
        plotHist.setText("Plot Histogram")
        plotHist.triggered.connect(self.plotHist)
        delete = QAction(self)
        delete.setText("Remove")
        delete.triggered.connect(self.removeItem)
        curveDialog = QAction(self)
        curveDialog.setText("Open Curve Dialog")
        curveDialog.triggered.connect(self.openCurveDialog)
        self.arraylist.addAction(newArray)
        self.arraylist.addAction(newArrayWithName)
        self.arraylist.addAction(plotArray)
        self.arraylist.addAction(plotScatter)
        self.arraylist.addAction(plotHist)
        self.arraylist.addAction(modifyArray)
        self.arraylist.addAction(curveDialog)
        self.arraylist.addAction(delete)

        self.addWidget(self.arraylist)

        # Properties widget
        self.properties = DataSetEditGroupBox(_("參數(Properties)"), CsvParam)
        self.properties.setEnabled(False)
        self.addWidget(self.properties)
Ejemplo n.º 9
0
    def __init__(self, parent):
        QSplitter.__init__(self, parent)
        # List Widget
        self.csvlist = QListWidget(self)
        self.csvlist.setContextMenuPolicy(Qt.ActionsContextMenu)

        plotCSV = QAction(self)
        plotCSV.setText("Plot")
        plotCSV.triggered.connect(self.plotCSV)
        delete = QAction(self)
        delete.setText("Remove")
        delete.triggered.connect(self.removeItem)
        extractCSV = QAction(self)
        extractCSV.setText("Extract to Arrays")
        extractCSV.triggered.connect(self.extractArray)
        self.csvlist.addAction(plotCSV)
        self.csvlist.addAction(extractCSV)
        self.csvlist.addAction(delete)

        self.addWidget(self.csvlist)

        # Properties widget
        self.properties = DataSetEditGroupBox(_("參數(Properties)"), CsvParam)
        self.properties.setEnabled(False)
        self.addWidget(self.properties)
Ejemplo n.º 10
0
 def setShortcuts(self):
     self.autoScaleAction = QAction(QIcon(), '&Autoscale', self)
     self.autoScaleAction.setShortcut("Ctrl+W")
     self.autoScaleAction.triggered.connect(self.plotWidget.autoScale)
Ejemplo n.º 11
0
class MainWindow(QMainWindow):
    def __init__(self, parent = None):
        QMainWindow.__init__(self, parent)
        self.console = None
        self.setup()
    
    def closeEvent(self, event):
        if self.console is not None:
            self.console.exit_interpreter()
        event.accept()

    def setup(self):
        """Setup window parameters"""
        self.setWindowIcon(get_icon('python.png'))
        self.setWindowTitle(APP_NAME)
        self.resize(QSize(600, 800))
        
        # Welcome message in statusbar:
        status = self.statusBar()
        status.showMessage(_("Welcome to guiqwt application example!"), 5000)
        self.setupMainWidget()

        # File menu
        file_menu = self.menuBar().addMenu(_("File"))

        new_action = create_action(self, _("New..."),
                                   shortcut="Ctrl+N",
                                   icon=get_icon('filenew.png'),
                                   tip=_("Create a new image"),
                                   triggered=self.new_image)
        open_action = create_action(self, _("Open..."),
                                    shortcut="Ctrl+O",
                                    icon=get_icon('fileopen.png'),
                                    tip=_("Open an image"),
                                    triggered=self.open_image)
        quit_action = create_action(self, _("Quit"),
                                    shortcut="Ctrl+Q",
                                    icon=get_std_icon("DialogCloseButton"),
                                    tip=_("Quit application"),
                                    triggered=self.close)
        add_actions(file_menu, (new_action, open_action, None, quit_action))
        
        processing_menu = self.menuBar().addMenu(_("Processing"))
        autoscale_action = create_action(self, _("Autoscale"),
                                    shortcut="Ctrl+W",
                                    tip=_("Autoscale Graph"),
                                    triggered=self.plotWidget.autoScale)
        add_actions(processing_menu, (autoscale_action,))
        # Help menu
        help_menu = self.menuBar().addMenu("?")
        about_action = create_action(self, _("About..."),
                                     icon=get_std_icon('MessageBoxInformation'),
                                     triggered=self.about)
        add_actions(help_menu, (about_action,))
        
        main_toolbar = self.addToolBar("Main")
        add_actions(main_toolbar, (new_action, open_action, ))
        
        self.curFIFOVal = 0
        self.rdb = r.Redis('localhost')

        # self.setShortcuts()

        # self.setCentralWidget(self.plotWidget)
        self.setCentralWidget(self.main_dock)  

    
    def setShortcuts(self):
        self.autoScaleAction = QAction(QIcon(), '&Autoscale', self)
        self.autoScaleAction.setShortcut("Ctrl+W")
        self.autoScaleAction.triggered.connect(self.plotWidget.autoScale)
        # print "initiating shortcuts"
    #------

    def setupMainWidget(self) :
        self.main_dock = QDockWidget(_(''))
        self.addDockWidget(Qt.BottomDockWidgetArea, self.main_dock)
        self.dockTab = QTabWidget()
        dockSplitter = QSplitter()
        dockSplitter.setOrientation(Qt.Vertical)
        #-----
        toolbar = self.addToolBar("Curve")
        self.plotWidget = CentralWidget(self, toolbar)        # Set central widget:
        self.dockTab.addTab(self.plotWidget, "Plot")
        #-----
        self.statusEdit = QTextEdit()
        self.statusEdit.setText("Status updates to go here.")
        self.statusEdit.setEnabled(False)
        self.statusEdit.moveCursor(QTextCursor.End)
        #-----
        self.testButton = QPushButton("Test Button")
        self.testButton.clicked.connect(self.__testClick__)
        dockSplitter.addWidget(self.testButton)
        dockSplitter.addWidget(self.statusEdit)
        self.dockTab.addTab(dockSplitter, "Status Info")

        if DockableConsole is None:
            self.console = None
        else:
            import time, scipy.signal as sps, scipy.ndimage as spi
            import sys, os
            import numpy as np
            ns = {'np': np, 'sps': sps, 'spi': spi,
                  'os': os, 'sys': sys, 'time': time}
            msg = "Example: np.arange(20)\n"\
                  "Modules imported at startup: "\
                  "os, sys, os.path as osp, time, "\
                  "numpy as np, scipy.signal as sps, scipy.ndimage as spi"
            self.console = DockableConsole(self, namespace=ns, message=msg)
            # console_dock = QDockWidget(_('Console'))
            # self.addDockWidget(Qt.BottomDockWidgetArea, console_dock)
            # console_dock.setWidget(self.console)
            self.dockTab.addTab(self.console, "Console")
            # dockSplitter.addWidget(self.console)


        # main_dock.setWidget(dockSplitter)
        self.main_dock.setWidget(self.dockTab)

    #------
    def __testClick__(self):
        # self.statusEdit.append("Clicked")
        self.dataList = self.rdb.lrange('activeData', 0, -1)
        if self.curFIFOVal>20:
            self.curFIFOVal = 0

        dataID = self.dataList[self.curFIFOVal]
        # metaDict, raw = WR.processDataJson(self.rdb, dataID)
        # metaDict, raw = WR.processData(self.rdb, dataID)
        metaDict, raw = WR.processDataSegmented(self.rdb, dataID)
        xVals = np.arange(len(raw))
        self.curFIFOVal+=1
        self.statusEdit.append(str(raw[0:5]))
        self.plotWidget.add_curve(dataID, xVals, raw)

    #------?
    def about(self):
        QMessageBox.about( self, _("About ")+APP_NAME,
              """<b>%s</b> v%s<p>%s Brian H. Clowers
              <br>
              <br>Copyright &copy; 2016
              <p>Python %s, Qt %s, PyQt %s %s %s""" % \
              (APP_NAME, VERSION, _("Developped by"), platform.python_version(),
               QT_VERSION_STR, PYQT_VERSION_STR, _("on"), platform.system()) )
        
    #------I/O
    def new_image(self):
        """Create a new image"""
        imagenew = ImageParamNew(title=_("Create a new image"))
        if not imagenew.edit(self):
            return
        image = ImageParam()
        image.title = imagenew.title
        if imagenew.type == 'zeros':
            image.data = np.zeros((imagenew.width, imagenew.height))
        elif imagenew.type == 'rand':
            image.data = np.random.randn(imagenew.width, imagenew.height)
        self.mainwidget.add_image(image)
    
    def open_image(self):
        """Open image file"""
        saved_in, saved_out, saved_err = sys.stdin, sys.stdout, sys.stderr
        sys.stdout = None
        filename, _filter = getopenfilename(self, _("Open"), "",
                                            io.iohandler.get_filters('load'))
        sys.stdin, sys.stdout, sys.stderr = saved_in, saved_out, saved_err
        if filename:
            self.mainwidget.add_image_from_file(filename)
Ejemplo n.º 12
0
    def __init__(self, xlabel=None, ylabel=None, winTitle=None):
        """
        Boilerplate code for guiqwt image window. Includes qt application,
        x-,y-crosssection,  itemlistpanel, contrast adjustment.

        Returns
        --------
        win : guiqwt.plot.ImageDialog
        _app : PyQt4.QtGui.QApplication
        """

        self._app = qapplication()
        self.win = ImageDialog(edit=False,
                               toolbar=True,
                               wintitle=winTitle,
                               options=dict(xlabel=xlabel,
                                            ylabel=ylabel,
                                            yreverse=False,
                                            lock_aspect_ratio=False))
        self.itemlist_panel = self.win.get_itemlist_panel()
        self.itemlist_panel.show()
        action = QAction(get_icon('busy.png'), "Reload", self.itemlist_panel)
        action.triggered.connect(self.reload_measurement)
        self.itemlist_panel.children()[-2].addAction(action)
        self.win.plot_widget.plot.SIG_ITEM_REMOVED.connect(
            self.remove_measurement)

        action = QAction(get_icon('save_all.png'), "Save all",
                         self.itemlist_panel)
        action.triggered.connect(self.save_measurements)
        self.itemlist_panel.children()[-3].addAction(action)

        def fun(shape):
            shape.symbol.pen().setWidth(2)
            shape.symbol.setColor(QColor(255, 0, 0))

        self.win.add_tool(PointTool, handle_final_shape_cb=fun)
        self.win.get_xcs_panel().show()
        self.win.get_ycs_panel().show()
        self.win.get_contrast_panel().show()

        action = QAction(get_icon('fileopen.png'), "Open measurement",
                         self.itemlist_panel)
        action.triggered.connect(self.load_measurement)
        self.win.get_toolbar().addAction(action)
        self.win.get_toolbar().addAction("Load VNA measurement",
                                         self.load_VNAMeasurement)
        self.win.get_toolbar().addAction(
            "Load VNA measurement ...",
            self.load_VNAMeasurement_select_channels)
        self.win.get_toolbar().addAction(
            "Load VNA fields measurement ",
            self.load_VNASeparateFieldsMeasurement)
        self.win.get_toolbar().addAction("Get points", self.get_points)

        if peakit:
            self.win.get_toolbar().addAction("Fitting tool ...",
                                             self.launchFittingTool)
            self.fitting_controller = MeasurementController()
        else:
            self.fitting_controller = None

        self.operations_widget = OperationsWidget()
        bbfmr_operations = list(
            filter(None,
                   [("bbFMR.processing.%s" % s) if "__" not in s else None
                    for s in dir(bp)]))
        self.operations_widget.populate_available_operations(bbfmr_operations)
        self.itemlist_panel.layout().addWidget(self.operations_widget)
        self.itemlist_panel.listwidget.selectionModel(
        ).selectionChanged.connect(self.refresh_operations)
        self.operations_widget.operations_changed.connect(
            self.replot_measurement)

        self.plot_items = self.win.plot_widget.plot.items
        self.measurements = []