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)
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)