celldetective 1.3.1__py3-none-any.whl → 1.3.3.post1__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/_version.py +1 -1
- celldetective/events.py +2 -0
- celldetective/gui/classifier_widget.py +51 -3
- celldetective/gui/control_panel.py +9 -3
- celldetective/gui/generic_signal_plot.py +161 -2
- celldetective/gui/gui_utils.py +90 -1
- celldetective/gui/measurement_options.py +35 -32
- celldetective/gui/plot_signals_ui.py +8 -3
- celldetective/gui/process_block.py +36 -114
- celldetective/gui/retrain_segmentation_model_options.py +3 -1
- celldetective/gui/signal_annotator.py +53 -26
- celldetective/gui/signal_annotator2.py +17 -30
- celldetective/gui/survival_ui.py +7 -3
- celldetective/gui/tableUI.py +300 -183
- celldetective/gui/thresholds_gui.py +195 -199
- celldetective/gui/viewers.py +267 -13
- celldetective/io.py +110 -10
- celldetective/measure.py +128 -88
- celldetective/models/segmentation_effectors/ricm_bf_all_last/config_input.json +79 -0
- 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 +37 -0
- celldetective/models/segmentation_effectors/test-transfer/config_input.json +39 -0
- celldetective/models/segmentation_effectors/test-transfer/test-transfer +0 -0
- celldetective/neighborhood.py +154 -69
- celldetective/relative_measurements.py +128 -4
- celldetective/scripts/measure_cells.py +3 -3
- celldetective/signals.py +207 -213
- celldetective/utils.py +16 -0
- {celldetective-1.3.1.dist-info → celldetective-1.3.3.post1.dist-info}/METADATA +11 -10
- {celldetective-1.3.1.dist-info → celldetective-1.3.3.post1.dist-info}/RECORD +34 -29
- {celldetective-1.3.1.dist-info → celldetective-1.3.3.post1.dist-info}/WHEEL +1 -1
- {celldetective-1.3.1.dist-info → celldetective-1.3.3.post1.dist-info}/LICENSE +0 -0
- {celldetective-1.3.1.dist-info → celldetective-1.3.3.post1.dist-info}/entry_points.txt +0 -0
- {celldetective-1.3.1.dist-info → celldetective-1.3.3.post1.dist-info}/top_level.txt +0 -0
|
@@ -291,6 +291,7 @@ class ProcessPanel(QFrame, Styles):
|
|
|
291
291
|
self.signal_models_list.addItems(signal_models)
|
|
292
292
|
|
|
293
293
|
def generate_tracking_options(self):
|
|
294
|
+
|
|
294
295
|
grid_track = QHBoxLayout()
|
|
295
296
|
|
|
296
297
|
self.track_action = QCheckBox("TRACK")
|
|
@@ -303,16 +304,6 @@ class ProcessPanel(QFrame, Styles):
|
|
|
303
304
|
padding-top: 5px;
|
|
304
305
|
""")
|
|
305
306
|
grid_track.addWidget(self.track_action, 75)
|
|
306
|
-
#self.to_disable.append(self.track_action_tc)
|
|
307
|
-
|
|
308
|
-
# self.show_track_table_btn = QPushButton()
|
|
309
|
-
# self.show_track_table_btn.setIcon(icon(MDI6.table,color="black"))
|
|
310
|
-
# self.show_track_table_btn.setIconSize(QSize(20, 20))
|
|
311
|
-
# self.show_track_table_btn.setToolTip("Show trajectories table.")
|
|
312
|
-
# self.show_track_table_btn.setStyleSheet(self.button_select_all)
|
|
313
|
-
# #self.show_track_table_btn.clicked.connect(self.display_trajectory_table)
|
|
314
|
-
# self.show_track_table_btn.setEnabled(False)
|
|
315
|
-
# grid_track.addWidget(self.show_track_table_btn, 6) #4,3,1,1, alignment=Qt.AlignLeft
|
|
316
307
|
|
|
317
308
|
self.delete_tracks_btn = QPushButton()
|
|
318
309
|
self.delete_tracks_btn.setIcon(icon(MDI6.trash_can,color="black"))
|
|
@@ -640,25 +631,6 @@ class ProcessPanel(QFrame, Styles):
|
|
|
640
631
|
|
|
641
632
|
self.seg_model_list.insertSeparator(len(self.models_truncated))
|
|
642
633
|
|
|
643
|
-
|
|
644
|
-
#if ("live_nuclei_channel" in self.exp_channels)*("dead_nuclei_channel" in self.exp_channels):
|
|
645
|
-
# print("both channels found")
|
|
646
|
-
# index = self.tc_seg_model_list.findText("MCF7_Hoescht_PI_w_primary_NK", Qt.MatchFixedString)
|
|
647
|
-
# if index >= 0:
|
|
648
|
-
# self.tc_seg_model_list.setCurrentIndex(index)
|
|
649
|
-
# elif ("live_nuclei_channel" in self.exp_channels)*("dead_nuclei_channel" not in self.exp_channels):
|
|
650
|
-
# index = self.tc_seg_model_list.findText("MCF7_Hoescht_w_primary_NK", Qt.MatchFixedString)
|
|
651
|
-
# if index >= 0:
|
|
652
|
-
# self.tc_seg_model_list.setCurrentIndex(index)
|
|
653
|
-
# elif ("live_nuclei_channel" not in self.exp_channels)*("dead_nuclei_channel" in self.exp_channels):
|
|
654
|
-
# index = self.tc_seg_model_list.findText("MCF7_PI_w_primary_NK", Qt.MatchFixedString)
|
|
655
|
-
# if index >= 0:
|
|
656
|
-
# self.tc_seg_model_list.setCurrentIndex(index)
|
|
657
|
-
# elif ("live_nuclei_channel" not in self.exp_channels)*("dead_nuclei_channel" not in self.exp_channels)*("adhesion_channel" in self.exp_channels):
|
|
658
|
-
# index = self.tc_seg_model_list.findText("RICM", Qt.MatchFixedString)
|
|
659
|
-
# if index >= 0:
|
|
660
|
-
# self.tc_seg_model_list.setCurrentIndex(index)
|
|
661
|
-
|
|
662
634
|
def tick_all_actions(self):
|
|
663
635
|
self.switch_all_ticks_option()
|
|
664
636
|
if self.all_ticked:
|
|
@@ -884,28 +856,7 @@ class ProcessPanel(QFrame, Styles):
|
|
|
884
856
|
if self.segment_action.isChecked():
|
|
885
857
|
self.segment_action.setChecked(False)
|
|
886
858
|
|
|
887
|
-
|
|
888
|
-
# self.unfreeze()
|
|
889
|
-
|
|
890
|
-
# def view_current_stack_with_scale_bar(self):
|
|
891
|
-
|
|
892
|
-
# self.parent_window.locate_image()
|
|
893
|
-
# if self.parent_window.current_stack is not None:
|
|
894
|
-
# self.viewer = CellSizeViewer(
|
|
895
|
-
# initial_diameter = float(self.diameter_le.text().replace(',', '.')),
|
|
896
|
-
# parent_le = self.diameter_le,
|
|
897
|
-
# stack_path=self.parent_window.current_stack,
|
|
898
|
-
# window_title=f'Position {self.parent_window.position_list.currentText()}',
|
|
899
|
-
# frame_slider = True,
|
|
900
|
-
# contrast_slider = True,
|
|
901
|
-
# channel_cb = True,
|
|
902
|
-
# channel_names = self.parent_window.exp_channels,
|
|
903
|
-
# n_channels = self.parent_window.nbr_channels,
|
|
904
|
-
# PxToUm = 1,
|
|
905
|
-
# )
|
|
906
|
-
# self.viewer.show()
|
|
907
|
-
|
|
908
|
-
|
|
859
|
+
self.cellpose_calibrated = False
|
|
909
860
|
|
|
910
861
|
def open_napari_tracking(self):
|
|
911
862
|
print(f'View the tracks before post-processing for position {self.parent_window.pos} in napari...')
|
|
@@ -920,7 +871,7 @@ class ProcessPanel(QFrame, Styles):
|
|
|
920
871
|
plot_mode = 'plot_track_signals'
|
|
921
872
|
if 'TRACK_ID' not in list(self.df.columns):
|
|
922
873
|
plot_mode = 'static'
|
|
923
|
-
self.tab_ui = TableUI(self.df, f"Well {self.parent_window.well_list.currentText()}; Position {self.parent_window.position_list.currentText()}", population=self.mode, plot_mode=plot_mode)
|
|
874
|
+
self.tab_ui = TableUI(self.df, f"Well {self.parent_window.well_list.currentText()}; Position {self.parent_window.position_list.currentText()}", population=self.mode, plot_mode=plot_mode, save_inplace_option=True)
|
|
924
875
|
self.tab_ui.show()
|
|
925
876
|
else:
|
|
926
877
|
print('Table could not be loaded...')
|
|
@@ -933,24 +884,6 @@ class ProcessPanel(QFrame, Styles):
|
|
|
933
884
|
if returnValue == QMessageBox.Ok:
|
|
934
885
|
return None
|
|
935
886
|
|
|
936
|
-
# def interpret_pos_location(self):
|
|
937
|
-
|
|
938
|
-
# """
|
|
939
|
-
# Read the well/position selection from the control panel to decide which data to load
|
|
940
|
-
# Set position_indices to None if all positions must be taken
|
|
941
|
-
|
|
942
|
-
# """
|
|
943
|
-
|
|
944
|
-
# if self.well_option==len(self.wells):
|
|
945
|
-
# self.well_indices = np.arange(len(self.wells))
|
|
946
|
-
# else:
|
|
947
|
-
# self.well_indices = np.array([self.well_option],dtype=int)
|
|
948
|
-
|
|
949
|
-
# if self.position_option==0:
|
|
950
|
-
# self.position_indices = None
|
|
951
|
-
# else:
|
|
952
|
-
# self.position_indices = np.array([self.position_option],dtype=int)
|
|
953
|
-
|
|
954
887
|
def load_available_tables(self):
|
|
955
888
|
|
|
956
889
|
"""
|
|
@@ -1016,6 +949,7 @@ class ProcessPanel(QFrame, Styles):
|
|
|
1016
949
|
self.process_population()
|
|
1017
950
|
|
|
1018
951
|
|
|
952
|
+
|
|
1019
953
|
class NeighPanel(QFrame, Styles):
|
|
1020
954
|
def __init__(self, parent_window):
|
|
1021
955
|
|
|
@@ -1207,28 +1141,19 @@ class NeighPanel(QFrame, Styles):
|
|
|
1207
1141
|
self.measure_pairs_action.setToolTip("Measure the relative quantities defined for the cell pairs, for all neighborhoods.")
|
|
1208
1142
|
rel_layout.addWidget(self.measure_pairs_action, 90)
|
|
1209
1143
|
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
# self.config_rel_annotator_btn = QPushButton()
|
|
1220
|
-
# self.config_rel_annotator_btn.setIcon(icon(MDI6.cog_outline, color="black"))
|
|
1221
|
-
# self.config_rel_annotator_btn.setIconSize(QSize(20, 20))
|
|
1222
|
-
# self.config_rel_annotator_btn.setToolTip("Configure the animation of the annotation tool.")
|
|
1223
|
-
# self.config_rel_annotator_btn.setStyleSheet(self.button_select_all)
|
|
1224
|
-
# self.config_rel_annotator_btn.clicked.connect(self.open_signal_annotator_configuration_ui)
|
|
1225
|
-
# # self.grid_contents.addWidget(self.config_rel_annotator_btn, 1,2,1,1, alignment=Qt.AlignRight)
|
|
1226
|
-
# rel_layout.addWidget(self.config_rel_annotator_btn, 6)
|
|
1144
|
+
self.classify_pairs_btn = QPushButton()
|
|
1145
|
+
self.classify_pairs_btn.setIcon(icon(MDI6.scatter_plot, color="black"))
|
|
1146
|
+
self.classify_pairs_btn.setIconSize(QSize(20, 20))
|
|
1147
|
+
self.classify_pairs_btn.setToolTip("Classify data.")
|
|
1148
|
+
self.classify_pairs_btn.setStyleSheet(self.button_select_all)
|
|
1149
|
+
self.classify_pairs_btn.clicked.connect(self.open_classifier_ui_pairs)
|
|
1150
|
+
rel_layout.addWidget(self.classify_pairs_btn, 5) #4,2,1,1, alignment=Qt.AlignRight
|
|
1151
|
+
|
|
1227
1152
|
self.grid_contents.addLayout(rel_layout, 6, 0, 1, 4)
|
|
1228
1153
|
|
|
1229
1154
|
signal_layout = QVBoxLayout()
|
|
1230
1155
|
signal_hlayout = QHBoxLayout()
|
|
1231
|
-
self.signal_analysis_action = QCheckBox("PAIR
|
|
1156
|
+
self.signal_analysis_action = QCheckBox("DETECT PAIR EVENTS")
|
|
1232
1157
|
self.signal_analysis_action.setStyleSheet("""
|
|
1233
1158
|
font-size: 10px;
|
|
1234
1159
|
padding-left: 10px;
|
|
@@ -1304,6 +1229,26 @@ class NeighPanel(QFrame, Styles):
|
|
|
1304
1229
|
self.neigh_action.setChecked(True)
|
|
1305
1230
|
self.neigh_action.setChecked(False)
|
|
1306
1231
|
|
|
1232
|
+
def open_classifier_ui_pairs(self):
|
|
1233
|
+
|
|
1234
|
+
self.mode = "pairs"
|
|
1235
|
+
self.load_available_tables()
|
|
1236
|
+
if self.df is None:
|
|
1237
|
+
|
|
1238
|
+
msgBox = QMessageBox()
|
|
1239
|
+
msgBox.setIcon(QMessageBox.Warning)
|
|
1240
|
+
msgBox.setText("No table was found...")
|
|
1241
|
+
msgBox.setWindowTitle("Warning")
|
|
1242
|
+
msgBox.setStandardButtons(QMessageBox.Ok)
|
|
1243
|
+
returnValue = msgBox.exec()
|
|
1244
|
+
if returnValue == QMessageBox.Ok:
|
|
1245
|
+
return None
|
|
1246
|
+
else:
|
|
1247
|
+
return None
|
|
1248
|
+
else:
|
|
1249
|
+
self.ClassifierWidget = ClassifierWidget(self)
|
|
1250
|
+
self.ClassifierWidget.show()
|
|
1251
|
+
|
|
1307
1252
|
|
|
1308
1253
|
def help_neighborhood(self):
|
|
1309
1254
|
|
|
@@ -1360,7 +1305,7 @@ class NeighPanel(QFrame, Styles):
|
|
|
1360
1305
|
|
|
1361
1306
|
if self.df is not None:
|
|
1362
1307
|
plot_mode = 'static'
|
|
1363
|
-
self.tab_ui = TableUI(self.df, f"Well {self.parent_window.well_list.currentText()}; Position {self.parent_window.position_list.currentText()}", population='pairs', plot_mode=plot_mode)
|
|
1308
|
+
self.tab_ui = TableUI(self.df, f"Well {self.parent_window.well_list.currentText()}; Position {self.parent_window.position_list.currentText()}", population='pairs', plot_mode=plot_mode, save_inplace_option=True)
|
|
1364
1309
|
self.tab_ui.show()
|
|
1365
1310
|
else:
|
|
1366
1311
|
print('Table could not be loaded...')
|
|
@@ -1512,35 +1457,12 @@ class NeighPanel(QFrame, Styles):
|
|
|
1512
1457
|
rel_measure_at_position(self.pos)
|
|
1513
1458
|
|
|
1514
1459
|
if self.signal_analysis_action.isChecked():
|
|
1515
|
-
|
|
1516
|
-
# df_targets = get_position_pickle(self.pos, population='targets')
|
|
1517
|
-
# df_effectors = get_position_pickle(self.pos, population='effectors')
|
|
1518
|
-
# self.dataframes = {
|
|
1519
|
-
# 'targets': df_targets,
|
|
1520
|
-
# 'effectors': df_effectors,
|
|
1521
|
-
# }
|
|
1522
|
-
|
|
1523
|
-
# df_pairs = get_position_table(self.pos, population='pairs')
|
|
1524
|
-
|
|
1525
|
-
# # Need to identify expected reference / neighbor tables
|
|
1526
|
-
# model_path = locate_signal_model(self.pair_signal_models_list.currentText(), pairs=True)
|
|
1527
|
-
# print(f'Looking for model in {model_path}...')
|
|
1528
|
-
# complete_path = model_path
|
|
1529
|
-
# complete_path = rf"{complete_path}"
|
|
1530
|
-
# model_config_path = os.sep.join([complete_path, 'config_input.json'])
|
|
1531
|
-
# model_config_path = rf"{model_config_path}"
|
|
1532
|
-
# f = open(model_config_path)
|
|
1533
|
-
# model_config_path = json.load(f)
|
|
1534
|
-
|
|
1535
|
-
# reference_population = model_config_path['reference_population']
|
|
1536
|
-
# neighbor_population = model_config_path['neighbor_population']
|
|
1537
|
-
|
|
1538
|
-
# analyze_pair_signals(df_pairs, self.dataframes[reference_population], self.dataframes[neighbor_population], model=self.pair_signal_models_list.currentText())
|
|
1460
|
+
|
|
1539
1461
|
analyze_pair_signals_at_position(self.pos, self.pair_signal_models_list.currentText(), use_gpu=self.parent_window.parent_window.use_gpu)
|
|
1462
|
+
|
|
1540
1463
|
self.parent_window.update_position_options()
|
|
1541
1464
|
print('Done.')
|
|
1542
1465
|
|
|
1543
|
-
|
|
1544
1466
|
def check_signals2(self):
|
|
1545
1467
|
|
|
1546
1468
|
test = self.parent_window.locate_selected_position()
|
|
@@ -616,4 +616,6 @@ class ConfigSegmentationModelTraining(QMainWindow, Styles):
|
|
|
616
616
|
|
|
617
617
|
train_segmentation_model(model_folder+"training_instructions.json", use_gpu=self.parent_window.parent_window.parent_window.use_gpu)
|
|
618
618
|
|
|
619
|
-
|
|
619
|
+
self.parent_window.init_seg_model_list()
|
|
620
|
+
idx = self.parent_window.seg_model_list.findText(model_name)
|
|
621
|
+
self.parent_window.seg_model_list.setCurrentIndex(idx)
|
|
@@ -35,7 +35,10 @@ class SignalAnnotator(QMainWindow, Styles):
|
|
|
35
35
|
def __init__(self, parent_window=None):
|
|
36
36
|
|
|
37
37
|
super().__init__()
|
|
38
|
+
|
|
38
39
|
center_window(self)
|
|
40
|
+
self.proceed = True
|
|
41
|
+
self.setAttribute(Qt.WA_DeleteOnClose)
|
|
39
42
|
|
|
40
43
|
self.parent_window = parent_window
|
|
41
44
|
self.setWindowTitle("Signal annotator")
|
|
@@ -65,18 +68,19 @@ class SignalAnnotator(QMainWindow, Styles):
|
|
|
65
68
|
self.status_name = 'status'
|
|
66
69
|
|
|
67
70
|
self.locate_stack()
|
|
68
|
-
self.
|
|
69
|
-
|
|
70
|
-
|
|
71
|
+
if not self.proceed:
|
|
72
|
+
self.close()
|
|
73
|
+
else:
|
|
74
|
+
self.load_annotator_config()
|
|
75
|
+
self.locate_tracks()
|
|
76
|
+
self.prepare_stack()
|
|
71
77
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
78
|
+
self.generate_signal_choices()
|
|
79
|
+
self.frame_lbl = QLabel('frame: ')
|
|
80
|
+
self.looped_animation()
|
|
81
|
+
self.create_cell_signal_canvas()
|
|
76
82
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
self.setAttribute(Qt.WA_DeleteOnClose)
|
|
83
|
+
self.populate_widget()
|
|
80
84
|
|
|
81
85
|
def populate_widget(self):
|
|
82
86
|
|
|
@@ -645,11 +649,14 @@ class SignalAnnotator(QMainWindow, Styles):
|
|
|
645
649
|
if len(movies) == 0:
|
|
646
650
|
msgBox = QMessageBox()
|
|
647
651
|
msgBox.setIcon(QMessageBox.Warning)
|
|
648
|
-
msgBox.setText("No
|
|
652
|
+
msgBox.setText("No movie is detected in the experiment folder.\nPlease check the stack prefix...")
|
|
649
653
|
msgBox.setWindowTitle("Warning")
|
|
650
654
|
msgBox.setStandardButtons(QMessageBox.Ok)
|
|
651
655
|
returnValue = msgBox.exec()
|
|
652
|
-
if returnValue == QMessageBox.
|
|
656
|
+
if returnValue == QMessageBox.Ok:
|
|
657
|
+
self.proceed = False
|
|
658
|
+
self.close()
|
|
659
|
+
else:
|
|
653
660
|
self.close()
|
|
654
661
|
else:
|
|
655
662
|
self.stack_path = movies[0]
|
|
@@ -977,15 +984,17 @@ class SignalAnnotator(QMainWindow, Styles):
|
|
|
977
984
|
self.stack[np.where(self.stack > 0.)] = np.log(self.stack[np.where(self.stack > 0.)])
|
|
978
985
|
|
|
979
986
|
def closeEvent(self, event):
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
987
|
+
try:
|
|
988
|
+
self.stop()
|
|
989
|
+
# result = QMessageBox.question(self,
|
|
990
|
+
# "Confirm Exit...",
|
|
991
|
+
# "Are you sure you want to exit ?",
|
|
992
|
+
# QMessageBox.Yes| QMessageBox.No,
|
|
993
|
+
# )
|
|
994
|
+
del self.stack
|
|
995
|
+
gc.collect()
|
|
996
|
+
except:
|
|
997
|
+
pass
|
|
989
998
|
|
|
990
999
|
def looped_animation(self):
|
|
991
1000
|
|
|
@@ -1118,6 +1127,7 @@ class SignalAnnotator(QMainWindow, Styles):
|
|
|
1118
1127
|
try:
|
|
1119
1128
|
min_values = []
|
|
1120
1129
|
max_values = []
|
|
1130
|
+
feats = []
|
|
1121
1131
|
for i in range(len(self.signal_choice_cb)):
|
|
1122
1132
|
signal = self.signal_choice_cb[i].currentText()
|
|
1123
1133
|
if signal == '--':
|
|
@@ -1127,9 +1137,26 @@ class SignalAnnotator(QMainWindow, Styles):
|
|
|
1127
1137
|
minn = np.nanpercentile(self.df_tracks.loc[:, signal].to_numpy().flatten(), 1)
|
|
1128
1138
|
min_values.append(minn)
|
|
1129
1139
|
max_values.append(maxx)
|
|
1140
|
+
feats.append(signal)
|
|
1141
|
+
|
|
1142
|
+
smallest_value = np.amin(min_values)
|
|
1143
|
+
feat_smallest_value = feats[np.argmin(min_values)]
|
|
1144
|
+
min_feat = self.df_tracks[feat_smallest_value].min()
|
|
1145
|
+
max_feat = self.df_tracks[feat_smallest_value].max()
|
|
1146
|
+
pad_small = (max_feat - min_feat) * 0.05
|
|
1147
|
+
if pad_small==0:
|
|
1148
|
+
pad_small = 0.05
|
|
1149
|
+
|
|
1150
|
+
largest_value = np.amax(max_values)
|
|
1151
|
+
feat_largest_value = feats[np.argmax(max_values)]
|
|
1152
|
+
min_feat = self.df_tracks[feat_largest_value].min()
|
|
1153
|
+
max_feat = self.df_tracks[feat_largest_value].max()
|
|
1154
|
+
pad_large = (max_feat - min_feat) * 0.05
|
|
1155
|
+
if pad_large==0:
|
|
1156
|
+
pad_large = 0.05
|
|
1130
1157
|
|
|
1131
1158
|
if len(min_values) > 0:
|
|
1132
|
-
self.cell_ax.set_ylim(
|
|
1159
|
+
self.cell_ax.set_ylim(smallest_value - pad_small, largest_value + pad_large)
|
|
1133
1160
|
except Exception as e:
|
|
1134
1161
|
pass
|
|
1135
1162
|
|
|
@@ -2305,8 +2332,8 @@ class MeasureAnnotator(SignalAnnotator):
|
|
|
2305
2332
|
else:
|
|
2306
2333
|
self.current_stack = self.current_stack[0]
|
|
2307
2334
|
if self.log_option:
|
|
2308
|
-
self.current_stack[np.where(self.current_stack > 0.)] = np.log(
|
|
2309
|
-
self.current_stack[np.where(self.current_stack > 0.)])
|
|
2335
|
+
self.current_stack[np.where((self.current_stack > 0.)&(self.current_stack==self.current_stack))] = np.log(
|
|
2336
|
+
self.current_stack[np.where((self.current_stack > 0.)&(self.current_stack==self.current_stack))])
|
|
2310
2337
|
|
|
2311
2338
|
def changed_channel(self):
|
|
2312
2339
|
|
|
@@ -2422,11 +2449,11 @@ class MeasureAnnotator(SignalAnnotator):
|
|
|
2422
2449
|
if len(movies) == 0:
|
|
2423
2450
|
msgBox = QMessageBox()
|
|
2424
2451
|
msgBox.setIcon(QMessageBox.Warning)
|
|
2425
|
-
msgBox.setText("No
|
|
2452
|
+
msgBox.setText("No movie is detected in the experiment folder.\nPlease check the stack prefix...")
|
|
2426
2453
|
msgBox.setWindowTitle("Warning")
|
|
2427
2454
|
msgBox.setStandardButtons(QMessageBox.Ok)
|
|
2428
2455
|
returnValue = msgBox.exec()
|
|
2429
|
-
if returnValue == QMessageBox.
|
|
2456
|
+
if returnValue == QMessageBox.Ok:
|
|
2430
2457
|
self.close()
|
|
2431
2458
|
else:
|
|
2432
2459
|
self.stack_path = movies[0]
|
|
@@ -140,17 +140,22 @@ class SignalAnnotator2(QMainWindow,Styles):
|
|
|
140
140
|
|
|
141
141
|
self.button_widget = QWidget()
|
|
142
142
|
main_layout = QHBoxLayout()
|
|
143
|
+
main_layout.setSpacing(30)
|
|
144
|
+
|
|
143
145
|
self.button_widget.setLayout(main_layout)
|
|
144
146
|
|
|
145
147
|
main_layout.setContentsMargins(30,30,30,30)
|
|
146
148
|
self.left_panel = QVBoxLayout()
|
|
147
|
-
self.left_panel.setContentsMargins(
|
|
148
|
-
self.left_panel.setSpacing(
|
|
149
|
+
self.left_panel.setContentsMargins(5,5,5,5)
|
|
150
|
+
self.left_panel.setSpacing(5)
|
|
149
151
|
|
|
150
152
|
self.right_panel = QVBoxLayout()
|
|
153
|
+
self.right_panel.setSpacing(0)
|
|
154
|
+
self.right_panel.setContentsMargins(5,5,5,5)
|
|
151
155
|
|
|
152
156
|
#NEIGHBORHOOD
|
|
153
157
|
neigh_hbox = QHBoxLayout()
|
|
158
|
+
neigh_hbox.setContentsMargins(0,0,0,0)
|
|
154
159
|
neigh_hbox.addWidget(QLabel('neighborhood: '), 25)
|
|
155
160
|
self.neighborhood_choice_cb = QComboBox()
|
|
156
161
|
self.neighborhood_choice_cb.addItems(self.neighborhood_cols)
|
|
@@ -193,17 +198,17 @@ class SignalAnnotator2(QMainWindow,Styles):
|
|
|
193
198
|
self.relative_del_class_btn.clicked.connect(self.del_relative_event_class)
|
|
194
199
|
subclass_hbox.addWidget(self.relative_del_class_btn, 5)
|
|
195
200
|
class_hbox.addLayout(subclass_hbox, 75)
|
|
196
|
-
|
|
197
|
-
|
|
198
201
|
self.left_panel.addLayout(class_hbox)
|
|
199
202
|
|
|
200
203
|
self.cell_events_hbox = QHBoxLayout()
|
|
204
|
+
self.cell_events_hbox.setContentsMargins(0,0,0,0)
|
|
201
205
|
self.cell_events_hbox.addWidget(QLabel('reference event: '), 25)
|
|
202
206
|
self.reference_event_choice_cb = QComboBox()
|
|
203
207
|
self.cell_events_hbox.addWidget(self.reference_event_choice_cb, 75)
|
|
204
208
|
|
|
205
209
|
#if 'self' not in self.neighborhood_choice_cb.currentText():
|
|
206
210
|
self.neigh_cell_events_hbox = QHBoxLayout()
|
|
211
|
+
self.neigh_cell_events_hbox.setContentsMargins(0,0,0,0)
|
|
207
212
|
self.neigh_lab=QLabel('neighbor event: ')
|
|
208
213
|
self.neigh_cell_events_hbox.addWidget(self.neigh_lab, 25)
|
|
209
214
|
self.neighbor_event_choice_cb = QComboBox()
|
|
@@ -214,7 +219,7 @@ class SignalAnnotator2(QMainWindow,Styles):
|
|
|
214
219
|
|
|
215
220
|
# Text information about selected cells
|
|
216
221
|
self.cell_info_hbox = QHBoxLayout()
|
|
217
|
-
self.cell_info_hbox.setContentsMargins(30,
|
|
222
|
+
self.cell_info_hbox.setContentsMargins(30,0,30,0)
|
|
218
223
|
|
|
219
224
|
reference_layout = QVBoxLayout()
|
|
220
225
|
reference_layout.addWidget(self.reference_cell_info)
|
|
@@ -232,7 +237,7 @@ class SignalAnnotator2(QMainWindow,Styles):
|
|
|
232
237
|
|
|
233
238
|
# Annotation buttons
|
|
234
239
|
options_hbox = QHBoxLayout()
|
|
235
|
-
options_hbox.setContentsMargins(150,
|
|
240
|
+
options_hbox.setContentsMargins(150, 0, 50, 0)
|
|
236
241
|
self.event_btn = QRadioButton('event')
|
|
237
242
|
self.event_btn.setStyleSheet(self.button_style_sheet_2)
|
|
238
243
|
self.event_btn.toggled.connect(self.enable_time_of_interest)
|
|
@@ -256,7 +261,7 @@ class SignalAnnotator2(QMainWindow,Styles):
|
|
|
256
261
|
self.left_panel.addLayout(options_hbox)
|
|
257
262
|
|
|
258
263
|
time_option_hbox = QHBoxLayout()
|
|
259
|
-
time_option_hbox.setContentsMargins(100,
|
|
264
|
+
time_option_hbox.setContentsMargins(100, 0, 100, 0)
|
|
260
265
|
self.time_of_interest_label = QLabel('time of interest: ')
|
|
261
266
|
time_option_hbox.addWidget(self.time_of_interest_label, 30)
|
|
262
267
|
self.time_of_interest_le = QLineEdit()
|
|
@@ -264,6 +269,7 @@ class SignalAnnotator2(QMainWindow,Styles):
|
|
|
264
269
|
self.left_panel.addLayout(time_option_hbox)
|
|
265
270
|
|
|
266
271
|
main_action_hbox = QHBoxLayout()
|
|
272
|
+
main_action_hbox.setContentsMargins(100, 0, 100, 0)
|
|
267
273
|
self.correct_btn = QPushButton('correct')
|
|
268
274
|
self.correct_btn.setIcon(icon(MDI6.redo_variant, color="white"))
|
|
269
275
|
self.correct_btn.setIconSize(QSize(20, 20))
|
|
@@ -320,7 +326,7 @@ class SignalAnnotator2(QMainWindow,Styles):
|
|
|
320
326
|
self.left_panel.addLayout(plot_buttons_hbox)
|
|
321
327
|
|
|
322
328
|
signal_choice_grid = QVBoxLayout()
|
|
323
|
-
signal_choice_grid.setContentsMargins(30,0,
|
|
329
|
+
signal_choice_grid.setContentsMargins(30,0,70,5)
|
|
324
330
|
|
|
325
331
|
header_layout = QHBoxLayout()
|
|
326
332
|
header_layout.addWidget(QLabel('reference'), 23, alignment=Qt.AlignCenter)
|
|
@@ -332,32 +338,14 @@ class SignalAnnotator2(QMainWindow,Styles):
|
|
|
332
338
|
for i in range(self.n_signals):
|
|
333
339
|
|
|
334
340
|
h_layout = QHBoxLayout()
|
|
341
|
+
if i==(self.n_signals-1):
|
|
342
|
+
h_layout.setContentsMargins(0,0,0,0)
|
|
335
343
|
h_layout.addWidget(self.reference_pop_option_buttons[i], 23, alignment=Qt.AlignCenter)
|
|
336
344
|
h_layout.addWidget(self.neighbor_pop_option_buttons[i], 23, alignment=Qt.AlignCenter)
|
|
337
345
|
h_layout.addWidget(self.relative_pop_option_buttons[i], 23, alignment=Qt.AlignCenter)
|
|
338
346
|
h_layout.addWidget(self.signal_choices[i], 30)
|
|
339
347
|
signal_choice_grid.addLayout(h_layout)
|
|
340
348
|
|
|
341
|
-
# signal_choice_vbox = QVBoxLayout()
|
|
342
|
-
# signal_choice_vbox.setContentsMargins(30,0,30,50)
|
|
343
|
-
# for i in range(len(self.signal_choices)):
|
|
344
|
-
# signal_choice_grid.addWidget(self.signal_choices[i],i+1,3)
|
|
345
|
-
# # hlayout = QHBoxLayout()
|
|
346
|
-
# #
|
|
347
|
-
# # #hlayout.addLayout(self.signal_labels[i], 20)
|
|
348
|
-
# # #hlayout.addLayout(self.signal_choices[i], 75)
|
|
349
|
-
# # # if i==0:
|
|
350
|
-
# # # hlayout.addWidget(self.signal_choices[i], 75,alignment=Qt.AlignBottom)
|
|
351
|
-
# # # else:
|
|
352
|
-
# # hlayout.addWidget(self.signal_choices[i], 75)
|
|
353
|
-
# # #hlayout.addWidget(self.log_btns[i], 5)
|
|
354
|
-
# # signal_choice_vbox.addLayout(hlayout)
|
|
355
|
-
|
|
356
|
-
# self.log_btns[i].setIcon(icon(MDI6.math_log,color="black"))
|
|
357
|
-
# self.log_btns[i].setStyleSheet(self.parent.parent.parent.button_select_all)
|
|
358
|
-
# self.log_btns[i].clicked.connect(lambda ch, i=i: self.switch_to_log(i))
|
|
359
|
-
#signal_choice_hbox.addLayout(signal_choice_vbox,alignment=Qt.AlignCenter)
|
|
360
|
-
|
|
361
349
|
self.left_panel.addLayout(signal_choice_grid)
|
|
362
350
|
|
|
363
351
|
btn_hbox = QHBoxLayout()
|
|
@@ -377,7 +365,6 @@ class SignalAnnotator2(QMainWindow,Styles):
|
|
|
377
365
|
# Animation
|
|
378
366
|
animation_buttons_box = QHBoxLayout()
|
|
379
367
|
|
|
380
|
-
|
|
381
368
|
animation_buttons_box.addWidget(self.frame_lbl, 20, alignment=Qt.AlignLeft)
|
|
382
369
|
|
|
383
370
|
self.first_frame_btn = QPushButton()
|
|
@@ -1817,7 +1804,7 @@ class SignalAnnotator2(QMainWindow,Styles):
|
|
|
1817
1804
|
else:
|
|
1818
1805
|
self.stack = self.stack[0]
|
|
1819
1806
|
if self.log_option:
|
|
1820
|
-
self.stack[np.where(self.stack>0.)] = np.log(self.stack[np.where(self.stack>0.)])
|
|
1807
|
+
self.stack[np.where((self.stack>0.)&(self.stack==self.stack))] = np.log(self.stack[np.where((self.stack>0.))&(self.stack==self.stack)])
|
|
1821
1808
|
|
|
1822
1809
|
print(f'Load stack of shape: {self.stack.shape}.')
|
|
1823
1810
|
|
celldetective/gui/survival_ui.py
CHANGED
|
@@ -126,13 +126,15 @@ class ConfigSurvival(QWidget, Styles):
|
|
|
126
126
|
main_layout.addLayout(select_layout)
|
|
127
127
|
|
|
128
128
|
time_cut_layout = QHBoxLayout()
|
|
129
|
-
|
|
129
|
+
cut_time_lbl = QLabel('cut obs.\ntime [min]: ')
|
|
130
|
+
cut_time_lbl.setToolTip('Filter out later events from\nthe analysis (in absolute time).')
|
|
131
|
+
time_cut_layout.addWidget(cut_time_lbl, 33)
|
|
130
132
|
self.query_time_cut = QLineEdit()
|
|
131
133
|
self.query_time_cut.setValidator(self.float_validator)
|
|
132
134
|
time_cut_layout.addWidget(self.query_time_cut, 66)
|
|
133
135
|
main_layout.addLayout(time_cut_layout)
|
|
134
136
|
|
|
135
|
-
self.
|
|
137
|
+
self.set_classes_and_times()
|
|
136
138
|
self.cbs[1].setCurrentText('t_firstdetection')
|
|
137
139
|
|
|
138
140
|
time_calib_layout = QHBoxLayout()
|
|
@@ -174,6 +176,8 @@ class ConfigSurvival(QWidget, Styles):
|
|
|
174
176
|
print('no column starts with t')
|
|
175
177
|
self.auto_close = True
|
|
176
178
|
return None
|
|
179
|
+
if 't0' in self.all_columns:
|
|
180
|
+
time_columns.append('t0')
|
|
177
181
|
|
|
178
182
|
self.cbs[1].clear()
|
|
179
183
|
self.cbs[1].addItems(np.unique(self.cb_options[1]+time_columns))
|
|
@@ -268,7 +272,7 @@ class ConfigSurvival(QWidget, Styles):
|
|
|
268
272
|
|
|
269
273
|
cut_observation_time = None
|
|
270
274
|
try:
|
|
271
|
-
cut_observation_time = float(self.query_time_cut.text()) / self.FrameToMin
|
|
275
|
+
cut_observation_time = float(self.query_time_cut.text().replace(',','.')) / self.FrameToMin
|
|
272
276
|
if not 0<cut_observation_time<=(self.df['FRAME'].max()):
|
|
273
277
|
print('Invalid cut time (larger than movie length)... Not applied.')
|
|
274
278
|
cut_observation_time = None
|