Exemplo n.º 1
0
    def __init__(self, modifiers_str, subjects=[], parent=None):

        super().__init__()
        self.setupUi(self)

        self.subjects = subjects
        if not self.subjects:
            self.pb_add_subjects.setEnabled(False)

        self.pbAddModifier.clicked.connect(self.addModifier)
        self.pbAddModifier.setIcon(QIcon(":/frame_forward"))
        self.pbAddSet.clicked.connect(self.addSet)
        self.pbRemoveSet.clicked.connect(self.removeSet)
        self.pbModifyModifier.clicked.connect(self.modifyModifier)
        self.pbModifyModifier.setIcon(QIcon(":/frame_backward"))

        self.pbMoveUp.clicked.connect(self.moveModifierUp)
        self.pbMoveDown.clicked.connect(self.moveModifierDown)
        self.pbMoveSetLeft.clicked.connect(self.moveSetLeft)
        self.pbMoveSetRight.clicked.connect(self.moveSetRight)
        self.pbRemoveModifier.clicked.connect(self.removeModifier)
        self.pb_sort_modifiers.clicked.connect(self.sort_modifiers)
        self.pb_add_subjects.clicked.connect(self.add_subjects)
        self.pb_load_file.clicked.connect(self.add_modifiers_from_file)

        self.pbOK.clicked.connect(lambda: self.pb_pushed("ok"))
        self.pbCancel.clicked.connect(lambda: self.pb_pushed("cancel"))

        self.leSetName.textChanged.connect(self.set_name_changed)

        self.cbType.currentIndexChanged.connect(self.type_changed)

        dummy_dict = eval(modifiers_str) if modifiers_str else {}
        modif_values = []
        for idx in sorted_keys(dummy_dict):
            modif_values.append(dummy_dict[idx])

        self.modifiers_sets_dict = {}
        for modif in modif_values:
            self.modifiers_sets_dict[str(len(self.modifiers_sets_dict))] = dict(modif)

        self.tabWidgetModifiersSets.currentChanged.connect(self.tabWidgetModifiersSets_changed)

        # create tab
        for idx in sorted_keys(self.modifiers_sets_dict):
            self.tabWidgetModifiersSets.addTab(QWidget(), f"Set #{int(idx) + 1}")

        if self.tabWidgetModifiersSets.currentIndex() == -1:
            for w in [self.lbSetName, self.lbType, self.lbValues, self.leSetName, self.cbType, self.lwModifiers, self.pbMoveUp,
                      self.pbMoveDown, self.pbRemoveModifier, self.pbRemoveSet, self.pbMoveSetLeft, self.pbMoveSetRight,
                      self.pb_add_subjects, self.pb_load_file, self.pb_sort_modifiers]:
                w.setVisible(False)
            for w in [self.leModifier, self.leCode, self.pbAddModifier, self.pbModifyModifier]:
                w.setEnabled(False)

        # set first tab as active
        self.tabMem = 0
Exemplo n.º 2
0
    def __init__(self, modifiers_str, subjects=[], parent=None):

        super().__init__()
        self.setupUi(self)

        self.subjects = subjects

        self.pbAddModifier.clicked.connect(self.addModifier)
        self.pbAddModifier.setIcon(QIcon(":/frame_forward"))
        self.pbAddSet.clicked.connect(self.addSet)
        self.pbRemoveSet.clicked.connect(self.removeSet)
        self.pbModifyModifier.clicked.connect(self.modifyModifier)
        self.pbModifyModifier.setIcon(QIcon(":/frame_backward"))

        self.pbMoveUp.clicked.connect(self.moveModifierUp)
        self.pbMoveDown.clicked.connect(self.moveModifierDown)
        self.pbMoveSetLeft.clicked.connect(self.moveSetLeft)
        self.pbMoveSetRight.clicked.connect(self.moveSetRight)
        self.pbRemoveModifier.clicked.connect(self.removeModifier)
        self.pb_sort_modifiers.clicked.connect(self.sort_modifiers)
        self.pb_add_subjects.clicked.connect(self.add_subjects)
        self.pb_load_file.clicked.connect(self.add_modifiers_from_file)

        self.pbOK.clicked.connect(lambda: self.pb_pushed("ok"))
        self.pbCancel.clicked.connect(lambda: self.pb_pushed("cancel"))

        self.leSetName.textChanged.connect(self.set_name_changed)

        self.cbType.currentIndexChanged.connect(self.type_changed)

        dummy_dict = eval(modifiers_str) if modifiers_str else {}
        modif_values = []
        for idx in sorted_keys(dummy_dict):
            modif_values.append(dummy_dict[idx])


        self.modifiers_sets_dict = {}
        for modif in modif_values:
            self.modifiers_sets_dict[str(len(self.modifiers_sets_dict))] = dict(modif)

        self.tabWidgetModifiersSets.currentChanged.connect(self.tabWidgetModifiersSets_changed)

        # create tab
        for idx in sorted_keys(self.modifiers_sets_dict):
            self.tabWidgetModifiersSets.addTab(QWidget(), f"Set #{int(idx) + 1}")

        if self.tabWidgetModifiersSets.currentIndex() == -1:
            for w in [self.lbSetName, self.lbType, self.lbValues, self.leSetName, self.cbType, self.lwModifiers, self.pbMoveUp,
                      self.pbMoveDown, self.pbRemoveModifier, self.pbRemoveSet, self.pbMoveSetLeft, self.pbMoveSetRight,
                      self.pb_add_subjects, self.pb_load_file, self.pb_sort_modifiers]:
                w.setVisible(False)
            for w in [self.leModifier, self.leCode, self.pbAddModifier, self.pbModifyModifier]:
                w.setEnabled(False)

        # set first tab as active
        self.tabMem = 0
Exemplo n.º 3
0
    def removeSet(self):
        """
        remove set of modifiers
        """

        if self.tabWidgetModifiersSets.currentIndex() != -1:
            if dialog.MessageDialog(programName, "Confirm deletion of this set of modifiers?", [YES, NO]) == YES:
                index_to_delete = self.tabWidgetModifiersSets.currentIndex()

                for k in range(index_to_delete, len(self.modifiers_sets_dict) - 1):
                    self.modifiers_sets_dict[str(k)] = self.modifiers_sets_dict[str(k + 1)]
                # del last key
                del self.modifiers_sets_dict[str(len(self.modifiers_sets_dict) - 1)]

                # remove all tabs
                while self.tabWidgetModifiersSets.count():
                    self.tabWidgetModifiersSets.removeTab(0)

                # recreate tabs
                for idx in sorted_keys(self.modifiers_sets_dict):
                    self.tabWidgetModifiersSets.addTab(QWidget(), f"Set #{int(idx) + 1}")

                # set not visible and not available buttons and others elements
                if self.tabWidgetModifiersSets.currentIndex() == -1:
                    for w in [self.lbSetName, self.lbType, self.lbValues, self.leSetName, self.cbType, self.lwModifiers, self.pbMoveUp,
                              self.pbMoveDown, self.pbRemoveModifier, self.pbRemoveSet, self.pbMoveSetLeft, self.pbMoveSetRight]:
                        w.setVisible(False)
                    for w in [self.leModifier, self.leCode, self.pbAddModifier, self.pbModifyModifier]:
                        w.setEnabled(False)
        else:
            QMessageBox.information(self, programName, "It is not possible to remove the last modifiers' set.")
Exemplo n.º 4
0
 def test_str_keys(self):
     r = utilities.sorted_keys({
         "10": "x",
         "0": "x",
         "1": "x",
         "11": "x",
         "05": "x"
     })
     #print(r)
     assert r == ['0', '1', '5', '10', '11']
Exemplo n.º 5
0
    def pbOK_clicked(self):

        for idx in sorted_keys(self.modifiers_dict):
            if self.modifiers_dict[idx]["type"] == NUMERIC_MODIFIER:
                if self.modifiers_dict[idx]["widget"].text():
                    try:
                        val = float(self.modifiers_dict[idx]["widget"].text())
                    except Exception:
                        QMessageBox.warning(self, programName,
                                            "<b>{}</b> is not a numeric value".format(self.modifiers_dict[idx]["widget"].text()))
                        return

        self.accept()
Exemplo n.º 6
0
    def pbOK_clicked(self):

        for idx in sorted_keys(self.modifiers_dict):
            if self.modifiers_dict[idx]["type"] == NUMERIC_MODIFIER:
                if self.modifiers_dict[idx]["widget"].text():
                    try:
                        val = float(self.modifiers_dict[idx]["widget"].text())
                    except Exception:
                        QMessageBox.warning(self, programName,
                                            "<b>{}</b> is not a numeric value".format(self.modifiers_dict[idx]["widget"].text()))
                        return

        self.accept()
Exemplo n.º 7
0
    def removeSet(self):
        """
        remove set of modifiers
        """

        if self.tabWidgetModifiersSets.currentIndex() != -1:
            if dialog.MessageDialog(
                    programName, "Confirm deletion of this set of modifiers?",
                [YES, NO]) == YES:
                index_to_delete = self.tabWidgetModifiersSets.currentIndex()

                for k in range(index_to_delete,
                               len(self.modifiers_sets_dict) - 1):
                    self.modifiers_sets_dict[str(
                        k)] = self.modifiers_sets_dict[str(k + 1)]
                # del last key
                del self.modifiers_sets_dict[str(
                    len(self.modifiers_sets_dict) - 1)]

                # remove all tabs
                while self.tabWidgetModifiersSets.count():
                    self.tabWidgetModifiersSets.removeTab(0)

                # recreate tabs
                for idx in sorted_keys(self.modifiers_sets_dict):
                    self.tabWidgetModifiersSets.addTab(QWidget(),
                                                       f"Set #{int(idx) + 1}")

                # set not visible and not available buttons and others elements
                if self.tabWidgetModifiersSets.currentIndex() == -1:
                    for w in [
                            self.lbSetName, self.lbType, self.lbValues,
                            self.leSetName, self.cbType, self.lwModifiers,
                            self.pbMoveUp, self.pbMoveDown,
                            self.pbRemoveModifier, self.pbRemoveSet,
                            self.pbMoveSetLeft, self.pbMoveSetRight
                    ]:
                        w.setVisible(False)
                    for w in [
                            self.leModifier, self.leCode, self.pbAddModifier,
                            self.pbModifyModifier
                    ]:
                        w.setEnabled(False)
        else:
            QMessageBox.information(
                self, programName,
                "It is not possible to remove the last modifiers' set.")
Exemplo n.º 8
0
    def get_modifiers(self):
        """
        get modifiers
        returns list of selected modifiers
        """
        modifiers = []
        for idx in sorted_keys(self.modifiers_dict):

            if self.modifiers_dict[idx]["type"] in [
                    SINGLE_SELECTION, MULTI_SELECTION, NUMERIC_MODIFIER
            ]:
                self.modifiers_dict[idx]["selected"] = []

            if self.modifiers_dict[idx]["type"] == MULTI_SELECTION:
                for j in range(self.modifiers_dict[idx]["widget"].count()):
                    if self.modifiers_dict[idx]["widget"].item(
                            j).checkState() == Qt.Checked:
                        self.modifiers_dict[idx]["selected"].append(
                            re.sub(
                                " \(.*\)", "", self.modifiers_dict[idx]
                                ["widget"].item(j).text()))

                if not self.modifiers_dict[idx]["selected"]:
                    self.modifiers_dict[idx]["selected"].append("None")

            if self.modifiers_dict[idx]["type"] == SINGLE_SELECTION:
                for item in self.modifiers_dict[idx]["widget"].selectedItems():
                    self.modifiers_dict[idx]["selected"].append(
                        re.sub(" \(.*\)", "", item.text()))

            if self.modifiers_dict[idx]["type"] == NUMERIC_MODIFIER:
                self.modifiers_dict[
                    idx]["selected"] = self.modifiers_dict[idx]["widget"].text(
                    ) if self.modifiers_dict[idx]["widget"].text() else "None"
        '''
        for widget in self.children():
            if widget.objectName() == "lw_modifiers_classic":
                for item in widget.selectedItems():
                    modifiers.append(re.sub(" \(.*\)", "", item.text()))
            if widget.objectName() == "lw_modifiers_from_set":
                for idx in range(widget.count()):
                    if widget.item(idx).checkState() == Qt.Checked:
                        modifiers.append(widget.item(idx).text())
        '''

        return self.modifiers_dict
Exemplo n.º 9
0
    def get_modifiers(self):
        """
        get modifiers
        returns list of selected modifiers
        """
        modifiers = []
        for idx in sorted_keys(self.modifiers_dict):

            if self.modifiers_dict[idx]["type"] in [SINGLE_SELECTION, MULTI_SELECTION, NUMERIC_MODIFIER]:
                self.modifiers_dict[idx]["selected"] = []

            if self.modifiers_dict[idx]["type"] == MULTI_SELECTION:
                for j in range(self.modifiers_dict[idx]["widget"].count()):
                    if self.modifiers_dict[idx]["widget"].item(j).checkState() == Qt.Checked:
                        self.modifiers_dict[idx]["selected"].append(
                            re.sub(" \(.*\)", "", self.modifiers_dict[idx]["widget"].item(j).text()))

                if not self.modifiers_dict[idx]["selected"]:
                    self.modifiers_dict[idx]["selected"].append("None")

            if self.modifiers_dict[idx]["type"] == SINGLE_SELECTION:
                for item in self.modifiers_dict[idx]["widget"].selectedItems():
                    self.modifiers_dict[idx]["selected"].append(re.sub(" \(.*\)", "", item.text()))

            if self.modifiers_dict[idx]["type"] == NUMERIC_MODIFIER:
                self.modifiers_dict[idx]["selected"] = self.modifiers_dict[idx]["widget"].text() if self.modifiers_dict[idx]["widget"].text(
                ) else "None"
        '''
        for widget in self.children():
            if widget.objectName() == "lw_modifiers_classic":
                for item in widget.selectedItems():
                    modifiers.append(re.sub(" \(.*\)", "", item.text()))
            if widget.objectName() == "lw_modifiers_from_set":
                for idx in range(widget.count()):
                    if widget.item(idx).checkState() == Qt.Checked:
                        modifiers.append(widget.item(idx).text())
        '''

        return self.modifiers_dict
Exemplo n.º 10
0
def create_events_plot(pj,
                       selected_observations,
                       parameters,
                       plot_colors=BEHAVIORS_PLOT_COLORS,
                       plot_directory="",
                       file_format="png"):

    selected_subjects = parameters[SELECTED_SUBJECTS]
    selected_behaviors = parameters[SELECTED_BEHAVIORS]
    include_modifiers = parameters[INCLUDE_MODIFIERS]
    interval = parameters[TIME_INTERVAL]
    start_time = parameters[START_TIME]
    end_time = parameters[END_TIME]

    ok, msg, db_connector = db_functions.load_aggregated_events_in_db(
        pj, selected_subjects, selected_observations, selected_behaviors)

    if not ok:
        return False, msg, None
    cursor = db_connector.cursor()

    # if modifiers not to be included set modifiers to ""
    if not include_modifiers:
        cursor.execute("UPDATE aggregated_events SET modifiers = ''")

    cursor.execute(
        "SELECT distinct behavior, modifiers FROM aggregated_events")
    distinct_behav_modif = [[rows["behavior"], rows["modifiers"]]
                            for rows in cursor.fetchall()]

    # add selected behaviors that are not observed
    for behav in selected_behaviors:
        if [x for x in distinct_behav_modif if x[0] == behav] == []:
            distinct_behav_modif.append([behav, "-"])

    distinct_behav_modif = sorted(distinct_behav_modif)
    max_len = len(distinct_behav_modif)

    all_behaviors = [
        pj[ETHOGRAM][x][BEHAVIOR_CODE]
        for x in utilities.sorted_keys(pj[ETHOGRAM])
    ]

    par1 = 1
    bar_height = 0.5
    init = dt.datetime(2017, 1, 1)

    for obs_id in selected_observations:

        if len(selected_subjects) > 1:
            fig, axs = plt.subplots(figsize=(20, 8),
                                    nrows=len(selected_subjects),
                                    ncols=1,
                                    sharex=True)
        else:
            fig, ax = plt.subplots(figsize=(20, 8),
                                   nrows=len(selected_subjects),
                                   ncols=1,
                                   sharex=True)
            axs = np.ndarray(shape=(1), dtype=type(ax))
            axs[0] = ax

        ok, msg, db_connector = db_functions.load_aggregated_events_in_db(
            pj, selected_subjects, [obs_id], selected_behaviors)

        cursor = db_connector.cursor()
        # if modifiers not to be included set modifiers to ""
        if not include_modifiers:
            cursor.execute("UPDATE aggregated_events SET modifiers = ''")
        cursor = db_connector.cursor()

        cursor.execute(
            "SELECT distinct behavior, modifiers FROM aggregated_events")
        distinct_behav_modif = [[rows["behavior"], rows["modifiers"]]
                                for rows in cursor.fetchall()]

        # add selected behaviors that are not observed
        if not parameters["exclude behaviors"]:
            for behav in selected_behaviors:
                if [x for x in distinct_behav_modif if x[0] == behav] == []:
                    distinct_behav_modif.append([behav, "-"])

        distinct_behav_modif = sorted(distinct_behav_modif)
        max_len = len(distinct_behav_modif)

        # time
        obs_length = project_functions.observation_total_length(
            pj[OBSERVATIONS][obs_id])
        if obs_length == -1:  # media length not available
            interval = TIME_EVENTS

        if interval == TIME_FULL_OBS:
            min_time = float(0)
            max_time = float(obs_length)

        if interval == TIME_EVENTS:
            try:
                min_time = float(pj[OBSERVATIONS][obs_id][EVENTS][0][0])
            except Exception:
                min_time = float(0)
            try:
                max_time = float(pj[OBSERVATIONS][obs_id][EVENTS][-1][0])
            except Exception:
                max_time = float(obs_length)

        if interval == TIME_ARBITRARY_INTERVAL:
            min_time = float(start_time)
            max_time = float(end_time)

        cursor.execute(
            "UPDATE aggregated_events SET start = ? WHERE observation = ? AND start < ? AND stop BETWEEN ? AND ?",
            (
                min_time,
                obs_id,
                min_time,
                min_time,
                max_time,
            ))
        cursor.execute(
            "UPDATE aggregated_events SET stop = ? WHERE observation = ? AND stop > ? AND start BETWEEN ? AND ?",
            (
                max_time,
                obs_id,
                max_time,
                min_time,
                max_time,
            ))
        cursor.execute(
            "UPDATE aggregated_events SET start = ?, stop = ? WHERE observation = ? AND start < ? AND stop > ?",
            (
                min_time,
                max_time,
                obs_id,
                min_time,
                max_time,
            ))

        ylabels = [" ".join(x) for x in distinct_behav_modif]
        for ax_idx, subject in enumerate(selected_subjects):

            if parameters["exclude behaviors"]:
                cursor.execute(
                    "SELECT distinct behavior, modifiers FROM aggregated_events WHERE subject = ?",
                    (subject, ))
                distinct_behav_modif = [[rows["behavior"], rows["modifiers"]]
                                        for rows in cursor.fetchall()]

                # add selected behaviors that are not observed
                if not parameters["exclude behaviors"]:
                    for behav in selected_behaviors:
                        if [x for x in distinct_behav_modif
                                if x[0] == behav] == []:
                            distinct_behav_modif.append([behav, "-"])

                distinct_behav_modif = sorted(distinct_behav_modif)
                max_len = len(distinct_behav_modif)
                ylabels = [" ".join(x) for x in distinct_behav_modif]

            if not ax_idx:
                axs[ax_idx].set_title(f"Observation {obs_id}\n{subject}",
                                      fontsize=14)
            else:
                axs[ax_idx].set_title(subject, fontsize=14)
            bars = {}
            i = 0
            for behavior_modifiers in distinct_behav_modif:
                behavior, modifiers = behavior_modifiers
                behavior_modifiers_str = "|".join(
                    behavior_modifiers) if modifiers else behavior
                bars[behavior_modifiers_str] = []

                # total duration
                cursor.execute((
                    "SELECT start,stop FROM aggregated_events "
                    "WHERE observation = ? AND subject = ? AND behavior = ? AND modifiers = ?"
                ), (
                    obs_id,
                    subject,
                    behavior,
                    modifiers,
                ))
                for row in cursor.fetchall():
                    bars[behavior_modifiers_str].append(
                        (row["start"], row["stop"]))

                    start_date = matplotlib.dates.date2num(init + dt.timedelta(
                        seconds=row["start"]))
                    end_date = matplotlib.dates.date2num(init + dt.timedelta(
                        seconds=row["stop"] + POINT_EVENT_PLOT_DURATION *
                        (row["stop"] == row["start"])))
                    try:
                        bar_color = utilities.behavior_color(
                            plot_colors, all_behaviors.index(behavior))
                    except Exception:
                        bar_color = "darkgray"
                    bar_color = POINT_EVENT_PLOT_COLOR if row["stop"] == row[
                        "start"] else bar_color

                    # sage colors removed from matplotlib colors list
                    if bar_color in ["sage", "darksage", "lightsage"]:
                        bar_color = {
                            "darksage": "#598556",
                            "lightsage": "#bcecac",
                            "sage": "#87ae73"
                        }[bar_color]

                    try:
                        axs[ax_idx].barh((i * par1) + par1,
                                         end_date - start_date,
                                         left=start_date,
                                         height=bar_height,
                                         align="center",
                                         edgecolor=bar_color,
                                         color=bar_color,
                                         alpha=1)
                    except Exception:
                        axs[ax_idx].barh((i * par1) + par1,
                                         end_date - start_date,
                                         left=start_date,
                                         height=bar_height,
                                         align="center",
                                         edgecolor="darkgray",
                                         color="darkgray",
                                         alpha=1)

                i += 1

            axs[ax_idx].set_ylim(bottom=0, top=(max_len * par1) + par1)
            pos = np.arange(par1, max_len * par1 + par1 + 1, par1)
            axs[ax_idx].set_yticks(pos[:len(ylabels)])

            axs[ax_idx].set_yticklabels(ylabels, fontdict={"fontsize": 10})

            axs[ax_idx].set_ylabel("Behaviors" +
                                   " (modifiers)" * include_modifiers,
                                   fontdict={"fontsize": 10})

            axs[ax_idx].set_xlim(
                left=matplotlib.dates.date2num(init +
                                               dt.timedelta(seconds=min_time)),
                right=matplotlib.dates.date2num(init + dt.timedelta(
                    seconds=max_time + 1)))

            axs[ax_idx].grid(color="g", linestyle=":")
            axs[ax_idx].xaxis_date()
            axs[ax_idx].xaxis.set_major_formatter(DateFormatter("%H:%M:%S"))
            axs[ax_idx].set_xlabel("Time (HH:MM:SS)",
                                   fontdict={"fontsize": 12})
            axs[ax_idx].invert_yaxis()

        fig.autofmt_xdate()
        plt.tight_layout()

        if len(selected_observations) > 1:
            output_file_name = str(
                pathlib.Path(
                    pathlib.Path(plot_directory) /
                    utilities.safeFileName(obs_id)).with_suffix("." +
                                                                file_format))
            plt.savefig(output_file_name)
        else:
            plt.show()
Exemplo n.º 11
0
def select_observations(pj: dict, mode: str, windows_title: str = "") -> tuple:
    """
    allow user to select observations
    mode: accepted values: OPEN, EDIT, SINGLE, MULTIPLE, SELECT1

    Args:
        pj (dict): BORIS project dictionary
        mode (str): mode foe selection: OPEN, EDIT, SINGLE, MULTIPLE, SELECT1
        windows_title (str): title for windows

    Returns:
        str: selected mode: OPEN, EDIT, VIEW
        list: list of selected observations
    """

    obsListFields = ["id", "date", "description", "subjects", "media"]
    indepVarHeader, column_type = [], [TEXT] * len(obsListFields)

    if INDEPENDENT_VARIABLES in pj:
        for idx in utilities.sorted_keys(pj[INDEPENDENT_VARIABLES]):
            indepVarHeader.append(pj[INDEPENDENT_VARIABLES][idx]["label"])
            column_type.append(pj[INDEPENDENT_VARIABLES][idx]["type"])

    data = []
    for obs in sorted(list(pj[OBSERVATIONS].keys())):
        date = pj[OBSERVATIONS][obs]["date"].replace("T", " ")
        descr = utilities.eol2space(pj[OBSERVATIONS][obs][DESCRIPTION])

        # subjects
        observedSubjects = [NO_FOCAL_SUBJECT if x == "" else x for x in project_functions.extract_observed_subjects(pj, [obs])]

        ''' removed 2020-01-13
        if "" in observedSubjects:
            observedSubjects.remove("")
        '''
        subjectsList = ", ".join(observedSubjects)

        mediaList = []
        if pj[OBSERVATIONS][obs][TYPE] in [MEDIA]:
            if pj[OBSERVATIONS][obs][FILE]:
                for player in sorted(pj[OBSERVATIONS][obs][FILE].keys()):
                    for media in pj[OBSERVATIONS][obs][FILE][player]:
                        mediaList.append(f"#{player}: {media}")

            if len(mediaList) > 8:
                media = " ".join(mediaList)
            else:
                media = "\n".join(mediaList)

        elif pj[OBSERVATIONS][obs][TYPE] in [LIVE]:
            media = LIVE

        # independent variables
        indepvar = []
        if INDEPENDENT_VARIABLES in pj[OBSERVATIONS][obs]:
            for var_label in indepVarHeader:
                if var_label in pj[OBSERVATIONS][obs][INDEPENDENT_VARIABLES]:
                    indepvar.append(pj[OBSERVATIONS][obs][INDEPENDENT_VARIABLES][var_label])
                else:
                    indepvar.append("")

        data.append([obs, date, descr, subjectsList, media] + indepvar)

    obsList = observations_list.observationsList_widget(data,
                                                        header=obsListFields + indepVarHeader,
                                                        column_type=column_type)
    if windows_title:
        obsList.setWindowTitle(windows_title)

    obsList.pbOpen.setVisible(False)
    obsList.pbView.setVisible(False)
    obsList.pbEdit.setVisible(False)
    obsList.pbOk.setVisible(False)
    obsList.pbSelectAll.setVisible(False)
    obsList.pbUnSelectAll.setVisible(False)
    obsList.mode = mode

    if mode == OPEN:
        obsList.view.setSelectionMode(QAbstractItemView.SingleSelection)
        obsList.pbOpen.setVisible(True)

    if mode == VIEW:
        obsList.view.setSelectionMode(QAbstractItemView.SingleSelection)
        obsList.pbView.setVisible(True)


    if mode == EDIT:
        obsList.view.setSelectionMode(QAbstractItemView.SingleSelection)
        obsList.pbEdit.setVisible(True)

    if mode == SINGLE:
        obsList.view.setSelectionMode(QAbstractItemView.SingleSelection)
        obsList.pbOpen.setVisible(True)
        obsList.pbView.setVisible(True)
        obsList.pbEdit.setVisible(True)

    if mode == MULTIPLE:
        obsList.view.setSelectionMode(QAbstractItemView.MultiSelection)
        obsList.pbOk.setVisible(True)
        obsList.pbSelectAll.setVisible(True)
        obsList.pbUnSelectAll.setVisible(True)

    if mode == SELECT1:
        obsList.view.setSelectionMode(QAbstractItemView.SingleSelection)
        obsList.pbOk.setVisible(True)

    obsList.resize(900, 600)

    obsList.view.sortItems(0, Qt.AscendingOrder)
    for row in range(obsList.view.rowCount()):
        obsList.view.resizeRowToContents(row)

    selectedObs = []

    result = obsList.exec_()

    if result:
        if obsList.view.selectedIndexes():
            for idx in obsList.view.selectedIndexes():
                if idx.column() == 0:   # first column
                    selectedObs.append(idx.data())

    if result == 0:  # cancel
        resultStr = ""
    if result == 1:   # select
        resultStr = "ok"
    if result == 2:   # open
        resultStr = OPEN
    if result == 3:   # edit
        resultStr = EDIT
    if result == 4:   # view
        resultStr = VIEW

    return resultStr, selectedObs
Exemplo n.º 12
0
 def test_str_keys(self):
     r = utilities.sorted_keys({"10": "x", "0": "x", "1": "x", "11": "x", "05": "x"})
     #print(r)
     assert r == ['0', '1', '5', '10', '11']
Exemplo n.º 13
0
def create_behaviors_bar_plot(pj: dict,
                       selected_observations: list,
                       param: dict,
                       plot_directory: str,
                       output_format: str,
                       plot_colors:list=BEHAVIORS_PLOT_COLORS):
    """
    time budget bar plot

    Args:
        pj (dict): project
        param (dict): parameters
        plot_directory (str): path of directory
        output_format (str): image format

    Returns:
        dict:
    """

    selected_subjects = param[SELECTED_SUBJECTS]
    selected_behaviors = param[SELECTED_BEHAVIORS]
    time_interval = param["time"]
    start_time = param[START_TIME]
    end_time = param[END_TIME]

    parameters = ["duration", "number of occurences"]

    ok, msg, db_connector = db_functions.load_aggregated_events_in_db(pj,
                                                                      selected_subjects,
                                                                      selected_observations,
                                                                      selected_behaviors)

    if not ok:
        return {"error": True, "message": msg}
    try:

        # extract all behaviors from ethogram for colors in plot
        all_behaviors = [pj[ETHOGRAM][x][BEHAVIOR_CODE] for x in utilities.sorted_keys(pj[ETHOGRAM])]

        for obs_id in selected_observations:

            cursor = db_connector.cursor()
            # distinct behaviors
            cursor.execute("SELECT distinct behavior FROM aggregated_events WHERE observation = ?",
                           (obs_id,))
            distinct_behav = [rows["behavior"] for rows in cursor.fetchall()]

            # add selected behaviors that are not observed
            '''
            if not param[EXCLUDE_BEHAVIORS]:
                for behavior in selected_behaviors:
                    if [x for x in distinct_behav if x == behavior] == []:
                        distinct_behav.append(behavior)
            '''

            # distinct subjects
            cursor.execute("SELECT distinct subject FROM aggregated_events WHERE observation = ?",
                           (obs_id,))
            distinct_subjects = [rows["subject"] for rows in cursor.fetchall()]

            behaviors = init_behav(pj[ETHOGRAM],
                                distinct_subjects,
                                distinct_behav,
                                parameters)

            # plot creation
            if len(distinct_subjects) > 1:
                fig, axs = plt.subplots(nrows=1, ncols=len(distinct_subjects), sharey=True)
                fig2, axs2 = plt.subplots(nrows=1, ncols=len(distinct_subjects), sharey=True)

            else:
                fig, ax = plt.subplots(nrows=1, ncols=len(distinct_subjects), sharey=True)
                axs = np.ndarray(shape=(1), dtype=type(ax))
                axs[0] = ax

                fig2, ax2 = plt.subplots(nrows=1, ncols=len(distinct_subjects), sharey=True)
                axs2 = np.ndarray(shape=(1), dtype=type(ax2))
                axs2[0] = ax2

            fig.suptitle("Durations of behaviors")
            fig2.suptitle("Number of occurences of behaviors")

            # if modifiers not to be included set modifiers to ""
            cursor.execute("UPDATE aggregated_events SET modifiers = ''")

            # time
            obs_length = project_functions.observation_total_length(pj[OBSERVATIONS][obs_id])
            if obs_length == -1:
                obs_length = 0

            if param["time"] == TIME_FULL_OBS:
                min_time = float(0)
                max_time = float(obs_length)

            if param["time"] == TIME_EVENTS:
                try:
                    min_time = float(pj[OBSERVATIONS][obs_id][EVENTS][0][0])
                except Exception:
                    min_time = float(0)
                try:
                    max_time = float(pj[OBSERVATIONS][obs_id][EVENTS][-1][0])
                except Exception:
                    max_time = float(obs_length)

            if param["time"] == TIME_ARBITRARY_INTERVAL:
                min_time = float(start_time)
                max_time = float(end_time)

            cursor.execute("UPDATE aggregated_events SET start = ? WHERE observation = ? AND start < ? AND stop BETWEEN ? AND ?",
                        (min_time, obs_id, min_time, min_time, max_time, ))
            cursor.execute("UPDATE aggregated_events SET stop = ? WHERE observation = ? AND stop > ? AND start BETWEEN ? AND ?",
                        (max_time, obs_id, max_time, min_time, max_time, ))
            cursor.execute("UPDATE aggregated_events SET start = ?, stop = ? WHERE observation = ? AND start < ? AND stop > ?",
                        (min_time, max_time, obs_id, min_time, max_time, ))

            for ax_idx, subject in enumerate(sorted(distinct_subjects)):

                for behavior in distinct_behav:

                    # number of occurences
                    cursor.execute(("SELECT COUNT(*) AS count FROM aggregated_events "
                                    "WHERE observation = ? AND subject = ? AND behavior = ?"),
                                (obs_id, subject, behavior, ))
                    for row in cursor.fetchall():
                        behaviors[subject][behavior]["number of occurences"] = 0 if row["count"] is None else row["count"]

                    # total duration
                    if STATE in project_functions.event_type(behavior, pj[ETHOGRAM]):
                        cursor.execute(("SELECT SUM(stop - start) AS duration FROM aggregated_events "
                                        "WHERE observation = ? AND subject = ? AND behavior = ?"),
                                    (obs_id, subject, behavior, ))
                        for row in cursor.fetchall():
                            behaviors[subject][behavior]["duration"] = 0 if row["duration"] is None else row["duration"]

                durations, n_occurences, colors, x_labels, colors_duration, x_labels_duration = [], [], [], [], [], []

                for behavior in sorted(distinct_behav):

                    if param[EXCLUDE_BEHAVIORS] and behaviors[subject][behavior]["number of occurences"] == 0:
                        continue

                    n_occurences.append(behaviors[subject][behavior]["number of occurences"])
                    x_labels.append(behavior)
                    try:
                        colors.append(utilities.behavior_color(plot_colors, all_behaviors.index(behavior)))
                    except Exception:
                        colors.append("darkgray")

                    if STATE in project_functions.event_type(behavior, pj[ETHOGRAM]):
                        durations.append(behaviors[subject][behavior]["duration"])
                        x_labels_duration.append(behavior)
                        try:
                            colors_duration.append(utilities.behavior_color(plot_colors, all_behaviors.index(behavior)))
                        except Exception:
                            colors_duration.append("darkgray")


                #width = 0.35       # the width of the bars: can also be len(x) sequence

                axs2[ax_idx].bar(np.arange(len(n_occurences)),
                                n_occurences,
                                #width,
                                color=colors
                                )


                axs[ax_idx].bar(np.arange(len(durations)),
                                durations,
                                #width,
                                color=colors_duration
                                )

                if ax_idx == 0:
                    axs[ax_idx].set_ylabel("Duration (s)")
                axs[ax_idx].set_xlabel("Behaviors")
                axs[ax_idx].set_title(f"{subject}")

                axs[ax_idx].set_xticks(np.arange(len(durations)))
                axs[ax_idx].set_xticklabels(x_labels_duration, rotation='vertical', fontsize=8)

                if ax_idx == 0:
                    axs2[ax_idx].set_ylabel("Number of occurences")
                axs2[ax_idx].set_xlabel("Behaviors")
                axs2[ax_idx].set_title(f"{subject}")

                axs2[ax_idx].set_xticks(np.arange(len(n_occurences)))
                axs2[ax_idx].set_xticklabels(x_labels, rotation='vertical', fontsize=8)


            fig.align_labels()
            fig.tight_layout(rect=[0, 0.03, 1, 0.95])

            fig2.align_labels()
            fig2.tight_layout(rect=[0, 0.03, 1, 0.95])


            if plot_directory:
                # output_file_name = f"{pathlib.Path(plot_directory) / utilities.safeFileName(obs_id)}.{output_format}"
                fig.savefig(f"{pathlib.Path(plot_directory) / utilities.safeFileName(obs_id)}.duration.{output_format}")
                fig2.savefig(f"{pathlib.Path(plot_directory) / utilities.safeFileName(obs_id)}.number_of_occurences.{output_format}")
                plt.close()
            else:
                fig.show()
                fig2.show()

        return {}

    except Exception:
        error_type, error_file_name, error_lineno = utilities.error_info(sys.exc_info())
        logging.critical(f"Error in time budget bar plot: {error_type} {error_file_name} {error_lineno}")
        return {"error": True, "exception": sys.exc_info()}
Exemplo n.º 14
0
 def test_empty_dict(self):
     r = utilities.sorted_keys({})
     assert r == []
Exemplo n.º 15
0
 def test_numeric_keys(self):
     r = utilities.sorted_keys({5: "a", 4: "7", 0: "z", 6: "a"})
     #print(r)
     assert r == ['0', '4', '5', '6']
Exemplo n.º 16
0
    def __init__(self, code, modifiers_dict, currentModifier):

        super().__init__()
        self.setWindowTitle(programName)
        self.setWindowFlags(Qt.WindowStaysOnTopHint)

        self.modifiers_dict = dict(modifiers_dict)
        currentModifierList = currentModifier.split("|")

        V1layout = QVBoxLayout()
        label = QLabel()
        label.setText(
            f"Choose the modifier{'s' * (len(self.modifiers_dict) > 1)} for <b>{code}</b> behavior"
        )
        V1layout.addWidget(label)

        Hlayout = QHBoxLayout()
        self.modifiersSetNumber = 0

        for idx in sorted_keys(modifiers_dict):

            if self.modifiers_dict[idx]["type"] not in [
                    SINGLE_SELECTION, MULTI_SELECTION, NUMERIC_MODIFIER
            ]:
                continue

            V2layout = QVBoxLayout()

            self.modifiersSetNumber += 1

            lb = QLabel()
            lb.setText(f"Modifier <b>{self.modifiers_dict[idx]['name']}</b>")
            V2layout.addWidget(lb)

            if self.modifiers_dict[idx]["type"] in [
                    SINGLE_SELECTION, MULTI_SELECTION
            ]:
                lw = QListWidget()
                self.modifiers_dict[idx]["widget"] = lw
                lw.setObjectName(
                    f"lw_modifiers_({self.modifiers_dict[idx]['type']})")
                lw.installEventFilter(self)

                if self.modifiers_dict[idx]["type"] == SINGLE_SELECTION:
                    item = QListWidgetItem("None")
                    lw.addItem(item)
                    item.setSelected(True)

                for modifier in self.modifiers_dict[idx]["values"]:
                    item = QListWidgetItem(modifier)
                    if self.modifiers_dict[idx]["type"] == MULTI_SELECTION:
                        item.setCheckState(Qt.Unchecked)

                        # previously selected
                        try:
                            if currentModifierList != [""] and re.sub(
                                    " \(.\)", "", modifier
                            ) in currentModifierList[int(idx)].split(","):
                                item.setCheckState(Qt.Checked)
                        except Exception:  # for old projects due to a fixed bug
                            pass

                    lw.addItem(item)

                    if self.modifiers_dict[idx]["type"] == SINGLE_SELECTION:
                        try:
                            if currentModifierList != [""] and re.sub(
                                    " \(.\)", "",
                                    modifier) == currentModifierList[int(idx)]:
                                item.setSelected(True)
                        except Exception:  # for old projects due to a fixed bug
                            pass
                V2layout.addWidget(lw)

            if self.modifiers_dict[idx]["type"] in [NUMERIC_MODIFIER]:
                le = QLineEdit()
                self.modifiers_dict[idx]["widget"] = le

                if currentModifierList != [
                        ""
                ] and currentModifierList[int(idx)] != "None":
                    le.setText(currentModifierList[int(idx)])

                V2layout.addWidget(le)

                # vertical spacer
                spacerItem = QSpacerItem(20, 40, QSizePolicy.Minimum,
                                         QSizePolicy.Expanding)
                V2layout.addItem(spacerItem)

            Hlayout.addLayout(V2layout)

        V1layout.addLayout(Hlayout)

        H2layout = QHBoxLayout()
        H2layout.addStretch(1)

        pbCancel = QPushButton(CANCEL)
        pbCancel.clicked.connect(self.reject)
        H2layout.addWidget(pbCancel)

        pbOK = QPushButton(OK)
        pbOK.setDefault(True)
        pbOK.clicked.connect(self.pbOK_clicked)
        H2layout.addWidget(pbOK)

        V1layout.addLayout(H2layout)
        self.setLayout(V1layout)

        self.installEventFilter(self)
        self.setMaximumSize(1024, 960)
Exemplo n.º 17
0
def export_observations_list(pj: dict,
                             selected_observations: list,
                             file_name: str,
                             output_format: str) -> bool:
    """
    create file with a list of selected observations

    Args:
        pj (dict): project dictionary
        selected_observations (list): list of observations to export
        file_name (str): path of file to save list of observations
        output_format (str): format output

    Returns:
        bool: True of OK else False
    """

    data = tablib.Dataset()
    data.headers = ["Observation id", "Date", "Description", "Subjects", "Media files/Live observation"]

    indep_var_header = []
    if INDEPENDENT_VARIABLES in pj:
        for idx in utilities.sorted_keys(pj[INDEPENDENT_VARIABLES]):
            indep_var_header.append(pj[INDEPENDENT_VARIABLES][idx]["label"])
    data.headers.extend(indep_var_header)

    for obs_id in selected_observations:

        subjects_list = sorted(list(set([x[EVENT_SUBJECT_FIELD_IDX] for x in pj[OBSERVATIONS][obs_id][EVENTS]])))
        if "" in subjects_list:
            subjects_list = [NO_FOCAL_SUBJECT] + subjects_list
            subjects_list.remove("")
        subjects = ", ".join(subjects_list)

        if pj[OBSERVATIONS][obs_id][TYPE] == LIVE:
            media_files = ["Live observation"]
        elif pj[OBSERVATIONS][obs_id][TYPE] == MEDIA:
            media_files = []
            if pj[OBSERVATIONS][obs_id][FILE]:
                for player in sorted(pj[OBSERVATIONS][obs_id][FILE].keys()):
                    for media in pj[OBSERVATIONS][obs_id][FILE][player]:
                        media_files.append("#{0}: {1}".format(player, media))

        # independent variables
        indep_var = []
        if INDEPENDENT_VARIABLES in pj[OBSERVATIONS][obs_id]:
            for var_label in indep_var_header:
                if var_label in pj[OBSERVATIONS][obs_id][INDEPENDENT_VARIABLES]:
                    indep_var.append(pj[OBSERVATIONS][obs_id][INDEPENDENT_VARIABLES][var_label])
                else:
                    indep_var.append("")

        data.append(
            [obs_id, pj[OBSERVATIONS][obs_id]["date"], pj[OBSERVATIONS][obs_id]["description"], subjects, ", ".join(media_files)] +
            indep_var
        )

    if output_format in ["tsv", "csv", "html"]:
        try:
            with open(file_name, "wb") as f:
                f.write(str.encode(data.export(output_format)))
        except Exception:
            return False
    if output_format in ["ods", "xlsx", "xls"]:
        try:
            with open(file_name, "wb") as f:
                f.write(data.export(output_format))
        except:
            return False

    return True
Exemplo n.º 18
0
def plot_time_ranges(pj, time_format, plot_colors, obs, obsId, minTime,
                     videoLength, excludeBehaviorsWithoutEvents, line_width):
    """
    create "hlines" matplotlib plot
    used by plot_event function (legacy)
    """
    def on_draw(event):
        # http://matplotlib.org/faq/howto_faq.html#move-the-edge-of-an-axes-to-make-room-for-tick-labels
        bboxes = []
        for label in labels:
            bbox = label.get_window_extent()
            bboxi = bbox.inverse_transformed(fig.transFigure)
            bboxes.append(bboxi)

        bbox = mtransforms.Bbox.union(bboxes)
        if fig.subplotpars.left < bbox.width:
            fig.subplots_adjust(left=1.1 * bbox.width)
            fig.canvas.draw()
        return False

    LINE_WIDTH = line_width
    all_behaviors, observedBehaviors = [], []
    maxTime = 0  # max time in all events of all subjects

    # all behaviors defined in project without modifiers
    all_project_behaviors = [
        pj[ETHOGRAM][idx]["code"]
        for idx in utilities.sorted_keys(pj[ETHOGRAM])
    ]
    all_project_subjects = [NO_FOCAL_SUBJECT] + [
        pj[SUBJECTS][idx]["name"]
        for idx in utilities.sorted_keys(pj[SUBJECTS])
    ]

    for subject in obs:

        for behavior_modifiers_json in obs[subject]:

            behavior_modifiers = json.loads(behavior_modifiers_json)

            if not excludeBehaviorsWithoutEvents:
                observedBehaviors.append(behavior_modifiers_json)
            else:
                if obs[subject][behavior_modifiers_json]:
                    observedBehaviors.append(behavior_modifiers_json)

            if not behavior_modifiers_json in all_behaviors:
                all_behaviors.append(behavior_modifiers_json)

            for t1, t2 in obs[subject][behavior_modifiers_json]:
                maxTime = max(maxTime, t1, t2)

        observedBehaviors.append("")

    lbl = []
    if excludeBehaviorsWithoutEvents:
        for behav_modif_json in observedBehaviors:

            if not behav_modif_json:
                lbl.append("")
                continue

            behav_modif = json.loads(behav_modif_json)
            if len(behav_modif) == 2:
                lbl.append("{0} ({1})".format(behav_modif[0], behav_modif[1]))
            else:
                lbl.append(behav_modif[0])

    else:
        all_behaviors.append('[""]')  # empty json list element
        for behav_modif_json in all_behaviors:

            behav_modif = json.loads(behav_modif_json)
            if len(behav_modif) == 2:
                lbl.append("{0} ({1})".format(behav_modif[0], behav_modif[1]))
            else:
                lbl.append(behav_modif[0])
        lbl = lbl[:] * len(obs)

    lbl = lbl[:-1]  # remove last empty line

    fig = plt.figure(figsize=(20, 10))
    fig.suptitle("Time diagram of observation {}".format(obsId), fontsize=14)
    ax = fig.add_subplot(111)
    labels = ax.set_yticklabels(lbl)

    ax.set_ylabel("Behaviors")

    if time_format == HHMMSS:
        fmtr = matplotlib.dates.DateFormatter("%H:%M:%S")  # %H:%M:%S:%f
        ax.xaxis.set_major_formatter(fmtr)
        ax.set_xlabel("Time (hh:mm:ss)")
    else:
        ax.set_xlabel("Time (s)")

    plt.ylim(len(lbl), -0.5)

    if not videoLength:
        videoLength = maxTime

    if pj[OBSERVATIONS][obsId]["time offset"]:
        t0 = round(pj[OBSERVATIONS][obsId]["time offset"] + minTime)
        t1 = round(pj[OBSERVATIONS][obsId]["time offset"] + videoLength + 2)
    else:
        t0 = round(minTime)
        t1 = round(videoLength)
    subjectPosition = t0 + (t1 - t0) * 0.05

    if time_format == HHMMSS:
        t0d = dt.datetime(1970, 1, 1, int(t0 / 3600),
                          int((t0 - int(t0 / 3600) * 3600) / 60), int(t0 % 60),
                          round(round(t0 % 1, 3) * 1000000))
        t1d = dt.datetime(1970, 1, 1, int(t1 / 3600),
                          int((t1 - int(t1 / 3600) * 3600) / 60), int(t1 % 60),
                          round(round(t1 % 1, 3) * 1000000))
        subjectPositiond = dt.datetime(
            1970, 1, 1, int(subjectPosition / 3600),
            int((subjectPosition - int(subjectPosition / 3600) * 3600) / 60),
            int(subjectPosition % 60),
            round(round(subjectPosition % 1, 3) * 1000000))

    if time_format == S:
        t0d, t1d = t0, t1
        subjectPositiond = subjectPosition

    plt.xlim(t0d, t1d)
    plt.yticks(range(len(lbl) + 1), np.array(lbl))

    count = 0
    flagFirstSubject = True

    for subject in all_project_subjects:
        if subject not in obs:
            continue

        if not flagFirstSubject:
            if excludeBehaviorsWithoutEvents:
                count += 1
            ax.axhline(y=(count - 1), linewidth=1, color="black")
            ax.hlines(np.array([count]),
                      np.array([0]),
                      np.array([0]),
                      lw=LINE_WIDTH,
                      color=col)
        else:
            flagFirstSubject = False

        ax.text(subjectPositiond, count - 0.5, subject)

        behaviors = obs[subject]

        x1, x2, y, col, pointsx, pointsy, guide = [], [], [], [], [], [], []
        col_count = 0

        for bm_json in all_behaviors:
            if bm_json in obs[subject]:
                if obs[subject][bm_json]:
                    for t1, t2 in obs[subject][bm_json]:
                        if t1 == t2:
                            pointsx.append(t1)
                            pointsy.append(count)
                            ax.axhline(y=count,
                                       linewidth=1,
                                       color="lightgray",
                                       zorder=-1)
                        else:
                            x1.append(t1)
                            x2.append(t2)
                            y.append(count)

                            col.append(
                                utilities.behavior_color(
                                    plot_colors,
                                    all_project_behaviors.index(
                                        json.loads(bm_json)[0])))
                            ax.axhline(y=count,
                                       linewidth=1,
                                       color="lightgray",
                                       zorder=-1)
                    count += 1
                else:
                    x1.append(0)
                    x2.append(0)
                    y.append(count)
                    col.append("white")
                    ax.axhline(y=count,
                               linewidth=1,
                               color="lightgray",
                               zorder=-1)
                    count += 1

            else:
                if not excludeBehaviorsWithoutEvents:
                    x1.append(0)
                    x2.append(0)
                    y.append(count)
                    col.append("white")
                    ax.axhline(y=count,
                               linewidth=1,
                               color="lightgray",
                               zorder=-1)
                    count += 1

            col_count += 1

        if time_format == HHMMSS:
            ax.hlines(np.array(y),
                      np.array([
                          dt.datetime(1970, 1, 1, int(p / 3600),
                                      int((p - int(p / 3600) * 3600) / 60),
                                      int(p % 60),
                                      round(round(p % 1, 3) * 1e6)) for p in x1
                      ]),
                      np.array([
                          dt.datetime(1970, 1, 1, int(p / 3600),
                                      int((p - int(p / 3600) * 3600) / 60),
                                      int(p % 60),
                                      round(round(p % 1, 3) * 1e6)) for p in x2
                      ]),
                      lw=LINE_WIDTH,
                      color=col)

        if time_format == S:
            ax.hlines(np.array(y),
                      np.array(x1),
                      np.array(x2),
                      lw=LINE_WIDTH,
                      color=col)

        if time_format == HHMMSS:

            ax.plot(
                np.array([
                    dt.datetime(1970, 1, 1, int(p / 3600),
                                int((p - int(p / 3600) * 3600) / 60),
                                int(p % 60), round(round(p % 1, 3) * 1e6))
                    for p in pointsx
                ]), pointsy, "r^")

        if time_format == S:
            ax.plot(pointsx, pointsy, "r^")

    fig.canvas.mpl_connect("draw_event", on_draw)
    plt.show()

    return True
Exemplo n.º 19
0
    def __init__(self, key, modifiers_dict, currentModifier):

        super().__init__()
        self.setWindowTitle(programName)
        self.setWindowFlags(Qt.WindowStaysOnTopHint)

        self.modifiers_dict = dict(modifiers_dict)
        currentModifierList = currentModifier.split("|")

        print("currentModifierList", currentModifierList)

        V1layout = QVBoxLayout()
        label = QLabel()
        label.setText("Choose the modifier{0} for <b>{1}</b> behavior".format(
            "s" * (len(self.modifiers_dict) > 1), key))
        V1layout.addWidget(label)

        Hlayout = QHBoxLayout()
        self.modifiersSetNumber = 0

        for idx in sorted_keys(modifiers_dict):

            V2layout = QVBoxLayout()

            self.modifiersSetNumber += 1

            lb = QLabel()
            lb.setText("Modifier <b>{}</b>".format(
                self.modifiers_dict[idx]["name"]))
            V2layout.addWidget(lb)

            if self.modifiers_dict[idx]["type"] in [
                    SINGLE_SELECTION, MULTI_SELECTION
            ]:
                lw = QListWidget()
                self.modifiers_dict[idx]["widget"] = lw
                lw.setObjectName("lw_modifiers")
                lw.installEventFilter(self)

                if self.modifiers_dict[idx]["type"] == SINGLE_SELECTION:
                    item = QListWidgetItem("None")
                    lw.addItem(item)
                    lw.setItemSelected(
                        item, True
                    ) if QT_VERSION_STR[0] == "4" else item.setSelected(True)

                #lw.setFixedHeight(len(modifiers_dict[idx]["values"])*20)
                for modifier in self.modifiers_dict[idx]["values"]:
                    item = QListWidgetItem(modifier)
                    if self.modifiers_dict[idx]["type"] == MULTI_SELECTION:
                        item.setCheckState(Qt.Unchecked)

                        # previously selected
                        '''
                        print("\n\nmodifier:", modifier)
                        print(re.sub(" \(.\)", "", modifier))
                        print("currentModifierList",currentModifierList)
                        print("idx", idx)
                        print(currentModifierList[int(idx)])
                        '''
                        try:
                            if currentModifierList != [""] and re.sub(
                                    " \(.\)", "", modifier
                            ) in currentModifierList[int(idx)].split(","):
                                item.setCheckState(Qt.Checked)
                        except:  # for old projects due to a fixed bug
                            pass

                    lw.addItem(item)

                    if self.modifiers_dict[idx]["type"] == SINGLE_SELECTION:
                        try:
                            if currentModifierList != [""] and re.sub(
                                    " \(.\)", "",
                                    modifier) == currentModifierList[int(idx)]:
                                if QT_VERSION_STR[0] == "4":
                                    lw.setItemSelected(item, True)
                                else:
                                    item.setSelected(True)
                        except:  # for old projects due to a fixed bug
                            pass
                V2layout.addWidget(lw)

            if self.modifiers_dict[idx]["type"] in [NUMERIC_MODIFIER]:
                le = QLineEdit()
                self.modifiers_dict[idx]["widget"] = le

                if currentModifierList != [
                        ""
                ] and currentModifierList[int(idx)] != "None":
                    le.setText(currentModifierList[int(idx)])

                V2layout.addWidget(le)

                # vertical spacer
                spacerItem = QSpacerItem(20, 40, QSizePolicy.Minimum,
                                         QSizePolicy.Expanding)
                V2layout.addItem(spacerItem)

            Hlayout.addLayout(V2layout)

        V1layout.addLayout(Hlayout)

        H2layout = QHBoxLayout()
        H2layout.addStretch(1)

        pbCancel = QPushButton(CANCEL)
        pbCancel.clicked.connect(self.reject)
        H2layout.addWidget(pbCancel)

        pbOK = QPushButton(OK)
        pbOK.setDefault(True)
        pbOK.clicked.connect(self.pbOK_clicked)
        H2layout.addWidget(pbOK)

        V1layout.addLayout(H2layout)
        self.setLayout(V1layout)

        self.installEventFilter(self)
        #self.setMinimumSize(630, 50)
        self.setMaximumSize(1024, 960)
Exemplo n.º 20
0
def select_observations(pj: dict, mode: str) -> tuple:
    """
    allow user to select observations
    mode: accepted values: OPEN, EDIT, SINGLE, MULTIPLE, SELECT1

    Args:
        pj (dict): BORIS project dictionary
        mode (str): mode foe selection: OPEN, EDIT, SINGLE, MULTIPLE, SELECT1

    Returns:
        str: selected mode: OPEN, EDIT, VIEW
        list: list of selected observations
    """

    obsListFields = ["id", "date", "description", "subjects", "media"]
    indepVarHeader, column_type = [], [TEXT] * len(obsListFields)

    if INDEPENDENT_VARIABLES in pj:
        for idx in utilities.sorted_keys(pj[INDEPENDENT_VARIABLES]):
            indepVarHeader.append(pj[INDEPENDENT_VARIABLES][idx]["label"])
            column_type.append(pj[INDEPENDENT_VARIABLES][idx]["type"])

    data = []
    for obs in sorted(list(pj[OBSERVATIONS].keys())):
        date = pj[OBSERVATIONS][obs]["date"].replace("T", " ")
        descr = utilities.eol2space(pj[OBSERVATIONS][obs]["description"])

        # subjects
        observedSubjects = project_functions.extract_observed_subjects(pj, [obs])

        # remove when No focal subject
        if "" in observedSubjects:
            observedSubjects.remove("")
        subjectsList = ", ".join(observedSubjects)

        mediaList = []
        if pj[OBSERVATIONS][obs][TYPE] in [MEDIA]:
            if pj[OBSERVATIONS][obs][FILE]:
                for player in sorted(pj[OBSERVATIONS][obs][FILE].keys()):
                    for media in pj[OBSERVATIONS][obs][FILE][player]:
                        mediaList.append("#{0}: {1}".format(player, media))

            if len(mediaList) > 8:
                media = " ".join(mediaList)
            else:
                media = "\n".join(mediaList)

        elif pj[OBSERVATIONS][obs][TYPE] in [LIVE]:
            media = LIVE

        # independent variables
        indepvar = []
        if INDEPENDENT_VARIABLES in pj[OBSERVATIONS][obs]:
            for var_label in indepVarHeader:
                if var_label in pj[OBSERVATIONS][obs][INDEPENDENT_VARIABLES]:
                    indepvar.append(pj[OBSERVATIONS][obs][INDEPENDENT_VARIABLES][var_label])
                else:
                    indepvar.append("")

        data.append([obs, date, descr, subjectsList, media] + indepvar)

    obsList = observations_list.observationsList_widget(data, header=obsListFields + indepVarHeader, column_type=column_type)

    obsList.pbOpen.setVisible(False)
    obsList.pbView.setVisible(False)
    obsList.pbEdit.setVisible(False)
    obsList.pbOk.setVisible(False)
    obsList.pbSelectAll.setVisible(False)
    obsList.pbUnSelectAll.setVisible(False)
    obsList.mode = mode

    if mode == OPEN:
        obsList.view.setSelectionMode(QAbstractItemView.SingleSelection)
        obsList.pbOpen.setVisible(True)

    if mode == VIEW:
        obsList.view.setSelectionMode(QAbstractItemView.SingleSelection)
        obsList.pbView.setVisible(True)


    if mode == EDIT:
        obsList.view.setSelectionMode(QAbstractItemView.SingleSelection)
        obsList.pbEdit.setVisible(True)

    if mode == SINGLE:
        obsList.view.setSelectionMode(QAbstractItemView.SingleSelection)
        obsList.pbOpen.setVisible(True)
        obsList.pbView.setVisible(True)
        obsList.pbEdit.setVisible(True)

    if mode == MULTIPLE:
        obsList.view.setSelectionMode(QAbstractItemView.MultiSelection)
        obsList.pbOk.setVisible(True)
        obsList.pbSelectAll.setVisible(True)
        obsList.pbUnSelectAll.setVisible(True)

    if mode == SELECT1:
        obsList.view.setSelectionMode(QAbstractItemView.SingleSelection)
        obsList.pbOk.setVisible(True)

    obsList.resize(900, 600)

    obsList.view.sortItems(0, Qt.AscendingOrder)
    for row in range(obsList.view.rowCount()):
        obsList.view.resizeRowToContents(row)

    selectedObs = []

    result = obsList.exec_()

    if result:
        if obsList.view.selectedIndexes():
            for idx in obsList.view.selectedIndexes():
                if idx.column() == 0:   # first column
                    selectedObs.append(idx.data())

    if result == 0:  # cancel
        resultStr = ""
    if result == 1:   # select
        resultStr = "ok"
    if result == 2:   # open
        resultStr = OPEN
    if result == 3:   # edit
        resultStr = EDIT
    if result == 4:   # view
        resultStr = VIEW

    return resultStr, selectedObs
Exemplo n.º 21
0
def create_events_plot(pj,
                       selected_observations,
                       parameters,
                       plot_colors=BEHAVIORS_PLOT_COLORS,
                       plot_directory="",
                       file_format="png"):


    selected_subjects = parameters["selected subjects"]
    selected_behaviors = parameters["selected behaviors"]
    include_modifiers = parameters["include modifiers"]
    interval = parameters[TIME_INTERVAL]
    start_time = parameters[START_TIME]
    end_time = parameters[END_TIME]

    ok, msg, db_connector = db_functions.load_aggregated_events_in_db(pj,
                                                       selected_subjects,
                                                       selected_observations,
                                                       selected_behaviors)

    if not ok:
        return False, msg, None
    cursor = db_connector.cursor()

    # if modifiers not to be included set modifiers to ""
    if not include_modifiers:
        cursor.execute("UPDATE aggregated_events SET modifiers = ''")

    cursor.execute("SELECT distinct behavior, modifiers FROM aggregated_events")
    distinct_behav_modif = [[rows["behavior"], rows["modifiers"]] for rows in cursor.fetchall()]

    # add selected behaviors that are not observed
    for behav in selected_behaviors:
        if [x for x in distinct_behav_modif if x[0] == behav] == []:
            distinct_behav_modif.append([behav, "-"])

    distinct_behav_modif = sorted(distinct_behav_modif)
    max_len = len(distinct_behav_modif)

    all_behaviors = [pj[ETHOGRAM][x][BEHAVIOR_CODE] for x in utilities.sorted_keys(pj[ETHOGRAM])]

    par1 = 1
    bar_height = 0.5
    init = dt.datetime(2017, 1, 1)

    for obs_id in selected_observations:

        if len(selected_subjects) > 1:
            fig, axs = plt.subplots(figsize=(20, 8), nrows=len(selected_subjects), ncols=1, sharex=True)
        else:
            fig, ax = plt.subplots(figsize=(20, 8), nrows=len(selected_subjects), ncols=1, sharex=True)
            axs = np.ndarray(shape=(1), dtype=type(ax))
            axs[0] = ax


        ok, msg, db_connector = db_functions.load_aggregated_events_in_db(
            pj,
            selected_subjects,
            [obs_id],
            selected_behaviors)

        cursor = db_connector.cursor()
        # if modifiers not to be included set modifiers to ""
        if not include_modifiers:
            cursor.execute("UPDATE aggregated_events SET modifiers = ''")
        cursor = db_connector.cursor()

        cursor.execute("SELECT distinct behavior, modifiers FROM aggregated_events")
        distinct_behav_modif = [[rows["behavior"], rows["modifiers"]] for rows in cursor.fetchall()]

        # add selected behaviors that are not observed
        if not parameters["exclude behaviors"]:
            for behav in selected_behaviors:
                if [x for x in distinct_behav_modif if x[0] == behav] == []:
                    distinct_behav_modif.append([behav, "-"])

        distinct_behav_modif = sorted(distinct_behav_modif)
        max_len = len(distinct_behav_modif)


        # time
        obs_length = project_functions.observation_total_length(pj[OBSERVATIONS][obs_id])
        if obs_length == -1: # media length not available
            interval = TIME_EVENTS

        if interval == TIME_FULL_OBS:
            min_time = float(0)
            max_time = float(obs_length)

        if interval == TIME_EVENTS:
            try:
                min_time = float(pj[OBSERVATIONS][obs_id][EVENTS][0][0])
            except Exception:
                min_time = float(0)
            try:
                max_time = float(pj[OBSERVATIONS][obs_id][EVENTS][-1][0])
            except Exception:
                max_time = float(obs_length)

        if interval == TIME_ARBITRARY_INTERVAL:
            min_time = float(start_time)
            max_time = float(end_time)

        cursor.execute("UPDATE aggregated_events SET start = ? WHERE observation = ? AND start < ? AND stop BETWEEN ? AND ?",
                       (min_time, obs_id, min_time, min_time, max_time, ))
        cursor.execute("UPDATE aggregated_events SET stop = ? WHERE observation = ? AND stop > ? AND start BETWEEN ? AND ?",
                       (max_time, obs_id, max_time, min_time, max_time, ))
        cursor.execute("UPDATE aggregated_events SET start = ?, stop = ? WHERE observation = ? AND start < ? AND stop > ?",
                       (min_time, max_time, obs_id, min_time, max_time, ))

        ylabels = [" ".join(x) for x in distinct_behav_modif]
        for ax_idx, subject in enumerate(selected_subjects):

            if parameters["exclude behaviors"]:
                cursor.execute("SELECT distinct behavior, modifiers FROM aggregated_events WHERE subject = ?", (subject, ))
                distinct_behav_modif = [[rows["behavior"], rows["modifiers"]] for rows in cursor.fetchall()]

                # add selected behaviors that are not observed
                if not parameters["exclude behaviors"]:
                    for behav in selected_behaviors:
                        if [x for x in distinct_behav_modif if x[0] == behav] == []:
                            distinct_behav_modif.append([behav, "-"])

                distinct_behav_modif = sorted(distinct_behav_modif)
                max_len = len(distinct_behav_modif)
                ylabels = [" ".join(x) for x in distinct_behav_modif]

            if not ax_idx:
                axs[ax_idx].set_title("Observation {}\n{}".format(obs_id, subject), fontsize=14)
            else:
                axs[ax_idx].set_title(subject, fontsize=14)
            bars = {}
            i = 0
            for behavior_modifiers in distinct_behav_modif:
                behavior, modifiers = behavior_modifiers
                behavior_modifiers_str = "|".join(behavior_modifiers) if modifiers else behavior
                bars[behavior_modifiers_str] = []

                # total duration
                cursor.execute(("SELECT start,stop FROM aggregated_events "
                                "WHERE observation = ? AND subject = ? AND behavior = ? AND modifiers = ?"),
                               (obs_id, subject, behavior, modifiers,))
                for row in cursor.fetchall():
                    bars[behavior_modifiers_str].append((row["start"], row["stop"]))

                    start_date = matplotlib.dates.date2num(init + dt.timedelta(seconds=row["start"]))
                    end_date = matplotlib.dates.date2num(
                        init + dt.timedelta(seconds=row["stop"] + POINT_EVENT_PLOT_DURATION * (row["stop"] == row["start"])))
                    try:
                        bar_color = utilities.behavior_color(plot_colors, all_behaviors.index(behavior))
                    except Exception:
                        bar_color = "darkgray"
                    bar_color = POINT_EVENT_PLOT_COLOR if row["stop"] == row["start"] else bar_color

                    # sage colors removed from matplotlib colors list
                    if bar_color in ["sage", "darksage", "lightsage"]:
                        bar_color = {"darksage": "#598556", "lightsage": "#bcecac", "sage": "#87ae73"}[bar_color]

                    try:
                        axs[ax_idx].barh((i * par1) + par1, end_date - start_date, left=start_date, height=bar_height,
                                         align="center", edgecolor=bar_color, color=bar_color, alpha=1)
                    except Exception:
                        axs[ax_idx].barh((i * par1) + par1, end_date - start_date, left=start_date, height=bar_height,
                                         align="center", edgecolor="darkgray", color="darkgray", alpha=1)

                i += 1

            axs[ax_idx].set_ylim(bottom=0, top=(max_len * par1) + par1)
            pos = np.arange(par1, max_len * par1 + par1 + 1, par1)
            axs[ax_idx].set_yticks(pos[:len(ylabels)])

            axs[ax_idx].set_yticklabels(ylabels, fontdict={"fontsize": 10})

            axs[ax_idx].set_ylabel("Behaviors" + " (modifiers)" * include_modifiers, fontdict={"fontsize": 10})

            axs[ax_idx].set_xlim(left=matplotlib.dates.date2num(init + dt.timedelta(seconds=min_time)),
                                 right=matplotlib.dates.date2num(init + dt.timedelta(seconds=max_time + 1)))

            axs[ax_idx].grid(color="g", linestyle=":")
            axs[ax_idx].xaxis_date()
            axs[ax_idx].xaxis.set_major_formatter(DateFormatter("%H:%M:%S"))
            axs[ax_idx].set_xlabel("Time (HH:MM:SS)", fontdict={"fontsize": 12})
            axs[ax_idx].invert_yaxis()

        fig.autofmt_xdate()
        plt.tight_layout()

        if len(selected_observations) > 1:
            output_file_name = str(pathlib.Path(pathlib.Path(plot_directory) / utilities.safeFileName(obs_id)).with_suffix(
                "." + file_format))
            plt.savefig(output_file_name)
        else:
            plt.show()
Exemplo n.º 22
0
def plot_time_ranges(pj, time_format, plot_colors, obs, obsId, minTime, videoLength, excludeBehaviorsWithoutEvents, line_width):
    """
    create "hlines" matplotlib plot
    used by plot_event function (legacy)
    """

    def on_draw(event):
        # http://matplotlib.org/faq/howto_faq.html#move-the-edge-of-an-axes-to-make-room-for-tick-labels
        bboxes = []
        for label in labels:
            bbox = label.get_window_extent()
            bboxi = bbox.inverse_transformed(fig.transFigure)
            bboxes.append(bboxi)

        bbox = mtransforms.Bbox.union(bboxes)
        if fig.subplotpars.left < bbox.width:
            fig.subplots_adjust(left=1.1*bbox.width)
            fig.canvas.draw()
        return False

    LINE_WIDTH = line_width
    all_behaviors, observedBehaviors = [], []
    maxTime = 0  # max time in all events of all subjects

    # all behaviors defined in project without modifiers
    all_project_behaviors = [pj[ETHOGRAM][idx]["code"] for idx in utilities.sorted_keys(pj[ETHOGRAM])]
    all_project_subjects = [NO_FOCAL_SUBJECT] + [pj[SUBJECTS][idx]["name"] for idx in utilities.sorted_keys(pj[SUBJECTS])]

    for subject in obs:

        for behavior_modifiers_json in obs[subject]:

            behavior_modifiers = json.loads(behavior_modifiers_json)

            if not excludeBehaviorsWithoutEvents:
                observedBehaviors.append(behavior_modifiers_json)
            else:
                if obs[subject][behavior_modifiers_json]:
                    observedBehaviors.append(behavior_modifiers_json)

            if not behavior_modifiers_json in all_behaviors:
                all_behaviors.append(behavior_modifiers_json)

            for t1, t2 in obs[subject][behavior_modifiers_json]:
                maxTime = max(maxTime, t1, t2)

        observedBehaviors.append("")

    lbl = []
    if excludeBehaviorsWithoutEvents:
        for behav_modif_json in observedBehaviors:

            if not behav_modif_json:
                lbl.append("")
                continue

            behav_modif = json.loads(behav_modif_json)
            if len(behav_modif) == 2:
                lbl.append("{0} ({1})".format(behav_modif[0], behav_modif[1]))
            else:
                lbl.append(behav_modif[0])

    else:
        all_behaviors.append('[""]') # empty json list element
        for behav_modif_json in all_behaviors:

            behav_modif = json.loads(behav_modif_json)
            if len(behav_modif) == 2:
                lbl.append("{0} ({1})".format(behav_modif[0], behav_modif[1]))
            else:
                lbl.append(behav_modif[0])
        lbl = lbl[:] * len(obs)


    lbl = lbl[:-1]  # remove last empty line

    fig = plt.figure(figsize=(20, 10))
    fig.suptitle("Time diagram of observation {}".format(obsId), fontsize=14)
    ax = fig.add_subplot(111)
    labels = ax.set_yticklabels(lbl)

    ax.set_ylabel("Behaviors")

    if time_format == HHMMSS:
        fmtr = matplotlib.dates.DateFormatter("%H:%M:%S") # %H:%M:%S:%f
        ax.xaxis.set_major_formatter(fmtr)
        ax.set_xlabel("Time (hh:mm:ss)")
    else:
        ax.set_xlabel("Time (s)")

    plt.ylim(len(lbl), -0.5)

    if not videoLength:
        videoLength = maxTime

    if pj[OBSERVATIONS][obsId]["time offset"]:
        t0 = round(pj[OBSERVATIONS][obsId]["time offset"] + minTime)
        t1 = round(pj[OBSERVATIONS][obsId]["time offset"] + videoLength + 2)
    else:
        t0 = round(minTime)
        t1 = round(videoLength)
    subjectPosition = t0 + (t1 - t0) * 0.05

    if time_format == HHMMSS:
        t0d = dt.datetime(1970, 1, 1, int(t0 / 3600), int((t0 - int(t0 / 3600) * 3600) / 60), int(t0 % 60), round(round(t0 % 1, 3) * 1000000))
        t1d = dt.datetime(1970, 1, 1, int(t1 / 3600), int((t1 - int(t1 / 3600) * 3600) / 60), int(t1 % 60), round(round(t1 % 1, 3) * 1000000))
        subjectPositiond = dt.datetime(1970, 1, 1, int(subjectPosition / 3600), int((subjectPosition - int(subjectPosition / 3600) * 3600) / 60), int(subjectPosition % 60), round(round(subjectPosition % 1, 3) * 1000000))

    if time_format == S:
        t0d, t1d = t0, t1
        subjectPositiond = subjectPosition

    plt.xlim(t0d, t1d)
    plt.yticks(range(len(lbl) + 1), np.array(lbl))

    count = 0
    flagFirstSubject = True

    for subject in all_project_subjects:
        if subject not in obs:
            continue

        if not flagFirstSubject:
            if excludeBehaviorsWithoutEvents:
                count += 1
            ax.axhline(y=(count-1), linewidth=1, color="black")
            ax.hlines(np.array([count]), np.array([0]), np.array([0]), lw=LINE_WIDTH, color=col)
        else:
            flagFirstSubject = False

        ax.text(subjectPositiond, count - 0.5, subject)

        behaviors = obs[subject]

        x1, x2, y, col, pointsx, pointsy, guide = [], [], [], [], [], [], []
        col_count = 0

        for bm_json in all_behaviors:
            if bm_json in obs[subject]:
                if obs[subject][bm_json]:
                    for t1, t2 in obs[subject][bm_json]:
                        if t1 == t2:
                            pointsx.append(t1)
                            pointsy.append(count)
                            ax.axhline(y=count, linewidth=1, color="lightgray", zorder=-1)
                        else:
                            x1.append(t1)
                            x2.append(t2)
                            y.append(count)

                            col.append(utilities.behavior_color(plot_colors, all_project_behaviors.index(json.loads(bm_json)[0])))
                            ax.axhline(y=count, linewidth=1, color="lightgray", zorder=-1)
                    count += 1
                else:
                    x1.append(0)
                    x2.append(0)
                    y.append(count)
                    col.append("white")
                    ax.axhline(y=count, linewidth=1, color="lightgray", zorder=-1)
                    count += 1

            else:
                if not excludeBehaviorsWithoutEvents:
                    x1.append(0)
                    x2.append(0)
                    y.append(count)
                    col.append("white")
                    ax.axhline(y=count, linewidth=1, color="lightgray", zorder=-1)
                    count += 1

            col_count += 1

        if time_format == HHMMSS:
            ax.hlines(np.array(y), np.array([dt.datetime(1970, 1, 1, int(p / 3600),
                                                               int((p - int(p / 3600) * 3600) / 60),
                                                               int(p % 60), round(round(p % 1, 3) * 1e6))
                                            for p in x1]),
            np.array([dt.datetime(1970, 1, 1, int(p / 3600), int((p - int(p / 3600) * 3600) / 60), int(p % 60), round(round(p % 1, 3) * 1e6)) for p in x2]),
            lw=LINE_WIDTH, color=col)

        if time_format == S:
            ax.hlines(np.array(y), np.array(x1), np.array(x2), lw=LINE_WIDTH, color=col)

        if time_format == HHMMSS:

            ax.plot(
                np.array([
                    dt.datetime(1970, 1, 1, int(p / 3600),
                                int((p - int(p / 3600) * 3600) / 60), int(p % 60),
                                round(round(p % 1, 3) * 1e6)) for p in pointsx
                ]), pointsy, "r^")

        if time_format == S:
            ax.plot(pointsx, pointsy, "r^")

    fig.canvas.mpl_connect("draw_event", on_draw)
    plt.show()

    return True
Exemplo n.º 23
0
def export_aggregated_events(pj: dict, parameters: dict, obsId: str):
    """
    export aggregated events

    Args:
        pj (dict): BORIS project
        parameters (dict): subjects, behaviors
        obsId (str): observation id

    Returns:
        tablib.Dataset:

    """
    logging.debug(f"function: export aggregated events {parameters} {obsId}")

    interval = parameters["time"]
    start_time = parameters[START_TIME]
    end_time = parameters[END_TIME]

    data = tablib.Dataset()
    observation = pj[OBSERVATIONS][obsId]

    duration1 = []  # in seconds
    if observation[TYPE] in [MEDIA]:
        try:
            for mediaFile in observation[FILE][PLAYER1]:
                if MEDIA_INFO in observation:
                    duration1.append(
                        observation[MEDIA_INFO]["length"][mediaFile])
        except Exception:
            duration1 = []

    obs_length = project_functions.observation_total_length(
        pj[OBSERVATIONS][obsId])
    if obs_length == Decimal("-1"):  # media length not available
        interval = TIME_EVENTS

    logging.debug(f"obs_length: {obs_length}")

    ok, msg, connector = db_functions.load_aggregated_events_in_db(
        pj, parameters[SELECTED_SUBJECTS], [obsId],
        parameters[SELECTED_BEHAVIORS])
    if connector is None:
        logging.critical(f"error when loading aggregated events in DB")
        return data

    # time
    cursor = connector.cursor()

    if interval == TIME_FULL_OBS:
        min_time = float(0)
        max_time = float(obs_length)

    if interval == TIME_EVENTS:
        try:
            min_time = float(pj[OBSERVATIONS][obsId][EVENTS][0][0])
        except Exception:
            min_time = float(0)
        try:
            max_time = float(pj[OBSERVATIONS][obsId][EVENTS][-1][0])
        except Exception:
            max_time = float(obs_length)

    if interval == TIME_ARBITRARY_INTERVAL:
        min_time = float(start_time)
        max_time = float(end_time)

    # adapt start and stop to the selected time interval
    cursor.execute(
        "UPDATE aggregated_events SET start = ? WHERE observation = ? AND start < ? AND stop BETWEEN ? AND ?",
        (
            min_time,
            obsId,
            min_time,
            min_time,
            max_time,
        ))
    cursor.execute(
        "UPDATE aggregated_events SET stop = ? WHERE observation = ? AND stop > ? AND start BETWEEN ? AND ?",
        (
            max_time,
            obsId,
            max_time,
            min_time,
            max_time,
        ))

    cursor.execute(
        "UPDATE aggregated_events SET start = ?, stop = ? WHERE observation = ? AND start < ? AND stop > ?",
        (
            min_time,
            max_time,
            obsId,
            min_time,
            max_time,
        ))

    cursor.execute(
        "DELETE FROM aggregated_events WHERE observation = ? AND (start < ? AND stop < ?) OR (start > ? AND stop > ?)",
        (
            obsId,
            min_time,
            min_time,
            max_time,
            max_time,
        ))

    behavioral_category = project_functions.behavior_category(pj[ETHOGRAM])

    for subject in parameters[SELECTED_SUBJECTS]:

        for behavior in parameters[SELECTED_BEHAVIORS]:

            cursor.execute(
                "SELECT distinct modifiers FROM aggregated_events where subject=? AND behavior=? order by modifiers",
                (
                    subject,
                    behavior,
                ))

            rows_distinct_modifiers = list(x[0] for x in cursor.fetchall())

            for distinct_modifiers in rows_distinct_modifiers:

                cursor.execute((
                    "SELECT start, stop, type, modifiers, comment, comment_stop FROM aggregated_events "
                    "WHERE subject = ? AND behavior = ? AND modifiers = ? ORDER by start"
                ), (subject, behavior, distinct_modifiers))
                rows = list(cursor.fetchall())

                for row in rows:

                    if observation[TYPE] in [MEDIA]:
                        if duration1:
                            mediaFileIdx = [
                                idx1 for idx1, x in enumerate(duration1)
                                if row["start"] >= sum(duration1[0:idx1])
                            ][-1]
                            mediaFileString = observation[FILE][PLAYER1][
                                mediaFileIdx]
                            try:
                                fpsString = observation[MEDIA_INFO]["fps"][
                                    observation[FILE][PLAYER1][mediaFileIdx]]
                            except Exception:
                                fpsString = "NA"
                        else:
                            try:
                                if len(observation[FILE][PLAYER1]) == 1:
                                    mediaFileString = observation[FILE][
                                        PLAYER1][0]
                                else:
                                    mediaFileString = "NA"
                            except Exception:
                                mediaFileString = "NA"
                            fpsString = "NA"

                    if observation[TYPE] in [LIVE]:
                        mediaFileString = "LIVE"
                        fpsString = "NA"

                    if row["type"] == POINT:

                        row_data = []
                        row_data.extend([
                            obsId, observation["date"].replace("T", " "),
                            mediaFileString, f"{obs_length:.3f}"
                            if obs_length != Decimal("-1") else "NA", fpsString
                        ])

                        # independent variables
                        if INDEPENDENT_VARIABLES in pj:
                            for idx_var in utilities.sorted_keys(
                                    pj[INDEPENDENT_VARIABLES]):
                                if pj[INDEPENDENT_VARIABLES][idx_var][
                                        "label"] in observation[
                                            INDEPENDENT_VARIABLES]:
                                    row_data.append(
                                        observation[INDEPENDENT_VARIABLES][
                                            pj[INDEPENDENT_VARIABLES][idx_var]
                                            ["label"]])
                                else:
                                    row_data.append("")

                        row_data.extend([
                            subject,
                            behavior,
                            behavioral_category[behavior],
                            row["modifiers"],
                            POINT,
                            f"{row['start']:.3f}",  # start
                            f"{row['stop']:.3f}",  # stop
                            "NA",  # duration
                            row["comment"],
                            ""
                        ])
                        data.append(row_data)

                    if row["type"] == STATE:
                        if idx % 2 == 0:
                            row_data = []
                            row_data.extend([
                                obsId, observation["date"].replace("T", " "),
                                mediaFileString, f"{obs_length:.3f}"
                                if obs_length != Decimal("-1") else "NA",
                                fpsString
                            ])

                            # independent variables
                            if INDEPENDENT_VARIABLES in pj:
                                for idx_var in utilities.sorted_keys(
                                        pj[INDEPENDENT_VARIABLES]):
                                    if pj[INDEPENDENT_VARIABLES][idx_var][
                                            "label"] in observation[
                                                INDEPENDENT_VARIABLES]:
                                        row_data.append(
                                            observation[INDEPENDENT_VARIABLES]
                                            [pj[INDEPENDENT_VARIABLES][idx_var]
                                             ["label"]])
                                    else:
                                        row_data.append("")

                            row_data.extend([
                                subject, behavior,
                                behavioral_category[behavior],
                                row["modifiers"], STATE, f"{row['start']:.3f}",
                                f"{row['stop']:.3f}",
                                f"{row['stop'] - row['start']:.3f}",
                                row["comment"], row["comment_stop"]
                            ])
                            data.append(row_data)

    return data
Exemplo n.º 24
0
    def __init__(self, code, modifiers_dict, currentModifier):

        super().__init__()
        self.setWindowTitle(programName)
        self.setWindowFlags(Qt.WindowStaysOnTopHint)

        self.modifiers_dict = dict(modifiers_dict)
        currentModifierList = currentModifier.split("|")

        V1layout = QVBoxLayout()
        label = QLabel()
        label.setText(f"Choose the modifier{'s' * (len(self.modifiers_dict) > 1)} for <b>{code}</b> behavior")
        V1layout.addWidget(label)

        Hlayout = QHBoxLayout()
        self.modifiersSetNumber = 0

        for idx in sorted_keys(modifiers_dict):

            if self.modifiers_dict[idx]["type"] not in [SINGLE_SELECTION, MULTI_SELECTION, NUMERIC_MODIFIER]:
                continue

            V2layout = QVBoxLayout()

            self.modifiersSetNumber += 1

            lb = QLabel()
            lb.setText(f"Modifier <b>{self.modifiers_dict[idx]['name']}</b>")
            V2layout.addWidget(lb)

            if self.modifiers_dict[idx]["type"] in [SINGLE_SELECTION, MULTI_SELECTION]:
                lw = QListWidget()
                self.modifiers_dict[idx]["widget"] = lw
                lw.setObjectName(f"lw_modifiers_({self.modifiers_dict[idx]['type']})")
                lw.installEventFilter(self)

                if self.modifiers_dict[idx]["type"] == SINGLE_SELECTION:
                    item = QListWidgetItem("None")
                    lw.addItem(item)
                    item.setSelected(True)

                for modifier in self.modifiers_dict[idx]["values"]:
                    item = QListWidgetItem(modifier)
                    if self.modifiers_dict[idx]["type"] == MULTI_SELECTION:
                        item.setCheckState(Qt.Unchecked)

                        # previously selected
                        try:
                            if currentModifierList != [""] and re.sub(" \(.\)", "", modifier) in currentModifierList[int(idx)].split(","):
                                item.setCheckState(Qt.Checked)
                        except Exception:  # for old projects due to a fixed bug
                            pass

                    lw.addItem(item)

                    if self.modifiers_dict[idx]["type"] == SINGLE_SELECTION:
                        try:
                            if currentModifierList != [""] and re.sub(" \(.\)", "", modifier) == currentModifierList[int(idx)]:
                                item.setSelected(True)
                        except Exception:  # for old projects due to a fixed bug
                            pass
                V2layout.addWidget(lw)

            if self.modifiers_dict[idx]["type"] in [NUMERIC_MODIFIER]:
                le = QLineEdit()
                self.modifiers_dict[idx]["widget"] = le

                if currentModifierList != [""] and currentModifierList[int(idx)] != "None":
                    le.setText(currentModifierList[int(idx)])

                V2layout.addWidget(le)

                # vertical spacer
                spacerItem = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding)
                V2layout.addItem(spacerItem)

            Hlayout.addLayout(V2layout)

        V1layout.addLayout(Hlayout)

        H2layout = QHBoxLayout()
        H2layout.addStretch(1)

        pbCancel = QPushButton(CANCEL)
        pbCancel.clicked.connect(self.reject)
        H2layout.addWidget(pbCancel)

        pbOK = QPushButton(OK)
        pbOK.setDefault(True)
        pbOK.clicked.connect(self.pbOK_clicked)
        H2layout.addWidget(pbOK)

        V1layout.addLayout(H2layout)
        self.setLayout(V1layout)

        self.installEventFilter(self)
        self.setMaximumSize(1024, 960)
Exemplo n.º 25
0
def export_observations_list(pj: dict, selected_observations: list,
                             file_name: str, output_format: str) -> bool:
    """
    create file with a list of selected observations

    Args:
        pj (dict): project dictionary
        selected_observations (list): list of observations to export
        file_name (str): path of file to save list of observations
        output_format (str): format output

    Returns:
        bool: True of OK else False
    """

    data = tablib.Dataset()
    data.headers = [
        "Observation id", "Date", "Description", "Subjects",
        "Media files/Live observation"
    ]

    indep_var_header = []
    if INDEPENDENT_VARIABLES in pj:
        for idx in utilities.sorted_keys(pj[INDEPENDENT_VARIABLES]):
            indep_var_header.append(pj[INDEPENDENT_VARIABLES][idx]["label"])
    data.headers.extend(indep_var_header)

    for obs_id in selected_observations:

        subjects_list = sorted(
            list(
                set([
                    x[EVENT_SUBJECT_FIELD_IDX]
                    for x in pj[OBSERVATIONS][obs_id][EVENTS]
                ])))
        if "" in subjects_list:
            subjects_list = [NO_FOCAL_SUBJECT] + subjects_list
            subjects_list.remove("")
        subjects = ", ".join(subjects_list)

        if pj[OBSERVATIONS][obs_id][TYPE] == LIVE:
            media_files = ["Live observation"]
        elif pj[OBSERVATIONS][obs_id][TYPE] == MEDIA:
            media_files = []
            if pj[OBSERVATIONS][obs_id][FILE]:
                for player in sorted(pj[OBSERVATIONS][obs_id][FILE].keys()):
                    for media in pj[OBSERVATIONS][obs_id][FILE][player]:
                        media_files.append("#{0}: {1}".format(player, media))

        # independent variables
        indep_var = []
        if INDEPENDENT_VARIABLES in pj[OBSERVATIONS][obs_id]:
            for var_label in indep_var_header:
                if var_label in pj[OBSERVATIONS][obs_id][
                        INDEPENDENT_VARIABLES]:
                    indep_var.append(pj[OBSERVATIONS][obs_id]
                                     [INDEPENDENT_VARIABLES][var_label])
                else:
                    indep_var.append("")

        data.append([
            obs_id, pj[OBSERVATIONS][obs_id]["date"], pj[OBSERVATIONS][obs_id]
            ["description"], subjects, ", ".join(media_files)
        ] + indep_var)

    if output_format in ["tsv", "csv", "html"]:
        try:
            with open(file_name, "wb") as f:
                f.write(str.encode(data.export(output_format)))
        except Exception:
            return False
    if output_format in ["ods", "xlsx", "xls"]:
        try:
            with open(file_name, "wb") as f:
                f.write(data.export(output_format))
        except:
            return False

    return True
Exemplo n.º 26
0
def export_aggregated_events(pj: dict, parameters: dict, obsId: str):
    """
    export aggregated events

    Args:
        pj (dict): BORIS project
        parameters (dict): subjects, behaviors
        obsId (str): observation id

    Returns:
        tablib.Dataset:

    """
    logging.debug(f"function: export aggregated events {parameters} {obsId}")

    interval = parameters["time"]
    start_time = parameters[START_TIME]
    end_time = parameters[END_TIME]

    data = tablib.Dataset()
    observation = pj[OBSERVATIONS][obsId]


    duration1 = []   # in seconds
    if observation[TYPE] in [MEDIA]:
        try:
            for mediaFile in observation[FILE][PLAYER1]:
                if MEDIA_INFO in observation:
                    duration1.append(observation[MEDIA_INFO]["length"][mediaFile])
        except Exception:
            duration1 = []


    obs_length = project_functions.observation_total_length(pj[OBSERVATIONS][obsId])
    if obs_length == Decimal("-1"): # media length not available
        interval = TIME_EVENTS

    logging.debug(f"obs_length: {obs_length}")

    ok, msg, connector = db_functions.load_aggregated_events_in_db(pj,
                                                                   parameters[SELECTED_SUBJECTS],
                                                                   [obsId],
                                                                   parameters[SELECTED_BEHAVIORS])
    if connector is None:
        logging.critical(f"error when loading aggregated events in DB")
        return data

    # time
    cursor = connector.cursor()

    if interval == TIME_FULL_OBS:
        min_time = float(0)
        max_time = float(obs_length)

    if interval == TIME_EVENTS:
        try:
            min_time = float(pj[OBSERVATIONS][obsId][EVENTS][0][0])
        except Exception:
            min_time = float(0)
        try:
            max_time = float(pj[OBSERVATIONS][obsId][EVENTS][-1][0])
        except Exception:
            max_time = float(obs_length)

    if interval == TIME_ARBITRARY_INTERVAL:
        min_time = float(start_time)
        max_time = float(end_time)

    # adapt start and stop to the selected time interval
    cursor.execute("UPDATE aggregated_events SET start = ? WHERE observation = ? AND start < ? AND stop BETWEEN ? AND ?",
                   (min_time, obsId, min_time, min_time, max_time, ))
    cursor.execute("UPDATE aggregated_events SET stop = ? WHERE observation = ? AND stop > ? AND start BETWEEN ? AND ?",
                   (max_time, obsId, max_time, min_time, max_time, ))

    cursor.execute("UPDATE aggregated_events SET start = ?, stop = ? WHERE observation = ? AND start < ? AND stop > ?",
                   (min_time, max_time, obsId, min_time, max_time, ))

    cursor.execute("DELETE FROM aggregated_events WHERE observation = ? AND (start < ? AND stop < ?) OR (start > ? AND stop > ?)",
                   (obsId, min_time, min_time, max_time, max_time, ))


    behavioral_category = project_functions.behavior_category(pj[ETHOGRAM])

    for subject in parameters[SELECTED_SUBJECTS]:

        for behavior in parameters[SELECTED_BEHAVIORS]:

            cursor.execute("SELECT distinct modifiers FROM aggregated_events where subject=? AND behavior=? order by modifiers",
                           (subject, behavior,))

            rows_distinct_modifiers = list(x[0] for x in cursor.fetchall())

            for distinct_modifiers in rows_distinct_modifiers:

                cursor.execute(("SELECT start, stop, type, modifiers, comment, comment_stop FROM aggregated_events "
                                "WHERE subject = ? AND behavior = ? AND modifiers = ? ORDER by start"),
                               (subject, behavior, distinct_modifiers))
                rows = list(cursor.fetchall())

                for row in rows:

                    if observation[TYPE] in [MEDIA]:
                        if duration1:
                            mediaFileIdx = [idx1 for idx1, x in enumerate(duration1) if row["start"] >= sum(duration1[0:idx1])][-1]
                            mediaFileString = observation[FILE][PLAYER1][mediaFileIdx]
                            try:
                                fpsString = observation[MEDIA_INFO]["fps"][observation[FILE][PLAYER1][mediaFileIdx]]
                            except Exception:
                                fpsString = "NA"
                        else:
                            try:
                                if len(observation[FILE][PLAYER1]) == 1:
                                    mediaFileString = observation[FILE][PLAYER1][0]
                                else:
                                    mediaFileString = "NA"
                            except Exception:
                                mediaFileString = "NA"
                            fpsString = "NA"

                    if observation[TYPE] in [LIVE]:
                        mediaFileString = "LIVE"
                        fpsString = "NA"

                    if row["type"] == POINT:

                        row_data = []
                        row_data.extend([obsId,
                                         observation["date"].replace("T", " "),
                                         mediaFileString,
                                         f"{obs_length:.3f}" if obs_length != Decimal("-1") else "NA",
                                         fpsString])

                        # independent variables
                        if INDEPENDENT_VARIABLES in pj:
                            for idx_var in utilities.sorted_keys(pj[INDEPENDENT_VARIABLES]):
                                if pj[INDEPENDENT_VARIABLES][idx_var]["label"] in observation[INDEPENDENT_VARIABLES]:
                                    row_data.append(observation[INDEPENDENT_VARIABLES][pj[INDEPENDENT_VARIABLES][idx_var]["label"]])
                                else:
                                    row_data.append("")

                        row_data.extend([subject,
                                         behavior,
                                         behavioral_category[behavior],
                                         row["modifiers"],
                                         POINT,
                                         "{0:.3f}".format(row["start"]),  # start
                                         "{0:.3f}".format(row["stop"]),  # stop
                                         "NA",  # duration
                                         row["comment"],
                                         ""
                                         ])
                        data.append(row_data)

                    if row["type"] == STATE:
                        if idx % 2 == 0:
                            row_data = []
                            row_data.extend([obsId,
                                             observation["date"].replace("T", " "),
                                             mediaFileString,
                                             f"{obs_length:.3f}" if obs_length != Decimal("-1") else "NA",
                                             fpsString])

                            # independent variables
                            if INDEPENDENT_VARIABLES in pj:
                                for idx_var in utilities.sorted_keys(pj[INDEPENDENT_VARIABLES]):
                                    if pj[INDEPENDENT_VARIABLES][idx_var]["label"] in observation[INDEPENDENT_VARIABLES]:
                                        row_data.append(observation[INDEPENDENT_VARIABLES][pj[INDEPENDENT_VARIABLES][idx_var]["label"]])
                                    else:
                                        row_data.append("")

                            row_data.extend([subject,
                                             behavior,
                                             behavioral_category[behavior],
                                             row["modifiers"],
                                             STATE,
                                             "{0:.3f}".format(row["start"]),
                                             "{0:.3f}".format(row["stop"]),
                                             "{0:.3f}".format(row["stop"] - row["start"]),
                                             row["comment"],
                                             row["comment_stop"]
                                             ])
                            data.append(row_data)

    return data
Exemplo n.º 27
0
        print()
    '''

if args.project_info:
    if not args.command:
        if pj:
            print("Project name: {}".format(pj[PROJECT_NAME]))
            print("Project date: {}".format(pj[PROJECT_DATE]))
            print("Project description: {}".format(pj[PROJECT_DESCRIPTION]))
            print()

            if not observations_id_list:
                print("Ethogram\n========")
                print("Number of behaviors in ethogram: {}".format(
                    len(pj[ETHOGRAM])))
                for idx in utilities.sorted_keys(pj[ETHOGRAM]):
                    print("Code: {}\tDescription: {}\tType: {}".format(
                        pj[ETHOGRAM][idx][BEHAVIOR_CODE],
                        pj[ETHOGRAM][idx]["description"],
                        pj[ETHOGRAM][idx][TYPE]))
                '''print("Behaviors: {}".format(",".join([pj[ETHOGRAM][k]["code"] for k in utilities.sorted_keys(pj[ETHOGRAM])])))'''
                print()

                print("Subjects\n========")
                print("Number of subjects: {}".format(len(pj[SUBJECTS])))
                for idx in utilities.sorted_keys(pj[SUBJECTS]):
                    print("Name: {}\tDescription: {}".format(
                        pj[SUBJECTS][idx]["name"],
                        pj[SUBJECTS][idx]["description"]))
                print()
Exemplo n.º 28
0
 def test_numeric_keys(self):
     r = utilities.sorted_keys({5: "a", 4: "7", 0: "z", 6: "a"})
     assert r == ['0', '4', '5', '6']
Exemplo n.º 29
0
    def __init__(self, modifiers_str, parent=None):

        super(addModifierDialog, self).__init__(parent)
        self.setupUi(self)

        self.pbAddModifier.clicked.connect(self.addModifier)
        self.pbAddModifier.setIcon(QIcon(":/frame_forward"))
        self.pbAddSet.clicked.connect(self.addSet)
        self.pbRemoveSet.clicked.connect(self.removeSet)
        self.pbModifyModifier.clicked.connect(self.modifyModifier)
        self.pbModifyModifier.setIcon(QIcon(":/frame_backward"))

        self.pbMoveUp.clicked.connect(self.moveModifierUp)
        self.pbMoveDown.clicked.connect(self.moveModifierDown)

        self.pbMoveSetLeft.clicked.connect(self.moveSetLeft)
        self.pbMoveSetRight.clicked.connect(self.moveSetRight)

        self.pbRemoveModifier.clicked.connect(self.removeModifier)
        self.pbOK.clicked.connect(self.accept)
        self.pbCancel.clicked.connect(self.reject)

        self.leSetName.textChanged.connect(self.set_name_changed)

        self.cbType.currentIndexChanged.connect(self.type_changed)

        dummy_dict = eval(modifiers_str) if modifiers_str else {}
        modif_values = []
        for idx in sorted_keys(dummy_dict):
            modif_values.append(dummy_dict[idx])
        print("modifiers ", modif_values)

        self.modifiers_sets_dict = {}
        for modif in modif_values:
            self.modifiers_sets_dict[str(len(
                self.modifiers_sets_dict))] = copy.deepcopy(modif)

        self.tabWidgetModifiersSets.currentChanged.connect(
            self.tabWidgetModifiersSets_changed)

        # create tab
        for idx in sorted_keys(self.modifiers_sets_dict):
            self.tabWidgetModifiersSets.addTab(QWidget(),
                                               "Set #{}".format(int(idx) + 1))
            '''
            if idx != "0":
                self.tabWidgetModifiersSets.addTab(QWidget(), "Set #{}".format(int(idx) + 1))
            '''

        print(self.tabWidgetModifiersSets.currentIndex())
        if self.tabWidgetModifiersSets.currentIndex() == -1:
            for w in [
                    self.lbSetName, self.lbType, self.lbValues, self.leSetName,
                    self.cbType, self.lwModifiers, self.pbMoveUp,
                    self.pbMoveDown, self.pbRemoveModifier, self.pbRemoveSet,
                    self.pbMoveSetLeft, self.pbMoveSetRight
            ]:
                w.setVisible(False)
            for w in [
                    self.leModifier, self.leCode, self.pbAddModifier,
                    self.pbModifyModifier
            ]:
                w.setEnabled(False)

        # set first tab as active
        '''
        if self.modifiers_sets_dict:
            self.leSetName.setText(self.modifiers_sets_dict["0"]["name"])
            self.cbType.setCurrentIndex(self.modifiers_sets_dict["0"]["type"])
            self.lwModifiers.addItems(self.modifiers_sets_dict["0"]["values"])
        '''
        self.tabMem = 0
Exemplo n.º 30
0
        print()
    '''


if args.project_info:
    if not args.command:
        if pj:
            print("Project name: {}".format(pj[PROJECT_NAME]))
            print("Project date: {}".format(pj[PROJECT_DATE]))
            print("Project description: {}".format(pj[PROJECT_DESCRIPTION]))
            print()

            if not observations_id_list:
                print("Ethogram\n========")
                print("Number of behaviors in ethogram: {}".format(len(pj[ETHOGRAM])))
                for idx in utilities.sorted_keys(pj[ETHOGRAM]):
                    print("Code: {}\tDescription: {}\tType: {}".format(pj[ETHOGRAM][idx][BEHAVIOR_CODE],
                                                                       pj[ETHOGRAM][idx]["description"],
                                                                       pj[ETHOGRAM][idx][TYPE]
                                                                       ))
                '''print("Behaviors: {}".format(",".join([pj[ETHOGRAM][k]["code"] for k in utilities.sorted_keys(pj[ETHOGRAM])])))'''
                print()

                print("Subjects\n========")
                print("Number of subjects: {}".format(len(pj[SUBJECTS])))
                for idx in utilities.sorted_keys(pj[SUBJECTS]):
                    print("Name: {}\tDescription: {}".format(pj[SUBJECTS][idx]["name"], pj[SUBJECTS][idx]["description"]))
                print()

                print("Observations\n============")
                print("Number of observations: {}".format(len(pj[OBSERVATIONS])))
Exemplo n.º 31
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
            }
Exemplo n.º 32
0
def export_aggregated_events(pj, parameters, obsId):
    """
    export aggregated events

    Args:
        pj (dict): BORIS project
        parameters (dict): subjects, behaviors
        obsId (str): observation id

    Returns:
        tablib.Dataset:

    """
    data = tablib.Dataset()
    observation = pj[OBSERVATIONS][obsId]

    duration1 = []  # in seconds
    if observation[TYPE] in [MEDIA]:
        try:
            for mediaFile in observation[FILE][PLAYER1]:
                if "media_info" in observation:
                    duration1.append(
                        observation["media_info"]["length"][mediaFile])
        except:
            duration1 = []

    total_length = "{0:.3f}".format(
        project_functions.observation_total_length(observation))

    ok, msg, connector = db_functions.load_aggregated_events_in_db(
        pj, parameters["selected subjects"], [obsId],
        parameters["selected behaviors"])
    if not ok:
        data

    cursor = connector.cursor()

    for subject in parameters["selected subjects"]:

        for behavior in parameters["selected behaviors"]:

            cursor.execute(
                "select distinct modifiers from aggregated_events where subject=? AND behavior=? order by modifiers",
                (
                    subject,
                    behavior,
                ))
            rows_distinct_modifiers = list(x[0].strip()
                                           for x in cursor.fetchall())

            for distinct_modifiers in rows_distinct_modifiers:

                cursor.execute((
                    "SELECT start, stop, type, modifiers, comment, comment_stop FROM aggregated_events "
                    "WHERE subject = ? AND behavior = ? AND modifiers = ? ORDER by start"
                ), (subject, behavior, distinct_modifiers))
                rows = list(cursor.fetchall())

                for row in rows:

                    if observation[TYPE] in [MEDIA]:
                        if duration1:
                            mediaFileIdx = [
                                idx1 for idx1, x in enumerate(duration1)
                                if row["start"] >= sum(duration1[0:idx1])
                            ][-1]
                            mediaFileString = observation[FILE][PLAYER1][
                                mediaFileIdx]
                            fpsString = observation["media_info"]["fps"][
                                observation[FILE][PLAYER1][mediaFileIdx]]
                        else:
                            mediaFileString = "-"
                            fpsString = "NA"

                    if observation[TYPE] in [LIVE]:
                        mediaFileString = "LIVE"
                        fpsString = "NA"

                    #if POINT in project_functions.event_type(behavior, pj[ETHOGRAM]):
                    if row["type"] == POINT:

                        row_data = []
                        row_data.extend([
                            obsId, observation["date"].replace("T", " "),
                            mediaFileString, total_length, fpsString
                        ])

                        # independent variables
                        if INDEPENDENT_VARIABLES in pj:
                            for idx_var in utilities.sorted_keys(
                                    pj[INDEPENDENT_VARIABLES]):
                                if pj[INDEPENDENT_VARIABLES][idx_var][
                                        "label"] in observation[
                                            INDEPENDENT_VARIABLES]:
                                    row_data.append(
                                        observation[INDEPENDENT_VARIABLES][
                                            pj[INDEPENDENT_VARIABLES][idx_var]
                                            ["label"]])
                                else:
                                    row_data.append("")

                        row_data.extend([
                            subject,
                            behavior,
                            row["modifiers"].strip(),
                            POINT,
                            "{0:.3f}".format(row["start"]),  # start
                            "{0:.3f}".format(row["stop"]),  # stop
                            "NA",  # duration
                            row["comment"],
                            ""
                        ])
                        data.append(row_data)

                    #if STATE in project_functions.event_type(behavior, pj[ETHOGRAM]):
                    if row["type"] == STATE:
                        if idx % 2 == 0:
                            row_data = []
                            row_data.extend([
                                obsId, observation["date"].replace("T", " "),
                                mediaFileString, total_length, fpsString
                            ])

                            # independent variables
                            if INDEPENDENT_VARIABLES in pj:
                                for idx_var in utilities.sorted_keys(
                                        pj[INDEPENDENT_VARIABLES]):
                                    if pj[INDEPENDENT_VARIABLES][idx_var][
                                            "label"] in observation[
                                                INDEPENDENT_VARIABLES]:
                                        row_data.append(
                                            observation[INDEPENDENT_VARIABLES]
                                            [pj[INDEPENDENT_VARIABLES][idx_var]
                                             ["label"]])
                                    else:
                                        row_data.append("")

                            row_data.extend([
                                subject, behavior, row["modifiers"].strip(),
                                STATE, "{0:.3f}".format(row["start"]),
                                "{0:.3f}".format(row["stop"]),
                                "{0:.3f}".format(row["stop"] - row["start"]),
                                row["comment"], row["comment_stop"]
                            ])
                            data.append(row_data)

    return data