boris-behav-obs 9.4.1__py2.py3-none-any.whl → 9.5.2__py2.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/preferences.py CHANGED
@@ -35,6 +35,7 @@ from .preferences_ui import Ui_prefDialog
35
35
 
36
36
  from PySide6.QtWidgets import QDialog, QFileDialog, QListWidgetItem, QMessageBox
37
37
  from PySide6.QtCore import Qt
38
+ from PySide6.QtGui import QFont
38
39
 
39
40
 
40
41
  class Preferences(QDialog, Ui_prefDialog):
@@ -43,8 +44,6 @@ class Preferences(QDialog, Ui_prefDialog):
43
44
  self.setupUi(self)
44
45
 
45
46
  # plugins
46
- """self.pb_add_plugin.clicked.connect(self.add_plugin)
47
- self.pb_remove_plugin.clicked.connect(self.remove_plugin)"""
48
47
  self.pb_browse_plugins_dir.clicked.connect(self.browse_plugins_dir)
49
48
 
50
49
  self.pbBrowseFFmpegCacheDir.clicked.connect(self.browseFFmpegCacheDir)
@@ -58,6 +57,12 @@ class Preferences(QDialog, Ui_prefDialog):
58
57
 
59
58
  self.flag_refresh = False
60
59
 
60
+ # Create a monospace QFont
61
+ monospace_font = QFont("Courier New") # or "Monospace", "Consolas", "Liberation Mono", etc.
62
+ monospace_font.setStyleHint(QFont.Monospace)
63
+ monospace_font.setPointSize(13)
64
+ self.pte_plugin_code.setFont(monospace_font)
65
+
61
66
  def browse_plugins_dir(self):
62
67
  """
63
68
  get the personal plugins directory
@@ -69,14 +74,21 @@ class Preferences(QDialog, Ui_prefDialog):
69
74
  self.le_personal_plugins_dir.setText(directory)
70
75
  self.lw_personal_plugins.clear()
71
76
  for file_ in Path(directory).glob("*.py"):
72
- item = QListWidgetItem(file_.stem)
77
+ if file_.name.startswith("_"):
78
+ continue
79
+ plugin_name = plugins.get_plugin_name(file_)
80
+ if plugin_name is None:
81
+ continue
82
+ # check if personal plugin name is in BORIS plugins (case sensitive)
83
+ if plugin_name in [self.lv_all_plugins.item(i).text() for i in range(self.lv_all_plugins.count())]:
84
+ continue
85
+ item = QListWidgetItem(plugin_name)
86
+ # item = QListWidgetItem(file_.stem)
73
87
  item.setFlags(item.flags() | Qt.ItemIsUserCheckable)
74
- # if plugin_name in self.config_param.get(cfg.EXCLUDED_PLUGINS, set()):
75
- # item.setCheckState(Qt.Unchecked)
76
- # else:
77
88
  item.setCheckState(Qt.Checked)
78
- item.setData(100, file_.stem)
89
+ item.setData(100, str(file_))
79
90
  self.lw_personal_plugins.addItem(item)
91
+
80
92
  if self.lw_personal_plugins.count() == 0:
81
93
  QMessageBox.warning(self, cfg.programName, f"No plugin found in {directory}")
82
94
 
@@ -87,7 +99,7 @@ class Preferences(QDialog, Ui_prefDialog):
87
99
  if (
88
100
  dialog.MessageDialog(
89
101
  "BORIS",
90
- ("Refresh will re-initialize " "all your preferences and close BORIS"),
102
+ ("Refresh will re-initialize all your preferences and close BORIS"),
91
103
  [cfg.CANCEL, "Refresh preferences"],
92
104
  )
93
105
  == "Refresh preferences"
@@ -138,21 +150,39 @@ def preferences(self):
138
150
  if item.text() not in self.config_param[cfg.ANALYSIS_PLUGINS]:
139
151
  return
140
152
 
141
- import importlib
142
-
143
153
  plugin_path = item.data(100)
144
154
 
145
- module_name = Path(plugin_path).stem
146
- spec = importlib.util.spec_from_file_location(module_name, plugin_path)
147
- plugin_module = importlib.util.module_from_spec(spec)
148
- spec.loader.exec_module(plugin_module)
149
- out: list = []
150
- out.append(plugin_module.__plugin_name__ + "\n")
151
- out.append(plugin_module.__author__)
152
- out.append(f"{plugin_module.__version__} ({plugin_module.__version_date__})\n")
153
- out.append(plugin_module.run.__doc__.strip())
155
+ if Path(plugin_path).suffix == ".py":
156
+ import importlib
157
+
158
+ module_name = Path(plugin_path).stem
159
+ spec = importlib.util.spec_from_file_location(module_name, plugin_path)
160
+ plugin_module = importlib.util.module_from_spec(spec)
161
+ spec.loader.exec_module(plugin_module)
162
+
163
+ out: list = []
164
+ out.append(plugin_module.__plugin_name__ + "\n")
165
+ out.append(plugin_module.__author__)
166
+ out.append(f"{plugin_module.__version__} ({plugin_module.__version_date__})\n")
167
+ out.append(plugin_module.run.__doc__.strip())
154
168
 
155
- preferencesWindow.pte_plugin_description.setPlainText("\n".join(out))
169
+ preferencesWindow.pte_plugin_description.setPlainText("\n".join(out))
170
+
171
+ if Path(plugin_path).suffix == ".R":
172
+ plugin_description = plugins.get_r_plugin_description(plugin_path)
173
+ if plugin_description is not None:
174
+ preferencesWindow.pte_plugin_description.setPlainText("\n".join(plugin_description.split("\\n")))
175
+ else:
176
+ preferencesWindow.pte_plugin_description.setPlainText("Plugin description not found")
177
+
178
+ # display plugin code
179
+ try:
180
+ with open(plugin_path, "r") as f_in:
181
+ plugin_code = f_in.read()
182
+ except Exception:
183
+ plugin_code = "Not available"
184
+
185
+ preferencesWindow.pte_plugin_code.setPlainText(plugin_code)
156
186
 
157
187
  preferencesWindow = Preferences()
158
188
  preferencesWindow.tabWidget.setCurrentIndex(0)
@@ -205,7 +235,7 @@ def preferences(self):
205
235
  preferencesWindow.lv_all_plugins.clear()
206
236
 
207
237
  for file_ in (Path(__file__).parent / "analysis_plugins").glob("*.py"):
208
- if file_.name == "__init__.py":
238
+ if file_.name.startswith("_"):
209
239
  continue
210
240
  plugin_name = plugins.get_plugin_name(file_)
211
241
  if plugin_name is not None:
@@ -225,7 +255,7 @@ def preferences(self):
225
255
  preferencesWindow.lw_personal_plugins.clear()
226
256
  if self.config_param.get(cfg.PERSONAL_PLUGINS_DIR, ""):
227
257
  for file_ in Path(self.config_param[cfg.PERSONAL_PLUGINS_DIR]).glob("*.py"):
228
- if file_.name == "__init__.py":
258
+ if file_.name.startswith("_"):
229
259
  continue
230
260
  plugin_name = plugins.get_plugin_name(file_)
231
261
  if plugin_name is None:
@@ -242,6 +272,22 @@ def preferences(self):
242
272
  item.setData(100, str(file_))
243
273
  preferencesWindow.lw_personal_plugins.addItem(item)
244
274
 
275
+ for file_ in Path(self.config_param[cfg.PERSONAL_PLUGINS_DIR]).glob("*.R"):
276
+ plugin_name = plugins.get_r_plugin_name(file_)
277
+ if plugin_name is None:
278
+ continue
279
+ # check if personal plugin name is in BORIS plugins (case sensitive)
280
+ if plugin_name in [preferencesWindow.lv_all_plugins.item(i).text() for i in range(preferencesWindow.lv_all_plugins.count())]:
281
+ continue
282
+ item = QListWidgetItem(plugin_name)
283
+ item.setFlags(item.flags() | Qt.ItemIsUserCheckable)
284
+ if plugin_name in self.config_param.get(cfg.EXCLUDED_PLUGINS, set()):
285
+ item.setCheckState(Qt.Unchecked)
286
+ else:
287
+ item.setCheckState(Qt.Checked)
288
+ item.setData(100, str(file_))
289
+ preferencesWindow.lw_personal_plugins.addItem(item)
290
+
245
291
  # PROJET FILE INDENTATION
246
292
  preferencesWindow.combo_project_file_indentation.clear()
247
293
  preferencesWindow.combo_project_file_indentation.addItems(cfg.PROJECT_FILE_INDENTATION_COMBO_OPTIONS)
@@ -272,16 +318,21 @@ def preferences(self):
272
318
  preferencesWindow.cbSpectrogramColorMap.setCurrentIndex(cfg.SPECTROGRAM_COLOR_MAPS.index(self.spectrogram_color_map))
273
319
  except Exception:
274
320
  preferencesWindow.cbSpectrogramColorMap.setCurrentIndex(cfg.SPECTROGRAM_COLOR_MAPS.index(cfg.SPECTROGRAM_DEFAULT_COLOR_MAP))
275
-
276
- try:
277
- preferencesWindow.cbSpectrogramColorMap.setCurrentIndex(cfg.SPECTROGRAM_COLOR_MAPS.index(self.spectrogram_color_map))
278
- except Exception:
279
- preferencesWindow.cbSpectrogramColorMap.setCurrentIndex(cfg.SPECTROGRAM_COLOR_MAPS.index(cfg.SPECTROGRAM_DEFAULT_COLOR_MAP))
280
-
321
+ # time interval
281
322
  try:
282
323
  preferencesWindow.sb_time_interval.setValue(self.spectrogram_time_interval)
283
324
  except Exception:
284
325
  preferencesWindow.sb_time_interval.setValue(cfg.SPECTROGRAM_DEFAULT_TIME_INTERVAL)
326
+ # window type
327
+ preferencesWindow.cb_window_type.setCurrentText(self.config_param.get(cfg.SPECTROGRAM_WINDOW_TYPE, cfg.SPECTROGRAM_DEFAULT_WINDOW_TYPE))
328
+ # NFFT
329
+ preferencesWindow.cb_NFFT.setCurrentText(self.config_param.get(cfg.SPECTROGRAM_NFFT, cfg.SPECTROGRAM_DEFAULT_NFFT))
330
+ # noverlap
331
+ preferencesWindow.sb_noverlap.setValue(self.config_param.get(cfg.SPECTROGRAM_NOVERLAP, cfg.SPECTROGRAM_DEFAULT_NOVERLAP))
332
+ # vmin
333
+ preferencesWindow.sb_vmin.setValue(self.config_param.get(cfg.SPECTROGRAM_VMIN, cfg.SPECTROGRAM_DEFAULT_VMIN))
334
+ # vmax
335
+ preferencesWindow.sb_vmax.setValue(self.config_param.get(cfg.SPECTROGRAM_VMAX, cfg.SPECTROGRAM_DEFAULT_VMAX))
285
336
 
286
337
  # behavior colors
287
338
  if not self.plot_colors:
@@ -298,114 +349,137 @@ def preferences(self):
298
349
 
299
350
  gui_utilities.restore_geometry(preferencesWindow, "preferences", (700, 500))
300
351
 
301
- if preferencesWindow.exec_():
302
- gui_utilities.save_geometry(preferencesWindow, "preferences")
352
+ while True:
353
+ if preferencesWindow.exec():
354
+ if preferencesWindow.sb_vmin.value() >= preferencesWindow.sb_vmax.value():
355
+ QMessageBox.warning(self, cfg.programName, "Spectrogram parameters: the vmin value must be lower than the vmax value.")
356
+ continue
357
+
358
+ if preferencesWindow.sb_noverlap.value() >= int(preferencesWindow.cb_NFFT.currentText()):
359
+ QMessageBox.warning(self, cfg.programName, "Spectrogram parameters: the noverlap value must be lower than the NFFT value.")
360
+ continue
303
361
 
304
- if preferencesWindow.flag_refresh:
305
- # refresh preferences remove the config file
362
+ gui_utilities.save_geometry(preferencesWindow, "preferences")
306
363
 
307
- logging.debug("flag refresh ")
364
+ if preferencesWindow.flag_refresh:
365
+ # refresh preferences remove the config file
308
366
 
309
- self.config_param["refresh_preferences"] = True
310
- self.close()
311
- # check if refresh canceled for not saved project
312
- if "refresh_preferences" in self.config_param:
313
- if (Path.home() / ".boris").exists():
314
- os.remove(Path.home() / ".boris")
315
- sys.exit()
367
+ logging.debug("flag refresh ")
316
368
 
317
- if preferencesWindow.cbTimeFormat.currentIndex() == 0:
318
- self.timeFormat = cfg.S
369
+ self.config_param["refresh_preferences"] = True
370
+ self.close()
371
+ # check if refresh canceled for not saved project
372
+ if "refresh_preferences" in self.config_param:
373
+ if (Path.home() / ".boris").exists():
374
+ os.remove(Path.home() / ".boris")
375
+ sys.exit()
319
376
 
320
- if preferencesWindow.cbTimeFormat.currentIndex() == 1:
321
- self.timeFormat = cfg.HHMMSS
377
+ if preferencesWindow.cbTimeFormat.currentIndex() == 0:
378
+ self.timeFormat = cfg.S
322
379
 
323
- self.fast = preferencesWindow.sbffSpeed.value()
380
+ if preferencesWindow.cbTimeFormat.currentIndex() == 1:
381
+ self.timeFormat = cfg.HHMMSS
324
382
 
325
- self.config_param[cfg.ADAPT_FAST_JUMP] = preferencesWindow.cb_adapt_fast_jump.isChecked()
383
+ self.fast = preferencesWindow.sbffSpeed.value()
326
384
 
327
- self.repositioningTimeOffset = preferencesWindow.sbRepositionTimeOffset.value()
385
+ self.config_param[cfg.ADAPT_FAST_JUMP] = preferencesWindow.cb_adapt_fast_jump.isChecked()
328
386
 
329
- self.play_rate_step = preferencesWindow.sbSpeedStep.value()
387
+ self.repositioningTimeOffset = preferencesWindow.sbRepositionTimeOffset.value()
330
388
 
331
- self.automaticBackup = preferencesWindow.sbAutomaticBackup.value()
332
- if self.automaticBackup:
333
- self.automaticBackupTimer.start(self.automaticBackup * 60000)
334
- else:
335
- self.automaticBackupTimer.stop()
389
+ self.play_rate_step = preferencesWindow.sbSpeedStep.value()
336
390
 
337
- self.behav_seq_separator = preferencesWindow.leSeparator.text()
391
+ self.automaticBackup = preferencesWindow.sbAutomaticBackup.value()
392
+ if self.automaticBackup:
393
+ self.automaticBackupTimer.start(self.automaticBackup * 60000)
394
+ else:
395
+ self.automaticBackupTimer.stop()
338
396
 
339
- self.close_the_same_current_event = preferencesWindow.cbCloseSameEvent.isChecked()
397
+ self.behav_seq_separator = preferencesWindow.leSeparator.text()
340
398
 
341
- self.confirmSound = preferencesWindow.cbConfirmSound.isChecked()
399
+ self.close_the_same_current_event = preferencesWindow.cbCloseSameEvent.isChecked()
342
400
 
343
- self.beep_every = preferencesWindow.sbBeepEvery.value()
401
+ self.confirmSound = preferencesWindow.cbConfirmSound.isChecked()
344
402
 
345
- self.alertNoFocalSubject = preferencesWindow.cbAlertNoFocalSubject.isChecked()
403
+ self.beep_every = preferencesWindow.sbBeepEvery.value()
346
404
 
347
- self.trackingCursorAboveEvent = preferencesWindow.cbTrackingCursorAboveEvent.isChecked()
405
+ self.alertNoFocalSubject = preferencesWindow.cbAlertNoFocalSubject.isChecked()
348
406
 
349
- self.checkForNewVersion = preferencesWindow.cbCheckForNewVersion.isChecked()
407
+ self.trackingCursorAboveEvent = preferencesWindow.cbTrackingCursorAboveEvent.isChecked()
350
408
 
351
- self.config_param[cfg.DISPLAY_SUBTITLES] = preferencesWindow.cb_display_subtitles.isChecked()
409
+ self.checkForNewVersion = preferencesWindow.cbCheckForNewVersion.isChecked()
352
410
 
353
- self.pause_before_addevent = preferencesWindow.cb_pause_before_addevent.isChecked()
411
+ self.config_param[cfg.DISPLAY_SUBTITLES] = preferencesWindow.cb_display_subtitles.isChecked()
354
412
 
355
- # MPV hwdec
356
- self.config_param[cfg.MPV_HWDEC] = cfg.MPV_HWDEC_OPTIONS[preferencesWindow.cb_hwdec.currentIndex()]
413
+ self.pause_before_addevent = preferencesWindow.cb_pause_before_addevent.isChecked()
357
414
 
358
- # check project integrity
359
- self.config_param[cfg.CHECK_PROJECT_INTEGRITY] = preferencesWindow.cb_check_integrity_at_opening.isChecked()
415
+ # MPV hwdec
416
+ self.config_param[cfg.MPV_HWDEC] = cfg.MPV_HWDEC_OPTIONS[preferencesWindow.cb_hwdec.currentIndex()]
360
417
 
361
- # update BORIS analysis plugins
362
- self.config_param[cfg.ANALYSIS_PLUGINS] = {}
363
- self.config_param[cfg.EXCLUDED_PLUGINS] = set()
364
- for i in range(preferencesWindow.lv_all_plugins.count()):
365
- if preferencesWindow.lv_all_plugins.item(i).checkState() == Qt.Checked:
366
- self.config_param[cfg.ANALYSIS_PLUGINS][preferencesWindow.lv_all_plugins.item(i).text()] = (
367
- preferencesWindow.lv_all_plugins.item(i).data(100)
368
- )
369
- else:
370
- self.config_param[cfg.EXCLUDED_PLUGINS].add(preferencesWindow.lv_all_plugins.item(i).text())
371
-
372
- # update personal plugins
373
- self.config_param[cfg.PERSONAL_PLUGINS_DIR] = preferencesWindow.le_personal_plugins_dir.text()
374
- for i in range(preferencesWindow.lw_personal_plugins.count()):
375
- if preferencesWindow.lw_personal_plugins.item(i).checkState() == Qt.Checked:
376
- self.config_param[cfg.ANALYSIS_PLUGINS][preferencesWindow.lw_personal_plugins.item(i).text()] = (
377
- preferencesWindow.lw_personal_plugins.item(i).data(100)
378
- )
379
- else:
380
- self.config_param[cfg.EXCLUDED_PLUGINS].add(preferencesWindow.lw_personal_plugins.item(i).text())
418
+ # check project integrity
419
+ self.config_param[cfg.CHECK_PROJECT_INTEGRITY] = preferencesWindow.cb_check_integrity_at_opening.isChecked()
381
420
 
382
- plugins.load_plugins(self)
383
- plugins.add_plugins_to_menu(self)
421
+ # update BORIS analysis plugins
422
+ self.config_param[cfg.ANALYSIS_PLUGINS] = {}
423
+ self.config_param[cfg.EXCLUDED_PLUGINS] = set()
424
+ for i in range(preferencesWindow.lv_all_plugins.count()):
425
+ if preferencesWindow.lv_all_plugins.item(i).checkState() == Qt.Checked:
426
+ self.config_param[cfg.ANALYSIS_PLUGINS][preferencesWindow.lv_all_plugins.item(i).text()] = (
427
+ preferencesWindow.lv_all_plugins.item(i).data(100)
428
+ )
429
+ else:
430
+ self.config_param[cfg.EXCLUDED_PLUGINS].add(preferencesWindow.lv_all_plugins.item(i).text())
384
431
 
385
- # project file indentation
386
- self.config_param[cfg.PROJECT_FILE_INDENTATION] = cfg.PROJECT_FILE_INDENTATION_OPTIONS[
387
- preferencesWindow.combo_project_file_indentation.currentIndex()
388
- ]
432
+ # update personal plugins
433
+ self.config_param[cfg.PERSONAL_PLUGINS_DIR] = preferencesWindow.le_personal_plugins_dir.text()
434
+ for i in range(preferencesWindow.lw_personal_plugins.count()):
435
+ if preferencesWindow.lw_personal_plugins.item(i).checkState() == Qt.Checked:
436
+ self.config_param[cfg.ANALYSIS_PLUGINS][preferencesWindow.lw_personal_plugins.item(i).text()] = (
437
+ preferencesWindow.lw_personal_plugins.item(i).data(100)
438
+ )
439
+ else:
440
+ self.config_param[cfg.EXCLUDED_PLUGINS].add(preferencesWindow.lw_personal_plugins.item(i).text())
389
441
 
390
- if self.observationId:
391
- self.load_tw_events(self.observationId)
392
- self.display_statusbar_info(self.observationId)
442
+ plugins.load_plugins(self)
443
+ plugins.add_plugins_to_menu(self)
393
444
 
394
- self.ffmpeg_cache_dir = preferencesWindow.leFFmpegCacheDir.text()
445
+ # project file indentation
446
+ self.config_param[cfg.PROJECT_FILE_INDENTATION] = cfg.PROJECT_FILE_INDENTATION_OPTIONS[
447
+ preferencesWindow.combo_project_file_indentation.currentIndex()
448
+ ]
449
+
450
+ if self.observationId:
451
+ self.load_tw_events(self.observationId)
452
+ self.display_statusbar_info(self.observationId)
453
+
454
+ self.ffmpeg_cache_dir = preferencesWindow.leFFmpegCacheDir.text()
395
455
 
396
- # spectrogram
397
- self.spectrogram_color_map = preferencesWindow.cbSpectrogramColorMap.currentText()
398
- # self.spectrogramHeight = preferencesWindow.sbSpectrogramHeight.value()
399
- self.spectrogram_time_interval = preferencesWindow.sb_time_interval.value()
456
+ # spectrogram
457
+ self.spectrogram_color_map = preferencesWindow.cbSpectrogramColorMap.currentText()
458
+ self.spectrogram_time_interval = preferencesWindow.sb_time_interval.value()
459
+ # window type
460
+ self.config_param[cfg.SPECTROGRAM_WINDOW_TYPE] = preferencesWindow.cb_window_type.currentText()
461
+ # NFFT
462
+ self.config_param[cfg.SPECTROGRAM_NFFT] = preferencesWindow.cb_NFFT.currentText()
463
+ # noverlap
464
+ self.config_param[cfg.SPECTROGRAM_NOVERLAP] = preferencesWindow.sb_noverlap.value()
465
+ # vmin
466
+ self.config_param[cfg.SPECTROGRAM_VMIN] = preferencesWindow.sb_vmin.value()
467
+ # vmax
468
+ self.config_param[cfg.SPECTROGRAM_VMAX] = preferencesWindow.sb_vmax.value()
400
469
 
401
- # behav colors
402
- self.plot_colors = preferencesWindow.te_behav_colors.toPlainText().split()
403
- # category colors
404
- self.behav_category_colors = preferencesWindow.te_category_colors.toPlainText().split()
470
+ # behav colors
471
+ self.plot_colors = preferencesWindow.te_behav_colors.toPlainText().split()
472
+ # category colors
473
+ self.behav_category_colors = preferencesWindow.te_category_colors.toPlainText().split()
405
474
 
406
- # interface
407
- self.config_param[cfg.TOOLBAR_ICON_SIZE] = preferencesWindow.sb_toolbar_icon_size.value()
475
+ # interface
476
+ self.config_param[cfg.TOOLBAR_ICON_SIZE] = preferencesWindow.sb_toolbar_icon_size.value()
408
477
 
409
- menu_options.update_menu(self)
478
+ menu_options.update_menu(self)
410
479
 
411
- config_file.save(self)
480
+ config_file.save(self)
481
+
482
+ break
483
+
484
+ else:
485
+ break