celldetective 1.2.2.post2__py3-none-any.whl → 1.3.0.post1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1438,59 +1438,65 @@ class MeasureAnnotator(SignalAnnotator):
1438
1438
  self.plot_signals()
1439
1439
 
1440
1440
  def plot_signals(self):
1441
- try:
1442
- current_frame = self.current_frame # Assuming you have a variable for the current frame
1443
- yvalues = []
1444
- all_yvalues = []
1445
- current_yvalues = []
1446
- all_median_values = []
1447
- labels = []
1448
- for i in range(len(self.signal_choice_cb)):
1449
- signal_choice = self.signal_choice_cb[i].currentText()
1441
+
1442
+ #try:
1443
+ current_frame = self.current_frame # Assuming you have a variable for the current frame
1444
+
1445
+ yvalues = []
1446
+ all_yvalues = []
1447
+ current_yvalues = []
1448
+ all_median_values = []
1449
+ labels = []
1450
+
1451
+ for i in range(len(self.signal_choice_cb)):
1452
+
1453
+ signal_choice = self.signal_choice_cb[i].currentText()
1450
1454
 
1451
- if signal_choice != "--":
1452
- if 'TRACK_ID' in self.df_tracks.columns:
1453
- ydata = self.df_tracks.loc[
1454
- (self.df_tracks['TRACK_ID'] == self.track_of_interest) &
1455
- (self.df_tracks['FRAME'] == current_frame), signal_choice].to_numpy()
1456
- else:
1457
- ydata = self.df_tracks.loc[
1458
- (self.df_tracks['ID'] == self.track_of_interest), signal_choice].to_numpy()
1459
- all_ydata = self.df_tracks.loc[:, signal_choice].to_numpy()
1460
- ydata = ydata[ydata == ydata] # remove nan
1461
- current_ydata = self.df_tracks.loc[
1455
+ if signal_choice != "--":
1456
+ if 'TRACK_ID' in self.df_tracks.columns:
1457
+ ydata = self.df_tracks.loc[
1458
+ (self.df_tracks['TRACK_ID'] == self.track_of_interest) &
1462
1459
  (self.df_tracks['FRAME'] == current_frame), signal_choice].to_numpy()
1463
- current_ydata = current_ydata[current_ydata == current_ydata]
1464
- all_ydata = all_ydata[all_ydata == all_ydata]
1465
- yvalues.extend(ydata)
1466
- current_yvalues.append(current_ydata)
1467
- all_yvalues.append(all_ydata)
1468
- labels.append(signal_choice)
1460
+ else:
1461
+ ydata = self.df_tracks.loc[
1462
+ (self.df_tracks['ID'] == self.track_of_interest), signal_choice].to_numpy()
1463
+ all_ydata = self.df_tracks.loc[:, signal_choice].to_numpy()
1464
+ ydataNaN = ydata
1465
+ ydata = ydata[ydata == ydata] # remove nan
1466
+ current_ydata = self.df_tracks.loc[
1467
+ (self.df_tracks['FRAME'] == current_frame), signal_choice].to_numpy()
1468
+ current_ydata = current_ydata[current_ydata == current_ydata]
1469
+ all_ydata = all_ydata[all_ydata == all_ydata]
1470
+ yvalues.extend(ydataNaN)
1471
+ current_yvalues.append(current_ydata)
1472
+ all_yvalues.append(all_ydata)
1473
+ labels.append(signal_choice)
1469
1474
 
1470
- self.cell_ax.clear()
1475
+ self.cell_ax.clear()
1471
1476
 
1472
- if len(yvalues) > 0:
1473
- self.cell_ax.boxplot(all_yvalues, showfliers=self.show_fliers)
1474
- ylim = self.cell_ax.get_ylim()
1475
- self.cell_ax.set_ylim(ylim)
1476
- x_pos = np.arange(len(all_yvalues)) + 1
1477
+ if len(yvalues) > 0:
1478
+ self.cell_ax.boxplot(all_yvalues, showfliers=self.show_fliers)
1479
+ ylim = self.cell_ax.get_ylim()
1480
+ self.cell_ax.set_ylim(ylim)
1481
+ x_pos = np.arange(len(all_yvalues)) + 1
1477
1482
 
1478
- for index, feature in enumerate(current_yvalues):
1479
- x_values_strip = (index + 1) + np.random.normal(0, 0.04, size=len(
1480
- feature))
1481
- self.cell_ax.plot(x_values_strip, feature, marker='o', linestyle='None', color=tab10.colors[0],
1482
- alpha=0.1)
1483
- self.cell_ax.plot(x_pos, yvalues, marker='H', linestyle='None', color=tab10.colors[3], alpha=1)
1483
+ for index, feature in enumerate(current_yvalues):
1484
+ x_values_strip = (index + 1) + np.random.normal(0, 0.04, size=len(
1485
+ feature))
1486
+ self.cell_ax.plot(x_values_strip, feature, marker='o', linestyle='None', color=tab10.colors[0],
1487
+ alpha=0.1)
1488
+
1489
+ self.cell_ax.plot(x_pos, yvalues, marker='H', linestyle='None', color=tab10.colors[3], alpha=1)
1484
1490
 
1485
1491
 
1486
- else:
1487
- self.cell_ax.text(0.5, 0.5, "No data available", horizontalalignment='center',
1488
- verticalalignment='center', transform=self.cell_ax.transAxes)
1492
+ else:
1493
+ self.cell_ax.text(0.5, 0.5, "No data available", horizontalalignment='center',
1494
+ verticalalignment='center', transform=self.cell_ax.transAxes)
1489
1495
 
1490
- self.cell_fcanvas.canvas.draw()
1496
+ self.cell_fcanvas.canvas.draw()
1491
1497
 
1492
- except Exception as e:
1493
- print(f"{e=}")
1498
+ # except Exception as e:
1499
+ # print("plot_signals: ",f"{e=}")
1494
1500
 
1495
1501
  def configure_ylims(self):
1496
1502
 
@@ -1954,7 +1960,7 @@ class MeasureAnnotator(SignalAnnotator):
1954
1960
  try:
1955
1961
  cell_selected = f"cell: {self.track_of_interest}\n"
1956
1962
  if 'TRACK_ID' in self.df_tracks.columns:
1957
- cell_status = f"phenotype: {self.df_tracks.loc[self.df_tracks['TRACK_ID'] == self.track_of_interest, self.status_name].to_numpy()[0]}\n"
1963
+ cell_status = f"phenotype: {self.df_tracks.loc[(self.df_tracks['FRAME']==self.current_frame)&(self.df_tracks['TRACK_ID'] == self.track_of_interest), self.status_name].to_numpy()[0]}\n"
1958
1964
  else:
1959
1965
  cell_status = f"phenotype: {self.df_tracks.loc[self.df_tracks['ID'] == self.track_of_interest, self.status_name].to_numpy()[0]}\n"
1960
1966
  self.cell_info.setText(cell_selected + cell_status)
@@ -2032,9 +2038,8 @@ class MeasureAnnotator(SignalAnnotator):
2032
2038
 
2033
2039
  def assign_color_state(self, state):
2034
2040
  if np.isnan(state):
2035
- pass
2036
- else:
2037
- return self.state_color_map[state]
2041
+ state = "nan"
2042
+ return self.state_color_map[state]
2038
2043
 
2039
2044
  def draw_frame(self, framedata):
2040
2045
 
@@ -2045,10 +2050,10 @@ class MeasureAnnotator(SignalAnnotator):
2045
2050
  self.frame_lbl.setText(f'position: {self.framedata}')
2046
2051
  self.im.set_array(self.img)
2047
2052
  self.status_scatter.set_offsets(self.positions[self.framedata])
2048
- try:
2049
- self.status_scatter.set_edgecolors(self.colors[self.framedata][:, 0])
2050
- except Exception as e:
2051
- pass
2053
+ # try:
2054
+ self.status_scatter.set_edgecolors(self.colors[self.framedata][:, 0])
2055
+ # except Exception as e:
2056
+ # pass
2052
2057
 
2053
2058
  self.current_label = self.labels[self.current_frame]
2054
2059
  self.current_label = contour_of_instance_segmentation(self.current_label, 5)
@@ -2060,18 +2065,23 @@ class MeasureAnnotator(SignalAnnotator):
2060
2065
  return (self.im, self.status_scatter,self.im_mask,)
2061
2066
 
2062
2067
  def compute_status_and_colors(self):
2068
+ print('compute status and colors!')
2063
2069
  if self.class_choice_cb.currentText() == '':
2064
2070
  self.status_name=self.target_class
2065
2071
  else:
2066
2072
  self.status_name = self.class_choice_cb.currentText()
2067
2073
 
2074
+ print(f'{self.status_name=}')
2068
2075
  if self.status_name not in self.df_tracks.columns:
2076
+ print('not in df, make column')
2069
2077
  self.make_status_column()
2070
2078
  else:
2071
2079
  all_states = self.df_tracks.loc[:, self.status_name].tolist()
2072
2080
  all_states = np.array(all_states)
2073
2081
  self.state_color_map = color_from_state(all_states, recently_modified=False)
2082
+ print(f'{self.state_color_map=}')
2074
2083
  self.df_tracks['group_color'] = self.df_tracks[self.status_name].apply(self.assign_color_state)
2084
+ print(self.df_tracks['group_color'])
2075
2085
 
2076
2086
  def del_event_class(self):
2077
2087
 
@@ -2342,9 +2352,11 @@ class MeasureAnnotator(SignalAnnotator):
2342
2352
  # self.extract_scatter_from_trajectories()
2343
2353
 
2344
2354
  def modify(self):
2355
+
2345
2356
  all_states = self.df_tracks.loc[:, self.status_name].tolist()
2346
2357
  all_states = np.array(all_states)
2347
2358
  self.state_color_map = color_from_state(all_states, recently_modified=False)
2359
+ print(f'{self.state_color_map=}')
2348
2360
 
2349
2361
  self.df_tracks['group_color'] = self.df_tracks[self.status_name].apply(self.assign_color_state)
2350
2362
 
@@ -2383,7 +2395,7 @@ class MeasureAnnotator(SignalAnnotator):
2383
2395
  self.colors[t][idx, 0] = self.previous_color[k][0]
2384
2396
  # self.colors[t][idx, 1] = self.previous_color[k][1]
2385
2397
  except Exception as e:
2386
- print(f'{e=}')
2398
+ print("cancel_selection: ",f'{e=}')
2387
2399
 
2388
2400
  def locate_stack(self):
2389
2401
 
@@ -1,10 +1,11 @@
1
1
  from PyQt5.QtWidgets import QRadioButton, QButtonGroup, QMainWindow, QTableView, QAction, QMenu,QFileDialog, QLineEdit, QHBoxLayout, QWidget, QPushButton, QVBoxLayout, QComboBox, QLabel, QCheckBox, QMessageBox
2
2
  from PyQt5.QtCore import Qt, QAbstractTableModel
3
+ from PyQt5.QtGui import QBrush, QColor
3
4
  import pandas as pd
4
5
  import matplotlib.pyplot as plt
5
6
  plt.rcParams['svg.fonttype'] = 'none'
6
- from celldetective.gui.gui_utils import FigureCanvas, center_window
7
- from celldetective.utils import differentiate_per_track, collapse_trajectories_by_status
7
+ from celldetective.gui.gui_utils import FigureCanvas, center_window, QHSeperationLine
8
+ from celldetective.utils import differentiate_per_track, collapse_trajectories_by_status, test_2samp_generic
8
9
  import numpy as np
9
10
  import seaborn as sns
10
11
  import matplotlib.cm as mcm
@@ -26,6 +27,7 @@ class PandasModel(QAbstractTableModel):
26
27
  def __init__(self, data):
27
28
  QAbstractTableModel.__init__(self)
28
29
  self._data = data
30
+ self.colors = dict()
29
31
 
30
32
  def rowCount(self, parent=None):
31
33
  return self._data.shape[0]
@@ -37,13 +39,24 @@ class PandasModel(QAbstractTableModel):
37
39
  if index.isValid():
38
40
  if role == Qt.DisplayRole:
39
41
  return str(self._data.iloc[index.row(), index.column()])
42
+ if role == Qt.BackgroundRole:
43
+ color = self.colors.get((index.row(), index.column()))
44
+ if color is not None:
45
+ return color
40
46
  return None
41
47
 
42
- def headerData(self, col, orientation, role):
48
+ def headerData(self, rowcol, orientation, role):
43
49
  if orientation == Qt.Horizontal and role == Qt.DisplayRole:
44
- return self._data.columns[col]
50
+ return self._data.columns[rowcol]
51
+ if orientation == Qt.Vertical and role == Qt.DisplayRole:
52
+ return self._data.index[rowcol]
45
53
  return None
46
54
 
55
+ def change_color(self, row, column, color):
56
+ ix = self.index(row, column)
57
+ self.colors[(row, column)] = color
58
+ self.dataChanged.emit(ix, ix, (Qt.BackgroundRole,))
59
+
47
60
 
48
61
  class QueryWidget(QWidget):
49
62
 
@@ -316,6 +329,111 @@ class RenameColWidget(QWidget):
316
329
  self.parent_window.table_view.setModel(self.parent_window.model)
317
330
  self.close()
318
331
 
332
+ class PivotTableUI(QWidget):
333
+
334
+ def __init__(self, data, title="", mode=None, *args, **kwargs):
335
+
336
+ QWidget.__init__(self, *args, **kwargs)
337
+
338
+ self.data = data
339
+ self.title = title
340
+ self.mode = mode
341
+
342
+ self.setWindowTitle(title)
343
+ print("tab to show: ",self.data)
344
+
345
+ self.table = QTableView(self)
346
+
347
+ self.v_layout = QVBoxLayout()
348
+ self.information_label = QLabel('Information about color code...')
349
+ self.v_layout.addWidget(self.information_label)
350
+ self.v_layout.addWidget(self.table)
351
+ self.setLayout(self.v_layout)
352
+
353
+ self.showdata()
354
+
355
+ if self.mode=="cliff":
356
+ self.color_cells_cliff()
357
+ elif self.mode=="pvalue":
358
+ self.color_cells_pvalue()
359
+
360
+ self.table.resizeColumnsToContents()
361
+ self.setAttribute(Qt.WA_DeleteOnClose)
362
+ center_window(self)
363
+
364
+ def showdata(self):
365
+ self.model = PandasModel(self.data)
366
+ self.table.setModel(self.model)
367
+
368
+ def set_cell_color(self, row, column, color='red'):
369
+ self.model.change_color(row, column, QBrush(QColor(color))) #eval(f"Qt.{color}")
370
+
371
+ def color_cells_cliff(self):
372
+
373
+ color_codes = {
374
+ "negligible": "#eff3ff", # Green
375
+ "small": "#bdd7e7", # Yellow
376
+ "medium": "#6baed6", # Orange
377
+ "large": "#2171b5" # Red
378
+ }
379
+
380
+ for i in range(self.data.shape[0]):
381
+ for j in range(self.data.shape[1]):
382
+ value = self.data.iloc[i,j]
383
+ if value < 0.147:
384
+ self.set_cell_color(i,j,color_codes['negligible'])
385
+ elif value < 0.33:
386
+ self.set_cell_color(i,j,color_codes['small'])
387
+ elif value < 0.474:
388
+ self.set_cell_color(i,j,color_codes['medium'])
389
+ elif value >= 0.474:
390
+ self.set_cell_color(i,j,color_codes['large'])
391
+
392
+ # Create the HTML text for the label
393
+ html_caption = f"""
394
+ <p style="background-color:black; padding: 5px; font-weight:bold;">
395
+ <span style="color:{color_codes['negligible']}">Negligible</span>,
396
+ <span style="color:{color_codes['small']}">Small</span>,
397
+ <span style="color:{color_codes['medium']}">Medium</span>,
398
+ <span style="color:{color_codes['large']}">Large</span>
399
+ </p>
400
+ """
401
+ self.information_label.setText(html_caption)
402
+
403
+ def color_cells_pvalue(self):
404
+
405
+ color_codes = {
406
+ "ns": "#fee5d9",
407
+ "*": "#fcae91",
408
+ "**": "#fb6a4a",
409
+ "***": "#de2d26",
410
+ "****": "#a50f15"
411
+ }
412
+
413
+ for i in range(self.data.shape[0]):
414
+ for j in range(self.data.shape[1]):
415
+ value = self.data.iloc[i,j]
416
+ if value <= 0.0001:
417
+ self.set_cell_color(i,j,color_codes['****'])
418
+ elif value <= 0.001:
419
+ self.set_cell_color(i,j,color_codes['***'])
420
+ elif value <= 0.01:
421
+ self.set_cell_color(i,j,color_codes['**'])
422
+ elif value <= 0.05:
423
+ self.set_cell_color(i,j,color_codes['*'])
424
+ elif value > 0.05:
425
+ self.set_cell_color(i,j,color_codes['ns'])
426
+
427
+ html_caption = f"""
428
+ <p style="background-color:black; padding: 5px; font-weight:bold;">
429
+ <span style="color:{color_codes['ns']}">ns</span>,
430
+ <span style="color:{color_codes['*']}">*</span>,
431
+ <span style="color:{color_codes['**']}">**</span>,
432
+ <span style="color:{color_codes['***']}">***</span>,
433
+ <span style="color:{color_codes['****']}">****</span>
434
+ </p>
435
+ """
436
+ self.information_label.setText(html_caption)
319
437
 
320
438
  class TableUI(QMainWindow, Styles):
321
439
 
@@ -744,6 +862,10 @@ class TableUI(QMainWindow, Styles):
744
862
  self.box_check = QCheckBox('boxplot')
745
863
  self.boxenplot_check = QCheckBox('boxenplot')
746
864
 
865
+ self.sep_line = QHSeperationLine()
866
+ self.pvalue_check = QCheckBox("Compute KS test p-value?")
867
+ self.effect_size_check = QCheckBox("Compute effect size?\n(Cliff's Delta)")
868
+
747
869
  layout.addWidget(self.hist_check)
748
870
  layout.addWidget(self.kde_check)
749
871
  layout.addWidget(self.count_check)
@@ -754,6 +876,9 @@ class TableUI(QMainWindow, Styles):
754
876
  layout.addWidget(self.strip_check)
755
877
  layout.addWidget(self.box_check)
756
878
  layout.addWidget(self.boxenplot_check)
879
+ layout.addWidget(self.sep_line)
880
+ layout.addWidget(self.pvalue_check)
881
+ layout.addWidget(self.effect_size_check)
757
882
 
758
883
  self.x_cb = QSearchableComboBox()
759
884
  self.x_cb.addItems(['--']+list(self.data.columns))
@@ -830,13 +955,13 @@ class TableUI(QMainWindow, Styles):
830
955
  cmap = getattr(mcm, self.cmap_cb.currentText())
831
956
 
832
957
  try:
833
- hue_variable = self.hue_cb.currentText()
834
- colors = [cmap(i / len(self.data[hue_variable].unique())) for i in range(len(self.data[hue_variable].unique()))]
958
+ self.hue_variable = self.hue_cb.currentText()
959
+ colors = [cmap(i / len(self.data[self.hue_variable].unique())) for i in range(len(self.data[self.hue_variable].unique()))]
835
960
  except:
836
961
  colors = None
837
962
 
838
963
  if self.hue_cb.currentText()=='--':
839
- hue_variable = None
964
+ self.hue_variable = None
840
965
 
841
966
  if self.y_cb.currentText()=='--':
842
967
  self.y = None
@@ -852,42 +977,42 @@ class TableUI(QMainWindow, Styles):
852
977
 
853
978
  if self.hist_check.isChecked():
854
979
  if self.x is not None:
855
- 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')
980
+ sns.histplot(data=self.data, x=self.x, hue=self.hue_variable, legend=legend, ax=self.ax, palette=colors, kde=True, common_norm=False, stat='density')
856
981
  legend = False
857
982
  elif self.x is None and self.y is not None:
858
- sns.histplot(data=self.data, x=self.y, hue=hue_variable, legend=legend, ax=self.ax, palette=colors, kde=True, common_norm=False, stat='density')
983
+ sns.histplot(data=self.data, x=self.y, hue=self.hue_variable, legend=legend, ax=self.ax, palette=colors, kde=True, common_norm=False, stat='density')
859
984
  legend = False
860
985
  else:
861
986
  pass
862
987
 
863
988
  if self.kde_check.isChecked():
864
989
  if self.x is not None:
865
- sns.kdeplot(data=self.data, x=self.x, hue=hue_variable, legend=legend, ax=self.ax, palette=colors, cut=0)
990
+ sns.kdeplot(data=self.data, x=self.x, hue=self.hue_variable, legend=legend, ax=self.ax, palette=colors, cut=0)
866
991
  legend = False
867
992
  elif self.x is None and self.y is not None:
868
- sns.kdeplot(data=self.data, x=self.y, hue=hue_variable, legend=legend, ax=self.ax, palette=colors, cut=0)
993
+ sns.kdeplot(data=self.data, x=self.y, hue=self.hue_variable, legend=legend, ax=self.ax, palette=colors, cut=0)
869
994
  legend = False
870
995
  else:
871
996
  pass
872
997
 
873
998
  if self.count_check.isChecked():
874
- sns.countplot(data=self.data, x=self.x, hue=hue_variable, legend=legend, ax=self.ax, palette=colors)
999
+ sns.countplot(data=self.data, x=self.x, hue=self.hue_variable, legend=legend, ax=self.ax, palette=colors)
875
1000
  legend = False
876
1001
 
877
1002
 
878
1003
  if self.ecdf_check.isChecked():
879
1004
  if self.x is not None:
880
- sns.ecdfplot(data=self.data, x=self.x, hue=hue_variable, legend=legend, ax=self.ax, palette=colors)
1005
+ sns.ecdfplot(data=self.data, x=self.x, hue=self.hue_variable, legend=legend, ax=self.ax, palette=colors)
881
1006
  legend = False
882
1007
  elif self.x is None and self.y is not None:
883
- sns.ecdfplot(data=self.data, x=self.y, hue=hue_variable, legend=legend, ax=self.ax, palette=colors)
1008
+ sns.ecdfplot(data=self.data, x=self.y, hue=self.hue_variable, legend=legend, ax=self.ax, palette=colors)
884
1009
  legend = False
885
1010
  else:
886
1011
  pass
887
1012
 
888
1013
  if self.scat_check.isChecked():
889
1014
  if self.x_option:
890
- sns.scatterplot(data=self.data, x=self.x,y=self.y, hue=hue_variable,legend=legend, ax=self.ax, palette=colors)
1015
+ sns.scatterplot(data=self.data, x=self.x,y=self.y, hue=self.hue_variable,legend=legend, ax=self.ax, palette=colors)
891
1016
  legend = False
892
1017
  else:
893
1018
  print('please provide a -x variable...')
@@ -895,42 +1020,42 @@ class TableUI(QMainWindow, Styles):
895
1020
 
896
1021
  if self.swarm_check.isChecked():
897
1022
  if self.x_option:
898
- sns.swarmplot(data=self.data, x=self.x,y=self.y,dodge=True, hue=hue_variable,legend=legend, ax=self.ax, palette=colors)
1023
+ sns.swarmplot(data=self.data, x=self.x,y=self.y,dodge=True, hue=self.hue_variable,legend=legend, ax=self.ax, palette=colors)
899
1024
  legend = False
900
1025
  else:
901
- sns.swarmplot(data=self.data, y=self.y,dodge=True, hue=hue_variable,legend=legend, ax=self.ax, palette=colors)
1026
+ sns.swarmplot(data=self.data, y=self.y,dodge=True, hue=self.hue_variable,legend=legend, ax=self.ax, palette=colors)
902
1027
  legend = False
903
1028
 
904
1029
  if self.violin_check.isChecked():
905
1030
  if self.x_option:
906
- sns.violinplot(data=self.data,x=self.x, y=self.y,dodge=True, ax=self.ax, hue=hue_variable, legend=legend, palette=colors)
1031
+ sns.violinplot(data=self.data,x=self.x, y=self.y,dodge=True, ax=self.ax, hue=self.hue_variable, legend=legend, palette=colors)
907
1032
  legend = False
908
1033
  else:
909
- sns.violinplot(data=self.data, y=self.y,dodge=True, hue=hue_variable,legend=legend, ax=self.ax, palette=colors, cut=0)
1034
+ sns.violinplot(data=self.data, y=self.y,dodge=True, hue=self.hue_variable,legend=legend, ax=self.ax, palette=colors, cut=0)
910
1035
  legend = False
911
1036
 
912
1037
  if self.box_check.isChecked():
913
1038
  if self.x_option:
914
- 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,)
1039
+ sns.boxplot(data=self.data, x=self.x, y=self.y,dodge=True, hue=self.hue_variable,legend=legend, ax=self.ax, fill=False,palette=colors, linewidth=2,)
915
1040
  legend = False
916
1041
  else:
917
- sns.boxplot(data=self.data, y=self.y,dodge=True, hue=hue_variable,legend=legend, ax=self.ax, fill=False,palette=colors, linewidth=2,)
1042
+ sns.boxplot(data=self.data, y=self.y,dodge=True, hue=self.hue_variable,legend=legend, ax=self.ax, fill=False,palette=colors, linewidth=2,)
918
1043
  legend = False
919
1044
 
920
1045
  if self.boxenplot_check.isChecked():
921
1046
  if self.x_option:
922
- 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,)
1047
+ sns.boxenplot(data=self.data, x=self.x, y=self.y,dodge=True, hue=self.hue_variable,legend=legend, ax=self.ax, fill=False,palette=colors, linewidth=2,)
923
1048
  legend = False
924
1049
  else:
925
- sns.boxenplot(data=self.data, y=self.y,dodge=True, hue=hue_variable,legend=legend, ax=self.ax, fill=False,palette=colors, linewidth=2,)
1050
+ sns.boxenplot(data=self.data, y=self.y,dodge=True, hue=self.hue_variable,legend=legend, ax=self.ax, fill=False,palette=colors, linewidth=2,)
926
1051
  legend = False
927
1052
 
928
1053
  if self.strip_check.isChecked():
929
1054
  if self.x_option:
930
- sns.stripplot(data=self.data, x = self.x, y=self.y,dodge=True, ax=self.ax, hue=hue_variable, legend=legend, palette=colors)
1055
+ sns.stripplot(data=self.data, x = self.x, y=self.y,dodge=True, ax=self.ax, hue=self.hue_variable, legend=legend, palette=colors)
931
1056
  legend = False
932
1057
  else:
933
- sns.stripplot(data=self.data, y=self.y,dodge=True, ax=self.ax, hue=hue_variable, legend=legend, palette=colors)
1058
+ sns.stripplot(data=self.data, y=self.y,dodge=True, ax=self.ax, hue=self.hue_variable, legend=legend, palette=colors)
934
1059
  legend = False
935
1060
 
936
1061
  plt.tight_layout()
@@ -939,6 +1064,51 @@ class TableUI(QMainWindow, Styles):
939
1064
  self.plot1dWindow.canvas.draw()
940
1065
  self.plot1dWindow.show()
941
1066
 
1067
+ if self.effect_size_check.isChecked():
1068
+ self.compute_effect_size()
1069
+ if self.pvalue_check.isChecked():
1070
+ self.compute_pvalue()
1071
+
1072
+ def extract_groupby_cols(self):
1073
+
1074
+ x = self.x
1075
+ y = self.y
1076
+ hue_variable = self.hue_variable
1077
+
1078
+ if self.hist_check.isChecked() or self.ecdf_check.isChecked() or self.kde_check.isChecked():
1079
+ y = self.x
1080
+ x = None
1081
+
1082
+ groupby_cols = []
1083
+ if x is not None:
1084
+ groupby_cols.append(x)
1085
+ if hue_variable is not None:
1086
+ groupby_cols.append(hue_variable)
1087
+
1088
+ return groupby_cols, y
1089
+
1090
+ def compute_effect_size(self):
1091
+
1092
+ if self.count_check.isChecked() or self.scat_check.isChecked():
1093
+ print('Please select a valid plot representation to compute effect size (histogram, boxplot, etc.)...')
1094
+ return None
1095
+
1096
+ groupby_cols, y = self.extract_groupby_cols()
1097
+ pivot = test_2samp_generic(self.data, feature=y, groupby_cols=groupby_cols, method="cliffs_delta")
1098
+ self.effect_size_table = PivotTableUI(pivot, title="Effect size (Cliff's Delta)", mode="cliff")
1099
+ self.effect_size_table.show()
1100
+
1101
+ def compute_pvalue(self):
1102
+
1103
+ if self.count_check.isChecked() or self.scat_check.isChecked():
1104
+ print('Please select a valid plot representation to compute effect size (histogram, boxplot, etc.)...')
1105
+ return None
1106
+
1107
+ groupby_cols, y = self.extract_groupby_cols()
1108
+ pivot = test_2samp_generic(self.data, feature=y, groupby_cols=groupby_cols, method="ks_2samp")
1109
+ self.pval_table = PivotTableUI(pivot, title="p-value (1-sided KS test)", mode="pvalue")
1110
+ self.pval_table.show()
1111
+
942
1112
 
943
1113
  def set_proj_mode(self):
944
1114
 
@@ -1003,7 +1173,7 @@ class TableUI(QMainWindow, Styles):
1003
1173
 
1004
1174
 
1005
1175
  elif self.per_status_option.isChecked():
1006
-
1176
+ self.projection_mode = self.status_operation.currentText()
1007
1177
  group_table = collapse_trajectories_by_status(self.data, status=self.per_status_cb.currentText(),population=self.population, projection=self.status_operation.currentText(), groupby_columns=self.groupby_cols)
1008
1178
 
1009
1179
  self.subtable = TableUI(group_table,f"Group by tracks: {self.projection_mode}", plot_mode="static")
celldetective/io.py CHANGED
@@ -766,6 +766,9 @@ def locate_stack_and_labels(position, prefix='Aligned', population="target"):
766
766
  position = position.replace('\\', '/')
767
767
  labels = locate_labels(position, population=population)
768
768
  stack = locate_stack(position, prefix=prefix)
769
+ if len(labels) < len(stack):
770
+ fix_missing_labels(position, population=population, prefix=prefix)
771
+ labels = locate_labels(position, population=population)
769
772
  assert len(stack) == len(
770
773
  labels), f"The shape of the stack {stack.shape} does not match with the shape of the labels {labels.shape}"
771
774
 
@@ -1272,7 +1275,7 @@ def view_on_napari_btrack(data, properties, graph, stack=None, labels=None, rela
1272
1275
  if stack is not None:
1273
1276
  viewer.add_image(stack, channel_axis=-1, colormap=["gray"] * stack.shape[-1])
1274
1277
  if labels is not None:
1275
- viewer.add_labels(labels, name='segmentation', opacity=0.4)
1278
+ viewer.add_labels(labels.astype(int), name='segmentation', opacity=0.4)
1276
1279
  viewer.add_points(vertices, size=4, name='points', opacity=0.3)
1277
1280
  if data.shape[1]==4:
1278
1281
  viewer.add_tracks(data, properties=properties, graph=graph, name='tracks')