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
siibra/core/space.py CHANGED
@@ -45,24 +45,25 @@ class Space(AtlasConcept, configuration_folder="spaces"):
45
45
 
46
46
  Parameters
47
47
  ----------
48
- identifier : str
49
- Unique identifier of the space
50
- name : str
51
- Human-readable name of the space
52
- species: str or Species
53
- Specification of the species
54
- volumes: list of template volumes
55
- shortname: str
56
- Shortform of human-readable name (optional)
57
- description: str
58
- Textual description of the parcellation
59
- modality : str or None
60
- Specification of the modality representing this reference space
61
- publications: list
62
- List of ssociated publications, each a dictionary with "doi" and/or "citation" fields
63
- ebrains_ids : dict
64
- Identifiers of EBRAINS entities corresponding to this Parcellation.
65
- Key: EBRAINS KG schema, value: EBRAINS KG @id
48
+ identifier : str
49
+ Unique identifier of the space
50
+ name : str
51
+ Human-readable name of the space
52
+ species: str or Species
53
+ Specification of the species
54
+ volumes: list[Volume]
55
+ list of template volumes
56
+ shortname: str, optional
57
+ Shortform of human-readable name
58
+ description: str, optional
59
+ Textual description of the parcellation
60
+ modality : str or None
61
+ Specification of the modality representing this reference space
62
+ publications: list
63
+ List of associated publications, each a dictionary with "doi" and/or "citation" fields
64
+ ebrains_ids : dict
65
+ Identifiers of EBRAINS entities corresponding to this Parcellation.
66
+ Key: EBRAINS KG schema, value: EBRAINS KG @id
66
67
  """
67
68
 
68
69
  AtlasConcept.__init__(
@@ -86,19 +87,20 @@ class Space(AtlasConcept, configuration_folder="spaces"):
86
87
 
87
88
  Parameters
88
89
  ----------
89
- variant: str (optional)
90
- Some templates are provided in different variants, e.g.
91
- freesurfer is available as either white matter, pial or
92
- inflated surface for left and right hemispheres (6 variants).
93
- This field could be used to request a specific variant.
94
- Per default, the first found variant is returned.
95
- format: str (optional)
96
- Volumes are typically available in multiple formats.
97
- Use this to select a specific one, if needed.
98
-
99
- Yields
100
- ------
101
- A VolumeSrc object representing the reference template, or None if not available.
90
+ variant: str, optional
91
+ Some templates are provided in different variants, e.g.
92
+ freesurfer is available as either white matter, pial or
93
+ inflated surface for left and right hemispheres (6 variants).
94
+ This field could be used to request a specific variant.
95
+ Per default, the first found variant is returned.
96
+ format: str, optional
97
+ Volumes are typically available in multiple formats.
98
+ Use this to select a specific one, if needed.
99
+
100
+ Returns
101
+ -------
102
+ Volume
103
+ representing the reference template, or None if not available.
102
104
  """
103
105
  tests = []
104
106
  if variant is not None:
@@ -131,10 +133,10 @@ class Space(AtlasConcept, configuration_folder="spaces"):
131
133
  """
132
134
  Get a volume of interest specification from this space.
133
135
 
134
- Arguments
135
- ---------
136
- slices: triple of slice
137
- defines the x, y and z range
136
+ Parameters
137
+ ----------
138
+ slices: triple of slice
139
+ Defines the x, y and z range
138
140
  """
139
141
  if len(slices) != 3:
140
142
  raise TypeError(
@@ -153,9 +155,12 @@ class Space(AtlasConcept, configuration_folder="spaces"):
153
155
  """
154
156
  Get a volume of interest specification from this space.
155
157
 
156
- Arguments
157
- ---------
158
- point1: 3D tuple defined in physical coordinates of this reference space
159
- point2: 3D tuple defined in physical coordinates of this reference space
158
+ Parameters
159
+ ----------
160
+ point1: 3D tuple defined in physical coordinates of this reference space
161
+ point2: 3D tuple defined in physical coordinates of this reference space
162
+ Returns
163
+ -------
164
+ BoundingBox
160
165
  """
161
166
  return BoundingBox(point1, point2, self)
@@ -13,19 +13,16 @@
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
15
 
16
- __all__ = ["cellular", "molecular", "fibres", "connectivity", "external"]
17
16
 
18
17
  from . import (
19
- cellular,
20
- molecular,
21
- fibres,
22
18
  connectivity,
23
- external
19
+ tabular,
20
+ image,
21
+ dataset,
24
22
  )
25
23
 
26
- from .basetypes.feature import Feature
27
- from .basetypes.cortical_profile import CorticalProfile
28
- from .basetypes.volume_of_interest import VolumeOfInterest
24
+
25
+ from .feature import Feature
29
26
  get = Feature.match
30
27
 
31
28
 
@@ -33,14 +30,17 @@ TYPES = Feature._get_subclasses()
33
30
 
34
31
 
35
32
  def __dir__():
36
- return [
37
- "cellular",
38
- "molecular",
39
- "fibres",
40
- "connectivity",
41
- "external",
42
- "Feature",
43
- "get",
44
- "CorticalProfile",
45
- "VolumeOfInterest"
46
- ]
33
+ return list(Feature.CATEGORIZED.keys())
34
+
35
+
36
+ def __getattr__(attr: str):
37
+ if attr in Feature.CATEGORIZED:
38
+ return Feature.CATEGORIZED[attr]
39
+ else:
40
+ hint = ""
41
+ if isinstance(attr, str):
42
+ import difflib
43
+ closest = difflib.get_close_matches(attr, list(__dir__()), n=3)
44
+ if len(closest) > 0:
45
+ hint = f"Did you mean {' or '.join(closest)}?"
46
+ raise AttributeError(f"No such attribute: {__name__}.{attr} " + hint)
siibra/features/anchor.py CHANGED
@@ -33,6 +33,7 @@ class AssignmentQualification(Enum):
33
33
  OVERLAPS = 2
34
34
  CONTAINED = 3
35
35
  CONTAINS = 4
36
+ APPROXIMATE = 5
36
37
 
37
38
  @property
38
39
  def verb(self):
@@ -45,6 +46,7 @@ class AssignmentQualification(Enum):
45
46
  'OVERLAPS': 'overlaps with',
46
47
  'CONTAINED': 'is contained in',
47
48
  'CONTAINS': 'contains',
49
+ 'APPROXIMATE': 'approximates to',
48
50
  }
49
51
  return transl[self.name]
50
52
 
@@ -57,6 +59,7 @@ class AssignmentQualification(Enum):
57
59
  "OVERLAPS": "OVERLAPS",
58
60
  "CONTAINED": "CONTAINS",
59
61
  "CONTAINS": "CONTAINED",
62
+ "APPROXIMATE": "APPROXIMATE",
60
63
  }
61
64
  return AssignmentQualification[inverses[self.name]]
62
65
 
@@ -144,11 +147,11 @@ class AnatomicalAnchor:
144
147
  return self._location_cached
145
148
 
146
149
  @property
147
- def parcellations(self):
150
+ def parcellations(self) -> List[Parcellation]:
148
151
  return list({region.root for region in self.regions})
149
152
 
150
153
  @property
151
- def space(self):
154
+ def space(self) -> Space:
152
155
  # may be overriden by derived classes, e.g. in features.VolumeOfInterest
153
156
  if self.location is None:
154
157
  return None
@@ -158,10 +161,10 @@ class AnatomicalAnchor:
158
161
  @property
159
162
  def region_aliases(self):
160
163
  if self._aliases_cached is None:
161
- self._aliases_cached = {
162
- k: v
164
+ self._aliases_cached: Dict[str, Dict[str, str]] = {
165
+ species_str: region_alias_mapping
163
166
  for s in self.species
164
- for k, v in REGION_ALIASES.get(str(s), {}).get(self._regionspec, {}).items()
167
+ for species_str, region_alias_mapping in REGION_ALIASES.get(str(s), {}).get(self._regionspec, {}).items()
165
168
  }
166
169
  return self._aliases_cached
167
170
 
@@ -192,7 +195,7 @@ class AnatomicalAnchor:
192
195
  for regionspec, qualificationspec in aliases.items():
193
196
  for r in Parcellation.find_regions(regionspec, alt_species):
194
197
  if r not in self._regions_cached:
195
- regions[r] = qualificationspec
198
+ regions[r] = AssignmentQualification[qualificationspec.upper()]
196
199
  self.__class__._MATCH_MEMO[self._regionspec] = regions
197
200
  self._regions_cached = self.__class__._MATCH_MEMO[self._regionspec]
198
201
 
@@ -16,11 +16,3 @@
16
16
  from .functional_connectivity import FunctionalConnectivity
17
17
  from .streamline_counts import StreamlineCounts
18
18
  from .streamline_lengths import StreamlineLengths
19
-
20
-
21
- def __dir__():
22
- return [
23
- "FunctionalConnectivity",
24
- "StreamlineCounts",
25
- "StreamlineLengths",
26
- ]
@@ -13,15 +13,23 @@
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
15
 
16
- from ..basetypes import regional_connectivity
17
-
16
+ from . import regional_connectivity
17
+ from hashlib import md5
18
18
 
19
19
  class FunctionalConnectivity(
20
20
  regional_connectivity.RegionalConnectivity,
21
- configuration_folder="features/connectivitymatrix/functional"
21
+ configuration_folder="features/connectivity/regional/functional",
22
+ category="connectivity"
22
23
  ):
23
24
  """Functional connectivity matrix grouped by a parcellation."""
24
25
 
25
26
  def __init__(self, paradigm: str, **kwargs):
26
27
  regional_connectivity.RegionalConnectivity.__init__(self, **kwargs)
27
28
  self.paradigm = paradigm
29
+
30
+ # paradign is used to distinguish functional connectivity features from each other.
31
+ assert self.paradigm, f"Functional connectivity must have paradigm defined!"
32
+
33
+ @property
34
+ def id(self):
35
+ return super().id + "--" + md5(self.paradigm.encode("utf-8")).hexdigest()
@@ -13,12 +13,12 @@
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
15
 
16
- from .feature import Feature
17
- from .tabular import Tabular
16
+ from ..feature import Feature
17
+ from ..tabular.tabular import Tabular
18
18
 
19
19
  from .. import anchor as _anchor
20
20
 
21
- from ...commons import logger, QUIET
21
+ from ...commons import logger, QUIET, siibra_tqdm
22
22
  from ...core import region as _region
23
23
  from ...locations import pointset
24
24
  from ...retrieval.repositories import RepositoryConnector
@@ -26,14 +26,12 @@ from ...retrieval.repositories import RepositoryConnector
26
26
  from typing import Callable, Dict, Union, List
27
27
  import pandas as pd
28
28
  import numpy as np
29
- from tqdm import tqdm
30
29
 
31
30
 
32
31
  class RegionalConnectivity(Feature):
33
32
  """
34
- Parcellation-averaged connectivity, providing one or more
35
- matrices of a given modality for a given parcellation.
36
-
33
+ Parcellation-averaged connectivity, providing one or more matrices of a
34
+ given modality for a given parcellation.
37
35
  """
38
36
 
39
37
  def __init__(
@@ -48,8 +46,8 @@ class RegionalConnectivity(Feature):
48
46
  description: str = "",
49
47
  datasets: list = [],
50
48
  ):
51
- """j
52
- Construct a parcellation-averaged connectivty matrix.
49
+ """
50
+ Construct a parcellation-averaged connectivity matrix.
53
51
 
54
52
  Parameters
55
53
  ----------
@@ -57,7 +55,7 @@ class RegionalConnectivity(Feature):
57
55
  Name of the cohort used for computing the connectivity.
58
56
  modality: str
59
57
  Connectivity modality, typically set by derived classes.
60
- regions: list of str
58
+ regions: list[str]
61
59
  Names of the regions from the parcellation
62
60
  connector: Connector
63
61
  Repository connector for loading the actual data array(s).
@@ -69,9 +67,9 @@ class RegionalConnectivity(Feature):
69
67
  anchor: AnatomicalAnchor
70
68
  anatomical localization of the matrix, expected to encode the parcellation
71
69
  in the region attribute.
72
- description: str (optional)
70
+ description: str, optional
73
71
  textual description of this connectivity matrix.
74
- datasets : list
72
+ datasets : list[Dataset]
75
73
  list of datasets corresponding to this feature.
76
74
  """
77
75
  Feature.__init__(
@@ -95,16 +93,24 @@ class RegionalConnectivity(Feature):
95
93
  """
96
94
  return list(self._files.keys())
97
95
 
96
+ @property
97
+ def name(self):
98
+ supername = super().name
99
+ return f"{supername} with cohort {self.cohort}"
100
+
98
101
  def get_matrix(self, subject: str = None):
99
102
  """
100
103
  Returns a matrix as a pandas dataframe.
101
104
 
102
105
  Parameters
103
106
  ----------
104
- subject: str
107
+ subject: str, default: None
105
108
  Name of the subject (see ConnectivityMatrix.subjects for available names).
106
- If "mean" or None is given, the mean is taken in case of multiple
107
- available matrices.
109
+ If None, the mean is taken in case of multiple available matrices.
110
+ Returns
111
+ -------
112
+ pd.DataFrame
113
+ A square matrix with region names as the column and row names.
108
114
  """
109
115
  assert len(self) > 0
110
116
  if (subject is None) and (len(self) > 1):
@@ -116,21 +122,21 @@ class RegionalConnectivity(Feature):
116
122
  if "mean" not in self._matrices:
117
123
  all_arrays = [
118
124
  self._connector.get(fname, decode_func=self._decode_func)
119
- for fname in tqdm(
125
+ for fname in siibra_tqdm(
120
126
  self._files.values(),
121
127
  total=len(self),
122
128
  desc=f"Averaging {len(self)} connectivity matrices"
123
129
  )
124
130
  ]
125
131
  self._matrices['mean'] = self._array_to_dataframe(np.stack(all_arrays).mean(0))
126
- return self._matrices['mean']
132
+ return self._matrices['mean'].copy()
127
133
  if subject is None:
128
134
  subject = next(iter(self._files.keys()))
129
135
  if subject not in self._files:
130
136
  raise ValueError(f"Subject name '{subject}' not known, use one of: {', '.join(self._files)}")
131
137
  if subject not in self._matrices:
132
138
  self._matrices[subject] = self._load_matrix(subject)
133
- return self._matrices[subject]
139
+ return self._matrices[subject].copy()
134
140
 
135
141
  def plot_matrix(self, subject: str = None, regions: List[str] = None, logscale: bool = False, **kwargs):
136
142
  """
@@ -181,9 +187,17 @@ class RegionalConnectivity(Feature):
181
187
  """
182
188
  Extract a regional profile from the matrix, to obtain a tabular data feature
183
189
  with the connectivity as the single column.
190
+
184
191
  Rows will be sorted by descending connection strength.
185
192
  Regions with connectivity smaller than "min_connectivity" will be discarded.
186
193
  If max_rows is given, only the subset of regions with highest connectivity is returned.
194
+
195
+ Parameters
196
+ ----------
197
+ region: str, Region
198
+ subject: str, default: None
199
+ min_connectivity: float, default: 0
200
+ max_rows: int, default: None
187
201
  """
188
202
  matrix = self.get_matrix(subject)
189
203
 
@@ -236,8 +250,15 @@ class RegionalConnectivity(Feature):
236
250
 
237
251
  def compute_centroids(self, space):
238
252
  """
239
- compute the list of centroid coordinates corresponding to
240
- matrix rows, in the given space.
253
+ Computes the list of centroid coordinates corresponding to
254
+ matrix rows, in the given reference space.
255
+
256
+ Parameters
257
+ ----------
258
+ space: Space, str
259
+ Returns
260
+ -------
261
+ list[tuple(float, float, float)]
241
262
  """
242
263
  result = []
243
264
  parcellations = self.anchor.represented_parcellations()
@@ -261,7 +282,7 @@ class RegionalConnectivity(Feature):
261
282
  def _array_to_dataframe(self, array: np.ndarray) -> pd.DataFrame:
262
283
  """
263
284
  Convert a numpy array with the connectivity matrix to
264
- a dataframe with regions as column and row headers.
285
+ a DataFrame with regions as column and row headers.
265
286
  """
266
287
  df = pd.DataFrame(array)
267
288
  parcellations = self.anchor.represented_parcellations()
@@ -273,23 +294,15 @@ class RegionalConnectivity(Feature):
273
294
  for i, regionname in enumerate(self.regions)
274
295
  }
275
296
  nrows = array.shape[0]
276
- if len(indexmap) == nrows:
297
+ try:
298
+ assert len(indexmap) == nrows
277
299
  remapper = {
278
300
  label - min(indexmap.keys()): region
279
301
  for label, region in indexmap.items()
280
302
  }
281
303
  df = df.rename(index=remapper).rename(columns=remapper)
282
- else:
283
- labels = {r.index.label for r in parc.regiontree} - {None}
284
- if max(labels) - min(labels) + 1 == nrows:
285
- indexmap = {
286
- r.index.label - min(labels): r
287
- for r in parc.regiontree
288
- if r.index.label is not None
289
- }
290
- df = df.rename(index=indexmap).rename(columns=indexmap)
291
- else:
292
- logger.warn("Could not decode connectivity matrix regions.")
304
+ except:
305
+ raise RuntimeError("Could not decode connectivity matrix regions.")
293
306
  return df
294
307
 
295
308
  def _load_matrix(self, subject: str):
@@ -13,12 +13,13 @@
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
15
 
16
- from ..basetypes import regional_connectivity
16
+ from . import regional_connectivity
17
17
 
18
18
 
19
19
  class StreamlineCounts(
20
20
  regional_connectivity.RegionalConnectivity,
21
- configuration_folder="features/connectivitymatrix/streamlinecounts"
21
+ configuration_folder="features/connectivity/regional/streamlinecounts",
22
+ category="connectivity"
22
23
  ):
23
24
  """Structural connectivity matrix of streamline counts grouped by a parcellation."""
24
25
 
@@ -13,12 +13,13 @@
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
15
 
16
- from ..basetypes import regional_connectivity
16
+ from . import regional_connectivity
17
17
 
18
18
 
19
19
  class StreamlineLengths(
20
20
  regional_connectivity.RegionalConnectivity,
21
- configuration_folder="features/connectivitymatrix/streamlinelengths"
21
+ configuration_folder="features/connectivity/regional/streamlinelengths",
22
+ category="connectivity"
22
23
  ):
23
24
  """Structural connectivity matrix of streamline lengths grouped by a parcellation."""
24
25
 
@@ -12,3 +12,5 @@
12
12
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
+
16
+ from .ebrains import EbrainsDataFeature
@@ -16,12 +16,12 @@
16
16
  # simple data features anchored to a point in space
17
17
 
18
18
  from .. import anchor as _anchor
19
- from ..basetypes import feature
19
+ from .. import feature
20
20
 
21
21
  from ...retrieval import datasets
22
22
 
23
23
 
24
- class EbrainsDataFeature(feature.Feature, datasets.EbrainsDataset):
24
+ class EbrainsDataFeature(feature.Feature, datasets.EbrainsDataset, category='other'):
25
25
 
26
26
  def __init__(
27
27
  self,
@@ -64,7 +64,7 @@ class EbrainsDataFeature(feature.Feature, datasets.EbrainsDataset):
64
64
 
65
65
  @property
66
66
  def name(self):
67
- return self._name_cached
67
+ return self._name
68
68
 
69
69
  @property
70
70
  def version_history(self):