Ejemplo n.º 1
0
def default_value(ethogram, behav, param):
    """
    return value for duration in case of point event
    """
    default_value_ = 0
    if (project_functions.event_type(behav, ethogram) == "POINT EVENT"
            and param in ["duration"]):
        default_value_ = "-"
    return default_value_
Ejemplo n.º 2
0
def default_value(ethogram, behav, param):
    """
    return value for duration in case of point event
    """
    default_value_ = 0
    if (project_functions.event_type(behav, ethogram) == "POINT EVENT"
       and param in ["duration"]):
           default_value_ = "-"
    return default_value_
Ejemplo n.º 3
0
def behaviors_bar_plot(pj, selected_observations, selected_subjects,
                       selected_behaviors, include_modifiers, interval,
                       start_time, end_time, plot_directory, output_format):
    """
    scatter plot
    """
    parameters = [
        ["duration", "Total duration"],
    ]

    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 include_modifiers:
        cursor.execute(
            "SELECT distinct behavior, modifiers FROM aggregated_events")
        distinct_behav_modif = [[rows["behavior"], rows["modifiers"]]
                                for rows in cursor.fetchall()]
    else:
        cursor.execute("SELECT distinct behavior FROM aggregated_events")
        distinct_behav_modif = [[rows["behavior"], ""]
                                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, "-"])

    behaviors = init_behav_modif(pj[ETHOGRAM], selected_subjects,
                                 distinct_behav_modif, include_modifiers,
                                 parameters)

    # select time interval
    for obs_id in selected_observations:

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

        # if modifiers not to be included set modifiers to ""
        if not include_modifiers:
            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 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,
            ))

        for subject in selected_subjects:
            for behavior_modifiers in distinct_behav_modif:
                behavior, modifiers = behavior_modifiers

                # skip if behavior defined as POINT
                if POINT in project_functions.event_type(
                        behavior, pj[ETHOGRAM]):
                    continue

                behavior_modifiers_str = "|".join(
                    behavior_modifiers) if modifiers else behavior

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

        print("behaviors")
        print(behaviors)

        print()
        print("sorted(distinct_behav_modif)", sorted(distinct_behav_modif))

        max_length = 0
        behaviors_duration = {}
        mb = {}

        for ax_idx, subj in enumerate(selected_subjects):
            behaviors_duration[subj] = {}

            behavior_ticks = []

            for behavior_modifiers in sorted(distinct_behav_modif):

                behavior, modifiers = behavior_modifiers

                # skip if behavior defined as POINT
                if POINT in project_functions.event_type(
                        behavior, pj[ETHOGRAM]):
                    continue

                if behavior not in behaviors_duration[subj]:
                    behaviors_duration[subj][behavior] = [[], []]

                behavior_modifiers_str = "|".join(
                    behavior_modifiers) if modifiers else behavior

                if behavior not in behavior_ticks:
                    behavior_ticks.append(behavior)

                for param in parameters:
                    behaviors_duration[subj][behavior][0].append(
                        behaviors[subj][behavior_modifiers_str][param[0]])
                    behaviors_duration[subj][behavior][1].append(modifiers)
                    max_length = max(
                        max_length, len(behaviors_duration[subj][behavior][1]))

            print()
            print("behaviors_duration", behaviors_duration)
            print()
            print("behavior_ticks", behavior_ticks)
            print()

        behavior_mod_ticks = behavior_ticks[:]
        for ax_idx, subj in enumerate(selected_subjects):

            print("subject", subj)
            md_lgd = []
            b = {}
            for i in range(max_length):

                b[i] = []

                for behavior in sorted(behaviors_duration[subj].keys()):
                    try:
                        b[i].append(behaviors_duration[subj][behavior][0][i])
                        if include_modifiers:

                            if behaviors_duration[subj][behavior][1][i]:
                                md_lgd.append(
                                    behavior + " " +
                                    behaviors_duration[subj][behavior][1][i])
                            else:
                                md_lgd.append(behavior)
                    except Exception:
                        b[i].append(0)

            print()
            print("behavior_mod_ticks", behavior_mod_ticks)
            print()
            print("b")
            print(b)
            print()
            print("md_lgd")
            print(md_lgd)

            ind = np.arange(len(behavior_ticks))

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

            pp = []
            max_obs = 0
            bottom_ = []

            idx_color = 0

            for i in sorted(b.keys()):

                if i == 0:
                    pp.append(axs[ax_idx].bar(
                        ind,
                        b[i],
                        width,
                        color=BEHAVIORS_PLOT_COLORS[idx_color:idx_color +
                                                    len(b[i])]))
                else:
                    pp.append(axs[ax_idx].bar(
                        ind,
                        b[i],
                        width,
                        color=BEHAVIORS_PLOT_COLORS[idx_color:idx_color +
                                                    len(b[i])],
                        bottom=bottom_))

                idx_color += len(b[i])

                if not bottom_:
                    bottom_ = b[i]
                else:
                    bottom_ = [x + bottom_[idx] for idx, x in enumerate(b[i])]

                max_obs = max(max_obs, sum(b[i]))

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

            axs[ax_idx].set_xticks(ind)
            axs[ax_idx].set_xticklabels(behavior_mod_ticks, rotation=90)
            axs[ax_idx].set_yticks(np.arange(0, max(bottom_), 50))

            lgd_col = []
            for p in pp:
                for r in p:
                    if r.get_height():
                        lgd_col.append(r)

            plt.legend(lgd_col, md_lgd)

        if plot_directory:
            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()
Ejemplo n.º 4
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()}
Ejemplo n.º 5
0
def time_budget_analysis(ethogram: dict,
                         cursor,
                         selected_observations: list,
                         parameters: dict,
                         by_category: bool = False):
    """
    extract number of occurrences, total duration, mean ...
    if start_time = 0 and end_time = 0 all events are extracted

    Args:
        ethogram (dict): project ethogram
        cursor: cursor on temporary database
        selected_observations (list): selected observations
        parameters (dict): parameters for analysis
        by_category (bool): True for grouping in category else False

    Returns:
        list: results
        dict:
    """

    categories, out = {}, []
    for subject in parameters[SELECTED_SUBJECTS]:
        out_cat, categories[subject] = [], {}

        for behavior in parameters[SELECTED_BEHAVIORS]:

            if parameters[INCLUDE_MODIFIERS]:

                cursor.execute(
                    "SELECT DISTINCT modifiers FROM events WHERE subject = ? AND code = ?",
                    (subject, behavior))
                distinct_modifiers = list(cursor.fetchall())

                if not distinct_modifiers:
                    if not parameters[EXCLUDE_BEHAVIORS]:

                        if STATE in project_functions.event_type(
                                behavior, ethogram):

                            out.append({
                                "subject": subject,
                                "behavior": behavior,
                                "modifiers": "",
                                "duration": 0,
                                "duration_mean": 0,
                                "duration_stdev": "NA",
                                "number": "0",
                                "inter_duration_mean": "NA",
                                "inter_duration_stdev": "NA"
                            })
                        else:  # point
                            out.append({
                                "subject": subject,
                                "behavior": behavior,
                                "modifiers": "",
                                "duration": 0,
                                "duration_mean": 0,
                                "duration_stdev": "NA",
                                "number": "0",
                                "inter_duration_mean": "NA",
                                "inter_duration_stdev": "NA"
                            })
                    continue

                if POINT in project_functions.event_type(behavior, ethogram):

                    for modifier in distinct_modifiers:
                        cursor.execute(
                            ("SELECT occurence, observation FROM events "
                             "WHERE subject = ? "
                             "AND code = ? "
                             "AND modifiers = ? "
                             "ORDER BY observation, occurence"),
                            (subject, behavior, modifier[0]))

                        rows = cursor.fetchall()

                        # inter events duration
                        all_event_interdurations = []
                        for idx, row in enumerate(rows):
                            if idx and row[1] == rows[idx - 1][1]:
                                all_event_interdurations.append(
                                    float(row[0]) - float(rows[idx - 1][0]))

                        out_cat.append({
                            "subject":
                            subject,
                            "behavior":
                            behavior,
                            "modifiers":
                            modifier[0],
                            "duration":
                            NA,
                            "duration_mean":
                            NA,
                            "duration_stdev":
                            NA,
                            "number":
                            len(rows),
                            "inter_duration_mean":
                            round(statistics.mean(all_event_interdurations), 3)
                            if len(all_event_interdurations) else NA,
                            "inter_duration_stdev":
                            round(statistics.stdev(all_event_interdurations),
                                  3)
                            if len(all_event_interdurations) > 1 else NA
                        })

                if STATE in project_functions.event_type(behavior, ethogram):

                    for modifier in distinct_modifiers:
                        cursor.execute(
                            ("SELECT occurence, observation FROM events "
                             "WHERE subject = ? "
                             "AND code = ? "
                             "AND modifiers = ? "
                             "ORDER BY observation, occurence"),
                            (subject, behavior, modifier[0]))

                        rows = list(cursor.fetchall())
                        if len(rows) % 2:
                            out.append({
                                "subject": subject,
                                "behavior": behavior,
                                "modifiers": modifier[0],
                                "duration": UNPAIRED,
                                "duration_mean": UNPAIRED,
                                "duration_stdev": UNPAIRED,
                                "number": UNPAIRED,
                                "inter_duration_mean": UNPAIRED,
                                "inter_duration_stdev": UNPAIRED
                            })
                        else:
                            all_event_durations, all_event_interdurations = [], []
                            for idx, row in enumerate(rows):
                                # event
                                if idx % 2 == 0:
                                    new_init, new_end = float(row[0]), float(
                                        rows[idx + 1][0])

                                    all_event_durations.append(new_end -
                                                               new_init)

                                # inter event if same observation
                                if idx % 2 and idx != len(rows) - 1 and row[
                                        1] == rows[idx + 1][1]:
                                    if (parameters["start time"] <= row[0] <=
                                            parameters["end time"]
                                            and parameters["start time"] <=
                                            rows[idx + 1][0] <=
                                            parameters["end time"]):
                                        all_event_interdurations.append(
                                            float(rows[idx + 1][0]) -
                                            float(row[0]))

                            out_cat.append({
                                "subject":
                                subject,
                                "behavior":
                                behavior,
                                "modifiers":
                                modifier[0],
                                "duration":
                                round(sum(all_event_durations), 3),
                                "duration_mean":
                                round(statistics.mean(all_event_durations), 3)
                                if len(all_event_durations) else "NA",
                                "duration_stdev":
                                round(statistics.stdev(all_event_durations), 3)
                                if len(all_event_durations) > 1 else "NA",
                                "number":
                                len(all_event_durations),
                                "inter_duration_mean":
                                round(
                                    statistics.mean(all_event_interdurations),
                                    3)
                                if len(all_event_interdurations) else "NA",
                                "inter_duration_stdev":
                                round(
                                    statistics.stdev(all_event_interdurations),
                                    3)
                                if len(all_event_interdurations) > 1 else "NA"
                            })

            else:  # no modifiers

                if POINT in project_functions.event_type(behavior, ethogram):

                    cursor.execute((
                        "SELECT occurence,observation FROM events "
                        "WHERE subject = ? AND code = ? ORDER BY observation, occurence"
                    ), (subject, behavior))

                    rows = list(cursor.fetchall())

                    if len(selected_observations) == 1:
                        new_rows = []
                        for occurence, observation in rows:
                            new_occurence = max(
                                float(parameters["start time"]), occurence)
                            new_occurence = min(new_occurence,
                                                float(parameters["end time"]))
                            new_rows.append([new_occurence, observation])
                        rows = list(new_rows)

                    # include behaviors without events
                    if not len(rows):
                        if not parameters[EXCLUDE_BEHAVIORS]:
                            out.append({
                                "subject": subject,
                                "behavior": behavior,
                                "modifiers": "",
                                "duration": NA,
                                "duration_mean": NA,
                                "duration_stdev": NA,
                                "number": "0",
                                "inter_duration_mean": NA,
                                "inter_duration_stdev": NA
                            })
                        continue

                    # inter events duration
                    all_event_interdurations = []
                    for idx, row in enumerate(rows):
                        if idx and row[1] == rows[idx - 1][1]:
                            all_event_interdurations.append(
                                float(row[0]) - float(rows[idx - 1][0]))

                    out_cat.append({
                        "subject":
                        subject,
                        "behavior":
                        behavior,
                        "modifiers":
                        "",
                        "duration":
                        NA,
                        "duration_mean":
                        NA,
                        "duration_stdev":
                        NA,
                        "number":
                        len(rows),
                        "inter_duration_mean":
                        round(statistics.mean(all_event_interdurations), 3)
                        if len(all_event_interdurations) else NA,
                        "inter_duration_stdev":
                        round(statistics.stdev(all_event_interdurations), 3)
                        if len(all_event_interdurations) > 1 else NA
                    })

                if STATE in project_functions.event_type(behavior, ethogram):

                    cursor.execute((
                        "SELECT occurence, observation FROM events "
                        "WHERE subject = ? AND code = ? ORDER BY observation, occurence"
                    ), (subject, behavior))

                    rows = list(cursor.fetchall())
                    if not len(rows):
                        if not parameters[
                                EXCLUDE_BEHAVIORS]:  # include behaviors without events
                            out.append({
                                "subject": subject,
                                "behavior": behavior,
                                "modifiers": "",
                                "duration": 0,
                                "duration_mean": 0,
                                "duration_stdev": "NA",
                                "number": 0,
                                "inter_duration_mean": "-",
                                "inter_duration_stdev": "-"
                            })
                        continue

                    if len(rows) % 2:
                        out.append({
                            "subject": subject,
                            "behavior": behavior,
                            "modifiers": "",
                            "duration": UNPAIRED,
                            "duration_mean": UNPAIRED,
                            "duration_stdev": UNPAIRED,
                            "number": UNPAIRED,
                            "inter_duration_mean": UNPAIRED,
                            "inter_duration_stdev": UNPAIRED
                        })
                    else:
                        all_event_durations, all_event_interdurations = [], []
                        for idx, row in enumerate(rows):
                            # event
                            if idx % 2 == 0:
                                new_init, new_end = float(row[0]), float(
                                    rows[idx + 1][0])

                                all_event_durations.append(new_end - new_init)

                            # inter event if same observation
                            if idx % 2 and idx != len(rows) - 1 and row[
                                    1] == rows[idx + 1][1]:
                                if (parameters["start time"] <= row[0] <=
                                        parameters["end time"]
                                        and parameters["start time"] <=
                                        rows[idx + 1][0] <=
                                        parameters["end time"]):
                                    all_event_interdurations.append(
                                        float(rows[idx + 1][0]) -
                                        float(row[0]))

                        out_cat.append({
                            "subject":
                            subject,
                            "behavior":
                            behavior,
                            "modifiers":
                            "",
                            "duration":
                            round(sum(all_event_durations), 3),
                            "duration_mean":
                            round(statistics.mean(all_event_durations), 3)
                            if len(all_event_durations) else NA,
                            "duration_stdev":
                            round(statistics.stdev(all_event_durations), 3)
                            if len(all_event_durations) > 1 else NA,
                            "number":
                            len(all_event_durations),
                            "inter_duration_mean":
                            round(statistics.mean(all_event_interdurations), 3)
                            if len(all_event_interdurations) else NA,
                            "inter_duration_stdev":
                            round(statistics.stdev(all_event_interdurations),
                                  3)
                            if len(all_event_interdurations) > 1 else NA
                        })

        out += out_cat

        if by_category:  # and flagCategories:

            for behav in out_cat:

                try:
                    category = [
                        ethogram[x]["category"] for x in ethogram
                        if "category" in ethogram[x]
                        and ethogram[x]["code"] == behav['behavior']
                    ][0]
                except Exception:
                    category = ""

                if category in categories[subject]:
                    if behav["duration"] not in [
                            "-", "NA"
                    ] and categories[subject][category]["duration"] not in [
                            "-", "NA"
                    ]:
                        categories[subject][category]["duration"] += behav[
                            "duration"]
                    else:
                        categories[subject][category]["duration"] = "-"
                    categories[subject][category]["number"] += behav["number"]
                else:
                    categories[subject][category] = {
                        "duration": behav["duration"],
                        "number": behav["number"]
                    }

    out_sorted = []
    for subject in parameters[SELECTED_SUBJECTS]:
        for behavior in parameters[SELECTED_BEHAVIORS]:
            for row in out:
                if row["subject"] == subject and row["behavior"] == behavior:
                    out_sorted.append(row)

    # http://stackoverflow.com/questions/673867/python-arbitrary-order-by
    return out_sorted, categories
Ejemplo n.º 6
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))

    cursor = db_functions.load_events_in_db(pj,
                                            parameters["selected subjects"],
                                            [obsId],
                                            parameters["selected behaviors"])

    for subject in parameters["selected subjects"]:

        for behavior in parameters["selected behaviors"]:

            cursor.execute(
                "SELECT occurence, modifiers, comment FROM events WHERE observation = ? AND subject = ? AND code = ? ORDER by occurence",
                (obsId, subject, behavior))
            rows = list(cursor.fetchall())

            for idx, row in enumerate(rows):

                if observation[TYPE] in [MEDIA]:
                    if duration1:
                        mediaFileIdx = [
                            idx1 for idx1, x in enumerate(duration1)
                            if row["occurence"] >= 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]):

                    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["occurence"]),  # start
                        "NA",  # stop
                        "NA",  # duration
                        row["comment"],
                        ""
                    ])
                    data.append(row_data)

                if STATE in project_functions.event_type(
                        behavior, pj[ETHOGRAM]):
                    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["occurence"]),
                            "{0:.3f}".format(rows[idx + 1]["occurence"]),
                            "{0:.3f}".format(rows[idx + 1]["occurence"] -
                                             row["occurence"]), row["comment"],
                            rows[idx + 1]["comment"]
                        ])
                        data.append(row_data)

    return data
Ejemplo n.º 7
0
def behaviors_bar_plot(pj, selected_observations, selected_subjects, selected_behaviors, include_modifiers,
                       interval, start_time, end_time,
                       plot_directory, output_format):
    """
    scatter plot
    """
    parameters = [["duration", "Total duration"],
                  ]

    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 include_modifiers:
        cursor.execute("SELECT distinct behavior, modifiers FROM aggregated_events")
        distinct_behav_modif = [[rows["behavior"], rows["modifiers"]] for rows in cursor.fetchall()]
    else:
        cursor.execute("SELECT distinct behavior FROM aggregated_events")
        distinct_behav_modif = [[rows["behavior"], ""] 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, "-"])

    behaviors = init_behav_modif(pj[ETHOGRAM],
                                 selected_subjects,
                                 distinct_behav_modif,
                                 include_modifiers,
                                 parameters)


    # select time interval
    for obs_id in selected_observations:

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

        # if modifiers not to be included set modifiers to ""
        if not include_modifiers:
            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 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, ))

        for subject in selected_subjects:
            for behavior_modifiers in distinct_behav_modif:
                behavior, modifiers = behavior_modifiers

                # skip if behavior defined as POINT
                if POINT in project_functions.event_type(behavior, pj[ETHOGRAM]):
                    continue

                behavior_modifiers_str = "|".join(behavior_modifiers) if modifiers else behavior

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

        print("behaviors")
        print(behaviors)

        print()
        print("sorted(distinct_behav_modif)", sorted(distinct_behav_modif))

        max_length = 0
        behaviors_duration = {}
        mb = {}

        for ax_idx, subj in enumerate(selected_subjects):
            behaviors_duration[subj] = {}

            behavior_ticks = []

            for behavior_modifiers in sorted(distinct_behav_modif):

                behavior, modifiers = behavior_modifiers

                # skip if behavior defined as POINT
                if POINT in project_functions.event_type(behavior, pj[ETHOGRAM]):
                    continue

                if behavior not in behaviors_duration[subj]:
                    behaviors_duration[subj][behavior] = [[],[]]

                behavior_modifiers_str = "|".join(behavior_modifiers) if modifiers else behavior
                #print(subj, behavior, modifiers)
                if behavior not in behavior_ticks:
                    behavior_ticks.append(behavior)

                for param in parameters:
                    behaviors_duration[subj][behavior][0].append(behaviors[subj][behavior_modifiers_str][param[0]])
                    behaviors_duration[subj][behavior][1].append(modifiers)
                    max_length = max(max_length, len(behaviors_duration[subj][behavior][1]))


            print()
            print("behaviors_duration", behaviors_duration)
            print()
            print("behavior_ticks", behavior_ticks)
            print()


        #b = {}

        behavior_mod_ticks = behavior_ticks[:]
        for ax_idx, subj in enumerate(selected_subjects):

            print("subject", subj)
            md_lgd = []
            b = {}
            for i in range(max_length):

                b[i] = []

                for behavior in sorted(behaviors_duration[subj].keys()):
                    try:
                        b[i].append(behaviors_duration[subj][behavior][0][i])
                        if include_modifiers:

                            '''
                            if behaviors_duration[subj][behavior][1][i]:
                                behavior_mod_ticks[behavior_ticks.index(behavior)] = behavior_mod_ticks[behavior_ticks.index(behavior)] + "\n" + \
                                                                                        behaviors_duration[subj][behavior][1][i]
                            '''

                            if behaviors_duration[subj][behavior][1][i]:
                                md_lgd.append(behavior + " " + behaviors_duration[subj][behavior][1][i])
                            else:
                                md_lgd.append(behavior)
                    except:
                        b[i].append(0)

            print()
            print("behavior_mod_ticks", behavior_mod_ticks)
            print()
            print("b")
            print(b)
            print()
            print("md_lgd")
            print(md_lgd)

            #ind = np.arange(len(behavior_ticks))    # the x locations for the groups

            ind = np.arange(len(behavior_ticks))

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



            pp = []
            max_obs = 0
            bottom_ = []

            idx_color = 0

            for i in sorted(b.keys()):
                print(i, b[i])
                if i == 0:
                    pp.append(axs[ax_idx].bar(ind, b[i], width, color=BEHAVIORS_PLOT_COLORS[idx_color:idx_color + len(b[i])]))
                else:
                    pp.append(axs[ax_idx].bar(ind, b[i], width, color=BEHAVIORS_PLOT_COLORS[idx_color:idx_color + len(b[i])], bottom=bottom_))

                idx_color += len(b[i])

                if not bottom_:
                    bottom_ = b[i]
                else:
                    bottom_ = [x + bottom_[idx] for idx,x in enumerate(b[i])]

                max_obs = max(max_obs, sum(b[i]))

            if ax_idx == 0:
                axs[ax_idx].set_ylabel('Duration (s)')
            axs[ax_idx].set_xlabel('Behaviors')
            axs[ax_idx].set_title('{}'.format(subj))

            axs[ax_idx].set_xticks(ind)
            axs[ax_idx].set_xticklabels(behavior_mod_ticks,rotation=90)
            axs[ax_idx].set_yticks(np.arange(0, max(bottom_), 50))

            lgd_col = []
            for p in pp:
                for r in p:
                    if r.get_height():
                        lgd_col.append(r)

            plt.legend(lgd_col, md_lgd)


        if plot_directory:
            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()