siibra 0.5a2__py3-none-any.whl → 1.0.0a1__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 +20 -12
- siibra/commons.py +145 -90
- siibra/configuration/__init__.py +1 -1
- siibra/configuration/configuration.py +22 -17
- siibra/configuration/factory.py +177 -128
- siibra/core/__init__.py +1 -8
- siibra/core/{relation_qualification.py → assignment.py} +17 -14
- siibra/core/atlas.py +66 -35
- siibra/core/concept.py +81 -39
- siibra/core/parcellation.py +83 -67
- siibra/core/region.py +569 -263
- siibra/core/space.py +7 -39
- siibra/core/structure.py +111 -0
- siibra/exceptions.py +63 -0
- siibra/experimental/__init__.py +19 -0
- siibra/experimental/contour.py +61 -0
- siibra/experimental/cortical_profile_sampler.py +57 -0
- siibra/experimental/patch.py +98 -0
- siibra/experimental/plane3d.py +256 -0
- siibra/explorer/__init__.py +16 -0
- siibra/explorer/url.py +112 -52
- siibra/explorer/util.py +31 -9
- siibra/features/__init__.py +73 -8
- siibra/features/anchor.py +75 -196
- siibra/features/connectivity/__init__.py +1 -1
- siibra/features/connectivity/functional_connectivity.py +2 -2
- siibra/features/connectivity/regional_connectivity.py +99 -10
- siibra/features/connectivity/streamline_counts.py +1 -1
- siibra/features/connectivity/streamline_lengths.py +1 -1
- siibra/features/connectivity/tracing_connectivity.py +1 -1
- siibra/features/dataset/__init__.py +1 -1
- siibra/features/dataset/ebrains.py +3 -3
- siibra/features/feature.py +219 -110
- siibra/features/image/__init__.py +1 -1
- siibra/features/image/image.py +21 -13
- siibra/features/image/sections.py +1 -1
- siibra/features/image/volume_of_interest.py +1 -1
- siibra/features/tabular/__init__.py +1 -1
- siibra/features/tabular/bigbrain_intensity_profile.py +24 -13
- siibra/features/tabular/cell_density_profile.py +111 -69
- siibra/features/tabular/cortical_profile.py +82 -16
- siibra/features/tabular/gene_expression.py +117 -6
- siibra/features/tabular/layerwise_bigbrain_intensities.py +7 -9
- siibra/features/tabular/layerwise_cell_density.py +9 -24
- siibra/features/tabular/receptor_density_fingerprint.py +11 -6
- siibra/features/tabular/receptor_density_profile.py +12 -15
- siibra/features/tabular/regional_timeseries_activity.py +74 -18
- siibra/features/tabular/tabular.py +17 -8
- siibra/livequeries/__init__.py +1 -7
- siibra/livequeries/allen.py +139 -77
- siibra/livequeries/bigbrain.py +104 -128
- siibra/livequeries/ebrains.py +7 -4
- siibra/livequeries/query.py +1 -2
- siibra/locations/__init__.py +32 -25
- siibra/locations/boundingbox.py +153 -127
- siibra/locations/location.py +45 -80
- siibra/locations/point.py +97 -83
- siibra/locations/pointcloud.py +349 -0
- siibra/retrieval/__init__.py +1 -1
- siibra/retrieval/cache.py +107 -13
- siibra/retrieval/datasets.py +9 -14
- siibra/retrieval/exceptions/__init__.py +2 -1
- siibra/retrieval/repositories.py +147 -53
- siibra/retrieval/requests.py +64 -29
- siibra/vocabularies/__init__.py +2 -2
- siibra/volumes/__init__.py +7 -9
- siibra/volumes/parcellationmap.py +396 -253
- siibra/volumes/providers/__init__.py +20 -0
- siibra/volumes/providers/freesurfer.py +113 -0
- siibra/volumes/{gifti.py → providers/gifti.py} +29 -18
- siibra/volumes/{neuroglancer.py → providers/neuroglancer.py} +204 -92
- siibra/volumes/{nifti.py → providers/nifti.py} +64 -44
- siibra/volumes/providers/provider.py +107 -0
- siibra/volumes/sparsemap.py +159 -260
- siibra/volumes/volume.py +720 -152
- {siibra-0.5a2.dist-info → siibra-1.0.0a1.dist-info}/METADATA +25 -28
- siibra-1.0.0a1.dist-info/RECORD +84 -0
- {siibra-0.5a2.dist-info → siibra-1.0.0a1.dist-info}/WHEEL +1 -1
- siibra/locations/pointset.py +0 -198
- siibra-0.5a2.dist-info/RECORD +0 -74
- {siibra-0.5a2.dist-info → siibra-1.0.0a1.dist-info}/LICENSE +0 -0
- {siibra-0.5a2.dist-info → siibra-1.0.0a1.dist-info}/top_level.txt +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright 2018-
|
|
1
|
+
# Copyright 2018-2024
|
|
2
2
|
# Institute of Neuroscience and Medicine (INM-1), Forschungszentrum Jülich GmbH
|
|
3
3
|
|
|
4
4
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
|
|
16
16
|
from .. import anchor as _anchor
|
|
17
17
|
from . import tabular
|
|
18
|
+
from ...retrieval.datasets import GenericDataset
|
|
18
19
|
|
|
19
20
|
import pandas as pd
|
|
20
21
|
from textwrap import wrap
|
|
@@ -46,6 +47,114 @@ class GeneExpressions(
|
|
|
46
47
|
as specified at https://alleninstitute.org/legal/terms-use/.
|
|
47
48
|
"""
|
|
48
49
|
|
|
50
|
+
DATASET = GenericDataset(
|
|
51
|
+
name="An anatomically comprehensive atlas of the adult human brain transcriptome",
|
|
52
|
+
contributors=[
|
|
53
|
+
'Michael J. Hawrylycz',
|
|
54
|
+
'Ed S. Lein',
|
|
55
|
+
'Angela L. Guillozet-Bongaarts',
|
|
56
|
+
'Elaine H. Shen',
|
|
57
|
+
'Lydia Ng',
|
|
58
|
+
'Jeremy A. Miller',
|
|
59
|
+
'Louie N. van de Lagemaat',
|
|
60
|
+
'Kimberly A. Smith',
|
|
61
|
+
'Amanda Ebbert',
|
|
62
|
+
'Zackery L. Riley',
|
|
63
|
+
'Chris Abajian',
|
|
64
|
+
'Christian F. Beckmann',
|
|
65
|
+
'Amy Bernard',
|
|
66
|
+
'Darren Bertagnolli',
|
|
67
|
+
'Andrew F. Boe',
|
|
68
|
+
'Preston M. Cartagena',
|
|
69
|
+
'M. Mallar Chakravarty',
|
|
70
|
+
'Mike Chapin',
|
|
71
|
+
'Jimmy Chong',
|
|
72
|
+
'Rachel A. Dalley',
|
|
73
|
+
'Barry David Daly',
|
|
74
|
+
'Chinh Dang',
|
|
75
|
+
'Suvro Datta',
|
|
76
|
+
'Nick Dee',
|
|
77
|
+
'Tim A. Dolbeare',
|
|
78
|
+
'Vance Faber',
|
|
79
|
+
'David Feng',
|
|
80
|
+
'David R. Fowler',
|
|
81
|
+
'Jeff Goldy',
|
|
82
|
+
'Benjamin W. Gregor',
|
|
83
|
+
'Zeb Haradon',
|
|
84
|
+
'David R. Haynor',
|
|
85
|
+
'John G. Hohmann',
|
|
86
|
+
'Steve Horvath',
|
|
87
|
+
'Robert E. Howard',
|
|
88
|
+
'Andreas Jeromin',
|
|
89
|
+
'Jayson M. Jochim',
|
|
90
|
+
'Marty Kinnunen',
|
|
91
|
+
'Christopher Lau',
|
|
92
|
+
'Evan T. Lazarz',
|
|
93
|
+
'Changkyu Lee',
|
|
94
|
+
'Tracy A. Lemon',
|
|
95
|
+
'Ling Li',
|
|
96
|
+
'Yang Li',
|
|
97
|
+
'John A. Morris',
|
|
98
|
+
'Caroline C. Overly',
|
|
99
|
+
'Patrick D. Parker',
|
|
100
|
+
'Sheana E. Parry',
|
|
101
|
+
'Melissa Reding',
|
|
102
|
+
'Joshua J. Royall',
|
|
103
|
+
'Jay Schulkin',
|
|
104
|
+
'Pedro Adolfo Sequeira',
|
|
105
|
+
'Clifford R. Slaughterbeck',
|
|
106
|
+
'Simon C. Smith',
|
|
107
|
+
'Andy J. Sodt',
|
|
108
|
+
'Susan M. Sunkin',
|
|
109
|
+
'Beryl E. Swanson',
|
|
110
|
+
'Marquis P. Vawter',
|
|
111
|
+
'Derric Williams',
|
|
112
|
+
'Paul Wohnoutka',
|
|
113
|
+
'H. Ronald Zielke',
|
|
114
|
+
'Daniel H. Geschwind',
|
|
115
|
+
'Patrick R. Hof',
|
|
116
|
+
'Stephen M. Smith',
|
|
117
|
+
'Christof Koch',
|
|
118
|
+
'Seth G. N. Grant',
|
|
119
|
+
'Allan R. Jones'
|
|
120
|
+
],
|
|
121
|
+
url="https://doi.org/10.1038%2Fnature11405",
|
|
122
|
+
description='Neuroanatomically precise, genome-wide maps of transcript '
|
|
123
|
+
'distributions are critical resources to complement genomic '
|
|
124
|
+
'sequence data and to correlate functional and genetic brain '
|
|
125
|
+
'architecture. Here we describe the generation and analysis '
|
|
126
|
+
'of a transcriptional atlas of the adult human brain, '
|
|
127
|
+
'comprising extensive histological analysis and comprehensive '
|
|
128
|
+
'microarray profiling of ~900 neuroanatomically precise '
|
|
129
|
+
'subdivisions in two individuals. Transcriptional regulation '
|
|
130
|
+
'varies enormously by anatomical location, with different '
|
|
131
|
+
'regions and their constituent cell types displaying robust '
|
|
132
|
+
'molecular signatures that are highly conserved between '
|
|
133
|
+
'individuals. Analysis of differential gene expression and '
|
|
134
|
+
'gene co-expression relationships demonstrates that brain-'
|
|
135
|
+
'wide variation strongly reflects the distributions of major '
|
|
136
|
+
'cell classes such as neurons, oligodendrocytes, astrocytes '
|
|
137
|
+
'and microglia. Local neighbourhood relationships between '
|
|
138
|
+
'fine anatomical subdivisions are associated with discrete '
|
|
139
|
+
'neuronal subtypes and genes involved with synaptic '
|
|
140
|
+
'transmission. The neocortex displays a relatively '
|
|
141
|
+
'homogeneous transcriptional pattern, but with distinct '
|
|
142
|
+
'features associated selectively with primary sensorimotor '
|
|
143
|
+
'cortices and with enriched frontal lobe expression. Notably, '
|
|
144
|
+
'the spatial topography of the neocortex is strongly '
|
|
145
|
+
'reflected in its molecular topography— the closer two '
|
|
146
|
+
'cortical regions, the more similar their transcriptomes. '
|
|
147
|
+
'This freely accessible online data resource forms a high-'
|
|
148
|
+
'resolution transcriptional baseline for neurogenetic studies '
|
|
149
|
+
'of normal and abnormal human brain function.'
|
|
150
|
+
""
|
|
151
|
+
"For retrieving microarray data, siibra connects to the web API of "
|
|
152
|
+
"the Allen Brain Atlas (© 2015 Allen Institute for Brain Science), "
|
|
153
|
+
"available from https://brain-map.org/api/index.html. Any use of the "
|
|
154
|
+
"microarray data needs to be in accordance with their terms of use, "
|
|
155
|
+
"as specified at https://alleninstitute.org/legal/terms-use/."
|
|
156
|
+
)
|
|
157
|
+
|
|
49
158
|
class _DonorDict(TypedDict):
|
|
50
159
|
id: int
|
|
51
160
|
name: str
|
|
@@ -66,7 +175,7 @@ class GeneExpressions(
|
|
|
66
175
|
genes: List[str],
|
|
67
176
|
additional_columns: dict,
|
|
68
177
|
anchor: _anchor.AnatomicalAnchor,
|
|
69
|
-
datasets: List = []
|
|
178
|
+
datasets: List = [DATASET]
|
|
70
179
|
):
|
|
71
180
|
"""
|
|
72
181
|
Construct gene expression table.
|
|
@@ -130,15 +239,17 @@ class GeneExpressions(
|
|
|
130
239
|
"""
|
|
131
240
|
wrapwidth = kwargs.pop("textwrap") if "textwrap" in kwargs else 40
|
|
132
241
|
kwargs["title"] = kwargs.pop("title", None) \
|
|
133
|
-
or "\n".join(wrap(f"{self.modality} measured in {self.anchor._regionspec}", wrapwidth))
|
|
242
|
+
or "\n".join(wrap(f"{self.modality} measured in {self.anchor._regionspec or self.anchor.location}", wrapwidth))
|
|
134
243
|
kwargs["kind"] = "box"
|
|
135
244
|
if backend == "matplotlib":
|
|
136
245
|
for arg in ['yerr', 'y', 'ylabel', 'xlabel', 'width']:
|
|
137
246
|
assert arg not in kwargs
|
|
138
|
-
|
|
139
|
-
"grid": True, "legend": False, 'by': "gene",
|
|
247
|
+
default_kwargs = {
|
|
248
|
+
"grid": True, "legend": False, 'by': "gene",
|
|
249
|
+
'column': ['level'], 'showfliers': False, 'ax': None,
|
|
250
|
+
'ylabel': 'expression level'
|
|
140
251
|
}
|
|
141
|
-
return self.data.plot(*args, **
|
|
252
|
+
return self.data.plot(*args, **{**default_kwargs, **kwargs}, backend=backend)
|
|
142
253
|
elif backend == "plotly":
|
|
143
254
|
kwargs["title"] = kwargs["title"].replace('\n', "<br>")
|
|
144
255
|
return self.data.plot(y='level', x='gene', backend=backend, **kwargs)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright 2018-
|
|
1
|
+
# Copyright 2018-2024
|
|
2
2
|
# Institute of Neuroscience and Medicine (INM-1), Forschungszentrum Jülich GmbH
|
|
3
3
|
|
|
4
4
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
@@ -19,6 +19,10 @@ from . import tabular
|
|
|
19
19
|
import pandas as pd
|
|
20
20
|
import numpy as np
|
|
21
21
|
|
|
22
|
+
from typing import TYPE_CHECKING
|
|
23
|
+
if TYPE_CHECKING:
|
|
24
|
+
from ...features.anchor import AnatomicalAnchor
|
|
25
|
+
|
|
22
26
|
|
|
23
27
|
class LayerwiseBigBrainIntensities(
|
|
24
28
|
tabular.Tabular,
|
|
@@ -31,7 +35,7 @@ class LayerwiseBigBrainIntensities(
|
|
|
31
35
|
"'Wagstyl, K., et al (2020). BigBrain 3D atlas of "
|
|
32
36
|
"cortical layers: Cortical and laminar thickness gradients diverge in sensory and "
|
|
33
37
|
"motor cortices. PLoS Biology, 18(4), e3000678. "
|
|
34
|
-
"http://dx.doi.org/10.1371/journal.pbio.3000678
|
|
38
|
+
"http://dx.doi.org/10.1371/journal.pbio.3000678."
|
|
35
39
|
"The data is taken from the tutorial at "
|
|
36
40
|
"https://github.com/kwagstyl/cortical_layers_tutorial. Each vertex is "
|
|
37
41
|
"assigned to the regional map when queried."
|
|
@@ -39,16 +43,10 @@ class LayerwiseBigBrainIntensities(
|
|
|
39
43
|
|
|
40
44
|
def __init__(
|
|
41
45
|
self,
|
|
42
|
-
|
|
46
|
+
anchor: "AnatomicalAnchor",
|
|
43
47
|
means: list,
|
|
44
48
|
stds: list,
|
|
45
49
|
):
|
|
46
|
-
|
|
47
|
-
from ..anchor import AnatomicalAnchor
|
|
48
|
-
anchor = AnatomicalAnchor(
|
|
49
|
-
region=regionname,
|
|
50
|
-
species='Homo sapiens'
|
|
51
|
-
)
|
|
52
50
|
data = pd.DataFrame(
|
|
53
51
|
np.array([means, stds]).T,
|
|
54
52
|
columns=['mean', 'std'],
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright 2018-
|
|
1
|
+
# Copyright 2018-2024
|
|
2
2
|
# Institute of Neuroscience and Medicine (INM-1), Forschungszentrum Jülich GmbH
|
|
3
3
|
|
|
4
4
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
@@ -16,13 +16,13 @@
|
|
|
16
16
|
from . import cortical_profile
|
|
17
17
|
from .. import anchor as _anchor
|
|
18
18
|
from . import tabular
|
|
19
|
+
from ..tabular.cell_density_profile import cell_reader, layer_reader
|
|
19
20
|
|
|
20
21
|
from ... import commons
|
|
21
22
|
from ...retrieval import requests
|
|
22
23
|
|
|
23
24
|
import pandas as pd
|
|
24
25
|
import numpy as np
|
|
25
|
-
from io import BytesIO
|
|
26
26
|
|
|
27
27
|
|
|
28
28
|
class LayerwiseCellDensity(
|
|
@@ -40,22 +40,14 @@ class LayerwiseCellDensity(
|
|
|
40
40
|
"The cortical depth is estimated from the measured layer thicknesses."
|
|
41
41
|
)
|
|
42
42
|
|
|
43
|
-
@classmethod
|
|
44
|
-
def CELL_READER(cls, b):
|
|
45
|
-
return pd.read_csv(BytesIO(b[2:]), delimiter=" ", header=0).astype(
|
|
46
|
-
{"layer": int, "label": int}
|
|
47
|
-
)
|
|
48
|
-
|
|
49
|
-
@classmethod
|
|
50
|
-
def LAYER_READER(cls, b):
|
|
51
|
-
return pd.read_csv(BytesIO(b[2:]), delimiter=" ", header=0, index_col=0)
|
|
52
|
-
|
|
53
43
|
def __init__(
|
|
54
44
|
self,
|
|
55
45
|
segmentfiles: list,
|
|
56
46
|
layerfiles: list,
|
|
57
47
|
anchor: _anchor.AnatomicalAnchor,
|
|
58
48
|
datasets: list = [],
|
|
49
|
+
id: str = None,
|
|
50
|
+
prerelease: bool = False,
|
|
59
51
|
):
|
|
60
52
|
tabular.Tabular.__init__(
|
|
61
53
|
self,
|
|
@@ -63,7 +55,9 @@ class LayerwiseCellDensity(
|
|
|
63
55
|
modality="Cell body density",
|
|
64
56
|
anchor=anchor,
|
|
65
57
|
datasets=datasets,
|
|
66
|
-
data=None # lazy loading below
|
|
58
|
+
data=None, # lazy loading below
|
|
59
|
+
id=id,
|
|
60
|
+
prerelease=prerelease,
|
|
67
61
|
)
|
|
68
62
|
self.unit = "# detected cells/0.1mm3"
|
|
69
63
|
self._filepairs = list(zip(segmentfiles, layerfiles))
|
|
@@ -73,8 +67,8 @@ class LayerwiseCellDensity(
|
|
|
73
67
|
density_dict = {}
|
|
74
68
|
for i, (cellfile, layerfile) in enumerate(self._filepairs):
|
|
75
69
|
try:
|
|
76
|
-
cells = requests.HttpRequest(cellfile, func=
|
|
77
|
-
layers = requests.HttpRequest(layerfile, func=
|
|
70
|
+
cells = requests.HttpRequest(cellfile, func=cell_reader).data
|
|
71
|
+
layers = requests.HttpRequest(layerfile, func=layer_reader).data
|
|
78
72
|
except requests.SiibraHttpRequestError as e:
|
|
79
73
|
print(str(e))
|
|
80
74
|
commons.logger.error(f"Skipping to bootstrap a {self.__class__.__name__} feature, cannot access file resource.")
|
|
@@ -99,12 +93,3 @@ class LayerwiseCellDensity(
|
|
|
99
93
|
)
|
|
100
94
|
self._data_cached.index.name = 'layer'
|
|
101
95
|
return self._data_cached
|
|
102
|
-
|
|
103
|
-
@property
|
|
104
|
-
def key(self):
|
|
105
|
-
assert len(self.species) == 1
|
|
106
|
-
return commons.create_key("{}_{}_{}".format(
|
|
107
|
-
self.dataset_id,
|
|
108
|
-
self.species[0]['name'],
|
|
109
|
-
self.regionspec
|
|
110
|
-
))
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright 2018-
|
|
1
|
+
# Copyright 2018-2024
|
|
2
2
|
# Institute of Neuroscience and Medicine (INM-1), Forschungszentrum Jülich GmbH
|
|
3
3
|
|
|
4
4
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
@@ -42,7 +42,9 @@ class ReceptorDensityFingerprint(
|
|
|
42
42
|
self,
|
|
43
43
|
tsvfile: str,
|
|
44
44
|
anchor: _anchor.AnatomicalAnchor,
|
|
45
|
-
datasets: list = []
|
|
45
|
+
datasets: list = [],
|
|
46
|
+
id: str = None,
|
|
47
|
+
prerelease: bool = False,
|
|
46
48
|
):
|
|
47
49
|
""" Generate a receptor fingerprint from a URL to a .tsv file
|
|
48
50
|
formatted according to the structure used by Palomero-Gallagher et al.
|
|
@@ -54,6 +56,8 @@ class ReceptorDensityFingerprint(
|
|
|
54
56
|
anchor=anchor,
|
|
55
57
|
data=None, # lazy loading below
|
|
56
58
|
datasets=datasets,
|
|
59
|
+
id=id,
|
|
60
|
+
prerelease=prerelease,
|
|
57
61
|
)
|
|
58
62
|
self._loader = requests.HttpRequest(tsvfile)
|
|
59
63
|
|
|
@@ -170,10 +174,11 @@ class ReceptorDensityFingerprint(
|
|
|
170
174
|
self.data["mean"] + self.data["std"]
|
|
171
175
|
]
|
|
172
176
|
),
|
|
173
|
-
"cat":
|
|
174
|
-
len(self.data) * ["mean"]
|
|
175
|
-
len(self.data) * ["mean - std"]
|
|
176
|
-
len(self.data) * ["mean + std"]
|
|
177
|
+
"cat": (
|
|
178
|
+
len(self.data) * ["mean"]
|
|
179
|
+
+ len(self.data) * ["mean - std"]
|
|
180
|
+
+ len(self.data) * ["mean + std"]
|
|
181
|
+
)
|
|
177
182
|
}
|
|
178
183
|
)
|
|
179
184
|
return line_polar(
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright 2018-
|
|
1
|
+
# Copyright 2018-2024
|
|
2
2
|
# Institute of Neuroscience and Medicine (INM-1), Forschungszentrum Jülich GmbH
|
|
3
3
|
|
|
4
4
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
@@ -41,7 +41,9 @@ class ReceptorDensityProfile(
|
|
|
41
41
|
receptor: str,
|
|
42
42
|
tsvfile: str,
|
|
43
43
|
anchor: _anchor.AnatomicalAnchor,
|
|
44
|
-
datasets: list = []
|
|
44
|
+
datasets: list = [],
|
|
45
|
+
id: str = None,
|
|
46
|
+
prerelease: bool = False,
|
|
45
47
|
):
|
|
46
48
|
"""Generate a receptor density profile from a URL to a .tsv file
|
|
47
49
|
formatted according to the structure used by Palomero-Gallagher et al.
|
|
@@ -52,8 +54,10 @@ class ReceptorDensityProfile(
|
|
|
52
54
|
modality="Receptor density",
|
|
53
55
|
anchor=anchor,
|
|
54
56
|
datasets=datasets,
|
|
57
|
+
id=id,
|
|
58
|
+
prerelease=prerelease
|
|
55
59
|
)
|
|
56
|
-
self.
|
|
60
|
+
self.receptor = receptor
|
|
57
61
|
self._data_cached = None
|
|
58
62
|
self._loader = requests.HttpRequest(tsvfile)
|
|
59
63
|
self._unit_cached = None
|
|
@@ -65,25 +69,18 @@ class ReceptorDensityProfile(
|
|
|
65
69
|
self.id,
|
|
66
70
|
create_key(self.species_name),
|
|
67
71
|
create_key(self.regionspec),
|
|
68
|
-
create_key(self.
|
|
72
|
+
create_key(self.receptor)
|
|
69
73
|
)
|
|
70
74
|
|
|
71
75
|
@property
|
|
72
|
-
def
|
|
73
|
-
return
|
|
74
|
-
self.type,
|
|
75
|
-
vocabularies.RECEPTOR_SYMBOLS[self.type]['receptor']['name'],
|
|
76
|
-
)
|
|
77
|
-
|
|
78
|
-
@property
|
|
79
|
-
def name(self):
|
|
80
|
-
return super().name + f" for {self.type}"
|
|
76
|
+
def receptor_fullname(self):
|
|
77
|
+
return vocabularies.RECEPTOR_SYMBOLS[self.receptor]['receptor']['name']
|
|
81
78
|
|
|
82
79
|
@property
|
|
83
80
|
def neurotransmitter(self):
|
|
84
81
|
return "{} ({})".format(
|
|
85
|
-
vocabularies.RECEPTOR_SYMBOLS[self.
|
|
86
|
-
vocabularies.RECEPTOR_SYMBOLS[self.
|
|
82
|
+
vocabularies.RECEPTOR_SYMBOLS[self.receptor]['neurotransmitter']['label'],
|
|
83
|
+
vocabularies.RECEPTOR_SYMBOLS[self.receptor]['neurotransmitter']['name'],
|
|
87
84
|
)
|
|
88
85
|
|
|
89
86
|
@property
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright 2018-
|
|
1
|
+
# Copyright 2018-2024
|
|
2
2
|
# Institute of Neuroscience and Medicine (INM-1), Forschungszentrum Jülich GmbH
|
|
3
3
|
|
|
4
4
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
@@ -16,13 +16,14 @@
|
|
|
16
16
|
from . import tabular
|
|
17
17
|
from ..feature import Compoundable
|
|
18
18
|
|
|
19
|
+
from ...core import region as _region
|
|
19
20
|
from .. import anchor as _anchor
|
|
20
|
-
from ...commons import QUIET
|
|
21
|
-
from ...locations import
|
|
21
|
+
from ...commons import QUIET, siibra_tqdm
|
|
22
|
+
from ...locations import pointcloud
|
|
22
23
|
from ...retrieval.repositories import RepositoryConnector
|
|
23
24
|
from ...retrieval.requests import HttpRequest
|
|
24
25
|
|
|
25
|
-
from typing import Callable, List
|
|
26
|
+
from typing import Callable, List, Union
|
|
26
27
|
import pandas as pd
|
|
27
28
|
import numpy as np
|
|
28
29
|
|
|
@@ -47,7 +48,9 @@ class RegionalTimeseriesActivity(tabular.Tabular, Compoundable):
|
|
|
47
48
|
timestep: str,
|
|
48
49
|
description: str = "",
|
|
49
50
|
datasets: list = [],
|
|
50
|
-
subject: str = "average"
|
|
51
|
+
subject: str = "average",
|
|
52
|
+
id: str = None,
|
|
53
|
+
prerelease: bool = False,
|
|
51
54
|
):
|
|
52
55
|
"""
|
|
53
56
|
"""
|
|
@@ -57,7 +60,9 @@ class RegionalTimeseriesActivity(tabular.Tabular, Compoundable):
|
|
|
57
60
|
description=description,
|
|
58
61
|
anchor=anchor,
|
|
59
62
|
datasets=datasets,
|
|
60
|
-
data=None # lazy loading below
|
|
63
|
+
data=None, # lazy loading below
|
|
64
|
+
id=id,
|
|
65
|
+
prerelease=prerelease,
|
|
61
66
|
)
|
|
62
67
|
self.cohort = cohort.upper()
|
|
63
68
|
if isinstance(connector, str) and connector:
|
|
@@ -74,12 +79,12 @@ class RegionalTimeseriesActivity(tabular.Tabular, Compoundable):
|
|
|
74
79
|
|
|
75
80
|
@property
|
|
76
81
|
def subject(self):
|
|
77
|
-
"""Returns the subject identifiers for which the
|
|
82
|
+
"""Returns the subject identifiers for which the table represents."""
|
|
78
83
|
return self._subject
|
|
79
84
|
|
|
80
85
|
@property
|
|
81
86
|
def name(self):
|
|
82
|
-
return f"{super().name
|
|
87
|
+
return f"{self.subject} - " + super().name + f" cohort: {self.cohort}"
|
|
83
88
|
|
|
84
89
|
@property
|
|
85
90
|
def data(self) -> pd.DataFrame:
|
|
@@ -90,16 +95,61 @@ class RegionalTimeseriesActivity(tabular.Tabular, Compoundable):
|
|
|
90
95
|
self._load_table()
|
|
91
96
|
return self._table.copy()
|
|
92
97
|
|
|
98
|
+
@classmethod
|
|
99
|
+
def _merge_elements(
|
|
100
|
+
cls,
|
|
101
|
+
elements: List["RegionalTimeseriesActivity"],
|
|
102
|
+
description: str,
|
|
103
|
+
modality: str,
|
|
104
|
+
anchor: _anchor.AnatomicalAnchor,
|
|
105
|
+
):
|
|
106
|
+
assert len({f.cohort for f in elements}) == 1
|
|
107
|
+
assert len({f.timestep for f in elements}) == 1
|
|
108
|
+
merged = cls(
|
|
109
|
+
cohort=elements[0].cohort,
|
|
110
|
+
regions=elements[0].regions,
|
|
111
|
+
connector=elements[0]._connector,
|
|
112
|
+
decode_func=elements[0]._decode_func,
|
|
113
|
+
filename="",
|
|
114
|
+
timestep=" ".join(str(val) for val in elements[0].timestep),
|
|
115
|
+
subject="average",
|
|
116
|
+
description=description,
|
|
117
|
+
modality=modality,
|
|
118
|
+
anchor=anchor,
|
|
119
|
+
**{"paradigm": "average"} if getattr(elements[0], "paradigm") else {}
|
|
120
|
+
)
|
|
121
|
+
if isinstance(elements[0]._connector, HttpRequest):
|
|
122
|
+
getter = lambda elm: elm._connector.get()
|
|
123
|
+
else:
|
|
124
|
+
getter = lambda elm: elm._connector.get(elm._filename, decode_func=elm._decode_func)
|
|
125
|
+
all_arrays = [
|
|
126
|
+
getter(elm)
|
|
127
|
+
for elm in siibra_tqdm(
|
|
128
|
+
elements,
|
|
129
|
+
total=len(elements),
|
|
130
|
+
desc=f"Averaging {len(elements)} activity tables"
|
|
131
|
+
)
|
|
132
|
+
]
|
|
133
|
+
merged._table = elements[0]._arraylike_to_dataframe(
|
|
134
|
+
np.stack(all_arrays).mean(0)
|
|
135
|
+
)
|
|
136
|
+
return merged
|
|
137
|
+
|
|
93
138
|
def _load_table(self):
|
|
94
139
|
"""
|
|
95
140
|
Extract the timeseries table.
|
|
96
141
|
"""
|
|
97
|
-
|
|
142
|
+
if isinstance(self._connector, HttpRequest):
|
|
143
|
+
array = self._connector.data
|
|
144
|
+
else:
|
|
145
|
+
array = self._connector.get(self._filename, decode_func=self._decode_func)
|
|
146
|
+
self._table = self._arraylike_to_dataframe(array)
|
|
147
|
+
|
|
148
|
+
def _arraylike_to_dataframe(self, array: Union[np.ndarray, pd.DataFrame]) -> pd.DataFrame:
|
|
98
149
|
if not isinstance(array, np.ndarray):
|
|
99
|
-
assert isinstance(array, pd.DataFrame)
|
|
100
150
|
array = array.to_numpy()
|
|
101
151
|
ncols = array.shape[1]
|
|
102
|
-
|
|
152
|
+
table = pd.DataFrame(
|
|
103
153
|
array,
|
|
104
154
|
index=pd.TimedeltaIndex(
|
|
105
155
|
np.arange(0, array.shape[0]) * self.timestep[0],
|
|
@@ -120,7 +170,9 @@ class RegionalTimeseriesActivity(tabular.Tabular, Compoundable):
|
|
|
120
170
|
label - min(columnmap.keys()): region
|
|
121
171
|
for label, region in columnmap.items()
|
|
122
172
|
}
|
|
123
|
-
|
|
173
|
+
table = table.rename(columns=remapper)
|
|
174
|
+
|
|
175
|
+
return table
|
|
124
176
|
|
|
125
177
|
def __str__(self):
|
|
126
178
|
return self.name
|
|
@@ -151,14 +203,14 @@ class RegionalTimeseriesActivity(tabular.Tabular, Compoundable):
|
|
|
151
203
|
found = [r for r in region if r.name in all_centroids]
|
|
152
204
|
assert len(found) > 0
|
|
153
205
|
result.append(
|
|
154
|
-
tuple(
|
|
206
|
+
tuple(pointcloud.PointCloud(
|
|
155
207
|
[all_centroids[r.name] for r in found], space=space
|
|
156
208
|
).centroid)
|
|
157
209
|
)
|
|
158
210
|
return result
|
|
159
211
|
|
|
160
212
|
def plot(
|
|
161
|
-
self, regions: List[str] = None, *args,
|
|
213
|
+
self, regions: List[Union[str, "_region.Region"]] = None, *args,
|
|
162
214
|
backend="matplotlib", **kwargs
|
|
163
215
|
):
|
|
164
216
|
"""
|
|
@@ -166,13 +218,15 @@ class RegionalTimeseriesActivity(tabular.Tabular, Compoundable):
|
|
|
166
218
|
|
|
167
219
|
Parameters
|
|
168
220
|
----------
|
|
169
|
-
regions: str
|
|
221
|
+
regions: List[str or Region]
|
|
170
222
|
subject: str, default: None
|
|
171
223
|
If None, returns the subject averaged table.
|
|
172
224
|
args and kwargs:
|
|
173
225
|
takes arguments and keyword arguments for the desired plotting
|
|
174
226
|
backend.
|
|
175
227
|
"""
|
|
228
|
+
if isinstance(regions, (str, _region.Region)):
|
|
229
|
+
regions = [regions]
|
|
176
230
|
if regions is None:
|
|
177
231
|
regions = self.regions
|
|
178
232
|
indices = [self.regions.index(r) for r in regions]
|
|
@@ -181,7 +235,7 @@ class RegionalTimeseriesActivity(tabular.Tabular, Compoundable):
|
|
|
181
235
|
return table.mean().plot(kind="bar", *args, backend=backend, **kwargs)
|
|
182
236
|
|
|
183
237
|
def plot_carpet(
|
|
184
|
-
self, regions: List[str] = None, *args,
|
|
238
|
+
self, regions: List[Union[str, "_region.Region"]] = None, *args,
|
|
185
239
|
backend="plotly", **kwargs
|
|
186
240
|
):
|
|
187
241
|
"""
|
|
@@ -189,7 +243,7 @@ class RegionalTimeseriesActivity(tabular.Tabular, Compoundable):
|
|
|
189
243
|
|
|
190
244
|
Parameters
|
|
191
245
|
----------
|
|
192
|
-
regions: str
|
|
246
|
+
regions: List[str or Region]
|
|
193
247
|
subject: str, default: None
|
|
194
248
|
If None, returns the subject averaged table.
|
|
195
249
|
args and kwargs:
|
|
@@ -197,6 +251,8 @@ class RegionalTimeseriesActivity(tabular.Tabular, Compoundable):
|
|
|
197
251
|
"""
|
|
198
252
|
if backend != "plotly":
|
|
199
253
|
raise NotImplementedError("Currently, carpet plot is only implemented with `plotly`.")
|
|
254
|
+
if isinstance(regions, (str, _region.Region)):
|
|
255
|
+
regions = [regions]
|
|
200
256
|
if regions is None:
|
|
201
257
|
regions = self.regions
|
|
202
258
|
indices = [self.regions.index(r) for r in regions]
|
|
@@ -235,4 +291,4 @@ class RegionalBOLD(
|
|
|
235
291
|
|
|
236
292
|
@property
|
|
237
293
|
def name(self):
|
|
238
|
-
return
|
|
294
|
+
return super().name + f", paradigm: {self.paradigm}"
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright 2018-
|
|
1
|
+
# Copyright 2018-2024
|
|
2
2
|
# Institute of Neuroscience and Medicine (INM-1), Forschungszentrum Jülich GmbH
|
|
3
3
|
|
|
4
4
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
@@ -44,14 +44,18 @@ class Tabular(feature.Feature):
|
|
|
44
44
|
modality: str,
|
|
45
45
|
anchor: _anchor.AnatomicalAnchor,
|
|
46
46
|
data: pd.DataFrame, # sample x feature dimension
|
|
47
|
-
datasets: list = []
|
|
47
|
+
datasets: list = [],
|
|
48
|
+
id: str = None,
|
|
49
|
+
prerelease: bool = False,
|
|
48
50
|
):
|
|
49
51
|
feature.Feature.__init__(
|
|
50
52
|
self,
|
|
51
53
|
modality=modality,
|
|
52
54
|
description=description,
|
|
53
55
|
anchor=anchor,
|
|
54
|
-
datasets=datasets
|
|
56
|
+
datasets=datasets,
|
|
57
|
+
id=id,
|
|
58
|
+
prerelease=prerelease
|
|
55
59
|
)
|
|
56
60
|
self._data_cached = data
|
|
57
61
|
|
|
@@ -59,8 +63,8 @@ class Tabular(feature.Feature):
|
|
|
59
63
|
def data(self):
|
|
60
64
|
return self._data_cached.copy()
|
|
61
65
|
|
|
62
|
-
def
|
|
63
|
-
super().
|
|
66
|
+
def _to_zip(self, fh: ZipFile):
|
|
67
|
+
super()._to_zip(fh)
|
|
64
68
|
fh.writestr("tabular.csv", self.data.to_csv())
|
|
65
69
|
|
|
66
70
|
def plot(self, *args, backend="matplotlib", **kwargs):
|
|
@@ -97,19 +101,24 @@ class Tabular(feature.Feature):
|
|
|
97
101
|
kwargs["width"] = kwargs.get("width", 0.95)
|
|
98
102
|
kwargs["ylabel"] = kwargs.get(
|
|
99
103
|
"ylabel",
|
|
100
|
-
f"{kwargs['y']}{yerr_label} {self.unit if hasattr(self, 'unit') else
|
|
104
|
+
f"{kwargs['y']}{yerr_label}" + f"\n{self.unit}" if hasattr(self, 'unit') else ""
|
|
101
105
|
)
|
|
102
106
|
kwargs["grid"] = kwargs.get("grid", True)
|
|
103
107
|
kwargs["legend"] = kwargs.get("legend", False)
|
|
108
|
+
xticklabel_rotation = kwargs.get("xticklabel_rotation", 60)
|
|
104
109
|
ax = self.data.plot(*args, backend=backend, **kwargs)
|
|
105
110
|
ax.set_title(ax.get_title(), fontsize="medium")
|
|
106
|
-
ax.set_xticklabels(
|
|
111
|
+
ax.set_xticklabels(
|
|
112
|
+
ax.get_xticklabels(),
|
|
113
|
+
rotation=xticklabel_rotation,
|
|
114
|
+
ha='center' if xticklabel_rotation % 90 == 0 else 'right'
|
|
115
|
+
)
|
|
107
116
|
plt.tight_layout()
|
|
108
117
|
return ax
|
|
109
118
|
elif backend == "plotly":
|
|
110
119
|
kwargs["title"] = kwargs["title"].replace("\n", "<br>")
|
|
111
120
|
kwargs["error_y"] = kwargs.get("error_y", 'std' if 'std' in self.data.columns else None)
|
|
112
|
-
error_y_label = f" ± {kwargs.get('error_y')}" if kwargs.get('error_y') else ''
|
|
121
|
+
error_y_label = f" ± {kwargs.get('error_y')}<br>" if kwargs.get('error_y') else ''
|
|
113
122
|
kwargs["labels"] = {
|
|
114
123
|
"index": kwargs.pop("xlabel", None) or kwargs.pop("index", ""),
|
|
115
124
|
"value": kwargs.pop("ylabel", None) or kwargs.pop(
|
siibra/livequeries/__init__.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright 2018-
|
|
1
|
+
# Copyright 2018-2024
|
|
2
2
|
# Institute of Neuroscience and Medicine (INM-1), Forschungszentrum Jülich GmbH
|
|
3
3
|
|
|
4
4
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
@@ -17,9 +17,3 @@
|
|
|
17
17
|
from .allen import AllenBrainAtlasQuery
|
|
18
18
|
from .bigbrain import LayerwiseBigBrainIntensityQuery, BigBrainProfileQuery
|
|
19
19
|
from .ebrains import EbrainsFeatureQuery
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
def warm_cache():
|
|
23
|
-
"""Preload downloadable livequeries."""
|
|
24
|
-
from .bigbrain import WagstylProfileLoader
|
|
25
|
-
WagstylProfileLoader()
|