small-fish-gui 2.0.3__py3-none-any.whl → 2.1.1__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/prompt.py +1 -1
- small_fish_gui/batch/values.txt +65 -0
- small_fish_gui/gui/_napari_widgets.py +18 -6
- small_fish_gui/gui/layout.py +10 -10
- small_fish_gui/gui/napari_visualiser.py +39 -16
- small_fish_gui/interface/settings.json +3 -3
- small_fish_gui/pipeline/detection.py +1 -1
- small_fish_gui/pipeline/segmentation.py +1 -1
- small_fish_gui/pipeline/testing.ipynb +3636 -0
- small_fish_gui/small_fish_gui.code-workspace +7 -0
- {small_fish_gui-2.0.3.dist-info → small_fish_gui-2.1.1.dist-info}/METADATA +18 -9
- {small_fish_gui-2.0.3.dist-info → small_fish_gui-2.1.1.dist-info}/RECORD +15 -13
- small_fish_gui/interface/testing.ipynb +0 -4354
- {small_fish_gui-2.0.3.dist-info → small_fish_gui-2.1.1.dist-info}/WHEEL +0 -0
- {small_fish_gui-2.0.3.dist-info → small_fish_gui-2.1.1.dist-info}/licenses/LICENSE +0 -0
small_fish_gui/__init__.py
CHANGED
|
@@ -37,7 +37,7 @@ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
37
37
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
38
38
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
39
39
|
"""
|
|
40
|
-
__version__ = "2.
|
|
40
|
+
__version__ = "2.1.1"
|
|
41
41
|
__wiki__ = "https://github.com/2Echoes/small_fish_gui/wiki"
|
|
42
42
|
|
|
43
43
|
import os, platform
|
small_fish_gui/batch/prompt.py
CHANGED
|
@@ -104,7 +104,7 @@ def batch_promp(
|
|
|
104
104
|
preset["reordered_shape"] = None
|
|
105
105
|
preset.setdefault("filename", "")
|
|
106
106
|
#Segmentation tab
|
|
107
|
-
preset.setdefault("other_nucleus_image",
|
|
107
|
+
preset.setdefault("other_nucleus_image", "")
|
|
108
108
|
preset.setdefault("cytoplasm_channel", default.detection_channel)
|
|
109
109
|
preset.setdefault("cytoplasm_segmentation_3D", default.do_3D_segmentation)
|
|
110
110
|
preset.setdefault("nucleus_segmentation_3D", default.do_3D_segmentation)
|
|
@@ -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
|
+
do_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
|
+
show_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
|
|
@@ -256,6 +256,7 @@ class ClusterMerger(ClusterWidget) :
|
|
|
256
256
|
|
|
257
257
|
#Dropping selected clusters
|
|
258
258
|
self.cluster_layer.data = np.delete(self.cluster_layer.data, selected_clusters, axis=0)
|
|
259
|
+
self.cluster_layer.features = self.cluster_layer.features.drop(selected_clusters, axis=0)
|
|
259
260
|
|
|
260
261
|
#Updating spots
|
|
261
262
|
belonging_spots = self.single_layer.features.loc[self.single_layer.features['cluster_id'].isin(selected_cluster_ids)].index
|
|
@@ -813,6 +814,7 @@ class DenseRegionDeconvolver(NapariWidget) :
|
|
|
813
814
|
self.spot_radius = spot_radius
|
|
814
815
|
self.kernel_size = kernel_size
|
|
815
816
|
self.voxel_size = voxel_size
|
|
817
|
+
self.dim = len(voxel_size)
|
|
816
818
|
self.update_dense_regions()
|
|
817
819
|
super().__init__()
|
|
818
820
|
|
|
@@ -830,13 +832,23 @@ class DenseRegionDeconvolver(NapariWidget) :
|
|
|
830
832
|
for label, region in enumerate(dense_regions) :
|
|
831
833
|
reg_im = region.image
|
|
832
834
|
coordinates = np.argwhere(reg_im)
|
|
833
|
-
z,y,x = coordinates.T
|
|
834
|
-
min_z,min_y,min_x,*_ = region.bbox
|
|
835
|
-
z += min_z
|
|
836
|
-
y += min_y
|
|
837
|
-
x += min_x
|
|
838
835
|
|
|
839
|
-
|
|
836
|
+
if self.dim == 2 :
|
|
837
|
+
y,x = coordinates.T
|
|
838
|
+
min_y,min_x,*_ = region.bbox
|
|
839
|
+
y += min_y
|
|
840
|
+
x += min_x
|
|
841
|
+
|
|
842
|
+
mask[y,x] = label + 1
|
|
843
|
+
|
|
844
|
+
else :
|
|
845
|
+
z,y,x = coordinates.T
|
|
846
|
+
min_z,min_y,min_x,*_ = region.bbox
|
|
847
|
+
z += min_z
|
|
848
|
+
y += min_y
|
|
849
|
+
x += min_x
|
|
850
|
+
|
|
851
|
+
mask[z,y,x] = label + 1
|
|
840
852
|
|
|
841
853
|
self.dense_regions = mask
|
|
842
854
|
|
small_fish_gui/gui/layout.py
CHANGED
|
@@ -308,12 +308,14 @@ def _segmentate_object_layout(
|
|
|
308
308
|
options_3D = list()
|
|
309
309
|
layout = []
|
|
310
310
|
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
311
|
+
radio_2D_seg = sg.Radio("2D segmentation", group_id=object_key+"_seg_dim", default=not segmentation_3D, visible = True, enable_events=True, key=key_2D)
|
|
312
|
+
radio_max_proj = sg.Radio("max proj", group_id=object_key+"_2D_proj", default=False, disabled= segmentation_3D, key= object_key+"_max_proj")
|
|
313
|
+
radio_mean_proj = sg.Radio("mean proj", group_id=object_key+"_2D_proj", default=True, disabled= segmentation_3D, key = object_key + "_mean_proj")
|
|
314
|
+
radio_slice_proj = sg.Radio("select slice", group_id=object_key+"_2D_proj", default=False, disabled= segmentation_3D, key=object_key + "_select_slice")
|
|
315
|
+
radio_3D_seg = sg.Radio("3D segmentation", group_id=object_key+"_seg_dim", default=segmentation_3D, visible = True, enable_events=True, key= key_3D)
|
|
316
|
+
anisotropy = sg.Input(default_text = 1, key = object_key + "_anisotropy",size=5, disabled=not segmentation_3D)
|
|
317
|
+
|
|
318
|
+
if is_3D_stack :
|
|
317
319
|
slice_number = reordered_shape[0 + is_multichannel] if not reordered_shape is None else 999
|
|
318
320
|
int_slice_proj = sg.Spin(list(range(slice_number)), size= (5,1), disabled= segmentation_3D, key=object_key+"_selected_slice")
|
|
319
321
|
|
|
@@ -329,8 +331,6 @@ def _segmentate_object_layout(
|
|
|
329
331
|
[sg.Column([[radio_max_proj, radio_mean_proj, radio_slice_proj, int_slice_proj]], pad= (15,0,0,5))]
|
|
330
332
|
]
|
|
331
333
|
|
|
332
|
-
radio_3D_seg = sg.Radio("3D segmentation", group_id=object_key+"_seg_dim", default=segmentation_3D, visible = True, enable_events=True, key= key_3D)
|
|
333
|
-
anisotropy = sg.Input(default_text = 1, key = object_key + "_anisotropy",size=5, disabled=not segmentation_3D)
|
|
334
334
|
|
|
335
335
|
layout += [
|
|
336
336
|
[radio_3D_seg],
|
|
@@ -428,11 +428,12 @@ def _detection_layout(
|
|
|
428
428
|
|
|
429
429
|
if (do_segmentation and is_multichannel) or (is_multichannel and segmentation_done):
|
|
430
430
|
layout += [[sg.Text("nucleus channel signal "), sg.InputText(default_text=default_dict.setdefault('nucleus_channel',default.nucleus_channel), 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.")]]
|
|
431
|
+
layout += bool_layout(['Interactive threshold selector'],keys = ['show_interactive_threshold_selector'], preset=[default.interactive_threshold_selector])
|
|
431
432
|
|
|
432
433
|
#Deconvolution
|
|
433
434
|
if do_dense_region_deconvolution :
|
|
434
435
|
default_dense_regions_deconvolution = [default_dict.setdefault('alpha',default.alpha), default_dict.setdefault('beta',default.beta)]
|
|
435
|
-
layout += parameters_layout(['alpha', 'beta',], default_values= default_dense_regions_deconvolution, header= '
|
|
436
|
+
layout += parameters_layout(['alpha', 'beta',], default_values= default_dense_regions_deconvolution, header= 'Dense regions deconvolution')
|
|
436
437
|
layout += parameters_layout(['gamma'], unit= 'px', default_values= [default_dict.setdefault('gamma',default.gamma)])
|
|
437
438
|
layout += tuple_layout(opt= {"deconvolution_kernel" : True}, unit= {"deconvolution_kernel" : 'px'}, default_dict=default_dict, deconvolution_kernel = tuple_shape)
|
|
438
439
|
|
|
@@ -441,7 +442,6 @@ def _detection_layout(
|
|
|
441
442
|
layout += parameters_layout(['Cluster radius'],keys=['cluster_size'], unit="radius(nm)", default_values=[default_dict.setdefault('cluster_size',default.cluster_size)])
|
|
442
443
|
layout += parameters_layout(['Min nb spots per cluster'],keys=['min_number_of_spots'], default_values=[default_dict.setdefault('min_number_of_spots', default.min_spot)])
|
|
443
444
|
|
|
444
|
-
layout += bool_layout(['Interactive threshold selector'],keys = ['show_interactive_threshold_selector'], preset=[default.interactive_threshold_selector])
|
|
445
445
|
layout += path_layout(
|
|
446
446
|
keys=['spots_extraction_folder'],
|
|
447
447
|
look_for_dir=True,
|
|
@@ -39,22 +39,24 @@ def correct_spots(
|
|
|
39
39
|
dim = len(voxel_size)
|
|
40
40
|
|
|
41
41
|
if dim == 3 and type(cell_label) != type(None) :
|
|
42
|
-
cell_label
|
|
43
|
-
cell_label
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
42
|
+
if cell_label.ndim == 2 :
|
|
43
|
+
cell_label = np.repeat(
|
|
44
|
+
cell_label[np.newaxis],
|
|
45
|
+
repeats= len(image),
|
|
46
|
+
axis=0
|
|
47
|
+
)
|
|
47
48
|
if dim == 3 and type(nucleus_label) != type(None) :
|
|
48
|
-
nucleus_label
|
|
49
|
-
nucleus_label
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
49
|
+
if nucleus_label == 2 :
|
|
50
|
+
nucleus_label = np.repeat(
|
|
51
|
+
nucleus_label[np.newaxis],
|
|
52
|
+
repeats= len(image),
|
|
53
|
+
axis=0
|
|
54
|
+
)
|
|
53
55
|
|
|
54
56
|
scale = compute_anisotropy_coef(voxel_size)
|
|
55
57
|
Viewer = napari.Viewer(ndisplay=2, title= 'Spot correction', axis_labels=['z','y','x'], show= False)
|
|
56
|
-
Viewer.add_image(image, scale=scale, name= "rna signal", blending= 'additive', colormap='
|
|
57
|
-
other_colors = ['
|
|
58
|
+
Viewer.add_image(image, scale=scale, name= "rna signal", blending= 'additive', colormap='green', contrast_limits=[image.min(), image.max()])
|
|
59
|
+
other_colors = ['red', 'blue', 'gray', 'cyan', 'bop orange', 'bop purple'] * ((len(other_images)-1 // 7) + 1)
|
|
58
60
|
for im, color in zip(other_images, other_colors) :
|
|
59
61
|
Viewer.add_image(im, scale=scale, blending='additive', visible=False, colormap=color, contrast_limits=[im.min(), im.max()])
|
|
60
62
|
|
|
@@ -93,11 +95,13 @@ def correct_spots(
|
|
|
93
95
|
"cluster_id" : clusters[:,dim+1],
|
|
94
96
|
"end" : [True] * len(clusters_coordinates)
|
|
95
97
|
},
|
|
96
|
-
feature_defaults= {"spot_number" :
|
|
98
|
+
feature_defaults= {"spot_number" : min_spot_number, "cluster_id" : -2, "end" : True} # napari features default will not work with np.nan passing -2 instead.
|
|
97
99
|
)
|
|
98
100
|
|
|
99
|
-
if type(cell_label) != type(None) and not np.array_equal(nucleus_label, cell_label) :
|
|
100
|
-
|
|
101
|
+
if type(cell_label) != type(None) and not np.array_equal(nucleus_label, cell_label) :
|
|
102
|
+
cell_label_layer = Viewer.add_labels(cell_label, scale=scale, opacity= 0.2, blending= 'additive')
|
|
103
|
+
if type(nucleus_label) != type(None) :
|
|
104
|
+
nucleus_label_layer = Viewer.add_labels(nucleus_label, scale=scale, opacity= 0.2, blending= 'additive')
|
|
101
105
|
|
|
102
106
|
#Adding widget
|
|
103
107
|
if type(clusters) != type(None) :
|
|
@@ -153,7 +157,26 @@ def correct_spots(
|
|
|
153
157
|
new_cluster_radius = None
|
|
154
158
|
new_min_spot_number = None
|
|
155
159
|
|
|
156
|
-
|
|
160
|
+
#Preparing updated segmentation masks
|
|
161
|
+
if type(cell_label) != type(None) and not np.array_equal(nucleus_label, cell_label) :
|
|
162
|
+
new_cell_label = cell_label_layer.data
|
|
163
|
+
else :
|
|
164
|
+
new_cell_label = cell_label
|
|
165
|
+
if type(nucleus_label) != type(None) :
|
|
166
|
+
new_nucleus_label = nucleus_label_layer.data
|
|
167
|
+
else :
|
|
168
|
+
new_nucleus_label = nucleus_label
|
|
169
|
+
|
|
170
|
+
if dim == 3 and type(cell_label) != type(None) :
|
|
171
|
+
if cell_label.ndim == 2 :
|
|
172
|
+
new_cell_label = new_cell_label.max(axis=0)
|
|
173
|
+
if dim == 3 and type(nucleus_label) != type(None) :
|
|
174
|
+
if nucleus_label == 2 :
|
|
175
|
+
new_nucleus_label = new_nucleus_label.max(axis=0)
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
return new_spots, new_clusters, new_cluster_radius, new_min_spot_number, new_nucleus_label, new_cell_label
|
|
157
180
|
|
|
158
181
|
|
|
159
182
|
# Segmentation
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"working_directory": "/
|
|
2
|
+
"working_directory": "/home/floric/Documents/fish_images",
|
|
3
3
|
"do_background_removal": false,
|
|
4
4
|
"background_channel": 0,
|
|
5
5
|
"multichannel_stack": true,
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"do_dense_regions_deconvolution": false,
|
|
33
33
|
"do_cluster": false,
|
|
34
34
|
"show_napari_corrector": true,
|
|
35
|
-
"interactive_threshold_selector":
|
|
35
|
+
"interactive_threshold_selector": true,
|
|
36
36
|
"alpha": 0.5,
|
|
37
37
|
"beta": 1.0,
|
|
38
38
|
"gamma": 3.0,
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"coloc_range": 400,
|
|
42
42
|
"do_csv": false,
|
|
43
43
|
"do_excel": false,
|
|
44
|
-
"spot_extraction_folder": "/home/floric",
|
|
44
|
+
"spot_extraction_folder": "/home/floric/my_projects/small_fish_gui",
|
|
45
45
|
"voxel_size": [
|
|
46
46
|
1,
|
|
47
47
|
2,
|
|
@@ -660,7 +660,7 @@ def launch_detection(
|
|
|
660
660
|
|
|
661
661
|
if user_parameters['show_napari_corrector'] :
|
|
662
662
|
|
|
663
|
-
spots, clusters, new_cluster_radius, new_min_spot_number = correct_spots(
|
|
663
|
+
spots, clusters, new_cluster_radius, new_min_spot_number, nucleus_label, cell_label = correct_spots(
|
|
664
664
|
image,
|
|
665
665
|
spots,
|
|
666
666
|
user_parameters['voxel_size'],
|
|
@@ -68,7 +68,7 @@ def launch_segmentation(user_parameters: pipeline_parameters, nucleus_label, cyt
|
|
|
68
68
|
#Ask user for parameters
|
|
69
69
|
#if incorrect parameters --> set relaunch to True
|
|
70
70
|
while True :
|
|
71
|
-
segmentation_parameters.setdefault("other_nucleus_image",
|
|
71
|
+
segmentation_parameters.setdefault("other_nucleus_image", "")
|
|
72
72
|
segmentation_parameters.setdefault("cytoplasm_channel", segmentation_parameters["detection_channel"])
|
|
73
73
|
segmentation_parameters.setdefault("cytoplasm_segmentation_3D", segmentation_parameters["do_3D_segmentation"])
|
|
74
74
|
segmentation_parameters.setdefault("nucleus_segmentation_3D", segmentation_parameters["do_3D_segmentation"])
|