celldetective 1.2.2.post2__tar.gz → 1.3.0.post1__tar.gz

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 (108) hide show
  1. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/PKG-INFO +3 -1
  2. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective/__init__.py +1 -0
  3. celldetective-1.3.0.post1/celldetective/_version.py +1 -0
  4. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective/events.py +5 -0
  5. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective/gui/about.py +2 -1
  6. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective/gui/classifier_widget.py +43 -33
  7. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective/gui/control_panel.py +33 -23
  8. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective/gui/gui_utils.py +9 -3
  9. celldetective-1.3.0.post1/celldetective/gui/measurement_options.py +1001 -0
  10. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective/gui/signal_annotator.py +65 -53
  11. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective/gui/tableUI.py +196 -26
  12. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective/io.py +4 -1
  13. celldetective-1.3.0.post1/celldetective/links/zenodo.json +752 -0
  14. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective/measure.py +46 -18
  15. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective/segmentation.py +17 -9
  16. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective/utils.py +82 -26
  17. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective.egg-info/PKG-INFO +3 -1
  18. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective.egg-info/SOURCES.txt +1 -0
  19. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective.egg-info/requires.txt +2 -0
  20. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/setup.py +13 -2
  21. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/tests/test_segmentation.py +5 -4
  22. celldetective-1.2.2.post2/celldetective/gui/measurement_options.py +0 -1001
  23. celldetective-1.2.2.post2/celldetective/links/zenodo.json +0 -561
  24. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/LICENSE +0 -0
  25. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/README.md +0 -0
  26. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective/__main__.py +0 -0
  27. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective/datasets/segmentation_annotations/blank +0 -0
  28. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective/datasets/signal_annotations/blank +0 -0
  29. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective/extra_properties.py +0 -0
  30. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective/filters.py +0 -0
  31. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective/gui/InitWindow.py +0 -0
  32. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective/gui/__init__.py +0 -0
  33. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective/gui/analyze_block.py +0 -0
  34. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective/gui/btrack_options.py +0 -0
  35. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective/gui/configure_new_exp.py +0 -0
  36. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective/gui/generic_signal_plot.py +0 -0
  37. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective/gui/help/DL-segmentation-strategy.json +0 -0
  38. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective/gui/help/Threshold-vs-DL.json +0 -0
  39. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective/gui/help/cell-populations.json +0 -0
  40. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective/gui/help/exp-structure.json +0 -0
  41. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective/gui/help/feature-btrack.json +0 -0
  42. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective/gui/help/neighborhood.json +0 -0
  43. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective/gui/help/prefilter-for-segmentation.json +0 -0
  44. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective/gui/help/preprocessing.json +0 -0
  45. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective/gui/help/propagate-classification.json +0 -0
  46. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective/gui/help/track-postprocessing.json +0 -0
  47. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective/gui/help/tracking.json +0 -0
  48. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective/gui/json_readers.py +0 -0
  49. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective/gui/layouts.py +0 -0
  50. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective/gui/neighborhood_options.py +0 -0
  51. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective/gui/plot_measurements.py +0 -0
  52. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective/gui/plot_signals_ui.py +0 -0
  53. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective/gui/process_block.py +0 -0
  54. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective/gui/retrain_segmentation_model_options.py +0 -0
  55. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective/gui/retrain_signal_model_options.py +0 -0
  56. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective/gui/seg_model_loader.py +0 -0
  57. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective/gui/signal_annotator2.py +0 -0
  58. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective/gui/signal_annotator_options.py +0 -0
  59. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective/gui/styles.py +0 -0
  60. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective/gui/survival_ui.py +0 -0
  61. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective/gui/thresholds_gui.py +0 -0
  62. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective/gui/viewers.py +0 -0
  63. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective/icons/logo-large.png +0 -0
  64. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective/icons/logo.png +0 -0
  65. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective/icons/signals_icon.png +0 -0
  66. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective/icons/splash-test.png +0 -0
  67. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective/icons/splash.png +0 -0
  68. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective/icons/splash0.png +0 -0
  69. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective/icons/survival2.png +0 -0
  70. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective/icons/vignette_signals2.png +0 -0
  71. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective/icons/vignette_signals2.svg +0 -0
  72. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective/models/pair_signal_detection/blank +0 -0
  73. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective/models/segmentation_effectors/blank +0 -0
  74. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective/models/segmentation_generic/blank +0 -0
  75. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective/models/segmentation_targets/blank +0 -0
  76. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective/models/signal_detection/blank +0 -0
  77. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective/models/tracking_configs/mcf7.json +0 -0
  78. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective/models/tracking_configs/ricm.json +0 -0
  79. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective/models/tracking_configs/ricm2.json +0 -0
  80. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective/neighborhood.py +0 -0
  81. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective/preprocessing.py +0 -0
  82. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective/relative_measurements.py +0 -0
  83. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective/scripts/analyze_signals.py +0 -0
  84. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective/scripts/measure_cells.py +0 -0
  85. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective/scripts/measure_relative.py +0 -0
  86. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective/scripts/segment_cells.py +0 -0
  87. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective/scripts/segment_cells_thresholds.py +0 -0
  88. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective/scripts/track_cells.py +0 -0
  89. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective/scripts/train_segmentation_model.py +0 -0
  90. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective/scripts/train_signal_model.py +0 -0
  91. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective/signals.py +0 -0
  92. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective/tracking.py +0 -0
  93. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective.egg-info/dependency_links.txt +0 -0
  94. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective.egg-info/entry_points.txt +0 -0
  95. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective.egg-info/not-zip-safe +0 -0
  96. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/celldetective.egg-info/top_level.txt +0 -0
  97. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/setup.cfg +0 -0
  98. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/tests/__init__.py +0 -0
  99. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/tests/test_events.py +0 -0
  100. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/tests/test_filters.py +0 -0
  101. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/tests/test_io.py +0 -0
  102. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/tests/test_measure.py +0 -0
  103. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/tests/test_neighborhood.py +0 -0
  104. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/tests/test_preprocessing.py +0 -0
  105. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/tests/test_qt.py +0 -0
  106. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/tests/test_signals.py +0 -0
  107. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/tests/test_tracking.py +0 -0
  108. {celldetective-1.2.2.post2 → celldetective-1.3.0.post1}/tests/test_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: celldetective
3
- Version: 1.2.2.post2
3
+ Version: 1.3.0.post1
4
4
  Summary: description
5
5
  Home-page: http://github.com/remyeltorro/celldetective
6
6
  Author: Rémy Torro
@@ -39,6 +39,8 @@ Requires-Dist: matplotlib_scalebar
39
39
  Requires-Dist: numpy==1.26.4
40
40
  Requires-Dist: pytest
41
41
  Requires-Dist: pytest-qt
42
+ Requires-Dist: h5py
43
+ Requires-Dist: cliffs_delta
42
44
 
43
45
  # Celldetective
44
46
 
@@ -1,3 +1,4 @@
1
+ from ._version import __version__
1
2
  #from .tracking import track, clean_trajectories
2
3
  #from .measure import contour_of_instance_segmentation
3
4
 
@@ -0,0 +1 @@
1
+ __version__ = "1.3.0.post1"
@@ -117,6 +117,11 @@ def compute_survival(df, class_of_interest, t_event, t_reference=None, FrameToMi
117
117
  event_times = df.groupby(['position','TRACK_ID'])[t_event].min().values
118
118
  max_times = df.groupby(['position','TRACK_ID'])['FRAME'].max().values
119
119
 
120
+ if t_reference=="0" or t_reference==0:
121
+ t_reference = None
122
+ left_censored = False
123
+ first_detections = None
124
+
120
125
  if t_reference is not None:
121
126
  left_censored = True
122
127
  assert t_reference in cols,"The reference time cannot be found in the dataframe..."
@@ -4,6 +4,7 @@ from PyQt5.QtCore import Qt
4
4
  from celldetective.utils import get_software_location
5
5
  import os
6
6
  from celldetective.gui.gui_utils import center_window
7
+ from celldetective._version import __version__
7
8
 
8
9
  class AboutWidget(QWidget):
9
10
 
@@ -27,7 +28,7 @@ class AboutWidget(QWidget):
27
28
  """)
28
29
  layout.addWidget(self.soft_name, alignment=Qt.AlignCenter)
29
30
 
30
- self.version_lbl = QLabel(f"Version X.X.X <a href=\"https://github.com/remyeltorro/celldetective/releases\">(release notes)</a>")
31
+ self.version_lbl = QLabel(f"Version {__version__} <a href=\"https://github.com/remyeltorro/celldetective/releases\">(release notes)</a>")
31
32
  self.version_lbl.setOpenExternalLinks(True)
32
33
  layout.addWidget(self.version_lbl, alignment=Qt.AlignCenter)
33
34
 
@@ -10,7 +10,7 @@ import numpy as np
10
10
  import matplotlib.pyplot as plt
11
11
  import json
12
12
 
13
- from celldetective.gui.gui_utils import FigureCanvas, center_window, color_from_status, help_generic
13
+ from celldetective.gui.gui_utils import FigureCanvas, center_window, color_from_status, help_generic, color_from_class
14
14
  from celldetective.gui import Styles
15
15
  from celldetective.utils import get_software_location
16
16
  from celldetective.measure import classify_cells_from_query, interpret_track_classification
@@ -242,42 +242,50 @@ class ClassifierWidget(QWidget, Styles):
242
242
 
243
243
  def update_props_scatter(self, feature_changed=True):
244
244
 
245
- if not self.project_times:
246
- self.scat_props.set_offsets(self.df.loc[self.df['FRAME']==self.currentFrame,[self.features_cb[1].currentText(),self.features_cb[0].currentText()]].to_numpy())
247
- colors = [color_from_status(c) for c in self.df.loc[self.df['FRAME']==self.currentFrame,self.class_name].to_numpy()]
248
- self.scat_props.set_facecolor(colors)
249
- self.scat_props.set_alpha(self.currentAlpha)
250
- self.ax_props.set_xlabel(self.features_cb[1].currentText())
251
- self.ax_props.set_ylabel(self.features_cb[0].currentText())
252
- else:
253
- self.scat_props.set_offsets(self.df[[self.features_cb[1].currentText(),self.features_cb[0].currentText()]].to_numpy())
254
- colors = [color_from_class(c) for c in self.df[self.class_name].to_numpy()]
255
- self.scat_props.set_facecolor(colors)
256
- self.scat_props.set_alpha(self.currentAlpha)
257
- self.ax_props.set_xlabel(self.features_cb[1].currentText())
258
- self.ax_props.set_ylabel(self.features_cb[0].currentText())
259
-
260
-
261
- feat_x = self.features_cb[1].currentText()
262
- feat_y = self.features_cb[0].currentText()
263
- min_x = self.df.dropna(subset=feat_x)[feat_x].min()
264
- max_x = self.df.dropna(subset=feat_x)[feat_x].max()
265
- min_y = self.df.dropna(subset=feat_y)[feat_y].min()
266
- max_y = self.df.dropna(subset=feat_y)[feat_y].max()
267
-
268
- if min_x==min_x and max_x==max_x:
269
- self.ax_props.set_xlim(min_x, max_x)
270
- if min_y==min_y and max_y==max_y:
271
- self.ax_props.set_ylim(min_y, max_y)
245
+ class_name = self.class_name
246
+
247
+ try:
248
+
249
+ if not self.project_times:
250
+ self.scat_props.set_offsets(self.df.loc[self.df['FRAME']==self.currentFrame,[self.features_cb[1].currentText(),self.features_cb[0].currentText()]].to_numpy())
251
+ colors = [color_from_status(c) for c in self.df.loc[self.df['FRAME']==self.currentFrame,class_name].to_numpy()]
252
+ self.scat_props.set_facecolor(colors)
253
+ self.scat_props.set_alpha(self.currentAlpha)
254
+ self.ax_props.set_xlabel(self.features_cb[1].currentText())
255
+ self.ax_props.set_ylabel(self.features_cb[0].currentText())
256
+ else:
257
+ self.scat_props.set_offsets(self.df[[self.features_cb[1].currentText(),self.features_cb[0].currentText()]].to_numpy())
258
+ colors = [color_from_status(c) for c in self.df[class_name].to_numpy()]
259
+ self.scat_props.set_facecolor(colors)
260
+ self.scat_props.set_alpha(self.currentAlpha)
261
+ self.ax_props.set_xlabel(self.features_cb[1].currentText())
262
+ self.ax_props.set_ylabel(self.features_cb[0].currentText())
263
+
264
+
265
+ feat_x = self.features_cb[1].currentText()
266
+ feat_y = self.features_cb[0].currentText()
267
+ min_x = self.df.dropna(subset=feat_x)[feat_x].min()
268
+ max_x = self.df.dropna(subset=feat_x)[feat_x].max()
269
+ min_y = self.df.dropna(subset=feat_y)[feat_y].min()
270
+ max_y = self.df.dropna(subset=feat_y)[feat_y].max()
271
+
272
+ if min_x==min_x and max_x==max_x:
273
+ self.ax_props.set_xlim(min_x, max_x)
274
+ if min_y==min_y and max_y==max_y:
275
+ self.ax_props.set_ylim(min_y, max_y)
276
+
277
+ if feature_changed:
278
+ self.propscanvas.canvas.toolbar.update()
279
+ self.propscanvas.canvas.draw_idle()
272
280
 
273
- if feature_changed:
274
- self.propscanvas.canvas.toolbar.update()
275
- self.propscanvas.canvas.draw_idle()
281
+ except Exception as e:
282
+ pass
276
283
 
277
284
  def apply_property_query(self):
278
285
 
279
286
  query = self.property_query_le.text()
280
- self.df = classify_cells_from_query(self.df, self.class_name, query)
287
+ self.df = classify_cells_from_query(self.df, self.name_le.text(), query)
288
+ self.class_name = "status_"+self.name_le.text()
281
289
  if self.df is None:
282
290
  msgBox = QMessageBox()
283
291
  msgBox.setIcon(QMessageBox.Warning)
@@ -287,7 +295,6 @@ class ClassifierWidget(QWidget, Styles):
287
295
  returnValue = msgBox.exec()
288
296
  if returnValue == QMessageBox.Ok:
289
297
  return None
290
-
291
298
  self.update_props_scatter()
292
299
 
293
300
  def set_frame(self, value):
@@ -346,6 +353,7 @@ class ClassifierWidget(QWidget, Styles):
346
353
  return None
347
354
 
348
355
  name_map = {self.class_name: self.class_name_user}
356
+ print(f"{name_map=}")
349
357
  self.df = self.df.drop(list(set(name_map.values()) & set(self.df.columns)), axis=1).rename(columns=name_map)
350
358
  self.df.reset_index(inplace=True, drop=True)
351
359
 
@@ -374,6 +382,8 @@ class ClassifierWidget(QWidget, Styles):
374
382
  #self.df[self.group_name_user] = self.df[self.group_name_user].replace({0: 1, 1: 0})
375
383
  self.df.reset_index(inplace=True, drop=True)
376
384
 
385
+ if 'custom' in list(self.df.columns):
386
+ self.df = self.df.drop(['custom'],axis=1)
377
387
 
378
388
  for pos,pos_group in self.df.groupby('position'):
379
389
  pos_group.to_csv(pos+os.sep.join(['output', 'tables', f'trajectories_{self.mode}.csv']), index=False)
@@ -138,14 +138,6 @@ class ControlPanel(QMainWindow, Styles):
138
138
  self.edit_config_button.clicked.connect(self.open_config_editor)
139
139
  self.edit_config_button.setStyleSheet(self.button_select_all)
140
140
 
141
- self.exp_options_layout = QHBoxLayout()
142
- self.exp_options_layout.addWidget(experiment_label, 32, alignment=Qt.AlignRight)
143
- self.exp_options_layout.addWidget(QLabel(name), 65, alignment=Qt.AlignLeft)
144
- self.exp_options_layout.addWidget(self.folder_exp_btn, 5, alignment=Qt.AlignRight)
145
- self.exp_options_layout.addWidget(self.edit_config_button, 5, alignment=Qt.AlignRight)
146
- self.grid.addLayout(self.exp_options_layout, 0,0,1,3)
147
-
148
- well_layout = QHBoxLayout()
149
141
  self.well_list = QComboBox()
150
142
  thresh = 32
151
143
  self.well_truncated = [w[:thresh - 3]+'...' if len(w)>thresh else w for w in self.well_labels]
@@ -156,7 +148,6 @@ class ControlPanel(QMainWindow, Styles):
156
148
  self.well_list.activated.connect(self.display_positions)
157
149
  self.to_disable.append(self.well_list)
158
150
 
159
- position_layout = QHBoxLayout()
160
151
  self.position_list = QComboBox()
161
152
  self.position_list.addItems(["*"])
162
153
  self.position_list.addItems(self.positions[0])
@@ -172,27 +163,46 @@ class ControlPanel(QMainWindow, Styles):
172
163
  self.view_stack_btn.clicked.connect(self.view_current_stack)
173
164
  self.view_stack_btn.setEnabled(False)
174
165
 
175
- well_layout.setContentsMargins(0,0,0,0)
176
166
  well_lbl = QLabel('Well: ')
177
167
  well_lbl.setAlignment(Qt.AlignRight)
178
- well_layout.addWidget(well_lbl, 32)
179
- well_layout.addWidget(self.well_list, 68)
180
- self.grid.addLayout(well_layout, 1, 0, 1, 3)
181
168
 
182
- position_layout.setContentsMargins(0,0,0,0)
183
169
  pos_lbl = QLabel('Position: ')
184
170
  pos_lbl.setAlignment(Qt.AlignRight)
185
- position_layout.addWidget(pos_lbl, 32)
186
171
 
187
- subposition_layout = QHBoxLayout()
188
- subposition_layout.addWidget(self.position_list, 95)
189
- subposition_layout.addWidget(self.view_stack_btn, 5)
190
- position_layout.addLayout(subposition_layout, 68)
191
- self.grid.addLayout(position_layout, 2, 0, 1, 3)
192
-
193
-
194
172
  hsep = QHSeperationLine()
195
- self.grid.addWidget(hsep, 5, 0, 1, 3)
173
+
174
+ ## LAYOUT
175
+
176
+ # Header layout
177
+ vbox = QVBoxLayout()
178
+ self.grid.addLayout(vbox, 0,0,1,3)
179
+
180
+ # Experiment row
181
+ exp_hbox = QHBoxLayout()
182
+ exp_hbox.addWidget(experiment_label, 25, alignment=Qt.AlignRight)
183
+ exp_subhbox = QHBoxLayout()
184
+ exp_subhbox.addWidget(QLabel(name), 90, alignment=Qt.AlignLeft)
185
+ exp_subhbox.addWidget(self.folder_exp_btn, 5, alignment=Qt.AlignRight)
186
+ exp_subhbox.addWidget(self.edit_config_button, 5, alignment=Qt.AlignRight)
187
+ exp_hbox.addLayout(exp_subhbox, 75)
188
+ vbox.addLayout(exp_hbox)
189
+
190
+ # Well row
191
+ well_hbox = QHBoxLayout()
192
+ well_hbox.addWidget(well_lbl, 25, alignment=Qt.AlignVCenter)
193
+ well_hbox.addWidget(self.well_list, 75)
194
+ vbox.addLayout(well_hbox)
195
+
196
+ # Position row
197
+ position_hbox = QHBoxLayout()
198
+ position_hbox.addWidget(pos_lbl, 25, alignment=Qt.AlignVCenter)
199
+ pos_subhbox = QHBoxLayout()
200
+ pos_subhbox.addWidget(self.position_list, 95)
201
+ pos_subhbox.addWidget(self.view_stack_btn, 5)
202
+ position_hbox.addLayout(pos_subhbox, 75)
203
+ vbox.addLayout(position_hbox)
204
+
205
+ vbox.addWidget(hsep)
196
206
 
197
207
  def locate_image(self):
198
208
 
@@ -768,7 +768,7 @@ def color_from_status(status, recently_modified=False):
768
768
  else:
769
769
  return 'k'
770
770
 
771
- def color_from_state(state):
771
+ def color_from_state(state, recently_modified=False):
772
772
 
773
773
  """
774
774
  Generate a color map based on unique values in the provided state array.
@@ -797,9 +797,15 @@ def color_from_state(state):
797
797
  unique_values = np.unique(state)
798
798
  color_map={}
799
799
  for value in unique_values:
800
- color_map[value] = plt.cm.tab10(value)
801
- if value == 99:
800
+ if np.isnan(value):
801
+ value = "nan"
802
802
  color_map[value] = 'k'
803
+ elif value==0:
804
+ color_map[value] = 'tab:blue'
805
+ elif value==1:
806
+ color_map[value] = 'tab:red'
807
+ else:
808
+ color_map[value] = plt.cm.tab10(value)
803
809
 
804
810
  return color_map
805
811