small-fish-gui 1.0.4__py3-none-any.whl → 1.2.0__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 +15 -2
- small_fish_gui/__init__.py +1 -1
- small_fish_gui/__main__.py +16 -2
- small_fish_gui/gui/help_module.py +1 -1
- small_fish_gui/gui/layout.py +3 -3
- small_fish_gui/gui/prompts.py +5 -3
- small_fish_gui/pipeline/_colocalisation.py +7 -7
- small_fish_gui/pipeline/_preprocess.py +13 -1
- small_fish_gui/pipeline/_segmentation.py +7 -2
- small_fish_gui/pipeline/actions.py +35 -2
- small_fish_gui/pipeline/detection.py +60 -11
- small_fish_gui/pipeline/main.py +9 -3
- {small_fish_gui-1.0.4.dist-info → small_fish_gui-1.2.0.dist-info}/METADATA +1 -1
- {small_fish_gui-1.0.4.dist-info → small_fish_gui-1.2.0.dist-info}/RECORD +16 -16
- {small_fish_gui-1.0.4.dist-info → small_fish_gui-1.2.0.dist-info}/WHEEL +0 -0
- {small_fish_gui-1.0.4.dist-info → small_fish_gui-1.2.0.dist-info}/licenses/LICENSE +0 -0
small_fish_gui/README.md
CHANGED
|
@@ -1,19 +1,27 @@
|
|
|
1
1
|
# Small Fish
|
|
2
2
|
**Small Fish** is a python application for the analysis of smFish images. It provides a ready to use graphical interface to combine famous python packages for cell analysis without any need for coding.
|
|
3
3
|
|
|
4
|
-
Cell segmentation is peformed using *cellpose* (published work) : https://github.com/MouseLand/cellpose
|
|
4
|
+
Cell segmentation (**2D**) is peformed using *cellpose* (published work) : https://github.com/MouseLand/cellpose; compatible with your own cellpose models.
|
|
5
5
|
|
|
6
6
|
Spot detection is performed via *big-fish* (published work) : https://github.com/fish-quant/big-fish
|
|
7
7
|
|
|
8
8
|
Time stacks are not yet supported.
|
|
9
9
|
|
|
10
|
+
## What can you do with small fish ?
|
|
11
|
+
|
|
12
|
+
- Single molecule quantification (including a lot of spatial features)
|
|
13
|
+
- Foci/Transcription site quantification
|
|
14
|
+
- Nuclear signal quantification
|
|
15
|
+
- Signal to noise analysis
|
|
16
|
+
- multichannel colocalisation
|
|
17
|
+
|
|
10
18
|
## Installation
|
|
11
19
|
|
|
12
20
|
It is higly recommanded to create a specific [conda](https://docs.conda.io/projects/conda/en/latest/user-guide/tasks/manage-environments.html) or [virtual](https://docs.python.org/3.6/library/venv.html) environnement to install small fish.
|
|
13
21
|
|
|
14
22
|
```bash
|
|
15
23
|
conda create -n small_fish python=3.8
|
|
16
|
-
activate small_fish
|
|
24
|
+
conda activate small_fish
|
|
17
25
|
```
|
|
18
26
|
Then download the small_fish package :
|
|
19
27
|
```bash
|
|
@@ -35,6 +43,11 @@ Then launch Small fish :
|
|
|
35
43
|
```bash
|
|
36
44
|
python -m small_fish_gui
|
|
37
45
|
```
|
|
46
|
+
|
|
47
|
+
## Cellpose configuration
|
|
48
|
+
|
|
49
|
+
If you want to train your own cellpose model or set-up your GPU you can follow the official cellpose documentation, just remember to **first activate your small_fish environnement**.
|
|
50
|
+
|
|
38
51
|
## Developpement
|
|
39
52
|
|
|
40
53
|
Optional features to include in future versions :
|
small_fish_gui/__init__.py
CHANGED
small_fish_gui/__main__.py
CHANGED
|
@@ -1,12 +1,26 @@
|
|
|
1
|
-
import sys
|
|
2
|
-
import os
|
|
1
|
+
import sys, subprocess
|
|
3
2
|
import PySimpleGUI as sg
|
|
4
3
|
|
|
5
4
|
def main():
|
|
6
5
|
import small_fish_gui.pipeline.main
|
|
7
6
|
|
|
7
|
+
def is_last_version() :
|
|
8
|
+
latest_version = str(subprocess.run([sys.executable, '-m', 'pip', 'install', '{}==random'.format('small_fish_gui')], capture_output=True, text=True))
|
|
9
|
+
latest_version = latest_version[latest_version.find('(from versions:')+15:]
|
|
10
|
+
latest_version = latest_version[:latest_version.find(')')]
|
|
11
|
+
latest_version = latest_version.replace(' ','').split(',')[-1]
|
|
12
|
+
|
|
13
|
+
current_version = str(subprocess.run([sys.executable, '-m', 'pip', 'show', '{}'.format('small_fish_gui')], capture_output=True, text=True))
|
|
14
|
+
current_version = current_version[current_version.find('Version:')+8:]
|
|
15
|
+
current_version = current_version[:current_version.find('\\n')].replace(' ','')
|
|
16
|
+
|
|
17
|
+
return current_version == latest_version
|
|
8
18
|
|
|
9
19
|
if __name__ == "__main__":
|
|
20
|
+
|
|
21
|
+
if not is_last_version() :
|
|
22
|
+
print("A new version of Small Fish is available. To update close small fish and type :\npip install --upgrade small_fish_gui")
|
|
23
|
+
|
|
10
24
|
try :
|
|
11
25
|
sys.exit(main())
|
|
12
26
|
except Exception as error :
|
|
@@ -227,7 +227,7 @@ def _mapping_help() :
|
|
|
227
227
|
This window present the shape of your image : example (1080,1080,4)
|
|
228
228
|
1080x1080 are the xy dimension (pixel resolution); and 4 is the number of channel. Another example a 3D multichannel
|
|
229
229
|
stack could be (18,4,1080,1080)...
|
|
230
|
-
The machine understand the order of the information such as (1080,1080,4) positions are (0,1,2).
|
|
230
|
+
The machine understand the order of the information such as (1080,1080,4) positions are (0,1,2). It starts from zero!
|
|
231
231
|
The mapping purpose is to link the position to the type of informations, in this case we want :
|
|
232
232
|
|
|
233
233
|
x : 1
|
small_fish_gui/gui/layout.py
CHANGED
|
@@ -151,7 +151,7 @@ def radio_layout(values, header=None) :
|
|
|
151
151
|
layout = add_header(header, layout=layout)
|
|
152
152
|
return layout
|
|
153
153
|
|
|
154
|
-
def _segmentation_layout(cytoplasm_model_preset= 'cyto2', nucleus_model_preset= 'nuclei', cytoplasm_channel_preset=0, nucleus_channel_preset=0, cyto_diameter_preset=30, nucleus_diameter_preset= 30, show_segmentation_preset= False, segment_only_nuclei_preset=False, saving_path_preset=os.getcwd(), filename_preset='cell_segmentation.png') :
|
|
154
|
+
def _segmentation_layout(multichannel, cytoplasm_model_preset= 'cyto2', nucleus_model_preset= 'nuclei', cytoplasm_channel_preset=0, nucleus_channel_preset=0, cyto_diameter_preset=30, nucleus_diameter_preset= 30, show_segmentation_preset= False, segment_only_nuclei_preset=False, saving_path_preset=os.getcwd(), filename_preset='cell_segmentation.png',) :
|
|
155
155
|
|
|
156
156
|
USE_GPU = use_gpu()
|
|
157
157
|
|
|
@@ -165,14 +165,14 @@ def _segmentation_layout(cytoplasm_model_preset= 'cyto2', nucleus_model_preset=
|
|
|
165
165
|
layout += [add_header("Cell Segmentation", [sg.Text("Choose cellpose model for cytoplasm: \n")]),
|
|
166
166
|
[combo_layout(models_list, key='cyto_model_name', default_value= cytoplasm_model_preset)]
|
|
167
167
|
]
|
|
168
|
-
layout += [parameters_layout(['cytoplasm channel'],default_values= [cytoplasm_channel_preset])]
|
|
168
|
+
if multichannel : layout += [parameters_layout(['cytoplasm channel'],default_values= [cytoplasm_channel_preset])]
|
|
169
169
|
layout += [parameters_layout(['cytoplasm diameter'], unit= "px", default_values= [cyto_diameter_preset])]
|
|
170
170
|
#Nucleus parameters
|
|
171
171
|
layout += [
|
|
172
172
|
add_header("Nucleus segmentation",[sg.Text("Choose cellpose model for nucleus: \n")]),
|
|
173
173
|
combo_layout(models_list, key='nucleus_model_name', default_value= nucleus_model_preset)
|
|
174
174
|
]
|
|
175
|
-
layout += [parameters_layout(['nucleus channel'], default_values= [nucleus_channel_preset])]
|
|
175
|
+
if multichannel : layout += [parameters_layout(['nucleus channel'], default_values= [nucleus_channel_preset])]
|
|
176
176
|
layout += [parameters_layout([ 'nucleus diameter'],unit= "px", default_values= [nucleus_diameter_preset])]
|
|
177
177
|
layout += [bool_layout(["Segment only nuclei"], preset=segment_only_nuclei_preset)]
|
|
178
178
|
|
small_fish_gui/gui/prompts.py
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import PySimpleGUI as sg
|
|
2
2
|
import pandas as pd
|
|
3
3
|
import os
|
|
4
|
+
import numpy as np
|
|
4
5
|
from .layout import path_layout, parameters_layout, bool_layout, tuple_layout, combo_layout, add_header
|
|
5
6
|
from ..interface import open_image, check_format, FormatError
|
|
6
7
|
from .help_module import ask_help
|
|
@@ -266,6 +267,7 @@ def _warning_popup(warning:str) :
|
|
|
266
267
|
def _sumup_df(results: pd.DataFrame) :
|
|
267
268
|
|
|
268
269
|
if len(results) > 0 :
|
|
270
|
+
if 'channel to compute' not in results : results['channel to compute'] = np.NaN
|
|
269
271
|
res = results.loc[:,['acquisition_id', 'spot_number', 'cell_number', 'filename', 'channel to compute']]
|
|
270
272
|
else :
|
|
271
273
|
res = pd.DataFrame(columns= ['acquisition_id', 'spot_number', 'cell_number', 'filename', 'channel to compute'])
|
|
@@ -284,9 +286,9 @@ def hub_prompt(fov_results, do_segmentation=False) :
|
|
|
284
286
|
layout = [
|
|
285
287
|
[sg.Text('RESULTS', font= 'bold 13')],
|
|
286
288
|
[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],
|
|
287
|
-
[sg.Button('Add detection'), sg.Button('Compute colocalisation')
|
|
288
|
-
|
|
289
|
-
[sg.Button('Save results', button_color= 'green'), sg.Button('Reset results',button_color= 'gray')]
|
|
289
|
+
[sg.Button('Add detection'), sg.Button('Compute colocalisation')],#, sg.Button('Batch detection')],
|
|
290
|
+
[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')]
|
|
291
|
+
# [sg.Button('Save results', button_color= 'green'), sg.Button('Reset results',button_color= 'gray')]
|
|
290
292
|
]
|
|
291
293
|
|
|
292
294
|
window = sg.Window('small fish', layout= layout, margins= (10,10))
|
|
@@ -204,13 +204,9 @@ def launch_colocalisation(result_tables, result_dataframe, colocalisation_distan
|
|
|
204
204
|
voxel_size = voxel_size1
|
|
205
205
|
|
|
206
206
|
if shape1 != shape2 :
|
|
207
|
-
print(shape1)
|
|
208
|
-
print(shape2)
|
|
209
207
|
raise MissMatchError("shape 1 different than shape 2")
|
|
210
208
|
else :
|
|
211
209
|
shape = shape1
|
|
212
|
-
print(shape1)
|
|
213
|
-
print(shape2)
|
|
214
210
|
|
|
215
211
|
acquisition_couple = (acquisition1.at['acquisition_id'], acquisition2.at['acquisition_id'])
|
|
216
212
|
|
|
@@ -235,6 +231,9 @@ def launch_colocalisation(result_tables, result_dataframe, colocalisation_distan
|
|
|
235
231
|
except MissMatchError as e :
|
|
236
232
|
sg.popup(str(e))
|
|
237
233
|
fraction_spots2_coloc_cluster1 = np.NaN
|
|
234
|
+
except TypeError : # Clusters not computed
|
|
235
|
+
fraction_spots2_coloc_cluster1 = np.NaN
|
|
236
|
+
|
|
238
237
|
|
|
239
238
|
else : fraction_spots2_coloc_cluster1 = np.NaN
|
|
240
239
|
|
|
@@ -242,9 +241,12 @@ def launch_colocalisation(result_tables, result_dataframe, colocalisation_distan
|
|
|
242
241
|
try :
|
|
243
242
|
clusters2 = acquisition2['clusters'][:,:len(voxel_size)]
|
|
244
243
|
fraction_spots1_coloc_cluster2 = spots_colocalisation(image_shape=shape, spot_list1=spots1, spot_list2=clusters2, distance= colocalisation_distance, voxel_size=voxel_size) / spot1_total
|
|
245
|
-
except MissMatchError as e
|
|
244
|
+
except MissMatchError as e :# Clusters not computed
|
|
246
245
|
sg.popup(str(e))
|
|
247
246
|
fraction_spots1_coloc_cluster2 = np.NaN
|
|
247
|
+
except TypeError :
|
|
248
|
+
fraction_spots1_coloc_cluster2 = np.NaN
|
|
249
|
+
|
|
248
250
|
|
|
249
251
|
else : fraction_spots1_coloc_cluster2 = np.NaN
|
|
250
252
|
|
|
@@ -261,6 +263,4 @@ def launch_colocalisation(result_tables, result_dataframe, colocalisation_distan
|
|
|
261
263
|
'fraction_spots1_coloc_cluster2' : [fraction_spots1_coloc_cluster2],
|
|
262
264
|
})
|
|
263
265
|
|
|
264
|
-
print(coloc_df.loc[:,['fraction_spots1_coloc_spots2','fraction_spots2_coloc_spots1', 'fraction_spots2_coloc_cluster1', 'fraction_spots1_coloc_cluster2']])
|
|
265
|
-
|
|
266
266
|
return coloc_df
|
|
@@ -269,4 +269,16 @@ def reorder_shape(shape, map) :
|
|
|
269
269
|
np.array(shape)[source]
|
|
270
270
|
)
|
|
271
271
|
|
|
272
|
-
return new_shape
|
|
272
|
+
return new_shape
|
|
273
|
+
|
|
274
|
+
def clean_unused_parameters_cache(user_parameters: dict) :
|
|
275
|
+
"""
|
|
276
|
+
Clean unused parameters that were set to None in previous run.
|
|
277
|
+
"""
|
|
278
|
+
parameters = ['alpha', 'beta', 'gamma', 'cluster size', 'min number of spots']
|
|
279
|
+
for parameter in parameters :
|
|
280
|
+
if parameter in user_parameters.keys() :
|
|
281
|
+
if type(user_parameters[parameter]) == type(None) :
|
|
282
|
+
del user_parameters[parameter]
|
|
283
|
+
|
|
284
|
+
return user_parameters
|
|
@@ -31,7 +31,7 @@ def launch_segmentation(image: np.ndarray, user_parameters: dict) :
|
|
|
31
31
|
|
|
32
32
|
while True : # Loop if show_segmentation
|
|
33
33
|
#Default parameters
|
|
34
|
-
cyto_model_name = user_parameters.setdefault('cyto_model_name', '
|
|
34
|
+
cyto_model_name = user_parameters.setdefault('cyto_model_name', 'cyto3')
|
|
35
35
|
cyto_size = user_parameters.setdefault('cytoplasm diameter', 180)
|
|
36
36
|
cytoplasm_channel = user_parameters.setdefault('cytoplasm channel', 0)
|
|
37
37
|
nucleus_model_name = user_parameters.setdefault('nucleus_model_name', 'nuclei')
|
|
@@ -42,6 +42,7 @@ def launch_segmentation(image: np.ndarray, user_parameters: dict) :
|
|
|
42
42
|
segment_only_nuclei = user_parameters.setdefault('Segment only nuclei', False)
|
|
43
43
|
filename = user_parameters['filename']
|
|
44
44
|
available_channels = list(range(image.shape[0]))
|
|
45
|
+
multichannel = user_parameters.get('multichannel')
|
|
45
46
|
|
|
46
47
|
|
|
47
48
|
#Ask user for parameters
|
|
@@ -58,6 +59,7 @@ def launch_segmentation(image: np.ndarray, user_parameters: dict) :
|
|
|
58
59
|
show_segmentation_preset=show_segmentation,
|
|
59
60
|
segment_only_nuclei_preset=segment_only_nuclei,
|
|
60
61
|
filename_preset=filename,
|
|
62
|
+
multichannel=multichannel,
|
|
61
63
|
)
|
|
62
64
|
|
|
63
65
|
event, values = prompt_with_help(layout, help='segmentation')
|
|
@@ -236,7 +238,10 @@ def _segmentate_object(im, model_name, object_size_px, channels = [0,0]) :
|
|
|
236
238
|
|
|
237
239
|
return label
|
|
238
240
|
|
|
239
|
-
def _cast_segmentation_parameters(values) :
|
|
241
|
+
def _cast_segmentation_parameters(values:dict) :
|
|
242
|
+
|
|
243
|
+
values.setdefault('cytoplasm channel',0)
|
|
244
|
+
values.setdefault('nucleus channel',0)
|
|
240
245
|
|
|
241
246
|
if values['cyto_model_name'] == '' :
|
|
242
247
|
values['cyto_model_name'] = None
|
|
@@ -31,7 +31,8 @@ def add_detection(user_parameters, segmentation_done, acquisition_id, cytoplasm_
|
|
|
31
31
|
if user_parameters['Segmentation'] and not segmentation_done:
|
|
32
32
|
im_seg = reorder_image_stack(map, user_parameters)
|
|
33
33
|
cytoplasm_label, nucleus_label, user_parameters = launch_segmentation(im_seg, user_parameters=user_parameters)
|
|
34
|
-
|
|
34
|
+
elif segmentation_done :
|
|
35
|
+
pass
|
|
35
36
|
else :
|
|
36
37
|
cytoplasm_label, nucleus_label = None,None
|
|
37
38
|
|
|
@@ -124,4 +125,36 @@ def compute_colocalisation(result_tables, result_dataframe) :
|
|
|
124
125
|
else :
|
|
125
126
|
res_coloc = launch_colocalisation(result_tables, result_dataframe=result_dataframe, colocalisation_distance=colocalisation_distance)
|
|
126
127
|
|
|
127
|
-
return res_coloc
|
|
128
|
+
return res_coloc
|
|
129
|
+
|
|
130
|
+
def delete_acquisitions(selected_acquisitions : pd.DataFrame,
|
|
131
|
+
result_df : pd.DataFrame,
|
|
132
|
+
cell_result_df : pd.DataFrame,
|
|
133
|
+
coloc_df : pd.DataFrame
|
|
134
|
+
) :
|
|
135
|
+
|
|
136
|
+
if len(result_df) == 0 :
|
|
137
|
+
sg.popup("No acquisition to delete.")
|
|
138
|
+
return result_df, cell_result_df, coloc_df
|
|
139
|
+
|
|
140
|
+
if len(selected_acquisitions) == 0 :
|
|
141
|
+
sg.popup("Please select the acquisitions you would like to delete.")
|
|
142
|
+
else :
|
|
143
|
+
acquisition_ids = list(result_df.iloc[list(selected_acquisitions)]['acquisition_id'])
|
|
144
|
+
print("Acquisitions to delete : ", acquisition_ids)
|
|
145
|
+
result_drop_idx = result_df[result_df['acquisition_id'].isin(acquisition_ids)].index
|
|
146
|
+
print("{0} acquisitions to delete.".format(len(result_drop_idx)))
|
|
147
|
+
|
|
148
|
+
if len(cell_result_df) > 0 :
|
|
149
|
+
cell_result_df_drop_idx = cell_result_df[cell_result_df['acquisition_id'].isin(acquisition_ids)].index
|
|
150
|
+
print("{0} cells to delete.".format(len(cell_result_df_drop_idx)))
|
|
151
|
+
cell_result_df = cell_result_df.drop(cell_result_df_drop_idx, axis=0)
|
|
152
|
+
|
|
153
|
+
if len(coloc_df) > 0 :
|
|
154
|
+
coloc_df_drop_idx = coloc_df[(coloc_df["acquisition_id_1"].isin(acquisition_ids)) | (coloc_df['acquisition_id_2'].isin(acquisition_ids))].index
|
|
155
|
+
print("{0} coloc measurement to delete.".format(len(coloc_df_drop_idx)))
|
|
156
|
+
coloc_df = coloc_df.drop(coloc_df_drop_idx, axis=0)
|
|
157
|
+
|
|
158
|
+
result_df = result_df.drop(result_drop_idx, axis=0)
|
|
159
|
+
|
|
160
|
+
return result_df, cell_result_df, coloc_df
|
|
@@ -357,15 +357,17 @@ def launch_post_detection(image, spots, image_input_values: dict,) :
|
|
|
357
357
|
#features
|
|
358
358
|
fov_res['spot_number'] = len(spots)
|
|
359
359
|
snr_res = compute_snr_spots(image, spots, voxel_size, spot_size)
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
Z,Y,X = list(zip(*spots))
|
|
363
|
-
spots_values = image[Z,Y,X]
|
|
360
|
+
if len(spots) == 0 :
|
|
361
|
+
fov_res['spotsSignal_median'], fov_res['spotsSignal_mean'], fov_res['spotsSignal_std'] = np.NaN, np.NaN, np.NaN
|
|
364
362
|
else :
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
363
|
+
if dim == 3 :
|
|
364
|
+
Z,Y,X = list(zip(*spots))
|
|
365
|
+
spots_values = image[Z,Y,X]
|
|
366
|
+
else :
|
|
367
|
+
Y,X = list(zip(*spots))
|
|
368
|
+
spots_values = image[Y,X]
|
|
369
|
+
fov_res['spotsSignal_median'], fov_res['spotsSignal_mean'], fov_res['spotsSignal_std'] = np.median(spots_values), np.mean(spots_values), np.std(spots_values)
|
|
370
|
+
|
|
369
371
|
fov_res['median_pixel'] = np.median(image)
|
|
370
372
|
fov_res['mean_pixel'] = np.mean(image)
|
|
371
373
|
|
|
@@ -374,6 +376,38 @@ def launch_post_detection(image, spots, image_input_values: dict,) :
|
|
|
374
376
|
|
|
375
377
|
return spots, fov_res
|
|
376
378
|
|
|
379
|
+
def _compute_cell_snr(image: np.ndarray, bbox, spots, voxel_size, spot_size) :
|
|
380
|
+
|
|
381
|
+
min_y, min_x, max_y, max_x = bbox
|
|
382
|
+
image= image[min_y: max_y, min_x: max_x]
|
|
383
|
+
|
|
384
|
+
if len(spots) == 0 :
|
|
385
|
+
res = {
|
|
386
|
+
'snr_mean' : np.NaN,
|
|
387
|
+
'snr_median' : np.NaN,
|
|
388
|
+
'snr_std' : np.NaN,
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
return res
|
|
392
|
+
|
|
393
|
+
if len(spots[0]) == 3 :
|
|
394
|
+
Z,Y,X = zip(*spots)
|
|
395
|
+
spots = np.array(
|
|
396
|
+
list(zip(Y,X)),
|
|
397
|
+
dtype= int
|
|
398
|
+
)
|
|
399
|
+
voxel_size = voxel_size[1:]
|
|
400
|
+
spot_size = spot_size[1:]
|
|
401
|
+
|
|
402
|
+
snr_dict = compute_snr_spots(
|
|
403
|
+
image= image,
|
|
404
|
+
spots= spots,
|
|
405
|
+
spot_radius= spot_size,
|
|
406
|
+
voxel_size=voxel_size
|
|
407
|
+
)
|
|
408
|
+
|
|
409
|
+
return snr_dict
|
|
410
|
+
|
|
377
411
|
@add_default_loading
|
|
378
412
|
def launch_cell_extraction(acquisition_id, spots, clusters, image, nucleus_signal, cell_label, nucleus_label, user_parameters) :
|
|
379
413
|
|
|
@@ -414,6 +448,7 @@ def launch_cell_extraction(acquisition_id, spots, clusters, image, nucleus_signa
|
|
|
414
448
|
|
|
415
449
|
#Nucleus features : area is computed in bigfish
|
|
416
450
|
features_names += ['nucleus_mean_signal', 'nucleus_median_signal', 'nucleus_max_signal', 'nucleus_min_signal']
|
|
451
|
+
features_names += ['snr_mean', 'snr_median', 'snr_std']
|
|
417
452
|
|
|
418
453
|
result_frame = pd.DataFrame()
|
|
419
454
|
|
|
@@ -450,8 +485,22 @@ def launch_cell_extraction(acquisition_id, spots, clusters, image, nucleus_signa
|
|
|
450
485
|
compute_topography=True
|
|
451
486
|
)
|
|
452
487
|
|
|
488
|
+
#Signal to noise
|
|
489
|
+
snr_dict = _compute_cell_snr(
|
|
490
|
+
image,
|
|
491
|
+
cell_bbox,
|
|
492
|
+
spots=rna_coords,
|
|
493
|
+
voxel_size=voxel_size,
|
|
494
|
+
spot_size=user_parameters['spot_size']
|
|
495
|
+
)
|
|
496
|
+
|
|
497
|
+
snr_mean = snr_dict['snr_mean']
|
|
498
|
+
snr_median = snr_dict['snr_median']
|
|
499
|
+
snr_std = snr_dict['snr_std']
|
|
500
|
+
|
|
453
501
|
features = list(features)
|
|
454
502
|
features += [np.mean(nuc_signal), np.median(nuc_signal), np.max(nuc_signal), np.min(nuc_signal)]
|
|
503
|
+
features += [snr_mean, snr_median, snr_std]
|
|
455
504
|
|
|
456
505
|
features = [acquisition_id, cell_id, cell_bbox] + features
|
|
457
506
|
|
|
@@ -554,9 +603,9 @@ def launch_features_computation(acquisition_id, image, nucleus_signal, spots, cl
|
|
|
554
603
|
if user_parameters['Cluster computation'] :
|
|
555
604
|
frame_results['cluster_number'] = len(clusters)
|
|
556
605
|
if dim == 3 :
|
|
557
|
-
frame_results['total_spots_in_clusters'] = clusters.sum(axis=0)[3]
|
|
606
|
+
frame_results['total_spots_in_clusters'] = clusters.sum(axis=0)[3] if len(clusters) >0 else 0
|
|
558
607
|
else :
|
|
559
|
-
frame_results['total_spots_in_clusters'] = clusters.sum(axis=0)[2]
|
|
608
|
+
frame_results['total_spots_in_clusters'] = clusters.sum(axis=0)[2] if len(clusters) >0 else 0
|
|
560
609
|
|
|
561
610
|
if type(cell_label) != type(None) and type(nucleus_label) != type(None):
|
|
562
611
|
cell_result_dframe = launch_cell_extraction(
|
|
@@ -626,7 +675,7 @@ def get_nucleus_signal(image, other_images, user_parameters) :
|
|
|
626
675
|
return np.zeros(shape=image.shape)
|
|
627
676
|
|
|
628
677
|
if rna_signal_channel == nucleus_signal_channel :
|
|
629
|
-
nucleus_signal
|
|
678
|
+
nucleus_signal = image
|
|
630
679
|
|
|
631
680
|
elif nucleus_signal_channel > rna_signal_channel :
|
|
632
681
|
nucleus_signal_channel -=1
|
small_fish_gui/pipeline/main.py
CHANGED
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
import pandas as pd
|
|
3
3
|
import PySimpleGUI as sg
|
|
4
4
|
from ..gui import hub_prompt
|
|
5
|
-
from .actions import add_detection, save_results, compute_colocalisation
|
|
5
|
+
from .actions import add_detection, save_results, compute_colocalisation, delete_acquisitions
|
|
6
|
+
from ._preprocess import clean_unused_parameters_cache
|
|
6
7
|
|
|
7
8
|
#'Global' parameters
|
|
8
9
|
user_parameters = dict() # Very important object containg all choice from user that will influence the behavior of the main loop.
|
|
@@ -15,10 +16,15 @@ cytoplasm_label = None
|
|
|
15
16
|
nucleus_label = None
|
|
16
17
|
|
|
17
18
|
while True : #Break this loop to close small_fish
|
|
19
|
+
result_df = result_df.reset_index(drop=True)
|
|
20
|
+
cell_result_df = cell_result_df.reset_index(drop=True)
|
|
21
|
+
coloc_df = coloc_df.reset_index(drop=True)
|
|
18
22
|
try :
|
|
19
23
|
event, values = hub_prompt(result_df, segmentation_done)
|
|
20
24
|
|
|
21
25
|
if event == 'Add detection' :
|
|
26
|
+
user_parameters = clean_unused_parameters_cache(user_parameters)
|
|
27
|
+
|
|
22
28
|
|
|
23
29
|
new_result_df, new_cell_result_df, acquisition_id, user_parameters, segmentation_done, cytoplasm_label, nucleus_label = add_detection(
|
|
24
30
|
user_parameters=user_parameters,
|
|
@@ -64,8 +70,8 @@ while True : #Break this loop to close small_fish
|
|
|
64
70
|
nucleus_label = None
|
|
65
71
|
|
|
66
72
|
elif event == "Delete acquisitions" :
|
|
67
|
-
|
|
68
|
-
|
|
73
|
+
selected_acquisitions = values.setdefault('result_table', []) #Contains the lines selected by the user on the sum-up array.
|
|
74
|
+
result_df, cell_result_df, coloc_df = delete_acquisitions(selected_acquisitions, result_df, cell_result_df, coloc_df)
|
|
69
75
|
|
|
70
76
|
elif event == "Batch detection" :
|
|
71
77
|
#TODO
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: small_fish_gui
|
|
3
|
-
Version: 1.0
|
|
3
|
+
Version: 1.2.0
|
|
4
4
|
Summary: Small Fish is a python application for the analysis of smFish images. It provides a ready to use graphical interface to combine famous python packages for cell analysis without any need for coding.
|
|
5
5
|
Project-URL: Homepage, https://github.com/2Echoes/small_fish
|
|
6
6
|
Project-URL: Issues, https://github.com/2Echoes/small_fish/issues
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
small_fish_gui/LICENSE,sha256=-iFy8VGBYs5VsHglKpk4D-hxqQ2jMJaqmfq_ulIzDks,1303
|
|
2
|
-
small_fish_gui/README.md,sha256=
|
|
3
|
-
small_fish_gui/__init__.py,sha256=
|
|
4
|
-
small_fish_gui/__main__.py,sha256=
|
|
2
|
+
small_fish_gui/README.md,sha256=LuvmYYwCVw7-rKhdhrtqxnxUfQxPUE-bbPlGNwzJh_4,1830
|
|
3
|
+
small_fish_gui/__init__.py,sha256=X2D6chgv6h8daHaMPwY_iCAscI86KwOkCCez6vsShPw,1941
|
|
4
|
+
small_fish_gui/__main__.py,sha256=EzSCoJ7jpSdK-QbzUwQLGZeQWjybNeq8VnCBucA8MZw,1372
|
|
5
5
|
small_fish_gui/requirements.txt,sha256=9OMfUAnLdHevq6w_fVoDmVmkSMJeFofkOK_86_fu9C0,321
|
|
6
6
|
small_fish_gui/start.py,sha256=HTbzsVcaMji1BZnWyjfn3bDGIQeXGG4zFzvCBepqFvA,108
|
|
7
7
|
small_fish_gui/utils.py,sha256=tSoMb8N69WdKTtMItPb1DYZiIAz1mjI26BCKJAi6vuc,1798
|
|
@@ -9,10 +9,10 @@ small_fish_gui/.github/workflows/python-publish.yml,sha256=5Ltnuhw9TevhzndlBmdUg
|
|
|
9
9
|
small_fish_gui/gui/__init__.py,sha256=178HC3t2z4EnP0iBnMcaP_pyh5xHwOkEE6p3WJwBQeU,911
|
|
10
10
|
small_fish_gui/gui/animation.py,sha256=6_Y15_NzJ_TYBYseu3sSKaVkYRp2UCsVClAWOk3dESY,714
|
|
11
11
|
small_fish_gui/gui/general_help_screenshot.png,sha256=X4E6Td5f04K-pBUPDaBJRAE3D5b8fuEdiAUKhkIDr-0,54210
|
|
12
|
-
small_fish_gui/gui/help_module.py,sha256=
|
|
13
|
-
small_fish_gui/gui/layout.py,sha256=
|
|
12
|
+
small_fish_gui/gui/help_module.py,sha256=PmgkkDs7bZ2-po83A_PK9uldQcHjehYmqre21nYb6DQ,9600
|
|
13
|
+
small_fish_gui/gui/layout.py,sha256=_ErOS2IUejeUuPLkDmPB3FzLkoHOWR-Iaxz-aUeETks,7695
|
|
14
14
|
small_fish_gui/gui/mapping_help_screenshot.png,sha256=HcuRh5TYciUogUasza5vZ_QSshaiHsskQK23mh9vQS8,34735
|
|
15
|
-
small_fish_gui/gui/prompts.py,sha256=
|
|
15
|
+
small_fish_gui/gui/prompts.py,sha256=74JPsGGtGMcHNdNQFjjHEN5XwdSd7hZKog_DTIcYaJ8,12389
|
|
16
16
|
small_fish_gui/gui/segmentation_help_screenshot.png,sha256=rbSgIydT0gZtfMh1qk4mdMbEIyCaakvHmxa2eOrLwO0,118944
|
|
17
17
|
small_fish_gui/gui/test.py,sha256=Pf-GW9AgW-0VL1mFbYtqRvPAaa8DgwCThv2dDUHCcmU,156
|
|
18
18
|
small_fish_gui/interface/__init__.py,sha256=PB86R4Y9kV80aGZ-vP0ZW2KeaCwGbBbCtFCmbN2yl28,275
|
|
@@ -20,17 +20,17 @@ small_fish_gui/interface/image.py,sha256=X1L7S5svxUwdoDcI3QM1PbN-c4Nz5w30hixq3Ig
|
|
|
20
20
|
small_fish_gui/interface/output.py,sha256=wqXJHk-PzqZwYr8NHLg9jcEJlZQXZk8R76aeWcTxsEw,1337
|
|
21
21
|
small_fish_gui/interface/parameters.py,sha256=lUugD-4W2TZyJF3TH1q70TlktEYhhPtcPCrvxm5Dk50,36
|
|
22
22
|
small_fish_gui/interface/testing.py,sha256=MY5-GcPOUHagcrwR8A7QOjAmjZIDVC8Wz3NibLe3KQw,321
|
|
23
|
-
small_fish_gui/pipeline/_colocalisation.py,sha256
|
|
23
|
+
small_fish_gui/pipeline/_colocalisation.py,sha256=peBw2Qz5m6wSejDkDz240UgvWl8ohNelrnmEgznbEsw,9635
|
|
24
24
|
small_fish_gui/pipeline/_custom_errors.py,sha256=tQ-AUhgzIFpK30AZiQQrtHCHyGVRDdAoIjzL0Fk-1pA,43
|
|
25
25
|
small_fish_gui/pipeline/_detection_visualisation.py,sha256=CNxCQpiCzC9Uk-2RqSuTp55Glf1URCL_s8zidwljY9Y,5774
|
|
26
|
-
small_fish_gui/pipeline/_preprocess.py,sha256=
|
|
27
|
-
small_fish_gui/pipeline/_segmentation.py,sha256=
|
|
26
|
+
small_fish_gui/pipeline/_preprocess.py,sha256=RHbMeYG6GPYyPJzxksgCQ8bs2O3qSXU0V-z4NZWQhrA,10487
|
|
27
|
+
small_fish_gui/pipeline/_segmentation.py,sha256=0f8M2Ujczm0tU5AVwxhfOyzRCi_P_gg1393S4RAvDFs,12968
|
|
28
28
|
small_fish_gui/pipeline/_signaltonoise.py,sha256=7A9t7xu7zghI6cr201Ldm-LjJ5NOuP56VSeJ8KIzcUo,8497
|
|
29
|
-
small_fish_gui/pipeline/actions.py,sha256=
|
|
30
|
-
small_fish_gui/pipeline/detection.py,sha256=
|
|
31
|
-
small_fish_gui/pipeline/main.py,sha256=
|
|
29
|
+
small_fish_gui/pipeline/actions.py,sha256=eKKmT3SSDYKQz-zU8HKz9h0PPgqyYrj4qHbrw1hfpRQ,7118
|
|
30
|
+
small_fish_gui/pipeline/detection.py,sha256=n-uuk2cP9Ls3WaZnuQfNHWyPoJWZNh8k9yW_8ZDC3fA,27484
|
|
31
|
+
small_fish_gui/pipeline/main.py,sha256=AAW-zK3b7Ece9cdHn9y6QG8lTa1HXG-8JtnvJ3m0HwA,3149
|
|
32
32
|
small_fish_gui/pipeline/test.py,sha256=w4ZMGDmUDXxVgWTlZ2TKw19W8q5gcE9gLMKe0SWnRrw,2827
|
|
33
|
-
small_fish_gui-1.0.
|
|
34
|
-
small_fish_gui-1.0.
|
|
35
|
-
small_fish_gui-1.0.
|
|
36
|
-
small_fish_gui-1.0.
|
|
33
|
+
small_fish_gui-1.2.0.dist-info/METADATA,sha256=ayA13aIDIc9K64nQLNlxWcTNNM7tO17BaK3kEycGiQw,2567
|
|
34
|
+
small_fish_gui-1.2.0.dist-info/WHEEL,sha256=zEMcRr9Kr03x1ozGwg5v9NQBKn3kndp6LSoSlVg-jhU,87
|
|
35
|
+
small_fish_gui-1.2.0.dist-info/licenses/LICENSE,sha256=-iFy8VGBYs5VsHglKpk4D-hxqQ2jMJaqmfq_ulIzDks,1303
|
|
36
|
+
small_fish_gui-1.2.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|