Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce image volumes as an input for feature query #480

Merged
merged 109 commits into from
Nov 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
109 commits
Select commit Hold shift + click to select a range
cbb2ddb
remove slicing operator for building volumes of interest from Space o…
dickscheid Sep 6, 2023
8868a78
remove setting __repr__ to name in Region
dickscheid Sep 6, 2023
7f7da54
introduce NIfTI FeatureMaps as Location subclass and move assignment …
dickscheid Sep 6, 2023
437be1f
deal more consistently with points that could not be warped
dickscheid Sep 6, 2023
654da71
still accept Map.get_index() for multiple matches in case there is on…
dickscheid Sep 6, 2023
dbd1ae9
introduce spatialmap as a location object; simplify matching in live …
dickscheid Sep 8, 2023
6fe6fa6
WIP: introduce LocationFilter, make Volume a LocationFilter; use Loca…
dickscheid Sep 13, 2023
3dcf228
first attempt to re-enable feature query by region object - still tes…
dickscheid Sep 19, 2023
9656765
introducde SpaceWapringFailedException; remove contains implementatio…
dickscheid Sep 20, 2023
6da6bbc
fix sparsemap.fetch, small bug fixes
AhmetNSimsek Sep 21, 2023
daeebde
Merge branch 'main' into feat_feature_query_nifti
AhmetNSimsek Sep 21, 2023
7579ae4
_assign_image deal with updated commons.split_components api
dickscheid Sep 22, 2023
7bcf45e
Region.spatial_props accept modified get_regional_map function
dickscheid Sep 22, 2023
f20fd55
fix coordinate selection in Volume.points_inside
dickscheid Sep 22, 2023
7a8eaee
fix collecting coordinates for feature anchor
dickscheid Sep 22, 2023
c678889
fix syntax error
dickscheid Sep 22, 2023
c2216d8
fix typo
AhmetNSimsek Sep 22, 2023
25daef2
avoid redundant calls of child region maps in Region.get_regional_map
dickscheid Sep 22, 2023
789ed99
Merge branch 'feat_feature_query_nifti' of github.com:FZJ-INM1-BDA/si…
dickscheid Sep 22, 2023
0300d76
raise proper exception in volume.warp
dickscheid Sep 22, 2023
2b10a6b
Fix recursion error due to locationfilter.assign. Replace __contains_…
AhmetNSimsek Sep 22, 2023
efa458c
overwrite LocationFilter.assign() in Region to handle all cases
dickscheid Sep 22, 2023
8c5ab6e
fix order of "in" operator
dickscheid Sep 22, 2023
c5c0526
remove debug output
dickscheid Sep 22, 2023
b4b197b
allow quering receptor with a nifti volume
dickscheid Sep 22, 2023
2fcaa0f
accept volumes for intersection computations
dickscheid Sep 22, 2023
fb73902
rename LocationFilter to BrainStructure
dickscheid Sep 22, 2023
940cc6c
some description what a brain structure is as opposed to a brain region
dickscheid Sep 22, 2023
b388468
fix issues caused by contains->__contains__
AhmetNSimsek Sep 22, 2023
ebcfd39
Use tuple instead of subscripted generics in isinstance
AhmetNSimsek Sep 22, 2023
d8f35b2
Fix import errors in tests
AhmetNSimsek Sep 22, 2023
358f585
allow sampling and clustering from volumes
dickscheid Sep 22, 2023
3327cd4
Merge branch 'feat_feature_query_nifti' of github.com:FZJ-INM1-BDA/si…
dickscheid Sep 22, 2023
68c7f7e
add hdbscan to requirements, make label colors a property of pointset
dickscheid Sep 22, 2023
99b21d7
use sigma_mm of pointset for volume.from_points
dickscheid Sep 22, 2023
ef0f623
If volume intersection results in zeroslike, return None
AhmetNSimsek Sep 22, 2023
f11c270
add find_peaks method to all volumes
dickscheid Sep 22, 2023
22263cf
Fix image feature query (case: inverse assignment is None)
AhmetNSimsek Sep 22, 2023
a772ecd
fix from_pointset function in volume
dickscheid Sep 25, 2023
8bfee1c
a few fixes
dickscheid Oct 3, 2023
96f58d6
a few fixes
dickscheid Oct 3, 2023
13a0b87
Fix small bugs and tests
AhmetNSimsek Oct 30, 2023
5c601fe
add matplotlib to test requirements
AhmetNSimsek Oct 30, 2023
5e36a89
More fixes
AhmetNSimsek Oct 30, 2023
6c4ef39
Fix some bugs, examples, e2e tests, and all unit tests. Add hdbscan t…
AhmetNSimsek Oct 31, 2023
c6213ee
use scikit-learn HDBSCAN instead of hdbscan
AhmetNSimsek Oct 31, 2023
7d47972
map.assign takes locations. _assign_image->_assign_volume
AhmetNSimsek Oct 31, 2023
257b772
Bug fix: connected_components has no element == 0
AhmetNSimsek Oct 31, 2023
98c57df
Fix fetch cache for volumes
AhmetNSimsek Oct 31, 2023
e11d93b
Fix assignment of location to regions
AhmetNSimsek Nov 2, 2023
1c60742
Array conversion with `item` (Deprecation warning NumPy 1.25)
AhmetNSimsek Nov 2, 2023
5fd4394
Check child region masks for intersection if affine of the children d…
AhmetNSimsek Nov 2, 2023
4cedba4
Use neuroglancer format if not format is given but resolution_mm is g…
AhmetNSimsek Nov 2, 2023
99aeadf
Todo artifact and typo fix
AhmetNSimsek Nov 2, 2023
a9b0dba
fix fetch format selection, format order. add _maintain_fetch_cache
AhmetNSimsek Nov 3, 2023
93be43c
add notes to volume.fetch and protect against poisoning _FETCH_CACHE
AhmetNSimsek Nov 3, 2023
d40aade
Array conversion with `item` (Deprecation warning NumPy 1.25)
AhmetNSimsek Nov 3, 2023
2d1301b
maint: parcmap
AhmetNSimsek Nov 3, 2023
96cc202
Maint: anchor
AhmetNSimsek Nov 3, 2023
d570fe1
sparsemap._assigne_image -> _assign_volume
AhmetNSimsek Nov 6, 2023
6ed8547
Clean up map._assing_volume. fetch_iter goes through fragments as well
AhmetNSimsek Nov 6, 2023
3bf9657
fix volume.points_inside
AhmetNSimsek Nov 7, 2023
bb99929
feat: add maps from nifti and label information
AhmetNSimsek Oct 25, 2023
7074416
Use AICHA atlas as an example
AhmetNSimsek Nov 7, 2023
5281e71
Anchor: use a species specific match cache key
AhmetNSimsek Nov 8, 2023
a0ae3c3
Use volume for querying image in 03.000 example
AhmetNSimsek Nov 8, 2023
3a5e266
carry from_volume to parcellationmap submodule
AhmetNSimsek Nov 8, 2023
ad8e963
Remove strict requirement of scikit-learn>=1.3.0 for finding clusters…
AhmetNSimsek Nov 8, 2023
0774e76
remove hdbscan from requirements
AhmetNSimsek Nov 8, 2023
9816c62
remove volume._maintain_fetch_cache
AhmetNSimsek Nov 8, 2023
823f2d2
hide volum.points_inside
AhmetNSimsek Nov 8, 2023
84b899a
Merge pull request #502 from FZJ-INM1-BDA/feat_add_custom_map_and_que…
AhmetNSimsek Nov 8, 2023
b71f938
Merge branch 'main' into feat_feature_query_nifti
AhmetNSimsek Nov 9, 2023
bc46a4c
fix several bugs from the merge with 0.5a01
AhmetNSimsek Nov 9, 2023
5033be2
Merge pull request #501 from FZJ-INM1-BDA/maint_parcmap_assignvol_fet…
AhmetNSimsek Nov 9, 2023
a025377
Add unit to tqdm for building_objects
AhmetNSimsek Nov 10, 2023
1861ba6
Allow merging volumes from volume submodule
AhmetNSimsek Nov 10, 2023
eac5763
Fix: Region.intersection(Location) if region map is not available on …
AhmetNSimsek Nov 10, 2023
00f0a89
Fix RegionRelationAssessments
AhmetNSimsek Nov 10, 2023
d019a1a
maint: location.union
AhmetNSimsek Nov 10, 2023
e75ee43
add some documentation to boundingbox
AhmetNSimsek Nov 10, 2023
be0915d
Fix assignment.Qualification.inverse
AhmetNSimsek Nov 10, 2023
a63b890
Fix: Volume.intersection(PointSet)
AhmetNSimsek Nov 10, 2023
6a9b835
Test: fetching a map with multiple volumes wo args and volume.merge
AhmetNSimsek Nov 10, 2023
7b7c19e
Maint tests, fix volume.intersection, organize TODOs
AhmetNSimsek Nov 10, 2023
50e4db3
get_uuid -> generate_uuid
AhmetNSimsek Nov 10, 2023
7356b80
Add tests: check region-volume intersection, centroid containednedness
AhmetNSimsek Nov 10, 2023
fff4592
Make BigBrainIntensityProfile.location a property and refer to its an…
AhmetNSimsek Nov 13, 2023
e7028b4
Remove gifit import from volumes package
AhmetNSimsek Nov 13, 2023
6485f57
Remove redundant tests from e2e\feature\test_get
AhmetNSimsek Nov 13, 2023
e4ae9e7
Make Location a BrainStructure. Use this to ensure implementation of …
AhmetNSimsek Nov 13, 2023
fd5301c
update str and repr of core concepts
AhmetNSimsek Nov 14, 2023
3421cae
Several bug fixes
AhmetNSimsek Nov 14, 2023
1312160
no name field bug fix volume.from_nifti
AhmetNSimsek Nov 14, 2023
b6365ae
further volume name adjustments for get_regional map
AhmetNSimsek Nov 14, 2023
ae02d54
Fix PointSet.intersection (rewrite)
AhmetNSimsek Nov 14, 2023
8c9aed3
Fix Point le and ge. Use other's intersection in intersection when no…
AhmetNSimsek Nov 14, 2023
973d33b
Fix boundingbox.intersection
AhmetNSimsek Nov 14, 2023
3aaa398
Remove non-convex region maps from volume tests
AhmetNSimsek Nov 14, 2023
d3732e9
fix try-except block of region assignment to locations
AhmetNSimsek Nov 14, 2023
8694184
Update compound feature _export
AhmetNSimsek Nov 15, 2023
2ba1f83
Remove redundant `bigbrain._choose_space` and tidy bigbrain.py up
AhmetNSimsek Nov 15, 2023
6cabaf1
add/correct type hints in anchor.py
AhmetNSimsek Nov 15, 2023
f69efa8
Use location's space for region assignment first. region.supported_sp…
AhmetNSimsek Nov 15, 2023
bf00962
Example 03-000: use region object for PLI feature query
AhmetNSimsek Nov 15, 2023
ea49333
maint: allen query
AhmetNSimsek Nov 15, 2023
23fb33e
fix test_voi and enable more unit tests
AhmetNSimsek Nov 15, 2023
abcf2fa
version bump v1.0a01
AhmetNSimsek Nov 16, 2023
c6c52b5
Merge branch 'main' into feat_feature_query_nifti
AhmetNSimsek Nov 16, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions CITATION.cff
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ license: Apache License, Version 2.0

repository-code: https://github.com/FZJ-INM1-BDA/siibra-python

version: v0.5a02
version: v1.0a01

date-released: 2023-11-15
date-released: 2023-11-16

doi: https://zenodo.org/records/7885729

Expand Down
9 changes: 7 additions & 2 deletions docs/developer.rst
Original file line number Diff line number Diff line change
Expand Up @@ -157,9 +157,14 @@ Basic definitions and notes
Fetching volumes
----------------

To access the actual image or mesh data from a volume requires explicit fetching.
The process of fetching typically involves finding an appropriate volume provider, loading the data, and returning the image or mesh data.
In simple volume objects however, this might only require to return already loaded image data.
Images are typially returned as Nifti1Image, while meshes are returned as a dictionary including the vertices, faces and sometimes label arrays.

Fetching volumes occurs in two main stages:

1. The determination of the volume by the user.
1. Request of a volume object, such as a template, parcellation map, or other plain image volume.

* The user sets the object they would like to fetch a volume from:

Expand All @@ -171,7 +176,7 @@ Fetching volumes occurs in two main stages:
* template directly accesses to ``volume.fetch()``
* ``fetch()`` first goes through ``map.fetch()`` to determine the associated volume.

2. Actual retrieval of the volume object by siibra after the user asks for the
2. Actual retrieval of the volume data by siibra after the user asks for the
volume via ``fetch()`` method. When ``fetch()`` is invoked it accesses to
corresponding volume provider based on the specifications given by volume
index, fragment, z, label, variant, and format. According to the source type,
Expand Down
8 changes: 5 additions & 3 deletions e2e/core/test_region.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
from itertools import repeat

import siibra
from siibra.core.relation_qualification import Qualification
from siibra.core.assignment import Qualification
from siibra.core.region import Region


regions = [
Expand All @@ -14,7 +15,7 @@


@pytest.mark.parametrize("region", regions)
def test_region_spatial_props(region: siibra.core.parcellation.region.Region):
def test_region_spatial_props(region: Region):
props = region.spatial_props("mni152")
for idx, cmp in enumerate(props.components, start=1):
assert cmp.volume >= props.components[idx - 1].volume
Expand Down Expand Up @@ -76,7 +77,7 @@ def test_find(parc_spec, region_spec, result_len, check_regions):


@pytest.mark.parametrize("parc, reg_spec, has_related, has_homology, has_related_ebrains_reg", [
("2.9", "PGa", True, True, False),
("julich 2.9", "PGa", True, True, False),
("monkey", "PG", False, True, False),
("waxholm v3", "cornu ammonis 1", True, False, True),
])
Expand All @@ -99,6 +100,7 @@ def test_homologies_related_regions(parc, reg_spec, has_related, has_homology, h
)
assert len([f for f in features]) > 0


def test_related_region_hemisphere():
reg = siibra.get_region("2.9", "PGa")
all_related_reg = [reg for reg in reg.get_related_regions()]
Expand Down
4 changes: 2 additions & 2 deletions e2e/features/external/test_ebrains.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import siibra
import pytest
from siibra.features.anchor import AssignmentQualification
from siibra.features.anchor import Qualification

concepts = [
(
Expand All @@ -25,4 +25,4 @@ def features_fixture():
def test_each_feature(features_fixture):
for f in features_fixture:
for qual in f.anchor.regions.values():
assert isinstance(qual, AssignmentQualification)
assert isinstance(qual, Qualification)
2 changes: 1 addition & 1 deletion e2e/features/image/test_image.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import pytest

features = siibra.features.get(
siibra.spaces["big brain"], "CellBodyStainedVolumeOfInterest"
siibra.get_template("big brain"), "CellBodyStainedVolumeOfInterest"
)


Expand Down
6 changes: 3 additions & 3 deletions e2e/features/test_get.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ def test_get_instances(Cls: siibra.features.Feature):
assert isinstance(instances, list)


ids = [
selected_ids = [
"lq0::EbrainsDataFeature::p:minds/core/parcellationatlas/v1.0.0/94c1125b-b87e-45e4-901c-00daee7f2579-290::r:Area hOc1 (V1, 17, CalcS) left::https://nexus.humanbrainproject.org/v0/data/minds/core/dataset/v1.0.0/3ff328fa-f48f-474b-bd81-b5ee7ca230b6",
"cf0::BigBrainIntensityProfile::p:minds/core/parcellationatlas/v1.0.0/94c1125b-b87e-45e4-901c-00daee7f2579-290::r:Area hOc1 (V1, 17, CalcS) left::nodsid::6ba1f5c180a63705d84c25db9ff7efa7", # CompoundFeature of 1579 BigBrainIntensityProfile features grouped by (Modified silver staining modality) anchored at Area hOc1 (V1, 17, CalcS) left with Set of 1579 points in the Bounding box from (-63.69,-59.94,-29.09) mm to (0.91,77.90,54.03)mm in BigBrain microscopic template (histology) space
"lq0::BigBrainIntensityProfile::p:minds/core/parcellationatlas/v1.0.0/94c1125b-b87e-45e4-901c-00daee7f2579-290::r:Area hOc1 (V1, 17, CalcS) left::a48879314d93d15c74e6512e9af9c91d", # BigBrainIntensityProfile (Modified silver staining) anchored at Area hOc1 (V1, 17, CalcS) left with Point in BigBrain microscopic template (histology) [0.4248340129852295,50.589298248291016,-14.839699745178223]
Expand All @@ -27,7 +27,7 @@ def test_get_instances(Cls: siibra.features.Feature):
]


@pytest.mark.parametrize("fid", ids)
@pytest.mark.parametrize("fid", selected_ids)
def test_get_instance(fid):
feat = siibra.features.Feature._get_instance_by_id(fid)
assert feat.id == fid
Expand All @@ -36,7 +36,7 @@ def test_get_instance(fid):
# this tests whether or not calling a live query caused proxy feature to be
# added to subclasses. (It should not: causes memory leak and also increases
# query time linearly)
@pytest.mark.parametrize("fid", ids)
@pytest.mark.parametrize("fid", selected_ids)
def test_subclass_count(fid):
len_before = len(siibra.features.Feature.SUBCLASSES[siibra.features.Feature])
_ = siibra.features.Feature._get_instance_by_id(fid)
Expand Down
6 changes: 3 additions & 3 deletions e2e/volumes/test_mapshape.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ def test_map_shape(space_shape, parc_id, map_endpoint, region_name):
volume_data = None
if region_name is not None:
region = siibra.get_region(parc_id, region_name)
volume_data = region.fetch_regional_map(space_id, map_endpoint)
volume_data = region.get_regional_map(space_id, map_endpoint).fetch()
else:
labelled_map = siibra.get_map(parc_id, space_id, map_endpoint)
assert labelled_map is not None
Expand All @@ -56,5 +56,5 @@ def test_template_resampling():
mp_img = mp.fetch()
template = mp.space.get_template().fetch()
assert mp_img.shape != template.shape
resamp_template = mp.get_resampled_template()
assert mp_img.shape == resamp_template.shape
resamp_template = mp.get_resampled_template().fetch()
assert mp_img.shape == resamp_template.shape
7 changes: 7 additions & 0 deletions e2e/volumes/test_parcellationmap.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,3 +103,10 @@ def test_region_1to1ness_in_parcellation():
}
)
assert len(failed) == 0, print("The regions in maps that can't be gotten in respective parcellations\n", failed)


def test_fetching_merged_volume():
# this also tests for volume.merge as it is used in Map.fetch
mp = siibra.get_map("julich 2.9", "bigbrain")
assert len(mp) > 1
_ = mp.fetch()
35 changes: 35 additions & 0 deletions e2e/volumes/test_volume.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import siibra
from siibra.volumes import Volume
from siibra.core.region import Region
import numpy as np
import pytest
# TODO write a test for the volume-region and volume-volume intersection


# add more to the list when centroids can be calculated for non-convex regions as well
selected_regions = [
(siibra.get_region('julich 2.9', 'CA2 (Hippocampus) right'), 'mni152'),
(siibra.get_region('julich 2.9', 'CA2 (Hippocampus) left'), 'colin27'),
(siibra.get_region('julich 2.9', 'hoc1 left'), 'mni152'),
(siibra.get_region('julich 3', 'sts'), 'mni152')
]


@pytest.mark.parametrize("region, space", selected_regions)
def test_region_intersection_with_its_own_volume(region, space):
assert isinstance(region, Region)
volume = region.get_regional_map(space)
intersection = region.intersection(volume)
assert isinstance(intersection, Volume)
assert np.all(
np.equal(intersection.fetch().dataobj, volume.fetch().dataobj)
), "Intersection of a regional map with its region object should be the same volume."


@pytest.mark.parametrize("region, space", selected_regions)
def test_region_intersection_with_its_centroid(region, space):
assert isinstance(region, Region)
centroids = region.compute_centroids(space)
assert centroids in region
assert region.intersection(centroids) == centroids
assert centroids.intersection(region) == centroids
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,6 @@
# gives us a Nifti1Image object as provided by `nibabel <https://nipy.org/nibabel/>`_,
# and which we can directly visualize using plotting functions like the ones in
# `nilearn <https://nilearn.github.io/stable/index.html>`_:
mask = v1_left.fetch_regional_map(space, maptype="labelled")
mask = v1_left.get_regional_map(space, maptype="labelled")
from nilearn import plotting
plotting.plot_roi(mask, title=f"Mask of {v1_left.name} in {space.name}")
plotting.plot_roi(mask.fetch(), title=f"Mask of {v1_left.name} in {space.name}")
9 changes: 4 additions & 5 deletions examples/02_maps_and_templates/003_accessing_maps.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@

# %%
# We select the maximum probability map of Julich-Brain in MNI152 space,
# which is a parcellation map with discrete labels.
# which is a parcellation map with discrete labels.
# `get_map` assumes maptype='labelled' by default.
julich_mpm = siibra.get_map(space="icbm 2009c", parcellation="julich 2.9", maptype="labelled")
julich_mpm = siibra.get_map(space="icbm 2009c", parcellation="julich 3", maptype="labelled")
print(julich_mpm)

# %%
Expand Down Expand Up @@ -120,6 +120,5 @@
# %%
# In addition to parcellation maps, `siibra` can produce binary masks of brain regions.
hoc5L = siibra.get_region(parcellation='julich 2.9', region='hoc5 left')
hoc5L_mask = hoc5L.fetch_regional_map(space="mni152", maptype="labelled")
plotting.plot_roi(hoc5L_mask, title=f"Mask of {hoc5L.name}")

hoc5L_mask = hoc5L.get_regional_map(space="mni152", maptype="labelled")
plotting.plot_roi(hoc5L_mask.fetch(), title=f"Mask of {hoc5L.name}")
24 changes: 15 additions & 9 deletions examples/02_maps_and_templates/004_access_bigbrain.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,10 @@
# %%
# Per default, `siibra` will fetch the whole brain volume at a reasonably
# reduced resolution.
bigbrain = siibra.get_template('bigbrain')
bigbrain_whole = bigbrain.fetch()
plotting.view_img(bigbrain_whole, bg_img=None, cmap='gray')
space = siibra.spaces['bigbrain']
bigbrain_template = space.get_template()
bigbrain_whole_img = bigbrain_template.fetch()
plotting.view_img(bigbrain_whole_img, bg_img=None, cmap='gray')

# %%
# To see the full resolution, we may specify a bounding box in the physical
Expand All @@ -47,19 +48,24 @@
# a string representation, which could be conveniently copy pasted from the
# interactive viewer `siibra explorer <https://atlases.ebrains.eu/viewer>`_.
# Note that the coordinates can be specified by 3-tuples, and in other ways.
space = siibra.spaces.get('bigbrain')
voi = space.get_bounding_box(
voi = siibra.locations.BoundingBox(
point1="-30.590mm, 3.270mm, 47.814mm",
point2="-26.557mm, 6.277mm, 50.631mm"
point2="-26.557mm, 6.277mm, 50.631mm",
space=space
)
bigbrain_chunk = bigbrain.fetch(voi=voi, resolution_mm=0.02)
bigbrain_chunk = bigbrain_template.fetch(voi=voi, resolution_mm=0.02)
plotting.view_img(bigbrain_chunk, bg_img=None, cmap='gray')

# %%
# Note that since both fetched image volumes are spatial images with a properly
# defined transformation between their voxel and physical spaces, we can
# directly plot them correctly superimposed on each other:
plotting.view_img(bigbrain_chunk, bg_img=bigbrain_whole, cmap='magma', cut_coords=tuple(voi.center))
plotting.view_img(
bigbrain_chunk,
bg_img=bigbrain_whole_img,
cmap='magma',
cut_coords=tuple(voi.center)
)

# %%
# Next we select a parcellation which provides a map for BigBrain, and extract
Expand Down Expand Up @@ -103,7 +109,7 @@
section1402 = features[3]
plotting.plot_img(
section1402.fetch(),
bg_img=bigbrain_whole,
bg_img=bigbrain_whole_img,
title="#1402",
cmap='gray'
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,4 +77,3 @@
surf_map=thicknesses[4],
symmetric_cmap=False, cmap='magma', vmax=0.3
)
# %%
83 changes: 83 additions & 0 deletions examples/02_maps_and_templates/007_adding_custom_parcellation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# Copyright 2018-2023
# Institute of Neuroscience and Medicine (INM-1), Forschungszentrum Jülich GmbH

# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at

# http://www.apache.org/licenses/LICENSE-2.0

# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""
Adding a custom parcellation map
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Sometimes you might want to use a custom parcellation map to perform feature
queries in siibra. For this example, we retrieve a freely available AICHA -
Atlas of Intrinsic Connectivity of Homotopic Areas (Tzourio-Mazoyer N, Landeau B,
Papathanassiou D, Crivello F, Etard O, Delcroix N, Mazoyer B, Joliot M (2002)
Automated anatomical labeling of activations in SPM using a macroscopic
anatomical parcellation of the MNI MRI single-subject brain. Neuroimage
15:273-289.). This atlas provided in the MNI ICBM 152 space.
"""


# %%
import siibra
from nilearn import plotting

# %%
# Load the custom parcellation map from the online resource. For the retrieval,
# siibra's zipfile connector is very helpful. We can use the resulting NIfTI
# to create a custom parcellation map inside siibra.

# connect to the online zip file
conn = siibra.retrieval.ZipfileConnector(
"http://www.gin.cnrs.fr/wp-content/uploads/aicha_v1.zip"
)

# the NIfTI file is easily retrieved:
nifti = conn.get("AICHA/AICHA.nii")
# and create a volume on space MNI152 (note that this assumes our
# external knowledge that the map is in MNI152 space)
volume = siibra.volumes.from_nifti(nifti, 'mni152', "AICHA")

# The text file with label mappings has a custom format. We provide a tsv
# decoder to extract the list of region/label pairs since the txt file is tab
# seperated.
volume_info = conn.get("AICHA/AICHA_vol1.txt", decode_func=siibra.retrieval.requests.DECODERS['.tsv'])
volume_info

# %%
# Now we use this to add a custom map to siibra.
regionnames = [
name.replace('-R', ' right').replace('-L', ' left')
for name in volume_info['nom_l']
]
labels = [int(label) for label in volume_info['color']]
custom_map = siibra.volumes.parcellationmap.from_volume(
name="AICHA - Atlas of Intrinsic Connectivity of Homotopic Areas",
volume=volume,
regionnames=regionnames,
regionlabels=labels
)

# %%
# let's plot the final map
plotting.plot_roi(custom_map.fetch())


# %%
# We can already use this map to find spatial features, such as BigBrain
# intensity profiles.
region = custom_map.parcellation.get_region('S_Rolando-1 left')
profiles = siibra.features.get(
region,
siibra.features.cellular.BigBrainIntensityProfile
)[0]
print(f"{len(profiles)} intensity profiles found.")
11 changes: 4 additions & 7 deletions examples/03_data_features/002_colorize_map.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,11 @@
"""

# %%
# We start by selecting an atlas and the Julich-Brain parcellation.
from nilearn import plotting
import siibra
# We start by selecting an atlas and the Julich-Brain parcellation.
atlas = siibra.atlases.MULTILEVEL_HUMAN_ATLAS
jubrain = atlas.get_parcellation('julich 2.9')
jubrain = atlas.get_parcellation('julich 3')
# sphinx_gallery_thumbnail_path = '_static/example_thumbnails/03-002.png'

# %%
Expand All @@ -53,8 +54,7 @@

# %%
# Now colorize the Julich-Brain maximum probability map and plot it.
colorized_map = jubrain.get_map(space='mni152').colorize(mapping)
from nilearn import plotting
colorized_map = jubrain.get_map(space='mni152').colorize(mapping).fetch()
plotting.view_img(
colorized_map, cmap='magma',
title=f"Average densities available for {receptor}", symmetric_cmap=False
Expand All @@ -64,6 +64,3 @@
# Alternatively, we can display this map on a surface mesh using nilearn.
# Note that, you can switch between the hemispheres or variants (inflated or pial) from the plot itself.
plotting.view_img_on_surf(colorized_map, cmap='magma', symmetric_cmap=False, surf_mesh="fsaverage6")


# %%
Loading
Loading