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.
- siibra/VERSION +1 -1
- siibra/__init__.py +2 -0
- siibra/commons.py +53 -8
- siibra/configuration/configuration.py +21 -17
- siibra/configuration/factory.py +95 -19
- siibra/core/atlas.py +11 -8
- siibra/core/concept.py +41 -8
- siibra/core/parcellation.py +94 -43
- siibra/core/region.py +160 -187
- siibra/core/space.py +44 -39
- siibra/features/__init__.py +19 -19
- siibra/features/anchor.py +9 -6
- siibra/features/connectivity/__init__.py +0 -8
- siibra/features/connectivity/functional_connectivity.py +11 -3
- siibra/features/{basetypes → connectivity}/regional_connectivity.py +46 -33
- siibra/features/connectivity/streamline_counts.py +3 -2
- siibra/features/connectivity/streamline_lengths.py +3 -2
- siibra/features/{basetypes → dataset}/__init__.py +2 -0
- siibra/features/{external → dataset}/ebrains.py +3 -3
- siibra/features/feature.py +420 -0
- siibra/{samplers → features/image}/__init__.py +7 -1
- siibra/features/{basetypes/volume_of_interest.py → image/image.py} +12 -7
- siibra/features/{external/__init__.py → image/sections.py} +8 -5
- siibra/features/image/volume_of_interest.py +70 -0
- siibra/features/{cellular → tabular}/__init__.py +7 -11
- siibra/features/{cellular → tabular}/bigbrain_intensity_profile.py +5 -2
- siibra/features/{cellular → tabular}/cell_density_profile.py +6 -2
- siibra/features/{basetypes → tabular}/cortical_profile.py +48 -41
- siibra/features/{molecular → tabular}/gene_expression.py +5 -2
- siibra/features/{cellular → tabular}/layerwise_bigbrain_intensities.py +6 -2
- siibra/features/{cellular → tabular}/layerwise_cell_density.py +9 -3
- siibra/features/{molecular → tabular}/receptor_density_fingerprint.py +3 -2
- siibra/features/{molecular → tabular}/receptor_density_profile.py +6 -2
- siibra/features/tabular/regional_timeseries_activity.py +213 -0
- siibra/features/{basetypes → tabular}/tabular.py +14 -9
- siibra/livequeries/allen.py +1 -1
- siibra/livequeries/bigbrain.py +2 -3
- siibra/livequeries/ebrains.py +3 -9
- siibra/livequeries/query.py +1 -1
- siibra/locations/location.py +4 -3
- siibra/locations/point.py +21 -17
- siibra/locations/pointset.py +2 -2
- siibra/retrieval/__init__.py +1 -1
- siibra/retrieval/cache.py +8 -2
- siibra/retrieval/datasets.py +149 -29
- siibra/retrieval/repositories.py +19 -8
- siibra/retrieval/requests.py +98 -116
- siibra/volumes/gifti.py +26 -11
- siibra/volumes/neuroglancer.py +35 -19
- siibra/volumes/nifti.py +8 -9
- siibra/volumes/parcellationmap.py +341 -184
- siibra/volumes/sparsemap.py +67 -53
- siibra/volumes/volume.py +25 -13
- {siibra-0.4a33.dist-info → siibra-0.4a46.dist-info}/METADATA +4 -3
- siibra-0.4a46.dist-info/RECORD +69 -0
- {siibra-0.4a33.dist-info → siibra-0.4a46.dist-info}/WHEEL +1 -1
- siibra/features/basetypes/feature.py +0 -248
- siibra/features/fibres/__init__.py +0 -14
- siibra/features/functional/__init__.py +0 -14
- siibra/features/molecular/__init__.py +0 -26
- siibra/samplers/bigbrain.py +0 -181
- siibra-0.4a33.dist-info/RECORD +0 -71
- {siibra-0.4a33.dist-info → siibra-0.4a46.dist-info}/LICENSE +0 -0
- {siibra-0.4a33.dist-info → siibra-0.4a46.dist-info}/top_level.txt +0 -0
siibra/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.
|
|
1
|
+
0.4a46
|
siibra/__init__.py
CHANGED
|
@@ -119,6 +119,7 @@ def __dir__():
|
|
|
119
119
|
"use_configuration",
|
|
120
120
|
"extend_configuration",
|
|
121
121
|
"get_region",
|
|
122
|
+
"find_regions",
|
|
122
123
|
"get_map",
|
|
123
124
|
"get_template",
|
|
124
125
|
"MapType",
|
|
@@ -130,4 +131,5 @@ def __dir__():
|
|
|
130
131
|
"set_ebrains_token",
|
|
131
132
|
"vocabularies",
|
|
132
133
|
"__version__",
|
|
134
|
+
"cache",
|
|
133
135
|
]
|
siibra/commons.py
CHANGED
|
@@ -18,9 +18,11 @@ import re
|
|
|
18
18
|
from enum import Enum
|
|
19
19
|
from nibabel import Nifti1Image
|
|
20
20
|
import logging
|
|
21
|
+
from tqdm import tqdm
|
|
21
22
|
import numpy as np
|
|
22
23
|
from typing import Generic, Iterable, Iterator, List, TypeVar, Union, Dict
|
|
23
24
|
from skimage.filters import gaussian
|
|
25
|
+
from dataclasses import dataclass
|
|
24
26
|
|
|
25
27
|
logger = logging.getLogger(__name__.split(os.path.extsep)[0])
|
|
26
28
|
ch = logging.StreamHandler()
|
|
@@ -36,9 +38,20 @@ KEYCLOAK_CLIENT_SECRET = os.getenv("KEYCLOAK_CLIENT_SECRET")
|
|
|
36
38
|
SIIBRA_CACHEDIR = os.getenv("SIIBRA_CACHEDIR")
|
|
37
39
|
SIIBRA_LOG_LEVEL = os.getenv("SIIBRA_LOG_LEVEL", "INFO")
|
|
38
40
|
SIIBRA_USE_CONFIGURATION = os.getenv("SIIBRA_USE_CONFIGURATION")
|
|
41
|
+
|
|
42
|
+
SIIBRA_USE_LOCAL_SNAPSPOT = os.getenv("SIIBRA_USE_LOCAL_SNAPSPOT")
|
|
43
|
+
|
|
39
44
|
with open(os.path.join(ROOT_DIR, "VERSION"), "r") as fp:
|
|
40
45
|
__version__ = fp.read().strip()
|
|
41
46
|
|
|
47
|
+
@dataclass
|
|
48
|
+
class CompareMapsResult:
|
|
49
|
+
intersection_over_union: float
|
|
50
|
+
intersection_over_first: float
|
|
51
|
+
intersection_over_second: float
|
|
52
|
+
correlation: float
|
|
53
|
+
weighted_mean_of_first: float
|
|
54
|
+
weighted_mean_of_second: float
|
|
42
55
|
|
|
43
56
|
T = TypeVar("T")
|
|
44
57
|
|
|
@@ -233,6 +246,15 @@ QUIET = LoggingContext("ERROR")
|
|
|
233
246
|
VERBOSE = LoggingContext("DEBUG")
|
|
234
247
|
|
|
235
248
|
|
|
249
|
+
def siibra_tqdm(iterable: Iterable[T]=None, *args, **kwargs):
|
|
250
|
+
return tqdm(
|
|
251
|
+
iterable,
|
|
252
|
+
*args,
|
|
253
|
+
disable=kwargs.pop("disable", False) or (logger.level > 20),
|
|
254
|
+
**kwargs
|
|
255
|
+
)
|
|
256
|
+
|
|
257
|
+
|
|
236
258
|
def create_key(name: str):
|
|
237
259
|
"""
|
|
238
260
|
Creates an uppercase identifier string that includes only alphanumeric
|
|
@@ -350,6 +372,21 @@ def affine_scaling(affine):
|
|
|
350
372
|
return np.prod(unit_lengths)
|
|
351
373
|
|
|
352
374
|
|
|
375
|
+
def iterate_connected_components(img: Nifti1Image):
|
|
376
|
+
"""
|
|
377
|
+
Provide an iterator over masks of connected components in the given image.
|
|
378
|
+
"""
|
|
379
|
+
from skimage import measure
|
|
380
|
+
imgdata = np.asanyarray(img.dataobj).squeeze()
|
|
381
|
+
components = measure.label(imgdata > 0)
|
|
382
|
+
component_labels = np.unique(components)
|
|
383
|
+
assert component_labels[0] == 0
|
|
384
|
+
return (
|
|
385
|
+
(label, Nifti1Image((components == label).astype('uint8'), img.affine))
|
|
386
|
+
for label in component_labels[1:]
|
|
387
|
+
)
|
|
388
|
+
|
|
389
|
+
|
|
353
390
|
def compare_maps(map1: Nifti1Image, map2: Nifti1Image):
|
|
354
391
|
"""
|
|
355
392
|
Compare two maps, given as Nifti1Image objects.
|
|
@@ -396,7 +433,14 @@ def compare_maps(map1: Nifti1Image, map2: Nifti1Image):
|
|
|
396
433
|
m1, m2 = ((_ > 0).astype("uint8") for _ in [v1, v2])
|
|
397
434
|
intersection = np.minimum(m1, m2).sum()
|
|
398
435
|
if intersection == 0:
|
|
399
|
-
return
|
|
436
|
+
return CompareMapsResult(
|
|
437
|
+
intersection_over_union=0,
|
|
438
|
+
intersection_over_first=0,
|
|
439
|
+
intersection_over_second=0,
|
|
440
|
+
correlation=0,
|
|
441
|
+
weighted_mean_of_first=0,
|
|
442
|
+
weighted_mean_of_second=0,
|
|
443
|
+
)
|
|
400
444
|
|
|
401
445
|
# Compute the nonzero voxels in map1 with their correspondences in map2
|
|
402
446
|
XYZnz1 = nonzero_coordinates(a1)
|
|
@@ -430,13 +474,14 @@ def compare_maps(map1: Nifti1Image, map2: Nifti1Image):
|
|
|
430
474
|
|
|
431
475
|
bx = (x > 0).astype("uint8")
|
|
432
476
|
by = (y > 0).astype("uint8")
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
477
|
+
return CompareMapsResult(
|
|
478
|
+
intersection_over_union=intersection / np.maximum(bx, by).sum(),
|
|
479
|
+
intersection_over_first=intersection / N1,
|
|
480
|
+
intersection_over_second=intersection / N2,
|
|
481
|
+
correlation=r,
|
|
482
|
+
weighted_mean_of_first=np.sum(x * y) / np.sum(y),
|
|
483
|
+
weighted_mean_of_second=np.sum(x * y) / np.sum(x),
|
|
484
|
+
)
|
|
440
485
|
|
|
441
486
|
|
|
442
487
|
class PolyLine:
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
# See the License for the specific language governing permissions and
|
|
14
14
|
# limitations under the License.
|
|
15
15
|
|
|
16
|
-
from ..commons import logger, __version__, SIIBRA_USE_CONFIGURATION
|
|
16
|
+
from ..commons import logger, __version__, SIIBRA_USE_CONFIGURATION, siibra_tqdm
|
|
17
17
|
from ..retrieval.repositories import GitlabConnector, RepositoryConnector
|
|
18
18
|
from ..retrieval.exceptions import NoSiibraConfigMirrorsAvailableException
|
|
19
19
|
from ..retrieval.requests import SiibraHttpRequestError
|
|
@@ -21,7 +21,6 @@ from ..retrieval.requests import SiibraHttpRequestError
|
|
|
21
21
|
from typing import Union
|
|
22
22
|
from collections import defaultdict
|
|
23
23
|
from requests.exceptions import ConnectionError
|
|
24
|
-
from tqdm import tqdm
|
|
25
24
|
from os import path
|
|
26
25
|
|
|
27
26
|
|
|
@@ -47,12 +46,7 @@ class Configuration:
|
|
|
47
46
|
|
|
48
47
|
CONFIGURATION_EXTENSIONS = []
|
|
49
48
|
|
|
50
|
-
|
|
51
|
-
# found in the siibra configuration, stored per
|
|
52
|
-
# preconfigured class name. These files can
|
|
53
|
-
# loaded and fed to the Factory.from_json
|
|
54
|
-
# to produce the corresponding object.
|
|
55
|
-
spec_loaders = defaultdict(list)
|
|
49
|
+
|
|
56
50
|
|
|
57
51
|
_cleanup_funcs = []
|
|
58
52
|
|
|
@@ -65,6 +59,13 @@ class Configuration:
|
|
|
65
59
|
|
|
66
60
|
def __init__(self):
|
|
67
61
|
|
|
62
|
+
# lists of loaders for json specification files
|
|
63
|
+
# found in the siibra configuration, stored per
|
|
64
|
+
# preconfigured class name. These files can
|
|
65
|
+
# loaded and fed to the Factory.from_json
|
|
66
|
+
# to produce the corresponding object.
|
|
67
|
+
self.spec_loaders = defaultdict(list)
|
|
68
|
+
|
|
68
69
|
# retrieve json spec loaders from the default configuration
|
|
69
70
|
for connector in self.CONFIGURATIONS:
|
|
70
71
|
try:
|
|
@@ -122,11 +123,14 @@ class Configuration:
|
|
|
122
123
|
conn = RepositoryConnector._from_url(conn)
|
|
123
124
|
if not isinstance(conn, RepositoryConnector):
|
|
124
125
|
raise RuntimeError("conn needs to be an instance of RepositoryConnector or a valid str")
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
126
|
+
if conn in cls.CONFIGURATION_EXTENSIONS:
|
|
127
|
+
logger.warn(f"The configuration {str(conn)} is already registered.")
|
|
128
|
+
else:
|
|
129
|
+
logger.info(f"Extending configuration with {str(conn)}")
|
|
130
|
+
cls.CONFIGURATION_EXTENSIONS.append(conn)
|
|
131
|
+
# call registered cleanup functions
|
|
132
|
+
for func in cls._cleanup_funcs:
|
|
133
|
+
func()
|
|
130
134
|
|
|
131
135
|
@classmethod
|
|
132
136
|
def register_cleanup(cls, func):
|
|
@@ -143,7 +147,7 @@ class Configuration:
|
|
|
143
147
|
result = []
|
|
144
148
|
|
|
145
149
|
if folder not in self.folders:
|
|
146
|
-
logger.
|
|
150
|
+
logger.warning(f"No configuration found for building from configuration folder {folder}.")
|
|
147
151
|
return result
|
|
148
152
|
|
|
149
153
|
from .factory import Factory
|
|
@@ -158,12 +162,12 @@ class Configuration:
|
|
|
158
162
|
)
|
|
159
163
|
)
|
|
160
164
|
|
|
161
|
-
for fname, loader in
|
|
165
|
+
for fname, loader in siibra_tqdm(
|
|
162
166
|
specloaders,
|
|
163
167
|
total=len(specloaders),
|
|
164
168
|
desc=f"Loading preconfigured {obj0.__class__.__name__} instances"
|
|
165
169
|
):
|
|
166
|
-
# filename is added to allow Factory creating reasonable default object identifiers
|
|
170
|
+
# filename is added to allow Factory creating reasonable default object identifiers\
|
|
167
171
|
obj = Factory.from_json(dict(loader.data, **{'filename': fname}))
|
|
168
172
|
result.append(obj)
|
|
169
173
|
|
|
@@ -174,5 +178,5 @@ class Configuration:
|
|
|
174
178
|
|
|
175
179
|
|
|
176
180
|
if SIIBRA_USE_CONFIGURATION:
|
|
177
|
-
logger.
|
|
181
|
+
logger.warning(f"config.SIIBRA_USE_CONFIGURATION defined, use configuration at {SIIBRA_USE_CONFIGURATION}")
|
|
178
182
|
Configuration.use_configuration(SIIBRA_USE_CONFIGURATION)
|
siibra/configuration/factory.py
CHANGED
|
@@ -14,15 +14,19 @@
|
|
|
14
14
|
# limitations under the License.
|
|
15
15
|
|
|
16
16
|
from ..commons import logger, Species
|
|
17
|
-
from ..features import anchor
|
|
18
|
-
from ..features.
|
|
19
|
-
|
|
20
|
-
|
|
17
|
+
from ..features import anchor, connectivity
|
|
18
|
+
from ..features.tabular import (
|
|
19
|
+
receptor_density_profile,
|
|
20
|
+
receptor_density_fingerprint,
|
|
21
|
+
cell_density_profile,
|
|
22
|
+
layerwise_cell_density,
|
|
23
|
+
regional_timeseries_activity
|
|
24
|
+
)
|
|
25
|
+
from ..features.image import sections, volume_of_interest
|
|
21
26
|
from ..core import atlas, parcellation, space, region
|
|
22
27
|
from ..locations import point, pointset
|
|
23
28
|
from ..retrieval import datasets, repositories
|
|
24
29
|
from ..volumes import gifti, volume, nifti, neuroglancer, sparsemap, parcellationmap
|
|
25
|
-
from ..features import connectivity
|
|
26
30
|
|
|
27
31
|
from os import path
|
|
28
32
|
import json
|
|
@@ -49,7 +53,9 @@ BUILDFUNCS = {
|
|
|
49
53
|
"siibra/feature/fingerprint/receptor/v0.1": "build_receptor_density_fingerprint",
|
|
50
54
|
"siibra/feature/fingerprint/celldensity/v0.1": "build_cell_density_fingerprint",
|
|
51
55
|
"siibra/feature/connectivitymatrix/v0.2": "build_connectivity_matrix",
|
|
56
|
+
"siibra/feature/section/v0.1": "build_section",
|
|
52
57
|
"siibra/feature/voi/v0.1": "build_volume_of_interest",
|
|
58
|
+
"siibra/feature/timeseries/activity/v0.1": "build_activity_timeseries"
|
|
53
59
|
}
|
|
54
60
|
|
|
55
61
|
|
|
@@ -64,6 +70,10 @@ class Factory:
|
|
|
64
70
|
result.append(
|
|
65
71
|
datasets.EbrainsDataset(id=spec["ebrains"]["minds/core/dataset/v1.0.0"])
|
|
66
72
|
)
|
|
73
|
+
if "openminds/DatasetVersion" in spec.get("ebrains", {}):
|
|
74
|
+
result.append(
|
|
75
|
+
datasets.EbrainsV3DatasetVersion(id=spec["ebrains"]["openminds/DatasetVersion"])
|
|
76
|
+
)
|
|
67
77
|
return result
|
|
68
78
|
|
|
69
79
|
@classmethod
|
|
@@ -72,7 +82,7 @@ class Factory:
|
|
|
72
82
|
for vspec in volume_specs:
|
|
73
83
|
if space_id:
|
|
74
84
|
if 'space' in vspec:
|
|
75
|
-
logger.
|
|
85
|
+
logger.warning(f"Replacing space spec {vspec['space']} in volume spec with {space_id}")
|
|
76
86
|
vspec['space'] = {"@id": space_id}
|
|
77
87
|
if name and vspec.get('name') is None: # only use provided name if the volume has no specific name
|
|
78
88
|
vspec['name'] = name
|
|
@@ -135,7 +145,7 @@ class Factory:
|
|
|
135
145
|
reftag=repospec['branch']
|
|
136
146
|
)
|
|
137
147
|
else:
|
|
138
|
-
logger.
|
|
148
|
+
logger.warning(
|
|
139
149
|
"Do not know how to create a repository "
|
|
140
150
|
f"connector from specification type {spectype}."
|
|
141
151
|
)
|
|
@@ -236,7 +246,7 @@ class Factory:
|
|
|
236
246
|
break
|
|
237
247
|
else:
|
|
238
248
|
if srctype not in cls._warnings_issued:
|
|
239
|
-
logger.
|
|
249
|
+
logger.warning(f"No provider defined for volume Source type {srctype}")
|
|
240
250
|
cls._warnings_issued.append(srctype)
|
|
241
251
|
|
|
242
252
|
assert all([isinstance(provider, volume.VolumeProvider) for provider in providers])
|
|
@@ -245,6 +255,7 @@ class Factory:
|
|
|
245
255
|
providers=providers,
|
|
246
256
|
name=spec.get("name", {}),
|
|
247
257
|
variant=spec.get("variant"),
|
|
258
|
+
datasets=cls.extract_datasets(spec),
|
|
248
259
|
)
|
|
249
260
|
|
|
250
261
|
return result
|
|
@@ -267,7 +278,7 @@ class Factory:
|
|
|
267
278
|
else:
|
|
268
279
|
max_z = max(
|
|
269
280
|
d.get('z', 0)
|
|
270
|
-
for
|
|
281
|
+
for l in spec.get("indices", {}).values()
|
|
271
282
|
for d in l
|
|
272
283
|
) + 1
|
|
273
284
|
if max_z > MIN_VOLUMES_FOR_SPARSE_MAP:
|
|
@@ -364,17 +375,61 @@ class Factory:
|
|
|
364
375
|
datasets=cls.extract_datasets(spec),
|
|
365
376
|
)
|
|
366
377
|
|
|
378
|
+
@classmethod
|
|
379
|
+
def build_section(cls, spec):
|
|
380
|
+
vol = cls.build_volume(spec)
|
|
381
|
+
kwargs = {
|
|
382
|
+
"name": spec.get('name', ""),
|
|
383
|
+
"region": spec.get('region', None),
|
|
384
|
+
"space_spec": vol._space_spec,
|
|
385
|
+
"providers": vol._providers.values(),
|
|
386
|
+
"datasets": cls.extract_datasets(spec),
|
|
387
|
+
}
|
|
388
|
+
modality = spec.get('modality', "")
|
|
389
|
+
if modality == "cell body staining":
|
|
390
|
+
return sections.CellbodyStainedSection(**kwargs)
|
|
391
|
+
else:
|
|
392
|
+
raise ValueError(f"No method for building image section feature type {modality}.")
|
|
393
|
+
|
|
367
394
|
@classmethod
|
|
368
395
|
def build_volume_of_interest(cls, spec):
|
|
369
396
|
vol = cls.build_volume(spec)
|
|
370
|
-
|
|
371
|
-
name
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
)
|
|
397
|
+
kwargs = {
|
|
398
|
+
"name": spec.get('name', ""),
|
|
399
|
+
"region": spec.get('region', None),
|
|
400
|
+
"space_spec": vol._space_spec,
|
|
401
|
+
"providers": vol._providers.values(),
|
|
402
|
+
"datasets": cls.extract_datasets(spec),
|
|
403
|
+
}
|
|
404
|
+
modality = spec.get('modality', "")
|
|
405
|
+
if modality == "cell body staining":
|
|
406
|
+
return volume_of_interest.CellBodyStainedVolumeOfInterest(**kwargs)
|
|
407
|
+
elif modality == "blockface":
|
|
408
|
+
return volume_of_interest.BlockfaceVolumeOfInterest(**kwargs)
|
|
409
|
+
elif modality == "PLI HSV fibre orientation map":
|
|
410
|
+
return volume_of_interest.PLIVolumeOfInterest(
|
|
411
|
+
modality="HSV fibre orientation map", **kwargs
|
|
412
|
+
)
|
|
413
|
+
elif modality == "transmittance":
|
|
414
|
+
return volume_of_interest.PLIVolumeOfInterest(
|
|
415
|
+
modality="transmittance", **kwargs
|
|
416
|
+
)
|
|
417
|
+
elif modality == "XPCT":
|
|
418
|
+
return volume_of_interest.XPCTVolumeOfInterest(
|
|
419
|
+
modality="XPCT", **kwargs
|
|
420
|
+
)
|
|
421
|
+
# elif modality == "segmentation":
|
|
422
|
+
# return volume_of_interest.SegmentedVolumeOfInterest(**kwargs)
|
|
423
|
+
elif modality == "T2 weighted MRI":
|
|
424
|
+
return volume_of_interest.MRIVolumeOfInterest(
|
|
425
|
+
modality="T2", **kwargs
|
|
426
|
+
)
|
|
427
|
+
elif modality == "T1 weighted MRI":
|
|
428
|
+
return volume_of_interest.MRIVolumeOfInterest(
|
|
429
|
+
modality="T1", **kwargs
|
|
430
|
+
)
|
|
431
|
+
else:
|
|
432
|
+
raise ValueError(f"No method for building image section feature type {modality}.")
|
|
378
433
|
|
|
379
434
|
@classmethod
|
|
380
435
|
def build_connectivity_matrix(cls, spec):
|
|
@@ -398,10 +453,31 @@ class Factory:
|
|
|
398
453
|
kwargs["paradigm"] = spec.get("paradigm")
|
|
399
454
|
return connectivity.FunctionalConnectivity(**kwargs)
|
|
400
455
|
elif modality == "RestingState":
|
|
401
|
-
kwargs["paradigm"] = "RestingState"
|
|
456
|
+
kwargs["paradigm"] = spec.get("paradigm", "RestingState")
|
|
402
457
|
return connectivity.FunctionalConnectivity(**kwargs)
|
|
403
458
|
else:
|
|
404
|
-
raise ValueError(f"
|
|
459
|
+
raise ValueError(f"No method for building connectivity matrix of type {modality}.")
|
|
460
|
+
|
|
461
|
+
@classmethod
|
|
462
|
+
def build_activity_timeseries(cls, spec):
|
|
463
|
+
modality = spec["modality"]
|
|
464
|
+
kwargs = {
|
|
465
|
+
"cohort": spec["cohort"],
|
|
466
|
+
"modality": modality,
|
|
467
|
+
"regions": spec["regions"],
|
|
468
|
+
"connector": cls.extract_connector(spec),
|
|
469
|
+
"decode_func": cls.extract_decoder(spec),
|
|
470
|
+
"files": spec.get("files", {}),
|
|
471
|
+
"anchor": cls.extract_anchor(spec),
|
|
472
|
+
"description": spec.get("description", ""),
|
|
473
|
+
"datasets": cls.extract_datasets(spec),
|
|
474
|
+
"timestep": spec.get("timestep", ("1 no_unit"))
|
|
475
|
+
}
|
|
476
|
+
if modality == "Regional BOLD signal":
|
|
477
|
+
kwargs["paradigm"] = spec.get("paradigm", "")
|
|
478
|
+
return regional_timeseries_activity.RegionalBOLD(**kwargs)
|
|
479
|
+
else:
|
|
480
|
+
raise ValueError(f"No method for building signal table of type {modality}.")
|
|
405
481
|
|
|
406
482
|
@classmethod
|
|
407
483
|
def from_json(cls, spec: dict):
|
siibra/core/atlas.py
CHANGED
|
@@ -184,17 +184,20 @@ class Atlas(concept.AtlasConcept, configuration_folder="atlases"):
|
|
|
184
184
|
|
|
185
185
|
Parameters
|
|
186
186
|
----------
|
|
187
|
-
regionspec
|
|
188
|
-
- a string with a possibly inexact name
|
|
189
|
-
|
|
190
|
-
-
|
|
191
|
-
- a
|
|
187
|
+
regionspec: str, regex, int, Region, MapIndex
|
|
188
|
+
- a string with a possibly inexact name (matched both against the name and the identifier key)
|
|
189
|
+
- a string in '/pattern/flags' format to use regex search (acceptable flags: aiLmsux)
|
|
190
|
+
- a regex applied to region names
|
|
191
|
+
- a Region object
|
|
192
192
|
all_versions : Bool, default: False
|
|
193
193
|
If True, matched regions for all versions of a parcellation are returned.
|
|
194
|
+
filter_children : bool, default: True
|
|
195
|
+
If False, children of matched parents will be returned.
|
|
194
196
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
list
|
|
197
|
+
Returns
|
|
198
|
+
-------
|
|
199
|
+
list[Region]
|
|
200
|
+
list of regions matching to the regionspec
|
|
198
201
|
"""
|
|
199
202
|
result = []
|
|
200
203
|
for p in self._parcellation_ids:
|
siibra/core/concept.py
CHANGED
|
@@ -85,9 +85,29 @@ class AtlasConcept:
|
|
|
85
85
|
else Species.decode(species) # overwritable property implementation below
|
|
86
86
|
self.shortname = shortname
|
|
87
87
|
self.modality = modality
|
|
88
|
-
self.
|
|
89
|
-
self.
|
|
88
|
+
self._description = description
|
|
89
|
+
self._publications = publications
|
|
90
90
|
self.datasets = datasets
|
|
91
|
+
|
|
92
|
+
@property
|
|
93
|
+
def description(self):
|
|
94
|
+
if self._description:
|
|
95
|
+
return self._description
|
|
96
|
+
for ds in self.datasets:
|
|
97
|
+
if ds.description:
|
|
98
|
+
return ds.description
|
|
99
|
+
return ''
|
|
100
|
+
|
|
101
|
+
@property
|
|
102
|
+
def publications(self) -> List[TypePublication]:
|
|
103
|
+
return [
|
|
104
|
+
*self._publications,
|
|
105
|
+
*[{
|
|
106
|
+
'citation': 'DOI',
|
|
107
|
+
'url': url.get("url")
|
|
108
|
+
} for ds in self.datasets
|
|
109
|
+
for url in ds.urls]
|
|
110
|
+
]
|
|
91
111
|
|
|
92
112
|
@property
|
|
93
113
|
def species(self) -> Species:
|
|
@@ -135,12 +155,18 @@ class AtlasConcept:
|
|
|
135
155
|
@classmethod
|
|
136
156
|
def get_instance(cls, spec: str):
|
|
137
157
|
"""
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
158
|
+
Parameters
|
|
159
|
+
----------
|
|
160
|
+
spec: str
|
|
161
|
+
Specification of the class the instance is requested.
|
|
162
|
+
Returns
|
|
142
163
|
-------
|
|
143
|
-
|
|
164
|
+
an instance of this class matching the given specification from its
|
|
165
|
+
registry if possible, otherwise None.
|
|
166
|
+
Raises
|
|
167
|
+
------
|
|
168
|
+
IndexError
|
|
169
|
+
If spec cannot match any instance
|
|
144
170
|
"""
|
|
145
171
|
if cls.registry() is not None:
|
|
146
172
|
return cls.registry().get(spec)
|
|
@@ -168,7 +194,14 @@ class AtlasConcept:
|
|
|
168
194
|
|
|
169
195
|
def matches(self, spec):
|
|
170
196
|
"""
|
|
171
|
-
|
|
197
|
+
Parameters
|
|
198
|
+
----------
|
|
199
|
+
spec: str
|
|
200
|
+
Specification checked within the concept name, key or id
|
|
201
|
+
Returns
|
|
202
|
+
-------
|
|
203
|
+
bool
|
|
204
|
+
Whether the given specification matches the name, key or id of the concept.
|
|
172
205
|
"""
|
|
173
206
|
if isinstance(spec, self.__class__) and (spec == self):
|
|
174
207
|
return True
|