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,224 @@
|
|
|
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 the relation between study targets and BrainStructures."""
|
|
16
|
+
|
|
17
|
+
from ..commons import Species, logger
|
|
18
|
+
|
|
19
|
+
from ..core.structure import BrainStructure
|
|
20
|
+
from ..core.assignment import AnatomicalAssignment, Qualification
|
|
21
|
+
from ..locations.location import Location
|
|
22
|
+
from ..core.parcellation import Parcellation, find_regions
|
|
23
|
+
from ..core.region import Region
|
|
24
|
+
from ..core.space import Space
|
|
25
|
+
from ..exceptions import SpaceWarpingFailedError
|
|
26
|
+
|
|
27
|
+
from ..vocabularies import REGION_ALIASES
|
|
28
|
+
|
|
29
|
+
from typing import Union, List, Dict, Iterable
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class AnatomicalAnchor:
|
|
33
|
+
"""
|
|
34
|
+
Anatomical anchor to an atlas region, a geometric primitive in an atlas
|
|
35
|
+
reference space, or both.
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
_MATCH_MEMO: Dict[str, Dict[Region, Qualification]] = {}
|
|
39
|
+
|
|
40
|
+
def __init__(
|
|
41
|
+
self,
|
|
42
|
+
species: Union[List[Species], Species, str],
|
|
43
|
+
location: Location = None,
|
|
44
|
+
region: Union[str, Region] = None
|
|
45
|
+
):
|
|
46
|
+
|
|
47
|
+
if isinstance(species, (str, Species)):
|
|
48
|
+
self.species = {Species.decode(species)}
|
|
49
|
+
elif isinstance(species, Iterable):
|
|
50
|
+
assert all(isinstance(_, Species) for _ in species)
|
|
51
|
+
self.species = set(species)
|
|
52
|
+
else:
|
|
53
|
+
sp = Species.decode(species)
|
|
54
|
+
if sp is None:
|
|
55
|
+
raise ValueError(f"Invalid species specification: {species}")
|
|
56
|
+
else:
|
|
57
|
+
self.species = {sp}
|
|
58
|
+
self._location_cached = location
|
|
59
|
+
self._assignments: Dict[BrainStructure, List[AnatomicalAssignment]] = {}
|
|
60
|
+
self._last_matched_concept = None
|
|
61
|
+
if isinstance(region, dict):
|
|
62
|
+
self._regions_cached = region
|
|
63
|
+
self._regionspec = ", ".join({r.name for r in region.keys()})
|
|
64
|
+
else:
|
|
65
|
+
self._regions_cached = None
|
|
66
|
+
self._regionspec = None
|
|
67
|
+
if isinstance(region, Region):
|
|
68
|
+
self._regions_cached = {region: Qualification.EXACT}
|
|
69
|
+
elif isinstance(region, str):
|
|
70
|
+
# we will decode regions only when needed, see self.regions property
|
|
71
|
+
self._regionspec = region
|
|
72
|
+
else:
|
|
73
|
+
if region is not None:
|
|
74
|
+
raise ValueError(f"Invalid region specification: {region}")
|
|
75
|
+
self._aliases_cached = None
|
|
76
|
+
|
|
77
|
+
@property
|
|
78
|
+
def location(self) -> Location:
|
|
79
|
+
# allow to overwrite in derived classes
|
|
80
|
+
return self._location_cached
|
|
81
|
+
|
|
82
|
+
@property
|
|
83
|
+
def parcellations(self) -> List[Parcellation]:
|
|
84
|
+
"""
|
|
85
|
+
Return any parcellation objects that regions of this anchor belong to.
|
|
86
|
+
"""
|
|
87
|
+
return list({region.root for region in self.regions})
|
|
88
|
+
|
|
89
|
+
@property
|
|
90
|
+
def space(self) -> Space:
|
|
91
|
+
# may be overriden by derived classes, e.g. in features.VolumeOfInterest
|
|
92
|
+
return None if self.location is None else self.location.space
|
|
93
|
+
|
|
94
|
+
@property
|
|
95
|
+
def region_aliases(self):
|
|
96
|
+
# return any predefined aliases for the region specified in this anchor.
|
|
97
|
+
if self._aliases_cached is None:
|
|
98
|
+
self._aliases_cached: Dict[str, Dict[str, str]] = {
|
|
99
|
+
Species.decode(species_str): region_alias_mapping
|
|
100
|
+
for s in self.species
|
|
101
|
+
for species_str, region_alias_mapping in REGION_ALIASES.get(str(s), {}).get(self._regionspec, {}).items()
|
|
102
|
+
}
|
|
103
|
+
return self._aliases_cached
|
|
104
|
+
|
|
105
|
+
@property
|
|
106
|
+
def has_region_aliases(self) -> bool:
|
|
107
|
+
return len(self.region_aliases) > 0
|
|
108
|
+
|
|
109
|
+
@property
|
|
110
|
+
def regions(self) -> Dict[Region, Qualification]:
|
|
111
|
+
"""
|
|
112
|
+
Return the list of regions associated with this anchor.
|
|
113
|
+
Decode the self._regionspec string into region objects now,
|
|
114
|
+
if applicable and called for the first time.
|
|
115
|
+
"""
|
|
116
|
+
# decoding region strings is quite compute intensive, so we cache this at the class level
|
|
117
|
+
if self._regions_cached is not None:
|
|
118
|
+
return self._regions_cached
|
|
119
|
+
|
|
120
|
+
if self._regionspec is None:
|
|
121
|
+
self._regions_cached = dict()
|
|
122
|
+
return self._regions_cached
|
|
123
|
+
|
|
124
|
+
match_key = self._regionspec + '-' + str(self.species)
|
|
125
|
+
if match_key not in self.__class__._MATCH_MEMO:
|
|
126
|
+
# decode the region specification into a dict of region objects and assignment qualifications
|
|
127
|
+
regions = {
|
|
128
|
+
region: Qualification.EXACT
|
|
129
|
+
for region in find_regions(self._regionspec, filter_children=True, find_topmost=False)
|
|
130
|
+
if region.species in self.species
|
|
131
|
+
}
|
|
132
|
+
# add more regions from possible aliases of the region spec
|
|
133
|
+
for alt_species, aliases in self.region_aliases.items():
|
|
134
|
+
for alias_regionspec, qualificationspec in aliases.items():
|
|
135
|
+
for r in find_regions(alias_regionspec, filter_children=True, find_topmost=False):
|
|
136
|
+
if r.species != alt_species:
|
|
137
|
+
continue
|
|
138
|
+
if r not in regions:
|
|
139
|
+
regions[r] = Qualification[qualificationspec.upper()]
|
|
140
|
+
|
|
141
|
+
self.__class__._MATCH_MEMO[match_key] = regions
|
|
142
|
+
self._regions_cached = self.__class__._MATCH_MEMO[match_key]
|
|
143
|
+
|
|
144
|
+
return self._regions_cached
|
|
145
|
+
|
|
146
|
+
def __str__(self):
|
|
147
|
+
parcs = {p.id: p.name for p in self.represented_parcellations()}
|
|
148
|
+
if len(parcs) == 1 and self._regionspec in [pid for pid in parcs]:
|
|
149
|
+
region = parcs[self._regionspec] # if parcellation was anchored with the id instead of the name
|
|
150
|
+
else:
|
|
151
|
+
region = "" if self._regionspec is None else str(self._regionspec)
|
|
152
|
+
location = "" if self.location is None else str(self.location)
|
|
153
|
+
separator = " " if min(len(region), len(location)) > 0 else ""
|
|
154
|
+
if region and location:
|
|
155
|
+
return region + " with " + location
|
|
156
|
+
else:
|
|
157
|
+
return region + separator + location
|
|
158
|
+
|
|
159
|
+
def assign(self, concept: Union[BrainStructure, Space]) -> AnatomicalAssignment:
|
|
160
|
+
"""
|
|
161
|
+
Match this anchor to a query concept. Assignments are cached at runtime,
|
|
162
|
+
so repeated assignment with the same concept will be cheap.
|
|
163
|
+
"""
|
|
164
|
+
if isinstance(concept, Space):
|
|
165
|
+
if self.location is not None and self.location.space.matches(concept):
|
|
166
|
+
return [AnatomicalAssignment(concept, self.location, Qualification.CONTAINED)]
|
|
167
|
+
else:
|
|
168
|
+
return []
|
|
169
|
+
|
|
170
|
+
if concept not in self._assignments:
|
|
171
|
+
assignments: List[AnatomicalAssignment] = []
|
|
172
|
+
if self.location is not None:
|
|
173
|
+
try:
|
|
174
|
+
assignments.append(self.location.assign(concept))
|
|
175
|
+
except SpaceWarpingFailedError as e:
|
|
176
|
+
logger.debug(e)
|
|
177
|
+
for region in self.regions:
|
|
178
|
+
assignments.append(region.assign(concept))
|
|
179
|
+
self._assignments[concept] = sorted(a for a in assignments if a is not None)
|
|
180
|
+
|
|
181
|
+
self._last_matched_concept = concept \
|
|
182
|
+
if len(self._assignments[concept]) > 0 \
|
|
183
|
+
else None
|
|
184
|
+
return self._assignments[concept]
|
|
185
|
+
|
|
186
|
+
def matches(self, concept: Union[BrainStructure, Space]) -> bool:
|
|
187
|
+
return len(self.assign(concept)) > 0
|
|
188
|
+
|
|
189
|
+
def represented_parcellations(self) -> List[Parcellation]:
|
|
190
|
+
"""
|
|
191
|
+
Return any parcellation objects that this anchor explicitly points to.
|
|
192
|
+
"""
|
|
193
|
+
return [r for r in self.regions if isinstance(r, Parcellation)]
|
|
194
|
+
|
|
195
|
+
@property
|
|
196
|
+
def last_match_result(self) -> List[AnatomicalAssignment]:
|
|
197
|
+
return self._assignments.get(self._last_matched_concept, [])
|
|
198
|
+
|
|
199
|
+
@property
|
|
200
|
+
def last_match_description(self) -> str:
|
|
201
|
+
if self.last_match_result is None:
|
|
202
|
+
return ""
|
|
203
|
+
else:
|
|
204
|
+
return ' and '.join({str(_) for _ in self.last_match_result})
|
|
205
|
+
|
|
206
|
+
def __add__(self, other: 'AnatomicalAnchor') -> 'AnatomicalAnchor':
|
|
207
|
+
if not isinstance(other, AnatomicalAnchor):
|
|
208
|
+
raise ValueError(f"Cannot combine an AnatomicalAnchor with {other.__class__}")
|
|
209
|
+
|
|
210
|
+
if self.species != other.species:
|
|
211
|
+
raise ValueError("Cannot combine an AnatomicalAnchor from different species.")
|
|
212
|
+
else:
|
|
213
|
+
species = self.species.union(other.species)
|
|
214
|
+
|
|
215
|
+
regions = self.regions
|
|
216
|
+
regions.update(other.regions)
|
|
217
|
+
|
|
218
|
+
location = Location.union(self.location, other.location)
|
|
219
|
+
|
|
220
|
+
return AnatomicalAnchor(species, location, regions)
|
|
221
|
+
|
|
222
|
+
def __radd__(self, other) -> 'AnatomicalAnchor':
|
|
223
|
+
# required to enable `sum`
|
|
224
|
+
return self if other == 0 else self.__add__(other)
|
|
@@ -0,0 +1,33 @@
|
|
|
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
|
+
"""Multimodal data features concerning connectivity data."""
|
|
16
|
+
|
|
17
|
+
from .functional_connectivity import (
|
|
18
|
+
FunctionalConnectivity,
|
|
19
|
+
AnatomoFunctionalConnectivity
|
|
20
|
+
)
|
|
21
|
+
from .streamline_counts import StreamlineCounts
|
|
22
|
+
from .streamline_lengths import StreamlineLengths
|
|
23
|
+
from .tracing_connectivity import TracingConnectivity
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def __dir__():
|
|
27
|
+
return [
|
|
28
|
+
"FunctionalConnectivity",
|
|
29
|
+
"StreamlineCounts",
|
|
30
|
+
"StreamlineLengths",
|
|
31
|
+
"TracingConnectivity",
|
|
32
|
+
"AnatomoFunctionalConnectivity"
|
|
33
|
+
]
|
|
@@ -0,0 +1,57 @@
|
|
|
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
|
+
|
|
16
|
+
from . import regional_connectivity
|
|
17
|
+
|
|
18
|
+
from hashlib import md5
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class FunctionalConnectivity(
|
|
22
|
+
regional_connectivity.RegionalConnectivity,
|
|
23
|
+
configuration_folder="features/connectivity/regional/functional",
|
|
24
|
+
category="connectivity"
|
|
25
|
+
):
|
|
26
|
+
"""Functional connectivity matrix grouped by a parcellation."""
|
|
27
|
+
|
|
28
|
+
_filter_attrs = regional_connectivity.RegionalConnectivity._filter_attrs + ["paradigm"]
|
|
29
|
+
_compound_attrs = regional_connectivity.RegionalConnectivity._compound_attrs + ["paradigm"]
|
|
30
|
+
|
|
31
|
+
def __init__(self, paradigm: str, **kwargs):
|
|
32
|
+
regional_connectivity.RegionalConnectivity.__init__(self, **kwargs)
|
|
33
|
+
self.paradigm = paradigm
|
|
34
|
+
|
|
35
|
+
# paradign is used to distinguish functional connectivity features from each other.
|
|
36
|
+
assert self.paradigm, "Functional connectivity must have paradigm defined!"
|
|
37
|
+
|
|
38
|
+
@property
|
|
39
|
+
def id(self):
|
|
40
|
+
return super().id + "--" + md5(self.paradigm.encode("utf-8")).hexdigest()
|
|
41
|
+
|
|
42
|
+
@property
|
|
43
|
+
def name(self):
|
|
44
|
+
return super().name + f", paradigm: {self.paradigm}"
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class AnatomoFunctionalConnectivity(
|
|
48
|
+
regional_connectivity.RegionalConnectivity,
|
|
49
|
+
configuration_folder="features/connectivity/regional/anatomofunctional",
|
|
50
|
+
category="connectivity"
|
|
51
|
+
):
|
|
52
|
+
"""Functional connectivity matrix grouped by a parcellation."""
|
|
53
|
+
|
|
54
|
+
_filter_attrs = ["modality", "cohort", "feature"]
|
|
55
|
+
|
|
56
|
+
def __init__(self, **kwargs):
|
|
57
|
+
regional_connectivity.RegionalConnectivity.__init__(self, **kwargs)
|