Example #1
0
File: widgets.py Project: e-sr/KG
    def __init__(self, author, observations, local=True, db=None):
        # init super
        super(CaseCreatorWidget, self).__init__(setup=False)
        self.setWindowTitle('Create Case')
        # set wavepath casepath and local
        self.author = author
        self.local = local
        if self.local:
            self.db = None
            self.wavpath = pathlib.Path().joinpath('wav')
            self.casepath = pathlib.Path().joinpath('test_case').joinpath(self.author)
        else:
            self.db = db
            self.wavpath = pathlib.Path(WAV_PATH)
            self.casepath = pathlib.Path(CASE_FOLDER).joinpath(self.author)
        try:
            self.wavpath.mkdir()
            self.casepath.mkdir()
        except:
            pass

        # init logger
        fn = self.casepath.joinpath('saved_cases.log')
        logging.basicConfig(format='%(asctime)s %(message)s',
                            filename=str(fn),
                            level=logging.DEBUG,  # filemode = 'w+',
                            datefmt='%Y-%m-%d %H:%M:%S')
        logging.captureWarnings(True)
        logging.info('Start case creator session, local: {}.'.format(self.local))

        # set observations and cases to analyzee, dict observatioins contain observation casess ans its metadata
        self.obsKeys = []
        self.observations = {}
        for obs in observations:
            self.init_obs(obs)
        # set current noise
        self.currentNoise = 'Z'
        self.bothVisibles = True

        # Add New Widgets
        # structure:
        #
        #                   main Phonon Widget
        # ------------------------------------------------------
        #                  Figure canvas widget
        # ------------------------------------------------------
        # selectCase GB | selectSOI GB|
        #         set quality GB      | caseinfo GB | save button
        # ------------------------------------------------------

        # Figure Canvas
        plt.ioff()
        fig = Figure((15, 10))
        fig.set_dpi(110)  # default 110
        fig.set_facecolor('#272822')
        # canvas Widget: first fidget
        self.canvas = FigureCanvas(fig)
        # add axes
        self.ax = fig.add_subplot(111)
        # case Selector
        self.minspan = 0.05
        self.CS = CaseSelector(self.ax, self.onselect, self.onclick,
                               nrect=[50, 50], update_on_ext_event=True,
                               minspan=self.minspan)
        self.ca_bar_handle = [self.CS]
        self.ca_widget_handle = [self.CS]
        # add canvas to main vBox
        self.vBox.addWidget(self.canvas)

        # begin second hBox
        # .................
        secondhBox = QtGui.QHBoxLayout()

        # left vBox of second hBox
        leftvBox = QtGui.QVBoxLayout()
        # add first row to left vBox: hBox1
        hBox1 = QtGui.QHBoxLayout()
        # select case combo 
        groupBox = QtGui.QGroupBox('Select observation to analyze ')
        groupBox.setFixedWidth(280)
        self.obsCombo = QtGui.QComboBox()
        self.obsCombo.addItems(self.obsKeys)
        self.saved_obs_to_green()
        hbox1_1 = QtGui.QHBoxLayout()
        hbox1_1.addWidget(self.obsCombo)
        groupBox.setLayout(hbox1_1)
        hBox1.addWidget(groupBox)
        # select noise Type Group
        groupBox = QtGui.QGroupBox('Noise Type to select')
        groupBox.setFixedWidth(220)
        hbox1_2 = QtGui.QHBoxLayout()
        # noise Type combo
        self.SOIcombo = QtGui.QComboBox()
        self.SOIcombo.addItem('Zischen', 'Z')
        self.SOIcombo.setItemData(0, QtGui.QColor('#984ea3'),
                                  QtCore.Qt.BackgroundRole)
        self.SOIcombo.setItemData(0, QtGui.QColor('#f5f5f5'), QtCore.Qt.ForegroundRole)  # change text color
        self.SOIcombo.addItem('Kreischen', 'KG')
        # add backgroundcolor of combo K
        self.SOIcombo.setItemData(1, QtGui.QColor('#ffff33'),
                                  QtCore.Qt.BackgroundRole)
        # change text color
        self.SOIcombo.setItemData(1, QtGui.QColor('#272822'), QtCore.Qt.ForegroundRole)
        hbox1_2.addWidget(self.SOIcombo)
        # visualize both cb
        self.cb = QtGui.QCheckBox('both visible', self)
        self.cb.setChecked(self.bothVisibles)
        hbox1_2.addWidget(self.cb)
        groupBox.setLayout(hbox1_2)
        hBox1.addWidget(groupBox)
        hBox1.addStretch(1)
        leftvBox.addLayout(hBox1)
        # add second row to leftvBox: 
        # quality radios
        groupBox = QtGui.QGroupBox("Select quality: are noise events detectable?")
        groupBox.setFixedWidth(507)
        self.Qradios = [QtGui.QRadioButton(q) for q in ['good', 'medium', 'bad']]
        hbox2_1 = QtGui.QHBoxLayout()
        self.rbG = QtGui.QButtonGroup()
        for rb in self.Qradios:
            self.rbG.addButton(rb)
            hbox2_1.addWidget(rb)
        groupBox.setLayout(hbox2_1)
        # add to leftvBox    
        leftvBox.addWidget(groupBox)
        # add leftvBox to second hBox
        secondhBox.addLayout(leftvBox)

        # centre GB of secondhBox
        # add info Groupbox
        groupBox = QtGui.QGroupBox("case informations")
        # add centre GB to second hBox
        secondhBox.addWidget(groupBox)

        # rigth of second hBox
        # save button
        self.buttonSave = QtGui.QPushButton("save", self)
        # rigth second hBox
        secondhBox.addWidget(self.buttonSave)
        secondhBox.addStretch()
        # end second hBox

        # add second hBox to main vBox
        self.vBox.addLayout(secondhBox)
        # -------------

        # set and centralWidget
        centralWidget = QtGui.QWidget()
        centralWidget.setLayout(self.vBox)
        self.setCentralWidget(centralWidget)

        # add connections
        self.connections()
        self.set_current_obs(0)
Example #2
0
File: widgets.py Project: e-sr/KG
class CaseCreatorWidget(BaseAudioWidget):
    # todo: add reset button + method 
    # todo: add rm button + method + log
    # todo: from local constructor

    def __init__(self, author, observations, local=True, db=None):
        # init super
        super(CaseCreatorWidget, self).__init__(setup=False)
        self.setWindowTitle('Create Case')
        # set wavepath casepath and local
        self.author = author
        self.local = local
        if self.local:
            self.db = None
            self.wavpath = pathlib.Path().joinpath('wav')
            self.casepath = pathlib.Path().joinpath('test_case').joinpath(self.author)
        else:
            self.db = db
            self.wavpath = pathlib.Path(WAV_PATH)
            self.casepath = pathlib.Path(CASE_FOLDER).joinpath(self.author)
        try:
            self.wavpath.mkdir()
            self.casepath.mkdir()
        except:
            pass

        # init logger
        fn = self.casepath.joinpath('saved_cases.log')
        logging.basicConfig(format='%(asctime)s %(message)s',
                            filename=str(fn),
                            level=logging.DEBUG,  # filemode = 'w+',
                            datefmt='%Y-%m-%d %H:%M:%S')
        logging.captureWarnings(True)
        logging.info('Start case creator session, local: {}.'.format(self.local))

        # set observations and cases to analyzee, dict observatioins contain observation casess ans its metadata
        self.obsKeys = []
        self.observations = {}
        for obs in observations:
            self.init_obs(obs)
        # set current noise
        self.currentNoise = 'Z'
        self.bothVisibles = True

        # Add New Widgets
        # structure:
        #
        #                   main Phonon Widget
        # ------------------------------------------------------
        #                  Figure canvas widget
        # ------------------------------------------------------
        # selectCase GB | selectSOI GB|
        #         set quality GB      | caseinfo GB | save button
        # ------------------------------------------------------

        # Figure Canvas
        plt.ioff()
        fig = Figure((15, 10))
        fig.set_dpi(110)  # default 110
        fig.set_facecolor('#272822')
        # canvas Widget: first fidget
        self.canvas = FigureCanvas(fig)
        # add axes
        self.ax = fig.add_subplot(111)
        # case Selector
        self.minspan = 0.05
        self.CS = CaseSelector(self.ax, self.onselect, self.onclick,
                               nrect=[50, 50], update_on_ext_event=True,
                               minspan=self.minspan)
        self.ca_bar_handle = [self.CS]
        self.ca_widget_handle = [self.CS]
        # add canvas to main vBox
        self.vBox.addWidget(self.canvas)

        # begin second hBox
        # .................
        secondhBox = QtGui.QHBoxLayout()

        # left vBox of second hBox
        leftvBox = QtGui.QVBoxLayout()
        # add first row to left vBox: hBox1
        hBox1 = QtGui.QHBoxLayout()
        # select case combo 
        groupBox = QtGui.QGroupBox('Select observation to analyze ')
        groupBox.setFixedWidth(280)
        self.obsCombo = QtGui.QComboBox()
        self.obsCombo.addItems(self.obsKeys)
        self.saved_obs_to_green()
        hbox1_1 = QtGui.QHBoxLayout()
        hbox1_1.addWidget(self.obsCombo)
        groupBox.setLayout(hbox1_1)
        hBox1.addWidget(groupBox)
        # select noise Type Group
        groupBox = QtGui.QGroupBox('Noise Type to select')
        groupBox.setFixedWidth(220)
        hbox1_2 = QtGui.QHBoxLayout()
        # noise Type combo
        self.SOIcombo = QtGui.QComboBox()
        self.SOIcombo.addItem('Zischen', 'Z')
        self.SOIcombo.setItemData(0, QtGui.QColor('#984ea3'),
                                  QtCore.Qt.BackgroundRole)
        self.SOIcombo.setItemData(0, QtGui.QColor('#f5f5f5'), QtCore.Qt.ForegroundRole)  # change text color
        self.SOIcombo.addItem('Kreischen', 'KG')
        # add backgroundcolor of combo K
        self.SOIcombo.setItemData(1, QtGui.QColor('#ffff33'),
                                  QtCore.Qt.BackgroundRole)
        # change text color
        self.SOIcombo.setItemData(1, QtGui.QColor('#272822'), QtCore.Qt.ForegroundRole)
        hbox1_2.addWidget(self.SOIcombo)
        # visualize both cb
        self.cb = QtGui.QCheckBox('both visible', self)
        self.cb.setChecked(self.bothVisibles)
        hbox1_2.addWidget(self.cb)
        groupBox.setLayout(hbox1_2)
        hBox1.addWidget(groupBox)
        hBox1.addStretch(1)
        leftvBox.addLayout(hBox1)
        # add second row to leftvBox: 
        # quality radios
        groupBox = QtGui.QGroupBox("Select quality: are noise events detectable?")
        groupBox.setFixedWidth(507)
        self.Qradios = [QtGui.QRadioButton(q) for q in ['good', 'medium', 'bad']]
        hbox2_1 = QtGui.QHBoxLayout()
        self.rbG = QtGui.QButtonGroup()
        for rb in self.Qradios:
            self.rbG.addButton(rb)
            hbox2_1.addWidget(rb)
        groupBox.setLayout(hbox2_1)
        # add to leftvBox    
        leftvBox.addWidget(groupBox)
        # add leftvBox to second hBox
        secondhBox.addLayout(leftvBox)

        # centre GB of secondhBox
        # add info Groupbox
        groupBox = QtGui.QGroupBox("case informations")
        # add centre GB to second hBox
        secondhBox.addWidget(groupBox)

        # rigth of second hBox
        # save button
        self.buttonSave = QtGui.QPushButton("save", self)
        # rigth second hBox
        secondhBox.addWidget(self.buttonSave)
        secondhBox.addStretch()
        # end second hBox

        # add second hBox to main vBox
        self.vBox.addLayout(secondhBox)
        # -------------

        # set and centralWidget
        centralWidget = QtGui.QWidget()
        centralWidget.setLayout(self.vBox)
        self.setCentralWidget(centralWidget)

        # add connections
        self.connections()
        self.set_current_obs(0)

    def _connections(self):
        """connects the buttons/combobox to the methods to be applied"""
        self.obsCombo.currentIndexChanged.connect(self.set_current_obs)
        self.SOIcombo.currentIndexChanged.connect(self.set_SOI_noise_type)
        self.cb.stateChanged.connect(self.set_both_noise_types_visible)
        for rb in self.Qradios:
            rb.clicked.connect(self.set_case_quality)
        self.buttonSave.clicked.connect(self.save_case)

    def init_obs(self, observation):
        self.obsKeys.append(str(observation))
        #
        d = {
            'obs': observation,
            'wavpath': observation.export_to_wav(self.wavpath),
            'case': Case.new_from_obs(observation, self.author),
            'modified': False,
            'saved': False
        }

        if self.local:
            self.set_case_like_local(d)
        else:
            self.set_case_like_db(d)
        sR, t, p = observation.get_signal()
        d['t0'] = t.min()
        d['sn'] = [t, p]
        self.observations[str(observation)] = d

    def set_case_like_db(self, obs):
        c = self.db[CASE_COLLECTION].find_one(obs['case'].get_query())
        if c is not None:
            obs['case'] = Case.from_db(self.db, c['_id'])
            obs['saved'] = True
            return True
        else:
            return False

    def set_case_like_local(self, obs):
        casename = str(obs['case']) + ".json"
        if casename in [cn.name for cn in self.casepath.iterdir()]:
            path = str(self.casepath.joinpath(casename))
            obs['case'] = Case.from_JSON(path)
            obs['saved'] = True
            return True
        else:
            return False

    def set_current_obs(self, index):
        self.releaseKeyboard()
        # stop timer and audio
        self.timer_stop()
        self.media.stop()
        # set obs
        obsKey = self.obsKeys[index]
        self.currentObsKey = obsKey
        self.currentObs = self.observations[obsKey]
        self.case = self.currentObs['case']
        # set media
        self.set_media_source(self.currentObs['wavpath'], self.currentObs['t0'])
        # update buttons
        self.currentNoise = 'Z'
        index = {'Z': 0, 'KG': 1}[self.currentNoise]
        self.SOIcombo.setCurrentIndex(index)
        self.set_SOI_noise_type(index)
        # set cb quality button
        self.set_cb_quality()
        # plot
        self.ax.cla()
        t, p = self.currentObs['sn']
        self.ax.plot(t, p, label=obsKey, color='#272822', linewidth=0.4)
        self.ax.set_xlim([t.min(), t.max()])
        self.ax.set_ylim([p.min(), p.max()])
        self.ax.grid(True)
        self.canvas.draw()
        # update quality cb
        self.set_cb_quality()

        # start timer
        self.grabKeyboard()
        self.timer_start()

    def set_cb_quality(self):
        quality = self.case.get_quality()
        self.rbG.setExclusive(False)
        for rb, qb in zip(self.Qradios, ['good', 'medium', 'bad']):
            rb.setChecked(quality == qb)
        self.rbG.setExclusive(True)

    def set_case_quality(self):
        for q, rb in zip(['good', 'medium', 'bad'], self.Qradios):
            if rb.isChecked():
                self.case.set_quality(q)
                self.set_modified()

    def set_SOI_noise_type(self, index):
        self.currentNoise = ['Z', 'KG'][index]
        self.SOI = self.case.get_SOI(self.currentNoise)
        self.update_stay_rect()

    def set_both_noise_types_visible(self, state):
        if state == QtCore.Qt.Checked:
            self.bothVisibles = True
        else:
            self.bothVisibles = False
        self.update_stay_rect()

    def onclick(self, x):
        # remove Interval
        self.remove_int(x)

    def onselect(self, xmin, xmax, remove=False):
        # add interval1
        if remove:
            self.remove_int(xmin, xmax)
        else:
            self.add_int(xmin, xmax)

    def add_int(self, xmin, xmax):
        Int = Interval(xmin, xmax)
        self.SOI.append(Int)
        self.set_modified()
        self.update_stay_rect()

    def set_int(self, press):
        if press:
            self._t_int_min = self.t
            return
        else:
            tmax = self.t
            if abs(tmax - self._t_int_min) > self.minspan:
                self.add_int(self._t_int_min, tmax)

    def remove_int(self, xmin, xmax=None):
        if xmax == None:
            index = self.SOI.containspoint(xmin)
            if index is not None:
                self.SOI.removebyindex(index)
        else:
            self.SOI.remove(Interval(xmin, xmax))
        self.set_modified()
        self.update_stay_rect()

    def hide_rect(self):
        """hides the rectangles without touching the SOI"""
        self.update_stay_rect(True)
        self.update_canvas()

    def update_stay_rect(self, hide=False):
        for index, nT in enumerate(['Z', 'KG']):
            if not hide:
                if nT == self.currentNoise:
                    self.CS.set_stay_rects_x_bounds(self.SOI.tolist(), index)
                elif self.bothVisibles:
                    self.CS.set_stay_rects_x_bounds(self.case.get_SOI(nT).tolist(), index)
                else:
                    self.CS.set_stay_rect_visible(False, index)
            else:
                self.CS.set_stay_rects_x_bounds([], index)

    def set_modified(self):
        self.currentObs['modified'] = True
        self.case.set_last_update()

    def saved_obs_to_green(self):
        """
        turns the saved cases green
        """
        for n, obsKey in enumerate(self.obsKeys):
            if self.observations[obsKey]['saved']:
                self.obsCombo.setItemData(n, QtGui.QColor('#a6dba0'), QtCore.Qt.BackgroundRole)
            else:
                self.obsCombo.setItemData(n, QtGui.QColor('#EEEEEE'), QtCore.Qt.BackgroundRole)

    def save_case(self):
        obsKey = self.currentObsKey
        save = True
        if self.case.get_quality() == None:
            QtGui.QMessageBox.warning(self, self.trUtf8("save error"),
                                      self.trUtf8("Quality has to be set!"))
            return False
        elif self.observations[obsKey]['modified'] == False:
            QtGui.QMessageBox.information(self, self.trUtf8("save error"),
                                          self.trUtf8("No changes to save"))
            return False
        elif self.observations[obsKey]['saved'] == True:
            answ = QtGui.QMessageBox.question(self, 'Save',
                                              "Do you want overwrite the case?",
                                              QtGui.QMessageBox.Yes | QtGui.QMessageBox.No)
            if answ == QtGui.QMessageBox.No:
                save = False
                return save
        # save
        if save:
            self.observations[obsKey]['case'].save(self.casepath)
            cn = str(self.observations[obsKey]['case'])
            logging.info(cn + ' saved to ' + str(self.casepath))
            if not self.local:
                self.observations[obsKey]['case'].to_db(self.db, overwrite=True)
                _id = self.observations[obsKey]['case'].get_db_id()
                logging.info(cn + ' saved to db, _id: ' + str(_id))
            # set modified and saved flag
            self.observations[obsKey]['saved'] = True
            self.observations[obsKey]['modified'] = False
        self.saved_obs_to_green()

    def show_help(self):
        """call opening info page in external web browser"""
        modulepath = os.path.dirname(kg.widgets.__file__)
        path = pathlib.Path(modulepath).joinpath('case_creator_info/info.html')
        os.startfile(path.absolute().as_uri())

    @classmethod
    def from_local_folder(cls, path, config_file):
        author, ok = QtGui.QInputDialog.getText(None, "Set author", "Please your name : ")
        if ok:
            author = author.replace(' ', '_')
            if author == "":
                author = 'anonymus'
        else:
            author = 'anonymus'

        QtGui.QMessageBox.warning(None, 'Audio system',
                                  'Please use hearphones or a good audio system to analyze the signals.')

        obs_dict = pickle.load(config_file)
        obs = [Observation.from_dict(d) for k, d in obs_dict.items()]
        return cls(observations=obs, author=author, local=True)