boris-behav-obs 9.7.12__py3-none-any.whl → 9.7.15__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.
boris/core.py CHANGED
@@ -31,31 +31,32 @@ os.environ["PATH"] = str(Path(__file__).parent / "misc") + os.pathsep + os.envir
31
31
  sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), ".")))
32
32
 
33
33
  import datetime
34
+ import gzip
34
35
  import json
36
+ import locale
35
37
  import logging
38
+ import math
36
39
  import platform
37
40
  import re
38
- import PIL.Image
39
- import PIL.ImageEnhance
40
- from PIL.ImageQt import Image
41
+ import shutil
41
42
  import subprocess
42
- import locale
43
43
  import tempfile
44
- import math
45
44
  import time
46
45
  import urllib.request
47
- from decimal import Decimal as dec
48
- from decimal import ROUND_DOWN
49
- import gzip
46
+ import zipfile
50
47
  from collections import deque
48
+ from decimal import ROUND_DOWN
49
+ from decimal import Decimal as dec
50
+
51
51
  import matplotlib
52
- import zipfile
53
- import shutil
52
+ import PIL.Image
53
+ import PIL.ImageEnhance
54
+ from PIL.ImageQt import Image
54
55
 
55
56
  matplotlib.use("QtAgg")
56
57
 
57
- from PySide6.QtCore import Qt, QPoint, Signal, QEvent, QDateTime, QUrl, QAbstractTableModel, QElapsedTimer, QSettings, QTimer
58
- from PySide6.QtGui import QIcon, QPixmap, QFont, QKeyEvent, QDesktopServices, QColor, QPainter, QPolygon, QAction
58
+ from PySide6.QtCore import QAbstractTableModel, QDateTime, QElapsedTimer, QEvent, QPoint, QSettings, Qt, QUrl, Signal
59
+ from PySide6.QtGui import QAction, QColor, QDesktopServices, QFont, QIcon, QKeyEvent, QPainter, QPixmap, QPolygon
59
60
  from PySide6.QtMultimedia import QSoundEffect
60
61
  from PySide6.QtWidgets import (
61
62
  QAbstractItemView,
@@ -74,7 +75,6 @@ from PySide6.QtWidgets import (
74
75
  QTableWidgetItem,
75
76
  )
76
77
 
77
-
78
78
  from . import cmd_arguments
79
79
 
80
80
  # parse command line arguments
@@ -94,39 +94,39 @@ else:
94
94
  level=logging.INFO,
95
95
  )
96
96
 
97
- from . import utilities as util
98
-
99
- from . import dialog
100
- from . import gui_utilities
101
- from . import events_cursor
102
- from . import modifier_coding_map_creator
103
- from . import geometric_measurement
104
- from . import modifiers_coding_map
105
- from . import advanced_event_filtering
106
- from . import otx_parser
107
- from . import param_panel
108
- from . import plot_events
109
- from . import plot_spectrogram_rt
110
- from . import plot_waveform_rt
111
- from . import plot_events_rt
112
- from . import plugins
113
- from . import project_functions
114
- from . import select_observations
115
- from . import subjects_pad
116
- from . import version
117
- from . import event_operations
118
- from . import core_qrc
119
- from .core_ui import Ui_MainWindow
97
+ from . import (
98
+ advanced_event_filtering,
99
+ config_file,
100
+ core_qrc,
101
+ dialog,
102
+ event_operations,
103
+ events_cursor,
104
+ geometric_measurement,
105
+ gui_utilities,
106
+ modifier_coding_map_creator,
107
+ modifiers_coding_map,
108
+ observation_operations,
109
+ otx_parser,
110
+ param_panel,
111
+ plot_events,
112
+ plot_events_rt,
113
+ plot_spectrogram_rt,
114
+ plot_waveform_rt,
115
+ plugins,
116
+ project,
117
+ project_functions,
118
+ select_observations,
119
+ select_subj_behav,
120
+ subjects_pad,
121
+ version,
122
+ video_operations,
123
+ write_event,
124
+ )
120
125
  from . import config as cfg
121
- from . import video_operations
122
- from . import project
123
- from . import menu_options as menu_options
124
126
  from . import connections as connections
125
- from . import config_file
126
- from . import select_subj_behav
127
- from . import observation_operations
128
- from . import write_event
129
-
127
+ from . import menu_options as menu_options
128
+ from . import utilities as util
129
+ from .core_ui import Ui_MainWindow
130
130
 
131
131
  logging.debug("test")
132
132
 
@@ -177,8 +177,8 @@ class TableModel(QAbstractTableModel):
177
177
  self.observation_type = observation_type
178
178
 
179
179
  def headerData(self, section: int, orientation: Qt.Orientation, role: int):
180
- if role == Qt.DisplayRole:
181
- if orientation == Qt.Horizontal:
180
+ if role == Qt.ItemDataRole.DisplayRole:
181
+ if orientation == Qt.Orientation.Horizontal:
182
182
  return self.header[section]
183
183
  else:
184
184
  return str(section + 1)
@@ -189,8 +189,8 @@ class TableModel(QAbstractTableModel):
189
189
  def columnCount(self, parent=None):
190
190
  return len(self._data[0]) if self.rowCount() else 0
191
191
 
192
- def data(self, index, role=Qt.DisplayRole):
193
- if role == Qt.DisplayRole:
192
+ def data(self, index, role=Qt.ItemDataRole.DisplayRole):
193
+ if role == Qt.ItemDataRole.DisplayRole:
194
194
  row = index.row()
195
195
  if 0 <= row < self.rowCount():
196
196
  column = index.column()
@@ -348,7 +348,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
348
348
  super(MainWindow, self).__init__(parent)
349
349
  self.setupUi(self)
350
350
 
351
- self.pb_live_obs.setFocusPolicy(Qt.NoFocus)
351
+ self.pb_live_obs.setFocusPolicy(Qt.FocusPolicy.NoFocus)
352
352
 
353
353
  self.ffmpeg_bin = ffmpeg_bin
354
354
  # set icons
@@ -379,7 +379,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
379
379
 
380
380
  self.lbLogoBoris.setPixmap(QPixmap(":/logo"))
381
381
  self.lbLogoBoris.setScaledContents(False)
382
- self.lbLogoBoris.setAlignment(Qt.AlignCenter)
382
+ self.lbLogoBoris.setAlignment(Qt.AlignmentFlag.AlignCenter)
383
383
 
384
384
  self.toolBar.setEnabled(True)
385
385
 
@@ -413,13 +413,13 @@ class MainWindow(QMainWindow, Ui_MainWindow):
413
413
 
414
414
  # observation time interval
415
415
  self.lb_obs_time_interval = QLabel()
416
- self.lb_obs_time_interval.setFrameStyle(QFrame.StyledPanel)
416
+ self.lb_obs_time_interval.setFrameStyle(QFrame.Shape.StyledPanel)
417
417
  self.lb_obs_time_interval.setMinimumWidth(160)
418
418
  self.statusbar.addPermanentWidget(self.lb_obs_time_interval)
419
419
 
420
420
  # time offset
421
421
  self.lbTimeOffset = QLabel()
422
- self.lbTimeOffset.setFrameStyle(QFrame.StyledPanel)
422
+ self.lbTimeOffset.setFrameStyle(QFrame.Shape.StyledPanel)
423
423
  self.lbTimeOffset.setMinimumWidth(160)
424
424
  self.statusbar.addPermanentWidget(self.lbTimeOffset)
425
425
 
@@ -450,9 +450,9 @@ class MainWindow(QMainWindow, Ui_MainWindow):
450
450
  for w in (self.dwEvents, self.dwEthogram, self.dwSubjects):
451
451
  if self.action_block_dockwidgets.isChecked():
452
452
  w.setFloating(False)
453
- w.setFeatures(QDockWidget.NoDockWidgetFeatures)
453
+ w.setFeatures(QDockWidget.DockWidgetFeature.NoDockWidgetFeatures)
454
454
  else:
455
- w.setFeatures(QDockWidget.DockWidgetMovable | QDockWidget.DockWidgetFloatable)
455
+ w.setFeatures(QDockWidget.DockWidgetFeature.DockWidgetMovable | QDockWidget.DockWidgetFeature.DockWidgetFloatable)
456
456
 
457
457
  def advanced_event_filtering(self):
458
458
  """
@@ -524,7 +524,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
524
524
  "Removing the path of media files and image directories from the project file is irreversible.<br>"
525
525
  "Are you sure to continue?"
526
526
  ),
527
- [cfg.YES, cfg.NO],
527
+ (cfg.YES, cfg.NO),
528
528
  )
529
529
  == cfg.NO
530
530
  ):
@@ -542,13 +542,13 @@ class MainWindow(QMainWindow, Ui_MainWindow):
542
542
  dialog.MessageDialog(
543
543
  cfg.programName,
544
544
  ("Removing the path of external data files is irreversible.<br>Are you sure to continue?"),
545
- [cfg.YES, cfg.NO],
545
+ (cfg.YES, cfg.NO),
546
546
  )
547
547
  == cfg.NO
548
548
  ):
549
549
  return
550
550
 
551
- if project_functions.remove_data_files_path(self.pj, self.projectFileName):
551
+ if project_functions.remove_data_files_path(self.pj):
552
552
  self.project_changed()
553
553
 
554
554
  def set_media_files_path_relative_to_project_dir(self):
@@ -560,7 +560,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
560
560
  dialog.MessageDialog(
561
561
  cfg.programName,
562
562
  ("Are you sure to continue?"),
563
- [cfg.YES, cfg.NO],
563
+ (cfg.YES, cfg.NO),
564
564
  )
565
565
  == cfg.NO
566
566
  ):
@@ -577,7 +577,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
577
577
  dialog.MessageDialog(
578
578
  cfg.programName,
579
579
  ("Are you sure to continue?"),
580
- [cfg.YES, cfg.NO],
580
+ (cfg.YES, cfg.NO),
581
581
  )
582
582
  == cfg.NO
583
583
  ):
@@ -697,7 +697,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
697
697
  QMessageBox.warning(self, cfg.programName, "No subjects to show")
698
698
  return
699
699
  self.subjects_pad = subjects_pad.SubjectsPad(self.pj, filtered_subjects)
700
- self.subjects_pad.setWindowFlags(Qt.WindowStaysOnTopHint)
700
+ self.subjects_pad.setWindowFlags(Qt.WindowType.WindowStaysOnTopHint)
701
701
  self.subjects_pad.sendEventSignal.connect(self.signal_from_subjects_pad)
702
702
  self.subjects_pad.click_signal.connect(self.click_signal_from_subjects_pad)
703
703
  self.subjects_pad.close_signal.connect(self.close_signal_from_subjects_pad)
@@ -918,7 +918,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
918
918
  w = dialog.Info_widget()
919
919
  w.lwi.setVisible(False)
920
920
  w.resize(350, 100)
921
- w.setWindowFlags(Qt.WindowStaysOnTopHint)
921
+ w.setWindowFlags(Qt.WindowType.WindowStaysOnTopHint)
922
922
  w.setWindowTitle(cfg.programName)
923
923
  w.label.setText("Extracting WAV from media files...")
924
924
 
@@ -1000,7 +1000,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
1000
1000
  f"You choose to visualize the {plot_type} during this observation.<br>"
1001
1001
  f"{plot_type} generation can take some time for long media, be patient"
1002
1002
  ),
1003
- [cfg.YES, cfg.NO],
1003
+ (cfg.YES, cfg.NO),
1004
1004
  )
1005
1005
  == cfg.NO
1006
1006
  ):
@@ -1018,8 +1018,8 @@ class MainWindow(QMainWindow, Ui_MainWindow):
1018
1018
 
1019
1019
  self.spectro = plot_spectrogram_rt.Plot_spectrogram_RT()
1020
1020
 
1021
- self.spectro.setWindowFlags(Qt.WindowStaysOnTopHint)
1022
- self.spectro.setWindowFlags(self.spectro.windowFlags() & ~Qt.WindowMinimizeButtonHint)
1021
+ self.spectro.setWindowFlags(Qt.WindowType.WindowStaysOnTopHint)
1022
+ self.spectro.setWindowFlags(self.spectro.windowFlags() & ~Qt.WindowType.WindowMinimizeButtonHint)
1023
1023
 
1024
1024
  self.spectro.interval = self.spectrogram_time_interval
1025
1025
  self.spectro.cursor_color = cfg.REALTIME_PLOT_CURSOR_COLOR
@@ -1039,8 +1039,8 @@ class MainWindow(QMainWindow, Ui_MainWindow):
1039
1039
  self,
1040
1040
  cfg.programName,
1041
1041
  f"Error in spectrogram generation: {r['error']}",
1042
- QMessageBox.Ok | QMessageBox.Default,
1043
- QMessageBox.NoButton,
1042
+ QMessageBox.StandardButton.Ok,
1043
+ QMessageBox.StandardButton.NoButton,
1044
1044
  )
1045
1045
  del self.spectro
1046
1046
  return
@@ -1091,7 +1091,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
1091
1091
  "You choose to visualize the waveform during this observation.<br>"
1092
1092
  "The waveform generation can take some time for long media, be patient"
1093
1093
  ),
1094
- [cfg.YES, cfg.NO],
1094
+ (cfg.YES, cfg.NO),
1095
1095
  )
1096
1096
  == cfg.NO
1097
1097
  ):
@@ -1109,7 +1109,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
1109
1109
 
1110
1110
  self.waveform = plot_waveform_rt.Plot_waveform_RT()
1111
1111
 
1112
- self.waveform.setWindowFlags(Qt.WindowStaysOnTopHint)
1112
+ self.waveform.setWindowFlags(Qt.WindowType.WindowStaysOnTopHint)
1113
1113
  self.waveform.setWindowFlags(self.waveform.windowFlags() & ~Qt.WindowMinimizeButtonHint)
1114
1114
 
1115
1115
  self.waveform.interval = self.spectrogram_time_interval
@@ -1122,8 +1122,8 @@ class MainWindow(QMainWindow, Ui_MainWindow):
1122
1122
  self,
1123
1123
  cfg.programName,
1124
1124
  f"Error in waveform generation: {r['error']}",
1125
- QMessageBox.Ok | QMessageBox.Default,
1126
- QMessageBox.NoButton,
1125
+ QMessageBox.StandardButton.Ok,
1126
+ QMessageBox.StandardButton.NoButton,
1127
1127
  )
1128
1128
  del self.waveform
1129
1129
  return
@@ -1146,7 +1146,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
1146
1146
 
1147
1147
  self.plot_events = plot_events_rt.Plot_events_RT()
1148
1148
 
1149
- self.plot_events.setWindowFlags(Qt.WindowStaysOnTopHint)
1149
+ self.plot_events.setWindowFlags(Qt.WindowType.WindowStaysOnTopHint)
1150
1150
  self.plot_events.setWindowFlags(self.plot_events.windowFlags() & ~Qt.WindowMinimizeButtonHint)
1151
1151
 
1152
1152
  self.plot_events.groupby = "behaviors"
@@ -1285,8 +1285,8 @@ class MainWindow(QMainWindow, Ui_MainWindow):
1285
1285
  self,
1286
1286
  cfg.programName,
1287
1287
  "No project found",
1288
- QMessageBox.Ok | QMessageBox.Default,
1289
- QMessageBox.NoButton,
1288
+ QMessageBox.StandardButton.Ok,
1289
+ QMessageBox.StandardButton.NoButton,
1290
1290
  )
1291
1291
  return
1292
1292
 
@@ -1301,7 +1301,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
1301
1301
  f"with the same name (<b>{behav_coding_map['name']}</b>).<br>"
1302
1302
  "What do you want to do?"
1303
1303
  ),
1304
- ["Replace the coding map", cfg.CANCEL],
1304
+ ("Replace the coding map", cfg.CANCEL),
1305
1305
  )
1306
1306
  if response == cfg.CANCEL:
1307
1307
  return
@@ -1658,7 +1658,9 @@ class MainWindow(QMainWindow, Ui_MainWindow):
1658
1658
  time.sleep(0.3) # required for correct frame number
1659
1659
 
1660
1660
  dw.frame_viewer.setPixmap(
1661
- util.pil2pixmap(dw.player.screenshot_raw()).scaled(dw.frame_viewer.size(), Qt.KeepAspectRatio, Qt.SmoothTransformation)
1661
+ util.pil2pixmap(dw.player.screenshot_raw()).scaled(
1662
+ dw.frame_viewer.size(), Qt.AspectRatioMode.KeepAspectRatio, Qt.TransformationMode.SmoothTransformation
1663
+ )
1662
1664
  )
1663
1665
 
1664
1666
  if self.playerType == cfg.IMAGES:
@@ -1667,8 +1669,8 @@ class MainWindow(QMainWindow, Ui_MainWindow):
1667
1669
  None,
1668
1670
  cfg.programName,
1669
1671
  ("The picture directory has changed since the creation of observation."),
1670
- QMessageBox.Ok | QMessageBox.Default,
1671
- QMessageBox.NoButton,
1672
+ QMessageBox.StandardButton.Ok,
1673
+ QMessageBox.StandardButton.NoButton,
1672
1674
  )
1673
1675
  return
1674
1676
 
@@ -1806,7 +1808,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
1806
1808
  self,
1807
1809
  "Select a directory to save the frames",
1808
1810
  os.path.expanduser("~"),
1809
- options=QFileDialog.ShowDirsOnly,
1811
+ options=QFileDialog.Option.ShowDirsOnly,
1810
1812
  )
1811
1813
  if not output_dir:
1812
1814
  return
@@ -2188,8 +2190,8 @@ class MainWindow(QMainWindow, Ui_MainWindow):
2188
2190
  None,
2189
2191
  cfg.programName,
2190
2192
  ("This function is not yet implemented"),
2191
- QMessageBox.Ok | QMessageBox.Default,
2192
- QMessageBox.NoButton,
2193
+ QMessageBox.StandardButton.Ok,
2194
+ QMessageBox.StandardButton.NoButton,
2193
2195
  )
2194
2196
 
2195
2197
  return
@@ -2280,7 +2282,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
2280
2282
  self.tv_events.setModel(model)
2281
2283
 
2282
2284
  # column width
2283
- self.tv_events.horizontalHeader().setSectionResizeMode(QHeaderView.Interactive)
2285
+ self.tv_events.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeMode.Interactive)
2284
2286
 
2285
2287
  def load_tw_events(self, obs_id) -> None:
2286
2288
  """
@@ -2544,8 +2546,8 @@ class MainWindow(QMainWindow, Ui_MainWindow):
2544
2546
  None,
2545
2547
  cfg.programName,
2546
2548
  ("This function is not available for observations with events that do not have timestamp"),
2547
- QMessageBox.Ok | QMessageBox.Default,
2548
- QMessageBox.NoButton,
2549
+ QMessageBox.StandardButton.Ok,
2550
+ QMessageBox.StandardButton.NoButton,
2549
2551
  )
2550
2552
  return
2551
2553
 
@@ -2557,7 +2559,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
2557
2559
  self,
2558
2560
  "Choose a directory to save the plots",
2559
2561
  os.path.expanduser("~"),
2560
- options=QFileDialog.ShowDirsOnly,
2562
+ options=QFileDialog.Option.ShowDirsOnly,
2561
2563
  )
2562
2564
 
2563
2565
  if not plot_directory:
@@ -2660,8 +2662,8 @@ class MainWindow(QMainWindow, Ui_MainWindow):
2660
2662
  None,
2661
2663
  cfg.programName,
2662
2664
  ("The duration of one or more observation is not available"),
2663
- QMessageBox.Ok | QMessageBox.Default,
2664
- QMessageBox.NoButton,
2665
+ QMessageBox.StandardButton.Ok,
2666
+ QMessageBox.StandardButton.NoButton,
2665
2667
  )
2666
2668
  return
2667
2669
 
@@ -2673,8 +2675,8 @@ class MainWindow(QMainWindow, Ui_MainWindow):
2673
2675
  None,
2674
2676
  cfg.programName,
2675
2677
  ("This function is not available for observations with events that do not have timestamp"),
2676
- QMessageBox.Ok | QMessageBox.Default,
2677
- QMessageBox.NoButton,
2678
+ QMessageBox.StandardButton.Ok,
2679
+ QMessageBox.StandardButton.NoButton,
2678
2680
  )
2679
2681
  return
2680
2682
 
@@ -2709,7 +2711,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
2709
2711
  self,
2710
2712
  "Choose a directory to save the plots",
2711
2713
  os.path.expanduser("~"),
2712
- options=QFileDialog.ShowDirsOnly,
2714
+ options=QFileDialog.Option.ShowDirsOnly,
2713
2715
  )
2714
2716
  if not plot_directory:
2715
2717
  return
@@ -2777,7 +2779,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
2777
2779
  dialog.MessageDialog(
2778
2780
  cfg.programName,
2779
2781
  "There is a current observation. What do you want to do?",
2780
- ["Close observation", "Continue observation"],
2782
+ ("Close observation", "Continue observation"),
2781
2783
  )
2782
2784
  == "Close observation"
2783
2785
  ):
@@ -2789,7 +2791,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
2789
2791
  response = dialog.MessageDialog(
2790
2792
  cfg.programName,
2791
2793
  "What to do about the current unsaved project?",
2792
- [cfg.SAVE, cfg.DISCARD, cfg.CANCEL],
2794
+ (cfg.SAVE, cfg.DISCARD, cfg.CANCEL),
2793
2795
  )
2794
2796
 
2795
2797
  if response == cfg.SAVE:
@@ -2849,7 +2851,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
2849
2851
  "In this project all the behavior and subject keys are upper case.<br>"
2850
2852
  "Do you want to convert them in lower case?"
2851
2853
  ),
2852
- [cfg.YES, cfg.NO],
2854
+ (cfg.YES, cfg.NO),
2853
2855
  )
2854
2856
  == cfg.YES
2855
2857
  ):
@@ -2901,7 +2903,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
2901
2903
  dialog.MessageDialog(
2902
2904
  cfg.programName,
2903
2905
  "There is a current observation. What do you want to do?",
2904
- ["Close observation", "Continue observation"],
2906
+ ("Close observation", "Continue observation"),
2905
2907
  )
2906
2908
  == "Close observation"
2907
2909
  ):
@@ -2913,7 +2915,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
2913
2915
  response = dialog.MessageDialog(
2914
2916
  cfg.programName,
2915
2917
  "What to do about the current unsaved project?",
2916
- [cfg.SAVE, cfg.DISCARD, cfg.CANCEL],
2918
+ (cfg.SAVE, cfg.DISCARD, cfg.CANCEL),
2917
2919
  )
2918
2920
 
2919
2921
  if response == cfg.SAVE:
@@ -2964,7 +2966,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
2964
2966
  response = dialog.MessageDialog(
2965
2967
  cfg.programName,
2966
2968
  "There is a current observation. What do you want to do?",
2967
- ["Close observation", "Continue observation"],
2969
+ ("Close observation", "Continue observation"),
2968
2970
  )
2969
2971
  if response == "Close observation":
2970
2972
  observation_operations.close_observation(self)
@@ -2975,7 +2977,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
2975
2977
  response = dialog.MessageDialog(
2976
2978
  cfg.programName,
2977
2979
  "What to do about the current unsaved project?",
2978
- [cfg.SAVE, cfg.DISCARD, cfg.CANCEL],
2980
+ (cfg.SAVE, cfg.DISCARD, cfg.CANCEL),
2979
2981
  )
2980
2982
  if response == cfg.SAVE:
2981
2983
  if self.save_project_activated() == "not saved":
@@ -3019,7 +3021,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
3019
3021
  response = dialog.MessageDialog(
3020
3022
  cfg.programName,
3021
3023
  "The current observation will be closed. Do you want to continue?",
3022
- [cfg.YES, cfg.NO],
3024
+ (cfg.YES, cfg.NO),
3023
3025
  )
3024
3026
  if response == cfg.NO:
3025
3027
  self.show_data_files()
@@ -3032,7 +3034,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
3032
3034
  response = dialog.MessageDialog(
3033
3035
  cfg.programName,
3034
3036
  "What to do with the current unsaved project?",
3035
- [cfg.SAVE, cfg.DISCARD, cfg.CANCEL],
3037
+ (cfg.SAVE, cfg.DISCARD, cfg.CANCEL),
3036
3038
  )
3037
3039
 
3038
3040
  if response == cfg.SAVE:
@@ -3233,7 +3235,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
3233
3235
 
3234
3236
  del newProjectWindow
3235
3237
 
3236
- def save_project_json(self, project_file_name: str) -> int:
3238
+ def save_project_json(self, project_file_name: str) -> int | None:
3237
3239
  """
3238
3240
  save project to JSON file
3239
3241
  convert Decimal type in float
@@ -3299,21 +3301,21 @@ class MainWindow(QMainWindow, Ui_MainWindow):
3299
3301
  None,
3300
3302
  cfg.programName,
3301
3303
  "Permission denied to save the project file. Try another directory",
3302
- QMessageBox.Ok | QMessageBox.Default,
3303
- QMessageBox.NoButton,
3304
+ QMessageBox.StandardButton.Ok,
3305
+ QMessageBox.StandardButton.NoButton,
3304
3306
  )
3305
3307
  self.save_project_json_started = False
3306
3308
  return 1
3307
3309
 
3308
3310
  except OSError:
3309
3311
  _, value, _ = sys.exc_info()
3310
- QMessageBox.critical(None, cfg.programName, f"Error saving the project file: {value}", QMessageBox.Ok)
3312
+ QMessageBox.critical(None, cfg.programName, f"Error saving the project file: {value}", QMessageBox.StandardButton.Ok)
3311
3313
  self.save_project_json_started = False
3312
3314
  return 4
3313
3315
 
3314
3316
  except Exception:
3315
3317
  _, value, _ = sys.exc_info()
3316
- QMessageBox.critical(None, cfg.programName, f"Error saving the project file: {value}", QMessageBox.Ok)
3318
+ QMessageBox.critical(None, cfg.programName, f"Error saving the project file: {value}", QMessageBox.StandardButton.Ok)
3317
3319
  self.save_project_json_started = False
3318
3320
  return 2
3319
3321
 
@@ -3344,7 +3346,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
3344
3346
  dialog.MessageDialog(
3345
3347
  cfg.programName,
3346
3348
  f"The file {project_new_file_name} already exists.",
3347
- [cfg.CANCEL, cfg.OVERWRITE],
3349
+ (cfg.CANCEL, cfg.OVERWRITE),
3348
3350
  )
3349
3351
  == cfg.CANCEL
3350
3352
  ):
@@ -3360,7 +3362,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
3360
3362
  dialog.MessageDialog(
3361
3363
  cfg.programName,
3362
3364
  f"The file {project_new_file_name} already exists.",
3363
- [cfg.CANCEL, cfg.OVERWRITE],
3365
+ (cfg.CANCEL, cfg.OVERWRITE),
3364
3366
  )
3365
3367
  == cfg.CANCEL
3366
3368
  ):
@@ -3440,7 +3442,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
3440
3442
  dialog.MessageDialog(
3441
3443
  cfg.programName,
3442
3444
  f"The file {self.projectFileName} already exists.",
3443
- [cfg.CANCEL, cfg.OVERWRITE],
3445
+ (cfg.CANCEL, cfg.OVERWRITE),
3444
3446
  )
3445
3447
  == cfg.CANCEL
3446
3448
  ):
@@ -3459,7 +3461,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
3459
3461
  dialog.MessageDialog(
3460
3462
  cfg.programName,
3461
3463
  f"The file {self.projectFileName} already exists.",
3462
- [cfg.CANCEL, cfg.OVERWRITE],
3464
+ (cfg.CANCEL, cfg.OVERWRITE),
3463
3465
  )
3464
3466
  == cfg.CANCEL
3465
3467
  ):
@@ -3622,8 +3624,8 @@ class MainWindow(QMainWindow, Ui_MainWindow):
3622
3624
  None,
3623
3625
  cfg.programName,
3624
3626
  ("This function is not available for observations with events that do not have timestamp"),
3625
- QMessageBox.Ok | QMessageBox.Default,
3626
- QMessageBox.NoButton,
3627
+ QMessageBox.StandardButton.Ok,
3628
+ QMessageBox.StandardButton.NoButton,
3627
3629
  )
3628
3630
  return
3629
3631
 
@@ -3656,7 +3658,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
3656
3658
  self,
3657
3659
  "Choose a directory to save subtitles",
3658
3660
  os.path.expanduser("~"),
3659
- options=QFileDialog.ShowDirsOnly,
3661
+ options=QFileDialog.Option.ShowDirsOnly,
3660
3662
  )
3661
3663
  if not export_dir:
3662
3664
  return
@@ -3667,8 +3669,8 @@ class MainWindow(QMainWindow, Ui_MainWindow):
3667
3669
  None,
3668
3670
  cfg.programName,
3669
3671
  f"Error creating subtitles: {msg}",
3670
- QMessageBox.Ok | QMessageBox.Default,
3671
- QMessageBox.NoButton,
3672
+ QMessageBox.StandardButton.Ok,
3673
+ QMessageBox.StandardButton.NoButton,
3672
3674
  )
3673
3675
 
3674
3676
  def next_frame(self) -> None:
@@ -3900,7 +3902,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
3900
3902
  msg_box = QMessageBox(
3901
3903
  QMessageBox.Critical, cfg.programName, f"The code <b>{code}</b> of behavior coding map does not exist in ethogram."
3902
3904
  )
3903
- msg_box.setWindowFlags(msg_box.windowFlags() | Qt.WindowStaysOnTopHint)
3905
+ msg_box.setWindowFlags(msg_box.windowFlags() | Qt.WindowType.WindowStaysOnTopHint)
3904
3906
  msg_box.exec()
3905
3907
  return
3906
3908
 
@@ -4062,17 +4064,18 @@ class MainWindow(QMainWindow, Ui_MainWindow):
4062
4064
 
4063
4065
  Args:
4064
4066
  n_player (int): player
4065
- new_time (int): new time in ms
4067
+ new_time (float): new time in ms
4066
4068
  """
4069
+ new_time_dec = dec(new_time)
4067
4070
 
4068
4071
  if self.dw_player[n_player].player.playlist_count == 1:
4069
4072
  if self.pj[cfg.OBSERVATIONS][self.observationId][cfg.MEDIA_INFO][cfg.OFFSET][str(n_player + 1)]:
4070
4073
  if self.pj[cfg.OBSERVATIONS][self.observationId][cfg.MEDIA_INFO][cfg.OFFSET][str(n_player + 1)] > 0:
4071
- if new_time < self.pj[cfg.OBSERVATIONS][self.observationId][cfg.MEDIA_INFO][cfg.OFFSET][str(n_player + 1)]:
4074
+ if new_time_dec < self.pj[cfg.OBSERVATIONS][self.observationId][cfg.MEDIA_INFO][cfg.OFFSET][str(n_player + 1)]:
4072
4075
  # hide video and mute audio if time < offset
4073
4076
  self.media_player_enabled(n_player, enable=False)
4074
4077
  else:
4075
- if new_time - dec(
4078
+ if new_time_dec - dec(
4076
4079
  self.pj[cfg.OBSERVATIONS][self.observationId][cfg.MEDIA_INFO][cfg.OFFSET][str(n_player + 1)]
4077
4080
  ) > sum(self.dw_player[n_player].media_durations):
4078
4081
  # hide video and mute audio if required time > video time + offset
@@ -4081,26 +4084,27 @@ class MainWindow(QMainWindow, Ui_MainWindow):
4081
4084
  # show video and enable audio
4082
4085
  self.media_player_enabled(n_player, enable=True)
4083
4086
  self.seek_mediaplayer(
4084
- new_time
4087
+ new_time_dec
4085
4088
  - dec(self.pj[cfg.OBSERVATIONS][self.observationId][cfg.MEDIA_INFO][cfg.OFFSET][str(n_player + 1)]),
4086
4089
  player=n_player,
4087
4090
  )
4088
4091
 
4089
4092
  elif self.pj[cfg.OBSERVATIONS][self.observationId][cfg.MEDIA_INFO][cfg.OFFSET][str(n_player + 1)] < 0:
4090
- if new_time - dec(self.pj[cfg.OBSERVATIONS][self.observationId][cfg.MEDIA_INFO][cfg.OFFSET][str(n_player + 1)]) > sum(
4091
- self.dw_player[n_player].media_durations
4092
- ):
4093
+ if new_time_dec - dec(
4094
+ self.pj[cfg.OBSERVATIONS][self.observationId][cfg.MEDIA_INFO][cfg.OFFSET][str(n_player + 1)]
4095
+ ) > sum(self.dw_player[n_player].media_durations):
4093
4096
  # hide video and mute audio if required time > video time + offset
4094
4097
  self.media_player_enabled(n_player, enable=False)
4095
4098
  else:
4096
4099
  self.media_player_enabled(n_player, enable=True)
4097
4100
  self.seek_mediaplayer(
4098
- new_time - dec(self.pj[cfg.OBSERVATIONS][self.observationId][cfg.MEDIA_INFO][cfg.OFFSET][str(n_player + 1)]),
4101
+ new_time_dec
4102
+ - dec(self.pj[cfg.OBSERVATIONS][self.observationId][cfg.MEDIA_INFO][cfg.OFFSET][str(n_player + 1)]),
4099
4103
  player=n_player,
4100
4104
  )
4101
4105
 
4102
4106
  else: # no offset
4103
- self.seek_mediaplayer(new_time, player=n_player)
4107
+ self.seek_mediaplayer(new_time_dec, player=n_player)
4104
4108
 
4105
4109
  elif self.dw_player[n_player].player.playlist_count > 1:
4106
4110
  # check if new time is before the end of last video
@@ -4297,9 +4301,8 @@ class MainWindow(QMainWindow, Ui_MainWindow):
4297
4301
  self.mem_media_name = current_media_name
4298
4302
  self.mem_playlist_index = current_playlist_index
4299
4303
 
4300
- playlist_length = len(self.dw_player[0].player.playlist)
4301
-
4302
4304
  # update observation info
4305
+ playlist_length = len(playlist) if playlist else 0
4303
4306
  msg = ""
4304
4307
  if self.dw_player[0].player.time_pos is not None: # check if video
4305
4308
  msg = f"Current media name: <b>{current_media_name}</b> (#{self.dw_player[0].player.playlist_pos + 1} / {playlist_length})<br>"