celldetective 1.3.2__py3-none-any.whl → 1.3.4__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/__main__.py +30 -4
- celldetective/_version.py +1 -1
- celldetective/extra_properties.py +21 -0
- celldetective/filters.py +15 -2
- celldetective/gui/InitWindow.py +28 -34
- celldetective/gui/analyze_block.py +3 -498
- celldetective/gui/classifier_widget.py +1 -1
- celldetective/gui/control_panel.py +100 -29
- celldetective/gui/generic_signal_plot.py +35 -18
- celldetective/gui/gui_utils.py +143 -2
- celldetective/gui/layouts.py +7 -6
- celldetective/gui/measurement_options.py +38 -43
- celldetective/gui/plot_measurements.py +5 -13
- celldetective/gui/plot_signals_ui.py +30 -30
- celldetective/gui/process_block.py +66 -197
- celldetective/gui/retrain_segmentation_model_options.py +3 -1
- celldetective/gui/signal_annotator.py +50 -32
- celldetective/gui/signal_annotator2.py +7 -4
- celldetective/gui/styles.py +13 -0
- celldetective/gui/survival_ui.py +8 -21
- celldetective/gui/tableUI.py +1 -2
- celldetective/gui/thresholds_gui.py +195 -205
- celldetective/gui/viewers.py +262 -12
- celldetective/io.py +85 -11
- 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 +0 -2
- celldetective/scripts/measure_cells.py +21 -9
- celldetective/signals.py +77 -66
- celldetective/tracking.py +19 -13
- {celldetective-1.3.2.dist-info → celldetective-1.3.4.dist-info}/METADATA +12 -10
- {celldetective-1.3.2.dist-info → celldetective-1.3.4.dist-info}/RECORD +41 -36
- {celldetective-1.3.2.dist-info → celldetective-1.3.4.dist-info}/WHEEL +1 -1
- tests/test_qt.py +5 -3
- {celldetective-1.3.2.dist-info → celldetective-1.3.4.dist-info}/LICENSE +0 -0
- {celldetective-1.3.2.dist-info → celldetective-1.3.4.dist-info}/entry_points.txt +0 -0
- {celldetective-1.3.2.dist-info → celldetective-1.3.4.dist-info}/top_level.txt +0 -0
|
@@ -186,11 +186,8 @@ class ProcessPanel(QFrame, Styles):
|
|
|
186
186
|
measure_layout = QHBoxLayout()
|
|
187
187
|
|
|
188
188
|
self.measure_action = QCheckBox("MEASURE")
|
|
189
|
-
self.measure_action.setStyleSheet(
|
|
190
|
-
|
|
191
|
-
padding-left: 10px;
|
|
192
|
-
padding-top: 5px;
|
|
193
|
-
""")
|
|
189
|
+
self.measure_action.setStyleSheet(self.menu_check_style)
|
|
190
|
+
|
|
194
191
|
self.measure_action.setIcon(icon(MDI6.eyedropper,color="black"))
|
|
195
192
|
self.measure_action.setIconSize(QSize(20, 20))
|
|
196
193
|
self.measure_action.setToolTip("Measure.")
|
|
@@ -229,11 +226,7 @@ class ProcessPanel(QFrame, Styles):
|
|
|
229
226
|
signal_layout = QVBoxLayout()
|
|
230
227
|
signal_hlayout = QHBoxLayout()
|
|
231
228
|
self.signal_analysis_action = QCheckBox("DETECT EVENTS")
|
|
232
|
-
self.signal_analysis_action.setStyleSheet(
|
|
233
|
-
font-size: 10px;
|
|
234
|
-
padding-left: 10px;
|
|
235
|
-
padding-top: 5px;
|
|
236
|
-
""")
|
|
229
|
+
self.signal_analysis_action.setStyleSheet(self.menu_check_style)
|
|
237
230
|
self.signal_analysis_action.setIcon(icon(MDI6.chart_bell_curve_cumulative,color="black"))
|
|
238
231
|
self.signal_analysis_action.setIconSize(QSize(20, 20))
|
|
239
232
|
self.signal_analysis_action.setToolTip("Detect events in single-cell signals.")
|
|
@@ -291,28 +284,15 @@ class ProcessPanel(QFrame, Styles):
|
|
|
291
284
|
self.signal_models_list.addItems(signal_models)
|
|
292
285
|
|
|
293
286
|
def generate_tracking_options(self):
|
|
287
|
+
|
|
294
288
|
grid_track = QHBoxLayout()
|
|
295
289
|
|
|
296
290
|
self.track_action = QCheckBox("TRACK")
|
|
291
|
+
self.track_action.setStyleSheet(self.menu_check_style)
|
|
297
292
|
self.track_action.setIcon(icon(MDI6.chart_timeline_variant,color="black"))
|
|
298
293
|
self.track_action.setIconSize(QSize(20, 20))
|
|
299
294
|
self.track_action.setToolTip("Track the target cells using bTrack.")
|
|
300
|
-
self.track_action.setStyleSheet("""
|
|
301
|
-
font-size: 10px;
|
|
302
|
-
padding-left: 10px;
|
|
303
|
-
padding-top: 5px;
|
|
304
|
-
""")
|
|
305
295
|
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
296
|
|
|
317
297
|
self.delete_tracks_btn = QPushButton()
|
|
318
298
|
self.delete_tracks_btn.setIcon(icon(MDI6.trash_can,color="black"))
|
|
@@ -381,10 +361,7 @@ class ProcessPanel(QFrame, Styles):
|
|
|
381
361
|
grid_segment.setSpacing(0)
|
|
382
362
|
|
|
383
363
|
self.segment_action = QCheckBox("SEGMENT")
|
|
384
|
-
self.segment_action.setStyleSheet(
|
|
385
|
-
font-size: 10px;
|
|
386
|
-
padding-left: 10px;
|
|
387
|
-
""")
|
|
364
|
+
self.segment_action.setStyleSheet(self.menu_check_style)
|
|
388
365
|
self.segment_action.setIcon(icon(MDI6.bacteria, color='black'))
|
|
389
366
|
self.segment_action.setToolTip(f"Segment the {self.mode} cells on the images.")
|
|
390
367
|
self.segment_action.toggled.connect(self.enable_segmentation_model_list)
|
|
@@ -640,25 +617,6 @@ class ProcessPanel(QFrame, Styles):
|
|
|
640
617
|
|
|
641
618
|
self.seg_model_list.insertSeparator(len(self.models_truncated))
|
|
642
619
|
|
|
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
620
|
def tick_all_actions(self):
|
|
663
621
|
self.switch_all_ticks_option()
|
|
664
622
|
if self.all_ticked:
|
|
@@ -726,11 +684,24 @@ class ProcessPanel(QFrame, Styles):
|
|
|
726
684
|
|
|
727
685
|
def process_population(self):
|
|
728
686
|
|
|
729
|
-
if self.parent_window.well_list.currentText()
|
|
730
|
-
|
|
731
|
-
else:
|
|
732
|
-
|
|
733
|
-
|
|
687
|
+
# if self.parent_window.well_list.currentText().startswith('Multiple'):
|
|
688
|
+
# self.well_index = np.linspace(0,len(self.wells)-1,len(self.wells),dtype=int)
|
|
689
|
+
# else:
|
|
690
|
+
|
|
691
|
+
self.well_index = self.parent_window.well_list.getSelectedIndices()
|
|
692
|
+
if len(self.well_index)==0:
|
|
693
|
+
msgBox = QMessageBox()
|
|
694
|
+
msgBox.setIcon(QMessageBox.Warning)
|
|
695
|
+
msgBox.setText("Please select at least one well first...")
|
|
696
|
+
msgBox.setWindowTitle("Warning")
|
|
697
|
+
msgBox.setStandardButtons(QMessageBox.Ok)
|
|
698
|
+
returnValue = msgBox.exec()
|
|
699
|
+
if returnValue == QMessageBox.Ok:
|
|
700
|
+
return None
|
|
701
|
+
else:
|
|
702
|
+
return None
|
|
703
|
+
|
|
704
|
+
print(f"Processing {self.parent_window.well_list.currentText()}...")
|
|
734
705
|
|
|
735
706
|
# self.freeze()
|
|
736
707
|
# QApplication.setOverrideCursor(Qt.WaitCursor)
|
|
@@ -763,10 +734,10 @@ class ProcessPanel(QFrame, Styles):
|
|
|
763
734
|
|
|
764
735
|
loop_iter=0
|
|
765
736
|
|
|
766
|
-
if self.parent_window.position_list.
|
|
737
|
+
if self.parent_window.position_list.isMultipleSelection():
|
|
767
738
|
msgBox = QMessageBox()
|
|
768
739
|
msgBox.setIcon(QMessageBox.Question)
|
|
769
|
-
msgBox.setText("If you continue,
|
|
740
|
+
msgBox.setText("If you continue, several positions will be processed.\nDo you want to proceed?")
|
|
770
741
|
msgBox.setWindowTitle("Info")
|
|
771
742
|
msgBox.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
|
|
772
743
|
returnValue = msgBox.exec()
|
|
@@ -795,12 +766,8 @@ class ProcessPanel(QFrame, Styles):
|
|
|
795
766
|
for w_idx in self.well_index:
|
|
796
767
|
|
|
797
768
|
pos = self.parent_window.positions[w_idx]
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
print("Processing all positions...")
|
|
801
|
-
else:
|
|
802
|
-
pos_indices = natsorted([pos.index(self.parent_window.position_list.currentText())])
|
|
803
|
-
print(f"Processing position {self.parent_window.position_list.currentText()}...")
|
|
769
|
+
pos_indices = self.parent_window.position_list.getSelectedIndices()
|
|
770
|
+
#print(f"Processing position {self.parent_window.position_list.currentText()}...")
|
|
804
771
|
|
|
805
772
|
well = self.parent_window.wells[w_idx]
|
|
806
773
|
|
|
@@ -816,7 +783,7 @@ class ProcessPanel(QFrame, Styles):
|
|
|
816
783
|
|
|
817
784
|
if self.segment_action.isChecked():
|
|
818
785
|
|
|
819
|
-
if len(glob(os.sep.join([self.pos, f'labels_{self.mode}','*.tif'])))>0 and self.parent_window.position_list.
|
|
786
|
+
if len(glob(os.sep.join([self.pos, f'labels_{self.mode}','*.tif'])))>0 and not self.parent_window.position_list.isMultipleSelection():
|
|
820
787
|
msgBox = QMessageBox()
|
|
821
788
|
msgBox.setIcon(QMessageBox.Question)
|
|
822
789
|
msgBox.setText("Labels have already been produced for this position. Do you want to segment again?")
|
|
@@ -843,7 +810,7 @@ class ProcessPanel(QFrame, Styles):
|
|
|
843
810
|
segment_at_position(self.pos, self.mode, self.model_name, stack_prefix=self.parent_window.movie_prefix, use_gpu=self.parent_window.parent_window.use_gpu, threads=self.parent_window.parent_window.n_threads)
|
|
844
811
|
|
|
845
812
|
if self.track_action.isChecked():
|
|
846
|
-
if os.path.exists(os.sep.join([self.pos, 'output', 'tables', f'trajectories_{self.mode}.csv'])) and self.parent_window.position_list.
|
|
813
|
+
if os.path.exists(os.sep.join([self.pos, 'output', 'tables', f'trajectories_{self.mode}.csv'])) and not self.parent_window.position_list.isMultipleSelection():
|
|
847
814
|
msgBox = QMessageBox()
|
|
848
815
|
msgBox.setIcon(QMessageBox.Question)
|
|
849
816
|
msgBox.setText("A trajectory set already exists. Previously annotated data for\nthis position will be lost. Do you want to proceed?")
|
|
@@ -859,15 +826,12 @@ class ProcessPanel(QFrame, Styles):
|
|
|
859
826
|
|
|
860
827
|
table = os.sep.join([self.pos, 'output', 'tables', f'trajectories_{self.mode}.csv'])
|
|
861
828
|
if self.signal_analysis_action.isChecked() and os.path.exists(table):
|
|
862
|
-
print('table exists')
|
|
863
829
|
table = pd.read_csv(table)
|
|
864
830
|
cols = list(table.columns)
|
|
865
|
-
print(table, cols)
|
|
866
831
|
if 'class_color' in cols:
|
|
867
|
-
print(cols, 'class_color in cols')
|
|
868
832
|
colors = list(table['class_color'].to_numpy())
|
|
869
833
|
if 'tab:orange' in colors or 'tab:cyan' in colors:
|
|
870
|
-
if self.parent_window.position_list.
|
|
834
|
+
if not self.parent_window.position_list.isMultipleSelection():
|
|
871
835
|
msgBox = QMessageBox()
|
|
872
836
|
msgBox.setIcon(QMessageBox.Question)
|
|
873
837
|
msgBox.setText("The signals of the cells in the position appear to have been annotated... Do you want to proceed?")
|
|
@@ -884,28 +848,7 @@ class ProcessPanel(QFrame, Styles):
|
|
|
884
848
|
if self.segment_action.isChecked():
|
|
885
849
|
self.segment_action.setChecked(False)
|
|
886
850
|
|
|
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
|
-
|
|
851
|
+
self.cellpose_calibrated = False
|
|
909
852
|
|
|
910
853
|
def open_napari_tracking(self):
|
|
911
854
|
print(f'View the tracks before post-processing for position {self.parent_window.pos} in napari...')
|
|
@@ -920,7 +863,7 @@ class ProcessPanel(QFrame, Styles):
|
|
|
920
863
|
plot_mode = 'plot_track_signals'
|
|
921
864
|
if 'TRACK_ID' not in list(self.df.columns):
|
|
922
865
|
plot_mode = 'static'
|
|
923
|
-
self.tab_ui = TableUI(self.df, f"
|
|
866
|
+
self.tab_ui = TableUI(self.df, f"{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
867
|
self.tab_ui.show()
|
|
925
868
|
else:
|
|
926
869
|
print('Table could not be loaded...')
|
|
@@ -933,24 +876,6 @@ class ProcessPanel(QFrame, Styles):
|
|
|
933
876
|
if returnValue == QMessageBox.Ok:
|
|
934
877
|
return None
|
|
935
878
|
|
|
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
879
|
def load_available_tables(self):
|
|
955
880
|
|
|
956
881
|
"""
|
|
@@ -958,18 +883,10 @@ class ProcessPanel(QFrame, Styles):
|
|
|
958
883
|
|
|
959
884
|
"""
|
|
960
885
|
|
|
961
|
-
self.well_option = self.parent_window.well_list.
|
|
962
|
-
|
|
963
|
-
wo = '*'
|
|
964
|
-
else:
|
|
965
|
-
wo = self.well_option
|
|
966
|
-
self.position_option = self.parent_window.position_list.currentIndex()
|
|
967
|
-
if self.position_option==0:
|
|
968
|
-
po = '*'
|
|
969
|
-
else:
|
|
970
|
-
po = self.position_option - 1
|
|
886
|
+
self.well_option = self.parent_window.well_list.getSelectedIndices()
|
|
887
|
+
self.position_option = self.parent_window.position_list.getSelectedIndices()
|
|
971
888
|
|
|
972
|
-
self.df, self.df_pos_info = load_experiment_tables(self.exp_dir, well_option=
|
|
889
|
+
self.df, self.df_pos_info = load_experiment_tables(self.exp_dir, well_option=self.well_option, position_option=self.position_option, population=self.mode, return_pos_info=True)
|
|
973
890
|
if self.df is None:
|
|
974
891
|
print('No table could be found...')
|
|
975
892
|
|
|
@@ -1016,6 +933,7 @@ class ProcessPanel(QFrame, Styles):
|
|
|
1016
933
|
self.process_population()
|
|
1017
934
|
|
|
1018
935
|
|
|
936
|
+
|
|
1019
937
|
class NeighPanel(QFrame, Styles):
|
|
1020
938
|
def __init__(self, parent_window):
|
|
1021
939
|
|
|
@@ -1093,11 +1011,8 @@ class NeighPanel(QFrame, Styles):
|
|
|
1093
1011
|
# Button to compute the neighborhoods
|
|
1094
1012
|
neigh_option_hbox = QHBoxLayout()
|
|
1095
1013
|
self.neigh_action = QCheckBox('NEIGHBORHOODS')
|
|
1096
|
-
self.neigh_action.setStyleSheet(
|
|
1097
|
-
|
|
1098
|
-
padding-left: 10px;
|
|
1099
|
-
padding-top: 5px;
|
|
1100
|
-
""")
|
|
1014
|
+
self.neigh_action.setStyleSheet(self.menu_check_style)
|
|
1015
|
+
|
|
1101
1016
|
#self.neigh_action.setIcon(icon(MDI6.eyedropper, color="black"))
|
|
1102
1017
|
#self.neigh_action.setIconSize(QSize(20, 20))
|
|
1103
1018
|
self.neigh_action.setToolTip(
|
|
@@ -1197,11 +1112,8 @@ class NeighPanel(QFrame, Styles):
|
|
|
1197
1112
|
|
|
1198
1113
|
rel_layout = QHBoxLayout()
|
|
1199
1114
|
self.measure_pairs_action = QCheckBox("MEASURE PAIRS")
|
|
1200
|
-
self.measure_pairs_action.setStyleSheet(
|
|
1201
|
-
|
|
1202
|
-
padding-left: 10px;
|
|
1203
|
-
padding-top: 5px;
|
|
1204
|
-
""")
|
|
1115
|
+
self.measure_pairs_action.setStyleSheet(self.menu_check_style)
|
|
1116
|
+
|
|
1205
1117
|
self.measure_pairs_action.setIcon(icon(MDI6.eyedropper, color="black"))
|
|
1206
1118
|
self.measure_pairs_action.setIconSize(QSize(20, 20))
|
|
1207
1119
|
self.measure_pairs_action.setToolTip("Measure the relative quantities defined for the cell pairs, for all neighborhoods.")
|
|
@@ -1220,10 +1132,7 @@ class NeighPanel(QFrame, Styles):
|
|
|
1220
1132
|
signal_layout = QVBoxLayout()
|
|
1221
1133
|
signal_hlayout = QHBoxLayout()
|
|
1222
1134
|
self.signal_analysis_action = QCheckBox("DETECT PAIR EVENTS")
|
|
1223
|
-
self.signal_analysis_action.setStyleSheet(
|
|
1224
|
-
font-size: 10px;
|
|
1225
|
-
padding-left: 10px;
|
|
1226
|
-
padding-top: 5px;""")
|
|
1135
|
+
self.signal_analysis_action.setStyleSheet(self.menu_check_style)
|
|
1227
1136
|
|
|
1228
1137
|
self.signal_analysis_action.setIcon(icon(MDI6.chart_bell_curve_cumulative, color="black"))
|
|
1229
1138
|
self.signal_analysis_action.setIconSize(QSize(20, 20))
|
|
@@ -1348,18 +1257,10 @@ class NeighPanel(QFrame, Styles):
|
|
|
1348
1257
|
|
|
1349
1258
|
"""
|
|
1350
1259
|
|
|
1351
|
-
self.well_option = self.parent_window.well_list.
|
|
1352
|
-
|
|
1353
|
-
wo = '*'
|
|
1354
|
-
else:
|
|
1355
|
-
wo = self.well_option
|
|
1356
|
-
self.position_option = self.parent_window.position_list.currentIndex()
|
|
1357
|
-
if self.position_option==0:
|
|
1358
|
-
po = '*'
|
|
1359
|
-
else:
|
|
1360
|
-
po = self.position_option - 1
|
|
1260
|
+
self.well_option = self.parent_window.well_list.getSelectedIndices()
|
|
1261
|
+
self.position_option = self.parent_window.position_list.getSelectedIndices()
|
|
1361
1262
|
|
|
1362
|
-
self.df, self.df_pos_info = load_experiment_tables(self.exp_dir, well_option=
|
|
1263
|
+
self.df, self.df_pos_info = load_experiment_tables(self.exp_dir, well_option=self.well_option, position_option=self.position_option, population="pairs", return_pos_info=True)
|
|
1363
1264
|
if self.df is None:
|
|
1364
1265
|
print('No table could be found...')
|
|
1365
1266
|
|
|
@@ -1371,7 +1272,7 @@ class NeighPanel(QFrame, Styles):
|
|
|
1371
1272
|
|
|
1372
1273
|
if self.df is not None:
|
|
1373
1274
|
plot_mode = 'static'
|
|
1374
|
-
self.tab_ui = TableUI(self.df, f"
|
|
1275
|
+
self.tab_ui = TableUI(self.df, f"{self.parent_window.well_list.currentText()}; Position {self.parent_window.position_list.currentText()}", population='pairs', plot_mode=plot_mode, save_inplace_option=True)
|
|
1375
1276
|
self.tab_ui.show()
|
|
1376
1277
|
else:
|
|
1377
1278
|
print('Table could not be loaded...')
|
|
@@ -1448,18 +1349,18 @@ class NeighPanel(QFrame, Styles):
|
|
|
1448
1349
|
|
|
1449
1350
|
def process_neighborhood(self):
|
|
1450
1351
|
|
|
1451
|
-
if self.parent_window.well_list.currentText()
|
|
1452
|
-
|
|
1453
|
-
else:
|
|
1454
|
-
|
|
1455
|
-
|
|
1352
|
+
# if self.parent_window.well_list.currentText().startswith('Multiple'):
|
|
1353
|
+
# self.well_index = np.linspace(0,len(self.wells)-1,len(self.wells),dtype=int)
|
|
1354
|
+
# else:
|
|
1355
|
+
self.well_index = self.parent_window.well_list.getSelectedIndices()
|
|
1356
|
+
print(f"Processing well {self.parent_window.well_list.currentText()}...")
|
|
1456
1357
|
|
|
1457
1358
|
# self.freeze()
|
|
1458
1359
|
# QApplication.setOverrideCursor(Qt.WaitCursor)
|
|
1459
1360
|
|
|
1460
1361
|
loop_iter=0
|
|
1461
1362
|
|
|
1462
|
-
if self.parent_window.position_list.
|
|
1363
|
+
if self.parent_window.position_list.isMultipleSelection():
|
|
1463
1364
|
msgBox = QMessageBox()
|
|
1464
1365
|
msgBox.setIcon(QMessageBox.Question)
|
|
1465
1366
|
msgBox.setText("If you continue, all positions will be processed.\nDo you want to proceed?")
|
|
@@ -1472,12 +1373,7 @@ class NeighPanel(QFrame, Styles):
|
|
|
1472
1373
|
for w_idx in self.well_index:
|
|
1473
1374
|
|
|
1474
1375
|
pos = self.parent_window.positions[w_idx]
|
|
1475
|
-
|
|
1476
|
-
pos_indices = np.linspace(0,len(pos)-1,len(pos),dtype=int)
|
|
1477
|
-
print("Processing all positions...")
|
|
1478
|
-
else:
|
|
1479
|
-
pos_indices = natsorted([pos.index(self.parent_window.position_list.currentText())])
|
|
1480
|
-
print(f"Processing position {self.parent_window.position_list.currentText()}...")
|
|
1376
|
+
pos_indices = self.parent_window.position_list.getSelectedIndices()
|
|
1481
1377
|
|
|
1482
1378
|
well = self.parent_window.wells[w_idx]
|
|
1483
1379
|
|
|
@@ -1523,35 +1419,12 @@ class NeighPanel(QFrame, Styles):
|
|
|
1523
1419
|
rel_measure_at_position(self.pos)
|
|
1524
1420
|
|
|
1525
1421
|
if self.signal_analysis_action.isChecked():
|
|
1526
|
-
|
|
1527
|
-
# df_targets = get_position_pickle(self.pos, population='targets')
|
|
1528
|
-
# df_effectors = get_position_pickle(self.pos, population='effectors')
|
|
1529
|
-
# self.dataframes = {
|
|
1530
|
-
# 'targets': df_targets,
|
|
1531
|
-
# 'effectors': df_effectors,
|
|
1532
|
-
# }
|
|
1533
|
-
|
|
1534
|
-
# df_pairs = get_position_table(self.pos, population='pairs')
|
|
1535
|
-
|
|
1536
|
-
# # Need to identify expected reference / neighbor tables
|
|
1537
|
-
# model_path = locate_signal_model(self.pair_signal_models_list.currentText(), pairs=True)
|
|
1538
|
-
# print(f'Looking for model in {model_path}...')
|
|
1539
|
-
# complete_path = model_path
|
|
1540
|
-
# complete_path = rf"{complete_path}"
|
|
1541
|
-
# model_config_path = os.sep.join([complete_path, 'config_input.json'])
|
|
1542
|
-
# model_config_path = rf"{model_config_path}"
|
|
1543
|
-
# f = open(model_config_path)
|
|
1544
|
-
# model_config_path = json.load(f)
|
|
1545
|
-
|
|
1546
|
-
# reference_population = model_config_path['reference_population']
|
|
1547
|
-
# neighbor_population = model_config_path['neighbor_population']
|
|
1548
|
-
|
|
1549
|
-
# analyze_pair_signals(df_pairs, self.dataframes[reference_population], self.dataframes[neighbor_population], model=self.pair_signal_models_list.currentText())
|
|
1422
|
+
|
|
1550
1423
|
analyze_pair_signals_at_position(self.pos, self.pair_signal_models_list.currentText(), use_gpu=self.parent_window.parent_window.use_gpu)
|
|
1424
|
+
|
|
1551
1425
|
self.parent_window.update_position_options()
|
|
1552
1426
|
print('Done.')
|
|
1553
1427
|
|
|
1554
|
-
|
|
1555
1428
|
def check_signals2(self):
|
|
1556
1429
|
|
|
1557
1430
|
test = self.parent_window.locate_selected_position()
|
|
@@ -1707,8 +1580,8 @@ class PreprocessingPanel(QFrame, Styles):
|
|
|
1707
1580
|
if returnValue == QMessageBox.Cancel:
|
|
1708
1581
|
return None
|
|
1709
1582
|
elif returnValue == QMessageBox.Yes:
|
|
1710
|
-
self.parent_window.well_list.
|
|
1711
|
-
self.parent_window.position_list.
|
|
1583
|
+
self.parent_window.well_list.selectAll()
|
|
1584
|
+
self.parent_window.position_list.selectAll()
|
|
1712
1585
|
elif returnValue == QMessageBox.No:
|
|
1713
1586
|
msgBox2 = QMessageBox()
|
|
1714
1587
|
msgBox2.setIcon(QMessageBox.Question)
|
|
@@ -1723,16 +1596,11 @@ class PreprocessingPanel(QFrame, Styles):
|
|
|
1723
1596
|
|
|
1724
1597
|
print('Proceed with correction...')
|
|
1725
1598
|
|
|
1726
|
-
if self.parent_window.well_list.currentText()=='*':
|
|
1727
|
-
|
|
1728
|
-
else:
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
if self.parent_window.position_list.currentText()=='*':
|
|
1732
|
-
pos_option = "*"
|
|
1733
|
-
else:
|
|
1734
|
-
pos_option = self.parent_window.position_list.currentIndex()-1
|
|
1735
|
-
|
|
1599
|
+
# if self.parent_window.well_list.currentText()=='*':
|
|
1600
|
+
# well_option = "*"
|
|
1601
|
+
# else:
|
|
1602
|
+
well_option = self.parent_window.well_list.getSelectedIndices()
|
|
1603
|
+
position_option = self.parent_window.position_list.getSelectedIndices()
|
|
1736
1604
|
|
|
1737
1605
|
for k,correction_protocol in enumerate(self.protocol_layout.protocols):
|
|
1738
1606
|
|
|
@@ -1747,7 +1615,7 @@ class PreprocessingPanel(QFrame, Styles):
|
|
|
1747
1615
|
print(f'Model-free correction; {movie_prefix=} {export_prefix=}')
|
|
1748
1616
|
correct_background_model_free(self.exp_dir,
|
|
1749
1617
|
well_option=well_option,
|
|
1750
|
-
position_option=
|
|
1618
|
+
position_option=position_option,
|
|
1751
1619
|
export = True,
|
|
1752
1620
|
return_stacks=False,
|
|
1753
1621
|
show_progress_per_well = True,
|
|
@@ -1761,7 +1629,7 @@ class PreprocessingPanel(QFrame, Styles):
|
|
|
1761
1629
|
print(f'Fit correction; {movie_prefix=} {export_prefix=} {correction_protocol=}')
|
|
1762
1630
|
correct_background_model(self.exp_dir,
|
|
1763
1631
|
well_option=well_option,
|
|
1764
|
-
position_option=
|
|
1632
|
+
position_option=position_option,
|
|
1765
1633
|
export= True,
|
|
1766
1634
|
return_stacks=False,
|
|
1767
1635
|
show_progress_per_well = True,
|
|
@@ -1774,7 +1642,7 @@ class PreprocessingPanel(QFrame, Styles):
|
|
|
1774
1642
|
print(f'Offset correction; {movie_prefix=} {export_prefix=} {correction_protocol=}')
|
|
1775
1643
|
correct_channel_offset(self.exp_dir,
|
|
1776
1644
|
well_option=well_option,
|
|
1777
|
-
position_option=
|
|
1645
|
+
position_option=position_option,
|
|
1778
1646
|
export= True,
|
|
1779
1647
|
return_stacks=False,
|
|
1780
1648
|
show_progress_per_well = True,
|
|
@@ -1792,6 +1660,7 @@ class PreprocessingPanel(QFrame, Styles):
|
|
|
1792
1660
|
Load the first frame of the first movie found in the experiment folder as a sample.
|
|
1793
1661
|
"""
|
|
1794
1662
|
|
|
1663
|
+
print(f"{self.parent_window.pos}")
|
|
1795
1664
|
movies = glob(self.parent_window.pos + os.sep.join(['movie', f"{self.parent_window.movie_prefix}*.tif"]))
|
|
1796
1665
|
|
|
1797
1666
|
if len(movies) == 0:
|
|
@@ -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)
|
|
@@ -50,6 +50,7 @@ class SignalAnnotator(QMainWindow, Styles):
|
|
|
50
50
|
self.soft_path = get_software_location()
|
|
51
51
|
self.recently_modified = False
|
|
52
52
|
self.selection = []
|
|
53
|
+
|
|
53
54
|
if self.mode == "targets":
|
|
54
55
|
self.instructions_path = self.exp_dir + os.sep.join(['configs', 'signal_annotator_config_targets.json'])
|
|
55
56
|
self.trajectories_path = self.pos + os.sep.join(['output','tables','trajectories_targets.csv'])
|
|
@@ -505,6 +506,11 @@ class SignalAnnotator(QMainWindow, Styles):
|
|
|
505
506
|
self.df_tracks['class_color'] = [color_from_class(i) for i in self.df_tracks[self.class_name].to_numpy()]
|
|
506
507
|
|
|
507
508
|
self.extract_scatter_from_trajectories()
|
|
509
|
+
if len(self.selection)>0:
|
|
510
|
+
self.select_single_cell(self.selection[0][0], self.selection[0][1])
|
|
511
|
+
|
|
512
|
+
self.fcanvas.canvas.draw()
|
|
513
|
+
|
|
508
514
|
|
|
509
515
|
def contrast_slider_action(self):
|
|
510
516
|
|
|
@@ -527,14 +533,14 @@ class SignalAnnotator(QMainWindow, Styles):
|
|
|
527
533
|
try:
|
|
528
534
|
self.selection.pop(0)
|
|
529
535
|
except Exception as e:
|
|
530
|
-
print(e)
|
|
536
|
+
print(f"L 536 {e=}")
|
|
531
537
|
|
|
532
538
|
try:
|
|
533
539
|
for k, (t, idx) in enumerate(zip(self.loc_t, self.loc_idx)):
|
|
534
540
|
self.colors[t][idx, 0] = self.previous_color[k][0]
|
|
535
541
|
self.colors[t][idx, 1] = self.previous_color[k][1]
|
|
536
542
|
except Exception as e:
|
|
537
|
-
print(f'{e=}')
|
|
543
|
+
print(f'L 543 {e=}')
|
|
538
544
|
|
|
539
545
|
def hide_annotation_buttons(self):
|
|
540
546
|
|
|
@@ -589,7 +595,7 @@ class SignalAnnotator(QMainWindow, Styles):
|
|
|
589
595
|
self.line_dt.set_xdata([t0, t0])
|
|
590
596
|
self.cell_fcanvas.canvas.draw_idle()
|
|
591
597
|
except Exception as e:
|
|
592
|
-
print(e)
|
|
598
|
+
print(f"L 598 {e=}")
|
|
593
599
|
t0 = -1
|
|
594
600
|
cclass = 2
|
|
595
601
|
elif self.no_event_btn.isChecked():
|
|
@@ -611,9 +617,14 @@ class SignalAnnotator(QMainWindow, Styles):
|
|
|
611
617
|
status[:] = 2
|
|
612
618
|
if cclass > 2:
|
|
613
619
|
status[:] = 42
|
|
620
|
+
|
|
614
621
|
status_color = [color_from_status(s, recently_modified=True) for s in status]
|
|
615
622
|
class_color = [color_from_class(cclass, recently_modified=True) for i in range(len(status))]
|
|
616
623
|
|
|
624
|
+
|
|
625
|
+
# self.df_tracks['status_color'] = [color_from_status(i) for i in self.df_tracks[self.status_name].to_numpy()]
|
|
626
|
+
# self.df_tracks['class_color'] = [color_from_class(i) for i in self.df_tracks[self.class_name].to_numpy()]
|
|
627
|
+
|
|
617
628
|
self.df_tracks.loc[indices, self.status_name] = status
|
|
618
629
|
self.df_tracks.loc[indices, 'status_color'] = status_color
|
|
619
630
|
self.df_tracks.loc[indices, 'class_color'] = class_color
|
|
@@ -984,13 +995,9 @@ class SignalAnnotator(QMainWindow, Styles):
|
|
|
984
995
|
self.stack[np.where(self.stack > 0.)] = np.log(self.stack[np.where(self.stack > 0.)])
|
|
985
996
|
|
|
986
997
|
def closeEvent(self, event):
|
|
998
|
+
|
|
987
999
|
try:
|
|
988
1000
|
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
1001
|
del self.stack
|
|
995
1002
|
gc.collect()
|
|
996
1003
|
except:
|
|
@@ -1068,6 +1075,8 @@ class SignalAnnotator(QMainWindow, Styles):
|
|
|
1068
1075
|
|
|
1069
1076
|
def on_scatter_pick(self, event):
|
|
1070
1077
|
|
|
1078
|
+
self.event = event
|
|
1079
|
+
|
|
1071
1080
|
self.correct_btn.disconnect()
|
|
1072
1081
|
self.correct_btn.clicked.connect(self.show_annotation_buttons)
|
|
1073
1082
|
|
|
@@ -1082,36 +1091,41 @@ class SignalAnnotator(QMainWindow, Styles):
|
|
|
1082
1091
|
ind = [ind[np.argmin(dist)]]
|
|
1083
1092
|
|
|
1084
1093
|
if len(ind) > 0 and (len(self.selection) == 0):
|
|
1085
|
-
|
|
1086
|
-
self.selection.append(ind)
|
|
1087
|
-
self.
|
|
1088
|
-
self.cancel_btn.setEnabled(True)
|
|
1089
|
-
self.del_shortcut.setEnabled(True)
|
|
1090
|
-
self.no_event_shortcut.setEnabled(True)
|
|
1091
|
-
|
|
1092
|
-
self.track_of_interest = self.tracks[self.framedata][ind]
|
|
1093
|
-
print(f'You selected cell #{self.track_of_interest}...')
|
|
1094
|
-
self.give_cell_information()
|
|
1095
|
-
self.plot_signals()
|
|
1096
|
-
|
|
1097
|
-
self.loc_t = []
|
|
1098
|
-
self.loc_idx = []
|
|
1099
|
-
for t in range(len(self.tracks)):
|
|
1100
|
-
indices = np.where(self.tracks[t] == self.track_of_interest)[0]
|
|
1101
|
-
if len(indices) > 0:
|
|
1102
|
-
self.loc_t.append(t)
|
|
1103
|
-
self.loc_idx.append(indices[0])
|
|
1104
|
-
|
|
1105
|
-
self.previous_color = []
|
|
1106
|
-
for t, idx in zip(self.loc_t, self.loc_idx):
|
|
1107
|
-
self.previous_color.append(self.colors[t][idx].copy())
|
|
1108
|
-
self.colors[t][idx] = 'lime'
|
|
1094
|
+
|
|
1095
|
+
self.selection.append([ind[0],self.framedata])
|
|
1096
|
+
self.select_single_cell(ind[0], self.framedata)
|
|
1109
1097
|
|
|
1110
1098
|
elif len(ind) > 0 and len(self.selection) == 1:
|
|
1111
1099
|
self.cancel_btn.click()
|
|
1112
1100
|
else:
|
|
1113
1101
|
pass
|
|
1114
1102
|
|
|
1103
|
+
def select_single_cell(self, index, timepoint):
|
|
1104
|
+
|
|
1105
|
+
self.correct_btn.setEnabled(True)
|
|
1106
|
+
self.cancel_btn.setEnabled(True)
|
|
1107
|
+
self.del_shortcut.setEnabled(True)
|
|
1108
|
+
self.no_event_shortcut.setEnabled(True)
|
|
1109
|
+
|
|
1110
|
+
self.track_of_interest = self.tracks[timepoint][index]
|
|
1111
|
+
print(f'You selected cell #{self.track_of_interest}...')
|
|
1112
|
+
self.give_cell_information()
|
|
1113
|
+
self.plot_signals()
|
|
1114
|
+
|
|
1115
|
+
self.loc_t = []
|
|
1116
|
+
self.loc_idx = []
|
|
1117
|
+
for t in range(len(self.tracks)):
|
|
1118
|
+
indices = np.where(self.tracks[t] == self.track_of_interest)[0]
|
|
1119
|
+
if len(indices) > 0:
|
|
1120
|
+
self.loc_t.append(t)
|
|
1121
|
+
self.loc_idx.append(indices[0])
|
|
1122
|
+
|
|
1123
|
+
self.previous_color = []
|
|
1124
|
+
for t, idx in zip(self.loc_t, self.loc_idx):
|
|
1125
|
+
self.previous_color.append(self.colors[t][idx].copy())
|
|
1126
|
+
self.colors[t][idx] = 'lime'
|
|
1127
|
+
|
|
1128
|
+
|
|
1115
1129
|
def shortcut_suppr(self):
|
|
1116
1130
|
self.correct_btn.click()
|
|
1117
1131
|
self.suppr_btn.click()
|
|
@@ -1158,6 +1172,7 @@ class SignalAnnotator(QMainWindow, Styles):
|
|
|
1158
1172
|
if len(min_values) > 0:
|
|
1159
1173
|
self.cell_ax.set_ylim(smallest_value - pad_small, largest_value + pad_large)
|
|
1160
1174
|
except Exception as e:
|
|
1175
|
+
print(f"L1170 {e=}")
|
|
1161
1176
|
pass
|
|
1162
1177
|
|
|
1163
1178
|
def draw_frame(self, framedata):
|
|
@@ -1220,6 +1235,7 @@ class SignalAnnotator(QMainWindow, Styles):
|
|
|
1220
1235
|
self.df_tracks = self.df_tracks.drop(self.df_tracks[self.df_tracks[self.class_name] > 2].index)
|
|
1221
1236
|
self.df_tracks.to_csv(self.trajectories_path, index=False)
|
|
1222
1237
|
print('Table successfully exported...')
|
|
1238
|
+
self.compute_status_and_colors(0)
|
|
1223
1239
|
self.extract_scatter_from_trajectories()
|
|
1224
1240
|
|
|
1225
1241
|
# self.give_cell_information()
|
|
@@ -2424,6 +2440,8 @@ class MeasureAnnotator(SignalAnnotator):
|
|
|
2424
2440
|
except Exception as e:
|
|
2425
2441
|
print("cancel_selection: ",f'{e=}')
|
|
2426
2442
|
|
|
2443
|
+
self.event = None
|
|
2444
|
+
|
|
2427
2445
|
def locate_stack(self):
|
|
2428
2446
|
|
|
2429
2447
|
"""
|