The structure of this tutorial does not yet follow the documentation guidelines.
To visualize the data you can use standard Matlab functions. There are also several specialized plotting functions available in FieldTrip. Which functions you can use depends on the data you have, sensor data or volume data. In this tutorial we assume that you already have the data from the event related averaging tutorial, the time-frequency representations of power tutorial and the applying beamforming techniques in the frequency domain tutorial.
Data at the channel level has a value for each sensor (MEG) or electrode (EEG). These are the functions in FieldTrip for plotting channel level data:
Two dimensional data can be for instance: ERP/ERF data (time x average field / potential), a powerspectrum (freq x pow) or a coherence spectrum (freq x coh). Three dimensional data can be for instance a TFR of power (time x freq x pow), or a TFR of coherence of one channel with all others (time x freq x pow).
It is important to realize that in all these functions two sequential processes take place: First a selection of the data is made, for instance the channels, time bins and frequency bins to be plotted. Subsequently the selected data is plotted.
NB ft_clusterplot works a bit differently, look under Plotting clusters for details
Data at the source level usually has a single scalar value for each source location or voxel. If the source reconstruction is interpolated on an anatomical MRI, it is possible to plot these source reconstructions on top of the anatomy. The functions in FieldTrip for plotting source level data are:
To interpolate source data onto anatomical MRI:
You can also plot the data at the source level without interpolating it to an anatomical MRI, but only if the source reconstruction was done on a regular 3D grid.
It is also possible to reconstruct the timecourses of sources in the brain using virtual channels. FieldTrip does not have functions that can plot that type of data.
Here are first a few examples of plotting data on the channel level using the six functions mentioned above. Additional details will be discussed below.
With ft_singleplotER you can make a plot using the avgFC data from the ERF tutorial by the following code:
cfg = []; cfg.xlim = [-0.2 1.0]; cfg.ylim = [-1e-13 3e-13]; cfg.channel = 'MLC24'; clf; ft_singleplotER(cfg,avgFC);
The ft_singleplotER function first selects the data to be plotted, in this case channel MLC24, from -0.2 to 1.0 seconds. Subsequently this selected data is plotted with the Matlab PLOT.m function. You could make the same plot by the following code:
selected_data = avgFC.avg(9,241:601); %MLC24 is the 9th channel, -0.2 to 1.0 is sample 241 to 601 time = avgFC.time(241:601); figure; plot(time, selected_data) xlim([-0.2 1.0]) ylim([-1e-13 3e-13])
In ft_singleplotTFR the channel, time bins and frequency bins are selected and subsequently plotted with the Matlab IMAGESC.m function.
The FieldTrip plotting functions have a lot of build in intelligence to make the plotting of the multidimensional data easier. It is for instance possible to do baseline correction before plotting, by specifying the baseline type and time limits. In the plotting functions either the FieldTrip function ft_timelockbaseline or ft_freqbaseline is called. If you specify multiple channels in cfg.channel both singleplot functions will plot the mean over these channels. In the plotting functions the FieldTrip function ft_channelselection is called, which makes it straightforward to plot for instance the mean TFR of the left central channels.
cfg = []; cfg.baseline = [-0.5 -0.1]; cfg.baselinetype = 'absolute'; cfg.zlim = [-1.5e-27 1.5e-27]; cfg.channelname = 'MLC'; %or MRC figure;ft_singleplotTFR(cfg, TFRhann);
Try to replicate Figure 5 from the Event Related Averaging tutorial and Figure 3 from the Time Frequency analysis tutorial without using FieldTrip functions.
The multiplot functions work similarly to the singleplot functions, again first by selecting the data and subsequently using the Matlab functions PLOT.m and IMAGESC.m. But instead of one plot, multiple plots are made; one for each channel. These plots are arranged according to a specified layout in one pair of axes. In the subsequent figures you can see these axes that are normally set to “off”.
Normally the axes of the figure are not visible, only the “axis” of each channel, but remember these are not real axes on which you can use Matlab axis commands, the are just lines drawn by the function. Of course you can set the limits of the channel “axis” by the cfg structure (cfg.xlim, cfg.ylim). And you can see the limits in the scale in ft_multiplotER (righ upper corner) or in the comment for ft_multiplotTFR (left upper corner).
The layout is determined by the layout file. Read more on layout files here, and in the frequently asked questions
For multiplotting planar gradient data from the Neuromag system it is especially relevant to work with layout files: the Neuromag system has two planar gradiometers (plus one axial magnetometer) at each sensor location. You do not want to plot those on top of each other. Hence the Neuromag layout files contain two (for 122 channel) or three (for 306 channel) seperate subplots for each channel location. Those two (or three) subplots hold the data for the two planar gradients (and for the magnetometer signal).
Ft_topoplotER and ft_topoplotTFR plot the topographic distribution of 2-Dimensional or 3-Dimensional datatypes as a 2-D circular view (looking down at the top of the head). The arrangement of the channels is again specified in the layout (see above in multiplot functions). The ft_topoplotER and ft_topoplotTFR functions first again select the data to be plotted from the 2D or 3D input data and subsequently plot the selected data using low-level Fieldtrip functions. Using one value for each channel and the x and y coordinates, the values between points are interpolated and plotted. In the help of ft_topoplotER and ft_topoplotTFR you can find many cfg options. For instance by specifying the cfg.xlim as a vector the ft_topoplotER/TFR makes selections of multiple time-windows and plots them as subplots.
cfg = []; cfg.xlim = [0.3 0.5]; cfg.zlim = [0 6e-14]; cfg.layout = 'CTF151.lay' figure; ft_topoplotER(cfg,GA_FC)
cfg = []; cfg.xlim = [0.9 1.3]; cfg.ylim = [15 20]; cfg.zlim = [-1e-27 1e-27]; cfg.baseline = [-0.5 -0.1]; cfg.baselinetype = 'absolute'; cfg.layout = 'CTF151.lay' figure; ft_topoplotTFR(cfg,TFRhann)
% for the multiple plots also: cfg.xlim = [-0.4:0.2:1.4]; cfg.comment = 'xlim'; cfg.commentpos = 'title'; figure; ft_topoplotTFR(cfg,TFRhann)
The most left picture made with ft_topoplotER is planar ERF data. Planar data can not have values lower than zero. Explain why you nevertheless see values in the plot that correspond to negative values.
In ft_topoplotER and ft_topoplotTFR, you can specify many options to fully control the appearance of the picture. Subsequently you can use the matlab print function to write the figure to a file. Preferred file formats are EPS for vector drawings that can be edited in Adobe Illustrator or in Canvas (using “print -depsc”) or PNG for bitmaps (using “print -dpng”). To make the EPS-files optimally suitable for Adobe Illustrator, use the command “print -depsc -adobecs -painter”. Since it seems Matlab uses the 'painter' renderer to export in Illustrator format, with this method one can export quite complex figures that otherwise would be exported as bitmaps. Note, however, that the 'painter' renderer has many limitations compared to the z-buffer and openGL renderers. (See also Matlab help on selecting a renderer).
Some examples of what you can do:
% options for data selection: cfg = []; cfg.xlim = [0.9 1.3]; cfg.ylim = [15 20]; cfg.zlim = [-1e-27 1e-27]; cfg.baseline = [-0.5 -0.1]; cfg.baselinetype = 'absolute'; cfg.layout = 'CTF151.lay';
Options for plotting used by topoplot.m
cfg.gridscale = 300; cfg.style = 'straight'; cfg.marker = 'labels'; figure; ft_topoplotTFR(cfg,TFRhann)
cfg.gridscale = 300; cfg.contournum = 10; cfg.colormap = gray(10); figure; ft_topoplotTFR(cfg,TFRhann)
cfg.gridscale = 300; cfg.contournum = 4; cfg.colormap = spring(4); cfg.markersymbol = '.'; cfg.markersize = 12; cfg.markercolor = [0 0.69 0.94]; figure; ft_topoplotTFR(cfg,TFRhann)
In a data inspection phase you can use the interactive modus to go from one plot to the other. You can for instance select a certain frequency and time range in a singleplot, to get the average over that range plotted in a topoplot. Or select a group of channels in a topoplot or a multiplot and get the average over those channels for the whole time and frequency range in a single plot.
%interactive cfg = []; cfg.baseline = [-0.5 -0.1]; cfg.zlim = [-3e-27 3e-27]; cfg.baselinetype = 'absolute'; cfg.layout = 'CTF151.lay'; cfg.interactive = 'yes'; figure; ft_multiplotTFR(cfg,TFRhann)
Ft_clusterplot plots a series of topoplots with found clusters highlighted. The output “stat” is 2D data from ft_timelockstatistics or ft_freqstatistics with 'cluster' as cfg.correctmc. Stat should be 2D, therefore stat from ft_timelockstatistics data not averaged over time, or stat from ft_freqstatistics averaged over frequency not averaged over time.
The function automatically finds the clusters in the data which are smaller than the pre-specified alpha (cfg.alpha) and plots a series of topoplots with the data in “stat” field (are for instance t-values) and the sensors which are part of the cluster highlighted.
load preprocdata % see tutorial "Statistics using cluster-based permutation tests"
% downsample
cfg = [];
cfg.detrend = 'no';
cfg.resamplefs = 75;
FICpreproc = ft_resampledata(cfg, FICpreproc);
FCpreproc = ft_resampledata(cfg, FCpreproc);
% timelockanalysis
cfg = [];
cfg.keeptrials = 'yes';
FICdata = ft_timelockanalysis(cfg, FICpreproc);
FCdata = ft_timelockanalysis(cfg, FCpreproc);
% timelockstatistics
cfg = [];
cfg.channel = {'MEG'};
cfg.latency = [0 1];
cfg.method = 'montecarlo';
cfg.statistic = 'indepsamplesT';
cfg.clusteralpha = 0.05;
cfg.clusterstatistic = 'maxsum';
cfg.minnbchan = 2;
cfg.tail = 0;
cfg.clustertail = 0;
cfg.alpha = 0.05;
cfg.numrandomization = 100;
design = zeros(1,size(FICdata.trial,1)+size(FCdata.trial,1));
design(1,1:size(FICdata.trial,1)) = 1;
design(1,(size(FICdata.trial,1)+1):(size(FICdata.trial,1)+size(FCdata.trial,1)))=2;
cfg.design = design;
cfg.ivar = 1;
FIXME % remove dof
FICdata = rmfield(FICdata,'dof');
FCdata = rmfield(FCdata,'dof');
[stat] = ft_timelockstatistics(cfg, FICdata, FCdata);
% clusterplot
cfg = [];
cfg.zlim = [-6 6]; %Tvalues
cfg.alpha = 0.05;
ft_clusterplot(cfg,stat)
load TFR_planar_orig; % see tutorial "Statistics using cluster-based permutation tests"
% freqstatistics
cfg = [];
cfg.channel = {'MEG'};
cfg.latency = [0 1.4];
cfg.frequency = [20 20]; %beta band
cfg.avgoverfreq = 'yes';
cfg.method = 'montecarlo';
cfg.statistic = 'indepsamplesT';
cfg.clusteralpha = 0.05;
cfg.clusterstatistic = 'maxsum';
cfg.minnbchan = 2;
cfg.tail = 0;
cfg.clustertail = 0;
cfg.alpha = 0.05;
cfg.numrandomization = 100;
design = zeros(1,size(TFRFIC_planar_cmb.powspctrm,1)+size(TFRFC_planar_cmb.powspctrm,1));
design(1,1:size(TFRFIC_planar_cmb.powspctrm,1)) = 1;
design(1,(size(TFRFIC_planar_cmb.powspctrm,1)+1):(size(TFRFIC_planar_cmb.powspctrm,1)+...
size(TFRFC_planar_cmb.powspctrm,1)))=2;
cfg.design = design;
cfg.ivar = 1;
[stat] = ft_freqstatistics(cfg, TFRFIC_planar_cmb, TFRFC_planar_cmb);
% clusterplot
cfg = [];
cfg.zlim = [-5 5];
cfg.alpha = 0.05;
cfg.saveaspng = 'tutplot_clusterplotTFR';
ft_clusterplot(cfg,stat)
With the Ft_sourceplot function you can plot functional source reconstruction data, in which you have a value for each voxel in a volume. For instance data from ft_sourceanalysis or ft_sourcegrandaverage or statistical values from ft_sourcestatistics. You can plot this on an anatomical MRI or on a surface, and you can control the opacity of the data by masking.
Here are first a few examples, they will be explained in more detail below. The data used to create the following plots is from Subject01, which is used in the Beamforming tutorial.
Volume data needs a special approach since it is data in a 3 dimensional “box”. You have to do something with that data before you can plot it. Ft_sourceplot can make multiple 2D slices in one direction, one slice in three orthogonal directions, or project the functional data onto a surface. See below for details.
The three essential cfg parameters are:
All parameters must be interpolated onto the same grid. See ft_sourceinterpolate and ft_volumenormalise.
The anatomy can be read with ft_read_mri. The functional data can be interpolated onto the anatomy by ft_sourceinterpolate. The anatomy is scaled between 0 and 1 and plotted in gray scale.
The functional data is plotted in color optionally on top of the anatomy. The colors used can be determined by cfg.colormap (see Matlab function COLORMAP). How the functional values are assigned to the colormap is determined by cfg.colorlim. It makes sense to plot for instance source data as functional parameter, but also statistical values (for instance T-values).
You can control the opacity of the functional data by the mask parameter. Which values are plotted opaque and which transparent is determined by cfg.opacitymap and cfg.opacitylim (see Matlab function ALPHA and ALPHAMAP). The opacity map determines for instance that opacity goes from opaque to transparent, or from opaque to transparent to opaque. The opacity limits determine how the opacity map is assigned to the values of the mask parameter.
For instance if you have functional data with values ranging from -3 to 3 and you want to plot only the positive values with the strongest values opaque, and the values close to zero transparent, then you should specify:
cfg.maskparameter = cfg.funparameter cfg.colorlim = [0 3] (or'zeromax') cfg.opacitymap = 'rampup' cfg.opacitylim = [0 3] (or 'zeromax')
If you want to plot both the strong negative values and the strong positive values opaque, but the values around zero transparent, then you should specify:
cfg.maskparameter = cfg.funparameter cfg.colorlim = [-3 3] (or'maxabs') cfg.opacitymap = 'vdown' cfg.opacitylim = [-3 3] (or'maxabs')
You can also make a field in the data with an opacity value for each voxel, and apply that as your mask. For instance if you only want to plot the values between 2 and 2.5 you can specify:
data.mask = (data.fun>2 & data.fun<2.5) cfg.maskparameter = 'mask'
examples what happens with opacity when specifying cfg.opacitymap: