small-fish-gui 1.3.5__py3-none-any.whl → 1.4.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/__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 +426 -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/gui/animation.py +24 -15
- small_fish_gui/gui/layout.py +7 -4
- small_fish_gui/gui/prompts.py +3 -3
- small_fish_gui/interface/output.py +8 -4
- small_fish_gui/pipeline/__init__.py +21 -0
- small_fish_gui/pipeline/_preprocess.py +62 -8
- small_fish_gui/pipeline/_segmentation.py +36 -0
- small_fish_gui/pipeline/detection.py +68 -7
- small_fish_gui/pipeline/main.py +7 -3
- small_fish_gui/utils.py +6 -1
- {small_fish_gui-1.3.5.dist-info → small_fish_gui-1.4.0.dist-info}/METADATA +1 -1
- {small_fish_gui-1.3.5.dist-info → small_fish_gui-1.4.0.dist-info}/RECORD +26 -16
- small_fish_gui/gui/batch.py +0 -312
- small_fish_gui/gui/test.py +0 -5
- {small_fish_gui-1.3.5.dist-info → small_fish_gui-1.4.0.dist-info}/WHEEL +0 -0
- {small_fish_gui-1.3.5.dist-info → small_fish_gui-1.4.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
|
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
|
@@ -246,7 +246,12 @@ def _detection_layout(
|
|
|
246
246
|
unit = {'voxel_size' : 'nm', 'minimum_distance' : 'nm', 'spot_size' : 'radius(nm)', 'log_kernel_size' : 'px'}
|
|
247
247
|
|
|
248
248
|
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
|
-
|
|
249
|
+
|
|
250
|
+
if (do_segmentation and is_multichannel) or (is_multichannel and segmentation_done):
|
|
251
|
+
default_segmentation = [default_dict.setdefault('nucleus channel signal', default_dict.setdefault('nucleus channel',0))]
|
|
252
|
+
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.")]]
|
|
253
|
+
# 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.")]]
|
|
254
|
+
|
|
250
255
|
#Deconvolution
|
|
251
256
|
if do_dense_region_deconvolution :
|
|
252
257
|
default_dense_regions_deconvolution = [default_dict.setdefault('alpha',0.5), default_dict.setdefault('beta',1)]
|
|
@@ -259,9 +264,7 @@ def _detection_layout(
|
|
|
259
264
|
layout += parameters_layout(['cluster size'], unit="radius(nm)", default_values=[default_dict.setdefault('cluster size',400)])
|
|
260
265
|
layout += parameters_layout(['min number of spots'], default_values=[default_dict.setdefault('min number of spots', 5)])
|
|
261
266
|
|
|
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.")]]
|
|
267
|
+
|
|
265
268
|
|
|
266
269
|
layout += bool_layout(['Interactive threshold selector'], preset=[False])
|
|
267
270
|
layout += path_layout(
|
small_fish_gui/gui/prompts.py
CHANGED
|
@@ -300,7 +300,7 @@ def hub_prompt(fov_results, do_segmentation=False) :
|
|
|
300
300
|
layout = [
|
|
301
301
|
[sg.Text('RESULTS', font= 'bold 13')],
|
|
302
302
|
[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')
|
|
303
|
+
[sg.Button('Add detection'), sg.Button('Compute colocalisation'), sg.Button('Batch detection')],
|
|
304
304
|
[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
305
|
# [sg.Button('Save results', button_color= 'green'), sg.Button('Reset results',button_color= 'gray')]
|
|
306
306
|
]
|
|
@@ -333,7 +333,7 @@ def ask_detection_confirmation(used_threshold) :
|
|
|
333
333
|
[sg.Button("Ok"), sg.Button("Restart detection")]
|
|
334
334
|
]
|
|
335
335
|
|
|
336
|
-
event, value = prompt(layout, add_ok_cancel=False)
|
|
336
|
+
event, value = prompt(layout, add_ok_cancel=False, add_scrollbar=False)
|
|
337
337
|
|
|
338
338
|
if event == 'Restart detection' :
|
|
339
339
|
return False
|
|
@@ -346,7 +346,7 @@ def ask_cancel_detection() :
|
|
|
346
346
|
[sg.Button("Yes"), sg.Button("No")]
|
|
347
347
|
]
|
|
348
348
|
|
|
349
|
-
event, value = prompt(layout, add_ok_cancel=False)
|
|
349
|
+
event, value = prompt(layout, add_ok_cancel=False, add_scrollbar=False)
|
|
350
350
|
|
|
351
351
|
if event == 'No' :
|
|
352
352
|
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
|
|
@@ -67,7 +67,7 @@ def map_channels(user_parameters) :
|
|
|
67
67
|
multichannel = user_parameters['multichannel']
|
|
68
68
|
|
|
69
69
|
try :
|
|
70
|
-
map = _auto_map_channels(
|
|
70
|
+
map = _auto_map_channels(is_3D_stack, is_time_stack, multichannel, image=image)
|
|
71
71
|
except MappingError as e :
|
|
72
72
|
sg.popup("Automatic dimension mapping went wrong. Please indicate manually dimensions positions in the array.")
|
|
73
73
|
map = _ask_channel_map(image.shape, is_3D_stack, is_time_stack, multichannel, preset_map= e.get_map())
|
|
@@ -77,8 +77,9 @@ def map_channels(user_parameters) :
|
|
|
77
77
|
|
|
78
78
|
return map
|
|
79
79
|
|
|
80
|
-
def _auto_map_channels(image: np.ndarray,
|
|
81
|
-
shape
|
|
80
|
+
def _auto_map_channels(is_3D_stack, is_time_stack, multichannel, image: np.ndarray=None, shape=None) :
|
|
81
|
+
if type(shape) == type(None) :
|
|
82
|
+
shape = image.shape
|
|
82
83
|
reducing_list = list(shape)
|
|
83
84
|
|
|
84
85
|
#Set the biggest dimension to y
|
|
@@ -194,8 +195,8 @@ def convert_parameters_types(values:dict) :
|
|
|
194
195
|
else : values[tuple_parameter] = tuple_values
|
|
195
196
|
|
|
196
197
|
#Parameters
|
|
197
|
-
int_list = ['threshold', 'channel_to_compute', 'min number of spots', 'cluster size','nucleus channel signal']
|
|
198
|
-
float_list = ['
|
|
198
|
+
int_list = ['threshold', 'channel_to_compute', 'channel to compute', 'min number of spots', 'cluster size','nucleus channel signal']
|
|
199
|
+
float_list = ['alpha', 'beta', 'gamma', 'threshold penalty']
|
|
199
200
|
|
|
200
201
|
for parameter in int_list :
|
|
201
202
|
try :
|
|
@@ -213,7 +214,15 @@ def convert_parameters_types(values:dict) :
|
|
|
213
214
|
|
|
214
215
|
return values
|
|
215
216
|
|
|
216
|
-
def check_integrity(
|
|
217
|
+
def check_integrity(
|
|
218
|
+
values: dict,
|
|
219
|
+
do_dense_region_deconvolution,
|
|
220
|
+
do_clustering,
|
|
221
|
+
multichannel,
|
|
222
|
+
segmentation_done,
|
|
223
|
+
map,
|
|
224
|
+
shape
|
|
225
|
+
):
|
|
217
226
|
"""
|
|
218
227
|
Checks that parameters given in input by user are fit to be used for bigfish detection.
|
|
219
228
|
"""
|
|
@@ -233,10 +242,22 @@ def check_integrity(values: dict, do_dense_region_deconvolution, multichannel,se
|
|
|
233
242
|
_warning_popup('No gamma found; image will not be denoised before deconvolution.')
|
|
234
243
|
values['gamma'] = 0
|
|
235
244
|
|
|
245
|
+
if values['alpha'] > 1 or values['alpha'] < 0 :
|
|
246
|
+
raise ParameterInputError("alpha must be set between 0 and 1.")
|
|
247
|
+
|
|
248
|
+
if do_clustering :
|
|
249
|
+
if not isinstance(values['min number of spots'], (int)) :
|
|
250
|
+
raise ParameterInputError("Incorrect min spot number parameter.")
|
|
251
|
+
if not isinstance(values['cluster size'], (int)) :
|
|
252
|
+
raise ParameterInputError("Incorrect cluster size parameter.")
|
|
253
|
+
|
|
236
254
|
#channel
|
|
237
255
|
if multichannel :
|
|
238
256
|
ch_len = shape[int(map['c'])]
|
|
239
|
-
|
|
257
|
+
|
|
258
|
+
if type(segmentation_done) == type(None) :
|
|
259
|
+
pass
|
|
260
|
+
elif segmentation_done :
|
|
240
261
|
try : nuc_signal_ch = int(values['nucleus channel signal'])
|
|
241
262
|
except Exception :
|
|
242
263
|
raise ParameterInputError("Incorrect channel for nucleus signal measure.")
|
|
@@ -259,7 +280,6 @@ def check_integrity(values: dict, do_dense_region_deconvolution, multichannel,se
|
|
|
259
280
|
|
|
260
281
|
return values
|
|
261
282
|
|
|
262
|
-
|
|
263
283
|
def reorder_shape(shape, map) :
|
|
264
284
|
x = [int(map['x']),]
|
|
265
285
|
y = [int(map['y']),]
|
|
@@ -275,6 +295,40 @@ def reorder_shape(shape, map) :
|
|
|
275
295
|
|
|
276
296
|
return new_shape
|
|
277
297
|
|
|
298
|
+
def _check_segmentation_parameters(
|
|
299
|
+
user_parameters,
|
|
300
|
+
shape,
|
|
301
|
+
is_multichannel,
|
|
302
|
+
) :
|
|
303
|
+
|
|
304
|
+
available_channels = list(range(len(shape)))
|
|
305
|
+
do_only_nuc = user_parameters['Segment only nuclei']
|
|
306
|
+
cyto_model_name = user_parameters['cyto_model_name']
|
|
307
|
+
cyto_size = user_parameters['cytoplasm diameter']
|
|
308
|
+
cytoplasm_channel = user_parameters['cytoplasm channel']
|
|
309
|
+
nucleus_model_name = user_parameters['nucleus_model_name']
|
|
310
|
+
nucleus_size = user_parameters['nucleus diameter']
|
|
311
|
+
nucleus_channel = user_parameters['nucleus channel']
|
|
312
|
+
|
|
313
|
+
|
|
314
|
+
if type(cyto_model_name) != str and not do_only_nuc:
|
|
315
|
+
raise ParameterInputError('Invalid cytoplasm model name.')
|
|
316
|
+
if cytoplasm_channel not in available_channels and not do_only_nuc and is_multichannel:
|
|
317
|
+
raise ParameterInputError('For given input image please select channel in {0}\ncytoplasm channel : {1}'.format(available_channels, cytoplasm_channel))
|
|
318
|
+
|
|
319
|
+
if type(cyto_size) not in [int, float] and not do_only_nuc:
|
|
320
|
+
raise ParameterInputError("Incorrect cytoplasm size.")
|
|
321
|
+
|
|
322
|
+
if type(nucleus_model_name) != str :
|
|
323
|
+
raise ParameterInputError('Invalid nucleus model name.')
|
|
324
|
+
|
|
325
|
+
if nucleus_channel not in available_channels and is_multichannel:
|
|
326
|
+
raise ParameterInputError('For given input image please select channel in {0}\nnucleus channel : {1}'.format(available_channels, nucleus_channel))
|
|
327
|
+
|
|
328
|
+
if type(nucleus_size) not in [int, float] :
|
|
329
|
+
raise ParameterInputError("Incorrect nucleus size.")
|
|
330
|
+
|
|
331
|
+
|
|
278
332
|
def clean_unused_parameters_cache(user_parameters: dict) :
|
|
279
333
|
"""
|
|
280
334
|
Clean unused parameters that were set to None in previous run.
|
|
@@ -351,3 +351,39 @@ def remove_disjoint(image):
|
|
|
351
351
|
image_cleaned = image_cleaned.astype(bool)
|
|
352
352
|
|
|
353
353
|
return image_cleaned
|
|
354
|
+
|
|
355
|
+
def plot_segmentation(
|
|
356
|
+
cyto_image : np.ndarray,
|
|
357
|
+
cyto_label : np.ndarray,
|
|
358
|
+
nuc_image : np.ndarray,
|
|
359
|
+
nuc_label : np.ndarray,
|
|
360
|
+
path :str,
|
|
361
|
+
do_only_nuc=False
|
|
362
|
+
) :
|
|
363
|
+
|
|
364
|
+
if nuc_image.ndim == 3 :
|
|
365
|
+
nuc_image = np.max(nuc_image,axis=0)
|
|
366
|
+
|
|
367
|
+
plot.plot_segmentation_boundary(
|
|
368
|
+
image=nuc_image,
|
|
369
|
+
nuc_label= nuc_label,
|
|
370
|
+
boundary_size= 3,
|
|
371
|
+
contrast=True,
|
|
372
|
+
path_output=path + "_nuclei_segmentation.png",
|
|
373
|
+
show=False,
|
|
374
|
+
)
|
|
375
|
+
|
|
376
|
+
|
|
377
|
+
if not do_only_nuc :
|
|
378
|
+
if cyto_image.ndim == 3 :
|
|
379
|
+
cyto_image = np.max(cyto_image,axis=0)
|
|
380
|
+
|
|
381
|
+
plot.plot_segmentation_boundary(
|
|
382
|
+
image=cyto_image,
|
|
383
|
+
cell_label= cyto_label,
|
|
384
|
+
nuc_label= nuc_label,
|
|
385
|
+
boundary_size= 3,
|
|
386
|
+
contrast=True,
|
|
387
|
+
path_output=path + "_cytoplasm_segmentation.png",
|
|
388
|
+
show=False,
|
|
389
|
+
)
|
|
@@ -26,6 +26,7 @@ import bigfish.classification as classification
|
|
|
26
26
|
from bigfish.detection.spot_detection import get_object_radius_pixel
|
|
27
27
|
from types import GeneratorType
|
|
28
28
|
from skimage.measure import regionprops
|
|
29
|
+
from scipy.ndimage import binary_dilation
|
|
29
30
|
|
|
30
31
|
|
|
31
32
|
def ask_input_parameters(ask_for_segmentation=True) :
|
|
@@ -282,7 +283,15 @@ def initiate_detection(user_parameters, segmentation_done, map, shape) :
|
|
|
282
283
|
if type(user_parameters) == type(None) : return user_parameters
|
|
283
284
|
try :
|
|
284
285
|
user_parameters = convert_parameters_types(user_parameters)
|
|
285
|
-
user_parameters = check_integrity(
|
|
286
|
+
user_parameters = check_integrity(
|
|
287
|
+
user_parameters,
|
|
288
|
+
do_dense_region_deconvolution,
|
|
289
|
+
do_clustering,
|
|
290
|
+
is_multichannel,
|
|
291
|
+
segmentation_done,
|
|
292
|
+
map,
|
|
293
|
+
shape
|
|
294
|
+
)
|
|
286
295
|
except ParameterInputError as error:
|
|
287
296
|
sg.popup(error)
|
|
288
297
|
else :
|
|
@@ -592,7 +601,8 @@ def launch_detection(
|
|
|
592
601
|
other_image,
|
|
593
602
|
user_parameters,
|
|
594
603
|
cell_label= None,
|
|
595
|
-
nucleus_label = None
|
|
604
|
+
nucleus_label = None,
|
|
605
|
+
hide_loading=False,
|
|
596
606
|
) :
|
|
597
607
|
"""
|
|
598
608
|
Main call for features computation :
|
|
@@ -618,18 +628,18 @@ def launch_detection(
|
|
|
618
628
|
do_dense_region_deconvolution = user_parameters['Dense regions deconvolution']
|
|
619
629
|
do_clustering = user_parameters['Cluster computation']
|
|
620
630
|
|
|
621
|
-
spots, threshold = _launch_detection(image, user_parameters)
|
|
631
|
+
spots, threshold = _launch_detection(image, user_parameters, hide_loading = hide_loading)
|
|
622
632
|
|
|
623
633
|
if do_dense_region_deconvolution :
|
|
624
|
-
spots = launch_dense_region_deconvolution(image, spots, user_parameters)
|
|
634
|
+
spots = launch_dense_region_deconvolution(image, spots, user_parameters, hide_loading = hide_loading)
|
|
625
635
|
|
|
626
636
|
if do_clustering :
|
|
627
|
-
clusters = launch_clustering(spots, user_parameters) #012 are coordinates #3 is number of spots per cluster, #4 is cluster index
|
|
637
|
+
clusters = launch_clustering(spots, user_parameters, hide_loading = hide_loading) #012 are coordinates #3 is number of spots per cluster, #4 is cluster index
|
|
628
638
|
clusters = _update_clusters(clusters, spots, voxel_size=user_parameters['voxel_size'], cluster_size=user_parameters['cluster size'], min_spot_number= user_parameters['min number of spots'], shape=image.shape)
|
|
629
639
|
|
|
630
640
|
else : clusters = None
|
|
631
641
|
|
|
632
|
-
spots, post_detection_dict = launch_post_detection(image, spots, user_parameters)
|
|
642
|
+
spots, post_detection_dict = launch_post_detection(image, spots, user_parameters, hide_loading = hide_loading)
|
|
633
643
|
user_parameters['threshold'] = threshold
|
|
634
644
|
|
|
635
645
|
if user_parameters['Napari correction'] :
|
|
@@ -825,4 +835,55 @@ def _local_maxima_mask(
|
|
|
825
835
|
ndim=ndim)
|
|
826
836
|
mask_local_max = detection.local_maximum_detection(image_filtered, minimum_distance)
|
|
827
837
|
|
|
828
|
-
return mask_local_max.astype(bool)
|
|
838
|
+
return mask_local_max.astype(bool)
|
|
839
|
+
|
|
840
|
+
def output_spot_tiffvisual(channel,spots_list, path_output, dot_size = 3, rescale = True):
|
|
841
|
+
|
|
842
|
+
"""
|
|
843
|
+
Outputs a tiff image with one channel being {channel} and the other a mask containing dots where sports are located.
|
|
844
|
+
|
|
845
|
+
Parameters
|
|
846
|
+
----------
|
|
847
|
+
channel : np.ndarray
|
|
848
|
+
3D monochannel image
|
|
849
|
+
spots : list[np.ndarray] or np.ndarray
|
|
850
|
+
Spots arrays are ndarray where each element corresponds is a tuple(z,y,x) corresponding to 3D coordinate of a spot
|
|
851
|
+
To plot different spots on different channels a list of spots ndarray can be passed.
|
|
852
|
+
path_output : str
|
|
853
|
+
dot_size : int
|
|
854
|
+
in pixels
|
|
855
|
+
"""
|
|
856
|
+
|
|
857
|
+
stack.check_parameter(channel = (np.ndarray), spots_list= (list, np.ndarray), path_output = (str), dot_size = (int))
|
|
858
|
+
stack.check_array(channel, ndim= [2,3])
|
|
859
|
+
if isinstance(spots_list, np.ndarray) : spots_list = [spots_list]
|
|
860
|
+
|
|
861
|
+
if channel.ndim == 3 :
|
|
862
|
+
channel = stack.maximum_projection(channel)
|
|
863
|
+
|
|
864
|
+
im = np.zeros([1 + len(spots_list)] + list(channel.shape))
|
|
865
|
+
im[0,:,:] = channel
|
|
866
|
+
|
|
867
|
+
for level in range(len(spots_list)) :
|
|
868
|
+
if len(spots_list[level]) == 0 : continue
|
|
869
|
+
else :
|
|
870
|
+
spots_mask = np.zeros_like(channel)
|
|
871
|
+
|
|
872
|
+
#Unpacking spots
|
|
873
|
+
if len(spots_list[level][0]) == 2 :
|
|
874
|
+
Y,X = zip(*spots_list[level])
|
|
875
|
+
elif len(spots_list[level][0]) == 3 :
|
|
876
|
+
Z,Y,X = zip(*spots_list[level])
|
|
877
|
+
del Z
|
|
878
|
+
else :
|
|
879
|
+
Z,Y,X,*_ = zip(*spots_list[level])
|
|
880
|
+
del Z,_
|
|
881
|
+
|
|
882
|
+
#Reconstructing signal
|
|
883
|
+
spots_mask[Y,X] = 1
|
|
884
|
+
if dot_size > 1 : spots_mask = binary_dilation(spots_mask, iterations= dot_size-1)
|
|
885
|
+
spots_mask = stack.rescale(np.array(spots_mask, dtype = channel.dtype))
|
|
886
|
+
im[level + 1] = spots_mask
|
|
887
|
+
|
|
888
|
+
if rescale : channel = stack.rescale(channel, channel_to_stretch= 0)
|
|
889
|
+
stack.save_image(im, path_output, extension= 'tif')
|
small_fish_gui/pipeline/main.py
CHANGED
|
@@ -4,6 +4,7 @@ import PySimpleGUI as sg
|
|
|
4
4
|
from ..gui import hub_prompt
|
|
5
5
|
from .actions import add_detection, save_results, compute_colocalisation, delete_acquisitions
|
|
6
6
|
from ._preprocess import clean_unused_parameters_cache
|
|
7
|
+
from ..batch import batch_promp
|
|
7
8
|
|
|
8
9
|
#'Global' parameters
|
|
9
10
|
user_parameters = dict() # Very important object containg all choice from user that will influence the behavior of the main loop.
|
|
@@ -24,7 +25,6 @@ while True : #Break this loop to close small_fish
|
|
|
24
25
|
|
|
25
26
|
if event == 'Add detection' :
|
|
26
27
|
user_parameters = clean_unused_parameters_cache(user_parameters)
|
|
27
|
-
|
|
28
28
|
|
|
29
29
|
new_result_df, new_cell_result_df, acquisition_id, user_parameters, segmentation_done, cytoplasm_label, nucleus_label = add_detection(
|
|
30
30
|
user_parameters=user_parameters,
|
|
@@ -74,8 +74,12 @@ while True : #Break this loop to close small_fish
|
|
|
74
74
|
result_df, cell_result_df, coloc_df = delete_acquisitions(selected_acquisitions, result_df, cell_result_df, coloc_df)
|
|
75
75
|
|
|
76
76
|
elif event == "Batch detection" :
|
|
77
|
-
|
|
78
|
-
|
|
77
|
+
result_df, cell_result_df, acquisition_id, user_parameters, segmentation_done, cytoplasm_label,nucleus_label = batch_promp(
|
|
78
|
+
result_df,
|
|
79
|
+
cell_result_df,
|
|
80
|
+
acquisition_id=acquisition_id,
|
|
81
|
+
preset=user_parameters,
|
|
82
|
+
)
|
|
79
83
|
|
|
80
84
|
else :
|
|
81
85
|
break
|
small_fish_gui/utils.py
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import inspect
|
|
2
|
+
import datetime as dt
|
|
2
3
|
|
|
3
4
|
def check_parameter(**kwargs):
|
|
4
5
|
"""Check dtype of the function's parameters.
|
|
@@ -52,4 +53,8 @@ def compute_anisotropy_coef(voxel_size) :
|
|
|
52
53
|
return (z_anisotropy, xy_anisotropy, 1)
|
|
53
54
|
|
|
54
55
|
else :
|
|
55
|
-
return (voxel_size[0] / voxel_size[1], 1)
|
|
56
|
+
return (voxel_size[0] / voxel_size[1], 1)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def get_datetime():
|
|
60
|
+
return dt.datetime.now().strftime("%Y%m%d %H-%M-%S")
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: small_fish_gui
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.4.0
|
|
4
4
|
Summary: Small Fish is a python application for the analysis of smFish images. It provides a ready to use graphical interface to combine famous python packages for cell analysis without any need for coding.
|
|
5
5
|
Project-URL: Homepage, https://github.com/2Echoes/small_fish
|
|
6
6
|
Project-URL: Issues, https://github.com/2Echoes/small_fish/issues
|
|
@@ -1,39 +1,49 @@
|
|
|
1
1
|
small_fish_gui/LICENSE,sha256=-iFy8VGBYs5VsHglKpk4D-hxqQ2jMJaqmfq_ulIzDks,1303
|
|
2
2
|
small_fish_gui/README.md,sha256=2c_homYDJXX6VsBiEs5obhBh3HpcTSMdyjLo-35WzE4,4062
|
|
3
3
|
small_fish_gui/Segmentation example.jpg,sha256=opfiSbjmfF6z8kBs08sg_FNR2Om0AcMPU5sSwSLHdoQ,215038
|
|
4
|
-
small_fish_gui/__init__.py,sha256=
|
|
4
|
+
small_fish_gui/__init__.py,sha256=bAy5AbCcDOo7LXgavAnPpRWrr5bCcI8KVqQZX1nb1L0,1941
|
|
5
5
|
small_fish_gui/__main__.py,sha256=EzSCoJ7jpSdK-QbzUwQLGZeQWjybNeq8VnCBucA8MZw,1372
|
|
6
6
|
small_fish_gui/napari_detection_example.png,sha256=l5EZlrbXemLiGqb5inSVsD6Kko1Opz528-go-fBfrw8,977350
|
|
7
7
|
small_fish_gui/requirements.txt,sha256=9OMfUAnLdHevq6w_fVoDmVmkSMJeFofkOK_86_fu9C0,321
|
|
8
|
-
small_fish_gui/utils.py,sha256=
|
|
8
|
+
small_fish_gui/utils.py,sha256=LM6QW2ono_LIRv7JXIIq7ZxxbDXqBtZ5uR9gjKJfwM8,1903
|
|
9
9
|
small_fish_gui/.github/workflows/python-publish.yml,sha256=5Ltnuhw9TevhzndlBmdUgYMnS73xEAxSyd1u8DHdn5s,1084
|
|
10
|
+
small_fish_gui/batch/__init__.py,sha256=ku2_Yate-UG89Q0BmE2B9kFV4kOz-u9Lf2lj6VsdFXs,127
|
|
11
|
+
small_fish_gui/batch/input.py,sha256=mqnP8LBhyNbtlcqjVlUiVeuHw4YxOX3GgzJbq03isKE,1477
|
|
12
|
+
small_fish_gui/batch/integrity.py,sha256=yzVWBwm4Mxftd1sDziQwKc7d3ALdgWOhkqQrU5-p430,4849
|
|
13
|
+
small_fish_gui/batch/output.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
14
|
+
small_fish_gui/batch/pipeline.py,sha256=uZCwkoiSnTHWAf7C4XPNXg4ldIjbpRiULpzZWq7R1i0,8798
|
|
15
|
+
small_fish_gui/batch/prompt.py,sha256=K3Vb1ebcNe6JieXPDL1btrZR-4ASjs_HIklXx5B9lYU,18608
|
|
16
|
+
small_fish_gui/batch/test.py,sha256=q04a1YstnDsxy2Bi5563BfcOU-O3VPE9c5WSJjvFjMg,211
|
|
17
|
+
small_fish_gui/batch/update.py,sha256=hR4kZ7tP2tvn1tmDa4oJb2e7-SUqN1Lf8JR6OCIOMS8,5037
|
|
18
|
+
small_fish_gui/batch/utils.py,sha256=HgfPwfhqWXOGtCny_nTdGs8csWB1BQp7-hYgrNVLB70,1774
|
|
19
|
+
small_fish_gui/batch/values.py,sha256=C1hRlCpTIDsg89DMKIIW5NUxeK876ODRUuJ2D-mJv6o,1519
|
|
20
|
+
small_fish_gui/batch/values.txt,sha256=PVxzIaaF6DGFRx_CMaStXZI6OrbjNub1-jR3pklXVjc,991
|
|
10
21
|
small_fish_gui/gui/__init__.py,sha256=xQ_BfYcnQmKZtx_0leO4OmbkLNLv49ZPqEu_UXMgmDc,867
|
|
11
|
-
small_fish_gui/gui/animation.py,sha256=
|
|
12
|
-
small_fish_gui/gui/batch.py,sha256=aCd3UvzH6ljaWMdjQzOHA_D6QttWYIuv9iDK8iISSdg,10831
|
|
22
|
+
small_fish_gui/gui/animation.py,sha256=rnNP5FPp06Hu-R33c4AVTCknALBbxT2YlsKFCXHAp9k,981
|
|
13
23
|
small_fish_gui/gui/general_help_screenshot.png,sha256=X4E6Td5f04K-pBUPDaBJRAE3D5b8fuEdiAUKhkIDr-0,54210
|
|
14
24
|
small_fish_gui/gui/help_module.py,sha256=PmgkkDs7bZ2-po83A_PK9uldQcHjehYmqre21nYb6DQ,9600
|
|
15
|
-
small_fish_gui/gui/layout.py,sha256=
|
|
25
|
+
small_fish_gui/gui/layout.py,sha256=k_ATlpkzqzo7UotXwq6WkuqnevKT6UgFjfDH0UzHAOM,13563
|
|
16
26
|
small_fish_gui/gui/mapping_help_screenshot.png,sha256=HcuRh5TYciUogUasza5vZ_QSshaiHsskQK23mh9vQS8,34735
|
|
17
|
-
small_fish_gui/gui/prompts.py,sha256=
|
|
27
|
+
small_fish_gui/gui/prompts.py,sha256=WFxXLx-M3TM685iiQcNNNVX4Tpttn5JXPm6yM9eBRV4,13358
|
|
18
28
|
small_fish_gui/gui/segmentation_help_screenshot.png,sha256=rbSgIydT0gZtfMh1qk4mdMbEIyCaakvHmxa2eOrLwO0,118944
|
|
19
|
-
small_fish_gui/gui/test.py,sha256=6P8tnND4wHOE1bF7BGx26wWgE-WjaSCH9Mej7ZzauSg,101
|
|
20
29
|
small_fish_gui/interface/__init__.py,sha256=PB86R4Y9kV80aGZ-vP0ZW2KeaCwGbBbCtFCmbN2yl28,275
|
|
21
30
|
small_fish_gui/interface/image.py,sha256=X1L7S5svxUwdoDcI3QM1PbN-c4Nz5w30hixq3IgqSn8,1130
|
|
22
|
-
small_fish_gui/interface/output.py,sha256=
|
|
31
|
+
small_fish_gui/interface/output.py,sha256=5jC37tobgXgsiVJYx3RWaES09I-YFmbXKk65lHflTHc,1867
|
|
23
32
|
small_fish_gui/interface/parameters.py,sha256=lUugD-4W2TZyJF3TH1q70TlktEYhhPtcPCrvxm5Dk50,36
|
|
24
33
|
small_fish_gui/interface/testing.py,sha256=MY5-GcPOUHagcrwR8A7QOjAmjZIDVC8Wz3NibLe3KQw,321
|
|
34
|
+
small_fish_gui/pipeline/__init__.py,sha256=_Ey20GG8fJtqZvixbXNNYX6wTWMnCUArmARPqsNEhuQ,743
|
|
25
35
|
small_fish_gui/pipeline/_colocalisation.py,sha256=peBw2Qz5m6wSejDkDz240UgvWl8ohNelrnmEgznbEsw,9635
|
|
26
36
|
small_fish_gui/pipeline/_custom_errors.py,sha256=tQ-AUhgzIFpK30AZiQQrtHCHyGVRDdAoIjzL0Fk-1pA,43
|
|
27
37
|
small_fish_gui/pipeline/_napari_wrapper.py,sha256=_FkkY7IBKn1QgNvyea-x6XPjw_AwsLEVzdRKzg65oCE,9290
|
|
28
|
-
small_fish_gui/pipeline/_preprocess.py,sha256=
|
|
29
|
-
small_fish_gui/pipeline/_segmentation.py,sha256=
|
|
38
|
+
small_fish_gui/pipeline/_preprocess.py,sha256=9Ns0el109qeRD1I7HmKpuljyKZfYLwPapvrKYl9ebdc,12943
|
|
39
|
+
small_fish_gui/pipeline/_segmentation.py,sha256=jcNf_GxNov_O16Xt6XyDIfYC7JsdiAxGeqLMJCwEy5I,13925
|
|
30
40
|
small_fish_gui/pipeline/_signaltonoise.py,sha256=7A9t7xu7zghI6cr201Ldm-LjJ5NOuP56VSeJ8KIzcUo,8497
|
|
31
41
|
small_fish_gui/pipeline/actions.py,sha256=EIGIOlwJ_DADX1NcLWwrTP_AidDX-4f4ggZV0gkIb58,7988
|
|
32
|
-
small_fish_gui/pipeline/detection.py,sha256=
|
|
33
|
-
small_fish_gui/pipeline/main.py,sha256=
|
|
42
|
+
small_fish_gui/pipeline/detection.py,sha256=La8hCO2WvZgHjvgUIjwQbqKYhDHI5ZtLhYrxFc62qbs,34429
|
|
43
|
+
small_fish_gui/pipeline/main.py,sha256=QamUbM4pfLLWGAC8AkJ-vTcUNHpWeu9bBB1g5pBBoNY,3433
|
|
34
44
|
small_fish_gui/pipeline/spots.py,sha256=yHvqf1eD25UltELpzcouYXhLkxiXI_mOL1ANSzXK5pw,1907
|
|
35
45
|
small_fish_gui/pipeline/test.py,sha256=w4ZMGDmUDXxVgWTlZ2TKw19W8q5gcE9gLMKe0SWnRrw,2827
|
|
36
|
-
small_fish_gui-1.
|
|
37
|
-
small_fish_gui-1.
|
|
38
|
-
small_fish_gui-1.
|
|
39
|
-
small_fish_gui-1.
|
|
46
|
+
small_fish_gui-1.4.0.dist-info/METADATA,sha256=ga-XNAKMcj2t0XMTxUoj3aIMuIRE9DuiBPKQbmuadMk,2567
|
|
47
|
+
small_fish_gui-1.4.0.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
|
|
48
|
+
small_fish_gui-1.4.0.dist-info/licenses/LICENSE,sha256=-iFy8VGBYs5VsHglKpk4D-hxqQ2jMJaqmfq_ulIzDks,1303
|
|
49
|
+
small_fish_gui-1.4.0.dist-info/RECORD,,
|