siibra 0.4a33__py3-none-any.whl → 0.4a46__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 (64) hide show
  1. siibra/VERSION +1 -1
  2. siibra/__init__.py +2 -0
  3. siibra/commons.py +53 -8
  4. siibra/configuration/configuration.py +21 -17
  5. siibra/configuration/factory.py +95 -19
  6. siibra/core/atlas.py +11 -8
  7. siibra/core/concept.py +41 -8
  8. siibra/core/parcellation.py +94 -43
  9. siibra/core/region.py +160 -187
  10. siibra/core/space.py +44 -39
  11. siibra/features/__init__.py +19 -19
  12. siibra/features/anchor.py +9 -6
  13. siibra/features/connectivity/__init__.py +0 -8
  14. siibra/features/connectivity/functional_connectivity.py +11 -3
  15. siibra/features/{basetypes → connectivity}/regional_connectivity.py +46 -33
  16. siibra/features/connectivity/streamline_counts.py +3 -2
  17. siibra/features/connectivity/streamline_lengths.py +3 -2
  18. siibra/features/{basetypes → dataset}/__init__.py +2 -0
  19. siibra/features/{external → dataset}/ebrains.py +3 -3
  20. siibra/features/feature.py +420 -0
  21. siibra/{samplers → features/image}/__init__.py +7 -1
  22. siibra/features/{basetypes/volume_of_interest.py → image/image.py} +12 -7
  23. siibra/features/{external/__init__.py → image/sections.py} +8 -5
  24. siibra/features/image/volume_of_interest.py +70 -0
  25. siibra/features/{cellular → tabular}/__init__.py +7 -11
  26. siibra/features/{cellular → tabular}/bigbrain_intensity_profile.py +5 -2
  27. siibra/features/{cellular → tabular}/cell_density_profile.py +6 -2
  28. siibra/features/{basetypes → tabular}/cortical_profile.py +48 -41
  29. siibra/features/{molecular → tabular}/gene_expression.py +5 -2
  30. siibra/features/{cellular → tabular}/layerwise_bigbrain_intensities.py +6 -2
  31. siibra/features/{cellular → tabular}/layerwise_cell_density.py +9 -3
  32. siibra/features/{molecular → tabular}/receptor_density_fingerprint.py +3 -2
  33. siibra/features/{molecular → tabular}/receptor_density_profile.py +6 -2
  34. siibra/features/tabular/regional_timeseries_activity.py +213 -0
  35. siibra/features/{basetypes → tabular}/tabular.py +14 -9
  36. siibra/livequeries/allen.py +1 -1
  37. siibra/livequeries/bigbrain.py +2 -3
  38. siibra/livequeries/ebrains.py +3 -9
  39. siibra/livequeries/query.py +1 -1
  40. siibra/locations/location.py +4 -3
  41. siibra/locations/point.py +21 -17
  42. siibra/locations/pointset.py +2 -2
  43. siibra/retrieval/__init__.py +1 -1
  44. siibra/retrieval/cache.py +8 -2
  45. siibra/retrieval/datasets.py +149 -29
  46. siibra/retrieval/repositories.py +19 -8
  47. siibra/retrieval/requests.py +98 -116
  48. siibra/volumes/gifti.py +26 -11
  49. siibra/volumes/neuroglancer.py +35 -19
  50. siibra/volumes/nifti.py +8 -9
  51. siibra/volumes/parcellationmap.py +341 -184
  52. siibra/volumes/sparsemap.py +67 -53
  53. siibra/volumes/volume.py +25 -13
  54. {siibra-0.4a33.dist-info → siibra-0.4a46.dist-info}/METADATA +4 -3
  55. siibra-0.4a46.dist-info/RECORD +69 -0
  56. {siibra-0.4a33.dist-info → siibra-0.4a46.dist-info}/WHEEL +1 -1
  57. siibra/features/basetypes/feature.py +0 -248
  58. siibra/features/fibres/__init__.py +0 -14
  59. siibra/features/functional/__init__.py +0 -14
  60. siibra/features/molecular/__init__.py +0 -26
  61. siibra/samplers/bigbrain.py +0 -181
  62. siibra-0.4a33.dist-info/RECORD +0 -71
  63. {siibra-0.4a33.dist-info → siibra-0.4a46.dist-info}/LICENSE +0 -0
  64. {siibra-0.4a33.dist-info → siibra-0.4a46.dist-info}/top_level.txt +0 -0
@@ -15,16 +15,15 @@
15
15
  """Represents lists of probabilistic brain region maps."""
16
16
  from . import parcellationmap, volume as _volume
17
17
 
18
- from ..commons import MapIndex, logger
18
+ from ..commons import MapIndex, logger, iterate_connected_components, siibra_tqdm
19
19
  from ..locations import boundingbox
20
20
  from ..retrieval import cache
21
21
 
22
22
  from os import path
23
23
  import gzip
24
- from typing import Dict, Union, TYPE_CHECKING
24
+ from typing import Dict, Union, TYPE_CHECKING, List
25
25
  from nilearn import image
26
26
  from nibabel import Nifti1Image, load
27
- from tqdm import tqdm
28
27
  import numpy as np
29
28
 
30
29
  if TYPE_CHECKING:
@@ -111,8 +110,10 @@ class SparseIndex:
111
110
  return x, y, z, v
112
111
 
113
112
  def to_cache(self, prefix: str):
114
- """ Serialize this index to the cache,
115
- using the given prefix for the cache filenames. """
113
+ """
114
+ Serialize this index to the cache, using the given prefix for the cache
115
+ filenames.
116
+ """
116
117
  probsfile = cache.CACHE.build_filename(f"{prefix}", suffix="probs.txt.gz")
117
118
  bboxfile = cache.CACHE.build_filename(f"{prefix}", suffix="bboxes.txt.gz")
118
119
  voxelfile = cache.CACHE.build_filename(f"{prefix}", suffix="voxels.nii.gz")
@@ -132,9 +133,18 @@ class SparseIndex:
132
133
  @classmethod
133
134
  def from_cache(cls, prefix: str):
134
135
  """
135
- Attemts to build a sparse index from the siibra cache,
136
- looking for suitable cache files with the specified prefix.
137
- Returns None if cached files are not found or suitable.
136
+ Attempts to build a sparse index from the siibra cache, looking for
137
+ suitable cache files with the specified prefix.
138
+
139
+ Parameters
140
+ ----------
141
+ prefix: str
142
+ Prefix of the filenames.
143
+
144
+ Returns
145
+ -------
146
+ SparseIndex
147
+ None if cached files are not found or suitable.
138
148
  """
139
149
 
140
150
  probsfile = cache.CACHE.build_filename(f"{prefix}", suffix="probs.txt.gz")
@@ -152,12 +162,11 @@ class SparseIndex:
152
162
 
153
163
  with gzip.open(probsfile, "rt") as f:
154
164
  lines = f.readlines()
155
- for line in tqdm(
165
+ for line in siibra_tqdm(
156
166
  lines,
157
167
  total=len(lines),
158
168
  desc="Loading sparse index",
159
- unit="voxels",
160
- disable=logger.level > 20,
169
+ unit="voxels"
161
170
  ):
162
171
  fields = line.strip().split(" ")
163
172
  mapindices = list(map(int, fields[0::2]))
@@ -179,21 +188,22 @@ class SparseIndex:
179
188
 
180
189
 
181
190
  class SparseMap(parcellationmap.Map):
182
- """A sparse representation of list of statistical (e.g. probabilistic) brain region maps.
191
+ """
192
+ A sparse representation of list of statistical (e.g. probabilistic) brain
193
+ region maps.
183
194
 
184
195
  It represents the 3D statistical maps of N brain regions by two data structures:
185
- 1) 'spatial_index', a 3D volume where non-negative values represent unique
186
- indices into a list of region assignments
187
- 2) 'probs', a list of region assignments where each entry is a dict
188
196
 
189
- More precisely, given
190
- i = sparse_index.voxels[x, y, z]
191
- we define that
192
- - if i<0, no brain region is assigned at this location
193
- - if i>=0, probs[i] defines the probabilities of brain regions.
197
+ 1) 'spatial_index', a 3D volume where non-negative values represent unique indices into a list of region assignments
198
+ 2) 'probs', a list of region assignments where each entry is a dict
199
+
200
+ More precisely, given ``i = sparse_index.voxels[x, y, z]`` we define that
201
+
202
+ - if `i<0`, no brain region is assigned at this location
203
+ - if `i>=0`, ``probs[i]`` defines the probabilities of brain regions.
194
204
 
195
205
  Each entry in probs is a dictionary that represents the region assignments for
196
- the unique voxel where spatial_index==i. The assignment maps from a "mapindex"
206
+ the unique voxel where ``spatial_index == i``. The assignment maps from a MapIndex
197
207
  to the actual (probability) value.
198
208
  """
199
209
 
@@ -235,15 +245,14 @@ class SparseMap(parcellationmap.Map):
235
245
  @property
236
246
  def sparse_index(self):
237
247
  if self._sparse_index_cached is None:
238
- prefix = f"{self.parcellation.id}_{self.space.id}_{self.maptype}_index"
248
+ prefix = f"{self.parcellation.id}_{self.space.id}_{self.maptype}_{self.name}_index"
239
249
  spind = SparseIndex.from_cache(prefix)
240
- with _volume.SubvolumeProvider.UseCaching():
241
- if spind is None:
250
+ if spind is None:
251
+ with _volume.SubvolumeProvider.UseCaching():
242
252
  spind = SparseIndex()
243
- for vol in tqdm(
253
+ for vol in siibra_tqdm(
244
254
  range(len(self)), total=len(self), unit="maps",
245
- desc=f"Fetching {len(self)} volumetric maps",
246
- disable=logger.level > 20,
255
+ desc=f"Fetching {len(self)} volumetric maps"
247
256
  ):
248
257
  img = super().fetch(
249
258
  index=MapIndex(volume=vol, label=None)
@@ -253,8 +262,8 @@ class SparseMap(parcellationmap.Map):
253
262
  logger.error(f"Cannot retrieve volume #{vol} for {region.name}, it will not be included in the sparse map.")
254
263
  continue
255
264
  spind.add_img(img)
256
- spind.to_cache(prefix)
257
- self._sparse_index_cached = spind
265
+ spind.to_cache(prefix)
266
+ self._sparse_index_cached = spind
258
267
  assert self._sparse_index_cached.max() == len(self._sparse_index_cached.probs) - 1
259
268
  return self._sparse_index_cached
260
269
 
@@ -278,15 +287,19 @@ class SparseMap(parcellationmap.Map):
278
287
  Recreate a particular volumetric map from the sparse
279
288
  representation.
280
289
 
281
- Arguments
282
- ---------
283
- region_or_index: Union[str, Region, MapIndex]
290
+ Parameters
291
+ ----------
292
+ region_or_index: str, Region, MapIndex
284
293
  Lazy match the specification.
285
294
  index : MapIndex
286
295
  The index to be fetched.
287
- region: Union[str, Region]
288
- Region name specification. If given, will be used to
289
- decode the map index of a particular region.
296
+ region: str, Region
297
+ Region name specification. If given, will be used to decode the map
298
+ index of a particular region.
299
+
300
+ Returns
301
+ -------
302
+ An image or mesh
290
303
  """
291
304
  if kwargs.get('format') in ['mesh'] + _volume.Volume.MESH_FORMATS:
292
305
  # a mesh is requested, this is not handled by the sparse map
@@ -349,7 +362,7 @@ class SparseMap(parcellationmap.Map):
349
362
  for volume, value in spind.probs[voxel].items()
350
363
  )
351
364
 
352
- def _assign_image(self, queryimg: Nifti1Image, minsize_voxel: int, lower_threshold: float):
365
+ def _assign_image(self, queryimg: Nifti1Image, minsize_voxel: int, lower_threshold: float) -> List[parcellationmap.AssignImageResult]:
353
366
  """
354
367
  Assign an image volume to this parcellation map.
355
368
 
@@ -383,7 +396,7 @@ class SparseMap(parcellationmap.Map):
383
396
 
384
397
  querydata = np.asanyarray(queryimg.dataobj).squeeze()
385
398
 
386
- for mode, modeimg in parcellationmap.Map.iterate_connected_components(queryimg):
399
+ for mode, modeimg in iterate_connected_components(queryimg):
387
400
 
388
401
  # determine bounding box of the mode
389
402
  modemask = np.asanyarray(modeimg.dataobj)
@@ -400,12 +413,11 @@ class SparseMap(parcellationmap.Map):
400
413
 
401
414
  spind = self.sparse_index
402
415
 
403
- for volume in tqdm(
416
+ for volume in siibra_tqdm(
404
417
  range(len(self)),
405
418
  desc=f"Assigning structure #{mode} to {len(self)} sparse maps",
406
419
  total=len(self),
407
- unit=" map",
408
- disable=logger.level > 20,
420
+ unit=" map"
409
421
  ):
410
422
  bbox1 = boundingbox.BoundingBox(
411
423
  self.sparse_index.bboxes[volume]["minpoint"],
@@ -447,8 +459,6 @@ class SparseMap(parcellationmap.Map):
447
459
  iou = intersection / np.sum(
448
460
  (v1 > 0) | (v2 > 0)
449
461
  ) # np.maximum(v1, v2).sum()
450
- contains = intersection / (v1 > 0).sum()
451
- contained = intersection / (v2 > 0).sum()
452
462
 
453
463
  v1d = v1 - v1.mean()
454
464
  v2d = v2 - v2.mean()
@@ -460,16 +470,20 @@ class SparseMap(parcellationmap.Map):
460
470
 
461
471
  maxval = v1.max()
462
472
 
463
- assignments.append([
464
- mode,
465
- tuple(position.round(2)),
466
- volume,
467
- None,
468
- maxval,
469
- iou,
470
- contained,
471
- contains,
472
- rho
473
- ])
473
+ assignments.append(
474
+ parcellationmap.AssignImageResult(
475
+ input_structure=mode,
476
+ centroid=tuple(position.round(2)),
477
+ volume=volume,
478
+ fragment=None,
479
+ map_value=maxval,
480
+ intersection_over_union=iou,
481
+ intersection_over_first=intersection / (v1 > 0).sum(),
482
+ intersection_over_second=intersection / (v2 > 0).sum(),
483
+ correlation=rho,
484
+ weighted_mean_of_first=np.sum(v1 * v2) / np.sum(v2),
485
+ weighted_mean_of_second=np.sum(v1 * v2) / np.sum(v1)
486
+ )
487
+ )
474
488
 
475
489
  return assignments
siibra/volumes/volume.py CHANGED
@@ -20,9 +20,12 @@ from ..core import space
20
20
 
21
21
  import nibabel as nib
22
22
  from abc import ABC, abstractmethod
23
- from typing import List, Dict, Union, Set
23
+ from typing import List, Dict, Union, Set, TYPE_CHECKING
24
24
  import json
25
25
 
26
+ if TYPE_CHECKING:
27
+ from ..retrieval.datasets import EbrainsDataset
28
+ TypeDataset = EbrainsDataset
26
29
 
27
30
  class ColorVolumeNotSupported(NotImplementedError):
28
31
  pass
@@ -55,11 +58,13 @@ class Volume:
55
58
  providers: List['VolumeProvider'],
56
59
  name: str = "",
57
60
  variant: str = None,
61
+ datasets: List['TypeDataset'] = [],
58
62
  ):
59
63
  self._name_cached = name # see lazy implementation below
60
64
  self._space_spec = space_spec
61
65
  self.variant = variant
62
66
  self._providers: Dict[str, 'VolumeProvider'] = {}
67
+ self.datasets = datasets
63
68
  for provider in providers:
64
69
  srctype = provider.srctype
65
70
  assert srctype not in self._providers
@@ -69,13 +74,20 @@ class Volume:
69
74
 
70
75
  @property
71
76
  def name(self):
72
- """ allows derived classes to implemente a lazy name specification."""
77
+ """
78
+ Allows derived classes to implement a lazy name specification.
79
+ """
73
80
  return self._name_cached
74
81
 
75
82
  @property
76
83
  def providers(self):
84
+ def concat(url: Union[str, Dict[str, str]], concat: str):
85
+ if isinstance(url, str):
86
+ return url + concat
87
+ return {key: url[key] + concat for key in url}
77
88
  return {
78
- srctype: prov._url for srctype, prov in self._providers.items()
89
+ srctype: concat(prov._url, f" {prov.label}" if hasattr(prov, "label") else "")
90
+ for srctype, prov in self._providers.items()
79
91
  }
80
92
 
81
93
  @property
@@ -149,16 +161,16 @@ class Volume:
149
161
  ----------
150
162
  format: str
151
163
  Requested format. Per default, several formats are tried,
152
- starting with volumetric formats. You may explicitly specify:
153
- - 'surface' or 'mesh' to fetch a surface format
154
- - 'volumetric' or 'voxel' to fetch a volumetric format
155
- - supported format types, see :data:`Volume.SUPPORTED_FORMATS`. This includes:
156
- :class:`'nii'<siibra.volumes.nifti.NiftiProvider()>`,
157
- :class:`'zip/nii'<siibra.volumes.nifti.ZipContainedNiftiProvider()>`,
158
- :class:`'neuroglancer/precomputed'<siibra.volumes.neuroglancer.NeuroglancerProvider()>`,
159
- :class:`'gii-mesh'<siibra.volumes.gifti.GiftiMesh()>`,
160
- :class:`'neuroglancer/precompmesh'<siibra.volumes.neuroglancer.NeuroglancerMesh()>`,
161
- :class:`'gii-label'<siibra.volumes.gifti.GiftiSurfaceLabeling()>`
164
+ starting with volumetric formats. It can be explicitly specified as:
165
+ - 'surface' or 'mesh' to fetch a surface format
166
+ - 'volumetric' or 'voxel' to fetch a volumetric format
167
+ - supported format types, see SUPPORTED_FORMATS. This includes
168
+ 'nii', 'zip/nii', 'neuroglancer/precomputed', 'gii-mesh',
169
+ 'neuroglancer/precompmesh', 'gii-label'
170
+
171
+ Returns
172
+ -------
173
+ An image or mesh
162
174
  """
163
175
 
164
176
  if format is None:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: siibra
3
- Version: 0.4a33
3
+ Version: 0.4a46
4
4
  Summary: siibra - Software interfaces for interacting with brain atlases
5
5
  Home-page: https://github.com/FZJ-INM1-BDA/siibra-python
6
6
  Author: Big Data Analytics Group, Forschungszentrum Juelich, Institute of Neuroscience and Medicine (INM-1)
@@ -22,6 +22,7 @@ Requires-Dist: scikit-image
22
22
  Requires-Dist: requests
23
23
  Requires-Dist: neuroglancer-scripts
24
24
  Requires-Dist: nilearn
25
+ Requires-Dist: filelock
25
26
  Requires-Dist: typing-extensions ; python_version < "3.8"
26
27
 
27
28
  |License| |PyPI version| |Python versions| |Documentation Status|
@@ -39,7 +40,7 @@ Medicine (INM-1), Forschungszentrum Jülich GmbH*
39
40
  ``siibra`` is a Python client to a brain atlas framework that integrates brain parcellations and reference spaces at different spatial scales, and connects them with a broad range of multimodal regional data features.
40
41
  It aims to facilitate programmatic and reproducible incorporation of brain parcellations and brain region features from different sources into neuroscience workflows.
41
42
 
42
- **Note:** *``siibra-python`` is still in development. While care is taken that it works reliably, its API is not yet stable and you may still encounter bugs when using it.*
43
+ **Note:** ``siibra-python`` *is still in development. While care is taken that it works reliably, its API is not yet stable and you may still encounter bugs when using it.*
43
44
 
44
45
  ``siibra`` provides structured access to parcellation schemes in different brain reference spaces, including volumetric reference templates at macroscopic and microscopic resolutions as well as surface representations.
45
46
  It supports both discretely labelled and statistical (probabilistic) parcellation maps, which can be used to assign brain regions to spatial locations and image signals, to retrieve region-specific neuroscience datasets from multiple online repositories, and to sample information from high-resolution image data.
@@ -48,7 +49,7 @@ The datasets anchored to brain regions address features of molecular, cellular a
48
49
  ``siibra`` was developed in the frame of the `Human Brain Project <https://humanbrainproject.eu>`__ for accessing the `EBRAINS
49
50
  human brain atlas <https://ebrains.eu/service/human-brain-atlas>`__.
50
51
  It stores most of its contents as sustainable and open datasets in the `EBRAINS Knowledge Graph <https://kg.ebrains.eu>`__, and is designed to support the `OpenMINDS metadata standards <https://github.com/HumanBrainProject/openMINDS_SANDS>`__.
51
- Its functionalities include common actions known from the interactive viewer ``siibra explorer`` `hosted at EBRAINS <https://atlases.ebrains.eu/viewer>`__.
52
+ Its functionalities include common actions known from the interactive viewer ``siibra-explorer`` `hosted at EBRAINS <https://atlases.ebrains.eu/viewer>`__.
52
53
  In fact, the viewer is a good resource for exploring ``siibra``\ ’s core functionalities interactively: Selecting different parcellations, browsing and searching brain region hierarchies, downloading maps, identifying brain regions, and accessing multimodal features and connectivity information associated with brain regions.
53
54
  Feature queries in ``siibra`` are parameterized by data modality and anatomical location, while the latter could be a brain region, brain parcellation, or location in reference space.
54
55
  Beyond the explorative focus of ``siibra-explorer``, the Python library supports a range of data analysis functions suitable for typical neuroscience workflows.
@@ -0,0 +1,69 @@
1
+ siibra/VERSION,sha256=L13hDahuVhINiq4SVkPO6tDOa7WbXfZmeuvUoNN_ovw,7
2
+ siibra/__init__.py,sha256=VWA9EoVSVpkgwn3fmPw-nv4_kN63iWfyAwbU5W0_phY,3812
3
+ siibra/commons.py,sha256=dNANERrRyaRt_DYi24i-uyOb3ajt7zTfy-BS-gGg3_Q,24325
4
+ siibra/configuration/__init__.py,sha256=gXtcw2wbHCJ1o6jnd_HBudpaptHWBke71gcBd3ze7zE,688
5
+ siibra/configuration/configuration.py,sha256=YB02grlZbCHC5CfD0FX8bc4eEAQiLmZUzBRVT9lhXQ8,6886
6
+ siibra/configuration/factory.py,sha256=nonPGcDCBLavUQZQJBrPupBdUrOj8Te-Q_ghUBnPuvg,19405
7
+ siibra/core/__init__.py,sha256=YQkeqGqpOT3aH-PPHeGb1kxSyMbgR3ZHqDCy2I0Zlsk,735
8
+ siibra/core/atlas.py,sha256=FDtzpW1d492hFekttMz9aX-ggDwQrSwXlw1fWWF2tfE,7947
9
+ siibra/core/concept.py,sha256=zP76RKGOrityiJZQjKcYmsL1Z92IC4MPZUDl3qwz01k,8091
10
+ siibra/core/parcellation.py,sha256=eRX9FXEEPV-f6CsIUzh7hgSx100M48rLtnxZd7rBrSg,13405
11
+ siibra/core/region.py,sha256=cBcc5Jp5fgxxR_I-k3mDEbcxP0h2bDmF3f4XRUpCaGg,24613
12
+ siibra/core/space.py,sha256=iweTByicSWqSk-dJEscBceAGBUJ6k9pDFEUc8j29qXc,5959
13
+ siibra/features/__init__.py,sha256=da1Eyti0i6gMeZlwCQkf7SgZJpePc9CoUP7I53-DC6c,1315
14
+ siibra/features/anchor.py,sha256=Zz_0ovU_k5W_WM3z7sv7IjG2kGjt9jhku8RRw4jcByM,16131
15
+ siibra/features/feature.py,sha256=s_fixmcxRTR30r2WSOdKAlirD8rxQCEEXoq76vB5abA,15497
16
+ siibra/features/connectivity/__init__.py,sha256=c5ITfy6p6n-vze1jcgSguMq0Wk6QXVibmRvC-d92AbU,805
17
+ siibra/features/connectivity/functional_connectivity.py,sha256=9YYaeTSSDOv6Ha7gE0zJFgRP1bTL-0c7knukZtw2nqE,1407
18
+ siibra/features/connectivity/regional_connectivity.py,sha256=oUT_xvS2ngPVoxNG4UmkAGfJXKB8HvqipKsHvxnbpiQ,12083
19
+ siibra/features/connectivity/streamline_counts.py,sha256=ngl7xCiCUOyflyBvjZYa3ShOmtf21E5e0A_BeWfFtSQ,1064
20
+ siibra/features/connectivity/streamline_lengths.py,sha256=0a09Dag-eRvs1KgHSU47I3xQwbgHICsDozhZyuNzQME,1067
21
+ siibra/features/dataset/__init__.py,sha256=FB7PGXFyl0CEuVuzEU5VHPkxf7AwQK6Oyej3waClBKM,687
22
+ siibra/features/dataset/ebrains.py,sha256=vLWZvJAdTxtREf8-dlniIPiN4_itNujcvLhfic830V8,2699
23
+ siibra/features/image/__init__.py,sha256=514GkYVuxEwYpNZkRptHnygnYtoUaEgyUUNthXPxBKU,833
24
+ siibra/features/image/image.py,sha256=_P0V3WiF6TB_OF4F2Fo9Lobwm1esP8gNNve5-aqY5Dw,2819
25
+ siibra/features/image/sections.py,sha256=3Xllns8VBXdqrQHfIHJWt88tMN8uo8RHCEgvTZ3NQ7g,915
26
+ siibra/features/image/volume_of_interest.py,sha256=c4L5FMvfF0SWhD9m-_cpou64f6JwFWiO--oKA7W4DcI,2138
27
+ siibra/features/tabular/__init__.py,sha256=EuROA0DhSsMgw0FTLbIXGmPyOEG8UJ-ZQtl9wNQmbEU,1196
28
+ siibra/features/tabular/bigbrain_intensity_profile.py,sha256=JWG4KC9DlmsXazSn9tLdWkx7F8AlCtpwrBQcYZ0tRw0,2215
29
+ siibra/features/tabular/cell_density_profile.py,sha256=hPGE-lW36QCJrfLWHk9W4DmAow6HxSJG18onBcOicK8,9096
30
+ siibra/features/tabular/cortical_profile.py,sha256=-0xbLndu5_IYZYw-ElyMtBcLWkXhGuGefj3FVomDfJI,7911
31
+ siibra/features/tabular/gene_expression.py,sha256=gR2neifFbo_baPKEsXbnrn52CAg5kF5IovOxd6GvGKA,4798
32
+ siibra/features/tabular/layerwise_bigbrain_intensities.py,sha256=qbuOcV2EBuUFJDVrHBzDVLY3emV_xFslgESniOxl6cg,2138
33
+ siibra/features/tabular/layerwise_cell_density.py,sha256=hKwykSmzh7Z9zKgQXk_YQ3UUfULPnOHE85cIPQDkaCk,4266
34
+ siibra/features/tabular/receptor_density_fingerprint.py,sha256=xHt7woUKHRVz08i8dON7HTnzTR1R2jcAxyWL60mEeFE,6010
35
+ siibra/features/tabular/receptor_density_profile.py,sha256=6JO14y9WB40PbDDcxu8KvC_0HGi3l3rnUiGJWjgsk4w,3577
36
+ siibra/features/tabular/regional_timeseries_activity.py,sha256=C-QCBKraXH3qw1qHCRM8M4pyR_30eDyQwZ1UBakMHME,7247
37
+ siibra/features/tabular/tabular.py,sha256=r9CJ0UCEZImfjPkhWvzgITDJ9q37Cz_AKmupUhE2xMs,3201
38
+ siibra/livequeries/__init__.py,sha256=b5qKiJt_SrgSzy4abRYqvnbLSo01vUHrK8-K2zbnKIo,804
39
+ siibra/livequeries/allen.py,sha256=-XHS1zA4tMQCEX3x4tMhuADuvjCUK5RpafyfrTeK5mc,12179
40
+ siibra/livequeries/bigbrain.py,sha256=Rtfp2hwpX4pR45j0ZtFlEZx0AdHkpSEQgW_V59A5GRY,6834
41
+ siibra/livequeries/ebrains.py,sha256=tdDwiaVhIrlzwT68aNV3Ds8JLjbgJ0nOx6GGAPmBCbA,5789
42
+ siibra/livequeries/query.py,sha256=GYD_nidlKmC9N7M8Jo54iolSrcvg4P2ixjurbWMk0dk,1786
43
+ siibra/locations/__init__.py,sha256=ItA2BnaaqP9wdXUH78mMhPFR0dSDxnz66o-y9vJH2Ag,773
44
+ siibra/locations/boundingbox.py,sha256=Oh2FxRFcDIh3a59ko1wbp5LQBVgLPhJx8Tkn4R3z_MQ,16824
45
+ siibra/locations/location.py,sha256=s1HEafa8jGi2C47ohwgG9XgVKAotK1HtS7Ez5gMsf_U,4577
46
+ siibra/locations/point.py,sha256=1ea3X9cGKltNPZnnQyBoKoVhCE0U0hGtzWljf-xZw6I,12586
47
+ siibra/locations/pointset.py,sha256=GaWnHDN7NRuKvl4hSU6YREcydFX1yWygbEOJBKTW2Ws,7110
48
+ siibra/retrieval/__init__.py,sha256=VaR81n9ldwwbpPgIHmoUPmn8QHlZ0_R633yDqQrx6JA,1028
49
+ siibra/retrieval/cache.py,sha256=NfieYe-3stgjpWQXVGTJSVSLJQOoat-eswj5eWEEaB8,4889
50
+ siibra/retrieval/datasets.py,sha256=-MB8A-r3bmqPMOelSWZkaHq41Vu0YHjQEVHeq36qfW0,7660
51
+ siibra/retrieval/repositories.py,sha256=i_eDQcLmpIbImdVWkIWLSkshCPYQ9fWJe4gmvUMM790,26309
52
+ siibra/retrieval/requests.py,sha256=UYeo38hpbxWxmKOofiTIFcHabbwvIHWIcw0J9_xJsT0,20940
53
+ siibra/retrieval/exceptions/__init__.py,sha256=STIPOyunBN2f7d26NTElLTL3xM1KoB3U7jLhNBivguA,173
54
+ siibra/vocabularies/__init__.py,sha256=I_tTB-3xYAdVzRGP0CCVGgd3dP6QiltoJqEZFTr-lkI,1261
55
+ siibra/vocabularies/gene_names.json,sha256=i-gnh753GyZtQfX_dWibNYr_d5ccDPHooOwsdeKUYqE,1647972
56
+ siibra/vocabularies/receptor_symbols.json,sha256=F6DZIArPCBmJV_lWGV-zDpBBH_GOJOZm67LBE4qzMa4,5722
57
+ siibra/vocabularies/region_aliases.json,sha256=RFxH36D3JS-T6lGlATthcNbPkKINjiqZxFoeb7OTtJY,8449
58
+ siibra/volumes/__init__.py,sha256=b6O5aWKfFU0JGT8PMTUF6OewCti7aRyOno_kjJ4es_U,830
59
+ siibra/volumes/gifti.py,sha256=idULD08pB_wxqzSFHlC_JkhFr-KuHP7FZnqp62QLXGo,5504
60
+ siibra/volumes/neuroglancer.py,sha256=QX7rYsgLPowQsGbOYCUsFj-r3z16c1c7VFTDDL9dkNk,24056
61
+ siibra/volumes/nifti.py,sha256=3psZ8cdOVRe9nsf82sUivb7VwfhD5MtYqAOs9IzW8Is,8948
62
+ siibra/volumes/parcellationmap.py,sha256=lldGnmqp2_VZNv9cr5e7tvA_pgzXFapjzJ9WmhNPg74,42172
63
+ siibra/volumes/sparsemap.py,sha256=rRl8xZFIpI8WxMjDF_WQYqxtKoH6fCQWBfBvCf_mPJs,18071
64
+ siibra/volumes/volume.py,sha256=2YZdjcHScmYhdJI0gH-wzyE8ZjQcKrlhtEk9udtcyeE,9915
65
+ siibra-0.4a46.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
66
+ siibra-0.4a46.dist-info/METADATA,sha256=_us0IIlXJHZ25hgSeQc3b5S1JAdnweu5cXe7r5P5o6s,9248
67
+ siibra-0.4a46.dist-info/WHEEL,sha256=pkctZYzUS4AYVn6dJ-7367OJZivF2e8RA9b_ZBjif18,92
68
+ siibra-0.4a46.dist-info/top_level.txt,sha256=NF0OSGLL0li2qyC7MaU0iBB5Y9S09_euPpvisD0-8Hg,7
69
+ siibra-0.4a46.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.38.4)
2
+ Generator: bdist_wheel (0.40.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,248 +0,0 @@
1
- # Copyright 2018-2021
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 anchor as _anchor
17
-
18
- from ...commons import logger
19
- from ...core import concept
20
- from ...core import space, region, parcellation
21
-
22
- from typing import Union, TYPE_CHECKING, List, Dict, Type
23
- from tqdm import tqdm
24
- from hashlib import md5
25
- from collections import defaultdict
26
-
27
- if TYPE_CHECKING:
28
- from ...retrieval.datasets import EbrainsDataset
29
- TypeDataset = EbrainsDataset
30
-
31
-
32
- class Feature:
33
- """
34
- Base class for anatomically anchored data features.
35
- """
36
-
37
- SUBCLASSES: Dict[Type['Feature'], List[Type['Feature']]] = defaultdict(list)
38
-
39
- def __init__(
40
- self,
41
- modality: str,
42
- description: str,
43
- anchor: _anchor.AnatomicalAnchor,
44
- datasets: List['TypeDataset'] = []
45
- ):
46
- """
47
- Parameters
48
- ----------
49
- modality: str
50
- A textual description of the type of measured information
51
- description: str
52
- A textual description of the feature.
53
- anchor: AnatomicalAnchor
54
- datasets : list
55
- list of datasets corresponding to this feature
56
- """
57
- self._modality_cached = modality
58
- self._description = description
59
- self._anchor_cached = anchor
60
- self.datasets = datasets
61
-
62
- @property
63
- def modality(self):
64
- # allows subclasses to implement lazy loading of an anchor
65
- return self._modality_cached
66
-
67
- @property
68
- def anchor(self):
69
- # allows subclasses to implement lazy loading of an anchor
70
- return self._anchor_cached
71
-
72
- def __init_subclass__(cls, configuration_folder=None):
73
- # extend the subclass lists
74
-
75
- # Iterate over all mro, not just immediate base classes
76
- for BaseCls in cls.__mro__:
77
- # some base classes may not be sub class of feature, ignore these
78
- if not issubclass(BaseCls, Feature):
79
- continue
80
- cls.SUBCLASSES[BaseCls].append(cls)
81
-
82
- cls._live_queries = []
83
- cls._preconfigured_instances = None
84
- cls._configuration_folder = configuration_folder
85
- return super().__init_subclass__()
86
-
87
- @classmethod
88
- def _get_subclasses(cls):
89
- return {Cls.__name__: Cls for Cls in cls.SUBCLASSES}
90
-
91
- @property
92
- def description(self):
93
- """ Allowssubclasses to overwrite the description with a function call. """
94
- return self._description
95
-
96
- @property
97
- def name(self):
98
- """Returns a short human-readable name of this feature."""
99
- return f"{self.__class__.__name__} ({self.modality}) anchored at {self.anchor}"
100
-
101
- @classmethod
102
- def get_instances(cls, **kwargs) -> List['Feature']:
103
- """
104
- Retrieve objects of a particular feature subclass.
105
- Objects can be preconfigured in the configuration,
106
- or delivered by Live queries.
107
- """
108
- result = []
109
-
110
- if hasattr(cls, "_preconfigured_instances"):
111
- if cls._preconfigured_instances is None:
112
- if cls._configuration_folder is None:
113
- cls._preconfigured_instances = []
114
- else:
115
- from ...configuration.configuration import Configuration
116
- conf = Configuration()
117
- Configuration.register_cleanup(cls.clean_instances)
118
- assert cls._configuration_folder in conf.folders
119
- cls._preconfigured_instances = [
120
- o for o in conf.build_objects(cls._configuration_folder)
121
- if isinstance(o, cls)
122
- ]
123
- logger.debug(
124
- f"Built {len(cls._preconfigured_instances)} preconfigured {cls.__name__} "
125
- f"objects from {cls._configuration_folder}."
126
- )
127
- result.extend(cls._preconfigured_instances)
128
-
129
- return result
130
-
131
- @classmethod
132
- def clean_instances(cls):
133
- """ Removes all instantiated object instances"""
134
- cls._preconfigured_instances = None
135
-
136
- def matches(self, concept: concept.AtlasConcept) -> bool:
137
- if self.anchor and self.anchor.matches(concept):
138
- self.anchor._last_matched_concept = concept
139
- return True
140
- self.anchor._last_matched_concept = None
141
- return False
142
-
143
- @property
144
- def last_match_result(self):
145
- return None if self.anchor is None \
146
- else self.anchor.last_match_result
147
-
148
- @property
149
- def last_match_description(self):
150
- return "" if self.anchor is None \
151
- else self.anchor.last_match_description
152
-
153
- @property
154
- def id(self):
155
- prefix = ''
156
- id_set = {ds.id for ds in self.datasets if hasattr(ds, 'id')}
157
- if len(id_set) == 1:
158
- prefix = list(id_set)[0] + '--'
159
- return prefix + md5(self.name.encode("utf-8")).hexdigest()
160
-
161
- @classmethod
162
- def match(cls, concept: Union[region.Region, parcellation.Parcellation, space.Space], feature_type: Union[str, Type['Feature'], list], **kwargs) -> List['Feature']:
163
- """
164
- Retrieve data features of the desired modality.
165
-
166
- Parameters
167
- ----------
168
- concept: AtlasConcept
169
- An anatomical concept, typically a brain region or parcellation.
170
- modality: subclass of Feature
171
- specififies the type of features ("modality")
172
- """
173
- if isinstance(feature_type, list):
174
- # a list of feature types is given, collect match results on those
175
- assert all((isinstance(t, str) or issubclass(t, cls)) for t in feature_type)
176
- return sum((cls.match(concept, t, **kwargs) for t in feature_type), [])
177
-
178
- if isinstance(feature_type, str):
179
- # feature type given as a string. Decode the corresponding class.
180
- # Some string inputs, such as connectivity, may hit multiple matches
181
- # In this case
182
- candidates = [
183
- feattype
184
- for FeatCls, feattypes in cls.SUBCLASSES.items()
185
- if all(w.lower() in FeatCls.__name__.lower() for w in feature_type.split())
186
- for feattype in feattypes
187
- ]
188
- if len(candidates) == 0:
189
- raise ValueError(f"feature_type {str(feature_type)} did not match with any features. Available features are: {', '.join(cls.SUBCLASSES.keys())}")
190
-
191
- return [feat for c in candidates for feat in cls.match(concept, c, **kwargs)]
192
-
193
- assert issubclass(feature_type, Feature)
194
-
195
- if not isinstance(concept, (region.Region, parcellation.Parcellation, space.Space)):
196
- raise ValueError(
197
- "Feature.match / siibra.features.get only accepts Region, "
198
- "Space and Parcellation objects as concept."
199
- )
200
-
201
- msg = f"Matching {feature_type.__name__} to {concept}"
202
- instances = [
203
- instance
204
- for f_type in cls.SUBCLASSES[feature_type]
205
- for instance in f_type.get_instances()
206
- ]
207
-
208
- if logger.getEffectiveLevel() > 20:
209
- preconfigured_instances = [f for f in instances if f.matches(concept)]
210
- else:
211
- preconfigured_instances = [f for f in tqdm(instances, desc=msg, total=len(instances)) if f.matches(concept)]
212
-
213
- live_instances = []
214
- if hasattr(feature_type, "_live_queries"):
215
- for QueryType in feature_type._live_queries:
216
- argstr = f" ({', '.join('='.join(map(str,_)) for _ in kwargs.items())})" \
217
- if len(kwargs) > 0 else ""
218
- logger.info(
219
- f"Running live query for {QueryType.feature_type.__name__} "
220
- f"objects linked to {str(concept)}{argstr}"
221
- )
222
- q = QueryType(**kwargs)
223
- live_instances.extend(q.query(concept))
224
-
225
- return preconfigured_instances + live_instances
226
-
227
- @classmethod
228
- def get_ascii_tree(cls):
229
- # build an Ascii representation of class hierarchy
230
- # under this feature class
231
- from anytree.importer import DictImporter
232
- from anytree import RenderTree
233
-
234
- def create_treenode(feature_type):
235
- return {
236
- 'name': feature_type.__name__,
237
- 'children': [
238
- create_treenode(c)
239
- for c in feature_type.__subclasses__()
240
- ]
241
- }
242
- D = create_treenode(cls)
243
- importer = DictImporter()
244
- tree = importer.import_(D)
245
- return "\n".join(
246
- "%s%s" % (pre, node.name)
247
- for pre, _, node in RenderTree(tree)
248
- )