small-fish-gui 1.7.1__py3-none-any.whl → 1.8.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.
Files changed (35) hide show
  1. small_fish_gui/__init__.py +1 -1
  2. small_fish_gui/batch/integrity.py +3 -3
  3. small_fish_gui/batch/pipeline.py +14 -6
  4. small_fish_gui/batch/prompt.py +14 -14
  5. small_fish_gui/batch/update.py +2 -2
  6. small_fish_gui/batch/utils.py +8 -8
  7. small_fish_gui/batch/values.txt +2 -2
  8. small_fish_gui/gui/help_module.py +4 -4
  9. small_fish_gui/gui/layout.py +24 -20
  10. small_fish_gui/gui/prompts.py +99 -51
  11. small_fish_gui/hints.py +54 -0
  12. small_fish_gui/interface/__init__.py +1 -1
  13. small_fish_gui/interface/image.py +2 -2
  14. small_fish_gui/interface/{output.py → inoutput.py} +39 -0
  15. small_fish_gui/interface/testing.py +10 -6
  16. small_fish_gui/pipeline/__init__.py +4 -4
  17. small_fish_gui/pipeline/_colocalisation.py +19 -14
  18. small_fish_gui/pipeline/_preprocess.py +98 -50
  19. small_fish_gui/pipeline/actions.py +142 -38
  20. small_fish_gui/pipeline/detection.py +54 -106
  21. small_fish_gui/pipeline/main.py +28 -35
  22. small_fish_gui/pipeline/{_segmentation.py → segmentation.py} +32 -14
  23. small_fish_gui/pipeline/spots.py +4 -1
  24. {small_fish_gui-1.7.1.dist-info → small_fish_gui-1.8.1.dist-info}/METADATA +1 -2
  25. small_fish_gui-1.8.1.dist-info/RECORD +50 -0
  26. {small_fish_gui-1.7.1.dist-info → small_fish_gui-1.8.1.dist-info}/WHEEL +1 -1
  27. small_fish_gui/batch/output.py +0 -0
  28. small_fish_gui/batch/values.py +0 -3
  29. small_fish_gui/docs/conf.py +0 -1
  30. small_fish_gui/interface/parameters.py +0 -2
  31. small_fish_gui-1.7.1.dist-info/RECORD +0 -53
  32. /small_fish_gui/gui/{general_help_screenshot.png → screenshot/general_help_screenshot.png} +0 -0
  33. /small_fish_gui/gui/{mapping_help_screenshot.png → screenshot/mapping_help_screenshot.png} +0 -0
  34. /small_fish_gui/gui/{segmentation_help_screenshot.png → screenshot/segmentation_help_screenshot.png} +0 -0
  35. {small_fish_gui-1.7.1.dist-info → small_fish_gui-1.8.1.dist-info}/licenses/LICENSE +0 -0
@@ -38,4 +38,4 @@ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38
38
  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39
39
 
40
40
  """
41
- __version__ = "1.7.1"
41
+ __version__ = "1.8.1"
@@ -9,7 +9,7 @@ import numpy as np
9
9
  import PySimpleGUI as sg
10
10
 
11
11
  from ..pipeline._preprocess import check_integrity, convert_parameters_types, ParameterInputError, _check_segmentation_parameters
12
- from ..pipeline._segmentation import _cast_segmentation_parameters
12
+ from ..pipeline.segmentation import _cast_segmentation_parameters
13
13
 
14
14
  def check_file(filename:str) :
15
15
 
@@ -105,7 +105,7 @@ def check_detection_parameters(
105
105
  do_clustering,
106
106
  is_multichannel,
107
107
  is_3D,
108
- map,
108
+ map_,
109
109
  shape
110
110
  ) :
111
111
 
@@ -118,7 +118,7 @@ def check_detection_parameters(
118
118
  do_clustering=do_clustering,
119
119
  multichannel=is_multichannel,
120
120
  segmentation_done=None,
121
- map=map,
121
+ map_=map_,
122
122
  shape=shape
123
123
  )
124
124
  except ParameterInputError as e:
@@ -6,6 +6,8 @@ import os
6
6
  import pandas as pd
7
7
  import PySimpleGUI as sg
8
8
 
9
+ from ..hints import pipeline_parameters
10
+
9
11
  from .input import open_image
10
12
  from ..interface import write_results
11
13
  from ..pipeline import reorder_shape, reorder_image_stack, prepare_image_detection
@@ -24,10 +26,10 @@ def batch_pipeline(
24
26
  batch_window : sg.Window,
25
27
  batch_progress_bar : sg.ProgressBar,
26
28
  progress_count : sg.Text,
27
- parameters : dict,
29
+ parameters : pipeline_parameters,
28
30
  filenames_list : list,
29
31
  do_segmentation : bool,
30
- map : dict,
32
+ map_ : dict,
31
33
  results_df : pd.DataFrame,
32
34
  cell_results_df : pd.DataFrame,
33
35
  is_3D,
@@ -73,12 +75,12 @@ def batch_pipeline(
73
75
  #1. Re-order shape
74
76
  shape = image.shape
75
77
  parameters['shape'] = shape
76
- parameters['reordered_shape'] = reorder_shape(shape, map=map)
78
+ parameters['reordered_shape'] = reorder_shape(shape, map_=map_)
77
79
 
78
80
  #2. Segmentation (opt)
79
81
  if do_segmentation :
80
82
  window_print(batch_window,"Segmenting cells...")
81
- im_seg = reorder_image_stack(map, parameters)
83
+ im_seg = reorder_image_stack(map_, image)
82
84
  parameters = _cast_segmentation_parameters(parameters)
83
85
  cytoplasm_label, nucleus_label = cell_segmentation(
84
86
  im_seg,
@@ -90,6 +92,8 @@ def batch_pipeline(
90
92
  do_only_nuc=parameters['Segment only nuclei']
91
93
  )
92
94
 
95
+ parameters['segmentation_done'] = True
96
+
93
97
  if cytoplasm_label.max() == 0 : #No cell segmented
94
98
  window_print(batch_window,"No cell was segmented, computing next image.")
95
99
  continue
@@ -108,11 +112,12 @@ def batch_pipeline(
108
112
 
109
113
  else :
110
114
  cytoplasm_label, nucleus_label = None,None
115
+ parameters['segmentation_done'] = False
111
116
 
112
117
  #3. Detection, deconvolution, clusterisation
113
118
  window_print(batch_window,"Detecting spots...")
114
119
  parameters = convert_parameters_types(parameters)
115
- image, other_image = prepare_image_detection(map, parameters)
120
+ image, other_image = prepare_image_detection(map_, parameters)
116
121
  nucleus_signal = get_nucleus_signal(image, other_image, parameters)
117
122
  try : # Catch error raised if user enter a spot size too small compare to voxel size
118
123
  parameters, frame_result, spots, clusters = launch_detection(
@@ -132,7 +137,10 @@ def batch_pipeline(
132
137
  raise(error)
133
138
 
134
139
  if parameters['save detection'] :
135
- if parameters['Cluster computation'] : spots_list = [spots, clusters[:,:parameters['dim']]]
140
+ if parameters['do_cluster_computation'] :
141
+ if len(clusters) > 0 :
142
+ spots_list = [spots, clusters[:,:parameters['dim']]]
143
+ else : spots_list = [spots]
136
144
  else : spots_list = [spots]
137
145
  output_spot_tiffvisual(
138
146
  image,
@@ -45,18 +45,18 @@ def batch_promp(
45
45
  #Input tab
46
46
  input_layout = _input_parameters_layout(
47
47
  ask_for_segmentation=True,
48
- is_3D_stack_preset= preset.setdefault("3D stack" ,False),
48
+ is_3D_stack_preset= preset.setdefault("is_3D_stack" ,False),
49
49
  time_stack_preset=False,
50
- multichannel_preset=preset.setdefault("multichannel" ,False),
51
- do_dense_regions_deconvolution_preset=preset.setdefault("Dense regions deconvolution" ,False),
52
- do_clustering_preset= preset.setdefault("Cluster computation", False),
50
+ multichannel_preset=preset.setdefault("is_multichannel" ,False),
51
+ do_dense_regions_deconvolution_preset=preset.setdefault("do_dense_regions_deconvolution" ,False),
52
+ do_clustering_preset= preset.setdefault("do_cluster_computation", False),
53
53
  do_Napari_correction=False,
54
- do_segmentation_preset= preset.setdefault("Segmentation", False),
54
+ do_segmentation_preset= preset.setdefault("segmentation_done", False),
55
55
  )
56
56
  input_layout += [[sg.Button('Ok')]]
57
57
  input_tab = sg.Tab("Input", input_layout)
58
58
 
59
- napari_correction_elmt = get_elmt_from_key(input_tab, key='Napari correction')
59
+ napari_correction_elmt = get_elmt_from_key(input_tab, key='show_napari_corrector')
60
60
 
61
61
  #Maptab
62
62
  map_layout = _ask_channel_map_layout(
@@ -86,7 +86,7 @@ def batch_promp(
86
86
 
87
87
  apply_segmentation_button = sg.Button('apply', key='apply-segmentation')
88
88
  segmentation_layout += [[apply_segmentation_button]]
89
- seg_keys_to_hide = ['show segmentation', 'saving path', 'filename']
89
+ seg_keys_to_hide = ['show segmentation', 'saving path', 'filename', 'other_nucleus_image']
90
90
  segmentation_tab = sg.Tab("Segmentation", segmentation_layout, visible=False)
91
91
 
92
92
  #Detection tab
@@ -228,11 +228,11 @@ def batch_promp(
228
228
  print("Welcome to small fish batch analysis. Please start by loading some files and setting parameters.")
229
229
 
230
230
  batch_folder = values.get('Batch_folder')
231
- is_multichanel = values.get('multichannel')
232
- is_3D = values.get('3D stack')
233
- do_segmentation = values.get('Segmentation')
234
- do_dense_regions_deconvolution = values.get('Dense regions deconvolution')
235
- do_clustering = values.get('Cluster computation')
231
+ is_multichanel = values.get('is_multichannel')
232
+ is_3D = values.get('is_3D_stack')
233
+ do_segmentation = values.get('do_segmentation')
234
+ do_dense_regions_deconvolution = values.get('do_dense_regions_deconvolution')
235
+ do_clustering = values.get('do_cluster_computation')
236
236
 
237
237
  if type(batch_folder) != type(None) and event == 'Load':
238
238
 
@@ -321,7 +321,7 @@ def batch_promp(
321
321
  do_clustering=do_clustering,
322
322
  is_multichannel=is_multichanel,
323
323
  is_3D=is_3D,
324
- map= Master_parameters_dict.get('_map'),
324
+ map_= Master_parameters_dict.get('_map'),
325
325
  shape=last_shape
326
326
  )
327
327
 
@@ -350,7 +350,7 @@ def batch_promp(
350
350
  parameters=values,
351
351
  filenames_list=filename_list,
352
352
  do_segmentation=do_segmentation,
353
- map= Master_parameters_dict['_map'],
353
+ map_= Master_parameters_dict['_map'],
354
354
  results_df=results_df,
355
355
  cell_results_df=cell_results_df,
356
356
  is_3D=is_3D,
@@ -36,7 +36,7 @@ def update_detection_tab(
36
36
 
37
37
  #Acess elements
38
38
  ##Detection
39
- channel_to_compute = get_elmt_from_key(tab_elmt, key= 'channel to compute')
39
+ channel_to_compute = get_elmt_from_key(tab_elmt, key= 'channel_to_compute')
40
40
  voxel_size_z = get_elmt_from_key(tab_elmt, key= 'voxel_size_z')
41
41
  spot_size_z = get_elmt_from_key(tab_elmt, key= 'spot_size_z')
42
42
  log_kernel_size_z = get_elmt_from_key(tab_elmt, key= 'log_kernel_size_z')
@@ -58,7 +58,7 @@ def update_detection_tab(
58
58
  nucleus_channel_signal = get_elmt_from_key(tab_elmt, key= 'nucleus channel signal')
59
59
 
60
60
  #disable
61
- interactive_threshold_selector = get_elmt_from_key(tab_elmt, key= 'Interactive threshold selector')
61
+ interactive_threshold_selector = get_elmt_from_key(tab_elmt, key= 'show_interactive_threshold_selector')
62
62
 
63
63
  update_dict={
64
64
  'is_3D' : is_3D,
@@ -16,12 +16,12 @@ def call_auto_map(
16
16
  ) :
17
17
 
18
18
  if len(shape) < 2 + is_3D + is_multichannel :
19
- sg.popup("Image is of dimension {0} and you're trying to map {1} dimensions".format(len(shape), 2+is_3D+is_multichannel))
19
+ sg.popup("Image is of dimension {0} and you're trying to map_ {1} dimensions".format(len(shape), 2+is_3D+is_multichannel))
20
20
  return {}
21
21
 
22
- #Get auto map
22
+ #Get auto map_
23
23
  try :
24
- map = _auto_map_channels(
24
+ map_ = _auto_map_channels(
25
25
  is_3D_stack=is_3D,
26
26
  is_time_stack=False,
27
27
  multichannel=is_multichannel,
@@ -41,12 +41,12 @@ def call_auto_map(
41
41
  c_elmt = get_elmt_from_key(tab_elmt, 'c')
42
42
 
43
43
  #Update values
44
- x_elmt.update(value=map.get('x'))
45
- y_elmt.update(value=map.get('y'))
46
- z_elmt.update(value=map.get('z'))
47
- c_elmt.update(value=map.get('c'))
44
+ x_elmt.update(value=map_.get('x'))
45
+ y_elmt.update(value=map_.get('y'))
46
+ z_elmt.update(value=map_.get('z'))
47
+ c_elmt.update(value=map_.get('c'))
48
48
 
49
- return map
49
+ return map_
50
50
 
51
51
  def create_map(
52
52
  values:dict,
@@ -6,7 +6,7 @@ image path
6
6
  3D stack
7
7
  multichannel
8
8
  Dense regions deconvolution
9
- Cluster computation
9
+ do_cluster_computation
10
10
  Segmentation
11
11
  Napari correction
12
12
  x
@@ -48,7 +48,7 @@ deconvolution_kernel_y
48
48
  deconvolution_kernel_x
49
49
  cluster size
50
50
  min number of spots
51
- Interactive threshold selector
51
+ show_interactive_threshold_selector
52
52
  spots_extraction_folder
53
53
  spots_filename
54
54
  do_spots_csv
@@ -43,11 +43,11 @@ def _general_help() :
43
43
  help_text = """
44
44
  Pipeline settings :
45
45
 
46
- Dense regions deconvolution : (Recommanded for cluster computations) Detect dense and bright regions with potential clustered
46
+ do_dense_regions_deconvolution : (Recommanded for cluster computations) Detect dense and bright regions with potential clustered
47
47
  spots and simulate a more realistic number of spots in these regions.
48
48
  See bigfish documentation : https://big-fish.readthedocs.io/en/stable/detection/dense.html
49
49
 
50
- Cluster computation :
50
+ do_cluster_computation :
51
51
  DBScan algorithm is ran by big-fish to detecte clusters of spots. Use is you want to quantify one of the following :
52
52
  Transcription sites, foci, colocalisation of spots near foci...
53
53
 
@@ -73,7 +73,7 @@ def _detection_help() :
73
73
  Access fully detailed documentation :
74
74
 
75
75
  DETECTION : https://big-fish.readthedocs.io/en/stable/detection/spots.html
76
- DENSE REGIONS DECONVOLUTION : https://big-fish.readthedocs.io/en/stable/detection/dense.html
76
+ do_dense_regions_deconvolution : https://big-fish.readthedocs.io/en/stable/detection/dense.html
77
77
  CLUSTERING : https://big-fish.readthedocs.io/en/stable/detection/cluster.html
78
78
 
79
79
  """
@@ -114,7 +114,7 @@ def _detection_help() :
114
114
 
115
115
  """
116
116
  deconv_header="""
117
- DENSE REGIONS DECONVOLUTION PARAMETERS
117
+ do_dense_regions_deconvolution PARAMETERS
118
118
 
119
119
  """
120
120
  deconv_text="""
@@ -101,7 +101,7 @@ def path_layout(keys= [],look_for_dir = False, header=None, preset=os.getcwd())
101
101
  layout = [add_header(header)] + layout
102
102
  return layout
103
103
 
104
- def bool_layout(parameters= [], header=None, preset=None) :
104
+ def bool_layout(parameters= [], header=None, preset=None, keys=None) :
105
105
  if len(parameters) == 0 : return []
106
106
  check_parameter(parameters= list, header= (str, type(None)), preset=(type(None), list, tuple, bool))
107
107
  for key in parameters : check_parameter(key = str)
@@ -112,11 +112,19 @@ def bool_layout(parameters= [], header=None, preset=None) :
112
112
  else :
113
113
  for key in preset : check_parameter(key = bool)
114
114
 
115
+ max_length = len(max(parameters, key=len))
115
116
 
117
+ if type(keys) == type(None) :
118
+ keys = parameters
119
+ elif isinstance(keys,(list,tuple)) :
120
+ if len(keys) != len(parameters) : raise ValueError("keys arguement must be of same length than parameters argument")
121
+ elif len(parameters) == 1 and isinstance(keys, str) :
122
+ keys = [keys]
123
+ else :
124
+ raise ValueError('Incorrect keys parameters. Expected list of same length than parameters or None.')
116
125
 
117
- max_length = len(max(parameters, key=len))
118
126
  layout = [
119
- [sg.Checkbox(pad_right(name, max_length, ' '), key= name, default=box_preset)] for name, box_preset in zip(parameters,preset)
127
+ [sg.Checkbox(pad_right(name, max_length, ' '), key=key, default=box_preset)] for name, box_preset, key in zip(parameters,preset,keys)
120
128
  ]
121
129
  if isinstance(header, str) :
122
130
  layout = [add_header(header)] + layout
@@ -139,14 +147,14 @@ def combo_elmt(values, key, header=None, read_only=True, default_value=None) :
139
147
  layout = add_header(header) + layout
140
148
  return layout
141
149
 
142
- def radio_layout(values, header=None) :
150
+ def radio_layout(values, header=None, key=None) :
143
151
  """
144
152
  Single choice buttons.
145
153
  """
146
154
  if len(values) == 0 : return []
147
155
  check_parameter(values= list, header= (str, type(None)))
148
156
  layout = [
149
- [sg.Radio(value, group_id= 0) for value in values]
157
+ [sg.Radio(value, group_id= 0, key=key) for value in values]
150
158
  ]
151
159
  if isinstance(header, str) :
152
160
  layout = [add_header(header)] + layout
@@ -219,18 +227,14 @@ def _input_parameters_layout(
219
227
 
220
228
  ) :
221
229
  layout_image_path = path_layout(['image path'], header= "Image")
222
- layout_image_path += bool_layout(['3D stack', 'multichannel'], preset= [is_3D_stack_preset, time_stack_preset, multichannel_preset])
230
+ layout_image_path += bool_layout(['3D stack', 'Multichannel stack'], keys=['is_3D_stack', 'is_multichannel'], preset= [is_3D_stack_preset, multichannel_preset])
223
231
 
224
- if ask_for_segmentation :
225
- layout_image_path += bool_layout(
226
- ['Dense regions deconvolution', 'Cluster computation', 'Segmentation', 'Napari correction'],
227
- preset= [do_dense_regions_deconvolution_preset, do_clustering_preset, do_segmentation_preset, do_Napari_correction],
228
- header= "Pipeline settings")
229
- else :
230
- layout_image_path += bool_layout(
231
- ['Dense regions deconvolution', 'Cluster computation', 'Napari correction'],
232
- preset= [do_dense_regions_deconvolution_preset, do_clustering_preset, do_Napari_correction],
233
- header= "Pipeline settings")
232
+ layout_image_path += bool_layout(
233
+ ['Dense regions deconvolution', 'Compute clusters', 'Cell segmentation', 'Open Napari corrector'],
234
+ keys= ['do_dense_regions_deconvolution', 'do_cluster_computation', 'do_segmentation', 'show_napari_corrector'],
235
+ preset= [do_dense_regions_deconvolution_preset, do_clustering_preset, do_segmentation_preset, do_Napari_correction],
236
+ header= "Pipeline settings")
237
+
234
238
 
235
239
  return layout_image_path
236
240
 
@@ -251,9 +255,9 @@ def _detection_layout(
251
255
  default_detection = [default_dict.setdefault('threshold',''), default_dict.setdefault('threshold penalty', '1')]
252
256
  opt= [True, True]
253
257
  if is_multichannel :
254
- detection_parameters += ['channel to compute']
258
+ detection_parameters += ['channel_to_compute']
255
259
  opt += [False]
256
- default_detection += [default_dict.setdefault('channel to compute', '')]
260
+ default_detection += [default_dict.setdefault('channel_to_compute', '')]
257
261
 
258
262
  layout = [[sg.Text("Green parameters", text_color= 'green'), sg.Text(" are optional parameters.")]]
259
263
  layout += parameters_layout(detection_parameters, header= 'Detection', opt=opt, default_values=default_detection)
@@ -273,7 +277,7 @@ def _detection_layout(
273
277
  #Deconvolution
274
278
  if do_dense_region_deconvolution :
275
279
  default_dense_regions_deconvolution = [default_dict.setdefault('alpha',0.5), default_dict.setdefault('beta',1)]
276
- layout += parameters_layout(['alpha', 'beta',], default_values= default_dense_regions_deconvolution, header= 'Dense regions deconvolution')
280
+ layout += parameters_layout(['alpha', 'beta',], default_values= default_dense_regions_deconvolution, header= 'do_dense_regions_deconvolution')
277
281
  layout += parameters_layout(['gamma'], unit= 'px', default_values= [default_dict.setdefault('gamma',5)])
278
282
  layout += tuple_layout(opt= {"deconvolution_kernel" : True}, unit= {"deconvolution_kernel" : 'px'}, default_dict=default_dict, deconvolution_kernel = tuple_shape)
279
283
 
@@ -284,7 +288,7 @@ def _detection_layout(
284
288
 
285
289
 
286
290
 
287
- layout += bool_layout(['Interactive threshold selector'], preset=[False])
291
+ layout += bool_layout(['Interactive threshold selector'],keys = ['show_interactive_threshold_selector'], preset=[False])
288
292
  layout += path_layout(
289
293
  keys=['spots_extraction_folder'],
290
294
  look_for_dir=True,
@@ -2,7 +2,8 @@ import PySimpleGUI as sg
2
2
  import pandas as pd
3
3
  import os
4
4
  import numpy as np
5
- from .layout import path_layout, parameters_layout, bool_layout, tuple_layout, combo_elmt, add_header, path_layout
5
+ from typing import Literal, Union, Any
6
+ from .layout import path_layout, parameters_layout, bool_layout, tuple_layout, combo_elmt, add_header, path_layout, radio_layout
6
7
  from ..interface import open_image, check_format, FormatError
7
8
  from .help_module import ask_help
8
9
 
@@ -34,7 +35,6 @@ def prompt(layout, add_ok_cancel=True, timeout=None, timeout_key='TIMEOUT_KEY',
34
35
 
35
36
  def prompt_with_help(layout, help =None, add_scrollbar=True, vertical_scroll_only=True) :
36
37
  layout += [[]]
37
- layout += [[sg.Button('Help')]]
38
38
  layout += [[sg.Button('Ok'), sg.Button('Cancel')]]
39
39
 
40
40
  if add_scrollbar :
@@ -63,34 +63,29 @@ def prompt_with_help(layout, help =None, add_scrollbar=True, vertical_scroll_onl
63
63
 
64
64
  def input_image_prompt(
65
65
  is_3D_stack_preset=False,
66
- time_stack_preset=False,
67
66
  multichannel_preset = False,
68
67
  do_dense_regions_deconvolution_preset= False,
69
68
  do_clustering_preset = False,
70
- do_segmentation_preset= False,
71
69
  do_Napari_correction= False,
72
- ask_for_segmentation= True
73
70
  ) :
74
71
  """
75
72
  Keys :
76
73
  - 'image path'
77
- - '3D stack'
74
+ - 'is_3D_stack'
78
75
  - 'time stack'
79
- - 'multichannel'
80
- - 'Dense regions deconvolution'
76
+ - 'is_multichannel'
77
+ - 'do_dense_regions_deconvolution'
81
78
  - 'Segmentation'
82
- - 'Napari correction'
79
+ - 'show_napari_corrector'
83
80
 
84
81
  Returns Values
85
82
 
86
83
  """
87
84
  layout_image_path = path_layout(['image path'], header= "Image")
88
- layout_image_path += bool_layout(['3D stack', 'time stack', 'multichannel'], preset= [is_3D_stack_preset, time_stack_preset, multichannel_preset])
85
+ layout_image_path += bool_layout(['3D stack', 'Multichannel stack'],keys= ['is_3D_stack', 'is_multichannel'], preset= [is_3D_stack_preset, multichannel_preset])
89
86
 
90
- if ask_for_segmentation :
91
- layout_image_path += bool_layout(['Dense regions deconvolution', 'Cluster computation', 'Segmentation', 'Napari correction'], preset= [do_dense_regions_deconvolution_preset, do_clustering_preset, do_segmentation_preset, do_Napari_correction], header= "Pipeline settings")
92
- else :
93
- layout_image_path += bool_layout(['Dense regions deconvolution', 'Cluster computation', 'Napari correction'], preset= [do_dense_regions_deconvolution_preset, do_clustering_preset, do_Napari_correction], header= "Pipeline settings")
87
+ if type(do_dense_regions_deconvolution_preset) != type(None) and type(do_clustering_preset) != type(None) and type(do_Napari_correction) != type(None):
88
+ 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")
94
89
 
95
90
  event, values = prompt_with_help(layout_image_path, help= 'general', add_scrollbar=False)
96
91
 
@@ -98,18 +93,12 @@ def input_image_prompt(
98
93
  return None
99
94
 
100
95
  im_path = values['image path']
101
- is_3D_stack = values['3D stack']
102
- is_time_stack = values['time stack']
103
- is_multichannel = values['multichannel']
104
- if not ask_for_segmentation : values['Segmentation'] = False
105
-
106
- if is_time_stack :
107
- sg.popup("Sorry time stack images are not yet supported.")
108
- return values
96
+ is_3D_stack = values['is_3D_stack']
97
+ is_multichannel = values['is_multichannel']
109
98
 
110
99
  try :
111
100
  image = open_image(im_path)
112
- check_format(image, is_3D_stack, is_time_stack, is_multichannel)
101
+ check_format(image, is_3D_stack, is_multichannel)
113
102
  values.update({'image' : image})
114
103
  except FormatError as error:
115
104
  sg.popup("Inconsistency between image format and options selected.\n Image shape : {0}".format(image.shape))
@@ -159,24 +148,16 @@ def output_image_prompt(filename) :
159
148
 
160
149
  else : return values
161
150
 
162
- def detection_parameters_promt(is_3D_stack, is_multichannel, do_dense_region_deconvolution, do_clustering, do_segmentation, segmentation_done, default_dict: dict) :
151
+ def detection_parameters_promt(
152
+ is_3D_stack,
153
+ is_multichannel,
154
+ do_dense_region_deconvolution,
155
+ do_clustering,
156
+ segmentation_done,
157
+ default_dict: dict
158
+ ):
163
159
  """
164
160
 
165
- keys :
166
- - 'threshold'
167
- - 'threshold penalty
168
- - 'time step'
169
- - 'channel to compute'
170
- - 'alpha'
171
- - 'beta'
172
- - 'gamma'
173
- - 'voxel_size_{(z,y,x)}'
174
- - 'spot_size{(z,y,x)}'
175
- - 'log_kernel_size{(z,y,x)}'
176
- - 'minimum_distance{(z,y,x)}'
177
- - 'cluster size'
178
- - 'min number of spots'
179
-
180
161
  Returns Values
181
162
 
182
163
  """
@@ -188,9 +169,9 @@ def detection_parameters_promt(is_3D_stack, is_multichannel, do_dense_region_dec
188
169
  default_detection = [default_dict.setdefault('threshold',''), default_dict.setdefault('threshold penalty', '1')]
189
170
  opt= [True, True]
190
171
  if is_multichannel :
191
- detection_parameters += ['channel to compute']
172
+ detection_parameters += ['channel_to_compute']
192
173
  opt += [False]
193
- default_detection += [default_dict.setdefault('channel to compute', '')]
174
+ default_detection += [default_dict.setdefault('channel_to_compute', '')]
194
175
  layout = [[sg.Text("Green parameters", text_color= 'green'), sg.Text(" are optional parameters.")]]
195
176
  layout += parameters_layout(detection_parameters, header= 'Detection', opt=opt, default_values=default_detection)
196
177
 
@@ -204,7 +185,7 @@ def detection_parameters_promt(is_3D_stack, is_multichannel, do_dense_region_dec
204
185
  #Deconvolution
205
186
  if do_dense_region_deconvolution :
206
187
  default_dense_regions_deconvolution = [default_dict.setdefault('alpha',0.5), default_dict.setdefault('beta',1)]
207
- layout += parameters_layout(['alpha', 'beta',], default_values= default_dense_regions_deconvolution, header= 'Dense regions deconvolution')
188
+ layout += parameters_layout(['alpha', 'beta',], default_values= default_dense_regions_deconvolution, header= 'do_dense_regions_deconvolution')
208
189
  layout += parameters_layout(['gamma'], unit= 'px', default_values= [default_dict.setdefault('gamma',5)])
209
190
  layout += tuple_layout(opt= {"deconvolution_kernel" : True}, unit= {"deconvolution_kernel" : 'px'}, default_dict=default_dict, deconvolution_kernel = tuple_shape)
210
191
 
@@ -213,11 +194,11 @@ def detection_parameters_promt(is_3D_stack, is_multichannel, do_dense_region_dec
213
194
  layout += parameters_layout(['cluster size'], unit="radius(nm)", default_values=[default_dict.setdefault('cluster size',400)])
214
195
  layout += parameters_layout(['min number of spots'], default_values=[default_dict.setdefault('min number of spots', 5)])
215
196
 
216
- if (do_segmentation and is_multichannel) or (is_multichannel and segmentation_done):
197
+ if is_multichannel and segmentation_done :
217
198
  default_segmentation = [default_dict.setdefault('nucleus channel signal', default_dict.setdefault('nucleus channel',0))]
218
199
  layout += parameters_layout(['nucleus channel signal'], default_values=default_segmentation) + [[sg.Text(" channel from which signal will be measured for nucleus features.")]]
219
200
 
220
- layout += bool_layout(['Interactive threshold selector'], preset=[False])
201
+ layout += bool_layout(['Interactive threshold selector'], keys=['show_interactive_threshold_selector'], preset=[False])
221
202
  layout += path_layout(
222
203
  keys=['spots_extraction_folder'],
223
204
  look_for_dir=True,
@@ -230,7 +211,8 @@ def detection_parameters_promt(is_3D_stack, is_multichannel, do_dense_region_dec
230
211
  size= 13
231
212
  )
232
213
  layout += bool_layout(
233
- parameters= ['do_spots_csv', 'do_spots_excel', 'do_spots_feather'],
214
+ ['.csv','.excel','.feather'],
215
+ keys= ['do_spots_csv', 'do_spots_excel', 'do_spots_feather'],
234
216
  preset= [default_dict.setdefault('do_spots_csv',False), default_dict.setdefault('do_spots_excel',False),default_dict.setdefault('do_spots_feather',False)]
235
217
  )
236
218
 
@@ -280,17 +262,17 @@ def _warning_popup(warning:str) :
280
262
 
281
263
  def _sumup_df(results: pd.DataFrame) :
282
264
 
283
- COLUMNS = ['acquisition_id','name','threshold', 'spot_number', 'cell_number', 'filename', 'channel to compute']
265
+ COLUMNS = ['acquisition_id','name','threshold', 'spot_number', 'cell_number', 'filename', 'channel_to_compute']
284
266
 
285
267
  if len(results) > 0 :
286
- if 'channel to compute' not in results : results['channel to compute'] = np.NaN
268
+ if 'channel_to_compute' not in results : results['channel_to_compute'] = np.NaN
287
269
  res = results.loc[:,COLUMNS]
288
270
  else :
289
271
  res = pd.DataFrame(columns= COLUMNS)
290
272
 
291
273
  return res
292
274
 
293
- def hub_prompt(fov_results, do_segmentation=False) :
275
+ def hub_prompt(fov_results, do_segmentation=False) -> 'Union[Literal["Add detection", "Compute colocalisation", "Batch detection", "Rename acquisition", "Save results", "Delete acquisitions", "Reset segmentation", "Reset results", "Segment cells"], dict[Literal["result_table", ""]]]':
294
276
 
295
277
  sumup_df = _sumup_df(fov_results)
296
278
 
@@ -302,9 +284,9 @@ def hub_prompt(fov_results, do_segmentation=False) :
302
284
  layout = [
303
285
  [sg.Text('RESULTS', font= 'bold 13')],
304
286
  [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],
305
- [sg.Button('Add detection'), sg.Button('Compute colocalisation'), sg.Button('Batch detection')],
306
- [sg.Button('Rename acquisition', button_color= 'green'), 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')]
307
- # [sg.Button('Save results', button_color= 'green'), sg.Button('Reset results',button_color= 'gray')]
287
+ [sg.Button('Segment cells'), sg.Button('Add detection'), sg.Button('Compute colocalisation'), sg.Button('Batch detection')],
288
+ [sg.Button('Save results', button_color= 'green'), sg.Button('Save segmentation', button_color= 'green'), sg.Button('Load segmentation', button_color= 'green')],
289
+ [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')],
308
290
  ]
309
291
 
310
292
  window = sg.Window('small fish', layout= layout, margins= (10,10))
@@ -359,3 +341,69 @@ def ask_cancel_detection() :
359
341
  else :
360
342
  return True
361
343
 
344
+
345
+ def ask_confirmation(question_displayed : str) :
346
+ layout =[
347
+ [sg.Text(question_displayed, font= 'bold 10')],
348
+ [sg.Button("Yes"), sg.Button("No")]
349
+ ]
350
+
351
+ event, value = prompt(layout, add_ok_cancel=False, add_scrollbar=False)
352
+
353
+ if event == 'No' :
354
+ return False
355
+ else :
356
+ return True
357
+
358
+
359
+ def prompt_save_segmentation() -> 'dict[Literal["folder","filename","ext"]]':
360
+ while True :
361
+ relaunch = False
362
+ layout = path_layout(['folder'], look_for_dir= True, header= "Output parameters :")
363
+ layout += parameters_layout(["filename"], default_values= ["small_fish_segmentation"], size=25)
364
+ layout += radio_layout(['npy','npz_uncompressed', 'npz_compressed'], key= 'ext')
365
+
366
+ event,values= prompt(layout)
367
+ if event == ('Cancel') :
368
+ return None
369
+
370
+ values['filename'] = values['filename'].replace(".npy","")
371
+ values['filename'] = values['filename'].replace(".npz","")
372
+ filename = values['filename']
373
+
374
+ if not os.path.isdir(values['folder']) :
375
+ sg.popup("Incorrect folder")
376
+ relaunch = True
377
+ elif os.path.isfile(values['folder'] + filename):
378
+ if ask_replace_file(filename) :
379
+ pass
380
+ else :
381
+ relaunch = True
382
+
383
+ if not relaunch : break
384
+
385
+ return values
386
+
387
+ def prompt_load_segmentation() -> 'dict[Literal["nucleus","cytoplasm"]]':
388
+ while True :
389
+ relaunch = False
390
+ layout = path_layout(['nucleus'], look_for_dir= False, header= "Load segmentation :")
391
+ layout += path_layout(['cytoplasm'], look_for_dir= False)
392
+
393
+ event,values= prompt(layout)
394
+ if event == ('Cancel') :
395
+ return None
396
+
397
+ if not os.path.isfile(values['nucleus']) :
398
+ sg.popup("Incorrect nucleus file selected.")
399
+ relaunch = True
400
+
401
+ if not os.path.isfile(values['cytoplasm']) and values['cytoplasm'] != "" :
402
+ sg.popup("Incorrect cytoplasm file selected.")
403
+ relaunch = True
404
+
405
+
406
+ if not relaunch : break
407
+
408
+
409
+ return values