siibra 0.4a35__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.
- siibra/VERSION +1 -1
- siibra/__init__.py +1 -0
- siibra/commons.py +38 -17
- siibra/configuration/configuration.py +21 -17
- siibra/configuration/factory.py +38 -12
- siibra/core/atlas.py +11 -8
- siibra/core/concept.py +22 -2
- siibra/core/parcellation.py +42 -22
- siibra/core/region.py +56 -95
- siibra/features/anchor.py +7 -4
- siibra/features/connectivity/functional_connectivity.py +8 -1
- siibra/features/connectivity/regional_connectivity.py +14 -19
- siibra/features/dataset/ebrains.py +1 -1
- siibra/features/feature.py +193 -29
- siibra/features/image/__init__.py +1 -1
- siibra/features/image/image.py +1 -0
- siibra/features/image/volume_of_interest.py +14 -5
- siibra/features/tabular/__init__.py +2 -0
- siibra/features/tabular/regional_timeseries_activity.py +213 -0
- siibra/livequeries/ebrains.py +2 -3
- siibra/locations/location.py +4 -3
- siibra/locations/pointset.py +2 -2
- siibra/retrieval/datasets.py +73 -3
- siibra/retrieval/repositories.py +17 -6
- siibra/retrieval/requests.py +68 -61
- siibra/volumes/neuroglancer.py +9 -9
- siibra/volumes/nifti.py +4 -5
- siibra/volumes/parcellationmap.py +157 -97
- siibra/volumes/sparsemap.py +27 -31
- siibra/volumes/volume.py +1 -1
- {siibra-0.4a35.dist-info → siibra-0.4a46.dist-info}/METADATA +2 -1
- {siibra-0.4a35.dist-info → siibra-0.4a46.dist-info}/RECORD +35 -34
- {siibra-0.4a35.dist-info → siibra-0.4a46.dist-info}/WHEEL +1 -1
- {siibra-0.4a35.dist-info → siibra-0.4a46.dist-info}/LICENSE +0 -0
- {siibra-0.4a35.dist-info → siibra-0.4a46.dist-info}/top_level.txt +0 -0
siibra/core/region.py
CHANGED
|
@@ -20,11 +20,11 @@ from ..volumes import parcellationmap
|
|
|
20
20
|
|
|
21
21
|
from ..commons import (
|
|
22
22
|
logger,
|
|
23
|
-
MapIndex,
|
|
24
23
|
MapType,
|
|
25
24
|
affine_scaling,
|
|
26
25
|
create_key,
|
|
27
26
|
clear_name,
|
|
27
|
+
siibra_tqdm,
|
|
28
28
|
InstanceTable,
|
|
29
29
|
SIIBRA_DEFAULT_MAPTYPE,
|
|
30
30
|
SIIBRA_DEFAULT_MAP_THRESHOLD
|
|
@@ -36,12 +36,25 @@ import anytree
|
|
|
36
36
|
from typing import List, Set, Union
|
|
37
37
|
from nibabel import Nifti1Image
|
|
38
38
|
from difflib import SequenceMatcher
|
|
39
|
+
from dataclasses import dataclass, field
|
|
39
40
|
|
|
40
41
|
|
|
41
42
|
REGEX_TYPE = type(re.compile("test"))
|
|
42
43
|
|
|
43
44
|
THRESHOLD_STATISTICAL_MAPS = None
|
|
44
45
|
|
|
46
|
+
@dataclass
|
|
47
|
+
class SpatialPropCmpt:
|
|
48
|
+
centroid: point.Point
|
|
49
|
+
volume: int
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
@dataclass
|
|
53
|
+
class SpatialProp:
|
|
54
|
+
cog:SpatialPropCmpt=None
|
|
55
|
+
components:List[SpatialPropCmpt]=field(default_factory=list)
|
|
56
|
+
space:_space.Space=None
|
|
57
|
+
|
|
45
58
|
|
|
46
59
|
class Region(anytree.NodeMixin, concept.AtlasConcept):
|
|
47
60
|
"""
|
|
@@ -153,13 +166,9 @@ class Region(anytree.NodeMixin, concept.AtlasConcept):
|
|
|
153
166
|
c.parent = region
|
|
154
167
|
return region
|
|
155
168
|
|
|
156
|
-
@property
|
|
157
|
-
def labels(self):
|
|
158
|
-
return {r.index.label for r in self if r.index.label is not None} # Potenially a BUG
|
|
159
|
-
|
|
160
169
|
@property
|
|
161
170
|
def names(self):
|
|
162
|
-
return {r.
|
|
171
|
+
return {r.name for r in self}
|
|
163
172
|
|
|
164
173
|
def __eq__(self, other):
|
|
165
174
|
"""
|
|
@@ -171,9 +180,7 @@ class Region(anytree.NodeMixin, concept.AtlasConcept):
|
|
|
171
180
|
elif isinstance(other, str):
|
|
172
181
|
return any([self.name == other, self.key == other, self.id == other])
|
|
173
182
|
else:
|
|
174
|
-
|
|
175
|
-
f"Cannot compare object of type {type(other)} to {self.__class__.__name__}"
|
|
176
|
-
)
|
|
183
|
+
return False
|
|
177
184
|
|
|
178
185
|
def __hash__(self):
|
|
179
186
|
return hash(self.id)
|
|
@@ -207,25 +214,24 @@ class Region(anytree.NodeMixin, concept.AtlasConcept):
|
|
|
207
214
|
|
|
208
215
|
Parameters
|
|
209
216
|
----------
|
|
210
|
-
regionspec: str, regex, int, Region
|
|
217
|
+
regionspec: str, regex, int, Region
|
|
211
218
|
- a string with a possibly inexact name (matched both against the name and the identifier key)
|
|
212
219
|
- a string in '/pattern/flags' format to use regex search (acceptable flags: aiLmsux)
|
|
213
220
|
- a regex applied to region names
|
|
214
|
-
- an integer (interpreted as a labelindex)
|
|
215
221
|
- a Region object
|
|
216
|
-
- a full MapIndex object
|
|
217
222
|
filter_children : bool, default: False
|
|
218
223
|
If True, children of matched parents will not be returned
|
|
219
224
|
find_topmost : bool, default: True
|
|
220
|
-
If True, will return parent
|
|
221
|
-
|
|
225
|
+
If True (requires `filter_children=True`), will return parent
|
|
226
|
+
structures if all children are matched, even though the parent
|
|
227
|
+
itself might not match the specification.
|
|
222
228
|
Returns
|
|
223
229
|
-------
|
|
224
230
|
list[Region]
|
|
225
231
|
list of regions matching to the regionspec
|
|
226
232
|
Tip
|
|
227
233
|
---
|
|
228
|
-
See example 01-003 find regions
|
|
234
|
+
See example 01-003, find regions.
|
|
229
235
|
"""
|
|
230
236
|
key = (regionspec, filter_children, find_topmost)
|
|
231
237
|
MEM = self._CACHED_REGION_SEARCHES
|
|
@@ -244,40 +250,19 @@ class Region(anytree.NodeMixin, concept.AtlasConcept):
|
|
|
244
250
|
search_regex = (f"(?{flags})" if flags else "") + expression
|
|
245
251
|
regionspec = re.compile(search_regex)
|
|
246
252
|
|
|
247
|
-
if regionspec in self.names:
|
|
248
|
-
# key is given, this gives us an exact region
|
|
249
|
-
match = anytree.search.find_by_attr(self, regionspec, name="key")
|
|
250
|
-
MEM[key] = [] if match is None else [match]
|
|
251
|
-
return list(MEM[key])
|
|
252
|
-
|
|
253
253
|
candidates = list(
|
|
254
|
-
|
|
254
|
+
anytree.search.findall(self, lambda node: node.matches(regionspec))
|
|
255
255
|
)
|
|
256
256
|
|
|
257
257
|
if len(candidates) > 1 and filter_children:
|
|
258
|
-
|
|
259
258
|
filtered = []
|
|
260
259
|
for region in candidates:
|
|
261
260
|
children_included = [c for c in region.children if c in candidates]
|
|
262
|
-
# if the parcellation index matches only approximately,
|
|
263
|
-
# while a child has an exact matching index, use the child.
|
|
264
261
|
if len(children_included) > 0:
|
|
265
|
-
|
|
266
|
-
isinstance(regionspec, MapIndex)
|
|
267
|
-
and (region.index != regionspec)
|
|
268
|
-
and any(c.index == regionspec for c in children_included)
|
|
269
|
-
):
|
|
270
|
-
filtered.append(region)
|
|
262
|
+
filtered.append(region)
|
|
271
263
|
else:
|
|
272
264
|
if region.parent not in candidates:
|
|
273
265
|
filtered.append(region)
|
|
274
|
-
else:
|
|
275
|
-
if (
|
|
276
|
-
isinstance(regionspec, MapIndex)
|
|
277
|
-
and (region.index == regionspec)
|
|
278
|
-
and (region.parent.index != regionspec)
|
|
279
|
-
):
|
|
280
|
-
filtered.append(region)
|
|
281
266
|
|
|
282
267
|
# find any non-matched regions of which all children are matched
|
|
283
268
|
if find_topmost:
|
|
@@ -295,7 +280,10 @@ class Region(anytree.NodeMixin, concept.AtlasConcept):
|
|
|
295
280
|
else:
|
|
296
281
|
# filter child regions again
|
|
297
282
|
filtered += complete_parents
|
|
298
|
-
candidates = [
|
|
283
|
+
candidates = [
|
|
284
|
+
r for r in filtered
|
|
285
|
+
if (r.parent not in filtered) or r == regionspec
|
|
286
|
+
]
|
|
299
287
|
else:
|
|
300
288
|
candidates = filtered
|
|
301
289
|
|
|
@@ -307,12 +295,12 @@ class Region(anytree.NodeMixin, concept.AtlasConcept):
|
|
|
307
295
|
else:
|
|
308
296
|
candidates = list(candidates)
|
|
309
297
|
|
|
310
|
-
found_regions = sorted(candidates, key=lambda r: r.depth)
|
|
298
|
+
found_regions = sorted(set(candidates), key=lambda r: r.depth)
|
|
311
299
|
|
|
312
300
|
# reverse is set to True, since SequenceMatcher().ratio(), higher == better
|
|
313
301
|
MEM[key] = (
|
|
314
302
|
sorted(
|
|
315
|
-
|
|
303
|
+
found_regions,
|
|
316
304
|
reverse=True,
|
|
317
305
|
key=lambda region: SequenceMatcher(None, str(region), regionspec).ratio(),
|
|
318
306
|
)
|
|
@@ -429,14 +417,12 @@ class Region(anytree.NodeMixin, concept.AtlasConcept):
|
|
|
429
417
|
fetch_space = _space.Space.get_instance(fetch_space)
|
|
430
418
|
|
|
431
419
|
for m in parcellationmap.Map.registry():
|
|
432
|
-
if
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
self.name in m.regions
|
|
439
|
-
]
|
|
420
|
+
if (
|
|
421
|
+
m.space.matches(fetch_space) and
|
|
422
|
+
m.parcellation == self.parcellation and
|
|
423
|
+
m.provides_image and
|
|
424
|
+
m.maptype == maptype and
|
|
425
|
+
self.name in m.regions
|
|
440
426
|
):
|
|
441
427
|
result = m.fetch(region=self, format='image')
|
|
442
428
|
if (maptype == MapType.STATISTICAL) and (threshold is not None):
|
|
@@ -451,7 +437,12 @@ class Region(anytree.NodeMixin, concept.AtlasConcept):
|
|
|
451
437
|
dataobj = None
|
|
452
438
|
affine = None
|
|
453
439
|
if all(c.mapped_in_space(fetch_space) for c in self.children):
|
|
454
|
-
for c in
|
|
440
|
+
for c in siibra_tqdm(
|
|
441
|
+
self.children,
|
|
442
|
+
desc=f"Building mask of {self.name}",
|
|
443
|
+
leave=False,
|
|
444
|
+
unit=" child region"
|
|
445
|
+
):
|
|
455
446
|
mask = c.fetch_regional_map(fetch_space, maptype, threshold)
|
|
456
447
|
if dataobj is None:
|
|
457
448
|
dataobj = np.asanyarray(mask.dataobj)
|
|
@@ -536,41 +527,6 @@ class Region(anytree.NodeMixin, concept.AtlasConcept):
|
|
|
536
527
|
elements={s.key: s for s in self.supported_spaces},
|
|
537
528
|
)
|
|
538
529
|
|
|
539
|
-
def __getitem__(self, labelindex):
|
|
540
|
-
"""
|
|
541
|
-
Given an integer label index, return the corresponding region.
|
|
542
|
-
|
|
543
|
-
If multiple matches are found, return the unique parent if possible.
|
|
544
|
-
Otherwise, returns None.
|
|
545
|
-
|
|
546
|
-
Parameters
|
|
547
|
-
----------
|
|
548
|
-
regionlabel: int
|
|
549
|
-
Label index of the desired region.
|
|
550
|
-
Returns
|
|
551
|
-
-------
|
|
552
|
-
Region
|
|
553
|
-
"""
|
|
554
|
-
if not isinstance(labelindex, int):
|
|
555
|
-
raise TypeError(
|
|
556
|
-
"Index access into the regiontree expects label indices of integer type"
|
|
557
|
-
)
|
|
558
|
-
|
|
559
|
-
# first test this head node
|
|
560
|
-
if self.index.label == labelindex:
|
|
561
|
-
return self
|
|
562
|
-
|
|
563
|
-
# Consider children, and return the one with smallest depth
|
|
564
|
-
matches = list(
|
|
565
|
-
filter(lambda x: x is not None, [c[labelindex] for c in self.children])
|
|
566
|
-
)
|
|
567
|
-
if matches:
|
|
568
|
-
parentmatches = [m for m in matches if m.parent not in matches]
|
|
569
|
-
if len(parentmatches) == 1:
|
|
570
|
-
return parentmatches[0]
|
|
571
|
-
|
|
572
|
-
return None
|
|
573
|
-
|
|
574
530
|
def __str__(self):
|
|
575
531
|
return self.name
|
|
576
532
|
|
|
@@ -626,7 +582,7 @@ class Region(anytree.NodeMixin, concept.AtlasConcept):
|
|
|
626
582
|
maptype=maptype,
|
|
627
583
|
threshold=threshold_statistical,
|
|
628
584
|
)
|
|
629
|
-
logger.
|
|
585
|
+
logger.warning(
|
|
630
586
|
f"No bounding box for {self.name} defined in {spaceobj.name}, "
|
|
631
587
|
f"will warp the bounding box from {other_space.name} instead."
|
|
632
588
|
)
|
|
@@ -657,7 +613,7 @@ class Region(anytree.NodeMixin, concept.AtlasConcept):
|
|
|
657
613
|
"""
|
|
658
614
|
props = self.spatial_props(space)
|
|
659
615
|
return pointset.PointSet(
|
|
660
|
-
[
|
|
616
|
+
[c.centroid for c in props.components],
|
|
661
617
|
space=space
|
|
662
618
|
)
|
|
663
619
|
|
|
@@ -666,7 +622,7 @@ class Region(anytree.NodeMixin, concept.AtlasConcept):
|
|
|
666
622
|
space: _space.Space,
|
|
667
623
|
maptype: MapType = MapType.LABELLED,
|
|
668
624
|
threshold_statistical=None,
|
|
669
|
-
):
|
|
625
|
+
) -> SpatialProp:
|
|
670
626
|
"""
|
|
671
627
|
Compute spatial properties for connected components of this region in the given space.
|
|
672
628
|
|
|
@@ -687,14 +643,15 @@ class Region(anytree.NodeMixin, concept.AtlasConcept):
|
|
|
687
643
|
Dict
|
|
688
644
|
Dictionary of region's spatial properties
|
|
689
645
|
"""
|
|
690
|
-
result = {"space": space, "components": []}
|
|
691
646
|
from skimage import measure
|
|
692
647
|
|
|
693
648
|
if not isinstance(space, _space.Space):
|
|
694
649
|
space = _space.Space.get_instance(space)
|
|
695
650
|
|
|
651
|
+
result = SpatialProp(space=space)
|
|
652
|
+
|
|
696
653
|
if not self.mapped_in_space(space):
|
|
697
|
-
logger.
|
|
654
|
+
logger.warning(
|
|
698
655
|
f"Spatial properties of {self.name} cannot be computed in {space.name}. "
|
|
699
656
|
"This region is only mapped in these spaces: "
|
|
700
657
|
f"{', '.join(s.name for s in self.supported_spaces)}"
|
|
@@ -715,14 +672,18 @@ class Region(anytree.NodeMixin, concept.AtlasConcept):
|
|
|
715
672
|
|
|
716
673
|
# compute spatial properties of each connected component
|
|
717
674
|
for label in range(1, C.max() + 1):
|
|
718
|
-
props = {}
|
|
719
675
|
nonzero = np.c_[np.nonzero(C == label)]
|
|
720
|
-
|
|
721
|
-
|
|
676
|
+
result.components.append(
|
|
677
|
+
SpatialPropCmpt(
|
|
678
|
+
centroid=point.Point(
|
|
679
|
+
np.dot(pimg.affine, np.r_[nonzero.mean(0), 1])[:3], space=space
|
|
680
|
+
),
|
|
681
|
+
volume=nonzero.shape[0] * scale,
|
|
682
|
+
)
|
|
722
683
|
)
|
|
723
|
-
props["volume"] = nonzero.shape[0] * scale
|
|
724
684
|
|
|
725
|
-
|
|
685
|
+
# sort by volume
|
|
686
|
+
result.components.sort(key=lambda cmp: cmp.volume, reverse=True)
|
|
726
687
|
|
|
727
688
|
return result
|
|
728
689
|
|
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
|
|
|
@@ -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
|
-
|
|
164
|
+
self._aliases_cached: Dict[str, Dict[str, str]] = {
|
|
165
|
+
species_str: region_alias_mapping
|
|
163
166
|
for s in self.species
|
|
164
|
-
for
|
|
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
|
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
# limitations under the License.
|
|
15
15
|
|
|
16
16
|
from . import regional_connectivity
|
|
17
|
-
|
|
17
|
+
from hashlib import md5
|
|
18
18
|
|
|
19
19
|
class FunctionalConnectivity(
|
|
20
20
|
regional_connectivity.RegionalConnectivity,
|
|
@@ -26,3 +26,10 @@ class FunctionalConnectivity(
|
|
|
26
26
|
def __init__(self, paradigm: str, **kwargs):
|
|
27
27
|
regional_connectivity.RegionalConnectivity.__init__(self, **kwargs)
|
|
28
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()
|
|
@@ -18,7 +18,7 @@ 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,7 +26,6 @@ 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):
|
|
@@ -94,6 +93,11 @@ class RegionalConnectivity(Feature):
|
|
|
94
93
|
"""
|
|
95
94
|
return list(self._files.keys())
|
|
96
95
|
|
|
96
|
+
@property
|
|
97
|
+
def name(self):
|
|
98
|
+
supername = super().name
|
|
99
|
+
return f"{supername} with cohort {self.cohort}"
|
|
100
|
+
|
|
97
101
|
def get_matrix(self, subject: str = None):
|
|
98
102
|
"""
|
|
99
103
|
Returns a matrix as a pandas dataframe.
|
|
@@ -102,8 +106,7 @@ class RegionalConnectivity(Feature):
|
|
|
102
106
|
----------
|
|
103
107
|
subject: str, default: None
|
|
104
108
|
Name of the subject (see ConnectivityMatrix.subjects for available names).
|
|
105
|
-
If
|
|
106
|
-
available matrices.
|
|
109
|
+
If None, the mean is taken in case of multiple available matrices.
|
|
107
110
|
Returns
|
|
108
111
|
-------
|
|
109
112
|
pd.DataFrame
|
|
@@ -119,21 +122,21 @@ class RegionalConnectivity(Feature):
|
|
|
119
122
|
if "mean" not in self._matrices:
|
|
120
123
|
all_arrays = [
|
|
121
124
|
self._connector.get(fname, decode_func=self._decode_func)
|
|
122
|
-
for fname in
|
|
125
|
+
for fname in siibra_tqdm(
|
|
123
126
|
self._files.values(),
|
|
124
127
|
total=len(self),
|
|
125
128
|
desc=f"Averaging {len(self)} connectivity matrices"
|
|
126
129
|
)
|
|
127
130
|
]
|
|
128
131
|
self._matrices['mean'] = self._array_to_dataframe(np.stack(all_arrays).mean(0))
|
|
129
|
-
return self._matrices['mean']
|
|
132
|
+
return self._matrices['mean'].copy()
|
|
130
133
|
if subject is None:
|
|
131
134
|
subject = next(iter(self._files.keys()))
|
|
132
135
|
if subject not in self._files:
|
|
133
136
|
raise ValueError(f"Subject name '{subject}' not known, use one of: {', '.join(self._files)}")
|
|
134
137
|
if subject not in self._matrices:
|
|
135
138
|
self._matrices[subject] = self._load_matrix(subject)
|
|
136
|
-
return self._matrices[subject]
|
|
139
|
+
return self._matrices[subject].copy()
|
|
137
140
|
|
|
138
141
|
def plot_matrix(self, subject: str = None, regions: List[str] = None, logscale: bool = False, **kwargs):
|
|
139
142
|
"""
|
|
@@ -291,23 +294,15 @@ class RegionalConnectivity(Feature):
|
|
|
291
294
|
for i, regionname in enumerate(self.regions)
|
|
292
295
|
}
|
|
293
296
|
nrows = array.shape[0]
|
|
294
|
-
|
|
297
|
+
try:
|
|
298
|
+
assert len(indexmap) == nrows
|
|
295
299
|
remapper = {
|
|
296
300
|
label - min(indexmap.keys()): region
|
|
297
301
|
for label, region in indexmap.items()
|
|
298
302
|
}
|
|
299
303
|
df = df.rename(index=remapper).rename(columns=remapper)
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
if max(labels) - min(labels) + 1 == nrows:
|
|
303
|
-
indexmap = {
|
|
304
|
-
r.index.label - min(labels): r
|
|
305
|
-
for r in parc.regiontree
|
|
306
|
-
if r.index.label is not None
|
|
307
|
-
}
|
|
308
|
-
df = df.rename(index=indexmap).rename(columns=indexmap)
|
|
309
|
-
else:
|
|
310
|
-
logger.warn("Could not decode connectivity matrix regions.")
|
|
304
|
+
except:
|
|
305
|
+
raise RuntimeError("Could not decode connectivity matrix regions.")
|
|
311
306
|
return df
|
|
312
307
|
|
|
313
308
|
def _load_matrix(self, subject: str):
|
|
@@ -21,7 +21,7 @@ from .. import feature
|
|
|
21
21
|
from ...retrieval import datasets
|
|
22
22
|
|
|
23
23
|
|
|
24
|
-
class EbrainsDataFeature(feature.Feature, datasets.EbrainsDataset, category='
|
|
24
|
+
class EbrainsDataFeature(feature.Feature, datasets.EbrainsDataset, category='other'):
|
|
25
25
|
|
|
26
26
|
def __init__(
|
|
27
27
|
self,
|