celldetective 1.3.9.post5__py3-none-any.whl → 1.4.1__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 (94) hide show
  1. celldetective/__init__.py +0 -3
  2. celldetective/_version.py +1 -1
  3. celldetective/events.py +2 -4
  4. celldetective/exceptions.py +11 -0
  5. celldetective/extra_properties.py +132 -0
  6. celldetective/filters.py +7 -1
  7. celldetective/gui/InitWindow.py +37 -46
  8. celldetective/gui/__init__.py +3 -9
  9. celldetective/gui/about.py +19 -15
  10. celldetective/gui/analyze_block.py +34 -19
  11. celldetective/gui/base_annotator.py +786 -0
  12. celldetective/gui/base_components.py +23 -0
  13. celldetective/gui/classifier_widget.py +86 -94
  14. celldetective/gui/configure_new_exp.py +163 -46
  15. celldetective/gui/control_panel.py +76 -146
  16. celldetective/gui/{signal_annotator.py → event_annotator.py} +533 -1438
  17. celldetective/gui/generic_signal_plot.py +11 -13
  18. celldetective/gui/gui_utils.py +54 -23
  19. celldetective/gui/help/neighborhood.json +2 -2
  20. celldetective/gui/json_readers.py +5 -4
  21. celldetective/gui/layouts.py +265 -31
  22. celldetective/gui/{signal_annotator2.py → pair_event_annotator.py} +433 -635
  23. celldetective/gui/plot_measurements.py +21 -17
  24. celldetective/gui/plot_signals_ui.py +125 -72
  25. celldetective/gui/process_block.py +283 -188
  26. celldetective/gui/processes/compute_neighborhood.py +594 -0
  27. celldetective/gui/processes/downloader.py +37 -34
  28. celldetective/gui/processes/measure_cells.py +19 -8
  29. celldetective/gui/processes/segment_cells.py +47 -11
  30. celldetective/gui/processes/track_cells.py +18 -13
  31. celldetective/gui/seg_model_loader.py +21 -62
  32. celldetective/gui/settings/__init__.py +7 -0
  33. celldetective/gui/settings/_settings_base.py +70 -0
  34. celldetective/gui/{retrain_signal_model_options.py → settings/_settings_event_model_training.py} +54 -109
  35. celldetective/gui/{measurement_options.py → settings/_settings_measurements.py} +54 -92
  36. celldetective/gui/{neighborhood_options.py → settings/_settings_neighborhood.py} +10 -13
  37. celldetective/gui/settings/_settings_segmentation.py +49 -0
  38. celldetective/gui/{retrain_segmentation_model_options.py → settings/_settings_segmentation_model_training.py} +38 -92
  39. celldetective/gui/{signal_annotator_options.py → settings/_settings_signal_annotator.py} +78 -103
  40. celldetective/gui/{btrack_options.py → settings/_settings_tracking.py} +85 -116
  41. celldetective/gui/styles.py +2 -1
  42. celldetective/gui/survival_ui.py +49 -95
  43. celldetective/gui/tableUI.py +53 -25
  44. celldetective/gui/table_ops/__init__.py +0 -0
  45. celldetective/gui/table_ops/merge_groups.py +118 -0
  46. celldetective/gui/thresholds_gui.py +617 -1221
  47. celldetective/gui/viewers.py +107 -42
  48. celldetective/gui/workers.py +8 -4
  49. celldetective/io.py +137 -57
  50. celldetective/links/zenodo.json +145 -144
  51. celldetective/measure.py +94 -53
  52. celldetective/neighborhood.py +342 -268
  53. celldetective/preprocessing.py +56 -35
  54. celldetective/regionprops/_regionprops.py +16 -5
  55. celldetective/relative_measurements.py +50 -29
  56. celldetective/scripts/analyze_signals.py +4 -1
  57. celldetective/scripts/measure_cells.py +5 -5
  58. celldetective/scripts/measure_relative.py +20 -12
  59. celldetective/scripts/segment_cells.py +4 -10
  60. celldetective/scripts/segment_cells_thresholds.py +3 -3
  61. celldetective/scripts/track_cells.py +10 -8
  62. celldetective/scripts/train_segmentation_model.py +18 -6
  63. celldetective/signals.py +29 -14
  64. celldetective/tracking.py +14 -3
  65. celldetective/utils.py +91 -62
  66. {celldetective-1.3.9.post5.dist-info → celldetective-1.4.1.dist-info}/METADATA +24 -16
  67. celldetective-1.4.1.dist-info/RECORD +123 -0
  68. {celldetective-1.3.9.post5.dist-info → celldetective-1.4.1.dist-info}/WHEEL +1 -1
  69. tests/gui/__init__.py +0 -0
  70. tests/gui/test_new_project.py +228 -0
  71. tests/gui/test_project.py +99 -0
  72. tests/test_preprocessing.py +2 -2
  73. celldetective/models/segmentation_effectors/ricm_bf_all_last/config_input.json +0 -79
  74. celldetective/models/segmentation_effectors/ricm_bf_all_last/ricm_bf_all_last +0 -0
  75. celldetective/models/segmentation_effectors/ricm_bf_all_last/training_instructions.json +0 -37
  76. celldetective/models/segmentation_effectors/test-transfer/config_input.json +0 -39
  77. celldetective/models/segmentation_effectors/test-transfer/test-transfer +0 -0
  78. celldetective/models/signal_detection/NucCond/classification_loss.png +0 -0
  79. celldetective/models/signal_detection/NucCond/classifier.h5 +0 -0
  80. celldetective/models/signal_detection/NucCond/config_input.json +0 -1
  81. celldetective/models/signal_detection/NucCond/log_classifier.csv +0 -126
  82. celldetective/models/signal_detection/NucCond/log_regressor.csv +0 -282
  83. celldetective/models/signal_detection/NucCond/regression_loss.png +0 -0
  84. celldetective/models/signal_detection/NucCond/regressor.h5 +0 -0
  85. celldetective/models/signal_detection/NucCond/scores.npy +0 -0
  86. celldetective/models/signal_detection/NucCond/test_confusion_matrix.png +0 -0
  87. celldetective/models/signal_detection/NucCond/test_regression.png +0 -0
  88. celldetective/models/signal_detection/NucCond/validation_confusion_matrix.png +0 -0
  89. celldetective/models/signal_detection/NucCond/validation_regression.png +0 -0
  90. celldetective-1.3.9.post5.dist-info/RECORD +0 -129
  91. tests/test_qt.py +0 -103
  92. {celldetective-1.3.9.post5.dist-info → celldetective-1.4.1.dist-info}/entry_points.txt +0 -0
  93. {celldetective-1.3.9.post5.dist-info → celldetective-1.4.1.dist-info/licenses}/LICENSE +0 -0
  94. {celldetective-1.3.9.post5.dist-info → celldetective-1.4.1.dist-info}/top_level.txt +0 -0
@@ -1,7 +1,7 @@
1
- from PyQt5.QtWidgets import QCheckBox, QLineEdit, QWidget, QListWidget, QTabWidget, QHBoxLayout,QMessageBox, QPushButton, QVBoxLayout, QRadioButton, QLabel, QButtonGroup, QSizePolicy, QComboBox,QSpacerItem, QGridLayout
1
+ from PyQt5.QtWidgets import QCheckBox, QLineEdit, QListWidget, QTabWidget, QHBoxLayout,QMessageBox, QPushButton, QVBoxLayout, QRadioButton, QLabel, QButtonGroup, QSizePolicy, QComboBox,QSpacerItem, QGridLayout
2
2
  from celldetective.gui.gui_utils import ThresholdLineEdit, QuickSliderLayout, center_window
3
3
  from PyQt5.QtCore import Qt, QSize
4
- from PyQt5.QtGui import QIntValidator
4
+ from PyQt5.QtGui import QIntValidator, QDoubleValidator
5
5
 
6
6
  from superqt import QLabeledRangeSlider, QLabeledDoubleSlider, QLabeledSlider, QLabeledDoubleRangeSlider, QSearchableComboBox
7
7
 
@@ -9,15 +9,223 @@ from superqt.fonticon import icon
9
9
  from fonticon_mdi6 import MDI6
10
10
  from celldetective.utils import _extract_channel_indices_from_config
11
11
  from celldetective.gui.viewers import ThresholdedStackVisualizer, CellEdgeVisualizer, StackVisualizer, CellSizeViewer, ChannelOffsetViewer
12
- from celldetective.gui import Styles
12
+ from celldetective.gui import Styles, CelldetectiveWidget
13
13
  from celldetective.preprocessing import correct_background_model, correct_background_model_free, estimate_background_per_condition
14
14
  from functools import partial
15
15
  from glob import glob
16
16
  import os
17
17
  import pandas as pd
18
18
  import numpy as np
19
+ from celldetective.io import locate_segmentation_model, locate_signal_model
20
+ import json
19
21
 
20
- class StarDistParamsWidget(QWidget, Styles):
22
+
23
+ class SignalModelParamsWidget(CelldetectiveWidget):
24
+
25
+ def __init__(self, parent_window=None, model_name=None, *args, **kwargs):
26
+
27
+ super().__init__(*args)
28
+ self.setWindowTitle('Signals')
29
+ self.parent_window = parent_window
30
+ self.model_name = model_name
31
+ self.locate_model_path()
32
+ self.required_channels = self.input_config["channels"]
33
+ self.onlyFloat = QDoubleValidator()
34
+
35
+ # Setting up references to parent window attributes
36
+ if hasattr(self.parent_window.parent_window, 'locate_image'):
37
+ self.attr_parent = self.parent_window.parent_window
38
+ elif hasattr(self.parent_window.parent_window.parent_window, 'locate_image'):
39
+ self.attr_parent = self.parent_window.parent_window.parent_window
40
+ else:
41
+ self.attr_parent = self.parent_window.parent_window.parent_window.parent_window
42
+
43
+ # Set up layout and widgets
44
+ self.layout = QVBoxLayout()
45
+ self.populate_widgets()
46
+ self.setLayout(self.layout)
47
+ center_window(self)
48
+
49
+ def locate_model_path(self):
50
+
51
+ self.model_complete_path = locate_signal_model(self.model_name)
52
+ if self.model_complete_path is None:
53
+ print('Model could not be found. Abort.')
54
+ self.abort_process()
55
+ else:
56
+ print(f'Model path: {self.model_complete_path}...')
57
+
58
+ if not os.path.exists(self.model_complete_path+"config_input.json"):
59
+ print('The configuration for the inputs to the model could not be located. Abort.')
60
+ self.abort_process()
61
+
62
+ with open(self.model_complete_path+"config_input.json") as config_file:
63
+ self.input_config = json.load(config_file)
64
+
65
+ def populate_widgets(self):
66
+
67
+ self.n_channels = len(self.required_channels)
68
+ self.channel_cbs = [QComboBox() for i in range(self.n_channels)]
69
+
70
+ self.parent_window.load_available_tables()
71
+ available_channels = list(self.parent_window.signals)+['None']
72
+ # Populate the comboboxes with available channels from the experiment
73
+ for k in range(self.n_channels):
74
+ hbox_channel = QHBoxLayout()
75
+ hbox_channel.addWidget(QLabel(f'channel {k+1}: '), 33)
76
+
77
+ ch_vbox = QVBoxLayout()
78
+ ch_vbox.addWidget(QLabel(f'Req: {self.required_channels[k]}'), alignment=Qt.AlignLeft)
79
+ ch_vbox.addWidget(self.channel_cbs[k])
80
+
81
+ self.channel_cbs[k].addItems(available_channels) #Give none option for more than one channel input
82
+ idx = self.channel_cbs[k].findText(self.required_channels[k])
83
+
84
+ if idx>=0:
85
+ self.channel_cbs[k].setCurrentIndex(idx)
86
+ else:
87
+ self.channel_cbs[k].setCurrentIndex(len(available_channels)-1)
88
+
89
+ hbox_channel.addLayout(ch_vbox, 66)
90
+ self.layout.addLayout(hbox_channel)
91
+
92
+ # Button to apply the StarDist settings
93
+ self.set_btn = QPushButton('set')
94
+ self.set_btn.setStyleSheet(self.button_style_sheet)
95
+ self.set_btn.clicked.connect(self.parent_window.set_selected_signals_for_event_detection)
96
+ self.layout.addWidget(self.set_btn)
97
+
98
+
99
+
100
+ class SegModelParamsWidget(CelldetectiveWidget):
101
+
102
+ def __init__(self, parent_window=None, model_name='SD_versatile_fluo', *args, **kwargs):
103
+
104
+ super().__init__(*args)
105
+ self.setWindowTitle('Channels')
106
+ self.parent_window = parent_window
107
+ self.model_name = model_name
108
+ self.locate_model_path()
109
+ self.required_channels = self.input_config["channels"]
110
+ self.onlyFloat = QDoubleValidator()
111
+
112
+ # Setting up references to parent window attributes
113
+ if hasattr(self.parent_window.parent_window, 'locate_image'):
114
+ self.attr_parent = self.parent_window.parent_window
115
+ elif hasattr(self.parent_window.parent_window.parent_window, 'locate_image'):
116
+ self.attr_parent = self.parent_window.parent_window.parent_window
117
+ else:
118
+ self.attr_parent = self.parent_window.parent_window.parent_window.parent_window
119
+
120
+ # Set up layout and widgets
121
+ self.layout = QVBoxLayout()
122
+ self.populate_widgets()
123
+ self.setLayout(self.layout)
124
+ center_window(self)
125
+
126
+ def locate_model_path(self):
127
+
128
+ self.model_complete_path = locate_segmentation_model(self.model_name)
129
+ if self.model_complete_path is None:
130
+ print('Model could not be found. Abort.')
131
+ self.abort_process()
132
+ else:
133
+ print(f'Model path: {self.model_complete_path}...')
134
+
135
+ if not os.path.exists(self.model_complete_path+"config_input.json"):
136
+ print('The configuration for the inputs to the model could not be located. Abort.')
137
+ self.abort_process()
138
+
139
+ with open(self.model_complete_path+"config_input.json") as config_file:
140
+ self.input_config = json.load(config_file)
141
+
142
+ def populate_widgets(self):
143
+
144
+ self.n_channels = len(self.required_channels)
145
+ self.channel_cbs = [QComboBox() for i in range(self.n_channels)]
146
+
147
+ # Button to view the current stack with a scale bar
148
+ self.view_diameter_btn = QPushButton()
149
+ self.view_diameter_btn.setStyleSheet(self.button_select_all)
150
+ self.view_diameter_btn.setIcon(icon(MDI6.image_check, color="black"))
151
+ self.view_diameter_btn.setToolTip("View stack.")
152
+ self.view_diameter_btn.setIconSize(QSize(20, 20))
153
+ self.view_diameter_btn.clicked.connect(self.view_current_stack_with_scale_bar)
154
+
155
+ # Line edit for entering cell diameter
156
+ self.diameter_le = ThresholdLineEdit(init_value=40, connected_buttons=[self.view_diameter_btn],placeholder='cell diameter in µm', value_type='float')
157
+
158
+ available_channels = list(self.attr_parent.exp_channels)+['None']
159
+ # Populate the comboboxes with available channels from the experiment
160
+ for k in range(self.n_channels):
161
+ hbox_channel = QHBoxLayout()
162
+ hbox_channel.addWidget(QLabel(f'channel {k+1}: '), 33)
163
+
164
+ ch_vbox = QVBoxLayout()
165
+ ch_vbox.addWidget(QLabel(f'Req: {self.required_channels[k]}'), alignment=Qt.AlignLeft)
166
+ ch_vbox.addWidget(self.channel_cbs[k])
167
+
168
+ self.channel_cbs[k].addItems(available_channels) #Give none option for more than one channel input
169
+ idx = self.channel_cbs[k].findText(self.required_channels[k])
170
+
171
+ if idx>=0:
172
+ self.channel_cbs[k].setCurrentIndex(idx)
173
+ else:
174
+ self.channel_cbs[k].setCurrentIndex(len(available_channels)-1)
175
+
176
+ hbox_channel.addLayout(ch_vbox, 66)
177
+ self.layout.addLayout(hbox_channel)
178
+
179
+ if 'cell_size_um' in self.input_config:
180
+
181
+ # Layout for diameter input and button
182
+ hbox = QHBoxLayout()
183
+ hbox.addWidget(QLabel('cell size [µm]: '), 33)
184
+ hbox.addWidget(self.diameter_le, 61)
185
+ hbox.addWidget(self.view_diameter_btn)
186
+ self.layout.addLayout(hbox)
187
+
188
+ self.diameter_le.set_threshold(self.input_config['cell_size_um'])
189
+
190
+ # size_hbox = QHBoxLayout()
191
+ # size_hbox.addWidget(QLabel('cell size [µm]: '), 33)
192
+ # self.size_le = QLineEdit(str(self.input_config['cell_size_um']).replace('.',','))
193
+ # self.size_le.setValidator(self.onlyFloat)
194
+ # size_hbox.addWidget(self.size_le, 66)
195
+ # self.layout.addLayout(size_hbox)
196
+
197
+ # Button to apply the StarDist settings
198
+ self.set_btn = QPushButton('set')
199
+ self.set_btn.setStyleSheet(self.button_style_sheet)
200
+ self.set_btn.clicked.connect(self.parent_window.set_selected_channels_for_segmentation)
201
+ self.layout.addWidget(self.set_btn)
202
+
203
+ def view_current_stack_with_scale_bar(self):
204
+
205
+ """
206
+ Displays the current image stack with a scale bar, allowing users to visually estimate cell diameters.
207
+ """
208
+
209
+ self.attr_parent.locate_image()
210
+ if self.attr_parent.current_stack is not None:
211
+ max_size = np.amax([self.attr_parent.shape_x, self.attr_parent.shape_y])
212
+ self.viewer = CellSizeViewer(
213
+ initial_diameter = float(self.diameter_le.text().replace(',', '.')),
214
+ parent_le = self.diameter_le,
215
+ stack_path=self.attr_parent.current_stack,
216
+ window_title=f'Position {self.attr_parent.position_list.currentText()}',
217
+ diameter_slider_range=(0,max_size*self.attr_parent.PxToUm),
218
+ frame_slider = True,
219
+ contrast_slider = True,
220
+ channel_cb = True,
221
+ channel_names = self.attr_parent.exp_channels,
222
+ n_channels = self.attr_parent.nbr_channels,
223
+ PxToUm = self.attr_parent.PxToUm,
224
+ )
225
+ self.viewer.show()
226
+
227
+
228
+ class StarDistParamsWidget(CelldetectiveWidget):
21
229
 
22
230
  """
23
231
  A widget to configure parameters for StarDist segmentation.
@@ -101,7 +309,7 @@ class StarDistParamsWidget(QWidget, Styles):
101
309
  self.layout.addWidget(self.set_stardist_scale_btn)
102
310
 
103
311
 
104
- class CellposeParamsWidget(QWidget, Styles):
312
+ class CellposeParamsWidget(CelldetectiveWidget):
105
313
 
106
314
  """
107
315
  A widget to configure parameters for Cellpose segmentation, allowing users to set the cell diameter,
@@ -204,7 +412,7 @@ class CellposeParamsWidget(QWidget, Styles):
204
412
 
205
413
  # Flow threshold slider
206
414
  self.flow_slider = QLabeledDoubleSlider()
207
- self.flow_slider.setOrientation(1)
415
+ self.flow_slider.setOrientation(Qt.Horizontal)
208
416
  self.flow_slider.setRange(-6,6)
209
417
  self.flow_slider.setValue(0.4)
210
418
  hbox = QHBoxLayout()
@@ -214,7 +422,7 @@ class CellposeParamsWidget(QWidget, Styles):
214
422
 
215
423
  # Cell probability threshold slider
216
424
  self.cellprob_slider = QLabeledDoubleSlider()
217
- self.cellprob_slider.setOrientation(1)
425
+ self.cellprob_slider.setOrientation(Qt.Horizontal)
218
426
  self.cellprob_slider.setRange(-6,6)
219
427
  self.cellprob_slider.setValue(0.)
220
428
  hbox = QHBoxLayout()
@@ -236,18 +444,20 @@ class CellposeParamsWidget(QWidget, Styles):
236
444
 
237
445
  self.attr_parent.locate_image()
238
446
  if self.attr_parent.current_stack is not None:
447
+ max_size = np.amax([self.attr_parent.shape_x, self.attr_parent.shape_y])
239
448
  self.viewer = CellSizeViewer(
240
- initial_diameter = float(self.diameter_le.text().replace(',', '.')),
241
- parent_le = self.diameter_le,
242
- stack_path=self.attr_parent.current_stack,
243
- window_title=f'Position {self.attr_parent.position_list.currentText()}',
244
- frame_slider = True,
245
- contrast_slider = True,
246
- channel_cb = True,
247
- channel_names = self.attr_parent.exp_channels,
248
- n_channels = self.attr_parent.nbr_channels,
249
- PxToUm = 1,
250
- )
449
+ initial_diameter = float(self.diameter_le.text().replace(',', '.')),
450
+ parent_le = self.diameter_le,
451
+ stack_path=self.attr_parent.current_stack,
452
+ window_title=f'Position {self.attr_parent.position_list.currentText()}',
453
+ diameter_slider_range=(0, max_size),
454
+ frame_slider = True,
455
+ contrast_slider = True,
456
+ channel_cb = True,
457
+ channel_names = self.attr_parent.exp_channels,
458
+ n_channels = self.attr_parent.nbr_channels,
459
+ PxToUm = 1,
460
+ )
251
461
  self.viewer.show()
252
462
 
253
463
  class ChannelNormGenerator(QVBoxLayout, Styles):
@@ -672,7 +882,7 @@ class BackgroundFitCorrectionLayout(QGridLayout, Styles):
672
882
  else:
673
883
  clip = False
674
884
 
675
- corrected_stack = correct_background_model(self.attr_parent.exp_dir,
885
+ corrected_stack = correct_background_model(self.attr_parent.exp_dir,
676
886
  well_option=self.attr_parent.well_list.getSelectedIndices(), #+1 ??
677
887
  position_option=self.attr_parent.position_list.getSelectedIndices(), #+1??
678
888
  target_channel=self.channels_cb.currentText(),
@@ -687,14 +897,18 @@ class BackgroundFitCorrectionLayout(QGridLayout, Styles):
687
897
  show_progress_per_pos = False,
688
898
  )
689
899
 
690
- self.viewer = StackVisualizer(
691
- stack=corrected_stack[0],
692
- window_title='Corrected channel',
693
- target_channel=self.channels_cb.currentIndex(),
694
- frame_slider = True,
695
- contrast_slider = True
696
- )
697
- self.viewer.show()
900
+ if corrected_stack:
901
+ self.viewer = StackVisualizer(
902
+ stack=corrected_stack[0],
903
+ window_title='Corrected channel',
904
+ target_channel=self.channels_cb.currentIndex(),
905
+ frame_slider = True,
906
+ contrast_slider = True
907
+ )
908
+ self.viewer.show()
909
+ else:
910
+ print("Corrected stack could not be generated... No stack available...")
911
+
698
912
 
699
913
 
700
914
  class LocalCorrectionLayout(BackgroundFitCorrectionLayout):
@@ -864,7 +1078,7 @@ class ProtocolDesignerLayout(QVBoxLayout, Styles):
864
1078
  self.tabs.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
865
1079
 
866
1080
  for k in range(len(self.tab_layouts)):
867
- wg = QWidget()
1081
+ wg = CelldetectiveWidget()
868
1082
  self.tab_layouts[k].parent_window = self
869
1083
  wg.setLayout(self.tab_layouts[k])
870
1084
  self.tabs.addTab(wg, self.tab_names[k])
@@ -1120,6 +1334,8 @@ class BackgroundModelFreeCorrectionLayout(QGridLayout, Styles):
1120
1334
  for c in self.coef_widgets:
1121
1335
  c.setEnabled(False)
1122
1336
 
1337
+ self.interpolate_check = QCheckBox("interpolate NaNs")
1338
+
1123
1339
  def add_to_layout(self):
1124
1340
 
1125
1341
  channel_layout = QHBoxLayout()
@@ -1173,13 +1389,23 @@ class BackgroundModelFreeCorrectionLayout(QGridLayout, Styles):
1173
1389
  coef_nbr_layout.addWidget(self.nbr_coef_le, 75)
1174
1390
  self.addLayout(coef_nbr_layout, 7,0,1,3)
1175
1391
 
1392
+ offset_layout = QHBoxLayout()
1393
+ offset_layout.addWidget(QLabel("Offset: "), 25)
1394
+ self.camera_offset_le = QLineEdit("0")
1395
+ self.camera_offset_le.setPlaceholderText('camera black level')
1396
+ self.camera_offset_le.setValidator(QDoubleValidator())
1397
+ offset_layout.addWidget(self.camera_offset_le, 75)
1398
+ self.addLayout(offset_layout, 8, 0, 1, 3)
1399
+
1176
1400
  self.operation_layout = OperationLayout()
1177
- self.addLayout(self.operation_layout, 8, 0, 1, 3)
1401
+ self.addLayout(self.operation_layout, 9, 0, 1, 3)
1402
+
1403
+ self.addWidget(self.interpolate_check, 10, 0, 1, 1)
1178
1404
 
1179
1405
  correction_layout = QHBoxLayout()
1180
1406
  correction_layout.addWidget(self.add_correction_btn, 95)
1181
1407
  correction_layout.addWidget(self.corrected_stack_viewer_btn, 5)
1182
- self.addLayout(correction_layout, 9, 0, 1, 3)
1408
+ self.addLayout(correction_layout, 11, 0, 1, 3)
1183
1409
 
1184
1410
  # verticalSpacer = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding)
1185
1411
  # self.addItem(verticalSpacer, 5, 0, 1, 3)
@@ -1221,6 +1447,11 @@ class BackgroundModelFreeCorrectionLayout(QGridLayout, Styles):
1221
1447
  clip = True
1222
1448
  else:
1223
1449
  clip = False
1450
+
1451
+ if self.camera_offset_le.text()=="":
1452
+ offset = None
1453
+ else:
1454
+ offset = float(self.camera_offset_le.text().replace(",","."))
1224
1455
 
1225
1456
  self.instructions = {
1226
1457
  "target_channel": self.channels_cb.currentText(),
@@ -1232,7 +1463,9 @@ class BackgroundModelFreeCorrectionLayout(QGridLayout, Styles):
1232
1463
  "opt_coef_range": opt_coef_range,
1233
1464
  "opt_coef_nbr": opt_coef_nbr,
1234
1465
  "operation": operation,
1235
- "clip": clip
1466
+ "clip": clip,
1467
+ "offset": offset,
1468
+ "fix_nan": self.interpolate_check.isChecked(),
1236
1469
  }
1237
1470
 
1238
1471
  def set_target_channel(self):
@@ -1308,6 +1541,7 @@ class BackgroundModelFreeCorrectionLayout(QGridLayout, Styles):
1308
1541
  clip = clip,
1309
1542
  export= False,
1310
1543
  return_stacks=True,
1544
+ fix_nan=self.interpolate_check.isChecked(),
1311
1545
  show_progress_per_well = True,
1312
1546
  show_progress_per_pos = False,
1313
1547
  )