[MAINT]: Bump junifer-data version to v5 #470

Merged
synchon merged 4 commits from feat/freesurfer-aseg-parcellation into main 2025-10-16 09:27:26 +00:00
6 changed files with 149 additions and 8 deletions

View file

@ -453,6 +453,16 @@ Available
| Architecture | Architecture
| Cerebral Cortex, Volume 26(8), Pages 3508–3526 (2016). | Cerebral Cortex, Volume 26(8), Pages 3508–3526 (2016).
| https://doi.org/10.1093/cercor/bhw157 | https://doi.org/10.1093/cercor/bhw157
* - FreeSurfer 7.4.1 anatomical segmentation atlas
- None
- ``aseg-7_4_1``
- ``fsaverage``
- 0.0.7
- | Fischl B, Salat DH, Busa E, et al.
| Whole brain segmentation: automated labeling of neuroanatomical
| structures in the human brain.
| Neuron., Volume 33(3), Pages 341-355 (2002).
| https://doi:10.1016/s0896-6273(02)00569-x
Planned Planned
@ -492,12 +502,6 @@ Planned
| anatomical nomenclature. | anatomical nomenclature.
| NeuroImage, Volume 53(1), Pages 1–15 (2010). | NeuroImage, Volume 53(1), Pages 1–15 (2010).
| http://doi.org/10.1016/j.neuroimage.2010.06.010. | http://doi.org/10.1016/j.neuroimage.2010.06.010.
* - Fan
- | Fan, L., Li, H., Zhuo, J. et al.
| The human brainnetome atlas: a new brain atlas based on connectional
| architecture.
| Cerebral cortex, Volume 26(8), Pages 3508-3526 (2016).
| https://doi.org/10.1093/cercor/bhw157
* - Buckner * - Buckner
- | Buckner, R.L., Krienen, F.M., Castellanos, A., Diaz, J.C., Yeo, B.T.T. - | Buckner, R.L., Krienen, F.M., Castellanos, A., Diaz, J.C., Yeo, B.T.T.
| The organization of the human cerebellum estimated by intrinsic | The organization of the human cerebellum estimated by intrinsic

View file

@ -0,0 +1 @@
Add FreeSurfer 7.4.1 aseg parcellation to :class:`.ParcellationRegistry` by `Synchon Mandal`_

View file

@ -0,0 +1 @@
Bump ``junifer-data`` to ``v5`` by `Synchon Mandal`_

View file

@ -190,6 +190,15 @@ class ParcellationRegistry(BasePipelineDataRegistry):
}, },
} }
) )
# Add FreeSurfer 7.4.1 aseg
self._builtin.update(
{
"aseg-7_4_1": {
"family": "FreeSurfer",
"space": "fsaverage",
}
}
)
# Update registry with built-in ones # Update registry with built-in ones
self._registry.update(self._builtin) self._registry.update(self._builtin)
@ -355,6 +364,7 @@ class ParcellationRegistry(BasePipelineDataRegistry):
"Shen", "Shen",
"Yan2023", "Yan2023",
"Brainnetome", "Brainnetome",
"FreeSurfer",
]: ]:
# Load parcellation and labels # Load parcellation and labels
if t_family == "Schaefer2018": if t_family == "Schaefer2018":
@ -394,6 +404,10 @@ class ParcellationRegistry(BasePipelineDataRegistry):
**parcellation_definition, **parcellation_definition,
) )
) )
elif t_family == "FreeSurfer":
parcellation_fname, parcellation_labels = _retrieve_aseg(
resolution=resolution,
)
else: else:
raise_error(f"Unknown parcellation family: {t_family}") raise_error(f"Unknown parcellation family: {t_family}")
@ -1307,6 +1321,106 @@ def _retrieve_brainnetome(
return parcellation_img_path, labels return parcellation_img_path, labels
def _retrieve_aseg(
resolution: Optional[float] = None,
) -> tuple[Path, list[str]]:
"""Retrieve aseg generated from FreeSurfer 7.4.1 .
Parameters
----------
resolution : 1.0, optional
The desired resolution of the parcellation to load. If it is not
available, the closest resolution will be loaded. Preferably, use a
resolution higher than the desired one. By default, will load the
highest one (default None). Available resolution for this
parcellation is 1mm.
Returns
-------
pathlib.Path
File path to the parcellation image.
list of str
Parcellation labels.
"""
logger.info("Parcellation parameters:")
logger.info(f"\tresolution: {resolution}")
_valid_resolutions = [1.0]
_ = closest_resolution(resolution, _valid_resolutions)
path_prefix = Path("parcellations/FreeSurfer-7_4_1")
parcellation_img_path = get(
file_path=path_prefix / "aseg.nii",
dataset_path=get_dataset_path(),
**JUNIFER_DATA_PARAMS,
)
parcellation_label_path = get(
file_path=path_prefix / "ASegStatsLUT.txt",
dataset_path=get_dataset_path(),
**JUNIFER_DATA_PARAMS,
)
# Explicitly indexed to get proper labels
idxs = [
2,
3,
4,
5,
7,
8,
10,
11,
12,
13,
14,
15,
16,
17,
18,
24,
26,
28,
30,
31,
41,
42,
43,
44,
46,
47,
49,
50,
51,
52,
53,
54,
58,
60,
62,
63,
77,
85,
251,
252,
253,
254,
255,
]
labels = (
pd.read_csv(
parcellation_label_path,
sep=r"\s+",
skiprows=6,
header=None,
index_col=0,
)
.loc[idxs][1]
.to_list()
)
return parcellation_img_path, labels
def merge_parcellations( def merge_parcellations(
parcellations_list: list["Nifti1Image"], parcellations_list: list["Nifti1Image"],
parcellations_names: list[str], parcellations_names: list[str],

View file

@ -941,6 +941,27 @@ def test_retrieve_brainnetome_incorrect_threshold() -> None:
) )
def test_aseg() -> None:
"""Test FreeSurfer 7.4.1 aseg parcellation."""
parcellations = list_data(kind="parcellation")
assert "aseg-7_4_1" in parcellations
# Load parcellation
img, label, img_path, space = load_data(
kind="parcellation",
name="aseg-7_4_1",
target_space="fsaverage",
)
assert img is not None
assert img_path.name == "aseg.nii"
assert space == "fsaverage"
assert len(label) == 43
assert_array_equal(
img.header["pixdim"][1:4],
3 * [1],
)
def test_merge_parcellations() -> None: def test_merge_parcellations() -> None:
"""Test merging parcellations.""" """Test merging parcellations."""
# load some parcellations for testing # load some parcellations for testing

View file

@ -24,10 +24,10 @@ __all__ = [
# junifer-data version constant # junifer-data version constant
JUNIFER_DATA_VERSION = "4" JUNIFER_DATA_VERSION = "5"
# junifer-data hexsha constant # junifer-data hexsha constant
JUNIFER_DATA_HEXSHA = "d178bddf383fede04742d7020312a574de47f0ab" JUNIFER_DATA_HEXSHA = "62a0e3d187259a3c3ba7be638ee39cfb40df0a61"
JUNIFER_DATA_PARAMS = { JUNIFER_DATA_PARAMS = {
"tag": JUNIFER_DATA_VERSION, "tag": JUNIFER_DATA_VERSION,