celldetective 1.3.9.post5__py3-none-any.whl → 1.4.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.
- celldetective/__init__.py +0 -3
- celldetective/_version.py +1 -1
- celldetective/events.py +2 -4
- celldetective/exceptions.py +11 -0
- celldetective/extra_properties.py +132 -0
- celldetective/filters.py +7 -1
- celldetective/gui/InitWindow.py +37 -46
- celldetective/gui/__init__.py +3 -9
- celldetective/gui/about.py +19 -15
- celldetective/gui/analyze_block.py +34 -19
- celldetective/gui/base_annotator.py +786 -0
- celldetective/gui/base_components.py +23 -0
- celldetective/gui/classifier_widget.py +86 -94
- celldetective/gui/configure_new_exp.py +163 -46
- celldetective/gui/control_panel.py +76 -146
- celldetective/gui/{signal_annotator.py → event_annotator.py} +533 -1438
- celldetective/gui/generic_signal_plot.py +11 -13
- celldetective/gui/gui_utils.py +54 -23
- celldetective/gui/help/neighborhood.json +2 -2
- celldetective/gui/json_readers.py +5 -4
- celldetective/gui/layouts.py +265 -31
- celldetective/gui/{signal_annotator2.py → pair_event_annotator.py} +433 -635
- celldetective/gui/plot_measurements.py +21 -17
- celldetective/gui/plot_signals_ui.py +125 -72
- celldetective/gui/process_block.py +283 -188
- celldetective/gui/processes/compute_neighborhood.py +594 -0
- celldetective/gui/processes/downloader.py +37 -34
- celldetective/gui/processes/measure_cells.py +19 -8
- celldetective/gui/processes/segment_cells.py +47 -11
- celldetective/gui/processes/track_cells.py +18 -13
- celldetective/gui/seg_model_loader.py +21 -62
- celldetective/gui/settings/__init__.py +7 -0
- celldetective/gui/settings/_settings_base.py +70 -0
- celldetective/gui/{retrain_signal_model_options.py → settings/_settings_event_model_training.py} +54 -109
- celldetective/gui/{measurement_options.py → settings/_settings_measurements.py} +54 -92
- celldetective/gui/{neighborhood_options.py → settings/_settings_neighborhood.py} +10 -13
- celldetective/gui/settings/_settings_segmentation.py +49 -0
- celldetective/gui/{retrain_segmentation_model_options.py → settings/_settings_segmentation_model_training.py} +38 -92
- celldetective/gui/{signal_annotator_options.py → settings/_settings_signal_annotator.py} +78 -103
- celldetective/gui/{btrack_options.py → settings/_settings_tracking.py} +85 -116
- celldetective/gui/styles.py +2 -1
- celldetective/gui/survival_ui.py +49 -95
- celldetective/gui/tableUI.py +53 -25
- celldetective/gui/table_ops/__init__.py +0 -0
- celldetective/gui/table_ops/merge_groups.py +118 -0
- celldetective/gui/thresholds_gui.py +617 -1221
- celldetective/gui/viewers.py +107 -42
- celldetective/gui/workers.py +8 -4
- celldetective/io.py +137 -57
- celldetective/links/zenodo.json +145 -144
- celldetective/measure.py +94 -53
- celldetective/neighborhood.py +342 -268
- celldetective/preprocessing.py +56 -35
- celldetective/regionprops/_regionprops.py +16 -5
- celldetective/relative_measurements.py +50 -29
- celldetective/scripts/analyze_signals.py +4 -1
- celldetective/scripts/measure_cells.py +5 -5
- celldetective/scripts/measure_relative.py +20 -12
- celldetective/scripts/segment_cells.py +4 -10
- celldetective/scripts/segment_cells_thresholds.py +3 -3
- celldetective/scripts/track_cells.py +10 -8
- celldetective/scripts/train_segmentation_model.py +18 -6
- celldetective/signals.py +29 -14
- celldetective/tracking.py +14 -3
- celldetective/utils.py +91 -62
- {celldetective-1.3.9.post5.dist-info → celldetective-1.4.1.dist-info}/METADATA +24 -16
- celldetective-1.4.1.dist-info/RECORD +123 -0
- {celldetective-1.3.9.post5.dist-info → celldetective-1.4.1.dist-info}/WHEEL +1 -1
- tests/gui/__init__.py +0 -0
- tests/gui/test_new_project.py +228 -0
- tests/gui/test_project.py +99 -0
- tests/test_preprocessing.py +2 -2
- celldetective/models/segmentation_effectors/ricm_bf_all_last/config_input.json +0 -79
- celldetective/models/segmentation_effectors/ricm_bf_all_last/ricm_bf_all_last +0 -0
- celldetective/models/segmentation_effectors/ricm_bf_all_last/training_instructions.json +0 -37
- celldetective/models/segmentation_effectors/test-transfer/config_input.json +0 -39
- celldetective/models/segmentation_effectors/test-transfer/test-transfer +0 -0
- celldetective/models/signal_detection/NucCond/classification_loss.png +0 -0
- celldetective/models/signal_detection/NucCond/classifier.h5 +0 -0
- celldetective/models/signal_detection/NucCond/config_input.json +0 -1
- celldetective/models/signal_detection/NucCond/log_classifier.csv +0 -126
- celldetective/models/signal_detection/NucCond/log_regressor.csv +0 -282
- celldetective/models/signal_detection/NucCond/regression_loss.png +0 -0
- celldetective/models/signal_detection/NucCond/regressor.h5 +0 -0
- celldetective/models/signal_detection/NucCond/scores.npy +0 -0
- celldetective/models/signal_detection/NucCond/test_confusion_matrix.png +0 -0
- celldetective/models/signal_detection/NucCond/test_regression.png +0 -0
- celldetective/models/signal_detection/NucCond/validation_confusion_matrix.png +0 -0
- celldetective/models/signal_detection/NucCond/validation_regression.png +0 -0
- celldetective-1.3.9.post5.dist-info/RECORD +0 -129
- tests/test_qt.py +0 -103
- {celldetective-1.3.9.post5.dist-info → celldetective-1.4.1.dist-info}/entry_points.txt +0 -0
- {celldetective-1.3.9.post5.dist-info → celldetective-1.4.1.dist-info/licenses}/LICENSE +0 -0
- {celldetective-1.3.9.post5.dist-info → celldetective-1.4.1.dist-info}/top_level.txt +0 -0
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
from PyQt5.QtWidgets import
|
|
2
|
-
QPushButton,
|
|
1
|
+
from PyQt5.QtWidgets import QComboBox, QLabel, QRadioButton, QLineEdit, QFileDialog, QApplication, \
|
|
2
|
+
QPushButton, QVBoxLayout, QHBoxLayout, QMessageBox, QShortcut, QLineEdit, \
|
|
3
3
|
QButtonGroup
|
|
4
4
|
from PyQt5.QtCore import Qt, QSize
|
|
5
5
|
from PyQt5.QtGui import QKeySequence
|
|
6
|
-
from celldetective.gui import Styles
|
|
6
|
+
from celldetective.gui import Styles, CelldetectiveMainWindow, CelldetectiveWidget
|
|
7
7
|
from celldetective.gui.gui_utils import center_window
|
|
8
8
|
from superqt import QLabeledDoubleRangeSlider, QSearchableComboBox
|
|
9
9
|
from celldetective.utils import extract_experiment_channels, get_software_location, _get_img_num_per_channel
|
|
10
|
-
from celldetective.io import auto_load_number_of_frames, load_frames, get_experiment_metadata
|
|
10
|
+
from celldetective.io import auto_load_number_of_frames, load_frames, get_experiment_metadata, get_experiment_labels
|
|
11
11
|
from celldetective.gui.gui_utils import FigureCanvas, color_from_status, color_from_class
|
|
12
12
|
import json
|
|
13
13
|
import numpy as np
|
|
@@ -26,7 +26,7 @@ from sklearn.preprocessing import MinMaxScaler
|
|
|
26
26
|
from functools import partial
|
|
27
27
|
from pandas.api.types import is_numeric_dtype
|
|
28
28
|
|
|
29
|
-
class
|
|
29
|
+
class PairEventAnnotator(CelldetectiveMainWindow):
|
|
30
30
|
|
|
31
31
|
"""
|
|
32
32
|
UI to set tracking parameters for bTrack.
|
|
@@ -41,14 +41,12 @@ class SignalAnnotator2(QMainWindow,Styles):
|
|
|
41
41
|
|
|
42
42
|
self.pos = self.parent_window.parent_window.pos
|
|
43
43
|
self.exp_dir = self.parent_window.exp_dir
|
|
44
|
-
|
|
44
|
+
self.populations = self.parent_window.parent_window.populations
|
|
45
45
|
|
|
46
46
|
self.soft_path = get_software_location()
|
|
47
47
|
self.recently_modified = False
|
|
48
48
|
self.n_signals = 3
|
|
49
|
-
|
|
50
|
-
self.effector_selection = []
|
|
51
|
-
|
|
49
|
+
|
|
52
50
|
self.reference_selection = []
|
|
53
51
|
self.neighbor_selection = []
|
|
54
52
|
self.pair_selection = []
|
|
@@ -61,25 +59,27 @@ class SignalAnnotator2(QMainWindow,Styles):
|
|
|
61
59
|
self.neighbor_track_of_interest = None
|
|
62
60
|
self.value_magnitude = 1
|
|
63
61
|
|
|
64
|
-
self.cols_to_remove = ['
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
62
|
+
self.cols_to_remove = ['group', 'group_color', 'status', 'status_color', 'class_color', 'TRACK_ID', 'FRAME',
|
|
63
|
+
'x_anim', 'y_anim', 't','dummy','group_color',
|
|
64
|
+
'state', 'generation', 'root', 'parent', 'class_id', 'class', 't0', 'POSITION_X',
|
|
65
|
+
'POSITION_Y', 'position', 'well', 'well_index', 'well_name', 'pos_name', 'index',
|
|
66
|
+
'concentration', 'cell_type', 'antibody', 'pharmaceutical_agent', 'ID', "REFERENCE_ID", "NEIGHBOR_ID", "reference_population", "neighbor_population"]
|
|
67
|
+
|
|
69
68
|
meta = get_experiment_metadata(self.exp_dir)
|
|
70
69
|
if meta is not None:
|
|
71
70
|
keys = list(meta.keys())
|
|
72
|
-
self.cols_to_remove.extend(keys)
|
|
71
|
+
self.cols_to_remove.extend(keys)
|
|
72
|
+
|
|
73
|
+
labels = get_experiment_labels(self.exp_dir)
|
|
74
|
+
if labels is not None:
|
|
75
|
+
keys = list(labels.keys())
|
|
76
|
+
self.cols_to_remove.extend(labels)
|
|
77
|
+
|
|
73
78
|
|
|
74
79
|
# Read instructions from target block for now...
|
|
75
80
|
self.mode = "neighborhood"
|
|
76
81
|
self.instructions_path = self.exp_dir + os.sep.join(['configs', 'signal_annotator_config_neighborhood.json'])
|
|
77
82
|
|
|
78
|
-
# default params
|
|
79
|
-
self.target_class_name = 'class'
|
|
80
|
-
self.target_time_name = 't0'
|
|
81
|
-
self.target_status_name = 'status'
|
|
82
|
-
|
|
83
83
|
center_window(self)
|
|
84
84
|
|
|
85
85
|
# Locate stack
|
|
@@ -87,21 +87,15 @@ class SignalAnnotator2(QMainWindow,Styles):
|
|
|
87
87
|
self.load_annotator_config()
|
|
88
88
|
|
|
89
89
|
# Locate tracks
|
|
90
|
-
self.
|
|
91
|
-
self.
|
|
92
|
-
|
|
93
|
-
self.dataframes = {
|
|
94
|
-
'targets': self.df_targets,
|
|
95
|
-
'effectors': self.df_effectors,
|
|
96
|
-
}
|
|
90
|
+
self.locate_all_tracks()
|
|
91
|
+
self.extract_scatter_from_trajectories()
|
|
97
92
|
|
|
98
93
|
self.neighborhood_cols = []
|
|
99
|
-
|
|
100
|
-
self.
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
print(f"The following neighborhoods were detected: {self.neighborhood_cols=}")
|
|
94
|
+
for pop in self.dataframes.keys():
|
|
95
|
+
if self.dataframes[pop] is not None:
|
|
96
|
+
self.neighborhood_cols.extend([f'{pop}_ref_'+c for c in list(self.dataframes[pop].columns) if c.startswith('neighborhood')])
|
|
97
|
+
print(f"The following neighborhoods were detected: {self.neighborhood_cols=}...")
|
|
98
|
+
|
|
105
99
|
self.locate_relative_tracks()
|
|
106
100
|
|
|
107
101
|
# Prepare stack
|
|
@@ -132,8 +126,6 @@ class SignalAnnotator2(QMainWindow,Styles):
|
|
|
132
126
|
|
|
133
127
|
#self.cell_fcanvas.setMinimumHeight(int(0.3*self.screen_height))
|
|
134
128
|
|
|
135
|
-
self.setAttribute(Qt.WA_DeleteOnClose)
|
|
136
|
-
|
|
137
129
|
def resizeEvent(self, event):
|
|
138
130
|
|
|
139
131
|
super().resizeEvent(event)
|
|
@@ -149,7 +141,7 @@ class SignalAnnotator2(QMainWindow,Styles):
|
|
|
149
141
|
|
|
150
142
|
"""
|
|
151
143
|
|
|
152
|
-
self.button_widget =
|
|
144
|
+
self.button_widget = CelldetectiveWidget()
|
|
153
145
|
main_layout = QHBoxLayout()
|
|
154
146
|
main_layout.setSpacing(30)
|
|
155
147
|
|
|
@@ -175,8 +167,10 @@ class SignalAnnotator2(QMainWindow,Styles):
|
|
|
175
167
|
self.left_panel.addLayout(neigh_hbox)
|
|
176
168
|
|
|
177
169
|
self.reference_cell_info = QLabel('')
|
|
170
|
+
self.reference_cell_info.setStyleSheet("color: #1f77b4;")
|
|
178
171
|
self.pair_info = QLabel('')
|
|
179
172
|
self.neighbor_cell_info= QLabel('')
|
|
173
|
+
self.neighbor_cell_info.setStyleSheet("color: #d62728;")
|
|
180
174
|
|
|
181
175
|
class_hbox = QHBoxLayout()
|
|
182
176
|
class_hbox.addWidget(QLabel('interaction event: '), 25)
|
|
@@ -237,11 +231,11 @@ class SignalAnnotator2(QMainWindow,Styles):
|
|
|
237
231
|
reference_layout.addLayout(self.cell_events_hbox)
|
|
238
232
|
|
|
239
233
|
neighbor_layout = QVBoxLayout()
|
|
240
|
-
neighbor_layout.addWidget(self.neighbor_cell_info)
|
|
234
|
+
neighbor_layout.addWidget(self.neighbor_cell_info, alignment=Qt.AlignRight)
|
|
241
235
|
neighbor_layout.addLayout(self.neigh_cell_events_hbox)
|
|
242
236
|
|
|
243
237
|
self.cell_info_hbox.addLayout(reference_layout, 33)
|
|
244
|
-
self.cell_info_hbox.addWidget(self.pair_info, 33)
|
|
238
|
+
self.cell_info_hbox.addWidget(self.pair_info, 33, alignment=Qt.AlignCenter)
|
|
245
239
|
self.cell_info_hbox.addLayout(neighbor_layout, 33)
|
|
246
240
|
|
|
247
241
|
self.left_panel.addLayout(self.cell_info_hbox)
|
|
@@ -419,8 +413,6 @@ class SignalAnnotator2(QMainWindow,Styles):
|
|
|
419
413
|
|
|
420
414
|
|
|
421
415
|
self.right_panel.addLayout(animation_buttons_box, 5)
|
|
422
|
-
|
|
423
|
-
|
|
424
416
|
self.right_panel.addWidget(self.fcanvas, 90)
|
|
425
417
|
|
|
426
418
|
if not self.rgb_mode:
|
|
@@ -429,7 +421,7 @@ class SignalAnnotator2(QMainWindow,Styles):
|
|
|
429
421
|
self.contrast_slider = QLabeledDoubleRangeSlider()
|
|
430
422
|
# self.contrast_slider.setSingleStep(0.001)
|
|
431
423
|
# self.contrast_slider.setTickInterval(0.001)
|
|
432
|
-
self.contrast_slider.setOrientation(
|
|
424
|
+
self.contrast_slider.setOrientation(Qt.Horizontal)
|
|
433
425
|
print('range: ', [np.nanpercentile(self.stack.flatten(), 0.001), np.nanpercentile(self.stack.flatten(), 99.999)])
|
|
434
426
|
self.contrast_slider.setRange(
|
|
435
427
|
*[np.nanpercentile(self.stack, 0.001), np.nanpercentile(self.stack, 99.999)])
|
|
@@ -444,6 +436,7 @@ class SignalAnnotator2(QMainWindow,Styles):
|
|
|
444
436
|
main_layout.addLayout(self.right_panel, 65)
|
|
445
437
|
self.button_widget.adjustSize()
|
|
446
438
|
self.compute_status_and_colors_reference()
|
|
439
|
+
self.compute_status_and_colors_neighbor()
|
|
447
440
|
|
|
448
441
|
self.extract_relevant_events()
|
|
449
442
|
|
|
@@ -486,53 +479,6 @@ class SignalAnnotator2(QMainWindow,Styles):
|
|
|
486
479
|
self.neighbor_event_choice_cb.addItems(neighbor_class_cols)
|
|
487
480
|
self.neighbor_event_choice_cb.currentIndexChanged.connect(self.compute_status_and_colors_neighbor)
|
|
488
481
|
|
|
489
|
-
|
|
490
|
-
def del_target_event_class(self):
|
|
491
|
-
|
|
492
|
-
msgBox = QMessageBox()
|
|
493
|
-
msgBox.setIcon(QMessageBox.Warning)
|
|
494
|
-
msgBox.setText(f"You are about to delete event class {self.target_class_choice_cb.currentText()}. The associated time and\nstatus will also be deleted. Do you still want to proceed?")
|
|
495
|
-
msgBox.setWindowTitle("Warning")
|
|
496
|
-
msgBox.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
|
|
497
|
-
returnValue = msgBox.exec()
|
|
498
|
-
if returnValue == QMessageBox.No:
|
|
499
|
-
return None
|
|
500
|
-
else:
|
|
501
|
-
class_to_delete = self.target_class_choice_cb.currentText()
|
|
502
|
-
time_to_delete = class_to_delete.replace('class','t')
|
|
503
|
-
status_to_delete = class_to_delete.replace('class', 'status')
|
|
504
|
-
cols_to_delete = [class_to_delete, time_to_delete, status_to_delete]
|
|
505
|
-
for c in cols_to_delete:
|
|
506
|
-
try:
|
|
507
|
-
self.df_targets = self.df_targets.drop([c], axis=1)
|
|
508
|
-
except Exception as e:
|
|
509
|
-
print(e)
|
|
510
|
-
item_idx = self.target_class_choice_cb.findText(class_to_delete)
|
|
511
|
-
self.target_class_choice_cb.removeItem(item_idx)
|
|
512
|
-
|
|
513
|
-
def del_effector_event_class(self):
|
|
514
|
-
|
|
515
|
-
msgBox = QMessageBox()
|
|
516
|
-
msgBox.setIcon(QMessageBox.Warning)
|
|
517
|
-
msgBox.setText(f"You are about to delete event class {self.effector_class_choice_cb.currentText()}. The associated time and\nstatus will also be deleted. Do you still want to proceed?")
|
|
518
|
-
msgBox.setWindowTitle("Warning")
|
|
519
|
-
msgBox.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
|
|
520
|
-
returnValue = msgBox.exec()
|
|
521
|
-
if returnValue == QMessageBox.No:
|
|
522
|
-
return None
|
|
523
|
-
else:
|
|
524
|
-
class_to_delete = self.effector_class_choice_cb.currentText()
|
|
525
|
-
time_to_delete = class_to_delete.replace('class','t')
|
|
526
|
-
status_to_delete = class_to_delete.replace('class', 'status')
|
|
527
|
-
cols_to_delete = [class_to_delete, time_to_delete, status_to_delete]
|
|
528
|
-
for c in cols_to_delete:
|
|
529
|
-
try:
|
|
530
|
-
self.df_effectors = self.df_effectors.drop([c], axis=1)
|
|
531
|
-
except Exception as e:
|
|
532
|
-
print(e)
|
|
533
|
-
item_idx = self.effector_class_choice_cb.findText(class_to_delete)
|
|
534
|
-
self.effector_class_choice_cb.removeItem(item_idx)
|
|
535
|
-
|
|
536
482
|
def del_relative_event_class(self):
|
|
537
483
|
|
|
538
484
|
msgBox = QMessageBox()
|
|
@@ -557,55 +503,30 @@ class SignalAnnotator2(QMainWindow,Styles):
|
|
|
557
503
|
self.relative_class_choice_cb.removeItem(item_idx)
|
|
558
504
|
|
|
559
505
|
def update_cell_events(self):
|
|
560
|
-
if 'self' in self.current_neighborhood:
|
|
561
|
-
try:
|
|
562
|
-
self.neighbor_event_choice_cb.hide()
|
|
563
|
-
self.neigh_lab.hide()
|
|
564
|
-
except:
|
|
565
|
-
pass
|
|
566
|
-
self.reference_event_choice_cb.disconnect()
|
|
567
|
-
self.reference_event_choice_cb.clear()
|
|
568
|
-
if self.reference_population=='targets':
|
|
569
|
-
self.reference_event_choice_cb.addItems(self.target_class_cols)
|
|
570
|
-
self.reference_event_choice_cb.currentIndexChanged.connect(self.compute_status_and_colors_reference)
|
|
571
|
-
else:
|
|
572
|
-
self.reference_event_choice_cb.addItems(self.effector_class_cols)
|
|
573
|
-
self.reference_event_choice_cb.currentIndexChanged.connect(self.compute_status_and_colors_neighbor)
|
|
574
|
-
|
|
575
|
-
else:
|
|
576
|
-
try:
|
|
577
|
-
self.neighbor_event_choice_cb.show()
|
|
578
|
-
self.neigh_lab.show()
|
|
579
|
-
except:
|
|
580
|
-
pass
|
|
581
|
-
self.reference_event_choice_cb.disconnect()
|
|
582
|
-
self.reference_event_choice_cb.clear()
|
|
583
506
|
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
507
|
+
try:
|
|
508
|
+
self.neighbor_event_choice_cb.show()
|
|
509
|
+
self.neigh_lab.show()
|
|
510
|
+
except:
|
|
511
|
+
pass
|
|
587
512
|
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
513
|
+
self.reference_event_choice_cb.disconnect()
|
|
514
|
+
self.reference_event_choice_cb.clear()
|
|
515
|
+
self.reference_event_choice_cb.addItems(self.class_cols_per_pop[self.reference_population])
|
|
516
|
+
self.reference_event_choice_cb.currentIndexChanged.connect(self.compute_status_and_colors_reference)
|
|
591
517
|
|
|
518
|
+
if not 'self' in self.current_neighborhood:
|
|
592
519
|
self.neighbor_event_choice_cb.disconnect()
|
|
593
520
|
self.neighbor_event_choice_cb.clear()
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
self.neighbor_event_choice_cb.addItems(self.target_class_cols)
|
|
597
|
-
self.neighbor_event_choice_cb.currentIndexChanged.connect(self.compute_status_and_colors_reference)
|
|
598
|
-
|
|
599
|
-
else:
|
|
600
|
-
self.neighbor_event_choice_cb.addItems(self.effector_class_cols)
|
|
601
|
-
self.neighbor_event_choice_cb.currentIndexChanged.connect(self.compute_status_and_colors_neighbor)
|
|
521
|
+
self.neighbor_event_choice_cb.addItems(self.class_cols_per_pop[self.neighbor_population])
|
|
522
|
+
self.neighbor_event_choice_cb.currentIndexChanged.connect(self.compute_status_and_colors_reference)
|
|
602
523
|
|
|
603
524
|
|
|
604
525
|
|
|
605
526
|
def create_new_relative_event_class(self):
|
|
606
527
|
|
|
607
528
|
# display qwidget to name the event
|
|
608
|
-
self.newClassWidget =
|
|
529
|
+
self.newClassWidget = CelldetectiveWidget()
|
|
609
530
|
self.newClassWidget.setWindowTitle('Create new event class')
|
|
610
531
|
|
|
611
532
|
layout = QVBoxLayout()
|
|
@@ -723,12 +644,18 @@ class SignalAnnotator2(QMainWindow,Styles):
|
|
|
723
644
|
df_reference['status_color'] = [color_from_status(i) for i in df_reference[self.reference_status_name].to_numpy()]
|
|
724
645
|
df_reference['class_color'] = [color_from_class(i) for i in df_reference[self.reference_class_name].to_numpy()]
|
|
725
646
|
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
647
|
+
self.refresh_scatter_from_trajectories(self.reference_population, clear_selection=False)
|
|
648
|
+
|
|
649
|
+
if self.reference_track_of_interest is not None:
|
|
650
|
+
t_reference = df_reference.loc[
|
|
651
|
+
df_reference['TRACK_ID'] == self.reference_track_of_interest, self.reference_time_name].values
|
|
652
|
+
if len(t_reference) > 0:
|
|
653
|
+
t_reference = t_reference[0]
|
|
654
|
+
ymin, ymax = self.cell_ax.get_ylim()
|
|
655
|
+
self.line_dt_reference.set_xdata([t_reference, t_reference])
|
|
656
|
+
self.line_dt_reference.set_ydata([ymin,ymax])
|
|
657
|
+
self.cell_fcanvas.canvas.draw()
|
|
658
|
+
|
|
732
659
|
def compute_status_and_colors_neighbor(self):
|
|
733
660
|
|
|
734
661
|
df_neighbors = self.dataframes[self.neighbor_population]
|
|
@@ -767,10 +694,8 @@ class SignalAnnotator2(QMainWindow,Styles):
|
|
|
767
694
|
df_neighbors['status_color'] = [color_from_status(i) for i in df_neighbors[self.neighbor_status_name].to_numpy()]
|
|
768
695
|
df_neighbors['class_color'] = [color_from_class(i) for i in df_neighbors[self.neighbor_class_name].to_numpy()]
|
|
769
696
|
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
else:
|
|
773
|
-
self.extract_scatter_from_effector_trajectories()
|
|
697
|
+
self.refresh_scatter_from_trajectories(self.neighbor_population)
|
|
698
|
+
|
|
774
699
|
|
|
775
700
|
def compute_status_and_colors_pair(self):
|
|
776
701
|
|
|
@@ -845,13 +770,8 @@ class SignalAnnotator2(QMainWindow,Styles):
|
|
|
845
770
|
if len(self.pair_selection) > 0:
|
|
846
771
|
self.cancel_pair_selection()
|
|
847
772
|
|
|
848
|
-
if self.df_targets is not None:
|
|
849
|
-
self.target_selection = []
|
|
850
|
-
if self.df_effectors is not None:
|
|
851
|
-
self.effector_selection = []
|
|
852
|
-
|
|
853
773
|
_, _, neighbor_colors, initial_neighbor_colors = self.get_neighbor_sets()
|
|
854
|
-
_, _, reference_colors, initial_reference_colors = self.get_reference_sets()
|
|
774
|
+
_, _, _, reference_colors, initial_reference_colors = self.get_reference_sets()
|
|
855
775
|
|
|
856
776
|
for k, (t,idx) in enumerate(zip(self.neighbor_loc_t, self.neighbor_loc_idx)):
|
|
857
777
|
neighbor_colors[t][idx,0] = initial_neighbor_colors[k][0]
|
|
@@ -936,8 +856,17 @@ class SignalAnnotator2(QMainWindow,Styles):
|
|
|
936
856
|
if option!=0:
|
|
937
857
|
self.lines[i].set_xdata([])
|
|
938
858
|
self.lines[i].set_ydata([])
|
|
859
|
+
|
|
939
860
|
self.line_dt.set_xdata([])
|
|
940
861
|
self.line_dt.set_ydata([])
|
|
862
|
+
|
|
863
|
+
if self.reference_track_of_interest is None:
|
|
864
|
+
self.line_dt_reference.set_xdata([])
|
|
865
|
+
self.line_dt_reference.set_ydata([])
|
|
866
|
+
|
|
867
|
+
self.line_dt_neighbor.set_xdata([])
|
|
868
|
+
self.line_dt_neighbor.set_ydata([])
|
|
869
|
+
|
|
941
870
|
self.lines[i].set_label('')
|
|
942
871
|
|
|
943
872
|
self.correct_btn.setEnabled(False)
|
|
@@ -949,15 +878,15 @@ class SignalAnnotator2(QMainWindow,Styles):
|
|
|
949
878
|
# Plot the new time
|
|
950
879
|
t0 = -1
|
|
951
880
|
if self.event_btn.isChecked():
|
|
952
|
-
try:
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
except Exception as e:
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
881
|
+
# try:
|
|
882
|
+
cclass = 0
|
|
883
|
+
t0 = float(self.time_of_interest_le.text().replace(',', '.'))
|
|
884
|
+
self.line_dt.set_xdata([t0, t0])
|
|
885
|
+
self.cell_fcanvas.canvas.draw_idle()
|
|
886
|
+
# except Exception as e:
|
|
887
|
+
# print(e)
|
|
888
|
+
# t0 = -1
|
|
889
|
+
# cclass = 2
|
|
961
890
|
|
|
962
891
|
elif self.no_event_btn.isChecked():
|
|
963
892
|
cclass = 1
|
|
@@ -1012,8 +941,8 @@ class SignalAnnotator2(QMainWindow,Styles):
|
|
|
1012
941
|
# but keep reference
|
|
1013
942
|
|
|
1014
943
|
#self.make_status_column()
|
|
1015
|
-
self.
|
|
1016
|
-
self.
|
|
944
|
+
self.refresh_scatter_from_trajectories(self.reference_population)
|
|
945
|
+
self.refresh_scatter_from_trajectories(self.neighbor_population)
|
|
1017
946
|
|
|
1018
947
|
self.recolor_selection()
|
|
1019
948
|
self.trace_neighbors()
|
|
@@ -1048,234 +977,128 @@ class SignalAnnotator2(QMainWindow,Styles):
|
|
|
1048
977
|
self.channels = np.array(self.channels)
|
|
1049
978
|
self.nbr_channels = len(self.channels)
|
|
1050
979
|
|
|
1051
|
-
def
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
self.
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
980
|
+
def locate_all_tracks(self):
|
|
981
|
+
|
|
982
|
+
self.dataframes = {}
|
|
983
|
+
self.class_cols_per_pop = {}
|
|
984
|
+
self.population_columns = {}
|
|
985
|
+
self.MinMaxScaler_per_pop = {}
|
|
986
|
+
|
|
987
|
+
for population in self.populations:
|
|
988
|
+
|
|
989
|
+
population_trajectories_path = self.pos + os.sep.join(['output','tables', f'trajectories_{population}.pkl'])
|
|
990
|
+
if not os.path.exists(population_trajectories_path):
|
|
991
|
+
population_trajectories_path = population_trajectories_path.replace('.pkl','.csv')
|
|
992
|
+
|
|
993
|
+
if not os.path.exists(population_trajectories_path):
|
|
994
|
+
|
|
995
|
+
msgBox = QMessageBox()
|
|
996
|
+
msgBox.setIcon(QMessageBox.Warning)
|
|
997
|
+
msgBox.setText(f"The trajectories for the {population} population cannot be detected...")
|
|
998
|
+
msgBox.setWindowTitle("Warning")
|
|
999
|
+
msgBox.setStandardButtons(QMessageBox.Ok)
|
|
1000
|
+
returnValue = msgBox.exec()
|
|
1001
|
+
df_population = None
|
|
1073
1002
|
else:
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
self.target_class_cols = [c for c in list(self.df_targets.columns) if c.startswith('class')]
|
|
1080
|
-
|
|
1081
|
-
try:
|
|
1082
|
-
self.target_class_cols.remove('class_id')
|
|
1083
|
-
except:
|
|
1084
|
-
pass
|
|
1085
|
-
try:
|
|
1086
|
-
self.target_class_cols.remove('class_color')
|
|
1087
|
-
except:
|
|
1088
|
-
pass
|
|
1003
|
+
# Load and prep tracks
|
|
1004
|
+
if population_trajectories_path.endswith('.pkl'):
|
|
1005
|
+
df_population = np.load(population_trajectories_path, allow_pickle=True)
|
|
1006
|
+
else:
|
|
1007
|
+
df_population = pd.read_csv(population_trajectories_path)
|
|
1089
1008
|
|
|
1090
|
-
|
|
1009
|
+
df_population = df_population.sort_values(by=['TRACK_ID', 'FRAME'])
|
|
1091
1010
|
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
suffix = self.target_class_name.replace('class','').replace('_','')
|
|
1095
|
-
if suffix!='':
|
|
1096
|
-
self.target_expected_status+='_'+suffix
|
|
1097
|
-
self.target_expected_time = 't_'+suffix
|
|
1098
|
-
else:
|
|
1099
|
-
self.target_expected_time = 't0'
|
|
1100
|
-
self.target_time_name = self.target_expected_time
|
|
1101
|
-
self.target_status_name = self.target_expected_status
|
|
1102
|
-
else:
|
|
1103
|
-
self.target_class_name = 'class'
|
|
1104
|
-
self.target_time_name = 't0'
|
|
1105
|
-
self.target_status_name = 'status'
|
|
1011
|
+
cols = np.array(df_population.columns)
|
|
1012
|
+
class_cols = [c for c in list(df_population.columns) if c.startswith('class')]
|
|
1106
1013
|
|
|
1107
|
-
if self.target_time_name in self.df_targets.columns and self.target_class_name in self.df_targets.columns and not self.target_status_name in self.df_targets.columns:
|
|
1108
|
-
# only create the status column if it does not exist to not erase static classification results
|
|
1109
|
-
pass
|
|
1110
|
-
#self.make_target_status_column()
|
|
1111
|
-
elif self.target_time_name in self.df_targets.columns and self.target_class_name in self.df_targets.columns:
|
|
1112
|
-
# all good, do nothing
|
|
1113
|
-
pass
|
|
1114
|
-
else:
|
|
1115
|
-
if not self.target_status_name in self.df_targets.columns:
|
|
1116
|
-
self.df_targets[self.target_status_name] = 0
|
|
1117
|
-
self.df_targets['status_color'] = color_from_status(0)
|
|
1118
|
-
self.df_targets['class_color'] = color_from_class(1)
|
|
1119
|
-
|
|
1120
|
-
if not self.target_class_name in self.df_targets.columns:
|
|
1121
|
-
self.df_targets[self.target_class_name] = 1
|
|
1122
|
-
if not self.target_time_name in self.df_targets.columns:
|
|
1123
|
-
self.df_targets[self.target_time_name] = -1
|
|
1124
|
-
|
|
1125
|
-
self.df_targets['status_color'] = color_from_status(2) #[color_from_status(i) for i in self.df_targets[self.target_status_name].to_numpy()]
|
|
1126
|
-
self.df_targets['class_color'] = color_from_status(2) #[color_from_class(i) for i in self.df_targets[self.target_class_name].to_numpy()]
|
|
1127
|
-
|
|
1128
|
-
self.df_targets = self.df_targets.dropna(subset=['POSITION_X', 'POSITION_Y'])
|
|
1129
|
-
self.df_targets['x_anim'] = self.df_targets['POSITION_X'] * self.fraction
|
|
1130
|
-
self.df_targets['y_anim'] = self.df_targets['POSITION_Y'] * self.fraction
|
|
1131
|
-
self.df_targets['x_anim'] = self.df_targets['x_anim'].astype(int)
|
|
1132
|
-
self.df_targets['y_anim'] = self.df_targets['y_anim'].astype(int)
|
|
1133
|
-
|
|
1134
|
-
self.extract_scatter_from_target_trajectories()
|
|
1135
|
-
self.target_track_of_interest = self.df_targets['TRACK_ID'].min()
|
|
1136
|
-
|
|
1137
|
-
self.loc_t = []
|
|
1138
|
-
self.loc_idx = []
|
|
1139
|
-
for t in range(len(self.target_tracks)):
|
|
1140
|
-
indices = np.where(self.target_tracks[t]==self.target_track_of_interest)[0]
|
|
1141
|
-
if len(indices)>0:
|
|
1142
|
-
self.loc_t.append(t)
|
|
1143
|
-
self.loc_idx.append(indices[0])
|
|
1144
|
-
|
|
1145
|
-
self.MinMaxScaler_targets = MinMaxScaler()
|
|
1146
|
-
self.target_columns = list(self.df_targets.columns)
|
|
1147
|
-
cols_to_remove = [c for c in self.cols_to_remove if c in self.target_columns] + self.target_class_cols
|
|
1148
|
-
time_cols = [c for c in self.target_columns if c.startswith('t_')]
|
|
1149
|
-
cols_to_remove += time_cols
|
|
1150
|
-
neigh_cols = [c for c in self.target_columns if c.startswith('neighborhood_')]
|
|
1151
|
-
cols_to_remove += neigh_cols
|
|
1152
|
-
|
|
1153
|
-
for col in cols_to_remove:
|
|
1154
1014
|
try:
|
|
1155
|
-
|
|
1015
|
+
class_cols.remove('class_id')
|
|
1016
|
+
except:
|
|
1017
|
+
pass
|
|
1018
|
+
try:
|
|
1019
|
+
class_cols.remove('class_color')
|
|
1156
1020
|
except:
|
|
1157
1021
|
pass
|
|
1158
1022
|
|
|
1159
|
-
|
|
1160
|
-
self.MinMaxScaler_targets.fit(x)
|
|
1161
|
-
|
|
1162
|
-
def locate_effector_tracks(self):
|
|
1163
|
-
|
|
1164
|
-
population = 'effectors'
|
|
1165
|
-
self.effector_trajectories_path = self.pos + os.sep.join(['output','tables',f'trajectories_{population}.pkl'])
|
|
1166
|
-
if not os.path.exists(self.effector_trajectories_path):
|
|
1167
|
-
self.effector_trajectories_path = self.effector_trajectories_path.replace('.pkl','.csv')
|
|
1168
|
-
|
|
1169
|
-
if not os.path.exists(self.effector_trajectories_path):
|
|
1170
|
-
|
|
1171
|
-
msgBox = QMessageBox()
|
|
1172
|
-
msgBox.setIcon(QMessageBox.Warning)
|
|
1173
|
-
msgBox.setText("The effector trajectories cannot be detected...")
|
|
1174
|
-
msgBox.setWindowTitle("Warning")
|
|
1175
|
-
msgBox.setStandardButtons(QMessageBox.Ok)
|
|
1176
|
-
returnValue = msgBox.exec()
|
|
1177
|
-
self.df_effectors = None
|
|
1178
|
-
else:
|
|
1179
|
-
# Load and prep tracks
|
|
1180
|
-
if self.effector_trajectories_path.endswith('.pkl'):
|
|
1181
|
-
self.df_effectors = np.load(self.effector_trajectories_path, allow_pickle=True)
|
|
1182
|
-
else:
|
|
1183
|
-
self.df_effectors = pd.read_csv(self.effector_trajectories_path)
|
|
1184
|
-
|
|
1185
|
-
try:
|
|
1186
|
-
self.df_effectors = self.df_effectors.sort_values(by=['TRACK_ID', 'FRAME'])
|
|
1187
|
-
except:
|
|
1188
|
-
self.df_effectors = self.df_effectors.sort_values(by=['ID', 'FRAME'])
|
|
1189
|
-
|
|
1023
|
+
if len(class_cols)>0:
|
|
1190
1024
|
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
pass
|
|
1202
|
-
if len(self.effector_class_cols)>0:
|
|
1203
|
-
self.effector_class_name = self.effector_class_cols[0]
|
|
1204
|
-
self.effector_expected_status = 'status'
|
|
1205
|
-
suffix = self.effector_class_name.replace('class','').replace('_','')
|
|
1206
|
-
if suffix!='':
|
|
1207
|
-
self.effector_expected_status+='_'+suffix
|
|
1208
|
-
self.effector_expected_time = 't_'+suffix
|
|
1025
|
+
pop_class_name = class_cols[0]
|
|
1026
|
+
pop_expected_status = 'status'
|
|
1027
|
+
suffix = pop_class_name.replace('class','').replace('_','')
|
|
1028
|
+
if suffix!='':
|
|
1029
|
+
pop_expected_status+='_'+suffix
|
|
1030
|
+
pop_expected_time = 't_'+suffix
|
|
1031
|
+
else:
|
|
1032
|
+
pop_expected_time = 't0'
|
|
1033
|
+
pop_time_name = pop_expected_time
|
|
1034
|
+
pop_status_name = pop_expected_status
|
|
1209
1035
|
else:
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
else:
|
|
1214
|
-
self.effector_class_name = 'class'
|
|
1215
|
-
self.effector_time_name = 't0'
|
|
1216
|
-
self.effector_status_name = 'status'
|
|
1036
|
+
pop_class_name = 'class'
|
|
1037
|
+
pop_time_name = 't0'
|
|
1038
|
+
pop_status_name = 'status'
|
|
1217
1039
|
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
pass
|
|
1225
|
-
else:
|
|
1226
|
-
if not self.effector_status_name in self.df_effectors.columns:
|
|
1227
|
-
self.df_effectors[self.effector_status_name] = 0
|
|
1228
|
-
self.df_effectors['status_color'] = color_from_status(0)
|
|
1229
|
-
self.df_effectors['class_color'] = color_from_class(1)
|
|
1230
|
-
|
|
1231
|
-
if not self.effector_class_name in self.df_effectors.columns:
|
|
1232
|
-
self.df_effectors[self.effector_class_name] = 1
|
|
1233
|
-
if not self.effector_time_name in self.df_effectors.columns:
|
|
1234
|
-
self.df_effectors[self.effector_time_name] = -1
|
|
1235
|
-
|
|
1236
|
-
self.df_effectors['status_color'] = color_from_status(2) #[color_from_status(i) for i in self.df_effectors[self.effector_status_name].to_numpy()]
|
|
1237
|
-
self.df_effectors['class_color'] = color_from_status(2) #[color_from_class(i) for i in self.df_effectors[self.effector_class_name].to_numpy()]
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
self.df_effectors = self.df_effectors.dropna(subset=['POSITION_X', 'POSITION_Y'])
|
|
1241
|
-
self.df_effectors['x_anim'] = self.df_effectors['POSITION_X'] * self.fraction
|
|
1242
|
-
self.df_effectors['y_anim'] = self.df_effectors['POSITION_Y'] * self.fraction
|
|
1243
|
-
self.df_effectors['x_anim'] = self.df_effectors['x_anim'].astype(int)
|
|
1244
|
-
self.df_effectors['y_anim'] = self.df_effectors['y_anim'].astype(int)
|
|
1245
|
-
|
|
1246
|
-
self.extract_scatter_from_effector_trajectories()
|
|
1247
|
-
try:
|
|
1248
|
-
self.effector_track_of_interest = self.df_effectors['TRACK_ID'].min()
|
|
1249
|
-
except:
|
|
1250
|
-
self.effector_track_of_interest = self.df_effectors['ID'].min()
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
self.loc_t = []
|
|
1254
|
-
self.loc_idx = []
|
|
1255
|
-
for t in range(len(self.effector_tracks)):
|
|
1256
|
-
indices = np.where(self.effector_tracks[t]==self.effector_track_of_interest)[0]
|
|
1257
|
-
if len(indices)>0:
|
|
1258
|
-
self.loc_t.append(t)
|
|
1259
|
-
self.loc_idx.append(indices[0])
|
|
1260
|
-
|
|
1261
|
-
self.MinMaxScaler_effectors = MinMaxScaler()
|
|
1262
|
-
self.effector_columns = list(self.df_effectors.columns)
|
|
1263
|
-
cols_to_remove = [c for c in self.cols_to_remove if c in self.effector_columns] + self.effector_class_cols
|
|
1264
|
-
time_cols = [c for c in self.effector_columns if c.startswith('t_')]
|
|
1265
|
-
cols_to_remove += time_cols
|
|
1266
|
-
neigh_cols = [c for c in self.effector_columns if c.startswith('neighborhood_')]
|
|
1267
|
-
cols_to_remove += neigh_cols
|
|
1268
|
-
|
|
1269
|
-
for col in cols_to_remove:
|
|
1270
|
-
try:
|
|
1271
|
-
self.effector_columns.remove(col)
|
|
1272
|
-
except:
|
|
1040
|
+
if pop_time_name in df_population.columns and pop_class_name in df_population.columns and not pop_status_name in df_population.columns:
|
|
1041
|
+
# only create the status column if it does not exist to not erase static classification results
|
|
1042
|
+
pass
|
|
1043
|
+
#self.make_target_status_column()
|
|
1044
|
+
elif pop_time_name in df_population.columns and pop_class_name in df_population.columns:
|
|
1045
|
+
# all good, do nothing
|
|
1273
1046
|
pass
|
|
1047
|
+
else:
|
|
1048
|
+
if not pop_status_name in df_population.columns:
|
|
1049
|
+
df_population[pop_status_name] = 0
|
|
1050
|
+
df_population['status_color'] = color_from_status(0)
|
|
1051
|
+
df_population['class_color'] = color_from_class(1)
|
|
1052
|
+
|
|
1053
|
+
if not pop_class_name in df_population.columns:
|
|
1054
|
+
df_population[pop_class_name] = 1
|
|
1055
|
+
if not pop_time_name in df_population.columns:
|
|
1056
|
+
df_population[pop_time_name] = -1
|
|
1057
|
+
|
|
1058
|
+
df_population['status_color'] = color_from_status(2)
|
|
1059
|
+
df_population['class_color'] = color_from_status(2)
|
|
1060
|
+
|
|
1061
|
+
df_population = df_population.dropna(subset=['POSITION_X', 'POSITION_Y'])
|
|
1062
|
+
df_population['x_anim'] = df_population['POSITION_X'] * self.fraction
|
|
1063
|
+
df_population['y_anim'] = df_population['POSITION_Y'] * self.fraction
|
|
1064
|
+
df_population['x_anim'] = df_population['x_anim'].astype(int)
|
|
1065
|
+
df_population['y_anim'] = df_population['y_anim'].astype(int)
|
|
1066
|
+
|
|
1067
|
+
#self.reference_positions, self.reference_tracks, self.reference_colors, self.reference_initial_colors = self.extract_scatter_from_trajectories(self.reference_population)
|
|
1068
|
+
#self.extract_scatter_from_target_trajectories()
|
|
1069
|
+
|
|
1070
|
+
tracks = df_population['TRACK_ID'].unique()
|
|
1071
|
+
self.target_track_of_interest = df_population['TRACK_ID'].min()
|
|
1072
|
+
|
|
1073
|
+
self.loc_t = []
|
|
1074
|
+
self.loc_idx = []
|
|
1075
|
+
for t in range(len(tracks)):
|
|
1076
|
+
indices = np.where(tracks[t]==self.target_track_of_interest)[0]
|
|
1077
|
+
if len(indices)>0:
|
|
1078
|
+
self.loc_t.append(t)
|
|
1079
|
+
self.loc_idx.append(indices[0])
|
|
1080
|
+
|
|
1081
|
+
minmax = MinMaxScaler()
|
|
1082
|
+
pop_cols = list(df_population.columns)
|
|
1083
|
+
cols_to_remove = [c for c in self.cols_to_remove if c in pop_cols] + class_cols
|
|
1084
|
+
time_cols = [c for c in pop_cols if c.startswith('t_')]
|
|
1085
|
+
cols_to_remove += time_cols
|
|
1086
|
+
neigh_cols = [c for c in pop_cols if c.startswith('neighborhood_')]
|
|
1087
|
+
cols_to_remove += neigh_cols
|
|
1088
|
+
|
|
1089
|
+
for col in cols_to_remove:
|
|
1090
|
+
try:
|
|
1091
|
+
pop_cols.remove(col)
|
|
1092
|
+
except:
|
|
1093
|
+
pass
|
|
1274
1094
|
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
self.MinMaxScaler_effectors.fit(x)
|
|
1095
|
+
x = df_population[pop_cols].values
|
|
1096
|
+
minmax.fit(x)
|
|
1278
1097
|
|
|
1098
|
+
self.dataframes.update({population: df_population})
|
|
1099
|
+
self.class_cols_per_pop.update({population: class_cols})
|
|
1100
|
+
self.population_columns.update({population: pop_cols})
|
|
1101
|
+
self.MinMaxScaler_per_pop.update({population: minmax})
|
|
1279
1102
|
|
|
1280
1103
|
def locate_relative_tracks(self):
|
|
1281
1104
|
|
|
@@ -1294,7 +1117,8 @@ class SignalAnnotator2(QMainWindow,Styles):
|
|
|
1294
1117
|
else:
|
|
1295
1118
|
# Load and prep tracks
|
|
1296
1119
|
self.df_relative = pd.read_csv(self.relative_trajectories_path)
|
|
1297
|
-
|
|
1120
|
+
self.df_relative = self.df_relative.astype({"reference_population": str, "neighbor_population": str})
|
|
1121
|
+
|
|
1298
1122
|
self.df_relative= self.df_relative.sort_values(by=['REFERENCE_ID','NEIGHBOR_ID','reference_population','neighbor_population','FRAME'])
|
|
1299
1123
|
self.relative_cols = np.array(self.df_relative.columns)
|
|
1300
1124
|
|
|
@@ -1341,10 +1165,21 @@ class SignalAnnotator2(QMainWindow,Styles):
|
|
|
1341
1165
|
def set_reference_and_neighbor_populations(self):
|
|
1342
1166
|
|
|
1343
1167
|
neigh = self.neighborhood_choice_cb.currentText()
|
|
1344
|
-
|
|
1345
|
-
self.
|
|
1346
|
-
|
|
1168
|
+
|
|
1169
|
+
self.current_neighborhood = neigh
|
|
1170
|
+
for pop in self.dataframes.keys():
|
|
1171
|
+
self.current_neighborhood = self.current_neighborhood.replace(f'{pop}_ref_','')
|
|
1347
1172
|
|
|
1173
|
+
self.reference_population = self.neighborhood_choice_cb.currentText().split('_')[0]
|
|
1174
|
+
|
|
1175
|
+
if '_(' in self.current_neighborhood and ')_' in self.current_neighborhood:
|
|
1176
|
+
self.neighbor_population = self.current_neighborhood.split('_(')[-1].split(')_')[0].split('-')[-1]
|
|
1177
|
+
self.reference_population = self.current_neighborhood.split('_(')[-1].split(')_')[0].split('-')[0]
|
|
1178
|
+
else:
|
|
1179
|
+
if 'self' in self.current_neighborhood:
|
|
1180
|
+
self.neighbor_population = self.reference_population
|
|
1181
|
+
|
|
1182
|
+
|
|
1348
1183
|
print(f'Current neighborhood: {self.current_neighborhood}')
|
|
1349
1184
|
print(f'New reference population: {self.reference_population}')
|
|
1350
1185
|
print(f'New neighbor population: {self.neighbor_population}')
|
|
@@ -1395,7 +1230,6 @@ class SignalAnnotator2(QMainWindow,Styles):
|
|
|
1395
1230
|
status[:] = 2
|
|
1396
1231
|
if cclass>2:
|
|
1397
1232
|
status[:] = 42
|
|
1398
|
-
print(t0, status)
|
|
1399
1233
|
status_color = [color_from_status(s) for s in status]
|
|
1400
1234
|
class_color = [color_from_class(cclass) for i in range(len(status))]
|
|
1401
1235
|
|
|
@@ -1514,8 +1348,16 @@ class SignalAnnotator2(QMainWindow,Styles):
|
|
|
1514
1348
|
self.lines[i].set_xdata([])
|
|
1515
1349
|
self.lines[i].set_ydata([])
|
|
1516
1350
|
self.lines[i].set_label('')
|
|
1351
|
+
|
|
1517
1352
|
self.line_dt.set_xdata([])
|
|
1518
1353
|
self.line_dt.set_ydata([])
|
|
1354
|
+
|
|
1355
|
+
self.line_dt_reference.set_xdata([])
|
|
1356
|
+
self.line_dt_reference.set_ydata([])
|
|
1357
|
+
|
|
1358
|
+
self.line_dt_neighbor.set_xdata([])
|
|
1359
|
+
self.line_dt_neighbor.set_ydata([])
|
|
1360
|
+
|
|
1519
1361
|
self.cell_fcanvas.canvas.draw()
|
|
1520
1362
|
return None
|
|
1521
1363
|
else:
|
|
@@ -1528,11 +1370,18 @@ class SignalAnnotator2(QMainWindow,Styles):
|
|
|
1528
1370
|
signal = []; timeline = [];
|
|
1529
1371
|
signal_txt = self.signal_choices[i].currentText()
|
|
1530
1372
|
option = self.signal_pop_button_groups[i].checkedId()
|
|
1373
|
+
|
|
1374
|
+
n_cut = 25
|
|
1375
|
+
if len(signal_txt) > n_cut:
|
|
1376
|
+
signal_txt_to_show = signal_txt[:(n_cut - 3)] + '...'
|
|
1377
|
+
else:
|
|
1378
|
+
signal_txt_to_show = signal_txt
|
|
1531
1379
|
|
|
1532
1380
|
if option==0 and self.reference_track_of_interest is not None and signal_txt!='--' and signal_txt!='':
|
|
1533
1381
|
|
|
1534
1382
|
df_reference = self.dataframes[self.reference_population]
|
|
1535
|
-
|
|
1383
|
+
|
|
1384
|
+
self.lines[i].set_label(f'reference ({self.reference_population}) '+ signal_txt_to_show)
|
|
1536
1385
|
|
|
1537
1386
|
signal = df_reference.loc[df_reference['TRACK_ID']==self.reference_track_of_interest, signal_txt].to_numpy()
|
|
1538
1387
|
timeline = df_reference.loc[df_reference['TRACK_ID']==self.reference_track_of_interest, 'FRAME'].to_numpy()
|
|
@@ -1541,15 +1390,14 @@ class SignalAnnotator2(QMainWindow,Styles):
|
|
|
1541
1390
|
elif option==1 and self.neighbor_track_of_interest is not None and signal_txt!='--' and signal_txt!='':
|
|
1542
1391
|
|
|
1543
1392
|
df_neighbor = self.dataframes[self.neighbor_population]
|
|
1544
|
-
self.lines[i].set_label(f'neighbor ({self.neighbor_population}) '+
|
|
1393
|
+
self.lines[i].set_label(f'neighbor ({self.neighbor_population}) '+ signal_txt_to_show)
|
|
1545
1394
|
|
|
1546
1395
|
signal = df_neighbor.loc[df_neighbor['TRACK_ID']==self.neighbor_track_of_interest, signal_txt].to_numpy()
|
|
1547
1396
|
timeline = df_neighbor.loc[df_neighbor['TRACK_ID']==self.neighbor_track_of_interest, 'FRAME'].to_numpy()
|
|
1548
1397
|
range_values.extend(df_neighbor.loc[:,signal_txt].values)
|
|
1549
1398
|
|
|
1550
1399
|
elif option==2 and self.reference_track_of_interest is not None and self.neighbor_track_of_interest is not None and signal_txt!='--' and signal_txt!='':
|
|
1551
|
-
|
|
1552
|
-
self.lines[i].set_label(f'pair '+signal_txt)
|
|
1400
|
+
self.lines[i].set_label(f'pair '+signal_txt_to_show)
|
|
1553
1401
|
signal = self.df_relative.loc[(self.df_relative['REFERENCE_ID']==self.reference_track_of_interest)&(self.df_relative['NEIGHBOR_ID']==self.neighbor_track_of_interest)&(self.df_relative['reference_population']==self.reference_population)&(self.df_relative['neighbor_population']==self.neighbor_population), signal_txt].to_numpy()
|
|
1554
1402
|
timeline = self.df_relative.loc[(self.df_relative['REFERENCE_ID']==self.reference_track_of_interest)&(self.df_relative['NEIGHBOR_ID']==self.neighbor_track_of_interest)&(self.df_relative['reference_population']==self.reference_population)&(self.df_relative['neighbor_population']==self.neighbor_population), 'FRAME'].to_numpy()
|
|
1555
1403
|
range_values.extend(self.df_relative.loc[(self.df_relative['reference_population']==self.reference_population)&(self.df_relative['neighbor_population']==self.neighbor_population), signal_txt].values)
|
|
@@ -1560,7 +1408,7 @@ class SignalAnnotator2(QMainWindow,Styles):
|
|
|
1560
1408
|
self.lines[i].set_xdata(timeline)
|
|
1561
1409
|
self.lines[i].set_ydata(signal)
|
|
1562
1410
|
self.lines[i].set_color(tab10(i / float(self.n_signals)))
|
|
1563
|
-
|
|
1411
|
+
|
|
1564
1412
|
#self.configure_ylims()
|
|
1565
1413
|
if len(range_values)>0:
|
|
1566
1414
|
range_values = np.array(range_values)
|
|
@@ -1576,18 +1424,36 @@ class SignalAnnotator2(QMainWindow,Styles):
|
|
|
1576
1424
|
else:
|
|
1577
1425
|
self.cell_ax.set_ylim(self.value_magnitude, self.non_log_ymax)
|
|
1578
1426
|
|
|
1427
|
+
df_reference = self.dataframes[self.reference_population]
|
|
1428
|
+
t_reference = df_reference.loc[df_reference['TRACK_ID']==self.reference_track_of_interest, self.reference_time_name].values
|
|
1429
|
+
|
|
1430
|
+
if len(t_reference)>0:
|
|
1431
|
+
t_reference=t_reference[0]
|
|
1432
|
+
ymin,ymax = self.cell_ax.get_ylim()
|
|
1433
|
+
self.line_dt_reference.set_xdata([t_reference, t_reference])
|
|
1434
|
+
self.line_dt_reference.set_ydata([ymin,ymax])
|
|
1435
|
+
|
|
1436
|
+
|
|
1579
1437
|
if self.reference_track_of_interest is not None and self.neighbor_track_of_interest is not None:
|
|
1580
1438
|
t0 = self.df_relative.loc[(self.df_relative['REFERENCE_ID'] == self.reference_track_of_interest)&(self.df_relative['NEIGHBOR_ID'] == self.neighbor_track_of_interest)&(self.df_relative['reference_population'] == self.reference_population)&(self.df_relative['neighbor_population'] == self.neighbor_population), self.pair_time_name].dropna().values
|
|
1581
|
-
try:
|
|
1582
|
-
if t0!=[]:
|
|
1583
|
-
t0=t0[0]
|
|
1584
|
-
ymin,ymax = self.cell_ax.get_ylim()
|
|
1585
|
-
self.line_dt.set_xdata([t0, t0])
|
|
1586
|
-
self.line_dt.set_ydata([ymin,ymax])
|
|
1587
|
-
except Exception as e:
|
|
1588
|
-
print(e)
|
|
1589
1439
|
|
|
1590
|
-
|
|
1440
|
+
df_neighbor = self.dataframes[self.neighbor_population]
|
|
1441
|
+
t_neighbor = df_neighbor.loc[
|
|
1442
|
+
df_neighbor['TRACK_ID'] == self.neighbor_track_of_interest, self.neighbor_time_name].values
|
|
1443
|
+
|
|
1444
|
+
if len(t0)>0:
|
|
1445
|
+
t0=t0[0]
|
|
1446
|
+
ymin,ymax = self.cell_ax.get_ylim()
|
|
1447
|
+
self.line_dt.set_xdata([t0, t0])
|
|
1448
|
+
self.line_dt.set_ydata([ymin,ymax])
|
|
1449
|
+
|
|
1450
|
+
if len(t_neighbor)>0:
|
|
1451
|
+
t_neighbor=t_neighbor[0]
|
|
1452
|
+
ymin,ymax = self.cell_ax.get_ylim()
|
|
1453
|
+
self.line_dt_neighbor.set_xdata([t_neighbor, t_neighbor])
|
|
1454
|
+
self.line_dt_neighbor.set_ydata([ymin,ymax])
|
|
1455
|
+
|
|
1456
|
+
self.cell_ax.legend(fontsize=8)
|
|
1591
1457
|
self.cell_fcanvas.canvas.draw()
|
|
1592
1458
|
|
|
1593
1459
|
|
|
@@ -1603,55 +1469,63 @@ class SignalAnnotator2(QMainWindow,Styles):
|
|
|
1603
1469
|
for t in np.arange(self.len_movie):
|
|
1604
1470
|
|
|
1605
1471
|
# Append frame_positions to self.line_positions
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
self.
|
|
1609
|
-
|
|
1610
|
-
self.
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
self.target_positions = []
|
|
1617
|
-
self.target_colors = []
|
|
1618
|
-
self.target_tracks = []
|
|
1619
|
-
self.initial_target_colors = []
|
|
1620
|
-
|
|
1621
|
-
for t in np.arange(self.len_movie):
|
|
1622
|
-
|
|
1623
|
-
if self.df_targets is not None:
|
|
1624
|
-
self.target_positions.append(self.df_targets.loc[self.df_targets['FRAME']==t,['x_anim', 'y_anim']].to_numpy())
|
|
1625
|
-
self.target_colors.append(self.df_targets.loc[self.df_targets['FRAME']==t,['class_color', 'status_color']].to_numpy())
|
|
1626
|
-
self.initial_target_colors.append(
|
|
1627
|
-
self.df_targets.loc[self.df_targets['FRAME'] == t, ['class_color', 'status_color']].to_numpy())
|
|
1628
|
-
try:
|
|
1629
|
-
self.target_tracks.append(self.df_targets.loc[self.df_targets['FRAME']==t, 'TRACK_ID'].to_numpy())
|
|
1630
|
-
except:
|
|
1631
|
-
self.target_tracks.append(
|
|
1632
|
-
self.df_targets.loc[self.df_targets['FRAME'] == t, 'ID'].to_numpy())
|
|
1472
|
+
neigh_at_time_filter = (self.df_relative['FRAME'] == t)&(~self.df_relative['status_'+self.current_neighborhood].isnull())&(self.df_relative['reference_population']==self.reference_population)
|
|
1473
|
+
data = self.df_relative.loc[neigh_at_time_filter, ['REFERENCE_ID', 'NEIGHBOR_ID','status_color','class_color']].to_numpy()
|
|
1474
|
+
self.lines_tracks.append(data[:,[0,1]])
|
|
1475
|
+
|
|
1476
|
+
self.initial_lines_colors_status.append(data[:,[0,1,2]])
|
|
1477
|
+
self.lines_colors_status.append(data[:,[0,1,2]])
|
|
1478
|
+
|
|
1479
|
+
self.initial_lines_colors_class.append(data[:,[0,1,3]])
|
|
1480
|
+
self.lines_colors_class.append(data[:,[0,1,3]])
|
|
1633
1481
|
|
|
1482
|
+
def extract_scatter_from_trajectories(self):
|
|
1634
1483
|
|
|
1635
|
-
|
|
1484
|
+
self.tracks = {}
|
|
1485
|
+
self.positions = {}
|
|
1486
|
+
self.colors = {}
|
|
1487
|
+
self.initial_colors = {}
|
|
1488
|
+
self.timeline = {}
|
|
1489
|
+
|
|
1490
|
+
for population in self.dataframes.keys():
|
|
1491
|
+
self.refresh_scatter_from_trajectories(population)
|
|
1636
1492
|
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
self.
|
|
1640
|
-
|
|
1493
|
+
def refresh_scatter_from_trajectories(self, population, clear_selection=True):
|
|
1494
|
+
|
|
1495
|
+
df = self.dataframes[population]
|
|
1496
|
+
positions = []
|
|
1497
|
+
tracks = []
|
|
1498
|
+
timeline = []
|
|
1499
|
+
colors = []
|
|
1500
|
+
initial_colors = []
|
|
1641
1501
|
|
|
1642
|
-
|
|
1502
|
+
if df is not None:
|
|
1643
1503
|
|
|
1644
|
-
|
|
1504
|
+
for t in np.arange(self.len_movie):
|
|
1645
1505
|
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1506
|
+
positions.append(df.loc[df['FRAME']==t,['x_anim', 'y_anim']].to_numpy())
|
|
1507
|
+
colors.append(df.loc[df['FRAME']==t,['class_color', 'status_color']].to_numpy())
|
|
1508
|
+
initial_colors.append(
|
|
1509
|
+
df.loc[df['FRAME'] == t, ['class_color', 'status_color']].to_numpy())
|
|
1649
1510
|
try:
|
|
1650
|
-
|
|
1511
|
+
tracks.append(df.loc[df['FRAME']==t, 'TRACK_ID'].to_numpy())
|
|
1512
|
+
timeline.append(t)
|
|
1651
1513
|
except:
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1514
|
+
tracks.append(
|
|
1515
|
+
df.loc[df['FRAME'] == t, 'ID'].to_numpy())
|
|
1516
|
+
timeline.append(t)
|
|
1517
|
+
|
|
1518
|
+
self.tracks.update({population: tracks})
|
|
1519
|
+
self.timeline.update({population: timeline})
|
|
1520
|
+
self.positions.update({population: positions})
|
|
1521
|
+
self.colors.update({population: colors})
|
|
1522
|
+
self.initial_colors.update({population: initial_colors})
|
|
1523
|
+
|
|
1524
|
+
if self.reference_track_of_interest is not None:
|
|
1525
|
+
#self.recolor_selection()
|
|
1526
|
+
#self.trace_neighbors()
|
|
1527
|
+
self.highlight_the_pair()
|
|
1528
|
+
|
|
1655
1529
|
def load_annotator_config(self):
|
|
1656
1530
|
|
|
1657
1531
|
"""
|
|
@@ -1793,7 +1667,11 @@ class SignalAnnotator2(QMainWindow,Styles):
|
|
|
1793
1667
|
# "Are you sure you want to exit ?",
|
|
1794
1668
|
# QMessageBox.Yes| QMessageBox.No,
|
|
1795
1669
|
# )
|
|
1796
|
-
|
|
1670
|
+
try:
|
|
1671
|
+
del self.stack
|
|
1672
|
+
except:
|
|
1673
|
+
pass
|
|
1674
|
+
|
|
1797
1675
|
gc.collect()
|
|
1798
1676
|
|
|
1799
1677
|
def looped_animation(self):
|
|
@@ -1815,21 +1693,26 @@ class SignalAnnotator2(QMainWindow,Styles):
|
|
|
1815
1693
|
self.im = self.ax.imshow(self.stack[0], cmap='gray', vmin=np.nanpercentile(self.stack, 1), vmax=np.nanpercentile(self.stack, 99.99))
|
|
1816
1694
|
|
|
1817
1695
|
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1696
|
+
self.status_scatter = {}
|
|
1697
|
+
self.class_scatter = {}
|
|
1698
|
+
|
|
1699
|
+
n_pops = len(list(self.dataframes.keys()))
|
|
1700
|
+
markers = ['x','+','*','.','X']
|
|
1701
|
+
while len(markers) < n_pops:
|
|
1702
|
+
markers = markers*2
|
|
1703
|
+
|
|
1704
|
+
for i,pop in enumerate(self.dataframes.keys()):
|
|
1705
|
+
df = self.dataframes[pop]
|
|
1706
|
+
if df is not None:
|
|
1707
|
+
status_scatter = self.ax.scatter(self.positions[pop][0][:,0], self.positions[pop][0][:,1], c=self.colors[pop][0][:,1], s=50, picker=True, pickradius=150, zorder=10, marker=markers[i]) #marker="x",
|
|
1708
|
+
class_scatter = self.ax.scatter(self.positions[pop][0][:,0], self.positions[pop][0][:,1], marker='o', facecolors='none',edgecolors=self.colors[pop][0][:,0], s=200, zorder=10)
|
|
1709
|
+
else:
|
|
1710
|
+
status_scatter = self.ax.scatter([], [], s=50, picker=True, pickradius=10, marker=markers[i]) #marker="x",
|
|
1711
|
+
class_scatter = self.ax.scatter([], [], marker='o', facecolors='none', s=200)
|
|
1712
|
+
self.status_scatter.update({pop: status_scatter})
|
|
1713
|
+
self.class_scatter.update({pop: class_scatter})
|
|
1831
1714
|
|
|
1832
|
-
self.points=self.ax.scatter([], [], marker="
|
|
1715
|
+
self.points=self.ax.scatter([], [], marker="$\\Join$", s=100, picker=True, pickradius=10, zorder=10) #picker=True, pickradius=10
|
|
1833
1716
|
|
|
1834
1717
|
self.ax.set_xticks([])
|
|
1835
1718
|
self.ax.set_yticks([])
|
|
@@ -1869,13 +1752,17 @@ class SignalAnnotator2(QMainWindow,Styles):
|
|
|
1869
1752
|
|
|
1870
1753
|
self.lines = [self.cell_ax.plot([np.linspace(0,self.len_movie-1,self.len_movie)],[np.zeros((self.len_movie))])[0] for i in range(len(self.signal_choices))]
|
|
1871
1754
|
for i in range(len(self.lines)):
|
|
1755
|
+
|
|
1872
1756
|
self.lines[i].set_label(f'signal {i}')
|
|
1873
1757
|
|
|
1874
1758
|
min_val,max_val = self.cell_ax.get_ylim()
|
|
1875
1759
|
self.line_dt, = self.cell_ax.plot([-1,-1],[min_val,max_val],c="k",linestyle="--")
|
|
1760
|
+
self.line_dt_reference, = self.cell_ax.plot([-1,-1],[min_val,max_val],c="tab:blue",linestyle="--")
|
|
1761
|
+
self.line_dt_neighbor, = self.cell_ax.plot([-1,-1],[min_val,max_val],c="tab:red",linestyle="--")
|
|
1762
|
+
|
|
1876
1763
|
|
|
1877
1764
|
self.cell_ax.set_xlim(0,self.len_movie)
|
|
1878
|
-
self.cell_ax.legend()
|
|
1765
|
+
self.cell_ax.legend(fontsize=8)
|
|
1879
1766
|
self.cell_fcanvas.canvas.draw()
|
|
1880
1767
|
|
|
1881
1768
|
#self.plot_signals()
|
|
@@ -1884,9 +1771,8 @@ class SignalAnnotator2(QMainWindow,Styles):
|
|
|
1884
1771
|
def on_scatter_pick(self, event):
|
|
1885
1772
|
|
|
1886
1773
|
self.identify_closest_marker(event)
|
|
1887
|
-
print(self.pair_selected, self.reference_selection)
|
|
1888
1774
|
|
|
1889
|
-
_, tracks, _, _ = self.get_reference_sets()
|
|
1775
|
+
_, tracks, _, _, _ = self.get_reference_sets()
|
|
1890
1776
|
|
|
1891
1777
|
if self.selected_population == self.reference_population:
|
|
1892
1778
|
|
|
@@ -1949,12 +1835,15 @@ class SignalAnnotator2(QMainWindow,Styles):
|
|
|
1949
1835
|
|
|
1950
1836
|
print('You selected a pair...')
|
|
1951
1837
|
artist = event.artist
|
|
1952
|
-
print(self.index)
|
|
1953
1838
|
|
|
1954
1839
|
if self.index is not None and len(self.pair_selection)==0:
|
|
1955
1840
|
|
|
1956
|
-
|
|
1957
|
-
|
|
1841
|
+
try:
|
|
1842
|
+
selected_point = artist.get_offsets()[self.index]
|
|
1843
|
+
except Exception as e:
|
|
1844
|
+
print(f"L1788 {e}")
|
|
1845
|
+
return
|
|
1846
|
+
|
|
1958
1847
|
if len(self.pair_selection) == 0 and ((selected_point[0],selected_point[1]) in self.connections.keys()):
|
|
1959
1848
|
|
|
1960
1849
|
connect = self.connections[(selected_point[0], selected_point[1])]
|
|
@@ -2029,24 +1918,10 @@ class SignalAnnotator2(QMainWindow,Styles):
|
|
|
2029
1918
|
|
|
2030
1919
|
|
|
2031
1920
|
def get_neighbor_sets(self):
|
|
2032
|
-
|
|
2033
|
-
if self.reference_population != self.neighbor_population:
|
|
2034
|
-
if self.reference_population=='effectors':
|
|
2035
|
-
return self.target_positions, self.target_tracks, self.target_colors, self.initial_target_colors
|
|
2036
|
-
elif self.reference_population=='targets':
|
|
2037
|
-
return self.effector_positions, self.effector_tracks, self.effector_colors, self.initial_effector_colors
|
|
2038
|
-
else:
|
|
2039
|
-
if self.reference_population=='effectors':
|
|
2040
|
-
return self.effector_positions, self.effector_tracks, self.effector_colors, self.initial_effector_colors
|
|
2041
|
-
elif self.reference_population=='targets':
|
|
2042
|
-
return self.target_positions, self.target_tracks, self.target_colors, self.initial_target_colors
|
|
1921
|
+
return self.positions[self.neighbor_population], self.tracks[self.neighbor_population], self.colors[self.neighbor_population], self.initial_colors[self.neighbor_population]
|
|
2043
1922
|
|
|
2044
1923
|
def get_reference_sets(self):
|
|
2045
|
-
|
|
2046
|
-
if self.reference_population == 'effectors':
|
|
2047
|
-
return self.effector_positions, self.effector_tracks, self.effector_colors, self.initial_effector_colors
|
|
2048
|
-
elif self.reference_population == 'targets':
|
|
2049
|
-
return self.target_positions, self.target_tracks, self.target_colors, self.initial_target_colors
|
|
1924
|
+
return self.positions[self.reference_population], self.tracks[self.reference_population], self.timeline[self.reference_population], self.colors[self.reference_population], self.initial_colors[self.reference_population]
|
|
2050
1925
|
|
|
2051
1926
|
def trace_neighbors(self):
|
|
2052
1927
|
|
|
@@ -2056,7 +1931,8 @@ class SignalAnnotator2(QMainWindow,Styles):
|
|
|
2056
1931
|
self.line_connections={}
|
|
2057
1932
|
|
|
2058
1933
|
positions, tracks, colors, _ = self.get_neighbor_sets()
|
|
2059
|
-
|
|
1934
|
+
_, tracks_reference, _, _, _ = self.get_reference_sets()
|
|
1935
|
+
|
|
2060
1936
|
# Look for neighbors
|
|
2061
1937
|
for neigh in self.neighbors:
|
|
2062
1938
|
|
|
@@ -2065,46 +1941,39 @@ class SignalAnnotator2(QMainWindow,Styles):
|
|
|
2065
1941
|
|
|
2066
1942
|
for t in range(len(tracks)):
|
|
2067
1943
|
indices = np.where(tracks[t]==neigh)[0]
|
|
2068
|
-
|
|
1944
|
+
indices_reference = np.where(tracks_reference[t]==self.reference_track_of_interest)[0]
|
|
1945
|
+
if len(indices)>0 and len(indices_reference)>0:
|
|
2069
1946
|
self.neighbor_loc_t.append(t)
|
|
2070
1947
|
self.neighbor_loc_idx.append(indices[0])
|
|
2071
|
-
|
|
1948
|
+
|
|
2072
1949
|
self.neighbor_previous_color = []
|
|
2073
1950
|
for t, idx in zip(self.neighbor_loc_t, self.neighbor_loc_idx):
|
|
2074
|
-
|
|
2075
|
-
|
|
1951
|
+
|
|
1952
|
+
t_ref_idx = np.where(self.reference_timeline == t)[0]
|
|
1953
|
+
if t_ref_idx:
|
|
1954
|
+
t_ref_idx = t_ref_idx[0]
|
|
2076
1955
|
|
|
2077
1956
|
neigh_x = positions[t][idx, 0]
|
|
2078
1957
|
neigh_y = positions[t][idx, 1]
|
|
2079
|
-
x_m_point = (self.reference_x[
|
|
2080
|
-
y_m_point = (self.reference_y[
|
|
2081
|
-
|
|
1958
|
+
x_m_point = (self.reference_x[t_ref_idx] + neigh_x) / 2
|
|
1959
|
+
y_m_point = (self.reference_y[t_ref_idx] + neigh_y) / 2
|
|
1960
|
+
|
|
2082
1961
|
if t not in self.lines_data.keys():
|
|
2083
|
-
self.lines_data[t]=[([self.reference_x[
|
|
1962
|
+
self.lines_data[t]=[([self.reference_x[t_ref_idx], neigh_x], [self.reference_y[t_ref_idx], neigh_y])]
|
|
2084
1963
|
self.points_data[t]=[(x_m_point, y_m_point)]
|
|
2085
1964
|
else:
|
|
2086
|
-
self.lines_data[t].append(([self.reference_x[
|
|
1965
|
+
self.lines_data[t].append(([self.reference_x[t_ref_idx], neigh_x], [self.reference_y[t_ref_idx], neigh_y]))
|
|
2087
1966
|
self.points_data[t].append((x_m_point, y_m_point))
|
|
2088
|
-
|
|
1967
|
+
|
|
2089
1968
|
self.connections[(x_m_point, y_m_point)] = [(self.reference_track_of_interest, neigh)]
|
|
2090
|
-
self.line_connections[(self.reference_x[
|
|
2091
|
-
|
|
1969
|
+
self.line_connections[(self.reference_x[t_ref_idx], neigh_x, self.reference_y[t_ref_idx], neigh_y)]=[(self.reference_track_of_interest, neigh)]
|
|
1970
|
+
|
|
2092
1971
|
self.neighbor_previous_color.append(colors[t][idx].copy())
|
|
2093
|
-
except Exception as e:
|
|
2094
|
-
print(e)
|
|
2095
|
-
pass
|
|
2096
|
-
#colors[t][idx] = 'salmon'
|
|
2097
1972
|
|
|
2098
|
-
# for t in range(len(colors)):
|
|
2099
|
-
# for idx in range(len(colors[t])):
|
|
2100
|
-
# if colors[t][idx].any() != 'salmon':
|
|
2101
|
-
# if colors[t][idx].any() != 'magenta':
|
|
2102
|
-
# #init_color[t][idx] = colors[t][idx].copy()
|
|
2103
|
-
# colors[t][idx] = 'black'
|
|
2104
1973
|
|
|
2105
1974
|
def recolor_selection(self):
|
|
2106
1975
|
|
|
2107
|
-
positions, tracks, colors, init_colors = self.get_reference_sets()
|
|
1976
|
+
positions, tracks, timelines, colors, init_colors = self.get_reference_sets()
|
|
2108
1977
|
|
|
2109
1978
|
self.reference_loc_t = []
|
|
2110
1979
|
self.reference_loc_idx = []
|
|
@@ -2125,13 +1994,16 @@ class SignalAnnotator2(QMainWindow,Styles):
|
|
|
2125
1994
|
self.reference_not_picked_initial_colors=[]
|
|
2126
1995
|
self.reference_x = []
|
|
2127
1996
|
self.reference_y = []
|
|
1997
|
+
self.reference_timeline = []
|
|
2128
1998
|
|
|
2129
1999
|
# Recolor selected cell
|
|
2130
2000
|
for t,idx in zip(self.reference_loc_t,self.reference_loc_idx):
|
|
2131
2001
|
self.reference_x.append(positions[t][idx, 0])
|
|
2132
2002
|
self.reference_y.append(positions[t][idx, 1])
|
|
2003
|
+
self.reference_timeline.append(timelines[t])
|
|
2133
2004
|
self.reference_previous_color.append(colors[t][idx].copy())
|
|
2134
2005
|
colors[t][idx] = 'lime'
|
|
2006
|
+
self.reference_timeline = np.array(self.reference_timeline)
|
|
2135
2007
|
|
|
2136
2008
|
# Recolor all other cells in black
|
|
2137
2009
|
for t, idx in zip(self.reference_loc_t_not_picked, self.reference_loc_idx_not_picked):
|
|
@@ -2144,6 +2016,7 @@ class SignalAnnotator2(QMainWindow,Styles):
|
|
|
2144
2016
|
|
|
2145
2017
|
self.neighbors = self.df_relative.loc[(self.df_relative['REFERENCE_ID'] == selected_cell)&(~self.df_relative['status_'+self.current_neighborhood].isnull())&(self.df_relative['reference_population']==self.reference_population),'NEIGHBOR_ID']
|
|
2146
2018
|
self.neighbors = np.unique(self.neighbors)
|
|
2019
|
+
|
|
2147
2020
|
# if len(self.neighbors)>0:
|
|
2148
2021
|
# first_neighbor = np.min(self.neighbors)
|
|
2149
2022
|
# self.neighbor_track_of_interest = first_neighbor
|
|
@@ -2154,38 +2027,37 @@ class SignalAnnotator2(QMainWindow,Styles):
|
|
|
2154
2027
|
|
|
2155
2028
|
ind = event.ind
|
|
2156
2029
|
label = event.artist.get_label()
|
|
2157
|
-
print(f'{label=}')
|
|
2158
2030
|
|
|
2159
2031
|
# Identify the nature of the selected object (target/effector/pair)
|
|
2160
2032
|
self.pair_selected = False
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
if self.selected_population=='effectors':
|
|
2172
|
-
positions = self.effector_positions
|
|
2173
|
-
elif self.selected_population=='targets':
|
|
2174
|
-
positions = self.target_positions
|
|
2175
|
-
|
|
2176
|
-
if len(ind)==1:
|
|
2177
|
-
self.index = ind[0]
|
|
2178
|
-
elif len(ind)>1:
|
|
2179
|
-
# More than one point in vicinity
|
|
2180
|
-
try:
|
|
2181
|
-
datax,datay = [positions[self.framedata][i,0] for i in ind],[positions[self.framedata][i,1] for i in ind]
|
|
2182
|
-
msx, msy = event.mouseevent.xdata, event.mouseevent.ydata
|
|
2183
|
-
dist = np.sqrt((np.array(datax)-msx)**2+(np.array(datay)-msy)**2)
|
|
2184
|
-
self.index = ind[np.argmin(dist)]
|
|
2185
|
-
except Exception as e:
|
|
2186
|
-
print(f"{e=}")
|
|
2033
|
+
|
|
2034
|
+
populations = list(self.dataframes.keys())
|
|
2035
|
+
|
|
2036
|
+
number = int(label.split('_child')[1])
|
|
2037
|
+
|
|
2038
|
+
if number>len(populations)*2:
|
|
2039
|
+
print('A pair is selected...')
|
|
2040
|
+
self.pair_selected = True
|
|
2041
|
+
self.selected_population = None
|
|
2187
2042
|
else:
|
|
2188
|
-
self.
|
|
2043
|
+
self.selected_population = populations[(number-1)//2]
|
|
2044
|
+
|
|
2045
|
+
if self.selected_population is not None:
|
|
2046
|
+
positions = self.positions[self.selected_population]
|
|
2047
|
+
|
|
2048
|
+
if len(ind)==1:
|
|
2049
|
+
self.index = ind[0]
|
|
2050
|
+
elif len(ind)>1:
|
|
2051
|
+
# More than one point in vicinity
|
|
2052
|
+
try:
|
|
2053
|
+
datax,datay = [positions[self.framedata][i,0] for i in ind],[positions[self.framedata][i,1] for i in ind]
|
|
2054
|
+
msx, msy = event.mouseevent.xdata, event.mouseevent.ydata
|
|
2055
|
+
dist = np.sqrt((np.array(datax)-msx)**2+(np.array(datay)-msy)**2)
|
|
2056
|
+
self.index = ind[np.argmin(dist)]
|
|
2057
|
+
except Exception as e:
|
|
2058
|
+
print(f"Exception L2090 to find closest marker: {e=}")
|
|
2059
|
+
else:
|
|
2060
|
+
self.index = None
|
|
2189
2061
|
|
|
2190
2062
|
|
|
2191
2063
|
def show_annotation_buttons(self):
|
|
@@ -2304,58 +2176,46 @@ class SignalAnnotator2(QMainWindow,Styles):
|
|
|
2304
2176
|
self.framedata = framedata
|
|
2305
2177
|
self.frame_lbl.setText(f'frame: {self.framedata}')
|
|
2306
2178
|
self.im.set_array(self.stack[self.framedata])
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
if self.df_targets is not None:
|
|
2320
|
-
self.target_status_scatter.set_visible(True)
|
|
2321
|
-
self.target_status_scatter.set_picker(True)
|
|
2322
|
-
self.target_class_scatter.set_visible(True)
|
|
2323
|
-
self.target_status_scatter.set_offsets(self.target_positions[self.framedata])
|
|
2324
|
-
self.target_status_scatter.set_color(self.target_colors[self.framedata][:, 1])
|
|
2325
|
-
self.target_class_scatter.set_offsets(self.target_positions[self.framedata])
|
|
2326
|
-
self.target_class_scatter.set_edgecolor(self.target_colors[self.framedata][:, 0])
|
|
2179
|
+
|
|
2180
|
+
for pop in self.dataframes.keys():
|
|
2181
|
+
df = self.dataframes[pop]
|
|
2182
|
+
if df is not None:
|
|
2183
|
+
self.status_scatter[pop].set_visible(True)
|
|
2184
|
+
self.status_scatter[pop].set_picker(True)
|
|
2185
|
+
self.status_scatter[pop].set_offsets(self.positions[pop][self.framedata])
|
|
2186
|
+
self.status_scatter[pop].set_color(self.colors[pop][self.framedata][:,1])
|
|
2187
|
+
|
|
2188
|
+
self.class_scatter[pop].set_visible(True)
|
|
2189
|
+
self.class_scatter[pop].set_offsets(self.positions[pop][self.framedata])
|
|
2190
|
+
self.class_scatter[pop].set_edgecolor(self.colors[pop][self.framedata][:,0])
|
|
2327
2191
|
|
|
2328
2192
|
self.lines_list=[]
|
|
2329
2193
|
|
|
2330
2194
|
for key in self.lines_data:
|
|
2195
|
+
|
|
2331
2196
|
if key==self.framedata:
|
|
2197
|
+
|
|
2332
2198
|
for line in self.lines_data[key]:
|
|
2333
|
-
x_coords, y_coords = line
|
|
2334
|
-
pair=self.line_connections[x_coords[0],x_coords[1],y_coords[0],y_coords[1]]
|
|
2335
2199
|
|
|
2336
|
-
|
|
2200
|
+
x_coords, y_coords = line
|
|
2201
|
+
pair = self.line_connections[x_coords[0],x_coords[1],y_coords[0],y_coords[1]]
|
|
2202
|
+
this_frame = self.lines_colors_class[self.framedata]
|
|
2337
2203
|
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2204
|
+
this_pair = this_frame[(this_frame[:, 0] == pair[0][0]) & (this_frame[:, 1] == pair[0][1])]
|
|
2205
|
+
if len(this_pair)>0:
|
|
2206
|
+
c = this_pair[0][2]
|
|
2207
|
+
self.lines_plot = self.ax.plot(x_coords, y_coords, alpha=1, linewidth=2, color=c)
|
|
2341
2208
|
self.lines_list.append(self.lines_plot[0])
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
self.points.set_offsets(self.points_data[key])
|
|
2348
|
-
colors_at_this_frame = self.lines_colors_status[self.framedata]
|
|
2349
|
-
colors = [colors_at_this_frame[(colors_at_this_frame[:, 0] == self.connections[point[0],point[1]][0][0]) & (colors_at_this_frame[:, 1] == self.connections[point[0],point[1]][0][1])][0][2] for point in self.points_data[key]]
|
|
2350
|
-
self.points.set_color(colors)
|
|
2351
|
-
except Exception as e:
|
|
2352
|
-
print(e)
|
|
2209
|
+
|
|
2210
|
+
self.points.set_offsets(self.points_data[key])
|
|
2211
|
+
colors_at_this_frame = self.lines_colors_status[self.framedata]
|
|
2212
|
+
colors = [colors_at_this_frame[(colors_at_this_frame[:, 0] == self.connections[point[0],point[1]][0][0]) & (colors_at_this_frame[:, 1] == self.connections[point[0],point[1]][0][1])][0][2] for point in self.points_data[key]]
|
|
2213
|
+
self.points.set_color(colors)
|
|
2353
2214
|
|
|
2354
2215
|
if self.lines_list!=[]:
|
|
2355
|
-
return [self.im
|
|
2216
|
+
return [self.im] + [self.status_scatter[p] for p in self.status_scatter.keys()] + [self.class_scatter[p] for p in self.status_scatter.keys()] + self.lines_list + [self.points]
|
|
2356
2217
|
else:
|
|
2357
|
-
return [self.im, self.
|
|
2358
|
-
self.effector_class_scatter,]
|
|
2218
|
+
return [self.im,] + [self.status_scatter[p] for p in self.status_scatter.keys()] + [self.class_scatter[p] for p in self.status_scatter.keys()]
|
|
2359
2219
|
|
|
2360
2220
|
def stop(self):
|
|
2361
2221
|
# # On stop we disconnect all of our events.
|
|
@@ -2435,63 +2295,6 @@ class SignalAnnotator2(QMainWindow,Styles):
|
|
|
2435
2295
|
|
|
2436
2296
|
self.target_cell_info.setText('')
|
|
2437
2297
|
|
|
2438
|
-
# def give_effector_cell_information(self):
|
|
2439
|
-
# self.effector_cell_info.setSpacing(0)
|
|
2440
|
-
# self.effector_cell_info.setContentsMargins(0, 20, 0, 30)
|
|
2441
|
-
# self.neigh_eff_combo=QComboBox()
|
|
2442
|
-
# #self.neighb_eff_combo.addItems(self.df_relative.loc[(self.df_relative['target']==self.target_track_of_interest),'effecor'])
|
|
2443
|
-
# neighs=self.df_relative.loc[(self.df_relative['REFERENCE_ID']==self.target_track_of_interest),'NEIGHBOR_ID'].to_numpy()
|
|
2444
|
-
# neighs=np.unique(neighs)
|
|
2445
|
-
# for effector in neighs:
|
|
2446
|
-
# self.neigh_eff_combo.addItem(str(effector))
|
|
2447
|
-
# if self.effector_track_of_interest not in neighs:
|
|
2448
|
-
# self.neigh_eff_combo.addItem(str(self.effector_track_of_interest))
|
|
2449
|
-
# self.neigh_eff_combo.setCurrentText(str(self.effector_track_of_interest))
|
|
2450
|
-
# self.eff_cell_sel=QHBoxLayout()
|
|
2451
|
-
# #effector_cell_selected = f"effector cell: {self.effector_track_of_interest}"
|
|
2452
|
-
# self.effector_cell_selected = f"effector cell: "
|
|
2453
|
-
# self.eff_cell = QLabel(self.effector_cell_selected)
|
|
2454
|
-
# # self.eff_cell_sel.removeWidget(self.eff_cell)
|
|
2455
|
-
# # self.eff_cell_sel.removeWidget(self.neigh_eff_combo)
|
|
2456
|
-
# self.eff_cell_sel.addWidget(self.eff_cell)
|
|
2457
|
-
# self.eff_cell_sel.addWidget(self.neigh_eff_combo, alignment=Qt.AlignLeft)
|
|
2458
|
-
# try:
|
|
2459
|
-
# self.effector_cell_class = f"class: {self.df_effectors.loc[self.df_effectors['TRACK_ID']==self.effector_track_of_interest, self.effector_class_name].to_numpy()[0]}"
|
|
2460
|
-
# except:
|
|
2461
|
-
# self.effector_cell_class = f"class: {self.df_effectors.loc[self.df_effectors['ID'] == self.effector_track_of_interest, self.effector_class_name].to_numpy()[0]}"
|
|
2462
|
-
|
|
2463
|
-
# self.eff_cls = QLabel(self.effector_cell_class)
|
|
2464
|
-
# try:
|
|
2465
|
-
# self.effector_cell_time = f"time of interest: {self.df_effectors.loc[self.df_effectors['TRACK_ID']==self.effector_track_of_interest, self.effector_time_name].to_numpy()[0]}"
|
|
2466
|
-
# except:
|
|
2467
|
-
# self.effector_cell_time = f"time of interest: {self.df_effectors.loc[self.df_effectors['ID']==self.effector_track_of_interest, self.effector_time_name].to_numpy()[0]}"
|
|
2468
|
-
|
|
2469
|
-
# self.eff_tm=QLabel(self.effector_cell_time)
|
|
2470
|
-
# # try:
|
|
2471
|
-
# # self.effector_probabilty = f"probability: {self.df_relative.loc[(self.df_relative['REFERENCE_ID']==self.target_track_of_interest)&(self.df_relative['NEIGHBOR_ID']==self.effector_track_of_interest),'probability'].to_numpy()[0]}"
|
|
2472
|
-
# # except:
|
|
2473
|
-
# # self.effector_probabilty=f"probability: 0"
|
|
2474
|
-
# # self.eff_prb=QLabel(self.effector_probabilty)
|
|
2475
|
-
# #self.effector_cell_info.setText(effector_cell_selected+effector_cell_class+effector_cell_time+effector_probabilty)
|
|
2476
|
-
# # self.effector_cell_info.removeWidget(self.eff_cls)
|
|
2477
|
-
# # self.effector_cell_info.removeWidget(self.eff_tm)
|
|
2478
|
-
# # self.effector_cell_info.removeWidget(self.eff_prb)
|
|
2479
|
-
# self.effector_cell_info.addLayout(self.eff_cell_sel)
|
|
2480
|
-
# self.effector_cell_info.addWidget(self.eff_cls)
|
|
2481
|
-
# self.effector_cell_info.addWidget(self.eff_tm)
|
|
2482
|
-
# #self.effector_cell_info.addWidget(self.eff_prb)
|
|
2483
|
-
# self.neigh_eff_combo.currentIndexChanged.connect(self.update_effector_info)
|
|
2484
|
-
# self.eff_info_to_hide=[self.eff_cell,self.neigh_eff_combo,self.eff_cls,self.eff_tm]#self.eff_prb
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
# def hide_effector_cell_info(self):
|
|
2488
|
-
# self.eff_cls.clear()
|
|
2489
|
-
# self.eff_tm.clear()
|
|
2490
|
-
# #self.eff_prb.clear()
|
|
2491
|
-
|
|
2492
|
-
# for info in self.eff_info_to_hide:
|
|
2493
|
-
# info.hide()
|
|
2494
|
-
|
|
2495
2298
|
|
|
2496
2299
|
def save_trajectories(self):
|
|
2497
2300
|
|
|
@@ -2602,39 +2405,34 @@ class SignalAnnotator2(QMainWindow,Styles):
|
|
|
2602
2405
|
|
|
2603
2406
|
def normalize_features(self):
|
|
2604
2407
|
|
|
2605
|
-
if self.df_effectors is not None:
|
|
2606
|
-
x_effectors = self.df_effectors[self.effector_columns].values
|
|
2607
|
-
if self.df_targets is not None:
|
|
2608
|
-
x_targets = self.df_targets[self.target_columns].values
|
|
2609
|
-
if self.df_relative is not None:
|
|
2610
|
-
x_pairs = self.df_relative[self.pair_columns].values
|
|
2611
|
-
|
|
2612
2408
|
if not self.normalized_signals:
|
|
2409
|
+
for pop in self.dataframes.keys():
|
|
2410
|
+
df_pop = self.dataframes[pop]
|
|
2411
|
+
cols = self.population_columns[pop]
|
|
2412
|
+
if df_pop is not None:
|
|
2413
|
+
df_pop[cols] = self.MinMaxScaler_per_pop[pop].transform(df_pop[cols].values)
|
|
2414
|
+
self.dataframes.update({pop: df_pop})
|
|
2613
2415
|
|
|
2614
|
-
if self.df_effectors is not None:
|
|
2615
|
-
self.df_effectors[self.effector_columns] = self.MinMaxScaler_effectors.transform(x_effectors)
|
|
2616
|
-
if self.df_targets is not None:
|
|
2617
|
-
self.df_targets[self.target_columns] = self.MinMaxScaler_targets.transform(x_targets)
|
|
2618
2416
|
if self.df_relative is not None:
|
|
2619
|
-
self.df_relative[self.pair_columns] = self.MinMaxScaler_pairs.transform(
|
|
2417
|
+
self.df_relative[self.pair_columns] = self.MinMaxScaler_pairs.transform(self.df_relative[self.pair_columns].values)
|
|
2620
2418
|
|
|
2621
|
-
self.plot_signals()
|
|
2622
2419
|
self.normalized_signals = True
|
|
2623
2420
|
self.normalize_features_btn.setIcon(icon(MDI6.arrow_collapse_vertical, color="#1565c0"))
|
|
2624
|
-
self.normalize_features_btn.setIconSize(QSize(25, 25))
|
|
2625
2421
|
else:
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
|
|
2629
|
-
|
|
2630
|
-
|
|
2422
|
+
for pop in self.dataframes.keys():
|
|
2423
|
+
df_pop = self.dataframes[pop]
|
|
2424
|
+
cols = self.population_columns[pop]
|
|
2425
|
+
if df_pop is not None:
|
|
2426
|
+
df_pop[cols] = self.MinMaxScaler_per_pop[pop].inverse_transform(df_pop[cols].values)
|
|
2427
|
+
self.dataframes.update({pop: df_pop})
|
|
2631
2428
|
if self.df_relative is not None:
|
|
2632
|
-
self.df_relative[self.pair_columns] = self.MinMaxScaler_pairs.inverse_transform(
|
|
2429
|
+
self.df_relative[self.pair_columns] = self.MinMaxScaler_pairs.inverse_transform(self.df_relative[self.pair_columns].values)
|
|
2633
2430
|
|
|
2634
|
-
self.plot_signals()
|
|
2635
2431
|
self.normalized_signals = False
|
|
2636
2432
|
self.normalize_features_btn.setIcon(icon(MDI6.arrow_collapse_vertical, color="black"))
|
|
2637
|
-
|
|
2433
|
+
|
|
2434
|
+
self.plot_signals()
|
|
2435
|
+
self.normalize_features_btn.setIconSize(QSize(25, 25))
|
|
2638
2436
|
|
|
2639
2437
|
def switch_to_log(self):
|
|
2640
2438
|
|