boris-behav-obs 8.16.6__py3-none-any.whl → 9.7.1__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 (125) hide show
  1. boris/__init__.py +1 -1
  2. boris/__main__.py +1 -1
  3. boris/about.py +24 -40
  4. boris/add_modifier.py +88 -80
  5. boris/add_modifier_ui.py +235 -131
  6. boris/advanced_event_filtering.py +23 -29
  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 +228 -229
  18. boris/behavior_binary_table.py +33 -50
  19. boris/behaviors_coding_map.py +17 -18
  20. boris/boris_cli.py +6 -25
  21. boris/cmd_arguments.py +12 -1
  22. boris/coding_pad.py +16 -34
  23. boris/config.py +101 -49
  24. boris/config_file.py +55 -64
  25. boris/connections.py +105 -58
  26. boris/converters.py +13 -37
  27. boris/converters_ui.py +187 -110
  28. boris/cooccurence.py +250 -0
  29. boris/core.py +2108 -1275
  30. boris/core_qrc.py +15892 -10829
  31. boris/core_ui.py +941 -806
  32. boris/db_functions.py +17 -42
  33. boris/dev.py +134 -0
  34. boris/dialog.py +461 -242
  35. boris/duration_widget.py +9 -14
  36. boris/edit_event.py +61 -31
  37. boris/edit_event_ui.py +208 -97
  38. boris/event_operations.py +405 -281
  39. boris/events_cursor.py +25 -17
  40. boris/events_snapshots.py +36 -82
  41. boris/exclusion_matrix.py +4 -9
  42. boris/export_events.py +180 -203
  43. boris/export_observation.py +60 -73
  44. boris/external_processes.py +123 -98
  45. boris/geometric_measurement.py +427 -218
  46. boris/gui_utilities.py +91 -14
  47. boris/image_overlay.py +4 -4
  48. boris/import_observations.py +190 -98
  49. boris/ipc_mpv.py +304 -0
  50. boris/irr.py +20 -57
  51. boris/latency.py +31 -24
  52. boris/measurement_widget.py +14 -18
  53. boris/media_file.py +17 -19
  54. boris/menu_options.py +16 -6
  55. boris/modifier_coding_map_creator.py +1013 -0
  56. boris/modifiers_coding_map.py +7 -9
  57. boris/mpv2.py +127 -36
  58. boris/observation.py +493 -210
  59. boris/observation_operations.py +1010 -391
  60. boris/observation_ui.py +573 -363
  61. boris/observations_list.py +51 -58
  62. boris/otx_parser.py +74 -68
  63. boris/param_panel.py +45 -59
  64. boris/param_panel_ui.py +254 -138
  65. boris/player_dock_widget.py +91 -56
  66. boris/plot_data_module.py +18 -53
  67. boris/plot_events.py +56 -153
  68. boris/plot_events_rt.py +16 -30
  69. boris/plot_spectrogram_rt.py +80 -56
  70. boris/plot_waveform_rt.py +23 -48
  71. boris/plugins.py +431 -0
  72. boris/portion/__init__.py +18 -8
  73. boris/portion/const.py +35 -18
  74. boris/portion/dict.py +5 -5
  75. boris/portion/func.py +2 -2
  76. boris/portion/interval.py +21 -41
  77. boris/portion/io.py +41 -32
  78. boris/preferences.py +298 -123
  79. boris/preferences_ui.py +664 -225
  80. boris/project.py +293 -270
  81. boris/project_functions.py +610 -537
  82. boris/project_import_export.py +204 -213
  83. boris/project_ui.py +673 -441
  84. boris/qrc_boris.py +6 -3
  85. boris/qrc_boris5.py +6 -3
  86. boris/select_modifiers.py +62 -90
  87. boris/select_observations.py +19 -197
  88. boris/select_subj_behav.py +67 -39
  89. boris/state_events.py +51 -33
  90. boris/subjects_pad.py +6 -8
  91. boris/synthetic_time_budget.py +25 -17
  92. boris/time_budget_functions.py +169 -169
  93. boris/time_budget_widget.py +71 -86
  94. boris/transitions.py +41 -41
  95. boris/utilities.py +562 -222
  96. boris/version.py +3 -3
  97. boris/video_equalizer.py +16 -14
  98. boris/video_equalizer_ui.py +199 -130
  99. boris/video_operations.py +78 -28
  100. boris/view_df.py +104 -0
  101. boris/view_df_ui.py +75 -0
  102. boris/write_event.py +240 -136
  103. boris_behav_obs-9.7.1.dist-info/METADATA +140 -0
  104. boris_behav_obs-9.7.1.dist-info/RECORD +109 -0
  105. {boris_behav_obs-8.16.6.dist-info → boris_behav_obs-9.7.1.dist-info}/WHEEL +1 -1
  106. boris_behav_obs-9.7.1.dist-info/entry_points.txt +2 -0
  107. boris/README.TXT +0 -22
  108. boris/add_modifier.ui +0 -323
  109. boris/converters.ui +0 -289
  110. boris/core.qrc +0 -37
  111. boris/core.ui +0 -1571
  112. boris/edit_event.ui +0 -233
  113. boris/icons/logo_eye.ico +0 -0
  114. boris/map_creator.py +0 -982
  115. boris/observation.ui +0 -814
  116. boris/param_panel.ui +0 -379
  117. boris/preferences.ui +0 -537
  118. boris/project.ui +0 -1074
  119. boris/vlc_local.py +0 -90
  120. boris_behav_obs-8.16.6.dist-info/LICENSE.TXT +0 -674
  121. boris_behav_obs-8.16.6.dist-info/METADATA +0 -134
  122. boris_behav_obs-8.16.6.dist-info/RECORD +0 -106
  123. boris_behav_obs-8.16.6.dist-info/entry_points.txt +0 -2
  124. {boris → boris_behav_obs-9.7.1.dist-info/licenses}/LICENSE.TXT +0 -0
  125. {boris_behav_obs-8.16.6.dist-info → boris_behav_obs-9.7.1.dist-info}/top_level.txt +0 -0
boris/events_cursor.py CHANGED
@@ -1,7 +1,7 @@
1
1
  """
2
2
  BORIS
3
3
  Behavioral Observation Research Interactive Software
4
- Copyright 2012-2023 Olivier Friard
4
+ Copyright 2012-2025 Olivier Friard
5
5
 
6
6
 
7
7
  This program is free software; you can redistribute it and/or modify
@@ -21,14 +21,14 @@ Copyright 2012-2023 Olivier Friard
21
21
 
22
22
  """
23
23
 
24
- from PyQt5.QtCore import QPoint, Qt
25
- from PyQt5.QtGui import QPolygon, QPen, QColor, QBrush
26
- from PyQt5.QtWidgets import QStyledItemDelegate
24
+ from PySide6.QtCore import QPoint, Qt
25
+ from PySide6.QtGui import QPolygon, QPen, QColor, QBrush, QPainter
26
+ from PySide6.QtWidgets import QStyledItemDelegate
27
27
 
28
28
 
29
29
  class StyledItemDelegateTriangle(QStyledItemDelegate):
30
30
  """
31
- painter for twEvents with current time highlighting
31
+ painter for tv_events with current time highlighting
32
32
  """
33
33
 
34
34
  def __init__(self, row, parent=None):
@@ -36,18 +36,26 @@ class StyledItemDelegateTriangle(QStyledItemDelegate):
36
36
  self.row = row
37
37
 
38
38
  def paint(self, painter, option, index):
39
+ """
40
+ draw a red triangle on ceel corresponfing to current event
41
+ """
39
42
 
40
43
  super(StyledItemDelegateTriangle, self).paint(painter, option, index)
41
44
 
42
- if self.row != -1:
43
- if index.row() == self.row:
44
- polygonTriangle = QPolygon(3)
45
- polygonTriangle.setPoint(0, QPoint(option.rect.x() + 15, option.rect.y()))
46
- polygonTriangle.setPoint(1, QPoint(option.rect.x(), option.rect.y() - 5))
47
- polygonTriangle.setPoint(2, QPoint(option.rect.x(), option.rect.y() + 5))
48
- painter.save()
49
- painter.setRenderHint(painter.Antialiasing)
50
- painter.setBrush(QBrush(QColor(Qt.red)))
51
- painter.setPen(QPen(QColor(Qt.red)))
52
- painter.drawPolygon(polygonTriangle)
53
- painter.restore()
45
+ if self.row == -1:
46
+ return
47
+ if index.row() == self.row:
48
+ triangle = QPolygon(
49
+ [
50
+ QPoint(option.rect.x() + 15, option.rect.y()),
51
+ QPoint(option.rect.x(), option.rect.y() - 5),
52
+ QPoint(option.rect.x(), option.rect.y() + 5),
53
+ ]
54
+ )
55
+
56
+ painter.save()
57
+ painter.setRenderHint(QPainter.RenderHint.Antialiasing)
58
+ painter.setBrush(QBrush(QColor(Qt.red)))
59
+ painter.setPen(QPen(QColor(Qt.red)))
60
+ painter.drawPolygon(triangle)
61
+ painter.restore()
boris/events_snapshots.py CHANGED
@@ -1,7 +1,7 @@
1
1
  """
2
2
  BORIS
3
3
  Behavioral Observation Research Interactive Software
4
- Copyright 2012-2023 Olivier Friard
4
+ Copyright 2012-2025 Olivier Friard
5
5
 
6
6
 
7
7
  This program is free software; you can redistribute it and/or modify
@@ -21,14 +21,13 @@ Copyright 2012-2023 Olivier Friard
21
21
 
22
22
  """
23
23
 
24
-
25
24
  import logging
26
25
  import os
27
26
  import pathlib as pl
28
27
  import subprocess
29
28
  from decimal import Decimal as dec
30
29
 
31
- from PyQt5.QtWidgets import QFileDialog, QInputDialog, QMessageBox
30
+ from PySide6.QtWidgets import QApplication, QFileDialog, QInputDialog, QMessageBox
32
31
 
33
32
  from . import config as cfg
34
33
  from . import db_functions, dialog, project_functions, select_observations, select_subj_behav
@@ -80,8 +79,8 @@ def events_snapshots(self):
80
79
  selected_observations,
81
80
  start_coding=dec("NaN"),
82
81
  end_coding=dec("NaN"),
83
- flagShowIncludeModifiers=False,
84
- flagShowExcludeBehaviorsWoEvents=False,
82
+ show_include_modifiers=False,
83
+ show_exclude_non_coded_behaviors=False,
85
84
  n_observations=len(selected_observations),
86
85
  )
87
86
 
@@ -110,11 +109,11 @@ def events_snapshots(self):
110
109
  return
111
110
 
112
111
  # directory for saving frames
113
- export_dir = QFileDialog().getExistingDirectory(
112
+ export_dir = QFileDialog.getExistingDirectory(
114
113
  self,
115
114
  "Choose a directory to extract events",
116
115
  os.path.expanduser("~"),
117
- options=QFileDialog(self).ShowDirsOnly,
116
+ options=QFileDialog.ShowDirsOnly,
118
117
  )
119
118
  if not export_dir:
120
119
  return
@@ -128,9 +127,7 @@ def events_snapshots(self):
128
127
  )
129
128
 
130
129
  for obs_id in selected_observations:
131
-
132
130
  for nplayer in self.pj[cfg.OBSERVATIONS][obs_id][cfg.FILE]:
133
-
134
131
  if not self.pj[cfg.OBSERVATIONS][obs_id][cfg.FILE][nplayer]:
135
132
  continue
136
133
  duration1 = [] # in seconds
@@ -138,9 +135,7 @@ def events_snapshots(self):
138
135
  duration1.append(self.pj[cfg.OBSERVATIONS][obs_id][cfg.MEDIA_INFO][cfg.LENGTH][mediaFile])
139
136
 
140
137
  for subject in parameters[cfg.SELECTED_SUBJECTS]:
141
-
142
138
  for behavior in parameters[cfg.SELECTED_BEHAVIORS]:
143
-
144
139
  cursor.execute(
145
140
  "SELECT occurence FROM events WHERE observation = ? AND subject = ? AND code = ?",
146
141
  (obs_id, subject, behavior),
@@ -150,10 +145,7 @@ def events_snapshots(self):
150
145
  behavior_state = project_functions.event_type(behavior, self.pj[cfg.ETHOGRAM])
151
146
 
152
147
  for idx, row in enumerate(rows):
153
-
154
- mediaFileIdx = [
155
- idx1 for idx1, x in enumerate(duration1) if row["occurence"] >= sum(duration1[0:idx1])
156
- ][-1]
148
+ mediaFileIdx = [idx1 for idx1, x in enumerate(duration1) if row["occurence"] >= sum(duration1[0:idx1])][-1]
157
149
 
158
150
  # check if media has video
159
151
  flag_no_video = False
@@ -165,9 +157,7 @@ def events_snapshots(self):
165
157
  flag_no_video = True
166
158
 
167
159
  if flag_no_video:
168
- logging.debug(
169
- f"Media {self.pj[cfg.OBSERVATIONS][obs_id][cfg.FILE][nplayer][mediaFileIdx]} does not have video"
170
- )
160
+ logging.debug(f"Media {self.pj[cfg.OBSERVATIONS][obs_id][cfg.FILE][nplayer][mediaFileIdx]} does not have video")
171
161
  flag_no_video = True
172
162
  response = dialog.MessageDialog(
173
163
  cfg.programName,
@@ -197,9 +187,7 @@ def events_snapshots(self):
197
187
  mediafile_fps = 0
198
188
 
199
189
  if not mediafile_fps:
200
- logging.debug(
201
- f"FPS not found for {self.pj[cfg.OBSERVATIONS][obs_id][cfg.FILE][nplayer][mediaFileIdx]}"
202
- )
190
+ logging.debug(f"FPS not found for {self.pj[cfg.OBSERVATIONS][obs_id][cfg.FILE][nplayer][mediaFileIdx]}")
203
191
  response = dialog.MessageDialog(
204
192
  cfg.programName,
205
193
  (
@@ -213,11 +201,7 @@ def events_snapshots(self):
213
201
  if response == "Abort":
214
202
  return
215
203
 
216
- global_start = (
217
- dec("0.000")
218
- if row["occurence"] < time_interval
219
- else round(row["occurence"] - time_interval, 3)
220
- )
204
+ global_start = dec("0.000") if row["occurence"] < time_interval else round(row["occurence"] - time_interval, 3)
221
205
  start = round(
222
206
  row["occurence"]
223
207
  - time_interval
@@ -228,8 +212,7 @@ def events_snapshots(self):
228
212
  if start < time_interval:
229
213
  start = dec("0.000")
230
214
 
231
- if cfg.POINT in behavior_state:
232
-
215
+ if behavior_state in cfg.POINT_EVENT_TYPES:
233
216
  media_path = project_functions.full_path(
234
217
  self.pj[cfg.OBSERVATIONS][obs_id][cfg.FILE][nplayer][mediaFileIdx],
235
218
  self.projectFileName,
@@ -239,17 +222,14 @@ def events_snapshots(self):
239
222
  if vframes == 0:
240
223
  vframes = 1
241
224
 
242
- if cfg.STATE in behavior_state:
225
+ if behavior_state in cfg.STATE_EVENT_TYPES:
243
226
  if idx % 2 == 0:
244
-
245
227
  # check if stop is on same media file
246
228
  if (
247
229
  mediaFileIdx
248
- != [
249
- idx1
250
- for idx1, x in enumerate(duration1)
251
- if rows[idx + 1]["occurence"] >= sum(duration1[0:idx1])
252
- ][-1]
230
+ != [idx1 for idx1, x in enumerate(duration1) if rows[idx + 1]["occurence"] >= sum(duration1[0:idx1])][
231
+ -1
232
+ ]
253
233
  ):
254
234
  response = dialog.MessageDialog(
255
235
  cfg.programName,
@@ -365,8 +345,8 @@ def extract_events(self):
365
345
  selected_observations,
366
346
  start_coding=dec("NaN"),
367
347
  end_coding=dec("NaN"),
368
- flagShowIncludeModifiers=False,
369
- flagShowExcludeBehaviorsWoEvents=False,
348
+ show_include_modifiers=False,
349
+ show_exclude_non_coded_behaviors=False,
370
350
  )
371
351
  if parameters == {}:
372
352
  return
@@ -377,9 +357,7 @@ def extract_events(self):
377
357
 
378
358
  # Ask for time interval around the event
379
359
  while True:
380
- text, ok = QInputDialog.getDouble(
381
- self, "Time interval around the events", "Time (in seconds):", 0.0, 0.0, 86400, 1
382
- )
360
+ text, ok = QInputDialog.getDouble(self, "Time interval around the events", "Time (in seconds):", 0.0, 0.0, 86400, 1)
383
361
  if not ok:
384
362
  return
385
363
  try:
@@ -395,11 +373,11 @@ def extract_events(self):
395
373
  if not ok:
396
374
  return
397
375
 
398
- export_dir = QFileDialog().getExistingDirectory(
376
+ export_dir = QFileDialog.getExistingDirectory(
399
377
  self,
400
378
  "Choose a directory to extract events",
401
379
  os.path.expanduser("~"),
402
- options=QFileDialog(self).ShowDirsOnly,
380
+ options=QFileDialog.ShowDirsOnly,
403
381
  )
404
382
  if not export_dir:
405
383
  return
@@ -412,19 +390,13 @@ def extract_events(self):
412
390
  time_interval=cfg.TIME_FULL_OBS,
413
391
  )
414
392
 
415
- """
416
- ffmpeg_extract_command = (
417
- '"{ffmpeg_bin}" -i "{input_}" -y -ss {start} -to {stop} {codecs} '
418
- ' "{dir_}{sep}{obsId}_{player}_{subject}_{behavior}_{globalStart}'
419
- '-{globalStop}{extension}" '
420
- )
421
- """
393
+ self.statusBar().showMessage("Extracting sequences from media files")
394
+ QApplication.processEvents()
395
+
422
396
  ffmpeg_extract_command: str = '"{ffmpeg_bin}" -ss {start} -i "{input_}" -y -t {duration} {codecs} '
423
397
  mem_command: str = ""
424
398
  for obs_id in selected_observations:
425
-
426
399
  for nplayer in self.pj[cfg.OBSERVATIONS][obs_id][cfg.FILE]:
427
-
428
400
  if not self.pj[cfg.OBSERVATIONS][obs_id][cfg.FILE][nplayer]:
429
401
  continue
430
402
 
@@ -433,9 +405,7 @@ def extract_events(self):
433
405
  duration1.append(self.pj[cfg.OBSERVATIONS][obs_id][cfg.MEDIA_INFO][cfg.LENGTH][mediaFile])
434
406
 
435
407
  for subject in parameters[cfg.SELECTED_SUBJECTS]:
436
-
437
408
  for behavior in parameters[cfg.SELECTED_BEHAVIORS]:
438
-
439
409
  cursor.execute(
440
410
  "SELECT occurence FROM events WHERE observation = ? AND subject = ? AND code = ?",
441
411
  (obs_id, subject, behavior),
@@ -443,14 +413,11 @@ def extract_events(self):
443
413
  rows = [{"occurence": util.float2decimal(r["occurence"])} for r in cursor.fetchall()]
444
414
 
445
415
  behavior_state = project_functions.event_type(behavior, self.pj[cfg.ETHOGRAM])
446
- if cfg.STATE in behavior_state and len(rows) % 2: # unpaired events
416
+ if behavior_state in cfg.STATE_EVENT_TYPES and len(rows) % 2: # unpaired events
447
417
  continue
448
418
 
449
419
  for idx, row in enumerate(rows):
450
-
451
- mediaFileIdx = [
452
- idx1 for idx1, x in enumerate(duration1) if row["occurence"] >= sum(duration1[0:idx1])
453
- ][-1]
420
+ mediaFileIdx = [idx1 for idx1, x in enumerate(duration1) if row["occurence"] >= sum(duration1[0:idx1])][-1]
454
421
 
455
422
  if "VIDEO" in items_to_extract.upper():
456
423
  # check if media has video
@@ -459,7 +426,7 @@ def extract_events(self):
459
426
  has_video = self.pj[cfg.OBSERVATIONS][obs_id][cfg.MEDIA_INFO][cfg.HAS_VIDEO][
460
427
  self.pj[cfg.OBSERVATIONS][obs_id][cfg.FILE][nplayer][mediaFileIdx]
461
428
  ]
462
- except:
429
+ except Exception:
463
430
  has_video = False
464
431
  if not has_video:
465
432
  if (
@@ -487,10 +454,9 @@ def extract_events(self):
487
454
  has_audio = self.pj[cfg.OBSERVATIONS][obs_id][cfg.MEDIA_INFO][cfg.HAS_AUDIO][
488
455
  self.pj[cfg.OBSERVATIONS][obs_id][cfg.FILE][nplayer][mediaFileIdx]
489
456
  ]
490
- except:
457
+ except Exception:
491
458
  has_audio = False
492
459
  if not has_audio:
493
-
494
460
  if (
495
461
  dialog.MessageDialog(
496
462
  cfg.programName,
@@ -506,13 +472,8 @@ def extract_events(self):
506
472
  new_extension = ".wav"
507
473
  codecs = "-vn"
508
474
 
509
- if cfg.POINT in behavior_state:
510
-
511
- globalStart = (
512
- dec("0.000")
513
- if row["occurence"] < timeOffset
514
- else round(row["occurence"] - timeOffset, 3)
515
- )
475
+ if behavior_state in cfg.POINT_EVENT_TYPES:
476
+ globalStart = dec("0.000") if row["occurence"] < timeOffset else round(row["occurence"] - timeOffset, 3)
516
477
  start = round(
517
478
  row["occurence"]
518
479
  - (timeOffset if timeOffset else 1) # if time offset is not set default = 1 s
@@ -533,17 +494,14 @@ def extract_events(self):
533
494
  3,
534
495
  )
535
496
 
536
- if cfg.STATE in behavior_state:
537
-
497
+ if behavior_state in cfg.STATE_EVENT_TYPES:
538
498
  if idx % 2 == 0:
539
499
  # check if stop is on same media file
540
500
  if (
541
501
  mediaFileIdx
542
- != [
543
- idx1
544
- for idx1, x in enumerate(duration1)
545
- if rows[idx + 1]["occurence"] >= sum(duration1[0:idx1])
546
- ][-1]
502
+ != [idx1 for idx1, x in enumerate(duration1) if rows[idx + 1]["occurence"] >= sum(duration1[0:idx1])][
503
+ -1
504
+ ]
547
505
  ):
548
506
  response = dialog.MessageDialog(
549
507
  cfg.programName,
@@ -558,11 +516,7 @@ def extract_events(self):
558
516
  if response == "Abort":
559
517
  return
560
518
 
561
- globalStart = (
562
- dec("0.000")
563
- if row["occurence"] < timeOffset
564
- else round(row["occurence"] - timeOffset, 3)
565
- )
519
+ globalStart = dec("0.000") if row["occurence"] < timeOffset else round(row["occurence"] - timeOffset, 3)
566
520
  start = round(
567
521
  row["occurence"]
568
522
  - timeOffset
@@ -629,10 +583,10 @@ def extract_events(self):
629
583
  codecs=codecs,
630
584
  )
631
585
 
632
- logging.debug(f"ffmpeg command: {ffmpeg_command} '{new_file_name}'")
586
+ logging.debug(f'ffmpeg command: {ffmpeg_command} "{new_file_name}"')
633
587
 
634
588
  p = subprocess.Popen(
635
- f"{ffmpeg_command} '{new_file_name}'",
589
+ f'{ffmpeg_command} "{new_file_name}"',
636
590
  stdout=subprocess.PIPE,
637
591
  stderr=subprocess.PIPE,
638
592
  shell=True,
boris/exclusion_matrix.py CHANGED
@@ -1,7 +1,7 @@
1
1
  """
2
2
  BORIS
3
3
  Behavioral Observation Research Interactive Software
4
- Copyright 2012-2023 Olivier Friard
4
+ Copyright 2012-2025 Olivier Friard
5
5
 
6
6
  This file is part of BORIS.
7
7
 
@@ -21,7 +21,7 @@ This file is part of BORIS.
21
21
  """
22
22
 
23
23
  import logging
24
- from PyQt5.QtWidgets import (
24
+ from PySide6.QtWidgets import (
25
25
  QDialog,
26
26
  QVBoxLayout,
27
27
  QHBoxLayout,
@@ -42,10 +42,7 @@ class ExclusionMatrix(QDialog):
42
42
 
43
43
  self.label = QLabel()
44
44
  self.label.setText(
45
- (
46
- "Check if behaviors are mutually exclusive.\n"
47
- "The Point events (displayed on blue background) cannot be excluded)"
48
- )
45
+ ("Check if behaviors are mutually exclusive.\nThe Point events (displayed on blue background) cannot be excluded)")
49
46
  )
50
47
  hbox.addWidget(self.label)
51
48
 
@@ -139,8 +136,6 @@ class ExclusionMatrix(QDialog):
139
136
  if c_name != r_name:
140
137
  try:
141
138
  if f"{c_name}|{r_name}" in self.checkboxes:
142
- self.checkboxes[f"{c_name}|{r_name}"].setChecked(
143
- self.checkboxes[f"{r_name}|{c_name}"].isChecked()
144
- )
139
+ self.checkboxes[f"{c_name}|{r_name}"].setChecked(self.checkboxes[f"{r_name}|{c_name}"].isChecked())
145
140
  except Exception:
146
141
  logging.warning(f"Error during checking/unchecking for {r_name}/{c_name} in exclusion matrix")