/
ft_plot_headmodel.m
192 lines (169 loc) · 7.38 KB
/
ft_plot_headmodel.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
function ft_plot_headmodel(headmodel, varargin)
% FT_PLOT_HEADMODEL visualizes the boundaries in the volume conduction model of the
% head as specified in the headmodel structure. This works for any of the head models
% supported by FieldTrip. For spherical models, it will construct and plot a
% triangulated sphere.
%
% Use as
% ft_plot_headmodel(headmodel, ...)
%
% Optional arguments should come in key-value pairs and can include
% 'facecolor' = [r g b] values or string, for example 'brain', 'cortex', 'skin', 'black', 'red', 'r', or an Nx3 or Nx1 array where N is the number of faces
% 'vertexcolor' = [r g b] values or string, for example 'brain', 'cortex', 'skin', 'black', 'red', 'r', or an Nx3 or Nx1 array where N is the number of vertices
% 'edgecolor' = [r g b] values or string, for example 'brain', 'cortex', 'skin', 'black', 'red', 'r'
% 'faceindex' = true or false
% 'vertexindex' = true or false
% 'facealpha' = transparency, between 0 and 1 (default = 1)
% 'edgealpha' = transparency, between 0 and 1 (default = 1)
% 'surfaceonly' = true or false, plot only the outer surface of a hexahedral or tetrahedral mesh (default = false)
% 'unit' = string, convert to the specified geometrical units (default = [])
% 'axes' = boolean, whether to plot the axes of the 3D coordinate system (default = false)
% 'grad' = gradiometer array, used in combination with local spheres model
%
% Example
% headmodel = [];
% headmodel.r = [86 88 92 100];
% headmodel.o = [0 0 40];
% figure
% ft_plot_headmodel(headmodel)
%
% See also FT_PREPARE_HEADMODEL, FT_DATATAYPE_HEADMODEL, FT_PLOT_MESH,
% FT_PLOT_HEADSHAPE, FT_PLOT_SENS, FT_PLOT_DIPOLE, FT_PLOT_ORTHO, FT_PLOT_TOPO3D
% Copyright (C) 2009, Cristiano Micheli
% Copyright (C) 2009-2023, Robert Oostenveld
%
% This file is part of FieldTrip, see http://www.fieldtriptoolbox.org
% for the documentation and details.
%
% FieldTrip is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% FieldTrip is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with FieldTrip. If not, see <http://www.gnu.org/licenses/>.
%
% $Id$
% ensure that the volume conduction model description is up-to-date (Dec 2012)
headmodel = ft_datatype_headmodel(headmodel);
% get the optional input arguments
faceindex = ft_getopt(varargin, 'faceindex', 'none');
vertexindex = ft_getopt(varargin, 'vertexindex', 'none');
vertexsize = ft_getopt(varargin, 'vertexsize', 10);
facecolor = ft_getopt(varargin, 'facecolor', 'white');
vertexcolor = ft_getopt(varargin, 'vertexcolor', 'none');
edgecolor = ft_getopt(varargin, 'edgecolor'); % the default for this is set below
facealpha = ft_getopt(varargin, 'facealpha', 1);
edgealpha = ft_getopt(varargin, 'edgealpha', 1);
surfaceonly = ft_getopt(varargin, 'surfaceonly');
unit = ft_getopt(varargin, 'unit');
axes_ = ft_getopt(varargin, 'axes', false); % do not confuse with built-in (/Applications/MATLAB_R2020b.app/toolbox/matlab/graphics/axis/axes)
grad = ft_getopt(varargin, 'grad');
if ~isempty(unit)
headmodel = ft_convert_units(headmodel, unit);
if ~isempty(grad)
grad = ft_convert_units(grad, unit);
end
end
faceindex = istrue(faceindex); % yes=view the face number
vertexindex = istrue(vertexindex); % yes=view the vertex number
% we will probably need a sphere, so let's prepare one in advance
[pos, tri] = mesh_sphere(2562);
% prepare a mesh that consists of a single or multiple triangulated boundaries
switch ft_headmodeltype(headmodel)
case {'singlesphere' 'concentricspheres'}
headmodel.r = sort(headmodel.r);
mesh = repmat(struct(), numel(headmodel.r));
for i=1:numel(headmodel.r)
mesh(i).pos(:,1) = pos(:,1)*headmodel.r(i) + headmodel.o(1);
mesh(i).pos(:,2) = pos(:,2)*headmodel.r(i) + headmodel.o(2);
mesh(i).pos(:,3) = pos(:,3)*headmodel.r(i) + headmodel.o(3);
mesh(i).tri = tri;
if isfield(headmodel, 'unit')
mesh(i).unit = headmodel.unit;
end
if isfield(headmodel, 'coordsys')
mesh(i).coordsys= headmodel.coordsys;
end
end
if isempty(edgecolor)
edgecolor = 'none';
end
case 'localspheres'
if ~isempty(grad)
ft_notice('estimating point on head surface for each gradiometer');
[headmodel, grad] = ft_prepare_vol_sens(headmodel, grad);
[mesh.pos, mesh.tri] = headsurface(headmodel, grad);
else
ft_notice('plotting sphere for each gradiometer');
mesh = repmat(struct(), numel(headmodel.label));
for i=1:numel(headmodel.label)
mesh(i).pos(:,1) = pos(:,1)*headmodel.r(i) + headmodel.o(i,1);
mesh(i).pos(:,2) = pos(:,2)*headmodel.r(i) + headmodel.o(i,2);
mesh(i).pos(:,3) = pos(:,3)*headmodel.r(i) + headmodel.o(i,3);
mesh(i).tri = tri;
end
end
if isempty(edgecolor)
edgecolor = 'none';
end
case {'bem', 'dipoli', 'asa', 'bemcp', 'singleshell' 'openmeeg'}
% these already contain one or multiple triangulated surfaces for the boundaries
mesh = headmodel.bnd;
case 'simbio'
% the ft_plot_mesh function below wants the SIMBIO tetrahedral or hexahedral mesh
mesh = headmodel;
% only plot the outer surface of the volume
surfaceonly = true;
if isempty(edgecolor)
edgecolor = 'none';
end
case 'simnibs'
if isfield(headmodel, 'bnd')
% continue with the triangular mesh
mesh = headmodel.bnd;
else
% continue with the tetrahedral or hexahedral mesh
mesh = headmodel;
% only plot the outer surface of the volume
surfaceonly = true;
if isempty(edgecolor)
edgecolor = 'none';
end
end
case 'interpolate'
xgrid = 1:headmodel.dim(1);
ygrid = 1:headmodel.dim(2);
zgrid = 1:headmodel.dim(3);
[x, y, z] = ndgrid(xgrid, ygrid, zgrid);
gridpos = ft_warp_apply(headmodel.transform, [x(:) y(:) z(:)]);
% plot the dipole positions that are inside
plot3(gridpos(headmodel.inside, 1), gridpos(headmodel.inside, 2), gridpos(headmodel.inside, 3), 'k.');
% there is no boundary to be displayed
mesh = [];
case {'infinite' 'infinite_monopole' 'infinite_currentdipole' 'infinite_magneticdipole'}
ft_warning('there is nothing to plot for an infinite volume conductor')
% there is no boundary to be displayed
mesh = [];
otherwise
ft_error('unsupported headmodel type')
end
% use black edges unless otherwise specified
if isempty(edgecolor)
edgecolor = 'k';
end
% plot the triangulated surfaces of the volume conduction model
for i=1:length(mesh)
ft_plot_mesh(mesh(i), 'faceindex', faceindex, 'vertexindex', vertexindex, 'vertexsize', vertexsize, ...
'facecolor', facecolor, 'edgecolor', edgecolor, 'vertexcolor', vertexcolor, ...
'facealpha', facealpha, 'edgealpha', edgealpha, 'surfaceonly', surfaceonly, 'axes', axes_);
end
if isfield(headmodel, 'coordsys')
% add a context sensitive menu to change the 3d viewpoint to top|bottom|left|right|front|back
menu_viewpoint(gca, headmodel.coordsys)
end