boris-behav-obs 9.3.4__tar.gz → 9.3.5__tar.gz

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 (121) hide show
  1. {boris_behav_obs-9.3.4/boris_behav_obs.egg-info → boris_behav_obs-9.3.5}/PKG-INFO +1 -1
  2. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/config.py +2 -0
  3. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/core.py +21 -103
  4. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/dialog.py +6 -6
  5. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/edit_event.py +47 -27
  6. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/edit_event_ui.py +69 -36
  7. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/event_operations.py +50 -57
  8. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/observation.py +1 -2
  9. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/observation_operations.py +16 -3
  10. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/project_functions.py +1 -1
  11. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/select_observations.py +7 -1
  12. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/state_events.py +1 -1
  13. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/version.py +2 -2
  14. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5/boris_behav_obs.egg-info}/PKG-INFO +1 -1
  15. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/pyproject.toml +2 -2
  16. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/LICENSE.TXT +0 -0
  17. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/MANIFEST.in +0 -0
  18. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/README.TXT +0 -0
  19. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/README.md +0 -0
  20. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/__init__.py +0 -0
  21. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/__main__.py +0 -0
  22. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/about.py +0 -0
  23. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/add_modifier.py +0 -0
  24. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/add_modifier_ui.py +0 -0
  25. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/advanced_event_filtering.py +0 -0
  26. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/analysis_plugins/__init__.py +0 -0
  27. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/analysis_plugins/_latency.py +0 -0
  28. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/analysis_plugins/number_of_occurences.py +0 -0
  29. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/analysis_plugins/number_of_occurences_by_independent_variable.py +0 -0
  30. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/analysis_plugins/time_budget.py +0 -0
  31. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/behav_coding_map_creator.py +0 -0
  32. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/behavior_binary_table.py +0 -0
  33. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/behaviors_coding_map.py +0 -0
  34. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/boris_cli.py +0 -0
  35. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/cmd_arguments.py +0 -0
  36. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/coding_pad.py +0 -0
  37. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/config_file.py +0 -0
  38. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/connections.py +0 -0
  39. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/converters.py +0 -0
  40. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/converters_ui.py +0 -0
  41. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/cooccurence.py +0 -0
  42. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/core_qrc.py +0 -0
  43. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/core_ui.py +0 -0
  44. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/db_functions.py +0 -0
  45. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/dev.py +0 -0
  46. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/duration_widget.py +0 -0
  47. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/events_cursor.py +0 -0
  48. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/events_snapshots.py +0 -0
  49. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/exclusion_matrix.py +0 -0
  50. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/export_events.py +0 -0
  51. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/export_observation.py +0 -0
  52. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/external_processes.py +0 -0
  53. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/geometric_measurement.py +0 -0
  54. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/gui_utilities.py +0 -0
  55. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/image_overlay.py +0 -0
  56. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/import_observations.py +0 -0
  57. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/irr.py +0 -0
  58. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/latency.py +0 -0
  59. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/measurement_widget.py +0 -0
  60. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/media_file.py +0 -0
  61. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/menu_options.py +0 -0
  62. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/modifier_coding_map_creator.py +0 -0
  63. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/modifiers_coding_map.py +0 -0
  64. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/mpv-1.0.3.py +0 -0
  65. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/mpv.py +0 -0
  66. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/mpv2.py +0 -0
  67. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/observation_ui.py +0 -0
  68. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/observations_list.py +0 -0
  69. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/otx_parser.py +0 -0
  70. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/param_panel.py +0 -0
  71. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/param_panel_ui.py +0 -0
  72. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/player_dock_widget.py +0 -0
  73. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/plot_data_module.py +0 -0
  74. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/plot_events.py +0 -0
  75. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/plot_events_rt.py +0 -0
  76. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/plot_spectrogram_rt.py +0 -0
  77. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/plot_waveform_rt.py +0 -0
  78. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/plugins.py +0 -0
  79. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/portion/__init__.py +0 -0
  80. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/portion/const.py +0 -0
  81. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/portion/dict.py +0 -0
  82. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/portion/func.py +0 -0
  83. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/portion/interval.py +0 -0
  84. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/portion/io.py +0 -0
  85. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/preferences.py +0 -0
  86. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/preferences_ui.py +0 -0
  87. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/project.py +0 -0
  88. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/project_import_export.py +0 -0
  89. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/project_ui.py +0 -0
  90. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/qrc_boris.py +0 -0
  91. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/qrc_boris5.py +0 -0
  92. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/select_modifiers.py +0 -0
  93. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/select_subj_behav.py +0 -0
  94. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/subjects_pad.py +0 -0
  95. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/synthetic_time_budget.py +0 -0
  96. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/time_budget_functions.py +0 -0
  97. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/time_budget_widget.py +0 -0
  98. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/transitions.py +0 -0
  99. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/utilities.py +0 -0
  100. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/video_equalizer.py +0 -0
  101. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/video_equalizer_ui.py +0 -0
  102. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/video_operations.py +0 -0
  103. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/view_df.py +0 -0
  104. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/view_df_ui.py +0 -0
  105. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris/write_event.py +0 -0
  106. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris_behav_obs.egg-info/SOURCES.txt +0 -0
  107. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris_behav_obs.egg-info/dependency_links.txt +0 -0
  108. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris_behav_obs.egg-info/entry_points.txt +0 -0
  109. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris_behav_obs.egg-info/requires.txt +0 -0
  110. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/boris_behav_obs.egg-info/top_level.txt +0 -0
  111. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/setup.cfg +0 -0
  112. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/tests/test_db_functions.py +0 -0
  113. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/tests/test_export_observation.py +0 -0
  114. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/tests/test_irr.py +0 -0
  115. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/tests/test_observation_gui.py +0 -0
  116. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/tests/test_otx_parser.py +0 -0
  117. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/tests/test_preferences_gui.py +0 -0
  118. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/tests/test_project_functions.py +0 -0
  119. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/tests/test_time_budget.py +0 -0
  120. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/tests/test_utilities.py +0 -0
  121. {boris_behav_obs-9.3.4 → boris_behav_obs-9.3.5}/tests/test_utilities2.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: boris-behav-obs
3
- Version: 9.3.4
3
+ Version: 9.3.5
4
4
  Summary: BORIS - Behavioral Observation Research Interactive Software
5
5
  Author-email: Olivier Friard <olivier.friard@unito.it>
6
6
  License-Expression: GPL-3.0-only
@@ -37,6 +37,7 @@ SECONDS_PER_DAY: int = 86_400
37
37
  HOUR_CUTOFF: int = 7 * 24
38
38
  DATE_CUTOFF: int = HOUR_CUTOFF * 60 * 60 # 1 week
39
39
 
40
+ # cutoff for displaying time in HH:MM:SS.zzz format
40
41
  SMART_TIME_CUTOFF_DEFAULT: int = 300
41
42
 
42
43
  # minimal project version for handling observations from images
@@ -218,6 +219,7 @@ OVERLAY = "video overlay"
218
219
 
219
220
 
220
221
  USE_EXIF_DATE = "use_exif_date"
222
+ SUBSTRACT_FIRST_EXIF_DATE = "substract_first_exif_date"
221
223
  TIME_LAPSE = "time_lapse_delay"
222
224
 
223
225
 
@@ -308,9 +308,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
308
308
  play_rate_step: float = 0.1
309
309
  currentSubject: str = "" # contains the current subject of observation
310
310
 
311
- # FFmpeg
312
- memx = -1
313
- memy = -1
311
+ # geometric measurements
314
312
  mem_player = -1
315
313
 
316
314
  # path for ffmpeg/ffmpeg.exe program
@@ -339,6 +337,10 @@ class MainWindow(QMainWindow, Ui_MainWindow):
339
337
 
340
338
  mem_hash_obs: int = 0
341
339
 
340
+ # variables for list of observations
341
+ data: list = []
342
+ not_paired: list = []
343
+
342
344
  '''
343
345
  def add_button_menu(self, data, menu_obj):
344
346
  """
@@ -1342,21 +1344,6 @@ class MainWindow(QMainWindow, Ui_MainWindow):
1342
1344
  self.pj[cfg.BEHAVIORS_CODING_MAP][idx] = dict(behav_coding_map)
1343
1345
  return
1344
1346
 
1345
- """
1346
- QMessageBox.critical(
1347
- None,
1348
- cfg.programName,
1349
- (
1350
- "The current project already contains a behaviors coding map "
1351
- f"with the same name (<b>{behav_coding_map['name']}</b>)"
1352
- ),
1353
- QMessageBox.Ok | QMessageBox.Default,
1354
- QMessageBox.NoButton,
1355
- )
1356
-
1357
- return
1358
- """
1359
-
1360
1347
  self.pj[cfg.BEHAVIORS_CODING_MAP].append(behav_coding_map)
1361
1348
  QMessageBox.information(
1362
1349
  self,
@@ -1526,7 +1513,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
1526
1513
  jt.setWindowTitle("Jump to specific time")
1527
1514
  jt.label.setText("Set the time")
1528
1515
 
1529
- if jt.exec_():
1516
+ if jt.exec():
1530
1517
  new_time = jt.time_widget.get_time()
1531
1518
  if new_time < 0:
1532
1519
  return
@@ -1704,7 +1691,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
1704
1691
  QMessageBox.critical(
1705
1692
  None,
1706
1693
  cfg.programName,
1707
- ("The picture directory was changed since the creation of observation."),
1694
+ ("The picture directory has changed since the creation of observation."),
1708
1695
  QMessageBox.Ok | QMessageBox.Default,
1709
1696
  QMessageBox.NoButton,
1710
1697
  )
@@ -1718,15 +1705,13 @@ class MainWindow(QMainWindow, Ui_MainWindow):
1718
1705
  # extract EXIF tag
1719
1706
  if self.pj[cfg.OBSERVATIONS][self.observationId].get(cfg.USE_EXIF_DATE, False):
1720
1707
  date_time_original = util.extract_exif_DateTimeOriginal(self.images_list[self.image_idx])
1708
+
1721
1709
  if date_time_original != -1:
1722
1710
  msg += f"<br>EXIF Date/Time Original: <b>{datetime.datetime.fromtimestamp(date_time_original):%Y-%m-%d %H:%M:%S}</b>"
1723
- else:
1724
- msg += "<br>EXIF Date/Time Original: <b>NA</b>"
1725
1711
 
1726
- if self.image_idx == 0 and date_time_original != -1:
1727
- self.image_time_ref = date_time_original
1712
+ if self.image_idx == 0:
1713
+ self.image_time_ref = date_time_original
1728
1714
 
1729
- if date_time_original != -1:
1730
1715
  if self.image_time_ref is not None:
1731
1716
  seconds_from_1st = date_time_original - self.image_time_ref
1732
1717
 
@@ -1736,6 +1721,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
1736
1721
  seconds_from_1st_formated = seconds_from_1st
1737
1722
 
1738
1723
  else:
1724
+ msg += "<br>EXIF Date/Time Original: <b>NA</b>"
1739
1725
  seconds_from_1st_formated = cfg.NA
1740
1726
 
1741
1727
  msg += f"<br>Time from 1st image: <b>{seconds_from_1st_formated}</b>"
@@ -2311,11 +2297,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
2311
2297
  self.tv_events.setModel(model)
2312
2298
 
2313
2299
  # column width
2314
- # https://doc.qt.io/qtforpython-5/PySide2/QtWidgets/QHeaderView.html#more
2315
- self.tv_events.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeToContents)
2316
-
2317
- # self.table.setSortingEnabled(True)
2318
- # self.table.sortByColumn(0, Qt.AscendingOrder)
2300
+ self.tv_events.horizontalHeader().setSectionResizeMode(QHeaderView.Interactive)
2319
2301
 
2320
2302
  def load_tw_events(self, obs_id) -> None:
2321
2303
  """
@@ -2343,76 +2325,6 @@ class MainWindow(QMainWindow, Ui_MainWindow):
2343
2325
 
2344
2326
  return
2345
2327
 
2346
- """
2347
- DISABLED tableview component is used
2348
-
2349
- logging.debug(f"begin load events from obs in tablewidget: {obs_id}")
2350
-
2351
- t1 = time.time()
2352
-
2353
- self.twEvents.clear()
2354
-
2355
- self.twEvents.setColumnCount(len(cfg.TW_EVENTS_FIELDS[self.playerType]))
2356
- self.twEvents.setHorizontalHeaderLabels([s.capitalize() for s in cfg.TW_EVENTS_FIELDS[self.playerType]])
2357
-
2358
- for idx, field in enumerate(cfg.TW_EVENTS_FIELDS[self.playerType]):
2359
- if field not in self.config_param.get(f"{self.playerType} tw fields", cfg.TW_EVENTS_FIELDS[self.playerType]):
2360
- self.twEvents.horizontalHeader().hideSection(idx)
2361
- else:
2362
- self.twEvents.horizontalHeader().showSection(idx)
2363
-
2364
- self.twEvents.setRowCount(len(self.pj[cfg.OBSERVATIONS][obs_id][cfg.EVENTS]))
2365
- if self.filtered_behaviors or self.filtered_subjects:
2366
- self.twEvents.setRowCount(0)
2367
- row = 0
2368
-
2369
- for event_idx, event in enumerate(self.pj[cfg.OBSERVATIONS][obs_id][cfg.EVENTS]):
2370
- if self.filtered_behaviors and event[cfg.PJ_OBS_FIELDS[self.playerType][cfg.BEHAVIOR_CODE]] not in self.filtered_behaviors:
2371
- continue
2372
-
2373
- if self.filtered_subjects and event[cfg.PJ_OBS_FIELDS[self.playerType][cfg.SUBJECT]] not in self.filtered_subjects:
2374
- continue
2375
-
2376
- if self.filtered_behaviors or self.filtered_subjects:
2377
- self.twEvents.insertRow(self.twEvents.rowCount())
2378
-
2379
- for field_type in cfg.TW_EVENTS_FIELDS[self.playerType]:
2380
- if field_type in cfg.PJ_EVENTS_FIELDS[self.playerType]:
2381
- field = event_operations.read_event_field(event, self.playerType, field_type)
2382
-
2383
- if field_type == cfg.TIME:
2384
- item = QTableWidgetItem(str(util.convertTime(self.timeFormat, field)))
2385
-
2386
- # add index of project events
2387
- item.setData(Qt.UserRole, event_idx)
2388
- self.twEvents.setItem(row, cfg.TW_OBS_FIELD[self.playerType][field_type], item)
2389
- continue
2390
-
2391
- if field_type in (cfg.IMAGE_INDEX, cfg.FRAME_INDEX):
2392
- field = str(field)
2393
-
2394
- self.twEvents.setItem(
2395
- row,
2396
- cfg.TW_OBS_FIELD[self.playerType][field_type],
2397
- QTableWidgetItem(field),
2398
- )
2399
-
2400
- else:
2401
- self.twEvents.setItem(
2402
- row,
2403
- cfg.TW_OBS_FIELD[self.playerType][field_type],
2404
- QTableWidgetItem(""),
2405
- )
2406
-
2407
- row += 1
2408
-
2409
- self.update_events_start_stop()
2410
-
2411
- print("load twevent:", time.time() - t1)
2412
-
2413
- logging.debug("end load events from obs")
2414
- """
2415
-
2416
2328
  def close_tool_windows(self):
2417
2329
  """
2418
2330
  close tool windows:
@@ -3493,7 +3405,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
3493
3405
  return
3494
3406
 
3495
3407
  logging.debug(
3496
- f"{self.config_param[cfg.CHECK_PROJECT_INTEGRITY] if cfg.CHECK_PROJECT_INTEGRITY in self.config_param else "Check project integrity config NOT FOUND"=}"
3408
+ f"{self.config_param[cfg.CHECK_PROJECT_INTEGRITY] if cfg.CHECK_PROJECT_INTEGRITY in self.config_param else 'Check project integrity config NOT FOUND'=}"
3497
3409
  )
3498
3410
 
3499
3411
  if self.config_param.get(cfg.CHECK_PROJECT_INTEGRITY, True):
@@ -4707,7 +4619,10 @@ class MainWindow(QMainWindow, Ui_MainWindow):
4707
4619
  self.pj[cfg.OBSERVATIONS][self.observationId].get(cfg.USE_EXIF_DATE, False)
4708
4620
  and util.extract_exif_DateTimeOriginal(self.images_list[self.image_idx]) != -1
4709
4621
  ):
4710
- time_ = util.extract_exif_DateTimeOriginal(self.images_list[self.image_idx]) - self.image_time_ref
4622
+ time_ = util.extract_exif_DateTimeOriginal(self.images_list[self.image_idx])
4623
+ # check if first value must be substracted
4624
+ if self.pj[cfg.OBSERVATIONS][self.observationId].get(cfg.SUBSTRACT_FIRST_EXIF_DATE, True):
4625
+ time_ -= self.image_time_ref
4711
4626
 
4712
4627
  elif self.pj[cfg.OBSERVATIONS][self.observationId].get(cfg.TIME_LAPSE, 0):
4713
4628
  time_ = (self.image_idx + 1) * self.pj[cfg.OBSERVATIONS][self.observationId].get(cfg.TIME_LAPSE, 0)
@@ -4765,7 +4680,10 @@ class MainWindow(QMainWindow, Ui_MainWindow):
4765
4680
  self.pj[cfg.OBSERVATIONS][self.observationId].get(cfg.USE_EXIF_DATE, False)
4766
4681
  and util.extract_exif_DateTimeOriginal(self.images_list[self.image_idx]) != -1
4767
4682
  ):
4768
- time_ = util.extract_exif_DateTimeOriginal(self.images_list[self.image_idx]) - self.image_time_ref
4683
+ time_ = util.extract_exif_DateTimeOriginal(self.images_list[self.image_idx])
4684
+ # check if first value must be substracte
4685
+ if self.pj[cfg.OBSERVATIONS][self.observationId].get(cfg.SUBSTRACT_FIRST_EXIF_DATE, True):
4686
+ time_ -= self.image_time_ref
4769
4687
 
4770
4688
  elif self.pj[cfg.OBSERVATIONS][self.observationId].get(cfg.TIME_LAPSE, 0):
4771
4689
  time_ = (self.image_idx + 1) * self.pj[cfg.OBSERVATIONS][self.observationId].get(cfg.TIME_LAPSE, 0)
@@ -20,9 +20,8 @@ This file is part of BORIS.
20
20
 
21
21
  """
22
22
 
23
- from decimal import Decimal as dec
24
- from typing import Union
25
23
  import datetime as dt
24
+ from decimal import Decimal as dec
26
25
  import logging
27
26
  import math
28
27
  import pathlib as pl
@@ -30,6 +29,7 @@ import platform
30
29
  import subprocess
31
30
  import sys
32
31
  import traceback
32
+ from typing import Union
33
33
 
34
34
  from PySide6.QtCore import Qt, Signal, qVersion, QRect, QTime, QDateTime, QSize
35
35
  from PySide6.QtWidgets import (
@@ -383,7 +383,7 @@ class get_time_widget(QWidget):
383
383
  dec: time in seconds (None if no format selected)
384
384
  """
385
385
 
386
- time_sec = None
386
+ time_sec = dec("NaN")
387
387
 
388
388
  if self.rb_seconds.isChecked():
389
389
  try:
@@ -396,7 +396,7 @@ class get_time_widget(QWidget):
396
396
  QMessageBox.Ok | QMessageBox.Default,
397
397
  QMessageBox.NoButton,
398
398
  )
399
- return None
399
+ return dec("NaN")
400
400
 
401
401
  if self.rb_time.isChecked():
402
402
  time_sec = self.sb_hour.value() * 3600
@@ -408,7 +408,7 @@ class get_time_widget(QWidget):
408
408
  if self.pb_sign.text() == "-":
409
409
  time_sec = -time_sec
410
410
 
411
- return dec(time_sec).quantize(dec("0.001")) if time_sec is not None else None
411
+ return dec(time_sec).quantize(dec("0.001")) # if time_sec is not None else None
412
412
 
413
413
  def set_time(self, new_time: dec) -> None:
414
414
  """
@@ -489,7 +489,7 @@ class Ask_time(QDialog):
489
489
  )
490
490
  return
491
491
  # test time value
492
- if self.time_widget.get_time() is None:
492
+ if self.time_widget.get_time().is_nan():
493
493
  return
494
494
 
495
495
  self.accept()
@@ -21,7 +21,7 @@ This file is part of BORIS.
21
21
  """
22
22
 
23
23
  from decimal import Decimal as dec
24
- import math
24
+ import logging
25
25
 
26
26
  from PySide6.QtWidgets import (
27
27
  QDialog,
@@ -44,11 +44,12 @@ class DlgEditEvent(QDialog, Ui_Form):
44
44
  def __init__(
45
45
  self,
46
46
  observation_type: str,
47
- time_value: dec = dec(0),
47
+ time_value: dec = dec("NaN"),
48
48
  image_idx=None,
49
49
  current_time=0,
50
50
  time_format: str = cfg.S,
51
51
  show_set_current_time: bool = False,
52
+ exif_date_time: dec | None = None,
52
53
  parent=None,
53
54
  ):
54
55
  super().__init__(parent)
@@ -59,42 +60,49 @@ class DlgEditEvent(QDialog, Ui_Form):
59
60
 
60
61
  self.pb_set_to_current_time.setVisible(show_set_current_time)
61
62
  self.current_time = current_time
63
+ self.exif_date_time = exif_date_time
64
+
65
+ # hide frame index for all observations
66
+ # frame index is determined in base of time
67
+ for w in (
68
+ self.lb_frame_idx,
69
+ self.sb_frame_idx,
70
+ self.cb_set_frame_idx_na,
71
+ ):
72
+ w.setVisible(False)
62
73
 
63
74
  # hide image index
64
75
  if observation_type in (cfg.LIVE, cfg.MEDIA):
65
- for w in (self.lb_image_idx, self.sb_image_idx, self.cb_set_time_na, self.pb_set_to_current_image_index):
66
- w.setVisible(False)
67
- # hide frame index because frame index is automatically extracted
68
- for w in (self.lb_frame_idx, self.sb_frame_idx, self.cb_set_frame_idx_na):
76
+ # hide image index
77
+ for w in (
78
+ self.cb_set_time_na,
79
+ self.gb_image_index,
80
+ ):
69
81
  w.setVisible(False)
70
82
 
71
- if (observation_type in (cfg.LIVE, cfg.MEDIA)) or (observation_type == cfg.IMAGES and not math.isnan(self.time_value)):
72
- self.time_widget = dialog.get_time_widget(self.time_value)
83
+ # widget for time
84
+ self.time_widget = dialog.get_time_widget(self.time_value)
73
85
 
74
- if time_format == cfg.S:
75
- self.time_widget.rb_seconds.setChecked(True)
76
- if time_format == cfg.HHMMSS:
77
- self.time_widget.rb_time.setChecked(True)
78
- if self.time_value > cfg.DATE_CUTOFF:
79
- self.time_widget.rb_datetime.setChecked(True)
86
+ if time_format == cfg.S:
87
+ self.time_widget.rb_seconds.setChecked(True)
88
+ if time_format == cfg.HHMMSS:
89
+ self.time_widget.rb_time.setChecked(True)
90
+ if not self.time_value.is_nan() and int(self.time_value) > cfg.DATE_CUTOFF:
91
+ self.time_widget.rb_datetime.setChecked(True)
80
92
 
81
- self.horizontalLayout_2.insertWidget(0, self.time_widget)
93
+ self.horizontalLayout_3.insertWidget(0, self.time_widget)
82
94
 
83
95
  if observation_type == cfg.IMAGES:
84
- self.time_widget = dialog.get_time_widget(self.time_value)
85
96
  # hide frame index widgets
86
- for w in (self.lb_frame_idx, self.sb_frame_idx, self.cb_set_frame_idx_na, self.pb_set_to_current_time):
87
- w.setVisible(False)
97
+ self.pb_set_to_current_time.setVisible(self.exif_date_time is not None)
88
98
  self.sb_image_idx.setValue(self.image_idx)
89
99
 
90
- # self.pb_set_to_current_time.setText("Set to current image index")
91
-
92
100
  self.pb_set_to_current_time.clicked.connect(self.set_to_current_time)
93
101
  self.pb_set_to_current_image_index.clicked.connect(self.set_to_current_image_index)
94
102
 
95
103
  self.cb_set_time_na.stateChanged.connect(self.time_na)
96
104
 
97
- self.cb_set_frame_idx_na.stateChanged.connect(self.frame_idx_na)
105
+ # self.cb_set_frame_idx_na.stateChanged.connect(self.frame_idx_na)
98
106
  self.pbOK.clicked.connect(self.close_widget)
99
107
  self.pbCancel.clicked.connect(self.reject)
100
108
 
@@ -119,22 +127,34 @@ class DlgEditEvent(QDialog, Ui_Form):
119
127
  """
120
128
  set time to current media time
121
129
  """
130
+
131
+ print(f"{self.current_time=}")
132
+
122
133
  if self.observation_type in (cfg.LIVE, cfg.MEDIA):
123
134
  self.time_widget.set_time(dec(float(self.current_time)))
124
135
 
125
- def frame_idx_na(self):
126
- """
127
- set/unset frame index NA
128
- """
129
- self.lb_frame_idx.setEnabled(not self.cb_set_frame_idx_na.isChecked())
130
- self.sb_frame_idx.setEnabled(not self.cb_set_frame_idx_na.isChecked())
136
+ if self.observation_type == cfg.IMAGES:
137
+ if self.exif_date_time is not None:
138
+ self.time_widget.set_time(dec(self.exif_date_time))
139
+
140
+ # def frame_idx_na(self):
141
+ # """
142
+ # set/unset frame index NA
143
+ # """
144
+ # self.lb_frame_idx.setEnabled(not self.cb_set_frame_idx_na.isChecked())
145
+ # self.sb_frame_idx.setEnabled(not self.cb_set_frame_idx_na.isChecked())
131
146
 
132
147
  def time_na(self):
133
148
  """
134
149
  set/unset time to NA
135
150
  """
136
151
 
152
+ logging.debug("time_na function")
153
+
154
+ self.time_widget.setVisible(not self.cb_set_time_na.isChecked())
137
155
  self.time_widget.setEnabled(not self.cb_set_time_na.isChecked())
156
+
157
+ self.pb_set_to_current_time.setVisible(not self.cb_set_time_na.isChecked() and self.exif_date_time is not None)
138
158
  self.pb_set_to_current_time.setEnabled(not self.cb_set_time_na.isChecked())
139
159
 
140
160
 
@@ -3,7 +3,7 @@
3
3
  ################################################################################
4
4
  ## Form generated from reading UI file 'edit_event.ui'
5
5
  ##
6
- ## Created by: Qt User Interface Compiler version 6.8.0
6
+ ## Created by: Qt User Interface Compiler version 6.9.0
7
7
  ##
8
8
  ## WARNING! All changes made in this file will be lost when recompiling UI file!
9
9
  ################################################################################
@@ -15,60 +15,89 @@ from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor,
15
15
  QFont, QFontDatabase, QGradient, QIcon,
16
16
  QImage, QKeySequence, QLinearGradient, QPainter,
17
17
  QPalette, QPixmap, QRadialGradient, QTransform)
18
- from PySide6.QtWidgets import (QApplication, QCheckBox, QComboBox, QHBoxLayout,
19
- QLabel, QPlainTextEdit, QPushButton, QSizePolicy,
20
- QSpacerItem, QSpinBox, QVBoxLayout, QWidget)
18
+ from PySide6.QtWidgets import (QApplication, QCheckBox, QComboBox, QGroupBox,
19
+ QHBoxLayout, QLabel, QPlainTextEdit, QPushButton,
20
+ QSizePolicy, QSpacerItem, QSpinBox, QVBoxLayout,
21
+ QWidget)
21
22
 
22
23
  class Ui_Form(object):
23
24
  def setupUi(self, Form):
24
25
  if not Form.objectName():
25
26
  Form.setObjectName(u"Form")
26
- Form.resize(413, 488)
27
- self.verticalLayout = QVBoxLayout(Form)
27
+ Form.resize(600, 638)
28
+ self.verticalLayout_3 = QVBoxLayout(Form)
29
+ self.verticalLayout_3.setObjectName(u"verticalLayout_3")
30
+ self.gb_time = QGroupBox(Form)
31
+ self.gb_time.setObjectName(u"gb_time")
32
+ self.verticalLayout = QVBoxLayout(self.gb_time)
28
33
  self.verticalLayout.setObjectName(u"verticalLayout")
34
+ self.horizontalLayout_8 = QHBoxLayout()
35
+ self.horizontalLayout_8.setObjectName(u"horizontalLayout_8")
36
+ self.cb_set_time_na = QCheckBox(self.gb_time)
37
+ self.cb_set_time_na.setObjectName(u"cb_set_time_na")
38
+
39
+ self.horizontalLayout_8.addWidget(self.cb_set_time_na)
40
+
41
+ self.horizontalSpacer_7 = QSpacerItem(40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum)
42
+
43
+ self.horizontalLayout_8.addItem(self.horizontalSpacer_7)
44
+
45
+
46
+ self.verticalLayout.addLayout(self.horizontalLayout_8)
47
+
29
48
  self.horizontalLayout_3 = QHBoxLayout()
30
49
  self.horizontalLayout_3.setObjectName(u"horizontalLayout_3")
31
- self.label = QLabel(Form)
32
- self.label.setObjectName(u"label")
50
+ self.lb_time = QLabel(self.gb_time)
51
+ self.lb_time.setObjectName(u"lb_time")
33
52
 
34
- self.horizontalLayout_3.addWidget(self.label)
53
+ self.horizontalLayout_3.addWidget(self.lb_time)
35
54
 
36
55
  self.horizontalLayout_2 = QHBoxLayout()
37
56
  self.horizontalLayout_2.setObjectName(u"horizontalLayout_2")
38
- self.pb_set_to_current_time = QPushButton(Form)
57
+ self.horizontalSpacer = QSpacerItem(40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum)
58
+
59
+ self.horizontalLayout_2.addItem(self.horizontalSpacer)
60
+
61
+
62
+ self.horizontalLayout_3.addLayout(self.horizontalLayout_2)
63
+
64
+
65
+ self.verticalLayout.addLayout(self.horizontalLayout_3)
66
+
67
+ self.horizontalLayout_9 = QHBoxLayout()
68
+ self.horizontalLayout_9.setObjectName(u"horizontalLayout_9")
69
+ self.pb_set_to_current_time = QPushButton(self.gb_time)
39
70
  self.pb_set_to_current_time.setObjectName(u"pb_set_to_current_time")
40
71
 
41
- self.horizontalLayout_2.addWidget(self.pb_set_to_current_time)
72
+ self.horizontalLayout_9.addWidget(self.pb_set_to_current_time)
42
73
 
43
- self.cb_set_time_na = QCheckBox(Form)
44
- self.cb_set_time_na.setObjectName(u"cb_set_time_na")
74
+ self.horizontalSpacer_8 = QSpacerItem(40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum)
45
75
 
46
- self.horizontalLayout_2.addWidget(self.cb_set_time_na)
76
+ self.horizontalLayout_9.addItem(self.horizontalSpacer_8)
47
77
 
48
- self.horizontalSpacer = QSpacerItem(40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum)
49
78
 
50
- self.horizontalLayout_2.addItem(self.horizontalSpacer)
79
+ self.verticalLayout.addLayout(self.horizontalLayout_9)
51
80
 
81
+ self.verticalSpacer = QSpacerItem(20, 40, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding)
52
82
 
53
- self.horizontalLayout_3.addLayout(self.horizontalLayout_2)
83
+ self.verticalLayout.addItem(self.verticalSpacer)
54
84
 
55
85
 
56
- self.verticalLayout.addLayout(self.horizontalLayout_3)
86
+ self.verticalLayout_3.addWidget(self.gb_time)
57
87
 
88
+ self.gb_image_index = QGroupBox(Form)
89
+ self.gb_image_index.setObjectName(u"gb_image_index")
90
+ self.verticalLayout_2 = QVBoxLayout(self.gb_image_index)
91
+ self.verticalLayout_2.setObjectName(u"verticalLayout_2")
58
92
  self.horizontalLayout_7 = QHBoxLayout()
59
93
  self.horizontalLayout_7.setObjectName(u"horizontalLayout_7")
60
- self.lb_image_idx = QLabel(Form)
61
- self.lb_image_idx.setObjectName(u"lb_image_idx")
62
-
63
- self.horizontalLayout_7.addWidget(self.lb_image_idx)
64
-
65
- self.sb_image_idx = QSpinBox(Form)
94
+ self.sb_image_idx = QSpinBox(self.gb_image_index)
66
95
  self.sb_image_idx.setObjectName(u"sb_image_idx")
67
96
  self.sb_image_idx.setMaximum(10000000)
68
97
 
69
98
  self.horizontalLayout_7.addWidget(self.sb_image_idx)
70
99
 
71
- self.pb_set_to_current_image_index = QPushButton(Form)
100
+ self.pb_set_to_current_image_index = QPushButton(self.gb_image_index)
72
101
  self.pb_set_to_current_image_index.setObjectName(u"pb_set_to_current_image_index")
73
102
 
74
103
  self.horizontalLayout_7.addWidget(self.pb_set_to_current_image_index)
@@ -78,7 +107,10 @@ class Ui_Form(object):
78
107
  self.horizontalLayout_7.addItem(self.horizontalSpacer_6)
79
108
 
80
109
 
81
- self.verticalLayout.addLayout(self.horizontalLayout_7)
110
+ self.verticalLayout_2.addLayout(self.horizontalLayout_7)
111
+
112
+
113
+ self.verticalLayout_3.addWidget(self.gb_image_index)
82
114
 
83
115
  self.horizontalLayout_4 = QHBoxLayout()
84
116
  self.horizontalLayout_4.setObjectName(u"horizontalLayout_4")
@@ -97,7 +129,7 @@ class Ui_Form(object):
97
129
  self.horizontalLayout_4.addItem(self.horizontalSpacer_2)
98
130
 
99
131
 
100
- self.verticalLayout.addLayout(self.horizontalLayout_4)
132
+ self.verticalLayout_3.addLayout(self.horizontalLayout_4)
101
133
 
102
134
  self.horizontalLayout_5 = QHBoxLayout()
103
135
  self.horizontalLayout_5.setObjectName(u"horizontalLayout_5")
@@ -116,7 +148,7 @@ class Ui_Form(object):
116
148
  self.horizontalLayout_5.addItem(self.horizontalSpacer_3)
117
149
 
118
150
 
119
- self.verticalLayout.addLayout(self.horizontalLayout_5)
151
+ self.verticalLayout_3.addLayout(self.horizontalLayout_5)
120
152
 
121
153
  self.horizontalLayout_6 = QHBoxLayout()
122
154
  self.horizontalLayout_6.setObjectName(u"horizontalLayout_6")
@@ -142,17 +174,17 @@ class Ui_Form(object):
142
174
  self.horizontalLayout_6.addItem(self.horizontalSpacer_5)
143
175
 
144
176
 
145
- self.verticalLayout.addLayout(self.horizontalLayout_6)
177
+ self.verticalLayout_3.addLayout(self.horizontalLayout_6)
146
178
 
147
179
  self.label_4 = QLabel(Form)
148
180
  self.label_4.setObjectName(u"label_4")
149
181
 
150
- self.verticalLayout.addWidget(self.label_4)
182
+ self.verticalLayout_3.addWidget(self.label_4)
151
183
 
152
184
  self.leComment = QPlainTextEdit(Form)
153
185
  self.leComment.setObjectName(u"leComment")
154
186
 
155
- self.verticalLayout.addWidget(self.leComment)
187
+ self.verticalLayout_3.addWidget(self.leComment)
156
188
 
157
189
  self.horizontalLayout = QHBoxLayout()
158
190
  self.horizontalLayout.setObjectName(u"horizontalLayout")
@@ -171,7 +203,7 @@ class Ui_Form(object):
171
203
  self.horizontalLayout.addWidget(self.pbOK)
172
204
 
173
205
 
174
- self.verticalLayout.addLayout(self.horizontalLayout)
206
+ self.verticalLayout_3.addLayout(self.horizontalLayout)
175
207
 
176
208
 
177
209
  self.retranslateUi(Form)
@@ -184,13 +216,14 @@ class Ui_Form(object):
184
216
 
185
217
  def retranslateUi(self, Form):
186
218
  Form.setWindowTitle(QCoreApplication.translate("Form", u"Edit event", None))
187
- self.label.setText(QCoreApplication.translate("Form", u"Time", None))
219
+ self.gb_time.setTitle(QCoreApplication.translate("Form", u"Time", None))
220
+ self.cb_set_time_na.setText(QCoreApplication.translate("Form", u"Set time to NA", None))
221
+ self.lb_time.setText("")
188
222
  self.pb_set_to_current_time.setText(QCoreApplication.translate("Form", u"Set to current time", None))
189
- self.cb_set_time_na.setText(QCoreApplication.translate("Form", u"Set NA", None))
190
- self.lb_image_idx.setText(QCoreApplication.translate("Form", u"Image index", None))
223
+ self.gb_image_index.setTitle(QCoreApplication.translate("Form", u"Image index", None))
191
224
  self.pb_set_to_current_image_index.setText(QCoreApplication.translate("Form", u"Set to current image index", None))
192
225
  self.lbSubject.setText(QCoreApplication.translate("Form", u"Subject", None))
193
- self.label_2.setText(QCoreApplication.translate("Form", u"Code", None))
226
+ self.label_2.setText(QCoreApplication.translate("Form", u"Behavior", None))
194
227
  self.lb_frame_idx.setText(QCoreApplication.translate("Form", u"Frame index", None))
195
228
  self.cb_set_frame_idx_na.setText(QCoreApplication.translate("Form", u"Set NA", None))
196
229
  self.label_4.setText(QCoreApplication.translate("Form", u"Comment", None))