small-fish-gui 1.0.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/__init__.py +41 -0
- small_fish_gui/__main__.py +15 -0
- small_fish_gui/gui/__init__.py +29 -0
- small_fish_gui/gui/animation.py +30 -0
- small_fish_gui/gui/general_help_screenshot.png +0 -0
- small_fish_gui/gui/help_module.py +256 -0
- small_fish_gui/gui/layout.py +184 -0
- small_fish_gui/gui/mapping_help_screenshot.png +0 -0
- small_fish_gui/gui/prompts.py +338 -0
- small_fish_gui/gui/segmentation_help_screenshot.png +0 -0
- small_fish_gui/gui/test.py +4 -0
- small_fish_gui/interface/__init__.py +10 -0
- small_fish_gui/interface/image.py +38 -0
- small_fish_gui/interface/output.py +42 -0
- small_fish_gui/interface/parameters.py +2 -0
- small_fish_gui/interface/testing.py +8 -0
- small_fish_gui/pipeline/_colocalisation.py +266 -0
- small_fish_gui/pipeline/_custom_errors.py +2 -0
- small_fish_gui/pipeline/_detection_visualisation.py +139 -0
- small_fish_gui/pipeline/_preprocess.py +272 -0
- small_fish_gui/pipeline/_segmentation.py +334 -0
- small_fish_gui/pipeline/_signaltonoise.py +219 -0
- small_fish_gui/pipeline/actions.py +127 -0
- small_fish_gui/pipeline/detection.py +640 -0
- small_fish_gui/pipeline/main.py +80 -0
- small_fish_gui/pipeline/test.py +116 -0
- small_fish_gui/start.py +7 -0
- small_fish_gui/utils.py +55 -0
- small_fish_gui-1.0.0.dist-info/METADATA +57 -0
- small_fish_gui-1.0.0.dist-info/RECORD +32 -0
- small_fish_gui-1.0.0.dist-info/WHEEL +4 -0
- small_fish_gui-1.0.0.dist-info/licenses/LICENSE +24 -0
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
import PySimpleGUI as sg
|
|
2
|
+
import pandas as pd
|
|
3
|
+
import os
|
|
4
|
+
from .layout import path_layout, parameters_layout, bool_layout, tuple_layout, combo_layout, add_header
|
|
5
|
+
from ..interface import open_image, check_format, FormatError
|
|
6
|
+
from .help_module import ask_help
|
|
7
|
+
|
|
8
|
+
def prompt(layout, add_ok_cancel=True, timeout=None, timeout_key='TIMEOUT_KEY') :
|
|
9
|
+
"""
|
|
10
|
+
Default event : 'Ok', 'Cancel'
|
|
11
|
+
"""
|
|
12
|
+
if add_ok_cancel : layout += [[sg.Button('Ok'), sg.Button('Cancel')]]
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
window = sg.Window('small fish', layout=layout, margins=(10,10))
|
|
16
|
+
event, values = window.read(timeout=timeout, timeout_key=timeout_key)
|
|
17
|
+
if event == None :
|
|
18
|
+
window.close()
|
|
19
|
+
quit()
|
|
20
|
+
|
|
21
|
+
elif event == 'Cancel' :
|
|
22
|
+
window.close()
|
|
23
|
+
return event,{}
|
|
24
|
+
else :
|
|
25
|
+
window.close()
|
|
26
|
+
return event, values
|
|
27
|
+
|
|
28
|
+
def prompt_with_help(layout, help =None) :
|
|
29
|
+
layout += [[]]
|
|
30
|
+
layout += [[sg.Button('Help')]]
|
|
31
|
+
layout += [[sg.Button('Ok'), sg.Button('Cancel')]]
|
|
32
|
+
|
|
33
|
+
window = sg.Window('small fish', layout=layout)
|
|
34
|
+
while True :
|
|
35
|
+
event, values = window.read()
|
|
36
|
+
if event == None :
|
|
37
|
+
window.close()
|
|
38
|
+
quit()
|
|
39
|
+
|
|
40
|
+
elif event == 'Ok':
|
|
41
|
+
window.close()
|
|
42
|
+
return event, values
|
|
43
|
+
elif event == 'Help' :
|
|
44
|
+
ask_help(chapter= help)
|
|
45
|
+
|
|
46
|
+
else:
|
|
47
|
+
window.close()
|
|
48
|
+
return event,{}
|
|
49
|
+
|
|
50
|
+
def input_image_prompt(
|
|
51
|
+
is_3D_stack_preset=False,
|
|
52
|
+
time_stack_preset=False,
|
|
53
|
+
multichannel_preset = False,
|
|
54
|
+
do_dense_regions_deconvolution_preset= False,
|
|
55
|
+
do_clustering_preset = False,
|
|
56
|
+
do_segmentation_preset= False,
|
|
57
|
+
do_Napari_correction= False,
|
|
58
|
+
ask_for_segmentation= True
|
|
59
|
+
) :
|
|
60
|
+
"""
|
|
61
|
+
Keys :
|
|
62
|
+
- 'image path'
|
|
63
|
+
- '3D stack'
|
|
64
|
+
- 'time stack'
|
|
65
|
+
- 'multichannel'
|
|
66
|
+
- 'Dense regions deconvolution'
|
|
67
|
+
- 'Segmentation'
|
|
68
|
+
- 'Napari correction'
|
|
69
|
+
|
|
70
|
+
Returns Values
|
|
71
|
+
|
|
72
|
+
"""
|
|
73
|
+
layout_image_path = path_layout(['image path'], header= "Image")
|
|
74
|
+
layout_image_path += bool_layout(['3D stack', 'time stack', 'multichannel'], preset= [is_3D_stack_preset, time_stack_preset, multichannel_preset])
|
|
75
|
+
|
|
76
|
+
if ask_for_segmentation :
|
|
77
|
+
layout_image_path += bool_layout(['Dense regions deconvolution', 'Cluster computation', 'Segmentation', 'Napari correction'], preset= [do_dense_regions_deconvolution_preset, do_clustering_preset, do_segmentation_preset, do_Napari_correction], header= "Pipeline settings")
|
|
78
|
+
else :
|
|
79
|
+
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")
|
|
80
|
+
|
|
81
|
+
event, values = prompt_with_help(layout_image_path, help= 'general')
|
|
82
|
+
|
|
83
|
+
if event == 'Cancel' :
|
|
84
|
+
return None
|
|
85
|
+
|
|
86
|
+
im_path = values['image path']
|
|
87
|
+
is_3D_stack = values['3D stack']
|
|
88
|
+
is_time_stack = values['time stack']
|
|
89
|
+
is_multichannel = values['multichannel']
|
|
90
|
+
if not ask_for_segmentation : values['Segmentation'] = False
|
|
91
|
+
|
|
92
|
+
if is_time_stack :
|
|
93
|
+
sg.popup("Sorry time stack images are not yet supported.")
|
|
94
|
+
return values
|
|
95
|
+
|
|
96
|
+
try :
|
|
97
|
+
image = open_image(im_path)
|
|
98
|
+
check_format(image, is_3D_stack, is_time_stack, is_multichannel)
|
|
99
|
+
values.update({'image' : image})
|
|
100
|
+
except FormatError as error:
|
|
101
|
+
sg.popup("Inconsistency between image format and options selected.\n Image shape : {0}".format(image.shape))
|
|
102
|
+
except OSError as error :
|
|
103
|
+
sg.popup('Image format not supported.')
|
|
104
|
+
except ValueError as error :
|
|
105
|
+
sg.popup('Image format not supported.')
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
return values
|
|
109
|
+
|
|
110
|
+
def output_image_prompt(filename) :
|
|
111
|
+
while True :
|
|
112
|
+
relaunch = False
|
|
113
|
+
layout = path_layout(['folder'], look_for_dir= True, header= "Output parameters :")
|
|
114
|
+
layout += parameters_layout(["filename"], default_values= [filename + "_quantification"], size=25)
|
|
115
|
+
layout += bool_layout(['Excel', 'Feather'])
|
|
116
|
+
layout.append([sg.Button('Cancel')])
|
|
117
|
+
|
|
118
|
+
event,values= prompt(layout)
|
|
119
|
+
|
|
120
|
+
values['filename'] = values['filename'].replace(".xlsx","")
|
|
121
|
+
values['filename'] = values['filename'].replace(".feather","")
|
|
122
|
+
excel_filename = values['filename'] + ".xlsx"
|
|
123
|
+
feather_filename = values['filename'] + ".feather"
|
|
124
|
+
|
|
125
|
+
if not values['Excel'] and not values['Feather'] :
|
|
126
|
+
sg.popup("Please check at least one box : Excel/Feather")
|
|
127
|
+
relaunch = True
|
|
128
|
+
elif not os.path.isdir(values['folder']) :
|
|
129
|
+
sg.popup("Incorrect folder")
|
|
130
|
+
relaunch = True
|
|
131
|
+
elif os.path.isfile(values['folder'] + excel_filename) and values['Excel']:
|
|
132
|
+
if ask_replace_file(excel_filename) :
|
|
133
|
+
pass
|
|
134
|
+
else :
|
|
135
|
+
relaunch = True
|
|
136
|
+
elif os.path.isfile(values['folder'] + feather_filename) and values['Feather']:
|
|
137
|
+
if ask_replace_file(feather_filename) :
|
|
138
|
+
pass
|
|
139
|
+
else :
|
|
140
|
+
relaunch = True
|
|
141
|
+
|
|
142
|
+
if not relaunch : break
|
|
143
|
+
|
|
144
|
+
if event == ('Cancel') : return None
|
|
145
|
+
|
|
146
|
+
else : return values
|
|
147
|
+
|
|
148
|
+
def detection_parameters_promt(is_3D_stack, is_multichannel, do_dense_region_deconvolution, do_clustering, do_segmentation, segmentation_done, default_dict: dict) :
|
|
149
|
+
"""
|
|
150
|
+
|
|
151
|
+
keys :
|
|
152
|
+
- 'threshold'
|
|
153
|
+
- 'threshold penalty
|
|
154
|
+
- 'time step'
|
|
155
|
+
- 'channel to compute'
|
|
156
|
+
- 'alpha'
|
|
157
|
+
- 'beta'
|
|
158
|
+
- 'gamma'
|
|
159
|
+
- 'voxel_size_{(z,y,x)}'
|
|
160
|
+
- 'spot_size{(z,y,x)}'
|
|
161
|
+
- 'log_kernel_size{(z,y,x)}'
|
|
162
|
+
- 'minimum_distance{(z,y,x)}'
|
|
163
|
+
- 'cluster size'
|
|
164
|
+
- 'min number of spots'
|
|
165
|
+
|
|
166
|
+
Returns Values
|
|
167
|
+
|
|
168
|
+
"""
|
|
169
|
+
if is_3D_stack : dim = 3
|
|
170
|
+
else : dim = 2
|
|
171
|
+
|
|
172
|
+
#Detection
|
|
173
|
+
detection_parameters = ['threshold', 'threshold penalty']
|
|
174
|
+
default_detection = [default_dict.setdefault('threshold',''), default_dict.setdefault('threshold penalty', '1')]
|
|
175
|
+
opt= [True, True]
|
|
176
|
+
if is_multichannel :
|
|
177
|
+
detection_parameters += ['channel to compute']
|
|
178
|
+
opt += [False]
|
|
179
|
+
default_detection += [default_dict.setdefault('channel to compute', '')]
|
|
180
|
+
layout = [[sg.Text("Green parameters", text_color= 'green'), sg.Text(" are optional parameters.")]]
|
|
181
|
+
layout += parameters_layout(detection_parameters, header= 'Detection', opt=opt, default_values=default_detection)
|
|
182
|
+
|
|
183
|
+
if dim == 2 : tuple_shape = ('y','x')
|
|
184
|
+
else : tuple_shape = ('z','y','x')
|
|
185
|
+
opt = {'voxel_size' : False, 'spot_size' : False, 'log_kernel_size' : True, 'minimum_distance' : True}
|
|
186
|
+
unit = {'voxel_size' : 'nm', 'minimum_distance' : 'nm', 'spot_size' : 'radius(nm)', 'log_kernel_size' : 'px'}
|
|
187
|
+
|
|
188
|
+
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)
|
|
189
|
+
|
|
190
|
+
#Deconvolution
|
|
191
|
+
if do_dense_region_deconvolution :
|
|
192
|
+
default_dense_regions_deconvolution = [default_dict.setdefault('alpha',0.5), default_dict.setdefault('beta',1)]
|
|
193
|
+
layout += parameters_layout(['alpha', 'beta',], default_values= default_dense_regions_deconvolution, header= 'Dense regions deconvolution')
|
|
194
|
+
layout += parameters_layout(['gamma'], unit= 'px', default_values= [default_dict.setdefault('gamma',5)])
|
|
195
|
+
layout += tuple_layout(opt= {"deconvolution_kernel" : True}, unit= {"deconvolution_kernel" : 'px'}, default_dict=default_dict, deconvolution_kernel = tuple_shape)
|
|
196
|
+
|
|
197
|
+
#Clustering
|
|
198
|
+
if do_clustering :
|
|
199
|
+
layout += parameters_layout(['cluster size'], unit="radius(nm)", default_values=[default_dict.setdefault('cluster size',400)])
|
|
200
|
+
layout += parameters_layout(['min number of spots'], default_values=[default_dict.setdefault('min number of spots', 5)])
|
|
201
|
+
|
|
202
|
+
if (do_segmentation and is_multichannel) or (is_multichannel and segmentation_done):
|
|
203
|
+
default_segmentation = [default_dict.setdefault('nucleus channel signal', default_dict.setdefault('nucleus channel',0))]
|
|
204
|
+
layout += parameters_layout(['nucleus channel signal'], default_values=default_segmentation) + [[sg.Text(" channel from which signal will be measured for nucleus features.")]]
|
|
205
|
+
|
|
206
|
+
event, values = prompt_with_help(layout, help='detection')
|
|
207
|
+
if event == 'Cancel' : return None
|
|
208
|
+
if is_3D_stack : values['dim'] = 3
|
|
209
|
+
else : values['dim'] = 2
|
|
210
|
+
return values
|
|
211
|
+
|
|
212
|
+
def post_analysis_prompt() :
|
|
213
|
+
answer = events(['Save results','add_detection', 'colocalisation', 'open results in napari'])
|
|
214
|
+
|
|
215
|
+
return answer
|
|
216
|
+
|
|
217
|
+
def events(event_list) :
|
|
218
|
+
"""
|
|
219
|
+
Return event chose from user
|
|
220
|
+
"""
|
|
221
|
+
|
|
222
|
+
layout = [
|
|
223
|
+
[sg.Button(event) for event in event_list]
|
|
224
|
+
]
|
|
225
|
+
|
|
226
|
+
event, values = prompt(layout, add_ok_cancel= False)
|
|
227
|
+
return event
|
|
228
|
+
|
|
229
|
+
def ask_replace_file(filename:str) :
|
|
230
|
+
layout = [
|
|
231
|
+
[sg.Text("{0} already exists, replace ?")],
|
|
232
|
+
[sg.Button('Yes'), sg.Button('No')]
|
|
233
|
+
]
|
|
234
|
+
|
|
235
|
+
event, values = prompt(layout, add_ok_cancel= False)
|
|
236
|
+
|
|
237
|
+
return event == 'Yes'
|
|
238
|
+
|
|
239
|
+
def ask_cancel_segmentation() :
|
|
240
|
+
layout = [
|
|
241
|
+
[sg.Text("Cancel segmentation ?")],
|
|
242
|
+
[sg.Button('Yes'), sg.Button('No')]
|
|
243
|
+
]
|
|
244
|
+
|
|
245
|
+
event, values = prompt(layout, add_ok_cancel= False)
|
|
246
|
+
|
|
247
|
+
return event == 'Yes'
|
|
248
|
+
|
|
249
|
+
def ask_quit_small_fish() :
|
|
250
|
+
layout = [
|
|
251
|
+
[sg.Text("Quit small fish ?")],
|
|
252
|
+
[sg.Button('Yes'), sg.Button('No')]
|
|
253
|
+
]
|
|
254
|
+
|
|
255
|
+
event, values = prompt(layout, add_ok_cancel= False)
|
|
256
|
+
|
|
257
|
+
return event == 'Yes'
|
|
258
|
+
|
|
259
|
+
def _error_popup(error:Exception) :
|
|
260
|
+
sg.popup('Error : ' + str(error))
|
|
261
|
+
raise error
|
|
262
|
+
|
|
263
|
+
def _warning_popup(warning:str) :
|
|
264
|
+
sg.popup('Warning : ' + warning)
|
|
265
|
+
|
|
266
|
+
def _sumup_df(results: pd.DataFrame) :
|
|
267
|
+
|
|
268
|
+
if len(results) > 0 :
|
|
269
|
+
res = results.loc[:,['acquisition_id', 'spot_number', 'cell_number', 'filename', 'channel to compute']]
|
|
270
|
+
else :
|
|
271
|
+
res = pd.DataFrame(columns= ['acquisition_id', 'spot_number', 'cell_number', 'filename', 'channel to compute'])
|
|
272
|
+
|
|
273
|
+
return res
|
|
274
|
+
|
|
275
|
+
def hub_prompt(fov_results, do_segmentation=False) :
|
|
276
|
+
|
|
277
|
+
sumup_df = _sumup_df(fov_results)
|
|
278
|
+
|
|
279
|
+
if do_segmentation :
|
|
280
|
+
segmentation_object = sg.Text('Segmentation was performed', font='8', text_color= 'green')
|
|
281
|
+
else :
|
|
282
|
+
segmentation_object = sg.Text('Segmentation was not performed', font='8', text_color= 'red')
|
|
283
|
+
|
|
284
|
+
layout = [
|
|
285
|
+
[sg.Text('RESULTS', font= 'bold 13')],
|
|
286
|
+
[sg.Table(values= list(sumup_df.values), headings= list(sumup_df.columns), row_height=20, num_rows= 5, vertical_scroll_only=False, key= "result_table"), segmentation_object],
|
|
287
|
+
[sg.Button('Add detection'), sg.Button('Compute colocalisation'), sg.Button('Batch detection')],
|
|
288
|
+
# [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')]
|
|
289
|
+
[sg.Button('Save results', button_color= 'green'), sg.Button('Reset results',button_color= 'gray')]
|
|
290
|
+
]
|
|
291
|
+
|
|
292
|
+
window = sg.Window('small fish', layout= layout, margins= (10,10))
|
|
293
|
+
|
|
294
|
+
while True :
|
|
295
|
+
event, values = window.read()
|
|
296
|
+
if event == None : quit()
|
|
297
|
+
elif event == 'Help' : pass
|
|
298
|
+
else :
|
|
299
|
+
window.close()
|
|
300
|
+
return event, values
|
|
301
|
+
|
|
302
|
+
def coloc_prompt() :
|
|
303
|
+
layout = [
|
|
304
|
+
[parameters_layout(['colocalisation distance'], header= 'Colocalisation', default_values= 0)]
|
|
305
|
+
]
|
|
306
|
+
|
|
307
|
+
event, values = prompt_with_help(layout)
|
|
308
|
+
|
|
309
|
+
if event == 'Ok' :
|
|
310
|
+
return values['colocalisation distance']
|
|
311
|
+
else : return False
|
|
312
|
+
|
|
313
|
+
def ask_detection_confirmation(used_threshold) :
|
|
314
|
+
layout = [
|
|
315
|
+
[sg.Text("Proceed with current detection ?", font= 'bold 10')],
|
|
316
|
+
[sg.Text("Threshold : {0}".format(used_threshold))],
|
|
317
|
+
[sg.Button("Ok"), sg.Button("Restart detection")]
|
|
318
|
+
]
|
|
319
|
+
|
|
320
|
+
event, value = prompt(layout, add_ok_cancel=False)
|
|
321
|
+
|
|
322
|
+
if event == 'Restart detection' :
|
|
323
|
+
return False
|
|
324
|
+
else :
|
|
325
|
+
return True
|
|
326
|
+
|
|
327
|
+
def ask_cancel_detection() :
|
|
328
|
+
layout =[
|
|
329
|
+
[sg.Text("Cancel new detection and return to main window ?", font= 'bold 10')],
|
|
330
|
+
[sg.Button("Yes"), sg.Button("No")]
|
|
331
|
+
]
|
|
332
|
+
|
|
333
|
+
event, value = prompt(layout, add_ok_cancel=False)
|
|
334
|
+
|
|
335
|
+
if event == 'No' :
|
|
336
|
+
return False
|
|
337
|
+
else :
|
|
338
|
+
return True
|
|
Binary file
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This code handles the exchange between the computer and the code. That is to say opening and saving data.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from .image import open_image
|
|
6
|
+
from .image import get_filename
|
|
7
|
+
from .image import check_format
|
|
8
|
+
from .image import FormatError
|
|
9
|
+
|
|
10
|
+
from .output import write_results
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
from bigfish.stack import read_image
|
|
2
|
+
from czifile import imread
|
|
3
|
+
from ..utils import check_parameter
|
|
4
|
+
import re
|
|
5
|
+
|
|
6
|
+
class FormatError(Exception):
|
|
7
|
+
pass
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def open_image(full_path:str) :
|
|
11
|
+
if full_path.endswith('.czi') : im = imread(full_path)
|
|
12
|
+
else : im = read_image(full_path)
|
|
13
|
+
|
|
14
|
+
reshape = []
|
|
15
|
+
for axis in im.shape :
|
|
16
|
+
if axis != 1 : reshape.append(axis)
|
|
17
|
+
im = im.reshape(reshape)
|
|
18
|
+
|
|
19
|
+
return im
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def check_format(image, is_3D, is_time_stack, is_multichannel) :
|
|
23
|
+
shape = list(image.shape)
|
|
24
|
+
dim = image.ndim - (shape[image.ndim - 1] == 1)
|
|
25
|
+
if not dim == (2 + is_3D + is_time_stack + is_multichannel) :
|
|
26
|
+
raise FormatError("Inconsistency in image format and parameters.")
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def get_filename(full_path: str) :
|
|
31
|
+
check_parameter(full_path=str)
|
|
32
|
+
|
|
33
|
+
pattern = r'.*\/(.+)\..*$'
|
|
34
|
+
if not full_path.startswith('/') : full_path = '/' + full_path
|
|
35
|
+
re_match = re.findall(pattern, full_path)
|
|
36
|
+
if len(re_match) == 0 : raise ValueError("Could not read filename from image full path.")
|
|
37
|
+
if len(re_match) == 1 : return re_match[0]
|
|
38
|
+
else : raise AssertionError("Several filenames read from path")
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import pandas as pd
|
|
3
|
+
from bigfish.stack import check_parameter
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def _cast_spot_to_tuple(spot) :
|
|
8
|
+
return tuple([coord for coord in spot])
|
|
9
|
+
|
|
10
|
+
def _cast_spots_to_tuple(spots) :
|
|
11
|
+
return tuple(list(map(_cast_spot_to_tuple, spots)))
|
|
12
|
+
|
|
13
|
+
def write_results(dataframe: pd.DataFrame, path:str, filename:str, do_excel= True, do_feather= False) :
|
|
14
|
+
check_parameter(dataframe= pd.DataFrame, path= str, filename = str, do_excel = bool, do_feather = bool)
|
|
15
|
+
|
|
16
|
+
if len(dataframe) == 0 : return True
|
|
17
|
+
if not do_excel and not do_feather :
|
|
18
|
+
return False
|
|
19
|
+
|
|
20
|
+
if not path.endswith('/') : path +='/'
|
|
21
|
+
assert os.path.isdir(path)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
new_filename = filename
|
|
25
|
+
i= 1
|
|
26
|
+
while new_filename + '.xlsx' in os.listdir(path) or new_filename + '.feather' in os.listdir(path) :
|
|
27
|
+
new_filename = filename + '_{0}'.format(i)
|
|
28
|
+
i+=1
|
|
29
|
+
|
|
30
|
+
if 'image' in dataframe.columns :
|
|
31
|
+
dataframe = dataframe.drop(['image'], axis=1)
|
|
32
|
+
|
|
33
|
+
if 'spots' in dataframe.columns :
|
|
34
|
+
dataframe = dataframe.drop(['spots'], axis= 1)
|
|
35
|
+
|
|
36
|
+
if 'clusters' in dataframe.columns :
|
|
37
|
+
dataframe = dataframe.drop(['clusters'], axis= 1)
|
|
38
|
+
|
|
39
|
+
if do_excel : dataframe.reset_index(drop=True).to_excel(path + filename + '.xlsx')
|
|
40
|
+
if do_feather : dataframe.reset_index(drop=True).to_feather(path + filename + '.feather')
|
|
41
|
+
|
|
42
|
+
return True
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import imageio.v3 as iio
|
|
2
|
+
|
|
3
|
+
path = '/home/flo/Documents/IGH projects/SohaQuantif/SCC/input/230723 n1 b-cat bac APC IF fitc ires neo smfish cy3 without puromycin-01.tif'
|
|
4
|
+
|
|
5
|
+
props = iio.improps(path)
|
|
6
|
+
meta = iio.immeta(path)
|
|
7
|
+
print(props)
|
|
8
|
+
print(meta['channels'], meta['slices'], meta['unit'], meta['hyperstack'], meta['spacing'])
|