small-fish-gui 1.9.3__py3-none-any.whl → 1.10.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 +7 -9
- small_fish_gui/__init__.py +5 -2
- small_fish_gui/__main__.py +40 -17
- small_fish_gui/batch/prompt.py +1 -1
- small_fish_gui/batch/update.py +2 -2
- small_fish_gui/batch/values.txt +1 -1
- small_fish_gui/gui/__init__.py +1 -2
- small_fish_gui/gui/_napari_widgets.py +433 -25
- small_fish_gui/gui/layout.py +10 -7
- small_fish_gui/gui/napari_visualiser.py +68 -167
- small_fish_gui/gui/prompts.py +42 -45
- small_fish_gui/gui/testing.ipynb +138 -28
- small_fish_gui/gui/theme.py +5 -0
- small_fish_gui/hints.py +9 -7
- small_fish_gui/interface/__init__.py +1 -0
- small_fish_gui/interface/image.py +22 -1
- small_fish_gui/interface/testing.py +60 -9
- small_fish_gui/pipeline/_preprocess.py +18 -12
- small_fish_gui/pipeline/actions.py +5 -0
- small_fish_gui/pipeline/detection.py +31 -8
- small_fish_gui/pipeline/main.py +40 -3
- small_fish_gui/pipeline/segmentation.py +2 -2
- small_fish_gui/requirements.txt +12 -11
- {small_fish_gui-1.9.3.dist-info → small_fish_gui-1.10.0.dist-info}/METADATA +12 -10
- small_fish_gui-1.10.0.dist-info/RECORD +49 -0
- small_fish_gui/Segmentation example.jpg +0 -0
- small_fish_gui/gui/help_module.py +0 -256
- small_fish_gui/napari_detection_example.png +0 -0
- small_fish_gui-1.9.3.dist-info/RECORD +0 -51
- {small_fish_gui-1.9.3.dist-info → small_fish_gui-1.10.0.dist-info}/WHEEL +0 -0
- {small_fish_gui-1.9.3.dist-info → small_fish_gui-1.10.0.dist-info}/licenses/LICENSE +0 -0
small_fish_gui/hints.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
|
|
2
2
|
#Add keys hinting to user_parameters instance keys.
|
|
3
3
|
|
|
4
|
-
from typing import TypedDict,
|
|
4
|
+
from typing import TypedDict, Tuple
|
|
5
5
|
from numpy import ndarray
|
|
6
6
|
|
|
7
7
|
class pipeline_parameters(TypedDict) :
|
|
@@ -11,6 +11,7 @@ class pipeline_parameters(TypedDict) :
|
|
|
11
11
|
alpha : float
|
|
12
12
|
beta : float
|
|
13
13
|
channel_to_compute : int
|
|
14
|
+
cluster_size : int
|
|
14
15
|
do_cluster_computation : bool
|
|
15
16
|
do_dense_regions_deconvolution : bool
|
|
16
17
|
do_spots_excel : bool
|
|
@@ -22,11 +23,12 @@ class pipeline_parameters(TypedDict) :
|
|
|
22
23
|
image_path : str
|
|
23
24
|
image : ndarray
|
|
24
25
|
show_interactive_threshold_selector : bool
|
|
25
|
-
log_kernel_size :
|
|
26
|
+
log_kernel_size : Tuple[float,float,float]
|
|
26
27
|
log_kernel_size_x : float
|
|
27
28
|
log_kernel_size_y : float
|
|
28
29
|
log_kernel_size_z : float
|
|
29
|
-
|
|
30
|
+
min_number_of_spots : int
|
|
31
|
+
minimum_distance : Tuple[float,float,float]
|
|
30
32
|
minimum_distance_x : float
|
|
31
33
|
minimum_distance_y : float
|
|
32
34
|
minimum_distance_z : float
|
|
@@ -34,13 +36,13 @@ class pipeline_parameters(TypedDict) :
|
|
|
34
36
|
is_multichannel : bool
|
|
35
37
|
show_napari_corrector : bool
|
|
36
38
|
nucleus_channel_signal : int
|
|
37
|
-
reodered_shape :
|
|
39
|
+
reodered_shape : Tuple[int,int,int,int,int]
|
|
38
40
|
do_segmentation : bool
|
|
39
41
|
segmentation_done : bool
|
|
40
|
-
shape :
|
|
42
|
+
shape : Tuple[int,int,int,int,int]
|
|
41
43
|
spots_extraction_folder : str
|
|
42
44
|
spots_filename : str
|
|
43
|
-
spot_size :
|
|
45
|
+
spot_size : Tuple[int,int,int]
|
|
44
46
|
spot_size_x : int
|
|
45
47
|
spot_size_y : int
|
|
46
48
|
spot_size_z : int
|
|
@@ -48,7 +50,7 @@ class pipeline_parameters(TypedDict) :
|
|
|
48
50
|
threshold_penalty : int
|
|
49
51
|
time_stack : None
|
|
50
52
|
time_step : None
|
|
51
|
-
voxel_size :
|
|
53
|
+
voxel_size : Tuple[float,float,float]
|
|
52
54
|
voxel_size_x : float
|
|
53
55
|
voxel_size_y : float
|
|
54
56
|
voxel_size_z : float
|
|
@@ -2,6 +2,8 @@ from bigfish.stack import read_image
|
|
|
2
2
|
from czifile import imread
|
|
3
3
|
from ..utils import check_parameter
|
|
4
4
|
import re
|
|
5
|
+
from aicsimageio import AICSImage
|
|
6
|
+
from typing import Optional, Tuple
|
|
5
7
|
|
|
6
8
|
class FormatError(Exception):
|
|
7
9
|
pass
|
|
@@ -35,4 +37,23 @@ def get_filename(full_path: str) :
|
|
|
35
37
|
re_match = re.findall(pattern, full_path)
|
|
36
38
|
if len(re_match) == 0 : raise ValueError("Could not read filename from image full path.")
|
|
37
39
|
if len(re_match) == 1 : return re_match[0]
|
|
38
|
-
else : raise AssertionError("Several filenames read from path")
|
|
40
|
+
else : raise AssertionError("Several filenames read from path")
|
|
41
|
+
|
|
42
|
+
def get_voxel_size(filepath: str) -> Optional[Tuple[Optional[float], Optional[float], Optional[float]]]:
|
|
43
|
+
"""
|
|
44
|
+
Returns voxel size in nanometers (nm) as a tuple (X, Y, Z).
|
|
45
|
+
Any of the dimensions may be None if not available.
|
|
46
|
+
/WARINING\ : the unit might not be nm
|
|
47
|
+
"""
|
|
48
|
+
try:
|
|
49
|
+
img = AICSImage(filepath)
|
|
50
|
+
voxel_sizes = img.physical_pixel_sizes # values in meters
|
|
51
|
+
if voxel_sizes is None:
|
|
52
|
+
return None
|
|
53
|
+
x = voxel_sizes.X * 1e3 if voxel_sizes.X else None
|
|
54
|
+
y = voxel_sizes.Y * 1e3 if voxel_sizes.Y else None
|
|
55
|
+
z = voxel_sizes.Z * 1e3 if voxel_sizes.Z else None
|
|
56
|
+
return (z, y, x)
|
|
57
|
+
except Exception as e:
|
|
58
|
+
print(f"Failed to read voxel size from {filepath}: {e}")
|
|
59
|
+
return None
|
|
@@ -1,12 +1,63 @@
|
|
|
1
|
-
import
|
|
1
|
+
import os
|
|
2
|
+
from typing import Optional, Tuple
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
[sg.Radio(['A',], key='button', group_id=0, key='test1'),sg.Radio(['B'], key='button', group_id=0, key='test2'), sg.Radio(['C'], key='button', group_id=0, key='test3')],
|
|
5
|
-
[sg.Radio(['D',], key='button', group_id=1, key='test4')],
|
|
6
|
-
[sg.Button('Ok')]
|
|
7
|
-
]
|
|
4
|
+
IMAGE_PATH = "/home/floric/Documents/python/small_fish/images_test/Cropped_image_dapi_0.tif"
|
|
8
5
|
|
|
9
|
-
|
|
10
|
-
|
|
6
|
+
def get_voxel_size_0(filepath: str) -> Optional[Tuple[float, float, float]]:
|
|
7
|
+
ext = os.path.splitext(filepath)[1].lower()
|
|
8
|
+
|
|
9
|
+
if ext in ['.tif', '.tiff']:
|
|
10
|
+
import tifffile
|
|
11
|
+
with tifffile.TiffFile(filepath) as tif:
|
|
12
|
+
tags = tif.pages[0].tags
|
|
13
|
+
print(tags)
|
|
14
|
+
x_res = tags.get('XResolution')
|
|
15
|
+
y_res = tags.get('YResolution')
|
|
16
|
+
if x_res and y_res:
|
|
17
|
+
# Resolution is typically in (numerator, denominator)
|
|
18
|
+
x = x_res.value[1] / x_res.value[0]
|
|
19
|
+
y = y_res.value[1] / y_res.value[0]
|
|
20
|
+
# Microscopy images may store pixel size in microns per pixel (invert if necessary)
|
|
21
|
+
return (1.0, y, x) # Z usually not in TIFF metadata, so set as 1.0 or None
|
|
22
|
+
return None
|
|
23
|
+
|
|
24
|
+
elif ext == '.czi':
|
|
25
|
+
import czifile
|
|
26
|
+
with czifile.CziFile(filepath) as czi:
|
|
27
|
+
metadata = czi.metadata(raw=False)
|
|
28
|
+
scaling = metadata.get('ImageDocument', {}).get('Metadata', {}).get('Scaling', {})
|
|
29
|
+
try:
|
|
30
|
+
x = float(scaling['Items']['Distance'][0]['Value']) * 1e6 # in microns
|
|
31
|
+
y = float(scaling['Items']['Distance'][1]['Value']) * 1e6
|
|
32
|
+
z = float(scaling['Items']['Distance'][2]['Value']) * 1e6 if len(scaling['Items']['Distance']) > 2 else 1.0
|
|
33
|
+
return (x, y, z)
|
|
34
|
+
except Exception:
|
|
35
|
+
return None
|
|
36
|
+
|
|
37
|
+
return None
|
|
11
38
|
|
|
12
|
-
|
|
39
|
+
from aicsimageio import AICSImage
|
|
40
|
+
from typing import Optional, Tuple
|
|
41
|
+
|
|
42
|
+
def get_voxel_size(filepath: str) -> Optional[Tuple[Optional[float], Optional[float], Optional[float]]]:
|
|
43
|
+
"""
|
|
44
|
+
Returns voxel size in nanometers (nm) as a tuple (X, Y, Z).
|
|
45
|
+
Any of the dimensions may be None if not available.
|
|
46
|
+
/WARINING\ : the unit might not be nm
|
|
47
|
+
"""
|
|
48
|
+
try:
|
|
49
|
+
img = AICSImage(filepath)
|
|
50
|
+
voxel_sizes = img.physical_pixel_sizes # values in meters
|
|
51
|
+
if voxel_sizes is None:
|
|
52
|
+
return None
|
|
53
|
+
x = voxel_sizes.X * 1e3 if voxel_sizes.X else None
|
|
54
|
+
y = voxel_sizes.Y * 1e3 if voxel_sizes.Y else None
|
|
55
|
+
z = voxel_sizes.Z * 1e3 if voxel_sizes.Z else None
|
|
56
|
+
return (x, y, z)
|
|
57
|
+
except Exception as e:
|
|
58
|
+
print(f"Failed to read voxel size from {filepath}: {e}")
|
|
59
|
+
return None
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
res = get_voxel_size("/home/floric/Documents/python/small_fish/images_test/Cropped_image_dapi_0.tif")
|
|
63
|
+
print("RES : ",res)
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import numpy as np
|
|
2
2
|
import os
|
|
3
3
|
import FreeSimpleGUI as sg
|
|
4
|
-
from ..gui import _error_popup, _warning_popup, parameters_layout, add_header
|
|
5
|
-
from ..gui.prompts import input_image_prompt
|
|
4
|
+
from ..gui import _error_popup, _warning_popup, parameters_layout, add_header
|
|
5
|
+
from ..gui.prompts import input_image_prompt, prompt
|
|
6
6
|
|
|
7
7
|
class ParameterInputError(Exception) :
|
|
8
8
|
"""
|
|
@@ -141,7 +141,7 @@ def _ask_channel_map(shape, is_3D_stack, is_time_stack, multichannel, preset_map
|
|
|
141
141
|
if multichannel : layout += [parameters_layout(['c'], default_values=[c])]
|
|
142
142
|
if is_time_stack : layout += [parameters_layout(['t'], default_values=[t])]
|
|
143
143
|
|
|
144
|
-
event, preset_map =
|
|
144
|
+
event, preset_map = prompt(layout, add_scrollbar=False)
|
|
145
145
|
if event == 'Cancel' : return save_preset
|
|
146
146
|
|
|
147
147
|
#Check integrity
|
|
@@ -169,7 +169,7 @@ def _show_mapping(shape, map_, is_3D_stack, is_time_stack, multichannel) :
|
|
|
169
169
|
[sg.Button('Change mapping')]
|
|
170
170
|
]
|
|
171
171
|
|
|
172
|
-
event, values =
|
|
172
|
+
event, values = prompt(layout, add_scrollbar=False)
|
|
173
173
|
|
|
174
174
|
if event == 'Ok' :
|
|
175
175
|
return map_
|
|
@@ -186,20 +186,26 @@ def convert_parameters_types(values:dict) :
|
|
|
186
186
|
"""
|
|
187
187
|
|
|
188
188
|
#Tuples
|
|
189
|
-
|
|
189
|
+
tuples_dict = {
|
|
190
|
+
'voxel_size' : int,
|
|
191
|
+
'spot_size' : float,
|
|
192
|
+
'log_kernel_size' : float,
|
|
193
|
+
'minimum_distance' : float,
|
|
194
|
+
'deconvolution_kernel' : float,
|
|
195
|
+
}
|
|
190
196
|
dim = values['dim']
|
|
191
197
|
if dim == 3 : dim_tuple = ('z', 'y', 'x')
|
|
192
198
|
else : dim_tuple = ('y', 'x')
|
|
193
199
|
|
|
194
|
-
for tuple_parameter in
|
|
200
|
+
for tuple_parameter, type_cast in tuples_dict.items() :
|
|
195
201
|
try :
|
|
196
|
-
tuple_values = tuple([
|
|
202
|
+
tuple_values = tuple([type_cast(values.get(tuple_parameter + '_{0}'.format(dimension))) for dimension in dim_tuple])
|
|
197
203
|
except Exception as e : #execption when str cannot be converted to float or no parameter was given.
|
|
198
204
|
values[tuple_parameter] = None
|
|
199
205
|
else : values[tuple_parameter] = tuple_values
|
|
200
206
|
|
|
201
207
|
#Parameters
|
|
202
|
-
int_list = ['threshold', 'channel_to_compute', 'channel_to_compute', '
|
|
208
|
+
int_list = ['threshold', 'channel_to_compute', 'channel_to_compute', 'min_number_of_spots', 'cluster_size','nucleus channel signal']
|
|
203
209
|
float_list = ['alpha', 'beta', 'gamma', 'threshold penalty']
|
|
204
210
|
|
|
205
211
|
for parameter in int_list :
|
|
@@ -252,9 +258,9 @@ def check_integrity(
|
|
|
252
258
|
raise ParameterInputError("alpha must be set between 0 and 1.")
|
|
253
259
|
|
|
254
260
|
if do_clustering :
|
|
255
|
-
if not isinstance(values['
|
|
261
|
+
if not isinstance(values['min_number_of_spots'], (int)) :
|
|
256
262
|
raise ParameterInputError("Incorrect min spot number parameter.")
|
|
257
|
-
if not isinstance(values['
|
|
263
|
+
if not isinstance(values['cluster_size'], (int)) :
|
|
258
264
|
raise ParameterInputError("Incorrect cluster size parameter.")
|
|
259
265
|
|
|
260
266
|
#channel
|
|
@@ -339,7 +345,7 @@ def clean_unused_parameters_cache(user_parameters: dict) :
|
|
|
339
345
|
"""
|
|
340
346
|
Clean unused parameters that were set to None in previous run.
|
|
341
347
|
"""
|
|
342
|
-
parameters = ['alpha', 'beta', 'gamma', '
|
|
348
|
+
parameters = ['alpha', 'beta', 'gamma', 'cluster_size', 'min_number_of_spots']
|
|
343
349
|
for parameter in parameters :
|
|
344
350
|
if parameter in user_parameters.keys() :
|
|
345
351
|
if type(user_parameters[parameter]) == type(None) :
|
|
@@ -389,6 +395,6 @@ def ask_input_parameters(ask_for_segmentation=True) :
|
|
|
389
395
|
|
|
390
396
|
values.update(image_input_values)
|
|
391
397
|
values['dim'] = 3 if values['is_3D_stack'] else 2
|
|
392
|
-
values['filename'] = os.path.basename(values['
|
|
398
|
+
values['filename'] = os.path.basename(values['image_path'])
|
|
393
399
|
|
|
394
400
|
return values
|
|
@@ -22,11 +22,16 @@ from .segmentation import launch_segmentation
|
|
|
22
22
|
from ._colocalisation import initiate_colocalisation, launch_colocalisation
|
|
23
23
|
|
|
24
24
|
from ..hints import pipeline_parameters
|
|
25
|
+
from ..__init__ import __wiki__
|
|
25
26
|
|
|
26
27
|
import os
|
|
27
28
|
import pandas as pd
|
|
28
29
|
import FreeSimpleGUI as sg
|
|
29
30
|
import numpy as np
|
|
31
|
+
import webbrowser
|
|
32
|
+
|
|
33
|
+
def open_wiki() :
|
|
34
|
+
webbrowser.open_new_tab(__wiki__)
|
|
30
35
|
|
|
31
36
|
def segment_cells(user_parameters : pipeline_parameters, nucleus_label, cytoplasm_label) :
|
|
32
37
|
if user_parameters['segmentation_done'] :
|
|
@@ -3,7 +3,6 @@ Contains code to handle detection as well as bigfish wrappers related to spot de
|
|
|
3
3
|
"""
|
|
4
4
|
from ..hints import pipeline_parameters
|
|
5
5
|
|
|
6
|
-
|
|
7
6
|
from ._preprocess import ParameterInputError
|
|
8
7
|
from ._preprocess import check_integrity, convert_parameters_types
|
|
9
8
|
|
|
@@ -11,22 +10,24 @@ from ..gui.napari_visualiser import correct_spots, threshold_selection
|
|
|
11
10
|
from ..gui import add_default_loading
|
|
12
11
|
from ..gui import detection_parameters_promt
|
|
13
12
|
|
|
13
|
+
from ..interface import get_voxel_size
|
|
14
14
|
from ..utils import compute_anisotropy_coef
|
|
15
15
|
from ._signaltonoise import compute_snr_spots
|
|
16
16
|
|
|
17
17
|
from magicgui import magicgui
|
|
18
|
+
|
|
19
|
+
from types import GeneratorType
|
|
18
20
|
from napari.types import LayerDataTuple
|
|
19
21
|
|
|
20
22
|
import numpy as np
|
|
23
|
+
from numpy import NaN
|
|
21
24
|
import pandas as pd
|
|
22
25
|
import FreeSimpleGUI as sg
|
|
23
|
-
from numpy import NaN
|
|
24
26
|
import bigfish.detection as detection
|
|
25
27
|
import bigfish.stack as stack
|
|
26
28
|
import bigfish.multistack as multistack
|
|
27
29
|
import bigfish.classification as classification
|
|
28
30
|
from bigfish.detection.spot_detection import get_object_radius_pixel
|
|
29
|
-
from types import GeneratorType
|
|
30
31
|
from skimage.measure import regionprops
|
|
31
32
|
from scipy.ndimage import binary_dilation
|
|
32
33
|
|
|
@@ -211,6 +212,22 @@ def initiate_detection(user_parameters : pipeline_parameters, map_, shape) :
|
|
|
211
212
|
do_clustering = user_parameters['do_cluster_computation']
|
|
212
213
|
detection_parameters = user_parameters.copy()
|
|
213
214
|
|
|
215
|
+
#Attempt to read voxel size from metadata
|
|
216
|
+
voxel_size = get_voxel_size(user_parameters['image_path'])
|
|
217
|
+
if voxel_size is None or not user_parameters.get('voxel_size') is None:
|
|
218
|
+
pass
|
|
219
|
+
else :
|
|
220
|
+
detection_parameters['voxel_size'] = [int(v) for v in voxel_size]
|
|
221
|
+
detection_parameters['voxel_size_z'] = round(voxel_size[0])
|
|
222
|
+
detection_parameters['voxel_size_y'] = round(voxel_size[1])
|
|
223
|
+
detection_parameters['voxel_size_x'] = round(voxel_size[2])
|
|
224
|
+
|
|
225
|
+
#Setting default spot size to 1.5 voxel
|
|
226
|
+
if detection_parameters.get('spot_size') is None :
|
|
227
|
+
detection_parameters['spot_size_z'] = round(detection_parameters['voxel_size_z']*1.5) if not detection_parameters['voxel_size_z'] is None else None
|
|
228
|
+
detection_parameters['spot_size_y'] = round(detection_parameters['voxel_size_y']*1.5) if not detection_parameters['voxel_size_y'] is None else None
|
|
229
|
+
detection_parameters['spot_size_x'] = round(detection_parameters['voxel_size_x']*1.5) if not detection_parameters['voxel_size_x'] is None else None
|
|
230
|
+
|
|
214
231
|
while True :
|
|
215
232
|
detection_parameters = detection_parameters_promt(
|
|
216
233
|
is_3D_stack=is_3D_stack,
|
|
@@ -237,6 +254,7 @@ def initiate_detection(user_parameters : pipeline_parameters, map_, shape) :
|
|
|
237
254
|
else :
|
|
238
255
|
user_parameters.update(detection_parameters)
|
|
239
256
|
break
|
|
257
|
+
|
|
240
258
|
return user_parameters
|
|
241
259
|
|
|
242
260
|
@add_default_loading
|
|
@@ -557,8 +575,8 @@ def launch_cell_extraction(
|
|
|
557
575
|
def launch_clustering(spots, user_parameters : pipeline_parameters):
|
|
558
576
|
|
|
559
577
|
voxel_size = user_parameters['voxel_size']
|
|
560
|
-
nb_min_spots = user_parameters['
|
|
561
|
-
cluster_size = user_parameters['
|
|
578
|
+
nb_min_spots = user_parameters['min_number_of_spots']
|
|
579
|
+
cluster_size = user_parameters['cluster_size']
|
|
562
580
|
|
|
563
581
|
cluster_result_dict = cluster_detection(
|
|
564
582
|
spots=spots,
|
|
@@ -622,19 +640,24 @@ def launch_detection(
|
|
|
622
640
|
|
|
623
641
|
if user_parameters['show_napari_corrector'] :
|
|
624
642
|
|
|
625
|
-
spots, clusters = correct_spots(
|
|
643
|
+
spots, clusters, new_cluster_radius, new_min_spot_number = correct_spots(
|
|
626
644
|
image,
|
|
627
645
|
spots,
|
|
628
646
|
user_parameters['voxel_size'],
|
|
629
647
|
clusters=clusters,
|
|
630
648
|
spot_cluster_id = spots_cluster_id,
|
|
631
|
-
cluster_size= user_parameters.get('
|
|
632
|
-
min_spot_number= user_parameters.setdefault('
|
|
649
|
+
cluster_size= user_parameters.get('cluster_size'),
|
|
650
|
+
min_spot_number= user_parameters.setdefault('min_number_of_spots', 0),
|
|
633
651
|
cell_label=cell_label,
|
|
634
652
|
nucleus_label=nucleus_label,
|
|
635
653
|
other_images=other_image
|
|
636
654
|
)
|
|
637
655
|
|
|
656
|
+
if type(new_cluster_radius) != type(None) :
|
|
657
|
+
user_parameters['cluster_size'] = new_cluster_radius
|
|
658
|
+
if type(new_min_spot_number) != type(None) :
|
|
659
|
+
user_parameters['min_number_of_spots'] = new_min_spot_number
|
|
660
|
+
|
|
638
661
|
if do_clustering :
|
|
639
662
|
spots, spots_cluster_id = spots[:,:-1], spots[:,-1]
|
|
640
663
|
else :
|
small_fish_gui/pipeline/main.py
CHANGED
|
@@ -1,13 +1,22 @@
|
|
|
1
1
|
"""
|
|
2
2
|
This script is called when software starts; it is the main loop.
|
|
3
3
|
"""
|
|
4
|
+
import traceback, os
|
|
5
|
+
from small_fish_gui import __version__
|
|
4
6
|
|
|
5
7
|
import pandas as pd
|
|
6
8
|
import FreeSimpleGUI as sg
|
|
7
|
-
|
|
8
|
-
from .actions import add_detection
|
|
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
|
+
|
|
9
17
|
from ._preprocess import clean_unused_parameters_cache
|
|
10
18
|
from ..batch import batch_promp
|
|
19
|
+
from ..gui import hub_prompt, prompt_restore_main_menu
|
|
11
20
|
from ..hints import pipeline_parameters
|
|
12
21
|
|
|
13
22
|
#'Global' parameters
|
|
@@ -103,11 +112,39 @@ while True : #Break this loop to close small_fish
|
|
|
103
112
|
selected_acquisitions = values.setdefault('result_table', []) #Contains the lines selected by the user on the sum-up array.
|
|
104
113
|
result_df, cell_result_df, global_coloc_df, cell_coloc_df = rename_acquisitions(selected_acquisitions, result_df, cell_result_df, global_coloc_df, cell_coloc_df)
|
|
105
114
|
|
|
115
|
+
elif event == "wiki" :
|
|
116
|
+
open_wiki()
|
|
117
|
+
|
|
106
118
|
else :
|
|
107
119
|
break
|
|
108
120
|
|
|
109
121
|
|
|
110
122
|
except Exception as error :
|
|
111
123
|
sg.popup(str(error))
|
|
112
|
-
|
|
124
|
+
|
|
125
|
+
with open("error_log.txt",'a') as error_log :
|
|
126
|
+
error_log.writelines([
|
|
127
|
+
f"version {__version__}",
|
|
128
|
+
f"error : {error}",
|
|
129
|
+
f"traceback :\n{traceback.format_exc()}",
|
|
130
|
+
])
|
|
131
|
+
|
|
132
|
+
print(f"error_log saved at {os.getcwd()}/error_log.txt. Please consider reporting this by opening an issue on github.")
|
|
133
|
+
|
|
134
|
+
save_quit = prompt_restore_main_menu()
|
|
135
|
+
|
|
136
|
+
if save_quit is None :
|
|
137
|
+
raise error
|
|
138
|
+
|
|
139
|
+
elif save_quit :
|
|
140
|
+
save_results(
|
|
141
|
+
result_df=result_df,
|
|
142
|
+
cell_result_df=cell_result_df,
|
|
143
|
+
global_coloc_df=global_coloc_df,
|
|
144
|
+
cell_coloc_df = cell_coloc_df,
|
|
145
|
+
)
|
|
146
|
+
quit()
|
|
147
|
+
else :
|
|
148
|
+
continue
|
|
149
|
+
|
|
113
150
|
quit()
|
|
@@ -6,7 +6,7 @@ from cellpose.core import use_gpu
|
|
|
6
6
|
from skimage.measure import label
|
|
7
7
|
from ..hints import pipeline_parameters
|
|
8
8
|
from ..gui.layout import _segmentation_layout
|
|
9
|
-
from ..gui import prompt,
|
|
9
|
+
from ..gui import prompt, ask_cancel_segmentation
|
|
10
10
|
from ..interface import open_image
|
|
11
11
|
from ..gui.napari_visualiser import show_segmentation as napari_show_segmentation
|
|
12
12
|
from .utils import from_label_get_centeroidscoords
|
|
@@ -88,7 +88,7 @@ def launch_segmentation(user_parameters: pipeline_parameters, nucleus_label, cyt
|
|
|
88
88
|
multichannel=multichannel,
|
|
89
89
|
)
|
|
90
90
|
|
|
91
|
-
event, values =
|
|
91
|
+
event, values = prompt(layout)
|
|
92
92
|
if event == 'Cancel' :
|
|
93
93
|
cancel_segmentation = ask_cancel_segmentation()
|
|
94
94
|
|
small_fish_gui/requirements.txt
CHANGED
|
@@ -2,16 +2,17 @@ big-fish==0.6.2
|
|
|
2
2
|
cellpose==3.0.7
|
|
3
3
|
czifile==2019.7.2
|
|
4
4
|
imageio==2.34.0
|
|
5
|
-
napari
|
|
6
|
-
napari-console
|
|
7
|
-
napari-plugin-engine
|
|
8
|
-
napari-plugin-manager
|
|
9
|
-
napari-svg
|
|
10
|
-
numpy
|
|
11
|
-
pandas
|
|
12
|
-
FreeSimpleGUI
|
|
13
|
-
scipy
|
|
5
|
+
napari>=0.4.19.post1
|
|
6
|
+
napari-console>=0.0.9
|
|
7
|
+
napari-plugin-engine>=0.2.0
|
|
8
|
+
napari-plugin-manager>=0.1.0a2
|
|
9
|
+
napari-svg>=0.1.10
|
|
10
|
+
numpy>=1.24.4
|
|
11
|
+
pandas>=1.5.3
|
|
12
|
+
FreeSimpleGUI>=5.1.1
|
|
13
|
+
scipy>=1.9.1
|
|
14
14
|
scikit-image==0.19.1
|
|
15
15
|
scikit-learn==1.3.2
|
|
16
|
-
openpyxl
|
|
17
|
-
pyarrow
|
|
16
|
+
openpyxl>=3.1.2
|
|
17
|
+
pyarrow>=11.0.0
|
|
18
|
+
aicsimageio>=aicsimageio==4.14.0
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: small_fish_gui
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.10.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
|
+
Project-URL: Wiki, https://github.com/2Echoes/small_fish_gui/wiki
|
|
6
7
|
Project-URL: Issues, https://github.com/2Echoes/small_fish/issues
|
|
7
8
|
Author-email: Slimani Floric <floric.slimani@live.com>
|
|
8
9
|
License-File: LICENSE
|
|
@@ -10,23 +11,24 @@ Classifier: License :: OSI Approved :: BSD License
|
|
|
10
11
|
Classifier: Operating System :: OS Independent
|
|
11
12
|
Classifier: Programming Language :: Python :: 3
|
|
12
13
|
Requires-Python: >=3.8
|
|
14
|
+
Requires-Dist: aicsimageio>=4.14.0
|
|
13
15
|
Requires-Dist: big-fish==0.6.2
|
|
14
16
|
Requires-Dist: cellpose==3.0.7
|
|
15
17
|
Requires-Dist: czifile==2019.7.2
|
|
16
|
-
Requires-Dist: freesimplegui
|
|
18
|
+
Requires-Dist: freesimplegui>=5.1.1
|
|
17
19
|
Requires-Dist: imageio==2.34.0
|
|
18
|
-
Requires-Dist: napari-console
|
|
19
|
-
Requires-Dist: napari-plugin-engine
|
|
20
|
-
Requires-Dist: napari-plugin-manager
|
|
21
|
-
Requires-Dist: napari-svg
|
|
22
|
-
Requires-Dist: napari
|
|
23
|
-
Requires-Dist: numpy
|
|
20
|
+
Requires-Dist: napari-console>=0.0.9
|
|
21
|
+
Requires-Dist: napari-plugin-engine>=0.2.0
|
|
22
|
+
Requires-Dist: napari-plugin-manager>=0.1.0a2
|
|
23
|
+
Requires-Dist: napari-svg>=0.1.10
|
|
24
|
+
Requires-Dist: napari>=0.4.19.post1
|
|
25
|
+
Requires-Dist: numpy>=1.24.4
|
|
24
26
|
Requires-Dist: openpyxl==3.1.2
|
|
25
|
-
Requires-Dist: pandas
|
|
27
|
+
Requires-Dist: pandas>=1.5.3
|
|
26
28
|
Requires-Dist: pyarrow==11.0.0
|
|
27
29
|
Requires-Dist: scikit-image==0.19.1
|
|
28
30
|
Requires-Dist: scikit-learn==1.3.2
|
|
29
|
-
Requires-Dist: scipy
|
|
31
|
+
Requires-Dist: scipy>=1.9.1
|
|
30
32
|
Description-Content-Type: text/markdown
|
|
31
33
|
|
|
32
34
|
# Small Fish
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
small_fish_gui/LICENSE,sha256=-iFy8VGBYs5VsHglKpk4D-hxqQ2jMJaqmfq_ulIzDks,1303
|
|
2
|
+
small_fish_gui/README.md,sha256=SFXhmWiISVrOd_cBUodAYaHhMPeKBXyVoPe-fiBxuBw,4671
|
|
3
|
+
small_fish_gui/__init__.py,sha256=FQ99kPNleb90KdywZ4bt2NiizCwyfooTZhndH5O_no8,2050
|
|
4
|
+
small_fish_gui/__main__.py,sha256=mgO_BmBGBsp8steg_lcwCPZ7QzgjgeScL8Npgs1D9Pk,1643
|
|
5
|
+
small_fish_gui/hints.py,sha256=57pO8WA_PymBm5QyXCgYxnZIqqt86B-hO_s_6sv8b5s,1962
|
|
6
|
+
small_fish_gui/requirements.txt,sha256=udO54grAFrmnEqUQC4rDeUMaIyBz3hYB1LJtu1ld7tg,354
|
|
7
|
+
small_fish_gui/utils.py,sha256=LM6QW2ono_LIRv7JXIIq7ZxxbDXqBtZ5uR9gjKJfwM8,1903
|
|
8
|
+
small_fish_gui/.github/workflows/python-publish.yml,sha256=5Ltnuhw9TevhzndlBmdUgYMnS73xEAxSyd1u8DHdn5s,1084
|
|
9
|
+
small_fish_gui/batch/__init__.py,sha256=ku2_Yate-UG89Q0BmE2B9kFV4kOz-u9Lf2lj6VsdFXs,127
|
|
10
|
+
small_fish_gui/batch/input.py,sha256=mqnP8LBhyNbtlcqjVlUiVeuHw4YxOX3GgzJbq03isKE,1477
|
|
11
|
+
small_fish_gui/batch/integrity.py,sha256=qyttOwsukds6eE2j6NRmA8-fQtHxlnP4tgwQqrs3EWs,4853
|
|
12
|
+
small_fish_gui/batch/pipeline.py,sha256=-XSyGTrk7WYhgLZLZeUoJvyzfcoprJTofUuIz623Irw,10419
|
|
13
|
+
small_fish_gui/batch/prompt.py,sha256=pGwcszKkKrEr5MizlKk9e9a0mt7CGttqf3xl-3BuXR0,18851
|
|
14
|
+
small_fish_gui/batch/test.py,sha256=FcoCngSeueociwVoG8V3C6lQO7rrRHUfIVA2hJKr4v4,213
|
|
15
|
+
small_fish_gui/batch/update.py,sha256=opSwMLlQDUtCwWpx9d2GfNKVA-t90ziqc1qofDH74D8,5044
|
|
16
|
+
small_fish_gui/batch/utils.py,sha256=Pnmzlen8gmLBYBthMiUiK0TErjBBSId9SjKeBd9U6-U,1784
|
|
17
|
+
small_fish_gui/batch/values.txt,sha256=XY8FBgAqExVKbtCXLztptaOUTFKj0G6t1_xX-zjYuTk,999
|
|
18
|
+
small_fish_gui/gui/__init__.py,sha256=k08QFdLv2IXR8a6f8aPzy6iJ6MjDI7ZV143CH-BEXuA,845
|
|
19
|
+
small_fish_gui/gui/_napari_widgets.py,sha256=SohHKdlPrnky4He-tbw6X10FOGSAUA0dN-3eEs_keU0,18781
|
|
20
|
+
small_fish_gui/gui/animation.py,sha256=MnYsA1kxQZ72L_H0knxOs41lG0ZZv1re7gSgYNmZY00,983
|
|
21
|
+
small_fish_gui/gui/layout.py,sha256=f45acK2I7o9Q3LYY23G4XAJ8HPoD9mp7AJNNlLbUByI,14371
|
|
22
|
+
small_fish_gui/gui/napari_visualiser.py,sha256=L_A4V8FN2a-6Kr45t8KBdZVj5qnzajSvSTIUrGlXU9M,9937
|
|
23
|
+
small_fish_gui/gui/prompts.py,sha256=Z1ZAaayS1ywK4PxK4YyzrAUNYBFIQH4W05oX6P47OdM,15508
|
|
24
|
+
small_fish_gui/gui/testing.ipynb,sha256=4TJar2T0Q_EdnCzMFGqdLu7tVbNYud5C8DQcoVRttpU,74574
|
|
25
|
+
small_fish_gui/gui/theme.py,sha256=30nujS48ZRdD1HVbzdEBkiAWlhow1AGgXSQNZcGEsaQ,118
|
|
26
|
+
small_fish_gui/gui/screenshot/general_help_screenshot.png,sha256=X4E6Td5f04K-pBUPDaBJRAE3D5b8fuEdiAUKhkIDr-0,54210
|
|
27
|
+
small_fish_gui/gui/screenshot/mapping_help_screenshot.png,sha256=HcuRh5TYciUogUasza5vZ_QSshaiHsskQK23mh9vQS8,34735
|
|
28
|
+
small_fish_gui/gui/screenshot/segmentation_help_screenshot.png,sha256=rbSgIydT0gZtfMh1qk4mdMbEIyCaakvHmxa2eOrLwO0,118944
|
|
29
|
+
small_fish_gui/interface/__init__.py,sha256=tS4nWOTX2RpzRpzLbjvo5gbfqgvgLXEzjpUh7W-1RUE,311
|
|
30
|
+
small_fish_gui/interface/image.py,sha256=SOe3zlyTKqkkQflb3A9EJok8QduUn2ue6bMH9Ma2hKU,1933
|
|
31
|
+
small_fish_gui/interface/inoutput.py,sha256=FXKSSRrVou5VBWvTbiBjSCr7DncIyZbcV5MfRa6J64g,5467
|
|
32
|
+
small_fish_gui/interface/testing.py,sha256=AUdqmFJ6kBvFTOLRfZZJBBe3nm1key2bGpUDXJRaueI,2561
|
|
33
|
+
small_fish_gui/pipeline/__init__.py,sha256=Oww6dcuvnktl5jFKLriz8ZXObKo9MkneE739A8C1reY,739
|
|
34
|
+
small_fish_gui/pipeline/_colocalisation.py,sha256=PJ9IkICwPiaTNRTX4xqPhf1J3wyE2yAFRPtYEbw2k-A,21298
|
|
35
|
+
small_fish_gui/pipeline/_custom_errors.py,sha256=tQ-AUhgzIFpK30AZiQQrtHCHyGVRDdAoIjzL0Fk-1pA,43
|
|
36
|
+
small_fish_gui/pipeline/_preprocess.py,sha256=AzSbfIFWXVWs_WRGgZ_2X5afVkbnC0iBMvuP9F3Quc4,15136
|
|
37
|
+
small_fish_gui/pipeline/_signaltonoise.py,sha256=7A9t7xu7zghI6cr201Ldm-LjJ5NOuP56VSeJ8KIzcUo,8497
|
|
38
|
+
small_fish_gui/pipeline/actions.py,sha256=nwXD3NLSJHLQC3hpeNRf_JfBbnCZEQsRgH2W74vXAyk,16048
|
|
39
|
+
small_fish_gui/pipeline/detection.py,sha256=fEdSt8Tw6dETGg_qLrxVHv7Znmb1om5Qd09tQhQsjP4,36949
|
|
40
|
+
small_fish_gui/pipeline/main.py,sha256=5Mjw1glru0WL0o2D4uL8Gf5DtZMCd506Wn2C4wRkyNQ,5850
|
|
41
|
+
small_fish_gui/pipeline/segmentation.py,sha256=CwjNwcFiHYbbjuZednmE8P3S7bnVpebLqD_9mXfQoII,19864
|
|
42
|
+
small_fish_gui/pipeline/spots.py,sha256=9hNOGnOZhrtrIORt8UGBcI-SGCh1XftcUGerkBwN-QY,2201
|
|
43
|
+
small_fish_gui/pipeline/test.py,sha256=w4ZMGDmUDXxVgWTlZ2TKw19W8q5gcE9gLMKe0SWnRrw,2827
|
|
44
|
+
small_fish_gui/pipeline/testing.ipynb,sha256=Rs7VQ7TImNyUzT2_59JgbOjR5_Qs-0NjHHnqS87eiwA,76481
|
|
45
|
+
small_fish_gui/pipeline/utils.py,sha256=run6qtqCAe_mFnE3o1CnmF1xBBmK3ydgc8-jOV9P-_w,448
|
|
46
|
+
small_fish_gui-1.10.0.dist-info/METADATA,sha256=xMAo4wKuzpFdVgG4y8SFIagCEVDinLBYaJRUqyR4TUA,2670
|
|
47
|
+
small_fish_gui-1.10.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
48
|
+
small_fish_gui-1.10.0.dist-info/licenses/LICENSE,sha256=-iFy8VGBYs5VsHglKpk4D-hxqQ2jMJaqmfq_ulIzDks,1303
|
|
49
|
+
small_fish_gui-1.10.0.dist-info/RECORD,,
|
|
Binary file
|