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.

Files changed (84) hide show
  1. siibra/VERSION +1 -0
  2. siibra/__init__.py +164 -0
  3. siibra/commons.py +823 -0
  4. siibra/configuration/__init__.py +17 -0
  5. siibra/configuration/configuration.py +189 -0
  6. siibra/configuration/factory.py +589 -0
  7. siibra/core/__init__.py +16 -0
  8. siibra/core/assignment.py +110 -0
  9. siibra/core/atlas.py +239 -0
  10. siibra/core/concept.py +308 -0
  11. siibra/core/parcellation.py +387 -0
  12. siibra/core/region.py +1223 -0
  13. siibra/core/space.py +131 -0
  14. siibra/core/structure.py +111 -0
  15. siibra/exceptions.py +63 -0
  16. siibra/experimental/__init__.py +19 -0
  17. siibra/experimental/contour.py +61 -0
  18. siibra/experimental/cortical_profile_sampler.py +57 -0
  19. siibra/experimental/patch.py +98 -0
  20. siibra/experimental/plane3d.py +256 -0
  21. siibra/explorer/__init__.py +17 -0
  22. siibra/explorer/url.py +222 -0
  23. siibra/explorer/util.py +87 -0
  24. siibra/features/__init__.py +117 -0
  25. siibra/features/anchor.py +224 -0
  26. siibra/features/connectivity/__init__.py +33 -0
  27. siibra/features/connectivity/functional_connectivity.py +57 -0
  28. siibra/features/connectivity/regional_connectivity.py +494 -0
  29. siibra/features/connectivity/streamline_counts.py +27 -0
  30. siibra/features/connectivity/streamline_lengths.py +27 -0
  31. siibra/features/connectivity/tracing_connectivity.py +30 -0
  32. siibra/features/dataset/__init__.py +17 -0
  33. siibra/features/dataset/ebrains.py +90 -0
  34. siibra/features/feature.py +970 -0
  35. siibra/features/image/__init__.py +27 -0
  36. siibra/features/image/image.py +115 -0
  37. siibra/features/image/sections.py +26 -0
  38. siibra/features/image/volume_of_interest.py +88 -0
  39. siibra/features/tabular/__init__.py +24 -0
  40. siibra/features/tabular/bigbrain_intensity_profile.py +77 -0
  41. siibra/features/tabular/cell_density_profile.py +298 -0
  42. siibra/features/tabular/cortical_profile.py +322 -0
  43. siibra/features/tabular/gene_expression.py +257 -0
  44. siibra/features/tabular/layerwise_bigbrain_intensities.py +62 -0
  45. siibra/features/tabular/layerwise_cell_density.py +95 -0
  46. siibra/features/tabular/receptor_density_fingerprint.py +192 -0
  47. siibra/features/tabular/receptor_density_profile.py +110 -0
  48. siibra/features/tabular/regional_timeseries_activity.py +294 -0
  49. siibra/features/tabular/tabular.py +139 -0
  50. siibra/livequeries/__init__.py +19 -0
  51. siibra/livequeries/allen.py +352 -0
  52. siibra/livequeries/bigbrain.py +197 -0
  53. siibra/livequeries/ebrains.py +145 -0
  54. siibra/livequeries/query.py +49 -0
  55. siibra/locations/__init__.py +91 -0
  56. siibra/locations/boundingbox.py +454 -0
  57. siibra/locations/location.py +115 -0
  58. siibra/locations/point.py +344 -0
  59. siibra/locations/pointcloud.py +349 -0
  60. siibra/retrieval/__init__.py +27 -0
  61. siibra/retrieval/cache.py +233 -0
  62. siibra/retrieval/datasets.py +389 -0
  63. siibra/retrieval/exceptions/__init__.py +27 -0
  64. siibra/retrieval/repositories.py +769 -0
  65. siibra/retrieval/requests.py +659 -0
  66. siibra/vocabularies/__init__.py +45 -0
  67. siibra/vocabularies/gene_names.json +29176 -0
  68. siibra/vocabularies/receptor_symbols.json +210 -0
  69. siibra/vocabularies/region_aliases.json +460 -0
  70. siibra/volumes/__init__.py +23 -0
  71. siibra/volumes/parcellationmap.py +1279 -0
  72. siibra/volumes/providers/__init__.py +20 -0
  73. siibra/volumes/providers/freesurfer.py +113 -0
  74. siibra/volumes/providers/gifti.py +165 -0
  75. siibra/volumes/providers/neuroglancer.py +736 -0
  76. siibra/volumes/providers/nifti.py +266 -0
  77. siibra/volumes/providers/provider.py +107 -0
  78. siibra/volumes/sparsemap.py +468 -0
  79. siibra/volumes/volume.py +892 -0
  80. siibra-1.0.0a1.dist-info/LICENSE +201 -0
  81. siibra-1.0.0a1.dist-info/METADATA +160 -0
  82. siibra-1.0.0a1.dist-info/RECORD +84 -0
  83. siibra-1.0.0a1.dist-info/WHEEL +5 -0
  84. 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)