Skip to content

Commit

Permalink
Anatomy: Added support for MarsAtlas parcellation in BrainVISA
Browse files Browse the repository at this point in the history
  • Loading branch information
ftadel committed Jun 14, 2019
1 parent 1d5e544 commit 979771f
Show file tree
Hide file tree
Showing 7 changed files with 217 additions and 10 deletions.
2 changes: 1 addition & 1 deletion doc/license.html
Expand Up @@ -3,7 +3,7 @@

</head>
<body alink="#fff000" link="#fff000" vlink="#fff000">
<!-- LICENCE_START -->Version: 3.190612 (12-Jun-2019)<br>
<!-- LICENCE_START -->Version: 3.190614 (14-Jun-2019)<br>
<span style="font-style: italic;">COPYRIGHT &copy; 2000-2019
USC &amp; McGill University.<br>
</span>
Expand Down
1 change: 1 addition & 0 deletions doc/updates.txt
@@ -1,5 +1,6 @@
---------------------------------------------------------------
June 2019
- Anatomy: Added support for MarsAtlas parcellation in BrainVISA
- IO: Support for Intan RHS+RHD files
---------------------------------------------------------------
May 2019
Expand Down
2 changes: 1 addition & 1 deletion doc/version.txt
@@ -1,2 +1,2 @@
% Brainstorm
% v. 3.190612 (12-Jun-2019)
% v. 3.190614 (14-Jun-2019)
57 changes: 55 additions & 2 deletions toolbox/anatomy/tess_detect_region.m
Expand Up @@ -19,10 +19,14 @@
% For more information type "brainstorm license" at command prompt.
% =============================================================================@
%
% Authors: Francois Tadel, 2013
% Authors: Francois Tadel, 2013-2019

% Loop on all the scouts
for i = 1:length(sScouts)
% Remove L and R tags
if (length(sScouts(i).Label) > 3) && ismember(sScouts(i).Label(end-1:end), {' L', ' R'})
sScouts(i).Label = sScouts(i).Label(1:end-2);
end
% Detect region based on the scout name
% USCBrain labels have subdivisions after ' - ', so remove part after
ind = strfind(sScouts(i).Label, ' - ');
Expand Down Expand Up @@ -287,7 +291,56 @@
% Limbic
case 'cingulate gyrus', region = 'L';
case 'subcallosal area', region = 'L';
case 'subcallosal gyrus', region = 'L';
case 'subcallosal gyrus', region = 'L';

% ===== BRAINVISA MARSATLAS =====
% Prefrontal
case 'ofcvl', region = 'PF';
case 'ofcv', region = 'PF';
case 'ofcvm', region = 'PF';
case 'pfcvm', region = 'PF';
% Frontal
case 'pmrv', region = 'F';
case 'pmdl', region = 'F';
case 'pmdm', region = 'F';
case 'pfcdl', region = 'F';
case 'pfcdm', region = 'F';
case 'pfrvl', region = 'F';
case 'pfrdli', region = 'F';
case 'pfrdls', region = 'F';
case 'pfrd', region = 'F';
case 'pfrm', region = 'F';
% Central
case 'mv', region = 'C';
case 'mdl', region = 'C';
case 'mdm', region = 'C';
case 'sv', region = 'C';
case 'sdl', region = 'C';
case 'sdm', region = 'C';
% Parietal
case 'ipcv', region = 'P';
case 'ipcd', region = 'P';
case 'spc', region = 'P';
case 'spcm', region = 'P';
case 'pcm', region = 'P';
% Temporal
case 'itcm', region = 'T';
case 'itcr', region = 'T';
case 'mtcc', region = 'T';
case 'stcc', region = 'T';
case 'stcr', region = 'T';
case 'mtcr', region = 'T';
% Occipital
case 'vccm', region = 'O';
case 'vcl', region = 'O';
case 'vcs', region = 'O';
case 'cu', region = 'O';
case 'vcrm', region = 'O';
% Limbic
case 'icc', region = 'L';
case 'pcc', region = 'L';
case 'mcc', region = 'L';
case 'acc', region = 'L';

% DEFAULT: Unknown
otherwise
Expand Down
103 changes: 103 additions & 0 deletions toolbox/gui/panel_scout.m
Expand Up @@ -5566,6 +5566,109 @@ function SaveScouts(varargin)
end
end

%% ===== GET MARSATLAS LABELS =====
function Labels = GetMarsAtlasLabels()
Labels = {...
0, 'Unknown', [255 255 255]; ...
1, 'VCcm L', [255 0 0]; ...
101, 'VCcm R', [255 0 0]; ...
2, 'VCl L', [ 0 255 0]; ...
102, 'VCl R', [ 0 255 0]; ...
3, 'VCs L', [239 119 41]; ...
103, 'VCs R', [239 119 41]; ...
4, 'Cu L', [210 25 245]; ...
104, 'Cu R', [210 25 245]; ...
5, 'VCrm L', [167 117 74]; ...
105, 'VCrm R', [167 117 74]; ...
6, 'ITCm L', [255 218 47]; ...
106, 'ITCm R', [255 218 47]; ...
7, 'ITCr L', [ 0 30 200]; ...
107, 'ITCr R', [ 0 30 200]; ...
8, 'MTCc L', [145 250 250]; ...
108, 'MTCc R', [145 250 250]; ...
9, 'STCc L', [255 144 195]; ...
109, 'STCc R', [255 144 195]; ...
10, 'STCr L', [250 250 145]; ...
110, 'STCr R', [250 250 145]; ...
11, 'MTCr L', [147 147 179]; ...
111, 'MTCr R', [147 147 179]; ...
12, 'ICC L', [ 23 250 23]; ...
112, 'ICC R', [ 23 250 23]; ...
13, 'IPCv L', [253 238 5]; ...
113, 'IPCv R', [253 238 5]; ...
14, 'IPCd L', [229 24 254]; ...
114, 'IPCd R', [229 24 254]; ...
15, 'SPC L', [ 0 250 0]; ...
115, 'SPC R', [ 0 250 0]; ...
16, 'SPCm L', [125 100 50]; ...
116, 'SPCm R', [125 100 50]; ...
17, 'PCm L', [ 66 15 175]; ...
117, 'PCm R', [ 66 15 175]; ...
18, 'PCC L', [255 212 79]; ...
118, 'PCC R', [255 212 79]; ...
19, 'Sv L', [ 5 218 41]; ...
119, 'Sv R', [ 5 218 41]; ...
20, 'Sdl L', [ 19 219 243]; ...
120, 'Sdl R', [ 19 219 243]; ...
21, 'Sdm L', [250 0 0]; ...
121, 'Sdm R', [250 0 0]; ...
22, 'Mv L', [ 48 36 96]; ...
122, 'Mv R', [ 48 36 96]; ...
23, 'Mdl L', [168 159 174]; ...
123, 'Mdl R', [168 159 174]; ...
24, 'Mdm L', [255 83 219]; ...
124, 'Mdm R', [255 83 219]; ...
25, 'PMrv L', [248 188 124]; ...
125, 'PMrv R', [248 188 124]; ...
26, 'PMdl L', [250 0 250]; ...
126, 'PMdl R', [250 0 250]; ...
27, 'PMdm L', [250 250 0]; ...
127, 'PMdm R', [250 250 0]; ...
28, 'PFcdl L', [ 0 250 0]; ...
128, 'PFcdl R', [ 0 250 0]; ...
29, 'PFcdm L', [255 126 0]; ...
129, 'PFcdm R', [255 126 0]; ...
30, 'MCC L', [ 66 15 6]; ...
130, 'MCC R', [ 66 15 6]; ...
31, 'PFrvl L', [ 0 0 250]; ...
131, 'PFrvl R', [ 0 0 250]; ...
32, 'Pfrdli L', [ 88 43 1]; ...
132, 'Pfrdli R', [ 88 43 1]; ...
33, 'Pfrdls L', [250 0 0]; ...
133, 'Pfrdls R', [250 0 0]; ...
34, 'PFrd L', [ 0 173 0]; ...
134, 'PFrd R', [ 0 173 0]; ...
35, 'PFrm L', [250 250 0]; ...
135, 'PFrm R', [250 250 0]; ...
36, 'OFCvl L', [109 196 24]; ...
136, 'OFCvl R', [109 196 24]; ...
37, 'OFCv L', [188 43 143]; ...
137, 'OFCv R', [188 43 143]; ...
38, 'OFCvm L', [210 231 0]; ...
138, 'OFCvm R', [210 231 0]; ...
39, 'PFCvm L', [188 143 1]; ...
139, 'PFCvm R', [188 143 1]; ...
40, 'ACC L', [ 0 42 255]; ...
140, 'ACC R', [ 0 42 255]; ...
41, 'Insula L', [ 18 243 243]; ...
141, 'Insula R', [ 18 243 243]; ...
210, 'Thalamus L', [255 0 0]; ...
249, 'Thalamus R', [255 0 0]; ...
211, 'Caudate L', [147 147 179]; ...
250, 'Caudate R', [147 147 179]; ...
212, 'Puttamen L', [ 23 250 23]; ...
251, 'Puttamen R', [ 23 250 23]; ...
213, 'Pallidum L', [253 238 5]; ...
252, 'Pallidum R', [253 238 5]; ...
217, 'Hippocampus L', [229 24 254]; ...
253, 'Hippocampus R', [229 24 254]; ...
218, 'Amygdala L', [ 0 250 0]; ...
254, 'Amygdala R', [ 0 250 0]; ...
226, 'Accumbens L', [125 100 50]; ...
258, 'Accumbens R', [125 100 50]; ...
255, 'XIgnore', [255 255 255]};
end


%% ===== VOLUME ATLAS INFO =====
% The name of a volume scout is supposed to be: "Volume 10000: Name"
Expand Down
31 changes: 28 additions & 3 deletions toolbox/io/import_anatomy_bv.m
Expand Up @@ -31,7 +31,7 @@
% For more information type "brainstorm license" at command prompt.
% =============================================================================@
%
% Authors: Francois Tadel, 2012-2018
% Authors: Francois Tadel, 2012-2019

%% ===== PARSE INPUTS =====
% Fiducials
Expand Down Expand Up @@ -116,8 +116,8 @@
HeadFile = {file_find(BvDir, '*head*.mesh'), file_find(BvDir, '*head*.gii')};
TessLhFile = {file_find(BvDir, '*Lhemi*.mesh'), file_find(BvDir, '*Lhemi*.gii')};
TessRhFile = {file_find(BvDir, '*Rhemi*.mesh'), file_find(BvDir, '*Rhemi*.gii')};
TessLwFile = {file_find(BvDir, '*Lwhite*.mesh'), file_find(BvDir, '*Lwhite*.gii')};
TessRwFile = {file_find(BvDir, '*Rwhite*.mesh'), file_find(BvDir, '*Rwhite*.gii')};
TessLwFile = {file_find(BvDir, '*Lwhite*.mesh'), file_find(BvDir, '*Lwhite.gii')};
TessRwFile = {file_find(BvDir, '*Rwhite*.mesh'), file_find(BvDir, '*Rwhite.gii')};
% Find non-empty search results
HeadFile(cellfun(@isempty, HeadFile)) = [];
TessLhFile(cellfun(@isempty, TessLhFile)) = [];
Expand All @@ -127,6 +127,19 @@
if isempty(TessLhFile) || isempty(TessRhFile)
errorMsg = [errorMsg 'Surface file was not found: Lhemi or Rhemi' 10];
end
% Find labels
AnnotLwFiles = {file_find(BvDir, '*_Lwhite_parcels_marsAtlas.gii'), ...
file_find(BvDir, '*_Lwhite_parcels_model.gii'), ...
file_find(BvDir, '*_Lwhite_pole_cingular.gii'), ...
file_find(BvDir, '*_Lwhite_pole_insula.gii'), ...
file_find(BvDir, '*_Lwhite_sulcalines.gii')};
AnnotRwFiles = {file_find(BvDir, '*_Rwhite_parcels_marsAtlas.gii'), ...
file_find(BvDir, '*_Rwhite_parcels_model.gii'), ...
file_find(BvDir, '*_Rwhite_pole_cingular.gii'), ...
file_find(BvDir, '*_Rwhite_pole_insula.gii'), ...
file_find(BvDir, '*_Rwhite_sulcalines.gii')};
AnnotLwFiles(cellfun(@isempty, AnnotLwFiles)) = [];
AnnotRwFiles(cellfun(@isempty, AnnotRwFiles)) = [];
% Find fiducials definitions
FidFile = file_find(BvDir, 'fiducials.m');
% Find AC-PC file
Expand Down Expand Up @@ -319,6 +332,12 @@
% Import file
[iLw, BstTessLwFile] = import_surfaces(iSubject, TessLwFile, 'ALL', 0);
BstTessLwFile = BstTessLwFile{1};
% Load atlases
if ~isempty(AnnotLwFiles)
bst_progress('start', 'Import BrainVISA folder', 'Loading atlases: left...');
[sAllAtlas, err] = import_label(BstTessLwFile, AnnotLwFiles, 1);
errorMsg = [errorMsg err];
end
% Downsample
[BstTessLwLowFile, iLwLow] = tess_downsize(BstTessLwFile, nVertHemi, 'reducepatch');
end
Expand All @@ -327,6 +346,12 @@
% Import file
[iRw, BstTessRwFile] = import_surfaces(iSubject, TessRwFile, 'ALL', 0);
BstTessRwFile = BstTessRwFile{1};
% Load atlases
if ~isempty(AnnotRwFiles)
bst_progress('start', 'Import BrainVISA folder', 'Loading atlases: right...');
[sAllAtlas, err] = import_label(BstTessRwFile, AnnotRwFiles, 1);
errorMsg = [errorMsg err];
end
% Downsample
[BstTessRwLowFile, iRwLow] = tess_downsize(BstTessRwFile, nVertHemi, 'reducepatch');
end
Expand Down
31 changes: 28 additions & 3 deletions toolbox/io/import_label.m
Expand Up @@ -22,7 +22,7 @@
% For more information type "brainstorm license" at command prompt.
% =============================================================================@
%
% Authors: Francois Tadel, 2012-2016
% Authors: Francois Tadel, 2012-2019

import sun.misc.BASE64Decoder;

Expand Down Expand Up @@ -95,6 +95,7 @@
end
% Process one after the other
for iFile = 1:length(LabelFiles)
LabelsTable = [];
% Get updated atlases after the first iteration
if (iFile > 1)
sSurf = bst_memory('LoadSurface', file_short(SurfaceFile));
Expand Down Expand Up @@ -157,8 +158,21 @@
case {'lh.myaparc_250', 'rh.myaparc_250'}
sAtlas.Name = 'Lausanne-S250';
otherwise
% FreeSurfer left/right
if (length(fBase) > 3) && (strcmpi(fBase(1:3), 'lh.') || strcmpi(fBase(1:3), 'rh.'))
sAtlas.Name = fBase(4:end);
% BrainVISA/MarsAtlas
elseif (~isempty(strfind(fBase, '_Lwhite_parcels_marsAtlas')) || ~isempty(strfind(fBase, '_Rwhite_parcels_marsAtlas')))
sAtlas.Name = 'MarsAtlas';
LabelsTable = panel_scout('GetMarsAtlasLabels');
elseif (~isempty(strfind(fBase, '_Lwhite_parcels_model')) || ~isempty(strfind(fBase, '_Rwhite_parcels_model')))
sAtlas.Name = 'MarsAtlas model';
elseif (~isempty(strfind(fBase, '_Lwhite_pole_cingular')) || ~isempty(strfind(fBase, '_Rwhite_pole_cingular')))
sAtlas.Name = 'MarsAtlas pole cingular';
elseif (~isempty(strfind(fBase, '_Lwhite_pole_insula')) || ~isempty(strfind(fBase, '_Rwhite_pole_insula')))
sAtlas.Name = 'MarsAtlas pole insula';
elseif (~isempty(strfind(fBase, '_Lwhite_sulcalines')) || ~isempty(strfind(fBase, '_Rwhite_sulcalines')))
sAtlas.Name = 'MarsAtlas sulcal lines';
else
sAtlas.Name = fBase;
end
Expand Down Expand Up @@ -292,13 +306,21 @@
lablist = unique(Values{ia});
% Loop on each label
for i = 1:length(lablist)
% Scout label: atlas or simply value converted to strinf
if ~isempty(LabelsTable) && ismember(lablist(i), [LabelsTable{:,1}])
scoutLabel = LabelsTable{lablist(i) == [LabelsTable{:,1}], 2};
scoutColor = LabelsTable{lablist(i) == [LabelsTable{:,1}], 3} ./ 255;
else
scoutLabel = num2str(lablist(i));
scoutColor = [];
end
% New scout index
iScout = length(sAtlas(ia).Scouts) + 1;
% Get the vertices for this annotation
sAtlas(ia).Scouts(iScout).Vertices = find(Values{ia} == lablist(i));
sAtlas(ia).Scouts(iScout).Seed = [];
sAtlas(ia).Scouts(iScout).Label = file_unique(num2str(lablist(i)), {sAtlas(ia).Scouts.Label});
sAtlas(ia).Scouts(iScout).Color = [];
sAtlas(ia).Scouts(iScout).Label = file_unique(scoutLabel, {sAtlas(ia).Scouts.Label});
sAtlas(ia).Scouts(iScout).Color = scoutColor;
sAtlas(ia).Scouts(iScout).Function = 'Mean';
sAtlas(ia).Scouts(iScout).Region = 'UU';
end
Expand Down Expand Up @@ -558,6 +580,9 @@
ColorTable = panel_scout('GetScoutsColorTable');
% Loop on all the loaded atlases
for ia = 1:length(sAtlas)
if isempty(sAtlas(ia).Scouts)
continue;
end
% Brodmann atlas: remove the "Unknown" scout
iUnknown = find(strcmpi({sAtlas(ia).Scouts.Label}, 'unknown') | strcmpi({sAtlas(ia).Scouts.Label}, 'medial.wall') | strcmpi({sAtlas(ia).Scouts.Label}, 'freesurfer_defined_medial_wall'));
if ~isempty(iUnknown)
Expand Down

0 comments on commit 979771f

Please sign in to comment.