small-fish-gui 1.3.3__py3-none-any.whl → 1.3.5__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/__init__.py +1 -1
- small_fish_gui/gui/__init__.py +1 -2
- small_fish_gui/gui/batch.py +312 -0
- small_fish_gui/gui/layout.py +144 -21
- small_fish_gui/gui/prompts.py +21 -23
- small_fish_gui/gui/test.py +3 -2
- small_fish_gui/pipeline/_napari_wrapper.py +3 -2
- small_fish_gui/pipeline/_preprocess.py +10 -11
- small_fish_gui/pipeline/_segmentation.py +1 -1
- small_fish_gui/pipeline/detection.py +4 -1
- {small_fish_gui-1.3.3.dist-info → small_fish_gui-1.3.5.dist-info}/METADATA +1 -1
- {small_fish_gui-1.3.3.dist-info → small_fish_gui-1.3.5.dist-info}/RECORD +14 -13
- {small_fish_gui-1.3.3.dist-info → small_fish_gui-1.3.5.dist-info}/WHEEL +0 -0
- {small_fish_gui-1.3.3.dist-info → small_fish_gui-1.3.5.dist-info}/licenses/LICENSE +0 -0
small_fish_gui/__init__.py
CHANGED
small_fish_gui/gui/__init__.py
CHANGED
|
@@ -10,7 +10,6 @@ from .prompts import input_image_prompt
|
|
|
10
10
|
from .prompts import hub_prompt
|
|
11
11
|
from .prompts import detection_parameters_promt
|
|
12
12
|
from .prompts import coloc_prompt
|
|
13
|
-
from .prompts import post_analysis_prompt
|
|
14
13
|
from .prompts import output_image_prompt
|
|
15
14
|
from .prompts import ask_cancel_detection
|
|
16
15
|
from .prompts import ask_cancel_segmentation
|
|
@@ -21,7 +20,7 @@ from .prompts import ask_detection_confirmation
|
|
|
21
20
|
from .layout import parameters_layout
|
|
22
21
|
from .layout import bool_layout
|
|
23
22
|
from .layout import path_layout
|
|
24
|
-
from .layout import
|
|
23
|
+
from .layout import combo_elmt
|
|
25
24
|
from .layout import tuple_layout
|
|
26
25
|
from .layout import radio_layout
|
|
27
26
|
from .layout import add_header
|
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import numpy as np
|
|
3
|
+
import PySimpleGUI as sg
|
|
4
|
+
import bigfish.stack as stack
|
|
5
|
+
import czifile as czi
|
|
6
|
+
|
|
7
|
+
from .layout import _segmentation_layout, _detection_layout, _input_parameters_layout, _ask_channel_map_layout
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
from time import sleep
|
|
11
|
+
|
|
12
|
+
def get_images(filename:str) :
|
|
13
|
+
"""returns filename if is image else return None"""
|
|
14
|
+
|
|
15
|
+
supported_types = ('.tiff', '.tif', '.png', '.czi')
|
|
16
|
+
if filename.endswith(supported_types) :
|
|
17
|
+
return [filename]
|
|
18
|
+
else :
|
|
19
|
+
return None
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def get_files(path) :
|
|
23
|
+
|
|
24
|
+
filelist = os.listdir(path)
|
|
25
|
+
filelist = list(map(get_images,filelist))
|
|
26
|
+
|
|
27
|
+
while None in filelist : filelist.remove(None)
|
|
28
|
+
|
|
29
|
+
return filelist
|
|
30
|
+
|
|
31
|
+
def extract_files(filenames: list) :
|
|
32
|
+
return sum(filenames,[])
|
|
33
|
+
|
|
34
|
+
def check_file(filename:str) :
|
|
35
|
+
|
|
36
|
+
if filename.endswith('.czi') :
|
|
37
|
+
image = czi.imread(filename)
|
|
38
|
+
else :
|
|
39
|
+
image = stack.read_image(filename)
|
|
40
|
+
|
|
41
|
+
image = np.squeeze(image)
|
|
42
|
+
|
|
43
|
+
return image.shape
|
|
44
|
+
|
|
45
|
+
def sanity_check(
|
|
46
|
+
filename_list: list,
|
|
47
|
+
batch_folder : str,
|
|
48
|
+
window : sg.Window,
|
|
49
|
+
progress_bar: sg.ProgressBar,
|
|
50
|
+
) :
|
|
51
|
+
|
|
52
|
+
filenumber = len(filename_list)
|
|
53
|
+
if filenumber == 0 :
|
|
54
|
+
print("No file to check")
|
|
55
|
+
progress_bar.update(current_count= 0, bar_color=('gray','gray'))
|
|
56
|
+
return None
|
|
57
|
+
else :
|
|
58
|
+
print("{0} files to check".format(filenumber))
|
|
59
|
+
progress_bar.update(current_count=0, max= filenumber)
|
|
60
|
+
ref_shape = check_file(batch_folder + '/' + filename_list[0])
|
|
61
|
+
|
|
62
|
+
print("Starting sanity check. This could take some time...")
|
|
63
|
+
for i, file in enumerate(filename_list) :
|
|
64
|
+
progress_bar.update(current_count= i+1, bar_color=('green','gray'))
|
|
65
|
+
shape = check_file(batch_folder + '/' + file)
|
|
66
|
+
|
|
67
|
+
if len(shape) != len(ref_shape) : #then dimension missmatch
|
|
68
|
+
print("Different number of dimensions found : {0}, {1}".format(len(ref_shape), len(shape)))
|
|
69
|
+
progress_bar.update(current_count=filenumber, bar_color=('red','black'))
|
|
70
|
+
window= window.refresh()
|
|
71
|
+
break
|
|
72
|
+
|
|
73
|
+
window= window.refresh()
|
|
74
|
+
|
|
75
|
+
print("Sanity check completed.")
|
|
76
|
+
return None if len(shape) != len(ref_shape) else shape
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def get_elmt_from_key(Tab_elmt:sg.Tab, key) -> sg.Element:
|
|
80
|
+
elmt_list = sum(Tab_elmt.Rows,[])
|
|
81
|
+
for elmt in elmt_list :
|
|
82
|
+
if elmt.Key == key : return elmt
|
|
83
|
+
raise KeyError("{0} key not found amongst {1}.".format(key, [elmt.Key for elmt in elmt_list]))
|
|
84
|
+
|
|
85
|
+
def update_detection_tab(
|
|
86
|
+
tab_elmt:sg.Tab,
|
|
87
|
+
is_multichannel,
|
|
88
|
+
is_3D,
|
|
89
|
+
do_dense_region_deconvolution,
|
|
90
|
+
do_clustering
|
|
91
|
+
) :
|
|
92
|
+
|
|
93
|
+
#Acess elements
|
|
94
|
+
##Detection
|
|
95
|
+
channel_to_compute = get_elmt_from_key(tab_elmt, key= 'channel to compute')
|
|
96
|
+
voxel_size_z = get_elmt_from_key(tab_elmt, key= 'voxel_size_z')
|
|
97
|
+
spot_size_z = get_elmt_from_key(tab_elmt, key= 'spot_size_z')
|
|
98
|
+
log_kernel_size_z = get_elmt_from_key(tab_elmt, key= 'log_kernel_size_z')
|
|
99
|
+
minimum_distance_z = get_elmt_from_key(tab_elmt, key= 'minimum_distance_z')
|
|
100
|
+
|
|
101
|
+
##Dense regions deconvolution
|
|
102
|
+
alpha = get_elmt_from_key(tab_elmt, key= 'alpha')
|
|
103
|
+
beta = get_elmt_from_key(tab_elmt, key= 'beta')
|
|
104
|
+
gamma = get_elmt_from_key(tab_elmt, key= 'gamma')
|
|
105
|
+
deconvolution_kernel_z = get_elmt_from_key(tab_elmt, key= 'deconvolution_kernel_z')
|
|
106
|
+
cluster_size = get_elmt_from_key(tab_elmt, key= 'cluster size')
|
|
107
|
+
min_number_of_spot = get_elmt_from_key(tab_elmt, key= 'min number of spots')
|
|
108
|
+
nucleus_channel_signal = get_elmt_from_key(tab_elmt, key= 'nucleus channel signal')
|
|
109
|
+
interactive_threshold_selector = get_elmt_from_key(tab_elmt, key= 'Interactive threshold selector')
|
|
110
|
+
|
|
111
|
+
update_dict={
|
|
112
|
+
'is_3D' : is_3D,
|
|
113
|
+
'is_multichannel' : is_multichannel,
|
|
114
|
+
'do_dense_region_deconvolution' : do_dense_region_deconvolution,
|
|
115
|
+
'do_clustering' : do_clustering,
|
|
116
|
+
'always_hidden' : False
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
list_dict={
|
|
120
|
+
'is_3D' : [voxel_size_z, spot_size_z, log_kernel_size_z, minimum_distance_z, deconvolution_kernel_z],
|
|
121
|
+
'is_multichannel' : [channel_to_compute, nucleus_channel_signal],
|
|
122
|
+
'do_dense_region_deconvolution' : [alpha,beta,gamma],
|
|
123
|
+
'do_clustering' : [cluster_size, min_number_of_spot],
|
|
124
|
+
'always_hidden' : [interactive_threshold_selector]
|
|
125
|
+
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
for key, enabled in update_dict.items() :
|
|
129
|
+
for elmt in list_dict.get(key) :
|
|
130
|
+
elmt.update(disabled=not enabled)
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def update_segmentation_tab(tab_elmt : sg.Tab, do_segmentation, is_multichannel) : #TODO
|
|
135
|
+
|
|
136
|
+
#Access elements
|
|
137
|
+
cytoplasm_channel_elmt = get_elmt_from_key(tab_elmt, key= 'cytoplasm channel')
|
|
138
|
+
nucleus_channel_elmt = get_elmt_from_key(tab_elmt, key= 'nucleus channel')
|
|
139
|
+
|
|
140
|
+
#Update values
|
|
141
|
+
tab_elmt.update(visible=do_segmentation)
|
|
142
|
+
cytoplasm_channel_elmt.update(disabled = not is_multichannel)
|
|
143
|
+
nucleus_channel_elmt.update(disabled = not is_multichannel)
|
|
144
|
+
|
|
145
|
+
def update_map_tab() :
|
|
146
|
+
#TODO
|
|
147
|
+
pass
|
|
148
|
+
|
|
149
|
+
def batch_promp() :
|
|
150
|
+
|
|
151
|
+
files_values = [[]]
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
#LOAD FILES
|
|
155
|
+
files_table = sg.Table(values=files_values, headings=['Filenames'], col_widths=100, max_col_width= 200, def_col_width=100, num_rows= 10, auto_size_columns=False)
|
|
156
|
+
|
|
157
|
+
#Start&Stop
|
|
158
|
+
start_button =sg.Button('Start', button_color= 'green', disabled= True)
|
|
159
|
+
stop_button = sg.Button('Cancel', button_color= 'red')
|
|
160
|
+
|
|
161
|
+
#DIMENSION SANITY
|
|
162
|
+
sanity_progress = sg.ProgressBar(10, size_px=(500,10))
|
|
163
|
+
sanity_check_button = sg.Button(
|
|
164
|
+
'Check',
|
|
165
|
+
tooltip= "Will check that all files loaded have the same dimension number and that small fish is able to open them.",
|
|
166
|
+
pad=(10,0))
|
|
167
|
+
sanity_header = sg.Text("Dimension sanity", font=('bold',15), pad=(0,10))
|
|
168
|
+
dimension_number_text = sg.Text("Dimension number : unknown")
|
|
169
|
+
|
|
170
|
+
#Input tab
|
|
171
|
+
input_layout = _input_parameters_layout(
|
|
172
|
+
ask_for_segmentation=True,
|
|
173
|
+
is_3D_stack_preset=False,
|
|
174
|
+
time_stack_preset=False,
|
|
175
|
+
multichannel_preset=False,
|
|
176
|
+
do_dense_regions_deconvolution_preset=False,
|
|
177
|
+
do_clustering_preset=False,
|
|
178
|
+
do_Napari_correction=False,
|
|
179
|
+
do_segmentation_preset=False,
|
|
180
|
+
)
|
|
181
|
+
input_layout += [[sg.Button('Ok')]]
|
|
182
|
+
input_tab = sg.Tab("Input", input_layout)
|
|
183
|
+
|
|
184
|
+
#Maptab
|
|
185
|
+
map_layout = _ask_channel_map_layout(
|
|
186
|
+
shape=(0,1,2,3,4),
|
|
187
|
+
is_3D_stack=True,
|
|
188
|
+
is_time_stack=True,
|
|
189
|
+
multichannel=True,
|
|
190
|
+
)
|
|
191
|
+
last_shape_read = sg.Text("Last shape read : None")
|
|
192
|
+
auto_map = sg.Button("auto-map", disabled=True, pad=(10,0))
|
|
193
|
+
map_layout += [[last_shape_read, auto_map]]
|
|
194
|
+
map_tab = sg.Tab("Map", map_layout)
|
|
195
|
+
|
|
196
|
+
#Segmentation tab
|
|
197
|
+
segmentation_layout = _segmentation_layout(multichannel=True, cytoplasm_model_preset='cyto3')
|
|
198
|
+
segmentation_tab = sg.Tab("Segmentation", segmentation_layout, visible=False)
|
|
199
|
+
|
|
200
|
+
#Detection tab
|
|
201
|
+
detection_layout = _detection_layout(
|
|
202
|
+
is_3D_stack=True,
|
|
203
|
+
is_multichannel=True,
|
|
204
|
+
do_clustering=True,
|
|
205
|
+
do_dense_region_deconvolution=True,
|
|
206
|
+
do_segmentation=True,
|
|
207
|
+
)
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
detection_tab = sg.Tab("Detection", detection_layout)
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
#TABS
|
|
215
|
+
_tab_group = sg.TabGroup([[input_tab, map_tab, segmentation_tab, detection_tab]], enable_events=True)
|
|
216
|
+
tab_group = sg.Column( #Allow the tab to be scrollable
|
|
217
|
+
[[_tab_group]],
|
|
218
|
+
scrollable=True,
|
|
219
|
+
vertical_scroll_only=True,
|
|
220
|
+
pad=(150,5)
|
|
221
|
+
)
|
|
222
|
+
tab_dict= {
|
|
223
|
+
"Input" : input_tab,
|
|
224
|
+
"Segmentation" : segmentation_tab,
|
|
225
|
+
"Detection" : detection_tab,
|
|
226
|
+
"Map" : map_tab,
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
layout = [
|
|
230
|
+
[sg.Text("Batch Processing", font=('bold',20), pad=((300,0),(0,2)))],
|
|
231
|
+
[sg.Text("Select a folder : "), sg.FolderBrowse(initial_folder=os.getcwd(), key='Batch_folder'), sg.Button('Load')],
|
|
232
|
+
[files_table],
|
|
233
|
+
[sanity_header, sanity_check_button, sanity_progress],
|
|
234
|
+
[dimension_number_text],
|
|
235
|
+
[tab_group],
|
|
236
|
+
[sg.Output(size=(100,10), pad=(30,10))],
|
|
237
|
+
[start_button, stop_button],
|
|
238
|
+
]
|
|
239
|
+
|
|
240
|
+
window = sg.Window("small fish", layout=layout, size= (800,800), auto_size_buttons=True, auto_size_text=True)
|
|
241
|
+
loop = 0
|
|
242
|
+
timeout = 1
|
|
243
|
+
while True :
|
|
244
|
+
loop +=1
|
|
245
|
+
window = window.refresh()
|
|
246
|
+
event, values = window.read(timeout=timeout)
|
|
247
|
+
|
|
248
|
+
#Welcome message
|
|
249
|
+
if loop == 1 :
|
|
250
|
+
timeout = None
|
|
251
|
+
print("Welcome to small fish batch analysis. Please start by loading some files and setting parameters.")
|
|
252
|
+
|
|
253
|
+
batch_folder = values.get('Batch_folder')
|
|
254
|
+
is_multichanel = values.get('multichannel')
|
|
255
|
+
is_3D = values.get('3D stack')
|
|
256
|
+
do_segmentation = values.get('Segmentation')
|
|
257
|
+
do_dense_regions_deconvolution = values.get('Dense regions deconvolution')
|
|
258
|
+
do_clustering = values.get('Cluster computation')
|
|
259
|
+
|
|
260
|
+
if type(batch_folder) != type(None) and event == 'Load':
|
|
261
|
+
if not os.path.isdir(batch_folder) :
|
|
262
|
+
print("Can't open {0}".format(batch_folder))
|
|
263
|
+
else :
|
|
264
|
+
files_values = get_files(batch_folder)
|
|
265
|
+
files_table.update(values=files_values)
|
|
266
|
+
|
|
267
|
+
elif event == 'Check' :
|
|
268
|
+
filename_list = extract_files(files_values)
|
|
269
|
+
last_shape = sanity_check(
|
|
270
|
+
filename_list=filename_list,
|
|
271
|
+
batch_folder=batch_folder,
|
|
272
|
+
window=window,
|
|
273
|
+
progress_bar=sanity_progress
|
|
274
|
+
)
|
|
275
|
+
if isinstance(last_shape,(tuple,list)) :
|
|
276
|
+
dim_number = len(last_shape)
|
|
277
|
+
dimension_number_text.update("Dimension number : {0}".format(dim_number))
|
|
278
|
+
auto_map.update(disabled=False)
|
|
279
|
+
else :
|
|
280
|
+
dimension_number_text.update("Dimension number : unknown")
|
|
281
|
+
auto_map.update(disabled=True)
|
|
282
|
+
|
|
283
|
+
last_shape_read.update("Last shape read : {0}".format(last_shape))
|
|
284
|
+
|
|
285
|
+
|
|
286
|
+
elif event == _tab_group.key or event == 'Ok': #Tab switch in parameters
|
|
287
|
+
update_segmentation_tab(
|
|
288
|
+
tab_elmt=tab_dict.get("Segmentation"),
|
|
289
|
+
do_segmentation=do_segmentation,
|
|
290
|
+
is_multichannel=is_multichanel,
|
|
291
|
+
)
|
|
292
|
+
|
|
293
|
+
update_detection_tab(
|
|
294
|
+
tab_elmt=tab_dict.get("Detection"),
|
|
295
|
+
is_multichannel=is_multichanel,
|
|
296
|
+
is_3D=is_3D,
|
|
297
|
+
do_dense_region_deconvolution=do_dense_regions_deconvolution,
|
|
298
|
+
do_clustering=do_clustering,
|
|
299
|
+
)
|
|
300
|
+
|
|
301
|
+
elif event == 'auto-map' :
|
|
302
|
+
#TODO
|
|
303
|
+
pass
|
|
304
|
+
|
|
305
|
+
# elif event == 'apply' (map) #TODO
|
|
306
|
+
|
|
307
|
+
# elif event == 'check parameters' -> un/lock start #TODO
|
|
308
|
+
|
|
309
|
+
elif event == "Cancel" :
|
|
310
|
+
print(values)
|
|
311
|
+
elif event == None :
|
|
312
|
+
quit()
|
small_fish_gui/gui/layout.py
CHANGED
|
@@ -7,9 +7,10 @@ from cellpose.core import use_gpu
|
|
|
7
7
|
sg.theme('DarkAmber')
|
|
8
8
|
|
|
9
9
|
|
|
10
|
-
def add_header(header_text
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
def add_header(header_text) :
|
|
11
|
+
"""Returns [elmnt] not layout"""
|
|
12
|
+
header = [sg.Text('\n{0}'.format(header_text), size= (len(header_text),3), font= 'bold 15')]
|
|
13
|
+
return header
|
|
13
14
|
|
|
14
15
|
|
|
15
16
|
def pad_right(string, length, pad_char) :
|
|
@@ -50,7 +51,7 @@ def parameters_layout(parameters:'list[str]' = [], unit=None, header= None, defa
|
|
|
50
51
|
layout[line_id] += [sg.Text('{0}'.format(unit))]
|
|
51
52
|
|
|
52
53
|
if isinstance(header, str) :
|
|
53
|
-
layout = add_header(header
|
|
54
|
+
layout = [add_header(header)] + layout
|
|
54
55
|
return layout
|
|
55
56
|
|
|
56
57
|
def tuple_layout(opt=None, default_dict={}, unit:dict={}, **tuples) :
|
|
@@ -97,7 +98,7 @@ def path_layout(keys= [],look_for_dir = False, header=None, preset=os.getcwd())
|
|
|
97
98
|
[sg.Text(pad_right(name, max_length, ' ')), Browse(key= name, initial_folder= preset)] for name in keys
|
|
98
99
|
]
|
|
99
100
|
if isinstance(header, str) :
|
|
100
|
-
layout = add_header(header
|
|
101
|
+
layout = [add_header(header)] + layout
|
|
101
102
|
return layout
|
|
102
103
|
|
|
103
104
|
def bool_layout(parameters= [], header=None, preset=None) :
|
|
@@ -118,10 +119,10 @@ def bool_layout(parameters= [], header=None, preset=None) :
|
|
|
118
119
|
[sg.Checkbox(pad_right(name, max_length, ' '), key= name, default=box_preset)] for name, box_preset in zip(parameters,preset)
|
|
119
120
|
]
|
|
120
121
|
if isinstance(header, str) :
|
|
121
|
-
layout = add_header(header
|
|
122
|
+
layout = [add_header(header)] + layout
|
|
122
123
|
return layout
|
|
123
124
|
|
|
124
|
-
def
|
|
125
|
+
def combo_elmt(values, key, header=None, read_only=True, default_value=None) :
|
|
125
126
|
"""
|
|
126
127
|
drop-down list
|
|
127
128
|
"""
|
|
@@ -135,7 +136,7 @@ def combo_layout(values, key, header=None, read_only=True, default_value=None) :
|
|
|
135
136
|
sg.Combo(values, default_value=default_value, readonly=read_only, key=key)
|
|
136
137
|
]
|
|
137
138
|
if isinstance(header, str) :
|
|
138
|
-
layout = add_header(header
|
|
139
|
+
layout = add_header(header) + layout
|
|
139
140
|
return layout
|
|
140
141
|
|
|
141
142
|
def radio_layout(values, header=None) :
|
|
@@ -148,7 +149,7 @@ def radio_layout(values, header=None) :
|
|
|
148
149
|
[sg.Radio(value, group_id= 0) for value in values]
|
|
149
150
|
]
|
|
150
151
|
if isinstance(header, str) :
|
|
151
|
-
layout = add_header(header
|
|
152
|
+
layout = [add_header(header)] + layout
|
|
152
153
|
return layout
|
|
153
154
|
|
|
154
155
|
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',) :
|
|
@@ -162,23 +163,145 @@ def _segmentation_layout(multichannel, cytoplasm_model_preset= 'cyto2', nucleus_
|
|
|
162
163
|
layout = [[sg.Text("GPU is currently "), sg.Text('ON', text_color= 'green') if USE_GPU else sg.Text('OFF', text_color= 'red')]]
|
|
163
164
|
|
|
164
165
|
#cytoplasm parameters
|
|
165
|
-
layout += [
|
|
166
|
-
|
|
166
|
+
layout += [
|
|
167
|
+
add_header("Cell Segmentation"),
|
|
168
|
+
[sg.Text("Choose cellpose model for cytoplasm: \n")],
|
|
169
|
+
combo_elmt(models_list, key='cyto_model_name', default_value= cytoplasm_model_preset)
|
|
167
170
|
]
|
|
168
|
-
|
|
169
|
-
layout +=
|
|
171
|
+
|
|
172
|
+
if multichannel : layout += parameters_layout(['cytoplasm channel'],default_values= [cytoplasm_channel_preset])
|
|
173
|
+
layout += parameters_layout(['cytoplasm diameter'], unit= "px", default_values= [cyto_diameter_preset])
|
|
170
174
|
#Nucleus parameters
|
|
171
175
|
layout += [
|
|
172
|
-
add_header("Nucleus segmentation"
|
|
173
|
-
|
|
176
|
+
add_header("Nucleus segmentation"),
|
|
177
|
+
[sg.Text("Choose cellpose model for nucleus: \n")],
|
|
178
|
+
combo_elmt(models_list, key='nucleus_model_name', default_value= nucleus_model_preset)
|
|
174
179
|
]
|
|
175
|
-
|
|
176
|
-
layout +=
|
|
177
|
-
layout +=
|
|
180
|
+
|
|
181
|
+
if multichannel : layout += parameters_layout(['nucleus channel'], default_values= [nucleus_channel_preset])
|
|
182
|
+
layout += parameters_layout([ 'nucleus diameter'],unit= "px", default_values= [nucleus_diameter_preset])
|
|
183
|
+
layout += bool_layout(["Segment only nuclei"], preset=segment_only_nuclei_preset)
|
|
178
184
|
|
|
179
185
|
#Control plots
|
|
180
|
-
layout +=
|
|
181
|
-
layout +=
|
|
182
|
-
layout +=
|
|
186
|
+
layout += bool_layout(['show segmentation'], header= 'Segmentation plots', preset= show_segmentation_preset)
|
|
187
|
+
layout += path_layout(['saving path'], look_for_dir=True, preset=saving_path_preset)
|
|
188
|
+
layout += parameters_layout(['filename'], default_values=[filename_preset], size= 25)
|
|
189
|
+
|
|
190
|
+
return layout
|
|
191
|
+
|
|
192
|
+
def _input_parameters_layout(
|
|
193
|
+
ask_for_segmentation,
|
|
194
|
+
is_3D_stack_preset,
|
|
195
|
+
time_stack_preset,
|
|
196
|
+
multichannel_preset,
|
|
197
|
+
do_dense_regions_deconvolution_preset,
|
|
198
|
+
do_clustering_preset,
|
|
199
|
+
do_segmentation_preset,
|
|
200
|
+
do_Napari_correction
|
|
201
|
+
|
|
202
|
+
) :
|
|
203
|
+
layout_image_path = path_layout(['image path'], header= "Image")
|
|
204
|
+
layout_image_path += bool_layout(['3D stack', 'multichannel'], preset= [is_3D_stack_preset, time_stack_preset, multichannel_preset])
|
|
205
|
+
|
|
206
|
+
if ask_for_segmentation :
|
|
207
|
+
layout_image_path += bool_layout(
|
|
208
|
+
['Dense regions deconvolution', 'Cluster computation', 'Segmentation', 'Napari correction'],
|
|
209
|
+
preset= [do_dense_regions_deconvolution_preset, do_clustering_preset, do_segmentation_preset, do_Napari_correction],
|
|
210
|
+
header= "Pipeline settings")
|
|
211
|
+
else :
|
|
212
|
+
layout_image_path += bool_layout(
|
|
213
|
+
['Dense regions deconvolution', 'Cluster computation', 'Napari correction'],
|
|
214
|
+
preset= [do_dense_regions_deconvolution_preset, do_clustering_preset, do_Napari_correction],
|
|
215
|
+
header= "Pipeline settings")
|
|
216
|
+
|
|
217
|
+
return layout_image_path
|
|
218
|
+
|
|
219
|
+
def _detection_layout(
|
|
220
|
+
is_3D_stack,
|
|
221
|
+
is_multichannel,
|
|
222
|
+
do_dense_region_deconvolution,
|
|
223
|
+
do_clustering,
|
|
224
|
+
do_segmentation,
|
|
225
|
+
segmentation_done=False,
|
|
226
|
+
default_dict={},
|
|
227
|
+
) :
|
|
228
|
+
if is_3D_stack : dim = 3
|
|
229
|
+
else : dim = 2
|
|
230
|
+
|
|
231
|
+
#Detection
|
|
232
|
+
detection_parameters = ['threshold', 'threshold penalty']
|
|
233
|
+
default_detection = [default_dict.setdefault('threshold',''), default_dict.setdefault('threshold penalty', '1')]
|
|
234
|
+
opt= [True, True]
|
|
235
|
+
if is_multichannel :
|
|
236
|
+
detection_parameters += ['channel to compute']
|
|
237
|
+
opt += [False]
|
|
238
|
+
default_detection += [default_dict.setdefault('channel to compute', '')]
|
|
239
|
+
|
|
240
|
+
layout = [[sg.Text("Green parameters", text_color= 'green'), sg.Text(" are optional parameters.")]]
|
|
241
|
+
layout += parameters_layout(detection_parameters, header= 'Detection', opt=opt, default_values=default_detection)
|
|
242
|
+
|
|
243
|
+
if dim == 2 : tuple_shape = ('y','x')
|
|
244
|
+
else : tuple_shape = ('z','y','x')
|
|
245
|
+
opt = {'voxel_size' : False, 'spot_size' : False, 'log_kernel_size' : True, 'minimum_distance' : True}
|
|
246
|
+
unit = {'voxel_size' : 'nm', 'minimum_distance' : 'nm', 'spot_size' : 'radius(nm)', 'log_kernel_size' : 'px'}
|
|
247
|
+
|
|
248
|
+
layout += tuple_layout(opt=opt, unit=unit, default_dict=default_dict, voxel_size= tuple_shape, spot_size= tuple_shape, log_kernel_size= tuple_shape, minimum_distance= tuple_shape)
|
|
249
|
+
|
|
250
|
+
#Deconvolution
|
|
251
|
+
if do_dense_region_deconvolution :
|
|
252
|
+
default_dense_regions_deconvolution = [default_dict.setdefault('alpha',0.5), default_dict.setdefault('beta',1)]
|
|
253
|
+
layout += parameters_layout(['alpha', 'beta',], default_values= default_dense_regions_deconvolution, header= 'Dense regions deconvolution')
|
|
254
|
+
layout += parameters_layout(['gamma'], unit= 'px', default_values= [default_dict.setdefault('gamma',5)])
|
|
255
|
+
layout += tuple_layout(opt= {"deconvolution_kernel" : True}, unit= {"deconvolution_kernel" : 'px'}, default_dict=default_dict, deconvolution_kernel = tuple_shape)
|
|
256
|
+
|
|
257
|
+
#Clustering
|
|
258
|
+
if do_clustering :
|
|
259
|
+
layout += parameters_layout(['cluster size'], unit="radius(nm)", default_values=[default_dict.setdefault('cluster size',400)])
|
|
260
|
+
layout += parameters_layout(['min number of spots'], default_values=[default_dict.setdefault('min number of spots', 5)])
|
|
261
|
+
|
|
262
|
+
if (do_segmentation and is_multichannel) or (is_multichannel and segmentation_done):
|
|
263
|
+
default_segmentation = [default_dict.setdefault('nucleus channel signal', default_dict.setdefault('nucleus channel',0))]
|
|
264
|
+
layout += parameters_layout(['nucleus channel signal'], default_values=default_segmentation) + [[sg.Text(" channel from which signal will be measured for nucleus features.")]]
|
|
265
|
+
|
|
266
|
+
layout += bool_layout(['Interactive threshold selector'], preset=[False])
|
|
267
|
+
layout += path_layout(
|
|
268
|
+
keys=['spots_extraction_folder'],
|
|
269
|
+
look_for_dir=True,
|
|
270
|
+
header= "Individual spot extraction",
|
|
271
|
+
preset= default_dict.setdefault('spots_extraction_folder', '')
|
|
272
|
+
)
|
|
273
|
+
layout += parameters_layout(
|
|
274
|
+
parameters=['spots_filename'],
|
|
275
|
+
default_values=[default_dict.setdefault('spots_filename','spots_extraction')],
|
|
276
|
+
size= 13
|
|
277
|
+
)
|
|
278
|
+
layout += bool_layout(
|
|
279
|
+
parameters= ['do_spots_csv', 'do_spots_excel', 'do_spots_feather'],
|
|
280
|
+
preset= [default_dict.setdefault('do_spots_csv',False), default_dict.setdefault('do_spots_excel',False),default_dict.setdefault('do_spots_feather',False)]
|
|
281
|
+
)
|
|
282
|
+
|
|
283
|
+
return layout
|
|
284
|
+
|
|
285
|
+
def _ask_channel_map_layout(
|
|
286
|
+
shape,
|
|
287
|
+
is_3D_stack,
|
|
288
|
+
multichannel,
|
|
289
|
+
is_time_stack,
|
|
290
|
+
preset_map={},
|
|
291
|
+
) :
|
|
292
|
+
|
|
293
|
+
x = preset_map.setdefault('x',0)
|
|
294
|
+
y = preset_map.setdefault('y',0)
|
|
295
|
+
z = preset_map.setdefault('z',0)
|
|
296
|
+
c = preset_map.setdefault('c',0)
|
|
297
|
+
t = preset_map.setdefault('t',0)
|
|
298
|
+
|
|
299
|
+
layout = [
|
|
300
|
+
add_header("Dimensions mapping"), [sg.Text("Image shape : {0}".format(shape))]
|
|
301
|
+
]
|
|
302
|
+
layout += parameters_layout(['x','y'], default_values=[x,y])
|
|
303
|
+
if is_3D_stack : layout += parameters_layout(['z'], default_values=[z])
|
|
304
|
+
if multichannel : layout += parameters_layout(['c'], default_values=[c])
|
|
305
|
+
if is_time_stack : layout += parameters_layout(['t'], default_values=[t])
|
|
183
306
|
|
|
184
307
|
return layout
|
small_fish_gui/gui/prompts.py
CHANGED
|
@@ -2,18 +2,24 @@ 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,
|
|
5
|
+
from .layout import path_layout, parameters_layout, bool_layout, tuple_layout, combo_elmt, add_header, path_layout
|
|
6
6
|
from ..interface import open_image, check_format, FormatError
|
|
7
7
|
from .help_module import ask_help
|
|
8
8
|
|
|
9
|
-
def prompt(layout, add_ok_cancel=True, timeout=None, timeout_key='TIMEOUT_KEY') :
|
|
9
|
+
def prompt(layout, add_ok_cancel=True, timeout=None, timeout_key='TIMEOUT_KEY', add_scrollbar=True) :
|
|
10
10
|
"""
|
|
11
11
|
Default event : 'Ok', 'Cancel'
|
|
12
12
|
"""
|
|
13
13
|
if add_ok_cancel : layout += [[sg.Button('Ok'), sg.Button('Cancel')]]
|
|
14
14
|
|
|
15
|
+
if add_scrollbar :
|
|
16
|
+
size = (400,500)
|
|
17
|
+
col_elmt = sg.Column(layout, scrollable=True, vertical_scroll_only=True, size=size)
|
|
18
|
+
layout = [[col_elmt]]
|
|
19
|
+
else :
|
|
20
|
+
size = (None,None)
|
|
15
21
|
|
|
16
|
-
window = sg.Window('small fish', layout=layout, margins=(10,10))
|
|
22
|
+
window = sg.Window('small fish', layout=layout, margins=(10,10), size=size, resizable=True)
|
|
17
23
|
event, values = window.read(timeout=timeout, timeout_key=timeout_key)
|
|
18
24
|
if event == None :
|
|
19
25
|
window.close()
|
|
@@ -26,12 +32,19 @@ def prompt(layout, add_ok_cancel=True, timeout=None, timeout_key='TIMEOUT_KEY')
|
|
|
26
32
|
window.close()
|
|
27
33
|
return event, values
|
|
28
34
|
|
|
29
|
-
def prompt_with_help(layout, help =None) :
|
|
35
|
+
def prompt_with_help(layout, help =None, add_scrollbar=True) :
|
|
30
36
|
layout += [[]]
|
|
31
37
|
layout += [[sg.Button('Help')]]
|
|
32
38
|
layout += [[sg.Button('Ok'), sg.Button('Cancel')]]
|
|
33
39
|
|
|
34
|
-
|
|
40
|
+
if add_scrollbar :
|
|
41
|
+
size = (400,500)
|
|
42
|
+
col_elmt = sg.Column(layout, scrollable=True, vertical_scroll_only=True, size=size)
|
|
43
|
+
layout = [[col_elmt]]
|
|
44
|
+
else :
|
|
45
|
+
size = (None,None)
|
|
46
|
+
|
|
47
|
+
window = sg.Window('small fish', layout=layout, size=size, resizable=True)
|
|
35
48
|
while True :
|
|
36
49
|
event, values = window.read()
|
|
37
50
|
if event == None :
|
|
@@ -79,7 +92,7 @@ def input_image_prompt(
|
|
|
79
92
|
else :
|
|
80
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")
|
|
81
94
|
|
|
82
|
-
event, values = prompt_with_help(layout_image_path, help= 'general')
|
|
95
|
+
event, values = prompt_with_help(layout_image_path, help= 'general', add_scrollbar=False)
|
|
83
96
|
|
|
84
97
|
if event == 'Cancel' :
|
|
85
98
|
return None
|
|
@@ -227,22 +240,6 @@ def detection_parameters_promt(is_3D_stack, is_multichannel, do_dense_region_dec
|
|
|
227
240
|
else : values['dim'] = 2
|
|
228
241
|
return values
|
|
229
242
|
|
|
230
|
-
def post_analysis_prompt() :
|
|
231
|
-
answer = events(['Save results','add_detection', 'colocalisation', 'open results in napari'])
|
|
232
|
-
|
|
233
|
-
return answer
|
|
234
|
-
|
|
235
|
-
def events(event_list) :
|
|
236
|
-
"""
|
|
237
|
-
Return event chose from user
|
|
238
|
-
"""
|
|
239
|
-
|
|
240
|
-
layout = [
|
|
241
|
-
[sg.Button(event) for event in event_list]
|
|
242
|
-
]
|
|
243
|
-
|
|
244
|
-
event, values = prompt(layout, add_ok_cancel= False)
|
|
245
|
-
return event
|
|
246
243
|
|
|
247
244
|
def ask_replace_file(filename:str) :
|
|
248
245
|
layout = [
|
|
@@ -354,4 +351,5 @@ def ask_cancel_detection() :
|
|
|
354
351
|
if event == 'No' :
|
|
355
352
|
return False
|
|
356
353
|
else :
|
|
357
|
-
return True
|
|
354
|
+
return True
|
|
355
|
+
|
small_fish_gui/gui/test.py
CHANGED
|
@@ -199,19 +199,20 @@ def threshold_selection(
|
|
|
199
199
|
"""
|
|
200
200
|
|
|
201
201
|
Viewer = napari.Viewer(title= "Small fish - Threshold selector", ndisplay=2, show=True)
|
|
202
|
+
scale = compute_anisotropy_coef(voxel_size)
|
|
202
203
|
Viewer.add_image(
|
|
203
204
|
data= image,
|
|
204
205
|
contrast_limits= [image.min(), image.max()],
|
|
205
206
|
name= "raw signal",
|
|
206
207
|
colormap= 'green',
|
|
207
|
-
scale=
|
|
208
|
+
scale= scale,
|
|
208
209
|
blending= 'additive'
|
|
209
210
|
)
|
|
210
211
|
Viewer.add_image(
|
|
211
212
|
data= filtered_image,
|
|
212
213
|
contrast_limits= [filtered_image.min(), filtered_image.max()],
|
|
213
214
|
colormap= 'gray',
|
|
214
|
-
scale=
|
|
215
|
+
scale=scale,
|
|
215
216
|
blending='additive'
|
|
216
217
|
)
|
|
217
218
|
|
|
@@ -122,14 +122,13 @@ def _auto_map_channels(image: np.ndarray, is_3D_stack, is_time_stack, multichann
|
|
|
122
122
|
return map
|
|
123
123
|
|
|
124
124
|
def _ask_channel_map(shape, is_3D_stack, is_time_stack, multichannel, preset_map: dict= {}) :
|
|
125
|
-
map = preset_map
|
|
126
125
|
while True :
|
|
127
126
|
relaunch = False
|
|
128
|
-
x =
|
|
129
|
-
y =
|
|
130
|
-
z =
|
|
131
|
-
c =
|
|
132
|
-
t =
|
|
127
|
+
x = preset_map.setdefault('x',0)
|
|
128
|
+
y = preset_map.setdefault('y',0)
|
|
129
|
+
z = preset_map.setdefault('z',0)
|
|
130
|
+
c = preset_map.setdefault('c',0)
|
|
131
|
+
t = preset_map.setdefault('t',0)
|
|
133
132
|
|
|
134
133
|
layout = [
|
|
135
134
|
add_header("Dimensions mapping", [sg.Text("Image shape : {0}".format(shape))])
|
|
@@ -139,12 +138,12 @@ def _ask_channel_map(shape, is_3D_stack, is_time_stack, multichannel, preset_map
|
|
|
139
138
|
if multichannel : layout += [parameters_layout(['c'], default_values=[c])]
|
|
140
139
|
if is_time_stack : layout += [parameters_layout(['t'], default_values=[t])]
|
|
141
140
|
|
|
142
|
-
event,
|
|
141
|
+
event, preset_map = prompt_with_help(layout,help= 'mapping', add_scrollbar=False)
|
|
143
142
|
if event == 'Cancel' : quit()
|
|
144
143
|
|
|
145
144
|
#Check integrity
|
|
146
|
-
channels_values = np.array(list(
|
|
147
|
-
total_channels = len(
|
|
145
|
+
channels_values = np.array(list(preset_map.values()), dtype= int)
|
|
146
|
+
total_channels = len(preset_map)
|
|
148
147
|
unique_channel = len(np.unique(channels_values))
|
|
149
148
|
if total_channels != unique_channel :
|
|
150
149
|
sg.popup("{0} channel(s) are not uniquely mapped.".format(total_channels - unique_channel))
|
|
@@ -154,7 +153,7 @@ def _ask_channel_map(shape, is_3D_stack, is_time_stack, multichannel, preset_map
|
|
|
154
153
|
relaunch= True
|
|
155
154
|
if not relaunch : break
|
|
156
155
|
|
|
157
|
-
return
|
|
156
|
+
return preset_map
|
|
158
157
|
|
|
159
158
|
def _show_mapping(shape, map, is_3D_stack, is_time_stack, multichannel) :
|
|
160
159
|
layout = [
|
|
@@ -166,7 +165,7 @@ def _show_mapping(shape, map, is_3D_stack, is_time_stack, multichannel) :
|
|
|
166
165
|
[sg.Button('Change mapping')]
|
|
167
166
|
]
|
|
168
167
|
|
|
169
|
-
event, values = prompt_with_help(layout, help='mapping')
|
|
168
|
+
event, values = prompt_with_help(layout, help='mapping', add_scrollbar=False)
|
|
170
169
|
|
|
171
170
|
if event == 'Ok' :
|
|
172
171
|
return map
|
|
@@ -170,7 +170,7 @@ def launch_segmentation(image: np.ndarray, user_parameters: dict) :
|
|
|
170
170
|
[sg.Button("Yes"), sg.Button("No")]
|
|
171
171
|
]
|
|
172
172
|
|
|
173
|
-
event, values = prompt(layout=layout, add_ok_cancel=False)
|
|
173
|
+
event, values = prompt(layout=layout, add_ok_cancel=False, add_scrollbar=False)
|
|
174
174
|
if event == "No" :
|
|
175
175
|
continue
|
|
176
176
|
|
|
@@ -8,6 +8,7 @@ from ._signaltonoise import compute_snr_spots
|
|
|
8
8
|
from ._napari_wrapper import correct_spots, _update_clusters, threshold_selection
|
|
9
9
|
from ..gui import add_default_loading
|
|
10
10
|
from ..gui import detection_parameters_promt, input_image_prompt
|
|
11
|
+
from ..utils import compute_anisotropy_coef
|
|
11
12
|
from .spots import compute_Spots
|
|
12
13
|
from magicgui import magicgui
|
|
13
14
|
from napari.layers import Image, Points
|
|
@@ -766,9 +767,11 @@ def _create_threshold_slider(
|
|
|
766
767
|
threshold=threshold
|
|
767
768
|
)[0]
|
|
768
769
|
|
|
770
|
+
scale = compute_anisotropy_coef(voxel_size)
|
|
771
|
+
|
|
769
772
|
layer_args = {
|
|
770
773
|
'size': 5,
|
|
771
|
-
'scale' :
|
|
774
|
+
'scale' : scale,
|
|
772
775
|
'face_color' : 'transparent',
|
|
773
776
|
'edge_color' : 'blue',
|
|
774
777
|
'symbol' : 'ring',
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: small_fish_gui
|
|
3
|
-
Version: 1.3.
|
|
3
|
+
Version: 1.3.5
|
|
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,21 +1,22 @@
|
|
|
1
1
|
small_fish_gui/LICENSE,sha256=-iFy8VGBYs5VsHglKpk4D-hxqQ2jMJaqmfq_ulIzDks,1303
|
|
2
2
|
small_fish_gui/README.md,sha256=2c_homYDJXX6VsBiEs5obhBh3HpcTSMdyjLo-35WzE4,4062
|
|
3
3
|
small_fish_gui/Segmentation example.jpg,sha256=opfiSbjmfF6z8kBs08sg_FNR2Om0AcMPU5sSwSLHdoQ,215038
|
|
4
|
-
small_fish_gui/__init__.py,sha256
|
|
4
|
+
small_fish_gui/__init__.py,sha256=EnnsjHc4PvOZYdCT6JvKMiKDF_I6MMyBvj9TIDeOWco,1941
|
|
5
5
|
small_fish_gui/__main__.py,sha256=EzSCoJ7jpSdK-QbzUwQLGZeQWjybNeq8VnCBucA8MZw,1372
|
|
6
6
|
small_fish_gui/napari_detection_example.png,sha256=l5EZlrbXemLiGqb5inSVsD6Kko1Opz528-go-fBfrw8,977350
|
|
7
7
|
small_fish_gui/requirements.txt,sha256=9OMfUAnLdHevq6w_fVoDmVmkSMJeFofkOK_86_fu9C0,321
|
|
8
8
|
small_fish_gui/utils.py,sha256=tSoMb8N69WdKTtMItPb1DYZiIAz1mjI26BCKJAi6vuc,1798
|
|
9
9
|
small_fish_gui/.github/workflows/python-publish.yml,sha256=5Ltnuhw9TevhzndlBmdUgYMnS73xEAxSyd1u8DHdn5s,1084
|
|
10
|
-
small_fish_gui/gui/__init__.py,sha256=
|
|
10
|
+
small_fish_gui/gui/__init__.py,sha256=xQ_BfYcnQmKZtx_0leO4OmbkLNLv49ZPqEu_UXMgmDc,867
|
|
11
11
|
small_fish_gui/gui/animation.py,sha256=6_Y15_NzJ_TYBYseu3sSKaVkYRp2UCsVClAWOk3dESY,714
|
|
12
|
+
small_fish_gui/gui/batch.py,sha256=aCd3UvzH6ljaWMdjQzOHA_D6QttWYIuv9iDK8iISSdg,10831
|
|
12
13
|
small_fish_gui/gui/general_help_screenshot.png,sha256=X4E6Td5f04K-pBUPDaBJRAE3D5b8fuEdiAUKhkIDr-0,54210
|
|
13
14
|
small_fish_gui/gui/help_module.py,sha256=PmgkkDs7bZ2-po83A_PK9uldQcHjehYmqre21nYb6DQ,9600
|
|
14
|
-
small_fish_gui/gui/layout.py,sha256=
|
|
15
|
+
small_fish_gui/gui/layout.py,sha256=iLlSW40yBKoi4oW0TaWqbMV6ykr3P0Ar2ybf6X7VW3g,13139
|
|
15
16
|
small_fish_gui/gui/mapping_help_screenshot.png,sha256=HcuRh5TYciUogUasza5vZ_QSshaiHsskQK23mh9vQS8,34735
|
|
16
|
-
small_fish_gui/gui/prompts.py,sha256=
|
|
17
|
+
small_fish_gui/gui/prompts.py,sha256=KKDeinZ2qOD-zNDTUndmnff5hDrcwt0B4blkzozr1Wc,13319
|
|
17
18
|
small_fish_gui/gui/segmentation_help_screenshot.png,sha256=rbSgIydT0gZtfMh1qk4mdMbEIyCaakvHmxa2eOrLwO0,118944
|
|
18
|
-
small_fish_gui/gui/test.py,sha256=
|
|
19
|
+
small_fish_gui/gui/test.py,sha256=6P8tnND4wHOE1bF7BGx26wWgE-WjaSCH9Mej7ZzauSg,101
|
|
19
20
|
small_fish_gui/interface/__init__.py,sha256=PB86R4Y9kV80aGZ-vP0ZW2KeaCwGbBbCtFCmbN2yl28,275
|
|
20
21
|
small_fish_gui/interface/image.py,sha256=X1L7S5svxUwdoDcI3QM1PbN-c4Nz5w30hixq3IgqSn8,1130
|
|
21
22
|
small_fish_gui/interface/output.py,sha256=dyhpO1YrRCIbQYpqU_52E1DTNPf0wdktd--CB15iT3k,1712
|
|
@@ -23,16 +24,16 @@ small_fish_gui/interface/parameters.py,sha256=lUugD-4W2TZyJF3TH1q70TlktEYhhPtcPC
|
|
|
23
24
|
small_fish_gui/interface/testing.py,sha256=MY5-GcPOUHagcrwR8A7QOjAmjZIDVC8Wz3NibLe3KQw,321
|
|
24
25
|
small_fish_gui/pipeline/_colocalisation.py,sha256=peBw2Qz5m6wSejDkDz240UgvWl8ohNelrnmEgznbEsw,9635
|
|
25
26
|
small_fish_gui/pipeline/_custom_errors.py,sha256=tQ-AUhgzIFpK30AZiQQrtHCHyGVRDdAoIjzL0Fk-1pA,43
|
|
26
|
-
small_fish_gui/pipeline/_napari_wrapper.py,sha256=
|
|
27
|
-
small_fish_gui/pipeline/_preprocess.py,sha256=
|
|
28
|
-
small_fish_gui/pipeline/_segmentation.py,sha256=
|
|
27
|
+
small_fish_gui/pipeline/_napari_wrapper.py,sha256=_FkkY7IBKn1QgNvyea-x6XPjw_AwsLEVzdRKzg65oCE,9290
|
|
28
|
+
small_fish_gui/pipeline/_preprocess.py,sha256=cbgXUx8yn3Wi_R7hFy64VuEXbbTbYw9p0qKG9cigyaM,10760
|
|
29
|
+
small_fish_gui/pipeline/_segmentation.py,sha256=abltW2dKHarpDvM45TgkSJ4OzQV-b63VnA1PK4w1C_g,12998
|
|
29
30
|
small_fish_gui/pipeline/_signaltonoise.py,sha256=7A9t7xu7zghI6cr201Ldm-LjJ5NOuP56VSeJ8KIzcUo,8497
|
|
30
31
|
small_fish_gui/pipeline/actions.py,sha256=EIGIOlwJ_DADX1NcLWwrTP_AidDX-4f4ggZV0gkIb58,7988
|
|
31
|
-
small_fish_gui/pipeline/detection.py,sha256=
|
|
32
|
+
small_fish_gui/pipeline/detection.py,sha256=yMD9PGLJHH96PpXQRWbB5gv1EwQhtMWQ1a95g_0WU0E,32075
|
|
32
33
|
small_fish_gui/pipeline/main.py,sha256=AAW-zK3b7Ece9cdHn9y6QG8lTa1HXG-8JtnvJ3m0HwA,3149
|
|
33
34
|
small_fish_gui/pipeline/spots.py,sha256=yHvqf1eD25UltELpzcouYXhLkxiXI_mOL1ANSzXK5pw,1907
|
|
34
35
|
small_fish_gui/pipeline/test.py,sha256=w4ZMGDmUDXxVgWTlZ2TKw19W8q5gcE9gLMKe0SWnRrw,2827
|
|
35
|
-
small_fish_gui-1.3.
|
|
36
|
-
small_fish_gui-1.3.
|
|
37
|
-
small_fish_gui-1.3.
|
|
38
|
-
small_fish_gui-1.3.
|
|
36
|
+
small_fish_gui-1.3.5.dist-info/METADATA,sha256=K4HY1GO44LtO6PXUZmK3_jNNFmDXMsS9LpWa3l8WDB8,2567
|
|
37
|
+
small_fish_gui-1.3.5.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
|
|
38
|
+
small_fish_gui-1.3.5.dist-info/licenses/LICENSE,sha256=-iFy8VGBYs5VsHglKpk4D-hxqQ2jMJaqmfq_ulIzDks,1303
|
|
39
|
+
small_fish_gui-1.3.5.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|