small-fish-gui 1.5.0__tar.gz → 1.7.0__tar.gz
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-1.5.0 → small_fish_gui-1.7.0}/PKG-INFO +1 -1
- {small_fish_gui-1.5.0 → small_fish_gui-1.7.0}/pyproject.toml +1 -1
- {small_fish_gui-1.5.0 → small_fish_gui-1.7.0}/src/small_fish_gui/__init__.py +1 -1
- {small_fish_gui-1.5.0 → small_fish_gui-1.7.0}/src/small_fish_gui/__main__.py +3 -3
- small_fish_gui-1.7.0/src/small_fish_gui/gui/_napari_widgets.py +93 -0
- small_fish_gui-1.5.0/src/small_fish_gui/pipeline/_napari_wrapper.py → small_fish_gui-1.7.0/src/small_fish_gui/gui/napari.py +43 -21
- {small_fish_gui-1.5.0 → small_fish_gui-1.7.0}/src/small_fish_gui/gui/prompts.py +12 -8
- {small_fish_gui-1.5.0 → small_fish_gui-1.7.0}/src/small_fish_gui/interface/output.py +18 -14
- small_fish_gui-1.7.0/src/small_fish_gui/pipeline/_colocalisation.py +429 -0
- {small_fish_gui-1.5.0 → small_fish_gui-1.7.0}/src/small_fish_gui/pipeline/_segmentation.py +2 -2
- {small_fish_gui-1.5.0 → small_fish_gui-1.7.0}/src/small_fish_gui/pipeline/actions.py +77 -14
- {small_fish_gui-1.5.0 → small_fish_gui-1.7.0}/src/small_fish_gui/pipeline/detection.py +15 -4
- {small_fish_gui-1.5.0 → small_fish_gui-1.7.0}/src/small_fish_gui/pipeline/main.py +41 -14
- small_fish_gui-1.5.0/src/small_fish_gui/pipeline/_colocalisation.py +0 -266
- {small_fish_gui-1.5.0 → small_fish_gui-1.7.0}/LICENSE +0 -0
- {small_fish_gui-1.5.0 → small_fish_gui-1.7.0}/README.md +0 -0
- {small_fish_gui-1.5.0 → small_fish_gui-1.7.0}/src/small_fish_gui/.github/workflows/python-publish.yml +0 -0
- {small_fish_gui-1.5.0 → small_fish_gui-1.7.0}/src/small_fish_gui/.readthedocs.yaml +0 -0
- {small_fish_gui-1.5.0 → small_fish_gui-1.7.0}/src/small_fish_gui/LICENSE +0 -0
- {small_fish_gui-1.5.0 → small_fish_gui-1.7.0}/src/small_fish_gui/README.md +0 -0
- {small_fish_gui-1.5.0 → small_fish_gui-1.7.0}/src/small_fish_gui/Segmentation example.jpg +0 -0
- {small_fish_gui-1.5.0 → small_fish_gui-1.7.0}/src/small_fish_gui/batch/__init__.py +0 -0
- {small_fish_gui-1.5.0 → small_fish_gui-1.7.0}/src/small_fish_gui/batch/input.py +0 -0
- {small_fish_gui-1.5.0 → small_fish_gui-1.7.0}/src/small_fish_gui/batch/integrity.py +0 -0
- {small_fish_gui-1.5.0 → small_fish_gui-1.7.0}/src/small_fish_gui/batch/output.py +0 -0
- {small_fish_gui-1.5.0 → small_fish_gui-1.7.0}/src/small_fish_gui/batch/pipeline.py +0 -0
- {small_fish_gui-1.5.0 → small_fish_gui-1.7.0}/src/small_fish_gui/batch/prompt.py +0 -0
- {small_fish_gui-1.5.0 → small_fish_gui-1.7.0}/src/small_fish_gui/batch/test.py +0 -0
- {small_fish_gui-1.5.0 → small_fish_gui-1.7.0}/src/small_fish_gui/batch/update.py +0 -0
- {small_fish_gui-1.5.0 → small_fish_gui-1.7.0}/src/small_fish_gui/batch/utils.py +0 -0
- {small_fish_gui-1.5.0 → small_fish_gui-1.7.0}/src/small_fish_gui/batch/values.py +0 -0
- {small_fish_gui-1.5.0 → small_fish_gui-1.7.0}/src/small_fish_gui/batch/values.txt +0 -0
- {small_fish_gui-1.5.0 → small_fish_gui-1.7.0}/src/small_fish_gui/docs/conf.py +0 -0
- {small_fish_gui-1.5.0 → small_fish_gui-1.7.0}/src/small_fish_gui/gui/__init__.py +0 -0
- {small_fish_gui-1.5.0 → small_fish_gui-1.7.0}/src/small_fish_gui/gui/animation.py +0 -0
- {small_fish_gui-1.5.0 → small_fish_gui-1.7.0}/src/small_fish_gui/gui/general_help_screenshot.png +0 -0
- {small_fish_gui-1.5.0 → small_fish_gui-1.7.0}/src/small_fish_gui/gui/help_module.py +0 -0
- {small_fish_gui-1.5.0 → small_fish_gui-1.7.0}/src/small_fish_gui/gui/layout.py +0 -0
- {small_fish_gui-1.5.0 → small_fish_gui-1.7.0}/src/small_fish_gui/gui/mapping_help_screenshot.png +0 -0
- {small_fish_gui-1.5.0 → small_fish_gui-1.7.0}/src/small_fish_gui/gui/segmentation_help_screenshot.png +0 -0
- {small_fish_gui-1.5.0 → small_fish_gui-1.7.0}/src/small_fish_gui/interface/__init__.py +0 -0
- {small_fish_gui-1.5.0 → small_fish_gui-1.7.0}/src/small_fish_gui/interface/image.py +0 -0
- {small_fish_gui-1.5.0 → small_fish_gui-1.7.0}/src/small_fish_gui/interface/parameters.py +0 -0
- {small_fish_gui-1.5.0 → small_fish_gui-1.7.0}/src/small_fish_gui/interface/testing.py +0 -0
- {small_fish_gui-1.5.0 → small_fish_gui-1.7.0}/src/small_fish_gui/napari_detection_example.png +0 -0
- {small_fish_gui-1.5.0 → small_fish_gui-1.7.0}/src/small_fish_gui/pipeline/__init__.py +0 -0
- {small_fish_gui-1.5.0 → small_fish_gui-1.7.0}/src/small_fish_gui/pipeline/_custom_errors.py +0 -0
- {small_fish_gui-1.5.0 → small_fish_gui-1.7.0}/src/small_fish_gui/pipeline/_preprocess.py +0 -0
- {small_fish_gui-1.5.0 → small_fish_gui-1.7.0}/src/small_fish_gui/pipeline/_signaltonoise.py +0 -0
- {small_fish_gui-1.5.0 → small_fish_gui-1.7.0}/src/small_fish_gui/pipeline/spots.py +0 -0
- {small_fish_gui-1.5.0 → small_fish_gui-1.7.0}/src/small_fish_gui/pipeline/test.py +0 -0
- {small_fish_gui-1.5.0 → small_fish_gui-1.7.0}/src/small_fish_gui/pipeline/utils.py +0 -0
- {small_fish_gui-1.5.0 → small_fish_gui-1.7.0}/src/small_fish_gui/requirements.txt +0 -0
- {small_fish_gui-1.5.0 → small_fish_gui-1.7.0}/src/small_fish_gui/utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: small_fish_gui
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.7.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,6 +1,8 @@
|
|
|
1
1
|
import sys, subprocess
|
|
2
2
|
import PySimpleGUI as sg
|
|
3
3
|
|
|
4
|
+
from small_fish_gui import __version__
|
|
5
|
+
|
|
4
6
|
def main():
|
|
5
7
|
import small_fish_gui.pipeline.main
|
|
6
8
|
|
|
@@ -10,9 +12,7 @@ def is_last_version() :
|
|
|
10
12
|
latest_version = latest_version[:latest_version.find(')')]
|
|
11
13
|
latest_version = latest_version.replace(' ','').split(',')[-1]
|
|
12
14
|
|
|
13
|
-
current_version =
|
|
14
|
-
current_version = current_version[current_version.find('Version:')+8:]
|
|
15
|
-
current_version = current_version[:current_version.find('\\n')].replace(' ','')
|
|
15
|
+
current_version = __version__
|
|
16
16
|
|
|
17
17
|
return current_version == latest_version
|
|
18
18
|
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Submodule containing custom class for napari widgets
|
|
3
|
+
"""
|
|
4
|
+
import numpy as np
|
|
5
|
+
from napari.layers import Labels
|
|
6
|
+
from magicgui import magicgui
|
|
7
|
+
|
|
8
|
+
class cell_label_eraser :
|
|
9
|
+
"""
|
|
10
|
+
Must be instanced within Napari Viewer definition range for update connection to work, cell deletion works fine anyway.
|
|
11
|
+
"""
|
|
12
|
+
def __init__(self, label_list: 'list[Labels]'):
|
|
13
|
+
self.widget = self._create_eraser(label_list)
|
|
14
|
+
for label_layer in label_list :
|
|
15
|
+
label_layer.events.selected_label.connect((self, 'update'))
|
|
16
|
+
|
|
17
|
+
def update(self, event) :
|
|
18
|
+
layer : Labels = event.source
|
|
19
|
+
new_label = layer.selected_label
|
|
20
|
+
self.widget.label_number.value = new_label
|
|
21
|
+
self.widget.update()
|
|
22
|
+
|
|
23
|
+
def _create_eraser(self, label_list: 'list[Labels]') :
|
|
24
|
+
@magicgui(
|
|
25
|
+
call_button="Delete cell",
|
|
26
|
+
auto_call=False
|
|
27
|
+
)
|
|
28
|
+
def label_eraser(label_number: int) -> None :
|
|
29
|
+
|
|
30
|
+
for i, label in enumerate(label_list) :
|
|
31
|
+
label_list[i].data[label.data == label_number] = 0
|
|
32
|
+
label.refresh()
|
|
33
|
+
|
|
34
|
+
return label_eraser
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class free_label_picker :
|
|
39
|
+
def __init__(self, label_list):
|
|
40
|
+
self.widget = self._create_free_label_picker(label_list)
|
|
41
|
+
|
|
42
|
+
def _create_free_label_picker(self, label_list : 'list[Labels]') :
|
|
43
|
+
@magicgui(
|
|
44
|
+
call_button="Pick free label",
|
|
45
|
+
auto_call=False
|
|
46
|
+
)
|
|
47
|
+
def label_pick()->None :
|
|
48
|
+
max_list = [label_layer.data.max() for label_layer in label_list]
|
|
49
|
+
new_label = max(max_list) + 1
|
|
50
|
+
for label_layer in label_list :
|
|
51
|
+
label_layer.selected_label = new_label
|
|
52
|
+
label_layer.refresh()
|
|
53
|
+
|
|
54
|
+
return label_pick
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
class segmentation_reseter :
|
|
58
|
+
def __init__(self, label_list):
|
|
59
|
+
self.save = self._get_save(label_list)
|
|
60
|
+
self.widget = self._create_widget(label_list)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def _get_save(self, label_list : 'list[Labels]') :
|
|
64
|
+
return [label.data.copy() for label in label_list]
|
|
65
|
+
|
|
66
|
+
def _create_widget(self, label_list: 'list[Labels]') :
|
|
67
|
+
@magicgui(
|
|
68
|
+
call_button= 'Reset segmentation',
|
|
69
|
+
auto_call=False,
|
|
70
|
+
)
|
|
71
|
+
def reset_segmentation() -> None:
|
|
72
|
+
for save_data, layer in zip(self.save, label_list) :
|
|
73
|
+
layer.data = save_data.copy()
|
|
74
|
+
layer.refresh()
|
|
75
|
+
|
|
76
|
+
return reset_segmentation
|
|
77
|
+
|
|
78
|
+
class changes_propagater :
|
|
79
|
+
def __init__(self, label_list):
|
|
80
|
+
self.widget = self._create_widget(label_list)
|
|
81
|
+
|
|
82
|
+
def _create_widget(self, label_list: 'list[Labels]') :
|
|
83
|
+
@magicgui(
|
|
84
|
+
call_button='Apply changes',
|
|
85
|
+
auto_call=False,
|
|
86
|
+
)
|
|
87
|
+
def apply_changes() -> None:
|
|
88
|
+
for layer in label_list :
|
|
89
|
+
slices = layer.data.shape[0]
|
|
90
|
+
layer_2D = np.max(layer.data, axis=0)
|
|
91
|
+
layer.data = np.repeat(layer_2D[np.newaxis], slices, axis=0)
|
|
92
|
+
layer.refresh()
|
|
93
|
+
return apply_changes
|
|
@@ -7,13 +7,21 @@ import napari.types
|
|
|
7
7
|
import numpy as np
|
|
8
8
|
import napari
|
|
9
9
|
|
|
10
|
+
from napari.layers import Labels
|
|
11
|
+
|
|
12
|
+
from magicgui import widgets
|
|
13
|
+
from magicgui import magicgui
|
|
14
|
+
|
|
10
15
|
from bigfish.stack import check_parameter
|
|
16
|
+
from ._napari_widgets import cell_label_eraser, segmentation_reseter, changes_propagater, free_label_picker
|
|
11
17
|
from ..utils import compute_anisotropy_coef
|
|
12
|
-
from ._colocalisation import spots_multicolocalisation
|
|
18
|
+
from ..pipeline._colocalisation import spots_multicolocalisation
|
|
19
|
+
|
|
20
|
+
#Post detection
|
|
13
21
|
|
|
14
|
-
def _update_clusters(new_clusters: np.ndarray, spots: np.ndarray, voxel_size, cluster_size,
|
|
22
|
+
def _update_clusters(new_clusters: np.ndarray, spots: np.ndarray, voxel_size, cluster_size, shape) :
|
|
15
23
|
if len(new_clusters) == 0 : return new_clusters
|
|
16
|
-
if len(spots) == 0 : return
|
|
24
|
+
if len(spots) == 0 : return np.empty(shape=(0,2+len(voxel_size)))
|
|
17
25
|
|
|
18
26
|
if len(new_clusters[0]) in [2,3] :
|
|
19
27
|
new_clusters = np.concatenate([
|
|
@@ -25,13 +33,10 @@ def _update_clusters(new_clusters: np.ndarray, spots: np.ndarray, voxel_size, cl
|
|
|
25
33
|
assert len(new_clusters[0]) == 4 or len(new_clusters[0]) == 5, "Wrong number of coordinates for clusters should not happen."
|
|
26
34
|
|
|
27
35
|
# Update spots clusters
|
|
28
|
-
|
|
29
|
-
new_clusters[:,-2] = spots_multicolocalisation(new_clusters[:,:3], spots, radius_nm= cluster_size, voxel_size=voxel_size, image_shape=shape)
|
|
30
|
-
elif len(voxel_size) == 2 :
|
|
31
|
-
new_clusters[:,-2] = spots_multicolocalisation(new_clusters[:,:2], spots, radius_nm= cluster_size, voxel_size=voxel_size, image_shape=shape)
|
|
36
|
+
new_clusters[:,-2] = spots_multicolocalisation(new_clusters[:,:-2], spots, radius_nm= cluster_size, voxel_size=voxel_size, image_shape=shape)
|
|
32
37
|
|
|
33
38
|
# delete too small clusters
|
|
34
|
-
|
|
39
|
+
new_clusters = np.delete(new_clusters, new_clusters[:,-2] == 0, 0)
|
|
35
40
|
|
|
36
41
|
return new_clusters
|
|
37
42
|
|
|
@@ -98,13 +103,16 @@ def correct_spots(image, spots, voxel_size= (1,1,1), clusters= None, cluster_siz
|
|
|
98
103
|
new_spots = np.array(Viewer.layers['single spots'].data, dtype= int)
|
|
99
104
|
|
|
100
105
|
if type(clusters) != type(None) :
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
new_clusters = _update_clusters(new_clusters, new_spots, voxel_size=voxel_size, cluster_size=cluster_size, min_spot_number=min_spot_number, shape=image.shape)
|
|
106
|
+
new_clusters = np.array(Viewer.layers['foci'].data, dtype= int)
|
|
107
|
+
new_clusters = _update_clusters(new_clusters, new_spots, voxel_size=voxel_size, cluster_size=cluster_size, shape=image.shape)
|
|
104
108
|
else : new_clusters = None
|
|
105
109
|
|
|
106
110
|
return new_spots, new_clusters
|
|
107
111
|
|
|
112
|
+
# Segmentation
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
|
|
108
116
|
def show_segmentation(
|
|
109
117
|
nuc_image : np.ndarray,
|
|
110
118
|
nuc_label : np.ndarray,
|
|
@@ -135,26 +143,40 @@ def show_segmentation(
|
|
|
135
143
|
)
|
|
136
144
|
|
|
137
145
|
#Init Napari viewer
|
|
138
|
-
Viewer = napari.Viewer(ndisplay=2, title= 'Show segmentation', axis_labels=['z','y','x'] if dim == 3 else ['y', 'x']
|
|
146
|
+
Viewer = napari.Viewer(ndisplay=2, title= 'Show segmentation', axis_labels=['z','y','x'] if dim == 3 else ['y', 'x'])
|
|
139
147
|
|
|
140
|
-
# Adding
|
|
148
|
+
# Adding nuclei
|
|
141
149
|
nuc_signal_layer = Viewer.add_image(nuc_image, name= "nucleus signal", blending= 'additive', colormap='blue', contrast_limits=[nuc_image.min(), nuc_image.max()])
|
|
142
|
-
nuc_label_layer = Viewer.add_labels(nuc_label, opacity= 0.
|
|
150
|
+
nuc_label_layer = Viewer.add_labels(nuc_label, opacity= 0.6, name= 'nucleus_label',)
|
|
143
151
|
nuc_label_layer.preserve_labels = True
|
|
152
|
+
labels_layer_list = [nuc_label_layer]
|
|
144
153
|
|
|
145
|
-
#Adding
|
|
146
|
-
if type(cyto_image) != type(None) : Viewer.add_image(cyto_image, name= "cytoplasm signal", blending= 'additive', colormap='red', contrast_limits=[cyto_image.min(), cyto_image.max()])
|
|
154
|
+
#Adding cytoplasm
|
|
147
155
|
if (type(cyto_label) != type(None) and not np.array_equal(cyto_label, nuc_label) ) or (type(cyto_label) != type(None) and cyto_label.max() == 0):
|
|
148
|
-
|
|
156
|
+
Viewer.add_image(cyto_image, name= "cytoplasm signal", blending= 'additive', colormap='red', contrast_limits=[cyto_image.min(), cyto_image.max()])
|
|
157
|
+
cyto_label_layer = Viewer.add_labels(cyto_label, opacity= 0.6, name= 'cytoplasm_label')
|
|
149
158
|
cyto_label_layer.preserve_labels = True
|
|
150
|
-
|
|
159
|
+
labels_layer_list += [cyto_label_layer]
|
|
160
|
+
|
|
161
|
+
#Adding widget
|
|
162
|
+
label_eraser = cell_label_eraser(labels_layer_list)
|
|
163
|
+
label_picker = free_label_picker(labels_layer_list)
|
|
164
|
+
label_reseter = segmentation_reseter(labels_layer_list)
|
|
165
|
+
changes_applier = changes_propagater(labels_layer_list)
|
|
166
|
+
|
|
167
|
+
buttons_container = widgets.Container(widgets=[label_picker.widget, changes_applier.widget, label_reseter.widget], labels=False, layout='horizontal')
|
|
168
|
+
tools_container = widgets.Container(
|
|
169
|
+
widgets = [buttons_container, label_eraser.widget],
|
|
170
|
+
labels=False,
|
|
171
|
+
)
|
|
172
|
+
Viewer.window.add_dock_widget(tools_container, name='SmallFish', area='left')
|
|
173
|
+
|
|
151
174
|
#Launch Napari
|
|
152
|
-
Viewer.show(block=False)
|
|
153
175
|
napari.run()
|
|
154
176
|
|
|
155
|
-
|
|
156
177
|
new_nuc_label = Viewer.layers['nucleus_label'].data
|
|
157
|
-
if
|
|
178
|
+
if 'cytoplasm_label' in Viewer.layers :
|
|
179
|
+
new_cyto_label = Viewer.layers['cytoplasm_label'].data
|
|
158
180
|
else : new_cyto_label = new_nuc_label
|
|
159
181
|
|
|
160
182
|
return new_nuc_label, new_cyto_label
|
|
@@ -136,8 +136,8 @@ def output_image_prompt(filename) :
|
|
|
136
136
|
excel_filename = values['filename'] + ".xlsx"
|
|
137
137
|
feather_filename = values['filename'] + ".feather"
|
|
138
138
|
|
|
139
|
-
if not values['Excel'] and not values['Feather'] :
|
|
140
|
-
sg.popup("Please check at least one box : Excel/Feather")
|
|
139
|
+
if not values['Excel'] and not values['Feather'] and not values['csv'] :
|
|
140
|
+
sg.popup("Please check at least one box : Excel/Feather/csv")
|
|
141
141
|
relaunch = True
|
|
142
142
|
elif not os.path.isdir(values['folder']) :
|
|
143
143
|
sg.popup("Incorrect folder")
|
|
@@ -280,7 +280,7 @@ def _warning_popup(warning:str) :
|
|
|
280
280
|
|
|
281
281
|
def _sumup_df(results: pd.DataFrame) :
|
|
282
282
|
|
|
283
|
-
COLUMNS = ['acquisition_id','threshold', 'spot_number', 'cell_number', 'filename', 'channel to compute']
|
|
283
|
+
COLUMNS = ['acquisition_id','name','threshold', 'spot_number', 'cell_number', 'filename', 'channel to compute']
|
|
284
284
|
|
|
285
285
|
if len(results) > 0 :
|
|
286
286
|
if 'channel to compute' not in results : results['channel to compute'] = np.NaN
|
|
@@ -303,7 +303,7 @@ def hub_prompt(fov_results, do_segmentation=False) :
|
|
|
303
303
|
[sg.Text('RESULTS', font= 'bold 13')],
|
|
304
304
|
[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],
|
|
305
305
|
[sg.Button('Add detection'), sg.Button('Compute colocalisation'), sg.Button('Batch detection')],
|
|
306
|
-
[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')]
|
|
306
|
+
[sg.Button('Rename acquisition', button_color= 'green'), 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')]
|
|
307
307
|
# [sg.Button('Save results', button_color= 'green'), sg.Button('Reset results',button_color= 'gray')]
|
|
308
308
|
]
|
|
309
309
|
|
|
@@ -318,16 +318,20 @@ def hub_prompt(fov_results, do_segmentation=False) :
|
|
|
318
318
|
return event, values
|
|
319
319
|
|
|
320
320
|
def coloc_prompt() :
|
|
321
|
-
layout = [
|
|
322
|
-
[parameters_layout(['colocalisation distance'], header= 'Colocalisation', default_values= 0)]
|
|
323
|
-
]
|
|
324
|
-
|
|
321
|
+
layout = parameters_layout(['colocalisation distance'], unit= 'nm', header= 'Colocalisation', default_values= 0)
|
|
325
322
|
event, values = prompt_with_help(layout)
|
|
326
323
|
|
|
327
324
|
if event == 'Ok' :
|
|
328
325
|
return values['colocalisation distance']
|
|
329
326
|
else : return False
|
|
330
327
|
|
|
328
|
+
def rename_prompt() :
|
|
329
|
+
layout = parameters_layout(['name'], header= "Rename acquisitions", size=12)
|
|
330
|
+
event, values = prompt_with_help(layout)
|
|
331
|
+
if event == 'Ok' :
|
|
332
|
+
return values['name']
|
|
333
|
+
else : return False
|
|
334
|
+
|
|
331
335
|
def ask_detection_confirmation(used_threshold) :
|
|
332
336
|
layout = [
|
|
333
337
|
[sg.Text("Proceed with current detection ?", font= 'bold 10')],
|
|
@@ -10,11 +10,9 @@ def _cast_spot_to_tuple(spot) :
|
|
|
10
10
|
def _cast_spots_to_tuple(spots) :
|
|
11
11
|
return tuple(list(map(_cast_spot_to_tuple, spots)))
|
|
12
12
|
|
|
13
|
-
def write_results(dataframe: pd.DataFrame, path:str, filename:str, do_excel= True, do_feather= False, do_csv=False, overwrite=False) :
|
|
13
|
+
def write_results(dataframe: pd.DataFrame, path:str, filename:str, do_excel= True, do_feather= False, do_csv=False, overwrite=False, reset_index=True) :
|
|
14
14
|
check_parameter(dataframe= pd.DataFrame, path= str, filename = str, do_excel = bool, do_feather = bool)
|
|
15
15
|
|
|
16
|
-
dataframe.columns = dataframe.columns.astype(str) # assert columns header are string for feather
|
|
17
|
-
|
|
18
16
|
if len(dataframe) == 0 : return True
|
|
19
17
|
if not do_excel and not do_feather and not do_csv :
|
|
20
18
|
return False
|
|
@@ -22,6 +20,14 @@ def write_results(dataframe: pd.DataFrame, path:str, filename:str, do_excel= Tru
|
|
|
22
20
|
if not path.endswith('/') : path +='/'
|
|
23
21
|
assert os.path.isdir(path)
|
|
24
22
|
|
|
23
|
+
#Casting cols name to str for feather format
|
|
24
|
+
index_dim = dataframe.columns.nlevels
|
|
25
|
+
if index_dim == 1 :
|
|
26
|
+
dataframe.columns = dataframe.columns.astype(str)
|
|
27
|
+
else :
|
|
28
|
+
casted_cols = [dataframe.columns.get_level_values(level).astype(str) for level in range(index_dim)]
|
|
29
|
+
casted_cols = zip(*casted_cols)
|
|
30
|
+
dataframe.columns = pd.MultiIndex.from_tuples(casted_cols)
|
|
25
31
|
|
|
26
32
|
new_filename = filename
|
|
27
33
|
i= 1
|
|
@@ -31,23 +37,21 @@ def write_results(dataframe: pd.DataFrame, path:str, filename:str, do_excel= Tru
|
|
|
31
37
|
new_filename = filename + '_{0}'.format(i)
|
|
32
38
|
i+=1
|
|
33
39
|
|
|
34
|
-
|
|
35
|
-
|
|
40
|
+
COLUMNS_TO_DROP = ['image', 'spots', 'clusters', 'rna_coords', 'cluster_coords']
|
|
41
|
+
for col in COLUMNS_TO_DROP :
|
|
42
|
+
dataframe = dataframe.drop(columns=col)
|
|
36
43
|
|
|
37
|
-
if
|
|
38
|
-
dataframe = dataframe.drop(['spots'], axis= 1)
|
|
39
|
-
|
|
40
|
-
if 'clusters' in dataframe.columns :
|
|
41
|
-
dataframe = dataframe.drop(['clusters'], axis= 1)
|
|
44
|
+
if reset_index : dataframe = dataframe.reset_index(drop=True)
|
|
42
45
|
|
|
43
|
-
if
|
|
44
|
-
if do_csv : dataframe.reset_index(drop=True).to_csv(path + new_filename + '.csv', sep=";")
|
|
46
|
+
if do_csv : dataframe.to_csv(path + new_filename + '.csv', sep=";")
|
|
45
47
|
if do_excel :
|
|
46
48
|
if len(dataframe) < MAX_LEN_EXCEL :
|
|
47
|
-
dataframe.
|
|
49
|
+
dataframe.to_excel(path + new_filename + '.xlsx')
|
|
48
50
|
else :
|
|
49
51
|
print("Error : Table too big to be saved in excel format.")
|
|
50
52
|
return False
|
|
51
53
|
|
|
54
|
+
if do_feather :
|
|
55
|
+
dataframe.to_parquet(path + new_filename + '.parquet')
|
|
52
56
|
|
|
53
|
-
return True
|
|
57
|
+
return True
|