celldetective 1.4.2__py3-none-any.whl → 1.5.0b0__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.
- celldetective/__init__.py +25 -0
- celldetective/__main__.py +62 -43
- celldetective/_version.py +1 -1
- celldetective/extra_properties.py +477 -399
- celldetective/filters.py +192 -97
- celldetective/gui/InitWindow.py +541 -411
- celldetective/gui/__init__.py +0 -15
- celldetective/gui/about.py +44 -39
- celldetective/gui/analyze_block.py +120 -84
- celldetective/gui/base/__init__.py +0 -0
- celldetective/gui/base/channel_norm_generator.py +335 -0
- celldetective/gui/base/components.py +249 -0
- celldetective/gui/base/feature_choice.py +92 -0
- celldetective/gui/base/figure_canvas.py +52 -0
- celldetective/gui/base/list_widget.py +133 -0
- celldetective/gui/{styles.py → base/styles.py} +92 -36
- celldetective/gui/base/utils.py +33 -0
- celldetective/gui/base_annotator.py +900 -767
- celldetective/gui/classifier_widget.py +6 -22
- celldetective/gui/configure_new_exp.py +777 -671
- celldetective/gui/control_panel.py +635 -524
- celldetective/gui/dynamic_progress.py +449 -0
- celldetective/gui/event_annotator.py +2023 -1662
- celldetective/gui/generic_signal_plot.py +1292 -944
- celldetective/gui/gui_utils.py +899 -1289
- celldetective/gui/interactions_block.py +658 -0
- celldetective/gui/interactive_timeseries_viewer.py +447 -0
- celldetective/gui/json_readers.py +48 -15
- celldetective/gui/layouts/__init__.py +5 -0
- celldetective/gui/layouts/background_model_free_layout.py +537 -0
- celldetective/gui/layouts/channel_offset_layout.py +134 -0
- celldetective/gui/layouts/local_correction_layout.py +91 -0
- celldetective/gui/layouts/model_fit_layout.py +372 -0
- celldetective/gui/layouts/operation_layout.py +68 -0
- celldetective/gui/layouts/protocol_designer_layout.py +96 -0
- celldetective/gui/pair_event_annotator.py +3130 -2435
- celldetective/gui/plot_measurements.py +586 -267
- celldetective/gui/plot_signals_ui.py +724 -506
- celldetective/gui/preprocessing_block.py +395 -0
- celldetective/gui/process_block.py +1678 -1831
- celldetective/gui/seg_model_loader.py +580 -473
- celldetective/gui/settings/__init__.py +0 -7
- celldetective/gui/settings/_cellpose_model_params.py +181 -0
- celldetective/gui/settings/_event_detection_model_params.py +95 -0
- celldetective/gui/settings/_segmentation_model_params.py +159 -0
- celldetective/gui/settings/_settings_base.py +77 -65
- celldetective/gui/settings/_settings_event_model_training.py +752 -526
- celldetective/gui/settings/_settings_measurements.py +1133 -964
- celldetective/gui/settings/_settings_neighborhood.py +574 -488
- celldetective/gui/settings/_settings_segmentation_model_training.py +779 -564
- celldetective/gui/settings/_settings_signal_annotator.py +329 -305
- celldetective/gui/settings/_settings_tracking.py +1304 -1094
- celldetective/gui/settings/_stardist_model_params.py +98 -0
- celldetective/gui/survival_ui.py +422 -312
- celldetective/gui/tableUI.py +1665 -1701
- celldetective/gui/table_ops/_maths.py +295 -0
- celldetective/gui/table_ops/_merge_groups.py +140 -0
- celldetective/gui/table_ops/_merge_one_hot.py +95 -0
- celldetective/gui/table_ops/_query_table.py +43 -0
- celldetective/gui/table_ops/_rename_col.py +44 -0
- celldetective/gui/thresholds_gui.py +382 -179
- celldetective/gui/viewers/__init__.py +0 -0
- celldetective/gui/viewers/base_viewer.py +700 -0
- celldetective/gui/viewers/channel_offset_viewer.py +331 -0
- celldetective/gui/viewers/contour_viewer.py +394 -0
- celldetective/gui/viewers/size_viewer.py +153 -0
- celldetective/gui/viewers/spot_detection_viewer.py +341 -0
- celldetective/gui/viewers/threshold_viewer.py +309 -0
- celldetective/gui/workers.py +304 -126
- celldetective/log_manager.py +92 -0
- celldetective/measure.py +1895 -1478
- celldetective/napari/__init__.py +0 -0
- celldetective/napari/utils.py +1025 -0
- celldetective/neighborhood.py +1914 -1448
- celldetective/preprocessing.py +1620 -1220
- celldetective/processes/__init__.py +0 -0
- celldetective/processes/background_correction.py +271 -0
- celldetective/processes/compute_neighborhood.py +894 -0
- celldetective/processes/detect_events.py +246 -0
- celldetective/processes/measure_cells.py +565 -0
- celldetective/processes/segment_cells.py +760 -0
- celldetective/processes/track_cells.py +435 -0
- celldetective/processes/train_segmentation_model.py +694 -0
- celldetective/processes/train_signal_model.py +265 -0
- celldetective/processes/unified_process.py +292 -0
- celldetective/regionprops/_regionprops.py +358 -317
- celldetective/relative_measurements.py +987 -710
- celldetective/scripts/measure_cells.py +313 -212
- celldetective/scripts/measure_relative.py +90 -46
- celldetective/scripts/segment_cells.py +165 -104
- celldetective/scripts/segment_cells_thresholds.py +96 -68
- celldetective/scripts/track_cells.py +198 -149
- celldetective/scripts/train_segmentation_model.py +324 -201
- celldetective/scripts/train_signal_model.py +87 -45
- celldetective/segmentation.py +844 -749
- celldetective/signals.py +3514 -2861
- celldetective/tracking.py +30 -15
- celldetective/utils/__init__.py +0 -0
- celldetective/utils/cellpose_utils/__init__.py +133 -0
- celldetective/utils/color_mappings.py +42 -0
- celldetective/utils/data_cleaning.py +630 -0
- celldetective/utils/data_loaders.py +450 -0
- celldetective/utils/dataset_helpers.py +207 -0
- celldetective/utils/downloaders.py +197 -0
- celldetective/utils/event_detection/__init__.py +8 -0
- celldetective/utils/experiment.py +1782 -0
- celldetective/utils/image_augmenters.py +308 -0
- celldetective/utils/image_cleaning.py +74 -0
- celldetective/utils/image_loaders.py +926 -0
- celldetective/utils/image_transforms.py +335 -0
- celldetective/utils/io.py +62 -0
- celldetective/utils/mask_cleaning.py +348 -0
- celldetective/utils/mask_transforms.py +5 -0
- celldetective/utils/masks.py +184 -0
- celldetective/utils/maths.py +351 -0
- celldetective/utils/model_getters.py +325 -0
- celldetective/utils/model_loaders.py +296 -0
- celldetective/utils/normalization.py +380 -0
- celldetective/utils/parsing.py +465 -0
- celldetective/utils/plots/__init__.py +0 -0
- celldetective/utils/plots/regression.py +53 -0
- celldetective/utils/resources.py +34 -0
- celldetective/utils/stardist_utils/__init__.py +104 -0
- celldetective/utils/stats.py +90 -0
- celldetective/utils/types.py +21 -0
- {celldetective-1.4.2.dist-info → celldetective-1.5.0b0.dist-info}/METADATA +1 -1
- celldetective-1.5.0b0.dist-info/RECORD +187 -0
- {celldetective-1.4.2.dist-info → celldetective-1.5.0b0.dist-info}/WHEEL +1 -1
- tests/gui/test_new_project.py +129 -117
- tests/gui/test_project.py +127 -79
- tests/test_filters.py +39 -15
- tests/test_notebooks.py +8 -0
- tests/test_tracking.py +232 -13
- tests/test_utils.py +123 -77
- celldetective/gui/base_components.py +0 -23
- celldetective/gui/layouts.py +0 -1602
- celldetective/gui/processes/compute_neighborhood.py +0 -594
- celldetective/gui/processes/measure_cells.py +0 -360
- celldetective/gui/processes/segment_cells.py +0 -499
- celldetective/gui/processes/track_cells.py +0 -303
- celldetective/gui/processes/train_segmentation_model.py +0 -270
- celldetective/gui/processes/train_signal_model.py +0 -108
- celldetective/gui/table_ops/merge_groups.py +0 -118
- celldetective/gui/viewers.py +0 -1354
- celldetective/io.py +0 -3663
- celldetective/utils.py +0 -3108
- celldetective-1.4.2.dist-info/RECORD +0 -123
- /celldetective/{gui/processes → processes}/downloader.py +0 -0
- {celldetective-1.4.2.dist-info → celldetective-1.5.0b0.dist-info}/entry_points.txt +0 -0
- {celldetective-1.4.2.dist-info → celldetective-1.5.0b0.dist-info}/licenses/LICENSE +0 -0
- {celldetective-1.4.2.dist-info → celldetective-1.5.0b0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,395 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import os
|
|
3
|
+
from glob import glob
|
|
4
|
+
|
|
5
|
+
import numpy as np
|
|
6
|
+
from PyQt5.QtCore import QSize, QTimer, Qt
|
|
7
|
+
from PyQt5.QtGui import QDoubleValidator, QIntValidator
|
|
8
|
+
from PyQt5.QtWidgets import (
|
|
9
|
+
QDialog,
|
|
10
|
+
QFrame,
|
|
11
|
+
QGridLayout,
|
|
12
|
+
QLabel,
|
|
13
|
+
QMessageBox,
|
|
14
|
+
QPushButton,
|
|
15
|
+
QVBoxLayout,
|
|
16
|
+
)
|
|
17
|
+
from fonticon_mdi6 import MDI6
|
|
18
|
+
from superqt.fonticon import icon
|
|
19
|
+
|
|
20
|
+
from celldetective import get_software_location
|
|
21
|
+
from celldetective.gui.base.styles import Styles
|
|
22
|
+
from celldetective.gui.base.utils import center_window
|
|
23
|
+
from celldetective.gui.gui_utils import help_generic
|
|
24
|
+
from celldetective.gui.layouts import (
|
|
25
|
+
BackgroundFitCorrectionLayout,
|
|
26
|
+
BackgroundModelFreeCorrectionLayout,
|
|
27
|
+
ChannelOffsetOptionsLayout,
|
|
28
|
+
ProtocolDesignerLayout,
|
|
29
|
+
)
|
|
30
|
+
from celldetective.utils.experiment import extract_experiment_channels
|
|
31
|
+
from celldetective import get_logger
|
|
32
|
+
|
|
33
|
+
logger = get_logger(__name__)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class PreprocessingPanel(QFrame, Styles):
|
|
37
|
+
|
|
38
|
+
def __init__(self, parent_window):
|
|
39
|
+
|
|
40
|
+
super().__init__()
|
|
41
|
+
self.parent_window = parent_window
|
|
42
|
+
self.exp_channels = self.parent_window.exp_channels
|
|
43
|
+
self.exp_dir = self.parent_window.exp_dir
|
|
44
|
+
self.wells = np.array(self.parent_window.wells, dtype=str)
|
|
45
|
+
exp_config = self.exp_dir + "config.ini"
|
|
46
|
+
self.channel_names, self.channels = extract_experiment_channels(self.exp_dir)
|
|
47
|
+
self.channel_names = np.array(self.channel_names)
|
|
48
|
+
self.background_correction = []
|
|
49
|
+
self.onlyFloat = QDoubleValidator()
|
|
50
|
+
self.onlyInt = QIntValidator()
|
|
51
|
+
|
|
52
|
+
self.setFrameStyle(QFrame.StyledPanel | QFrame.Raised)
|
|
53
|
+
self.grid = QGridLayout(self)
|
|
54
|
+
|
|
55
|
+
self.generate_header()
|
|
56
|
+
|
|
57
|
+
def generate_header(self):
|
|
58
|
+
"""
|
|
59
|
+
Read the mode and prepare a collapsable block to process a specific cell population.
|
|
60
|
+
|
|
61
|
+
"""
|
|
62
|
+
|
|
63
|
+
panel_title = QLabel(f"PREPROCESSING")
|
|
64
|
+
panel_title.setStyleSheet(
|
|
65
|
+
"""
|
|
66
|
+
font-weight: bold;
|
|
67
|
+
padding: 0px;
|
|
68
|
+
"""
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
self.grid.addWidget(panel_title, 0, 0, 1, 4, alignment=Qt.AlignCenter)
|
|
72
|
+
|
|
73
|
+
# self.select_all_btn = QPushButton()
|
|
74
|
+
# self.select_all_btn.setIcon(icon(MDI6.checkbox_blank_outline,color="black"))
|
|
75
|
+
# self.select_all_btn.setIconSize(QSize(20, 20))
|
|
76
|
+
# self.all_ticked = False
|
|
77
|
+
# #self.select_all_btn.clicked.connect(self.tick_all_actions)
|
|
78
|
+
# self.select_all_btn.setStyleSheet(self.button_select_all)
|
|
79
|
+
# self.grid.addWidget(self.select_all_btn, 0, 0, 1, 4, alignment=Qt.AlignLeft)
|
|
80
|
+
# self.to_disable.append(self.all_tc_actions)
|
|
81
|
+
|
|
82
|
+
self.collapse_btn = QPushButton()
|
|
83
|
+
self.collapse_btn.setIcon(icon(MDI6.chevron_down, color="black"))
|
|
84
|
+
self.collapse_btn.setIconSize(QSize(25, 25))
|
|
85
|
+
self.collapse_btn.setStyleSheet(self.button_select_all)
|
|
86
|
+
self.grid.addWidget(self.collapse_btn, 0, 0, 1, 4, alignment=Qt.AlignRight)
|
|
87
|
+
|
|
88
|
+
self.populate_contents()
|
|
89
|
+
|
|
90
|
+
self.grid.addWidget(self.ContentsFrame, 1, 0, 1, 4, alignment=Qt.AlignTop)
|
|
91
|
+
self.collapse_btn.clicked.connect(
|
|
92
|
+
lambda: self.ContentsFrame.setHidden(not self.ContentsFrame.isHidden())
|
|
93
|
+
)
|
|
94
|
+
self.collapse_btn.clicked.connect(self.collapse_advanced)
|
|
95
|
+
self.ContentsFrame.hide()
|
|
96
|
+
|
|
97
|
+
def collapse_advanced(self):
|
|
98
|
+
|
|
99
|
+
panels_open = [
|
|
100
|
+
not p.ContentsFrame.isHidden()
|
|
101
|
+
for p in self.parent_window.ProcessPopulations
|
|
102
|
+
]
|
|
103
|
+
interactions_open = not self.parent_window.NeighPanel.ContentsFrame.isHidden()
|
|
104
|
+
preprocessing_open = (
|
|
105
|
+
not self.parent_window.PreprocessingPanel.ContentsFrame.isHidden()
|
|
106
|
+
)
|
|
107
|
+
is_open = np.array(panels_open + [interactions_open, preprocessing_open])
|
|
108
|
+
|
|
109
|
+
if self.ContentsFrame.isHidden():
|
|
110
|
+
self.collapse_btn.setIcon(icon(MDI6.chevron_down, color="black"))
|
|
111
|
+
self.collapse_btn.setIconSize(QSize(20, 20))
|
|
112
|
+
if len(is_open[is_open]) == 0:
|
|
113
|
+
self.parent_window.scroll.setMinimumHeight(int(550))
|
|
114
|
+
self.parent_window.adjustSize()
|
|
115
|
+
else:
|
|
116
|
+
self.collapse_btn.setIcon(icon(MDI6.chevron_up, color="black"))
|
|
117
|
+
self.collapse_btn.setIconSize(QSize(20, 20))
|
|
118
|
+
self.parent_window.scroll.setMinimumHeight(
|
|
119
|
+
min(int(930), int(0.9 * self.parent_window.screen_height))
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
def safe_center():
|
|
123
|
+
try:
|
|
124
|
+
center_window(self.window())
|
|
125
|
+
except RuntimeError:
|
|
126
|
+
pass
|
|
127
|
+
|
|
128
|
+
try:
|
|
129
|
+
QTimer.singleShot(10, safe_center)
|
|
130
|
+
except:
|
|
131
|
+
pass
|
|
132
|
+
|
|
133
|
+
def populate_contents(self):
|
|
134
|
+
|
|
135
|
+
self.ContentsFrame = QFrame()
|
|
136
|
+
self.grid_contents = QGridLayout(self.ContentsFrame)
|
|
137
|
+
|
|
138
|
+
self.model_free_correction_layout = BackgroundModelFreeCorrectionLayout(self)
|
|
139
|
+
self.fit_correction_layout = BackgroundFitCorrectionLayout(self)
|
|
140
|
+
|
|
141
|
+
self.protocol_layout = ProtocolDesignerLayout(
|
|
142
|
+
parent_window=self,
|
|
143
|
+
tab_layouts=[self.fit_correction_layout, self.model_free_correction_layout],
|
|
144
|
+
tab_names=["Fit", "Model-free"],
|
|
145
|
+
title="BACKGROUND CORRECTION",
|
|
146
|
+
list_title="Corrections to apply:",
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
self.help_background_btn = QPushButton()
|
|
150
|
+
self.help_background_btn.setIcon(icon(MDI6.help_circle, color=self.help_color))
|
|
151
|
+
self.help_background_btn.setIconSize(QSize(20, 20))
|
|
152
|
+
self.help_background_btn.clicked.connect(self.help_background)
|
|
153
|
+
self.help_background_btn.setStyleSheet(self.button_select_all)
|
|
154
|
+
self.help_background_btn.setToolTip("Help.")
|
|
155
|
+
|
|
156
|
+
self.protocol_layout.title_layout.addWidget(
|
|
157
|
+
self.help_background_btn, 5, alignment=Qt.AlignRight
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
self.channel_offset_correction_layout = QVBoxLayout()
|
|
161
|
+
|
|
162
|
+
self.channel_shift_lbl = QLabel("CHANNEL OFFSET CORRECTION")
|
|
163
|
+
self.channel_shift_lbl.setStyleSheet(
|
|
164
|
+
"""
|
|
165
|
+
font-weight: bold;
|
|
166
|
+
padding: 0px;
|
|
167
|
+
"""
|
|
168
|
+
)
|
|
169
|
+
self.channel_offset_correction_layout.addWidget(
|
|
170
|
+
self.channel_shift_lbl, alignment=Qt.AlignCenter
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
self.channel_offset_options_layout = ChannelOffsetOptionsLayout(self)
|
|
174
|
+
self.channel_offset_correction_layout.addLayout(
|
|
175
|
+
self.channel_offset_options_layout
|
|
176
|
+
)
|
|
177
|
+
|
|
178
|
+
self.protocol_layout.correction_layout.addWidget(QLabel(""))
|
|
179
|
+
self.protocol_layout.correction_layout.addLayout(
|
|
180
|
+
self.channel_offset_correction_layout
|
|
181
|
+
)
|
|
182
|
+
|
|
183
|
+
self.grid_contents.addLayout(self.protocol_layout, 0, 0, 1, 4)
|
|
184
|
+
|
|
185
|
+
self.submit_preprocessing_btn = QPushButton("Submit")
|
|
186
|
+
self.submit_preprocessing_btn.setStyleSheet(self.button_style_sheet)
|
|
187
|
+
self.submit_preprocessing_btn.clicked.connect(self.launch_preprocessing)
|
|
188
|
+
|
|
189
|
+
self.grid_contents.addWidget(self.submit_preprocessing_btn, 1, 0, 1, 4)
|
|
190
|
+
|
|
191
|
+
def add_offset_instructions_to_parent_list(self):
|
|
192
|
+
logger.info("adding instructions")
|
|
193
|
+
|
|
194
|
+
def launch_preprocessing(self):
|
|
195
|
+
|
|
196
|
+
msgBox1 = QMessageBox()
|
|
197
|
+
msgBox1.setIcon(QMessageBox.Question)
|
|
198
|
+
msgBox1.setText(
|
|
199
|
+
"Do you want to apply the preprocessing\nto all wells and positions?"
|
|
200
|
+
)
|
|
201
|
+
msgBox1.setWindowTitle("Selection")
|
|
202
|
+
msgBox1.setStandardButtons(
|
|
203
|
+
QMessageBox.Yes | QMessageBox.No | QMessageBox.Cancel
|
|
204
|
+
)
|
|
205
|
+
returnValue = msgBox1.exec()
|
|
206
|
+
if returnValue == QMessageBox.Cancel:
|
|
207
|
+
return None
|
|
208
|
+
elif returnValue == QMessageBox.Yes:
|
|
209
|
+
self.parent_window.well_list.selectAll()
|
|
210
|
+
self.parent_window.position_list.selectAll()
|
|
211
|
+
elif returnValue == QMessageBox.No:
|
|
212
|
+
msgBox2 = QMessageBox()
|
|
213
|
+
msgBox2.setIcon(QMessageBox.Question)
|
|
214
|
+
msgBox2.setText(
|
|
215
|
+
"Do you want to apply the preprocessing\nto the positions selected at the top only?"
|
|
216
|
+
)
|
|
217
|
+
msgBox2.setWindowTitle("Selection")
|
|
218
|
+
msgBox2.setStandardButtons(
|
|
219
|
+
QMessageBox.Yes | QMessageBox.No | QMessageBox.Cancel
|
|
220
|
+
)
|
|
221
|
+
returnValue = msgBox2.exec()
|
|
222
|
+
if returnValue == QMessageBox.Cancel:
|
|
223
|
+
return None
|
|
224
|
+
if returnValue == QMessageBox.No:
|
|
225
|
+
return None
|
|
226
|
+
|
|
227
|
+
logger.info("Proceed with correction...")
|
|
228
|
+
|
|
229
|
+
# if self.parent_window.well_list.currentText()=='*':
|
|
230
|
+
# well_option = "*"
|
|
231
|
+
# else:
|
|
232
|
+
well_option = self.parent_window.well_list.getSelectedIndices()
|
|
233
|
+
position_option = self.parent_window.position_list.getSelectedIndices()
|
|
234
|
+
|
|
235
|
+
for k, correction_protocol in enumerate(self.protocol_layout.protocols):
|
|
236
|
+
|
|
237
|
+
movie_prefix = None
|
|
238
|
+
export_prefix = "Corrected"
|
|
239
|
+
if k > 0:
|
|
240
|
+
# switch source stack to cumulate multi-channel preprocessing
|
|
241
|
+
movie_prefix = "Corrected"
|
|
242
|
+
export_prefix = None
|
|
243
|
+
|
|
244
|
+
if correction_protocol["correction_type"] == "model-free":
|
|
245
|
+
print(f"Model-free correction; {movie_prefix=} {export_prefix=}")
|
|
246
|
+
from celldetective.gui.workers import ProgressWindow
|
|
247
|
+
from celldetective.processes.background_correction import (
|
|
248
|
+
BackgroundCorrectionProcess,
|
|
249
|
+
)
|
|
250
|
+
|
|
251
|
+
process_args = {
|
|
252
|
+
"exp_dir": self.exp_dir,
|
|
253
|
+
"well_option": well_option,
|
|
254
|
+
"position_option": position_option,
|
|
255
|
+
"movie_prefix": movie_prefix,
|
|
256
|
+
"export_prefix": export_prefix,
|
|
257
|
+
"export": True,
|
|
258
|
+
"return_stacks": False,
|
|
259
|
+
"activation_protocol": [["gauss", 2], ["std", 4]],
|
|
260
|
+
"correction_type": "model-free", # Explicitly set type
|
|
261
|
+
}
|
|
262
|
+
process_args.update(correction_protocol)
|
|
263
|
+
|
|
264
|
+
self.job = ProgressWindow(
|
|
265
|
+
BackgroundCorrectionProcess,
|
|
266
|
+
parent_window=None,
|
|
267
|
+
title="Model-Free Background Correction",
|
|
268
|
+
position_info=False,
|
|
269
|
+
process_args=process_args,
|
|
270
|
+
)
|
|
271
|
+
result = self.job.exec_()
|
|
272
|
+
if result == QDialog.Rejected:
|
|
273
|
+
logger.info("Background correction cancelled.")
|
|
274
|
+
return None
|
|
275
|
+
|
|
276
|
+
elif correction_protocol["correction_type"] == "fit":
|
|
277
|
+
print(
|
|
278
|
+
f"Fit correction; {movie_prefix=} {export_prefix=} {correction_protocol=}"
|
|
279
|
+
)
|
|
280
|
+
from celldetective.gui.workers import ProgressWindow
|
|
281
|
+
from celldetective.processes.background_correction import (
|
|
282
|
+
BackgroundCorrectionProcess,
|
|
283
|
+
)
|
|
284
|
+
|
|
285
|
+
process_args = {
|
|
286
|
+
"exp_dir": self.exp_dir,
|
|
287
|
+
"well_option": well_option,
|
|
288
|
+
"position_option": position_option,
|
|
289
|
+
"movie_prefix": movie_prefix,
|
|
290
|
+
"export_prefix": export_prefix,
|
|
291
|
+
"export": True,
|
|
292
|
+
"return_stacks": False,
|
|
293
|
+
"activation_protocol": [["gauss", 2], ["std", 4]],
|
|
294
|
+
}
|
|
295
|
+
process_args.update(correction_protocol)
|
|
296
|
+
|
|
297
|
+
self.job = ProgressWindow(
|
|
298
|
+
BackgroundCorrectionProcess,
|
|
299
|
+
parent_window=None,
|
|
300
|
+
title="Fit Background Correction",
|
|
301
|
+
position_info=False,
|
|
302
|
+
process_args=process_args,
|
|
303
|
+
)
|
|
304
|
+
result = self.job.exec_()
|
|
305
|
+
if result == QDialog.Rejected:
|
|
306
|
+
logger.info("Background correction cancelled.")
|
|
307
|
+
return None
|
|
308
|
+
elif correction_protocol["correction_type"] == "offset":
|
|
309
|
+
logger.info(
|
|
310
|
+
f"Offset correction; {movie_prefix=} {export_prefix=} {correction_protocol=}"
|
|
311
|
+
)
|
|
312
|
+
from celldetective.gui.workers import ProgressWindow
|
|
313
|
+
from celldetective.processes.background_correction import (
|
|
314
|
+
BackgroundCorrectionProcess,
|
|
315
|
+
)
|
|
316
|
+
|
|
317
|
+
process_args = {
|
|
318
|
+
"exp_dir": self.exp_dir,
|
|
319
|
+
"well_option": well_option,
|
|
320
|
+
"position_option": position_option,
|
|
321
|
+
"movie_prefix": movie_prefix,
|
|
322
|
+
"export_prefix": export_prefix,
|
|
323
|
+
"export": True,
|
|
324
|
+
"return_stacks": False,
|
|
325
|
+
# Offset specific args if any, otherwise they are in correction_protocol
|
|
326
|
+
}
|
|
327
|
+
process_args.update(correction_protocol)
|
|
328
|
+
|
|
329
|
+
self.job = ProgressWindow(
|
|
330
|
+
BackgroundCorrectionProcess,
|
|
331
|
+
parent_window=None,
|
|
332
|
+
title="Offset Correction",
|
|
333
|
+
position_info=False,
|
|
334
|
+
process_args=process_args,
|
|
335
|
+
)
|
|
336
|
+
result = self.job.exec_()
|
|
337
|
+
if result == QDialog.Rejected:
|
|
338
|
+
logger.info("Correction cancelled.")
|
|
339
|
+
return None
|
|
340
|
+
logger.info("Done.")
|
|
341
|
+
|
|
342
|
+
def locate_image(self):
|
|
343
|
+
"""
|
|
344
|
+
Load the first frame of the first movie found in the experiment folder as a sample.
|
|
345
|
+
"""
|
|
346
|
+
|
|
347
|
+
logger.info(f"{self.parent_window.pos}")
|
|
348
|
+
movies = glob(
|
|
349
|
+
self.parent_window.pos
|
|
350
|
+
+ os.sep.join(["movie", f"{self.parent_window.movie_prefix}*.tif"])
|
|
351
|
+
)
|
|
352
|
+
|
|
353
|
+
if len(movies) == 0:
|
|
354
|
+
msgBox = QMessageBox()
|
|
355
|
+
msgBox.setIcon(QMessageBox.Warning)
|
|
356
|
+
msgBox.setText("Please select a position containing a movie...")
|
|
357
|
+
msgBox.setWindowTitle("Warning")
|
|
358
|
+
msgBox.setStandardButtons(QMessageBox.Ok)
|
|
359
|
+
returnValue = msgBox.exec()
|
|
360
|
+
if returnValue == QMessageBox.Ok:
|
|
361
|
+
self.current_stack = None
|
|
362
|
+
return None
|
|
363
|
+
else:
|
|
364
|
+
self.current_stack = movies[0]
|
|
365
|
+
|
|
366
|
+
def help_background(self):
|
|
367
|
+
"""
|
|
368
|
+
Helper to choose a proper cell population structure.
|
|
369
|
+
"""
|
|
370
|
+
|
|
371
|
+
dict_path = os.sep.join(
|
|
372
|
+
[
|
|
373
|
+
get_software_location(),
|
|
374
|
+
"celldetective",
|
|
375
|
+
"gui",
|
|
376
|
+
"help",
|
|
377
|
+
"preprocessing.json",
|
|
378
|
+
]
|
|
379
|
+
)
|
|
380
|
+
|
|
381
|
+
with open(dict_path) as f:
|
|
382
|
+
d = json.load(f)
|
|
383
|
+
|
|
384
|
+
suggestion = help_generic(d)
|
|
385
|
+
if isinstance(suggestion, str):
|
|
386
|
+
logger.info(f"{suggestion=}")
|
|
387
|
+
msgBox = QMessageBox()
|
|
388
|
+
msgBox.setIcon(QMessageBox.Information)
|
|
389
|
+
msgBox.setTextFormat(Qt.RichText)
|
|
390
|
+
msgBox.setText(suggestion)
|
|
391
|
+
msgBox.setWindowTitle("Info")
|
|
392
|
+
msgBox.setStandardButtons(QMessageBox.Ok)
|
|
393
|
+
returnValue = msgBox.exec()
|
|
394
|
+
if returnValue == QMessageBox.Ok:
|
|
395
|
+
return None
|