siibra 1.0a1__1-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.
Potentially problematic release.
This version of siibra might be problematic. Click here for more details.
- siibra/VERSION +1 -0
- siibra/__init__.py +164 -0
- siibra/commons.py +823 -0
- siibra/configuration/__init__.py +17 -0
- siibra/configuration/configuration.py +189 -0
- siibra/configuration/factory.py +589 -0
- siibra/core/__init__.py +16 -0
- siibra/core/assignment.py +110 -0
- siibra/core/atlas.py +239 -0
- siibra/core/concept.py +308 -0
- siibra/core/parcellation.py +387 -0
- siibra/core/region.py +1223 -0
- siibra/core/space.py +131 -0
- siibra/core/structure.py +111 -0
- siibra/exceptions.py +63 -0
- siibra/experimental/__init__.py +19 -0
- siibra/experimental/contour.py +61 -0
- siibra/experimental/cortical_profile_sampler.py +57 -0
- siibra/experimental/patch.py +98 -0
- siibra/experimental/plane3d.py +256 -0
- siibra/explorer/__init__.py +17 -0
- siibra/explorer/url.py +222 -0
- siibra/explorer/util.py +87 -0
- siibra/features/__init__.py +117 -0
- siibra/features/anchor.py +224 -0
- siibra/features/connectivity/__init__.py +33 -0
- siibra/features/connectivity/functional_connectivity.py +57 -0
- siibra/features/connectivity/regional_connectivity.py +494 -0
- siibra/features/connectivity/streamline_counts.py +27 -0
- siibra/features/connectivity/streamline_lengths.py +27 -0
- siibra/features/connectivity/tracing_connectivity.py +30 -0
- siibra/features/dataset/__init__.py +17 -0
- siibra/features/dataset/ebrains.py +90 -0
- siibra/features/feature.py +970 -0
- siibra/features/image/__init__.py +27 -0
- siibra/features/image/image.py +115 -0
- siibra/features/image/sections.py +26 -0
- siibra/features/image/volume_of_interest.py +88 -0
- siibra/features/tabular/__init__.py +24 -0
- siibra/features/tabular/bigbrain_intensity_profile.py +77 -0
- siibra/features/tabular/cell_density_profile.py +298 -0
- siibra/features/tabular/cortical_profile.py +322 -0
- siibra/features/tabular/gene_expression.py +257 -0
- siibra/features/tabular/layerwise_bigbrain_intensities.py +62 -0
- siibra/features/tabular/layerwise_cell_density.py +95 -0
- siibra/features/tabular/receptor_density_fingerprint.py +192 -0
- siibra/features/tabular/receptor_density_profile.py +110 -0
- siibra/features/tabular/regional_timeseries_activity.py +294 -0
- siibra/features/tabular/tabular.py +139 -0
- siibra/livequeries/__init__.py +19 -0
- siibra/livequeries/allen.py +352 -0
- siibra/livequeries/bigbrain.py +197 -0
- siibra/livequeries/ebrains.py +145 -0
- siibra/livequeries/query.py +49 -0
- siibra/locations/__init__.py +91 -0
- siibra/locations/boundingbox.py +454 -0
- siibra/locations/location.py +115 -0
- siibra/locations/point.py +344 -0
- siibra/locations/pointcloud.py +349 -0
- siibra/retrieval/__init__.py +27 -0
- siibra/retrieval/cache.py +233 -0
- siibra/retrieval/datasets.py +389 -0
- siibra/retrieval/exceptions/__init__.py +27 -0
- siibra/retrieval/repositories.py +769 -0
- siibra/retrieval/requests.py +659 -0
- siibra/vocabularies/__init__.py +45 -0
- siibra/vocabularies/gene_names.json +29176 -0
- siibra/vocabularies/receptor_symbols.json +210 -0
- siibra/vocabularies/region_aliases.json +460 -0
- siibra/volumes/__init__.py +23 -0
- siibra/volumes/parcellationmap.py +1279 -0
- siibra/volumes/providers/__init__.py +20 -0
- siibra/volumes/providers/freesurfer.py +113 -0
- siibra/volumes/providers/gifti.py +165 -0
- siibra/volumes/providers/neuroglancer.py +736 -0
- siibra/volumes/providers/nifti.py +266 -0
- siibra/volumes/providers/provider.py +107 -0
- siibra/volumes/sparsemap.py +468 -0
- siibra/volumes/volume.py +892 -0
- siibra-1.0.0a1.dist-info/LICENSE +201 -0
- siibra-1.0.0a1.dist-info/METADATA +160 -0
- siibra-1.0.0a1.dist-info/RECORD +84 -0
- siibra-1.0.0a1.dist-info/WHEEL +5 -0
- siibra-1.0.0a1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Copyright 2018-2024
|
|
2
|
+
# Institute of Neuroscience and Medicine (INM-1), Forschungszentrum Jülich GmbH
|
|
3
|
+
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
"""Subpackage handling the digestion of different volume and mesh types"""
|
|
16
|
+
|
|
17
|
+
from .neuroglancer import NeuroglancerProvider, NeuroglancerMesh
|
|
18
|
+
from .nifti import NiftiProvider
|
|
19
|
+
from .gifti import GiftiSurfaceLabeling, GiftiMesh
|
|
20
|
+
from .freesurfer import ZippedFreesurferAnnot, FreesurferAnnot
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# Copyright 2018-2024
|
|
2
|
+
# Institute of Neuroscience and Medicine (INM-1), Forschungszentrum Jülich GmbH
|
|
3
|
+
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
"""Handles reading and preparing gii files."""
|
|
16
|
+
|
|
17
|
+
from . import provider as _provider
|
|
18
|
+
|
|
19
|
+
from ...retrieval.requests import HttpRequest, ZipfileRequest
|
|
20
|
+
|
|
21
|
+
import numpy as np
|
|
22
|
+
from typing import Union, Dict, TYPE_CHECKING
|
|
23
|
+
|
|
24
|
+
if TYPE_CHECKING:
|
|
25
|
+
from ...locations import boundingbox as _boundingbox
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class FreesurferAnnot(_provider.VolumeProvider, srctype="freesurfer-annot"):
|
|
29
|
+
def __init__(self, url: Union[str, dict]):
|
|
30
|
+
self._init_url = url
|
|
31
|
+
if isinstance(url, str): # single mesh labelling
|
|
32
|
+
self._loaders = {None: HttpRequest(url)}
|
|
33
|
+
elif isinstance(url, dict): # named label fragments
|
|
34
|
+
self._loaders = {lbl: HttpRequest(u) for lbl, u in url.items()}
|
|
35
|
+
else:
|
|
36
|
+
raise NotImplementedError(f"Urls for {self.__class__.__name__} are expected to be of type str.")
|
|
37
|
+
|
|
38
|
+
def fetch(self, fragment: str = None, label: int = None, **kwargs):
|
|
39
|
+
"""Returns a 1D numpy array of label indices."""
|
|
40
|
+
vertex_labels = []
|
|
41
|
+
if fragment is None:
|
|
42
|
+
matched_frags = list(self._loaders.keys())
|
|
43
|
+
else:
|
|
44
|
+
matched_frags = [frg for frg in self._loaders.keys() if fragment.lower() in frg.lower()]
|
|
45
|
+
if len(matched_frags) != 1:
|
|
46
|
+
raise ValueError(
|
|
47
|
+
f"Requested fragment '{fragment}' could not be matched uniquely "
|
|
48
|
+
f"to [{', '.join(self._loaders)}]"
|
|
49
|
+
)
|
|
50
|
+
for frag in matched_frags:
|
|
51
|
+
frag_labels, *_ = self._loaders[frag].data
|
|
52
|
+
if label is not None: # create the mask
|
|
53
|
+
selected_label = frag_labels == label
|
|
54
|
+
frag_labels[selected_label] = 1
|
|
55
|
+
frag_labels[~selected_label] = 0
|
|
56
|
+
else:
|
|
57
|
+
frag_labels[frag_labels == -1] = 0 # annot files store backgorund as -1 while siibra uses 0
|
|
58
|
+
vertex_labels.append(frag_labels)
|
|
59
|
+
|
|
60
|
+
return {"labels": np.hstack(vertex_labels)}
|
|
61
|
+
|
|
62
|
+
def get_boundingbox(self, clip=False, background=0.0) -> '_boundingbox.BoundingBox':
|
|
63
|
+
raise NotImplementedError(
|
|
64
|
+
f"Bounding box access to {self.__class__.__name__} objects not yet implemented."
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
@property
|
|
68
|
+
def _url(self) -> Union[str, Dict[str, str]]:
|
|
69
|
+
return self._init_url
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
class ZippedFreesurferAnnot(_provider.VolumeProvider, srctype="zip/freesurfer-annot"):
|
|
73
|
+
def __init__(self, url: Union[str, dict]):
|
|
74
|
+
self._init_url = url
|
|
75
|
+
if isinstance(url, str): # single mesh labelling
|
|
76
|
+
self._loaders = {None: ZipfileRequest(*url.split(" "))}
|
|
77
|
+
elif isinstance(url, dict): # named label fragments
|
|
78
|
+
self._loaders = {lbl: ZipfileRequest(*u.split(" ")) for lbl, u in url.items()}
|
|
79
|
+
else:
|
|
80
|
+
raise NotImplementedError(f"Urls for {self.__class__.__name__} are expected to be of type str.")
|
|
81
|
+
|
|
82
|
+
def fetch(self, fragment: str = None, label: int = None, **kwargs):
|
|
83
|
+
"""Returns a 1D numpy array of label indices."""
|
|
84
|
+
vertex_labels = []
|
|
85
|
+
if fragment is None:
|
|
86
|
+
matched_frags = list(self._loaders.keys())
|
|
87
|
+
else:
|
|
88
|
+
matched_frags = [frg for frg in self._loaders.keys() if fragment.lower() in frg.lower()]
|
|
89
|
+
if len(matched_frags) != 1:
|
|
90
|
+
raise ValueError(
|
|
91
|
+
f"Requested fragment '{fragment}' could not be matched uniquely "
|
|
92
|
+
f"to [{', '.join(self._loaders)}]"
|
|
93
|
+
)
|
|
94
|
+
for frag in matched_frags:
|
|
95
|
+
frag_labels, *_ = self._loaders[frag].data
|
|
96
|
+
if label is not None: # create the mask
|
|
97
|
+
selected_label = frag_labels == label
|
|
98
|
+
frag_labels[selected_label] = 1
|
|
99
|
+
frag_labels[~selected_label] = 0
|
|
100
|
+
else:
|
|
101
|
+
frag_labels[frag_labels == -1] = 0 # annot files store backgorund as -1 while siibra uses 0
|
|
102
|
+
vertex_labels.append(frag_labels)
|
|
103
|
+
|
|
104
|
+
return {"labels": np.hstack(vertex_labels)}
|
|
105
|
+
|
|
106
|
+
def get_boundingbox(self, clip=False, background=0.0) -> '_boundingbox.BoundingBox':
|
|
107
|
+
raise NotImplementedError(
|
|
108
|
+
f"Bounding box access to {self.__class__.__name__} objects not yet implemented."
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
@property
|
|
112
|
+
def _url(self) -> Union[str, Dict[str, str]]:
|
|
113
|
+
return self._init_url
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
# Copyright 2018-2024
|
|
2
|
+
# Institute of Neuroscience and Medicine (INM-1), Forschungszentrum Jülich GmbH
|
|
3
|
+
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
"""Handles reading and preparing gii files."""
|
|
16
|
+
|
|
17
|
+
from . import provider as _provider
|
|
18
|
+
|
|
19
|
+
from ...retrieval import requests
|
|
20
|
+
from ...commons import logger, merge_meshes
|
|
21
|
+
from ...locations import boundingbox as _boundingbox
|
|
22
|
+
|
|
23
|
+
import numpy as np
|
|
24
|
+
from typing import Union, Dict
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class GiftiMesh(_provider.VolumeProvider, srctype="gii-mesh"):
|
|
28
|
+
"""
|
|
29
|
+
One or more surface mesh fragments in Gifti format.
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
def __init__(self, url: Union[str, Dict[str, str]], volume=None):
|
|
33
|
+
self._init_url = url
|
|
34
|
+
self.volume = volume
|
|
35
|
+
# TODO duplicated code to NgMesh
|
|
36
|
+
if isinstance(url, str): # single mesh
|
|
37
|
+
self._loaders = {None: requests.HttpRequest(url)}
|
|
38
|
+
elif isinstance(url, dict): # named mesh fragments
|
|
39
|
+
self._loaders = {lbl: requests.HttpRequest(u) for lbl, u in url.items()}
|
|
40
|
+
else:
|
|
41
|
+
raise NotImplementedError(f"Urls for {self.__class__.__name__} are expected to be of type str or dict.")
|
|
42
|
+
|
|
43
|
+
@property
|
|
44
|
+
def _url(self) -> Union[str, Dict[str, str]]:
|
|
45
|
+
return self._init_url
|
|
46
|
+
|
|
47
|
+
def get_boundingbox(self, clip=False, background=0.0, **fetch_kwargs) -> '_boundingbox.BoundingBox':
|
|
48
|
+
"""
|
|
49
|
+
Bounding box calculation is not yet implemented for meshes.
|
|
50
|
+
"""
|
|
51
|
+
raise NotImplementedError(
|
|
52
|
+
f"Bounding box access to {self.__class__.__name__} objects not yet implemented."
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
@property
|
|
56
|
+
def fragments(self):
|
|
57
|
+
return [k for k in self._loaders if k is not None]
|
|
58
|
+
|
|
59
|
+
def fetch(self, fragment: str = None, **kwargs):
|
|
60
|
+
"""
|
|
61
|
+
Returns the mesh as a dictionary with two numpy arrays.
|
|
62
|
+
|
|
63
|
+
Parameters
|
|
64
|
+
----------
|
|
65
|
+
fragment: str, default: None
|
|
66
|
+
A fragment name can be specified to choose from multiple fragments.
|
|
67
|
+
|
|
68
|
+
Note
|
|
69
|
+
----
|
|
70
|
+
If not specified, multiple fragments will be merged into one mesh.
|
|
71
|
+
In such a case, the verts and faces arrays of different fragments
|
|
72
|
+
are appended to one another.
|
|
73
|
+
|
|
74
|
+
Returns
|
|
75
|
+
-------
|
|
76
|
+
dict
|
|
77
|
+
- 'verts': An Nx3 array of vertex coordinates,
|
|
78
|
+
- 'faces': an Mx3 array of face definitions using row indices of the vertex array
|
|
79
|
+
"""
|
|
80
|
+
for arg in ["resolution_mm", "voi"]:
|
|
81
|
+
if kwargs.get(arg):
|
|
82
|
+
raise NotImplementedError(f"Parameter {arg} ignored by {self.__class__}.")
|
|
83
|
+
|
|
84
|
+
fragments_included = []
|
|
85
|
+
meshes = []
|
|
86
|
+
for fragment_name, loader in self._loaders.items():
|
|
87
|
+
if fragment and fragment.lower() not in fragment_name.lower():
|
|
88
|
+
continue
|
|
89
|
+
assert len(loader.data.darrays) > 1
|
|
90
|
+
meshes.append({
|
|
91
|
+
"verts": loader.data.darrays[0].data,
|
|
92
|
+
"faces": loader.data.darrays[1].data
|
|
93
|
+
})
|
|
94
|
+
fragments_included.append(fragment_name)
|
|
95
|
+
|
|
96
|
+
if len(fragments_included) > 1:
|
|
97
|
+
logger.info(
|
|
98
|
+
f"The mesh fragments [{', '.join(fragments_included)}] were merged by "
|
|
99
|
+
"appending vertex information of fragments. "
|
|
100
|
+
f"You could select one with the 'fragment' parameter in fetch()."
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
return merge_meshes(meshes)
|
|
104
|
+
|
|
105
|
+
@property
|
|
106
|
+
def variants(self):
|
|
107
|
+
return list(self._loaders.keys())
|
|
108
|
+
|
|
109
|
+
def fetch_iter(self):
|
|
110
|
+
"""
|
|
111
|
+
Iterator returning all submeshes
|
|
112
|
+
|
|
113
|
+
Returns
|
|
114
|
+
-------
|
|
115
|
+
dict
|
|
116
|
+
- 'verts': An Nx3 array of vertex coordinates,
|
|
117
|
+
- 'faces': an Mx3 array of face definitions using row indices of the vertex array
|
|
118
|
+
- 'name': Name of the of the mesh variant
|
|
119
|
+
"""
|
|
120
|
+
return (self.fetch(v) for v in self.variants)
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
class GiftiSurfaceLabeling(_provider.VolumeProvider, srctype="gii-label"):
|
|
124
|
+
"""
|
|
125
|
+
A mesh labeling, specified by a gifti file.
|
|
126
|
+
"""
|
|
127
|
+
|
|
128
|
+
def __init__(self, url: Union[str, dict]):
|
|
129
|
+
self._init_url = url
|
|
130
|
+
if isinstance(url, str): # single mesh labelling
|
|
131
|
+
self._loaders = {None: requests.HttpRequest(url)}
|
|
132
|
+
elif isinstance(url, dict): # labelling for multiple mesh fragments
|
|
133
|
+
self._loaders = {lbl: requests.HttpRequest(u) for lbl, u in url.items()}
|
|
134
|
+
else:
|
|
135
|
+
raise NotImplementedError(f"Urls for {self.__class__.__name__} are expected to be of type str or dict.")
|
|
136
|
+
|
|
137
|
+
def fetch(self, fragment: str = None, label: int = None, **kwargs):
|
|
138
|
+
"""Returns a 1D numpy array of label indices."""
|
|
139
|
+
labels = []
|
|
140
|
+
if fragment is None:
|
|
141
|
+
matched_frags = list(self._loaders.keys())
|
|
142
|
+
else:
|
|
143
|
+
matched_frags = [frg for frg in self._loaders.keys() if fragment.lower() in frg.lower()]
|
|
144
|
+
if len(matched_frags) != 1:
|
|
145
|
+
raise ValueError(
|
|
146
|
+
f"Requested fragment '{fragment}' could not be matched uniquely "
|
|
147
|
+
f"to [{', '.join(self._loaders)}]"
|
|
148
|
+
)
|
|
149
|
+
for frag in matched_frags:
|
|
150
|
+
assert len(self._loaders[frag].data.darrays) == 1
|
|
151
|
+
if label is not None:
|
|
152
|
+
labels.append((self._loaders[frag].data.darrays[0].data == label).astype('uint8'))
|
|
153
|
+
else:
|
|
154
|
+
labels.append(self._loaders[frag].data.darrays[0].data)
|
|
155
|
+
|
|
156
|
+
return {"labels": np.hstack(labels)}
|
|
157
|
+
|
|
158
|
+
def get_boundingbox(self, clip=False, background=0.0) -> '_boundingbox.BoundingBox':
|
|
159
|
+
raise NotImplementedError(
|
|
160
|
+
f"Bounding box access to {self.__class__.__name__} objects not yet implemented."
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
@property
|
|
164
|
+
def _url(self) -> Union[str, Dict[str, str]]:
|
|
165
|
+
return self._init_url
|