Jump to: navigation, search

Measure Projection Toolbox (MPT) is an open source Matlab toolbox for probabilistic multi-subject EEG independent component source comparison and inference (an alternative to IC clustering).

Ersp measure projection and domains for wiki.png

Developed and Maintained by: Nima Bigdely-Shamlo (SCCN, INC, UCSD)
Email: <Nima's first name> (at) sccn (dot) ucsd (dot) edu with help from: Özgür Yiğit Balkan

MPT includes derived data from LONI Probabilistic Brain Atlas (LPBA40): Shattuck DW, Mirza M, Adisetiyo V, Hojatkashani C, Salamon G, Narr KL, Poldrack RA, Bilder RM, Toga AW, Construction of a 3D Probabilistic Atlas of Human Cortical Structures, NeuroImage (2007), doi: 10.1016/j.neuroimage.2007.09.031



Measure Projection reference paper was recently published in NeuroImage and made it to the cover of the magazine:

Neuro image cover png small.png

Here is the reference:

Bigdely-Shamlo, Nima, Mullen, Tim, Kreutz-Delgado,  Kenneth, Makeig, Scott, 
Measure Projection Analysis: A Probabilistic  Approach  to EEG Source Comparison and Multi-Subject Inference,
NeuroImage (2013), Vol. 72, pp. 287-303, doi:   10.1016/j.neuroimage.2013.01.04 (download preprint)

Quick Start

Download the latest version of the toolbox, unzip it and place the folder under /plugins/ folder of EEGLAB ( or later, otherwise will likely encounter errors). If EEGLAB is already running you may run:

>> eeglab rebuild

to load the toolbox. You should see 'Measure Projection' menu under STUDY (if STUDY menu is active). You may also type:

>> pr.getVersionString

to obtain the version of the toolbox (and check if it is installed). Load your EEGLAB study and look under Study to find Measure Projection submenu. To use the toolbox you must have pre-computed the measure(s) of interest and localized equivalent IC dipoles, similar to what you would do before performing default EEGLAB IC clustering.


The latest version of Measure Projection Toolbox (MPT).

MPT reference paper.

Tutorial RSVP EEGLAB Study: as a single (4.7 GB) zip file], or as an FTP folder.

Paper describing tutorial EEGLAB Study

Report an issue or make a suggestion.



A crucial step in the analysis of multi-subject electroencephalographic (EEG) data using Independent Component Analysis (ICA) is combining information across multiple recordings from different subjects, each associated with its own set of independent component (IC) processes. IC clustering (e.g. as implemented in EEGLAB software) is a common method for analyzing multi-session data, but it is associated with some issues that limit its usefulness for statistical analysis of EEG signal:

  • High sensitivity to clustering parameters such as number of clusters and relative weights of different EEG measures (e.g. ERSP vs. ERP).
  • Difficulty in proper statistical evaluation of cluster memberships.
  • Discontinuous nature of clustering which confounds group comparisons.


Measure Projection Analysis (MPA) is a novel probabilistic multi-subject inference method that overcomes IC clustering issues by abandoning the notion of distinct IC clusters. Instead, it searches voxel by voxel for brain regions having event-related IC process dynamics that exhibit statistically significant consistency across subjects and/or sessions as quantified by the values of various EEG measures. Local-mean EEG measure values are then assigned to all such locations based on a probabilistic model of IC localization error and inter-subject anatomical and functional differences.

MPA overcomes issues associated with IC clustering by reducing the number of analysis parameters while avoiding over-simplifying the implicit neurophysiological assumptions of cluster-based analysis. Instead of representing equivalent dipoles of independent components as points, Measure Projection models each of them by a Gaussian density.

MPA calculates the expected value (or ‘Projected value’) of the selected EEG measure M (e.g. ERSP of a certain experiment condition, like button-press) at brain locations spanning a regular grid (~8 mm spacing):

Next, it obtains significance values for these brain locations to find out which brain areas, or neighborhoods, contain similarities between nearby dipoles which are highly unlikely to have occurred by chance. To do so, Convergence at each brain location is calculated:

In this equation is the probability density of dipole at brain position and is the degree of similarity (e.g. correlation) between measure vectors associated with dipoles and . Calculated convergence quantity is higher for areas with homogeneous (similar) measures and significance (p-values) may be obtained for each brain location by bootstrap statistics. Projected values associated with highly significant brain locations are then grouped based on their similarities and analyzed.

Here is a comparison between IC clustering and Measure Projection:

Clustering and mpa flowchart.png


Mpt tutorial memorysettings.png

Loading the Study

Load tutorial study called in EEGLAB by clicking File -> Load existing study. You should now be able to see the Measure Project menu as shown to the right.

EEGLAB Measure Project Submenu.png

  • Go to Study -> Measure Projection -> ERSP -> Project
  • Click Show colored by Measure under the ERSP menu

Mpt tutorial coloredbymeasure.png

  • Click Create Domains under the ERSP menu. Notice the 'Domains' submenu becomes available which takes some time to finish. Alternatively, you may load, but this can crash Matlab 2009a on 32 bit Windows.
  • Click Show colored by Domain under the ERSP menu

|Mpt tutorial coloredbydomain.png

Note: if your Matlab crashed while loading or, try loading which is considerably smaller. If you do so, follow the tutorial steps for ERP instead of ERSP.

GUI: Condition Differences

  • Click on ERSP -> Domains -> Domain 2 -> Show Measure
  • Click on ERSP -> Domains -> Domain 2 -> Show condition difference

GUI: Domain Dipoles

  • Click on ERSP -> Domains -> Domain 2 -> Show high contributing scalp maps
  • Click on ERSP -> Domains -> Domain 2 -> Show high contributing dipoles


  • Load in EEGLAB

Note: On Windows 21bit with Matlab 2009a, this operation may crash Matlab. You may choose instead to try loading files named study_rsvp_with_{erp, ersp, ...}

Setting Options from GUI

  1. Select Measure Projection -> Options
  2. Change ERSP -> Significance from 0.01 to 0.001
  3. Close the figure
  4. Select STUDY -> Measure Projection -> ERSP -> Show colored by Measure


Projection from Script

This is the code than runs 'under the hood' when you use M<PT GUI. You can use it as a basis for your scripts. The example below is for ERSP measure, you may replace 'ERSP' in the following commands with other measure names (ITC, ERP, Spec).

// read the data (calculated measure, etc.) from STUDY
STUDY.measureProjection.ersp.object = pr.dipoleAndMeasureOfStudyErsp(STUDY, ALLEEG);

// define HeadGRID based on GUI options (you can change this in your script of course)
STUDY.measureProjection.ersp.headGrid = pr.headGrid(STUDY.measureProjection.option.headGridSpacing);

// do the actual projection 
STUDY.measureProjection.ersp.projection = pr.meanProjection(STUDY.measureProjection.ersp.object,...
STUDY.measureProjection.ersp.object.getPairwiseMutualInformationSimilarity, ...
STUDY.measureProjection.ersp.headGrid, 'numberOfPermutations', ...
STUDY.measureProjection.option.numberOfPermutations, 'stdOfDipoleGaussian',...
STUDY.measureProjection.option.numberOfStandardDeviationsToTruncatedGaussaian, 'normalizeInBrainDipoleDenisty', ...
fastif(STUDY.measureProjection.option.normalizeInBrainDipoleDenisty,'on', 'off'));

// visualize significant voxels individually (voxel p < 0.01)

// visualize significant voxles as a volume (voxel p < 0.01)
// create domains
// find out the significance level to use (e.g. corrected by FDR)
if STUDY.measureProjection.option.('erspFdrCorrection')
   significanceLevel = fdr(STUDY.measureProjection.ersp.projection.convergenceSignificance(...
STUDY.measureProjection.ersp.headGrid.insideBrainCube(:)), STUDY.measureProjection.option.(['erspSignificance']));
   significanceLevel = STUDY.measureProjection.option.('erspSignificance');

maxDomainExemplarCorrelation = STUDY.measureProjection.option.('erspMaxCorrelation');

// the command below makes the domains using parameters significanceLevel and maxDomainExemplarCorrelation:
STUDY.measureProjection.(measureName).projection = ...
STUDY.measureProjection.(measureName).object, maxDomainExemplarCorrelation, significanceLevel);

// visualize domains (change 'voxle' to 'volume' for a different type of visualization) 

Finding ICs associated with a Domain

You may want to find out which ICs contribute most to a certain domain. This can be done by calculating the dipole mass that lays inside the domain as it provides the probability that the dipoles is located inside the domain volume. This may be obtained from getDipoleDensityContributionToRegionOfInterest() function in pr.dipole class:

function [dipoleId sortedDipoleDensity orderOfDipoles dipoleDenisty dipoleDenistyInRegion] = getDipoleDensityContributionToRegionOfInterest(obj, regionOfInterest, projection, cutoffRatio)
           % [dipoleId sortedDipoleDensity orderOfDipoles dipoleDenistyInRegion dipoleDenistyInRegion] = getDipoleDensityContributionToRegionOfInterest(obj, projection, regionOfInterest, cutoffRatio)
           % projection is a type of meanProjection (or compatible).
           % return dipoles ids (in dipoleId)  which cumulatively contribute at least 'cutoffRatio' to the dipole
           % denisty over the region.
           % cutoffRatio is either a scalar or a 2-vector. The first number contains the percent of
           % region (domain) dipole mass explained by selected dipoles after which there will be a no 
           % other dipole selected. The second is the miminum dipole mass ratio contribution to the 
           % region (dipoles with a  contribution less than this value will not be selected).
           % For example cutoffRatio = 0.98 requires selected dipoles to at least explain 98% of
           % dipoles mass in the region.
           % cutoffRatio = [1 0.05] means that all dipoles that at least contribute %5 of their
           % mass to the region will be selected.
           % default cutoffRatio is [1 0.05].

For example, lets assume you have made 5 ERSP domains and want to find out ICs associated with domain #3. Here is the code to do this:

domainNumber = 3;
dipoleAndMeasure = STUDY.measureProjection.ersp.object; % get the ERSP and dipole data (dataAndMeasure object) from the STUDY structure.
domain = STUDY.measureProjection.ersp.projection.domain(domainNumber); % get the domain in a separate variable
projection  = STUDY.measureProjection.ersp.projection;
[dipoleId sortedDipoleDensity orderOfDipoles dipoleDenisty dipoleDenistyInRegion] = dipoleAndMeasure.getDipoleDensityContributionToRegionOfInterest(domain.membershipCube, projection, [1 0.05])% the last value, [1 0.05]) indicates that we want all the ICs that at least has a 0.05 chance of being in the domain. You may want to use 0.1 or even 0.5 to get fewer ICs.

domainICs = dipoleAndMeasure.createSubsetForId(dipoleId); % here we create a new variable that contain information only for dipoles associates with domain ICs.

domainICs will have all the information you need to identify domain ICs, for example:

>> domainICs
domainICs = 
 dipoleAndMeasureOfStudyErsp with properties:
                        time: [1x200 double]
                   frequency: [1x100 double]
                 conditionId: [1 2]
              conditionLabel: {'PM_C'  'NTaC & TarC'}
   relationshipToBrainVolume: 'insidebrain'
                    scalpmap: [1x1 pr.scalpmapOfStudy]
                   removedIc: [1x1 struct]
           linearizedMeasure: [40000x34 single]
                measureLabel: 'ERSP'
   numberOfMeasureDimensions: 2
                    location: [34x3 double]
                   direction: [34x3 double]
            residualVariance: []
            coordinateFormat: 'mni'
              numberOfGroups: 2
                 insideBrain: [1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1]
                   datasetId: [31 11 48 43 49 44 43 44 12 41 9 35 43 47 40 1 43 8 27 10 32 14 47 1 32 47 23 27 3 39 31 43 14 1]
      datasetIdAllConditions: [31 11 48 43 49 44 43 44 12 41 9 35 43 47 40 1 43 8 27 10 32 14 47 1 32 47 23 27 3 39 31 43 14 1]
                   groupName: {1x34 cell}
                 groupNumber: [1 1 2 1 1 2 1 2 2 1 1 1 1 1 2 1 1 2 1 2 2 2 1 1 2 1 1 1 1 1 1 1 2 1]
             uniqueGroupName: {'C'  'P'}
             numberInDataset: [17 12 29 26 14 37 37 53 26 82 6 83 33 48 12 62 23 40 12 11 29 20 32 24 33 21 1 4 58 13 42 10 8 1]
        icIndexForEachDipole: [1x34 double]
                 subjectName: {1x34 cell}
               subjectNumber: [13 43 32 27 33 28 27 28 44 25 41 17 27 31 24 19 27 40 9 42 14 46 31 19 14 31 5 9 35 23 13 27 46 19]
           uniqueSubjectName: {1x21 cell}

of these fields, the most relevant ones are datasetIdAllConditions and numberInDataset. datasetIdAllConditions gives you the IDs in ALLEEG structure array of the dataset associated with each IC. numberInDataset gives you the IC number in the dataset. (for exmaple IC #5 in dataset ALLEEG(10)).

Exporting session projected measures for a Domain

You may want to have access to the measures projected to a domain from each session. This could be used to perform different types of statistics and try more complicated designs. It is also quite easy do to in MPT with the getMeanProjectedMeasureForEachSession function provided in pr.dipoleAndMeasureOfStudy class:

(for session)

 function [linearProjectedMeasure sessionConditionCell groupId uniqeDatasetId dipoleDensity] = getMeanProjectedMeasureForEachSession(obj, headGrid, regionOfInterestCube, projectionParameter, varargin)
           % [linearProjectedMeasure sessionConditionCell groupId uniqeDatasetId dipoleDensity] = getProjectedMeasureForEachSession(obj, headGrid, regionOfInterestCube, projectionParameter, (key, value pair options))
           % projects each session (dataset) to provided position(s) and returns a NxS
           % matrix containing dipole-density-weghted- average measures for each session over the
           % region.
           % N is the numbr of dimensions of the linearized measure.
           % S is the number of sessions (datasets)
           % by setting 'calculateMeasure' to 'off' you can only get the total dipole density (much
           % faster and less memory).      
           % sessionConditionCell is a cell array of number of sessions x number of conditions,
           % each containing a single condition with the original shape (e.g. 2-D for ERSP).

Here is an example code to export projected session data to domain #3 on an ERSP projection:

domainNumber = 3;
dipoleAndMeasure = STUDY.measureProjection.ersp.object; % get the ERSP and dipole data (dataAndMeasure object) from the STUDY structure.
domain = STUDY.measureProjection.ersp.projection.domain(domainNumber); % get the domain in a separate variable
projection  = STUDY.measureProjection.ersp.projection;
headGrid = STUDY.measureProjection.ersp.headGrid;
[linearProjectedMeasure sessionConditionCell groupId uniqeDatasetId dipoleDensity] = dipoleAndMeasure.getMeanProjectedMeasureForEachSession(headGrid, domain.membershipCube, projection.projectionParameter);

sessionConditionCell variable will contain a cell array of number of sessions x number of conditions, each containing a single condition with the original shape (e.g. 2-D for ERSP). For example:

>> sessionConditionCell
sessionConditionCell = 
   [200x100 double]    [200x100 double]
   [200x100 double]    [200x100 double]
   [200x100 double]    [200x100 double]
   [200x100 double]    [200x100 double]...

You can now use these in your own custom analysis.

ROI-based Measure Projection

Instead of creating domains based on your data and then finding their associated anatomical areas you can directly use anatomical ROIs as “super voxels” and perform measure projection on them with two lines of code (change 'ersp' below to your desired measure):

>> roiProjection = pr.regionOfInterestProjection(STUDY.measureProjection.ersp.object, STUDY.measureProjection.ersp.object.getPairwiseFishersZSimilarity, pr.headGrid);

This makes an object that contains projection for AAL atlas ROIs. To see the output:

>> roiProjection.makeReport(‘[name of your report]',‘[top report folder]’ );

Currently the report only compares the first two conditions.