/
ft_plot_dipole.m
212 lines (185 loc) · 6.78 KB
/
ft_plot_dipole.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
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
function h = ft_plot_dipole(pos, ori, varargin)
% FT_PLOT_DIPOLE makes a 3-D representation of a dipole using a sphere and a stick
% pointing along the dipole orientation
%
% Use as
% ft_plot_dipole(pos, mom, ...)
% where pos and mom are the dipole mosition and moment.
%
% Optional input arguments should be specified in key-value pairs and can include
% 'diameter' = number indicating sphere diameter (default = 'auto')
% 'length' = number indicating length of the stick (default = 'auto')
% 'thickness' = number indicating thickness of the stick (default = 'auto')
% 'color' = [r g b] values or string, for example 'brain', 'cortex', 'skin', 'black', 'red', 'r' (default = 'r')
% 'alpha' = alpha value of the plotted dipole
% 'scale' = scale the dipole with the amplitude, can be 'none', 'both', 'diameter', 'length' (default = 'none')
% 'unit' = 'm', 'cm' or 'mm', used for automatic scaling (default = 'cm')
% 'coordsys' = string, assume the data to be in the specified coordinate system (default = 'unknown')
% 'axes' = boolean, whether to plot the axes of the 3D coordinate system (default = false)
% 'tag' = string, the tag assigned to the plotted elements (default = '')
%
% Example
% ft_plot_dipole([0 0 0], [1 2 3], 'color', 'r', 'alpha', 1)
%
% See also FT_PLOT_MESH, FT_PLOT_HEADMODEL, FT_PLOT_HEADSHAPE, FT_PLOT_ORTHO,
% QUIVER3, PLOT3
% 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$
% get the optional input arguments
amplitudescale = ft_getopt(varargin, 'scale', 'none');
color = ft_getopt(varargin, 'color', 'r'); % can also be a RGB triplet
alpha = ft_getopt(varargin, 'alpha', 1);
diameter = ft_getopt(varargin, 'diameter', 'auto');
length = ft_getopt(varargin, 'length', 'auto');
thickness = ft_getopt(varargin, 'thickness', 'auto');
unit = ft_getopt(varargin, 'unit', 'cm');
coordsys = ft_getopt(varargin, 'coordsys');
axes_ = ft_getopt(varargin, 'axes', false); % do not confuse with built-in function
% for backward compatibility, this can be changed into an error at the end of 2016
units = ft_getopt(varargin, 'units');
if ~isempty(units)
ft_warning('please use "unit" instead of "units"');
unit = units;
clear units
end
if isequal(diameter, 'auto')
% the default is a 5 mm sphere
switch unit
case 'm'
diameter = 0.005;
case 'dm'
diameter = 0.05;
case 'cm'
diameter = 0.5;
case 'mm'
diameter = 5;
otherwise
ft_error('unsupported unit');
end
end
if isequal(length, 'auto')
% the default is a 15 mm long stick
switch unit
case 'm'
length = 0.015;
case 'dm'
length = 0.15;
case 'cm'
length = 1.5;
case 'mm'
length = 15;
otherwise
ft_error('unsupported unit');
end
end
if isequal(thickness, 'auto')
% the default is 1/3 of the sphere diameter
thickness = diameter/3;
end
% dipole position should be Nx3
if all(size(pos) == [3 1])
pos = pos';
end
% dipole moment and orientation should be 3xN
if all(size(ori) == [1 3])
ori = ori';
end
h = [];
% everything is added to the current figure
holdflag = ishold;
if ~holdflag
hold on
end
% these are reused
[unitsphere.pos, unitsphere.tri] = mesh_sphere(642);
[unitcylinder.pos, unitcylinder.tri] = mesh_cylinder(36, 2);
for i=1:size(pos,1)
amplitude = norm(ori(:,i));
ori(:,i) = ori(:,i) ./ amplitude;
% scale the dipole diameter and length with its amplitude
if strcmp(amplitudescale, 'length') || strcmp(amplitudescale, 'both')
this_length = length*amplitude;
else
this_length = length;
end
if strcmp(amplitudescale, 'diameter') || strcmp(amplitudescale, 'both')
this_diameter = diameter*amplitude;
this_thickness = thickness*amplitude;
else
this_diameter = diameter;
this_thickness = thickness;
end
% start with a unit sphere and cylinder
sphere = unitsphere;
stick = unitcylinder;
sphere.pos = ft_warp_apply(scale([0.5 0.5 0.5]), sphere.pos, 'homogeneous'); % the diameter should be 1
stick.pos = ft_warp_apply(scale([0.5 0.5 0.5]), stick.pos, 'homogeneous'); % the length and thickness should be 1
stick.pos = ft_warp_apply(translate([0 0 0.5]), stick.pos, 'homogeneous'); % it should start in the origin
% scale the sphere
sx = this_diameter;
sy = this_diameter;
sz = this_diameter;
sphere.pos = ft_warp_apply(scale([sx sy sz]), sphere.pos, 'homogeneous');
% translate the sphere
tx = pos(i,1);
ty = pos(i,2);
tz = pos(i,3);
sphere.pos = ft_warp_apply(translate([tx ty tz]), sphere.pos, 'homogeneous');
% scale the stick
sx = this_thickness;
sy = this_thickness;
sz = this_length;
stick.pos = ft_warp_apply(scale([sx sy sz]), stick.pos, 'homogeneous');
% first rotate the stick to point along the x-axis
stick.pos = ft_warp_apply(rotate([0 90 0]), stick.pos, 'homogeneous');
% then rotate the stick in the desired direction
[az, el] = cart2sph(ori(1,i), ori(2,i), ori(3,i));
stick.pos = ft_warp_apply(rotate([0 -el*180/pi 0]), stick.pos, 'homogeneous'); % rotate around y-axis
stick.pos = ft_warp_apply(rotate([0 0 az*180/pi]), stick.pos, 'homogeneous'); % rotate around z-axis
% translate the stick
tx = pos(i,1);
ty = pos(i,2);
tz = pos(i,3);
stick.pos = ft_warp_apply(translate([tx ty tz]), stick.pos, 'homogeneous');
% plot the sphere and the stick
p1 = ft_plot_mesh(sphere, 'vertexcolor', 'none', 'edgecolor', false, 'facecolor', color, 'facealpha', alpha);
h = cat(2, h(:)', p1(:)');
clear p1;
p2 = ft_plot_mesh(stick, 'vertexcolor', 'none', 'edgecolor', false, 'facecolor', color, 'facealpha', alpha);
h = cat(2, h(:)', p2(:)');
clear p2;
end % for each dipole
axis off
axis vis3d
axis equal
if istrue(axes_)
% plot the 3D axes, this depends on the units and coordsys
ft_plot_axes([], 'coordsys', coordsys, 'unit', unit);
end
if ~isempty(coordsys)
% add a context sensitive menu to change the 3d viewpoint to top|bottom|left|right|front|back
menu_viewpoint(gca, coordsys)
end
if ~holdflag
hold off
end
if ~nargout
clear h
end