boris-behav-obs 8.16.5__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.
- boris/__init__.py +1 -1
- boris/__main__.py +1 -1
- boris/about.py +24 -36
- boris/add_modifier.py +88 -80
- boris/add_modifier_ui.py +235 -131
- boris/advanced_event_filtering.py +23 -29
- boris/analysis_plugins/__init__.py +0 -0
- boris/analysis_plugins/_latency.py +59 -0
- boris/analysis_plugins/irr_cohen_kappa.py +109 -0
- boris/analysis_plugins/irr_cohen_kappa_with_modifiers.py +112 -0
- boris/analysis_plugins/irr_weighted_cohen_kappa.py +157 -0
- boris/analysis_plugins/irr_weighted_cohen_kappa_with_modifiers.py +162 -0
- boris/analysis_plugins/list_of_dataframe_columns.py +22 -0
- boris/analysis_plugins/number_of_occurences.py +22 -0
- boris/analysis_plugins/number_of_occurences_by_independent_variable.py +54 -0
- boris/analysis_plugins/time_budget.py +61 -0
- boris/behav_coding_map_creator.py +228 -229
- boris/behavior_binary_table.py +33 -50
- boris/behaviors_coding_map.py +17 -18
- boris/boris_cli.py +6 -25
- boris/cmd_arguments.py +12 -1
- boris/coding_pad.py +16 -34
- boris/config.py +102 -50
- boris/config_file.py +55 -64
- boris/connections.py +105 -58
- boris/converters.py +13 -37
- boris/converters_ui.py +187 -110
- boris/cooccurence.py +250 -0
- boris/core.py +2108 -1275
- boris/core_qrc.py +15892 -10829
- boris/core_ui.py +941 -806
- boris/db_functions.py +17 -42
- boris/dev.py +27 -7
- boris/dialog.py +461 -242
- boris/duration_widget.py +9 -14
- boris/edit_event.py +61 -31
- boris/edit_event_ui.py +208 -97
- boris/event_operations.py +405 -281
- boris/events_cursor.py +25 -17
- boris/events_snapshots.py +36 -82
- boris/exclusion_matrix.py +4 -9
- boris/export_events.py +180 -203
- boris/export_observation.py +60 -73
- boris/external_processes.py +123 -98
- boris/geometric_measurement.py +427 -218
- boris/gui_utilities.py +91 -14
- boris/image_overlay.py +4 -4
- boris/import_observations.py +190 -98
- boris/ipc_mpv.py +304 -0
- boris/irr.py +20 -57
- boris/latency.py +31 -24
- boris/measurement_widget.py +14 -18
- boris/media_file.py +17 -19
- boris/menu_options.py +16 -6
- boris/modifier_coding_map_creator.py +1013 -0
- boris/modifiers_coding_map.py +7 -9
- boris/mpv2.py +128 -35
- boris/observation.py +493 -210
- boris/observation_operations.py +1010 -391
- boris/observation_ui.py +573 -363
- boris/observations_list.py +51 -58
- boris/otx_parser.py +74 -68
- boris/param_panel.py +45 -59
- boris/param_panel_ui.py +254 -138
- boris/player_dock_widget.py +91 -56
- boris/plot_data_module.py +18 -53
- boris/plot_events.py +56 -153
- boris/plot_events_rt.py +16 -30
- boris/plot_spectrogram_rt.py +80 -56
- boris/plot_waveform_rt.py +23 -48
- boris/plugins.py +431 -0
- boris/portion/__init__.py +18 -8
- boris/portion/const.py +35 -18
- boris/portion/dict.py +5 -5
- boris/portion/func.py +2 -2
- boris/portion/interval.py +21 -41
- boris/portion/io.py +41 -32
- boris/preferences.py +298 -123
- boris/preferences_ui.py +664 -225
- boris/project.py +293 -270
- boris/project_functions.py +610 -537
- boris/project_import_export.py +204 -213
- boris/project_ui.py +673 -441
- boris/qrc_boris.py +6 -3
- boris/qrc_boris5.py +6 -3
- boris/select_modifiers.py +62 -90
- boris/select_observations.py +19 -197
- boris/select_subj_behav.py +67 -39
- boris/state_events.py +51 -33
- boris/subjects_pad.py +6 -8
- boris/synthetic_time_budget.py +42 -26
- boris/time_budget_functions.py +169 -169
- boris/time_budget_widget.py +77 -89
- boris/transitions.py +41 -41
- boris/utilities.py +562 -222
- boris/version.py +3 -3
- boris/video_equalizer.py +16 -14
- boris/video_equalizer_ui.py +199 -130
- boris/video_operations.py +78 -28
- boris/view_df.py +104 -0
- boris/view_df_ui.py +75 -0
- boris/write_event.py +240 -136
- boris_behav_obs-9.7.1.dist-info/METADATA +140 -0
- boris_behav_obs-9.7.1.dist-info/RECORD +109 -0
- {boris_behav_obs-8.16.5.dist-info → boris_behav_obs-9.7.1.dist-info}/WHEEL +1 -1
- boris_behav_obs-9.7.1.dist-info/entry_points.txt +2 -0
- boris/README.TXT +0 -22
- boris/add_modifier.ui +0 -323
- boris/converters.ui +0 -289
- boris/core.qrc +0 -37
- boris/core.ui +0 -1571
- boris/edit_event.ui +0 -233
- boris/icons/logo_eye.ico +0 -0
- boris/map_creator.py +0 -982
- boris/observation.ui +0 -814
- boris/param_panel.ui +0 -379
- boris/preferences.ui +0 -537
- boris/project.ui +0 -1074
- boris/vlc_local.py +0 -90
- boris_behav_obs-8.16.5.dist-info/LICENSE.TXT +0 -674
- boris_behav_obs-8.16.5.dist-info/METADATA +0 -134
- boris_behav_obs-8.16.5.dist-info/RECORD +0 -107
- boris_behav_obs-8.16.5.dist-info/entry_points.txt +0 -2
- {boris → boris_behav_obs-9.7.1.dist-info/licenses}/LICENSE.TXT +0 -0
- {boris_behav_obs-8.16.5.dist-info → boris_behav_obs-9.7.1.dist-info}/top_level.txt +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"""
|
|
2
2
|
BORIS
|
|
3
3
|
Behavioral Observation Research Interactive Software
|
|
4
|
-
Copyright 2012-
|
|
4
|
+
Copyright 2012-2025 Olivier Friard
|
|
5
5
|
|
|
6
6
|
This file is part of BORIS.
|
|
7
7
|
|
|
@@ -23,15 +23,12 @@ This file is part of BORIS.
|
|
|
23
23
|
import binascii
|
|
24
24
|
import io
|
|
25
25
|
import json
|
|
26
|
-
import
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
from
|
|
30
|
-
|
|
31
|
-
from
|
|
32
|
-
from PyQt5.QtGui import QBrush, QColor, QIcon, QMouseEvent, QPen, QPixmap, QPolygonF
|
|
33
|
-
from PyQt5.QtWidgets import (
|
|
34
|
-
QAction,
|
|
26
|
+
from pathlib import Path
|
|
27
|
+
import gui_utilities
|
|
28
|
+
|
|
29
|
+
from PySide6.QtCore import QBuffer, QByteArray, QIODevice, QLineF, QPoint, Qt, Signal
|
|
30
|
+
from PySide6.QtGui import QBrush, QColor, QIcon, QMouseEvent, QPen, QPixmap, QPolygonF, QAction
|
|
31
|
+
from PySide6.QtWidgets import (
|
|
35
32
|
QApplication,
|
|
36
33
|
QColorDialog,
|
|
37
34
|
QFileDialog,
|
|
@@ -71,15 +68,14 @@ selectedBrush.setColor(QColor(255, 255, 0, 255))
|
|
|
71
68
|
|
|
72
69
|
|
|
73
70
|
class BehaviorsMapCreatorWindow(QMainWindow):
|
|
74
|
-
|
|
75
|
-
signal_add_to_project = pyqtSignal(dict)
|
|
71
|
+
signal_add_to_project = Signal(dict)
|
|
76
72
|
|
|
77
73
|
class View(QGraphicsView):
|
|
78
74
|
"""
|
|
79
75
|
class for handling mousepress event in QGraphicsView
|
|
80
76
|
"""
|
|
81
77
|
|
|
82
|
-
mousePress =
|
|
78
|
+
mousePress = Signal(QMouseEvent)
|
|
83
79
|
|
|
84
80
|
def mousePressEvent(self, event):
|
|
85
81
|
self.mousePress.emit(event)
|
|
@@ -99,7 +95,6 @@ class BehaviorsMapCreatorWindow(QMainWindow):
|
|
|
99
95
|
areaColor = QColor("lime")
|
|
100
96
|
|
|
101
97
|
def __init__(self, arg):
|
|
102
|
-
|
|
103
98
|
self.codes_list = arg
|
|
104
99
|
|
|
105
100
|
super(BehaviorsMapCreatorWindow, self).__init__()
|
|
@@ -120,14 +115,14 @@ class BehaviorsMapCreatorWindow(QMainWindow):
|
|
|
120
115
|
self.openMapAction.setStatusTip("Open a behaviors coding map")
|
|
121
116
|
self.openMapAction.triggered.connect(self.openMap)
|
|
122
117
|
|
|
123
|
-
self.saveMapAction = QAction(QIcon(), "&Save the
|
|
118
|
+
self.saveMapAction = QAction(QIcon(), "&Save the behavior coding map", self)
|
|
124
119
|
self.saveMapAction.setShortcut("Ctrl+S")
|
|
125
|
-
self.saveMapAction.setStatusTip("Save the
|
|
120
|
+
self.saveMapAction.setStatusTip("Save the behavior coding map")
|
|
126
121
|
self.saveMapAction.setEnabled(False)
|
|
127
122
|
self.saveMapAction.triggered.connect(self.saveMap_clicked)
|
|
128
123
|
|
|
129
|
-
self.saveAsMapAction = QAction(QIcon(), "Save the
|
|
130
|
-
self.saveAsMapAction.setStatusTip("Save the
|
|
124
|
+
self.saveAsMapAction = QAction(QIcon(), "Save the behavior coding map as ...", self)
|
|
125
|
+
self.saveAsMapAction.setStatusTip("Save the behavior coding map as ...")
|
|
131
126
|
self.saveAsMapAction.setEnabled(False)
|
|
132
127
|
self.saveAsMapAction.triggered.connect(self.saveAsMap_clicked)
|
|
133
128
|
|
|
@@ -137,13 +132,18 @@ class BehaviorsMapCreatorWindow(QMainWindow):
|
|
|
137
132
|
self.mapNameAction.setEnabled(False)
|
|
138
133
|
self.mapNameAction.triggered.connect(self.mapName_clicked)
|
|
139
134
|
|
|
135
|
+
self.resizeAction = QAction(QIcon(), "Resize the image", self)
|
|
136
|
+
self.resizeAction.setStatusTip("Resize the image")
|
|
137
|
+
self.resizeAction.setEnabled(False)
|
|
138
|
+
self.resizeAction.triggered.connect(self.resize_clicked)
|
|
139
|
+
|
|
140
140
|
self.addToProject = QAction(QIcon(), "Add coding map to project", self)
|
|
141
141
|
self.addToProject.setStatusTip("Add coding map to project")
|
|
142
142
|
self.addToProject.setEnabled(False)
|
|
143
143
|
self.addToProject.triggered.connect(self.add_to_project)
|
|
144
144
|
|
|
145
145
|
self.exitAction = QAction(QIcon(), "&Close", self)
|
|
146
|
-
self.exitAction.setStatusTip(
|
|
146
|
+
self.exitAction.setStatusTip(cfg.CLOSE)
|
|
147
147
|
self.exitAction.triggered.connect(self.close)
|
|
148
148
|
|
|
149
149
|
menubar = self.menuBar()
|
|
@@ -155,16 +155,13 @@ class BehaviorsMapCreatorWindow(QMainWindow):
|
|
|
155
155
|
fileMenu.addSeparator()
|
|
156
156
|
fileMenu.addAction(self.mapNameAction)
|
|
157
157
|
fileMenu.addSeparator()
|
|
158
|
+
fileMenu.addAction(self.resizeAction)
|
|
159
|
+
fileMenu.addSeparator()
|
|
158
160
|
fileMenu.addAction(self.addToProject)
|
|
159
161
|
fileMenu.addSeparator()
|
|
160
162
|
fileMenu.addAction(self.exitAction)
|
|
161
163
|
|
|
162
164
|
splitter1 = QSplitter(Qt.Vertical)
|
|
163
|
-
"""
|
|
164
|
-
splitter1.addWidget(splitter1)
|
|
165
|
-
splitter1.addWidget(bottom)
|
|
166
|
-
"""
|
|
167
|
-
"""vlayout_list = QVBoxLayout()"""
|
|
168
165
|
|
|
169
166
|
self.view = self.View(self)
|
|
170
167
|
self.view.mousePress.connect(self.viewMousePressEvent)
|
|
@@ -174,7 +171,6 @@ class BehaviorsMapCreatorWindow(QMainWindow):
|
|
|
174
171
|
vlayout_list.addWidget(QLabel("Defined area"))
|
|
175
172
|
|
|
176
173
|
self.area_list = QListWidget(self)
|
|
177
|
-
# self.area_list.setMaximumHeight(120)
|
|
178
174
|
self.area_list.itemClicked.connect(self.area_list_item_click)
|
|
179
175
|
vlayout_list.addWidget(self.area_list)
|
|
180
176
|
w = QWidget()
|
|
@@ -183,10 +179,6 @@ class BehaviorsMapCreatorWindow(QMainWindow):
|
|
|
183
179
|
splitter1.setSizes([300, 100])
|
|
184
180
|
splitter1.setStretchFactor(2, 8)
|
|
185
181
|
|
|
186
|
-
self.btLoad = QPushButton("Load bitmap", self)
|
|
187
|
-
self.btLoad.clicked.connect(self.loadBitmap)
|
|
188
|
-
self.btLoad.setVisible(False)
|
|
189
|
-
|
|
190
182
|
hlayout_cmd = QHBoxLayout()
|
|
191
183
|
|
|
192
184
|
self.btNewArea = QPushButton("New behavior area", self)
|
|
@@ -204,6 +196,8 @@ class BehaviorsMapCreatorWindow(QMainWindow):
|
|
|
204
196
|
self.btCancelAreaCreation.setVisible(False)
|
|
205
197
|
hlayout_cmd.addWidget(self.btCancelAreaCreation)
|
|
206
198
|
|
|
199
|
+
hlayout_cmd.addItem(QSpacerItem(40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum))
|
|
200
|
+
|
|
207
201
|
self.btDeleteArea = QPushButton("Delete selected behavior area", self)
|
|
208
202
|
self.btDeleteArea.clicked.connect(self.deleteArea)
|
|
209
203
|
self.btDeleteArea.setVisible(False)
|
|
@@ -253,16 +247,9 @@ class BehaviorsMapCreatorWindow(QMainWindow):
|
|
|
253
247
|
frame.setLayout(vlayout_frame)
|
|
254
248
|
|
|
255
249
|
vlayout = QVBoxLayout()
|
|
256
|
-
"""
|
|
257
|
-
vlayout.addWidget(self.view)
|
|
258
|
-
vlayout.addWidget(QLabel("Defined area"))
|
|
259
|
-
vlayout.addWidget(self.area_list)
|
|
260
|
-
"""
|
|
261
|
-
vlayout.addWidget(splitter1)
|
|
262
|
-
"""vlayout.addLayout(vlayout_view_list)"""
|
|
263
250
|
|
|
251
|
+
vlayout.addWidget(splitter1)
|
|
264
252
|
vlayout.addWidget(frame)
|
|
265
|
-
vlayout.addWidget(self.btLoad)
|
|
266
253
|
|
|
267
254
|
main_widget = QWidget(self)
|
|
268
255
|
main_widget.setLayout(vlayout)
|
|
@@ -277,7 +264,6 @@ class BehaviorsMapCreatorWindow(QMainWindow):
|
|
|
277
264
|
|
|
278
265
|
map_dict = self.make_coding_map_dict()
|
|
279
266
|
if map_dict["areas"] == {}:
|
|
280
|
-
|
|
281
267
|
QMessageBox.critical(
|
|
282
268
|
self,
|
|
283
269
|
cfg.programName,
|
|
@@ -310,19 +296,21 @@ class BehaviorsMapCreatorWindow(QMainWindow):
|
|
|
310
296
|
|
|
311
297
|
self.selectedPolygon.setPen(QPen(QColor(255, 0, 0, 255), 2, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin))
|
|
312
298
|
|
|
313
|
-
self.lb.setVisible(True)
|
|
314
299
|
self.leAreaCode.setText(ac)
|
|
315
|
-
self.leAreaCode.setVisible(True)
|
|
316
|
-
self.btEditAreaCode.setVisible(True)
|
|
317
300
|
|
|
318
|
-
|
|
301
|
+
for widget in (
|
|
302
|
+
self.lb,
|
|
303
|
+
self.leAreaCode,
|
|
304
|
+
self.btEditAreaCode,
|
|
305
|
+
self.btDeleteArea,
|
|
306
|
+
self.btColor,
|
|
307
|
+
self.slAlpha,
|
|
308
|
+
):
|
|
309
|
+
widget.setVisible(True)
|
|
319
310
|
|
|
320
311
|
self.areaColor = self.selectedPolygon.brush().color()
|
|
321
312
|
self.btColor.setStyleSheet(f"QWidget {{background-color:{self.selectedPolygon.brush().color().name()}}}")
|
|
322
|
-
self.
|
|
323
|
-
|
|
324
|
-
self.slAlpha.setValue(int(self.selectedPolygon.brush().color().alpha() / 255 * 100))
|
|
325
|
-
self.slAlpha.setVisible(True)
|
|
313
|
+
self.slAlpha.setValue(int(self.areaColor.alpha() / 255 * 100))
|
|
326
314
|
|
|
327
315
|
def edit_area_code(self):
|
|
328
316
|
"""
|
|
@@ -334,9 +322,7 @@ class BehaviorsMapCreatorWindow(QMainWindow):
|
|
|
334
322
|
else:
|
|
335
323
|
code_index = 0
|
|
336
324
|
|
|
337
|
-
item, ok = QInputDialog.getItem(
|
|
338
|
-
self, "Select a behavior", "Available behaviors", self.codes_list, code_index, False
|
|
339
|
-
)
|
|
325
|
+
item, ok = QInputDialog.getItem(self, "Select a behavior", "Available behaviors", self.codes_list, code_index, False)
|
|
340
326
|
self.leAreaCode.setText(item)
|
|
341
327
|
|
|
342
328
|
if self.selectedPolygon:
|
|
@@ -376,9 +362,7 @@ class BehaviorsMapCreatorWindow(QMainWindow):
|
|
|
376
362
|
cd.setWindowFlags(Qt.WindowStaysOnTopHint)
|
|
377
363
|
cd.setOptions(QColorDialog.DontUseNativeDialog)
|
|
378
364
|
|
|
379
|
-
|
|
380
|
-
# if col.isValid():
|
|
381
|
-
if cd.exec_():
|
|
365
|
+
if cd.exec():
|
|
382
366
|
self.areaColor = cd.currentColor()
|
|
383
367
|
self.btColor.setStyleSheet(f"QWidget {{background-color:{self.areaColor.name()}}}")
|
|
384
368
|
self.areaColor.setAlpha(int(self.slAlpha.value() / 100 * 255))
|
|
@@ -397,9 +381,7 @@ class BehaviorsMapCreatorWindow(QMainWindow):
|
|
|
397
381
|
self.closedPolygon.setBrush(self.areaColor)
|
|
398
382
|
|
|
399
383
|
def closeEvent(self, event):
|
|
400
|
-
|
|
401
384
|
if self.flag_map_changed:
|
|
402
|
-
|
|
403
385
|
response = dialog.MessageDialog(
|
|
404
386
|
"BORIS - Behaviors map creator",
|
|
405
387
|
"What to do about the current unsaved behaviors coding map?",
|
|
@@ -439,52 +421,38 @@ class BehaviorsMapCreatorWindow(QMainWindow):
|
|
|
439
421
|
|
|
440
422
|
test = self.view.mapToScene(event.pos()).toPoint() # coordinates of clicked point
|
|
441
423
|
|
|
442
|
-
if (
|
|
443
|
-
test.x() < 0
|
|
444
|
-
or test.y() < 0
|
|
445
|
-
or test.x() > self.pixmap.size().width()
|
|
446
|
-
or test.y() > self.pixmap.size().height()
|
|
447
|
-
):
|
|
424
|
+
if test.x() < 0 or test.y() < 0 or test.x() > self.pixmap.size().width() or test.y() > self.pixmap.size().height():
|
|
448
425
|
return
|
|
449
426
|
|
|
450
427
|
if not self.flagNewArea: # test clicked point for areas
|
|
451
|
-
|
|
452
428
|
# reset selected polygon to default pen
|
|
453
429
|
if self.selectedPolygon:
|
|
454
430
|
self.selectedPolygon.setPen(QPen(designColor, penWidth, penStyle, Qt.RoundCap, Qt.RoundJoin))
|
|
455
431
|
self.selectedPolygon = None
|
|
456
432
|
self.selectedPolygonMemBrush = None
|
|
457
433
|
|
|
434
|
+
idx = 0
|
|
458
435
|
for areaCode, pg in self.polygonsList2:
|
|
459
|
-
|
|
460
436
|
if pg.contains(test):
|
|
461
|
-
|
|
462
437
|
self.selectedPolygon = pg
|
|
463
|
-
|
|
464
438
|
self.selectedPolygonMemBrush = self.selectedPolygon.brush()
|
|
465
|
-
|
|
466
|
-
self.selectedPolygon.setPen(
|
|
467
|
-
QPen(QColor(255, 0, 0, 255), 2, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin)
|
|
468
|
-
)
|
|
469
|
-
|
|
470
|
-
self.lb.setVisible(True)
|
|
439
|
+
self.selectedPolygon.setPen(QPen(QColor(255, 0, 0, 255), 2, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin))
|
|
471
440
|
self.leAreaCode.setText(areaCode)
|
|
472
|
-
self.leAreaCode.setVisible(True)
|
|
473
|
-
# self.leAreaCode.setEnabled(False)
|
|
474
|
-
self.btEditAreaCode.setVisible(True)
|
|
475
441
|
|
|
476
|
-
self.btDeleteArea
|
|
442
|
+
for widget in (self.lb, self.leAreaCode, self.btEditAreaCode, self.btColor, self.slAlpha, self.btDeleteArea):
|
|
443
|
+
widget.setVisible(True)
|
|
477
444
|
|
|
478
445
|
self.areaColor = self.selectedPolygon.brush().color()
|
|
479
|
-
self.btColor.setStyleSheet(
|
|
480
|
-
f"QWidget {{background-color:{self.selectedPolygon.brush().color().name()}}}"
|
|
481
|
-
)
|
|
482
|
-
self.btColor.setVisible(True)
|
|
446
|
+
self.btColor.setStyleSheet(f"QWidget {{background-color:{self.selectedPolygon.brush().color().name()}}}")
|
|
483
447
|
|
|
484
|
-
self.slAlpha.setValue(int(self.
|
|
485
|
-
|
|
448
|
+
self.slAlpha.setValue(int(self.areaColor.alpha() / 255 * 100))
|
|
449
|
+
|
|
450
|
+
# select area in list widget
|
|
451
|
+
item = self.area_list.item(idx)
|
|
452
|
+
self.area_list.setCurrentItem(item)
|
|
486
453
|
|
|
487
454
|
break
|
|
455
|
+
idx += 1
|
|
488
456
|
|
|
489
457
|
if not self.selectedPolygon:
|
|
490
458
|
self.leAreaCode.setVisible(False)
|
|
@@ -497,7 +465,6 @@ class BehaviorsMapCreatorWindow(QMainWindow):
|
|
|
497
465
|
|
|
498
466
|
# delete last line item
|
|
499
467
|
if (event.buttons() & Qt.RightButton) and not self.closedPolygon:
|
|
500
|
-
|
|
501
468
|
if self.view.points:
|
|
502
469
|
self.view.points = self.view.points[0:-1]
|
|
503
470
|
|
|
@@ -511,18 +478,28 @@ class BehaviorsMapCreatorWindow(QMainWindow):
|
|
|
511
478
|
self.view.scene().removeItem(self.view.elList[-1])
|
|
512
479
|
self.view.elList = self.view.elList[0:-1]
|
|
513
480
|
|
|
481
|
+
# middle button automatically close the polygon
|
|
482
|
+
if (event.buttons() & Qt.MiddleButton) and not self.closedPolygon:
|
|
483
|
+
line = QGraphicsLineItem(QLineF(self.view._start, QPoint(self.view.points[0][0], self.view.points[0][1])))
|
|
484
|
+
line.setPen(QPen(designColor, penWidth, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin))
|
|
485
|
+
|
|
486
|
+
self.view.scene().addItem(line)
|
|
487
|
+
self.view.elList.append(line)
|
|
488
|
+
|
|
489
|
+
self.statusBar().showMessage("Area completed")
|
|
490
|
+
|
|
491
|
+
# create polygon
|
|
492
|
+
add_polygon()
|
|
493
|
+
return
|
|
494
|
+
|
|
514
495
|
# add line item
|
|
515
496
|
if event.buttons() == Qt.LeftButton and not self.closedPolygon:
|
|
516
|
-
|
|
517
497
|
if self.view._start:
|
|
518
|
-
|
|
519
498
|
end = test
|
|
520
499
|
|
|
521
500
|
# test is polygon is crossed
|
|
522
501
|
if len(self.view.points) >= 3:
|
|
523
|
-
|
|
524
502
|
for idx, _ in enumerate(self.view.points[:-2]):
|
|
525
|
-
|
|
526
503
|
if util.intersection(
|
|
527
504
|
self.view.points[idx],
|
|
528
505
|
self.view.points[idx + 1],
|
|
@@ -534,10 +511,7 @@ class BehaviorsMapCreatorWindow(QMainWindow):
|
|
|
534
511
|
|
|
535
512
|
# test if polygon closed (dist min 10 px)
|
|
536
513
|
if abs(end.x() - self.view.points[0][0]) < 10 and abs(end.y() - self.view.points[0][1]) < 10:
|
|
537
|
-
|
|
538
|
-
line = QGraphicsLineItem(
|
|
539
|
-
QLineF(self.view._start, QPoint(self.view.points[0][0], self.view.points[0][1]))
|
|
540
|
-
)
|
|
514
|
+
line = QGraphicsLineItem(QLineF(self.view._start, QPoint(self.view.points[0][0], self.view.points[0][1])))
|
|
541
515
|
line.setPen(QPen(designColor, penWidth, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin))
|
|
542
516
|
|
|
543
517
|
self.view.scene().addItem(line)
|
|
@@ -559,7 +533,6 @@ class BehaviorsMapCreatorWindow(QMainWindow):
|
|
|
559
533
|
self.view._start = test
|
|
560
534
|
|
|
561
535
|
else: # first point
|
|
562
|
-
|
|
563
536
|
self.view._start = test
|
|
564
537
|
|
|
565
538
|
ellipse = QGraphicsEllipseItem(self.view._start.x(), self.view._start.y(), 3, 3)
|
|
@@ -577,15 +550,12 @@ class BehaviorsMapCreatorWindow(QMainWindow):
|
|
|
577
550
|
|
|
578
551
|
# automatically close the polygon
|
|
579
552
|
if event.buttons() == Qt.MiddleButton and not self.closedPolygon:
|
|
580
|
-
|
|
581
553
|
# add first point as last point of polygon
|
|
582
554
|
|
|
583
555
|
# test is polygon is crossed
|
|
584
556
|
|
|
585
557
|
if len(self.view.points) >= 3:
|
|
586
|
-
|
|
587
558
|
for idx, _ in enumerate(self.view.points[1:-2]):
|
|
588
|
-
|
|
589
559
|
if util.intersection(
|
|
590
560
|
self.view.points[idx],
|
|
591
561
|
self.view.points[idx + 1],
|
|
@@ -638,7 +608,6 @@ class BehaviorsMapCreatorWindow(QMainWindow):
|
|
|
638
608
|
"""
|
|
639
609
|
|
|
640
610
|
if self.flag_map_changed:
|
|
641
|
-
|
|
642
611
|
response = dialog.MessageDialog(
|
|
643
612
|
cfg.programName + " - Behaviors coding map creator",
|
|
644
613
|
"What to do about the current unsaved coding map?",
|
|
@@ -655,9 +624,9 @@ class BehaviorsMapCreatorWindow(QMainWindow):
|
|
|
655
624
|
self.cancelMap()
|
|
656
625
|
|
|
657
626
|
while True:
|
|
658
|
-
map_name, ok = QInputDialog.getText(
|
|
659
|
-
|
|
660
|
-
|
|
627
|
+
map_name, ok = QInputDialog.getText(self, "Behaviors coding map name", "Enter a name for the new coding map")
|
|
628
|
+
if not ok:
|
|
629
|
+
return
|
|
661
630
|
if map_name.upper() in self.bcm_list:
|
|
662
631
|
QMessageBox.critical(
|
|
663
632
|
self,
|
|
@@ -671,18 +640,10 @@ class BehaviorsMapCreatorWindow(QMainWindow):
|
|
|
671
640
|
if ok and map_name and map_name.upper() not in self.bcm_list:
|
|
672
641
|
self.mapName = map_name
|
|
673
642
|
break
|
|
674
|
-
if not ok:
|
|
675
|
-
return
|
|
676
|
-
"""
|
|
677
|
-
if not self.mapName:
|
|
678
|
-
QMessageBox.critical(self, "", "You must define a name for the new coding map")
|
|
679
|
-
return
|
|
680
|
-
"""
|
|
681
643
|
|
|
682
644
|
self.setWindowTitle(f"{cfg.programName} - Behaviors coding map creator tool - {self.mapName}")
|
|
683
645
|
|
|
684
|
-
self.
|
|
685
|
-
self.statusBar().showMessage('Click "Load bitmap" button to select and load a bitmap into the viewer')
|
|
646
|
+
self.loadBitmap()
|
|
686
647
|
|
|
687
648
|
def openMap(self):
|
|
688
649
|
"""
|
|
@@ -701,79 +662,75 @@ class BehaviorsMapCreatorWindow(QMainWindow):
|
|
|
701
662
|
if (response == "Save" and not self.saveMap_clicked()) or (response == "Cancel"):
|
|
702
663
|
return
|
|
703
664
|
|
|
704
|
-
|
|
665
|
+
fileName, _ = QFileDialog(self).getOpenFileName(
|
|
705
666
|
self, "Open a behaviors coding map", "", "Behaviors coding map (*.behav_coding_map);;All files (*)"
|
|
706
667
|
)
|
|
707
|
-
fileName = fn[0] if type(fn) is tuple else fn
|
|
708
668
|
|
|
709
|
-
if fileName:
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
if (
|
|
718
|
-
"coding_map_type" not in self.codingMap
|
|
719
|
-
or self.codingMap["coding_map_type"] != "BORIS behaviors coding map"
|
|
720
|
-
):
|
|
721
|
-
QMessageBox.critical(self, cfg.programName, f"The file {fileName} is not a BORIS behaviors coding map.")
|
|
669
|
+
if not fileName:
|
|
670
|
+
return
|
|
671
|
+
try:
|
|
672
|
+
self.codingMap = json.loads(open(fileName, "r").read())
|
|
673
|
+
except Exception:
|
|
674
|
+
QMessageBox.critical(self, cfg.programName, f"The file {fileName} is not a behaviors coding map.")
|
|
675
|
+
return
|
|
722
676
|
|
|
723
|
-
|
|
677
|
+
if "coding_map_type" not in self.codingMap or self.codingMap["coding_map_type"] != "BORIS behaviors coding map":
|
|
678
|
+
QMessageBox.critical(self, cfg.programName, f"The file {fileName} is not a BORIS behaviors coding map.")
|
|
679
|
+
return
|
|
724
680
|
|
|
725
|
-
|
|
681
|
+
self.cancelMap()
|
|
726
682
|
|
|
727
|
-
|
|
683
|
+
self.mapName = self.codingMap["name"]
|
|
728
684
|
|
|
729
|
-
|
|
685
|
+
self.setWindowTitle(f"{cfg.programName} - Behaviors coding map creator - {self.mapName}")
|
|
730
686
|
|
|
731
|
-
|
|
687
|
+
self.bitmapFileName = True
|
|
732
688
|
|
|
733
|
-
|
|
689
|
+
self.fileName = fileName
|
|
734
690
|
|
|
735
|
-
|
|
691
|
+
bitmapContent = binascii.a2b_base64(self.codingMap["bitmap"])
|
|
736
692
|
|
|
737
|
-
|
|
738
|
-
self.view.setMinimumHeight(self.pixmap.size().height())
|
|
739
|
-
# self.view.setMaximumHeight(self.pixmap.size().height())
|
|
740
|
-
pixItem = QGraphicsPixmapItem(self.pixmap)
|
|
741
|
-
pixItem.setPos(0, 0)
|
|
742
|
-
self.view.scene().addItem(pixItem)
|
|
693
|
+
self.pixmap.loadFromData(bitmapContent)
|
|
743
694
|
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
695
|
+
self.view.setSceneRect(0, 0, self.pixmap.size().width(), self.pixmap.size().height())
|
|
696
|
+
self.view.setMinimumHeight(self.pixmap.size().height())
|
|
697
|
+
# self.view.setMaximumHeight(self.pixmap.size().height())
|
|
698
|
+
pixItem = QGraphicsPixmapItem(self.pixmap)
|
|
699
|
+
pixItem.setPos(0, 0)
|
|
700
|
+
self.view.scene().addItem(pixItem)
|
|
747
701
|
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
702
|
+
for key in self.codingMap["areas"]:
|
|
703
|
+
areaCode = self.codingMap["areas"][key]["code"]
|
|
704
|
+
points = self.codingMap["areas"][key]["geometry"]
|
|
751
705
|
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
polygon.setPolygon(newPolygon)
|
|
756
|
-
clr = QColor()
|
|
757
|
-
clr.setRgba(self.codingMap["areas"][key]["color"])
|
|
758
|
-
polygon.setPen(QPen(clr, penWidth, penStyle, Qt.RoundCap, Qt.RoundJoin))
|
|
759
|
-
polygon.setBrush(QBrush(clr, Qt.SolidPattern))
|
|
706
|
+
newPolygon = QPolygonF()
|
|
707
|
+
for p in points:
|
|
708
|
+
newPolygon.append(QPoint(p[0], p[1]))
|
|
760
709
|
|
|
761
|
-
|
|
710
|
+
# draw polygon
|
|
711
|
+
polygon = QGraphicsPolygonItem()
|
|
712
|
+
polygon.setPolygon(newPolygon)
|
|
713
|
+
clr = QColor()
|
|
714
|
+
clr.setRgba(self.codingMap["areas"][key]["color"])
|
|
715
|
+
polygon.setPen(QPen(clr, penWidth, penStyle, Qt.RoundCap, Qt.RoundJoin))
|
|
716
|
+
polygon.setBrush(QBrush(clr, Qt.SolidPattern))
|
|
762
717
|
|
|
763
|
-
|
|
718
|
+
self.view.scene().addItem(polygon)
|
|
764
719
|
|
|
765
|
-
self.
|
|
766
|
-
self.btLoad.setVisible(False)
|
|
720
|
+
self.polygonsList2.append([areaCode, polygon])
|
|
767
721
|
|
|
768
|
-
|
|
769
|
-
self.saveAsMapAction.setEnabled(True)
|
|
770
|
-
self.addToProject.setEnabled(True)
|
|
771
|
-
self.mapNameAction.setEnabled(True)
|
|
722
|
+
self.btNewArea.setVisible(True)
|
|
772
723
|
|
|
773
|
-
|
|
724
|
+
for action in (
|
|
725
|
+
self.saveMapAction,
|
|
726
|
+
self.saveAsMapAction,
|
|
727
|
+
self.addToProject,
|
|
728
|
+
self.mapNameAction,
|
|
729
|
+
self.resizeAction,
|
|
730
|
+
):
|
|
731
|
+
action.setEnabled(True)
|
|
774
732
|
|
|
775
|
-
|
|
776
|
-
self.statusBar().showMessage("No file", 5000)
|
|
733
|
+
self.update_area_list()
|
|
777
734
|
|
|
778
735
|
def make_coding_map_dict(self) -> dict:
|
|
779
736
|
"""
|
|
@@ -827,29 +784,26 @@ class BehaviorsMapCreatorWindow(QMainWindow):
|
|
|
827
784
|
return False
|
|
828
785
|
|
|
829
786
|
def saveAsMap_clicked(self):
|
|
830
|
-
|
|
831
787
|
filters = "Behaviors coding map (*.behav_coding_map);;All files (*)"
|
|
832
788
|
|
|
833
|
-
|
|
834
|
-
self.fileName = fn[0] if type(fn) is tuple else fn
|
|
789
|
+
self.fileName, _ = QFileDialog.getSaveFileName(self, "Save behaviors coding map as", "", filters)
|
|
835
790
|
|
|
836
|
-
if self.fileName:
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
self.
|
|
791
|
+
if not self.fileName:
|
|
792
|
+
return
|
|
793
|
+
if Path(self.fileName).suffix != ".behav_coding_map":
|
|
794
|
+
self.fileName += ".behav_coding_map"
|
|
795
|
+
self.saveMap()
|
|
840
796
|
|
|
841
797
|
def saveMap_clicked(self):
|
|
842
|
-
|
|
843
798
|
if not self.fileName:
|
|
844
|
-
|
|
799
|
+
self.fileName, _ = QFileDialog().getSaveFileName(
|
|
845
800
|
self,
|
|
846
801
|
"Save modifiers map",
|
|
847
802
|
self.mapName + ".behav_coding_map",
|
|
848
803
|
"Behaviors coding map (*.behav_coding_map);;All files (*)",
|
|
849
804
|
)
|
|
850
|
-
self.fileName = fn[0] if type(fn) is tuple else fn
|
|
851
805
|
|
|
852
|
-
if self.fileName and
|
|
806
|
+
if self.fileName and Path(self.fileName).suffix != ".behav_coding_map":
|
|
853
807
|
self.fileName += ".behav_coding_map"
|
|
854
808
|
|
|
855
809
|
if self.fileName:
|
|
@@ -859,7 +813,7 @@ class BehaviorsMapCreatorWindow(QMainWindow):
|
|
|
859
813
|
|
|
860
814
|
def newArea(self):
|
|
861
815
|
if not self.bitmapFileName:
|
|
862
|
-
QMessageBox.critical(self, cfg.programName, "
|
|
816
|
+
QMessageBox.critical(self, cfg.programName, "An image must be loaded before to define areas")
|
|
863
817
|
return
|
|
864
818
|
|
|
865
819
|
if self.selectedPolygon:
|
|
@@ -880,19 +834,15 @@ class BehaviorsMapCreatorWindow(QMainWindow):
|
|
|
880
834
|
self.btDeleteArea.setVisible(False)
|
|
881
835
|
|
|
882
836
|
self.statusBar().showMessage(
|
|
883
|
-
(
|
|
884
|
-
"Click on bitmap to set the vertices of the area with the mouse "
|
|
885
|
-
"(right click will cancel the last point)"
|
|
886
|
-
)
|
|
837
|
+
("Click on bitmap to set the vertices of the area with the mouse (right click will cancel the last point)")
|
|
887
838
|
)
|
|
888
839
|
|
|
889
840
|
def saveArea(self):
|
|
890
|
-
|
|
891
841
|
if not self.closedPolygon:
|
|
892
842
|
QMessageBox.critical(
|
|
893
843
|
self,
|
|
894
844
|
cfg.programName,
|
|
895
|
-
("You must close your area before saving it.\
|
|
845
|
+
("You must close your area before saving it.\nThe last vertex must correspond to the first one."),
|
|
896
846
|
)
|
|
897
847
|
|
|
898
848
|
if len(self.view.points) < 3:
|
|
@@ -905,19 +855,20 @@ class BehaviorsMapCreatorWindow(QMainWindow):
|
|
|
905
855
|
return
|
|
906
856
|
|
|
907
857
|
# remove all lines
|
|
908
|
-
for
|
|
909
|
-
self.view.scene().removeItem(
|
|
858
|
+
for x in self.view.elList:
|
|
859
|
+
self.view.scene().removeItem(x)
|
|
910
860
|
|
|
911
861
|
# draw polygon
|
|
912
862
|
self.closedPolygon.setBrush(QBrush(self.areaColor, Qt.SolidPattern))
|
|
913
|
-
# self.polygonsList2[self.leAreaCode.text()] = self.closedPolygon
|
|
914
863
|
self.polygonsList2.append([self.leAreaCode.text(), self.closedPolygon])
|
|
915
864
|
|
|
916
|
-
self.
|
|
865
|
+
self.flagNewArea = None
|
|
866
|
+
self.closedPolygon = None
|
|
917
867
|
self.view._start = 0
|
|
918
|
-
self.view.points
|
|
868
|
+
self.view.points = []
|
|
869
|
+
self.view.elList = []
|
|
919
870
|
|
|
920
|
-
for widget in
|
|
871
|
+
for widget in (
|
|
921
872
|
self.btSaveArea,
|
|
922
873
|
self.btCancelAreaCreation,
|
|
923
874
|
self.lb,
|
|
@@ -927,26 +878,26 @@ class BehaviorsMapCreatorWindow(QMainWindow):
|
|
|
927
878
|
self.slAlpha,
|
|
928
879
|
self.btDeleteArea,
|
|
929
880
|
self.btNewArea,
|
|
930
|
-
|
|
881
|
+
):
|
|
931
882
|
widget.setVisible(False)
|
|
932
883
|
|
|
933
884
|
self.btNewArea.setVisible(True)
|
|
934
885
|
|
|
935
886
|
self.leAreaCode.setText("")
|
|
936
887
|
|
|
888
|
+
self.update_area_list()
|
|
889
|
+
|
|
937
890
|
self.flag_map_changed = True
|
|
938
891
|
self.statusBar().showMessage("New area saved", 5000)
|
|
939
892
|
|
|
940
|
-
self.update_area_list()
|
|
941
|
-
|
|
942
893
|
def cancelAreaCreation(self):
|
|
943
894
|
if self.closedPolygon:
|
|
944
895
|
self.view.scene().removeItem(self.closedPolygon)
|
|
945
896
|
self.closedPolygon = None
|
|
946
897
|
|
|
947
898
|
# remove all lines
|
|
948
|
-
for
|
|
949
|
-
self.view.scene().removeItem(
|
|
899
|
+
for x in self.view.elList:
|
|
900
|
+
self.view.scene().removeItem(x)
|
|
950
901
|
|
|
951
902
|
self.view.elList = []
|
|
952
903
|
|
|
@@ -997,18 +948,15 @@ class BehaviorsMapCreatorWindow(QMainWindow):
|
|
|
997
948
|
self.view._start = 0
|
|
998
949
|
self.view.points = []
|
|
999
950
|
self.flagNewArea = False
|
|
1000
|
-
self.btSaveArea.setVisible(False)
|
|
1001
|
-
self.lb.setVisible(False)
|
|
1002
951
|
|
|
1003
|
-
self.btColor.
|
|
1004
|
-
|
|
952
|
+
for widget in (self.btSaveArea, self.lb, self.btColor, self.slAlpha, self.leAreaCode, self.btDeleteArea):
|
|
953
|
+
widget.setVisible(False)
|
|
954
|
+
|
|
1005
955
|
self.btNewArea.setVisible(True)
|
|
1006
956
|
|
|
1007
|
-
self.leAreaCode.setVisible(False)
|
|
1008
957
|
self.leAreaCode.setText("")
|
|
1009
958
|
self.btEditAreaCode.setVisible(False)
|
|
1010
959
|
|
|
1011
|
-
self.btDeleteArea.setVisible(False)
|
|
1012
960
|
self.statusBar().showMessage("")
|
|
1013
961
|
|
|
1014
962
|
self.update_area_list()
|
|
@@ -1019,63 +967,114 @@ class BehaviorsMapCreatorWindow(QMainWindow):
|
|
|
1019
967
|
"""
|
|
1020
968
|
self.flagNewArea = False
|
|
1021
969
|
self.polygonsList2 = []
|
|
970
|
+
self.closedPolygon = None
|
|
971
|
+
self.selectedPolygon = None
|
|
972
|
+
self.area_list.clear()
|
|
1022
973
|
self.view.scene().clear()
|
|
1023
|
-
self.btLoad.setVisible(False)
|
|
1024
974
|
self.btDeleteArea.setVisible(False)
|
|
1025
975
|
self.btNewArea.setVisible(False)
|
|
1026
976
|
self.saveMapAction.setEnabled(False)
|
|
1027
977
|
self.saveAsMapAction.setEnabled(False)
|
|
1028
978
|
self.addToProject.setEnabled(False)
|
|
1029
979
|
self.mapNameAction.setEnabled(False)
|
|
980
|
+
self.resizeAction.setEnabled(False)
|
|
1030
981
|
self.statusBar().showMessage("")
|
|
1031
982
|
|
|
983
|
+
self.btNewArea.setVisible(True)
|
|
984
|
+
self.btNewArea.setEnabled(True)
|
|
985
|
+
|
|
1032
986
|
self.flag_map_changed = False
|
|
1033
987
|
|
|
1034
988
|
def loadBitmap(self):
|
|
1035
989
|
"""
|
|
1036
990
|
load bitmap as background for coding map
|
|
1037
|
-
resize bitmap to CODING_MAP_RESIZE_W x CODING_MAP_RESIZE_H defined in config.py
|
|
991
|
+
no more resize bitmap to CODING_MAP_RESIZE_W x CODING_MAP_RESIZE_H defined in config.py
|
|
1038
992
|
"""
|
|
1039
993
|
|
|
1040
|
-
|
|
1041
|
-
fileName = fn[0] if type(fn) is tuple else fn
|
|
994
|
+
fileName, _ = QFileDialog.getOpenFileName(self, "Load bitmap", "", "bitmap files (*.png *.jpg);;All files (*)")
|
|
1042
995
|
|
|
1043
|
-
if fileName:
|
|
1044
|
-
|
|
996
|
+
if not fileName:
|
|
997
|
+
return
|
|
998
|
+
self.bitmapFileName = fileName
|
|
1045
999
|
|
|
1046
|
-
|
|
1000
|
+
self.pixmap.load(self.bitmapFileName)
|
|
1047
1001
|
|
|
1048
|
-
|
|
1002
|
+
# scale image
|
|
1003
|
+
"""
|
|
1004
|
+
if (
|
|
1005
|
+
self.pixmap.size().width() > cfg.CODING_MAP_RESIZE_W
|
|
1006
|
+
or self.pixmap.size().height() > cfg.CODING_MAP_RESIZE_H
|
|
1007
|
+
):
|
|
1008
|
+
self.pixmap = self.pixmap.scaled(cfg.CODING_MAP_RESIZE_W, cfg.CODING_MAP_RESIZE_H, Qt.KeepAspectRatio)
|
|
1009
|
+
QMessageBox.information(
|
|
1010
|
+
self,
|
|
1011
|
+
cfg.programName,
|
|
1012
|
+
(
|
|
1013
|
+
f"The bitmap was resized to {self.pixmap.size().width()}x{self.pixmap.size().height()} pixels\n"
|
|
1014
|
+
"The original file was not modified"
|
|
1015
|
+
),
|
|
1016
|
+
)
|
|
1017
|
+
"""
|
|
1018
|
+
|
|
1019
|
+
self.view.setSceneRect(0, 0, self.pixmap.size().width(), self.pixmap.size().height())
|
|
1020
|
+
pixitem = QGraphicsPixmapItem(self.pixmap)
|
|
1021
|
+
pixitem.setPos(0, 0)
|
|
1022
|
+
self.view.scene().addItem(pixitem)
|
|
1023
|
+
|
|
1024
|
+
self.btNewArea.setVisible(True)
|
|
1025
|
+
|
|
1026
|
+
self.saveMapAction.setEnabled(True)
|
|
1027
|
+
self.saveAsMapAction.setEnabled(True)
|
|
1028
|
+
self.addToProject.setEnabled(True)
|
|
1029
|
+
self.mapNameAction.setEnabled(True)
|
|
1030
|
+
self.resizeAction.setEnabled(True)
|
|
1031
|
+
|
|
1032
|
+
self.statusBar().showMessage("""Click "New behavior area" to create a new behavior area""")
|
|
1033
|
+
|
|
1034
|
+
self.flag_map_changed = True
|
|
1035
|
+
|
|
1036
|
+
def resize_clicked(self):
|
|
1037
|
+
"""
|
|
1038
|
+
resize the bitmap
|
|
1039
|
+
"""
|
|
1040
|
+
|
|
1041
|
+
if self.polygonsList2:
|
|
1049
1042
|
if (
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
QMessageBox.information(
|
|
1055
|
-
self,
|
|
1056
|
-
cfg.programName,
|
|
1057
|
-
(
|
|
1058
|
-
f"The bitmap was resized to {self.pixmap.size().width()}x{self.pixmap.size().height()} pixels\n"
|
|
1059
|
-
"The original file was not modified"
|
|
1060
|
-
),
|
|
1043
|
+
dialog.MessageDialog(
|
|
1044
|
+
"BORIS - Behaviors map creator",
|
|
1045
|
+
"The map contains modifiers. Erase all modifiers",
|
|
1046
|
+
(cfg.NO, cfg.YES),
|
|
1061
1047
|
)
|
|
1048
|
+
== cfg.NO
|
|
1049
|
+
):
|
|
1050
|
+
return
|
|
1062
1051
|
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1052
|
+
integer, ok = QInputDialog.getInt(
|
|
1053
|
+
self, "Resize image", "New horizontal size (in pixels)", value=self.pixmap.size().width(), minValue=100, maxValue=3048, step=10
|
|
1054
|
+
)
|
|
1055
|
+
if not ok:
|
|
1056
|
+
return
|
|
1067
1057
|
|
|
1068
|
-
|
|
1058
|
+
self.cancelMap()
|
|
1069
1059
|
|
|
1070
|
-
|
|
1071
|
-
self.saveMapAction.setEnabled(True)
|
|
1072
|
-
self.saveAsMapAction.setEnabled(True)
|
|
1073
|
-
self.addToProject.setEnabled(True)
|
|
1074
|
-
self.mapNameAction.setEnabled(True)
|
|
1060
|
+
h = int(self.pixmap.size().width() / (self.pixmap.size().width() / integer))
|
|
1075
1061
|
|
|
1076
|
-
|
|
1062
|
+
self.pixmap = self.pixmap.scaled(integer, h, Qt.KeepAspectRatio)
|
|
1077
1063
|
|
|
1078
|
-
|
|
1064
|
+
self.view.scene().clear()
|
|
1065
|
+
self.view.setSceneRect(0, 0, self.pixmap.size().width(), self.pixmap.size().height())
|
|
1066
|
+
pixitem = QGraphicsPixmapItem(self.pixmap)
|
|
1067
|
+
pixitem.setPos(0, 0)
|
|
1068
|
+
self.view.scene().addItem(pixitem)
|
|
1069
|
+
|
|
1070
|
+
QMessageBox.information(
|
|
1071
|
+
self,
|
|
1072
|
+
cfg.programName,
|
|
1073
|
+
(
|
|
1074
|
+
f"The bitmap was resized to {self.pixmap.size().width()}x{self.pixmap.size().height()} pixels\n"
|
|
1075
|
+
"The original file was not modified"
|
|
1076
|
+
),
|
|
1077
|
+
)
|
|
1079
1078
|
|
|
1080
1079
|
|
|
1081
1080
|
def behaviors_coding_map_creator(self):
|
|
@@ -1085,7 +1084,7 @@ def behaviors_coding_map_creator(self):
|
|
|
1085
1084
|
|
|
1086
1085
|
if not self.project:
|
|
1087
1086
|
QMessageBox.warning(
|
|
1088
|
-
self, cfg.programName, "
|
|
1087
|
+
self, cfg.programName, "Create or open a project first", QMessageBox.Ok | QMessageBox.Default, QMessageBox.NoButton
|
|
1089
1088
|
)
|
|
1090
1089
|
return
|
|
1091
1090
|
|
|
@@ -1101,11 +1100,11 @@ def behaviors_coding_map_creator(self):
|
|
|
1101
1100
|
|
|
1102
1101
|
|
|
1103
1102
|
if __name__ == "__main__":
|
|
1104
|
-
|
|
1105
1103
|
import sys
|
|
1106
1104
|
|
|
1107
1105
|
app = QApplication(sys.argv)
|
|
1108
1106
|
window = BehaviorsMapCreatorWindow(["North zone", "East zone", "South zone", "West zone"])
|
|
1109
|
-
window.
|
|
1107
|
+
window.bcm_list = []
|
|
1108
|
+
gui_utilities.resize_center(app, window, cfg.CODING_MAP_RESIZE_W, cfg.CODING_MAP_RESIZE_H)
|
|
1110
1109
|
window.show()
|
|
1111
|
-
sys.exit(app.
|
|
1110
|
+
sys.exit(app.exec())
|