small-fish-gui 1.9.4__py3-none-any.whl → 1.10.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/README.md +2 -1
- small_fish_gui/__init__.py +5 -1
- small_fish_gui/__main__.py +24 -34
- small_fish_gui/batch/prompt.py +1 -1
- small_fish_gui/batch/update.py +2 -2
- small_fish_gui/batch/values.txt +1 -1
- small_fish_gui/gui/__init__.py +0 -2
- small_fish_gui/gui/_napari_widgets.py +433 -25
- small_fish_gui/gui/layout.py +10 -7
- small_fish_gui/gui/napari_visualiser.py +72 -167
- small_fish_gui/gui/prompts.py +16 -41
- small_fish_gui/gui/testing.ipynb +138 -28
- small_fish_gui/gui/theme.py +5 -0
- small_fish_gui/hints.py +9 -7
- small_fish_gui/interface/__init__.py +1 -0
- small_fish_gui/interface/image.py +22 -1
- small_fish_gui/interface/testing.py +60 -9
- small_fish_gui/pipeline/_preprocess.py +18 -12
- small_fish_gui/pipeline/actions.py +5 -0
- small_fish_gui/pipeline/detection.py +34 -10
- small_fish_gui/pipeline/main.py +23 -3
- small_fish_gui/pipeline/segmentation.py +2 -2
- small_fish_gui/requirements.txt +12 -11
- {small_fish_gui-1.9.4.dist-info → small_fish_gui-1.10.1.dist-info}/METADATA +12 -11
- small_fish_gui-1.10.1.dist-info/RECORD +49 -0
- small_fish_gui/Segmentation example.jpg +0 -0
- small_fish_gui/gui/help_module.py +0 -256
- small_fish_gui/napari_detection_example.png +0 -0
- small_fish_gui-1.9.4.dist-info/RECORD +0 -51
- {small_fish_gui-1.9.4.dist-info → small_fish_gui-1.10.1.dist-info}/WHEEL +0 -0
- {small_fish_gui-1.9.4.dist-info → small_fish_gui-1.10.1.dist-info}/licenses/LICENSE +0 -0
small_fish_gui/gui/layout.py
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import FreeSimpleGUI as sg
|
|
2
2
|
import os
|
|
3
3
|
from ..utils import check_parameter
|
|
4
|
+
from ..hints import pipeline_parameters
|
|
5
|
+
from typing import Optional, Union
|
|
4
6
|
import cellpose.models as models
|
|
5
7
|
from cellpose.core import use_gpu
|
|
6
8
|
|
|
@@ -18,7 +20,7 @@ def pad_right(string, length, pad_char) :
|
|
|
18
20
|
else : return string + pad_char* (length - len(string))
|
|
19
21
|
|
|
20
22
|
|
|
21
|
-
def parameters_layout(parameters:'list[str]' = [], unit=None, header= None, default_values=None, size=5, opt=None) :
|
|
23
|
+
def parameters_layout(parameters:'list[str]' = [], unit=None, header= None, default_values=None, size=5, opt:list=None) :
|
|
22
24
|
|
|
23
25
|
if len(parameters) == 0 : return []
|
|
24
26
|
check_parameter(parameters= list, header = (str, type(None)))
|
|
@@ -101,7 +103,7 @@ def path_layout(keys= [],look_for_dir = False, header=None, preset=os.getcwd())
|
|
|
101
103
|
layout = [add_header(header)] + layout
|
|
102
104
|
return layout
|
|
103
105
|
|
|
104
|
-
def bool_layout(parameters= [], header=None, preset=None, keys=None) :
|
|
106
|
+
def bool_layout(parameters= [], header=None, preset : Optional[Union['list[bool]',bool,None]]=None, keys=None) :
|
|
105
107
|
if len(parameters) == 0 : return []
|
|
106
108
|
check_parameter(parameters= list, header= (str, type(None)), preset=(type(None), list, tuple, bool))
|
|
107
109
|
for key in parameters : check_parameter(key = str)
|
|
@@ -226,7 +228,7 @@ def _input_parameters_layout(
|
|
|
226
228
|
do_Napari_correction
|
|
227
229
|
|
|
228
230
|
) :
|
|
229
|
-
layout_image_path = path_layout(['
|
|
231
|
+
layout_image_path = path_layout(['image_path'], header= "Image")
|
|
230
232
|
layout_image_path += bool_layout(['3D stack', 'Multichannel stack'], keys=['is_3D_stack', 'is_multichannel'], preset= [is_3D_stack_preset, multichannel_preset])
|
|
231
233
|
|
|
232
234
|
layout_image_path += bool_layout(
|
|
@@ -245,7 +247,7 @@ def _detection_layout(
|
|
|
245
247
|
do_clustering,
|
|
246
248
|
do_segmentation,
|
|
247
249
|
segmentation_done=False,
|
|
248
|
-
default_dict={},
|
|
250
|
+
default_dict : pipeline_parameters={},
|
|
249
251
|
) :
|
|
250
252
|
if is_3D_stack : dim = 3
|
|
251
253
|
else : dim = 2
|
|
@@ -283,8 +285,8 @@ def _detection_layout(
|
|
|
283
285
|
|
|
284
286
|
#Clustering
|
|
285
287
|
if do_clustering :
|
|
286
|
-
layout += parameters_layout(['
|
|
287
|
-
layout += parameters_layout(['
|
|
288
|
+
layout += parameters_layout(['cluster_size'], unit="radius(nm)", default_values=[default_dict.setdefault('cluster_size',400)])
|
|
289
|
+
layout += parameters_layout(['min_number_of_spots'], default_values=[default_dict.setdefault('min_number_of_spots', 5)])
|
|
288
290
|
|
|
289
291
|
|
|
290
292
|
|
|
@@ -295,9 +297,10 @@ def _detection_layout(
|
|
|
295
297
|
header= "Individual spot extraction",
|
|
296
298
|
preset= default_dict.setdefault('spots_extraction_folder', '')
|
|
297
299
|
)
|
|
300
|
+
default_filename = default_dict.setdefault("filename","") + "_spot_extraction"
|
|
298
301
|
layout += parameters_layout(
|
|
299
302
|
parameters=['spots_filename'],
|
|
300
|
-
default_values=[
|
|
303
|
+
default_values=[default_filename],
|
|
301
304
|
size= 13
|
|
302
305
|
)
|
|
303
306
|
layout += bool_layout(
|
|
@@ -2,145 +2,16 @@
|
|
|
2
2
|
Contains Napari wrappers to visualise and correct spots/clusters.
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
-
import napari.layers
|
|
6
|
-
import napari.types
|
|
7
5
|
import numpy as np
|
|
8
6
|
import napari
|
|
9
7
|
|
|
10
|
-
from sklearn.cluster import DBSCAN
|
|
11
|
-
from sklearn.neighbors import NearestNeighbors
|
|
12
|
-
|
|
13
8
|
from magicgui import widgets
|
|
14
9
|
|
|
15
10
|
from bigfish.stack import check_parameter
|
|
16
|
-
from
|
|
17
|
-
from ._napari_widgets import
|
|
11
|
+
from ._napari_widgets import CellLabelEraser, SegmentationReseter, ChangesPropagater, FreeLabelPicker
|
|
12
|
+
from ._napari_widgets import ClusterIDSetter, ClusterMerger, ClusterUpdater, ClusterCreator
|
|
13
|
+
from ._napari_widgets import initialize_all_cluster_wizards
|
|
18
14
|
from ..utils import compute_anisotropy_coef
|
|
19
|
-
from ..pipeline._colocalisation import spots_multicolocalisation
|
|
20
|
-
|
|
21
|
-
#Post detection
|
|
22
|
-
|
|
23
|
-
def _update_clusters(
|
|
24
|
-
old_spots : np.ndarray,
|
|
25
|
-
spot_cluster_id : np.ndarray,
|
|
26
|
-
new_spots : np.ndarray,
|
|
27
|
-
old_clusters : np.ndarray,
|
|
28
|
-
new_clusters : np.ndarray,
|
|
29
|
-
cluster_size : int,
|
|
30
|
-
min_number_spot : int,
|
|
31
|
-
voxel_size : tuple,
|
|
32
|
-
null_value = -2,
|
|
33
|
-
talks = False,
|
|
34
|
-
) :
|
|
35
|
-
"""
|
|
36
|
-
|
|
37
|
-
new_spots get weight of 1.
|
|
38
|
-
spots already in cluster get weight 1
|
|
39
|
-
spots not in cluster before but now in cluster radius get weigth = min_number_spot/*number of spot in new cluster radius (>=1)*
|
|
40
|
-
spots in radius of deleted cluster get weight = 0 unless they are in radius of a new cluster.
|
|
41
|
-
|
|
42
|
-
Parameters
|
|
43
|
-
----------
|
|
44
|
-
new_spots : array (spots_number, space_dim + 1,) containing coordinates of each spots after napari correction as well as the id of belonging cluster. -1 if free spot, np.NaN if unknown.
|
|
45
|
-
old_clusters : array (spots_number, space_dim + 2,) containing coordinates of each clusters centroid before napari correction, number of spots in cluster and the id of cluster.
|
|
46
|
-
new_clusters : array (spots_number, space_dim + 2,) containing coordinates of each clusters centroid after napari correction, number of spots in cluster and the id of cluster. number of spots is NaN if new cluster.
|
|
47
|
-
cluster_size : size of cluster in nanometer passed to DBSCAN.
|
|
48
|
-
|
|
49
|
-
Returns
|
|
50
|
-
-------
|
|
51
|
-
corrected_spots : array with updated cluster id.
|
|
52
|
-
corrected_clusters : array with updated number of spot.
|
|
53
|
-
|
|
54
|
-
"""
|
|
55
|
-
|
|
56
|
-
spots_weights = np.ones(len(new_spots), dtype=float)
|
|
57
|
-
|
|
58
|
-
if talks :
|
|
59
|
-
print("\nTALKS IN napari_visualiser._update_clusters")
|
|
60
|
-
print('new_spots_shape : ', new_spots.shape)
|
|
61
|
-
print('old_clusters : ', old_clusters.shape)
|
|
62
|
-
print('new_clusters : ', new_clusters.shape)
|
|
63
|
-
|
|
64
|
-
#Finding new and deleted clusters
|
|
65
|
-
deleted_cluster = old_clusters[~(np.isin(old_clusters[:,-1], new_clusters[:,-1]))]
|
|
66
|
-
added_cluster = new_clusters[new_clusters[:,-1] == null_value]
|
|
67
|
-
|
|
68
|
-
if talks :
|
|
69
|
-
print('deleted_cluster : ', deleted_cluster.shape)
|
|
70
|
-
print('added_cluster : ', added_cluster.shape)
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
#Removing cluster_id from points clustered in deleted clusters
|
|
75
|
-
spots_0_weights = old_spots[np.isin(spot_cluster_id, deleted_cluster[:,-1])]
|
|
76
|
-
spots_weights[np.isin(new_spots, spots_0_weights).all(axis=1)] = 0 #Setting weigth to 0 for spots in deleted clusters.
|
|
77
|
-
|
|
78
|
-
if talks :
|
|
79
|
-
print("deleted cluster ids : ", deleted_cluster[:,-1])
|
|
80
|
-
print("spots in deleted cluster : \n", spots_0_weights)
|
|
81
|
-
|
|
82
|
-
#Finding spots in range of new clusters
|
|
83
|
-
if len(added_cluster) > 0 :
|
|
84
|
-
points_neighbors = NearestNeighbors(radius= cluster_size)
|
|
85
|
-
points_neighbors.fit(new_spots*voxel_size)
|
|
86
|
-
neighbor_query = points_neighbors.radius_neighbors(added_cluster[:,:-2]*voxel_size, return_distance=False)
|
|
87
|
-
|
|
88
|
-
for cluster_neighbor in neighbor_query :
|
|
89
|
-
neighboring_spot_number = len(cluster_neighbor)
|
|
90
|
-
if neighboring_spot_number == 0 : continue # will not add a cluster if there is not even one spot nearby.
|
|
91
|
-
weight = min_number_spot / neighboring_spot_number # >1
|
|
92
|
-
if weight <= 1 : print("napari._update_clusters warning : weight <= 1; this should not happen some clusters might be missed during post napari computation.")
|
|
93
|
-
if any(spots_weights[cluster_neighbor] > weight) : # Not replacing a weight for a smaller weigth to ensure all new clusters will be added.
|
|
94
|
-
mask = spots_weights[cluster_neighbor] > weight
|
|
95
|
-
cluster_neighbor = np.delete(cluster_neighbor, mask)
|
|
96
|
-
if len(cluster_neighbor) > 0 : spots_weights[cluster_neighbor] = weight
|
|
97
|
-
|
|
98
|
-
#Initiating new DBSCAN model
|
|
99
|
-
dbscan_model = DBSCAN(cluster_size, min_samples=min_number_spot)
|
|
100
|
-
dbscan_model.fit(new_spots*voxel_size, sample_weight=spots_weights)
|
|
101
|
-
|
|
102
|
-
#Constructing corrected_arrays
|
|
103
|
-
spots_labels = dbscan_model.labels_.reshape(len(new_spots), 1)
|
|
104
|
-
corrected_spots = np.concatenate([new_spots, spots_labels], axis=1).astype(int)
|
|
105
|
-
corrected_cluster = _extract_information(corrected_spots)
|
|
106
|
-
|
|
107
|
-
if talks :
|
|
108
|
-
print("spots with weigth 0 :", len(spots_weights[spots_weights == 0]))
|
|
109
|
-
print("spots with weigth > 1 :", len(spots_weights[spots_weights > 1]))
|
|
110
|
-
print("spots with weigth == 1 :", len(spots_weights[spots_weights == 1]))
|
|
111
|
-
print("spots with weigth < 1 :", len(spots_weights[np.logical_and(spots_weights < 1,spots_weights > 0)]))
|
|
112
|
-
|
|
113
|
-
print('corrected_spots : ', corrected_spots.shape)
|
|
114
|
-
print('corrected_cluster : ', corrected_cluster.shape)
|
|
115
|
-
print("END TALK\n")
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
return corrected_spots, corrected_cluster
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
def __update_clusters(new_clusters: np.ndarray, spots: np.ndarray, voxel_size, cluster_size, shape) :
|
|
122
|
-
"""
|
|
123
|
-
Outdated. previous behaviour.
|
|
124
|
-
"""
|
|
125
|
-
if len(new_clusters) == 0 : return new_clusters
|
|
126
|
-
if len(spots) == 0 : return np.empty(shape=(0,2+len(voxel_size)), dtype=int)
|
|
127
|
-
|
|
128
|
-
if len(new_clusters[0]) in [2,3] :
|
|
129
|
-
new_clusters = np.concatenate([
|
|
130
|
-
new_clusters,
|
|
131
|
-
np.zeros(shape=(len(new_clusters),1), dtype=int),
|
|
132
|
-
np.arange(len(new_clusters), dtype=int).reshape(len(new_clusters),1)
|
|
133
|
-
],axis=1, dtype=int)
|
|
134
|
-
|
|
135
|
-
assert len(new_clusters[0]) == 4 or len(new_clusters[0]) == 5, "Wrong number of coordinates for clusters should not happen."
|
|
136
|
-
|
|
137
|
-
# Update spots clusters
|
|
138
|
-
new_clusters[:,-2] = spots_multicolocalisation(new_clusters[:,:-2], spots, radius_nm= cluster_size, voxel_size=voxel_size, image_shape=shape)
|
|
139
|
-
|
|
140
|
-
# delete too small clusters
|
|
141
|
-
new_clusters = np.delete(new_clusters, new_clusters[:,-2] == 0, 0)
|
|
142
|
-
|
|
143
|
-
return new_clusters
|
|
144
15
|
|
|
145
16
|
def correct_spots(
|
|
146
17
|
image,
|
|
@@ -184,14 +55,21 @@ def correct_spots(
|
|
|
184
55
|
for im, color in zip(other_images, other_colors) :
|
|
185
56
|
Viewer.add_image(im, scale=scale, blending='additive', visible=False, colormap=color, contrast_limits=[im.min(), im.max()])
|
|
186
57
|
|
|
187
|
-
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
single_layer = Viewer.add_points( # single molecule spots; this layer can be update by user.
|
|
188
61
|
spots,
|
|
189
62
|
size = 5,
|
|
190
63
|
scale=scale,
|
|
191
|
-
face_color= 'transparent',
|
|
64
|
+
face_color= 'transparent',
|
|
65
|
+
border_color ='red',
|
|
192
66
|
opacity= 1,
|
|
193
67
|
symbol= 'disc',
|
|
194
|
-
name= 'single spots'
|
|
68
|
+
name= 'single spots',
|
|
69
|
+
features={
|
|
70
|
+
"cluster_id" : spot_cluster_id if not spot_cluster_id is None else [None] * len(spots),
|
|
71
|
+
"end" : [True] * len(spots)
|
|
72
|
+
}
|
|
195
73
|
)
|
|
196
74
|
|
|
197
75
|
if type(clusters) != type(None) :
|
|
@@ -199,7 +77,7 @@ def correct_spots(
|
|
|
199
77
|
clusters_coordinates = clusters[:, :dim]
|
|
200
78
|
else :
|
|
201
79
|
clusters_coordinates = np.empty(shape=(0,dim), dtype=int)
|
|
202
|
-
Viewer.add_points( # cluster; this layer can be update by user.
|
|
80
|
+
cluster_layer = Viewer.add_points( # cluster; this layer can be update by user.
|
|
203
81
|
clusters_coordinates,
|
|
204
82
|
size = 10,
|
|
205
83
|
scale=scale,
|
|
@@ -207,45 +85,72 @@ def correct_spots(
|
|
|
207
85
|
opacity= 0.7,
|
|
208
86
|
symbol= 'diamond',
|
|
209
87
|
name= 'foci',
|
|
210
|
-
features= {
|
|
211
|
-
|
|
88
|
+
features= {
|
|
89
|
+
"spot_number" : clusters[:,dim],
|
|
90
|
+
"cluster_id" : clusters[:,dim+1],
|
|
91
|
+
"end" : [True] * len(clusters_coordinates)
|
|
92
|
+
},
|
|
93
|
+
feature_defaults= {"spot_number" : 0, "cluster_id" : -2, "end" : True} # napari features default will not work with np.NaN passing -2 instead.
|
|
212
94
|
)
|
|
213
95
|
|
|
214
96
|
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')
|
|
215
97
|
if type(nucleus_label) != type(None) : Viewer.add_labels(nucleus_label, scale=scale, opacity= 0.2, blending= 'additive')
|
|
216
|
-
|
|
98
|
+
|
|
99
|
+
#Adding widget
|
|
100
|
+
if type(clusters) != type(None) :
|
|
101
|
+
initialize_all_cluster_wizards(
|
|
102
|
+
single_layer=single_layer,
|
|
103
|
+
cluster_layer=cluster_layer
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
widget_clusterID = ClusterIDSetter(single_layer=single_layer, cluster_layer=cluster_layer)
|
|
107
|
+
widget_cluster_merge =ClusterMerger(single_layer=single_layer, cluster_layer=cluster_layer)
|
|
108
|
+
widget_cluster_updater = ClusterUpdater(
|
|
109
|
+
single_layer=single_layer,
|
|
110
|
+
cluster_layer=cluster_layer,
|
|
111
|
+
default_cluster_radius= cluster_size,
|
|
112
|
+
default_min_spot= min_spot_number,
|
|
113
|
+
voxel_size=voxel_size
|
|
114
|
+
)
|
|
115
|
+
widget_cluster_creator = ClusterCreator(
|
|
116
|
+
cluster_layer=cluster_layer,
|
|
117
|
+
single_layer=single_layer
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
buttons_container = widgets.Container(widgets=[widget_clusterID.widget, widget_cluster_creator.widget], labels=False, layout='horizontal')
|
|
122
|
+
updater_container = widgets.Container(widgets=[widget_cluster_updater.widget, widget_cluster_merge.widget], labels=False)
|
|
123
|
+
tools_container = widgets.Container(
|
|
124
|
+
widgets = [updater_container, buttons_container],
|
|
125
|
+
labels=False,
|
|
126
|
+
)
|
|
127
|
+
Viewer.window.add_dock_widget(tools_container, name='SmallFish', area='left')
|
|
128
|
+
|
|
217
129
|
Viewer.show(block=False)
|
|
218
130
|
napari.run()
|
|
219
131
|
|
|
220
|
-
new_spots = np.array(Viewer.layers['single spots'].data, dtype= int)
|
|
221
132
|
|
|
222
133
|
if type(clusters) != type(None) :
|
|
223
|
-
new_clusters = np.
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
new_spots = np.concatenate([new_spots, new_cluster_id], axis=1)
|
|
228
|
-
else :
|
|
229
|
-
new_cluster_id = Viewer.layers['foci'].features.to_numpy()
|
|
230
|
-
new_clusters = np.concatenate([new_clusters, new_cluster_id], axis=1)
|
|
134
|
+
new_clusters = np.concatenate([
|
|
135
|
+
cluster_layer.data,
|
|
136
|
+
cluster_layer.features.loc[:,["spot_number","cluster_id"]].to_numpy()
|
|
137
|
+
],axis=1)
|
|
231
138
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
cluster_size=cluster_size,
|
|
240
|
-
min_number_spot=min_spot_number,
|
|
241
|
-
voxel_size=voxel_size,
|
|
242
|
-
null_value= -2
|
|
243
|
-
)
|
|
244
|
-
|
|
139
|
+
new_spots = np.concatenate([
|
|
140
|
+
single_layer.data,
|
|
141
|
+
single_layer.features.loc[:,["cluster_id"]].to_numpy()
|
|
142
|
+
], axis=1).astype(int)
|
|
143
|
+
|
|
144
|
+
new_cluster_radius = widget_cluster_updater.cluster_radius
|
|
145
|
+
new_min_spot_number = widget_cluster_updater.min_spot
|
|
245
146
|
|
|
246
|
-
else :
|
|
147
|
+
else :
|
|
148
|
+
new_spots = single_layer.data
|
|
149
|
+
new_clusters = None
|
|
150
|
+
new_cluster_radius = None
|
|
151
|
+
new_min_spot_number = None
|
|
247
152
|
|
|
248
|
-
return new_spots, new_clusters
|
|
153
|
+
return new_spots, new_clusters, new_cluster_radius, new_min_spot_number
|
|
249
154
|
|
|
250
155
|
|
|
251
156
|
# Segmentation
|
|
@@ -295,10 +200,10 @@ def show_segmentation(
|
|
|
295
200
|
labels_layer_list += [cyto_label_layer]
|
|
296
201
|
|
|
297
202
|
#Adding widget
|
|
298
|
-
label_eraser =
|
|
299
|
-
label_picker =
|
|
300
|
-
label_reseter =
|
|
301
|
-
changes_applier =
|
|
203
|
+
label_eraser = CellLabelEraser(labels_layer_list)
|
|
204
|
+
label_picker = FreeLabelPicker(labels_layer_list)
|
|
205
|
+
label_reseter = SegmentationReseter(labels_layer_list)
|
|
206
|
+
changes_applier = ChangesPropagater(labels_layer_list)
|
|
302
207
|
|
|
303
208
|
buttons_container = widgets.Container(widgets=[label_picker.widget, changes_applier.widget, label_reseter.widget], labels=False, layout='horizontal')
|
|
304
209
|
tools_container = widgets.Container(
|
small_fish_gui/gui/prompts.py
CHANGED
|
@@ -5,13 +5,13 @@ import numpy as np
|
|
|
5
5
|
from typing import Literal, Union, Any
|
|
6
6
|
from .layout import path_layout, parameters_layout, bool_layout, tuple_layout, combo_elmt, add_header, path_layout, radio_layout
|
|
7
7
|
from ..interface import open_image, check_format, FormatError
|
|
8
|
-
|
|
8
|
+
|
|
9
9
|
|
|
10
10
|
def prompt(layout, add_ok_cancel=True, timeout=None, timeout_key='TIMEOUT_KEY', add_scrollbar=True) :
|
|
11
11
|
"""
|
|
12
12
|
Default event : 'Ok', 'Cancel'
|
|
13
13
|
"""
|
|
14
|
-
if add_ok_cancel : layout += [[sg.Button('Ok'), sg.Button('Cancel')]]
|
|
14
|
+
if add_ok_cancel : layout += [[sg.Button('Ok', bind_return_key=True), sg.Button('Cancel')]]
|
|
15
15
|
|
|
16
16
|
if add_scrollbar :
|
|
17
17
|
size = (400,500)
|
|
@@ -20,7 +20,7 @@ def prompt(layout, add_ok_cancel=True, timeout=None, timeout_key='TIMEOUT_KEY',
|
|
|
20
20
|
else :
|
|
21
21
|
size = (None,None)
|
|
22
22
|
|
|
23
|
-
window = sg.Window('small fish', layout=layout, margins=(10,10), size=size, resizable=True)
|
|
23
|
+
window = sg.Window('small fish', layout=layout, margins=(10,10), size=size, resizable=True, location=None)
|
|
24
24
|
event, values = window.read(timeout=timeout, timeout_key=timeout_key)
|
|
25
25
|
if event == None :
|
|
26
26
|
window.close()
|
|
@@ -33,33 +33,7 @@ def prompt(layout, add_ok_cancel=True, timeout=None, timeout_key='TIMEOUT_KEY',
|
|
|
33
33
|
window.close()
|
|
34
34
|
return event, values
|
|
35
35
|
|
|
36
|
-
def prompt_with_help(layout, help =None, add_scrollbar=True, vertical_scroll_only=True) :
|
|
37
|
-
layout += [[]]
|
|
38
|
-
layout += [[sg.Button('Ok'), sg.Button('Cancel')]]
|
|
39
|
-
|
|
40
|
-
if add_scrollbar :
|
|
41
|
-
size = (400,500)
|
|
42
|
-
col_elmt = sg.Column(layout, scrollable=True, vertical_scroll_only=vertical_scroll_only, size=size)
|
|
43
|
-
layout = [[col_elmt]]
|
|
44
|
-
else :
|
|
45
|
-
size = (None,None)
|
|
46
36
|
|
|
47
|
-
window = sg.Window('small fish', layout=layout, size=size, resizable=True)
|
|
48
|
-
while True :
|
|
49
|
-
event, values = window.read()
|
|
50
|
-
if event == None :
|
|
51
|
-
window.close()
|
|
52
|
-
quit()
|
|
53
|
-
|
|
54
|
-
elif event == 'Ok':
|
|
55
|
-
window.close()
|
|
56
|
-
return event, values
|
|
57
|
-
elif event == 'Help' :
|
|
58
|
-
ask_help(chapter= help)
|
|
59
|
-
|
|
60
|
-
else:
|
|
61
|
-
window.close()
|
|
62
|
-
return event,{}
|
|
63
37
|
|
|
64
38
|
def input_image_prompt(
|
|
65
39
|
is_3D_stack_preset=False,
|
|
@@ -70,7 +44,7 @@ def input_image_prompt(
|
|
|
70
44
|
) :
|
|
71
45
|
"""
|
|
72
46
|
Keys :
|
|
73
|
-
- '
|
|
47
|
+
- 'image_path'
|
|
74
48
|
- 'is_3D_stack'
|
|
75
49
|
- 'time stack'
|
|
76
50
|
- 'is_multichannel'
|
|
@@ -81,18 +55,18 @@ def input_image_prompt(
|
|
|
81
55
|
Returns Values
|
|
82
56
|
|
|
83
57
|
"""
|
|
84
|
-
layout_image_path = path_layout(['
|
|
58
|
+
layout_image_path = path_layout(['image_path'], header= "Image")
|
|
85
59
|
layout_image_path += bool_layout(['3D stack', 'Multichannel stack'],keys= ['is_3D_stack', 'is_multichannel'], preset= [is_3D_stack_preset, multichannel_preset])
|
|
86
60
|
|
|
87
61
|
if type(do_dense_regions_deconvolution_preset) != type(None) and type(do_clustering_preset) != type(None) and type(do_Napari_correction) != type(None):
|
|
88
62
|
layout_image_path += bool_layout(['Dense regions deconvolution', 'Compute clusters', 'Open results in Napari'], keys = ['do_dense_regions_deconvolution', 'do_cluster_computation', 'show_napari_corrector'], preset= [do_dense_regions_deconvolution_preset, do_clustering_preset, do_Napari_correction], header= "Pipeline settings")
|
|
89
63
|
|
|
90
|
-
event, values =
|
|
64
|
+
event, values = prompt(layout_image_path, add_scrollbar=False)
|
|
91
65
|
|
|
92
66
|
if event == 'Cancel' :
|
|
93
67
|
return None
|
|
94
68
|
|
|
95
|
-
im_path = values['
|
|
69
|
+
im_path = values['image_path']
|
|
96
70
|
is_3D_stack = values['is_3D_stack']
|
|
97
71
|
is_multichannel = values['is_multichannel']
|
|
98
72
|
|
|
@@ -191,8 +165,8 @@ def detection_parameters_promt(
|
|
|
191
165
|
|
|
192
166
|
#Clustering
|
|
193
167
|
if do_clustering :
|
|
194
|
-
layout += parameters_layout(['
|
|
195
|
-
layout += parameters_layout(['
|
|
168
|
+
layout += parameters_layout(['cluster_size'], unit="radius(nm)", default_values=[default_dict.setdefault('cluster_size',400)])
|
|
169
|
+
layout += parameters_layout(['min_number_of_spots'], default_values=[default_dict.setdefault('min_number_of_spots', 5)])
|
|
196
170
|
|
|
197
171
|
if is_multichannel and segmentation_done :
|
|
198
172
|
default_segmentation = [default_dict.setdefault('nucleus channel signal', default_dict.setdefault('nucleus channel',0))]
|
|
@@ -205,9 +179,10 @@ def detection_parameters_promt(
|
|
|
205
179
|
header= "Individual spot extraction",
|
|
206
180
|
preset= default_dict.setdefault('spots_extraction_folder', '')
|
|
207
181
|
)
|
|
182
|
+
default_filename = default_dict.setdefault("filename","") + "_spot_extraction"
|
|
208
183
|
layout += parameters_layout(
|
|
209
184
|
parameters=['spots_filename'],
|
|
210
|
-
default_values=[
|
|
185
|
+
default_values=[default_filename],
|
|
211
186
|
size= 13
|
|
212
187
|
)
|
|
213
188
|
layout += bool_layout(
|
|
@@ -216,7 +191,7 @@ def detection_parameters_promt(
|
|
|
216
191
|
preset= [default_dict.setdefault('do_spots_csv',False), default_dict.setdefault('do_spots_excel',False),default_dict.setdefault('do_spots_feather',False)]
|
|
217
192
|
)
|
|
218
193
|
|
|
219
|
-
event, values =
|
|
194
|
+
event, values = prompt(layout)
|
|
220
195
|
if event == 'Cancel' : return None
|
|
221
196
|
if is_3D_stack : values['dim'] = 3
|
|
222
197
|
else : values['dim'] = 2
|
|
@@ -285,10 +260,10 @@ def hub_prompt(fov_results : pd.DataFrame, do_segmentation=False) -> 'Union[Lite
|
|
|
285
260
|
[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],
|
|
286
261
|
[sg.Button('Segment cells'), sg.Button('Add detection'), sg.Button('Compute colocalisation'), sg.Button('Batch detection')],
|
|
287
262
|
[sg.Button('Save results', button_color= 'green'), sg.Button('Save segmentation', button_color= 'green'), sg.Button('Load segmentation', button_color= 'green')],
|
|
288
|
-
[sg.Button('Rename acquisition', button_color= 'gray'), sg.Button('Delete acquisitions',button_color= 'gray'), sg.Button('Reset segmentation',button_color= 'gray'), sg.Button('Reset all',button_color= 'gray')],
|
|
263
|
+
[sg.Button('Rename acquisition', button_color= 'gray'), sg.Button('Delete acquisitions',button_color= 'gray'), sg.Button('Reset segmentation',button_color= 'gray'), sg.Button('Reset all',button_color= 'gray'), sg.Button('Open wiki',button_color= 'yellow', key='wiki')],
|
|
289
264
|
]
|
|
290
265
|
|
|
291
|
-
window = sg.Window('small fish', layout= layout, margins= (10,10))
|
|
266
|
+
window = sg.Window('small fish', layout= layout, margins= (10,10), location=None)
|
|
292
267
|
|
|
293
268
|
while True :
|
|
294
269
|
event, values = window.read()
|
|
@@ -300,7 +275,7 @@ def hub_prompt(fov_results : pd.DataFrame, do_segmentation=False) -> 'Union[Lite
|
|
|
300
275
|
|
|
301
276
|
def coloc_prompt() :
|
|
302
277
|
layout = parameters_layout(['colocalisation distance'], unit= 'nm', header= 'Colocalisation', default_values= 0)
|
|
303
|
-
event, values =
|
|
278
|
+
event, values = prompt(layout)
|
|
304
279
|
|
|
305
280
|
if event == 'Ok' :
|
|
306
281
|
return values['colocalisation distance']
|
|
@@ -308,7 +283,7 @@ def coloc_prompt() :
|
|
|
308
283
|
|
|
309
284
|
def rename_prompt() :
|
|
310
285
|
layout = parameters_layout(['name'], header= "Rename acquisitions", size=12)
|
|
311
|
-
event, values =
|
|
286
|
+
event, values = prompt(layout)
|
|
312
287
|
if event == 'Ok' :
|
|
313
288
|
return values['name']
|
|
314
289
|
else : return False
|