celldetective 1.0.2__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 (66) hide show
  1. celldetective/__init__.py +2 -0
  2. celldetective/__main__.py +432 -0
  3. celldetective/datasets/segmentation_annotations/blank +0 -0
  4. celldetective/datasets/signal_annotations/blank +0 -0
  5. celldetective/events.py +149 -0
  6. celldetective/extra_properties.py +100 -0
  7. celldetective/filters.py +89 -0
  8. celldetective/gui/__init__.py +20 -0
  9. celldetective/gui/about.py +44 -0
  10. celldetective/gui/analyze_block.py +563 -0
  11. celldetective/gui/btrack_options.py +898 -0
  12. celldetective/gui/classifier_widget.py +386 -0
  13. celldetective/gui/configure_new_exp.py +532 -0
  14. celldetective/gui/control_panel.py +438 -0
  15. celldetective/gui/gui_utils.py +495 -0
  16. celldetective/gui/json_readers.py +113 -0
  17. celldetective/gui/measurement_options.py +1425 -0
  18. celldetective/gui/neighborhood_options.py +452 -0
  19. celldetective/gui/plot_signals_ui.py +1042 -0
  20. celldetective/gui/process_block.py +1055 -0
  21. celldetective/gui/retrain_segmentation_model_options.py +706 -0
  22. celldetective/gui/retrain_signal_model_options.py +643 -0
  23. celldetective/gui/seg_model_loader.py +460 -0
  24. celldetective/gui/signal_annotator.py +2388 -0
  25. celldetective/gui/signal_annotator_options.py +340 -0
  26. celldetective/gui/styles.py +217 -0
  27. celldetective/gui/survival_ui.py +903 -0
  28. celldetective/gui/tableUI.py +608 -0
  29. celldetective/gui/thresholds_gui.py +1300 -0
  30. celldetective/icons/logo-large.png +0 -0
  31. celldetective/icons/logo.png +0 -0
  32. celldetective/icons/signals_icon.png +0 -0
  33. celldetective/icons/splash-test.png +0 -0
  34. celldetective/icons/splash.png +0 -0
  35. celldetective/icons/splash0.png +0 -0
  36. celldetective/icons/survival2.png +0 -0
  37. celldetective/icons/vignette_signals2.png +0 -0
  38. celldetective/icons/vignette_signals2.svg +114 -0
  39. celldetective/io.py +2050 -0
  40. celldetective/links/zenodo.json +561 -0
  41. celldetective/measure.py +1258 -0
  42. celldetective/models/segmentation_effectors/blank +0 -0
  43. celldetective/models/segmentation_generic/blank +0 -0
  44. celldetective/models/segmentation_targets/blank +0 -0
  45. celldetective/models/signal_detection/blank +0 -0
  46. celldetective/models/tracking_configs/mcf7.json +68 -0
  47. celldetective/models/tracking_configs/ricm.json +203 -0
  48. celldetective/models/tracking_configs/ricm2.json +203 -0
  49. celldetective/neighborhood.py +717 -0
  50. celldetective/scripts/analyze_signals.py +51 -0
  51. celldetective/scripts/measure_cells.py +275 -0
  52. celldetective/scripts/segment_cells.py +212 -0
  53. celldetective/scripts/segment_cells_thresholds.py +140 -0
  54. celldetective/scripts/track_cells.py +206 -0
  55. celldetective/scripts/train_segmentation_model.py +246 -0
  56. celldetective/scripts/train_signal_model.py +49 -0
  57. celldetective/segmentation.py +712 -0
  58. celldetective/signals.py +2826 -0
  59. celldetective/tracking.py +974 -0
  60. celldetective/utils.py +1681 -0
  61. celldetective-1.0.2.dist-info/LICENSE +674 -0
  62. celldetective-1.0.2.dist-info/METADATA +192 -0
  63. celldetective-1.0.2.dist-info/RECORD +66 -0
  64. celldetective-1.0.2.dist-info/WHEEL +5 -0
  65. celldetective-1.0.2.dist-info/entry_points.txt +2 -0
  66. celldetective-1.0.2.dist-info/top_level.txt +1 -0
@@ -0,0 +1,608 @@
1
+ from PyQt5.QtWidgets import QMainWindow, QTableView, QAction, QMenu,QFileDialog, QLineEdit, QHBoxLayout, QWidget, QPushButton, QVBoxLayout, QComboBox, QLabel, QCheckBox, QMessageBox
2
+ from PyQt5.QtCore import Qt, QAbstractTableModel
3
+ import pandas as pd
4
+ import matplotlib.pyplot as plt
5
+ from matplotlib.cm import viridis
6
+ plt.rcParams['svg.fonttype'] = 'none'
7
+ from celldetective.gui.gui_utils import FigureCanvas, center_window
8
+ import numpy as np
9
+ import seaborn as sns
10
+ import matplotlib.cm as mcm
11
+ import os
12
+
13
+ class PandasModel(QAbstractTableModel):
14
+
15
+ def __init__(self, data):
16
+ QAbstractTableModel.__init__(self)
17
+ self._data = data
18
+
19
+ def rowCount(self, parent=None):
20
+ return self._data.shape[0]
21
+
22
+ def columnCount(self, parent=None):
23
+ return self._data.shape[1]
24
+
25
+ def data(self, index, role=Qt.DisplayRole):
26
+ if index.isValid():
27
+ if role == Qt.DisplayRole:
28
+ return str(self._data.iloc[index.row(), index.column()])
29
+ return None
30
+
31
+ def headerData(self, col, orientation, role):
32
+ if orientation == Qt.Horizontal and role == Qt.DisplayRole:
33
+ return self._data.columns[col]
34
+ return None
35
+
36
+
37
+ class QueryWidget(QWidget):
38
+
39
+ def __init__(self, parent):
40
+
41
+ super().__init__()
42
+ self.parent = parent
43
+ self.setWindowTitle("Filter table")
44
+ # Create the QComboBox and add some items
45
+ center_window(self)
46
+
47
+
48
+ layout = QHBoxLayout(self)
49
+ layout.setContentsMargins(30,30,30,30)
50
+ self.query_le = QLineEdit()
51
+ layout.addWidget(self.query_le, 70)
52
+
53
+ self.submit_btn = QPushButton('submit')
54
+ self.submit_btn.clicked.connect(self.filter_table)
55
+ layout.addWidget(self.submit_btn, 30)
56
+
57
+ def filter_table(self):
58
+ try:
59
+ query_text = self.query_le.text().replace('class', '`class`')
60
+ tab = self.parent.data.query(query_text)
61
+ self.subtable = TableUI(tab, query_text, plot_mode="scatter")
62
+ self.subtable.show()
63
+ self.close()
64
+ except Exception as e:
65
+ print(e)
66
+ return None
67
+
68
+ class RenameColWidget(QWidget):
69
+
70
+ def __init__(self, parent, column=None):
71
+
72
+ super().__init__()
73
+ self.parent = parent
74
+ self.column = column
75
+ if self.column is None:
76
+ self.column = ''
77
+
78
+ self.setWindowTitle("Rename column")
79
+ # Create the QComboBox and add some items
80
+ center_window(self)
81
+
82
+ layout = QHBoxLayout(self)
83
+ layout.setContentsMargins(30,30,30,30)
84
+ self.new_col_name = QLineEdit()
85
+ self.new_col_name.setText(self.column)
86
+ layout.addWidget(self.new_col_name, 70)
87
+
88
+ self.submit_btn = QPushButton('rename')
89
+ self.submit_btn.clicked.connect(self.rename_col)
90
+ layout.addWidget(self.submit_btn, 30)
91
+
92
+ def rename_col(self):
93
+
94
+ old_name = self.column
95
+ new_name = self.new_col_name.text()
96
+ self.parent.data = self.parent.data.rename(columns={old_name: new_name})
97
+ print(self.parent.data.columns)
98
+
99
+ self.parent.model = PandasModel(self.parent.data)
100
+ self.parent.table_view.setModel(self.parent.model)
101
+ self.close()
102
+
103
+
104
+ class TableUI(QMainWindow):
105
+ def __init__(self, data, title, population='targets',plot_mode="plot_track_signals", *args, **kwargs):
106
+
107
+ QMainWindow.__init__(self, *args, **kwargs)
108
+
109
+ self.setWindowTitle(title)
110
+ self.setGeometry(100,100,1000,400)
111
+ center_window(self)
112
+ self.title = title
113
+ self.plot_mode = plot_mode
114
+ self.population = population
115
+ self.numerics = ['int16', 'int32', 'int64', 'float16', 'float32', 'float64']
116
+
117
+ self._createMenuBar()
118
+ self._createActions()
119
+
120
+ self.table_view = QTableView(self)
121
+ self.setCentralWidget(self.table_view)
122
+
123
+ # Set the model for the table view
124
+ self.data = data
125
+
126
+ self.model = PandasModel(data)
127
+ self.table_view.setModel(self.model)
128
+ self.table_view.resizeColumnsToContents()
129
+
130
+ def _createActions(self):
131
+
132
+ self.save_as = QAction("&Save as...", self)
133
+ self.save_as.triggered.connect(self.save_as_csv)
134
+ self.save_as.setShortcut("Ctrl+s")
135
+ self.fileMenu.addAction(self.save_as)
136
+
137
+ self.save_inplace = QAction("&Save inplace...", self)
138
+ self.save_inplace.triggered.connect(self.save_as_csv_inplace_per_pos)
139
+ #self.save_inplace.setShortcut("Ctrl+s")
140
+ self.fileMenu.addAction(self.save_inplace)
141
+
142
+ self.plot_action = QAction("&Plot...", self)
143
+ self.plot_action.triggered.connect(self.plot)
144
+ self.plot_action.setShortcut("Ctrl+p")
145
+ self.fileMenu.addAction(self.plot_action)
146
+
147
+ self.groupby_action = QAction("&Group by tracks...", self)
148
+ self.groupby_action.triggered.connect(self.set_projection_mode_tracks)
149
+ self.groupby_action.setShortcut("Ctrl+g")
150
+ self.fileMenu.addAction(self.groupby_action)
151
+
152
+ self.groupby_time_action = QAction("&Group by frames...", self)
153
+ self.groupby_time_action.triggered.connect(self.groupby_time_table)
154
+ self.groupby_time_action.setShortcut("Ctrl+t")
155
+ self.fileMenu.addAction(self.groupby_time_action)
156
+
157
+ self.query_action = QAction('Query...', self)
158
+ self.query_action.triggered.connect(self.perform_query)
159
+ self.fileMenu.addAction(self.query_action)
160
+
161
+ self.delete_action = QAction('&Delete...', self)
162
+ self.delete_action.triggered.connect(self.delete_columns)
163
+ self.delete_action.setShortcut(Qt.Key_Delete)
164
+ self.editMenu.addAction(self.delete_action)
165
+
166
+ self.rename_col_action = QAction('&Rename...', self)
167
+ self.rename_col_action.triggered.connect(self.rename_column)
168
+ #self.rename_col_action.setShortcut(Qt.Key_Delete)
169
+ self.editMenu.addAction(self.rename_col_action)
170
+
171
+ self.derivative_action = QAction('&Differentiate...', self)
172
+ self.derivative_action.triggered.connect(self.differenciate_selected_feature)
173
+ self.derivative_action.setShortcut("Ctrl+D")
174
+ self.mathMenu.addAction(self.derivative_action)
175
+
176
+ def delete_columns(self):
177
+
178
+ x = self.table_view.selectedIndexes()
179
+ col_idx = np.unique(np.array([l.column() for l in x]))
180
+ cols = np.array(list(self.data.columns))
181
+
182
+ msgBox = QMessageBox()
183
+ msgBox.setIcon(QMessageBox.Question)
184
+ msgBox.setText(f"You are about to delete columns {cols[col_idx]}... Do you want to proceed?")
185
+ msgBox.setWindowTitle("Info")
186
+ msgBox.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
187
+ returnValue = msgBox.exec()
188
+ if returnValue == QMessageBox.No:
189
+ return None
190
+
191
+ self.data = self.data.drop(list(cols[col_idx]),axis=1)
192
+ self.model = PandasModel(self.data)
193
+ self.table_view.setModel(self.model)
194
+
195
+ def rename_column(self):
196
+
197
+ x = self.table_view.selectedIndexes()
198
+ col_idx = np.unique(np.array([l.column() for l in x]))
199
+
200
+ if len(col_idx) == 0:
201
+ msgBox = QMessageBox()
202
+ msgBox.setIcon(QMessageBox.Question)
203
+ msgBox.setText(f"Please select a column first.")
204
+ msgBox.setWindowTitle("Warning")
205
+ msgBox.setStandardButtons(QMessageBox.Ok)
206
+ returnValue = msgBox.exec()
207
+ if returnValue == QMessageBox.Ok:
208
+ return None
209
+ else:
210
+ return None
211
+
212
+ cols = np.array(list(self.data.columns))
213
+ selected_col = str(cols[col_idx][0])
214
+
215
+ self.renameWidget = RenameColWidget(self, selected_col)
216
+ self.renameWidget.show()
217
+
218
+ def save_as_csv_inplace_per_pos(self):
219
+
220
+ print("Saving each table in its respective position folder...")
221
+ for pos,pos_group in self.data.groupby('position'):
222
+ pos_group.to_csv(pos+os.sep.join(['output', 'tables', f'trajectories_{self.population}.csv']), index=False)
223
+ print("Done...")
224
+
225
+
226
+
227
+ def differenciate_selected_feature(self):
228
+
229
+ # check only one col selected and assert is numerical
230
+ # open widget to select window parameters, directionality
231
+ # create new col
232
+ print('you want to differentiate? cool but I"m too tired to code it now...')
233
+ pass
234
+
235
+
236
+ def groupby_time_table(self):
237
+
238
+ """
239
+
240
+ Perform a time average across each track for all features
241
+
242
+ """
243
+
244
+ num_df = self.data.select_dtypes(include=self.numerics)
245
+
246
+ timeseries = num_df.groupby("FRAME").mean().copy()
247
+ timeseries["timeline"] = timeseries.index
248
+ self.subtable = TableUI(timeseries,"Group by frames", plot_mode="plot_timeseries")
249
+ self.subtable.show()
250
+
251
+ def perform_query(self):
252
+
253
+ """
254
+
255
+ Perform a time average across each track for all features
256
+
257
+ """
258
+ self.query_widget = QueryWidget(self)
259
+ self.query_widget.show()
260
+
261
+ # num_df = self.data.select_dtypes(include=self.numerics)
262
+
263
+ # timeseries = num_df.groupby("FRAME").mean().copy()
264
+ # timeseries["timeline"] = timeseries.index
265
+ # self.subtable = TableUI(timeseries,"Group by frames", plot_mode="plot_timeseries")
266
+ # self.subtable.show()
267
+
268
+ def set_projection_mode_tracks(self):
269
+
270
+ self.projectionWidget = QWidget()
271
+ self.projectionWidget.setWindowTitle('Set projection mode')
272
+
273
+ layout = QVBoxLayout()
274
+ self.projectionWidget.setLayout(layout)
275
+ self.projection_op_cb = QComboBox()
276
+ self.projection_op_cb.addItems(['mean','median','min','max', 'prod', 'sum'])
277
+ hbox = QHBoxLayout()
278
+ hbox.addWidget(QLabel('operation: '), 33)
279
+ hbox.addWidget(self.projection_op_cb, 66)
280
+ layout.addLayout(hbox)
281
+
282
+ self.set_projection_btn = QPushButton('set')
283
+ self.set_projection_btn.clicked.connect(self.set_proj_mode)
284
+ layout.addWidget(self.set_projection_btn)
285
+
286
+ self.projectionWidget.show()
287
+ center_window(self.projectionWidget)
288
+
289
+ def set_1D_plot_params(self):
290
+
291
+ self.plot1Dparams = QWidget()
292
+ self.plot1Dparams.setWindowTitle('Set 1D plot parameters')
293
+
294
+ layout = QVBoxLayout()
295
+ self.plot1Dparams.setLayout(layout)
296
+
297
+ layout.addWidget(QLabel('Representations: '))
298
+ self.hist_check = QCheckBox('histogram')
299
+ self.kde_check = QCheckBox('KDE plot')
300
+ self.ecdf_check = QCheckBox('ECDF plot')
301
+ self.swarm_check = QCheckBox('swarm')
302
+ self.violin_check = QCheckBox('violin')
303
+ self.strip_check = QCheckBox('strip')
304
+ self.box_check = QCheckBox('Boxplot')
305
+ self.boxenplot_check = QCheckBox('Boxenplot')
306
+
307
+ layout.addWidget(self.hist_check)
308
+ layout.addWidget(self.kde_check)
309
+ layout.addWidget(self.ecdf_check)
310
+ layout.addWidget(self.swarm_check)
311
+ layout.addWidget(self.violin_check)
312
+ layout.addWidget(self.strip_check)
313
+ layout.addWidget(self.box_check)
314
+ layout.addWidget(self.boxenplot_check)
315
+
316
+ self.hue_cb = QComboBox()
317
+ self.hue_cb.addItems(list(self.data.columns))
318
+ idx = self.hue_cb.findText('well_index')
319
+ self.hue_cb.setCurrentIndex(idx)
320
+ hbox = QHBoxLayout()
321
+ hbox.addWidget(QLabel('hue: '), 33)
322
+ hbox.addWidget(self.hue_cb, 66)
323
+ layout.addLayout(hbox)
324
+
325
+
326
+ self.cmap_cb = QComboBox()
327
+ self.cmap_cb.addItems(list(plt.colormaps()))
328
+ hbox = QHBoxLayout()
329
+ hbox.addWidget(QLabel('colormap: '), 33)
330
+ hbox.addWidget(self.cmap_cb, 66)
331
+ layout.addLayout(hbox)
332
+
333
+ self.plot1d_btn = QPushButton('set')
334
+ self.plot1d_btn.clicked.connect(self.plot1d)
335
+ layout.addWidget(self.plot1d_btn)
336
+
337
+ self.plot1Dparams.show()
338
+ center_window(self.plot1Dparams)
339
+
340
+
341
+ def plot1d(self):
342
+
343
+ x = self.table_view.selectedIndexes()
344
+ col_idx = np.array([l.column() for l in x])
345
+ row_idx = np.array([l.row() for l in x])
346
+ column_names = self.data.columns
347
+ unique_cols = np.unique(col_idx)[0]
348
+
349
+ self.fig, self.ax = plt.subplots(1,1,figsize=(4,3))
350
+ self.plot1dWindow = FigureCanvas(self.fig, title="scatter")
351
+ self.ax.clear()
352
+ row_idx_i = row_idx[np.where(col_idx==unique_cols)[0]]
353
+ y = self.data.iloc[row_idx_i, unique_cols]
354
+
355
+ cmap = getattr(mcm, self.cmap_cb.currentText())
356
+ hue_variable = self.hue_cb.currentText()
357
+
358
+ colors = [cmap(i / len(self.data[hue_variable].unique())) for i in range(len(self.data[hue_variable].unique()))]
359
+ #for w,well_group in self.data.groupby('well_index'):
360
+
361
+ legend=True
362
+ if self.hist_check.isChecked():
363
+ 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')
364
+ legend = False
365
+ if self.kde_check.isChecked():
366
+ sns.kdeplot(data=self.data, x=column_names[unique_cols], hue=hue_variable, legend=legend, ax=self.ax, palette=colors, cut=0)
367
+ legend = False
368
+
369
+ if self.ecdf_check.isChecked():
370
+ sns.ecdfplot(data=self.data, x=column_names[unique_cols], hue=hue_variable, legend=legend, ax=self.ax, palette=colors)
371
+ legend = False
372
+
373
+ if self.swarm_check.isChecked():
374
+ sns.swarmplot(data=self.data, y=column_names[unique_cols],dodge=True, hue=hue_variable,legend=legend, ax=self.ax, palette=colors)
375
+ legend = False
376
+
377
+ if self.violin_check.isChecked():
378
+ sns.violinplot(data=self.data, y=column_names[unique_cols],dodge=True, hue=hue_variable,legend=legend, ax=self.ax, palette=colors, cut=0)
379
+ legend = False
380
+
381
+ if self.box_check.isChecked():
382
+ 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,)
383
+ legend = False
384
+
385
+ if self.boxenplot_check.isChecked():
386
+ 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,)
387
+ legend = False
388
+
389
+ if self.strip_check.isChecked():
390
+ sns.stripplot(data=self.data, y=column_names[unique_cols],dodge=True, ax=self.ax, hue=hue_variable, legend=legend, palette=colors)
391
+ legend = False
392
+
393
+ plt.tight_layout()
394
+ self.fig.set_facecolor('none') # or 'None'
395
+ self.fig.canvas.setStyleSheet("background-color: transparent;")
396
+ self.plot1dWindow.canvas.draw()
397
+ self.plot1dWindow.show()
398
+
399
+
400
+ def set_proj_mode(self):
401
+ self.projection_mode = self.projection_op_cb.currentText()
402
+ #eval(self.projection_mode)
403
+ op = getattr(self.data.groupby(['position', 'TRACK_ID']), self.projection_mode)
404
+ group_table = op(self.data.groupby(['position', 'TRACK_ID']))
405
+
406
+ self.static_columns = ['well_index', 'well_name', 'pos_name', 'position', 'well', 'status', 't0', 'class', 'concentration', 'antibody', 'pharmaceutical_agent']
407
+ for c in self.static_columns:
408
+ try:
409
+ group_table[c] = self.data.groupby(['position','TRACK_ID'])[c].apply(lambda x: x.unique()[0])
410
+ except Exception as e:
411
+ print(e)
412
+ pass
413
+ self.subtable = TableUI(group_table,f"Group by tracks: {self.projection_mode}", plot_mode="static")
414
+ self.subtable.show()
415
+
416
+ self.projectionWidget.close()
417
+
418
+ # def groupby_track_table(self):
419
+
420
+ # """
421
+
422
+ # Perform a time average across each track for all features
423
+
424
+ # """
425
+
426
+ # self.subtable = TrajectoryTablePanel(self.data.groupby("TRACK_ID").mean(),"Group by tracks", plot_mode="scatter")
427
+ # self.subtable.show()
428
+
429
+ def _createMenuBar(self):
430
+ menuBar = self.menuBar()
431
+ self.fileMenu = QMenu("&File", self)
432
+ menuBar.addMenu(self.fileMenu)
433
+ self.editMenu = QMenu("&Edit", self)
434
+ menuBar.addMenu(self.editMenu)
435
+ self.mathMenu = QMenu('&Math', self)
436
+ menuBar.addMenu(self.mathMenu)
437
+
438
+ def save_as_csv(self):
439
+ options = QFileDialog.Options()
440
+ options |= QFileDialog.ReadOnly
441
+ file_name, _ = QFileDialog.getSaveFileName(self, "Save as .csv", "","CSV Files (*.csv);;All Files (*)", options=options)
442
+ if file_name:
443
+ if not file_name.endswith(".csv"):
444
+ file_name += ".csv"
445
+ self.data.to_csv(file_name, index=False)
446
+
447
+ def test_bool(self, array):
448
+ if array.dtype=="bool":
449
+ return np.array(array, dtype=int)
450
+ else:
451
+ return array
452
+
453
+ def plot(self):
454
+ if self.plot_mode == "static":
455
+
456
+ x = self.table_view.selectedIndexes()
457
+ col_idx = [l.column() for l in x]
458
+ row_idx = [l.row() for l in x]
459
+ column_names = self.data.columns
460
+ unique_cols = np.unique(col_idx)
461
+
462
+ if len(unique_cols)==1:
463
+ # 1D plot
464
+ # Open widget to set 1D data representations
465
+ self.set_1D_plot_params()
466
+
467
+
468
+
469
+ # x = self.table_view.selectedIndexes()
470
+ # col_idx = np.array([l.column() for l in x])
471
+ # row_idx = np.array([l.row() for l in x])
472
+ # column_names = self.data.columns
473
+ # unique_cols = np.unique(col_idx)[0]
474
+
475
+ # self.fig, self.ax = plt.subplots(1,1,figsize=(4,3))
476
+ # self.histogram_window = FigureCanvas(self.fig, title="scatter")
477
+ # self.ax.clear()
478
+ # row_idx_i = row_idx[np.where(col_idx==unique_cols)[0]]
479
+ # y = self.data.iloc[row_idx_i, unique_cols]
480
+
481
+ # colors = [viridis(i / len(self.data['well_index'].unique())) for i in range(len(self.data['well_index'].unique()))]
482
+ # #for w,well_group in self.data.groupby('well_index'):
483
+ # 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,)
484
+ # sns.stripplot(data=self.data, y=column_names[unique_cols],dodge=True, ax=self.ax, hue='well_index', legend=False, palette=colors)
485
+ # # 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,)
486
+ # # for k,(w,well_group) in enumerate(self.data.groupby('well_index')):
487
+ # # self.ax.hist(well_group[column_names[unique_cols]],label=w, density=True, alpha=0.5, color=colors[k])
488
+ # #self.ax.legend()
489
+ # self.ax.set_xlabel(column_names[unique_cols])
490
+ # plt.tight_layout()
491
+ # self.fig.set_facecolor('none') # or 'None'
492
+ # self.fig.canvas.setStyleSheet("background-color: transparent;")
493
+ # self.histogram_window.canvas.draw()
494
+ # self.histogram_window.show()
495
+
496
+
497
+ elif len(unique_cols) == 2:
498
+
499
+ print("two columns, plot mode")
500
+ x1 = self.test_bool(self.data.iloc[row_idx, unique_cols[0]])
501
+ x2 = self.test_bool(self.data.iloc[row_idx, unique_cols[1]])
502
+
503
+ self.fig, self.ax = plt.subplots(1, 1, figsize=(4,3))
504
+ self.scatter_wdw = FigureCanvas(self.fig, title="scatter")
505
+ self.ax.clear()
506
+ self.ax.scatter(x1,x2)
507
+ self.ax.set_xlabel(column_names[unique_cols[0]])
508
+ self.ax.set_ylabel(column_names[unique_cols[1]])
509
+ plt.tight_layout()
510
+ self.fig.set_facecolor('none') # or 'None'
511
+ self.fig.canvas.setStyleSheet("background-color: transparent;")
512
+ self.scatter_wdw.canvas.draw()
513
+ self.scatter_wdw.show()
514
+
515
+ else:
516
+ print("please select less columns")
517
+
518
+ elif self.plot_mode == "plot_timeseries":
519
+ print("mode plot frames")
520
+ x = self.table_view.selectedIndexes()
521
+ col_idx = np.array([l.column() for l in x])
522
+ row_idx = np.array([l.row() for l in x])
523
+ column_names = self.data.columns
524
+ unique_cols = np.unique(col_idx)
525
+
526
+ self.fig, self.ax = plt.subplots(1, 1, figsize=(4, 3))
527
+ self.plot_wdw = FigureCanvas(self.fig, title="scatter")
528
+ self.ax.clear()
529
+ for k in range(len(unique_cols)):
530
+ row_idx_i = row_idx[np.where(col_idx == unique_cols[k])[0]]
531
+ y = self.data.iloc[row_idx_i, unique_cols[k]]
532
+ self.ax.plot(self.data["timeline"][row_idx_i], y, label=column_names[unique_cols[k]])
533
+
534
+ self.ax.legend()
535
+ self.ax.set_xlabel("time [frame]")
536
+ self.ax.set_ylabel(self.title)
537
+ plt.tight_layout()
538
+ self.fig.set_facecolor('none') # or 'None'
539
+ self.fig.canvas.setStyleSheet("background-color: transparent;")
540
+ self.plot_wdw.canvas.draw()
541
+ plt.show()
542
+
543
+ elif self.plot_mode == "plot_track_signals":
544
+
545
+ print("mode plot track signals")
546
+ print('we plot here')
547
+
548
+ x = self.table_view.selectedIndexes()
549
+ col_idx = np.array([l.column() for l in x])
550
+ row_idx = np.array([l.row() for l in x])
551
+ column_names = self.data.columns
552
+ unique_cols = np.unique(col_idx)
553
+
554
+ if len(unique_cols) > 2:
555
+ fig,ax = plt.subplots(1, 1, figsize=(7, 5.5))
556
+ for k in range(len(unique_cols)):
557
+
558
+ row_idx_i = row_idx[np.where(col_idx == unique_cols[k])[0]]
559
+ y = self.data.iloc[row_idx_i, unique_cols[k]]
560
+ print(unique_cols[k])
561
+ for w,well_group in self.data.groupby('well_name'):
562
+ for pos,pos_group in well_group.groupby('pos_name'):
563
+ for tid,group_track in pos_group.groupby('TRACK_ID'):
564
+ ax.plot(group_track["FRAME"], group_track[column_names[unique_cols[k]]],label=column_names[unique_cols[k]])
565
+ #ax.plot(self.data["FRAME"][row_idx_i], y, label=column_names[unique_cols[k]])
566
+ ax.legend()
567
+ ax.set_xlabel("time [frame]")
568
+ ax.set_ylabel(self.title)
569
+ plt.tight_layout()
570
+ plt.show(block=False)
571
+
572
+ if len(unique_cols) == 2:
573
+
574
+ self.fig, self.ax = plt.subplots(1, 1, figsize=(4, 3))
575
+ self.scatter_wdw = FigureCanvas(self.fig, title="scatter")
576
+ self.ax.clear()
577
+ for tid,group in self.data.groupby('TRACK_ID'):
578
+ self.ax.plot(group[column_names[unique_cols[0]]], group[column_names[unique_cols[1]]], marker="o")
579
+ self.ax.set_xlabel(column_names[unique_cols[0]])
580
+ self.ax.set_ylabel(column_names[unique_cols[1]])
581
+ plt.tight_layout()
582
+ self.fig.set_facecolor('none') # or 'None'
583
+ self.fig.canvas.setStyleSheet("background-color: transparent;")
584
+ self.scatter_wdw.canvas.draw()
585
+ self.scatter_wdw.show()
586
+
587
+ if len(unique_cols) == 1:
588
+
589
+ self.fig, self.ax = plt.subplots(1, 1, figsize=(4, 3))
590
+ self.plot_wdw = FigureCanvas(self.fig, title="scatter")
591
+ self.ax.clear()
592
+
593
+ # if 't0' in list(self.data.columns):
594
+ # ref_time_col = 't0'
595
+ # else:
596
+ # ref_time_col = 'FRAME'
597
+
598
+ for w,well_group in self.data.groupby('well_name'):
599
+ for pos,pos_group in well_group.groupby('pos_name'):
600
+ for tid,group_track in pos_group.groupby('TRACK_ID'):
601
+ self.ax.plot(group_track["FRAME"], group_track[column_names[unique_cols[0]]],c="k", alpha = 0.1)
602
+ self.ax.set_xlabel(r"$t$ [frame]")
603
+ self.ax.set_ylabel(column_names[unique_cols[0]])
604
+ plt.tight_layout()
605
+ self.fig.set_facecolor('none') # or 'None'
606
+ self.fig.canvas.setStyleSheet("background-color: transparent;")
607
+ self.plot_wdw.canvas.draw()
608
+ self.plot_wdw.show()