small-fish-gui 1.10.4__py3-none-any.whl → 2.0.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- small_fish_gui/README.md +54 -69
- small_fish_gui/__init__.py +9 -3
- small_fish_gui/__main__.py +1 -1
- small_fish_gui/batch/integrity.py +8 -1
- small_fish_gui/batch/output.py +16 -0
- small_fish_gui/batch/pipeline.py +43 -24
- small_fish_gui/batch/prompt.py +44 -26
- small_fish_gui/batch/update.py +19 -3
- small_fish_gui/batch/utils.py +2 -0
- small_fish_gui/batch/values.txt +5 -5
- small_fish_gui/default_values.py +51 -0
- small_fish_gui/gui/__init__.py +3 -1
- small_fish_gui/gui/_napari_widgets.py +15 -4
- small_fish_gui/gui/layout.py +123 -54
- small_fish_gui/gui/napari_visualiser.py +12 -8
- small_fish_gui/gui/prompts.py +61 -74
- small_fish_gui/gui/tooltips.py +15 -0
- small_fish_gui/hints.py +23 -4
- small_fish_gui/illustrations/DetectionVitrine_filtre.png +0 -0
- small_fish_gui/illustrations/DetectionVitrine_signal.png +0 -0
- small_fish_gui/illustrations/FocciVitrine.png +0 -0
- small_fish_gui/illustrations/FocciVitrine_no_spots.png +0 -0
- small_fish_gui/illustrations/Segmentation2D.png +0 -0
- small_fish_gui/illustrations/Segmentation2D_with_labels.png +0 -0
- small_fish_gui/logo.png +0 -0
- small_fish_gui/{pipeline/main.py → main_menu.py} +16 -15
- small_fish_gui/pipeline/_colocalisation.py +60 -41
- small_fish_gui/pipeline/_preprocess.py +13 -12
- small_fish_gui/pipeline/actions.py +102 -14
- small_fish_gui/pipeline/detection.py +5 -1
- small_fish_gui/pipeline/segmentation.py +206 -73
- small_fish_gui/pipeline/spots.py +129 -5
- small_fish_gui/pipeline/testing.ipynb +1571 -2
- small_fish_gui/requirements.txt +4 -4
- {small_fish_gui-1.10.4.dist-info → small_fish_gui-2.0.2.dist-info}/METADATA +14 -16
- small_fish_gui-2.0.2.dist-info/RECORD +59 -0
- small_fish_gui-1.10.4.dist-info/RECORD +0 -49
- {small_fish_gui-1.10.4.dist-info → small_fish_gui-2.0.2.dist-info}/WHEEL +0 -0
- {small_fish_gui-1.10.4.dist-info → small_fish_gui-2.0.2.dist-info}/licenses/LICENSE +0 -0
|
@@ -14,6 +14,8 @@ from ._preprocess import ask_input_parameters
|
|
|
14
14
|
from ._preprocess import map_channels, reorder_shape, reorder_image_stack
|
|
15
15
|
from matplotlib.colors import ListedColormap
|
|
16
16
|
|
|
17
|
+
import small_fish_gui.default_values as default
|
|
18
|
+
|
|
17
19
|
import matplotlib as mpl
|
|
18
20
|
import cellpose.models as models
|
|
19
21
|
import numpy as np
|
|
@@ -55,19 +57,26 @@ def launch_segmentation(user_parameters: pipeline_parameters, nucleus_label, cyt
|
|
|
55
57
|
|
|
56
58
|
while True : # Loop if show_segmentation
|
|
57
59
|
#Default parameters
|
|
58
|
-
cyto_model_name = segmentation_parameters.setdefault('cyto_model_name',
|
|
59
|
-
cyto_size = segmentation_parameters.setdefault('
|
|
60
|
-
cytoplasm_channel = segmentation_parameters.setdefault('
|
|
61
|
-
nucleus_model_name = segmentation_parameters.setdefault('nucleus_model_name',
|
|
62
|
-
nucleus_size = segmentation_parameters.setdefault('
|
|
63
|
-
nucleus_channel = segmentation_parameters.setdefault('
|
|
60
|
+
cyto_model_name = segmentation_parameters.setdefault('cyto_model_name', default.CYTO_MODEL)
|
|
61
|
+
cyto_size = segmentation_parameters.setdefault('cytoplasm_diameter', default.CYTO_DIAMETER)
|
|
62
|
+
cytoplasm_channel = segmentation_parameters.setdefault('cytoplasm_channel', default.CHANNEL)
|
|
63
|
+
nucleus_model_name = segmentation_parameters.setdefault('nucleus_model_name', default.NUC_MODEL)
|
|
64
|
+
nucleus_size = segmentation_parameters.setdefault('nucleus_diameter', default.NUC_DIAMETER)
|
|
65
|
+
nucleus_channel = segmentation_parameters.setdefault('nucleus_channel', default.CHANNEL)
|
|
64
66
|
other_nucleus_image = segmentation_parameters.setdefault('other_nucleus_image',None)
|
|
65
67
|
path = os.getcwd()
|
|
66
|
-
show_segmentation = segmentation_parameters.setdefault('
|
|
67
|
-
|
|
68
|
+
show_segmentation = segmentation_parameters.setdefault('show_segmentation', default.SHOW_SEGMENTATION)
|
|
69
|
+
save_segmentation_visual = segmentation_parameters.setdefault('save_segmentation_visual', default.SAVE_SEGMENTATION_VISUAL)
|
|
70
|
+
segment_only_nuclei = segmentation_parameters.setdefault('segment_only_nuclei', default.SEGMENT_ONLY_NUCLEI)
|
|
71
|
+
multichannel = segmentation_parameters.setdefault('is_multichannel', default.IS_MULTICHANNEL)
|
|
72
|
+
is_3D_stack = segmentation_parameters.setdefault('is_3D_stack', default.IS_3D_STACK)
|
|
73
|
+
anisotropy = segmentation_parameters.setdefault('anisotropy', default.ANISOTROPY)
|
|
74
|
+
cytoplasm_segmentation_3D = segmentation_parameters.setdefault('cytoplasm_segmentation_3D', default.DO_3D_SEMGENTATION)
|
|
75
|
+
nucleus_segmentation_3D = segmentation_parameters.setdefault('nucleus_segmentation_3D', default.DO_3D_SEMGENTATION)
|
|
76
|
+
flow_threshold = segmentation_parameters.setdefault("flow_threshold",0.4)
|
|
77
|
+
cellprob_threshold = segmentation_parameters.setdefault("cellprob_threshold",0)
|
|
68
78
|
filename = segmentation_parameters['filename']
|
|
69
79
|
available_channels = list(range(image.shape[0]))
|
|
70
|
-
multichannel = segmentation_parameters.get('is_multichannel')
|
|
71
80
|
|
|
72
81
|
|
|
73
82
|
#Ask user for parameters
|
|
@@ -82,10 +91,17 @@ def launch_segmentation(user_parameters: pipeline_parameters, nucleus_label, cyt
|
|
|
82
91
|
nucleus_diameter_preset= nucleus_size,
|
|
83
92
|
other_nucleus_image_preset=other_nucleus_image,
|
|
84
93
|
saving_path_preset= path,
|
|
94
|
+
save_segmentation_visual_preset=save_segmentation_visual,
|
|
85
95
|
show_segmentation_preset=show_segmentation,
|
|
86
96
|
segment_only_nuclei_preset=segment_only_nuclei,
|
|
87
97
|
filename_preset=filename,
|
|
88
98
|
multichannel=multichannel,
|
|
99
|
+
is_3D_stack=is_3D_stack,
|
|
100
|
+
cytoplasm_segmentation_3D=cytoplasm_segmentation_3D,
|
|
101
|
+
nucleus_segmentation_3D=nucleus_segmentation_3D,
|
|
102
|
+
anisotropy=anisotropy,
|
|
103
|
+
flow_threshold=flow_threshold,
|
|
104
|
+
cellprob_threshold=cellprob_threshold,
|
|
89
105
|
)
|
|
90
106
|
|
|
91
107
|
event, values = prompt(layout)
|
|
@@ -98,56 +114,98 @@ def launch_segmentation(user_parameters: pipeline_parameters, nucleus_label, cyt
|
|
|
98
114
|
continue
|
|
99
115
|
|
|
100
116
|
#Extract parameters
|
|
101
|
-
values = _cast_segmentation_parameters(values)
|
|
102
|
-
do_only_nuc = values['
|
|
117
|
+
values : pipeline_parameters = _cast_segmentation_parameters(values)
|
|
118
|
+
do_only_nuc = values['segment_only_nuclei']
|
|
103
119
|
cyto_model_name = values['cyto_model_name']
|
|
104
|
-
cyto_size = values['
|
|
105
|
-
cytoplasm_channel = values['
|
|
120
|
+
cyto_size = values['cytoplasm_diameter']
|
|
121
|
+
cytoplasm_channel = values['cytoplasm_channel']
|
|
106
122
|
nucleus_model_name = values['nucleus_model_name']
|
|
107
|
-
nucleus_size = values['
|
|
108
|
-
nucleus_channel = values['
|
|
123
|
+
nucleus_size = values['nucleus_diameter']
|
|
124
|
+
nucleus_channel = values['nucleus_channel']
|
|
109
125
|
other_nucleus_image = values['other_nucleus_image']
|
|
110
126
|
path = values['saving path'] if values['saving path'] != '' else None
|
|
111
|
-
|
|
127
|
+
save_segmentation_visual = values['save_segmentation_visual']
|
|
128
|
+
show_segmentation = values['show_segmentation']
|
|
112
129
|
filename = values['filename'] if type(path) != type(None) else None
|
|
113
130
|
channels = [cytoplasm_channel, nucleus_channel] if multichannel else [...,...]
|
|
131
|
+
nucleus_segmentation_3D = values['nucleus_segmentation_3D']
|
|
132
|
+
cytoplasm_segmentation_3D = values['cytoplasm_segmentation_3D']
|
|
133
|
+
anisotropy = values['anisotropy']
|
|
134
|
+
cellprob_threshold_cyto = values['cellprob_threshold_cyto']
|
|
135
|
+
cellprob_threshold_nuc = values['cellprob_threshold_nuc']
|
|
136
|
+
flow_threshold_cyto = values['flow_threshold_cyto']
|
|
137
|
+
flow_threshold_nuc = values['flow_threshold_nuc']
|
|
114
138
|
|
|
115
139
|
relaunch= False
|
|
116
140
|
#Checking integrity of parameters
|
|
141
|
+
|
|
142
|
+
#flow thresholds
|
|
143
|
+
if type(flow_threshold_nuc) != float :
|
|
144
|
+
sg.popup('Invalid value for flow threshold in nuc parameters, must be a float between 0 and 1.')
|
|
145
|
+
values['flow_threshold_nuc'] = user_parameters.setdefault('flow_threshold_nuc',default.FLOW_THRESHOLD)
|
|
146
|
+
relaunch= True
|
|
147
|
+
if type(flow_threshold_cyto) != float :
|
|
148
|
+
sg.popup('Invalid value for flow threshold in cyto parameters, must be a float between 0 and 1.')
|
|
149
|
+
values['flow_threshold_cyto'] = user_parameters.setdefault('flow_threshold_cyto',default.FLOW_THRESHOLD)
|
|
150
|
+
relaunch= True
|
|
151
|
+
|
|
152
|
+
#cellprob thresholds
|
|
153
|
+
if type(flow_threshold_nuc) != float :
|
|
154
|
+
sg.popup('Invalid value for cellprob threshold in nuc parameters, must be a float between -3 and +3.')
|
|
155
|
+
values['flow_threshold_nuc'] = user_parameters.setdefault('flow_threshold_nuc',default.FLOW_THRESHOLD)
|
|
156
|
+
relaunch= True
|
|
157
|
+
if type(flow_threshold_cyto) != float :
|
|
158
|
+
sg.popup('Invalid value for cellprob threshold in cyto parameters, must be a float between -3 and +3.')
|
|
159
|
+
values['flow_threshold_cyto'] = user_parameters.setdefault('flow_threshold_cyto',default.FLOW_THRESHOLD)
|
|
160
|
+
relaunch= True
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
#Models
|
|
117
164
|
if type(cyto_model_name) != str and not do_only_nuc:
|
|
118
165
|
sg.popup('Invalid cytoplasm model name.')
|
|
119
|
-
values['cyto_model_name'] = user_parameters.setdefault('cyto_model_name',
|
|
166
|
+
values['cyto_model_name'] = user_parameters.setdefault('cyto_model_name', default.CYTO_MODEL)
|
|
120
167
|
relaunch= True
|
|
121
168
|
if multichannel :
|
|
122
169
|
if cytoplasm_channel not in available_channels and not do_only_nuc:
|
|
123
|
-
sg.popup('For given input image please select channel in {0}\
|
|
170
|
+
sg.popup('For given input image please select channel in {0}\ncytoplasm_channel : {1}'.format(available_channels, cytoplasm_channel))
|
|
124
171
|
relaunch= True
|
|
125
|
-
values['
|
|
172
|
+
values['cytoplasm_channel'] = user_parameters.setdefault('cytoplasm_channel',default.CHANNEL)
|
|
126
173
|
else :
|
|
127
174
|
cytoplasm_channel = ...
|
|
128
175
|
|
|
176
|
+
if is_3D_stack :
|
|
177
|
+
try :
|
|
178
|
+
float(anisotropy)
|
|
179
|
+
if anisotropy <0 : raise ValueError()
|
|
180
|
+
|
|
181
|
+
except ValueError :
|
|
182
|
+
sg.popup("Anisotropy must be a positive float.")
|
|
183
|
+
relaunch = True
|
|
184
|
+
values['anisotropy'] = user_parameters.setdefault('anisotropy', default.ANISOTROPY)
|
|
185
|
+
|
|
129
186
|
if type(cyto_size) not in [int, float] and not do_only_nuc:
|
|
130
187
|
sg.popup("Incorrect cytoplasm size.")
|
|
131
188
|
relaunch= True
|
|
132
|
-
values['
|
|
189
|
+
values['cytoplasm_diameter'] = user_parameters.setdefault('cytoplasm_diameter', default.CYTO_DIAMETER)
|
|
133
190
|
|
|
134
191
|
if type(nucleus_model_name) != str :
|
|
135
192
|
sg.popup('Invalid nucleus model name.')
|
|
136
|
-
values['nucleus_model_name'] = user_parameters.setdefault('nucleus_model_name',
|
|
193
|
+
values['nucleus_model_name'] = user_parameters.setdefault('nucleus_model_name', default.NUC_MODEL)
|
|
137
194
|
relaunch= True
|
|
138
195
|
|
|
139
196
|
if multichannel :
|
|
140
197
|
if nucleus_channel not in available_channels :
|
|
141
198
|
sg.popup('For given input image please select channel in {0}\nnucleus channel : {1}'.format(available_channels, nucleus_channel))
|
|
142
199
|
relaunch= True
|
|
143
|
-
values['
|
|
200
|
+
values['nucleus_channel'] = user_parameters.setdefault('nucleus_channel', default.CHANNEL)
|
|
144
201
|
else :
|
|
145
202
|
nucleus_channel = ...
|
|
146
203
|
|
|
147
204
|
if type(nucleus_size) not in [int, float] :
|
|
148
205
|
sg.popup("Incorrect nucleus size.")
|
|
149
206
|
relaunch= True
|
|
150
|
-
values['
|
|
207
|
+
values['nucleus_diameter'] = user_parameters.setdefault('nucleus_diameter', default.NUC_DIAMETER)
|
|
208
|
+
|
|
151
209
|
if other_nucleus_image != '' :
|
|
152
210
|
if not os.path.isfile(other_nucleus_image) :
|
|
153
211
|
sg.popup("Nucleus image is not a file.")
|
|
@@ -202,7 +260,6 @@ def launch_segmentation(user_parameters: pipeline_parameters, nucleus_label, cyt
|
|
|
202
260
|
nuc_path = None
|
|
203
261
|
cyto_path = None
|
|
204
262
|
|
|
205
|
-
|
|
206
263
|
cytoplasm_label, nucleus_label = cell_segmentation(
|
|
207
264
|
image,
|
|
208
265
|
cyto_model_name= cyto_model_name,
|
|
@@ -212,6 +269,14 @@ def launch_segmentation(user_parameters: pipeline_parameters, nucleus_label, cyt
|
|
|
212
269
|
channels=channels,
|
|
213
270
|
do_only_nuc=do_only_nuc,
|
|
214
271
|
external_nucleus_image = nucleus_image,
|
|
272
|
+
anisotropy=anisotropy,
|
|
273
|
+
nucleus_3D_segmentation=nucleus_segmentation_3D,
|
|
274
|
+
cyto_3D_segmentation=cytoplasm_segmentation_3D,
|
|
275
|
+
cellprob_threshold_cyto=cellprob_threshold_cyto,
|
|
276
|
+
cellprob_threshold_nuc=cellprob_threshold_nuc,
|
|
277
|
+
flow_threshold_cyto=flow_threshold_cyto,
|
|
278
|
+
flow_threshold_nuc=flow_threshold_nuc,
|
|
279
|
+
|
|
215
280
|
)
|
|
216
281
|
|
|
217
282
|
finally : window.close()
|
|
@@ -222,6 +287,7 @@ def launch_segmentation(user_parameters: pipeline_parameters, nucleus_label, cyt
|
|
|
222
287
|
nuc_label= nucleus_label,
|
|
223
288
|
cyto_image=image[cytoplasm_channel],
|
|
224
289
|
cyto_label=cytoplasm_label,
|
|
290
|
+
anisotrpy=anisotropy,
|
|
225
291
|
)
|
|
226
292
|
|
|
227
293
|
if nucleus_label.ndim == 3 : nucleus_label = np.max(nucleus_label, axis=0)
|
|
@@ -236,20 +302,29 @@ def launch_segmentation(user_parameters: pipeline_parameters, nucleus_label, cyt
|
|
|
236
302
|
if event == "No" :
|
|
237
303
|
continue
|
|
238
304
|
|
|
239
|
-
if type(output_path) != type(None) :
|
|
305
|
+
if type(output_path) != type(None) and save_segmentation_visual:
|
|
240
306
|
|
|
241
307
|
#Get backgrounds
|
|
242
308
|
nuc_proj = image[nucleus_channel]
|
|
243
309
|
im_proj = image[cytoplasm_channel]
|
|
244
310
|
if im_proj.ndim == 3 :
|
|
245
|
-
im_proj = stack.
|
|
311
|
+
im_proj = stack.mean_projection(im_proj)
|
|
246
312
|
if nuc_proj.ndim == 3 :
|
|
247
|
-
nuc_proj = stack.
|
|
313
|
+
nuc_proj = stack.mean_projection(nuc_proj)
|
|
314
|
+
if nucleus_label.ndim == 3 :
|
|
315
|
+
nucleus_label_proj = np.max(nucleus_channel,axis=0)
|
|
316
|
+
else :
|
|
317
|
+
nucleus_label_proj = nucleus_label
|
|
318
|
+
if cytoplasm_label.ndim == 3 :
|
|
319
|
+
cytoplasm_label_proj = np.max(cytoplasm_label,axis=0)
|
|
320
|
+
else :
|
|
321
|
+
cytoplasm_label_proj = cytoplasm_label
|
|
322
|
+
|
|
248
323
|
|
|
249
324
|
#Call plots
|
|
250
|
-
plot.plot_segmentation_boundary(nuc_proj,
|
|
325
|
+
plot.plot_segmentation_boundary(nuc_proj, cytoplasm_label_proj, nucleus_label_proj, boundary_size=2, contrast=True, show=False, path_output=nuc_path, title= "Nucleus segmentation (blue)", remove_frame=True,)
|
|
251
326
|
if not do_only_nuc :
|
|
252
|
-
plot.plot_segmentation_boundary(im_proj,
|
|
327
|
+
plot.plot_segmentation_boundary(im_proj, cytoplasm_label_proj, nucleus_label_proj, boundary_size=2, contrast=True, show=False, path_output=cyto_path, title="Cytoplasm Segmentation (red)", remove_frame=True)
|
|
253
328
|
plot_labels(
|
|
254
329
|
nucleus_label,
|
|
255
330
|
path_output=output_path + "_nucleus_label_map.png",
|
|
@@ -257,7 +332,7 @@ def launch_segmentation(user_parameters: pipeline_parameters, nucleus_label, cyt
|
|
|
257
332
|
)
|
|
258
333
|
if not do_only_nuc :
|
|
259
334
|
plot_labels(
|
|
260
|
-
|
|
335
|
+
cytoplasm_label_proj,
|
|
261
336
|
path_output=output_path + "_cytoplasm_label_map.png",
|
|
262
337
|
show=False
|
|
263
338
|
)
|
|
@@ -284,91 +359,140 @@ def cell_segmentation(
|
|
|
284
359
|
image, cyto_model_name,
|
|
285
360
|
nucleus_model_name,
|
|
286
361
|
channels, cyto_diameter,
|
|
287
|
-
nucleus_diameter,
|
|
362
|
+
nucleus_diameter,
|
|
363
|
+
nucleus_3D_segmentation=False,
|
|
364
|
+
cyto_3D_segmentation=False,
|
|
365
|
+
anisotropy = 1,
|
|
366
|
+
flow_threshold_nuc = 0.4,
|
|
367
|
+
flow_threshold_cyto = 0.4,
|
|
368
|
+
cellprob_threshold_nuc = 0.,
|
|
369
|
+
cellprob_threshold_cyto = 0.,
|
|
288
370
|
do_only_nuc=False,
|
|
289
371
|
external_nucleus_image = None,
|
|
290
372
|
) :
|
|
291
373
|
|
|
292
374
|
nuc_channel = channels[1]
|
|
293
|
-
|
|
294
|
-
cyto_channel = channels[0]
|
|
295
|
-
if image[cyto_channel].ndim >= 3 :
|
|
296
|
-
cyto = stack.maximum_projection(image[cyto_channel])
|
|
297
|
-
else :
|
|
298
|
-
cyto = image[cyto_channel]
|
|
375
|
+
|
|
299
376
|
|
|
300
377
|
if type(external_nucleus_image) != type(None) :
|
|
301
378
|
nuc = external_nucleus_image
|
|
302
379
|
else :
|
|
303
380
|
nuc = image[nuc_channel]
|
|
304
381
|
|
|
305
|
-
if nuc.ndim >= 3 :
|
|
306
|
-
nuc = stack.
|
|
382
|
+
if nuc.ndim >= 3 and not nucleus_3D_segmentation:
|
|
383
|
+
nuc = stack.mean_projection(nuc)
|
|
384
|
+
nuc_label = _segmentate_object(
|
|
385
|
+
nuc,
|
|
386
|
+
nucleus_model_name,
|
|
387
|
+
nucleus_diameter,
|
|
388
|
+
do_3D=nucleus_3D_segmentation,
|
|
389
|
+
anisotropy=anisotropy,
|
|
390
|
+
flow_threshold= flow_threshold_nuc,
|
|
391
|
+
cellprob_threshold=cellprob_threshold_nuc
|
|
392
|
+
)
|
|
307
393
|
|
|
308
|
-
if not do_only_nuc :
|
|
394
|
+
if not do_only_nuc :
|
|
395
|
+
cyto_channel = channels[0]
|
|
396
|
+
nuc = image[nuc_channel] if type(external_nucleus_image) == type(None) else external_nucleus_image
|
|
397
|
+
|
|
398
|
+
if image[cyto_channel].ndim >= 3 and not cyto_3D_segmentation:
|
|
399
|
+
cyto = stack.mean_projection(image[cyto_channel])
|
|
400
|
+
else :
|
|
401
|
+
cyto = image[cyto_channel]
|
|
402
|
+
if nuc.ndim >= 3 and not cyto_3D_segmentation:
|
|
403
|
+
nuc = stack.mean_projection(nuc)
|
|
404
|
+
|
|
309
405
|
image = np.zeros(shape=(2,) + cyto.shape)
|
|
310
406
|
image[0] = cyto
|
|
311
407
|
image[1] = nuc
|
|
312
|
-
|
|
408
|
+
source = list(range(image.ndim))
|
|
409
|
+
dest = source[-1:] + source[:-1]
|
|
410
|
+
image = np.moveaxis(image, source=range(image.ndim), destination= dest)
|
|
411
|
+
|
|
412
|
+
cytoplasm_label = _segmentate_object(
|
|
413
|
+
image,
|
|
414
|
+
cyto_model_name,
|
|
415
|
+
cyto_diameter,
|
|
416
|
+
do_3D=cyto_3D_segmentation,
|
|
417
|
+
anisotropy=anisotropy,
|
|
418
|
+
flow_threshold=flow_threshold_cyto,
|
|
419
|
+
cellprob_threshold=cellprob_threshold_cyto,
|
|
420
|
+
)
|
|
421
|
+
|
|
422
|
+
if cytoplasm_label.ndim == 3 and nuc_label.ndim == 2 :
|
|
423
|
+
nuc_label = np.repeat(nuc_label[np.newaxis], len(cytoplasm_label), axis= 0)
|
|
424
|
+
if nuc_label.ndim == 3 and cytoplasm_label.ndim == 2 :
|
|
425
|
+
cytoplasm_label = np.repeat(cytoplasm_label[np.newaxis], len(nuc_label), axis= 0)
|
|
313
426
|
|
|
314
|
-
nuc_label = _segmentate_object(nuc, nucleus_model_name, nucleus_diameter, [0,0])
|
|
315
|
-
if not do_only_nuc :
|
|
316
|
-
cytoplasm_label = _segmentate_object(image, cyto_model_name, cyto_diameter, [1,2])
|
|
317
427
|
nuc_label, cytoplasm_label = multistack.match_nuc_cell(nuc_label=nuc_label, cell_label=cytoplasm_label, single_nuc=True, cell_alone=False)
|
|
318
428
|
else :
|
|
319
429
|
cytoplasm_label = nuc_label
|
|
320
430
|
|
|
321
431
|
return cytoplasm_label, nuc_label
|
|
322
432
|
|
|
323
|
-
def _segmentate_object(
|
|
433
|
+
def _segmentate_object(
|
|
434
|
+
im : np.ndarray,
|
|
435
|
+
model_name : str,
|
|
436
|
+
object_size_px : int,
|
|
437
|
+
do_3D = False,
|
|
438
|
+
anisotropy : float = 1.0,
|
|
439
|
+
flow_threshold : float = 0.4,
|
|
440
|
+
cellprob_threshold : float = 0,
|
|
441
|
+
) :
|
|
324
442
|
|
|
325
443
|
model = models.CellposeModel(
|
|
326
444
|
gpu= use_gpu(),
|
|
327
|
-
|
|
445
|
+
pretrained_model= model_name,
|
|
328
446
|
)
|
|
329
447
|
|
|
330
|
-
label = model.eval(
|
|
448
|
+
label, flow, style = model.eval(
|
|
331
449
|
im,
|
|
332
450
|
diameter= object_size_px,
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
451
|
+
do_3D= do_3D,
|
|
452
|
+
z_axis=0 if do_3D else None,
|
|
453
|
+
channel_axis= im.ndim -1 if im.ndim == 3+ do_3D else None,
|
|
454
|
+
anisotropy=anisotropy,
|
|
455
|
+
flow_threshold=flow_threshold,
|
|
456
|
+
cellprob_threshold=cellprob_threshold,
|
|
457
|
+
)
|
|
458
|
+
|
|
336
459
|
label = np.array(label, dtype= np.int64)
|
|
337
|
-
label = remove_disjoint(label)
|
|
460
|
+
if not do_3D : label = remove_disjoint(label) # Too much time consuming in 3D
|
|
461
|
+
else : pass #TODO : filter too litle regions
|
|
338
462
|
|
|
339
463
|
return label
|
|
340
464
|
|
|
341
465
|
def _cast_segmentation_parameters(values:dict) :
|
|
342
466
|
|
|
343
|
-
values.setdefault('
|
|
344
|
-
values.setdefault('
|
|
467
|
+
values.setdefault('cytoplasm_channel',0)
|
|
468
|
+
values.setdefault('nucleus_channel',0)
|
|
345
469
|
|
|
470
|
+
cast_rules = {
|
|
471
|
+
'cytoplasm_diameter' : int,
|
|
472
|
+
'nucleus_diameter' : int,
|
|
473
|
+
'cytoplasm_channel' : int,
|
|
474
|
+
'nucleus_channel' : int,
|
|
475
|
+
'anisotropy' : float,
|
|
476
|
+
'flow_threshold_cyto' : float,
|
|
477
|
+
'cellprob_threshold_cyto' : float,
|
|
478
|
+
'flow_threshold_nuc' : float,
|
|
479
|
+
'cellprob_threshold_nuc' : float,
|
|
480
|
+
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
for key, constructor in cast_rules.items() :
|
|
484
|
+
try :
|
|
485
|
+
if key in values.keys() : values[key] = constructor(values[key])
|
|
486
|
+
except ValueError :
|
|
487
|
+
pass
|
|
488
|
+
|
|
489
|
+
#None if default
|
|
346
490
|
if values['cyto_model_name'] == '' :
|
|
347
491
|
values['cyto_model_name'] = None
|
|
348
492
|
|
|
349
493
|
if values['nucleus_model_name'] == '' :
|
|
350
494
|
values['nucleus_model_name'] = None
|
|
351
495
|
|
|
352
|
-
try : #cytoplasm channel
|
|
353
|
-
values['cytoplasm channel'] = int(values['cytoplasm channel'])
|
|
354
|
-
except ValueError :
|
|
355
|
-
pass
|
|
356
|
-
|
|
357
|
-
try : #nucleus channel
|
|
358
|
-
values['nucleus channel'] = int(values['nucleus channel'])
|
|
359
|
-
except ValueError :
|
|
360
|
-
pass
|
|
361
|
-
|
|
362
|
-
try : #object size
|
|
363
|
-
values['cytoplasm diameter'] = float(values['cytoplasm diameter'])
|
|
364
|
-
except ValueError :
|
|
365
|
-
pass
|
|
366
|
-
|
|
367
|
-
try : #object size
|
|
368
|
-
values['nucleus diameter'] = float(values['nucleus diameter'])
|
|
369
|
-
except ValueError :
|
|
370
|
-
pass
|
|
371
|
-
|
|
372
496
|
return values
|
|
373
497
|
|
|
374
498
|
def remove_disjoint(image):
|
|
@@ -450,6 +574,15 @@ def plot_segmentation(
|
|
|
450
574
|
if nuc_image.ndim == 3 :
|
|
451
575
|
nuc_image = np.max(nuc_image,axis=0)
|
|
452
576
|
|
|
577
|
+
if cyto_label.ndim == 3 :
|
|
578
|
+
cyto_label = np.max(cyto_label,axis=0)
|
|
579
|
+
|
|
580
|
+
if nuc_label.ndim == 3 :
|
|
581
|
+
nuc_label = np.max(nuc_label,axis=0)
|
|
582
|
+
|
|
583
|
+
if cyto_image.ndim == 3 :
|
|
584
|
+
cyto_image = np.max(cyto_image,axis=0)
|
|
585
|
+
|
|
453
586
|
plot.plot_segmentation_boundary(
|
|
454
587
|
image=nuc_image,
|
|
455
588
|
nuc_label= nuc_label,
|
small_fish_gui/pipeline/spots.py
CHANGED
|
@@ -31,7 +31,6 @@ def launch_spots_extraction(
|
|
|
31
31
|
filename= user_parameters['spots_filename'],
|
|
32
32
|
do_excel=user_parameters['do_spots_excel'],
|
|
33
33
|
do_csv=user_parameters['do_spots_csv'],
|
|
34
|
-
do_feather=user_parameters['do_spots_feather'],
|
|
35
34
|
)
|
|
36
35
|
|
|
37
36
|
if did_output : print("Individual spots extracted at {0}".format(user_parameters['spots_extraction_folder']))
|
|
@@ -41,8 +40,8 @@ def compute_Spots(
|
|
|
41
40
|
image : np.ndarray,
|
|
42
41
|
spots : np.ndarray,
|
|
43
42
|
cluster_id : np.ndarray,
|
|
44
|
-
nucleus_label = None,
|
|
45
|
-
cell_label = None,
|
|
43
|
+
nucleus_label : np.ndarray = None,
|
|
44
|
+
cell_label : np.ndarray = None,
|
|
46
45
|
) :
|
|
47
46
|
|
|
48
47
|
if len(spots) == 0 :
|
|
@@ -55,11 +54,17 @@ def compute_Spots(
|
|
|
55
54
|
index = tuple(index)
|
|
56
55
|
spot_intensities_list = list(image[index])
|
|
57
56
|
if type(nucleus_label) != type(None) :
|
|
58
|
-
|
|
57
|
+
if nucleus_label.ndim == 2 :
|
|
58
|
+
in_nuc_list = list(nucleus_label.astype(bool)[index[-2:]]) #Only plane coordinates
|
|
59
|
+
else :
|
|
60
|
+
in_nuc_list = list(nucleus_label.astype(bool)[index])
|
|
59
61
|
else :
|
|
60
62
|
in_nuc_list = np.NaN
|
|
61
63
|
if type(cell_label) != type(None) :
|
|
62
|
-
|
|
64
|
+
if cell_label.ndim == 3 :
|
|
65
|
+
cell_label_list = list(cell_label[index])
|
|
66
|
+
else :
|
|
67
|
+
cell_label_list = list(cell_label[index[-2:]]) #Only plane coordinates
|
|
63
68
|
else :
|
|
64
69
|
cell_label_list = np.NaN
|
|
65
70
|
id_list = np.arange(len(spots))
|
|
@@ -78,4 +83,123 @@ def compute_Spots(
|
|
|
78
83
|
|
|
79
84
|
return Spots
|
|
80
85
|
|
|
86
|
+
def load_spots(
|
|
87
|
+
table_path : str
|
|
88
|
+
) -> pd.DataFrame :
|
|
89
|
+
|
|
90
|
+
if table_path.endswith('.csv') :
|
|
91
|
+
Spots = pd.read_csv(table_path, sep= ";")
|
|
92
|
+
elif table_path.endswith('.xlsx') or table_path.endswith('.xls') :
|
|
93
|
+
Spots = pd.read_excel(table_path)
|
|
94
|
+
elif table_path.endswith('.feather') :
|
|
95
|
+
Spots = pd.read_feather(table_path)
|
|
96
|
+
else :
|
|
97
|
+
raise ValueError("Table format not recognized. Please use .csv, .xlsx or .feather files.")
|
|
98
|
+
|
|
99
|
+
if "coordinates" in Spots.columns :
|
|
100
|
+
pass
|
|
101
|
+
elif "y" in Spots.columns and "x" in Spots.columns :
|
|
102
|
+
if "z" in Spots.columns :
|
|
103
|
+
pass
|
|
104
|
+
else :
|
|
105
|
+
pass
|
|
106
|
+
else :
|
|
107
|
+
raise ValueError("Coordinates information not found in table. Please provide a 'coordinates' column with tuples (z,y,x) or (y,x) or 'y' and 'x' columns.")
|
|
108
|
+
|
|
109
|
+
return Spots
|
|
110
|
+
|
|
111
|
+
def reconstruct_acquisition_data(
|
|
112
|
+
Spots : pd.DataFrame,
|
|
113
|
+
max_id : int,
|
|
114
|
+
filename : str,
|
|
115
|
+
voxel_size : 'tuple[int]'
|
|
116
|
+
) -> pd.DataFrame:
|
|
117
|
+
"""
|
|
118
|
+
Aim : creating a acquisition to add to result_dataframe from loaded spots for co-localization use
|
|
119
|
+
|
|
120
|
+
**Needed keys for colocalization**
|
|
121
|
+
* acquisition_id
|
|
122
|
+
* name
|
|
123
|
+
* spots : np.ndarray[int] (nb_spots, nb_coordinates)
|
|
124
|
+
* clusters : np.ndarray[int] (nb_cluster, nb_coordinate + 2)
|
|
125
|
+
* spots_cluster_id : list[int]
|
|
126
|
+
* voxel_size : tuple[int]
|
|
127
|
+
* shape : tuple[int]
|
|
128
|
+
* filename : str
|
|
129
|
+
"""
|
|
130
|
+
|
|
131
|
+
spots = reconstruct_spots(Spots['coordinates'])
|
|
132
|
+
has_clusters = not Spots['cluster_id'].isna().all()
|
|
133
|
+
spot_number = len(spots)
|
|
134
|
+
|
|
135
|
+
if has_clusters :
|
|
136
|
+
|
|
137
|
+
clusters = np.empty(shape=(0,5), dtype=int) #useless for coloc only needded in columns to enable coloc on clusters
|
|
138
|
+
spot_cluster_id = Spots['cluster_id'].to_numpy().astype(int).tolist()
|
|
139
|
+
|
|
140
|
+
new_acquisition = pd.DataFrame({
|
|
141
|
+
'acquisition_id' : [max_id + 1],
|
|
142
|
+
'name' : ["loaded_spots_{}".format(max_id + 1)],
|
|
143
|
+
'threshold' : [0],
|
|
144
|
+
'spots' : [spots],
|
|
145
|
+
'clusters' : [clusters],
|
|
146
|
+
'spots_cluster_id' : [spot_cluster_id],
|
|
147
|
+
'spot_number' : [spot_number],
|
|
148
|
+
'filename' : [filename],
|
|
149
|
+
'voxel_size' : [voxel_size],
|
|
150
|
+
})
|
|
151
|
+
else :
|
|
152
|
+
new_acquisition = pd.DataFrame({
|
|
153
|
+
'acquisition_id' : [max_id + 1],
|
|
154
|
+
'name' : ["loaded_spots_{}".format(max_id + 1)],
|
|
155
|
+
'threshold' : [0],
|
|
156
|
+
'spots' : [spots],
|
|
157
|
+
'spot_number' : [spot_number],
|
|
158
|
+
'filename' : [filename],
|
|
159
|
+
'voxel_size' : [voxel_size],
|
|
160
|
+
})
|
|
161
|
+
|
|
162
|
+
return new_acquisition
|
|
163
|
+
|
|
164
|
+
def reconstruct_spots(
|
|
165
|
+
coordinates_serie : pd.Series
|
|
166
|
+
) :
|
|
167
|
+
spots = coordinates_serie.str.replace('(','').str.replace(')','')
|
|
168
|
+
spots = spots.str.split(',')
|
|
169
|
+
spots = spots.apply(np.array)
|
|
170
|
+
spots = np.array(spots.to_list()).astype(int)
|
|
171
|
+
|
|
172
|
+
return spots
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
def reconstruct_cell_data(
|
|
176
|
+
Spots : pd.DataFrame,
|
|
177
|
+
max_id : int,
|
|
178
|
+
) :
|
|
179
|
+
|
|
180
|
+
has_cluster = not Spots['cluster_id'].isna().all()
|
|
181
|
+
coordinates = reconstruct_spots(Spots['coordinates'])
|
|
182
|
+
Spots['coordinates'] = pd.Series(coordinates.tolist(), dtype=object, index= Spots.index)
|
|
183
|
+
|
|
184
|
+
cell = Spots.groupby('cell_label')['coordinates'].apply(np.array).rename("rna_coords").reset_index(drop=False)
|
|
185
|
+
|
|
186
|
+
#Handle cells with no spots
|
|
187
|
+
na_mask =cell[cell['rna_coords'].isna()].index
|
|
188
|
+
cell.loc[na_mask, ['rna_coords']] = pd.Series([np.empty(shape=(0,3))]*len(na_mask), dtype= object, index=na_mask)
|
|
189
|
+
|
|
190
|
+
cell['total_rna_number'] = cell['rna_coords'].apply(len)
|
|
191
|
+
|
|
192
|
+
if has_cluster :
|
|
193
|
+
cell['clustered_spots_coords'] = Spots[Spots['cluster_id'] !=-1].groupby('cell_label')['coordinates'].apply(np.array).rename("clustered_spots_coords")
|
|
194
|
+
|
|
195
|
+
#Handle cells with no clusters
|
|
196
|
+
na_mask =cell[cell['clustered_spots_coords'].isna()].index
|
|
197
|
+
cell.loc[na_mask, ['clustered_spots_coords']] = pd.Series([np.empty(shape=(0,3))]*len(na_mask), dtype= object, index=na_mask)
|
|
198
|
+
|
|
199
|
+
cell['clustered_spot_number'] = cell['clustered_spots_coords'].apply(len)
|
|
200
|
+
|
|
201
|
+
cell['acquisition_id'] = max_id + 1
|
|
202
|
+
cell['name'] = "loaded_spots_{}".format(max_id + 1)
|
|
203
|
+
cell = cell.rename(columns={"cell_label": "cell_id"})
|
|
81
204
|
|
|
205
|
+
return cell
|