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.
Files changed (41) hide show
  1. celldetective/__main__.py +30 -4
  2. celldetective/_version.py +1 -1
  3. celldetective/extra_properties.py +21 -0
  4. celldetective/filters.py +15 -2
  5. celldetective/gui/InitWindow.py +28 -34
  6. celldetective/gui/analyze_block.py +3 -498
  7. celldetective/gui/classifier_widget.py +1 -1
  8. celldetective/gui/control_panel.py +100 -29
  9. celldetective/gui/generic_signal_plot.py +35 -18
  10. celldetective/gui/gui_utils.py +143 -2
  11. celldetective/gui/layouts.py +7 -6
  12. celldetective/gui/measurement_options.py +38 -43
  13. celldetective/gui/plot_measurements.py +5 -13
  14. celldetective/gui/plot_signals_ui.py +30 -30
  15. celldetective/gui/process_block.py +66 -197
  16. celldetective/gui/retrain_segmentation_model_options.py +3 -1
  17. celldetective/gui/signal_annotator.py +50 -32
  18. celldetective/gui/signal_annotator2.py +7 -4
  19. celldetective/gui/styles.py +13 -0
  20. celldetective/gui/survival_ui.py +8 -21
  21. celldetective/gui/tableUI.py +1 -2
  22. celldetective/gui/thresholds_gui.py +195 -205
  23. celldetective/gui/viewers.py +262 -12
  24. celldetective/io.py +85 -11
  25. celldetective/measure.py +128 -88
  26. celldetective/models/segmentation_effectors/ricm_bf_all_last/config_input.json +79 -0
  27. celldetective/models/segmentation_effectors/ricm_bf_all_last/ricm_bf_all_last +0 -0
  28. celldetective/models/segmentation_effectors/ricm_bf_all_last/training_instructions.json +37 -0
  29. celldetective/models/segmentation_effectors/test-transfer/config_input.json +39 -0
  30. celldetective/models/segmentation_effectors/test-transfer/test-transfer +0 -0
  31. celldetective/neighborhood.py +0 -2
  32. celldetective/scripts/measure_cells.py +21 -9
  33. celldetective/signals.py +77 -66
  34. celldetective/tracking.py +19 -13
  35. {celldetective-1.3.2.dist-info → celldetective-1.3.4.dist-info}/METADATA +12 -10
  36. {celldetective-1.3.2.dist-info → celldetective-1.3.4.dist-info}/RECORD +41 -36
  37. {celldetective-1.3.2.dist-info → celldetective-1.3.4.dist-info}/WHEEL +1 -1
  38. tests/test_qt.py +5 -3
  39. {celldetective-1.3.2.dist-info → celldetective-1.3.4.dist-info}/LICENSE +0 -0
  40. {celldetective-1.3.2.dist-info → celldetective-1.3.4.dist-info}/entry_points.txt +0 -0
  41. {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
- font-size: 10px;
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
- self.well_index = np.linspace(0,len(self.wells)-1,len(self.wells),dtype=int)
731
- else:
732
- self.well_index = [self.parent_window.well_list.currentIndex()]
733
- print(f"Processing well {self.parent_window.well_list.currentText()}...")
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.currentText()=="*":
737
+ if self.parent_window.position_list.isMultipleSelection():
767
738
  msgBox = QMessageBox()
768
739
  msgBox.setIcon(QMessageBox.Question)
769
- msgBox.setText("If you continue, all positions will be processed.\nDo you want to proceed?")
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
- if self.parent_window.position_list.currentText()=="*":
799
- pos_indices = np.linspace(0,len(pos)-1,len(pos),dtype=int)
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.currentText()!="*":
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.currentText()!="*":
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.currentText()!="*":
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
- # QApplication.restoreOverrideCursor()
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"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)
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.currentIndex()
962
- if self.well_option==len(self.wells):
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=wo, position_option=po, population=self.mode, return_pos_info=True)
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
- font-size: 10px;
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
- font-size: 10px;
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.currentIndex()
1352
- if self.well_option==len(self.wells):
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=wo, position_option=po, population="pairs", return_pos_info=True)
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"Well {self.parent_window.well_list.currentText()}; Position {self.parent_window.position_list.currentText()}", population='pairs', plot_mode=plot_mode, save_inplace_option=True)
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
- self.well_index = np.linspace(0,len(self.wells)-1,len(self.wells),dtype=int)
1453
- else:
1454
- self.well_index = [self.parent_window.well_list.currentIndex()]
1455
- print(f"Processing well {self.parent_window.well_list.currentText()}...")
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.currentText()=="*":
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
- if self.parent_window.position_list.currentText()=="*":
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.setCurrentIndex(self.parent_window.well_list.count()-1)
1711
- self.parent_window.position_list.setCurrentIndex(0)
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
- well_option = "*"
1728
- else:
1729
- well_option = self.parent_window.well_list.currentIndex()
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=pos_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=pos_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=pos_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
- # self.parent.refresh_signal_models()
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
- ind = ind[0]
1086
- self.selection.append(ind)
1087
- self.correct_btn.setEnabled(True)
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
  """