boris-behav-obs 9.4.1__py2.py3-none-any.whl → 9.5__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/plugins.py CHANGED
@@ -47,12 +47,12 @@ def add_plugins_to_menu(self):
47
47
  self.menu_plugins.addAction(action)
48
48
 
49
49
 
50
- def get_plugin_name(plugin_path: str):
50
+ def get_plugin_name(plugin_path: str) -> str | None:
51
51
  """
52
- get name of plugin
52
+ get name of a Python plugin
53
53
  """
54
54
  # search plugin name
55
- plugin_name = None
55
+ plugin_name: str | None = None
56
56
  with open(plugin_path, "r") as f_in:
57
57
  for line in f_in:
58
58
  if line.startswith("__plugin_name__"):
@@ -61,6 +61,48 @@ def get_plugin_name(plugin_path: str):
61
61
  return plugin_name
62
62
 
63
63
 
64
+ def get_r_plugin_name(plugin_path: str) -> str | None:
65
+ """
66
+ get name of a R plugin
67
+ """
68
+ # search plugin name
69
+ plugin_name: str | None = None
70
+ with open(plugin_path, "r") as f_in:
71
+ for line in f_in:
72
+ if line.startswith("plugin_name"):
73
+ if "=" in line:
74
+ plugin_name = line.split("=")[1].strip().replace('"', "").replace("'", "")
75
+ break
76
+ elif "<-" in line:
77
+ plugin_name = line.split("<-")[1].strip().replace('"', "").replace("'", "")
78
+ break
79
+ else:
80
+ plugin_name = None
81
+ break
82
+ return plugin_name
83
+
84
+
85
+ def get_r_plugin_description(plugin_path: str) -> str | None:
86
+ """
87
+ get description of a R plugin
88
+ """
89
+ # search plugin name
90
+ plugin_description: str | None = None
91
+ with open(plugin_path, "r") as f_in:
92
+ for line in f_in:
93
+ if line.startswith("description"):
94
+ if "=" in line:
95
+ plugin_description = line.split("=")[1].strip().replace('"', "").replace("'", "")
96
+ break
97
+ elif "<-" in line:
98
+ plugin_description = line.split("<-")[1].strip().replace('"', "").replace("'", "")
99
+ break
100
+ else:
101
+ plugin_description = None
102
+ break
103
+ return plugin_description
104
+
105
+
64
106
  def load_plugins(self):
65
107
  """
66
108
  load selected plugins in analysis menu
@@ -80,8 +122,6 @@ def load_plugins(self):
80
122
 
81
123
  # load BORIS plugins
82
124
  for file_ in sorted((Path(__file__).parent / "analysis_plugins").glob("*.py")):
83
- if file_.name == "__init__.py":
84
- continue
85
125
  if file_.name.startswith("_"):
86
126
  continue
87
127
  plugin_name = get_plugin_name(file_)
@@ -96,8 +136,6 @@ def load_plugins(self):
96
136
  # load personal plugins
97
137
  if self.config_param.get(cfg.PERSONAL_PLUGINS_DIR, ""):
98
138
  for file_ in sorted(Path(self.config_param.get(cfg.PERSONAL_PLUGINS_DIR, "")).glob("*.py")):
99
- if file_.name == "__init__.py":
100
- continue
101
139
  if file_.name.startswith("_"):
102
140
  continue
103
141
  plugin_name = get_plugin_name(file_)
@@ -109,6 +147,20 @@ def load_plugins(self):
109
147
 
110
148
  self.config_param[cfg.ANALYSIS_PLUGINS][plugin_name] = str(file_)
111
149
 
150
+ # load personal R plugins
151
+ if self.config_param.get(cfg.PERSONAL_PLUGINS_DIR, ""):
152
+ for file_ in sorted(Path(self.config_param.get(cfg.PERSONAL_PLUGINS_DIR, "")).glob("*.R")):
153
+ if file_.name.startswith("_"):
154
+ continue
155
+ plugin_name = get_r_plugin_name(file_)
156
+ if plugin_name is not None and plugin_name not in self.config_param.get(cfg.EXCLUDED_PLUGINS, set()):
157
+ # check if plugin with same name already loaded
158
+ if plugin_name in self.config_param[cfg.ANALYSIS_PLUGINS]:
159
+ msg()
160
+ continue
161
+
162
+ self.config_param[cfg.ANALYSIS_PLUGINS][plugin_name] = str(file_)
163
+
112
164
  logging.debug(f"{self.config_param.get(cfg.ANALYSIS_PLUGINS, {})=}")
113
165
 
114
166
 
@@ -203,7 +255,7 @@ def run_plugin(self, plugin_name):
203
255
  QMessageBox.critical(self, cfg.programName, f"Plugin '{plugin_name}' not found")
204
256
  return
205
257
 
206
- plugin_path = self.config_param.get(cfg.ANALYSIS_PLUGINS, {})[plugin_name]
258
+ plugin_path: str = self.config_param.get(cfg.ANALYSIS_PLUGINS, {}).get(plugin_name, "")
207
259
 
208
260
  logging.debug(f"{plugin_path=}")
209
261
 
@@ -213,24 +265,12 @@ def run_plugin(self, plugin_name):
213
265
 
214
266
  logging.debug(f"run plugin from {plugin_path}")
215
267
 
216
- module_name = Path(plugin_path).stem
217
-
218
- spec = importlib.util.spec_from_file_location(module_name, plugin_path)
219
- plugin_module = importlib.util.module_from_spec(spec)
220
-
221
- logging.debug(f"{plugin_module=}")
222
-
223
- spec.loader.exec_module(plugin_module)
224
-
225
- logging.info(
226
- f"{plugin_module.__plugin_name__} loaded v.{getattr(plugin_module, '__version__')} v. {getattr(plugin_module, '__version_date__')}"
227
- )
228
-
268
+ # select observations to analyze
229
269
  selected_observations, parameters = self.obs_param()
230
270
  if not selected_observations:
231
271
  return
232
272
 
233
- logging.info("preparing dtaaframe for plugin")
273
+ logging.info("preparing dataframe for plugin")
234
274
 
235
275
  df = project_functions.project2dataframe(self.pj, selected_observations)
236
276
 
@@ -247,8 +287,79 @@ def run_plugin(self, plugin_name):
247
287
  filtered_df = plugin_df_filter(df, observations_list=selected_observations, parameters=parameters)
248
288
  logging.info("done")
249
289
 
250
- plugin_results = plugin_module.run(filtered_df)
251
- # test if plugin_tests is a tuple: if not transform to tuple
290
+ if Path(plugin_path).suffix == ".py":
291
+ # load plugin as module
292
+ module_name = Path(plugin_path).stem
293
+
294
+ spec = importlib.util.spec_from_file_location(module_name, plugin_path)
295
+ plugin_module = importlib.util.module_from_spec(spec)
296
+
297
+ logging.debug(f"{plugin_module=}")
298
+
299
+ spec.loader.exec_module(plugin_module)
300
+
301
+ plugin_version = plugin_module.__version__
302
+ plugin_version_date = plugin_module.__version_date__
303
+
304
+ logging.info(
305
+ f"{plugin_module.__plugin_name__} loaded v.{getattr(plugin_module, '__version__')} v. {getattr(plugin_module, '__version_date__')}"
306
+ )
307
+
308
+ # run plugin
309
+ plugin_results = plugin_module.run(filtered_df)
310
+
311
+ if Path(plugin_path).suffix in (".R", ".r"):
312
+ try:
313
+ from rpy2 import robjects
314
+ from rpy2.robjects import pandas2ri
315
+ from rpy2.robjects.packages import SignatureTranslatedAnonymousPackage
316
+ from rpy2.robjects.conversion import localconverter
317
+ except Exception:
318
+ QMessageBox.critical(self, cfg.programName, "The rpy2 Python module is not installed. R plugins cannot be used")
319
+ return
320
+
321
+ # Read code from file
322
+ try:
323
+ with open(plugin_path, "r") as f:
324
+ r_code = f.read()
325
+ except Exception:
326
+ QMessageBox.critical(self, cfg.programName, f"Error reading the plugin {plugin_path}.")
327
+ return
328
+
329
+ # read version
330
+ plugin_version = next(
331
+ (
332
+ x.split("<-")[1].replace('"', "").replace("'", "").strip()
333
+ for x in r_code.splitlines()
334
+ if x.replace(" ", "").startswith("version<-")
335
+ ),
336
+ None,
337
+ )
338
+ # read version date
339
+ plugin_version_date = next(
340
+ (
341
+ x.split("<-")[1].replace('"', "").replace("'", "").strip()
342
+ for x in r_code.split("\n")
343
+ if x.replace(" ", "").startswith("version_date<")
344
+ ),
345
+ None,
346
+ )
347
+
348
+ r_plugin = SignatureTranslatedAnonymousPackage(r_code, "r_plugin")
349
+
350
+ with localconverter(robjects.default_converter + pandas2ri.converter):
351
+ r_df = robjects.conversion.py2rpy(filtered_df)
352
+
353
+ try:
354
+ r_result = r_plugin.run(r_df)
355
+ except Exception as e:
356
+ QMessageBox.critical(self, cfg.programName, f"Error in the plugin {plugin_path}: {e}.")
357
+ return
358
+
359
+ with localconverter(robjects.default_converter + pandas2ri.converter):
360
+ plugin_results = robjects.conversion.rpy2py(r_result)
361
+
362
+ # test if plugin_results is a tuple: if not transform it to tuple
252
363
  if not isinstance(plugin_results, tuple):
253
364
  plugin_results = tuple([plugin_results])
254
365
 
@@ -261,7 +372,7 @@ def run_plugin(self, plugin_name):
261
372
  self.plugin_visu[-1].ptText.appendPlainText(result)
262
373
  self.plugin_visu[-1].show()
263
374
  elif isinstance(result, pd.DataFrame):
264
- self.plugin_visu.append(view_df.View_df(plugin_name, f"{plugin_module.__version__} ({plugin_module.__version_date__})", result))
375
+ self.plugin_visu.append(view_df.View_df(plugin_name, f"{plugin_version} ({plugin_version_date})", result))
265
376
  self.plugin_visu[-1].show()
266
377
  else:
267
378
  # result is not str nor dataframe
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