celldetective 1.1.1.post1__py3-none-any.whl → 1.1.1.post4__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.
@@ -27,6 +27,7 @@ from matplotlib.cm import tab10
27
27
  import pandas as pd
28
28
  from sklearn.preprocessing import MinMaxScaler
29
29
  from celldetective.gui import Styles
30
+ from celldetective.measure import contour_of_instance_segmentation
30
31
 
31
32
  class SignalAnnotator(QMainWindow, Styles):
32
33
  """
@@ -76,9 +77,9 @@ class SignalAnnotator(QMainWindow, Styles):
76
77
 
77
78
  self.populate_widget()
78
79
 
79
- self.setMinimumWidth(int(0.8 * self.screen_width))
80
+ #self.setMinimumWidth(int(0.8 * self.screen_width))
80
81
  # self.setMaximumHeight(int(0.8*self.screen_height))
81
- self.setMinimumHeight(int(0.8 * self.screen_height))
82
+ #self.setMinimumHeight(int(0.8 * self.screen_height))
82
83
  # self.setMaximumHeight(int(0.8*self.screen_height))
83
84
 
84
85
  self.setAttribute(Qt.WA_DeleteOnClose)
@@ -119,7 +120,6 @@ class SignalAnnotator(QMainWindow, Styles):
119
120
 
120
121
  self.class_choice_cb.addItems(self.class_cols)
121
122
  self.class_choice_cb.currentIndexChanged.connect(self.compute_status_and_colors)
122
- self.class_choice_cb.setCurrentIndex(0)
123
123
 
124
124
  class_hbox.addWidget(self.class_choice_cb, 70)
125
125
 
@@ -346,6 +346,8 @@ class SignalAnnotator(QMainWindow, Styles):
346
346
  main_layout.addLayout(self.right_panel, 65)
347
347
  self.button_widget.adjustSize()
348
348
 
349
+ self.compute_status_and_colors(0)
350
+
349
351
  self.setCentralWidget(self.button_widget)
350
352
  self.show()
351
353
 
@@ -462,6 +464,7 @@ class SignalAnnotator(QMainWindow, Styles):
462
464
  self.newClassWidget.close()
463
465
 
464
466
  def compute_status_and_colors(self, i):
467
+
465
468
  self.class_name = self.class_choice_cb.currentText()
466
469
  self.expected_status = 'status'
467
470
  suffix = self.class_name.replace('class', '').replace('_', '', 1)
@@ -474,11 +477,15 @@ class SignalAnnotator(QMainWindow, Styles):
474
477
  self.status_name = self.expected_status
475
478
 
476
479
  print('selection and expected names: ', self.class_name, self.expected_time, self.expected_status)
480
+ cols = list(self.df_tracks.columns)
477
481
 
478
- if self.time_name in self.df_tracks.columns and self.class_name in self.df_tracks.columns and not self.status_name in self.df_tracks.columns:
482
+ if self.time_name in cols and self.class_name in cols and not self.status_name in cols:
479
483
  # only create the status column if it does not exist to not erase static classification results
480
484
  self.make_status_column()
481
- elif self.time_name in self.df_tracks.columns and self.class_name in self.df_tracks.columns:
485
+ elif self.time_name in cols and self.class_name in cols and self.df_tracks[self.status_name].isnull().all():
486
+ print('this is the case!', )
487
+ self.make_status_column()
488
+ elif self.time_name in cols and self.class_name in cols:
482
489
  # all good, do nothing
483
490
  pass
484
491
  else:
@@ -855,7 +862,7 @@ class SignalAnnotator(QMainWindow, Styles):
855
862
  self.cell_ax.legend()
856
863
  self.cell_fcanvas.canvas.draw()
857
864
  except Exception as e:
858
- print(f"{e=}")
865
+ print(f"Plot signals: {e=}")
859
866
 
860
867
  def extract_scatter_from_trajectories(self):
861
868
 
@@ -1109,7 +1116,7 @@ class SignalAnnotator(QMainWindow, Styles):
1109
1116
  if len(min_values) > 0:
1110
1117
  self.cell_ax.set_ylim(np.amin(min_values), np.amax(max_values))
1111
1118
  except Exception as e:
1112
- print(e)
1119
+ print('Ylim error:',e)
1113
1120
 
1114
1121
  def draw_frame(self, framedata):
1115
1122
 
@@ -1301,7 +1308,9 @@ class SignalAnnotator(QMainWindow, Styles):
1301
1308
 
1302
1309
 
1303
1310
  class MeasureAnnotator(SignalAnnotator):
1311
+
1304
1312
  def __init__(self, parent_window=None):
1313
+
1305
1314
  QMainWindow.__init__(self)
1306
1315
  self.parent_window = parent_window
1307
1316
  self.setWindowTitle("Signal annotator")
@@ -1315,11 +1324,11 @@ class MeasureAnnotator(SignalAnnotator):
1315
1324
  self.int_validator = QIntValidator()
1316
1325
  self.current_alpha=0.5
1317
1326
  if self.mode == "targets":
1318
- self.instructions_path = self.exp_dir + "configs/signal_annotator_config_targets.json"
1319
- self.trajectories_path = self.pos + 'output/tables/trajectories_targets.csv'
1327
+ self.instructions_path = self.exp_dir + os.sep.join(['configs','signal_annotator_config_targets.json'])
1328
+ self.trajectories_path = self.pos + os.sep.join(['output','tables','trajectories_targets.csv'])
1320
1329
  elif self.mode == "effectors":
1321
- self.instructions_path = self.exp_dir + "configs/signal_annotator_config_effectors.json"
1322
- self.trajectories_path = self.pos + 'output/tables/trajectories_effectors.csv'
1330
+ self.instructions_path = self.exp_dir + os.sep.join(['configs','signal_annotator_config_effectors.json'])
1331
+ self.trajectories_path = self.pos + os.sep.join(['output','tables','trajectories_effectors.csv'])
1323
1332
 
1324
1333
  self.screen_height = self.parent_window.parent_window.parent_window.screen_height
1325
1334
  self.screen_width = self.parent_window.parent_window.parent_window.screen_width
@@ -1330,8 +1339,13 @@ class MeasureAnnotator(SignalAnnotator):
1330
1339
  center_window(self)
1331
1340
 
1332
1341
  self.locate_stack()
1342
+
1333
1343
  data, properties, graph, labels, _ = load_napari_data(self.pos, prefix=None, population=self.mode,return_stack=False)
1334
- self.labels = relabel_segmentation(labels,data,properties)
1344
+ if data is not None:
1345
+ self.labels = relabel_segmentation(labels,data,properties)
1346
+ else:
1347
+ self.labels = labels
1348
+
1335
1349
  self.current_channel = 0
1336
1350
 
1337
1351
  self.locate_tracks()
@@ -1577,8 +1591,10 @@ class MeasureAnnotator(SignalAnnotator):
1577
1591
  self.class_choice_cb = QComboBox()
1578
1592
 
1579
1593
  cols = np.array(self.df_tracks.columns)
1580
- self.class_cols = np.array([c.startswith('group') for c in list(self.df_tracks.columns)])
1594
+ self.class_cols = np.array([c.startswith('group') or c.startswith('status') for c in list(self.df_tracks.columns)])
1581
1595
  self.class_cols = list(cols[self.class_cols])
1596
+ print(self.class_cols)
1597
+
1582
1598
  try:
1583
1599
  self.class_cols.remove('group_id')
1584
1600
  except Exception:
@@ -1711,6 +1727,14 @@ class MeasureAnnotator(SignalAnnotator):
1711
1727
  btn_hbox.addWidget(self.save_btn, 90)
1712
1728
  self.left_panel.addLayout(btn_hbox)
1713
1729
 
1730
+ self.export_btn = QPushButton('')
1731
+ self.export_btn.setStyleSheet(self.button_select_all)
1732
+ self.export_btn.clicked.connect(self.export_measurements)
1733
+ self.export_btn.setIcon(icon(MDI6.export, color="black"))
1734
+ self.export_btn.setIconSize(QSize(25, 25))
1735
+ btn_hbox.addWidget(self.export_btn, 10)
1736
+ self.left_panel.addLayout(btn_hbox)
1737
+
1714
1738
  # Animation
1715
1739
  animation_buttons_box = QHBoxLayout()
1716
1740
 
@@ -1810,6 +1834,28 @@ class MeasureAnnotator(SignalAnnotator):
1810
1834
  # del self.img
1811
1835
  gc.collect()
1812
1836
 
1837
+
1838
+ def export_measurements(self):
1839
+
1840
+ auto_dataset_name = self.pos.split(os.sep)[-4] + '_' + self.pos.split(os.sep)[-2] + f'_{str(self.current_frame).zfill(3)}' + f'_{self.status_name}.npy'
1841
+
1842
+ if self.normalized_signals:
1843
+ self.normalize_features_btn.click()
1844
+
1845
+ subdf = self.df_tracks.loc[self.df_tracks['FRAME']==self.current_frame,:]
1846
+ subdf['class'] = subdf[self.status_name]
1847
+ dico = subdf.to_dict('records')
1848
+
1849
+ pathsave = QFileDialog.getSaveFileName(self, "Select file name", self.exp_dir + auto_dataset_name, ".npy")[0]
1850
+ if pathsave != '':
1851
+ if not pathsave.endswith(".npy"):
1852
+ pathsave += ".npy"
1853
+ try:
1854
+ np.save(pathsave, dico)
1855
+ print(f'File successfully written in {pathsave}.')
1856
+ except Exception as e:
1857
+ print(f"Error {e}...")
1858
+
1813
1859
  def set_next_frame(self):
1814
1860
 
1815
1861
  self.current_frame = self.current_frame + 1
@@ -1887,13 +1933,17 @@ class MeasureAnnotator(SignalAnnotator):
1887
1933
 
1888
1934
  def give_cell_information(self):
1889
1935
 
1890
- cell_selected = f"cell: {self.track_of_interest}\n"
1891
- if 'TRACK_ID' in self.df_tracks.columns:
1892
- cell_status = f"phenotype: {self.df_tracks.loc[self.df_tracks['TRACK_ID'] == self.track_of_interest, self.status_name].to_numpy()[0]}\n"
1893
- else:
1894
- cell_status = f"phenotype: {self.df_tracks.loc[self.df_tracks['ID'] == self.track_of_interest, self.status_name].to_numpy()[0]}\n"
1895
- self.cell_info.setText(cell_selected + cell_status)
1896
-
1936
+ try:
1937
+ cell_selected = f"cell: {self.track_of_interest}\n"
1938
+ if 'TRACK_ID' in self.df_tracks.columns:
1939
+ cell_status = f"phenotype: {self.df_tracks.loc[self.df_tracks['TRACK_ID'] == self.track_of_interest, self.status_name].to_numpy()[0]}\n"
1940
+ else:
1941
+ cell_status = f"phenotype: {self.df_tracks.loc[self.df_tracks['ID'] == self.track_of_interest, self.status_name].to_numpy()[0]}\n"
1942
+ self.cell_info.setText(cell_selected + cell_status)
1943
+ except Exception as e:
1944
+ print('Cell info:',e)
1945
+ print(self.track_of_interest, self.status_name)
1946
+
1897
1947
  def create_new_event_class(self):
1898
1948
 
1899
1949
  # display qwidget to name the event
@@ -1978,8 +2028,14 @@ class MeasureAnnotator(SignalAnnotator):
1978
2028
  self.frame_lbl.setText(f'position: {self.framedata}')
1979
2029
  self.im.set_array(self.img)
1980
2030
  self.status_scatter.set_offsets(self.positions[self.framedata])
1981
- self.status_scatter.set_edgecolors(self.colors[self.framedata][:, 0])
2031
+ try:
2032
+ self.status_scatter.set_edgecolors(self.colors[self.framedata][:, 0])
2033
+ except Exception as e:
2034
+ print('L1993: ',e)
2035
+
1982
2036
  self.current_label = self.labels[self.current_frame]
2037
+ self.current_label = contour_of_instance_segmentation(self.current_label, 5)
2038
+
1983
2039
  self.im_mask.remove()
1984
2040
  self.im_mask = self.ax.imshow(np.ma.masked_where(self.current_label == 0, self.current_label),
1985
2041
  cmap='viridis', interpolation='none',alpha=self.current_alpha,vmin=0,vmax=np.nanmax(self.labels.flatten()))
@@ -2108,9 +2164,9 @@ class MeasureAnnotator(SignalAnnotator):
2108
2164
 
2109
2165
  self.extract_scatter_from_trajectories()
2110
2166
  if 'TRACK_ID' in self.df_tracks.columns:
2111
- self.track_of_interest = self.df_tracks['TRACK_ID'].min()
2167
+ self.track_of_interest = self.df_tracks.dropna(subset='TRACK_ID')['TRACK_ID'].min()
2112
2168
  else:
2113
- self.track_of_interest = self.df_tracks['ID'].min()
2169
+ self.track_of_interest = self.df_tracks.dropna(subset='ID')['ID'].min()
2114
2170
 
2115
2171
  self.loc_t = []
2116
2172
  self.loc_idx = []
@@ -2172,9 +2228,13 @@ class MeasureAnnotator(SignalAnnotator):
2172
2228
  """
2173
2229
  self.current_frame = self.frame_slider.value()
2174
2230
  self.reload_frame()
2175
- if 'ID' in self.df_tracks.columns:
2231
+ if 'TRACK_ID' in list(self.df_tracks.columns):
2232
+ pass
2233
+ elif 'ID' in list(self.df_tracks.columns):
2234
+ print('ID in cols... change class of interest... ')
2176
2235
  self.track_of_interest = self.df_tracks[self.df_tracks['FRAME'] == self.current_frame]['ID'].min()
2177
2236
  self.modify()
2237
+
2178
2238
  self.draw_frame(self.current_frame)
2179
2239
  self.fcanvas.canvas.draw()
2180
2240
  self.plot_signals()
@@ -2302,7 +2362,7 @@ class MeasureAnnotator(SignalAnnotator):
2302
2362
  try:
2303
2363
  self.selection.pop(0)
2304
2364
  except Exception as e:
2305
- print(e)
2365
+ print('Cancel selection: ',e)
2306
2366
 
2307
2367
  try:
2308
2368
  for k, (t, idx) in enumerate(zip(self.loc_t, self.loc_idx)):
@@ -12,6 +12,8 @@ import matplotlib.cm as mcm
12
12
  import os
13
13
  from celldetective.gui import Styles
14
14
  from superqt import QColormapComboBox, QLabeledSlider, QSearchableComboBox
15
+ from superqt.fonticon import icon
16
+ from fonticon_mdi6 import MDI6
15
17
  from math import floor
16
18
 
17
19
  from matplotlib import colormaps
@@ -63,15 +65,101 @@ class QueryWidget(QWidget):
63
65
 
64
66
  def filter_table(self):
65
67
  try:
66
- query_text = self.query_le.text().replace('class', '`class`')
68
+ query_text = self.query_le.text() #.replace('class', '`class`')
67
69
  tab = self.parent_window.data.query(query_text)
68
- self.subtable = TableUI(tab, query_text, plot_mode="scatter")
70
+ self.subtable = TableUI(tab, query_text, plot_mode="static")
69
71
  self.subtable.show()
70
72
  self.close()
71
73
  except Exception as e:
72
74
  print(e)
73
75
  return None
74
76
 
77
+
78
+ class MergeOneHotWidget(QWidget, Styles):
79
+
80
+ def __init__(self, parent_window, selected_columns=None):
81
+
82
+ super().__init__()
83
+ self.parent_window = parent_window
84
+ self.selected_columns = selected_columns
85
+
86
+ self.setWindowTitle("Merge one-hot encoded columns...")
87
+ # Create the QComboBox and add some items
88
+ center_window(self)
89
+
90
+ self.layout = QVBoxLayout(self)
91
+ self.layout.setContentsMargins(30,30,30,30)
92
+
93
+ if self.selected_columns is not None:
94
+ n_cols = len(self.selected_columns)
95
+ else:
96
+ n_cols = 2
97
+
98
+ name_hbox = QHBoxLayout()
99
+ name_hbox.addWidget(QLabel('New categorical column: '), 33)
100
+ self.new_col_le = QLineEdit()
101
+ self.new_col_le.setText('categorical_')
102
+ self.new_col_le.textChanged.connect(self.allow_merge)
103
+ name_hbox.addWidget(self.new_col_le, 66)
104
+ self.layout.addLayout(name_hbox)
105
+
106
+
107
+ self.layout.addWidget(QLabel('Source columns: '))
108
+
109
+ self.cbs = [QSearchableComboBox() for i in range(n_cols)]
110
+ self.cbs_layout = QVBoxLayout()
111
+
112
+ for i in range(n_cols):
113
+ lay = QHBoxLayout()
114
+ lay.addWidget(QLabel(f'column {i}: '), 33)
115
+ self.cbs[i].addItems(['--']+list(self.parent_window.data.columns))
116
+ if self.selected_columns is not None:
117
+ self.cbs[i].setCurrentText(self.selected_columns[i])
118
+ lay.addWidget(self.cbs[i], 66)
119
+ self.cbs_layout.addLayout(lay)
120
+
121
+ self.layout.addLayout(self.cbs_layout)
122
+
123
+ hbox = QHBoxLayout()
124
+ self.add_col_btn = QPushButton('Add column')
125
+ self.add_col_btn.clicked.connect(self.add_col)
126
+ self.add_col_btn.setStyleSheet(self.button_add)
127
+ self.add_col_btn.setIcon(icon(MDI6.plus,color="black"))
128
+
129
+ hbox.addWidget(QLabel(''), 50)
130
+ hbox.addWidget(self.add_col_btn, 50, alignment=Qt.AlignRight)
131
+ self.layout.addLayout(hbox)
132
+
133
+ self.submit_btn = QPushButton('Merge')
134
+ self.submit_btn.setStyleSheet(self.button_style_sheet)
135
+ self.submit_btn.clicked.connect(self.merge_cols)
136
+ self.layout.addWidget(self.submit_btn, 30)
137
+
138
+ self.setAttribute(Qt.WA_DeleteOnClose)
139
+
140
+ def add_col(self):
141
+ self.cbs.append(QSearchableComboBox())
142
+ self.cbs[-1].addItems(['--']+list(self.parent_window.data.columns))
143
+ lay = QHBoxLayout()
144
+ lay.addWidget(QLabel(f'column {len(self.cbs)-1}: '), 33)
145
+ lay.addWidget(self.cbs[-1], 66)
146
+ self.cbs_layout.addLayout(lay)
147
+
148
+ def merge_cols(self):
149
+
150
+ self.parent_window.data[self.new_col_le.text()] = self.parent_window.data.loc[:,list(self.selected_columns)].idxmax(axis=1)
151
+ self.parent_window.model = PandasModel(self.parent_window.data)
152
+ self.parent_window.table_view.setModel(self.parent_window.model)
153
+ self.close()
154
+
155
+ def allow_merge(self):
156
+
157
+ if self.new_col_le.text()=='':
158
+ self.submit_btn.setEnabled(False)
159
+ else:
160
+ self.submit_btn.setEnabled(True)
161
+
162
+
75
163
  class DifferentiateColWidget(QWidget, Styles):
76
164
 
77
165
  def __init__(self, parent_window, column=None):
@@ -180,7 +268,6 @@ class RenameColWidget(QWidget):
180
268
  old_name = self.column
181
269
  new_name = self.new_col_name.text()
182
270
  self.parent_window.data = self.parent_window.data.rename(columns={old_name: new_name})
183
- print(self.parent.data.columns)
184
271
 
185
272
  self.parent_window.model = PandasModel(self.parent_window.data)
186
273
  self.parent_window.table_view.setModel(self.parent_window.model)
@@ -264,7 +351,12 @@ class TableUI(QMainWindow, Styles):
264
351
  self.derivative_action = QAction('&Differentiate...', self)
265
352
  self.derivative_action.triggered.connect(self.differenciate_selected_feature)
266
353
  self.derivative_action.setShortcut("Ctrl+D")
267
- self.mathMenu.addAction(self.derivative_action)
354
+ self.mathMenu.addAction(self.derivative_action)
355
+
356
+ self.onehot_action = QAction('&One hot to categorical...', self)
357
+ self.onehot_action.triggered.connect(self.transform_one_hot_cols_to_categorical)
358
+ #self.onehot_action.setShortcut("Ctrl+D")
359
+ self.mathMenu.addAction(self.onehot_action)
268
360
 
269
361
  def delete_columns(self):
270
362
 
@@ -334,6 +426,19 @@ class TableUI(QMainWindow, Styles):
334
426
  self.diffWidget = DifferentiateColWidget(self, selected_col)
335
427
  self.diffWidget.show()
336
428
 
429
+ def transform_one_hot_cols_to_categorical(self):
430
+
431
+ x = self.table_view.selectedIndexes()
432
+ col_idx = np.unique(np.array([l.column() for l in x]))
433
+ if list(col_idx):
434
+ cols = np.array(list(self.data.columns))
435
+ selected_cols = cols[col_idx]
436
+ else:
437
+ selected_cols = None
438
+
439
+ self.mergewidget = MergeOneHotWidget(self, selected_columns=selected_cols)
440
+ self.mergewidget.show()
441
+
337
442
 
338
443
  def groupby_time_table(self):
339
444
 
@@ -477,16 +582,20 @@ class TableUI(QMainWindow, Styles):
477
582
  layout.addWidget(QLabel('Representations: '))
478
583
  self.hist_check = QCheckBox('histogram')
479
584
  self.kde_check = QCheckBox('KDE plot')
585
+ self.count_check = QCheckBox('countplot')
480
586
  self.ecdf_check = QCheckBox('ECDF plot')
587
+ self.scat_check = QCheckBox('scatter plot')
481
588
  self.swarm_check = QCheckBox('swarm')
482
589
  self.violin_check = QCheckBox('violin')
483
590
  self.strip_check = QCheckBox('strip')
484
- self.box_check = QCheckBox('Boxplot')
485
- self.boxenplot_check = QCheckBox('Boxenplot')
591
+ self.box_check = QCheckBox('boxplot')
592
+ self.boxenplot_check = QCheckBox('boxenplot')
486
593
 
487
594
  layout.addWidget(self.hist_check)
488
595
  layout.addWidget(self.kde_check)
596
+ layout.addWidget(self.count_check)
489
597
  layout.addWidget(self.ecdf_check)
598
+ layout.addWidget(self.scat_check)
490
599
  layout.addWidget(self.swarm_check)
491
600
  layout.addWidget(self.violin_check)
492
601
  layout.addWidget(self.strip_check)
@@ -496,16 +605,38 @@ class TableUI(QMainWindow, Styles):
496
605
  self.x_cb = QSearchableComboBox()
497
606
  self.x_cb.addItems(['--']+list(self.data.columns))
498
607
 
608
+ self.y_cb = QSearchableComboBox()
609
+ self.y_cb.addItems(['--']+list(self.data.columns))
610
+
499
611
  self.hue_cb = QSearchableComboBox()
500
612
  self.hue_cb.addItems(['--']+list(self.data.columns))
501
613
  idx = self.hue_cb.findText('--')
614
+ self.hue_cb.setCurrentIndex(idx)
615
+
616
+ # Set selected column
617
+
618
+ try:
619
+ x = self.table_view.selectedIndexes()
620
+ col_idx = np.array([l.column() for l in x])
621
+ row_idx = np.array([l.row() for l in x])
622
+ column_names = self.data.columns
623
+ unique_cols = np.unique(col_idx)[0]
624
+ y = column_names[unique_cols]
625
+ idx = self.y_cb.findText(y)
626
+ self.y_cb.setCurrentIndex(idx)
627
+ except:
628
+ pass
502
629
 
503
- self.x_cb.findText('--')
504
630
  hbox = QHBoxLayout()
505
631
  hbox.addWidget(QLabel('x: '), 33)
506
632
  hbox.addWidget(self.x_cb, 66)
507
633
  layout.addLayout(hbox)
508
634
 
635
+ hbox = QHBoxLayout()
636
+ hbox.addWidget(QLabel('y: '), 33)
637
+ hbox.addWidget(self.y_cb, 66)
638
+ layout.addLayout(hbox)
639
+
509
640
  hbox = QHBoxLayout()
510
641
  hbox.addWidget(QLabel('hue: '), 33)
511
642
  hbox.addWidget(self.hue_cb, 66)
@@ -539,18 +670,10 @@ class TableUI(QMainWindow, Styles):
539
670
  self.x_option = True
540
671
  self.x = self.x_cb.currentText()
541
672
 
542
- x = self.table_view.selectedIndexes()
543
- col_idx = np.array([l.column() for l in x])
544
- row_idx = np.array([l.row() for l in x])
545
- column_names = self.data.columns
546
- unique_cols = np.unique(col_idx)[0]
547
-
548
673
  self.fig, self.ax = plt.subplots(1,1,figsize=(4,3))
549
674
  self.plot1dWindow = FigureCanvas(self.fig, title="scatter")
550
675
  self.ax.clear()
551
- row_idx_i = row_idx[np.where(col_idx==unique_cols)[0]]
552
- y = self.data.iloc[row_idx_i, unique_cols]
553
-
676
+
554
677
  cmap = getattr(mcm, self.cmap_cb.currentText())
555
678
 
556
679
  try:
@@ -562,58 +685,76 @@ class TableUI(QMainWindow, Styles):
562
685
  if self.hue_cb.currentText()=='--':
563
686
  hue_variable = None
564
687
 
565
- #for w,well_group in self.data.groupby('well_index'):
688
+ if self.y_cb.currentText()=='--':
689
+ self.y = None
690
+ else:
691
+ self.y = self.y_cb.currentText()
692
+
693
+ if self.x_cb.currentText()=='--':
694
+ self.x = None
695
+ else:
696
+ self.x = self.x_cb.currentText()
566
697
 
567
698
  legend=True
568
699
  if self.hist_check.isChecked():
569
- sns.histplot(data=self.data, x=column_names[unique_cols], hue=hue_variable, legend=legend, ax=self.ax, palette=colors, kde=True, common_norm=False, stat='density')
700
+ sns.histplot(data=self.data, x=self.x, hue=hue_variable, legend=legend, ax=self.ax, palette=colors, kde=True, common_norm=False, stat='density')
570
701
  legend = False
571
702
  if self.kde_check.isChecked():
572
- sns.kdeplot(data=self.data, x=column_names[unique_cols], hue=hue_variable, legend=legend, ax=self.ax, palette=colors, cut=0)
703
+ sns.kdeplot(data=self.data, x=self.x, hue=hue_variable, legend=legend, ax=self.ax, palette=colors, cut=0)
704
+ legend = False
705
+ if self.count_check.isChecked():
706
+ sns.countplot(data=self.data, x=self.x, hue=hue_variable, legend=legend, ax=self.ax, palette=colors)
573
707
  legend = False
574
-
575
708
  if self.ecdf_check.isChecked():
576
- sns.ecdfplot(data=self.data, x=column_names[unique_cols], hue=hue_variable, legend=legend, ax=self.ax, palette=colors)
709
+ sns.ecdfplot(data=self.data, x=self.x, hue=hue_variable, legend=legend, ax=self.ax, palette=colors)
577
710
  legend = False
711
+
712
+ if self.scat_check.isChecked():
713
+ if self.x_option:
714
+ sns.scatterplot(data=self.data, x=self.x,y=self.y, hue=hue_variable,legend=legend, ax=self.ax, palette=colors)
715
+ legend = False
716
+ else:
717
+ print('please provide a -x variable...')
718
+ pass
578
719
 
579
720
  if self.swarm_check.isChecked():
580
721
  if self.x_option:
581
- sns.swarmplot(data=self.data, x=self.x,y=column_names[unique_cols],dodge=True, hue=hue_variable,legend=legend, ax=self.ax, palette=colors)
722
+ sns.swarmplot(data=self.data, x=self.x,y=self.y,dodge=True, hue=hue_variable,legend=legend, ax=self.ax, palette=colors)
582
723
  legend = False
583
724
  else:
584
- sns.swarmplot(data=self.data, y=column_names[unique_cols],dodge=True, hue=hue_variable,legend=legend, ax=self.ax, palette=colors)
725
+ sns.swarmplot(data=self.data, y=self.y,dodge=True, hue=hue_variable,legend=legend, ax=self.ax, palette=colors)
585
726
  legend = False
586
727
 
587
728
  if self.violin_check.isChecked():
588
729
  if self.x_option:
589
- sns.stripplot(data=self.data,x=self.x, y=column_names[unique_cols],dodge=True, ax=self.ax, hue=hue_variable, legend=legend, palette=colors)
730
+ sns.stripplot(data=self.data,x=self.x, y=self.y,dodge=True, ax=self.ax, hue=hue_variable, legend=legend, palette=colors)
590
731
  legend = False
591
732
  else:
592
- sns.violinplot(data=self.data, y=column_names[unique_cols],dodge=True, hue=hue_variable,legend=legend, ax=self.ax, palette=colors, cut=0)
733
+ sns.violinplot(data=self.data, y=self.y,dodge=True, hue=hue_variable,legend=legend, ax=self.ax, palette=colors, cut=0)
593
734
  legend = False
594
735
 
595
736
  if self.box_check.isChecked():
596
737
  if self.x_option:
597
- sns.boxplot(data=self.data, x=self.x, y=column_names[unique_cols],dodge=True, hue=hue_variable,legend=legend, ax=self.ax, fill=False,palette=colors, linewidth=2,)
738
+ sns.boxplot(data=self.data, x=self.x, y=self.y,dodge=True, hue=hue_variable,legend=legend, ax=self.ax, fill=False,palette=colors, linewidth=2,)
598
739
  legend = False
599
740
  else:
600
- sns.boxplot(data=self.data, y=column_names[unique_cols],dodge=True, hue=hue_variable,legend=legend, ax=self.ax, fill=False,palette=colors, linewidth=2,)
741
+ sns.boxplot(data=self.data, y=self.y,dodge=True, hue=hue_variable,legend=legend, ax=self.ax, fill=False,palette=colors, linewidth=2,)
601
742
  legend = False
602
743
 
603
744
  if self.boxenplot_check.isChecked():
604
745
  if self.x_option:
605
- sns.boxenplot(data=self.data, x = self.x, y=column_names[unique_cols],dodge=True, hue=hue_variable,legend=legend, ax=self.ax, fill=False,palette=colors, linewidth=2,)
746
+ sns.boxenplot(data=self.data, x=self.x, y=self.y,dodge=True, hue=hue_variable,legend=legend, ax=self.ax, fill=False,palette=colors, linewidth=2,)
606
747
  legend = False
607
748
  else:
608
- sns.boxenplot(data=self.data, y=column_names[unique_cols],dodge=True, hue=hue_variable,legend=legend, ax=self.ax, fill=False,palette=colors, linewidth=2,)
749
+ sns.boxenplot(data=self.data, y=self.y,dodge=True, hue=hue_variable,legend=legend, ax=self.ax, fill=False,palette=colors, linewidth=2,)
609
750
  legend = False
610
751
 
611
752
  if self.strip_check.isChecked():
612
753
  if self.x_option:
613
- sns.stripplot(data=self.data, x = self.x, y=column_names[unique_cols],dodge=True, ax=self.ax, hue=hue_variable, legend=legend, palette=colors)
754
+ sns.stripplot(data=self.data, x = self.x, y=self.y,dodge=True, ax=self.ax, hue=hue_variable, legend=legend, palette=colors)
614
755
  legend = False
615
756
  else:
616
- sns.stripplot(data=self.data, y=column_names[unique_cols],dodge=True, ax=self.ax, hue=hue_variable, legend=legend, palette=colors)
757
+ sns.stripplot(data=self.data, y=self.y,dodge=True, ax=self.ax, hue=hue_variable, legend=legend, palette=colors)
617
758
  legend = False
618
759
 
619
760
  plt.tight_layout()
@@ -762,42 +903,10 @@ class TableUI(QMainWindow, Styles):
762
903
  column_names = self.data.columns
763
904
  unique_cols = np.unique(col_idx)
764
905
 
765
- if len(unique_cols)==1:
766
- # 1D plot
767
- # Open widget to set 1D data representations
906
+ if len(unique_cols)==1 or len(unique_cols)==0:
768
907
  self.set_1D_plot_params()
769
908
 
770
-
771
-
772
- # x = self.table_view.selectedIndexes()
773
- # col_idx = np.array([l.column() for l in x])
774
- # row_idx = np.array([l.row() for l in x])
775
- # column_names = self.data.columns
776
- # unique_cols = np.unique(col_idx)[0]
777
-
778
- # self.fig, self.ax = plt.subplots(1,1,figsize=(4,3))
779
- # self.histogram_window = FigureCanvas(self.fig, title="scatter")
780
- # self.ax.clear()
781
- # row_idx_i = row_idx[np.where(col_idx==unique_cols)[0]]
782
- # y = self.data.iloc[row_idx_i, unique_cols]
783
-
784
- # colors = [viridis(i / len(self.data['well_index'].unique())) for i in range(len(self.data['well_index'].unique()))]
785
- # #for w,well_group in self.data.groupby('well_index'):
786
- # sns.boxplot(data=self.data, y=column_names[unique_cols],dodge=True, hue='well_index',legend=False, ax=self.ax, fill=False,palette=colors, linewidth=2,)
787
- # sns.stripplot(data=self.data, y=column_names[unique_cols],dodge=True, ax=self.ax, hue='well_index', legend=False, palette=colors)
788
- # # sns.kdeplot(data=self.data, x=column_names[unique_cols], hue='well_index', ax=self.ax, fill=False,common_norm=False, palette=colors, alpha=.5, linewidth=2,)
789
- # # for k,(w,well_group) in enumerate(self.data.groupby('well_index')):
790
- # # self.ax.hist(well_group[column_names[unique_cols]],label=w, density=True, alpha=0.5, color=colors[k])
791
- # #self.ax.legend()
792
- # self.ax.set_xlabel(column_names[unique_cols])
793
- # plt.tight_layout()
794
- # self.fig.set_facecolor('none') # or 'None'
795
- # self.fig.canvas.setStyleSheet("background-color: transparent;")
796
- # self.histogram_window.canvas.draw()
797
- # self.histogram_window.show()
798
-
799
-
800
- elif len(unique_cols) == 2:
909
+ if len(unique_cols) == 2:
801
910
 
802
911
  print("two columns, plot mode")
803
912
  x1 = self.test_bool(self.data.iloc[row_idx, unique_cols[0]])
@@ -396,7 +396,7 @@ class ThresholdedStackVisualizer(StackVisualizer):
396
396
  # Compute the mask based on the threshold value
397
397
  self.preprocess_image()
398
398
  edge = estimate_unreliable_edge(self.preprocessing)
399
- self.mask = threshold_image(self.processed_image, threshold_value, 1.0E06, foreground_value=1, edge_exclusion=edge).astype(int)
399
+ self.mask = threshold_image(self.processed_image, threshold_value, np.inf, foreground_value=1, edge_exclusion=edge).astype(int)
400
400
 
401
401
  def preprocess_image(self):
402
402
  # Preprocess the image before thresholding