siibra 0.4a76__py3-none-any.whl → 0.5a1__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/commons.py +3 -2
- siibra/configuration/configuration.py +6 -2
- siibra/configuration/factory.py +48 -27
- siibra/explorer/__init__.py +1 -0
- siibra/explorer/url.py +162 -0
- siibra/explorer/util.py +65 -0
- siibra/features/anchor.py +36 -9
- siibra/features/connectivity/__init__.py +6 -2
- siibra/features/connectivity/functional_connectivity.py +21 -0
- siibra/features/connectivity/regional_connectivity.py +91 -86
- siibra/features/dataset/ebrains.py +1 -1
- siibra/features/feature.py +331 -35
- siibra/features/tabular/bigbrain_intensity_profile.py +5 -2
- siibra/features/tabular/cell_density_profile.py +3 -1
- siibra/features/tabular/cortical_profile.py +14 -10
- siibra/features/tabular/gene_expression.py +0 -2
- siibra/features/tabular/layerwise_bigbrain_intensities.py +3 -2
- siibra/features/tabular/receptor_density_profile.py +7 -1
- siibra/features/tabular/regional_timeseries_activity.py +81 -102
- siibra/features/tabular/tabular.py +21 -9
- siibra/livequeries/bigbrain.py +11 -22
- siibra/locations/__init__.py +65 -1
- siibra/locations/boundingbox.py +0 -16
- siibra/locations/location.py +13 -0
- siibra/locations/pointset.py +1 -3
- siibra/retrieval/cache.py +5 -3
- siibra/retrieval/datasets.py +27 -27
- siibra/volumes/neuroglancer.py +6 -9
- {siibra-0.4a76.dist-info → siibra-0.5a1.dist-info}/METADATA +1 -1
- {siibra-0.4a76.dist-info → siibra-0.5a1.dist-info}/RECORD +34 -31
- {siibra-0.4a76.dist-info → siibra-0.5a1.dist-info}/WHEEL +1 -1
- {siibra-0.4a76.dist-info → siibra-0.5a1.dist-info}/LICENSE +0 -0
- {siibra-0.4a76.dist-info → siibra-0.5a1.dist-info}/top_level.txt +0 -0
|
@@ -14,19 +14,21 @@
|
|
|
14
14
|
# limitations under the License.
|
|
15
15
|
|
|
16
16
|
from zipfile import ZipFile
|
|
17
|
-
from ..feature import Feature
|
|
17
|
+
from ..feature import Feature, Compoundable
|
|
18
18
|
from ..tabular.tabular import Tabular
|
|
19
19
|
|
|
20
20
|
from .. import anchor as _anchor
|
|
21
21
|
|
|
22
|
-
from ...commons import logger, QUIET
|
|
22
|
+
from ...commons import logger, QUIET
|
|
23
23
|
from ...core import region as _region
|
|
24
24
|
from ...locations import pointset
|
|
25
25
|
from ...retrieval.repositories import RepositoryConnector
|
|
26
|
+
from ...retrieval.requests import HttpRequest
|
|
27
|
+
|
|
26
28
|
|
|
27
29
|
import pandas as pd
|
|
28
30
|
import numpy as np
|
|
29
|
-
from typing import Callable,
|
|
31
|
+
from typing import Callable, Union, List
|
|
30
32
|
|
|
31
33
|
try:
|
|
32
34
|
from typing import Literal
|
|
@@ -34,12 +36,15 @@ except ImportError: # support python 3.7
|
|
|
34
36
|
from typing_extensions import Literal
|
|
35
37
|
|
|
36
38
|
|
|
37
|
-
class RegionalConnectivity(Feature):
|
|
39
|
+
class RegionalConnectivity(Feature, Compoundable):
|
|
38
40
|
"""
|
|
39
41
|
Parcellation-averaged connectivity, providing one or more matrices of a
|
|
40
42
|
given modality for a given parcellation.
|
|
41
43
|
"""
|
|
42
44
|
|
|
45
|
+
_filter_attrs = ["modality", "cohort", "subject"]
|
|
46
|
+
_compound_attrs = ["modality", "cohort"]
|
|
47
|
+
|
|
43
48
|
def __init__(
|
|
44
49
|
self,
|
|
45
50
|
cohort: str,
|
|
@@ -47,10 +52,12 @@ class RegionalConnectivity(Feature):
|
|
|
47
52
|
regions: list,
|
|
48
53
|
connector: RepositoryConnector,
|
|
49
54
|
decode_func: Callable,
|
|
50
|
-
|
|
55
|
+
filename: str,
|
|
51
56
|
anchor: _anchor.AnatomicalAnchor,
|
|
52
57
|
description: str = "",
|
|
53
58
|
datasets: list = [],
|
|
59
|
+
subject: str = "average",
|
|
60
|
+
feature: str = None
|
|
54
61
|
):
|
|
55
62
|
"""
|
|
56
63
|
Construct a parcellation-averaged connectivity matrix.
|
|
@@ -81,71 +88,52 @@ class RegionalConnectivity(Feature):
|
|
|
81
88
|
Feature.__init__(
|
|
82
89
|
self,
|
|
83
90
|
modality=modality,
|
|
84
|
-
description=description
|
|
91
|
+
description=description,
|
|
85
92
|
anchor=anchor,
|
|
86
93
|
datasets=datasets,
|
|
87
94
|
)
|
|
88
95
|
self.cohort = cohort.upper()
|
|
89
|
-
|
|
90
|
-
|
|
96
|
+
if isinstance(connector, str) and connector:
|
|
97
|
+
self._connector = HttpRequest(connector, decode_func)
|
|
98
|
+
else:
|
|
99
|
+
self._connector = connector
|
|
100
|
+
self._filename = filename
|
|
91
101
|
self._decode_func = decode_func
|
|
92
102
|
self.regions = regions
|
|
93
|
-
self.
|
|
103
|
+
self._matrix = None
|
|
104
|
+
self._subject = subject
|
|
105
|
+
self._feature = feature
|
|
94
106
|
|
|
95
107
|
@property
|
|
96
|
-
def
|
|
97
|
-
"""
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
108
|
+
def subject(self):
|
|
109
|
+
"""Returns the subject identifiers for which the matrix represents."""
|
|
110
|
+
return self._subject
|
|
111
|
+
|
|
112
|
+
@property
|
|
113
|
+
def feature(self):
|
|
114
|
+
"""If applicable, returns the type of feature for which the matrix represents."""
|
|
115
|
+
return self._feature
|
|
101
116
|
|
|
102
117
|
@property
|
|
103
118
|
def name(self):
|
|
104
|
-
|
|
105
|
-
return f"{supername} with cohort {self.cohort}"
|
|
119
|
+
return f"{super().name} with cohort {self.cohort} - {self.feature or self.subject}"
|
|
106
120
|
|
|
107
|
-
|
|
121
|
+
@property
|
|
122
|
+
def data(self) -> pd.DataFrame:
|
|
108
123
|
"""
|
|
109
124
|
Returns a matrix as a pandas dataframe.
|
|
110
125
|
|
|
111
|
-
Parameters
|
|
112
|
-
----------
|
|
113
|
-
subject: str, default: None
|
|
114
|
-
Name of the subject (see ConnectivityMatrix.subjects for available names).
|
|
115
|
-
If None, the mean is taken in case of multiple available matrices.
|
|
116
126
|
Returns
|
|
117
127
|
-------
|
|
118
128
|
pd.DataFrame
|
|
119
129
|
A square matrix with region names as the column and row names.
|
|
120
130
|
"""
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
)
|
|
128
|
-
if "mean" not in self._matrices:
|
|
129
|
-
all_arrays = [
|
|
130
|
-
self._connector.get(fname, decode_func=self._decode_func)
|
|
131
|
-
for fname in siibra_tqdm(
|
|
132
|
-
self._files.values(),
|
|
133
|
-
total=len(self),
|
|
134
|
-
desc=f"Averaging {len(self)} connectivity matrices"
|
|
135
|
-
)
|
|
136
|
-
]
|
|
137
|
-
self._matrices['mean'] = self._arraylike_to_dataframe(np.stack(all_arrays).mean(0))
|
|
138
|
-
return self._matrices['mean'].copy()
|
|
139
|
-
if subject is None:
|
|
140
|
-
subject = next(iter(self._files.keys()))
|
|
141
|
-
if subject not in self._files:
|
|
142
|
-
raise ValueError(f"Subject name '{subject}' not known, use one of: {', '.join(self._files)}")
|
|
143
|
-
if subject not in self._matrices:
|
|
144
|
-
self._matrices[subject] = self._load_matrix(subject)
|
|
145
|
-
return self._matrices[subject].copy()
|
|
146
|
-
|
|
147
|
-
def plot_matrix(
|
|
148
|
-
self, subject: str = None, regions: List[str] = None,
|
|
131
|
+
if self._matrix is None:
|
|
132
|
+
self._load_matrix()
|
|
133
|
+
return self._matrix.copy()
|
|
134
|
+
|
|
135
|
+
def _plot_matrix(
|
|
136
|
+
self, regions: List[str] = None,
|
|
149
137
|
logscale: bool = False, *args, backend="nilearn", **kwargs
|
|
150
138
|
):
|
|
151
139
|
"""
|
|
@@ -153,10 +141,6 @@ class RegionalConnectivity(Feature):
|
|
|
153
141
|
|
|
154
142
|
Parameters
|
|
155
143
|
----------
|
|
156
|
-
subject: str
|
|
157
|
-
Name of the subject (see ConnectivityMatrix.subjects for available names).
|
|
158
|
-
If "mean" or None is given, the mean is taken in case of multiple
|
|
159
|
-
available matrices.
|
|
160
144
|
regions: list[str]
|
|
161
145
|
Display the matrix only for selected regions. By default, shows all the regions.
|
|
162
146
|
It can only be a subset of regions of the feature.
|
|
@@ -171,16 +155,19 @@ class RegionalConnectivity(Feature):
|
|
|
171
155
|
if regions is None:
|
|
172
156
|
regions = self.regions
|
|
173
157
|
indices = [self.regions.index(r) for r in regions]
|
|
174
|
-
matrix = self.
|
|
158
|
+
matrix = self.data.iloc[indices, indices].to_numpy() # nilearn.plotting.plot_matrix works better with a numpy array
|
|
175
159
|
|
|
176
160
|
if logscale:
|
|
177
161
|
matrix = np.log10(matrix)
|
|
178
162
|
|
|
179
163
|
# default kwargs
|
|
180
|
-
subject_title = subject or ""
|
|
181
164
|
kwargs["title"] = kwargs.get(
|
|
182
165
|
"title",
|
|
183
|
-
|
|
166
|
+
"".join([
|
|
167
|
+
f"{self.feature if self.feature else ''} - {self.subject} - ",
|
|
168
|
+
f"{self.modality} in ",
|
|
169
|
+
f"{', '.join({_.name for _ in self.anchor.regions})}"
|
|
170
|
+
])
|
|
184
171
|
)
|
|
185
172
|
|
|
186
173
|
if kwargs.get("reorder") or (backend == "nilearn"):
|
|
@@ -199,19 +186,16 @@ class RegionalConnectivity(Feature):
|
|
|
199
186
|
f"Plotting connectivity matrices with {backend} is not supported."
|
|
200
187
|
)
|
|
201
188
|
|
|
202
|
-
def __iter__(self):
|
|
203
|
-
return ((sid, self.get_matrix(sid)) for sid in self._files)
|
|
204
|
-
|
|
205
189
|
def _export(self, fh: ZipFile):
|
|
206
190
|
super()._export(fh)
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
191
|
+
if self.feature is None:
|
|
192
|
+
fh.writestr(f"sub/{self._filename}/matrix.csv", self.data.to_csv())
|
|
193
|
+
else:
|
|
194
|
+
fh.writestr(f"feature/{self._filename}/matrix.csv", self.data.to_csv())
|
|
210
195
|
|
|
211
196
|
def get_profile(
|
|
212
197
|
self,
|
|
213
198
|
region: Union[str, _region.Region],
|
|
214
|
-
subject: str = None,
|
|
215
199
|
min_connectivity: float = 0,
|
|
216
200
|
max_rows: int = None,
|
|
217
201
|
direction: Literal['column', 'row'] = 'column'
|
|
@@ -233,7 +217,7 @@ class RegionalConnectivity(Feature):
|
|
|
233
217
|
Choose the direction of profile extraction particularly for
|
|
234
218
|
non-symmetric matrices. ('column' or 'row')
|
|
235
219
|
"""
|
|
236
|
-
matrix = self.
|
|
220
|
+
matrix = self.data
|
|
237
221
|
if direction.lower() not in ['column', 'row']:
|
|
238
222
|
raise ValueError("Direction can only be 'column' or 'row'")
|
|
239
223
|
if direction.lower() == 'row':
|
|
@@ -252,9 +236,7 @@ class RegionalConnectivity(Feature):
|
|
|
252
236
|
elif len(regions) > 1:
|
|
253
237
|
raise ValueError(f"Region specification {region} matched more than one profile: {regions}")
|
|
254
238
|
else:
|
|
255
|
-
name =
|
|
256
|
-
f"Averaged {self.modality}" if subject is None \
|
|
257
|
-
else f"{self.modality}"
|
|
239
|
+
name = self.modality
|
|
258
240
|
series = matrix[regions[0]]
|
|
259
241
|
last_index = len(series) - 1 if max_rows is None \
|
|
260
242
|
else min(max_rows, len(series) - 1)
|
|
@@ -275,10 +257,9 @@ class RegionalConnectivity(Feature):
|
|
|
275
257
|
datasets=self.datasets
|
|
276
258
|
)
|
|
277
259
|
|
|
278
|
-
def
|
|
260
|
+
def plot(
|
|
279
261
|
self,
|
|
280
|
-
|
|
281
|
-
subject: str = None,
|
|
262
|
+
regions: Union[str, _region.Region, List[Union[str, _region.Region]]] = None,
|
|
282
263
|
min_connectivity: float = 0,
|
|
283
264
|
max_rows: int = None,
|
|
284
265
|
direction: Literal['column', 'row'] = 'column',
|
|
@@ -287,7 +268,32 @@ class RegionalConnectivity(Feature):
|
|
|
287
268
|
backend="matplotlib",
|
|
288
269
|
**kwargs
|
|
289
270
|
):
|
|
290
|
-
|
|
271
|
+
"""
|
|
272
|
+
Parameters
|
|
273
|
+
----------
|
|
274
|
+
regions: Union[str, _region.Region], None
|
|
275
|
+
If None, returns the full connectivity matrix.
|
|
276
|
+
If a region is provided, returns the profile for that region.
|
|
277
|
+
If list of regions is provided, returns the matrix for the selected
|
|
278
|
+
regions.
|
|
279
|
+
min_connectivity: float, default 0
|
|
280
|
+
Only for region profile.
|
|
281
|
+
max_rows: int, default None
|
|
282
|
+
Only for region profile.
|
|
283
|
+
direction: 'column' or 'row', default: 'column'
|
|
284
|
+
Only for matrix.
|
|
285
|
+
logscale: bool, default: False
|
|
286
|
+
backend: str, default: "matplotlib" for profiles and "nilearn" for matrices
|
|
287
|
+
"""
|
|
288
|
+
if regions is None or isinstance(regions, list):
|
|
289
|
+
plot_matrix_backend = "nilearn" if backend == "matplotlib" else backend
|
|
290
|
+
return self._plot_matrix(
|
|
291
|
+
regions=regions, logscale=logscale, *args,
|
|
292
|
+
backend=plot_matrix_backend,
|
|
293
|
+
**kwargs
|
|
294
|
+
)
|
|
295
|
+
|
|
296
|
+
profile = self.get_profile(regions, min_connectivity, max_rows, direction)
|
|
291
297
|
kwargs["kind"] = kwargs.get("kind", "barh")
|
|
292
298
|
if backend == "matplotlib":
|
|
293
299
|
kwargs["logx"] = kwargs.get("logx", logscale)
|
|
@@ -299,7 +305,7 @@ class RegionalConnectivity(Feature):
|
|
|
299
305
|
"log_x": logscale,
|
|
300
306
|
"labels": {"y": " ", "x": ""},
|
|
301
307
|
"color_continuous_scale": "jet",
|
|
302
|
-
"width": 600, "height":
|
|
308
|
+
"width": 600, "height": 15 * len(profile.data)
|
|
303
309
|
})
|
|
304
310
|
fig = profile.data.plot(*args, backend=backend, **kwargs)
|
|
305
311
|
fig.update_layout({
|
|
@@ -311,18 +317,14 @@ class RegionalConnectivity(Feature):
|
|
|
311
317
|
"margin": dict(l=0, r=0, b=0, t=0, pad=0)
|
|
312
318
|
})
|
|
313
319
|
return fig
|
|
314
|
-
|
|
320
|
+
else:
|
|
321
|
+
return profile.data.plot(*args, backend=backend, **kwargs)
|
|
315
322
|
|
|
316
323
|
def __len__(self):
|
|
317
|
-
return len(self.
|
|
324
|
+
return len(self._filename)
|
|
318
325
|
|
|
319
326
|
def __str__(self):
|
|
320
|
-
return
|
|
321
|
-
self.paradigm if hasattr(self, "paradigm") else self.modality,
|
|
322
|
-
"_".join(p.name for p in self.anchor.parcellations),
|
|
323
|
-
self.cohort,
|
|
324
|
-
len(self._files),
|
|
325
|
-
)
|
|
327
|
+
return self.name
|
|
326
328
|
|
|
327
329
|
def compute_centroids(self, space):
|
|
328
330
|
"""
|
|
@@ -362,6 +364,7 @@ class RegionalConnectivity(Feature):
|
|
|
362
364
|
"""
|
|
363
365
|
if not isinstance(array, np.ndarray):
|
|
364
366
|
array = array.to_numpy()
|
|
367
|
+
assert array.shape[0] == array.shape[1], f"Connectivity matrices must be square but found {array.shape}"
|
|
365
368
|
if not (array == array.T).all():
|
|
366
369
|
logger.warning("The connectivity matrix is not symmetric.")
|
|
367
370
|
df = pd.DataFrame(array)
|
|
@@ -385,16 +388,18 @@ class RegionalConnectivity(Feature):
|
|
|
385
388
|
raise RuntimeError("Could not decode connectivity matrix regions.")
|
|
386
389
|
return df
|
|
387
390
|
|
|
388
|
-
def _load_matrix(self
|
|
391
|
+
def _load_matrix(self):
|
|
389
392
|
"""
|
|
390
393
|
Extract connectivity matrix.
|
|
391
394
|
"""
|
|
392
|
-
|
|
393
|
-
|
|
395
|
+
if isinstance(self._connector, HttpRequest):
|
|
396
|
+
array = self._connector.data
|
|
397
|
+
else:
|
|
398
|
+
array = self._connector.get(self._filename, decode_func=self._decode_func)
|
|
394
399
|
nrows = array.shape[0]
|
|
395
400
|
if array.shape[1] != nrows:
|
|
396
401
|
raise RuntimeError(
|
|
397
402
|
f"Non-quadratic connectivity matrix {nrows}x{array.shape[1]} "
|
|
398
|
-
f"from {self.
|
|
403
|
+
f"from {self._filename} in {str(self._connector)}"
|
|
399
404
|
)
|
|
400
|
-
|
|
405
|
+
self._matrix = self._arraylike_to_dataframe(array)
|