siibra 1.0.1a2__py3-none-any.whl → 1.0.1a5__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 +10 -1
- siibra/configuration/configuration.py +0 -1
- siibra/configuration/factory.py +4 -0
- siibra/core/assignment.py +18 -7
- siibra/explorer/url.py +2 -2
- siibra/features/anchor.py +1 -3
- siibra/features/connectivity/regional_connectivity.py +41 -27
- siibra/features/feature.py +8 -2
- siibra/features/image/__init__.py +2 -1
- siibra/features/image/volume_of_interest.py +9 -0
- siibra/features/tabular/gene_expression.py +28 -11
- siibra/features/tabular/layerwise_cell_density.py +79 -18
- siibra/features/tabular/tabular.py +10 -2
- siibra/livequeries/allen.py +3 -0
- siibra/locations/boundingbox.py +4 -3
- siibra/locations/location.py +10 -4
- siibra/locations/point.py +7 -3
- siibra/locations/pointcloud.py +7 -3
- siibra/volumes/parcellationmap.py +3 -1
- siibra/volumes/sparsemap.py +13 -21
- {siibra-1.0.1a2.dist-info → siibra-1.0.1a5.dist-info}/METADATA +28 -12
- {siibra-1.0.1a2.dist-info → siibra-1.0.1a5.dist-info}/RECORD +26 -26
- {siibra-1.0.1a2.dist-info → siibra-1.0.1a5.dist-info}/WHEEL +1 -1
- {siibra-1.0.1a2.dist-info → siibra-1.0.1a5.dist-info/licenses}/LICENSE +0 -0
- {siibra-1.0.1a2.dist-info → siibra-1.0.1a5.dist-info}/top_level.txt +0 -0
siibra/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
1.0.1-alpha.
|
|
1
|
+
1.0.1-alpha.5
|
siibra/commons.py
CHANGED
|
@@ -534,13 +534,21 @@ def resample_img_to_img(
|
|
|
534
534
|
-------
|
|
535
535
|
Nifti1Image
|
|
536
536
|
"""
|
|
537
|
+
from nilearn._version import version as nilearn_version
|
|
538
|
+
from packaging.version import Version
|
|
539
|
+
|
|
537
540
|
interpolation = "nearest" if np.array_equal(np.unique(source_img.dataobj), [0, 1]) else "linear"
|
|
538
|
-
|
|
541
|
+
kwargs = dict(
|
|
539
542
|
source_img=source_img,
|
|
540
543
|
target_img=target_img,
|
|
541
544
|
interpolation=interpolation,
|
|
542
545
|
force_resample=True, # False is intended for testing. see nilearn docs
|
|
543
546
|
)
|
|
547
|
+
if Version(nilearn_version) >= Version("0.11.0"):
|
|
548
|
+
# because nilearn>=0.11.0 don't support "copy_header" and python <= 3.8
|
|
549
|
+
kwargs["copy_header"] = True # use new default in nilearn >= 0.11.0
|
|
550
|
+
|
|
551
|
+
resampled_img = resample_to_img(**kwargs)
|
|
544
552
|
return resampled_img
|
|
545
553
|
|
|
546
554
|
|
|
@@ -725,6 +733,7 @@ class Species(Enum):
|
|
|
725
733
|
MACACA_MULATTA = 5
|
|
726
734
|
MACACA_FUSCATA = 6
|
|
727
735
|
CHLOROCEBUS_AETHIOPS_SABAEUS = 7
|
|
736
|
+
CALLITHRIX_JACCHUS = 8
|
|
728
737
|
|
|
729
738
|
UNSPECIFIED_SPECIES = 999
|
|
730
739
|
|
siibra/configuration/factory.py
CHANGED
|
@@ -487,6 +487,10 @@ class Factory:
|
|
|
487
487
|
return volume_of_interest.LSFMVolumeOfInterest(
|
|
488
488
|
modality="Light Sheet Fluorescence Microscopy", **kwargs
|
|
489
489
|
)
|
|
490
|
+
elif modality == "morphometry":
|
|
491
|
+
return volume_of_interest.MorphometryVolumeOfInterest(
|
|
492
|
+
modality="Morphometry", **kwargs
|
|
493
|
+
)
|
|
490
494
|
else:
|
|
491
495
|
raise ValueError(
|
|
492
496
|
f"No method for building image section feature type {modality}."
|
siibra/core/assignment.py
CHANGED
|
@@ -26,12 +26,12 @@ T = TypeVar("T")
|
|
|
26
26
|
|
|
27
27
|
class Qualification(Enum):
|
|
28
28
|
EXACT = 1
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
29
|
+
APPROXIMATE = 2
|
|
30
|
+
OTHER_VERSION = 3
|
|
31
|
+
CONTAINED = 4
|
|
32
|
+
CONTAINS = 5
|
|
33
|
+
OVERLAPS = 6
|
|
34
|
+
HOMOLOGOUS = 7
|
|
35
35
|
|
|
36
36
|
@property
|
|
37
37
|
def verb(self):
|
|
@@ -67,6 +67,17 @@ class Qualification(Enum):
|
|
|
67
67
|
assert self in inverses, f"{str(self)} inverses cannot be found."
|
|
68
68
|
return inverses[self]
|
|
69
69
|
|
|
70
|
+
def __lt__(self, other: "Qualification"):
|
|
71
|
+
"""
|
|
72
|
+
This is used to sort feature query results. Since it is very difficult
|
|
73
|
+
to determine a well-ordering principle and it is difficult to sort
|
|
74
|
+
without one, the enum values are used for sorting. This means
|
|
75
|
+
not all comparisons have logical basis but they are well-defined,
|
|
76
|
+
making it reproducible but also clearly distinguishes important
|
|
77
|
+
comparisons.
|
|
78
|
+
"""
|
|
79
|
+
return self.value < other.value
|
|
80
|
+
|
|
70
81
|
def __str__(self):
|
|
71
82
|
return f"{self.__class__.__name__}={self.name.lower()}"
|
|
72
83
|
|
|
@@ -108,4 +119,4 @@ class AnatomicalAssignment(Generic[T]):
|
|
|
108
119
|
def __lt__(self, other: 'AnatomicalAssignment'):
|
|
109
120
|
if not isinstance(other, AnatomicalAssignment):
|
|
110
121
|
raise ValueError(f"Cannot compare AnatomicalAssignment with instances of '{type(other)}'")
|
|
111
|
-
return self.qualification
|
|
122
|
+
return self.qualification < other.qualification
|
siibra/explorer/url.py
CHANGED
|
@@ -136,7 +136,7 @@ def encode_url(
|
|
|
136
136
|
|
|
137
137
|
try:
|
|
138
138
|
result_props = region.spatial_props(space, maptype="labelled")
|
|
139
|
-
if len(result_props
|
|
139
|
+
if len(result_props) == 0:
|
|
140
140
|
return return_url + nav_string.format(encoded_nav=encoded_position or "0.0.0", **zoom_kwargs)
|
|
141
141
|
except Exception as e:
|
|
142
142
|
print(f"Cannot get_spatial_props {str(e)}")
|
|
@@ -144,7 +144,7 @@ def encode_url(
|
|
|
144
144
|
raise e
|
|
145
145
|
return return_url + nav_string.format(encoded_nav=encoded_position or "0.0.0", **zoom_kwargs)
|
|
146
146
|
|
|
147
|
-
centroid = result_props
|
|
147
|
+
centroid = result_props[0].centroid
|
|
148
148
|
|
|
149
149
|
encoded_centroid = separator.join(
|
|
150
150
|
[encode_number(math.floor(val * 1e6)) for val in centroid]
|
siibra/features/anchor.py
CHANGED
|
@@ -176,9 +176,7 @@ class AnatomicalAnchor:
|
|
|
176
176
|
assignments.append(region.assign(concept))
|
|
177
177
|
self._assignments[concept] = sorted(a for a in assignments if a is not None)
|
|
178
178
|
|
|
179
|
-
self._last_matched_concept = concept
|
|
180
|
-
if len(self._assignments[concept]) > 0 \
|
|
181
|
-
else None
|
|
179
|
+
self._last_matched_concept = concept if len(self._assignments[concept]) > 0 else None
|
|
182
180
|
return self._assignments[concept]
|
|
183
181
|
|
|
184
182
|
def matches(self, concept: Union[BrainStructure, Space]) -> bool:
|
|
@@ -104,6 +104,7 @@ class RegionalConnectivity(Feature, Compoundable):
|
|
|
104
104
|
self._matrix = None
|
|
105
105
|
self._subject = subject
|
|
106
106
|
self._feature = feature
|
|
107
|
+
self._matrix_std = None # only used for compound feature
|
|
107
108
|
|
|
108
109
|
@property
|
|
109
110
|
def subject(self):
|
|
@@ -170,6 +171,9 @@ class RegionalConnectivity(Feature, Compoundable):
|
|
|
170
171
|
merged._matrix = elements[0]._arraylike_to_dataframe(
|
|
171
172
|
np.stack(all_arrays).mean(0)
|
|
172
173
|
)
|
|
174
|
+
merged._matrix_std = elements[0]._arraylike_to_dataframe(
|
|
175
|
+
np.stack(all_arrays).std(0)
|
|
176
|
+
)
|
|
173
177
|
return merged
|
|
174
178
|
|
|
175
179
|
def _plot_matrix(
|
|
@@ -258,10 +262,14 @@ class RegionalConnectivity(Feature, Compoundable):
|
|
|
258
262
|
non-symmetric matrices. ('column' or 'row')
|
|
259
263
|
"""
|
|
260
264
|
matrix = self.data
|
|
265
|
+
assert isinstance(matrix, pd.DataFrame)
|
|
266
|
+
matrix_std = self._matrix_std
|
|
261
267
|
if direction.lower() not in ['column', 'row']:
|
|
262
268
|
raise ValueError("Direction can only be 'column' or 'row'")
|
|
263
269
|
if direction.lower() == 'row':
|
|
264
270
|
matrix = matrix.transpose()
|
|
271
|
+
if matrix_std is not None:
|
|
272
|
+
matrix_std = matrix_std.transpose()
|
|
265
273
|
|
|
266
274
|
def matches(r1, r2):
|
|
267
275
|
if isinstance(r1, tuple):
|
|
@@ -270,32 +278,38 @@ class RegionalConnectivity(Feature, Compoundable):
|
|
|
270
278
|
assert isinstance(r1, _region.Region)
|
|
271
279
|
return r1.matches(r2)
|
|
272
280
|
|
|
273
|
-
|
|
274
|
-
if
|
|
281
|
+
# decode region spec
|
|
282
|
+
region_candidates = [r for r in matrix.index if matches(r, region)]
|
|
283
|
+
if len(region_candidates) == 0:
|
|
275
284
|
raise ValueError(f"Invalid region specification: {region}")
|
|
276
|
-
|
|
277
|
-
raise ValueError(f"Region specification {region} matched more than one profile: {
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
285
|
+
if len(region_candidates) > 1:
|
|
286
|
+
raise ValueError(f"Region specification {region} matched more than one profile: {region_candidates}")
|
|
287
|
+
region = region_candidates[0]
|
|
288
|
+
|
|
289
|
+
# create DataFrame
|
|
290
|
+
data = matrix[region].to_frame('mean')
|
|
291
|
+
if matrix_std is not None:
|
|
292
|
+
data = pd.concat([data, matrix_std[region].rename('std')], axis=1)
|
|
293
|
+
|
|
294
|
+
last_index = len(data) if max_rows is None else min(max_rows, len(data))
|
|
295
|
+
|
|
296
|
+
data = (
|
|
297
|
+
data
|
|
298
|
+
.query(f'`mean` > {min_connectivity}')
|
|
299
|
+
.sort_values(by="mean", ascending=False)
|
|
300
|
+
.rename_axis('Target regions')
|
|
301
|
+
)[:last_index]
|
|
302
|
+
|
|
303
|
+
return Tabular(
|
|
304
|
+
description=self.description,
|
|
305
|
+
modality=f"{self.modality} {self.cohort}",
|
|
306
|
+
anchor=_anchor.AnatomicalAnchor(
|
|
307
|
+
species=list(self.anchor.species)[0],
|
|
308
|
+
region=region
|
|
309
|
+
),
|
|
310
|
+
data=data,
|
|
311
|
+
datasets=self.datasets
|
|
312
|
+
)
|
|
299
313
|
|
|
300
314
|
def plot(
|
|
301
315
|
self,
|
|
@@ -336,8 +350,8 @@ class RegionalConnectivity(Feature, Compoundable):
|
|
|
336
350
|
profile = self.get_profile(regions, min_connectivity, max_rows, direction)
|
|
337
351
|
kwargs["kind"] = kwargs.get("kind", "barh")
|
|
338
352
|
if backend == "matplotlib":
|
|
339
|
-
kwargs["
|
|
340
|
-
return profile.
|
|
353
|
+
kwargs["logy"] = kwargs.get("logy", logscale)
|
|
354
|
+
return profile.plot(*args, backend=backend, **kwargs)
|
|
341
355
|
elif backend == "plotly":
|
|
342
356
|
kwargs.update({
|
|
343
357
|
"color": kwargs.get("color", profile.data.columns[0]),
|
siibra/features/feature.py
CHANGED
|
@@ -232,7 +232,10 @@ class Feature:
|
|
|
232
232
|
from ..configuration.configuration import Configuration
|
|
233
233
|
conf = Configuration()
|
|
234
234
|
Configuration.register_cleanup(cls._clean_instances)
|
|
235
|
-
|
|
235
|
+
if cls._configuration_folder not in conf.folders:
|
|
236
|
+
logger.debug(f"{cls._configuration_folder} is not in current configuration")
|
|
237
|
+
return []
|
|
238
|
+
|
|
236
239
|
cls._preconfigured_instances = [
|
|
237
240
|
o for o in conf.build_objects(cls._configuration_folder)
|
|
238
241
|
if isinstance(o, cls)
|
|
@@ -580,7 +583,10 @@ class Feature:
|
|
|
580
583
|
# with the query concept.
|
|
581
584
|
live_instances = feature_type._livequery(concept, **kwargs)
|
|
582
585
|
|
|
583
|
-
results =
|
|
586
|
+
results = sorted(
|
|
587
|
+
dict.fromkeys(preconfigured_instances + live_instances), # to remove duplicates
|
|
588
|
+
key=lambda f: min(f.last_match_result) if f.last_match_result else False, # to order according to assignmnent ranking
|
|
589
|
+
)
|
|
584
590
|
return CompoundFeature._compound(results, concept)
|
|
585
591
|
|
|
586
592
|
@classmethod
|
|
@@ -78,3 +78,12 @@ class LSFMVolumeOfInterest(
|
|
|
78
78
|
):
|
|
79
79
|
def __init__(self, modality, **kwargs):
|
|
80
80
|
image.Image.__init__(self, **kwargs, modality=modality)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
class MorphometryVolumeOfInterest(
|
|
84
|
+
image.Image,
|
|
85
|
+
configuration_folder="features/images/vois/morphometry",
|
|
86
|
+
category="macrostructural"
|
|
87
|
+
):
|
|
88
|
+
def __init__(self, modality, **kwargs):
|
|
89
|
+
image.Image.__init__(self, **kwargs, modality=modality)
|
|
@@ -225,6 +225,7 @@ class GeneExpressions(
|
|
|
225
225
|
datasets=datasets
|
|
226
226
|
)
|
|
227
227
|
self.unit = "expression level"
|
|
228
|
+
self._genes = list(set(genes))
|
|
228
229
|
|
|
229
230
|
def plot(self, *args, backend="matplotlib", **kwargs):
|
|
230
231
|
"""
|
|
@@ -239,18 +240,34 @@ class GeneExpressions(
|
|
|
239
240
|
Keyword arguments are passed on to the plot command.
|
|
240
241
|
"""
|
|
241
242
|
wrapwidth = kwargs.pop("textwrap") if "textwrap" in kwargs else 40
|
|
242
|
-
kwargs["title"] = kwargs.pop(
|
|
243
|
-
|
|
244
|
-
|
|
243
|
+
kwargs["title"] = kwargs.pop(
|
|
244
|
+
"title",
|
|
245
|
+
"\n".join(wrap(
|
|
246
|
+
f"{self.modality}\n{self.anchor._regionspec or self.anchor.location}",
|
|
247
|
+
wrapwidth
|
|
248
|
+
))
|
|
249
|
+
)
|
|
250
|
+
kwargs["kind"] = kwargs.get("kind", "box")
|
|
245
251
|
if backend == "matplotlib":
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
252
|
+
if kwargs["kind"] == "box":
|
|
253
|
+
from matplotlib.pyplot import tight_layout
|
|
254
|
+
|
|
255
|
+
title = kwargs.pop("title")
|
|
256
|
+
default_kwargs = {
|
|
257
|
+
"grid": True,
|
|
258
|
+
'by': "gene",
|
|
259
|
+
'column': ['level'],
|
|
260
|
+
'showfliers': False,
|
|
261
|
+
'ylabel': 'expression level',
|
|
262
|
+
'xlabel': 'gene',
|
|
263
|
+
'color': 'dimgray',
|
|
264
|
+
'rot': 90 if len(self._genes) > 1 else 0,
|
|
265
|
+
}
|
|
266
|
+
ax, *_ = self.data.plot(*args, backend=backend, **{**default_kwargs, **kwargs})
|
|
267
|
+
ax.set_title(title)
|
|
268
|
+
tight_layout()
|
|
269
|
+
return ax
|
|
270
|
+
return self.data.plot(*args, backend=backend, **kwargs)
|
|
254
271
|
elif backend == "plotly":
|
|
255
272
|
kwargs["title"] = kwargs["title"].replace('\n', "<br>")
|
|
256
273
|
return self.data.plot(y='level', x='gene', backend=backend, **kwargs)
|
|
@@ -15,8 +15,8 @@
|
|
|
15
15
|
|
|
16
16
|
import numpy as np
|
|
17
17
|
import pandas as pd
|
|
18
|
+
from textwrap import wrap
|
|
18
19
|
|
|
19
|
-
from . import cortical_profile
|
|
20
20
|
from . import tabular, cell_reader, layer_reader
|
|
21
21
|
from .. import anchor as _anchor
|
|
22
22
|
from ... import commons
|
|
@@ -37,6 +37,7 @@ class LayerwiseCellDensity(
|
|
|
37
37
|
"detected cells in that layer with the area covered by the layer. Therefore, each profile contains 6 measurement points. "
|
|
38
38
|
"The cortical depth is estimated from the measured layer thicknesses."
|
|
39
39
|
)
|
|
40
|
+
BIGBRAIN_VOLUMETRIC_SHRINKAGE_FACTOR = 1.931
|
|
40
41
|
|
|
41
42
|
def __init__(
|
|
42
43
|
self,
|
|
@@ -57,13 +58,13 @@ class LayerwiseCellDensity(
|
|
|
57
58
|
id=id,
|
|
58
59
|
prerelease=prerelease,
|
|
59
60
|
)
|
|
60
|
-
self.unit = "# detected cells/0.
|
|
61
|
+
self.unit = "# detected cells / $0.1mm^3$"
|
|
61
62
|
self._filepairs = list(zip(segmentfiles, layerfiles))
|
|
62
63
|
self._densities = None
|
|
63
64
|
|
|
64
65
|
def _load_densities(self):
|
|
65
|
-
|
|
66
|
-
for
|
|
66
|
+
data = []
|
|
67
|
+
for cellfile, layerfile in self._filepairs:
|
|
67
68
|
try:
|
|
68
69
|
cells = requests.HttpRequest(cellfile, func=cell_reader).data
|
|
69
70
|
layers = requests.HttpRequest(layerfile, func=layer_reader).data
|
|
@@ -72,22 +73,82 @@ class LayerwiseCellDensity(
|
|
|
72
73
|
commons.logger.error(f"Skipping to bootstrap a {self.__class__.__name__} feature, cannot access file resource.")
|
|
73
74
|
continue
|
|
74
75
|
counts = cells.layer.value_counts()
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
76
|
+
# compute the volumetric shrinkage corrections in the same ways as it was used
|
|
77
|
+
# for the pdf reports in the underlying dataset
|
|
78
|
+
shrinkage_volumetric = self.BIGBRAIN_VOLUMETRIC_SHRINKAGE_FACTOR
|
|
79
|
+
layer_volumes = (
|
|
80
|
+
layers["Area(micron**2)"] # this is the number of pixels, shrinkage corrected from the dataset
|
|
81
|
+
* 20 # go to cube micrometer in one patch with 20 micron thickness
|
|
82
|
+
* np.cbrt(shrinkage_volumetric) # compensate linear shrinkage for 3rd dimension
|
|
83
|
+
/ 100 ** 3 # go to 0.1 cube millimeter
|
|
84
|
+
)
|
|
85
|
+
fields = cellfile.split("/")
|
|
86
|
+
for layer in layer_volumes.index:
|
|
87
|
+
data.append({
|
|
88
|
+
'layer': layer,
|
|
89
|
+
'layername': layers["Name"].loc[layer],
|
|
90
|
+
'counts': counts.loc[layer],
|
|
91
|
+
'area_mu2': layers["Area(micron**2)"].loc[layer],
|
|
92
|
+
'volume': layer_volumes.loc[layer],
|
|
93
|
+
'density': counts.loc[layer] / layer_volumes.loc[layer],
|
|
94
|
+
'regionspec': fields[-5],
|
|
95
|
+
'section': int(fields[-3]),
|
|
96
|
+
'patch': int(fields[-2]),
|
|
97
|
+
})
|
|
98
|
+
return pd.DataFrame(data)
|
|
79
99
|
|
|
80
100
|
@property
|
|
81
101
|
def data(self):
|
|
82
102
|
if self._data_cached is None:
|
|
83
|
-
|
|
84
|
-
self._data_cached =
|
|
85
|
-
np.array([
|
|
86
|
-
list(densities.mean(axis=1)),
|
|
87
|
-
list(densities.std(axis=1))
|
|
88
|
-
]).T,
|
|
89
|
-
columns=['mean', 'std'],
|
|
90
|
-
index=[cortical_profile.CorticalProfile.LAYERS[_] for _ in densities.index]
|
|
91
|
-
)
|
|
92
|
-
self._data_cached.index.name = 'layer'
|
|
103
|
+
self._data_cached = self._load_densities()
|
|
104
|
+
# self._data_cached.index.name = 'layer'
|
|
93
105
|
return self._data_cached
|
|
106
|
+
|
|
107
|
+
def plot(self, *args, backend="matplotlib", **kwargs):
|
|
108
|
+
wrapwidth = kwargs.pop("textwrap") if "textwrap" in kwargs else 40
|
|
109
|
+
kwargs["title"] = kwargs.pop(
|
|
110
|
+
"title",
|
|
111
|
+
"\n".join(wrap(
|
|
112
|
+
f"{self.modality} in {self.anchor._regionspec or self.anchor.location}",
|
|
113
|
+
wrapwidth
|
|
114
|
+
))
|
|
115
|
+
)
|
|
116
|
+
kwargs["kind"] = kwargs.get("kind", "box")
|
|
117
|
+
kwargs["ylabel"] = kwargs.get(
|
|
118
|
+
"ylabel",
|
|
119
|
+
f"\n{self.unit}" if hasattr(self, 'unit') else ""
|
|
120
|
+
)
|
|
121
|
+
if backend == "matplotlib":
|
|
122
|
+
if kwargs["kind"] == "box":
|
|
123
|
+
from matplotlib.pyplot import tight_layout
|
|
124
|
+
|
|
125
|
+
np.random.seed(int(self.data["density"].mean()))
|
|
126
|
+
|
|
127
|
+
title = kwargs.pop("title")
|
|
128
|
+
default_kwargs = {
|
|
129
|
+
"grid": True,
|
|
130
|
+
'by': "layername",
|
|
131
|
+
'column': ['density'],
|
|
132
|
+
'showfliers': False,
|
|
133
|
+
'xlabel': 'layer',
|
|
134
|
+
'color': 'dimgray',
|
|
135
|
+
}
|
|
136
|
+
ax, *_ = self.data.plot(*args, backend=backend, **{**default_kwargs, **kwargs})
|
|
137
|
+
for i, (layer, d) in enumerate(self.data.groupby('layername')):
|
|
138
|
+
ax.scatter(
|
|
139
|
+
np.random.normal(i + 1, 0.05, len(d.density)),
|
|
140
|
+
d.density,
|
|
141
|
+
c='b', s=3
|
|
142
|
+
)
|
|
143
|
+
ax.set_title(title)
|
|
144
|
+
tight_layout()
|
|
145
|
+
return ax
|
|
146
|
+
return self.data.plot(*args, backend=backend, **kwargs)
|
|
147
|
+
elif backend == "plotly":
|
|
148
|
+
kwargs["title"] = kwargs["title"].replace('\n', "<br>")
|
|
149
|
+
yaxis_title = kwargs.pop("ylabel")
|
|
150
|
+
fig = self.data.plot(y='density', x='layer', points="all", backend=backend, **kwargs)
|
|
151
|
+
fig.update_layout(yaxis_title=yaxis_title)
|
|
152
|
+
return fig
|
|
153
|
+
else:
|
|
154
|
+
return self.data.plot(*args, backend=backend, **kwargs)
|
|
@@ -99,14 +99,20 @@ class Tabular(feature.Feature):
|
|
|
99
99
|
if kwargs.get("error_y") is None:
|
|
100
100
|
kwargs["yerr"] = kwargs.get("yerr", 'std' if 'std' in self.data.columns else None)
|
|
101
101
|
yerr_label = f" \u00b1 {kwargs.get('yerr')}" if kwargs.get('yerr') else ''
|
|
102
|
-
|
|
102
|
+
if kwargs.get('kind') == 'bar':
|
|
103
|
+
kwargs["width"] = kwargs.get("width", 0.8)
|
|
104
|
+
kwargs["edgecolor"] = kwargs.get('edgecolor', 'black')
|
|
105
|
+
kwargs["linewidth"] = kwargs.get('linewidth', 1.0)
|
|
106
|
+
kwargs["capsize"] = kwargs.get('capsize', 4)
|
|
103
107
|
kwargs["ylabel"] = kwargs.get(
|
|
104
108
|
"ylabel",
|
|
105
109
|
f"{kwargs['y']}{yerr_label}" + f"\n{self.unit}" if hasattr(self, 'unit') else ""
|
|
106
110
|
)
|
|
107
111
|
kwargs["grid"] = kwargs.get("grid", True)
|
|
108
112
|
kwargs["legend"] = kwargs.get("legend", False)
|
|
109
|
-
|
|
113
|
+
kwargs["color"] = kwargs.get('color', 'darkgrey')
|
|
114
|
+
|
|
115
|
+
xticklabel_rotation = kwargs.get("rot", 60)
|
|
110
116
|
ax = self.data.plot(*args, backend=backend, **kwargs)
|
|
111
117
|
ax.set_title(ax.get_title(), fontsize="medium")
|
|
112
118
|
ax.set_xticklabels(
|
|
@@ -114,6 +120,8 @@ class Tabular(feature.Feature):
|
|
|
114
120
|
rotation=xticklabel_rotation,
|
|
115
121
|
ha='center' if xticklabel_rotation % 90 == 0 else 'right'
|
|
116
122
|
)
|
|
123
|
+
ax.spines['top'].set_visible(False)
|
|
124
|
+
ax.spines['right'].set_visible(False)
|
|
117
125
|
plt.tight_layout()
|
|
118
126
|
return ax
|
|
119
127
|
elif backend == "plotly":
|
siibra/livequeries/allen.py
CHANGED
|
@@ -22,6 +22,7 @@ import numpy as np
|
|
|
22
22
|
|
|
23
23
|
from . import query as _query
|
|
24
24
|
from ..core import structure
|
|
25
|
+
from ..core.region import Region
|
|
25
26
|
from ..features import anchor as _anchor
|
|
26
27
|
from ..features.tabular.gene_expression import GeneExpressions
|
|
27
28
|
from ..commons import logger, Species
|
|
@@ -173,6 +174,8 @@ class AllenBrainAtlasQuery(_query.LiveQuery, args=['gene'], FeatureType=GeneExpr
|
|
|
173
174
|
explanation=explanation
|
|
174
175
|
)]
|
|
175
176
|
anchor._last_matched_concept = concept
|
|
177
|
+
if isinstance(concept, Region):
|
|
178
|
+
anchor._regionspec = concept.name
|
|
176
179
|
|
|
177
180
|
return [GeneExpressions(
|
|
178
181
|
anchor=anchor,
|
siibra/locations/boundingbox.py
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
|
|
17
17
|
from itertools import product
|
|
18
18
|
import hashlib
|
|
19
|
-
from typing import TYPE_CHECKING, Union
|
|
19
|
+
from typing import TYPE_CHECKING, Union, Dict
|
|
20
20
|
|
|
21
21
|
import numpy as np
|
|
22
22
|
|
|
@@ -282,14 +282,15 @@ class BoundingBox(location.Location):
|
|
|
282
282
|
sigma_mm=np.mean([self.minpoint.sigma, self.maxpoint.sigma])
|
|
283
283
|
)
|
|
284
284
|
|
|
285
|
-
def warp(self, space):
|
|
285
|
+
def warp(self, space: Union[str, Dict, "Space"]):
|
|
286
286
|
"""Returns a new bounding box obtained by warping the
|
|
287
287
|
min- and maxpoint of this one into the new target space.
|
|
288
288
|
|
|
289
289
|
TODO process the sigma values o the points
|
|
290
290
|
"""
|
|
291
291
|
from ..core.space import Space
|
|
292
|
-
|
|
292
|
+
|
|
293
|
+
spaceobj = space if isinstance(space, Space) else Space.get_instance(space)
|
|
293
294
|
if spaceobj == self.space:
|
|
294
295
|
return self
|
|
295
296
|
else:
|
siibra/locations/location.py
CHANGED
|
@@ -45,18 +45,24 @@ class Location(BrainStructure):
|
|
|
45
45
|
_MASK_MEMO = {} # cache region masks for Location._assign_region()
|
|
46
46
|
_ASSIGNMENT_CACHE = {} # caches assignment results, see Region.assign()
|
|
47
47
|
|
|
48
|
-
def __init__(self, spacespec: Union[str, Dict[str, str],
|
|
48
|
+
def __init__(self, spacespec: Union[str, Dict[str, str], _space.Space]):
|
|
49
49
|
self._space_spec = spacespec
|
|
50
50
|
self._space_cached = None
|
|
51
51
|
|
|
52
52
|
@property
|
|
53
|
-
def space(self) ->
|
|
53
|
+
def space(self) -> _space.Space:
|
|
54
54
|
if self._space_cached is None:
|
|
55
|
-
if
|
|
55
|
+
if self._space_spec is None:
|
|
56
|
+
return None
|
|
57
|
+
elif isinstance(self._space_spec, _space.Space):
|
|
58
|
+
self._space_cached = self._space_spec
|
|
59
|
+
elif isinstance(self._space_spec, dict):
|
|
56
60
|
spec = self._space_spec.get("@id") or self._space_spec.get("name")
|
|
57
61
|
self._space_cached = _space.Space.get_instance(spec)
|
|
58
|
-
|
|
62
|
+
elif isinstance(self._space_spec, str):
|
|
59
63
|
self._space_cached = _space.Space.get_instance(self._space_spec)
|
|
64
|
+
else:
|
|
65
|
+
raise ValueError(f"Invalid space spec type: '{type(self._space_spec)}'")
|
|
60
66
|
return self._space_cached
|
|
61
67
|
|
|
62
68
|
@abstractmethod
|
siibra/locations/point.py
CHANGED
|
@@ -19,7 +19,7 @@ import re
|
|
|
19
19
|
import json
|
|
20
20
|
import numbers
|
|
21
21
|
import hashlib
|
|
22
|
-
from typing import Tuple, Union
|
|
22
|
+
from typing import Tuple, Union, Dict, TYPE_CHECKING
|
|
23
23
|
|
|
24
24
|
import numpy as np
|
|
25
25
|
|
|
@@ -28,6 +28,9 @@ from ..commons import logger
|
|
|
28
28
|
from ..retrieval.requests import HttpRequest
|
|
29
29
|
from ..exceptions import SpaceWarpingFailedError, NoneCoordinateSuppliedError
|
|
30
30
|
|
|
31
|
+
if TYPE_CHECKING:
|
|
32
|
+
from ..core.space import Space
|
|
33
|
+
|
|
31
34
|
|
|
32
35
|
class Point(location.Location):
|
|
33
36
|
"""A single 3D point in reference space."""
|
|
@@ -118,13 +121,14 @@ class Point(location.Location):
|
|
|
118
121
|
else:
|
|
119
122
|
return self if other.intersection(self) else None
|
|
120
123
|
|
|
121
|
-
def warp(self, space):
|
|
124
|
+
def warp(self, space: Union[str, Dict, "Space"]):
|
|
122
125
|
"""
|
|
123
126
|
Creates a new point by warping this point to another space
|
|
124
127
|
TODO this needs to maintain the sigma parameter!
|
|
125
128
|
"""
|
|
126
129
|
from ..core.space import Space
|
|
127
|
-
|
|
130
|
+
|
|
131
|
+
spaceobj = space if isinstance(space, Space) else Space.get_instance(space)
|
|
128
132
|
if spaceobj == self.space:
|
|
129
133
|
return self
|
|
130
134
|
if any(_ not in location.Location.SPACEWARP_IDS for _ in [self.space.id, spaceobj.id]):
|
siibra/locations/pointcloud.py
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
# limitations under the License.
|
|
15
15
|
"""A set of coordinates on a reference space."""
|
|
16
16
|
|
|
17
|
-
from typing import List, Union, Tuple
|
|
17
|
+
from typing import List, Union, Tuple, Dict, TYPE_CHECKING
|
|
18
18
|
import numbers
|
|
19
19
|
import json
|
|
20
20
|
|
|
@@ -31,6 +31,9 @@ from ..retrieval.requests import HttpRequest
|
|
|
31
31
|
from ..commons import logger
|
|
32
32
|
from ..exceptions import SpaceWarpingFailedError, EmptyPointCloudError
|
|
33
33
|
|
|
34
|
+
if TYPE_CHECKING:
|
|
35
|
+
from ..core.space import Space
|
|
36
|
+
|
|
34
37
|
|
|
35
38
|
def from_points(points: List["point.Point"], newlabels: List[Union[int, float, tuple]] = None) -> "PointCloud":
|
|
36
39
|
"""
|
|
@@ -140,9 +143,10 @@ class PointCloud(location.Location):
|
|
|
140
143
|
def has_constant_sigma(self) -> bool:
|
|
141
144
|
return len(set(self.sigma)) == 1
|
|
142
145
|
|
|
143
|
-
def warp(self, space, chunksize=1000):
|
|
146
|
+
def warp(self, space: Union[str, Dict, "Space"], chunksize: int = 1000):
|
|
144
147
|
"""Creates a new point set by warping its points to another space"""
|
|
145
148
|
from ..core.space import Space
|
|
149
|
+
|
|
146
150
|
spaceobj = space if isinstance(space, Space) else Space.get_instance(space)
|
|
147
151
|
if spaceobj == self.space:
|
|
148
152
|
return self
|
|
@@ -354,7 +358,7 @@ class Contour(PointCloud):
|
|
|
354
358
|
def __init__(self, coordinates, space=None, sigma_mm=0, labels: list = None):
|
|
355
359
|
PointCloud.__init__(self, coordinates, space, sigma_mm, labels)
|
|
356
360
|
|
|
357
|
-
def crop(self, voi: "_boundingbox.BoundingBox"):
|
|
361
|
+
def crop(self, voi: "_boundingbox.BoundingBox") -> List["Contour"]:
|
|
358
362
|
"""
|
|
359
363
|
Crop the contour with a volume of interest.
|
|
360
364
|
Since the contour might be split from the cropping,
|
|
@@ -761,10 +761,12 @@ class Map(concept.AtlasConcept, configuration_folder="maps"):
|
|
|
761
761
|
f"{no_predefined_color}"
|
|
762
762
|
)
|
|
763
763
|
|
|
764
|
+
max_label_index = max(index[0].label for index in self._indices.values())
|
|
765
|
+
|
|
764
766
|
palette = np.array(
|
|
765
767
|
[
|
|
766
768
|
list(colors[i]) + [1] if i in colors else [0, 0, 0, 0]
|
|
767
|
-
for i in range(
|
|
769
|
+
for i in range(max_label_index + 1)
|
|
768
770
|
]
|
|
769
771
|
) / [255, 255, 255, 1]
|
|
770
772
|
return ListedColormap(palette)
|
siibra/volumes/sparsemap.py
CHANGED
|
@@ -18,11 +18,10 @@ from os import path, makedirs
|
|
|
18
18
|
from typing import Dict, List
|
|
19
19
|
|
|
20
20
|
import numpy as np
|
|
21
|
-
from nilearn import image
|
|
22
21
|
|
|
23
22
|
from . import parcellationmap, volume as _volume
|
|
24
23
|
from .providers import provider
|
|
25
|
-
from ..commons import MapIndex, logger, connected_components, siibra_tqdm
|
|
24
|
+
from ..commons import MapIndex, logger, connected_components, siibra_tqdm, resample_img_to_img
|
|
26
25
|
from ..locations import boundingbox
|
|
27
26
|
from ..retrieval.cache import CACHE
|
|
28
27
|
from ..retrieval.requests import HttpRequest, FileLoader
|
|
@@ -353,30 +352,23 @@ class SparseMap(parcellationmap.Map):
|
|
|
353
352
|
split_components: bool, default: True
|
|
354
353
|
Whether to split the query volume into disjoint components.
|
|
355
354
|
"""
|
|
355
|
+
from nibabel import Nifti1Image
|
|
356
|
+
|
|
356
357
|
queryimg = queryvolume.fetch()
|
|
357
|
-
|
|
358
|
-
imgaffine = queryimg.affine
|
|
358
|
+
assert isinstance(queryimg, Nifti1Image)
|
|
359
359
|
assignments = []
|
|
360
360
|
|
|
361
|
-
# resample query image into this image's voxel space, if required
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
interp = "nearest"
|
|
367
|
-
else:
|
|
368
|
-
interp = "linear"
|
|
369
|
-
from nibabel import Nifti1Image
|
|
370
|
-
queryimg = image.resample_img(
|
|
371
|
-
Nifti1Image(imgdata, imgaffine),
|
|
372
|
-
target_affine=self.affine,
|
|
373
|
-
target_shape=self.shape,
|
|
374
|
-
interpolation=interp,
|
|
361
|
+
# resample query image into this image's voxel space, if required (nilearn checks)
|
|
362
|
+
queryimg = resample_img_to_img(
|
|
363
|
+
source_img=queryimg,
|
|
364
|
+
target_img=Nifti1Image(
|
|
365
|
+
np.zeros(self.shape), affine=self.affine, dtype=queryimg.dataobj.dtype
|
|
375
366
|
)
|
|
376
|
-
|
|
367
|
+
)
|
|
368
|
+
self.space.get_template()
|
|
369
|
+
querydata = np.asanyarray(queryimg.dataobj).squeeze()
|
|
377
370
|
|
|
378
|
-
iter_func = connected_components if split_components
|
|
379
|
-
else lambda img: [(1, img)]
|
|
371
|
+
iter_func = connected_components if split_components else lambda img: [(1, img)]
|
|
380
372
|
|
|
381
373
|
for mode, modemask in iter_func(querydata):
|
|
382
374
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: siibra
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.1a5
|
|
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)
|
|
@@ -33,6 +33,7 @@ Dynamic: classifier
|
|
|
33
33
|
Dynamic: description
|
|
34
34
|
Dynamic: description-content-type
|
|
35
35
|
Dynamic: home-page
|
|
36
|
+
Dynamic: license-file
|
|
36
37
|
Dynamic: requires-dist
|
|
37
38
|
Dynamic: requires-python
|
|
38
39
|
Dynamic: summary
|
|
@@ -43,18 +44,16 @@ Dynamic: summary
|
|
|
43
44
|
siibra - Software interface for interacting with brain atlases
|
|
44
45
|
==============================================================
|
|
45
46
|
|
|
46
|
-
Copyright 2018-
|
|
47
|
+
Copyright 2018-2025, Forschungszentrum Jülich GmbH
|
|
47
48
|
|
|
48
49
|
*Authors: Big Data Analytics Group, Institute of Neuroscience and
|
|
49
50
|
Medicine (INM-1), Forschungszentrum Jülich GmbH*
|
|
50
51
|
|
|
51
52
|
.. intro-start
|
|
52
53
|
|
|
53
|
-
``siibra`` is a Python client to a brain atlas framework that integrates brain parcellations and reference spaces at different spatial scales, and connects them with a broad range of multimodal regional data features.
|
|
54
|
+
``siibra-python`` is a Python client to a brain atlas framework that integrates brain parcellations and reference spaces at different spatial scales, and connects them with a broad range of multimodal regional data features.
|
|
54
55
|
It aims to facilitate programmatic and reproducible incorporation of brain parcellations and brain region features from different sources into neuroscience workflows.
|
|
55
56
|
|
|
56
|
-
**Note:** ``siibra-python`` *is still in development. While care is taken that it works reliably, its API is not yet stable and you may still encounter bugs when using it.*
|
|
57
|
-
|
|
58
57
|
``siibra`` provides structured access to parcellation schemes in different brain reference spaces, including volumetric reference templates at macroscopic and microscopic resolutions as well as surface representations.
|
|
59
58
|
It supports both discretely labelled and statistical (probabilistic) parcellation maps, which can be used to assign brain regions to spatial locations and image signals, to retrieve region-specific neuroscience datasets from multiple online repositories, and to sample information from high-resolution image data.
|
|
60
59
|
The datasets anchored to brain regions address features of molecular, cellular and architecture as well as connectivity, and are complemented with live queries to external repositories as well as dynamic extraction from "big" image volumes such as the 20 micrometer BigBrain model.
|
|
@@ -84,10 +83,26 @@ Installation
|
|
|
84
83
|
|
|
85
84
|
``siibra`` is available on pypi.
|
|
86
85
|
To install the latest released version, simply run ``pip install siibra``.
|
|
86
|
+
The installation typically takes about 2 minutes on a standard computer where Python is already installed.
|
|
87
87
|
In order to work with the latest version from github, use ``pip install git+https://github.com/FZJ-INM1-BDA/siibra-python.git@main``.
|
|
88
88
|
|
|
89
|
-
|
|
90
|
-
|
|
89
|
+
``siibra-python`` should be installable on recent versions of Windows, Linux and Mac OS in a recent Python 3 environment.
|
|
90
|
+
We run continuous integration tests for versions 3.7 - 3.12 on recent Ubuntu images.
|
|
91
|
+
|
|
92
|
+
The library requires a couple of open source packages, namely:
|
|
93
|
+
```
|
|
94
|
+
anytree >= 2.12.1
|
|
95
|
+
nibabel >= 5.3.2
|
|
96
|
+
appdirs >= 1.4.4
|
|
97
|
+
scikit-image >= 0.25.0
|
|
98
|
+
requests >= 2.32.3
|
|
99
|
+
neuroglancer-scripts >= 1.2.0
|
|
100
|
+
nilearn >= 0.11.0
|
|
101
|
+
filelock >= 3.16.1
|
|
102
|
+
ebrains-drive >= 0.6.0
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
You can also install a docker image with all dependencies included:
|
|
91
106
|
.. code-block:: sh
|
|
92
107
|
|
|
93
108
|
docker run -dit \
|
|
@@ -97,19 +112,20 @@ There is also an image based on jupyter:scipy-notebook, which already includes `
|
|
|
97
112
|
docker-registry.ebrains.eu/siibra/siibra-python:latest
|
|
98
113
|
|
|
99
114
|
|
|
115
|
+
|
|
100
116
|
Documentation & Help
|
|
101
117
|
====================
|
|
102
118
|
|
|
103
119
|
``siibra-python``\ ’s documentation is hosted on https://siibra-python.readthedocs.io.
|
|
104
120
|
The documentation includes a catalogue of documented code examples that walk you through the different concepts and functionalities.
|
|
121
|
+
These examples use real data and include both the code and the produced expected outputs.
|
|
122
|
+
They can be accessed at https://siibra-python.readthedocs.io/en/latest/examples.html, and are
|
|
123
|
+
automatically tested and updated whenever a new version of ``siibra-python`` is published.
|
|
105
124
|
As a new user, it is recommended to go through these examples - they are easy and will quickly provide you with the right code snippets that get you started.
|
|
106
|
-
|
|
107
|
-
We are working on a full API documentation of the library. You find the current status on readthedocs, but be aware that it is not yet complete and as up-to-date as the code examples.
|
|
125
|
+
The documentation on readthedocs further includes introductory explanations and an API reference.
|
|
108
126
|
|
|
109
127
|
If you run into issues, please open a ticket on `EBRAINS support <https://ebrains.eu/support/>`__ or file bugs and
|
|
110
128
|
feature requests on `github <https://github.com/FZJ-INM1-BDA/siibra-python/issues>`__.
|
|
111
|
-
Please keep in mind that ``siibra-python`` is still in development.
|
|
112
|
-
While care is taken to make everything work reliably, the API of the library is not yet stable, and the software is not yet fully tested.
|
|
113
129
|
|
|
114
130
|
.. getting-started-end
|
|
115
131
|
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
siibra/VERSION,sha256=
|
|
1
|
+
siibra/VERSION,sha256=ipm-gM9pHLEb5l5Cx8ZcZ8wKJBYKiaWH87grIEoJ_OM,14
|
|
2
2
|
siibra/__init__.py,sha256=1uWhsE93KG4N9wiWoMdEokUXxfoRcyznXDktjAGhpEI,4496
|
|
3
|
-
siibra/commons.py,sha256=
|
|
3
|
+
siibra/commons.py,sha256=KmbRdX6pfKTgIgbYufxhkE9YiLQ35GObbw6VyFdRm_w,28016
|
|
4
4
|
siibra/exceptions.py,sha256=6MlXOadwXcCsceOE4lmy4fLJyAaBCCVvJF6BZlMYjU8,1371
|
|
5
5
|
siibra/configuration/__init__.py,sha256=ArqQ_B8C_O61KA4Fk3ho8ksckbjLu-COOlPGiXyf8LE,752
|
|
6
|
-
siibra/configuration/configuration.py,sha256=
|
|
7
|
-
siibra/configuration/factory.py,sha256=
|
|
6
|
+
siibra/configuration/configuration.py,sha256=A651Tg632_a_c_yjxs-FJW_douQyzSJBoCDad4expVk,7151
|
|
7
|
+
siibra/configuration/factory.py,sha256=srhxxOAW_qyfe7oIFfuiX6gviou5CRfle5DVKe8FtB0,22798
|
|
8
8
|
siibra/core/__init__.py,sha256=zW887SH2txImUfvU80k83NbxxnlHlbdzBjdryY-3-48,766
|
|
9
|
-
siibra/core/assignment.py,sha256=
|
|
9
|
+
siibra/core/assignment.py,sha256=aSzunUMKVVE0wl_2qEK_NryQIoV8_qMV5t3MBmkdEo8,4310
|
|
10
10
|
siibra/core/atlas.py,sha256=Iwqgcf8sG8_iL4mlw_4Nzi7HWVR-wxYLESqnIS0CFTw,8549
|
|
11
11
|
siibra/core/concept.py,sha256=rLqgJ72Mt1Mc8mlh-bGYOyq65rV7Vc8vCZGs-amJp1w,10891
|
|
12
12
|
siibra/core/parcellation.py,sha256=JzrnoB8G0XupffP8mnwE3oHYmHjo2Mzn4-pXnZ2R6Ow,14480
|
|
@@ -14,45 +14,45 @@ siibra/core/region.py,sha256=036Fjck1H6wGSubJomjEHUN1I-XMPSPqx3_78MEYbG8,44108
|
|
|
14
14
|
siibra/core/space.py,sha256=X7FyKgdhao3ezSWQZ0MAjDxlQh305S-4a4D630RaM-c,4588
|
|
15
15
|
siibra/core/structure.py,sha256=M2li4PPiJf27dOc3b2ycCfHf7Ad1AWxBYc9OpSFazJM,4498
|
|
16
16
|
siibra/explorer/__init__.py,sha256=XBAeYm4W3HlbWsKtt8gOwqE_FinIEY7RdA6Rg4Y275A,781
|
|
17
|
-
siibra/explorer/url.py,sha256=
|
|
17
|
+
siibra/explorer/url.py,sha256=S6Tpg1p2gmu5byHVqsXfkugUStLd1Fu94EqsDzgEU9E,7047
|
|
18
18
|
siibra/explorer/util.py,sha256=ul82TQZAULdupr4tJBACdkjlHm2mt8LJ9UpwNWGHYhE,2083
|
|
19
19
|
siibra/features/__init__.py,sha256=FER6DMnkPhXSV1XMZWibZdyBwVhIgWYSUGYMEYEKb9c,3970
|
|
20
|
-
siibra/features/anchor.py,sha256=
|
|
21
|
-
siibra/features/feature.py,sha256=
|
|
20
|
+
siibra/features/anchor.py,sha256=cMuaGB8ZCGMpdeb3plzHzNC4ImsxsriQ66janWcjhjk,9101
|
|
21
|
+
siibra/features/feature.py,sha256=uVTp1vvZRnl9DIks49-StrZ88UEfEe-ixshuK5_bvwg,35576
|
|
22
22
|
siibra/features/connectivity/__init__.py,sha256=FkPf0vyrLo3ERxrDbsRHUd7FUgJyajD87NiiXIiXhmY,1161
|
|
23
23
|
siibra/features/connectivity/functional_connectivity.py,sha256=9lQoOXv8lZUnyMduAbWABwDIkQC0QTI8V23yx0NjOBg,2122
|
|
24
|
-
siibra/features/connectivity/regional_connectivity.py,sha256=
|
|
24
|
+
siibra/features/connectivity/regional_connectivity.py,sha256=6oDx-tsvQIh-MG823-6yLpVHvr-rOoS--CKR22GSwxA,18706
|
|
25
25
|
siibra/features/connectivity/streamline_counts.py,sha256=JaAYf6-1S8NYhkE4lhshCSY__EQ5BFcL2i_XXdFfgrM,1064
|
|
26
26
|
siibra/features/connectivity/streamline_lengths.py,sha256=QeuoW_ZDVa9dxCguaemj4Cq9CCPB8ur8_alhATto2-w,1067
|
|
27
27
|
siibra/features/connectivity/tracing_connectivity.py,sha256=rkYgD8mOZzDp0STo5djhDqOaEdz-9j5EuLffXE0F01A,1083
|
|
28
28
|
siibra/features/dataset/__init__.py,sha256=qRV_P0335b4LnSMiONRpSC4elGckp0FXmtJz_QQuVLA,748
|
|
29
29
|
siibra/features/dataset/ebrains.py,sha256=zA_GSIJzeJgClY5KrsfAJgrdjcM5N2Z_mz442UR_1vc,2544
|
|
30
|
-
siibra/features/image/__init__.py,sha256=
|
|
30
|
+
siibra/features/image/__init__.py,sha256=i_NccD2WJmVAtpLVWeccn8UEnViDMC6Y2CSGARL0Qt8,1049
|
|
31
31
|
siibra/features/image/image.py,sha256=heXBen5Sq3dVEcHSb4W4rs7n9nOXy3Nqp-eO0Vzjz4A,3583
|
|
32
32
|
siibra/features/image/sections.py,sha256=rZPoeZbu_cK8td5J4LVxZxsojjwTodrHe42P2de28_Y,3708
|
|
33
|
-
siibra/features/image/volume_of_interest.py,sha256=
|
|
33
|
+
siibra/features/image/volume_of_interest.py,sha256=fBkTUujUHdcfzF1kPvMTV4x41VJXPUJ5Lbpr_g4GxYM,2649
|
|
34
34
|
siibra/features/tabular/__init__.py,sha256=DdE1GXPEsHSNJ3pyNYZNWu5JxDfuI08DbrDF1iBrXIA,1203
|
|
35
35
|
siibra/features/tabular/bigbrain_intensity_profile.py,sha256=C7rP2QTJPyTz_EnRlgdFWPVaDcwJszTlm1ylHBydJOE,2709
|
|
36
36
|
siibra/features/tabular/cell_density_profile.py,sha256=ScpjD9W-w-lLxdG6q42Zfyqe8LW4JvaorIdnixuPzo4,10818
|
|
37
37
|
siibra/features/tabular/cortical_profile.py,sha256=x0TqZh8FzcVx13EwPtbt8kBYfF1dREWWuf9BhpWzj7o,12542
|
|
38
|
-
siibra/features/tabular/gene_expression.py,sha256=
|
|
38
|
+
siibra/features/tabular/gene_expression.py,sha256=8gJuUrL13oIySOPgiy5j46a5Udae_cJ1_QfrUHA72CI,10309
|
|
39
39
|
siibra/features/tabular/layerwise_bigbrain_intensities.py,sha256=iFCNG641yCSuIXFTY30xgRQqLERDHMqJrAy3SdKkAJ4,2118
|
|
40
|
-
siibra/features/tabular/layerwise_cell_density.py,sha256=
|
|
40
|
+
siibra/features/tabular/layerwise_cell_density.py,sha256=MYFiUfDfx6XQj8dezV5-3eKWBg0VOn0T3a1utELE2PM,6513
|
|
41
41
|
siibra/features/tabular/receptor_density_fingerprint.py,sha256=CvFJv940whxzavhEQWnTjueDEq0ZoiuYVpqUpR8t-Ec,8065
|
|
42
42
|
siibra/features/tabular/receptor_density_profile.py,sha256=VW2Ry8ifQLfmiBDKqIdvaN7K1YzMENGU92Lnm4wA8P0,3724
|
|
43
43
|
siibra/features/tabular/regional_timeseries_activity.py,sha256=wuno4oI1I-dyxRr8-tLFj42iaD6dYZiPigCqVMhrG50,10027
|
|
44
|
-
siibra/features/tabular/tabular.py,sha256=
|
|
44
|
+
siibra/features/tabular/tabular.py,sha256=37lSZ10cEAzGorA8jxdJvMcAIZvklIR3Vo75YPz7ONA,5783
|
|
45
45
|
siibra/livequeries/__init__.py,sha256=hToUNmyFq1UW5CxScHyBB-mSZ7kUK_w1Cvrk1OkZQf0,875
|
|
46
|
-
siibra/livequeries/allen.py,sha256=
|
|
46
|
+
siibra/livequeries/allen.py,sha256=l5OqVqq3SZ3x7-pol1PwX6AnvdyufjVUYXtGr3wWBj0,14946
|
|
47
47
|
siibra/livequeries/bigbrain.py,sha256=hT-T6gKRoZQFPWvitm1hv-DoMkkGjz-NfqSx7khfLR0,15762
|
|
48
48
|
siibra/livequeries/ebrains.py,sha256=GBwpm9f_rVjZgF-SyGZ5PGMmL9e9OZzXhHs78uCNhYs,5952
|
|
49
49
|
siibra/livequeries/query.py,sha256=P_uUVFxv4KyOPQXh2WnDQxuaSSBK_dXPKEr8I0-4xSQ,1849
|
|
50
50
|
siibra/locations/__init__.py,sha256=yTJVMdv-pICm_gUYLQ09lDKSkZBfgUihM6LNv07e_yk,3546
|
|
51
|
-
siibra/locations/boundingbox.py,sha256=
|
|
51
|
+
siibra/locations/boundingbox.py,sha256=ACRittMABMZwLPzGnv5Z5E6cIHJfCFWv851s5Bg87WQ,16442
|
|
52
52
|
siibra/locations/experimental.py,sha256=kd9yroLKpnY-N6hoMVgtHK4pVdgeGqhpad4GyxYy6LU,14484
|
|
53
|
-
siibra/locations/location.py,sha256=
|
|
54
|
-
siibra/locations/point.py,sha256=
|
|
55
|
-
siibra/locations/pointcloud.py,sha256=
|
|
53
|
+
siibra/locations/location.py,sha256=tb__0td1c7_3BKJFqqEqwspO5m8BZ8ZlyYwvtVBq8SY,4706
|
|
54
|
+
siibra/locations/point.py,sha256=cL2hqbejec24ZoXpbBQQXtHZ-H7KcyxnbITzSBjkXTs,12675
|
|
55
|
+
siibra/locations/pointcloud.py,sha256=AxtR43xG4i1hUXNmal4F_g5WKQo_A1ZtW4l4jsf3p6o,14108
|
|
56
56
|
siibra/retrieval/__init__.py,sha256=E-UA8rDQZFGkHmAcmit6siONo7G2mH_Y0xgLlR1RfvY,1062
|
|
57
57
|
siibra/retrieval/cache.py,sha256=uMWEi93VePSOSXaiU5PZAbUlWBYyO7gbpRxod4jO2Rc,7833
|
|
58
58
|
siibra/retrieval/datasets.py,sha256=JgnSc41TM0oGNAVn8zQjL84HML-feOBVy5bLxxHrEt8,11110
|
|
@@ -64,8 +64,8 @@ siibra/vocabularies/gene_names.json,sha256=i-gnh753GyZtQfX_dWibNYr_d5ccDPHooOwsd
|
|
|
64
64
|
siibra/vocabularies/receptor_symbols.json,sha256=F6DZIArPCBmJV_lWGV-zDpBBH_GOJOZm67LBE4qzMa4,5722
|
|
65
65
|
siibra/vocabularies/region_aliases.json,sha256=T2w1wRlxPNTsPppXn0bzC70tNsb8mOjLsoHuxDSYm2w,8563
|
|
66
66
|
siibra/volumes/__init__.py,sha256=9eiVjgGTqq9BiFJaLVLABtTrhIcE2k3Cn51yC4EKplg,936
|
|
67
|
-
siibra/volumes/parcellationmap.py,sha256
|
|
68
|
-
siibra/volumes/sparsemap.py,sha256=
|
|
67
|
+
siibra/volumes/parcellationmap.py,sha256=z5wWxK_kcFpS_ROpc9ny4aCbM7P9qc3DRDxrOKGp2Hk,51409
|
|
68
|
+
siibra/volumes/sparsemap.py,sha256=Yv07LIlt5yigw-ubWFq89hHnsivT7dymYCsCTe7Wu9I,17167
|
|
69
69
|
siibra/volumes/volume.py,sha256=wLmtqoXBDoPvE3WBO_Hc8uny3cdE9mB0KgdCq0LOTa0,32408
|
|
70
70
|
siibra/volumes/providers/__init__.py,sha256=AHZCjutCqO4mnHxyykVjqxlz85jDqFWcSjsa4ciwc1A,934
|
|
71
71
|
siibra/volumes/providers/freesurfer.py,sha256=l3zkLlE28EAEmg75tv9yp1YYiaHVkf4Zi8rKn9TUWVs,4893
|
|
@@ -73,8 +73,8 @@ siibra/volumes/providers/gifti.py,sha256=JGuixlSJTVjbDU_M5oMDCV8BAwIzuczhnI-qZ7L
|
|
|
73
73
|
siibra/volumes/providers/neuroglancer.py,sha256=b3TiJ6yrx_akLFKgHRKZyHculzzRIqbZ7U3TMQHy6-k,28618
|
|
74
74
|
siibra/volumes/providers/nifti.py,sha256=aAzkmeDZaXRZ-dkAeEb2cSywNn9WzIz0z7yFtN6iNpU,10135
|
|
75
75
|
siibra/volumes/providers/provider.py,sha256=Vn02au_LKynO5SIfqLyjqzxCf7JD9Wm4i7yEFcTX0WU,3585
|
|
76
|
-
siibra-1.0.
|
|
77
|
-
siibra-1.0.
|
|
78
|
-
siibra-1.0.
|
|
79
|
-
siibra-1.0.
|
|
80
|
-
siibra-1.0.
|
|
76
|
+
siibra-1.0.1a5.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
77
|
+
siibra-1.0.1a5.dist-info/METADATA,sha256=CO_Qej2SZ4h9saebuTGGPQLhPZOI4PQE4xSEHKVqKl4,9301
|
|
78
|
+
siibra-1.0.1a5.dist-info/WHEEL,sha256=0CuiUZ_p9E4cD6NyLD6UG80LBXYyiSYZOKDm5lp32xk,91
|
|
79
|
+
siibra-1.0.1a5.dist-info/top_level.txt,sha256=NF0OSGLL0li2qyC7MaU0iBB5Y9S09_euPpvisD0-8Hg,7
|
|
80
|
+
siibra-1.0.1a5.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|