Skip to content

Commit ed1b621

Browse files
cleaned up code and updated documentation, added an example script for testing
1 parent 6c7cdda commit ed1b621

8 files changed

+170
-80
lines changed

ni2_activation.m

+9-14
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,19 @@
11
function [data, time] = ni2_activation(varargin)
22

3-
% NI2_ACTIVATION creates a timecourse of simplified activity.
3+
% NI2_ACTIVATION creates a timecourse of the activity of a dipole in the brain.
44
%
55
% Use as
66
% [data, time] = ni2_activation
77
% [data, time] = ni2_activation('key1', value1, 'key2', value2)
88
%
9-
% Input arguments:
10-
% key-value pairs determine the shape of the activations.
11-
%
12-
% frequency, scalar value (in Hz): frequency of oscillatory burst, default = 10 Hz
13-
% phase, scalar value (in radians): phase of the oscillation at the
14-
% peak latency, default = 0
15-
% latency, scalar value (in s): latency at which the amplitude of the
16-
% oscillation peaks, default = 0.5
17-
% length, scalar value (in s): length of the activation time course,
18-
% the sampling interval is fixed to 1 ms/sampl, default = 1
19-
% ncycle, scalar value: number of oscillatory cycles in the burst, default = 5
20-
% powerup, binary value: 1 = power burst (default); 0 = power loss
21-
% fsample, scalar value: sampling rate (Hz) (default 1000 Hz)
9+
% Options should be specified as key-value pairs and can be
10+
% frequency = scalar value (in Hz): frequency of oscillatory burst, default = 10 Hz
11+
% phase = scalar value (in radians): phase of the oscillation at the peak latency, default = 0
12+
% latency = scalar value (in s): latency at which the amplitude of the oscillation peaks, default = 0.5
13+
% length = scalar value (in s): length of the activation time course, the sampling interval is fixed to 1 ms/sampl, default = 1
14+
% ncycle = scalar value: number of oscillatory cycles in the burst, default = 5
15+
% powerup = binary value: 1 = power burst (default); 0 = power loss
16+
% fsample = scalar value: sampling rate (Hz) (default 1000 Hz)
2217
%
2318
% Output arguments:
2419
% data = 1xN vector with the activation time course

ni2_example.m

+68
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
[activity, time] = ni2_activation;
2+
figure; plot(time, activity);
3+
4+
%%
5+
6+
[activity, time] = ni2_activation('frequency', 100);
7+
figure; plot(time, activity);
8+
9+
%%
10+
11+
[activity, time] = ni2_activation('frequency', 5);
12+
figure; plot(time, activity);
13+
14+
%%
15+
16+
headmodel = ni2_headmodel('type', 'singleshell');
17+
figure; ft_plot_headmodel(headmodel, 'axes', true);
18+
19+
%%
20+
21+
headmodel = ni2_headmodel('type', 'spherical', 'nshell', 3);
22+
figure; ft_plot_headmodel(headmodel, 'axes', true);
23+
24+
%%
25+
26+
headmodel = ni2_headmodel('type', 'spherical', 'nshell', 1);
27+
figure; ft_plot_headmodel(headmodel, 'axes', true);
28+
29+
%%
30+
31+
sens = ni2_sensors('type', 'eeg');
32+
figure; ft_plot_sens(sens, 'label', 'number')
33+
34+
%%
35+
36+
sens = ni2_sensors('type', 'ctf151');
37+
figure; ft_plot_sens(sens, 'label', 'label', 'coil', false)
38+
figure; ft_plot_sens(sens, 'label', 'label', 'coil', true)
39+
40+
%%
41+
42+
sens = ni2_sensors('type', 'meg');
43+
figure; ft_plot_sens(sens, 'label', 'number', 'coil', true)
44+
45+
%%
46+
47+
leadfield = ni2_leadfield(sens, headmodel, [0 0 6 1 0 0]);
48+
figure; ni2_topoplot(sens, leadfield)
49+
50+
%%
51+
52+
data = leadfield * activity;
53+
54+
figure; ni2_topomovie(sens, data, time)
55+
56+
%%
57+
58+
sourcemodel = ni2_sourcemodel('type', 'mesh');
59+
60+
figure; ft_plot_mesh(sourcemodel)
61+
figure; ft_plot_mesh(sourcemodel.pos(sourcemodel.inside,:))
62+
63+
%%
64+
65+
sourcemodel = ni2_sourcemodel('type', 'grid', 'resolution', 1);
66+
67+
figure; ft_plot_mesh(sourcemodel)
68+
figure; ft_plot_mesh(sourcemodel.pos(sourcemodel.inside,:))

ni2_headmodel.m

+10-6
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
11
function headmodel = ni2_headmodel(varargin)
22

3-
% NI2_HEADMODEL generates a simple headmodel for forward modeling.
3+
% NI2_HEADMODEL generates a simple headmodel for forward modeling.
44
%
5-
% Use as:
6-
% headmodel = ni2_headmodel('type', 'spherical', 'nshell', 1);
7-
% headmodel = ni2_headmodel('type', 'spherical', 'nshell', 3);
5+
% Use as
6+
% headmodel = ni2_headmodel('type', 'spherical', 'nshell', 1);
7+
% headmodel = ni2_headmodel('type', 'spherical', 'nshell', 3);
88
%
99
% The first call creates a singlesphere volume conduction model that can be
1010
% used in combination with MEG sensor-arrays. The second call creates a
1111
% three concentric spheres model that can be used in combination with EEG
1212
% sensor-arrays.
13+
%
14+
% The headmodel is expressed in cm and in the CTF coordinate system.
1315

1416
type = ft_getopt(varargin, 'type', 'spherical');
1517
n = ft_getopt(varargin, 'nshell', 1);
@@ -25,6 +27,7 @@
2527
headmodel.type = 'singlesphere';
2628
headmodel = ft_datatype_headmodel(headmodel);
2729
headmodel.coordsys = 'ctf';
30+
2831
case 3
2932
headmodel.o = [0 0 0];
3033
headmodel.r = [0.88 0.92 1.00]*10;
@@ -33,15 +36,16 @@
3336
headmodel.type = 'concentricspheres';
3437
headmodel = ft_datatype_headmodel(headmodel);
3538
headmodel.coordsys = 'ctf';
39+
3640
otherwise
3741
error('number of spheres other than 1 or 3 is not supported');
3842
end
3943

4044
case 'singleshell'
4145
% note that this is in CTF coordinates
42-
load('Subject01_headmodel');
46+
load('Subject01_headmodel.mat');
4347
headmodel.coordsys = 'ctf';
4448

4549
otherwise
46-
error('unknown type requested');
50+
error('unknown headmodel type');
4751
end

ni2_leadfield.m

+19-14
Original file line numberDiff line numberDiff line change
@@ -3,40 +3,45 @@
33
% NI2_LEADFIELD generates a leadfield for a given source (or set of
44
% sources) using a specified sensor array and volume conductor model.
55
%
6-
% Use as:
6+
% Use as
77
% leadfield = ni2_leadfield(sens, headmodel, dippar)
88
%
99
% Input arguments:
10-
% - sens = a sensor array, obtained with ni2_sensors
11-
% - headmodel = a volume conductor model, obtained with ni2_headmodel
12-
% - dippar = Nx6, or Nx3 matrix with dipole parameters.
10+
% sens = a sensor array, obtained with NI2_SENSORS
11+
% headmodel = a volume conductor model, obtained with NI2_HEADMODEL
12+
% dippar = Nx3 or Nx6 matrix with dipole parameters, where N is the number of dipoles
13+
%
14+
% Each row in the dippar-matrix represents a source, the first columns 1-3 are the
15+
% dipole position parameters (x,y,z coordinates in Cartesian space), and the optional
16+
% columns 4-6 are the dipole moment parameters (x,y,z orientation, these can include
17+
% the amplitude).
1318
%
14-
% Each row in the dippar-matrix represents a source, the first 3 columns
15-
% are the position parameters (x,y,z coordinates in Cartesian space), and
16-
% the options 4-6 columns are the dipole moment parameters (x,y,z
17-
% orientation and amplitude).
18-
%
1919
% Output argument:
20-
% - leadfield = MxN or Mx(Nx3) matrix with the leadfield, where M is the
21-
% number of sensors, and N the number of sources
20+
% leadfield = MxN or Mx(Nx3) matrix with the leadfield, where M is the number of sensors
21+
% and N is the number of dipoles. There are three columns for dipoles with
22+
% an unspecified orientation.
2223

2324
ndip = size(dippar, 1);
2425

2526
cfg = [];
27+
2628
if strcmp(sens.chantype{1}, 'eeg')
2729
cfg.elec = sens;
2830
else
2931
cfg.grad = sens;
3032
end
31-
cfg.headmodel = headmodel;
33+
34+
cfg.headmodel = headmodel;
3235
cfg.sourcemodel.pos = dippar(:,1:3);
3336
cfg.sourcemodel.inside = 1:ndip;
3437
cfg.sourcemodel.unit = headmodel.unit;
35-
cfg.reducerank = 'no';
38+
cfg.reducerank = 'no';
39+
3640
if strcmp(headmodel.type, 'singleshell')
3741
cfg.singleshell.batchsize = 2500;
3842
end
39-
leadf = ft_prepare_leadfield(cfg);
43+
44+
leadf = ft_prepare_leadfield(cfg);
4045

4146
if size(dippar, 2)==6
4247
leadfield = zeros(size(leadf.leadfield{1},1), ndip);

ni2_sensors.m

+15-8
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,23 @@
11
function sens = ni2_sensors(varargin)
22

3-
% NI2_SENSORS create a fictive sensor-array.
3+
% NI2_SENSORS creates an EEG or MEG sensor array.
44
%
55
% Use as
6-
% sens = ni2_sensors('type', senstype);
6+
% sens = ni2_sensors('type', 'eeg')
7+
% sens = ni2_sensors('type', 'meg')
8+
% sens = ni2_sensors('type', 'ctf151')
9+
% sens = ni2_sensors('type', 'ctf275')
10+
% sens = ni2_sensors('type', 'bti248')
11+
% sens = ni2_sensors('type', 'neuromag306')
12+
% sens = ni2_sensors('type', 'eeg1020')
13+
% sens = ni2_sensors('type', 'eeg1010')
714
%
8-
% Where senstype can be any of the following:
9-
% 'eeg' generates a 91-channel eeg sensor array
10-
% 'meg' generates a 301-channel meg magnetometer sensor array
11-
% 'meg_grad_axial' generates a 301-channel meg axial gradiometer sensor
12-
% array.
13-
15+
% The default EEG sensor array consists of 91 electrodes over the upper half of a
16+
% sphere. The default MEG sensor array consists of 301 axial magnetometers over the
17+
% upper half of a sphere.
18+
%
19+
% Note that the units and the coordinate systems in which the sensors are described
20+
% can differ.
1421

1522
type = ft_getopt(varargin, 'type', 'eeg');
1623
jitter = ft_getopt(varargin, 'jitter', 0);

ni2_sourcemodel.m

+16-15
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,38 @@
11
function sourcemodel = ni2_sourcemodel(varargin)
22

3-
% NI2_SOURCEMODEL generates a sourcemodel for forward and inverse modeling.
3+
% NI2_SOURCEMODEL generates a sourcemodel for forward and inverse modeling.
44
%
5-
% Use as:
6-
% sourcemodel = ni2_sourcemodel('type', 'grid', 'resolution', res)
5+
% Use as
6+
% sourcemodel = ni2_sourcemodel('type', 'mesh');
7+
% sourcemodel = ni2_sourcemodel('type', 'grid', 'resolution', res)
78
%
8-
% Where res is a scalar that specifies the spacing between the dipoles (in
9-
% cm). A regular 3-dimensional grid of dipoles is created.
9+
% The first call returns a source model that consists of many dipoles that form a
10+
% triangulated mesh that describes the cortical sheet.
11+
%
12+
% The second call creates a regular 3-dimensional grid of dipoles. The parameter res
13+
% is a scalar (in cm) that specifies the resolution, i.e., the spacing between the
14+
% dipoles.
1015

11-
type = ft_getopt(varargin, 'type', 'grid');
16+
type = ft_getopt(varargin, 'type', 'grid');
1217
headmodel = ft_getopt(varargin, 'headmodel', []);
1318
resolution = ft_getopt(varargin, 'resolution', 0.5); % in cm
1419

1520
switch type
1621
case 'grid'
1722
if isempty(headmodel)
18-
resolution = ft_getopt(varargin, 'resolution', 0.5);
1923
ax = 0:resolution:9;
2024
ax = [-fliplr(ax(2:end)) ax];
2125
[x,y,z] = ndgrid(ax, ax, ax(ax>-1));
22-
in = false(size(x));
23-
in(sqrt(x.^2+y.^2+z.^2)<=9) = true;
26+
inside = false(size(x));
27+
inside(sqrt(x.^2+y.^2+z.^2)<=9) = true;
2428

2529
pos = [x(:) y(:) z(:)];
26-
% inside = find(in);
27-
% outside = find(in==0);
2830
clear x y z
2931

3032
sourcemodel.pos = pos;
31-
% sourcemodel.inside = inside;
32-
% sourcemodel.outside = outside;
33-
sourcemodel.inside = in(:);
33+
sourcemodel.inside = inside(:);
3434
sourcemodel.dim = [numel(ax) numel(ax) numel(ax(ax>-1))];
35+
sourcemodel.unit = 'cm';
3536

3637
else
3738
headmodel = ft_convert_units(headmodel);
@@ -40,7 +41,7 @@
4041

4142
cfg = [];
4243
cfg.headmodel = headmodel;
43-
cfg.resolution = resolution;
44+
cfg.resolution = resolution; % in cm
4445
cfg.inwardshift = -1.*resolution;
4546
sourcemodel = ft_prepare_sourcemodel(cfg);
4647

ni2_topomovie.m

+19-7
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,30 @@
1-
function ni2_topomovie(sens, dat, time, cfg)
1+
function ni2_topomovie(sens, data, time, cfg)
2+
3+
% NI2_TOPOMOVIE makes a movie of the 2D-projection of the spatial EEG or MEG
4+
% topography as it changes over time.
5+
%
6+
% Use as
7+
% ni2_topoplot(sens, data, time)
8+
%
9+
% Input arguments:
10+
% sens = a sensor-array as obtained with NI2_SENSORS
11+
% data = a NxT matrix representing a spatial topography over time. The number of rows (N)
12+
% should be equal to the number of sensors in the sens structure, the number of
13+
% columns should be equal to the number of time points.
14+
15+
if nargin<4
16+
cfg = [];
17+
end
218

319
% ensure the sensor description to be according to what FieldTrip expects
420
sens = ft_datatype_sens(sens);
521

6-
% construct a timelocked ERP data structure
22+
% construct a timelocked ERP data structure that FieldTrip can deal with
723
timelock = [];
824
timelock.time = time;
9-
timelock.avg = dat;
25+
timelock.avg = data;
1026
timelock.label = sens.label;
1127

12-
if nargin<4
13-
cfg = [];
14-
end
15-
1628
if ~isfield(cfg, 'layout')
1729
% create layout
1830
if strncmp(sens.chantype{1}, 'meg', 3)

0 commit comments

Comments
 (0)