[FieldTrip] Electrode alignment to standard MRI template

Schoffelen, J.M. (Jan Mathijs) jan.schoffelen at donders.ru.nl
Thu Aug 23 14:57:16 CEST 2018

Dear Annika,

It’s a bit unfortunate that you ended up using the low-level information in the mri.hdr.fiducial field (in combination with the transformation matrices). I agree with you that the values are strange, and I am pretty sure that they do not correspond with the volumetric image in the same data structure. Note that the mri itself also has a ‘transform’ field, which provides you with the mapping between voxels and head space (MNI-convention, ACPC-based RAS). If you aim for a 3-point (nas,lpa,rpa) based coregistration between your electrodes and the templates needed for source reconstruction, you could use the set of fiducial positions that can be found in fieldtrip/electrode/standard1005.elc. (an alternative and possibly better coregistration could be achieved using a non-linear matching with the ‘template’ method, but that might be a story of its own).

If you do:

>> sens=ft_read_sens('standard_1005.elc');
>> sens.chanpos(1:3,:)

ans =

  -86.0761  -19.9897  -47.9860
   85.7939  -20.0093  -48.0310
    0.0083   86.8110  -39.9830

(note that this very nicely corresponds with the template fiducials you reported in your e-mail)

>> sens.label(1:3)

ans =


you can verify that these three fiducials are expressed in head coordinates according to the ‘spm’ convention, i.e. Anterior Commissure is origin, the line through AC and PC is the y-axis, x-axis pointing to the right etc). This verification can be done with


>>cfg = [];
>>cfg.location = sens.chanpos(1,:);
>>figure;ft_sourceplot(cfg, mri);

Now, if your electrodes' coordinate system is the same as the anatomical mri’s, then you can proceed to ft_electroderealign.

Yet, your electrodes’ coordinate system is different, because you report that you’d expect the nasion to be [100 0 0], i.e. the x-axis to go exactly through the nasion, and the positive y-axis pointing to the left. This is then an ALS-based coordinate system with the origin somewhere between the ears (the exact definition depends on whether you are using the convention that e.g. CTF uses, as compared to the ASA coordinate system: see ‘help ft_headcoordinates’ and the fieldtrip wiki’s faq about coordinate systems).

Now, if you need to get your electrodes expressed in the coordinate system that is the same as the one in which the headmodel is specified (called ‘spm’, or ‘acpc’), then you can do the following:

T = ft_headcoordinates(sens.chanpos(3,:),sens.chanpos(1,:),sens.chanpos(2,:),’ctf’); % or ‘asa'

This gives you a transformation matrix that maps from the space in which the ‘fiducials’ are expressed (in this case: spm) to a ctf/asa-based coordinate system. This you can verify with

ft_warp_apply(T, sens.chanpos(1:3,:));,

which will give you the fiducials’ coordinates with values close to 0, on 2 out of three values. Then, the inv(T) is transforming from the ctf/asa-based coordinate system into spm’s convention, so you can do:

chanlocs_124_transformed = ft_transform_geometry(inv(T), chanlocs_124);

I think that this already should get you close to where you want to end up.

And yes, coordinate systems are always complicated.

Good luck,


PS: I have removed the hdr-fields from standard_mri and standard_seg in the release version of the code, to avoid any future confusion.

On 23 Aug 2018, at 11:06, Annika Thierfelder <athierfelder at tuebingen.mpg.de<mailto:athierfelder at tuebingen.mpg.de>> wrote:

Hello everyone,

short update on my question, that is maybe easier to answer without going through the code itself.

I believe that the heart of the problem lies (of course) in the coordinate definitions of the electrodes and the MRI. So, I experimented a little with the example electrode set that is aligned to the standard BEM model that results from the standard MRI. If I try to align the example electrodes to the MRI (which is not necessary but it also should not hurt), I discovered that I get the same shift into the z-direction for the example electrodes.

So, the basic question underlying my problem would be: How can the MRI and the eletrodes be aligned if their fiducials are so different, they even seem to be in different coordinate systems? Shouldn't they be kind of similar if they are aligned? I did not see any further coordinate transformation in the BEM computation from the MRI (except for the conversion into 'acpc' in ft_volumesegment which doesn't change anything) that would explain the alignment later on.

MRI fiducials:
NAS [1, 0, 0]
LPA [0, 83, 0]
RPA [0, -117, 0]

template electrode fiducials are roughly:
NAS [0, 87, -40]
LPA [-86, -20, -48]
RPA [86, -20, -48]

Also, the MRI is supposed to be in MNI coordinates, which I don't understand why, because already the first dimension doesn't point to the right. I feel like understanding why the coordinates are this way would be a crucial step to solve my problem.

I'm very thankful for any help on this problem. If I understand this, I hopefully can figure out the rest myself.

Best regards,

On 8/21/2018 6:21 PM, Annika Thierfelder wrote:
Hello everyone,

I started using fieldtrip last week to do EEG source analysis and I experienced some issues when trying to align the EEG to the MRI. Since we don't have MRI scans for our subjects, I used the standard_mri from the template folder.

The solution that works "best" until now is to align the electrodes with the MRI fiducials and compute the BEM from the MRI seperately (I used bemcp for that since I work on windows, so dipoli doesn't run). However, when I plot the aligned electrodes together with the BEM head surface, the electrodes are in the correct orientation but they have an offset along the z-axis. I put the code I used below and uploaded the picture of the electrodes and the head model on google drive: https://drive.google.com/open?id=1b7Q3YGWGyzaa5oXeE-PfOOHNIDoFaLO1

There are two things I'm wondering about now:

Why are the nasion head coordinates in the MRI template [1, 0, 0] and not [100, 0, 0], which would make more sense (at least in my opinion) since the units are in mm and I thought the nasion is not supposed to be inside the head? The LPA and RPA values are [0, 83, 0] and [0, -117, 0] respectively, which seems perfectly fine to me.

I have the feeling that the problem arises because the two coordinate systems of the data do not have the same origin. Can I shift the coordinate system of the electrode space before aligning them? I only found ways how to change the coordinate system of the MRI. I also tried to change the MRI coordinate system first before aligning the electrodes, but I found that I cannot create the BEM model with 'bemcp' anymore. It seems to throw an error if I give it an MRI with any coordinate system that is not 'spm'. So I kind of have the feeling that I need to get the electrodes into the 'spm' coordinates to match the MRI and BEM head.

Thank you a lot in advance for your support!


PS: I know there has been a similar problem once in this mailing list, but I checked the suggestions and they did not work for me, also it seemed as if in the end it came down to fitting the electrodes manually there, and I suppose there can be another solution for this.


Code for the electrode alignment:

%This is my how my electrode data looks like:
      label: {124×1 cell}
    elecpos: [124×3 double]
       unit: 'mm'

% get fiducials from the MRI template
vox_Nas = mri_spm.hdr.fiducial.mri.nas;
vox_Lpa = mri_spm.hdr.fiducial.mri.lpa;
vox_Rpa = mri_spm.hdr.fiducial.mri.rpa;

% I know I can skip this step because I can directly use the head-coordinates given in the MRI template
% I kept it because it doesn't make a difference
vox2head = mri_spm.hdr.transformMRI2Head;
head_Nas = ft_warp_apply(vox2head, vox_Nas, 'homogeneous'); % nasion
head_Lpa = ft_warp_apply(vox2head, vox_Lpa, 'homogeneous'); % Left preauricular
head_Rpa = ft_warp_apply(vox2head, vox_Rpa, 'homogeneous'); % Right preauricular

% save the MRI fiducials as target structure for the realignment
% in our data set, the LPA is named TTP9 and the RPA is TTP10, so I renamed them
elec_mri.elecpos(1,:) = head_Nas;
elec_mri.elecpos(2,:) = head_Lpa;
elec_mri.elecpos(3,:) = head_Rpa;
elec_mri.label = {'Nz', 'TTP9', 'TTP10'};
elec_mri.unit  = 'mm';

% coregister the electrodes to the MRI using fiducials
cfg = [];
cfg.method   = 'fiducial';
cfg.target   = elec_mri;
cfg.elec     = chanlocs_124;
cfg.fiducial = {'Nz', 'TTP9', 'TTP10'};
chanlocs_124_spm = ft_electroderealign(cfg);

Just in case this is also of interest, this is how I compute the BEM headmodel from the same MRI template:

% segments the MRI into three different tissue parts
% creates binary masks for each point and tissue part
cfg = [];
cfg.output    = {'brain','skull','scalp'};
segmented_mri  = ft_volumesegment(cfg, mri_spm);

%% create mesh with different tissues
cfg.numvertices = [3000 2000 1000];

% compute headmodel
cfg        = [];
cfg.method ='bemcp';
vol        = ft_prepare_headmodel(cfg, bnd);

fieldtrip mailing list

fieldtrip mailing list

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.science.ru.nl/pipermail/fieldtrip/attachments/20180823/79e601c4/attachment-0002.html>

More information about the fieldtrip mailing list