fusion-tools 3.3.2__tar.gz → 3.3.4__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.
- {fusion_tools-3.3.2 → fusion_tools-3.3.4}/PKG-INFO +1 -1
- {fusion_tools-3.3.2 → fusion_tools-3.3.4}/setup.py +1 -1
- fusion_tools-3.3.4/src/fusion_tools/fusion/data_types.py +503 -0
- {fusion_tools-3.3.2 → fusion_tools-3.3.4}/src/fusion_tools/fusion/vis.py +19 -9
- {fusion_tools-3.3.2 → fusion_tools-3.3.4}/src/fusion_tools/handler/dataset_builder.py +53 -17
- {fusion_tools-3.3.2 → fusion_tools-3.3.4}/src/fusion_tools/handler/dataset_uploader.py +13 -2
- {fusion_tools-3.3.2 → fusion_tools-3.3.4}/src/fusion_tools/utils/shapes.py +2 -2
- {fusion_tools-3.3.2 → fusion_tools-3.3.4}/src/fusion_tools.egg-info/PKG-INFO +1 -1
- {fusion_tools-3.3.2 → fusion_tools-3.3.4}/src/fusion_tools.egg-info/SOURCES.txt +1 -0
- fusion_tools-3.3.4/tests/test_fusion_layout.py +39 -0
- fusion_tools-3.3.2/src/fusion_tools/fusion/data_types.py +0 -62
- {fusion_tools-3.3.2 → fusion_tools-3.3.4}/LICENSE +0 -0
- {fusion_tools-3.3.2 → fusion_tools-3.3.4}/README.md +0 -0
- {fusion_tools-3.3.2 → fusion_tools-3.3.4}/pyproject.toml +0 -0
- {fusion_tools-3.3.2 → fusion_tools-3.3.4}/setup.cfg +0 -0
- {fusion_tools-3.3.2 → fusion_tools-3.3.4}/src/fusion_tools/__init__.py +0 -0
- {fusion_tools-3.3.2 → fusion_tools-3.3.4}/src/fusion_tools/components/__init__.py +0 -0
- {fusion_tools-3.3.2 → fusion_tools-3.3.4}/src/fusion_tools/components/maps.py +0 -0
- {fusion_tools-3.3.2 → fusion_tools-3.3.4}/src/fusion_tools/components/segmentation.py +0 -0
- {fusion_tools-3.3.2 → fusion_tools-3.3.4}/src/fusion_tools/components/tools.py +0 -0
- {fusion_tools-3.3.2 → fusion_tools-3.3.4}/src/fusion_tools/dataset.py +0 -0
- {fusion_tools-3.3.2 → fusion_tools-3.3.4}/src/fusion_tools/feature_extraction.py +0 -0
- {fusion_tools-3.3.2 → fusion_tools-3.3.4}/src/fusion_tools/fusion/__init__.py +0 -0
- {fusion_tools-3.3.2 → fusion_tools-3.3.4}/src/fusion_tools/fusion/surveys.py +0 -0
- {fusion_tools-3.3.2 → fusion_tools-3.3.4}/src/fusion_tools/handler/__init__.py +0 -0
- {fusion_tools-3.3.2 → fusion_tools-3.3.4}/src/fusion_tools/handler/dsa_handler.py +0 -0
- {fusion_tools-3.3.2 → fusion_tools-3.3.4}/src/fusion_tools/handler/login.py +0 -0
- {fusion_tools-3.3.2 → fusion_tools-3.3.4}/src/fusion_tools/handler/plugin.py +0 -0
- {fusion_tools-3.3.2 → fusion_tools-3.3.4}/src/fusion_tools/handler/resource_selector.py +0 -0
- {fusion_tools-3.3.2 → fusion_tools-3.3.4}/src/fusion_tools/handler/survey.py +0 -0
- {fusion_tools-3.3.2 → fusion_tools-3.3.4}/src/fusion_tools/tileserver.py +0 -0
- {fusion_tools-3.3.2 → fusion_tools-3.3.4}/src/fusion_tools/utils/__init__.py +0 -0
- {fusion_tools-3.3.2 → fusion_tools-3.3.4}/src/fusion_tools/utils/images.py +0 -0
- {fusion_tools-3.3.2 → fusion_tools-3.3.4}/src/fusion_tools/utils/omics.py +0 -0
- {fusion_tools-3.3.2 → fusion_tools-3.3.4}/src/fusion_tools/utils/stats.py +0 -0
- {fusion_tools-3.3.2 → fusion_tools-3.3.4}/src/fusion_tools/visualization/__init__.py +0 -0
- {fusion_tools-3.3.2 → fusion_tools-3.3.4}/src/fusion_tools/visualization/components.py +0 -0
- {fusion_tools-3.3.2 → fusion_tools-3.3.4}/src/fusion_tools/visualization/vis_utils.py +0 -0
- {fusion_tools-3.3.2 → fusion_tools-3.3.4}/src/fusion_tools.egg-info/dependency_links.txt +0 -0
- {fusion_tools-3.3.2 → fusion_tools-3.3.4}/src/fusion_tools.egg-info/requires.txt +0 -0
- {fusion_tools-3.3.2 → fusion_tools-3.3.4}/src/fusion_tools.egg-info/top_level.txt +0 -0
- {fusion_tools-3.3.2 → fusion_tools-3.3.4}/tests/test_classification_model.py +0 -0
- {fusion_tools-3.3.2 → fusion_tools-3.3.4}/tests/test_custom_component.py +0 -0
- {fusion_tools-3.3.2 → fusion_tools-3.3.4}/tests/test_dash_table_dropdowns.py +0 -0
- {fusion_tools-3.3.2 → fusion_tools-3.3.4}/tests/test_data_extractor.py +0 -0
- {fusion_tools-3.3.2 → fusion_tools-3.3.4}/tests/test_dataset_classes.py +0 -0
- {fusion_tools-3.3.2 → fusion_tools-3.3.4}/tests/test_dsa_components.py +0 -0
- {fusion_tools-3.3.2 → fusion_tools-3.3.4}/tests/test_extract_nested_prop.py +0 -0
- {fusion_tools-3.3.2 → fusion_tools-3.3.4}/tests/test_extract_recursive.py +0 -0
- {fusion_tools-3.3.2 → fusion_tools-3.3.4}/tests/test_feature_annotation.py +0 -0
- {fusion_tools-3.3.2 → fusion_tools-3.3.4}/tests/test_feature_extraction.py +0 -0
- {fusion_tools-3.3.2 → fusion_tools-3.3.4}/tests/test_file_selector.py +0 -0
- {fusion_tools-3.3.2 → fusion_tools-3.3.4}/tests/test_generate_property_dict.py +0 -0
- {fusion_tools-3.3.2 → fusion_tools-3.3.4}/tests/test_get_gene_info.py +0 -0
- {fusion_tools-3.3.2 → fusion_tools-3.3.4}/tests/test_global_property_plotter.py +0 -0
- {fusion_tools-3.3.2 → fusion_tools-3.3.4}/tests/test_hra_viewer.py +0 -0
- {fusion_tools-3.3.2 → fusion_tools-3.3.4}/tests/test_image_overlay.py +0 -0
- {fusion_tools-3.3.2 → fusion_tools-3.3.4}/tests/test_large_slide_maps.py +0 -0
- {fusion_tools-3.3.2 → fusion_tools-3.3.4}/tests/test_load_visium_csv.py +0 -0
- {fusion_tools-3.3.2 → fusion_tools-3.3.4}/tests/test_meta_embed.py +0 -0
- {fusion_tools-3.3.2 → fusion_tools-3.3.4}/tests/test_model_train.py +0 -0
- {fusion_tools-3.3.2 → fusion_tools-3.3.4}/tests/test_multiframe_rgb.py +0 -0
- {fusion_tools-3.3.2 → fusion_tools-3.3.4}/tests/test_multiframeslidemap.py +0 -0
- {fusion_tools-3.3.2 → fusion_tools-3.3.4}/tests/test_multipage_layout.py +0 -0
- {fusion_tools-3.3.2 → fusion_tools-3.3.4}/tests/test_parse_cli_xml.py +0 -0
- {fusion_tools-3.3.2 → fusion_tools-3.3.4}/tests/test_path_extraction.py +0 -0
- {fusion_tools-3.3.2 → fusion_tools-3.3.4}/tests/test_plugin_runner.py +0 -0
- {fusion_tools-3.3.2 → fusion_tools-3.3.4}/tests/test_plugins.py +0 -0
- {fusion_tools-3.3.2 → fusion_tools-3.3.4}/tests/test_process.py +0 -0
- {fusion_tools-3.3.2 → fusion_tools-3.3.4}/tests/test_property_plotter.py +0 -0
- {fusion_tools-3.3.2 → fusion_tools-3.3.4}/tests/test_read_anndata.py +0 -0
- {fusion_tools-3.3.2 → fusion_tools-3.3.4}/tests/test_remote_slide_annotations.py +0 -0
- {fusion_tools-3.3.2 → fusion_tools-3.3.4}/tests/test_remote_tileserver.py +0 -0
- {fusion_tools-3.3.2 → fusion_tools-3.3.4}/tests/test_segmentation.py +0 -0
- {fusion_tools-3.3.2 → fusion_tools-3.3.4}/tests/test_slide_annotations.py +0 -0
- {fusion_tools-3.3.2 → fusion_tools-3.3.4}/tests/test_spatial_aggregation.py +0 -0
- {fusion_tools-3.3.2 → fusion_tools-3.3.4}/tests/test_tile_server.py +0 -0
- {fusion_tools-3.3.2 → fusion_tools-3.3.4}/tests/test_visualization_component.py +0 -0
|
@@ -5,7 +5,7 @@ with open("README.md", "r") as fh:
|
|
|
5
5
|
|
|
6
6
|
setuptools.setup(
|
|
7
7
|
name="fusion-tools",
|
|
8
|
-
version="3.3.
|
|
8
|
+
version="3.3.4",
|
|
9
9
|
author="Sam Border",
|
|
10
10
|
author_email="sam.border2256@gmail.com",
|
|
11
11
|
description="Modular visualization and analysis dashboard creation for high-resolution microscopy images",
|
|
@@ -0,0 +1,503 @@
|
|
|
1
|
+
"""Defining UploadTypes which are accepted in FUSION
|
|
2
|
+
"""
|
|
3
|
+
|
|
4
|
+
from fusion_tools.handler.dataset_uploader import DSAUploadType, WSI_TYPES, ANN_TYPES
|
|
5
|
+
|
|
6
|
+
def get_upload_types():
|
|
7
|
+
|
|
8
|
+
# Basic Type:
|
|
9
|
+
kidney_basic_type = DSAUploadType(
|
|
10
|
+
name = "Kidney Histology Image",
|
|
11
|
+
description= 'This is a kidney histology image upload with the option to add annotations. Glomeruli, sclerotic glomeruli, tubules, and cortical and medullary interstitium are first segmented using DL and then pathomic features are calculated.',
|
|
12
|
+
input_files = [
|
|
13
|
+
{
|
|
14
|
+
'name': 'Image',
|
|
15
|
+
'description': 'This is any kidney histology image you would like to upload.',
|
|
16
|
+
'accepted_types': WSI_TYPES,
|
|
17
|
+
'preprocessing_plugins': None,
|
|
18
|
+
'type': 'item',
|
|
19
|
+
'required': True
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
'name': 'Annotation',
|
|
23
|
+
'description': 'This is an annotation file that is processed and added to the uploaded image.',
|
|
24
|
+
'accepted_types': ANN_TYPES,
|
|
25
|
+
'preprocessing_plugins': None,
|
|
26
|
+
'type': 'annotation',
|
|
27
|
+
'parent': 'Image',
|
|
28
|
+
'required': False
|
|
29
|
+
}
|
|
30
|
+
],
|
|
31
|
+
processing_plugins=[
|
|
32
|
+
[
|
|
33
|
+
{
|
|
34
|
+
'name': 'MultiCompartmentSegment',
|
|
35
|
+
'image': 'samborder2256/multicomp:latest',
|
|
36
|
+
'input_args': [
|
|
37
|
+
{
|
|
38
|
+
'name': 'files',
|
|
39
|
+
'default': {
|
|
40
|
+
'type': 'upload_file',
|
|
41
|
+
'name': 'Image'
|
|
42
|
+
},
|
|
43
|
+
'disabled': True
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
'name': 'base_dir',
|
|
47
|
+
'default': {
|
|
48
|
+
'type': 'upload_folder',
|
|
49
|
+
'name': 'Image'
|
|
50
|
+
},
|
|
51
|
+
'disabled': True
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
'name': 'modelfile',
|
|
55
|
+
'default': {
|
|
56
|
+
'value': '648123761019450486d13dce'
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
]
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
'name': 'FeatureExtraction',
|
|
63
|
+
'image': 'fusionplugins/general:latest',
|
|
64
|
+
'input_args': [
|
|
65
|
+
{
|
|
66
|
+
'name': 'input_image',
|
|
67
|
+
'default': {
|
|
68
|
+
'type': 'upload_file',
|
|
69
|
+
'name': 'Image'
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
'name': 'extract_sub_compartments',
|
|
74
|
+
'default': {
|
|
75
|
+
'value': True
|
|
76
|
+
},
|
|
77
|
+
'disabled': True
|
|
78
|
+
},
|
|
79
|
+
'hematoxylin_threshold',
|
|
80
|
+
'eosinophilic_threshold',
|
|
81
|
+
'hematoxylin_min_size',
|
|
82
|
+
'eosinophilic_min_size'
|
|
83
|
+
]
|
|
84
|
+
}
|
|
85
|
+
]
|
|
86
|
+
],
|
|
87
|
+
required_metadata=[]
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
# Basic Type:
|
|
91
|
+
basic_type = DSAUploadType(
|
|
92
|
+
name = "General Histology Image",
|
|
93
|
+
description= 'This is a histology image upload with the option to add annotations. Glomeruli, sclerotic glomeruli, tubules, and cortical and medullary interstitium are first segmented using DL and then pathomic features are calculated.',
|
|
94
|
+
input_files = [
|
|
95
|
+
{
|
|
96
|
+
'name': 'Image',
|
|
97
|
+
'description': 'This is any histology image you would like to upload.',
|
|
98
|
+
'accepted_types': WSI_TYPES,
|
|
99
|
+
'preprocessing_plugins': None,
|
|
100
|
+
'type': 'item',
|
|
101
|
+
'required': True
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
'name': 'Annotation',
|
|
105
|
+
'description': 'This is an annotation file that is processed and added to the uploaded image.',
|
|
106
|
+
'accepted_types': ANN_TYPES,
|
|
107
|
+
'preprocessing_plugins': None,
|
|
108
|
+
'type': 'annotation',
|
|
109
|
+
'parent': 'Image',
|
|
110
|
+
'required': False
|
|
111
|
+
}
|
|
112
|
+
],
|
|
113
|
+
processing_plugins=[
|
|
114
|
+
{
|
|
115
|
+
'name': 'FeatureExtraction',
|
|
116
|
+
'image': 'fusionplugins/general:latest',
|
|
117
|
+
'input_args': [
|
|
118
|
+
{
|
|
119
|
+
'name': 'input_image',
|
|
120
|
+
'default': {
|
|
121
|
+
'type': 'upload_file',
|
|
122
|
+
'name': 'Image'
|
|
123
|
+
}
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
'name': 'extract_sub_compartments',
|
|
127
|
+
'default': {
|
|
128
|
+
'value': True
|
|
129
|
+
}
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
'name': 'hematoxylin_threshold',
|
|
133
|
+
'default': {
|
|
134
|
+
'value': 150
|
|
135
|
+
}
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
'name': 'eosinophilic_threshold',
|
|
139
|
+
'default': {
|
|
140
|
+
'value': 30
|
|
141
|
+
}
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
'name': 'hematoxylin_min_size',
|
|
145
|
+
'default': {
|
|
146
|
+
'value': 40
|
|
147
|
+
}
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
'name': 'eosinophilic_min_size',
|
|
151
|
+
'default': {
|
|
152
|
+
'value': 20
|
|
153
|
+
}
|
|
154
|
+
},
|
|
155
|
+
]
|
|
156
|
+
}
|
|
157
|
+
],
|
|
158
|
+
required_metadata=[
|
|
159
|
+
{
|
|
160
|
+
'name': 'Organ',
|
|
161
|
+
'required': True,
|
|
162
|
+
'item': 'Image'
|
|
163
|
+
}
|
|
164
|
+
]
|
|
165
|
+
)
|
|
166
|
+
|
|
167
|
+
# 10x Types:
|
|
168
|
+
visium_type = DSAUploadType(
|
|
169
|
+
name = '10x Visium',
|
|
170
|
+
description = 'This upload type is for 10x Visium spatial transcriptomics samples. It includes one histology image and information related to the transcript counts per-"spot".',
|
|
171
|
+
input_files = [
|
|
172
|
+
{
|
|
173
|
+
'name': 'Image',
|
|
174
|
+
'description': 'This is the full-resolution image associated with this upload. If the full-resolution image is not available, upload the "hires_image" and the "scalefactors_json.json" file to appropriately scale coordinates.',
|
|
175
|
+
'accepted_types': WSI_TYPES,
|
|
176
|
+
'preprocessing_plugins': None,
|
|
177
|
+
'type': 'item',
|
|
178
|
+
'required': True
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
'name': 'Counts',
|
|
182
|
+
'description': 'This is the file containing per-spot gene counts',
|
|
183
|
+
'accepted_types': ['h5','h5ad','csv','rds','RDS'],
|
|
184
|
+
'preprocessing_plugins': None,
|
|
185
|
+
'type': 'file',
|
|
186
|
+
'parent': 'Image',
|
|
187
|
+
'required': True
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
'name': 'Structures',
|
|
191
|
+
'description': 'If you have annotated any additional structures on the histology image, upload those annotations here.',
|
|
192
|
+
'accepted_types': ANN_TYPES,
|
|
193
|
+
'preprocessing_plugins': None,
|
|
194
|
+
'type': 'annotation',
|
|
195
|
+
'parent': 'Image',
|
|
196
|
+
'required': False
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
'name': 'Scale Factors',
|
|
200
|
+
'description': 'If using the "hires" image, upload the "scalefactors_json.json" file here.',
|
|
201
|
+
'accepted_types': ['json'],
|
|
202
|
+
'preprocessing_plugins': None,
|
|
203
|
+
'type': 'file',
|
|
204
|
+
'parent': 'Image',
|
|
205
|
+
'required': False
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
'name': 'Genes List File',
|
|
209
|
+
'description': 'If you want to include specific genes which are not included in the "most variable" genes, upload CSV file containing one column with those gene IDs.',
|
|
210
|
+
'accepted_types': ['csv'],
|
|
211
|
+
'preprocessing_plugins': None,
|
|
212
|
+
'type': 'file',
|
|
213
|
+
'parent': 'Image',
|
|
214
|
+
'required': False
|
|
215
|
+
}
|
|
216
|
+
],
|
|
217
|
+
processing_plugins=[
|
|
218
|
+
[
|
|
219
|
+
{
|
|
220
|
+
'name': 'CellDeconvolution',
|
|
221
|
+
'image': 'fusionplugins/visium:latest',
|
|
222
|
+
'input_args': [
|
|
223
|
+
{
|
|
224
|
+
'name': 'counts_file',
|
|
225
|
+
'default': {
|
|
226
|
+
'type': 'upload_file',
|
|
227
|
+
'name': 'Counts File'
|
|
228
|
+
},
|
|
229
|
+
'disabled': False
|
|
230
|
+
},
|
|
231
|
+
'organ'
|
|
232
|
+
]
|
|
233
|
+
},
|
|
234
|
+
{
|
|
235
|
+
'name': 'SpotAnnotation',
|
|
236
|
+
'image': 'fusionplugins/visium:latest',
|
|
237
|
+
'input_args': [
|
|
238
|
+
{
|
|
239
|
+
'name': 'counts_file',
|
|
240
|
+
'default': {
|
|
241
|
+
'type': 'upload_file',
|
|
242
|
+
'name': 'Counts File',
|
|
243
|
+
},
|
|
244
|
+
'disabled': True
|
|
245
|
+
},
|
|
246
|
+
{
|
|
247
|
+
'name': 'input_files',
|
|
248
|
+
'default': {
|
|
249
|
+
'type': 'upload_file',
|
|
250
|
+
'name': 'Image'
|
|
251
|
+
},
|
|
252
|
+
'disabled': False
|
|
253
|
+
},
|
|
254
|
+
'use_gene_selection',
|
|
255
|
+
'gene_selection_method',
|
|
256
|
+
'n'
|
|
257
|
+
]
|
|
258
|
+
}
|
|
259
|
+
]
|
|
260
|
+
],
|
|
261
|
+
required_metadata=[
|
|
262
|
+
{
|
|
263
|
+
'name': 'Organ',
|
|
264
|
+
'required': True,
|
|
265
|
+
'item': 'Image'
|
|
266
|
+
}
|
|
267
|
+
]
|
|
268
|
+
)
|
|
269
|
+
|
|
270
|
+
xenium_type = DSAUploadType(
|
|
271
|
+
name = '10x Xenium',
|
|
272
|
+
description='This is for 10x Xenium samples. It includes a morphology (DAPI) image and, optionally, a histology image as well as cell centroids/boundaries and assigned "group" labels or other information for each segmented cell.',
|
|
273
|
+
input_files = [
|
|
274
|
+
{
|
|
275
|
+
'name': 'Morphology Image',
|
|
276
|
+
'description': 'This is the morphology image showing the location of nuclei in the sample at different levels.',
|
|
277
|
+
'accepted_types': ['tif','tiff'],
|
|
278
|
+
'preprocessing_plugins': None,
|
|
279
|
+
'type': 'item',
|
|
280
|
+
'required': True
|
|
281
|
+
},
|
|
282
|
+
{
|
|
283
|
+
'name': 'Histology Image',
|
|
284
|
+
'description': 'This is a histology image from the same section used for alignment of derived cell segmentations.',
|
|
285
|
+
'accepted_types': WSI_TYPES,
|
|
286
|
+
'preprocessing_plugins': None,
|
|
287
|
+
'type': 'item',
|
|
288
|
+
'required': False
|
|
289
|
+
},
|
|
290
|
+
{
|
|
291
|
+
'name': 'Cell Segmentations',
|
|
292
|
+
'description': 'This is a file containing either cell centroids and areas or the boundaries of segmented cells.',
|
|
293
|
+
'accepted_types': ['csv'],
|
|
294
|
+
'preprocessing_plugins': None,
|
|
295
|
+
'type': 'annotation',
|
|
296
|
+
'parent': 'Morphology Image',
|
|
297
|
+
'required': True
|
|
298
|
+
},
|
|
299
|
+
{
|
|
300
|
+
'name': 'Cell Groups',
|
|
301
|
+
'description': 'This is a csv file containing one column with "cell_id" and then other columns which are added to per-cell properties (could be cell group labels or any other measurement).',
|
|
302
|
+
'accepted_types': ['csv'],
|
|
303
|
+
'preprocessing_plugins': None,
|
|
304
|
+
'type': 'file',
|
|
305
|
+
'parent': 'Morphology Image',
|
|
306
|
+
'required': False
|
|
307
|
+
}
|
|
308
|
+
],
|
|
309
|
+
processing_plugins=[
|
|
310
|
+
{
|
|
311
|
+
'name': '',
|
|
312
|
+
'image': '',
|
|
313
|
+
'input_args': [
|
|
314
|
+
{
|
|
315
|
+
|
|
316
|
+
}
|
|
317
|
+
]
|
|
318
|
+
}
|
|
319
|
+
],
|
|
320
|
+
required_metadata=[
|
|
321
|
+
{
|
|
322
|
+
'name': 'Organ',
|
|
323
|
+
'required': True,
|
|
324
|
+
'item': 'Image'
|
|
325
|
+
}
|
|
326
|
+
]
|
|
327
|
+
)
|
|
328
|
+
|
|
329
|
+
hd_type = DSAUploadType(
|
|
330
|
+
name = "10x Visium HD",
|
|
331
|
+
description = 'This is for the 10x Visium HD data type.',
|
|
332
|
+
input_files = [
|
|
333
|
+
{
|
|
334
|
+
'name': 'Image',
|
|
335
|
+
'description': '',
|
|
336
|
+
'accepted_types': WSI_TYPES,
|
|
337
|
+
'preprocessing_plugins': None,
|
|
338
|
+
'type': 'item',
|
|
339
|
+
'required': True
|
|
340
|
+
}
|
|
341
|
+
],
|
|
342
|
+
processing_plugins=[],
|
|
343
|
+
required_metadata=[
|
|
344
|
+
{
|
|
345
|
+
'name': 'Organ',
|
|
346
|
+
'required': True,
|
|
347
|
+
'item': 'Image'
|
|
348
|
+
}
|
|
349
|
+
]
|
|
350
|
+
)
|
|
351
|
+
|
|
352
|
+
# MxIF/PhenoCycler
|
|
353
|
+
mxif_type = DSAUploadType(
|
|
354
|
+
name = "MxIF / PhenoCycler",
|
|
355
|
+
description = 'This is for a multiplexed - immunofluorescence (mxIF) type image containing several different fluorescence channels for different markers. If available, you may also choose to align this image with a same-section histology image.',
|
|
356
|
+
input_files = [
|
|
357
|
+
{
|
|
358
|
+
'name': 'IF Image',
|
|
359
|
+
'description': 'This is a single multi-frame immunofluorescence image containing aligned channels.',
|
|
360
|
+
'accepted_types': ['tif','tiff'],
|
|
361
|
+
'preprocessing_plugins': None,
|
|
362
|
+
'type': 'item',
|
|
363
|
+
'required': True
|
|
364
|
+
},
|
|
365
|
+
{
|
|
366
|
+
'name': 'Histology Image',
|
|
367
|
+
'description': 'This is a same-section histology image which the IF image is aligned to during processing.',
|
|
368
|
+
'accepted_types': WSI_TYPES,
|
|
369
|
+
'preprocessing_plugins': None,
|
|
370
|
+
'type': 'item',
|
|
371
|
+
'required': False
|
|
372
|
+
},
|
|
373
|
+
{
|
|
374
|
+
'name': 'IF Annotations',
|
|
375
|
+
'description': 'If any structures have been segmented from the IF image, upload them here.',
|
|
376
|
+
'accepted_types': ANN_TYPES,
|
|
377
|
+
'preprocessing_plugins': None,
|
|
378
|
+
'type': 'annotation',
|
|
379
|
+
'parent': 'IF Image',
|
|
380
|
+
'required': False
|
|
381
|
+
},
|
|
382
|
+
{
|
|
383
|
+
'name': 'Histology Annotations',
|
|
384
|
+
'description': 'If any structures were segmented from the histology image, upload them here.',
|
|
385
|
+
'accepted_types': ANN_TYPES,
|
|
386
|
+
'preprocessing_plugins': None,
|
|
387
|
+
'type': 'annotation',
|
|
388
|
+
'parent': 'Histology Image',
|
|
389
|
+
'required': False
|
|
390
|
+
}
|
|
391
|
+
],
|
|
392
|
+
processing_plugins = [
|
|
393
|
+
[
|
|
394
|
+
{
|
|
395
|
+
'image': 'fusionplugins/codex:latest',
|
|
396
|
+
'name': 'CellSegmentation',
|
|
397
|
+
'input_args': [
|
|
398
|
+
{
|
|
399
|
+
'name': 'input_image',
|
|
400
|
+
'default': {
|
|
401
|
+
'type': 'upload_file',
|
|
402
|
+
'name': 'IF Image'
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
]
|
|
406
|
+
},
|
|
407
|
+
{
|
|
408
|
+
'image': 'fusionplugins/general:latest',
|
|
409
|
+
'name': 'FeatureExtraction',
|
|
410
|
+
'input_args': [
|
|
411
|
+
{
|
|
412
|
+
'name': 'input_image',
|
|
413
|
+
'default': {
|
|
414
|
+
'type': 'upload_file',
|
|
415
|
+
'name': 'IF Image'
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
]
|
|
419
|
+
}
|
|
420
|
+
],
|
|
421
|
+
{
|
|
422
|
+
'image': 'fusionplugins/general:latest',
|
|
423
|
+
'name': 'FeatureExtraction',
|
|
424
|
+
'input_args': [
|
|
425
|
+
{
|
|
426
|
+
'name': 'input_image',
|
|
427
|
+
'default': {
|
|
428
|
+
'type': 'upload_file',
|
|
429
|
+
'name': 'Histology Image'
|
|
430
|
+
}
|
|
431
|
+
},
|
|
432
|
+
{
|
|
433
|
+
'name': 'extract_sub_compartments',
|
|
434
|
+
'default': {
|
|
435
|
+
'value': True
|
|
436
|
+
}
|
|
437
|
+
},
|
|
438
|
+
'hematoxylin_threshold',
|
|
439
|
+
'eosinophilic_threshold',
|
|
440
|
+
'hematoxylin_min_size',
|
|
441
|
+
'eosinophilic_min_size'
|
|
442
|
+
]
|
|
443
|
+
}
|
|
444
|
+
],
|
|
445
|
+
required_metadata = [
|
|
446
|
+
{
|
|
447
|
+
'name': 'Organ',
|
|
448
|
+
'required': True,
|
|
449
|
+
'item': 'Image'
|
|
450
|
+
}
|
|
451
|
+
]
|
|
452
|
+
)
|
|
453
|
+
|
|
454
|
+
# HuBMAP Processed Dataset
|
|
455
|
+
hubmap_type = DSAUploadType(
|
|
456
|
+
name = "HuBMAP Processed",
|
|
457
|
+
description='This is for a dataset which has been processed by the Human Biomolecular Atlas Program (HuBMAP).',
|
|
458
|
+
input_files = [
|
|
459
|
+
{
|
|
460
|
+
'name': 'Image',
|
|
461
|
+
'description': '',
|
|
462
|
+
'accepted_types': WSI_TYPES,
|
|
463
|
+
'preprocessing_plugins': None,
|
|
464
|
+
'type': 'item',
|
|
465
|
+
'required': True
|
|
466
|
+
}
|
|
467
|
+
],
|
|
468
|
+
processing_plugins= [
|
|
469
|
+
{
|
|
470
|
+
'name': '',
|
|
471
|
+
'image': '',
|
|
472
|
+
'input_args': []
|
|
473
|
+
}
|
|
474
|
+
],
|
|
475
|
+
required_metadata=[
|
|
476
|
+
{
|
|
477
|
+
'name': 'Organ',
|
|
478
|
+
'required': True,
|
|
479
|
+
'item': 'Image'
|
|
480
|
+
},
|
|
481
|
+
{
|
|
482
|
+
'name': 'Sample ID',
|
|
483
|
+
'required': True,
|
|
484
|
+
'item': 'Image'
|
|
485
|
+
},
|
|
486
|
+
{
|
|
487
|
+
'name': 'Assay Type',
|
|
488
|
+
'required': True,
|
|
489
|
+
'item': 'Image'
|
|
490
|
+
}
|
|
491
|
+
]
|
|
492
|
+
)
|
|
493
|
+
|
|
494
|
+
return [
|
|
495
|
+
basic_type,
|
|
496
|
+
kidney_basic_type,
|
|
497
|
+
visium_type,
|
|
498
|
+
xenium_type,
|
|
499
|
+
hd_type,
|
|
500
|
+
mxif_type,
|
|
501
|
+
hubmap_type
|
|
502
|
+
]
|
|
503
|
+
|
|
@@ -3,16 +3,18 @@
|
|
|
3
3
|
from fusion_tools.visualization import Visualization
|
|
4
4
|
from fusion_tools.handler.dsa_handler import DSAHandler
|
|
5
5
|
from fusion_tools.components import (
|
|
6
|
+
SlideMap,
|
|
6
7
|
MultiFrameSlideMap,
|
|
7
8
|
ChannelMixer,
|
|
8
9
|
OverlayOptions,
|
|
9
10
|
PropertyViewer,
|
|
10
11
|
GlobalPropertyPlotter,
|
|
11
12
|
HRAViewer,
|
|
12
|
-
FeatureAnnotation,
|
|
13
13
|
BulkLabels
|
|
14
14
|
)
|
|
15
15
|
|
|
16
|
+
from fusion_tools.fusion.data_types import get_upload_types
|
|
17
|
+
|
|
16
18
|
|
|
17
19
|
def get_layout(args):
|
|
18
20
|
|
|
@@ -27,12 +29,10 @@ def get_layout(args):
|
|
|
27
29
|
|
|
28
30
|
dsa_plugin_progress = dsa_handler.create_plugin_progress()
|
|
29
31
|
|
|
30
|
-
dsa_dataset_builder = dsa_handler.create_dataset_builder(
|
|
31
|
-
include = args['dataset_builder_include']
|
|
32
|
-
)
|
|
32
|
+
dsa_dataset_builder = dsa_handler.create_dataset_builder()
|
|
33
33
|
|
|
34
34
|
dsa_dataset_uploader = dsa_handler.create_uploader(
|
|
35
|
-
|
|
35
|
+
upload_types = get_upload_types()
|
|
36
36
|
)
|
|
37
37
|
|
|
38
38
|
user_surveys = []
|
|
@@ -51,12 +51,9 @@ def get_layout(args):
|
|
|
51
51
|
components = {
|
|
52
52
|
"Visualization": [
|
|
53
53
|
[
|
|
54
|
-
|
|
55
|
-
],
|
|
56
|
-
[
|
|
54
|
+
SlideMap(),
|
|
57
55
|
[
|
|
58
56
|
OverlayOptions(),
|
|
59
|
-
ChannelMixer(),
|
|
60
57
|
PropertyViewer(ignore_list=['_id','_index']),
|
|
61
58
|
GlobalPropertyPlotter(ignore_list = ['_id','_index']),
|
|
62
59
|
HRAViewer(),
|
|
@@ -64,6 +61,19 @@ def get_layout(args):
|
|
|
64
61
|
]
|
|
65
62
|
]
|
|
66
63
|
],
|
|
64
|
+
"MultiFrame Visualization": [
|
|
65
|
+
[
|
|
66
|
+
MultiFrameSlideMap(),
|
|
67
|
+
[
|
|
68
|
+
ChannelMixer(),
|
|
69
|
+
OverlayOptions(),
|
|
70
|
+
PropertyViewer(ignore_list = ['_id','_index']),
|
|
71
|
+
GlobalPropertyPlotter(ignore_list = ['_id','_index']),
|
|
72
|
+
HRAViewer(),
|
|
73
|
+
BulkLabels()
|
|
74
|
+
]
|
|
75
|
+
]
|
|
76
|
+
],
|
|
67
77
|
"Dataset Builder": [
|
|
68
78
|
dsa_dataset_builder
|
|
69
79
|
],
|
|
@@ -82,7 +82,8 @@ class DatasetBuilder(DSATool):
|
|
|
82
82
|
'Collection Name': f'User: {session_data["current_user"]["login"]}',
|
|
83
83
|
'Collection ID': session_data["current_user"]['_id'],
|
|
84
84
|
'Number of Folder': 2,
|
|
85
|
-
'Last Updated': '-'
|
|
85
|
+
'Last Updated': '-',
|
|
86
|
+
'token': session_data['current_user']['token']
|
|
86
87
|
})
|
|
87
88
|
|
|
88
89
|
collections_df = pd.DataFrame.from_records(collections_info)
|
|
@@ -146,7 +147,10 @@ class DatasetBuilder(DSATool):
|
|
|
146
147
|
dcc.Store(
|
|
147
148
|
id = {'type':'dataset-builder-data-store','index': 0},
|
|
148
149
|
storage_type='memory',
|
|
149
|
-
data = json.dumps({
|
|
150
|
+
data = json.dumps({
|
|
151
|
+
'selected_slides':starting_slides,
|
|
152
|
+
'selected_collections': [],
|
|
153
|
+
'available_collections': collections_df.to_dict("records")})
|
|
150
154
|
)
|
|
151
155
|
),
|
|
152
156
|
dbc.Row([
|
|
@@ -238,7 +242,8 @@ class DatasetBuilder(DSATool):
|
|
|
238
242
|
],
|
|
239
243
|
[
|
|
240
244
|
State({'type':'dataset-builder-data-store','index': ALL},'data'),
|
|
241
|
-
State({'type':'dataset-builder-collection-contents-div','index': ALL},'children')
|
|
245
|
+
State({'type':'dataset-builder-collection-contents-div','index': ALL},'children'),
|
|
246
|
+
State('anchor-vis-store','data')
|
|
242
247
|
],
|
|
243
248
|
[
|
|
244
249
|
Output({'type':'dataset-builder-collection-contents-div','index': ALL},'children'),
|
|
@@ -323,7 +328,7 @@ class DatasetBuilder(DSATool):
|
|
|
323
328
|
dataframe = pd.json_normalize(dataframe.to_dict('records'))
|
|
324
329
|
selectable_table = dash_table.DataTable(
|
|
325
330
|
id = id,
|
|
326
|
-
columns = [{'name':i,'id':i,'deletable':False} for i in dataframe.columns],
|
|
331
|
+
columns = [{'name':i,'id':i,'deletable':False} for i in dataframe.columns if not i=='token'],
|
|
327
332
|
data = dataframe.to_dict('records'),
|
|
328
333
|
editable = False,
|
|
329
334
|
filter_action='native',
|
|
@@ -352,13 +357,15 @@ class DatasetBuilder(DSATool):
|
|
|
352
357
|
|
|
353
358
|
return selectable_table
|
|
354
359
|
|
|
355
|
-
def organize_folder_contents(self, folder_info:dict, show_empty:bool=True, ignore_histoqc:bool=True)->list:
|
|
360
|
+
def organize_folder_contents(self, folder_info:dict, show_empty:bool=True, ignore_histoqc:bool=True,session_data:dict = {})->list:
|
|
356
361
|
"""For a given folder selection, return a list of slides(0th) and folders (1th)
|
|
357
362
|
|
|
358
363
|
:param folder_info: Folder info dict returned by self.handler.get_path_info(path)
|
|
359
364
|
:type folder_info: dict
|
|
360
365
|
:param show_empty: Whether or not to display folders which contain 0 slides, defaults to False
|
|
361
366
|
:type show_empty: bool, optional
|
|
367
|
+
:param session_data: Current session information
|
|
368
|
+
:type session_data: dict
|
|
362
369
|
:return: List of slides within the current folder as well as folders within that folder
|
|
363
370
|
:rtype: list
|
|
364
371
|
"""
|
|
@@ -371,7 +378,8 @@ class DatasetBuilder(DSATool):
|
|
|
371
378
|
all_folder_slides = self.handler.get_folder_slides(
|
|
372
379
|
folder_path = folder_info['_id'],
|
|
373
380
|
folder_type = folder_info['_modelType'],
|
|
374
|
-
ignore_histoqc=ignore_histoqc
|
|
381
|
+
ignore_histoqc=ignore_histoqc,
|
|
382
|
+
user_token = session_data['current_user']['token'] if 'current_user' in session_data else None
|
|
375
383
|
)
|
|
376
384
|
|
|
377
385
|
folder_slides_folders = [i['folderId'] for i in all_folder_slides]
|
|
@@ -381,8 +389,14 @@ class DatasetBuilder(DSATool):
|
|
|
381
389
|
if not u==folder_info['_id'] and not u in folders_in_folder:
|
|
382
390
|
# This is for all folders in this folder
|
|
383
391
|
# This grabs parent folders of this folder
|
|
384
|
-
u_folder_info = self.handler.get_folder_info(
|
|
385
|
-
|
|
392
|
+
u_folder_info = self.handler.get_folder_info(
|
|
393
|
+
folder_id=u,
|
|
394
|
+
user_token = session_data['current_user']['token'] if 'current_user' in session_data else None
|
|
395
|
+
)
|
|
396
|
+
u_folder_rootpath = self.handler.get_folder_rootpath(
|
|
397
|
+
u,
|
|
398
|
+
user_token = session_data['current_user']['token'] if 'current_user' in session_data else None
|
|
399
|
+
)
|
|
386
400
|
# Folders in order from collection-->child folder-->etc.
|
|
387
401
|
folder_ids = [i['object']['_id'] for i in u_folder_rootpath]
|
|
388
402
|
|
|
@@ -400,7 +414,8 @@ class DatasetBuilder(DSATool):
|
|
|
400
414
|
|
|
401
415
|
|
|
402
416
|
child_folder_path_info = self.handler.get_path_info(
|
|
403
|
-
path = child_folder_path
|
|
417
|
+
path = child_folder_path,
|
|
418
|
+
user_token = session_data['current_user']['token'] if 'current_user' in session_data else None
|
|
404
419
|
)
|
|
405
420
|
if not child_folder_path_info['_id'] in folders_in_folder:
|
|
406
421
|
folders_in_folder.append(child_folder_path_info['_id'])
|
|
@@ -429,10 +444,13 @@ class DatasetBuilder(DSATool):
|
|
|
429
444
|
|
|
430
445
|
else:
|
|
431
446
|
|
|
447
|
+
folders_in_folder = []
|
|
448
|
+
unique_folders = []
|
|
432
449
|
user_folders = ['Private','Public']
|
|
433
450
|
for u_f in user_folders:
|
|
434
451
|
user_folder_info = self.handler.get_path_info(
|
|
435
|
-
path = f'/user/{folder_info["login"]}/{u_f}'
|
|
452
|
+
path = f'/user/{folder_info["login"]}/{u_f}',
|
|
453
|
+
user_token = session_data['current_user']['token'] if 'current_user' in session_data else None
|
|
436
454
|
)
|
|
437
455
|
|
|
438
456
|
folder_folders.append({
|
|
@@ -443,16 +461,23 @@ class DatasetBuilder(DSATool):
|
|
|
443
461
|
'Last Updated': user_folder_info['updated']
|
|
444
462
|
})
|
|
445
463
|
|
|
464
|
+
unique_folders.append(user_folder_info['_id'])
|
|
465
|
+
|
|
466
|
+
|
|
446
467
|
if show_empty:
|
|
447
468
|
# This is how you get all the empty folders within a folder (does not get child empty folders)
|
|
448
469
|
empty_folders = self.handler.get_folder_folders(
|
|
449
470
|
folder_id = folder_info['_id'],
|
|
450
|
-
folder_type = folder_info['_modelType']
|
|
471
|
+
folder_type = folder_info['_modelType'],
|
|
472
|
+
user_token = session_data['current_user']['token'] if 'current_user' in session_data else None
|
|
451
473
|
)
|
|
452
474
|
|
|
453
475
|
for f in empty_folders:
|
|
454
476
|
if not f['_id'] in folders_in_folder and not f['_id'] in unique_folders:
|
|
455
|
-
|
|
477
|
+
if not 'current_user' in session_data:
|
|
478
|
+
folder_info = self.handler.gc.get(f'/folder/{f["_id"]}/details')
|
|
479
|
+
else:
|
|
480
|
+
folder_info = self.handler.gc.get(f'/folder/{f["_id"]}/details?token={session_data["current_user"]["token"]}')
|
|
456
481
|
folder_folders.append(
|
|
457
482
|
{
|
|
458
483
|
'Folder Name': f['name'],
|
|
@@ -528,20 +553,23 @@ class DatasetBuilder(DSATool):
|
|
|
528
553
|
|
|
529
554
|
return slide_card
|
|
530
555
|
|
|
531
|
-
def collection_selection(self, collection_rows, builder_data, collection_div_children):
|
|
556
|
+
def collection_selection(self, collection_rows, builder_data, collection_div_children,session_data):
|
|
532
557
|
"""Callback for when one/multiple collections are selected from the collections table
|
|
533
558
|
|
|
534
559
|
:param collection_rows: Row indices of selected collections
|
|
535
560
|
:type collection_rows: list
|
|
536
561
|
:param builder_data: Data store on available collections and currently included slides
|
|
537
562
|
:type builder_data: list
|
|
538
|
-
:param
|
|
539
|
-
:type
|
|
563
|
+
:param collection_div_children: Child cards created by collection_selection
|
|
564
|
+
:type collection_div_children: list
|
|
565
|
+
:param session_data: Current session information
|
|
566
|
+
:type session_data: dict
|
|
540
567
|
:return: Children of collection-contents-div (items/folders within selected collections)
|
|
541
568
|
:rtype: list
|
|
542
569
|
"""
|
|
543
570
|
selected_collections = get_pattern_matching_value(collection_rows)
|
|
544
571
|
builder_data = json.loads(get_pattern_matching_value(builder_data))
|
|
572
|
+
session_data = json.loads(session_data)
|
|
545
573
|
|
|
546
574
|
collection_card_indices = self.get_component_indices(collection_div_children)
|
|
547
575
|
|
|
@@ -559,11 +587,19 @@ class DatasetBuilder(DSATool):
|
|
|
559
587
|
# For each collection, grab all items and unique folders (as well as those that are not nested in a folder)
|
|
560
588
|
if not 'User: ' in collection_info["Collection Name"]:
|
|
561
589
|
folder_slides, folder_folders = self.organize_folder_contents(
|
|
562
|
-
folder_info = self.handler.get_path_info(
|
|
590
|
+
folder_info = self.handler.get_path_info(
|
|
591
|
+
f'/collection/{collection_info["Collection Name"]}',
|
|
592
|
+
user_token = session_data['current_user']['token'] if 'current_user' in session_data else None
|
|
593
|
+
),
|
|
594
|
+
session_data = session_data
|
|
563
595
|
)
|
|
564
596
|
else:
|
|
565
597
|
folder_slides, folder_folders = self.organize_folder_contents(
|
|
566
|
-
folder_info=self.handler.get_path_info(
|
|
598
|
+
folder_info=self.handler.get_path_info(
|
|
599
|
+
f'/user/{collection_info["Collection Name"].replace("User: ","")}',
|
|
600
|
+
user_token = session_data['current_user']['token'] if 'current_user' in session_data else None
|
|
601
|
+
),
|
|
602
|
+
session_data = session_data
|
|
567
603
|
)
|
|
568
604
|
|
|
569
605
|
if len(folder_slides)>0:
|
|
@@ -32,12 +32,17 @@ from fusion_tools.handler.resource_selector import DSAResourceSelector
|
|
|
32
32
|
from girder_job_sequence import Job, Sequence
|
|
33
33
|
from girder_job_sequence.utils import from_list, from_dict
|
|
34
34
|
import threading
|
|
35
|
+
import large_image
|
|
36
|
+
|
|
35
37
|
|
|
36
38
|
# Maximum allowed size of uploads (Mb)
|
|
37
39
|
MAX_UPLOAD_SIZE = 1e4
|
|
38
40
|
# Minimum chunk size (Mb)
|
|
39
41
|
MIN_UPLOAD_SIZE = 6
|
|
40
42
|
|
|
43
|
+
WSI_TYPES = [i for i in list(large_image.listSources()['extensions'].keys()) if not i in ['json','yaml','yml']]
|
|
44
|
+
ANN_TYPES = ['json','geojson','xml','csv']
|
|
45
|
+
|
|
41
46
|
|
|
42
47
|
class DSAUploadType:
|
|
43
48
|
"""Formatted upload type for a DSAUploader Component.
|
|
@@ -305,7 +310,8 @@ class DSAUploadHandler:
|
|
|
305
310
|
upload_info
|
|
306
311
|
)
|
|
307
312
|
post_response = {
|
|
308
|
-
'n_annotations': post_response
|
|
313
|
+
'n_annotations': post_response,
|
|
314
|
+
'_modelType': 'annotation'
|
|
309
315
|
}
|
|
310
316
|
else:
|
|
311
317
|
post_response = r.filename
|
|
@@ -1719,7 +1725,7 @@ class DSAUploader(DSATool):
|
|
|
1719
1725
|
file_uploads = html.Div([
|
|
1720
1726
|
dbc.Stack([
|
|
1721
1727
|
html.Div([
|
|
1722
|
-
html.H5(f'{f["name"]}
|
|
1728
|
+
html.H5(f'{f["name"]}',style={'textTransform':'none'}),
|
|
1723
1729
|
html.Div(
|
|
1724
1730
|
self.create_upload_component(
|
|
1725
1731
|
file_info = f | {'parentId': folder_info["_id"],'parentType': 'folder', 'fusion_upload_name': f['name'], 'fusion_upload_type': f['type']},
|
|
@@ -1730,6 +1736,11 @@ class DSAUploader(DSATool):
|
|
|
1730
1736
|
id = {'type': f'{self.component_prefix}-dsa-uploader-file-upload-div','index': f_idx},
|
|
1731
1737
|
style = {'width': '100%'}
|
|
1732
1738
|
),
|
|
1739
|
+
dbc.Tooltip(
|
|
1740
|
+
target = {'type': f'{self.component_prefix}-dsa-uploader-file-upload-div','index': f_idx},
|
|
1741
|
+
placement='top',
|
|
1742
|
+
children = ','.join(f['accepted_types'])
|
|
1743
|
+
),
|
|
1733
1744
|
html.Div(
|
|
1734
1745
|
id = {'type': f'{self.component_prefix}-dsa-uploader-file-upload-status-div','index': f_idx},
|
|
1735
1746
|
children = []
|
|
@@ -584,7 +584,7 @@ def geojson_to_histomics(geojson_anns: Union[list,dict]):
|
|
|
584
584
|
{
|
|
585
585
|
'type': 'polyline',
|
|
586
586
|
'user': f['properties'],
|
|
587
|
-
'points': [i+[0] for i in f['geometry']['coordinates'][0]]
|
|
587
|
+
'points': [list(i)+[0] if type(i)==tuple else i+[0] for i in f['geometry']['coordinates'][0]]
|
|
588
588
|
}
|
|
589
589
|
for f in g['features']
|
|
590
590
|
]
|
|
@@ -841,7 +841,7 @@ def spatially_aggregate(child_geo:dict, parent_geos: list, separate: bool = True
|
|
|
841
841
|
a_shape = shape(a['geometry'])
|
|
842
842
|
agg_props = {}
|
|
843
843
|
for b_idx,b in enumerate(base_gdf):
|
|
844
|
-
b_intersect = b.sindex.query(a_shape,predicate='
|
|
844
|
+
b_intersect = b.sindex.query(a_shape,predicate='intersects')
|
|
845
845
|
if len(b_intersect)>0:
|
|
846
846
|
agg_props[base_names[b_idx]] = []
|
|
847
847
|
for c in b_intersect:
|
|
@@ -46,6 +46,7 @@ tests/test_extract_recursive.py
|
|
|
46
46
|
tests/test_feature_annotation.py
|
|
47
47
|
tests/test_feature_extraction.py
|
|
48
48
|
tests/test_file_selector.py
|
|
49
|
+
tests/test_fusion_layout.py
|
|
49
50
|
tests/test_generate_property_dict.py
|
|
50
51
|
tests/test_get_gene_info.py
|
|
51
52
|
tests/test_global_property_plotter.py
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"""Testing FUSION layout
|
|
2
|
+
"""
|
|
3
|
+
|
|
4
|
+
import os
|
|
5
|
+
import sys
|
|
6
|
+
sys.path.append('./src/')
|
|
7
|
+
|
|
8
|
+
from fusion_tools.fusion.vis import get_layout
|
|
9
|
+
|
|
10
|
+
def main():
|
|
11
|
+
|
|
12
|
+
dsa_url = os.environ.get('DSA_URL')
|
|
13
|
+
dsa_user = os.environ.get('DSA_USER')
|
|
14
|
+
dsa_pword = os.environ.get('DSA_PWORD')
|
|
15
|
+
|
|
16
|
+
if all([i is None for i in [dsa_url,dsa_user,dsa_pword]]):
|
|
17
|
+
raise Exception('Need to initialize with at least the environment variable: DSA_URL')
|
|
18
|
+
|
|
19
|
+
initial_items = [
|
|
20
|
+
'6495a4e03e6ae3107da10dc5',
|
|
21
|
+
'6495a4df3e6ae3107da10dc2'
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
args_dict = {
|
|
25
|
+
'girderApiUrl': dsa_url,
|
|
26
|
+
'user': dsa_user,
|
|
27
|
+
'pword': dsa_pword,
|
|
28
|
+
'initialItems': initial_items,
|
|
29
|
+
'app_options': {
|
|
30
|
+
'port': 8050
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
fusion_vis = get_layout(args_dict)
|
|
35
|
+
|
|
36
|
+
fusion_vis.start()
|
|
37
|
+
|
|
38
|
+
if __name__=='__main__':
|
|
39
|
+
main()
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
"""Defining UploadTypes which are accepted in FUSION
|
|
2
|
-
"""
|
|
3
|
-
|
|
4
|
-
from fusion_tools.handler.dataset_uploader import DSAUploadType
|
|
5
|
-
|
|
6
|
-
def get_upload_types(args):
|
|
7
|
-
|
|
8
|
-
# Basic Type:
|
|
9
|
-
basic_type = DSAUploadType(
|
|
10
|
-
name = "Histology Image",
|
|
11
|
-
input_files = [],
|
|
12
|
-
processing_plugins=[],
|
|
13
|
-
required_metadata=[]
|
|
14
|
-
)
|
|
15
|
-
|
|
16
|
-
# 10x Types:
|
|
17
|
-
visium_type = DSAUploadType(
|
|
18
|
-
name = '10x Visium',
|
|
19
|
-
input_files = [],
|
|
20
|
-
processing_plugins=[],
|
|
21
|
-
required_metadata=[]
|
|
22
|
-
)
|
|
23
|
-
|
|
24
|
-
xenium_type = DSAUploadType(
|
|
25
|
-
name = '10x Xenium',
|
|
26
|
-
input_files = [],
|
|
27
|
-
processing_plugins=[],
|
|
28
|
-
required_metadata=[]
|
|
29
|
-
)
|
|
30
|
-
|
|
31
|
-
hd_type = DSAUploadType(
|
|
32
|
-
name = "10x Visium HD",
|
|
33
|
-
input_files = [],
|
|
34
|
-
processing_plugins=[],
|
|
35
|
-
required_metadata=[]
|
|
36
|
-
)
|
|
37
|
-
|
|
38
|
-
# MxIF/CODEX
|
|
39
|
-
mxif_type = DSAUploadType(
|
|
40
|
-
name = "MxIF / CODEX",
|
|
41
|
-
input_files = [],
|
|
42
|
-
processing_plugins = [],
|
|
43
|
-
required_metadata = []
|
|
44
|
-
)
|
|
45
|
-
|
|
46
|
-
# HuBMAP Processed Dataset
|
|
47
|
-
hubmap_type = DSAUploadType(
|
|
48
|
-
name = "HuBMAP Processed",
|
|
49
|
-
input_files = [],
|
|
50
|
-
processing_plugins= [],
|
|
51
|
-
required_metadata=[]
|
|
52
|
-
)
|
|
53
|
-
|
|
54
|
-
return [
|
|
55
|
-
basic_type,
|
|
56
|
-
visium_type,
|
|
57
|
-
xenium_type,
|
|
58
|
-
hd_type,
|
|
59
|
-
mxif_type,
|
|
60
|
-
hubmap_type
|
|
61
|
-
]
|
|
62
|
-
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|