small-fish-gui 1.10.4__py3-none-any.whl → 2.0.2__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 (39) hide show
  1. small_fish_gui/README.md +54 -69
  2. small_fish_gui/__init__.py +9 -3
  3. small_fish_gui/__main__.py +1 -1
  4. small_fish_gui/batch/integrity.py +8 -1
  5. small_fish_gui/batch/output.py +16 -0
  6. small_fish_gui/batch/pipeline.py +43 -24
  7. small_fish_gui/batch/prompt.py +44 -26
  8. small_fish_gui/batch/update.py +19 -3
  9. small_fish_gui/batch/utils.py +2 -0
  10. small_fish_gui/batch/values.txt +5 -5
  11. small_fish_gui/default_values.py +51 -0
  12. small_fish_gui/gui/__init__.py +3 -1
  13. small_fish_gui/gui/_napari_widgets.py +15 -4
  14. small_fish_gui/gui/layout.py +123 -54
  15. small_fish_gui/gui/napari_visualiser.py +12 -8
  16. small_fish_gui/gui/prompts.py +61 -74
  17. small_fish_gui/gui/tooltips.py +15 -0
  18. small_fish_gui/hints.py +23 -4
  19. small_fish_gui/illustrations/DetectionVitrine_filtre.png +0 -0
  20. small_fish_gui/illustrations/DetectionVitrine_signal.png +0 -0
  21. small_fish_gui/illustrations/FocciVitrine.png +0 -0
  22. small_fish_gui/illustrations/FocciVitrine_no_spots.png +0 -0
  23. small_fish_gui/illustrations/Segmentation2D.png +0 -0
  24. small_fish_gui/illustrations/Segmentation2D_with_labels.png +0 -0
  25. small_fish_gui/logo.png +0 -0
  26. small_fish_gui/{pipeline/main.py → main_menu.py} +16 -15
  27. small_fish_gui/pipeline/_colocalisation.py +60 -41
  28. small_fish_gui/pipeline/_preprocess.py +13 -12
  29. small_fish_gui/pipeline/actions.py +102 -14
  30. small_fish_gui/pipeline/detection.py +5 -1
  31. small_fish_gui/pipeline/segmentation.py +206 -73
  32. small_fish_gui/pipeline/spots.py +129 -5
  33. small_fish_gui/pipeline/testing.ipynb +1571 -2
  34. small_fish_gui/requirements.txt +4 -4
  35. {small_fish_gui-1.10.4.dist-info → small_fish_gui-2.0.2.dist-info}/METADATA +14 -16
  36. small_fish_gui-2.0.2.dist-info/RECORD +59 -0
  37. small_fish_gui-1.10.4.dist-info/RECORD +0 -49
  38. {small_fish_gui-1.10.4.dist-info → small_fish_gui-2.0.2.dist-info}/WHEEL +0 -0
  39. {small_fish_gui-1.10.4.dist-info → small_fish_gui-2.0.2.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,15 @@
1
+
2
+ CELLPROB_TOOLTIP = """ (float) from -6. to +6.
3
+ The network predicts 3 outputs: flows in X, flows in Y, and cell “probability”.
4
+ The predictions the network makes of the probability are the inputs to a sigmoid centered at zero (1 / (1 + e^-x)), so they vary from around -6 to +6.
5
+ The pixels greater than the cellprob_threshold are used to run dynamics and determine ROIs.
6
+ The default is cellprob_threshold=0.0.
7
+ Decrease this threshold if cellpose is not returning as many ROIs as you’d expect.
8
+ Similarly, increase this threshold if cellpose is returning too ROIs particularly from dim areas.
9
+ """ #Cellpose 4.0.6 doc
10
+
11
+ FLOW_THRESHOLD_TOOLTIP = """ (float) from 0. to 1.
12
+ The flow_threshold parameter is the maximum allowed error of the flows for each mask.
13
+ Increase this threshold if cellpose is not returning as many ROIs as you’d expect.
14
+ Similarly, decrease this threshold if cellpose is returning too many ill-shaped ROIs.
15
+ """ #Cellpose 4.0.6 doc
small_fish_gui/hints.py CHANGED
@@ -9,9 +9,16 @@ class pipeline_parameters(TypedDict) :
9
9
  At run time is a regular dict instance, this class is used for keys hinting
10
10
  """
11
11
  alpha : float
12
+ anisotropy : float
12
13
  beta : float
13
14
  channel_to_compute : int
15
+ cellprob_threshold_cyto : float
16
+ cellprob_threshold_nuc : float
17
+ cytoplasm_segmentation_3D : bool
14
18
  cluster_size : int
19
+ cyto_model_name : str
20
+ cytoplasm_diameter : int
21
+ cytoplasm_channel : int
15
22
  do_cluster_computation : bool
16
23
  do_dense_regions_deconvolution : bool
17
24
  do_spots_excel : bool
@@ -19,10 +26,11 @@ class pipeline_parameters(TypedDict) :
19
26
  do_spots_csv : bool
20
27
  dim : int
21
28
  filename : str
29
+ flow_threshold_cyto : int
30
+ flow_threshold_nuc : int
22
31
  gamma : float
23
32
  image_path : str
24
33
  image : ndarray
25
- show_interactive_threshold_selector : bool
26
34
  log_kernel_size : Tuple[float,float,float]
27
35
  log_kernel_size_x : float
28
36
  log_kernel_size_y : float
@@ -34,18 +42,29 @@ class pipeline_parameters(TypedDict) :
34
42
  minimum_distance_z : float
35
43
  is_3D_stack : bool
36
44
  is_multichannel : bool
37
- show_napari_corrector : bool
38
45
  nucleus_channel_signal : int
39
- reodered_shape : Tuple[int,int,int,int,int]
46
+ nucleus_segmentation_3D : bool
47
+ nucleus_diameter : int
48
+ nucleus_model_name : str
49
+ nucleus_channel : int
50
+ other_nucleus_image : str
51
+ reordered_shape : Tuple[int,int,int,int,int]
40
52
  do_segmentation : bool
41
- segmentation_done : bool
42
53
  shape : Tuple[int,int,int,int,int]
54
+ save_segmentation_visual : bool
55
+ segmentation_done : bool
56
+ show_interactive_threshold_selector : bool
43
57
  spots_extraction_folder : str
44
58
  spots_filename : str
45
59
  spot_size : Tuple[int,int,int]
46
60
  spot_size_x : int
47
61
  spot_size_y : int
48
62
  spot_size_z : int
63
+ segment_only_nuclei : bool
64
+ cytoplasm_segmentation_3D : bool
65
+ nucleus_segmentation_3D : bool
66
+ show_napari_corrector : bool
67
+ show_segmentation : bool
49
68
  threshold : int
50
69
  threshold_penalty : int
51
70
  time_stack : None
Binary file
@@ -7,31 +7,33 @@ from small_fish_gui import __version__
7
7
  import pandas as pd
8
8
  import FreeSimpleGUI as sg
9
9
 
10
- from .actions import add_detection
11
- from . actions import save_results
12
- from . actions import compute_colocalisation
13
- from . actions import delete_acquisitions, rename_acquisitions
14
- from . actions import save_segmentation, load_segmentation, segment_cells
15
- from .actions import open_wiki
16
-
17
- from ._preprocess import clean_unused_parameters_cache
18
- from ..batch import batch_promp
19
- from ..gui import hub_prompt, prompt_restore_main_menu
20
- from ..hints import pipeline_parameters
10
+ from .pipeline.actions import add_detection
11
+ from .pipeline.actions import save_results
12
+ from .pipeline.actions import compute_colocalisation
13
+ from .pipeline.actions import delete_acquisitions, rename_acquisitions
14
+ from .pipeline.actions import save_segmentation, load_segmentation, segment_cells
15
+ from .pipeline.actions import open_wiki
16
+
17
+ from .pipeline._preprocess import clean_unused_parameters_cache
18
+ from .batch import batch_promp
19
+ from .gui import hub_prompt, prompt_restore_main_menu, default_theme
20
+ from .hints import pipeline_parameters
21
21
 
22
22
  #'Global' parameters
23
23
  user_parameters = pipeline_parameters({'segmentation_done' : False}) #TypedDict
24
24
  acquisition_id = -1
25
- result_df = pd.DataFrame(columns=['acquisition_id'])
25
+ result_df = pd.DataFrame(columns=['acquisition_id', 'name'])
26
26
  cell_result_df = pd.DataFrame(columns=['acquisition_id'])
27
27
  global_coloc_df = pd.DataFrame()
28
28
  cell_coloc_df = dict()
29
29
  cytoplasm_label = None
30
30
  nucleus_label = None
31
31
 
32
+ default_theme()
32
33
  while True : #Break this loop to close small_fish
33
34
  try :
34
35
  result_df = result_df.reset_index(drop=True)
36
+
35
37
  event, values = hub_prompt(result_df, user_parameters['segmentation_done'])
36
38
 
37
39
  if event == 'Add detection' :
@@ -71,14 +73,13 @@ while True : #Break this loop to close small_fish
71
73
  nucleus_label, cytoplasm_label, user_parameters['segmentation_done'] = load_segmentation(nucleus_label, cytoplasm_label, user_parameters['segmentation_done'])
72
74
 
73
75
  elif event == 'Compute colocalisation' :
74
- result_tables = values.setdefault('result_table', []) #Contains the lines selected by the user on the sum-up array.
75
76
 
76
- global_coloc_df, cell_coloc_df = compute_colocalisation(
77
- result_tables,
77
+ global_coloc_df, cell_coloc_df, acquisition_id = compute_colocalisation(
78
78
  result_dataframe=result_df,
79
79
  cell_result_dataframe=cell_result_df,
80
80
  global_coloc_df=global_coloc_df,
81
81
  cell_coloc_df=cell_coloc_df,
82
+ max_id=acquisition_id,
82
83
  )
83
84
 
84
85
  elif event == "Reset all" :
@@ -1,6 +1,7 @@
1
1
  from ._custom_errors import MissMatchError
2
2
  from ..gui import coloc_prompt, add_default_loading
3
3
 
4
+ import os
4
5
  import numpy as np
5
6
  import pandas as pd
6
7
  import FreeSimpleGUI as sg
@@ -116,7 +117,12 @@ def spots_multicolocalisation(spots_list, anchor_list, radius_nm, image_shape, v
116
117
 
117
118
  return res
118
119
 
119
- def spots_colocalisation(spot_list1:list, spot_list2:list, distance: float, voxel_size)-> int :
120
+ def spots_colocalisation(
121
+ spot_list1:np.ndarray,
122
+ spot_list2:np.ndarray,
123
+ distance: int,
124
+ voxel_size : tuple
125
+ )-> int :
120
126
  """
121
127
  Return number of spots from spot_list1 located closer(large) than distance to at least one spot of spot_list2.
122
128
 
@@ -133,9 +139,15 @@ def spots_colocalisation(spot_list1:list, spot_list2:list, distance: float, voxe
133
139
  if len(spot_list1) == 0 or len(spot_list2) == 0 : return np.NaN
134
140
  if len(spot_list1[0]) != len(spot_list2[0]) :
135
141
  raise MissMatchError("dimensionalities of spots 1 and spots 2 don't match.")
136
-
142
+
143
+ spot_list1 = np.array([spot for spot in spot_list1], dtype=int)
144
+ spot_list2 = np.array([spot for spot in spot_list2], dtype=int)
145
+
137
146
  shape1 = np.max(spot_list1,axis=0)
138
147
  shape2 = np.max(spot_list2,axis=0)
148
+
149
+ Z,Y,X = list(zip(*spot_list2))
150
+
139
151
  image_shape = np.max([shape1, shape2],axis=0) + 1
140
152
 
141
153
  signal2 = reconstruct_boolean_signal(image_shape, spot_list2)
@@ -152,25 +164,48 @@ def spots_colocalisation(spot_list1:list, spot_list2:list, distance: float, voxe
152
164
  return count
153
165
 
154
166
 
155
-
167
+ def initiate_colocalisation(
168
+ result_tables : pd.DataFrame,
169
+ ) :
156
170
 
171
+ result_tables = result_tables.set_index('acquisition_id', drop=False)
172
+ available_spots = dict(zip(result_tables['acquisition_id'].astype(str).str.cat(result_tables['name'],sep='-'), result_tables.index))
157
173
 
174
+ while True :
175
+ try :
176
+ colocalisation_distance, voxel_size, spots1_key, spots2_key = coloc_prompt(list(available_spots.keys()))
177
+ if colocalisation_distance is None :
178
+ return None,None, None,None
179
+ colocalisation_distance = int(colocalisation_distance)
158
180
 
159
- def initiate_colocalisation(result_tables) :
160
- if len(result_tables) != 2 :
161
- sg.popup("Please select 2 acquisitions for colocalisation (Ctrl + click in the table)")
162
- return False
163
- else :
164
- while True :
165
- colocalisation_distance = coloc_prompt()
166
- if colocalisation_distance == False : return False
167
- try :
168
- colocalisation_distance = int(colocalisation_distance)
169
- except Exception :
170
- sg.popup("Incorrect colocalisation distance")
181
+ if spots1_key in available_spots.keys() :
182
+ spots1_key = available_spots[spots1_key]
183
+ elif os.path.isfile(spots1_key) :
184
+ pass
185
+
186
+ else :
187
+ raise ValueError("Incorrect value for spots1")
188
+
189
+ if spots2_key in available_spots.keys() :
190
+ spots2_key = available_spots[spots2_key]
191
+ elif os.path.isfile(spots2_key) :
192
+ pass
171
193
  else :
172
- break
173
- return colocalisation_distance
194
+ raise ValueError("Incorrect value for spots1")
195
+
196
+ except ValueError as e :
197
+
198
+ if str(e) == "Incorrect value for spots1" :
199
+ sg.popup(str(e))
200
+
201
+ elif str(e) == "Incorrect value for spots2" :
202
+ sg.popup(str(e))
203
+
204
+ else :
205
+ sg.popup("Incorrect colocalisation distance")
206
+ else :
207
+ break
208
+ return colocalisation_distance, voxel_size, spots1_key, spots2_key
174
209
 
175
210
  def _global_coloc(acquisition_id1,acquisition_id2, result_dataframe, colocalisation_distance) :
176
211
  """
@@ -198,20 +233,12 @@ def _global_coloc(acquisition_id1,acquisition_id2, result_dataframe, colocalisat
198
233
 
199
234
  voxel_size1 = acquisition1.iloc[0].at['voxel_size']
200
235
  voxel_size2 = acquisition2.iloc[0].at['voxel_size']
201
- shape1 = acquisition1.iloc[0].at['reordered_shape']
202
- shape2 = acquisition2.iloc[0].at['reordered_shape']
203
236
 
204
237
  if voxel_size1 != voxel_size2 :
205
238
  raise MissMatchError("voxel size 1 different than voxel size 2")
206
239
  else :
207
240
  voxel_size = voxel_size1
208
241
 
209
- if shape1 != shape2 :
210
- raise MissMatchError("shape 1 different than shape 2")
211
- else :
212
- shape = shape1
213
-
214
-
215
242
  spots1 = acquisition1.iloc[0].at['spots']
216
243
  spots2 = acquisition2.iloc[0].at['spots']
217
244
 
@@ -228,7 +255,7 @@ def _global_coloc(acquisition_id1,acquisition_id2, result_dataframe, colocalisat
228
255
 
229
256
  if 'clusters' in acquisition1.columns :
230
257
  try :
231
- clusters_id_1 = acquisition1.iloc[0].at['spots_cluster_id']
258
+ clusters_id_1 = np.array(acquisition1.iloc[0].at['spots_cluster_id'], dtype=int)
232
259
  fraction_spots2_coloc_cluster1 = spots_colocalisation(spot_list1=spots2, spot_list2=spots1[clusters_id_1 != -1], distance= colocalisation_distance, voxel_size=voxel_size) / spot2_total
233
260
  except MissMatchError as e :
234
261
  sg.popup(str(e))
@@ -241,7 +268,7 @@ def _global_coloc(acquisition_id1,acquisition_id2, result_dataframe, colocalisat
241
268
 
242
269
  if 'clusters' in acquisition2.columns :
243
270
  try :
244
- clusters_id_2 = acquisition2.iloc[0].at['spots_cluster_id']
271
+ clusters_id_2 = np.array(acquisition2.iloc[0].at['spots_cluster_id'], dtype=int)
245
272
  fraction_spots1_coloc_cluster2 = spots_colocalisation(spot_list1=spots1, spot_list2=spots2[clusters_id_2 != -1], distance= colocalisation_distance, voxel_size=voxel_size) / spot1_total
246
273
  except MissMatchError as e :# clusters not computed
247
274
  sg.popup(str(e))
@@ -314,10 +341,6 @@ def _cell_coloc(
314
341
  coloc_name_forward = '{0} -> {1}'.format(acquisition_name_id1, acquisition_name_id2)
315
342
  coloc_name_backward = '{1} -> {0}'.format(acquisition_name_id1, acquisition_name_id2)
316
343
 
317
- #Getting shape
318
- if not result_dataframe.at[acquisition_id1, 'reordered_shape'] == result_dataframe.at[acquisition_id2, 'reordered_shape'] :
319
- raise ValueError("Selected acquisitions have different shapes. Most likely they don't belong to the same fov.")
320
-
321
344
  #Getting voxel_size
322
345
  if not result_dataframe.at[acquisition_id1, 'voxel_size'] == result_dataframe.at[acquisition_id2, 'voxel_size'] :
323
346
  raise ValueError("Selected acquisitions have different voxel_size. Most likely they don't belong to the same fov.")
@@ -328,9 +351,9 @@ def _cell_coloc(
328
351
 
329
352
  #Putting spots lists in 2 cols for corresponding cells
330
353
  pivot_values_columns = ['rna_coords', 'total_rna_number']
331
- if 'clusters' in acquisition2.columns or 'clusters' in acquisition1.columns :
354
+ if 'clusters' in acquisition2.columns or 'clusters' in acquisition1.columns:
332
355
  pivot_values_columns.extend(['clustered_spots_coords','clustered_spot_number'])
333
- cell_dataframe['cell_id'] = cell_dataframe['cell_id'].astype(int)
356
+ cell_dataframe.loc[:,['cell_id']] = cell_dataframe['cell_id'].astype(int)
334
357
  colocalisation_df = cell_dataframe.pivot(
335
358
  columns=['name', 'acquisition_id'],
336
359
  values= pivot_values_columns,
@@ -357,7 +380,7 @@ def _cell_coloc(
357
380
  )
358
381
  colocalisation_df[("spots_with_spots_fraction",coloc_name_backward,"backward")] = colocalisation_df[("spots_with_spots_count",coloc_name_backward,"backward")].astype(float) / colocalisation_df[('total_rna_number',acquisition_name_id2,acquisition_id2)].astype(float)
359
382
 
360
- if acquisition2['do_cluster_computation'].iat[0] :
383
+ if 'clusters' in acquisition2.columns:
361
384
  if len(acquisition2['clusters'].iat[0]) > 0 :
362
385
 
363
386
  #spots to clusters
@@ -371,7 +394,7 @@ def _cell_coloc(
371
394
  )
372
395
  colocalisation_df[("spots_with_clustered_spots_fraction",coloc_name_forward,"forward")] = colocalisation_df[("spots_with_clustered_spots_count",coloc_name_forward,"forward")].astype(float) / colocalisation_df[('total_rna_number',acquisition_name_id1,acquisition_id1)].astype(float)
373
396
 
374
- if acquisition1['do_cluster_computation'].iat[0] :
397
+ if 'clusters' in acquisition1.columns:
375
398
  if len(acquisition1['clusters'].iat[0]) > 0 :
376
399
  colocalisation_df[("spots_with_clustered_spots_count",coloc_name_backward,"backward")] = colocalisation_df.apply(
377
400
  lambda x: spots_colocalisation(
@@ -384,7 +407,7 @@ def _cell_coloc(
384
407
 
385
408
  colocalisation_df[("spots_with_clustered_spots_fraction",coloc_name_backward,"backward")] = colocalisation_df[("spots_with_clustered_spots_count",coloc_name_backward,"backward")].astype(float) / colocalisation_df[('total_rna_number',acquisition_name_id2,acquisition_id2)].astype(float)
386
409
 
387
- if acquisition2['do_cluster_computation'].iat[0] and acquisition1['do_cluster_computation'].iat[0] :
410
+ if 'clusters' in acquisition2.columns and 'clusters' in acquisition1.columns:
388
411
  if len(acquisition1['clusters'].iat[0]) > 0 and len(acquisition2['clusters'].iat[0]) > 0 :
389
412
  #clusters to clusters
390
413
  colocalisation_df[("clustered_spots_with_clustered_spots_count",coloc_name_forward,"forward")] = colocalisation_df.apply(
@@ -420,12 +443,8 @@ def _cell_coloc(
420
443
  return colocalisation_df
421
444
 
422
445
  @add_default_loading
423
- def launch_colocalisation(result_tables, result_dataframe, cell_result_dataframe, colocalisation_distance, global_coloc_df, cell_coloc_df: dict) :
446
+ def launch_colocalisation(acquisition_id1, acquisition_id2, result_dataframe, cell_result_dataframe, colocalisation_distance, global_coloc_df, cell_coloc_df: dict) :
424
447
 
425
- acquisition1 = result_dataframe.iloc[result_tables[0]]
426
- acquisition2 = result_dataframe.iloc[result_tables[1]]
427
-
428
- acquisition_id1, acquisition_id2 = (acquisition1.at['acquisition_id'], acquisition2.at['acquisition_id'])
429
448
 
430
449
  if acquisition_id1 in list(cell_result_dataframe['acquisition_id']) and acquisition_id2 in list(cell_result_dataframe['acquisition_id']) :
431
450
  print("Launching cell to cell colocalisation.")
@@ -4,6 +4,8 @@ import FreeSimpleGUI as sg
4
4
  from ..gui import _error_popup, _warning_popup, parameters_layout, add_header
5
5
  from ..gui.prompts import input_image_prompt, prompt
6
6
 
7
+ import small_fish_gui.default_values as default
8
+
7
9
  class ParameterInputError(Exception) :
8
10
  """
9
11
  Raised when user inputs an incorrect parameter.
@@ -314,19 +316,19 @@ def _check_segmentation_parameters(
314
316
  ) :
315
317
 
316
318
  available_channels = list(range(len(shape)))
317
- do_only_nuc = user_parameters['Segment only nuclei']
319
+ do_only_nuc = user_parameters['segment_only_nuclei']
318
320
  cyto_model_name = user_parameters['cyto_model_name']
319
- cyto_size = user_parameters['cytoplasm diameter']
320
- cytoplasm_channel = user_parameters['cytoplasm channel']
321
+ cyto_size = user_parameters['cytoplasm_diameter']
322
+ cytoplasm_channel = user_parameters['cytoplasm_channel']
321
323
  nucleus_model_name = user_parameters['nucleus_model_name']
322
- nucleus_size = user_parameters['nucleus diameter']
323
- nucleus_channel = user_parameters['nucleus channel']
324
+ nucleus_size = user_parameters['nucleus_diameter']
325
+ nucleus_channel = user_parameters['nucleus_channel']
324
326
 
325
327
 
326
328
  if type(cyto_model_name) != str and not do_only_nuc:
327
329
  raise ParameterInputError('Invalid cytoplasm model name.')
328
330
  if cytoplasm_channel not in available_channels and not do_only_nuc and is_multichannel:
329
- raise ParameterInputError('For given input image please select channel in {0}\ncytoplasm channel : {1}'.format(available_channels, cytoplasm_channel))
331
+ raise ParameterInputError('For given input image please select channel in {0}\ncytoplasm_channel : {1}'.format(available_channels, cytoplasm_channel))
330
332
 
331
333
  if type(cyto_size) not in [int, float] and not do_only_nuc:
332
334
  raise ParameterInputError("Incorrect cytoplasm size.")
@@ -361,12 +363,11 @@ def ask_input_parameters(ask_for_segmentation=True) :
361
363
  values = {}
362
364
  image_input_values = {}
363
365
  while True :
364
- is_3D_preset = image_input_values.setdefault('is_3D_stack', False)
365
- is_time_preset = image_input_values.setdefault('time stack', False)
366
- is_multichannel_preset = image_input_values.setdefault('is_multichannel', False)
367
- denseregion_preset = image_input_values.setdefault('do_dense_regions_deconvolution', False)
368
- do_clustering_preset = image_input_values.setdefault('do_cluster_computation', False)
369
- do_napari_preset = image_input_values.setdefault('show_napari_corrector', False)
366
+ is_3D_preset = image_input_values.setdefault('is_3D_stack', default.IS_3D_STACK)
367
+ is_multichannel_preset = image_input_values.setdefault('is_multichannel', default.IS_MULTICHANNEL)
368
+ denseregion_preset = image_input_values.setdefault('do_dense_regions_deconvolution', default.DO_DENSE_REGIONS_DECONVOLUTION)
369
+ do_clustering_preset = image_input_values.setdefault('do_cluster_computation', default.DO_CLUSTER_COMPUTATION)
370
+ do_napari_preset = image_input_values.setdefault('show_napari_corrector', default.SHOW_NAPARI_CORRECTOR)
370
371
 
371
372
  if ask_for_segmentation :
372
373
  image_input_values = input_image_prompt(
@@ -17,6 +17,7 @@ from ._preprocess import ask_input_parameters
17
17
  from .detection import initiate_detection, launch_detection, launch_features_computation
18
18
  from .detection import get_nucleus_signal
19
19
  from .spots import launch_spots_extraction
20
+ from .spots import load_spots, reconstruct_acquisition_data, reconstruct_cell_data
20
21
 
21
22
  from .segmentation import launch_segmentation
22
23
  from ._colocalisation import initiate_colocalisation, launch_colocalisation
@@ -115,7 +116,7 @@ def add_detection(user_parameters : pipeline_parameters, acquisition_id, cytopla
115
116
 
116
117
  if user_parameters['spots_extraction_folder'] != '' and type(user_parameters['spots_extraction_folder']) != type(None) :
117
118
  if user_parameters['spots_filename'] != '' and type(user_parameters['spots_filename']) != type(None) :
118
- if any((user_parameters['do_spots_excel'], user_parameters['do_spots_csv'], user_parameters['do_spots_feather'])) :
119
+ if any([user_parameters['do_spots_excel'], user_parameters['do_spots_csv']]) :
119
120
  launch_spots_extraction(
120
121
  acquisition_id=acquisition_id,
121
122
  user_parameters=user_parameters,
@@ -242,9 +243,11 @@ def save_results(
242
243
  global_coloc_df : pd.DataFrame,
243
244
  cell_coloc_df : dict, #TODO : Rename to cell_coloc_dict
244
245
  ) :
245
- if len(result_df) != 0 :
246
+ if len(result_df) != 0 :
246
247
  dic = output_image_prompt(filename=result_df.iloc[0].at['filename'])
247
248
 
249
+ if dic is None : return None
250
+
248
251
  if isinstance(dic, dict) :
249
252
  path = dic['folder']
250
253
  filename = dic['filename']
@@ -260,26 +263,111 @@ def save_results(
260
263
  sucess4 = write_list_of_results(cell_coloc_df.values(), path= path, filename=filename + 'cell2cell_coloc_result', do_excel= do_excel, do_feather= do_feather, do_csv=do_csv)
261
264
  if all([sucess1,sucess2, sucess3, sucess4,]) : sg.popup("Sucessfully saved at {0}.".format(path))
262
265
 
266
+ elif len(global_coloc_df) !=0 or len(cell_coloc_df) !=0 :
267
+ dic = output_image_prompt(filename="loaded_spots_coloc")
268
+ if dic is None : return None
269
+ if isinstance(dic, dict) :
270
+ path = dic['folder']
271
+ filename = dic['filename']
272
+ do_excel = dic['Excel']
273
+ do_feather = dic['Feather']
274
+ do_csv = dic['csv']
275
+
276
+ if 'rna_coords' in cell_result_df.columns : cell_result_df = cell_result_df.drop(columns='rna_coords')
277
+
278
+ sucess3 = write_results(global_coloc_df, path= path, filename=filename + 'global_coloc_result', do_excel= do_excel, do_feather= do_feather, do_csv=do_csv)
279
+ sucess4 = write_list_of_results(cell_coloc_df.values(), path= path, filename=filename + 'cell2cell_coloc_result', do_excel= do_excel, do_feather= do_feather, do_csv=do_csv)
280
+ if all([sucess3, sucess4,]) : sg.popup("Sucessfully saved at {0}.".format(path))
281
+
282
+
263
283
  else :
264
284
  dic = None
265
285
  sg.popup('No results to save.')
266
286
 
267
- def compute_colocalisation(result_tables, result_dataframe, cell_result_dataframe, global_coloc_df, cell_coloc_df) :
268
- colocalisation_distance = initiate_colocalisation(result_tables)
287
+ def compute_colocalisation(
288
+ result_dataframe,
289
+ cell_result_dataframe,
290
+ global_coloc_df,
291
+ cell_coloc_df,
292
+ max_id,
293
+ ) :
294
+
295
+ colocalisation_distance, voxel_size, spots1_key, spots2_key = initiate_colocalisation(result_dataframe)
296
+ if colocalisation_distance is None :
297
+ return global_coloc_df, cell_coloc_df, max_id
298
+
299
+ if os.path.isfile(spots1_key) :
300
+ Spots1 = load_spots(spots1_key)
301
+ fake_acquisition = reconstruct_acquisition_data(
302
+ Spots=Spots1,
303
+ max_id=max_id,
304
+ filename= os.path.basename(spots1_key),
305
+ voxel_size = voxel_size
306
+ )
307
+ result_dataframe = pd.concat([
308
+ result_dataframe,
309
+ fake_acquisition
310
+ ], axis=0)
311
+
312
+ if not Spots1['cell_label'].isna().all() :
313
+ fake_cells = reconstruct_cell_data(
314
+ Spots=Spots1,
315
+ max_id=max_id,
316
+ )
317
+
318
+ cell_result_dataframe = pd.concat([
319
+ cell_result_dataframe,
320
+ fake_cells
321
+ ], axis=0)
322
+
323
+ max_id +=1
324
+ acquisition_id1 = fake_acquisition.iloc[0].at['acquisition_id']
269
325
 
270
- if colocalisation_distance == False :
271
- pass
272
326
  else :
273
- global_coloc_df, cell_coloc_df = launch_colocalisation(
274
- result_tables,
275
- result_dataframe=result_dataframe,
276
- cell_result_dataframe=cell_result_dataframe,
277
- colocalisation_distance=colocalisation_distance,
278
- global_coloc_df=global_coloc_df,
279
- cell_coloc_df=cell_coloc_df,
327
+ acquisition_id1 = spots1_key
328
+
329
+ if os.path.isfile(spots2_key) :
330
+ Spots2 = load_spots(spots2_key)
331
+ fake_acquisition = reconstruct_acquisition_data(
332
+ Spots=Spots2,
333
+ max_id=max_id,
334
+ filename= os.path.basename(spots2_key),
335
+ voxel_size = voxel_size
336
+ )
337
+ result_dataframe = pd.concat([
338
+ result_dataframe,
339
+ fake_acquisition
340
+ ], axis=0)
341
+
342
+ if not Spots2['cell_label'].isna().all() :
343
+ fake_cells = reconstruct_cell_data(
344
+ Spots=Spots2,
345
+ max_id=max_id,
280
346
  )
281
347
 
282
- return global_coloc_df, cell_coloc_df
348
+ cell_result_dataframe = pd.concat([
349
+ cell_result_dataframe,
350
+ fake_cells
351
+ ], axis=0)
352
+
353
+ max_id +=1
354
+ acquisition_id2 = fake_acquisition.iloc[0].at['acquisition_id']
355
+
356
+ else :
357
+ acquisition_id2 = spots2_key
358
+
359
+
360
+ global_coloc_df, cell_coloc_df = launch_colocalisation(
361
+ acquisition_id1 = acquisition_id1,
362
+ acquisition_id2 = acquisition_id2,
363
+ result_dataframe=result_dataframe,
364
+ cell_result_dataframe=cell_result_dataframe,
365
+ colocalisation_distance=colocalisation_distance,
366
+ global_coloc_df=global_coloc_df,
367
+ cell_coloc_df=cell_coloc_df,
368
+ )
369
+
370
+ return global_coloc_df, cell_coloc_df, max_id
283
371
 
284
372
  def delete_acquisitions(selected_acquisitions : pd.DataFrame,
285
373
  result_df : pd.DataFrame,
@@ -443,7 +443,11 @@ def launch_cell_extraction(
443
443
  image = stack.maximum_projection(image)
444
444
  if nucleus_signal.ndim == 3 :
445
445
  nucleus_signal = stack.maximum_projection(nucleus_signal)
446
-
446
+ if cell_label.ndim == 3 :
447
+ cell_label = stack.maximum_projection(nucleus_signal)
448
+ if nucleus_label.ndim == 3 :
449
+ nucleus_label = stack.maximum_projection(nucleus_signal)
450
+
447
451
  cells_results = multistack.extract_cell(
448
452
  cell_label=cell_label,
449
453
  ndim=dim,