Skip to content

Commit 0fa7b4d

Browse files
Merge pull request #38 from marcobarilari/marco_add-visfAtlas
Add visfAtlas
2 parents d9910b3 + 3786bb0 commit 0fa7b4d

16 files changed

+148
-20
lines changed

Makefile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33
clean:
44
rm -rf coverage*
55
rm version.txt
6+
7+
clean_lib:
8+
rm -rf lib/bids-matlab
9+
610
install_dev:
711
git clone https://github.com/bids-standard/bids-matlab.git --branch dev --depth 1 lib/bids-matlab
812

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,11 @@ as a submodule, and intitialized when running `initCppSpm`.
7070
Probabilistic Maps of Visual Topography in Human Cortex. Cerebral
7171
cortex (New York, N.Y. : 1991), 25(10), 3911–3931.
7272
https://doi.org/10.1093/cercor/bhu277
73+
- the probabilistic functional atlas of human occipito-temporal visual cortex
74+
- Rosenke, M., van Hoof, R., van den Hurk, J., Grill-Spector, K., & Goebel, R. (2021).
75+
A Probabilistic Functional Atlas of Human Occipito-Temporal Visual Cortex.
76+
Cerebral cortex (New York, N.Y. : 1991), 31(1), 603–619.
77+
https://doi.org/10.1093/cercor/bhaa246
7378

7479
Also includes:
7580

atlas/returnAtlasDir.m

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,21 @@
1414

1515
if nargin > 0
1616

17-
switch atlas
17+
switch lower(atlas)
1818

1919
case 'wang'
2020
atlasDir = fullfile(atlasDir, 'visual_topography_probability_atlas');
2121

2222
case 'anatomy_toobox'
2323
atlasDir = fullfile(spm('dir'), 'toolbox', 'Anatomy');
2424

25+
case 'visfatlas'
26+
atlasDir = fullfile(atlasDir, 'visfAtlas');
27+
28+
case 'neuromorphometrics'
29+
30+
otherwise
31+
error('unknown atlas type');
2532
end
2633

2734
end

atlas/visfAtlas/LUT.csv

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
label,ROI,func
2+
1,lh_mFus,faces
3+
2,lh_pFus,faces
4+
3,lh_IOG,faces
5+
4,lh_OTS,bodies
6+
5,lh_ITG,bodies
7+
6,lh_MTG,bodies
8+
7,lh_LOS,bodies
9+
8,lh_pOTS,characters
10+
9,lh_IOS,haracters
11+
10,lh_CoS,places
12+
11,lh_hMT,motion
13+
12,lh_v1d,retinotopic
14+
13,lh_v2d,retinotopic
15+
14,lh_v3d,retinotopic
16+
15,lh_v1v,retinotopic
17+
16,lh_v2v,retinotopic
18+
17,lh_v3v,retinotopic
19+
18,rh_mFus,faces
20+
19,rh_pFus,faces
21+
20,rh_IOG,faces
22+
21,rh_OTS,bodies
23+
22,rh_ITG,bodies
24+
23,rh_MTG,bodies
25+
24,rh_LOS,bodies
26+
25,rh_CoS,places
27+
26,rh_TOS,places
28+
27,rh_hMT,motion
29+
28,rh_v1d,retinotopic
30+
29,rh_v2d,retinotopic
31+
30,rh_v3d,retinotopic
32+
31,rh_v1v,retinotopic
33+
32,rh_v2v,retinotopic
34+
33,rh_v3v,retinotopic

atlas/visfAtlas/README.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
visfAtlas in nifti volume format
2+
3+
The visfAtlas is based on N19 subjects. In FreeSurfer, it is aligned to the fsaverage brain. In BrainVoyager, it is aligned to a newly generated average brain for BrainVoyager, called the BVaverage. The BVaverage is distributed with this publication. The nifti volume atlas is aligned to the MNI colin27 brain.
4+
5+
Citing:
6+
7+
Please cite the article for use of the functional atlas as well as the BVaverage.
8+
9+
Rosenke, M., van Hoof, R., van den Hurk, J., Goebel, R. (2020). A probabilistic functional parcellation of human occipito-temporal cortex. TBD
10+
11+
To acknowledge using this atlas in your research, you might include a sentence like one of the following:
12+
13+
"We used the functional atlas of visual cortex developed by Rosenke et al. (2020)…”
14+
15+
16+
The maximum probability map can be visualized by opening the visfATlas\_volume.nii.gz file and loading the correct color map (visfAtlas\_FSL.cmap) through the overlay display panel.
Binary file not shown.

demos/atlas/create_roi_from_atlas.m

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,18 @@
11
% (C) Copyright 2021 CPP ROI developers
22

3-
opt.roi.atlas = 'wang';
4-
opt.roi.name = {'V1v', 'V1d'};
3+
clear all;
4+
clc;
5+
6+
% options : 'wang', 'neuromorphometrics', 'anatomy_toobox', 'visfAtlas'
7+
opt.roi.atlas = 'visfAtlas';
8+
9+
% to get the list of possible run `getLookUpTable(opt.roi.atlas)`
10+
opt.roi.name = {'pFus', 'mFus', 'CoS'};
511
opt.roi.dir = fullfile(pwd, 'derivatives', 'cpp_roi', 'group');
612

713
spm_mkdir(opt.roi.dir);
814

9-
hemi = {'L', 'H'};
15+
hemi = {'L', 'R'};
1016

1117
for iHemi = 1:numel(hemi)
1218

src/atlas/extractRoiFromAtlas.m

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,19 +18,25 @@
1818
%
1919
% (C) Copyright 2021 CPP ROI developers
2020

21+
if ~ismember(hemisphere, {'L', 'R'})
22+
23+
error('\n Hemisphere label %s not valid, try "L" or "R"', hemisphere);
24+
25+
end
26+
2127
[atlasFile, lut] = getAtlasAndLut(atlasName);
2228

23-
if strcmp(atlasName, 'wang')
29+
if strcmpi(atlasName, 'wang')
2430

25-
if strcmp(hemisphere, 'L')
31+
if strcmpi(hemisphere, 'L')
2632
atlasFile = atlasFile(1, :);
2733
else
2834
atlasFile = atlasFile(2, :);
2935
end
3036

3137
roiIdx = strcmp(roiName, lut.ROI);
3238

33-
elseif strcmp(atlasName, 'neuromorphometrics')
39+
elseif strcmpi(atlasName, 'neuromorphometrics')
3440

3541
roiName = regexprep(roiName, '(Left )|(Right )', '');
3642

@@ -43,6 +49,17 @@
4349

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

52+
elseif strcmpi(atlasName, 'visfatlas')
53+
54+
prefix = '';
55+
if strcmp(hemisphere, 'L')
56+
prefix = 'lh_';
57+
elseif strcmp(hemisphere, 'R')
58+
prefix = 'rh_';
59+
end
60+
61+
roiIdx = strcmp([prefix roiName], lut.ROI);
62+
4663
end
4764

4865
% create ROI

src/atlas/getAtlasFilename.m

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

1919
atlasDir = returnAtlasDir(atlasName);
2020

21-
if ~ismember(atlasName, {'wang', 'neuromorphometrics', 'anatomy_toobox'})
21+
if ~ismember(lower(atlasName), {'wang', 'neuromorphometrics', 'anatomy_toobox', 'visfatlas'})
2222
% TODO throw a proper error here
2323
error('unknown atlas type');
2424
end
@@ -46,6 +46,10 @@
4646

4747
error('not implemented yet');
4848

49+
case 'visfatlas'
50+
51+
atlasFilename = fullfile(atlasDir, 'space-MNI_atlas-visfAtlas_dseg.nii');
52+
4953
end
5054

5155
end

src/atlas/getLookUpTable.m

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919

2020
atlasDir = returnAtlasDir(atlasName);
2121

22-
if ~ismember(atlasName, {'wang', 'neuromorphometrics', 'anatomy_toobox'})
22+
if ~ismember(lower(atlasName), {'wang', 'neuromorphometrics', 'anatomy_toobox', 'visfatlas'})
2323
% TODO throw a proper error here
2424
error('unknown atlas type');
2525
end
@@ -55,6 +55,12 @@
5555
roiLabelLUT = struct('ROI', C(1), ...
5656
'label', C(2));
5757

58+
case 'visfatlas'
59+
60+
unzipAtlas('visfAtlas');
61+
62+
roiLabelLUT = spm_load(fullfile(atlasDir, 'LUT.csv'));
63+
5864
end
5965

6066
end

src/atlas/unzipAtlas.m

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,12 @@ function unzipAtlas(atlas)
2222

2323
end
2424

25+
elseif strcmp(atlas, 'visfAtlas')
26+
27+
file = fullfile(atlasDir, 'visfAtlas/space-MNI_atlas-visfAtlas_dseg.nii.gz');
28+
29+
gunzip(file);
30+
2531
end
2632

2733
end

tests/test_createRoi.m

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ function test_createRoi_intersection_mask_sphere()
4949

5050
mask = createRoi('intersection', specification, volumeDefiningImage, outputDir, saveImg);
5151

52-
basename = 'rspace-MNI_atlas-neurosynth_label-visualMotionIntersection_desc-p10pt00_mask';
52+
basename = 'space-MNI_atlas-neurosynth_label-visualMotionIntersection_desc-p10pt00_mask';
5353

5454
assertEqual(exist(fullfile(thisDir(), [basename '.nii']), 'file'), 2);
5555
assertEqual(exist(fullfile(thisDir(), [basename '.json']), 'file'), 2);
@@ -75,7 +75,7 @@ function test_createRoi_intersection_mask_sphere()
7575

7676
mask = createRoi('expand', specification, volumeDefiningImage, outputDir, saveImg);
7777

78-
basename = 'rspace-MNI_atlas-neurosynth_label-visualMotionExpandVox57_desc-p10pt00_mask';
78+
basename = 'space-MNI_atlas-neurosynth_label-visualMotionExpandVox57_desc-p10pt00_mask';
7979

8080
assertEqual(mask.roi.size, 57);
8181

@@ -95,7 +95,8 @@ function test_createRoi_intersection_mask_sphere()
9595

9696
value = fullfile(thisDir(), '..', 'demos', 'roi', 'inputs');
9797

98-
if exist(fullfile(value, 'TStatistic.nii'), 'file') == 0
98+
if exist(fullfile(value, 'TStatistic.nii'), 'file') == 0 || ...
99+
exist(fullfile(value, 'visual motion_association-test_z_FDR_0.01.nii'), 'file') == 0
99100
gunzip(fullfile(value, '*.gz'));
100101
end
101102

@@ -106,7 +107,7 @@ function test_createRoi_intersection_mask_sphere()
106107
volumeDefiningImage = fullfile(demoDir(), 'TStatistic.nii');
107108

108109
roiFilename = fullfile(demoDir(), ...
109-
'rspace-MNI_atlas-neurosynth_label-visualMotion_desc-p10pt00_mask.nii');
110+
'space-MNI_atlas-neurosynth_label-visualMotion_desc-p10pt00_mask.nii');
110111

111112
if exist(roiFilename, 'file') == 2
112113

@@ -117,6 +118,8 @@ function test_createRoi_intersection_mask_sphere()
117118
zMap = renameNeuroSynth(zMap);
118119
zMap = resliceRoiImages(volumeDefiningImage, zMap);
119120

121+
zMap = removePrefix(zMap, 'r');
122+
120123
threshold = 10;
121124
roiFilename = thresholdToMask(zMap, threshold);
122125

tests/test_createRoiName.m

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,9 @@ function test_createRoiName_non_sphere()
2828
roiName = createRoiName(mask);
2929
assertEqual(roiName, 'one-entity_mask.nii');
3030

31-
% This will likely break when bids-matlab is updated and the order of entities
32-
% is imposed by the schema
33-
%
34-
% label-foo_one-entity_mask.nii
35-
%
3631
mask.label = 'foo';
3732
roiName = createRoiName(mask);
38-
assertEqual(roiName, 'one-entity_label-foo_mask.nii');
33+
assertEqual(roiName, 'label-foo_one-entity_mask.nii');
3934

4035
end
4136

tests/test_extractRoiFromAtlas.m

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,19 @@ function test_extractRoiFromAtlas_neuromorphometrics()
4040
delete(fullfile(pwd, '*.json'));
4141

4242
end
43+
44+
function test_extractRoiFromAtlas_visfAtlas()
45+
46+
roiImage = extractRoiFromAtlas(pwd, 'visfatlas', 'pFus', 'L');
47+
48+
assertEqual(exist(fullfile(pwd, 'hemi-L_space-MNI_atlas-visfatlas_label-pFus_mask.nii'), ...
49+
'file'), ...
50+
2);
51+
52+
vol = spm_read_vols(spm_vol(roiImage));
53+
assertEqual(sum(vol(:) == 1), 655); % check the ROI has the right number of voxel
54+
55+
delete(fullfile(pwd, '*.nii'));
56+
delete(fullfile(pwd, '*.json'));
57+
58+
end

tests/test_getLookUpTable.m

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,15 @@ function test_lut_neuromorpho()
4343

4444
end
4545

46+
function test_lut_visfAtlas()
47+
48+
lut = getLookUpTable('visfatlas');
49+
50+
assertEqual(lut.label, [1:33]');
51+
assertEqual(lut.ROI{1}, 'lh_mFus');
52+
53+
end
54+
4655
function cleanUp()
4756

4857
pause(1);

tests/test_unit_returnAtlasDir.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
function test_returnAtlasDir_default()
1212

13-
atlasDir = returnAtlasDir('neuromorphometric');
13+
atlasDir = returnAtlasDir('neuromorphometrics');
1414

1515
assertEqual(atlasDir, returnAtlasDir());
1616

0 commit comments

Comments
 (0)