boris-behav-obs 9.7.7__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (109) hide show
  1. boris/__init__.py +26 -0
  2. boris/__main__.py +25 -0
  3. boris/about.py +143 -0
  4. boris/add_modifier.py +635 -0
  5. boris/add_modifier_ui.py +303 -0
  6. boris/advanced_event_filtering.py +455 -0
  7. boris/analysis_plugins/__init__.py +0 -0
  8. boris/analysis_plugins/_latency.py +59 -0
  9. boris/analysis_plugins/irr_cohen_kappa.py +109 -0
  10. boris/analysis_plugins/irr_cohen_kappa_with_modifiers.py +112 -0
  11. boris/analysis_plugins/irr_weighted_cohen_kappa.py +157 -0
  12. boris/analysis_plugins/irr_weighted_cohen_kappa_with_modifiers.py +162 -0
  13. boris/analysis_plugins/list_of_dataframe_columns.py +22 -0
  14. boris/analysis_plugins/number_of_occurences.py +22 -0
  15. boris/analysis_plugins/number_of_occurences_by_independent_variable.py +54 -0
  16. boris/analysis_plugins/time_budget.py +61 -0
  17. boris/behav_coding_map_creator.py +1110 -0
  18. boris/behavior_binary_table.py +305 -0
  19. boris/behaviors_coding_map.py +239 -0
  20. boris/boris_cli.py +340 -0
  21. boris/cmd_arguments.py +49 -0
  22. boris/coding_pad.py +280 -0
  23. boris/config.py +785 -0
  24. boris/config_file.py +356 -0
  25. boris/connections.py +409 -0
  26. boris/converters.py +333 -0
  27. boris/converters_ui.py +225 -0
  28. boris/cooccurence.py +250 -0
  29. boris/core.py +5901 -0
  30. boris/core_qrc.py +15958 -0
  31. boris/core_ui.py +1107 -0
  32. boris/db_functions.py +324 -0
  33. boris/dev.py +134 -0
  34. boris/dialog.py +1108 -0
  35. boris/duration_widget.py +238 -0
  36. boris/edit_event.py +245 -0
  37. boris/edit_event_ui.py +233 -0
  38. boris/event_operations.py +1040 -0
  39. boris/events_cursor.py +61 -0
  40. boris/events_snapshots.py +596 -0
  41. boris/exclusion_matrix.py +141 -0
  42. boris/export_events.py +1006 -0
  43. boris/export_observation.py +1203 -0
  44. boris/external_processes.py +332 -0
  45. boris/geometric_measurement.py +941 -0
  46. boris/gui_utilities.py +135 -0
  47. boris/image_overlay.py +72 -0
  48. boris/import_observations.py +242 -0
  49. boris/ipc_mpv.py +325 -0
  50. boris/irr.py +634 -0
  51. boris/latency.py +244 -0
  52. boris/measurement_widget.py +161 -0
  53. boris/media_file.py +115 -0
  54. boris/menu_options.py +213 -0
  55. boris/modifier_coding_map_creator.py +1013 -0
  56. boris/modifiers_coding_map.py +157 -0
  57. boris/mpv.py +2016 -0
  58. boris/mpv2.py +2193 -0
  59. boris/observation.py +1453 -0
  60. boris/observation_operations.py +2538 -0
  61. boris/observation_ui.py +679 -0
  62. boris/observations_list.py +337 -0
  63. boris/otx_parser.py +442 -0
  64. boris/param_panel.py +201 -0
  65. boris/param_panel_ui.py +305 -0
  66. boris/player_dock_widget.py +198 -0
  67. boris/plot_data_module.py +536 -0
  68. boris/plot_events.py +634 -0
  69. boris/plot_events_rt.py +237 -0
  70. boris/plot_spectrogram_rt.py +316 -0
  71. boris/plot_waveform_rt.py +230 -0
  72. boris/plugins.py +431 -0
  73. boris/portion/__init__.py +31 -0
  74. boris/portion/const.py +95 -0
  75. boris/portion/dict.py +365 -0
  76. boris/portion/func.py +52 -0
  77. boris/portion/interval.py +581 -0
  78. boris/portion/io.py +181 -0
  79. boris/preferences.py +510 -0
  80. boris/preferences_ui.py +770 -0
  81. boris/project.py +2007 -0
  82. boris/project_functions.py +2041 -0
  83. boris/project_import_export.py +1096 -0
  84. boris/project_ui.py +794 -0
  85. boris/qrc_boris.py +10389 -0
  86. boris/qrc_boris5.py +2579 -0
  87. boris/select_modifiers.py +312 -0
  88. boris/select_observations.py +210 -0
  89. boris/select_subj_behav.py +286 -0
  90. boris/state_events.py +197 -0
  91. boris/subjects_pad.py +106 -0
  92. boris/synthetic_time_budget.py +290 -0
  93. boris/time_budget_functions.py +1136 -0
  94. boris/time_budget_widget.py +1039 -0
  95. boris/transitions.py +365 -0
  96. boris/utilities.py +1810 -0
  97. boris/version.py +24 -0
  98. boris/video_equalizer.py +159 -0
  99. boris/video_equalizer_ui.py +248 -0
  100. boris/video_operations.py +310 -0
  101. boris/view_df.py +104 -0
  102. boris/view_df_ui.py +75 -0
  103. boris/write_event.py +538 -0
  104. boris_behav_obs-9.7.7.dist-info/METADATA +139 -0
  105. boris_behav_obs-9.7.7.dist-info/RECORD +109 -0
  106. boris_behav_obs-9.7.7.dist-info/WHEEL +5 -0
  107. boris_behav_obs-9.7.7.dist-info/entry_points.txt +2 -0
  108. boris_behav_obs-9.7.7.dist-info/licenses/LICENSE.TXT +674 -0
  109. boris_behav_obs-9.7.7.dist-info/top_level.txt +1 -0
boris/connections.py ADDED
@@ -0,0 +1,409 @@
1
+ """
2
+ BORIS
3
+ Behavioral Observation Research Interactive Software
4
+ Copyright 2012-2025 Olivier Friard
5
+
6
+ This program is free software; you can redistribute it and/or modify
7
+ it under the terms of the GNU General Public License as published by
8
+ the Free Software Foundation; either version 2 of the License, or
9
+ (at your option) any later version.
10
+
11
+ This program is distributed in the hope that it will be useful,
12
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ GNU General Public License for more details.
15
+
16
+ You should have received a copy of the GNU General Public License
17
+ along with this program; if not, write to the Free Software
18
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
+ MA 02110-1301, USA.
20
+ """
21
+
22
+ from PySide6.QtCore import Qt, QTimer
23
+ from PySide6.QtGui import QAction
24
+
25
+ from . import config as cfg
26
+ from . import (
27
+ about,
28
+ behav_coding_map_creator,
29
+ behavior_binary_table,
30
+ behaviors_coding_map,
31
+ coding_pad,
32
+ event_operations,
33
+ events_snapshots,
34
+ export_events,
35
+ geometric_measurement,
36
+ image_overlay,
37
+ import_observations,
38
+ irr,
39
+ latency,
40
+ cooccurence,
41
+ media_file,
42
+ observation_operations,
43
+ preferences,
44
+ project_import_export,
45
+ synthetic_time_budget,
46
+ time_budget_widget,
47
+ transitions,
48
+ video_equalizer,
49
+ video_operations,
50
+ project_functions,
51
+ external_processes,
52
+ )
53
+
54
+ from . import state_events as state_events
55
+
56
+
57
+ def connections(self):
58
+ """
59
+ create connections between widgets and functions
60
+ """
61
+
62
+ # menu file
63
+ self.actionNew_project.triggered.connect(lambda: self.edit_project(cfg.NEW))
64
+ self.actionOpen_project.triggered.connect(self.open_project_activated)
65
+ self.actionNoldus_Observer_template.triggered.connect(self.import_project_from_observer_template)
66
+ self.actionEdit_project.triggered.connect(self.edit_project_activated)
67
+ self.actionCheck_project.triggered.connect(self.check_project_integrity)
68
+ self.actionSave_project.triggered.connect(self.save_project_activated)
69
+ self.actionSave_project_as.triggered.connect(self.save_project_as_activated)
70
+ self.actionExport_project.triggered.connect(lambda: project_import_export.export_project_as_pickle_object(self.pj))
71
+ self.actionClose_project.triggered.connect(self.close_project)
72
+
73
+ self.action_media_file_and_images_directories_relative_path.triggered.connect(self.set_media_files_path_relative_to_project_dir)
74
+ self.action_data_files_relative_path.triggered.connect(self.set_data_files_path_relative_to_project_dir)
75
+
76
+ self.action_remove_media_files_and_images_directories_path.triggered.connect(self.remove_media_files_path)
77
+ self.action_remove_data_files_path.triggered.connect(self.remove_data_files_path)
78
+
79
+ self.menuCreate_subtitles_2.triggered.connect(self.create_subtitles)
80
+
81
+ self.actionPreferences.triggered.connect(lambda: preferences.preferences(self))
82
+
83
+ self.actionQuit.triggered.connect(self.actionQuit_activated)
84
+
85
+ # menu observations
86
+ self.actionNew_observation.triggered.connect(lambda: observation_operations.new_observation(self, mode=cfg.NEW, obsId=""))
87
+
88
+ self.actionOpen_observation.triggered.connect(lambda: observation_operations.open_observation(self, mode=cfg.OBS_START))
89
+ self.actionView_observation.triggered.connect(lambda: observation_operations.open_observation(self, mode=cfg.VIEW))
90
+ self.actionEdit_observation_2.triggered.connect(lambda: observation_operations.edit_observation(self))
91
+ self.actionObservationsList.triggered.connect(lambda: observation_operations.observations_list(self))
92
+
93
+ self.actionClose_observation.triggered.connect(lambda: observation_operations.close_observation(self))
94
+
95
+ self.action_create_observations.triggered.connect(lambda: observation_operations.create_observations(self))
96
+ self.actionRemove_observations.triggered.connect(lambda: observation_operations.remove_observations(self))
97
+
98
+ self.actionAdd_event.triggered.connect(lambda: event_operations.add_event(self))
99
+ self.actionEdit_event.triggered.connect(lambda: event_operations.edit_event(self))
100
+ self.actionUndo.setEnabled(False)
101
+ self.actionUndo.triggered.connect(lambda: event_operations.undo_event_operation(self))
102
+ self.actionFilter_events.triggered.connect(lambda: event_operations.filter_events(self))
103
+ self.actionShow_all_events.triggered.connect(lambda: event_operations.show_all_events(self))
104
+
105
+ # twevent header
106
+ # self.actionConfigure_twEvents_columns.triggered.connect(self.configure_twevents_columns)
107
+
108
+ # tv_events header
109
+ self.actionConfigure_tvevents_columns.triggered.connect(self.configure_tvevents_columns)
110
+
111
+ self.actionExport_observations_list.triggered.connect(lambda: observation_operations.export_observations_list_clicked(self))
112
+
113
+ self.actionCheckStateEvents.triggered.connect(lambda: state_events.check_state_events(self, mode="all"))
114
+ self.actionCheckStateEventsSingleObs.triggered.connect(lambda: state_events.check_state_events(self, mode="current"))
115
+ self.actionClose_unpaired_events.triggered.connect(lambda: state_events.fix_unpaired_events(self))
116
+ self.actionAdd_frame_indexes.triggered.connect(lambda: event_operations.add_frame_indexes(self))
117
+
118
+ self.actionRunEventOutside.triggered.connect(self.run_event_outside)
119
+
120
+ self.actionSelect_observations.triggered.connect(lambda: event_operations.select_events_between_activated(self))
121
+
122
+ self.actionEdit_selected_events.triggered.connect(lambda: event_operations.edit_selected_events(self))
123
+ self.action_add_comment.triggered.connect(lambda: event_operations.add_comment(self))
124
+ self.actionEdit_event_time.triggered.connect(lambda: event_operations.edit_time_selected_events(self))
125
+
126
+ self.actionCopy_events.triggered.connect(lambda: event_operations.copy_selected_events(self))
127
+ self.actionPaste_events.triggered.connect(lambda: event_operations.paste_clipboard_to_events(self))
128
+
129
+ self.actionExplore_project.triggered.connect(lambda: project_functions.explore_project(self))
130
+ self.actionFind_events.triggered.connect(lambda: event_operations.find_events(self))
131
+ self.actionFind_replace_events.triggered.connect(lambda: event_operations.find_replace_events(self))
132
+ self.actionDelete_all_events.triggered.connect(lambda: event_operations.delete_all_events(self))
133
+ self.actionDelete_selected_events.triggered.connect(lambda: event_operations.delete_selected_events(self))
134
+
135
+ self.actionMedia_file_information.triggered.connect(lambda: media_file.get_info(self))
136
+
137
+ self.actionLoad_observations_file.triggered.connect(lambda: import_observations.import_observations(self))
138
+
139
+ self.actionExportEvents_2.triggered.connect(lambda: export_events.export_tabular_events(self, mode="tabular"))
140
+
141
+ # behavioral sequences
142
+ # self.actionExportEventString.triggered.connect(lambda: self.export_events_as_behavioral_sequences(timed=False))
143
+ self.actionseparated_subjects.triggered.connect(
144
+ lambda: export_events.export_events_as_behavioral_sequences(self, separated_subjects=True, timed=False)
145
+ )
146
+ self.actiongrouped_subjects.triggered.connect(
147
+ lambda: export_events.export_events_as_behavioral_sequences(self, separated_subjects=False, timed=False)
148
+ )
149
+
150
+ self.actionExport_aggregated_events.triggered.connect(lambda: export_events.export_aggregated_events(self))
151
+ self.actionExport_events_as_Praat_TextGrid.triggered.connect(lambda: export_events.export_events_as_textgrid(self))
152
+ self.actionJWatcher.triggered.connect(lambda: export_events.export_tabular_events(self, "jwatcher"))
153
+
154
+ self.actionExtract_events_from_media_files.triggered.connect(lambda: events_snapshots.extract_events(self))
155
+ self.actionExtract_frames_from_media_files.triggered.connect(lambda: events_snapshots.events_snapshots(self))
156
+
157
+ self.actionCohen_s_kappa.triggered.connect(lambda: irr.irr_cohen_kappa(self))
158
+ self.actionNeedleman_Wunsch.triggered.connect(lambda: irr.needleman_wunch(self))
159
+
160
+ self.actionAll_transitions.triggered.connect(lambda: transitions.transitions_matrix(self, "frequency"))
161
+ self.actionNumber_of_transitions.triggered.connect(lambda: transitions.transitions_matrix(self, "number"))
162
+
163
+ self.actionFrequencies_of_transitions_after_behaviors.triggered.connect(
164
+ lambda: transitions.transitions_matrix(self, "frequencies_after_behaviors")
165
+ )
166
+
167
+ # menu playback
168
+ self.actionJumpTo.triggered.connect(self.jump_to)
169
+ self.action_deinterlace.triggered.connect(lambda: video_operations.deinterlace(self))
170
+ self.action_change_time_offset_of_players.triggered.connect(lambda: video_operations.change_player_offset(self))
171
+ self.actionZoom_level.triggered.connect(lambda: video_operations.zoom_level(self))
172
+ self.actionRotate_current_video.triggered.connect(lambda: video_operations.rotate_displayed_video(self))
173
+
174
+ self.actionDisplay_subtitles.triggered.connect(lambda: video_operations.display_subtitles(self))
175
+ self.actionVideo_equalizer.triggered.connect(lambda: video_equalizer.video_equalizer_show(self))
176
+
177
+ # menu Tools
178
+ self.action_block_dockwidgets.triggered.connect(self.block_dockwidgets)
179
+
180
+ self.action_create_modifiers_coding_map.triggered.connect(self.modifiers_coding_map_creator)
181
+ self.action_create_behaviors_coding_map.triggered.connect(lambda: behav_coding_map_creator.behaviors_coding_map_creator(self))
182
+
183
+ self.actionShow_spectrogram.triggered.connect(lambda: self.show_plot_widget("spectrogram", warning=True))
184
+ self.actionShow_the_sound_waveform.triggered.connect(lambda: self.show_plot_widget("waveform", warning=True))
185
+ self.actionPlot_events_in_real_time.triggered.connect(lambda: self.show_plot_widget("plot_events", warning=False))
186
+
187
+ self.actionShow_data_files.triggered.connect(self.show_data_files)
188
+ self.action_geometric_measurements.triggered.connect(lambda: geometric_measurement.show_widget(self))
189
+
190
+ self.actionBehaviors_coding_map.triggered.connect(lambda: behaviors_coding_map.show_behaviors_coding_map(self))
191
+
192
+ self.actionCoding_pad.triggered.connect(lambda: coding_pad.show_coding_pad(self))
193
+ self.actionSubjects_pad.triggered.connect(self.show_subjects_pad)
194
+
195
+ # image overlay on video
196
+ self.actionAdd_image_overlay_on_video.triggered.connect(lambda: image_overlay.add_image_overlay(self))
197
+ self.actionRemove_image_overlay.triggered.connect(lambda: image_overlay.remove_image_overlay(self))
198
+
199
+ self.actionMedia_file_information_2.triggered.connect(lambda: media_file.get_info(self))
200
+ self.actionRecode_resize_video.triggered.connect(lambda: external_processes.ffmpeg_process(self, "reencode_resize"))
201
+ self.actionRotate_video.triggered.connect(lambda: external_processes.ffmpeg_process(self, "rotate"))
202
+ self.actionMerge_media_files.triggered.connect(lambda: external_processes.ffmpeg_process(self, "merge"))
203
+ self.actionCreate_video_spectrogram.triggered.connect(lambda: external_processes.ffmpeg_process(self, "video_spectrogram"))
204
+
205
+ self.actionCreate_transitions_flow_diagram.triggered.connect(transitions.transitions_dot_script)
206
+ self.actionCreate_transitions_flow_diagram_2.triggered.connect(transitions.transitions_flow_diagram)
207
+
208
+ # menu Analysis
209
+
210
+ self.actionTime_budget.triggered.connect(lambda: time_budget_widget.time_budget(self, mode="by_behavior"))
211
+ self.actionTime_budget_by_behaviors_category.triggered.connect(lambda: time_budget_widget.time_budget(self, mode="by_category"))
212
+
213
+ self.actionTime_budget_report.triggered.connect(lambda: synthetic_time_budget.synthetic_time_budget(self))
214
+ self.actionSynthetic_binned_time_budget.triggered.connect(lambda: synthetic_time_budget.synthetic_binned_time_budget(self))
215
+
216
+ self.actionBehavior_bar_plot.triggered.connect(lambda: self.behaviors_bar_plot(mode="list"))
217
+ self.actionBehavior_bar_plot.setVisible(True)
218
+
219
+ self.actionPlot_events1.setVisible(False)
220
+ self.actionPlot_events2.triggered.connect(lambda: self.plot_events_triggered(mode="list"))
221
+
222
+ self.action_behavior_binary_table.triggered.connect(lambda: behavior_binary_table.behavior_binary_table(self))
223
+
224
+ self.action_advanced_event_filtering.triggered.connect(self.advanced_event_filtering)
225
+
226
+ self.action_latency.triggered.connect(lambda: latency.get_latency(self))
227
+
228
+ self.action_cooccurence.triggered.connect(lambda: cooccurence.get_cooccurence(self))
229
+
230
+ # menu Help
231
+ self.actionUser_guide.triggered.connect(self.actionUser_guide_triggered)
232
+ self.actionAbout.triggered.connect(lambda: about.actionAbout_activated(self))
233
+ self.actionCheckUpdate.triggered.connect(self.actionCheckUpdate_activated)
234
+
235
+ # toolbar
236
+ self.action_obs_list.triggered.connect(lambda: observation_operations.observations_list(self))
237
+ self.actionPlay.triggered.connect(self.play_activated)
238
+ self.actionReset.triggered.connect(self.reset_activated)
239
+ self.actionJumpBackward.triggered.connect(self.jumpBackward_activated)
240
+ self.actionJumpForward.triggered.connect(self.jumpForward_activated)
241
+
242
+ self.actionFaster.triggered.connect(lambda: video_operations.video_faster_activated(self))
243
+ self.actionSlower.triggered.connect(lambda: video_operations.video_slower_activated(self))
244
+ self.actionNormalSpeed.triggered.connect(lambda: video_operations.video_normalspeed_activated(self))
245
+
246
+ self.actionPrevious.triggered.connect(self.previous_media_file)
247
+ self.actionNext.triggered.connect(self.next_media_file)
248
+
249
+ self.actionSnapshot.triggered.connect(lambda: video_operations.snapshot(self))
250
+
251
+ self.actionFrame_backward.triggered.connect(self.previous_frame)
252
+ self.actionFrame_forward.triggered.connect(self.next_frame)
253
+
254
+ self.actionCloseObs.triggered.connect(lambda: observation_operations.close_observation(self))
255
+ self.actionCurrent_Time_Budget.triggered.connect(lambda: time_budget_widget.time_budget(self, mode="by_behavior", mode2="current"))
256
+ self.actionPlot_current_observation.triggered.connect(lambda: self.plot_events_triggered(mode="current"))
257
+
258
+ self.actionPlot_current_time_budget.triggered.connect(lambda: self.behaviors_bar_plot(mode="current"))
259
+
260
+ self.actionFind_in_current_obs.triggered.connect(lambda: event_operations.find_events(self))
261
+
262
+ # table Widget double click
263
+ # self.twEvents.itemDoubleClicked.connect(self.twEvents_doubleClicked)
264
+ self.twEthogram.itemDoubleClicked.connect(self.twEthogram_doubleClicked)
265
+ self.twSubjects.itemDoubleClicked.connect(self.twSubjects_doubleClicked)
266
+
267
+ # events tableview
268
+ self.tv_events.doubleClicked.connect(self.tv_events_doubleClicked)
269
+
270
+ # Actions for twEthogram context menu
271
+ self.twEthogram.setContextMenuPolicy(Qt.ActionsContextMenu)
272
+ self.twEthogram.horizontalHeader().sortIndicatorChanged.connect(self.twEthogram_sorted)
273
+
274
+ self.actionViewBehavior.triggered.connect(self.view_behavior)
275
+ self.twEthogram.addAction(self.actionViewBehavior)
276
+
277
+ self.actionFilterBehaviors.triggered.connect(
278
+ lambda: self.filter_behaviors(table=cfg.ETHOGRAM, behavior_type=cfg.STATE_EVENT_TYPES + cfg.POINT_EVENT_TYPES)
279
+ )
280
+ self.twEthogram.addAction(self.actionFilterBehaviors)
281
+
282
+ self.actionShowAllBehaviors.triggered.connect(self.show_all_behaviors)
283
+ self.twEthogram.addAction(self.actionShowAllBehaviors)
284
+
285
+ # Actions for twSubjects context menu
286
+ self.twSubjects.setContextMenuPolicy(Qt.ActionsContextMenu)
287
+ self.twSubjects.horizontalHeader().sortIndicatorChanged.connect(self.sort_twSubjects)
288
+ self.actionFilterSubjects.triggered.connect(self.filter_subjects)
289
+ self.twSubjects.addAction(self.actionFilterSubjects)
290
+
291
+ self.actionShowAllSubjects.triggered.connect(self.show_all_subjects)
292
+ self.twSubjects.addAction(self.actionShowAllSubjects)
293
+
294
+ # actions for twEvents horizontal header menu
295
+ # tw_headers = self.twEvents.horizontalHeader()
296
+ # tw_headers.setContextMenuPolicy(Qt.ActionsContextMenu)
297
+ # tw_headers.addAction(self.actionConfigure_twEvents_columns)
298
+
299
+ tv_headers = self.tv_events.horizontalHeader()
300
+ tv_headers.setContextMenuPolicy(Qt.ActionsContextMenu)
301
+ tv_headers.addAction(self.actionConfigure_tvevents_columns)
302
+
303
+ # Actions for twEvents menu
304
+ # self.twEvents.setContextMenuPolicy(Qt.ActionsContextMenu)
305
+
306
+ # self.twEvents.addAction(self.actionAdd_event)
307
+ # self.twEvents.addAction(self.actionEdit_selected_events)
308
+ # self.twEvents.addAction(self.actionEdit_event_time)
309
+
310
+ # self.twEvents.addAction(self.actionCopy_events)
311
+ # self.twEvents.addAction(self.actionPaste_events)
312
+
313
+ # separator2 = QAction(self)
314
+ # separator2.setSeparator(True)
315
+ # self.twEvents.addAction(separator2)
316
+
317
+ # self.twEvents.addAction(self.actionFind_events)
318
+ # self.twEvents.addAction(self.actionFind_replace_events)
319
+
320
+ # separator2 = QAction(self)
321
+ # separator2.setSeparator(True)
322
+ # self.twEvents.addAction(separator2)
323
+
324
+ # self.twEvents.addAction(self.actionFilter_events)
325
+ # self.twEvents.addAction(self.actionShow_all_events)
326
+
327
+ # separator2 = QAction(self)
328
+ # separator2.setSeparator(True)
329
+ # self.twEvents.addAction(separator2)
330
+
331
+ # self.twEvents.addAction(self.actionCheckStateEventsSingleObs)
332
+ # self.twEvents.addAction(self.actionClose_unpaired_events)
333
+
334
+ # self.twEvents.addAction(self.actionRunEventOutside)
335
+
336
+ # separator2 = QAction(self)
337
+ # separator2.setSeparator(True)
338
+ # self.twEvents.addAction(separator2)
339
+
340
+ # self.twEvents.addAction(self.actionDelete_selected_events)
341
+
342
+ # Actions for tv_events menu
343
+ self.tv_events.setContextMenuPolicy(Qt.ActionsContextMenu)
344
+
345
+ self.tv_events.addAction(self.actionAdd_event)
346
+ self.tv_events.addAction(self.actionEdit_selected_events)
347
+ self.tv_events.addAction(self.action_add_comment)
348
+
349
+ self.tv_events.addAction(self.actionEdit_event_time)
350
+
351
+ self.tv_events.addAction(self.actionCopy_events)
352
+ self.tv_events.addAction(self.actionPaste_events)
353
+
354
+ separator2 = QAction(self)
355
+ separator2.setSeparator(True)
356
+ self.tv_events.addAction(separator2)
357
+
358
+ self.tv_events.addAction(self.actionFind_events)
359
+ self.tv_events.addAction(self.actionFind_replace_events)
360
+
361
+ separator2 = QAction(self)
362
+ separator2.setSeparator(True)
363
+ self.tv_events.addAction(separator2)
364
+
365
+ self.tv_events.addAction(self.actionFilter_events)
366
+ self.tv_events.addAction(self.actionShow_all_events)
367
+
368
+ separator2 = QAction(self)
369
+ separator2.setSeparator(True)
370
+ self.tv_events.addAction(separator2)
371
+
372
+ self.tv_events.addAction(self.actionCheckStateEventsSingleObs)
373
+ self.tv_events.addAction(self.actionClose_unpaired_events)
374
+
375
+ self.tv_events.addAction(self.actionAdd_frame_indexes)
376
+
377
+ self.tv_events.addAction(self.actionRunEventOutside)
378
+
379
+ separator2 = QAction(self)
380
+ separator2.setSeparator(True)
381
+ self.tv_events.addAction(separator2)
382
+
383
+ self.tv_events.addAction(self.actionDelete_selected_events)
384
+
385
+ # Actions for twSubjects context menu
386
+ self.actionDeselectCurrentSubject.triggered.connect(lambda: self.update_subject(""))
387
+
388
+ self.twSubjects.setContextMenuPolicy(Qt.ActionsContextMenu)
389
+ self.twSubjects.addAction(self.actionDeselectCurrentSubject)
390
+
391
+ # subjects
392
+
393
+ # timer for plot visualization
394
+ self.plot_timer = QTimer(self)
395
+ # TODO check value of interval
396
+ self.plot_timer.setInterval(cfg.SPECTRO_TIMER)
397
+ self.plot_timer.timeout.connect(self.plot_timer_out)
398
+
399
+ # timer for timing the live observation
400
+ self.liveTimer = QTimer(self)
401
+ self.liveTimer.timeout.connect(self.liveTimer_out)
402
+
403
+ # timer for automatic backup
404
+ self.automaticBackupTimer = QTimer(self)
405
+ self.automaticBackupTimer.timeout.connect(self.automatic_backup)
406
+ if self.automaticBackup:
407
+ self.automaticBackupTimer.start(self.automaticBackup * 60000)
408
+
409
+ self.pb_live_obs.clicked.connect(self.start_live_observation)