Пример #1
0
class MainWindow(QMainWindow):
    def __init__(self, test=Constants.test, parent=None):
        # UI init
        super(MainWindow, self).__init__(parent)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        self.voltageTimer = QTimer()
        self.voltageTimer.start(
            Constants.updateRate)  # update every 0.15 second
        self.guiTimer = QTimer()
        self.guiTimer.start(0)
        self.cm = plt.get_cmap('cool')
        self.alarm = Alarm(Constants.alarmParams, parent=self)
        self.judge = Judge(Constants.DATA_DIR)
        self.warning = Warning(parent=self)
        self.recorder = None
        self.setting = Setting(self.alarm.getInitialState())
        self.time = None
        self.measure = None
        self.predict = {'predict': 1, 'cnt': 0, 'curr_predict': None}

        # check it is test mode or not (arduino don't need to connect)
        try:
            self.arduino = Arduino()
        except:
            print('using monk arduino')
            self.arduino = ArduinoTest()

        # Connection
        self.voltageTimer.timeout.connect(self.voltageUpdate)
        self.ui.actionRecord_Data.triggered.connect(self.recordData)
        self.ui.actionSetting.triggered.connect(self.showSetting)
        self.setting.finished.connect(self.settingClose)
        self.guiTimer.timeout.connect(self.guiUpdate)

        # ShortCut
        self.ui.actionRecord_Data.setShortcut("Ctrl+D")
        self.ui.actionSetting.setShortcut("Ctrl+S")

        # Check is there are the data valid or not
        self.judgeStatusCheck()

        # Show the main window
        self.show()

        # Show and locate the warning message manually
        self.warning.showWarning()

    def voltageUpdate(self):
        data = self.arduino.get_pressure()
        if data:
            self.time = str(datetime.datetime.now())
            self.measure = data
            self.updatePosture()

            # record the data is data recorder is open
            if self.recorder is not None and self.recorder.recording:
                posture_id = self.recorder.ui.ComboClass.currentIndex()
                self.recorder.measure[posture_id].append(
                    (self.time, self.measure))

    def updatePosture(self):
        curr_predict = self.judge.predict(self.measure)
        if curr_predict == self.predict['curr_predict']:
            self.predict['cnt'] += 1
        else:
            self.predict['curr_predict'] = curr_predict
            self.predict['cnt'] = 1

        # update the predict only when it is greater than consecutive factor
        # to prevent the prediction change in a very short time
        if self.predict['cnt'] >= Constants.consecutiveFactor:
            self.predict['predict'] = self.predict['curr_predict']

        # update the alarm status
        if self.predict['predict'] not in Constants.goodPosture:
            self.alarm.tick()
        else:
            self.alarm.reset()

    def recordData(self):
        self.recorder = DataRecorder(self)
        self.recorder.finished.connect(self.recordDataClose)

    def judgeStatusCheck(self):
        # Check the data is available or not only when it is not in testing mode
        # Show the data recorder window if there are no data
        if not Constants.test and self.judge.clf is None:
            QMessageBox.warning(
                self, 'warning',
                'Please record some data to initialize the service')
            self.recordData()

    def recordDataClose(self, val):
        if val == 1:
            self.dumpStoringData()

        self.recorder.finished.disconnect(self.recordDataClose)
        self.recorder = None
        self.judge.initialize()
        self.judgeStatusCheck()

    def dumpStoringData(self):
        # dump the recording data when data recorder is done. (press ok)
        for class_id, data in self.recorder.measure.items():
            filename = join(Constants.DATA_DIR,
                            'class' + str(class_id) + '.txt')
            with open(filename, 'w+') as file:
                for time, measure in data:
                    txt = list(map(str, measure))
                    row = '\t'.join([time] + txt)
                    file.write(row + '\n')

    def guiUpdate(self):
        # convert a list of float to 0 ~ 255 in stylesheet format
        def getFormatColor(raw_color):
            res = 'rgb('
            res += ', '.join([str(int(i * 255)) for i in raw_color])
            res += ')'
            return res

        # convert volt into color
        def getColorMap(volts, cm):
            res = []
            for v in volts:
                color = cm(int(v / 5.15 * 255))
                res.append(getFormatColor(color))

            return res

        # update the pressure heatmap
        if self.measure is not None:
            colors = getColorMap(self.measure, self.cm)
            self.ui.bottomLeft.setStyleSheet('QWidget { background: %s }' %
                                             colors[0])
            self.ui.bottomBack.setStyleSheet('QWidget { background: %s }' %
                                             colors[1])
            self.ui.bottomRight.setStyleSheet('QWidget { background: %s }' %
                                              colors[2])
            self.ui.backLeft.setStyleSheet('QWidget { background: %s }' %
                                           colors[3])
            self.ui.backRight.setStyleSheet('QWidget { background: %s }' %
                                            colors[4])
            self.ui.backDown.setStyleSheet('QWidget { background: %s }' %
                                           colors[5])

        # update the posture image
        filename = str(Posture(self.predict['predict'])) + '.png'
        self.ui.imageHolder.setPixmap(
            QPixmap(join(Constants.IMG_DIR, filename)))
        self.ui.imageHolder.show()

    def showSetting(self):
        self.setting.initialize(self.alarm.getInitialState())

    def settingClose(self, val):
        if val == 1:
            # When close the window with committing the change
            self.alarm.updateParams = self.setting.getSetting()