Skip to content

[ENH] add HPC extended atlas #80

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

Merged
merged 6 commits into from
Dec 14, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,6 @@
path = lib/marsbar
url = https://github.com/marsbar-toolbox/marsbar.git
datalad-url = https://github.com/marsbar-toolbox/marsbar.git
[submodule "atlas/HCPex"]
path = atlas/HCPex
url = https://github.com/wayalan/HCPex.git
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,10 @@ as a submodule, and initialized when running `initCppSpm`.
- neurosynth probability maps
- the probabilistic maps of visual topography in human cortex [@wang2014]
- https://scholar.princeton.edu/napl/resources
- the probabilistic functional atlas of human occipito-temporal visual cortex [@rosenke2020]
- the probabilistic functional atlas of human occipito-temporal visual
cortex [@rosenke2020]
- [extended Human Connectome Project multimodal parcellation atlas](https://github.com/wayalan/HCPex.git)
of the human cortex and subcortical areas [@huang_extended_2022]

Also includes:

Expand Down
1 change: 1 addition & 0 deletions atlas/HCPex
Submodule HCPex added at 543e88
443 changes: 443 additions & 0 deletions atlas/HCPex.xml

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions atlas/miss_hit.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
exclude_dir: "HCPex"
3 changes: 3 additions & 0 deletions atlas/returnAtlasDir.m
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@
case 'visfatlas'
atlasDir = fullfile(atlasDir, 'visfAtlas');

case 'hcpex'
atlasDir = fullfile(atlasDir, 'HCPex', 'HCPex_v1.0');

case 'neuromorphometrics'

otherwise
Expand Down
4 changes: 4 additions & 0 deletions initCppRoi.m
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ function initCppRoi()
catch
end

unzipAtlas('hcpex');
copyAtlasToSpmDir('HCPex', 'verbose', true);
copyAtlasToSpmDir('AAL', 'verbose', true);

CPP_ROI_INITIALIZED = true();

else
Expand Down
16 changes: 16 additions & 0 deletions references.bib
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,19 @@ @article{wang2014
url = {https://doi.org/10.1093/cercor/bhu277},
eprint = {https://academic.oup.com/cercor/article-pdf/25/10/3911/14102011/bhu277.pdf}
}

@article{huang_extended_2022,
title = {An extended {Human} {Connectome} {Project} multimodal parcellation atlas of the human cortex and subcortical areas},
volume = {227},
issn = {1863-2653, 1863-2661},
url = {https://link.springer.com/10.1007/s00429-021-02421-6},
doi = {10.1007/s00429-021-02421-6},
language = {en},
number = {3},
urldate = {2022-12-14},
journal = {Brain Structure and Function},
author = {Huang, Chu-Chung and Rolls, Edmund T. and Feng, Jianfeng and Lin, Ching-Po},
month = apr,
year = {2022},
pages = {763--778},
}
10 changes: 7 additions & 3 deletions src/atlas/copyAtlasToSpmDir.m
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,17 @@ function copyAtlasToSpmDir(varargin)
verbose = args.Results.verbose;

spmAtlasDir = fullfile(spm('dir'), 'atlas');
cppRoiAtlasDir = returnAtlasDir();

switch lower(atlas)

case 'aal'
sourceAtlasImage = fullfile(cppRoiAtlasDir, 'AAL3', 'AAL3v1_1mm.nii.gz');
sourceAtlasXml = fullfile(cppRoiAtlasDir, 'AAL3', 'AAL3v1_1mm.xml');
sourceAtlasImage = fullfile(returnAtlasDir(), 'AAL3', 'AAL3v1_1mm.nii.gz');
sourceAtlasXml = fullfile(returnAtlasDir(), 'AAL3', 'AAL3v1_1mm.xml');

case 'hcpex'
sourceAtlasImage = fullfile(returnAtlasDir('hcpex'), 'HCPex.nii.gz');
sourceAtlasXml = fullfile(returnAtlasDir(), 'HCPex.xml');

end

targetAtlasImage = fullfile(spmAtlasDir, spm_file(sourceAtlasImage, 'filename'));
Expand Down
6 changes: 5 additions & 1 deletion src/atlas/extractRoiFromAtlas.m
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
% roiImage = extractRoiFromAtlas(outputDir, atlasName, roiName, hemisphere)
%
% :param outputDir:
% :param atlasName: ``wang``, ``neuromorphometrics``
% :param atlasName: ``wang``, ``neuromorphometrics``, ``'hcpex'``
% :param roiName: run ``getLookUpTable(atlasName)`` to get a list of ROI names to choose from
% :param hemisphere: ``L`` or ``R``
% :type outputDir: string
Expand Down Expand Up @@ -61,6 +61,10 @@

roiIdx = strcmp([prefix roiName], lut.ROI);

elseif strcmpi(atlasName, 'hcpex')

roiIdx = strcmp([hemisphere '_' roiName], lut.ROI);

end

% create ROI
Expand Down
16 changes: 5 additions & 11 deletions src/atlas/getAtlasFilename.m
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,17 @@
%
% Returns the atlas filename
%
% "Probabilistic Maps of Visual Topography in Human Cortex"
%
% USAGE::
%
% atlasFilename = getAtlasFilename(atlasName)
%
%
% DOI 10.1093/cercor/bhu277
% PMCID: PMC4585523
% PMID: 25452571
% Probabilistic Maps of Visual Topography in Human Cortex
%

% (C) Copyright 2021 CPP ROI developers

atlasDir = returnAtlasDir(atlasName);

if ~ismember(lower(atlasName), {'wang', 'neuromorphometrics', 'anatomy_toobox', 'visfatlas'})
% TODO throw a proper error here
error('unknown atlas type');
end
isAKnownAtlas(atlasName);

switch lower(atlasName)

Expand Down Expand Up @@ -51,6 +41,10 @@

atlasFilename = fullfile(atlasDir, 'space-MNI_atlas-visfAtlas_dseg.nii');

case 'hcpex'

atlasFilename = fullfile(atlasDir, 'HCPex.nii');

end

end
21 changes: 17 additions & 4 deletions src/atlas/getLookUpTable.m
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,7 @@

atlasDir = returnAtlasDir(atlasName);

if ~ismember(lower(atlasName), {'wang', 'neuromorphometrics', 'anatomy_toobox', 'visfatlas'})
% TODO throw a proper error here
error('unknown atlas type');
end
isAKnownAtlas(atlasName);

switch lower(atlasName)

Expand Down Expand Up @@ -56,6 +53,22 @@
roiLabelLUT = struct('ROI', C(1), ...
'label', C(2));

case 'hcpex'

roiLabelLUT = fullfile(atlasDir, 'HCPex.nii.txt');

fid = fopen(roiLabelLUT);
pattern = '%f%s%s%f';
C = textscan(fid, pattern, 'Headerlines', 1);
fclose(fid);

for i = 1:numel(C{2})
ROI{1}{i} = [C{2}{i} '_' C{3}{i}];
end

roiLabelLUT = struct('ROI', ROI(1), ...
'label', C(1));

case 'visfatlas'

unzipAtlas('visfAtlas');
Expand Down
11 changes: 11 additions & 0 deletions src/atlas/isAKnownAtlas.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
function isAKnownAtlas(atlasName)
% (C) Copyright 2021 CPP ROI developers
if ~ismember(lower(atlasName), {'wang', ...
'neuromorphometrics', ...
'anatomy_toobox', ...
'visfatlas', ...
'hcpex'})
% TODO throw a proper error here
error('unknown atlas type');
end
end
43 changes: 29 additions & 14 deletions src/atlas/unzipAtlas.m
Original file line number Diff line number Diff line change
Expand Up @@ -5,29 +5,44 @@ function unzipAtlas(atlas)

atlasDir = returnAtlasDir();

if strcmp(atlas, 'wang')
switch lower(atlas)

file = fullfile(atlasDir, 'visual_topography_probability_atlas.zip');
case 'wang'

if ~exist(fullfile(atlasDir, 'visual_topography_probability_atlas'), 'dir')
file = fullfile(atlasDir, 'visual_topography_probability_atlas.zip');

unzip(file, fileparts(file));
if ~exist(fullfile(atlasDir, 'visual_topography_probability_atlas'), 'dir')

labelImages = spm_select('FPList', ...
fullfile(atlasDir, ...
'visual_topography_probability_atlas', ...
'subj_vol_all'), ...
'^.*_dseg.nii.gz$');
unzip(file, fileparts(file));

gunzip(cellstr(labelImages));
labelImages = spm_select('FPList', ...
fullfile(atlasDir, ...
'visual_topography_probability_atlas', ...
'subj_vol_all'), ...
'^.*_dseg.nii.gz$');

end
gunzip(cellstr(labelImages));

elseif strcmp(atlas, 'visfAtlas')
end

file = fullfile(atlasDir, 'visfAtlas/space-MNI_atlas-visfAtlas_dseg.nii.gz');
case 'visfatlas'

gunzip(file);
file = fullfile(atlasDir, 'visfAtlas/space-MNI_atlas-visfAtlas_dseg.nii.gz');

gunzip(file);

case 'hcpex'

if exist(fullfile(returnAtlasDir('hcpex'), 'HCPex.nii'), 'file')
return
end

file = fullfile(returnAtlasDir('hcpex'), 'HCPex.nii.gz');
if isOctave()
copyfile(file, fullfile(returnAtlasDir('hcpex'), 'HCPex.nii.gz.bak'));
end

gunzip(file);

end

Expand Down
21 changes: 21 additions & 0 deletions src/utils/isOctave.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
function retval = isOctave()
%
% Returns true if the environment is Octave.
%
% USAGE::
%
% retval = isOctave()
%
% :returns: :retval: (boolean)
%

% (C) Copyright 2022 CPP ROI developers

persistent cacheval % speeds up repeated calls

if isempty (cacheval)
cacheval = (exist ('OCTAVE_VERSION', 'builtin') > 0);
end

retval = cacheval;
end
18 changes: 18 additions & 0 deletions tests/test_copyAtlasToSpmDir.m
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,21 @@ function test_copyAtlasToSpmDir_basic()
assertEqual(exist(targetAtlasXml, 'file'), 2);

end

function test_copyAtlasToSpmDir_HPCex()

if isGithubCi()
return
end

copyAtlasToSpmDir('HCPex', 'verbose', false);

spmAtlasDir = fullfile(spm('dir'), 'atlas');

targetAtlasImage = fullfile(spmAtlasDir, 'HCPex.nii');
targetAtlasXml = fullfile(spmAtlasDir, 'HCPex.xml');

assertEqual(exist(targetAtlasImage, 'file'), 2);
assertEqual(exist(targetAtlasXml, 'file'), 2);

end
18 changes: 18 additions & 0 deletions tests/test_extractRoiFromAtlas.m
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,21 @@ function test_extractRoiFromAtlas_visfAtlas()
delete(fullfile(pwd, '*.json'));

end

function test_extractRoiFromAtlas_hcpex()

unzipAtlas('hcpex');

roiImage = extractRoiFromAtlas(pwd, 'hcpex', 'MT', 'L');

assertEqual(exist(fullfile(pwd, 'hemi-L_space-MNI_atlas-hcpex_label-MT_mask.nii'), ...
'file'), ...
2);

vol = spm_read_vols(spm_vol(roiImage));
assertEqual(sum(vol(:) == 1), 620); % check the ROI has the right number of voxel

delete(fullfile(pwd, '*.nii'));
delete(fullfile(pwd, '*.json'));

end
4 changes: 3 additions & 1 deletion tests/test_getAtlasFilename.m
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@ function test_getAtlasFilename_wang()
rmRetinoAtlas();

atlasFilename = getAtlasFilename('wang');

assertEqual(size(atlasFilename, 1), 2);

atlasFilename = getAtlasFilename('HCPex');
assertEqual(size(atlasFilename, 1), 1);

rmRetinoAtlas();

end
Expand Down
9 changes: 9 additions & 0 deletions tests/test_getLookUpTable.m
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,15 @@ function test_lut_anat_tb()

end

function test_lut_hcpex()

lut = getLookUpTable('hcpex');

assertEqual(lut.label, [2:426]');
assertEqual(lut.ROI{417}, 'R_Gpe');

end

function test_lut_neuromorpho()

lut = getLookUpTable('neuromorphometrics');
Expand Down
7 changes: 7 additions & 0 deletions tests/test_unzipAtlas.m
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,13 @@ function test_unzipAtlas_default()
'file'), ...
2);

unzipAtlas('hcpex');

assertEqual(exist( ...
fullfile(returnAtlasDir('hcpex'), 'HCPex.nii'), ...
'file'), ...
2);

cleanUp();

end
Expand Down