siibra 1.0a14__py3-none-any.whl → 1.0.1a0__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 +15 -5
- siibra/commons.py +3 -48
- siibra/configuration/__init__.py +1 -1
- siibra/configuration/configuration.py +1 -1
- siibra/configuration/factory.py +164 -127
- siibra/core/__init__.py +1 -1
- siibra/core/assignment.py +1 -1
- siibra/core/atlas.py +24 -17
- siibra/core/concept.py +18 -9
- siibra/core/parcellation.py +76 -55
- siibra/core/region.py +163 -183
- siibra/core/space.py +3 -1
- siibra/core/structure.py +1 -2
- siibra/exceptions.py +17 -1
- siibra/experimental/contour.py +6 -6
- siibra/experimental/patch.py +2 -2
- siibra/experimental/plane3d.py +8 -8
- siibra/explorer/__init__.py +1 -1
- siibra/explorer/url.py +15 -0
- siibra/explorer/util.py +1 -1
- siibra/features/__init__.py +1 -1
- siibra/features/anchor.py +13 -14
- siibra/features/connectivity/__init__.py +1 -1
- siibra/features/connectivity/functional_connectivity.py +1 -1
- siibra/features/connectivity/regional_connectivity.py +7 -5
- 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 +1 -1
- siibra/features/feature.py +50 -28
- siibra/features/image/__init__.py +1 -1
- siibra/features/image/image.py +18 -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 +2 -2
- siibra/features/tabular/cell_density_profile.py +102 -66
- siibra/features/tabular/cortical_profile.py +5 -3
- siibra/features/tabular/gene_expression.py +1 -1
- siibra/features/tabular/layerwise_bigbrain_intensities.py +1 -1
- siibra/features/tabular/layerwise_cell_density.py +8 -25
- siibra/features/tabular/receptor_density_fingerprint.py +5 -3
- siibra/features/tabular/receptor_density_profile.py +5 -3
- siibra/features/tabular/regional_timeseries_activity.py +7 -5
- siibra/features/tabular/tabular.py +5 -3
- siibra/livequeries/__init__.py +1 -1
- siibra/livequeries/allen.py +46 -20
- siibra/livequeries/bigbrain.py +9 -9
- siibra/livequeries/ebrains.py +1 -1
- siibra/livequeries/query.py +1 -2
- siibra/locations/__init__.py +10 -10
- siibra/locations/boundingbox.py +77 -38
- siibra/locations/location.py +12 -4
- siibra/locations/point.py +14 -9
- siibra/locations/{pointset.py → pointcloud.py} +69 -27
- siibra/retrieval/__init__.py +1 -1
- siibra/retrieval/cache.py +1 -1
- siibra/retrieval/datasets.py +1 -1
- siibra/retrieval/exceptions/__init__.py +1 -1
- siibra/retrieval/repositories.py +10 -27
- siibra/retrieval/requests.py +20 -3
- siibra/vocabularies/__init__.py +1 -1
- siibra/volumes/__init__.py +2 -2
- siibra/volumes/parcellationmap.py +121 -94
- siibra/volumes/providers/__init__.py +1 -1
- siibra/volumes/providers/freesurfer.py +1 -1
- siibra/volumes/providers/gifti.py +1 -1
- siibra/volumes/providers/neuroglancer.py +68 -42
- siibra/volumes/providers/nifti.py +18 -28
- siibra/volumes/providers/provider.py +2 -2
- siibra/volumes/sparsemap.py +128 -247
- siibra/volumes/volume.py +252 -65
- {siibra-1.0a14.dist-info → siibra-1.0.1a0.dist-info}/METADATA +17 -4
- siibra-1.0.1a0.dist-info/RECORD +84 -0
- {siibra-1.0a14.dist-info → siibra-1.0.1a0.dist-info}/WHEEL +1 -1
- siibra-1.0a14.dist-info/RECORD +0 -84
- {siibra-1.0a14.dist-info → siibra-1.0.1a0.dist-info}/LICENSE +0 -0
- {siibra-1.0a14.dist-info → siibra-1.0.1a0.dist-info}/top_level.txt +0 -0
siibra/volumes/volume.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");
|
|
@@ -19,10 +19,11 @@ from .providers import provider as _provider
|
|
|
19
19
|
from .. import logger
|
|
20
20
|
from ..retrieval import requests
|
|
21
21
|
from ..core import space as _space, structure
|
|
22
|
-
from ..locations import
|
|
23
|
-
from ..commons import resample_img_to_img, siibra_tqdm
|
|
24
|
-
from ..exceptions import NoMapAvailableError, SpaceWarpingFailedError
|
|
22
|
+
from ..locations import point, pointcloud, boundingbox
|
|
23
|
+
from ..commons import resample_img_to_img, siibra_tqdm, affine_scaling, connected_components
|
|
24
|
+
from ..exceptions import NoMapAvailableError, SpaceWarpingFailedError, EmptyPointCloudError
|
|
25
25
|
|
|
26
|
+
from dataclasses import dataclass
|
|
26
27
|
from nibabel import Nifti1Image
|
|
27
28
|
import numpy as np
|
|
28
29
|
from typing import List, Dict, Union, Set, TYPE_CHECKING
|
|
@@ -36,7 +37,62 @@ if TYPE_CHECKING:
|
|
|
36
37
|
TypeDataset = EbrainsDataset
|
|
37
38
|
|
|
38
39
|
|
|
39
|
-
|
|
40
|
+
@dataclass
|
|
41
|
+
class ComponentSpatialProperties:
|
|
42
|
+
"""
|
|
43
|
+
Centroid and nonzero volume of an image.
|
|
44
|
+
"""
|
|
45
|
+
centroid: point.Point
|
|
46
|
+
volume: int
|
|
47
|
+
|
|
48
|
+
@staticmethod
|
|
49
|
+
def compute_from_image(
|
|
50
|
+
img: Nifti1Image,
|
|
51
|
+
space: Union[str, "_space.Space"],
|
|
52
|
+
split_components: bool = True
|
|
53
|
+
|
|
54
|
+
) -> List["ComponentSpatialProperties"]:
|
|
55
|
+
"""
|
|
56
|
+
Find the center of an image in its (non-zero) voxel space and and its
|
|
57
|
+
volume.
|
|
58
|
+
|
|
59
|
+
Parameters
|
|
60
|
+
----------
|
|
61
|
+
img: Nifti1Image
|
|
62
|
+
space: str, Space
|
|
63
|
+
split_components: bool, default: True
|
|
64
|
+
If True, finds the spatial properties for each connected component
|
|
65
|
+
found by skimage.measure.label.
|
|
66
|
+
"""
|
|
67
|
+
scale = affine_scaling(img.affine)
|
|
68
|
+
if split_components:
|
|
69
|
+
iter_components = lambda img: connected_components(
|
|
70
|
+
np.asanyarray(img.dataobj),
|
|
71
|
+
connectivity=None
|
|
72
|
+
)
|
|
73
|
+
else:
|
|
74
|
+
iter_components = lambda img: [(0, np.asanyarray(img.dataobj))]
|
|
75
|
+
|
|
76
|
+
spatial_props: List[ComponentSpatialProperties] = []
|
|
77
|
+
for _, component in iter_components(img):
|
|
78
|
+
nonzero: np.ndarray = np.c_[np.nonzero(component)]
|
|
79
|
+
spatial_props.append(
|
|
80
|
+
ComponentSpatialProperties(
|
|
81
|
+
centroid=point.Point(
|
|
82
|
+
np.dot(img.affine, np.r_[nonzero.mean(0), 1])[:3],
|
|
83
|
+
space=space
|
|
84
|
+
),
|
|
85
|
+
volume=nonzero.shape[0] * scale,
|
|
86
|
+
)
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
# sort by volume
|
|
90
|
+
spatial_props.sort(key=lambda cmp: cmp.volume, reverse=True)
|
|
91
|
+
|
|
92
|
+
return spatial_props
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
class Volume(structure.BrainStructure):
|
|
40
96
|
"""
|
|
41
97
|
A volume is a specific mesh or 3D array,
|
|
42
98
|
which can be accessible via multiple providers in different formats.
|
|
@@ -77,12 +133,14 @@ class Volume(location.Location):
|
|
|
77
133
|
name: str = "",
|
|
78
134
|
variant: str = None,
|
|
79
135
|
datasets: List['TypeDataset'] = [],
|
|
136
|
+
bbox: "boundingbox.BoundingBox" = None
|
|
80
137
|
):
|
|
81
138
|
self._name = name
|
|
82
139
|
self._space_spec = space_spec
|
|
83
140
|
self.variant = variant
|
|
84
141
|
self._providers: Dict[str, _provider.VolumeProvider] = {}
|
|
85
142
|
self.datasets = datasets
|
|
143
|
+
self._boundingbox = bbox
|
|
86
144
|
for provider in providers:
|
|
87
145
|
srctype = provider.srctype
|
|
88
146
|
assert srctype not in self._providers
|
|
@@ -142,6 +200,22 @@ class Volume(location.Location):
|
|
|
142
200
|
RuntimeError
|
|
143
201
|
If the volume provider does not have a bounding box calculator.
|
|
144
202
|
"""
|
|
203
|
+
if self._boundingbox is not None and len(fetch_kwargs) == 0:
|
|
204
|
+
return self._boundingbox
|
|
205
|
+
|
|
206
|
+
if not self.provides_image:
|
|
207
|
+
raise NotImplementedError("Bounding box calculation of meshes is not implemented yet.")
|
|
208
|
+
|
|
209
|
+
if clip: # clippin requires fetching the image
|
|
210
|
+
img = self.fetch(**fetch_kwargs)
|
|
211
|
+
assert isinstance(img, Nifti1Image)
|
|
212
|
+
return boundingbox.from_array(
|
|
213
|
+
array=np.asanyarray(img.dataobj),
|
|
214
|
+
background=background,
|
|
215
|
+
).transform(img.affine, space=self.space)
|
|
216
|
+
|
|
217
|
+
# if clipping is not required, providers migth have methods of creating
|
|
218
|
+
# bounding boxes without fetching the image
|
|
145
219
|
fmt = fetch_kwargs.get("format")
|
|
146
220
|
if (fmt is not None) and (fmt not in self.formats):
|
|
147
221
|
raise ValueError(
|
|
@@ -151,15 +225,15 @@ class Volume(location.Location):
|
|
|
151
225
|
providers = [self._providers[fmt]] if fmt else self._providers.values()
|
|
152
226
|
for provider in providers:
|
|
153
227
|
try:
|
|
228
|
+
assert clip is False
|
|
154
229
|
bbox = provider.get_boundingbox(
|
|
155
|
-
|
|
230
|
+
background=background, **fetch_kwargs
|
|
156
231
|
)
|
|
157
|
-
if bbox.space is None: # provider
|
|
232
|
+
if bbox.space is None: # provider do not know the space!
|
|
158
233
|
bbox._space_cached = self.space
|
|
159
234
|
bbox.minpoint._space_cached = self.space
|
|
160
235
|
bbox.maxpoint._space_cached = self.space
|
|
161
|
-
except NotImplementedError
|
|
162
|
-
logger.info(e)
|
|
236
|
+
except NotImplementedError:
|
|
163
237
|
continue
|
|
164
238
|
return bbox
|
|
165
239
|
raise RuntimeError(f"No bounding box specified by any volume provider of {str(self)}")
|
|
@@ -214,7 +288,7 @@ class Volume(location.Location):
|
|
|
214
288
|
|
|
215
289
|
def evaluate_points(
|
|
216
290
|
self,
|
|
217
|
-
points: Union['point.Point', '
|
|
291
|
+
points: Union['point.Point', 'pointcloud.PointCloud'],
|
|
218
292
|
outside_value: Union[int, float] = 0,
|
|
219
293
|
**fetch_kwargs
|
|
220
294
|
) -> np.ndarray:
|
|
@@ -233,7 +307,7 @@ class Volume(location.Location):
|
|
|
233
307
|
|
|
234
308
|
Parameters
|
|
235
309
|
----------
|
|
236
|
-
points:
|
|
310
|
+
points: PointCloud
|
|
237
311
|
outside_value: int, float. Default: 0
|
|
238
312
|
fetch_kwargs: dict
|
|
239
313
|
Any additional arguments are passed to the `fetch()` call for
|
|
@@ -253,9 +327,8 @@ class Volume(location.Location):
|
|
|
253
327
|
raise NotImplementedError("Filtering of points by pure mesh volumes not yet implemented.")
|
|
254
328
|
|
|
255
329
|
# make sure the points are in the same physical space as this volume
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
).warp(self.space)
|
|
330
|
+
as_pointcloud = pointcloud.from_points([points]) if isinstance(points, point.Point) else points
|
|
331
|
+
warped = as_pointcloud.warp(self.space)
|
|
259
332
|
assert warped is not None, SpaceWarpingFailedError
|
|
260
333
|
|
|
261
334
|
# get the voxel array of this volume
|
|
@@ -282,57 +355,50 @@ class Volume(location.Location):
|
|
|
282
355
|
|
|
283
356
|
def _points_inside(
|
|
284
357
|
self,
|
|
285
|
-
points: Union['point.Point', '
|
|
358
|
+
points: Union['point.Point', 'pointcloud.PointCloud'],
|
|
286
359
|
keep_labels: bool = True,
|
|
287
360
|
outside_value: Union[int, float] = 0,
|
|
288
361
|
**fetch_kwargs
|
|
289
|
-
) -> '
|
|
362
|
+
) -> 'pointcloud.PointCloud':
|
|
290
363
|
"""
|
|
291
|
-
Reduce a
|
|
364
|
+
Reduce a pointcloud to the points which fall inside nonzero pixels of
|
|
292
365
|
this map.
|
|
293
366
|
|
|
294
367
|
|
|
295
368
|
Paramaters
|
|
296
369
|
----------
|
|
297
|
-
points:
|
|
370
|
+
points: PointCloud
|
|
298
371
|
keep_labels: bool
|
|
299
|
-
If False, the returned
|
|
300
|
-
in the original
|
|
372
|
+
If False, the returned PointCloud will be labeled with their indices
|
|
373
|
+
in the original PointCloud.
|
|
301
374
|
fetch_kwargs: dict
|
|
302
375
|
Any additional arguments are passed to the `fetch()` call for
|
|
303
376
|
retrieving the image data.
|
|
304
377
|
|
|
305
378
|
Returns
|
|
306
379
|
-------
|
|
307
|
-
|
|
308
|
-
A new
|
|
380
|
+
PointCloud
|
|
381
|
+
A new PointCloud containing only the points inside the volume.
|
|
309
382
|
Labels reflect the indices of the original points if `keep_labels`
|
|
310
383
|
is False.
|
|
311
384
|
"""
|
|
312
|
-
ptset =
|
|
385
|
+
ptset = pointcloud.from_points([points]) if isinstance(points, point.Point) else points
|
|
313
386
|
values = self.evaluate_points(ptset, outside_value=outside_value, **fetch_kwargs)
|
|
314
387
|
inside = list(np.where(values != outside_value)[0])
|
|
315
|
-
return
|
|
388
|
+
return pointcloud.from_points(
|
|
316
389
|
[ptset[i] for i in inside],
|
|
317
390
|
newlabels=None if keep_labels else inside
|
|
318
391
|
)
|
|
319
392
|
|
|
320
|
-
def union(self, other: location.Location):
|
|
321
|
-
if isinstance(other, Volume):
|
|
322
|
-
return merge([self, other])
|
|
323
|
-
else:
|
|
324
|
-
raise NotImplementedError(
|
|
325
|
-
f"There are no union method for {(self.__class__.__name__, other.__class__.__name__)}"
|
|
326
|
-
)
|
|
327
|
-
|
|
328
393
|
def intersection(self, other: structure.BrainStructure, **fetch_kwargs) -> structure.BrainStructure:
|
|
329
394
|
"""
|
|
330
395
|
Compute the intersection of a location with this volume. This will
|
|
331
396
|
fetch actual image data. Any additional arguments are passed to fetch.
|
|
332
397
|
"""
|
|
333
|
-
if isinstance(other, (
|
|
334
|
-
|
|
335
|
-
|
|
398
|
+
if isinstance(other, (pointcloud.PointCloud, point.Point)):
|
|
399
|
+
try:
|
|
400
|
+
points_inside = self._points_inside(other, keep_labels=False, **fetch_kwargs)
|
|
401
|
+
except EmptyPointCloudError:
|
|
336
402
|
return None # BrainStructure.intersects checks for not None
|
|
337
403
|
if isinstance(other, point.Point): # preserve the type
|
|
338
404
|
return points_inside[0]
|
|
@@ -340,6 +406,8 @@ class Volume(location.Location):
|
|
|
340
406
|
elif isinstance(other, boundingbox.BoundingBox):
|
|
341
407
|
return self.get_boundingbox(clip=True, background=0.0, **fetch_kwargs).intersection(other)
|
|
342
408
|
elif isinstance(other, Volume):
|
|
409
|
+
if self.space != other.space:
|
|
410
|
+
raise NotImplementedError("Cannot intersect volumes from different spaces. Try comparing their boudning boxes.")
|
|
343
411
|
format = fetch_kwargs.pop('format', 'image')
|
|
344
412
|
v1 = self.fetch(format=format, **fetch_kwargs)
|
|
345
413
|
v2 = other.fetch(format=format, **fetch_kwargs)
|
|
@@ -361,15 +429,6 @@ class Volume(location.Location):
|
|
|
361
429
|
except NoMapAvailableError:
|
|
362
430
|
return None
|
|
363
431
|
|
|
364
|
-
def transform(self, affine: np.ndarray, space=None):
|
|
365
|
-
raise NotImplementedError("Volume transformation is not yet implemented.")
|
|
366
|
-
|
|
367
|
-
def warp(self, space):
|
|
368
|
-
if self.space.matches(space):
|
|
369
|
-
return self
|
|
370
|
-
else:
|
|
371
|
-
raise SpaceWarpingFailedError('Warping of full volumes is not yet supported.')
|
|
372
|
-
|
|
373
432
|
def fetch(
|
|
374
433
|
self,
|
|
375
434
|
format: str = None,
|
|
@@ -416,6 +475,20 @@ class Volume(location.Location):
|
|
|
416
475
|
f"volume are: {self.formats}"
|
|
417
476
|
)
|
|
418
477
|
|
|
478
|
+
# ensure the voi is inside the template
|
|
479
|
+
voi = kwargs.get("voi", None)
|
|
480
|
+
if voi is not None and voi.space is not None:
|
|
481
|
+
assert isinstance(voi, boundingbox.BoundingBox)
|
|
482
|
+
tmplt_bbox = voi.space.get_template().get_boundingbox(clip=False)
|
|
483
|
+
intersection_bbox = voi.intersection(tmplt_bbox)
|
|
484
|
+
if intersection_bbox is None:
|
|
485
|
+
raise RuntimeError(f"voi provided ({voi}) lies out side the voxel space of the {voi.space.name} template.")
|
|
486
|
+
if intersection_bbox != voi:
|
|
487
|
+
logger.info(
|
|
488
|
+
f"Since provided voi lies outside the template ({voi.space}) it is clipped as: {intersection_bbox}"
|
|
489
|
+
)
|
|
490
|
+
kwargs["voi"] = intersection_bbox
|
|
491
|
+
|
|
419
492
|
result = None
|
|
420
493
|
# try each possible format
|
|
421
494
|
for fmt in possible_formats:
|
|
@@ -460,19 +533,37 @@ class Volume(location.Location):
|
|
|
460
533
|
|
|
461
534
|
return self._FETCH_CACHE[fetch_hash]
|
|
462
535
|
|
|
463
|
-
def fetch_connected_components(self, **
|
|
536
|
+
def fetch_connected_components(self, **fetch_kwargs):
|
|
464
537
|
"""
|
|
465
|
-
Provide an
|
|
538
|
+
Provide an generator over masks of connected components in the volume
|
|
466
539
|
"""
|
|
467
|
-
img = self.fetch(**
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
540
|
+
img = self.fetch(**fetch_kwargs)
|
|
541
|
+
assert isinstance(img, Nifti1Image), NotImplementedError(
|
|
542
|
+
f"Connected components for type {type(img)} is not yet implemeneted."
|
|
543
|
+
)
|
|
544
|
+
for label, component in connected_components(np.asanyarray(img.dataobj)):
|
|
545
|
+
yield (
|
|
546
|
+
label,
|
|
547
|
+
Nifti1Image(component, img.affine)
|
|
548
|
+
)
|
|
549
|
+
|
|
550
|
+
def compute_spatial_props(self, split_components: bool = True, **fetch_kwargs) -> List[ComponentSpatialProperties]:
|
|
551
|
+
"""
|
|
552
|
+
Find the center of this volume in its (non-zero) voxel space and and its
|
|
553
|
+
volume.
|
|
554
|
+
|
|
555
|
+
Parameters
|
|
556
|
+
----------
|
|
557
|
+
split_components: bool, default: True
|
|
558
|
+
If True, finds the spatial properties for each connected component
|
|
559
|
+
found by skimage.measure.label.
|
|
560
|
+
"""
|
|
561
|
+
assert self.provides_image, NotImplementedError("Spatial properties can currently on be calculated for images.")
|
|
562
|
+
img = self.fetch(format=fetch_kwargs.pop("format", "image"), **fetch_kwargs)
|
|
563
|
+
return ComponentSpatialProperties.compute_from_image(
|
|
564
|
+
img=img,
|
|
565
|
+
space=self.space,
|
|
566
|
+
split_components=split_components
|
|
476
567
|
)
|
|
477
568
|
|
|
478
569
|
def draw_samples(self, N: int, sample_size: int = 100, e: float = 1, sigma_mm=None, invert=False, **kwargs):
|
|
@@ -502,7 +593,7 @@ class Volume(location.Location):
|
|
|
502
593
|
samples.extend(list(pts[inside, :][choice, :]))
|
|
503
594
|
if len(samples) > N:
|
|
504
595
|
break
|
|
505
|
-
voxels =
|
|
596
|
+
voxels = pointcloud.PointCloud(
|
|
506
597
|
np.random.permutation(samples)[:N, :],
|
|
507
598
|
space=None
|
|
508
599
|
)
|
|
@@ -523,11 +614,96 @@ class Volume(location.Location):
|
|
|
523
614
|
img = self.fetch(**kwargs)
|
|
524
615
|
array = np.asanyarray(img.dataobj)
|
|
525
616
|
voxels = skimage_feature.peak_local_max(array, min_distance=mindist)
|
|
526
|
-
points =
|
|
617
|
+
points = pointcloud.PointCloud(voxels, space=None, labels=list(range(len(voxels)))).transform(img.affine, space=self.space)
|
|
527
618
|
points.sigma_mm = [sigma_mm for _ in points]
|
|
528
619
|
return points
|
|
529
620
|
|
|
530
621
|
|
|
622
|
+
class FilteredVolume(Volume):
|
|
623
|
+
|
|
624
|
+
def __init__(
|
|
625
|
+
self,
|
|
626
|
+
parent_volume: Volume,
|
|
627
|
+
label: int = None,
|
|
628
|
+
fragment: str = None,
|
|
629
|
+
threshold: float = None,
|
|
630
|
+
):
|
|
631
|
+
"""
|
|
632
|
+
A prescribed Volume to fetch specified label and fragment.
|
|
633
|
+
If threshold is defined, a mask of the values above the threshold.
|
|
634
|
+
|
|
635
|
+
Parameters
|
|
636
|
+
----------
|
|
637
|
+
parent_volume : Volume
|
|
638
|
+
label : int, default: None
|
|
639
|
+
Get the mask of value equal to label.
|
|
640
|
+
fragment : str, default None
|
|
641
|
+
If a volume is fragmented, get a specified one.
|
|
642
|
+
threshold : float, default None
|
|
643
|
+
Provide a float value to threshold the image.
|
|
644
|
+
"""
|
|
645
|
+
name = parent_volume.name
|
|
646
|
+
if label:
|
|
647
|
+
name += f" - label: {label}"
|
|
648
|
+
if fragment:
|
|
649
|
+
name += f" - fragment: {fragment}"
|
|
650
|
+
if threshold:
|
|
651
|
+
name += f" - threshold: {threshold}"
|
|
652
|
+
Volume.__init__(
|
|
653
|
+
self,
|
|
654
|
+
space_spec=parent_volume._space_spec,
|
|
655
|
+
providers=list(parent_volume._providers.values()),
|
|
656
|
+
name=name
|
|
657
|
+
)
|
|
658
|
+
self.fragment = fragment
|
|
659
|
+
self.label = label
|
|
660
|
+
self.threshold = threshold
|
|
661
|
+
|
|
662
|
+
def fetch(
|
|
663
|
+
self,
|
|
664
|
+
format: str = None,
|
|
665
|
+
**kwargs
|
|
666
|
+
):
|
|
667
|
+
if "fragment" in kwargs:
|
|
668
|
+
assert kwargs.get("fragment") == self.fragment, f"This is a filtered volume that can only fetch fragment '{self.fragment}'."
|
|
669
|
+
else:
|
|
670
|
+
kwargs["fragment"] = self.fragment
|
|
671
|
+
if "label" in kwargs:
|
|
672
|
+
assert kwargs.get("label") == self.label, f"This is a filtered volume that can only fetch label '{self.label}' only."
|
|
673
|
+
else:
|
|
674
|
+
kwargs["label"] = self.label
|
|
675
|
+
|
|
676
|
+
result = super().fetch(format=format, **kwargs)
|
|
677
|
+
|
|
678
|
+
if self.threshold is not None:
|
|
679
|
+
assert self.label is None
|
|
680
|
+
if not isinstance(result, Nifti1Image):
|
|
681
|
+
raise NotImplementedError("Cannot threshold meshes.")
|
|
682
|
+
imgdata = np.asanyarray(result.dataobj)
|
|
683
|
+
return Nifti1Image(
|
|
684
|
+
dataobj=(imgdata > self.threshold).astype("uint8"),
|
|
685
|
+
affine=result.affine,
|
|
686
|
+
dtype="uint8"
|
|
687
|
+
)
|
|
688
|
+
|
|
689
|
+
return result
|
|
690
|
+
|
|
691
|
+
def get_boundingbox(
|
|
692
|
+
self,
|
|
693
|
+
clip: bool = True,
|
|
694
|
+
background: float = 0.0,
|
|
695
|
+
**fetch_kwargs
|
|
696
|
+
) -> "boundingbox.BoundingBox":
|
|
697
|
+
# NOTE: since some providers enable different simpllified ways to create a
|
|
698
|
+
# bounding box without fetching the image, the correct kwargs must be
|
|
699
|
+
# forwarded since FilteredVolumes enforce their specs to be fetched.
|
|
700
|
+
return super().get_boundingbox(
|
|
701
|
+
clip=clip,
|
|
702
|
+
background=background,
|
|
703
|
+
**fetch_kwargs
|
|
704
|
+
)
|
|
705
|
+
|
|
706
|
+
|
|
531
707
|
class Subvolume(Volume):
|
|
532
708
|
"""
|
|
533
709
|
Wrapper class for exposing a z level of a 4D volume to be used like a 3D volume.
|
|
@@ -540,7 +716,8 @@ class Subvolume(Volume):
|
|
|
540
716
|
providers=[
|
|
541
717
|
_provider.SubvolumeProvider(p, z=z)
|
|
542
718
|
for p in parent_volume._providers.values()
|
|
543
|
-
]
|
|
719
|
+
],
|
|
720
|
+
name=parent_volume.name + f" - z: {z}"
|
|
544
721
|
)
|
|
545
722
|
|
|
546
723
|
|
|
@@ -588,8 +765,8 @@ def from_array(
|
|
|
588
765
|
)
|
|
589
766
|
|
|
590
767
|
|
|
591
|
-
def
|
|
592
|
-
points:
|
|
768
|
+
def from_pointcloud(
|
|
769
|
+
points: pointcloud.PointCloud,
|
|
593
770
|
label: int = None,
|
|
594
771
|
target: Volume = None,
|
|
595
772
|
normalize=True,
|
|
@@ -601,7 +778,7 @@ def from_pointset(
|
|
|
601
778
|
|
|
602
779
|
Parameters
|
|
603
780
|
----------
|
|
604
|
-
points:
|
|
781
|
+
points: pointcloud.PointCloud
|
|
605
782
|
label: int, default: None
|
|
606
783
|
If None, finds the KDE for all points. Otherwise, selects the points
|
|
607
784
|
labelled with this integer value.
|
|
@@ -633,11 +810,11 @@ def from_pointset(
|
|
|
633
810
|
)
|
|
634
811
|
voxelcount_img[tuple(unique_coords.T)] = counts
|
|
635
812
|
|
|
636
|
-
# TODO: consider how to handle
|
|
813
|
+
# TODO: consider how to handle pointclouds with varied sigma_mm
|
|
637
814
|
sigmas = np.array(points.sigma_mm)[selection]
|
|
638
815
|
bandwidth = np.mean(sigmas)
|
|
639
816
|
if len(np.unique(sigmas)) > 1:
|
|
640
|
-
logger.warning(f"KDE of
|
|
817
|
+
logger.warning(f"KDE of pointcloud uses average bandwith {bandwidth} instead of the points' individual sigmas.")
|
|
641
818
|
|
|
642
819
|
filtered_arr = filters.gaussian(voxelcount_img, bandwidth)
|
|
643
820
|
if normalize:
|
|
@@ -653,7 +830,7 @@ def from_pointset(
|
|
|
653
830
|
|
|
654
831
|
def merge(volumes: List[Volume], labels: List[int] = [], **fetch_kwargs) -> Volume:
|
|
655
832
|
"""
|
|
656
|
-
Merge a list of volumes in the same space into a single volume.
|
|
833
|
+
Merge a list of nifti volumes in the same space into a single volume.
|
|
657
834
|
|
|
658
835
|
Note
|
|
659
836
|
----
|
|
@@ -670,6 +847,10 @@ def merge(volumes: List[Volume], labels: List[int] = [], **fetch_kwargs) -> Volu
|
|
|
670
847
|
-------
|
|
671
848
|
Volume
|
|
672
849
|
"""
|
|
850
|
+
if len(volumes) == 1:
|
|
851
|
+
logger.debug("Only one volume supplied returning as is (kwargs are ignored).")
|
|
852
|
+
return volumes[0]
|
|
853
|
+
|
|
673
854
|
assert len(volumes) > 1, "Need to supply at least two volumes to merge."
|
|
674
855
|
if labels:
|
|
675
856
|
assert len(volumes) == len(labels), "Need to supply as many labels as volumes."
|
|
@@ -677,8 +858,14 @@ def merge(volumes: List[Volume], labels: List[int] = [], **fetch_kwargs) -> Volu
|
|
|
677
858
|
space = volumes[0].space
|
|
678
859
|
assert all(v.space == space for v in volumes), "Cannot merge volumes from different spaces."
|
|
679
860
|
|
|
861
|
+
if len(labels) > 0:
|
|
862
|
+
dtype = 'int32'
|
|
863
|
+
elif FilteredVolume in {type(v) for v in volumes}:
|
|
864
|
+
dtype = 'uint8'
|
|
865
|
+
else:
|
|
866
|
+
dtype = volumes[0].fetch().dataobj.dtype
|
|
680
867
|
template_img = space.get_template().fetch(**fetch_kwargs)
|
|
681
|
-
merged_array = np.zeros(template_img.shape, dtype=
|
|
868
|
+
merged_array = np.zeros(template_img.shape, dtype=dtype)
|
|
682
869
|
|
|
683
870
|
for i, vol in siibra_tqdm(
|
|
684
871
|
enumerate(volumes),
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: siibra
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.0.1a0
|
|
4
4
|
Summary: siibra - Software interfaces for interacting with brain atlases
|
|
5
5
|
Home-page: https://github.com/FZJ-INM1-BDA/siibra-python
|
|
6
6
|
Author: Big Data Analytics Group, Forschungszentrum Juelich, Institute of Neuroscience and Medicine (INM-1)
|
|
@@ -24,9 +24,9 @@ Requires-Dist: scikit-image
|
|
|
24
24
|
Requires-Dist: requests
|
|
25
25
|
Requires-Dist: neuroglancer-scripts
|
|
26
26
|
Requires-Dist: nilearn
|
|
27
|
+
Requires-Dist: typing-extensions; python_version < "3.8"
|
|
27
28
|
Requires-Dist: filelock
|
|
28
|
-
Requires-Dist: ebrains-drive
|
|
29
|
-
Requires-Dist: typing-extensions ; python_version < "3.8"
|
|
29
|
+
Requires-Dist: ebrains-drive>=0.6.0
|
|
30
30
|
|
|
31
31
|
|License| |PyPI version| |doi| |Python versions| |Documentation Status|
|
|
32
32
|
|
|
@@ -34,7 +34,7 @@ Requires-Dist: typing-extensions ; python_version < "3.8"
|
|
|
34
34
|
siibra - Software interface for interacting with brain atlases
|
|
35
35
|
==============================================================
|
|
36
36
|
|
|
37
|
-
Copyright 2020-
|
|
37
|
+
Copyright 2020-2024, Forschungszentrum Jülich GmbH
|
|
38
38
|
|
|
39
39
|
*Authors: Big Data Analytics Group, Institute of Neuroscience and
|
|
40
40
|
Medicine (INM-1), Forschungszentrum Jülich GmbH*
|
|
@@ -145,3 +145,16 @@ https://doi.org/10.5281/zenodo.7885728`.
|
|
|
145
145
|
:target: https://siibra-python.readthedocs.io/en/latest/?badge=latest
|
|
146
146
|
.. |doi| image:: https://zenodo.org/badge/DOI/10.5281/zenodo.7885728.svg
|
|
147
147
|
:target: https://doi.org/10.5281/zenodo.7885728
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
Versioning
|
|
151
|
+
==========
|
|
152
|
+
Given a version number MAJOR.MINOR.PATCH, increments imply:
|
|
153
|
+
- MAJOR: incompatible API changes
|
|
154
|
+
- MINOR: a functionality in a backward compatible manner is added
|
|
155
|
+
- PATCH: backward compatible bug fixes and new configuration added such as new maps or features
|
|
156
|
+
|
|
157
|
+
Pre-release
|
|
158
|
+
-----------
|
|
159
|
+
For x.y.z, a full release,
|
|
160
|
+
- `x.y.z-alpha.t` is the development prerelease. By changing `t`, different siibra-configurations are targeted.
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
siibra/VERSION,sha256=obkBMWS4uPgy0Q8o6UWN0GqfjWFwM9_DzViNq5cAX98,14
|
|
2
|
+
siibra/__init__.py,sha256=odym0KtWXn55LqBXZDRgXCzSd5daKXrC0D6lSeYi3po,4715
|
|
3
|
+
siibra/commons.py,sha256=L0tEiZycG0GyDo-KxTeEs8abfTZC98VR_xsDRDdWWNQ,27561
|
|
4
|
+
siibra/exceptions.py,sha256=ruU9IGFBqD52mXUryBF41uE6mDV3kabfSAzUunhCWR8,1319
|
|
5
|
+
siibra/configuration/__init__.py,sha256=Kp00hs44rVSU5OPuZ26KFJpd6HXtMocEiLiZihdvav4,752
|
|
6
|
+
siibra/configuration/configuration.py,sha256=um31WGN0Ozl-3v5bUYECkJEJ5GMrEnrJO3_syUXgzFc,7263
|
|
7
|
+
siibra/configuration/factory.py,sha256=8PoPydqc_4csKF8f-E7Un1QnQ0yKDRgYyO1jbVhKeQU,22627
|
|
8
|
+
siibra/core/__init__.py,sha256=907tEZ3HxZSZqqhv0md3Sk8t9iy0-aWtbuo1G1oxN_w,735
|
|
9
|
+
siibra/core/assignment.py,sha256=9g2lLOj_ftuS623ZlVauTTLtJGAvDfE10wknJXJA7m4,3819
|
|
10
|
+
siibra/core/atlas.py,sha256=BNp96YZ3s6f5MrnuEWL8OktFtM528Dj9Zv6e9FbOAyg,8549
|
|
11
|
+
siibra/core/concept.py,sha256=cmWR2PFdWR3pdVa0NSOiPC-EWl0i_WBjyF3JjKt74gc,10889
|
|
12
|
+
siibra/core/parcellation.py,sha256=AF7yODxdhZZymFNzQdaL2qzSDwkgsogPs74e603Zl_Q,14506
|
|
13
|
+
siibra/core/region.py,sha256=6UDx31FmFYtFQJs5Z0fbpQ2yT9MCh4QCCANIa5GxTXQ,43423
|
|
14
|
+
siibra/core/space.py,sha256=0v_7aERZcVNPJmbr_LbeLRkbJj8TGaTrbqnXzr-I5Jg,4586
|
|
15
|
+
siibra/core/structure.py,sha256=eHvCRBZEDjTI8xc2UmSgt26ujgDxHTLai8NoGmeUU64,4497
|
|
16
|
+
siibra/experimental/__init__.py,sha256=s4bEYpMO4Ox-Xlx3FdnRUNKYs0mTHz5Hu4VnfNXpgxU,791
|
|
17
|
+
siibra/experimental/contour.py,sha256=uZOltesITk5t7EbohZtqA8gJRc3UuiqpJdJQhFP1gXo,2454
|
|
18
|
+
siibra/experimental/cortical_profile_sampler.py,sha256=JsX0FCJqvozdhWuayYJ-r3kHNsgSUfA00O9D0X6D7Rg,2086
|
|
19
|
+
siibra/experimental/patch.py,sha256=0VKVU7F7xMBr1hwtL-Z4K-_1XKw88WImPG4fWaiH5bw,3809
|
|
20
|
+
siibra/experimental/plane3d.py,sha256=XgmNemO9peDRDtHE_8joqroGpjCKI5H_vzyIFXDh434,10853
|
|
21
|
+
siibra/explorer/__init__.py,sha256=ZEBJlKs3r5tFWWoKvfrASb1M031FPwSVeysaktUnhbQ,781
|
|
22
|
+
siibra/explorer/url.py,sha256=1UWJyt18gMKTXuixfO8P1Xa5SJDUUagollow67VYT20,7068
|
|
23
|
+
siibra/explorer/util.py,sha256=lAy1pd-ym90H-BZx2X8GMT3qJIsRTgGCz6tW3t1duig,2083
|
|
24
|
+
siibra/features/__init__.py,sha256=NMmDmfrzscV-RHHZMoyjlH_bYfjNhGDX72dQ6-JCYXg,3970
|
|
25
|
+
siibra/features/anchor.py,sha256=FfeMfJxwApFE0iWo2RJj5_XFr0L5gF76V4ZxaPL2VUc,9130
|
|
26
|
+
siibra/features/feature.py,sha256=ls1E7BjRdPOkbtwzU-d01lwTRA_33IlzB44-tL0tg2g,35194
|
|
27
|
+
siibra/features/connectivity/__init__.py,sha256=A7fcXqlAtfFmuymfyOl7A7ecaP8nqIBPFaM76qwh4HA,1161
|
|
28
|
+
siibra/features/connectivity/functional_connectivity.py,sha256=3UiPpHfbYAOBwMn7TI79wy1fR9lWwI3ePMSRVziJONw,2122
|
|
29
|
+
siibra/features/connectivity/regional_connectivity.py,sha256=13uZ-TJBv_J3J-6KuJcKmJMKf7yWy21pzdsyvcWkWXg,18287
|
|
30
|
+
siibra/features/connectivity/streamline_counts.py,sha256=OBOQblhsqnfsvf2kdySRAoWxGsFi4Ulr2PNT9wOu1Ls,1064
|
|
31
|
+
siibra/features/connectivity/streamline_lengths.py,sha256=B9D6Y7szMRCuHRwisAorgTJfkq-1aTNB08H_HVZHpJs,1067
|
|
32
|
+
siibra/features/connectivity/tracing_connectivity.py,sha256=JehDrEEeYl_i-T81AE_AnamlKfzHkZ3nbheRAybFn24,1083
|
|
33
|
+
siibra/features/dataset/__init__.py,sha256=KlHddELER_5IQ-xQ1xx5ExcEtqXWI8gpNvzGlC2on-Y,748
|
|
34
|
+
siibra/features/dataset/ebrains.py,sha256=G3-jWGBMLyJm3X8g8vTVtXN2Kws3JZ7zIEDkO9jwWxc,2544
|
|
35
|
+
siibra/features/image/__init__.py,sha256=HZ5LdR6DzkkkgsftTu314-DAMMLdf6Sfg6ceYVzYjas,1013
|
|
36
|
+
siibra/features/image/image.py,sha256=QtFtXBt4rRkFq6AHeUOaQSCOjgBygIJ7lhz1gjsQ4c4,3585
|
|
37
|
+
siibra/features/image/sections.py,sha256=oQparLp7Nj5dLBvUAs09rgnSgAxH86wN1SMmwkit0S0,961
|
|
38
|
+
siibra/features/image/volume_of_interest.py,sha256=FuYxt-r6YOWN4tLaaZPL3_GAvX_WcZz3jRHxEnWySnQ,2654
|
|
39
|
+
siibra/features/tabular/__init__.py,sha256=sldsgKiwpGOk5PvntIO16lJlWiTy68qVI_pLhepqbdI,1176
|
|
40
|
+
siibra/features/tabular/bigbrain_intensity_profile.py,sha256=noXtsmQjW75epnpfHex0VAbvz7QLwvlkTn_PLSwASIQ,2708
|
|
41
|
+
siibra/features/tabular/cell_density_profile.py,sha256=W1GtrOCacankczxpkz2V3n9zJyf2WCW3W_BpYrEc6yk,10820
|
|
42
|
+
siibra/features/tabular/cortical_profile.py,sha256=I3MFsytAjvi6A2GaMhgXnF9-94LnAScIo_GR-HMEAv0,12540
|
|
43
|
+
siibra/features/tabular/gene_expression.py,sha256=GbXmsdHCz8eFErTLUd6DXhQaeObftrwl9aIEgzlEdXA,9827
|
|
44
|
+
siibra/features/tabular/layerwise_bigbrain_intensities.py,sha256=GIYjX7_Bfs7ywhJBkXd878BZGSiaKUV0BhILr-6D4zc,2117
|
|
45
|
+
siibra/features/tabular/layerwise_cell_density.py,sha256=V8c16KdBACUYFxMYh1T9tdlXs_V67iFAZqlYx7y_4RY,3783
|
|
46
|
+
siibra/features/tabular/receptor_density_fingerprint.py,sha256=GudVpZ2wWF1yGsDFKz4AEU761qA45rItLOwHYpY4Zcs,7299
|
|
47
|
+
siibra/features/tabular/receptor_density_profile.py,sha256=ZYgL-3WxevVFtmEQSbR8Ot24VCMg5xzfXYEPBH1oM6k,3725
|
|
48
|
+
siibra/features/tabular/regional_timeseries_activity.py,sha256=vfoEIu92l3wVdUbdnNqZ5nr9oBuahOrIGS5xhA8cW7s,10026
|
|
49
|
+
siibra/features/tabular/tabular.py,sha256=NoNexdPJ3nhSsztWdWnnIHcX6PakcjEAOV-f9azqa-s,5323
|
|
50
|
+
siibra/livequeries/__init__.py,sha256=yZ2bFYizwF_Z3F9VLNI95IrHcmSO5lqfFML_juifVHs,875
|
|
51
|
+
siibra/livequeries/allen.py,sha256=2jj1gMr9mZFaOfRSf9lPzrcRLAoAMuWjvT_N3_KUkHI,14809
|
|
52
|
+
siibra/livequeries/bigbrain.py,sha256=V7yRQIx6VLIkA9fwW6PfEw7kSkrwp3oE_-WYXe3bjMk,8365
|
|
53
|
+
siibra/livequeries/ebrains.py,sha256=nAIhyPlVeRPNmmMKkGATUSDRoGK7aAg8zOGEKuS-z_w,5820
|
|
54
|
+
siibra/livequeries/query.py,sha256=Yh24vRdcSYBTNx61sMoRCyXyNZ7TX1iqoiJ8fxOJ3V8,1849
|
|
55
|
+
siibra/locations/__init__.py,sha256=q97HYl9mdBWNuQKvgh1Wi0eAz1TlG_dLSIxpyJuHCZo,3342
|
|
56
|
+
siibra/locations/boundingbox.py,sha256=pdLZNyxUD-WvGHNYOvuqZtputCd5tPOxLYTvH6oBBNg,16492
|
|
57
|
+
siibra/locations/location.py,sha256=Taw7oUIFBdXTE8C3b2vbGicPusJlad_KI1wW6iLL324,4361
|
|
58
|
+
siibra/locations/point.py,sha256=wmtH0Isx1-bsk3TfNxXHFcYUmbsQXBt34l8LpFWxhHU,12863
|
|
59
|
+
siibra/locations/pointcloud.py,sha256=61sUvXw5dtKouNKinQNwgGOFd7iwgJLf4D4zYNWo7Js,12474
|
|
60
|
+
siibra/retrieval/__init__.py,sha256=bgoasCN6LFDlKVFCJC0q4kfGMZCsxt_NVCcJ5qy0sIo,1062
|
|
61
|
+
siibra/retrieval/cache.py,sha256=kVB-hYtvQIQmlCozKlYJPaQxgtCKWOS3jB2qqefCVNc,7832
|
|
62
|
+
siibra/retrieval/datasets.py,sha256=Hjai2cSFK1WoMgXp4uMJWBUqlO_APLQ_iDQ__8EpKEI,11031
|
|
63
|
+
siibra/retrieval/repositories.py,sha256=L-JrEuKF6Xq7sEIdJ3iPFQPWaf5CiHMt96X1zi-gOVM,29936
|
|
64
|
+
siibra/retrieval/requests.py,sha256=oup12LGw-MnSc7c3IwlX9Z5TrVXzCCRfGZFLLLR4jAs,23069
|
|
65
|
+
siibra/retrieval/exceptions/__init__.py,sha256=CEY_n-Eh0_EBXYHDPxmIXzO6C_Km0WQFvENAMvRXmYg,875
|
|
66
|
+
siibra/vocabularies/__init__.py,sha256=Qn_xBKrFhla7d_PjDgN6gX4gxroeSRP3ntBZ6gNnvtE,1288
|
|
67
|
+
siibra/vocabularies/gene_names.json,sha256=i-gnh753GyZtQfX_dWibNYr_d5ccDPHooOwsdeKUYqE,1647972
|
|
68
|
+
siibra/vocabularies/receptor_symbols.json,sha256=F6DZIArPCBmJV_lWGV-zDpBBH_GOJOZm67LBE4qzMa4,5722
|
|
69
|
+
siibra/vocabularies/region_aliases.json,sha256=T2w1wRlxPNTsPppXn0bzC70tNsb8mOjLsoHuxDSYm2w,8563
|
|
70
|
+
siibra/volumes/__init__.py,sha256=j7h6WNQk2juIyxs2OlruWj5VcKxsy1g-wD2Q05rM-wM,935
|
|
71
|
+
siibra/volumes/parcellationmap.py,sha256=lgqVjwHdmjmKj_2PguAH4jda3dc-L0p0QzfQ9emPJRg,49774
|
|
72
|
+
siibra/volumes/sparsemap.py,sha256=ZHkHh7NNEPZzRE2-XGWWPRaVVL2V4voYYzYdZ7RCxRg,17437
|
|
73
|
+
siibra/volumes/volume.py,sha256=-ULibtP5MCy0a3tHqbeFweIUP7sLZGuhj6eW558BRlM,32619
|
|
74
|
+
siibra/volumes/providers/__init__.py,sha256=0uDbnsjlAHnxoSdFghzYfhtjVki9721hi7Sp1P6GjNY,934
|
|
75
|
+
siibra/volumes/providers/freesurfer.py,sha256=LxPHbfVJLXkP4WVXCYhsildRUZUvzgv6jJOWeNLavw8,4893
|
|
76
|
+
siibra/volumes/providers/gifti.py,sha256=mPVFkBFnwbCbMks_ysuNbhe0Pj5ndxONPmq-Xr-ir3w,6231
|
|
77
|
+
siibra/volumes/providers/neuroglancer.py,sha256=JH8z6jb7u6nkqtNR3ZFYPrtwexAS6z68pesrLA2lYrk,28712
|
|
78
|
+
siibra/volumes/providers/nifti.py,sha256=AXhWvbt78uEvIT6Z8ABWZ6k0zYUEWZKniSxfLAqDE3k,10135
|
|
79
|
+
siibra/volumes/providers/provider.py,sha256=jxhOGHrSEeBgN0tAi7p8ju3twtUkhkjrk-e-3-chtxI,3695
|
|
80
|
+
siibra-1.0.1a0.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
81
|
+
siibra-1.0.1a0.dist-info/METADATA,sha256=jY1qR1aP2er68Kb1URFJ-bE4i8ZXYj8wlLviXdlkxlI,8884
|
|
82
|
+
siibra-1.0.1a0.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
|
|
83
|
+
siibra-1.0.1a0.dist-info/top_level.txt,sha256=NF0OSGLL0li2qyC7MaU0iBB5Y9S09_euPpvisD0-8Hg,7
|
|
84
|
+
siibra-1.0.1a0.dist-info/RECORD,,
|