small-fish-gui 1.3.5__py3-none-any.whl → 1.5.0__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/.readthedocs.yaml +21 -0
- small_fish_gui/README.md +2 -3
- small_fish_gui/__init__.py +1 -1
- small_fish_gui/batch/__init__.py +5 -0
- small_fish_gui/batch/input.py +62 -0
- small_fish_gui/batch/integrity.py +158 -0
- small_fish_gui/batch/output.py +0 -0
- small_fish_gui/batch/pipeline.py +218 -0
- small_fish_gui/batch/prompt.py +428 -0
- small_fish_gui/batch/test.py +10 -0
- small_fish_gui/batch/update.py +132 -0
- small_fish_gui/batch/utils.py +66 -0
- small_fish_gui/batch/values.py +3 -0
- small_fish_gui/batch/values.txt +65 -0
- small_fish_gui/docs/conf.py +1 -0
- small_fish_gui/gui/animation.py +24 -15
- small_fish_gui/gui/layout.py +28 -7
- small_fish_gui/gui/prompts.py +11 -9
- small_fish_gui/interface/output.py +8 -4
- small_fish_gui/pipeline/__init__.py +21 -0
- small_fish_gui/pipeline/_napari_wrapper.py +63 -90
- small_fish_gui/pipeline/_preprocess.py +86 -28
- small_fish_gui/pipeline/_segmentation.py +165 -16
- small_fish_gui/pipeline/actions.py +6 -1
- small_fish_gui/pipeline/detection.py +75 -16
- small_fish_gui/pipeline/main.py +12 -5
- small_fish_gui/pipeline/utils.py +16 -0
- small_fish_gui/utils.py +6 -1
- {small_fish_gui-1.3.5.dist-info → small_fish_gui-1.5.0.dist-info}/METADATA +1 -1
- small_fish_gui-1.5.0.dist-info/RECORD +52 -0
- small_fish_gui/gui/batch.py +0 -312
- small_fish_gui/gui/test.py +0 -5
- small_fish_gui-1.3.5.dist-info/RECORD +0 -39
- {small_fish_gui-1.3.5.dist-info → small_fish_gui-1.5.0.dist-info}/WHEEL +0 -0
- {small_fish_gui-1.3.5.dist-info → small_fish_gui-1.5.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
List of keys for batch 'values' dict instance :
|
|
2
|
+
|
|
3
|
+
Batch_folder
|
|
4
|
+
0
|
|
5
|
+
image path
|
|
6
|
+
3D stack
|
|
7
|
+
multichannel
|
|
8
|
+
Dense regions deconvolution
|
|
9
|
+
Cluster computation
|
|
10
|
+
Segmentation
|
|
11
|
+
Napari correction
|
|
12
|
+
x
|
|
13
|
+
y
|
|
14
|
+
z
|
|
15
|
+
c
|
|
16
|
+
t
|
|
17
|
+
cyto_model_name
|
|
18
|
+
cytoplasm channel
|
|
19
|
+
cytoplasm diameter
|
|
20
|
+
nucleus_model_name
|
|
21
|
+
nucleus channel
|
|
22
|
+
nucleus diameter
|
|
23
|
+
Segment only nuclei
|
|
24
|
+
show segmentation
|
|
25
|
+
saving path
|
|
26
|
+
filename
|
|
27
|
+
threshold
|
|
28
|
+
threshold penalty
|
|
29
|
+
channel to compute
|
|
30
|
+
voxel_size_z
|
|
31
|
+
voxel_size_y
|
|
32
|
+
voxel_size_x
|
|
33
|
+
spot_size_z
|
|
34
|
+
spot_size_y
|
|
35
|
+
spot_size_x
|
|
36
|
+
log_kernel_size_z
|
|
37
|
+
log_kernel_size_y
|
|
38
|
+
log_kernel_size_x
|
|
39
|
+
minimum_distance_z
|
|
40
|
+
minimum_distance_y
|
|
41
|
+
minimum_distance_x
|
|
42
|
+
nucleus channel signal
|
|
43
|
+
alpha
|
|
44
|
+
beta
|
|
45
|
+
gamma
|
|
46
|
+
deconvolution_kernel_z
|
|
47
|
+
deconvolution_kernel_y
|
|
48
|
+
deconvolution_kernel_x
|
|
49
|
+
cluster size
|
|
50
|
+
min number of spots
|
|
51
|
+
Interactive threshold selector
|
|
52
|
+
spots_extraction_folder
|
|
53
|
+
spots_filename
|
|
54
|
+
do_spots_csv
|
|
55
|
+
do_spots_excel
|
|
56
|
+
do_spots_feather
|
|
57
|
+
output_folder
|
|
58
|
+
batch_name
|
|
59
|
+
save segmentation
|
|
60
|
+
save detection
|
|
61
|
+
extract spots
|
|
62
|
+
csv
|
|
63
|
+
xlsx
|
|
64
|
+
feather
|
|
65
|
+
2
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
#init conf file
|
small_fish_gui/gui/animation.py
CHANGED
|
@@ -10,21 +10,30 @@ WAITING_TEXT = [
|
|
|
10
10
|
|
|
11
11
|
def add_default_loading(funct) :
|
|
12
12
|
def inner(*args,**kwargs) :
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
13
|
+
|
|
14
|
+
hide_loading = kwargs.get("hide_loading")
|
|
15
|
+
if 'hide_loading' in kwargs : del kwargs['hide_loading']
|
|
16
|
+
|
|
17
|
+
if not hide_loading :
|
|
18
|
+
random_text = np.random.randint(0,len(WAITING_TEXT))
|
|
19
|
+
waiting_layout = [
|
|
20
|
+
[sg.Text(WAITING_TEXT[random_text], font= '10')]
|
|
21
|
+
]
|
|
22
|
+
window = sg.Window(
|
|
23
|
+
title= 'small_fish',
|
|
24
|
+
layout= waiting_layout,
|
|
25
|
+
grab_anywhere= True,
|
|
26
|
+
finalize=True
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
window.read(timeout= 30, close= False)
|
|
30
|
+
try :
|
|
31
|
+
return funct(*args, **kwargs)
|
|
32
|
+
finally :
|
|
33
|
+
window.close()
|
|
34
|
+
|
|
35
|
+
else :
|
|
26
36
|
return funct(*args, **kwargs)
|
|
27
|
-
|
|
28
|
-
window.close()
|
|
37
|
+
|
|
29
38
|
return inner
|
|
30
39
|
|
small_fish_gui/gui/layout.py
CHANGED
|
@@ -95,7 +95,7 @@ def path_layout(keys= [],look_for_dir = False, header=None, preset=os.getcwd())
|
|
|
95
95
|
|
|
96
96
|
max_length = len(max(keys, key=len))
|
|
97
97
|
layout = [
|
|
98
|
-
[sg.Text(pad_right(name, max_length, ' ')), Browse(key= name, initial_folder= preset)] for name in keys
|
|
98
|
+
[sg.Text(pad_right(name, max_length, ' ')), Browse(key= name, target=(555666777,2), initial_folder= preset), sg.Text('')] for name in keys
|
|
99
99
|
]
|
|
100
100
|
if isinstance(header, str) :
|
|
101
101
|
layout = [add_header(header)] + layout
|
|
@@ -152,7 +152,20 @@ def radio_layout(values, header=None) :
|
|
|
152
152
|
layout = [add_header(header)] + layout
|
|
153
153
|
return layout
|
|
154
154
|
|
|
155
|
-
def _segmentation_layout(
|
|
155
|
+
def _segmentation_layout(
|
|
156
|
+
multichannel,
|
|
157
|
+
cytoplasm_model_preset= 'cyto3',
|
|
158
|
+
nucleus_model_preset= 'nuclei',
|
|
159
|
+
cytoplasm_channel_preset=0,
|
|
160
|
+
nucleus_channel_preset=0,
|
|
161
|
+
other_nucleus_image_preset = None,
|
|
162
|
+
cyto_diameter_preset=30,
|
|
163
|
+
nucleus_diameter_preset= 30,
|
|
164
|
+
show_segmentation_preset= False,
|
|
165
|
+
segment_only_nuclei_preset=False,
|
|
166
|
+
saving_path_preset=os.getcwd(),
|
|
167
|
+
filename_preset='cell_segmentation.png',
|
|
168
|
+
) :
|
|
156
169
|
|
|
157
170
|
USE_GPU = use_gpu()
|
|
158
171
|
|
|
@@ -160,7 +173,9 @@ def _segmentation_layout(multichannel, cytoplasm_model_preset= 'cyto2', nucleus_
|
|
|
160
173
|
if len(models_list) == 0 : models_list = ['no model found']
|
|
161
174
|
|
|
162
175
|
#Header : GPU availabality
|
|
163
|
-
layout = [
|
|
176
|
+
layout = [
|
|
177
|
+
[sg.Text("GPU is currently "), sg.Text('ON', text_color= 'green') if USE_GPU else sg.Text('OFF', text_color= 'red')]
|
|
178
|
+
]
|
|
164
179
|
|
|
165
180
|
#cytoplasm parameters
|
|
166
181
|
layout += [
|
|
@@ -170,6 +185,8 @@ def _segmentation_layout(multichannel, cytoplasm_model_preset= 'cyto2', nucleus_
|
|
|
170
185
|
]
|
|
171
186
|
|
|
172
187
|
if multichannel : layout += parameters_layout(['cytoplasm channel'],default_values= [cytoplasm_channel_preset])
|
|
188
|
+
|
|
189
|
+
|
|
173
190
|
layout += parameters_layout(['cytoplasm diameter'], unit= "px", default_values= [cyto_diameter_preset])
|
|
174
191
|
#Nucleus parameters
|
|
175
192
|
layout += [
|
|
@@ -179,6 +196,7 @@ def _segmentation_layout(multichannel, cytoplasm_model_preset= 'cyto2', nucleus_
|
|
|
179
196
|
]
|
|
180
197
|
|
|
181
198
|
if multichannel : layout += parameters_layout(['nucleus channel'], default_values= [nucleus_channel_preset])
|
|
199
|
+
layout += path_layout(['other_nucleus_image'], preset=other_nucleus_image_preset)
|
|
182
200
|
layout += parameters_layout([ 'nucleus diameter'],unit= "px", default_values= [nucleus_diameter_preset])
|
|
183
201
|
layout += bool_layout(["Segment only nuclei"], preset=segment_only_nuclei_preset)
|
|
184
202
|
|
|
@@ -246,7 +264,12 @@ def _detection_layout(
|
|
|
246
264
|
unit = {'voxel_size' : 'nm', 'minimum_distance' : 'nm', 'spot_size' : 'radius(nm)', 'log_kernel_size' : 'px'}
|
|
247
265
|
|
|
248
266
|
layout += tuple_layout(opt=opt, unit=unit, default_dict=default_dict, voxel_size= tuple_shape, spot_size= tuple_shape, log_kernel_size= tuple_shape, minimum_distance= tuple_shape)
|
|
249
|
-
|
|
267
|
+
|
|
268
|
+
if (do_segmentation and is_multichannel) or (is_multichannel and segmentation_done):
|
|
269
|
+
default_segmentation = [default_dict.setdefault('nucleus channel signal', default_dict.setdefault('nucleus channel',0))]
|
|
270
|
+
layout += [[sg.Text("nucleus channel signal "), sg.InputText(default_text=default_segmentation, key= "nucleus channel signal", size= 5, tooltip= "Channel from which signal will be measured for nucleus features, \nallowing you to measure signal from a different channel than the one used for segmentation.")]]
|
|
271
|
+
# layout += parameters_layout(['nucleus channel signal'], default_values=default_segmentation) + [[sg.Text("Channel from which signal will be measured for nucleus features, allowing you to measure signal from a different channel than the one used for segmentation.")]]
|
|
272
|
+
|
|
250
273
|
#Deconvolution
|
|
251
274
|
if do_dense_region_deconvolution :
|
|
252
275
|
default_dense_regions_deconvolution = [default_dict.setdefault('alpha',0.5), default_dict.setdefault('beta',1)]
|
|
@@ -259,9 +282,7 @@ def _detection_layout(
|
|
|
259
282
|
layout += parameters_layout(['cluster size'], unit="radius(nm)", default_values=[default_dict.setdefault('cluster size',400)])
|
|
260
283
|
layout += parameters_layout(['min number of spots'], default_values=[default_dict.setdefault('min number of spots', 5)])
|
|
261
284
|
|
|
262
|
-
|
|
263
|
-
default_segmentation = [default_dict.setdefault('nucleus channel signal', default_dict.setdefault('nucleus channel',0))]
|
|
264
|
-
layout += parameters_layout(['nucleus channel signal'], default_values=default_segmentation) + [[sg.Text(" channel from which signal will be measured for nucleus features.")]]
|
|
285
|
+
|
|
265
286
|
|
|
266
287
|
layout += bool_layout(['Interactive threshold selector'], preset=[False])
|
|
267
288
|
layout += path_layout(
|
small_fish_gui/gui/prompts.py
CHANGED
|
@@ -32,14 +32,14 @@ def prompt(layout, add_ok_cancel=True, timeout=None, timeout_key='TIMEOUT_KEY',
|
|
|
32
32
|
window.close()
|
|
33
33
|
return event, values
|
|
34
34
|
|
|
35
|
-
def prompt_with_help(layout, help =None, add_scrollbar=True) :
|
|
35
|
+
def prompt_with_help(layout, help =None, add_scrollbar=True, vertical_scroll_only=True) :
|
|
36
36
|
layout += [[]]
|
|
37
37
|
layout += [[sg.Button('Help')]]
|
|
38
38
|
layout += [[sg.Button('Ok'), sg.Button('Cancel')]]
|
|
39
39
|
|
|
40
40
|
if add_scrollbar :
|
|
41
41
|
size = (400,500)
|
|
42
|
-
col_elmt = sg.Column(layout, scrollable=True, vertical_scroll_only=
|
|
42
|
+
col_elmt = sg.Column(layout, scrollable=True, vertical_scroll_only=vertical_scroll_only, size=size)
|
|
43
43
|
layout = [[col_elmt]]
|
|
44
44
|
else :
|
|
45
45
|
size = (None,None)
|
|
@@ -280,11 +280,13 @@ def _warning_popup(warning:str) :
|
|
|
280
280
|
|
|
281
281
|
def _sumup_df(results: pd.DataFrame) :
|
|
282
282
|
|
|
283
|
+
COLUMNS = ['acquisition_id','threshold', 'spot_number', 'cell_number', 'filename', 'channel to compute']
|
|
284
|
+
|
|
283
285
|
if len(results) > 0 :
|
|
284
286
|
if 'channel to compute' not in results : results['channel to compute'] = np.NaN
|
|
285
|
-
res = results.loc[:,
|
|
287
|
+
res = results.loc[:,COLUMNS]
|
|
286
288
|
else :
|
|
287
|
-
res = pd.DataFrame(columns=
|
|
289
|
+
res = pd.DataFrame(columns= COLUMNS)
|
|
288
290
|
|
|
289
291
|
return res
|
|
290
292
|
|
|
@@ -293,14 +295,14 @@ def hub_prompt(fov_results, do_segmentation=False) :
|
|
|
293
295
|
sumup_df = _sumup_df(fov_results)
|
|
294
296
|
|
|
295
297
|
if do_segmentation :
|
|
296
|
-
segmentation_object = sg.Text('Segmentation
|
|
298
|
+
segmentation_object = sg.Text('Segmentation in memory', font='8', text_color= 'green')
|
|
297
299
|
else :
|
|
298
|
-
segmentation_object = sg.Text('
|
|
300
|
+
segmentation_object = sg.Text('No segmentation in memory', font='8', text_color= 'red')
|
|
299
301
|
|
|
300
302
|
layout = [
|
|
301
303
|
[sg.Text('RESULTS', font= 'bold 13')],
|
|
302
304
|
[sg.Table(values= list(sumup_df.values), headings= list(sumup_df.columns), row_height=20, num_rows= 5, vertical_scroll_only=False, key= "result_table"), segmentation_object],
|
|
303
|
-
[sg.Button('Add detection'), sg.Button('Compute colocalisation')
|
|
305
|
+
[sg.Button('Add detection'), sg.Button('Compute colocalisation'), sg.Button('Batch detection')],
|
|
304
306
|
[sg.Button('Save results', button_color= 'green'), sg.Button('Delete acquisitions',button_color= 'gray'), sg.Button('Reset segmentation',button_color= 'gray'), sg.Button('Reset results',button_color= 'gray')]
|
|
305
307
|
# [sg.Button('Save results', button_color= 'green'), sg.Button('Reset results',button_color= 'gray')]
|
|
306
308
|
]
|
|
@@ -333,7 +335,7 @@ def ask_detection_confirmation(used_threshold) :
|
|
|
333
335
|
[sg.Button("Ok"), sg.Button("Restart detection")]
|
|
334
336
|
]
|
|
335
337
|
|
|
336
|
-
event, value = prompt(layout, add_ok_cancel=False)
|
|
338
|
+
event, value = prompt(layout, add_ok_cancel=False, add_scrollbar=False)
|
|
337
339
|
|
|
338
340
|
if event == 'Restart detection' :
|
|
339
341
|
return False
|
|
@@ -346,7 +348,7 @@ def ask_cancel_detection() :
|
|
|
346
348
|
[sg.Button("Yes"), sg.Button("No")]
|
|
347
349
|
]
|
|
348
350
|
|
|
349
|
-
event, value = prompt(layout, add_ok_cancel=False)
|
|
351
|
+
event, value = prompt(layout, add_ok_cancel=False, add_scrollbar=False)
|
|
350
352
|
|
|
351
353
|
if event == 'No' :
|
|
352
354
|
return False
|
|
@@ -10,9 +10,11 @@ def _cast_spot_to_tuple(spot) :
|
|
|
10
10
|
def _cast_spots_to_tuple(spots) :
|
|
11
11
|
return tuple(list(map(_cast_spot_to_tuple, spots)))
|
|
12
12
|
|
|
13
|
-
def write_results(dataframe: pd.DataFrame, path:str, filename:str, do_excel= True, do_feather= False, do_csv=False) :
|
|
13
|
+
def write_results(dataframe: pd.DataFrame, path:str, filename:str, do_excel= True, do_feather= False, do_csv=False, overwrite=False) :
|
|
14
14
|
check_parameter(dataframe= pd.DataFrame, path= str, filename = str, do_excel = bool, do_feather = bool)
|
|
15
15
|
|
|
16
|
+
dataframe.columns = dataframe.columns.astype(str) # assert columns header are string for feather
|
|
17
|
+
|
|
16
18
|
if len(dataframe) == 0 : return True
|
|
17
19
|
if not do_excel and not do_feather and not do_csv :
|
|
18
20
|
return False
|
|
@@ -23,9 +25,11 @@ def write_results(dataframe: pd.DataFrame, path:str, filename:str, do_excel= Tru
|
|
|
23
25
|
|
|
24
26
|
new_filename = filename
|
|
25
27
|
i= 1
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
28
|
+
|
|
29
|
+
if not overwrite :
|
|
30
|
+
while new_filename + '.xlsx' in os.listdir(path) or new_filename + '.feather' in os.listdir(path) or new_filename + '.csv' in os.listdir(path) :
|
|
31
|
+
new_filename = filename + '_{0}'.format(i)
|
|
32
|
+
i+=1
|
|
29
33
|
|
|
30
34
|
if 'image' in dataframe.columns :
|
|
31
35
|
dataframe = dataframe.drop(['image'], axis=1)
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Module containing main pipeline for user mode as well as calls for pipeline functions.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from ._preprocess import reorder_shape
|
|
6
|
+
from ._preprocess import reorder_image_stack
|
|
7
|
+
from ._preprocess import prepare_image_detection
|
|
8
|
+
from ._preprocess import convert_parameters_types
|
|
9
|
+
|
|
10
|
+
from ._segmentation import launch_segmentation
|
|
11
|
+
from ._segmentation import _cast_segmentation_parameters
|
|
12
|
+
from ._segmentation import cell_segmentation
|
|
13
|
+
from ._segmentation import plot_segmentation
|
|
14
|
+
|
|
15
|
+
from .detection import launch_detection
|
|
16
|
+
from .detection import launch_features_computation
|
|
17
|
+
from .detection import launch_cell_extraction
|
|
18
|
+
from .detection import get_nucleus_signal
|
|
19
|
+
from .detection import output_spot_tiffvisual
|
|
20
|
+
|
|
21
|
+
from .spots import launch_spots_extraction
|
|
@@ -2,59 +2,26 @@
|
|
|
2
2
|
Contains Napari wrappers to visualise and correct spots/clusters.
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
+
import napari.layers
|
|
6
|
+
import napari.types
|
|
5
7
|
import numpy as np
|
|
6
|
-
import scipy.ndimage as ndi
|
|
7
8
|
import napari
|
|
8
9
|
|
|
9
|
-
from napari.utils.events import Event
|
|
10
|
-
from napari.layers import Points
|
|
11
10
|
from bigfish.stack import check_parameter
|
|
12
11
|
from ..utils import compute_anisotropy_coef
|
|
13
12
|
from ._colocalisation import spots_multicolocalisation
|
|
14
13
|
|
|
15
|
-
class Points_callback :
|
|
16
|
-
"""
|
|
17
|
-
Custom class to handle points number evolution during Napari run.
|
|
18
|
-
"""
|
|
19
|
-
|
|
20
|
-
def __init__(self, points, next_id) -> None:
|
|
21
|
-
self.points = points
|
|
22
|
-
self.next_id = next_id
|
|
23
|
-
self._set_callback()
|
|
24
|
-
|
|
25
|
-
def __str__(self) -> str:
|
|
26
|
-
string = 'Points_callback object state :\ncurrent_points_number : {0}\ncurrnet_id : {1}'.format(self.current_points_number, self.next_id)
|
|
27
|
-
return string
|
|
28
|
-
|
|
29
|
-
def get_points(self) :
|
|
30
|
-
return self.points
|
|
31
|
-
|
|
32
|
-
def get_next_id(self) :
|
|
33
|
-
return self.next_id
|
|
34
|
-
|
|
35
|
-
def _set_callback(self) :
|
|
36
|
-
def callback(event:Event) :
|
|
37
|
-
|
|
38
|
-
old_points = self.get_points()
|
|
39
|
-
new_points:Points = event.source.data
|
|
40
|
-
features = event.source.features
|
|
41
|
-
|
|
42
|
-
current_point_number = len(old_points)
|
|
43
|
-
next_id = self.get_next_id()
|
|
44
|
-
new_points_number = len(new_points)
|
|
45
|
-
|
|
46
|
-
if new_points_number > current_point_number :
|
|
47
|
-
features.at[new_points_number - 1, "id"] = next_id
|
|
48
|
-
self.next_id += 1
|
|
49
|
-
|
|
50
|
-
#preparing next callback
|
|
51
|
-
self.points = new_points
|
|
52
|
-
self._set_callback()
|
|
53
|
-
self.callback = callback
|
|
54
|
-
|
|
55
14
|
def _update_clusters(new_clusters: np.ndarray, spots: np.ndarray, voxel_size, cluster_size, min_spot_number, shape) :
|
|
56
15
|
if len(new_clusters) == 0 : return new_clusters
|
|
57
16
|
if len(spots) == 0 : return new_clusters
|
|
17
|
+
|
|
18
|
+
if len(new_clusters[0]) in [2,3] :
|
|
19
|
+
new_clusters = np.concatenate([
|
|
20
|
+
new_clusters,
|
|
21
|
+
np.zeros(shape=(len(new_clusters),1), dtype=int),
|
|
22
|
+
np.arange(len(new_clusters), dtype=int).reshape(len(new_clusters),1)
|
|
23
|
+
],axis=1, dtype=int)
|
|
24
|
+
|
|
58
25
|
assert len(new_clusters[0]) == 4 or len(new_clusters[0]) == 5, "Wrong number of coordinates for clusters should not happen."
|
|
59
26
|
|
|
60
27
|
# Update spots clusters
|
|
@@ -93,45 +60,48 @@ def correct_spots(image, spots, voxel_size= (1,1,1), clusters= None, cluster_siz
|
|
|
93
60
|
)
|
|
94
61
|
|
|
95
62
|
scale = compute_anisotropy_coef(voxel_size)
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
63
|
+
Viewer = napari.Viewer(ndisplay=2, title= 'Spot correction', axis_labels=['z','y','x'], show= False)
|
|
64
|
+
Viewer.add_image(image, scale=scale, name= "rna signal", blending= 'additive', colormap='red', contrast_limits=[image.min(), image.max()])
|
|
65
|
+
other_colors = ['green', 'blue', 'gray', 'cyan', 'bop orange', 'bop purple'] * ((len(other_images)-1 // 7) + 1)
|
|
66
|
+
for im, color in zip(other_images, other_colors) :
|
|
67
|
+
Viewer.add_image(im, scale=scale, blending='additive', visible=False, colormap=color, contrast_limits=[im.min(), im.max()])
|
|
68
|
+
layer_offset = len(other_images)
|
|
69
|
+
|
|
70
|
+
Viewer.add_points( # single molecule spots; this layer can be update by user.
|
|
71
|
+
spots,
|
|
72
|
+
size = 5,
|
|
73
|
+
scale=scale,
|
|
74
|
+
face_color= 'transparent',
|
|
75
|
+
opacity= 1,
|
|
76
|
+
symbol= 'disc',
|
|
77
|
+
name= 'single spots'
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
if type(clusters) != type(None) : Viewer.add_points( # cluster; this layer can be update by user.
|
|
81
|
+
clusters[:,:dim],
|
|
82
|
+
size = 10,
|
|
83
|
+
scale=scale,
|
|
84
|
+
face_color= 'blue',
|
|
85
|
+
opacity= 0.7,
|
|
86
|
+
symbol= 'diamond',
|
|
87
|
+
name= 'foci',
|
|
88
|
+
features= {"spot_number" : clusters[:,dim], "id" : clusters[:,dim+1]},
|
|
89
|
+
feature_defaults= {"spot_number" : 0, "id" : -1}
|
|
90
|
+
)
|
|
119
91
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
],
|
|
126
|
-
axis= 1)
|
|
92
|
+
if type(cell_label) != type(None) and not np.array_equal(nucleus_label, cell_label) : Viewer.add_labels(cell_label, scale=scale, opacity= 0.2, blending= 'additive')
|
|
93
|
+
if type(nucleus_label) != type(None) : Viewer.add_labels(nucleus_label, scale=scale, opacity= 0.2, blending= 'additive')
|
|
94
|
+
|
|
95
|
+
Viewer.show(block=False)
|
|
96
|
+
napari.run()
|
|
127
97
|
|
|
128
|
-
|
|
129
|
-
else : new_clusters = None
|
|
98
|
+
new_spots = np.array(Viewer.layers['single spots'].data, dtype= int)
|
|
130
99
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
100
|
+
if type(clusters) != type(None) :
|
|
101
|
+
if len(clusters) > 0 :
|
|
102
|
+
new_clusters = np.array(Viewer.layers['foci'].data, dtype= int)
|
|
103
|
+
new_clusters = _update_clusters(new_clusters, new_spots, voxel_size=voxel_size, cluster_size=cluster_size, min_spot_number=min_spot_number, shape=image.shape)
|
|
104
|
+
else : new_clusters = None
|
|
135
105
|
|
|
136
106
|
return new_spots, new_clusters
|
|
137
107
|
|
|
@@ -168,25 +138,27 @@ def show_segmentation(
|
|
|
168
138
|
Viewer = napari.Viewer(ndisplay=2, title= 'Show segmentation', axis_labels=['z','y','x'] if dim == 3 else ['y', 'x'], show= False)
|
|
169
139
|
|
|
170
140
|
# Adding channels
|
|
171
|
-
Viewer.add_image(nuc_image, name= "nucleus signal", blending= 'additive', colormap='blue', contrast_limits=[nuc_image.min(), nuc_image.max()])
|
|
172
|
-
Viewer.add_labels(nuc_label, opacity= 0.5, blending= 'additive')
|
|
141
|
+
nuc_signal_layer = Viewer.add_image(nuc_image, name= "nucleus signal", blending= 'additive', colormap='blue', contrast_limits=[nuc_image.min(), nuc_image.max()])
|
|
142
|
+
nuc_label_layer = Viewer.add_labels(nuc_label, opacity= 0.5, blending= 'additive', name= 'nucleus_label',)
|
|
143
|
+
nuc_label_layer.preserve_labels = True
|
|
173
144
|
|
|
174
145
|
#Adding labels
|
|
175
146
|
if type(cyto_image) != type(None) : Viewer.add_image(cyto_image, name= "cytoplasm signal", blending= 'additive', colormap='red', contrast_limits=[cyto_image.min(), cyto_image.max()])
|
|
176
|
-
if type(cyto_label) != type(None) and not np.array_equal(cyto_label, nuc_label)
|
|
147
|
+
if (type(cyto_label) != type(None) and not np.array_equal(cyto_label, nuc_label) ) or (type(cyto_label) != type(None) and cyto_label.max() == 0):
|
|
148
|
+
cyto_label_layer = Viewer.add_labels(cyto_label, opacity= 0.4, blending= 'additive', name= 'cytoplasm_label')
|
|
149
|
+
cyto_label_layer.preserve_labels = True
|
|
177
150
|
|
|
178
151
|
#Launch Napari
|
|
179
152
|
Viewer.show(block=False)
|
|
180
153
|
napari.run()
|
|
181
154
|
|
|
182
|
-
|
|
183
|
-
|
|
155
|
+
|
|
156
|
+
new_nuc_label = Viewer.layers['nucleus_label'].data
|
|
157
|
+
if type(cyto_label) != type(None) and not np.array_equal(cyto_label, nuc_label) : new_cyto_label = Viewer.layers['cytoplasm_label'].data
|
|
184
158
|
else : new_cyto_label = new_nuc_label
|
|
185
159
|
|
|
186
160
|
return new_nuc_label, new_cyto_label
|
|
187
161
|
|
|
188
|
-
|
|
189
|
-
|
|
190
162
|
def threshold_selection(
|
|
191
163
|
image : np.ndarray,
|
|
192
164
|
filtered_image : np.ndarray,
|
|
@@ -195,7 +167,7 @@ def threshold_selection(
|
|
|
195
167
|
) :
|
|
196
168
|
|
|
197
169
|
"""
|
|
198
|
-
To view code for spot selection
|
|
170
|
+
To view code for spot selection have a look at magicgui instance created with `detection._create_threshold_slider` which is then passed to this napari wrapper as 'threshold_slider' argument.
|
|
199
171
|
"""
|
|
200
172
|
|
|
201
173
|
Viewer = napari.Viewer(title= "Small fish - Threshold selector", ndisplay=2, show=True)
|
|
@@ -218,12 +190,13 @@ def threshold_selection(
|
|
|
218
190
|
|
|
219
191
|
Viewer.window.add_dock_widget(threshold_slider, name='threshold_selector')
|
|
220
192
|
threshold_slider() #First occurence with auto or entered threshold.
|
|
193
|
+
|
|
221
194
|
napari.run()
|
|
222
195
|
|
|
223
|
-
spots = Viewer.layers[
|
|
196
|
+
spots = Viewer.layers['single spots'].data.astype(int)
|
|
224
197
|
if len(spots) == 0 :
|
|
225
|
-
|
|
198
|
+
pass
|
|
226
199
|
else :
|
|
227
|
-
threshold = Viewer.layers[
|
|
200
|
+
threshold = Viewer.layers['single spots'].properties.get('threshold')[0]
|
|
228
201
|
|
|
229
202
|
return spots, threshold
|