def test_zero(self): assert utilities.time2seconds("00:00:00.000") == Decimal( "0.000")
def choose_obs_subj_behav_category(pj: dict, selected_observations: list, maxTime=0, flagShowIncludeModifiers: bool = True, flagShowExcludeBehaviorsWoEvents: bool = True, by_category: bool = False, show_time: bool = False, timeFormat: str = HHMMSS): """ show window for: - selection of subjects - selection of behaviors (based on selected subjects) - selection of time interval - inclusion/exclusion of modifiers - inclusion/exclusion of behaviors without events (flagShowExcludeBehaviorsWoEvents == True) Returns: dict: {"selected subjects": selectedSubjects, "selected behaviors": selectedBehaviors, "include modifiers": True/False, "exclude behaviors": True/False, "time": TIME_FULL_OBS / TIME_EVENTS / TIME_ARBITRARY_INTERVAL "start time": startTime, "end time": endTime } """ paramPanelWindow = param_panel.Param_panel() paramPanelWindow.resize(600, 500) paramPanelWindow.setWindowTitle("Select subjects and behaviors") paramPanelWindow.selectedObservations = selected_observations paramPanelWindow.pj = pj if not flagShowIncludeModifiers: paramPanelWindow.cbIncludeModifiers.setVisible(False) if not flagShowExcludeBehaviorsWoEvents: paramPanelWindow.cbExcludeBehaviors.setVisible(False) if by_category: paramPanelWindow.cbIncludeModifiers.setVisible(False) paramPanelWindow.cbExcludeBehaviors.setVisible(False) paramPanelWindow.frm_time_interval.setEnabled(False) if timeFormat == HHMMSS: paramPanelWindow.teStartTime.setTime(QTime.fromString("00:00:00.000", "hh:mm:ss.zzz")) paramPanelWindow.teEndTime.setTime(QTime.fromString(utilities.seconds2time(maxTime), "hh:mm:ss.zzz")) paramPanelWindow.dsbStartTime.setVisible(False) paramPanelWindow.dsbEndTime.setVisible(False) if timeFormat == S: paramPanelWindow.dsbStartTime.setValue(0.0) paramPanelWindow.dsbEndTime.setValue(maxTime) paramPanelWindow.teStartTime.setVisible(False) paramPanelWindow.teEndTime.setVisible(False) # hide max time if not maxTime: paramPanelWindow.frm_time.setVisible(False) if selected_observations: observedSubjects = project_functions.extract_observed_subjects(pj, selected_observations) else: # load all subjects and "No focal subject" observedSubjects = [pj[SUBJECTS][x][SUBJECT_NAME] for x in pj[SUBJECTS]] + [""] selectedSubjects = [] # add 'No focal subject' if "" in observedSubjects: selectedSubjects.append(NO_FOCAL_SUBJECT) paramPanelWindow.item = QListWidgetItem(paramPanelWindow.lwSubjects) paramPanelWindow.ch = QCheckBox() paramPanelWindow.ch.setText(NO_FOCAL_SUBJECT) paramPanelWindow.ch.stateChanged.connect(paramPanelWindow.cb_changed) paramPanelWindow.ch.setChecked(True) paramPanelWindow.lwSubjects.setItemWidget(paramPanelWindow.item, paramPanelWindow.ch) all_subjects = [pj[SUBJECTS][x][SUBJECT_NAME] for x in utilities.sorted_keys(pj[SUBJECTS])] for subject in all_subjects: paramPanelWindow.item = QListWidgetItem(paramPanelWindow.lwSubjects) paramPanelWindow.ch = QCheckBox() paramPanelWindow.ch.setText(subject) paramPanelWindow.ch.stateChanged.connect(paramPanelWindow.cb_changed) if subject in observedSubjects: selectedSubjects.append(subject) paramPanelWindow.ch.setChecked(True) paramPanelWindow.lwSubjects.setItemWidget(paramPanelWindow.item, paramPanelWindow.ch) logging.debug(f'selectedSubjects: {selectedSubjects}') if selected_observations: observedBehaviors = paramPanelWindow.extract_observed_behaviors(selected_observations, selectedSubjects) # not sorted else: # load all behaviors observedBehaviors = [pj[ETHOGRAM][x][BEHAVIOR_CODE] for x in pj[ETHOGRAM]] logging.debug(f'observed behaviors: {observedBehaviors}') if BEHAVIORAL_CATEGORIES in pj: categories = pj[BEHAVIORAL_CATEGORIES][:] # check if behavior not included in a category try: if "" in [pj[ETHOGRAM][idx][BEHAVIOR_CATEGORY] for idx in pj[ETHOGRAM] if BEHAVIOR_CATEGORY in pj[ETHOGRAM][idx]]: categories += [""] except Exception: categories = ["###no category###"] else: categories = ["###no category###"] for category in categories: if category != "###no category###": if category == "": paramPanelWindow.item = QListWidgetItem("No category") paramPanelWindow.item.setData(34, "No category") else: paramPanelWindow.item = QListWidgetItem(category) paramPanelWindow.item.setData(34, category) font = QFont() font.setBold(True) paramPanelWindow.item.setFont(font) paramPanelWindow.item.setData(33, "category") paramPanelWindow.item.setData(35, False) paramPanelWindow.lwBehaviors.addItem(paramPanelWindow.item) for behavior in [pj[ETHOGRAM][x][BEHAVIOR_CODE] for x in utilities.sorted_keys(pj[ETHOGRAM])]: if ((categories == ["###no category###"]) or (behavior in [pj[ETHOGRAM][x][BEHAVIOR_CODE] for x in pj[ETHOGRAM] if BEHAVIOR_CATEGORY in pj[ETHOGRAM][x] and pj[ETHOGRAM][x][BEHAVIOR_CATEGORY] == category])): paramPanelWindow.item = QListWidgetItem(behavior) if behavior in observedBehaviors: paramPanelWindow.item.setCheckState(Qt.Checked) else: paramPanelWindow.item.setCheckState(Qt.Unchecked) if category != "###no category###": paramPanelWindow.item.setData(33, "behavior") if category == "": paramPanelWindow.item.setData(34, "No category") else: paramPanelWindow.item.setData(34, category) paramPanelWindow.lwBehaviors.addItem(paramPanelWindow.item) if not paramPanelWindow.exec_(): return {SELECTED_SUBJECTS: [], SELECTED_BEHAVIORS: []} selectedSubjects = paramPanelWindow.selectedSubjects selectedBehaviors = paramPanelWindow.selectedBehaviors logging.debug(f"selected subjects: {selectedSubjects}") logging.debug(f"selected behaviors: {selectedBehaviors}") if timeFormat == HHMMSS: startTime = utilities.time2seconds(paramPanelWindow.teStartTime.time().toString(HHMMSSZZZ)) endTime = utilities.time2seconds(paramPanelWindow.teEndTime.time().toString(HHMMSSZZZ)) if timeFormat == S: startTime = Decimal(paramPanelWindow.dsbStartTime.value()) endTime = Decimal(paramPanelWindow.dsbEndTime.value()) if startTime > endTime: QMessageBox.warning(None, programName, "The start time is after the end time", QMessageBox.Ok | QMessageBox.Default, QMessageBox.NoButton) return {SELECTED_SUBJECTS: [], SELECTED_BEHAVIORS: []} if paramPanelWindow.rb_full.isChecked(): time_param = TIME_FULL_OBS if paramPanelWindow.rb_limit.isChecked(): time_param = TIME_EVENTS if paramPanelWindow.rb_interval.isChecked(): time_param = TIME_ARBITRARY_INTERVAL return {SELECTED_SUBJECTS: selectedSubjects, SELECTED_BEHAVIORS: selectedBehaviors, INCLUDE_MODIFIERS: paramPanelWindow.cbIncludeModifiers.isChecked(), EXCLUDE_BEHAVIORS: paramPanelWindow.cbExcludeBehaviors.isChecked(), "time": time_param, START_TIME: startTime, END_TIME: endTime }
def test_positive(self): assert utilities.time2seconds("11:22:33.44") == Decimal( "40953.44")
def test_negative(self): assert utilities.time2seconds("-11:22:33.44") == Decimal( "-40953.44")
def test_wrong_input(self): assert utilities.time2seconds("aaaaa") == Decimal("0.000")
def test_zero(self): assert utilities.time2seconds("00:00:00.000") == Decimal("0.000")
def test_negative(self): assert utilities.time2seconds("-11:22:33.44") == Decimal("-40953.44")
def test_positive(self): assert utilities.time2seconds("11:22:33.44") == Decimal("40953.44")
def check_parameters(self): """ check observation parameters return True if everything OK else False """ def is_numeric(s): """ check if s is numeric (float) Args: s (str/int/float): value to test Returns: boolean: True if numeric else False """ try: float(s) return True except ValueError: return False if self.tabProjectType.currentIndex() == 0: # check player number players_list = [] players = {} # for storing duration for row in range(self.twVideo1.rowCount()): players_list.append(int(self.twVideo1.cellWidget(row, 0).currentText())) if int(self.twVideo1.cellWidget(row, 0).currentText()) not in players: players[int(self.twVideo1.cellWidget(row, 0).currentText())] = [utilities.time2seconds(self.twVideo1.item(row, 3).text())] else: players[int(self.twVideo1.cellWidget(row, 0).currentText())].append(utilities.time2seconds(self.twVideo1.item(row, 3).text())) # check if player#1 used if not players_list or min(players_list) > 1: QMessageBox.critical(self, programName , "A media file must be loaded in player #1") return False # check if players are used in crescent order if set(list(range(min(players_list), max(players_list) + 1))) != set(players_list): QMessageBox.critical(self, programName , "Some player are not used. Please reorganize your media file") return False # check that longuest media is in player #1 durations = [] for i in players: durations.append(sum(players[i])) if [x for x in durations[1:] if x > durations[0]]: QMessageBox.critical(self, programName , "The longuest media file(s) must be loaded in player #1") return False # check time offset if not is_numeric(self.leTimeOffset.text()): QMessageBox.critical(self, programName , "<b>{}</b> is not recognized as a valid time offset format".format(self.leTimeOffset.text())) return False # check if indep variables are correct type for row in range(self.twIndepVariables.rowCount()): if self.twIndepVariables.item(row, 1).text() == NUMERIC: if self.twIndepVariables.item(row, 2).text() and not is_numeric( self.twIndepVariables.item(row, 2).text() ): QMessageBox.critical(self, programName, "The <b>{}</b> variable must be numeric!".format(self.twIndepVariables.item(row, 0).text())) return False # check if observation id not empty if not self.leObservationId.text(): QMessageBox.warning(self, programName , "The <b>observation id</b> is mandatory and must be unique!" ) return False # check if new obs and observation id already present or if edit obs and id changed if (self.mode == "new") or (self.mode == "edit" and self.leObservationId.text() != self.mem_obs_id): if self.leObservationId.text() in self.pj[OBSERVATIONS]: QMessageBox.critical(self, programName, "The observation id <b>{0}</b> is already used!<br>{1}<br>{2}".format(self.leObservationId.text(), self.pj['observations'][self.leObservationId.text()]['description'], self.pj['observations'][self.leObservationId.text()]['date'])) return False # check if media list #2 populated and media list #1 empty if self.tabProjectType.currentIndex() == 0 and not self.twVideo1.rowCount(): QMessageBox.critical(self, programName , "Add a media file in the first media player!" ) return False # check offset for external data files for row in range(self.tw_data_files.rowCount()): if not is_numeric(self.tw_data_files.item(row, PLOT_DATA_TIMEOFFSET_IDX).text()): QMessageBox.critical(self, programName, ("The external data file start value <b>{}</b> is not recognized as a numeric value.<br>" "Use decimal number of seconds (e.g. -58.5 or 32)").format( self.tw_data_files.item(row, PLOT_DATA_TIMEOFFSET_IDX).text())) return False for row in range(self.twIndepVariables.rowCount()): if self.twIndepVariables.item(row, 1).text() == NUMERIC: if self.twIndepVariables.item(row, 2).text() and not is_numeric( self.twIndepVariables.item(row, 2).text() ): QMessageBox.critical(self, programName, "The <b>{}</b> variable must be numeric!".format(self.twIndepVariables.item(row, 0).text())) return False return True