siibra 0.5a2__py3-none-any.whl → 1.0.0a1__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 (83) hide show
  1. siibra/VERSION +1 -1
  2. siibra/__init__.py +20 -12
  3. siibra/commons.py +145 -90
  4. siibra/configuration/__init__.py +1 -1
  5. siibra/configuration/configuration.py +22 -17
  6. siibra/configuration/factory.py +177 -128
  7. siibra/core/__init__.py +1 -8
  8. siibra/core/{relation_qualification.py → assignment.py} +17 -14
  9. siibra/core/atlas.py +66 -35
  10. siibra/core/concept.py +81 -39
  11. siibra/core/parcellation.py +83 -67
  12. siibra/core/region.py +569 -263
  13. siibra/core/space.py +7 -39
  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 +16 -0
  22. siibra/explorer/url.py +112 -52
  23. siibra/explorer/util.py +31 -9
  24. siibra/features/__init__.py +73 -8
  25. siibra/features/anchor.py +75 -196
  26. siibra/features/connectivity/__init__.py +1 -1
  27. siibra/features/connectivity/functional_connectivity.py +2 -2
  28. siibra/features/connectivity/regional_connectivity.py +99 -10
  29. siibra/features/connectivity/streamline_counts.py +1 -1
  30. siibra/features/connectivity/streamline_lengths.py +1 -1
  31. siibra/features/connectivity/tracing_connectivity.py +1 -1
  32. siibra/features/dataset/__init__.py +1 -1
  33. siibra/features/dataset/ebrains.py +3 -3
  34. siibra/features/feature.py +219 -110
  35. siibra/features/image/__init__.py +1 -1
  36. siibra/features/image/image.py +21 -13
  37. siibra/features/image/sections.py +1 -1
  38. siibra/features/image/volume_of_interest.py +1 -1
  39. siibra/features/tabular/__init__.py +1 -1
  40. siibra/features/tabular/bigbrain_intensity_profile.py +24 -13
  41. siibra/features/tabular/cell_density_profile.py +111 -69
  42. siibra/features/tabular/cortical_profile.py +82 -16
  43. siibra/features/tabular/gene_expression.py +117 -6
  44. siibra/features/tabular/layerwise_bigbrain_intensities.py +7 -9
  45. siibra/features/tabular/layerwise_cell_density.py +9 -24
  46. siibra/features/tabular/receptor_density_fingerprint.py +11 -6
  47. siibra/features/tabular/receptor_density_profile.py +12 -15
  48. siibra/features/tabular/regional_timeseries_activity.py +74 -18
  49. siibra/features/tabular/tabular.py +17 -8
  50. siibra/livequeries/__init__.py +1 -7
  51. siibra/livequeries/allen.py +139 -77
  52. siibra/livequeries/bigbrain.py +104 -128
  53. siibra/livequeries/ebrains.py +7 -4
  54. siibra/livequeries/query.py +1 -2
  55. siibra/locations/__init__.py +32 -25
  56. siibra/locations/boundingbox.py +153 -127
  57. siibra/locations/location.py +45 -80
  58. siibra/locations/point.py +97 -83
  59. siibra/locations/pointcloud.py +349 -0
  60. siibra/retrieval/__init__.py +1 -1
  61. siibra/retrieval/cache.py +107 -13
  62. siibra/retrieval/datasets.py +9 -14
  63. siibra/retrieval/exceptions/__init__.py +2 -1
  64. siibra/retrieval/repositories.py +147 -53
  65. siibra/retrieval/requests.py +64 -29
  66. siibra/vocabularies/__init__.py +2 -2
  67. siibra/volumes/__init__.py +7 -9
  68. siibra/volumes/parcellationmap.py +396 -253
  69. siibra/volumes/providers/__init__.py +20 -0
  70. siibra/volumes/providers/freesurfer.py +113 -0
  71. siibra/volumes/{gifti.py → providers/gifti.py} +29 -18
  72. siibra/volumes/{neuroglancer.py → providers/neuroglancer.py} +204 -92
  73. siibra/volumes/{nifti.py → providers/nifti.py} +64 -44
  74. siibra/volumes/providers/provider.py +107 -0
  75. siibra/volumes/sparsemap.py +159 -260
  76. siibra/volumes/volume.py +720 -152
  77. {siibra-0.5a2.dist-info → siibra-1.0.0a1.dist-info}/METADATA +25 -28
  78. siibra-1.0.0a1.dist-info/RECORD +84 -0
  79. {siibra-0.5a2.dist-info → siibra-1.0.0a1.dist-info}/WHEEL +1 -1
  80. siibra/locations/pointset.py +0 -198
  81. siibra-0.5a2.dist-info/RECORD +0 -74
  82. {siibra-0.5a2.dist-info → siibra-1.0.0a1.dist-info}/LICENSE +0 -0
  83. {siibra-0.5a2.dist-info → siibra-1.0.0a1.dist-info}/top_level.txt +0 -0
@@ -1,4 +1,4 @@
1
- # Copyright 2018-2021
1
+ # Copyright 2018-2024
2
2
  # Institute of Neuroscience and Medicine (INM-1), Forschungszentrum Jülich GmbH
3
3
 
4
4
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -17,11 +17,21 @@ from . import region
17
17
 
18
18
  from ..commons import logger, MapType, Species
19
19
  from ..volumes import parcellationmap
20
+ from ..exceptions import NoMapMatchingValues
20
21
 
21
- from typing import Union, List, Dict
22
+ from functools import lru_cache
22
23
  import re
24
+ from typing import Union, List, TYPE_CHECKING
25
+ try:
26
+ from typing import Literal
27
+ except ImportError:
28
+ # support python 3.7
29
+ from typing_extensions import Literal
23
30
 
24
31
 
32
+ if TYPE_CHECKING:
33
+ from .space import Space
34
+
25
35
  # NOTE : such code could be used to automatically resolve
26
36
  # multiple matching parcellations for a short spec to the newset version:
27
37
  # try:
@@ -68,8 +78,6 @@ class ParcellationVersion:
68
78
 
69
79
  class Parcellation(region.Region, configuration_folder="parcellations"):
70
80
 
71
- _CACHED_REGION_SEARCHES: Dict[str, List[region.Region]] = {}
72
-
73
81
  def __init__(
74
82
  self,
75
83
  identifier: str,
@@ -82,6 +90,7 @@ class Parcellation(region.Region, configuration_folder="parcellations"):
82
90
  modality: str = None,
83
91
  publications: list = [],
84
92
  datasets: list = [],
93
+ prerelease: bool = False,
85
94
  ):
86
95
  """
87
96
  Constructs a new parcellation object.
@@ -118,7 +127,8 @@ class Parcellation(region.Region, configuration_folder="parcellations"):
118
127
  description=description,
119
128
  publications=publications,
120
129
  datasets=datasets,
121
- modality=modality
130
+ modality=modality,
131
+ prerelease=prerelease,
122
132
  )
123
133
  self._species_cached = Species.decode(species)
124
134
  self._id = identifier
@@ -129,15 +139,21 @@ class Parcellation(region.Region, configuration_folder="parcellations"):
129
139
  return self._id
130
140
 
131
141
  def matches(self, spec):
132
- if isinstance(spec, str):
133
- if all(
134
- w in self.shortname.lower()
135
- for w in re.split(r'\s+', spec.lower())
136
- ):
137
- return True
142
+ if spec not in self._CACHED_MATCHES:
143
+ if isinstance(spec, str):
144
+ if all(
145
+ w in self.shortname.lower()
146
+ for w in re.split(r'\s+', spec.lower())
147
+ ):
148
+ self._CACHED_MATCHES[spec] = True
138
149
  return super().matches(spec)
139
150
 
140
- def get_map(self, space=None, maptype: Union[str, MapType] = MapType.LABELLED, spec: str = ""):
151
+ def get_map(
152
+ self,
153
+ space: Union[str, "Space"],
154
+ maptype: Union[Literal['labelled', 'statistical'], MapType] = MapType.LABELLED,
155
+ spec: str = ""
156
+ ):
141
157
  """
142
158
  Get the maps for the parcellation in the requested template space.
143
159
 
@@ -150,8 +166,8 @@ class Parcellation(region.Region, configuration_folder="parcellations"):
150
166
  Parameters
151
167
  ----------
152
168
  space: Space or str
153
- template space specification
154
- maptype: MapType
169
+ reference space specification such as name, id, or a `Space` instance.
170
+ maptype: MapType or str
155
171
  Type of map requested (e.g., statistical or labelled).
156
172
  Use MapType.STATISTICAL to request probability maps.
157
173
  Defaults to MapType.LABELLED.
@@ -166,26 +182,24 @@ class Parcellation(region.Region, configuration_folder="parcellations"):
166
182
  A ParcellationMap representing the volumetric map or
167
183
  a SparseMap representing the list of statistical maps.
168
184
  """
169
- if not isinstance(maptype, MapType):
185
+ if isinstance(maptype, str):
170
186
  maptype = MapType[maptype.upper()]
187
+ assert isinstance(maptype, MapType), "Possible values of `maptype` are `MapType`s, 'labelled', 'statistical'."
171
188
 
172
189
  candidates = [
173
190
  m for m in parcellationmap.Map.registry()
174
191
  if m.space.matches(space)
175
192
  and m.maptype == maptype
176
- and m.parcellation
177
193
  and m.parcellation.matches(self)
178
194
  ]
179
195
  if len(candidates) == 0:
180
- logger.error(f"No {maptype} map in {space} available for {str(self)}")
181
- return None
196
+ raise NoMapMatchingValues(f"No '{maptype}' map in '{space}' available for {str(self)}")
182
197
  if len(candidates) > 1:
183
198
  spec_candidates = [
184
- c for c in candidates if all(w.lower() in c.name.lower() for w in spec.split())
199
+ c for c in candidates if all(w.lower() in c.id.lower() for w in spec.split())
185
200
  ]
186
201
  if len(spec_candidates) == 0:
187
- logger.warning(f"'{spec}' does not match any options from {[c.name for c in candidates]}.")
188
- return None
202
+ raise NoMapMatchingValues(f"'{spec}' does not match any options from {[c.name for c in candidates]}.")
189
203
  if len(spec_candidates) > 1:
190
204
  logger.warning(
191
205
  f"Multiple maps are available in this specification of space, parcellation, and map type.\n"
@@ -194,43 +208,6 @@ class Parcellation(region.Region, configuration_folder="parcellations"):
194
208
  return spec_candidates[0]
195
209
  return candidates[0]
196
210
 
197
- @staticmethod
198
- def find_regions(region_spec: str, parents_only=True):
199
- """
200
- Find regions that match the given region specification in the subtree
201
- headed by each parcellation in the registry.
202
- Note
203
- ----
204
- Use Region.find() to search for a region in an instance of a
205
- parcellation.
206
-
207
- Parameters
208
- ----------
209
- regionspec: str
210
- a string with a possibly inexact name, which is matched both
211
- against the name and the identifier key,
212
- parents_only: bool
213
- If true, children of matched parents will not be returned
214
- Returns
215
- -------
216
- List[Region]
217
- list of matching regions
218
- """
219
- MEM = Parcellation._CACHED_REGION_SEARCHES
220
- if region_spec not in MEM:
221
- MEM[region_spec] = [
222
- r
223
- for p in Parcellation.registry()
224
- for r in p.find(regionspec=region_spec)
225
- ]
226
- if parents_only:
227
- return [
228
- r for r in MEM[region_spec]
229
- if (r.parent is None) or (r.parent not in MEM[region_spec])
230
- ]
231
- else:
232
- return MEM[region_spec]
233
-
234
211
  @property
235
212
  def is_newest_version(self):
236
213
  return (self.version is None) or (self.version.next_id is None)
@@ -260,7 +237,7 @@ class Parcellation(region.Region, configuration_folder="parcellations"):
260
237
  def get_region(
261
238
  self,
262
239
  regionspec: Union[str, region.Region],
263
- find_topmost: bool = True,
240
+ find_topmost: bool = False,
264
241
  allow_tuple: bool = False
265
242
  ):
266
243
  """
@@ -278,7 +255,7 @@ class Parcellation(region.Region, configuration_folder="parcellations"):
278
255
  regionspec: str, Region
279
256
  - a string with a possibly inexact name (matched both against the name and the identifier key)
280
257
  - a Region object
281
- find_topmost: bool, default: True
258
+ find_topmost: bool, default: False
282
259
  If True, will automatically return the parent of a decoded region
283
260
  the decoded region is its only child.
284
261
  allow_tuple: bool, default: False
@@ -308,7 +285,11 @@ class Parcellation(region.Region, configuration_folder="parcellations"):
308
285
 
309
286
  # if there exist an exact match of region spec to region name, return
310
287
  if isinstance(regionspec, str):
311
- exact_match = [region for region in self if hasattr(region, "name") and region.name == regionspec]
288
+ exact_match = [
289
+ region
290
+ for region in self
291
+ if region.name == regionspec or region.key == regionspec
292
+ ]
312
293
  if len(exact_match) == 1:
313
294
  return exact_match[0]
314
295
  if len(exact_match) > 1:
@@ -346,12 +327,6 @@ class Parcellation(region.Region, configuration_folder="parcellations"):
346
327
  f"Spec {regionspec!r} resulted in multiple matches: {', '.join(r.name for r in candidates)}."
347
328
  )
348
329
 
349
- def __str__(self):
350
- return self.name
351
-
352
- def __repr__(self):
353
- return self.name
354
-
355
330
  def __getitem__(self, regionspec: Union[str, int]):
356
331
  """
357
332
  Retrieve a region object from the parcellation by labelindex or partial name.
@@ -369,3 +344,44 @@ class Parcellation(region.Region, configuration_folder="parcellations"):
369
344
  )
370
345
  return self.name < other.name
371
346
  return self.version.__lt__(other.version)
347
+
348
+
349
+ @lru_cache(maxsize=128)
350
+ def find_regions(
351
+ regionspec: str,
352
+ filter_children=True,
353
+ find_topmost=False
354
+ ):
355
+ """
356
+ Find regions matching the given region specification across all parcellation
357
+ instances in the registery.
358
+
359
+ Parameters
360
+ ----------
361
+ regionspec: str, regex, Region
362
+ - a string with a possibly inexact name (matched both against the name and the identifier key)
363
+ - a string in '/pattern/flags' format to use regex search (acceptable flags: aiLmsux) (see https://docs.python.org/3/library/re.html#flags)
364
+ - a regex applied to region names
365
+ - a Region object
366
+ filter_children : bool, default: True
367
+ If True, children of matched parents will not be returned
368
+ find_topmost : bool, default: False
369
+ If True (requires `filter_children=True`), will return parent
370
+ structures if all children are matched, even though the parent
371
+ itself might not match the specification.
372
+
373
+ Returns
374
+ -------
375
+ list[Region]
376
+ list of regions matching to the regionspec
377
+ """
378
+ result = []
379
+ for p in Parcellation.registry():
380
+ result.extend(
381
+ p.find(
382
+ regionspec=regionspec,
383
+ filter_children=filter_children,
384
+ find_topmost=find_topmost
385
+ )
386
+ )
387
+ return result