small-fish-gui 2.0.2__py3-none-any.whl → 2.0.3__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 (51) hide show
  1. small_fish_gui/__init__.py +2 -2
  2. small_fish_gui/batch/integrity.py +2 -2
  3. small_fish_gui/batch/pipeline.py +46 -11
  4. small_fish_gui/batch/prompt.py +102 -41
  5. small_fish_gui/batch/update.py +26 -13
  6. small_fish_gui/batch/utils.py +1 -1
  7. small_fish_gui/gui/__init__.py +1 -0
  8. small_fish_gui/gui/_napari_widgets.py +418 -6
  9. small_fish_gui/gui/layout.py +332 -112
  10. small_fish_gui/gui/napari_visualiser.py +107 -22
  11. small_fish_gui/gui/prompts.py +161 -48
  12. small_fish_gui/gui/testing.ipynb +231 -24
  13. small_fish_gui/gui/tooltips.py +7 -1
  14. small_fish_gui/hints.py +23 -7
  15. small_fish_gui/interface/__init__.py +7 -1
  16. small_fish_gui/interface/default_settings.py +118 -0
  17. small_fish_gui/interface/image.py +43 -11
  18. small_fish_gui/interface/settings.json +50 -0
  19. small_fish_gui/interface/testing.ipynb +4354 -0
  20. small_fish_gui/interface/user_settings.py +96 -0
  21. small_fish_gui/main_menu.py +13 -1
  22. small_fish_gui/pipeline/{_signaltonoise.py → _bigfish_wrapers.py} +59 -7
  23. small_fish_gui/pipeline/_colocalisation.py +23 -24
  24. small_fish_gui/pipeline/_preprocess.py +46 -32
  25. small_fish_gui/pipeline/actions.py +48 -5
  26. small_fish_gui/pipeline/detection.py +71 -141
  27. small_fish_gui/pipeline/segmentation.py +360 -268
  28. small_fish_gui/pipeline/spots.py +3 -3
  29. small_fish_gui/pipeline/utils.py +5 -1
  30. small_fish_gui/README.md → small_fish_gui-2.0.3.dist-info/METADATA +35 -0
  31. small_fish_gui-2.0.3.dist-info/RECORD +46 -0
  32. {small_fish_gui-2.0.2.dist-info → small_fish_gui-2.0.3.dist-info}/WHEEL +1 -1
  33. small_fish_gui/.github/workflows/python-publish.yml +0 -39
  34. small_fish_gui/LICENSE +0 -24
  35. small_fish_gui/batch/values.txt +0 -65
  36. small_fish_gui/default_values.py +0 -51
  37. small_fish_gui/gui/screenshot/general_help_screenshot.png +0 -0
  38. small_fish_gui/gui/screenshot/mapping_help_screenshot.png +0 -0
  39. small_fish_gui/gui/screenshot/segmentation_help_screenshot.png +0 -0
  40. small_fish_gui/illustrations/DetectionVitrine_filtre.png +0 -0
  41. small_fish_gui/illustrations/DetectionVitrine_signal.png +0 -0
  42. small_fish_gui/illustrations/FocciVitrine.png +0 -0
  43. small_fish_gui/illustrations/FocciVitrine_no_spots.png +0 -0
  44. small_fish_gui/illustrations/Segmentation2D.png +0 -0
  45. small_fish_gui/illustrations/Segmentation2D_with_labels.png +0 -0
  46. small_fish_gui/logo.png +0 -0
  47. small_fish_gui/pipeline/testing.ipynb +0 -3636
  48. small_fish_gui/requirements.txt +0 -19
  49. small_fish_gui-2.0.2.dist-info/METADATA +0 -75
  50. small_fish_gui-2.0.2.dist-info/RECORD +0 -59
  51. {small_fish_gui-2.0.2.dist-info → small_fish_gui-2.0.3.dist-info}/licenses/LICENSE +0 -0
@@ -5,17 +5,16 @@ Contains cellpose wrappers to segmentate images.
5
5
  from cellpose.core import use_gpu
6
6
  from skimage.measure import label
7
7
  from ..hints import pipeline_parameters
8
- from ..gui.layout import _segmentation_layout
9
- from ..gui import prompt, ask_cancel_segmentation
10
- from ..interface import open_image
8
+ from ..interface import get_settings
9
+ from ..gui import prompt, ask_cancel_segmentation, segmentation_prompt
11
10
  from ..gui.napari_visualiser import show_segmentation as napari_show_segmentation
11
+ from ..interface import open_image, SettingsDict, get_settings
12
+
12
13
  from .utils import from_label_get_centeroidscoords
13
14
  from ._preprocess import ask_input_parameters
14
15
  from ._preprocess import map_channels, reorder_shape, reorder_image_stack
15
- from matplotlib.colors import ListedColormap
16
-
17
- import small_fish_gui.default_values as default
18
16
 
17
+ from matplotlib.colors import ListedColormap
19
18
  import matplotlib as mpl
20
19
  import cellpose.models as models
21
20
  import numpy as np
@@ -25,8 +24,9 @@ import bigfish.plot as plot
25
24
  import FreeSimpleGUI as sg
26
25
  import matplotlib.pyplot as plt
27
26
  import os
27
+ from .utils import using_mps
28
28
 
29
- def launch_segmentation(user_parameters: pipeline_parameters, nucleus_label, cytoplasm_label) :
29
+ def launch_segmentation(user_parameters: pipeline_parameters, nucleus_label, cytoplasm_label, batch_mode=False) :
30
30
  """
31
31
  Ask user for necessary parameters and perform cell segmentation (cytoplasm + nucleus) with cellpose.
32
32
 
@@ -40,10 +40,11 @@ def launch_segmentation(user_parameters: pipeline_parameters, nucleus_label, cyt
40
40
  cytoplasm_label, nucleus_label, user_parameters
41
41
  """
42
42
 
43
- segmentation_parameters = user_parameters.copy()
43
+ segmentation_parameters : pipeline_parameters = user_parameters.copy()
44
+ default = get_settings()
44
45
 
45
46
  #Ask for image parameters
46
- new_parameters = ask_input_parameters(ask_for_segmentation= True) #The image is open and stored inside user_parameters
47
+ new_parameters = ask_input_parameters(user_parameters, ask_for_segmentation= True) #The image is open and stored inside user_parameters
47
48
  if type(new_parameters) == type(None) : #if user clicks 'Cancel'
48
49
  return nucleus_label , cytoplasm_label, user_parameters
49
50
  else :
@@ -55,56 +56,28 @@ def launch_segmentation(user_parameters: pipeline_parameters, nucleus_label, cyt
55
56
  segmentation_parameters['reordered_shape'] = reorder_shape(segmentation_parameters['shape'], map_)
56
57
  image = reorder_image_stack(map_, segmentation_parameters['image'])
57
58
 
59
+ is_multichannel = segmentation_parameters["is_multichannel"]
60
+ is_3D_stack = segmentation_parameters["is_3D_stack"]
61
+
58
62
  while True : # Loop if show_segmentation
59
63
  #Default parameters
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)
66
- other_nucleus_image = segmentation_parameters.setdefault('other_nucleus_image',None)
67
64
  path = os.getcwd()
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)
78
- filename = segmentation_parameters['filename']
79
65
  available_channels = list(range(image.shape[0]))
80
-
66
+ available_slices = list(range(image.shape[is_multichannel])) #0 if not multichannel else 1
81
67
 
82
68
  #Ask user for parameters
83
69
  #if incorrect parameters --> set relaunch to True
84
70
  while True :
85
- layout = _segmentation_layout(
86
- cytoplasm_model_preset = cyto_model_name,
87
- cytoplasm_channel_preset= cytoplasm_channel,
88
- nucleus_model_preset = nucleus_model_name,
89
- nucleus_channel_preset= nucleus_channel,
90
- cyto_diameter_preset= cyto_size,
91
- nucleus_diameter_preset= nucleus_size,
92
- other_nucleus_image_preset=other_nucleus_image,
93
- saving_path_preset= path,
94
- save_segmentation_visual_preset=save_segmentation_visual,
95
- show_segmentation_preset=show_segmentation,
96
- segment_only_nuclei_preset=segment_only_nuclei,
97
- filename_preset=filename,
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,
105
- )
71
+ segmentation_parameters.setdefault("other_nucleus_image", segmentation_parameters["working_directory"])
72
+ segmentation_parameters.setdefault("cytoplasm_channel", segmentation_parameters["detection_channel"])
73
+ segmentation_parameters.setdefault("cytoplasm_segmentation_3D", segmentation_parameters["do_3D_segmentation"])
74
+ segmentation_parameters.setdefault("nucleus_segmentation_3D", segmentation_parameters["do_3D_segmentation"])
75
+
76
+ event, values = segmentation_prompt(
77
+ saving_path= segmentation_parameters.setdefault("seg_control_saving_path", segmentation_parameters["working_directory"]),
78
+ **segmentation_parameters
79
+ )
106
80
 
107
- event, values = prompt(layout)
108
81
  if event == 'Cancel' :
109
82
  cancel_segmentation = ask_cancel_segmentation()
110
83
 
@@ -114,180 +87,46 @@ def launch_segmentation(user_parameters: pipeline_parameters, nucleus_label, cyt
114
87
  continue
115
88
 
116
89
  #Extract parameters
117
- values : pipeline_parameters = _cast_segmentation_parameters(values)
118
- do_only_nuc = values['segment_only_nuclei']
119
- cyto_model_name = values['cyto_model_name']
120
- cyto_size = values['cytoplasm_diameter']
121
- cytoplasm_channel = values['cytoplasm_channel']
122
- nucleus_model_name = values['nucleus_model_name']
123
- nucleus_size = values['nucleus_diameter']
124
- nucleus_channel = values['nucleus_channel']
125
- other_nucleus_image = values['other_nucleus_image']
126
- path = values['saving path'] if values['saving path'] != '' else None
127
- save_segmentation_visual = values['save_segmentation_visual']
128
- show_segmentation = values['show_segmentation']
129
- filename = values['filename'] if type(path) != type(None) else None
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']
138
-
139
- relaunch= False
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
164
- if type(cyto_model_name) != str and not do_only_nuc:
165
- sg.popup('Invalid cytoplasm model name.')
166
- values['cyto_model_name'] = user_parameters.setdefault('cyto_model_name', default.CYTO_MODEL)
167
- relaunch= True
168
- if multichannel :
169
- if cytoplasm_channel not in available_channels and not do_only_nuc:
170
- sg.popup('For given input image please select channel in {0}\ncytoplasm_channel : {1}'.format(available_channels, cytoplasm_channel))
171
- relaunch= True
172
- values['cytoplasm_channel'] = user_parameters.setdefault('cytoplasm_channel',default.CHANNEL)
173
- else :
174
- cytoplasm_channel = ...
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
-
186
- if type(cyto_size) not in [int, float] and not do_only_nuc:
187
- sg.popup("Incorrect cytoplasm size.")
188
- relaunch= True
189
- values['cytoplasm_diameter'] = user_parameters.setdefault('cytoplasm_diameter', default.CYTO_DIAMETER)
190
-
191
- if type(nucleus_model_name) != str :
192
- sg.popup('Invalid nucleus model name.')
193
- values['nucleus_model_name'] = user_parameters.setdefault('nucleus_model_name', default.NUC_MODEL)
194
- relaunch= True
195
-
196
- if multichannel :
197
- if nucleus_channel not in available_channels :
198
- sg.popup('For given input image please select channel in {0}\nnucleus channel : {1}'.format(available_channels, nucleus_channel))
199
- relaunch= True
200
- values['nucleus_channel'] = user_parameters.setdefault('nucleus_channel', default.CHANNEL)
201
- else :
202
- nucleus_channel = ...
203
-
204
- if type(nucleus_size) not in [int, float] :
205
- sg.popup("Incorrect nucleus size.")
206
- relaunch= True
207
- values['nucleus_diameter'] = user_parameters.setdefault('nucleus_diameter', default.NUC_DIAMETER)
208
-
209
- if other_nucleus_image != '' :
210
- if not os.path.isfile(other_nucleus_image) :
211
- sg.popup("Nucleus image is not a file.")
212
- relaunch=True
213
- values['other_nucleus_image'] = None
214
- else :
215
- try :
216
- nucleus_image = open_image(other_nucleus_image)
217
- except Exception as e :
218
- sg.popup("Could not open image.\n{0}".format(e))
219
- relaunch=True
220
- values['other_nucleus_image'] = user_parameters.setdefault('other_nucleus_image', None)
221
- else :
222
- if nucleus_image.ndim != image.ndim - multichannel :
223
- sg.popup("Nucleus image dimension missmatched. Expected same dimension as cytoplasm_image for monochannel or same dimension as cytoplasm_image -1 for multichannel\ncytoplasm dimension : {0}, nucleus dimension : {1}".format(image.ndim, nucleus_image.ndim))
224
- nucleus_image = None
225
- relaunch=True
226
- values['other_nucleus_image'] = user_parameters.setdefault('other_nucleus_image', None)
227
-
228
- elif nucleus_image.shape != image[cytoplasm_channel].shape :
229
- sg.popup("Nucleus image shape missmatched. Expected same shape as cytoplasm_image \ncytoplasm shape : {0}, nucleus shape : {1}".format(image[cytoplasm_channel].shape, nucleus_image.shape))
230
- nucleus_image = None
231
- relaunch=True
232
- values['other_nucleus_image'] = user_parameters.setdefault('other_nucleus_image', None)
233
-
234
- else :
235
- nucleus_image = None
236
-
237
- user_parameters.update(values)
90
+ values, relaunch = _check_integrity_segmentation_parameters(values, segmentation_parameters, available_channels=available_channels, available_slices=available_slices)
91
+ segmentation_parameters.update(values)
238
92
  if not relaunch : break
239
93
 
240
- #Launching segmentation
241
- waiting_layout = [
242
- [sg.Text("Running segmentation...")]
243
- ]
244
- window = sg.Window(
245
- title= 'small_fish',
246
- layout= waiting_layout,
247
- grab_anywhere= True,
248
- no_titlebar= False
249
- )
94
+ if not batch_mode :
95
+ #Launching segmentation
96
+ waiting_layout = [
97
+ [sg.Text("Running segmentation...")]
98
+ ]
99
+ window = sg.Window(
100
+ title= 'small_fish',
101
+ layout= waiting_layout,
102
+ grab_anywhere= True,
103
+ no_titlebar= False
104
+ )
250
105
 
251
- window.read(timeout= 30, close= False)
106
+ window.read(timeout= 30, close= False)
252
107
 
253
108
  try :
254
- if type(path) != type(None) and filename != '':
255
- output_path = path + '/' + filename
256
- nuc_path = output_path + "_nucleus_segmentation"
257
- cyto_path = output_path + "_cytoplasm_segmentation"
258
- else :
259
- output_path = None
260
- nuc_path = None
261
- cyto_path = None
262
-
263
109
  cytoplasm_label, nucleus_label = cell_segmentation(
264
110
  image,
265
- cyto_model_name= cyto_model_name,
266
- cyto_diameter= cyto_size,
267
- nucleus_model_name= nucleus_model_name,
268
- nucleus_diameter= nucleus_size,
269
- channels=channels,
270
- do_only_nuc=do_only_nuc,
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
-
111
+ channels=[segmentation_parameters["cytoplasm_channel"], segmentation_parameters["nucleus_channel"]],
112
+ do_only_nuc=segmentation_parameters["segment_only_nuclei"],
113
+ external_nucleus_image = segmentation_parameters["other_nucleus_image"],
114
+ nucleus_3D_segmentation=segmentation_parameters["nucleus_segmentation_3D"],
115
+ cyto_3D_segmentation=segmentation_parameters["cytoplasm_segmentation_3D"],
116
+ **segmentation_parameters
280
117
  )
281
118
 
282
- finally : window.close()
119
+ finally :
120
+ if not batch_mode : window.close()
283
121
 
284
- if show_segmentation :
122
+ if segmentation_parameters["show_segmentation"] :
123
+
285
124
  nucleus_label, cytoplasm_label = napari_show_segmentation(
286
- nuc_image=image[nucleus_channel] if type(nucleus_image) == type(None) else nucleus_image,
125
+ nuc_image=image[segmentation_parameters["nucleus_channel"]] if type(segmentation_parameters["other_nucleus_image"]) == type(None) else segmentation_parameters["other_nucleus_image"],
287
126
  nuc_label= nucleus_label,
288
- cyto_image=image[cytoplasm_channel],
127
+ cyto_image=image[segmentation_parameters["cytoplasm_channel"]],
289
128
  cyto_label=cytoplasm_label,
290
- anisotrpy=anisotropy,
129
+ anisotrpy=segmentation_parameters["anisotropy"],
291
130
  )
292
131
 
293
132
  if nucleus_label.ndim == 3 : nucleus_label = np.max(nucleus_label, axis=0)
@@ -302,17 +141,17 @@ def launch_segmentation(user_parameters: pipeline_parameters, nucleus_label, cyt
302
141
  if event == "No" :
303
142
  continue
304
143
 
305
- if type(output_path) != type(None) and save_segmentation_visual:
144
+ if type(segmentation_parameters["seg_control_saving_path"]) != type(None) and segmentation_parameters["save_segmentation_visuals"]:
306
145
 
307
146
  #Get backgrounds
308
- nuc_proj = image[nucleus_channel]
309
- im_proj = image[cytoplasm_channel]
147
+ nuc_proj = image[segmentation_parameters["nucleus_channel"]]
148
+ im_proj = image[segmentation_parameters["cytoplasm_channel"]]
310
149
  if im_proj.ndim == 3 :
311
150
  im_proj = stack.mean_projection(im_proj)
312
151
  if nuc_proj.ndim == 3 :
313
152
  nuc_proj = stack.mean_projection(nuc_proj)
314
153
  if nucleus_label.ndim == 3 :
315
- nucleus_label_proj = np.max(nucleus_channel,axis=0)
154
+ nucleus_label_proj = np.max(segmentation_parameters["nucleus_channel"],axis=0)
316
155
  else :
317
156
  nucleus_label_proj = nucleus_label
318
157
  if cytoplasm_label.ndim == 3 :
@@ -322,21 +161,28 @@ def launch_segmentation(user_parameters: pipeline_parameters, nucleus_label, cyt
322
161
 
323
162
 
324
163
  #Call plots
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,)
326
- if not do_only_nuc :
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)
328
- plot_labels(
329
- nucleus_label,
330
- path_output=output_path + "_nucleus_label_map.png",
331
- show=False
332
- )
333
- if not do_only_nuc :
164
+ if segmentation_parameters["save_segmentation_visuals"]:
165
+ output_path = segmentation_parameters["seg_control_saving_path"] + '/' + segmentation_parameters["filename"]
166
+ nuc_path = output_path + "_nucleus_segmentation"
167
+ cyto_path = output_path + "_cytoplasm_segmentation"
168
+
169
+ #Plots boundaries
170
+ 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,)
171
+ if not segmentation_parameters["segment_only_nuclei"] :
172
+ 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)
173
+
174
+ #Plots cell labels
334
175
  plot_labels(
335
- cytoplasm_label_proj,
336
- path_output=output_path + "_cytoplasm_label_map.png",
176
+ nucleus_label,
177
+ path_output=output_path + "_nucleus_label_map.png",
337
178
  show=False
338
179
  )
339
-
180
+ if not segmentation_parameters["segment_only_nuclei"] :
181
+ plot_labels(
182
+ cytoplasm_label_proj,
183
+ path_output=output_path + "_cytoplasm_label_map.png",
184
+ show=False
185
+ )
340
186
 
341
187
 
342
188
  if cytoplasm_label.max() == 0 : #No cell segmented
@@ -344,31 +190,32 @@ def launch_segmentation(user_parameters: pipeline_parameters, nucleus_label, cyt
344
190
  [sg.Text("No cell segmented. Proceed anyway ?")],
345
191
  [sg.Button("Yes"), sg.Button("No")]
346
192
  ]
347
- event, values = prompt(layout=layout, add_ok_cancel=False)
193
+ event, _ = prompt(layout=layout, add_ok_cancel=False)
348
194
  if event == "Yes" :
349
195
  return None, None, user_parameters
350
196
  else :
351
197
  break
352
198
 
353
-
354
-
355
- user_parameters.update(values)
199
+ user_parameters.update(segmentation_parameters)
356
200
  return nucleus_label, cytoplasm_label, user_parameters
357
201
 
358
202
  def cell_segmentation(
359
- image, cyto_model_name,
203
+ reordered_image,
204
+ cytoplasm_model_name,
360
205
  nucleus_model_name,
361
- channels, cyto_diameter,
206
+ channels,
207
+ cytoplasm_diameter,
362
208
  nucleus_diameter,
363
209
  nucleus_3D_segmentation=False,
364
210
  cyto_3D_segmentation=False,
365
211
  anisotropy = 1,
366
- flow_threshold_nuc = 0.4,
367
- flow_threshold_cyto = 0.4,
368
- cellprob_threshold_nuc = 0.,
369
- cellprob_threshold_cyto = 0.,
212
+ nucleus_flow_threshold = 0.4,
213
+ cytoplasm_flow_threshold = 0.4,
214
+ nucleus_cellprob_threshold = 0.,
215
+ cytoplasm_cellprob_threshold = 0.,
370
216
  do_only_nuc=False,
371
217
  external_nucleus_image = None,
218
+ **segmentation_parameters : pipeline_parameters
372
219
  ) :
373
220
 
374
221
  nuc_channel = channels[1]
@@ -377,46 +224,60 @@ def cell_segmentation(
377
224
  if type(external_nucleus_image) != type(None) :
378
225
  nuc = external_nucleus_image
379
226
  else :
380
- nuc = image[nuc_channel]
227
+ nuc = reordered_image[nuc_channel]
381
228
 
382
229
  if nuc.ndim >= 3 and not nucleus_3D_segmentation:
383
- nuc = stack.mean_projection(nuc)
230
+
231
+ if segmentation_parameters["nucleus_max_proj"] : nuc = np.max(nuc, axis=0)
232
+ elif segmentation_parameters["nucleus_mean_proj"] : nuc = np.mean(nuc, axis=0)
233
+ elif segmentation_parameters["nucleus_select_slice"] : nuc = nuc[segmentation_parameters["nucleus_selected_slice"]]
234
+ else : raise AssertionError("No option found for 2D nucleus seg. Should be impossible as this error is raised after integrity checks")
235
+
236
+
384
237
  nuc_label = _segmentate_object(
385
238
  nuc,
386
239
  nucleus_model_name,
387
240
  nucleus_diameter,
388
241
  do_3D=nucleus_3D_segmentation,
389
242
  anisotropy=anisotropy,
390
- flow_threshold= flow_threshold_nuc,
391
- cellprob_threshold=cellprob_threshold_nuc
243
+ flow_threshold= nucleus_flow_threshold,
244
+ cellprob_threshold=nucleus_cellprob_threshold,
245
+ min_size=segmentation_parameters["nucleus_min_size"]
392
246
  )
393
247
 
394
248
  if not do_only_nuc :
395
249
  cyto_channel = channels[0]
396
- nuc = image[nuc_channel] if type(external_nucleus_image) == type(None) else external_nucleus_image
250
+ nuc = reordered_image[nuc_channel] if type(external_nucleus_image) == type(None) else external_nucleus_image
397
251
 
398
- if image[cyto_channel].ndim >= 3 and not cyto_3D_segmentation:
399
- cyto = stack.mean_projection(image[cyto_channel])
252
+ if reordered_image[cyto_channel].ndim >= 3 and not cyto_3D_segmentation:
253
+ if segmentation_parameters["cytoplasm_max_proj"] : cyto = np.max(reordered_image[cyto_channel], axis=0)
254
+ elif segmentation_parameters["cytoplasm_mean_proj"] : cyto = np.mean(reordered_image[cyto_channel], axis=0)
255
+ elif segmentation_parameters["cytoplasm_select_slice"] : cyto = reordered_image[cyto_channel][segmentation_parameters["cytoplasm_selected_slice"]]
256
+ else : raise AssertionError("No option found for 2D cytoplasm seg. Should be impossible as this error is raised after integrity checks")
400
257
  else :
401
- cyto = image[cyto_channel]
258
+ cyto = reordered_image[cyto_channel]
402
259
  if nuc.ndim >= 3 and not cyto_3D_segmentation:
403
- nuc = stack.mean_projection(nuc)
404
-
405
- image = np.zeros(shape=(2,) + cyto.shape)
406
- image[0] = cyto
407
- image[1] = nuc
408
- source = list(range(image.ndim))
260
+ if segmentation_parameters["cytoplasm_max_proj"] : nuc = np.max(nuc, axis=0)
261
+ elif segmentation_parameters["cytoplasm_mean_proj"] : nuc = np.mean(nuc, axis=0)
262
+ elif segmentation_parameters["cytoplasm_select_slice"] : nuc = nuc[segmentation_parameters["cytoplasm_selected_slice"]]
263
+ else : raise AssertionError("No option found for 2D cytoplasm seg. Should be impossible as this error is raised after integrity checks")
264
+
265
+ reordered_image = np.zeros(shape=(2,) + cyto.shape)
266
+ reordered_image[0] = cyto
267
+ reordered_image[1] = nuc
268
+ source = list(range(reordered_image.ndim))
409
269
  dest = source[-1:] + source[:-1]
410
- image = np.moveaxis(image, source=range(image.ndim), destination= dest)
270
+ reordered_image = np.moveaxis(reordered_image, source=range(reordered_image.ndim), destination= dest)
411
271
 
412
272
  cytoplasm_label = _segmentate_object(
413
- image,
414
- cyto_model_name,
415
- cyto_diameter,
273
+ reordered_image,
274
+ cytoplasm_model_name,
275
+ cytoplasm_diameter,
416
276
  do_3D=cyto_3D_segmentation,
417
277
  anisotropy=anisotropy,
418
- flow_threshold=flow_threshold_cyto,
419
- cellprob_threshold=cellprob_threshold_cyto,
278
+ flow_threshold=cytoplasm_flow_threshold,
279
+ cellprob_threshold=cytoplasm_cellprob_threshold,
280
+ min_size=segmentation_parameters["cytoplasm_min_size"]
420
281
  )
421
282
 
422
283
  if cytoplasm_label.ndim == 3 and nuc_label.ndim == 2 :
@@ -438,11 +299,14 @@ def _segmentate_object(
438
299
  anisotropy : float = 1.0,
439
300
  flow_threshold : float = 0.4,
440
301
  cellprob_threshold : float = 0,
302
+ min_size = 15 #Default cellpose
441
303
  ) :
304
+
442
305
 
443
306
  model = models.CellposeModel(
444
307
  gpu= use_gpu(),
445
308
  pretrained_model= model_name,
309
+ use_bfloat16= not using_mps()
446
310
  )
447
311
 
448
312
  label, flow, style = model.eval(
@@ -454,30 +318,32 @@ def _segmentate_object(
454
318
  anisotropy=anisotropy,
455
319
  flow_threshold=flow_threshold,
456
320
  cellprob_threshold=cellprob_threshold,
321
+ min_size=min_size,
457
322
  )
458
323
 
459
324
  label = np.array(label, dtype= np.int64)
460
325
  if not do_3D : label = remove_disjoint(label) # Too much time consuming in 3D
461
- else : pass #TODO : filter too litle regions
462
326
 
463
327
  return label
464
328
 
465
329
  def _cast_segmentation_parameters(values:dict) :
466
330
 
467
- values.setdefault('cytoplasm_channel',0)
468
- values.setdefault('nucleus_channel',0)
469
-
470
331
  cast_rules = {
471
332
  'cytoplasm_diameter' : int,
472
333
  'nucleus_diameter' : int,
473
334
  'cytoplasm_channel' : int,
474
335
  'nucleus_channel' : int,
475
336
  'anisotropy' : float,
476
- 'flow_threshold_cyto' : float,
477
- 'cellprob_threshold_cyto' : float,
478
- 'flow_threshold_nuc' : float,
479
- 'cellprob_threshold_nuc' : float,
480
-
337
+ 'cytoplasm_flow_threshold' : float,
338
+ 'cytoplasm_cellprob_threshold' : float,
339
+ 'nucleus_flow_threshold' : float,
340
+ 'nucleus_cellprob_threshold' : float,
341
+ 'cytoplasm_anisotropy' : float,
342
+ 'nucleus_anisotropy' : float,
343
+ 'cytoplasm_selected_slice' : int,
344
+ 'nucleus_selected_slice' : int,
345
+ 'cytoplasm_min_size' : int,
346
+ 'nucleus_min_size' : int,
481
347
  }
482
348
 
483
349
  for key, constructor in cast_rules.items() :
@@ -487,14 +353,240 @@ def _cast_segmentation_parameters(values:dict) :
487
353
  pass
488
354
 
489
355
  #None if default
490
- if values['cyto_model_name'] == '' :
491
- values['cyto_model_name'] = None
356
+ if values['cytoplasm_model_name'] == '' :
357
+ values['cytoplasm_model_name'] = None
492
358
 
493
359
  if values['nucleus_model_name'] == '' :
494
360
  values['nucleus_model_name'] = None
495
361
 
496
362
  return values
497
363
 
364
+ def _check_integrity_segmentation_parameters(
365
+ values : pipeline_parameters,
366
+ user_parameters : pipeline_parameters,
367
+ available_channels : list,
368
+ available_slices : list
369
+ ) :
370
+ """
371
+ Check that parameters entered by user comply with what we need to do with them. Type checking is handle in _cast_segmentation_parameters, if any parameters could not be cast to
372
+ appropriate type, it is set to None.
373
+ """
374
+
375
+ values : pipeline_parameters = _cast_segmentation_parameters(values)
376
+ is_3D_stack = user_parameters["is_3D_stack"]
377
+ is_multichannel = user_parameters["is_multichannel"]
378
+
379
+ relaunch= False
380
+ #Control plots
381
+ if values["save_segmentation_visuals"] :
382
+ if not os.path.isdir(values["seg_control_saving_path"]) :
383
+ relaunch=True
384
+ sg.popup(f"{values["seg_control_saving_path"]} is not a directory.")
385
+ values["seg_control_saving_path"] = user_parameters.get("seg_control_saving_path")
386
+ if values["filename"] == "" :
387
+ relaunch=True
388
+ sg.popup("Enter a filename for control plots.")
389
+ values["filename"] = user_parameters.get("filename")
390
+
391
+ #2D/3D seg
392
+ if is_3D_stack :
393
+ for obj in ["cytoplasm","nucleus"] :
394
+ assert values[obj + "_radio_2D"] + values[obj + "_radio_3D"] == 1, f"Incorrect number of segmentation dimension was selected (should be 1) for {obj}"
395
+ assert values[obj + "_max_proj"] + values[obj + "_mean_proj"] + values[obj + "_select_slice"] == 1, f"Incorrect number of 2D segmentation options were selected (should be 1) for {obj}"
396
+
397
+ if values[obj + "_radio_2D"] : values[obj + "_segmentation_3D"] = False
398
+ else : values[obj + "_segmentation_3D"] = True
399
+
400
+ #Selected slice
401
+ for key in ['cytoplasm_selected_slice', 'nucleus_selected_slice'] :
402
+ if not isinstance(values[key], int) :
403
+ relaunch = True
404
+ sg.popup("Invalid slice number for cytoplasm 2D segmentation.")
405
+ values[key] = user_parameters[key]
406
+ elif values[key] not in available_slices :
407
+ relaunch = True
408
+ sg.popup(f"Invalid slice number for cytoplasm 2D segmentation, selecgted between 0 and {available_slices[-1]}")
409
+ values[key] = user_parameters[key]
410
+
411
+ #anisotropy
412
+ if not "anisotropy" in values.keys() :
413
+ values["anisotropy"] = 1
414
+ if not isinstance(values["nucleus_anisotropy"], (float, int)) :
415
+ relaunch=True
416
+ sg.popup("Invalid value for nucleus anisotropy, must be a positive float.")
417
+ values["anisotropy"] = user_parameters.get("anisotropy")
418
+ elif values["nucleus_anisotropy"] < 0 :
419
+ relaunch=True
420
+ sg.popup("Invalid value for nucleus anisotropy, must be a positive float.")
421
+ values["anisotropy"] = user_parameters.get("anisotropy")
422
+
423
+ if not values["segment_only_nuclei"] :
424
+ if not isinstance(values["cytoplasm_anisotropy"], (float, int)) :
425
+ relaunch=True
426
+ sg.popup("Invalid value for cytoplasm anisotropy, must be a positive float.")
427
+ values["anisotropy"] = user_parameters.get("anisotropy")
428
+ elif values["cytoplasm_anisotropy"] < 0 :
429
+ relaunch=True
430
+ sg.popup("Invalid value for cytoplasm anisotropy, must be a positive float.")
431
+ values["anisotropy"] = user_parameters.get("anisotropy")
432
+
433
+ if values["segment_only_nuclei"] :
434
+ values["anisotropy"] = values["nucleus_anisotropy"]
435
+ elif isinstance(values["cytoplasm_anisotropy"], (float, int)) and isinstance(values["nucleus_anisotropy"], (float, int)) and values["nucleus_segmentation_3D"] and values["cytoplasm_segmentation_3D"]:
436
+ if (not values["cytoplasm_anisotropy"] == values["nucleus_anisotropy"]) and (not values["segment_only_nuclei"]) :
437
+ relaunch=True
438
+ sg.popup("Anisotropy must be equal for nucleus and cytoplasm segmentation")
439
+ values["anisotropy"] = user_parameters.get("anisotropy")
440
+ else :
441
+ values["anisotropy"] = values["nucleus_anisotropy"]
442
+ elif isinstance(values["nucleus_anisotropy"], (float, int)) and values["nucleus_segmentation_3D"] :
443
+ values["anisotropy"] = values["nucleus_anisotropy"]
444
+ elif isinstance(values["cytoplasm_anisotropy"], (float, int)) and values["cytoplasm_segmentation_3D"] :
445
+ values["anisotropy"] = values["cytoplasm_anisotropy"]
446
+
447
+ if not isinstance(values["anisotropy"], (float,int)) :
448
+ sg.popup("Anisotropy must be a positive float.")
449
+ relaunch = True
450
+ values['anisotropy'] = user_parameters.get("anisotropy")
451
+
452
+ else :
453
+ values["cytoplasm_segmentation_3D"] = False
454
+ values["nucleus_segmentation_3D"] = False
455
+ values["anisotropy"] = 1
456
+ for obj in ["nucleus","cytoplasm"] :
457
+ values[obj + "_max_proj"] = False
458
+ values[obj + "_mean_proj"] = True
459
+ values[obj + "_select_slice"] = False
460
+ values[obj + "_selected_slice"] = 0
461
+
462
+ #Min size
463
+ if not isinstance(values["cytoplasm_min_size"], int) :
464
+ relaunch=True
465
+ sg.popup("Invalid value for cytoplasm min size parameter, must be a positive int.")
466
+ values["cytoplasm_min_size"] = user_parameters["cytoplasm_min_size"]
467
+ elif values["cytoplasm_min_size"] < 0 :
468
+ relaunch=True
469
+ sg.popup("Invalid value for cytoplasm min size parameter, must be a positive int.")
470
+ values["cytoplasm_min_size"] = user_parameters["cytoplasm_min_size"]
471
+
472
+ if not isinstance(values["nucleus_min_size"], int) :
473
+ relaunch=True
474
+ sg.popup("Invalid value for nucleus min size parameter, must be a positive int.")
475
+ values["nucleus_min_size"] = user_parameters["nucleus_min_size"]
476
+ elif values["nucleus_min_size"] < 0 :
477
+ relaunch=True
478
+ sg.popup("Invalid value for nucleus min size parameter, must be a positive int.")
479
+ values["nucleus_min_size"] = user_parameters["nucleus_min_size"]
480
+
481
+ #flow thresholds
482
+ if type(values['nucleus_flow_threshold']) != float :
483
+ sg.popup('Invalid value for flow threshold in nuc parameters, must be a float between 0 and 1.')
484
+ values['nucleus_flow_threshold'] = user_parameters['nucleus_flow_threshold']
485
+ relaunch= True
486
+ elif abs(values['nucleus_flow_threshold']) > 1 or values['nucleus_flow_threshold'] < 0 :
487
+ sg.popup('Invalid value for flow threshold in cyto parameters, must be a float between 0 and 1.')
488
+ values['nucleus_flow_threshold'] = user_parameters['nucleus_flow_threshold']
489
+ relaunch= True
490
+
491
+ if type( values['cytoplasm_flow_threshold']) != float :
492
+ sg.popup('Invalid value for flow threshold in cyto parameters, must be a float between 0 and 1.')
493
+ values['cytoplasm_flow_threshold'] = user_parameters['cytoplasm_flow_threshold']
494
+ relaunch= True
495
+ elif abs(values['cytoplasm_flow_threshold']) > 1 or values['cytoplasm_flow_threshold'] < 0 :
496
+ sg.popup('Invalid value for flow threshold in cyto parameters, must be a float between 0 and 1.')
497
+ values['cytoplasm_flow_threshold'] = user_parameters['cytoplasm_flow_threshold']
498
+ relaunch= True
499
+
500
+ #cellprob thresholds
501
+ if type(values['nucleus_cellprob_threshold']) != float :
502
+ sg.popup('Invalid value for cellprob threshold in nuc parameters, must be a float between -3 and +3.')
503
+ values['nucleus_cellprob_threshold'] = user_parameters['nucleus_cellprob_threshold']
504
+ relaunch= True
505
+ elif abs(values['nucleus_cellprob_threshold']) > 3 :
506
+ sg.popup('Invalid value for cellprob threshold in cyto parameters, must be a float between -3 and +3.')
507
+ values['nucleus_cellprob_threshold'] = user_parameters['nucleus_cellprob_threshold']
508
+ relaunch= True
509
+
510
+ if type(values['cytoplasm_cellprob_threshold']) != float :
511
+ sg.popup('Invalid value for cellprob threshold in cyto parameters, must be a float between -3 and +3.')
512
+ values['cytoplasm_cellprob_threshold'] = user_parameters['cytoplasm_cellprob_threshold']
513
+ relaunch= True
514
+ elif abs(values['cytoplasm_cellprob_threshold']) > 3 :
515
+ sg.popup('Invalid value for cellprob threshold in cyto parameters, must be a float between -3 and +3.')
516
+ values['cytoplasm_cellprob_threshold'] = user_parameters['cytoplasm_cellprob_threshold']
517
+ relaunch= True
518
+
519
+
520
+ #Cytoplasm parameters
521
+ if type(values["cytoplasm_model_name"]) != str and not do_only_nuc:
522
+ sg.popup('Invalid cytoplasm model name.')
523
+ values['cytoplasm_model_name'] = user_parameters['cytoplasm_model_name']
524
+ relaunch= True
525
+ if is_multichannel :
526
+ if values["cytoplasm_channel"] not in available_channels and not do_only_nuc:
527
+ sg.popup('For given input image please select channel in {0}\ncytoplasm_channel : {1}'.format(available_channels, cytoplasm_channel))
528
+ relaunch= True
529
+ values['cytoplasm_channel'] = user_parameters['cytoplasm_channel']
530
+ else :
531
+ values["cytoplasm_channel"] = ...
532
+
533
+ if type(values["cytoplasm_diameter"]) not in [int, float] and not do_only_nuc:
534
+ sg.popup("Incorrect cytoplasm size.")
535
+ relaunch= True
536
+ values['cytoplasm_diameter'] = user_parameters['cytoplasm_diameter']
537
+
538
+ #Nucleus parameters
539
+ if type(values["nucleus_model_name"]) != str :
540
+ sg.popup('Invalid nucleus model name.')
541
+ values['nucleus_model_name'] = user_parameters['nucleus_model_name']
542
+ relaunch= True
543
+
544
+ if is_multichannel :
545
+ if values["nucleus_channel"] not in available_channels :
546
+ sg.popup('For given input image please select channel in {0}\nnucleus channel : {1}'.format(available_channels, nucleus_channel))
547
+ relaunch= True
548
+ values['nucleus_channel'] = user_parameters['nucleus_channel']
549
+ else :
550
+ values["nucleus_channel"] = ...
551
+
552
+ if type(values["nucleus_diameter"]) not in [int, float] :
553
+ sg.popup("Incorrect nucleus size.")
554
+ relaunch= True
555
+ values['nucleus_diameter'] = user_parameters['nucleus_diameter']
556
+
557
+ if values["other_nucleus_image"] != '' :
558
+ if os.path.isdir(values["other_nucleus_image"]) :
559
+ values['other_nucleus_image'] = None
560
+ elif not os.path.isfile(values["other_nucleus_image"]) :
561
+ sg.popup("Nucleus image is not a file.")
562
+ relaunch=True
563
+ values['other_nucleus_image'] = None
564
+ else :
565
+ try :
566
+ nucleus_image = open_image(other_nucleus_image)
567
+ except Exception as e :
568
+ sg.popup("Could not open image.\n{0}".format(e))
569
+ relaunch=True
570
+ values['other_nucleus_image'] = user_parameters['other_nucleus_image']
571
+ else :
572
+ if nucleus_image.ndim != image.ndim - is_multichannel :
573
+ sg.popup("Nucleus image dimension missmatched. Expected same dimension as cytoplasm_image for monochannel or same dimension as cytoplasm_image -1 for is_multichannel\ncytoplasm dimension : {0}, nucleus dimension : {1}".format(image.ndim, nucleus_image.ndim))
574
+ nucleus_image = None
575
+ relaunch=True
576
+ values['other_nucleus_image'] = user_parameters['other_nucleus_image']
577
+
578
+ elif nucleus_image.shape != image[cytoplasm_channel].shape :
579
+ sg.popup("Nucleus image shape missmatched. Expected same shape as cytoplasm_image \ncytoplasm shape : {0}, nucleus shape : {1}".format(image[cytoplasm_channel].shape, nucleus_image.shape))
580
+ nucleus_image = None
581
+ relaunch=True
582
+ values['other_nucleus_image'] = user_parameters['other_nucleus_image']
583
+
584
+ else :
585
+ values["other_nucleus_image"] = None
586
+
587
+ return values, relaunch
588
+
589
+
498
590
  def remove_disjoint(image):
499
591
  """
500
592
  *CODE FROM BIG-FISH (LICENCE IN __INIT__.PY) IMPORTED TO AVOID IMPORT ERROR WHEN BIGFISH SEGMENTATION MODULE INITIALISES : try to import deprecated module for python 3.8