Pattern information analysis in Matlab
Switch branches/tags
Nothing to show
Clone or download
Failed to load latest commit information.
base documentation Nov 23, 2014
containers more flexible container splits Oct 10, 2018
featureselection use logstr rather than fprintf Aug 25, 2015
glm use trace instead to sum efficiency over contrasts Oct 3, 2017
inference remove ieNotDefined dependency Mar 14, 2018
processing remove old comment Apr 23, 2018
rsa use varargparse instead of getargs to avoid variable name conflicts Oct 10, 2018
tutorials documentation, tutorial 3 Aug 3, 2016
util documentation Oct 3, 2017
visualisation handle 2-value errors, absent groupres input Apr 23, 2018
CentroidGLM.m remove commented-out code Oct 15, 2015
ConvGLM.m avoid unnecessary filtering by downcasting to superclass instance on … May 10, 2016
CovariateGLM.m add ConvGLM class for online convolution of design, remove cacheing f… Jan 15, 2016
DenoiseGLM.m new sub-class for denoise benchmark Apr 22, 2015
GLM.m Merge branch 'master' of Oct 10, 2018
MeanDiffRSA.m code for EDI style RSA. Likely not something I will be doing but comm… Aug 16, 2013
MeanRSA.m support for sub-classing Nov 23, 2014
MultiRSA.m now preserve squared data internally throughout for sanity Jul 6, 2015
PartialRankRSA.m support for model RDMs with NaNs, correct calculation of partial rho Nov 23, 2014
PearsonRSA.m documentation Apr 4, 2017
PluginRSA.m CorrRSA is now more general PluginRSA Feb 17, 2014 documentation, tutorial 3 Aug 3, 2016
RSA.m remove redundant data checks (now in resamplerdm Apr 23, 2018
RankRSA.m use new faster ranktrans function in place of tiedrank Nov 23, 2014
RidgeGLM.m refactor continues Nov 6, 2013
RidgeRSA.m better documentation Oct 24, 2013
SplitMeanDiffRSA.m documentation Feb 13, 2014
SplitMeanRSA.m new classes for estimating mean discriminants across RDMs Feb 13, 2014
SplitPluginRSA.m CorrRSA is now more general PluginRSA Feb 17, 2014
SplitRSA.m split data RSA is now a separate class. Better handling of condition … Aug 15, 2013
SplitRankRSA.m new module for split RDM analysis - this is now a separate object hie… Aug 16, 2013

This code provides some general tools for univariate and multivariate modelling of data in Matlab. The code is angled toward fMRI datasets but is sufficiently general to support other use cases too.



a simple demo

The function below provides a sort of crash course in how to use the code. See also the tutorials.

function pilabdemo()

% control variables for the simulation
n = 200;
tr = 2;
ntrial = 20;
ncon = 4;
nvox = 50;
nrun = 2;

% true parameters - same across runs
b = rand(ncon+1,nvox);
for r = 1:nrun
    % different trial order in each run
    conind = ceil(rand(ntrial,1) * ncon);
    onsets = rand(ntrial,1) * n;
    X = [convolveonsets(onsets,conind,tr,n,'dur',1) ones(n,1)];
    % scale design matrix to peak at 1
    X = X / max(X(:));
    % construct data as some mixture of gaussian noise and the true parameters
    % scaled by each predictor
    data = randn(n,nvox)*.1 + X*b;
    % build Volume instances for convolved design and data
    metasamp = struct('chunks',ones(n,1)*r);
    designvol{r} = Volume(X,'metasamples',metasamp,...
    datavol{r} = Volume(data,'metasamples',metasamp);
% operator overloading means we can use standard concatenation syntax to combine
% the Volume instances over runs
datavol = cat(1,datavol{:});
designvol = cat(1,designvol{:});

% now let's build a simple GLM instance to demonstrate some functionality
model = vol2glm(designvol,datavol);
% visualise model and data
fh = figure;
set(fh,'name','data vs model');
ph = plot(;
% cross-validated prediction - use model(2) fit and model(1) design matrix
% Notice that the GLM is an object array class, so can be indexed like a struct
% to run particular methods on say a train and a test split of the data.
prediction = predictY(model(2),model(1).X);
% evaluate on model(1) data
r2 = rsquare(model(1),prediction);
% visualise fit
fh = figure;
set(fh,'name','fit vs data');
ph = plot([prediction(:,1) model(1).data(:,1)],'.-');
% cross-validated linear discriminant contrast (train on 2, test on 1)
m = infoc(model(1),discriminant(model(2),[1 -1 0 0 0]),[1 -1 0 0 0]);

% or to use the higher level analysis functions, let's build an additional
% region of interest Volume, which stores the valid features for each ROI
roivol = Volume([ones(1,nvox); ones(1,floor(nvox/2)) zeros(1,ceil(nvox/2)); ...
    zeros(1,floor(nvox/2)) ones(1,ceil(nvox/2))],'metasamples',struct(...
% now we can just call this high-level analysis function to obtain the
% cross-validated linear discriminant contrast for each pair of conditions - a
% sort of distance matrix that we then visualise.
disvol = roidata2rdmvol_lindisc_batch(roivol,designvol,datavol);
maxd = max(abs(;
[fh,ax,intmap,cmap] = rdmfig(,disvol.meta.features.names,[],[],...
    'limits',[-maxd maxd]);
set(fh,'name','distance matrices');
cbax = subplot(2,2,4);
c = colorbarbetter(cbax,intmap{end},cmap{end});

Easy, right? There is a lot more going on under the surface. Probably the easiest way to go further is to explore the methods of the GLM and its sub classes. One of these days there will be a proper manual...


The core components of pilab are a set of container classes for storing and manipulating data and a set of GLM-based classes for data analysis. These classes generally implement low-level, basic functionality and are used by more high-level data-to-results functions for representational similarity analysis and decoding (see subfolders).

The basic design logic is that new features can be supported by sub-classing existing containers or GLM classes, while new specific applications can be supported by adding new analysis functions. Finally, batch processing is supported by a large number of modules for Automatic Analysis (AA, see my clone of this repo).

GLM-based classes

The key heavy lifting in pilab is done by a set of GLM-based classes. A number of key analysis methods (including representational similarity analysis) are implemented as special (sub) cases of the general linear model. Convenient class methods enable bootstrapping and permutation testing.


Data and metadata are stored together in Volume classes, which provide a convenient, pandas-like (but not as performant) interface. The basic representation of data is 2D (samples by features), and metadata is similarly supported for either dimension. A number of flexible methods are available for indexing data according to metadata, and (in the case of MriVolume) for converting samples (1 by nfeatures vectors) to volumetric 3D matrix form, or for writing out to disk in nifti format.

This flexibility and metadata support comes at a substantial performance cost. Most analysis functions therefore convert the container to a raw matrix or to a lighter GLM class for performance-dependent applications.

analysis functions

A few high level functions are used to provide a simple data-to-results interface.

representational similarity analysis

The bulk of pilab was developed for the purposes of representational similarity analysis (Kriegeskorte et al., 2008). Accordingly, there are functions to compute representational dissimilarity matrices from activation patterns of raw timecourses (rsa/roidata2rdmvol, rsa/roidata2rdmvol_lindisc) and for comparing data and model RDMs (rsa/roidata_rsa).


Information-based decoding using linear discriminant analysis is supported by rsa/roidata_lindisc.

random effects analysis

Results from the rsa and decoding functions are saved in a common format, which enables a standardised solution for random effects group analysis (glm/roidata_rfx).

about pattern information analysis and this repository

pilab is being developed by Johan Carlin. Any comments and queries are welcome.

This code is an implementation of analysis methods originally proposed by Niko Kriegeskorte and collaborators. The reference section below lists relevant academic publications, which should be cited in any publications resulting from the use of this code.

Note that pilab is pre-alpha code undergoing active development. Absolutely no guarantees are provided concerning the accuracy of results at this stage. Use at your own risk, and please validate results extensively.


Nili, H., Wingfield, C., Su, L., Walther, A., & Kriegeskorte, N. (2014). A toolbox for representational similarity analysis. PLoS Computational Biology, 10, e1003553.

Kriegeskorte, N., Goebel, R., & Bandettini, P. A. (2006). Information-based functional brain mapping. Proceedings of the National Academy of Sciences, 103, 3863–3868.

Kriegeskorte, N., & Bandettini, P. A. (2007). Analyzing for information, not activation, to exploit high-resolution fMRI. NeuroImage, 38, 649–662.

Kriegeskorte, N., Mur, M., & Bandettini, P. A. (2008). Representational similarity analysis - connecting the branches of systems neuroscience. Frontiers in Systems Neuroscience, 2, 1–28.