Example #1
0
 def test_zero(self):
     assert utilities.time2seconds("00:00:00.000") == Decimal(
         "0.000")
Example #2
0
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
            }
Example #3
0
 def test_positive(self):
     assert utilities.time2seconds("11:22:33.44") == Decimal(
         "40953.44")
Example #4
0
 def test_negative(self):
     assert utilities.time2seconds("-11:22:33.44") == Decimal(
         "-40953.44")
Example #5
0
 def test_wrong_input(self):
     assert utilities.time2seconds("aaaaa") == Decimal("0.000")
Example #6
0
 def test_zero(self):
     assert utilities.time2seconds("00:00:00.000") == Decimal("0.000")
Example #7
0
 def test_negative(self):
     assert utilities.time2seconds("-11:22:33.44") == Decimal("-40953.44")
Example #8
0
 def test_positive(self):
     assert utilities.time2seconds("11:22:33.44") == Decimal("40953.44")
Example #9
0
    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