diff --git a/boris.py b/boris.py index feb1fb7c..84c06ea9 100644 --- a/boris.py +++ b/boris.py @@ -735,17 +735,22 @@ def connections(self): self.actionTime_budget.triggered.connect(lambda: self.time_budget("by_behavior")) self.actionTime_budget_by_behaviors_category.triggered.connect(lambda: self.time_budget("by_category")) #self.actionTime_budget_report.triggered.connect(lambda: self.time_budget("synthetic")) - + self.actionTime_budget_report.triggered.connect(self.synthetic_time_budget) + + #self.actionTest_stb2.triggered.connect(self.synthetic_time_budget) + self.actionTest_stb2.setVisible(False) - self.actionBehavior_bar_plot.triggered.connect(self.behaviors_bar_plot) - #self.actionBehavior_bar_plot.setVisible(False) + #self.actionBehavior_bar_plot.triggered.connect(self.behaviors_bar_plot) + self.actionBehavior_bar_plot.setVisible(False) - self.actionPlot_events1.triggered.connect(self.plot_events1_triggered) - self.actionPlot_events2.triggered.connect(self.plot_events2_triggered) + #self.actionPlot_events1.triggered.connect(self.plot_events1_triggered) + self.actionPlot_events1.setVisible(False) + self.actionPlot_events2.triggered.connect(self.plot_events2_new_triggered) - self.actionTest.triggered.connect(self.plot_events2_new_triggered) + #self.actionTest.triggered.connect(self.plot_events2_new_triggered) + self.actionTest.setVisible(False) # menu Help @@ -3643,7 +3648,7 @@ def selectObservations(self, mode): mode: accepted values: OPEN, EDIT, SINGLE, MULTIPLE, SELECT1 """ resultStr, selectedObs = select_observations.select_observations(self.pj, mode) - + return resultStr, selectedObs @@ -4753,7 +4758,8 @@ def choose_obs_subj_behav_category(self, for behavior in [self.pj[ETHOGRAM][x]["code"] for x in sorted_keys(self.pj[ETHOGRAM])]: if ((categories == ["###no category###"]) - or (behavior in [self.pj[ETHOGRAM][x]["code"] for x in self.pj[ETHOGRAM] if "category" in self.pj[ETHOGRAM][x] and self.pj[ETHOGRAM][x]["category"] == category])): + or (behavior in [self.pj[ETHOGRAM][x][BEHAVIOR_CODE] for x in self.pj[ETHOGRAM] + if "category" in self.pj[ETHOGRAM][x] and self.pj[ETHOGRAM][x]["category"] == category])): paramPanelWindow.item = QListWidgetItem(behavior) if behavior in observedBehaviors: @@ -4788,7 +4794,8 @@ def choose_obs_subj_behav_category(self, 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) + 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(): @@ -4896,14 +4903,12 @@ def synthetic_time_budget(self): if pathlib.Path(file_name).suffix != "." + output_format: file_name = str(pathlib.Path(file_name)) + "." + output_format + + '''synth_tb_param["group observations"] = True''' + ok, msg, data_report = time_budget_functions.synthetic_time_budget(self.pj, selected_observations, - synth_tb_param["selected subjects"], - synth_tb_param["selected behaviors"], - synth_tb_param["include modifiers"], - synth_tb_param["time"], - synth_tb_param["start time"], - synth_tb_param["end time"] + synth_tb_param ) if not ok: @@ -5926,6 +5931,7 @@ def plot_events2_new_triggered(self): plot events in time diagram """ result, selected_observations = self.selectObservations(MULTIPLE) + if not selected_observations: return # check if state events are paired @@ -6011,7 +6017,7 @@ def plot_events2_new_triggered(self): parameters = self.choose_obs_subj_behav_category(selected_observations, maxTime=max_obs_length, - flagShowExcludeBehaviorsWoEvents=False, + flagShowExcludeBehaviorsWoEvents=True, by_category=False) if not parameters["selected subjects"] or not parameters["selected behaviors"]: @@ -6020,12 +6026,7 @@ def plot_events2_new_triggered(self): plot_events.create_events_plot2_new(self.pj, selected_observations, - parameters["selected subjects"], - parameters["selected behaviors"], - parameters["include modifiers"], - parameters["time"], - parameters["start time"], - parameters["end time"], + parameters, plot_colors=self.plot_colors, plot_directory=plot_directory, file_format=file_format) diff --git a/boris.ui b/boris.ui index 0f81fde6..29115ff4 100644 --- a/boris.ui +++ b/boris.ui @@ -211,6 +211,7 @@ + @@ -1198,6 +1199,11 @@ test + + + test stb2 + + diff --git a/boris_cli.py b/boris_cli.py index 9d72e915..a0ccd3c1 100644 --- a/boris_cli.py +++ b/boris_cli.py @@ -43,6 +43,9 @@ def cleanhtml(raw_html): cleantext = re.sub(cleanr, "", raw_html) return cleantext +def all_observations(pj): + return [idx for idx in sorted(pj[OBSERVATIONS])] + commands_list = ["check_state_events", "export_events", "irr", "subtitles", "check_project_integrity", "plot_events"] commands_usage = { @@ -69,10 +72,11 @@ def cleanhtml(raw_html): "check_project_integrity": "usage:\nboris_cli -p PROJECT_FILE --command check_project_integrity", -"plot_events": ("usage:\nboris_cli - p PROJECT_FILE -o OBSERVATION_ID --command plot_events [OUTPUT_DIRECTORY] [INCLUDE_MODIFIERS] [PLOT_FORMAT]\n" +"plot_events": ("usage:\nboris_cli - p PROJECT_FILE -o OBSERVATION_ID --command plot_events [OUTPUT_DIRECTORY] [INCLUDE_MODIFIERS] [EXCLUDE_BEHAVIORS] [PLOT_FORMAT]\n" "where\n" "OUTPUT_DIRECTORY is the directory where the plots will be saved\n" "INCLUDE_MODIFIERS must be true or false (default is true)\n" + "EXCLUDE_BEHAVIORS: True: behaviors without events are not plotted (default is true)\n" "PLOT_FORMAT can be png, svg, pdf, ps") } @@ -190,7 +194,7 @@ def cleanhtml(raw_html): if not observations_id_list: print("No observation selected. Command applied on all observations found in project\n") - observations_id_list = [idx for idx in pj[OBSERVATIONS]] + observations_id_list = all_observations(pj) for observation_id in observations_id_list: ret, msg = project_functions.check_state_events_obs(observation_id, pj[ETHOGRAM], pj[OBSERVATIONS][observation_id], HHMMSS) @@ -268,7 +272,7 @@ def cleanhtml(raw_html): if not observations_id_list: print("No observation selected. Command applied on all observations found in project\n") - observations_id_list = [idx for idx in pj[OBSERVATIONS]] + observations_id_list = all_observations(pj) behaviors = [pj[ETHOGRAM][k]["code"] for k in utilities.sorted_keys(pj[ETHOGRAM])] subjects = [pj[SUBJECTS][k]["name"] for k in utilities.sorted_keys(pj[SUBJECTS])] + [NO_FOCAL_SUBJECT] @@ -303,7 +307,7 @@ def cleanhtml(raw_html): if not observations_id_list: print("No observation selected. Command applied on all observations found in project\n") - observations_id_list = [idx for idx in pj[OBSERVATIONS]] + observations_id_list = all_observations(pj) behaviors = [pj[ETHOGRAM][k]["code"] for k in utilities.sorted_keys(pj[ETHOGRAM])] subjects = [pj[SUBJECTS][k]["name"] for k in utilities.sorted_keys(pj[SUBJECTS])] + [NO_FOCAL_SUBJECT] @@ -319,18 +323,23 @@ def cleanhtml(raw_html): if len(args.command) > 2: include_modifiers = "TRUE" in args.command[2].upper() - plot_format = "png" + exclude_behaviors = True if len(args.command) > 3: - plot_format = args.command[3].lower() + exclude_behaviors = False if "FALSE" in args.command[3].upper() else True + + plot_format = "png" + if len(args.command) > 4: + plot_format = args.command[4].lower() plot_events.create_events_plot2_new(pj, observations_id_list, - subjects, - behaviors, - True, - TIME_FULL_OBS, - 0, 0, + {"selected subjects": subjects, + "selected behaviors": behaviors, + "include modifiers": include_modifiers, + "exclude behaviors": exclude_behaviors, + "time": TIME_FULL_OBS, + "start time": 0, "end time": 0}, plot_colors=BEHAVIORS_PLOT_COLORS, plot_directory=export_dir, file_format=plot_format) diff --git a/boris_ui.py b/boris_ui.py index 56fdc0b7..832be4fb 100644 --- a/boris_ui.py +++ b/boris_ui.py @@ -449,6 +449,8 @@ def setupUi(self, MainWindow): self.action_obs_list.setObjectName(_fromUtf8("action_obs_list")) self.actionTest = QtGui.QAction(MainWindow) self.actionTest.setObjectName(_fromUtf8("actionTest")) + self.actionTest_stb2 = QtGui.QAction(MainWindow) + self.actionTest_stb2.setObjectName(_fromUtf8("actionTest_stb2")) self.menuHelp.addAction(self.actionUser_guide) self.menuHelp.addAction(self.actionCheckUpdate) self.menuHelp.addSeparator() @@ -514,6 +516,7 @@ def setupUi(self, MainWindow): self.menuAnalyze.addAction(self.actionTime_budget_by_behaviors_category) self.menuAnalyze.addAction(self.menuPlot_events.menuAction()) self.menuAnalyze.addAction(self.menuInter_rater_reliability.menuAction()) + self.menuAnalyze.addAction(self.actionTest_stb2) self.menuZoom1.addAction(self.actionZoom1_fitwindow) self.menuZoom1.addAction(self.actionZoom1_1_4) self.menuZoom1.addAction(self.actionZoom1_1_2) @@ -755,4 +758,5 @@ def retranslateUi(self, MainWindow): self.action_obs_list.setText(_translate("MainWindow", "Obs list", None)) self.action_obs_list.setToolTip(_translate("MainWindow", "Observations list", None)) self.actionTest.setText(_translate("MainWindow", "test", None)) + self.actionTest_stb2.setText(_translate("MainWindow", "test stb2", None)) diff --git a/boris_ui5.py b/boris_ui5.py index d97814c8..1fb6b530 100644 --- a/boris_ui5.py +++ b/boris_ui5.py @@ -435,6 +435,8 @@ def setupUi(self, MainWindow): self.action_obs_list.setObjectName("action_obs_list") self.actionTest = QtWidgets.QAction(MainWindow) self.actionTest.setObjectName("actionTest") + self.actionTest_stb2 = QtWidgets.QAction(MainWindow) + self.actionTest_stb2.setObjectName("actionTest_stb2") self.menuHelp.addAction(self.actionUser_guide) self.menuHelp.addAction(self.actionCheckUpdate) self.menuHelp.addSeparator() @@ -500,6 +502,7 @@ def setupUi(self, MainWindow): self.menuAnalyze.addAction(self.actionTime_budget_by_behaviors_category) self.menuAnalyze.addAction(self.menuPlot_events.menuAction()) self.menuAnalyze.addAction(self.menuInter_rater_reliability.menuAction()) + self.menuAnalyze.addAction(self.actionTest_stb2) self.menuZoom1.addAction(self.actionZoom1_fitwindow) self.menuZoom1.addAction(self.actionZoom1_1_4) self.menuZoom1.addAction(self.actionZoom1_1_2) @@ -742,4 +745,5 @@ def retranslateUi(self, MainWindow): self.action_obs_list.setText(_translate("MainWindow", "Obs list")) self.action_obs_list.setToolTip(_translate("MainWindow", "Observations list")) self.actionTest.setText(_translate("MainWindow", "test")) + self.actionTest_stb2.setText(_translate("MainWindow", "test stb2")) diff --git a/db_functions.py b/db_functions.py index e5499026..ec970460 100644 --- a/db_functions.py +++ b/db_functions.py @@ -26,6 +26,8 @@ from config import * import project_functions +import time + def load_events_in_db(pj, selectedSubjects, selectedObservations, selectedBehaviors): """ @@ -65,6 +67,10 @@ def load_events_in_db(pj, selectedSubjects, selectedObservations, selectedBehavi modifiers TEXT, occurence FLOAT, comment TEXT)""") + cursor.execute("CREATE INDEX observation_idx ON events(observation)") + cursor.execute("CREATE INDEX subject_idx ON events(subject)") + cursor.execute("CREATE INDEX code_idx ON events(code)") + cursor.execute("CREATE INDEX modifiers_idx ON events(modifiers)") for subject_to_analyze in selectedSubjects: @@ -121,7 +127,7 @@ def load_aggregated_events_in_db(pj, selectedSubjects, selectedObservations, sel # if no behavior selected select all if not selectedBehaviors: - selectedBehaviors = sorted([pj[ETHOGRAM][x]["code"] for x in pj[ETHOGRAM]]) + selectedBehaviors = sorted([pj[ETHOGRAM][x][BEHAVIOR_CODE] for x in pj[ETHOGRAM]]) # check if state events are paired out = "" @@ -135,16 +141,14 @@ def load_aggregated_events_in_db(pj, selectedSubjects, selectedObservations, sel return False, out, None # selected behaviors defined as state event - state_behaviors_codes = [pj[ETHOGRAM][x]["code"] for x in pj[ETHOGRAM] + state_behaviors_codes = [pj[ETHOGRAM][x][BEHAVIOR_CODE] for x in pj[ETHOGRAM] if STATE in pj[ETHOGRAM][x][TYPE].upper() - and pj[ETHOGRAM][x]["code"] in selectedBehaviors] + and pj[ETHOGRAM][x][BEHAVIOR_CODE] in selectedBehaviors] # selected behaviors defined as point event - point_behaviors_codes = [pj[ETHOGRAM][x]["code"] for x in pj[ETHOGRAM] + point_behaviors_codes = [pj[ETHOGRAM][x][BEHAVIOR_CODE] for x in pj[ETHOGRAM] if POINT in pj[ETHOGRAM][x][TYPE].upper() - and pj[ETHOGRAM][x]["code"] in selectedBehaviors] - - cursor1 = load_events_in_db(pj, selectedSubjects, selectedObservations, selectedBehaviors) + and pj[ETHOGRAM][x][BEHAVIOR_CODE] in selectedBehaviors] db = sqlite3.connect(":memory:") db.row_factory = sqlite3.Row @@ -161,25 +165,34 @@ def load_aggregated_events_in_db(pj, selectedSubjects, selectedObservations, sel comment TEXT, comment_stop TEXT)""") + + cursor2.execute("CREATE INDEX observation_idx ON aggregated_events(observation)") + cursor2.execute("CREATE INDEX subject_idx ON aggregated_events(subject)") + cursor2.execute("CREATE INDEX behavior_idx ON aggregated_events(behavior)") + cursor2.execute("CREATE INDEX modifiers_idx ON aggregated_events(modifiers)") + + for obsId in selectedObservations: + + cursor1 = load_events_in_db(pj, selectedSubjects, [obsId], selectedBehaviors) + for subject in selectedSubjects: for behavior in selectedBehaviors: - cursor1.execute("select distinct modifiers from events where observation=? AND subject=? AND code=? order by modifiers", + cursor1.execute("SELECT DISTINCT modifiers FROM events WHERE observation=? AND subject=? AND code=? ORDER BY modifiers", (obsId, subject, behavior,)) rows_distinct_modifiers = list(x[0].strip() for x in cursor1.fetchall()) for distinct_modifiers in rows_distinct_modifiers: - + cursor1.execute(("SELECT occurence, comment FROM events " "WHERE observation = ? AND subject = ? AND code = ? AND modifiers = ? ORDER by occurence"), (obsId, subject, behavior, distinct_modifiers)) rows = list(cursor1.fetchall()) - + for idx, row in enumerate(rows): if behavior in point_behaviors_codes: - cursor2.execute(("INSERT INTO aggregated_events (observation, subject, behavior, type, modifiers, " " start, stop, comment, comment_stop) " "VALUES (?,?,?,?,?,?,?,?,?)"), @@ -194,7 +207,9 @@ def load_aggregated_events_in_db(pj, selectedSubjects, selectedObservations, sel (obsId, subject, behavior, STATE, distinct_modifiers, row["occurence"], rows[idx + 1]["occurence"], row["comment"], rows[idx + 1]["comment"])) + db.commit() + return True, "", db diff --git a/plot_events.py b/plot_events.py index 02bb6761..6d083f36 100644 --- a/plot_events.py +++ b/plot_events.py @@ -515,17 +515,19 @@ def on_draw(event): def create_events_plot2_new(pj, selected_observations, - selected_subjects, - selected_behaviors, - include_modifiers, - interval, - start_time, - end_time, + 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"] + 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, @@ -557,6 +559,7 @@ def create_events_plot2_new(pj, init = dt.datetime(2017, 1, 1) for obs_id in selected_observations: + print(obs_id) if len(selected_subjects) > 1: fig, axs = plt.subplots(figsize=(20, 8), nrows=len(selected_subjects), ncols=1, sharex=True) @@ -566,9 +569,29 @@ def create_events_plot2_new(pj, 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]) @@ -597,13 +620,26 @@ def create_events_plot2_new(pj, (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: @@ -620,7 +656,7 @@ def create_events_plot2_new(pj, "WHERE observation = ? AND subject = ? AND behavior = ? AND modifiers = ?"), (obs_id, subject, behavior, modifiers,)) for row in cursor.fetchall(): - print(behavior_modifiers_str, row["start"],row["stop"]) + #print(behavior_modifiers_str, row["start"],row["stop"]) bars[behavior_modifiers_str].append((row["start"],row["stop"])) start_date = matplotlib.dates.date2num(init + dt.timedelta(seconds=row["start"])) @@ -635,7 +671,7 @@ def create_events_plot2_new(pj, align="center", edgecolor=bar_color, color=bar_color, alpha = 1) i += 1 - axs[ax_idx].set_ylim(ymin=0, ymax = (max_len * par1) + par1 + 1) + axs[ax_idx].set_ylim(ymin=0, ymax = (max_len * par1) + par1 ) pos = np.arange(par1, max_len * par1 + par1 + 1, par1) axs[ax_idx].set_yticks(pos[:len(ylabels)]) diff --git a/time_budget_functions.py b/time_budget_functions.py index 5ed488da..09da5850 100644 --- a/time_budget_functions.py +++ b/time_budget_functions.py @@ -26,6 +26,8 @@ import db_functions import project_functions +import time + def default_value(ethogram, behav, param): """ return value for duration in case of point event @@ -84,23 +86,28 @@ def finalize(self): def synthetic_time_budget(pj, selected_observations, - selected_subjects, - selected_behaviors, - include_modifiers, - interval, - start_time, - end_time): + parameters_obs + ): + + + selected_subjects = parameters_obs["selected subjects"] + selected_behaviors = parameters_obs["selected behaviors"] + include_modifiers = parameters_obs["include modifiers"] + interval = parameters_obs["time"] + start_time = parameters_obs["start time"] + end_time = parameters_obs["end time"] parameters = [["duration", "Total duration"], ["number", "Number of occurrences"], ["duration mean", "Duration mean"], ["duration stdev", "Duration std dev"], - ["proportion of time", "Proportion o time"], + ["proportion of time", "Proportion of time"], ] data_report = tablib.Dataset() data_report.title = "Synthetic time budget" + ok, msg, db_connector = db_functions.load_aggregated_events_in_db(pj, selected_subjects, selected_observations, @@ -122,6 +129,7 @@ def synthetic_time_budget(pj, distinct_behav_modif = [[rows["behavior"], ""] for rows in cursor.fetchall()] # add selected behaviors that are not observed + #if not parameters_obs["exclude behaviors"]: for behav in selected_behaviors: if [x for x in distinct_behav_modif if x[0] == behav] == []: distinct_behav_modif.append([behav, "-"]) @@ -145,6 +153,12 @@ def synthetic_time_budget(pj, modif_header.append(modifiers) param_header.append(param[1]) + ''' + if parameters_obs["group observations"]: + cursor.execute("UPDATE aggregated_events SET observation = 'all' " ) + #selected_observations = ["all"] + ''' + data_report.append(subj_header) data_report.append(behav_header) if include_modifiers: @@ -154,6 +168,18 @@ def synthetic_time_budget(pj, # select time interval for obs_id in selected_observations: + '''if not parameters_obs["group observations"]:''' + ok, msg, db_connector = db_functions.load_aggregated_events_in_db(pj, + selected_subjects, + [obs_id], + selected_behaviors) + + if not ok: + return False, msg, None + + db_connector.create_aggregate("stdev", 1, StdevFunc) + cursor = db_connector.cursor() + # if modifiers not to be included set modifiers to "" if not include_modifiers: cursor.execute("UPDATE aggregated_events SET modifiers = ''") @@ -180,6 +206,8 @@ def synthetic_time_budget(pj, if interval == TIME_ARBITRARY_INTERVAL: min_time = float(start_time) max_time = float(end_time) + + #duration = end_time - start_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, )) @@ -194,40 +222,19 @@ def synthetic_time_budget(pj, behavior, modifiers = behavior_modifiers behavior_modifiers_str = "|".join(behavior_modifiers) if modifiers else behavior - # total duration - cursor.execute(("SELECT SUM(stop-start) FROM aggregated_events " + + cursor.execute(("SELECT SUM(stop-start), COUNT(*), AVG(stop-start), stdev(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] - - # number of occurences - cursor.execute(("SELECT COUNT(*) 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]["number"] = 0 if row[0] is None else row[0] - - # mean duration - cursor.execute(("SELECT AVG(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 mean"] = 0 if row[0] is None else row[0] - - # std dev duration - cursor.execute(("SELECT stdev(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 stdev"] = 0 if row[0] is None else row[0] - - # % total duration - cursor.execute(("SELECT SUM(stop-start)/? FROM aggregated_events " - "WHERE observation = ? AND subject = ? AND behavior = ? AND modifiers = ?"), - (max_time - min_time, obs_id, subject, behavior, modifiers,)) - for row in cursor.fetchall(): - behaviors[subject][behavior_modifiers_str]["proportion of time"] = 0 if row[0] is None else row[0] + behaviors[subject][behavior_modifiers_str]["number"] = 0 if row[1] is None else row[1] + behaviors[subject][behavior_modifiers_str]["duration mean"] = 0 if row[2] is None else row[2] + behaviors[subject][behavior_modifiers_str]["duration stdev"] = 0 if row[3] is None else row[3] + behaviors[subject][behavior_modifiers_str]["proportion of time"] = 0 if row[0] is None else row[0]/(max_time - min_time) columns = [obs_id, "{:0.3f}".format(max_time - min_time)] for subj in selected_subjects: @@ -239,7 +246,7 @@ def synthetic_time_budget(pj, columns.append(behaviors[subj][behavior_modifiers_str][param[0]]) data_report.append(columns) - + return True, msg, data_report