siibra 0.4a90__tar.gz → 0.4a92__tar.gz

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-0.4a90/siibra.egg-info → siibra-0.4a92}/PKG-INFO +1 -1
  2. siibra-0.4a92/siibra/VERSION +1 -0
  3. {siibra-0.4a90 → siibra-0.4a92}/siibra/configuration/factory.py +4 -2
  4. {siibra-0.4a90 → siibra-0.4a92}/siibra/retrieval/requests.py +30 -1
  5. {siibra-0.4a90 → siibra-0.4a92}/siibra/volumes/__init__.py +1 -0
  6. siibra-0.4a92/siibra/volumes/freesurfer.py +123 -0
  7. {siibra-0.4a90 → siibra-0.4a92}/siibra/volumes/volume.py +4 -2
  8. {siibra-0.4a90 → siibra-0.4a92/siibra.egg-info}/PKG-INFO +1 -1
  9. {siibra-0.4a90 → siibra-0.4a92}/siibra.egg-info/SOURCES.txt +1 -0
  10. siibra-0.4a90/siibra/VERSION +0 -1
  11. {siibra-0.4a90 → siibra-0.4a92}/LICENSE +0 -0
  12. {siibra-0.4a90 → siibra-0.4a92}/MANIFEST.in +0 -0
  13. {siibra-0.4a90 → siibra-0.4a92}/README.rst +0 -0
  14. {siibra-0.4a90 → siibra-0.4a92}/setup.cfg +0 -0
  15. {siibra-0.4a90 → siibra-0.4a92}/setup.py +0 -0
  16. {siibra-0.4a90 → siibra-0.4a92}/siibra/__init__.py +0 -0
  17. {siibra-0.4a90 → siibra-0.4a92}/siibra/commons.py +0 -0
  18. {siibra-0.4a90 → siibra-0.4a92}/siibra/configuration/__init__.py +0 -0
  19. {siibra-0.4a90 → siibra-0.4a92}/siibra/configuration/configuration.py +0 -0
  20. {siibra-0.4a90 → siibra-0.4a92}/siibra/core/__init__.py +0 -0
  21. {siibra-0.4a90 → siibra-0.4a92}/siibra/core/atlas.py +0 -0
  22. {siibra-0.4a90 → siibra-0.4a92}/siibra/core/concept.py +0 -0
  23. {siibra-0.4a90 → siibra-0.4a92}/siibra/core/parcellation.py +0 -0
  24. {siibra-0.4a90 → siibra-0.4a92}/siibra/core/region.py +0 -0
  25. {siibra-0.4a90 → siibra-0.4a92}/siibra/core/relation_qualification.py +0 -0
  26. {siibra-0.4a90 → siibra-0.4a92}/siibra/core/space.py +0 -0
  27. {siibra-0.4a90 → siibra-0.4a92}/siibra/explorer/__init__.py +0 -0
  28. {siibra-0.4a90 → siibra-0.4a92}/siibra/explorer/url.py +0 -0
  29. {siibra-0.4a90 → siibra-0.4a92}/siibra/explorer/util.py +0 -0
  30. {siibra-0.4a90 → siibra-0.4a92}/siibra/features/__init__.py +0 -0
  31. {siibra-0.4a90 → siibra-0.4a92}/siibra/features/anchor.py +0 -0
  32. {siibra-0.4a90 → siibra-0.4a92}/siibra/features/connectivity/__init__.py +0 -0
  33. {siibra-0.4a90 → siibra-0.4a92}/siibra/features/connectivity/functional_connectivity.py +0 -0
  34. {siibra-0.4a90 → siibra-0.4a92}/siibra/features/connectivity/regional_connectivity.py +0 -0
  35. {siibra-0.4a90 → siibra-0.4a92}/siibra/features/connectivity/streamline_counts.py +0 -0
  36. {siibra-0.4a90 → siibra-0.4a92}/siibra/features/connectivity/streamline_lengths.py +0 -0
  37. {siibra-0.4a90 → siibra-0.4a92}/siibra/features/connectivity/tracing_connectivity.py +0 -0
  38. {siibra-0.4a90 → siibra-0.4a92}/siibra/features/dataset/__init__.py +0 -0
  39. {siibra-0.4a90 → siibra-0.4a92}/siibra/features/dataset/ebrains.py +0 -0
  40. {siibra-0.4a90 → siibra-0.4a92}/siibra/features/feature.py +0 -0
  41. {siibra-0.4a90 → siibra-0.4a92}/siibra/features/image/__init__.py +0 -0
  42. {siibra-0.4a90 → siibra-0.4a92}/siibra/features/image/image.py +0 -0
  43. {siibra-0.4a90 → siibra-0.4a92}/siibra/features/image/sections.py +0 -0
  44. {siibra-0.4a90 → siibra-0.4a92}/siibra/features/image/volume_of_interest.py +0 -0
  45. {siibra-0.4a90 → siibra-0.4a92}/siibra/features/tabular/__init__.py +0 -0
  46. {siibra-0.4a90 → siibra-0.4a92}/siibra/features/tabular/bigbrain_intensity_profile.py +0 -0
  47. {siibra-0.4a90 → siibra-0.4a92}/siibra/features/tabular/cell_density_profile.py +0 -0
  48. {siibra-0.4a90 → siibra-0.4a92}/siibra/features/tabular/cortical_profile.py +0 -0
  49. {siibra-0.4a90 → siibra-0.4a92}/siibra/features/tabular/gene_expression.py +0 -0
  50. {siibra-0.4a90 → siibra-0.4a92}/siibra/features/tabular/layerwise_bigbrain_intensities.py +0 -0
  51. {siibra-0.4a90 → siibra-0.4a92}/siibra/features/tabular/layerwise_cell_density.py +0 -0
  52. {siibra-0.4a90 → siibra-0.4a92}/siibra/features/tabular/receptor_density_fingerprint.py +0 -0
  53. {siibra-0.4a90 → siibra-0.4a92}/siibra/features/tabular/receptor_density_profile.py +0 -0
  54. {siibra-0.4a90 → siibra-0.4a92}/siibra/features/tabular/regional_timeseries_activity.py +0 -0
  55. {siibra-0.4a90 → siibra-0.4a92}/siibra/features/tabular/tabular.py +0 -0
  56. {siibra-0.4a90 → siibra-0.4a92}/siibra/livequeries/__init__.py +0 -0
  57. {siibra-0.4a90 → siibra-0.4a92}/siibra/livequeries/allen.py +0 -0
  58. {siibra-0.4a90 → siibra-0.4a92}/siibra/livequeries/bigbrain.py +0 -0
  59. {siibra-0.4a90 → siibra-0.4a92}/siibra/livequeries/ebrains.py +0 -0
  60. {siibra-0.4a90 → siibra-0.4a92}/siibra/livequeries/query.py +0 -0
  61. {siibra-0.4a90 → siibra-0.4a92}/siibra/locations/__init__.py +0 -0
  62. {siibra-0.4a90 → siibra-0.4a92}/siibra/locations/boundingbox.py +0 -0
  63. {siibra-0.4a90 → siibra-0.4a92}/siibra/locations/location.py +0 -0
  64. {siibra-0.4a90 → siibra-0.4a92}/siibra/locations/point.py +0 -0
  65. {siibra-0.4a90 → siibra-0.4a92}/siibra/locations/pointset.py +0 -0
  66. {siibra-0.4a90 → siibra-0.4a92}/siibra/retrieval/__init__.py +0 -0
  67. {siibra-0.4a90 → siibra-0.4a92}/siibra/retrieval/cache.py +0 -0
  68. {siibra-0.4a90 → siibra-0.4a92}/siibra/retrieval/datasets.py +0 -0
  69. {siibra-0.4a90 → siibra-0.4a92}/siibra/retrieval/exceptions/__init__.py +0 -0
  70. {siibra-0.4a90 → siibra-0.4a92}/siibra/retrieval/repositories.py +0 -0
  71. {siibra-0.4a90 → siibra-0.4a92}/siibra/vocabularies/__init__.py +0 -0
  72. {siibra-0.4a90 → siibra-0.4a92}/siibra/vocabularies/gene_names.json +0 -0
  73. {siibra-0.4a90 → siibra-0.4a92}/siibra/vocabularies/receptor_symbols.json +0 -0
  74. {siibra-0.4a90 → siibra-0.4a92}/siibra/vocabularies/region_aliases.json +0 -0
  75. {siibra-0.4a90 → siibra-0.4a92}/siibra/volumes/gifti.py +0 -0
  76. {siibra-0.4a90 → siibra-0.4a92}/siibra/volumes/neuroglancer.py +0 -0
  77. {siibra-0.4a90 → siibra-0.4a92}/siibra/volumes/nifti.py +0 -0
  78. {siibra-0.4a90 → siibra-0.4a92}/siibra/volumes/parcellationmap.py +0 -0
  79. {siibra-0.4a90 → siibra-0.4a92}/siibra/volumes/sparsemap.py +0 -0
  80. {siibra-0.4a90 → siibra-0.4a92}/siibra.egg-info/dependency_links.txt +0 -0
  81. {siibra-0.4a90 → siibra-0.4a92}/siibra.egg-info/requires.txt +0 -0
  82. {siibra-0.4a90 → siibra-0.4a92}/siibra.egg-info/top_level.txt +0 -0
  83. {siibra-0.4a90 → siibra-0.4a92}/test/test_siibra.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: siibra
3
- Version: 0.4a90
3
+ Version: 0.4a92
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)
@@ -0,0 +1 @@
1
+ 0.4a92
@@ -26,7 +26,7 @@ from ..features.image import sections, volume_of_interest
26
26
  from ..core import atlas, parcellation, space, region
27
27
  from ..locations import point, pointset
28
28
  from ..retrieval import datasets, repositories
29
- from ..volumes import gifti, volume, nifti, neuroglancer, sparsemap, parcellationmap
29
+ from ..volumes import gifti, volume, nifti, neuroglancer, freesurfer, sparsemap, parcellationmap
30
30
 
31
31
  from os import path
32
32
  import json
@@ -253,7 +253,9 @@ class Factory:
253
253
  nifti.NiftiProvider,
254
254
  nifti.ZipContainedNiftiProvider,
255
255
  gifti.GiftiMesh,
256
- gifti.GiftiSurfaceLabeling
256
+ gifti.GiftiSurfaceLabeling,
257
+ freesurfer.FreesurferAnnot,
258
+ freesurfer.ZippedFreesurferAnnot,
257
259
  ]
258
260
 
259
261
  for srctype, provider_spec in spec.get("providers", {}).items():
@@ -30,7 +30,7 @@ import json
30
30
  from zipfile import ZipFile
31
31
  import requests
32
32
  import os
33
- from nibabel import Nifti1Image, GiftiImage, streamlines
33
+ from nibabel import Nifti1Image, GiftiImage, streamlines, freesurfer
34
34
  from skimage import io as skimage_io
35
35
  import gzip
36
36
  from io import BytesIO
@@ -54,6 +54,34 @@ if TYPE_CHECKING:
54
54
 
55
55
  USER_AGENT_HEADER = {"User-Agent": f"siibra-python/{__version__}"}
56
56
 
57
+
58
+ def read_as_bytesio(function: Callable, suffix: str, bytesio: BytesIO):
59
+ """
60
+ Helper method to provide BytesIO to methods that only takes file path and
61
+ cannot handle BytesIO normally (e.g., `nibabel.freesurfer.read_annot()`).
62
+
63
+ Writes the bytes to a temporary file on cache and reads with the
64
+ original function.
65
+
66
+ Parameters
67
+ ----------
68
+ function : Callable
69
+ suffix : str
70
+ Must match the suffix expected by the function provided.
71
+ bytesio : BytesIO
72
+
73
+ Returns
74
+ -------
75
+ Return type of the provided function.
76
+ """
77
+ tempfile = CACHE.build_filename(f"temp_{suffix}") + suffix
78
+ with open(tempfile, "wb") as bf:
79
+ bf.write(bytesio.getbuffer())
80
+ result = function(tempfile)
81
+ os.remove(tempfile)
82
+ return result
83
+
84
+
57
85
  DECODERS = {
58
86
  ".nii": lambda b: Nifti1Image.from_bytes(b),
59
87
  ".gii": lambda b: GiftiImage.from_bytes(b),
@@ -65,6 +93,7 @@ DECODERS = {
65
93
  ".zip": lambda b: ZipFile(BytesIO(b)),
66
94
  ".png": lambda b: skimage_io.imread(BytesIO(b)),
67
95
  ".npy": lambda b: np.load(BytesIO(b)),
96
+ ".annot": lambda b: read_as_bytesio(freesurfer.read_annot, '.annot', BytesIO(b)),
68
97
  }
69
98
 
70
99
 
@@ -18,6 +18,7 @@ from .parcellationmap import Map
18
18
  from .neuroglancer import NeuroglancerProvider, NeuroglancerMesh
19
19
  from .nifti import NiftiProvider
20
20
  from .gifti import GiftiSurfaceLabeling, GiftiMesh
21
+ from .freesurfer import FreesurferAnnot, ZippedFreesurferAnnot
21
22
 
22
23
 
23
24
  def warm_cache():
@@ -0,0 +1,123 @@
1
+ # Copyright 2018-2025
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 typing import Union, Dict, TYPE_CHECKING
18
+
19
+ import numpy as np
20
+
21
+ from . import volume
22
+ from ..retrieval.requests import HttpRequest, ZipfileRequest
23
+
24
+ if TYPE_CHECKING:
25
+ from ..locations import boundingbox as _boundingbox
26
+
27
+
28
+ class FreesurferAnnot(volume.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 background as -1 while siibra uses 0
58
+ vertex_labels.append(frag_labels)
59
+
60
+ return {"labels": np.hstack(vertex_labels)}
61
+
62
+ @property
63
+ def boundingbox(self) -> '_boundingbox.BoundingBox':
64
+ raise NotImplementedError(
65
+ f"Bounding box access to {self.__class__.__name__} objects not yet implemented."
66
+ )
67
+
68
+ @property
69
+ def fragments(self):
70
+ return [k for k in self._loaders if k is not None]
71
+
72
+ @property
73
+ def _url(self) -> Union[str, Dict[str, str]]:
74
+ return self._init_url
75
+
76
+
77
+ class ZippedFreesurferAnnot(volume.VolumeProvider, srctype="zip/freesurfer-annot"):
78
+ def __init__(self, url: Union[str, dict]):
79
+ self._init_url = url
80
+ if isinstance(url, str): # single mesh labelling
81
+ self._loaders = {None: ZipfileRequest(*url.split(" "))}
82
+ elif isinstance(url, dict): # named label fragments
83
+ self._loaders = {lbl: ZipfileRequest(*u.split(" ")) for lbl, u in url.items()}
84
+ else:
85
+ raise NotImplementedError(f"Urls for {self.__class__.__name__} are expected to be of type str.")
86
+
87
+ def fetch(self, fragment: str = None, label: int = None, **kwargs):
88
+ """Returns a 1D numpy array of label indices."""
89
+ vertex_labels = []
90
+ if fragment is None:
91
+ matched_frags = list(self._loaders.keys())
92
+ else:
93
+ matched_frags = [frg for frg in self._loaders.keys() if fragment.lower() in frg.lower()]
94
+ if len(matched_frags) != 1:
95
+ raise ValueError(
96
+ f"Requested fragment '{fragment}' could not be matched uniquely "
97
+ f"to [{', '.join(self._loaders)}]"
98
+ )
99
+ for frag in matched_frags:
100
+ frag_labels, *_ = self._loaders[frag].data
101
+ if label is not None: # create the mask
102
+ selected_label = frag_labels == label
103
+ frag_labels[selected_label] = 1
104
+ frag_labels[~selected_label] = 0
105
+ else:
106
+ frag_labels[frag_labels == -1] = 0 # annot files store background as -1 while siibra uses 0
107
+ vertex_labels.append(frag_labels)
108
+
109
+ return {"labels": np.hstack(vertex_labels)}
110
+
111
+ @property
112
+ def boundingbox(self) -> '_boundingbox.BoundingBox':
113
+ raise NotImplementedError(
114
+ f"Bounding box access to {self.__class__.__name__} objects not yet implemented."
115
+ )
116
+
117
+ @property
118
+ def fragments(self):
119
+ return [k for k in self._loaders if k is not None]
120
+
121
+ @property
122
+ def _url(self) -> Union[str, Dict[str, str]]:
123
+ return self._init_url
@@ -49,7 +49,9 @@ class Volume:
49
49
  "neuroglancer/precompmesh",
50
50
  "neuroglancer/precompmesh/surface",
51
51
  "gii-mesh",
52
- "gii-label"
52
+ "gii-label",
53
+ "freesurfer-annot",
54
+ "zip/freesurfer-annot",
53
55
  ]
54
56
 
55
57
  SUPPORTED_FORMATS = IMAGE_FORMATS + MESH_FORMATS
@@ -218,7 +220,7 @@ class Volume:
218
220
  # try the selected format only
219
221
  for try_count in range(6):
220
222
  try:
221
- if selected_format == "gii-label":
223
+ if selected_format in ["gii-label", "freesurfer-annot", "zip/freesurfer-annot"]:
222
224
  tpl = self.space.get_template(variant=kwargs.get('variant'))
223
225
  mesh = tpl.fetch(**kwargs)
224
226
  labels = self._providers[selected_format].fetch(**kwargs)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: siibra
3
- Version: 0.4a90
3
+ Version: 0.4a92
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)
@@ -70,6 +70,7 @@ siibra/vocabularies/gene_names.json
70
70
  siibra/vocabularies/receptor_symbols.json
71
71
  siibra/vocabularies/region_aliases.json
72
72
  siibra/volumes/__init__.py
73
+ siibra/volumes/freesurfer.py
73
74
  siibra/volumes/gifti.py
74
75
  siibra/volumes/neuroglancer.py
75
76
  siibra/volumes/nifti.py
@@ -1 +0,0 @@
1
- 0.4a90
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes