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.
@@ -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(['image path'], header= "Image")
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(['cluster size'], unit="radius(nm)", default_values=[default_dict.setdefault('cluster size',400)])
287
- layout += parameters_layout(['min number of spots'], default_values=[default_dict.setdefault('min number of spots', 5)])
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=[default_dict.setdefault('spots_filename','spots_extraction')],
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 bigfish.detection.cluster_detection import _extract_information
17
- from ._napari_widgets import cell_label_eraser, segmentation_reseter, changes_propagater, free_label_picker
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
- Viewer.add_points( # single molecule spots; this layer can be update by user.
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= {"spot_number" : clusters[:,dim], "id" : clusters[:,dim+1]},
211
- feature_defaults= {"spot_number" : 0, "id" : -2} # napari features default will not work with np.NaN passing -2 instead.
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.round(Viewer.layers['foci'].data).astype(int)
224
- if len(new_clusters) == 0 :
225
- new_clusters = np.empty(shape=(0,dim + 2), dtype=int)
226
- new_cluster_id = -1 * np.ones(shape=(len(new_spots), 1), dtype=int)
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
- new_spots, new_clusters = _update_clusters(
234
- old_spots =spots,
235
- spot_cluster_id = spot_cluster_id,
236
- new_spots=new_spots,
237
- old_clusters=clusters,
238
- new_clusters=new_clusters,
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 : new_clusters = None
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 = cell_label_eraser(labels_layer_list)
299
- label_picker = free_label_picker(labels_layer_list)
300
- label_reseter = segmentation_reseter(labels_layer_list)
301
- changes_applier = changes_propagater(labels_layer_list)
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(
@@ -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
- from .help_module import ask_help
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
- - 'image path'
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(['image path'], header= "Image")
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 = prompt_with_help(layout_image_path, help= 'general', add_scrollbar=False)
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['image path']
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(['cluster size'], unit="radius(nm)", default_values=[default_dict.setdefault('cluster size',400)])
195
- layout += parameters_layout(['min number of spots'], default_values=[default_dict.setdefault('min number of spots', 5)])
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=[default_dict.setdefault('spots_filename','spots_extraction')],
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 = prompt_with_help(layout, help='detection')
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 = prompt_with_help(layout)
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 = prompt_with_help(layout)
286
+ event, values = prompt(layout)
312
287
  if event == 'Ok' :
313
288
  return values['name']
314
289
  else : return False