Home > bioelectromagnetism > emse_read_reg.m

emse_read_reg

PURPOSE ^

emse_read_reg - Read EMSE/MRVU coregistration matrices

SYNOPSIS ^

function [reg] = emse_read_reg(file)

DESCRIPTION ^

 emse_read_reg - Read EMSE/MRVU coregistration matrices

 [reg] = emse_read_reg(file)

 reg is a struct with the following fields:

 reg.translation - the translation in meters along the
                   x, y and z axes respectively, from
                   the MRI image frame to head/elec frame.

 reg.rotation - The rotation vector contains the angles
                (in radians) about the x, y and z axes,
                also from the MRI image frame to the
                head/elec frame.

 reg.elec2mri - 'HeadToImageMatrix' is the 4 x 4 matrix
                containing the electrode to MRI translation and
                rotation transformations in homogeneous coordinates:
                * the upper left 3 x 3 submatrix is rotations
                  around z, y, x in that order;
                * the rightmost 3 x 1 column is a projection
                  vector (all zeros here);
                * the bottom 1 x 3 row is a translation vector,
                  equal to -1 * reg.translation here; and
                * the bottom right (1 x 1) scalar is the
                  homogenous scale unit, usually 1

 reg.mri2elec - 'ImageToHeadMatrix' is the inverse of elec2mri,
                ie, reg.mri2elec = inv(reg.elec2mri).

 This function also reads the fiducial points and the electrode
 coordinates from the registration file, they are returned into:
 reg.RPA, reg.LPA, reg.NAS, reg.Helec, and reg.Melec.  Each of
 the fiducial structs (RPA,LPA,NAS) contains the electrode
 fiducials in the head space (Hh) and the MRI space (Hm), plus the
 MRI fiducials in the head space (Mh) and the MRI space (Mm).

 The transformation matrices (T) multiply a column vector, so that
 [x', y', z', 1] = [x, y, z, 1] * T;
 where x',y',z' are in the other coordinate system. For example,
 MRI coordinates into head space:
 tmp = [ reg.Melec ones(size(reg.Melec,1),1) ] * reg.mri2elec;
 Note reg.Helec ~= tmp(:,1:3) due to floating point rounding only.
 Similarly, head space (electrodes) into MRI coordinates:
 tmp = [ reg.Helec ones(size(reg.Helec,1),1) ] * reg.elec2mri;
 Note reg.Melec ~= tmp(:,1:3) due to floating point rounding only.

 EMSE Note: The origin in the head frame is at or near the center of
 the skull, while the origin in the image frame is located at the
 bottom right front corner of the bounding box (and so would be
 located at the upper left corner of the first axial slice as
 displayed by MR Viewer).

 A useful chapter on homogeneous coordinates, among other things,
 may be found in Mortenson, M. (1985, Chpt. 8), Geometric Modelling,
 New York: John Wiley & Sons.

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SUBFUNCTIONS ^

SOURCE CODE ^

0001 function [reg] = emse_read_reg(file)
0002 
0003 % emse_read_reg - Read EMSE/MRVU coregistration matrices
0004 %
0005 % [reg] = emse_read_reg(file)
0006 %
0007 % reg is a struct with the following fields:
0008 %
0009 % reg.translation - the translation in meters along the
0010 %                   x, y and z axes respectively, from
0011 %                   the MRI image frame to head/elec frame.
0012 %
0013 % reg.rotation - The rotation vector contains the angles
0014 %                (in radians) about the x, y and z axes,
0015 %                also from the MRI image frame to the
0016 %                head/elec frame.
0017 %
0018 % reg.elec2mri - 'HeadToImageMatrix' is the 4 x 4 matrix
0019 %                containing the electrode to MRI translation and
0020 %                rotation transformations in homogeneous coordinates:
0021 %                * the upper left 3 x 3 submatrix is rotations
0022 %                  around z, y, x in that order;
0023 %                * the rightmost 3 x 1 column is a projection
0024 %                  vector (all zeros here);
0025 %                * the bottom 1 x 3 row is a translation vector,
0026 %                  equal to -1 * reg.translation here; and
0027 %                * the bottom right (1 x 1) scalar is the
0028 %                  homogenous scale unit, usually 1
0029 %
0030 % reg.mri2elec - 'ImageToHeadMatrix' is the inverse of elec2mri,
0031 %                ie, reg.mri2elec = inv(reg.elec2mri).
0032 %
0033 % This function also reads the fiducial points and the electrode
0034 % coordinates from the registration file, they are returned into:
0035 % reg.RPA, reg.LPA, reg.NAS, reg.Helec, and reg.Melec.  Each of
0036 % the fiducial structs (RPA,LPA,NAS) contains the electrode
0037 % fiducials in the head space (Hh) and the MRI space (Hm), plus the
0038 % MRI fiducials in the head space (Mh) and the MRI space (Mm).
0039 %
0040 % The transformation matrices (T) multiply a column vector, so that
0041 % [x', y', z', 1] = [x, y, z, 1] * T;
0042 % where x',y',z' are in the other coordinate system. For example,
0043 % MRI coordinates into head space:
0044 % tmp = [ reg.Melec ones(size(reg.Melec,1),1) ] * reg.mri2elec;
0045 % Note reg.Helec ~= tmp(:,1:3) due to floating point rounding only.
0046 % Similarly, head space (electrodes) into MRI coordinates:
0047 % tmp = [ reg.Helec ones(size(reg.Helec,1),1) ] * reg.elec2mri;
0048 % Note reg.Melec ~= tmp(:,1:3) due to floating point rounding only.
0049 %
0050 % EMSE Note: The origin in the head frame is at or near the center of
0051 % the skull, while the origin in the image frame is located at the
0052 % bottom right front corner of the bounding box (and so would be
0053 % located at the upper left corner of the first axial slice as
0054 % displayed by MR Viewer).
0055 %
0056 % A useful chapter on homogeneous coordinates, among other things,
0057 % may be found in Mortenson, M. (1985, Chpt. 8), Geometric Modelling,
0058 % New York: John Wiley & Sons.
0059 %
0060 
0061 
0062 % $Revision: 1.1 $ $Date: 2004/11/12 01:32:34 $
0063 
0064 % Licence:  GNU GPL, no express or implied warranties
0065 % History:  06/2002, Darren.Weber@flinders.edu.au
0066 %           09/2002, Darren.Weber@flinders.edu.au
0067 %                    - transposed HeadToImageMatrix so it
0068 %                      can be used as described above
0069 %                    - added reading of most other fields
0070 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
0071 
0072 
0073 if ~exist('file','var'),
0074     fprintf('No input file - see help open_emse_reg\n');
0075     return;
0076 end
0077 
0078 [path,name,ext] = fileparts(file);
0079 file = fullfile(path,[name ext]);
0080 
0081 [fid,msg] = fopen(file,'r');
0082 if ~isempty(msg), error(msg); end
0083 
0084 fprintf('OPEN_EMSE_REG: Reading registration data...');
0085 tic
0086 fid = fopen(file,'r','ieee-le');
0087 reg = read_reg(fid);
0088 fclose(fid);
0089 t = toc;
0090 fprintf('done (%6.2f sec).\n',t);
0091 
0092 return
0093 
0094 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
0095 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
0096 function [reg] = read_reg(fid)
0097 
0098 while 1,
0099     text = fgetl(fid);
0100     if ~ischar(text), break, end
0101 
0102     if strmatch('Offset',text),
0103         % Offset is the translation in meters along the x, y and z axes
0104         % respectively, from the MRI image frame to head/elec frame.
0105         text = strrep(text,sscanf(text,'%c',8),'');
0106         text = strrep(text,']','');
0107         text = strrep(text,',','');
0108         reg.translation = sscanf(text,'%f')';
0109     end
0110     if strmatch('Rotation',text),
0111         % The Rotation vector contains the angles (in radians) about
0112         % the x, y and z axes, also from the MRI image frame to the
0113         % head/elec frame.
0114         text = strrep(text,sscanf(text,'%c',10),'');
0115         text = strrep(text,']','');
0116         text = strrep(text,',','');
0117         reg.rotation = sscanf(text,'%f')';
0118     end
0119     if strmatch('HeadToImageMatrix',text),
0120         reg.elec2mri = zeros(4,4);
0121         for i=1:4,
0122             text = fgetl(fid);
0123             reg.elec2mri(i,:) = sscanf(text,'%f')';
0124         end
0125         % The emse matrix requires transposition
0126         reg.elec2mri = reg.elec2mri';
0127         % It is more accurate to do this:
0128         reg.mri2elec = inv(reg.elec2mri);
0129     end
0130     % See inverse calculation above to get reg.mri2elec
0131     %if strmatch('ImageToHeadMatrix',text),
0132     %    reg.mri2elec = zeros(4,4);
0133     %    for i=1:4,
0134     %        text = fgetl(fid);
0135     %        reg.mri2elec(i,:) = sscanf(text,'%f')';
0136     %    end
0137     %    % The emse matrix requires transposition
0138     %    reg.mri2elec = reg.mri2elec';
0139     %end
0140 
0141     % The coordinates of the three fiducials are given in both frames.
0142     % For example, Head lists the fiducial coordinates (taken from the
0143     % electrode data) in the head frame, while Head' are the fiducial
0144     % coordinates from the image data expressed in the head frame.
0145     % Similarly, Image lists the fiducial coordinates from the image
0146     % data in the image frame while Image' lists those from the electrode
0147     % data in the image frame. The two sets of numbers should be close but
0148     % not identical.
0149 
0150     if strmatch('RPA',text,'exact'),
0151         format = '%7c %f %f %f';
0152         % Read the Right Preauricular coordinates
0153         text = fgetl(fid);
0154         tmp = sscanf(text,format)';
0155         reg.RPA.Hh = tmp(8:10);
0156         text = fgetl(fid);
0157         tmp = sscanf(text,format)';
0158         reg.RPA.Mh = tmp(8:10);
0159         text = fgetl(fid);
0160         tmp = sscanf(text,format)';
0161         reg.RPA.Mm = tmp(8:10);
0162         text = fgetl(fid);
0163         tmp = sscanf(text,format)';
0164         reg.RPA.Hm = tmp(8:10);
0165     end
0166 
0167     if strmatch('LPA',text,'exact'),
0168         format = '%7c %f %f %f';
0169         % Read the Left Preauricular coordinates
0170         text = fgetl(fid);
0171         tmp = sscanf(text,format)';
0172         reg.LPA.Hh = tmp(8:10);
0173         text = fgetl(fid);
0174         tmp = sscanf(text,format)';
0175         reg.LPA.Mh = tmp(8:10);
0176         text = fgetl(fid);
0177         tmp = sscanf(text,format)';
0178         reg.LPA.Mm = tmp(8:10);
0179         text = fgetl(fid);
0180         tmp = sscanf(text,format)';
0181         reg.LPA.Hm = tmp(8:10);
0182     end
0183 
0184     if strmatch('Nasion',text,'exact'),
0185         format = '%7c %f %f %f';
0186         % Read the Nasion coordinates
0187         text = fgetl(fid);
0188         tmp = sscanf(text,format)';
0189         reg.NAS.Hh = tmp(8:10);
0190         text = fgetl(fid);
0191         tmp = sscanf(text,format)';
0192         reg.NAS.Mh = tmp(8:10);
0193         text = fgetl(fid);
0194         tmp = sscanf(text,format)';
0195         reg.NAS.Mm = tmp(8:10);
0196         text = fgetl(fid);
0197         tmp = sscanf(text,format)';
0198         reg.NAS.Hm = tmp(8:10);
0199     end
0200 
0201     % The Electrode Positions block lists the coordinates (x, y, and z)
0202     % first in the head frame and then in the image frame.
0203     if strmatch('Electrode Positions',text),
0204         reg.Helec = zeros(1,3);
0205         reg.Melec = zeros(1,3);
0206         n = 1;
0207         while n < 400,
0208             % Read the Head space coordinates
0209             text = fgetl(fid);
0210             if isempty(text), break; end
0211             tmp = sscanf(text,'%f : %f %f')';
0212             reg.Helec(n,1:3) = tmp(2:4);
0213             % Read the MRI space coordinates
0214             text = fgetl(fid);
0215             tmp = sscanf(text,'%s %f %f %f')';
0216             reg.Melec(n,1:3) = tmp(2:4);
0217             n = n + 1;
0218         end
0219     end
0220 
0221 end
0222 
0223 % Create essential fiducial marker matrices
0224 % The order of these points in the matrices is very
0225 % important if they are used for coregistration
0226 reg.fiducials.head = [ reg.NAS.Hh; reg.RPA.Hh; reg.LPA.Hh ];
0227 reg.fiducials.mri  = [ reg.NAS.Mm; reg.RPA.Mm; reg.LPA.Mm ];
0228 
0229 
0230 return

Generated on Mon 15-Aug-2005 15:36:19 by m2html © 2003