freesurfer_surf2ctf - convert a freesurfer surface into CTF shape [ctf_shape,T] = freesurfer_surf2ctf(vertices) The input 'vertices' are obtained from freesurfer_read_surf; they are Nx3 vertex coordinates in the freesurfer RAS coordinate framework. This function first converts the vertex coordinates into the FreeSurfer MRI voxel index coordinate system and then from there into the CTF MRI voxel coordinate system. This assumes that a freesurfer MRI volume has been loaded into CTF MRI format correctly. To output the results as a CTF .shape file, use: ctf_write_headshape(ctf_shape,'filename.shape'); Both FreeSurfer and CTF volumes are 256^3 voxels, 1mm^3 each. However, they are different orientations, so the same voxel in each format has different voxel indices. CTF MRI default volume index has an origin at the left, anterior, superior voxel, such that: Sag increases from left to right (+X Right) Cor increases from anterior to posterior (+Y Posterior) Axi increases from superior to inferior (+Z Inferior) The origin is at the left, anterior, superior voxel CTF volume_index is: Sag, Cor, Axi (256^3, 1mm^3 voxels) CTF Sag = 256 - FreeSurfer Sag CTF Axi = FreeSurfer Axi CTF Cor = 256 - FreeSurfer Cor FreeSurfer volume_index is: Sag, Axi, Cor (256^3, 1mm^3 voxels) FreeSurfer Sag = 256 - CTF Sag FreeSurfer Axi = CTF Axi FreeSurfer Cor = 256 - CTF Cor So, we can convert from one to the other with the following transformations (T): T.fsVox2ctf = [ -1 0 0 0; 0 0 1 0; 0 -1 0 0; 256 256 0 1 ]; T.ctf2fsVox = [ -1 0 0 0; 0 0 -1 0; 0 1 0 0; 256 0 256 1 ]; This function calls freesurfer_surf2voxels, which employs the transforms: T.fsRAS2Vox = [ [-1 0 0 128]' [0 0 -1 128]' [ 0 1 0 128]' [ 0 0 0 1]' ]; T.fsVox2RAS = [ [-1 0 0 128]' [0 0 1 -128]' [ 0 -1 0 128]' [ 0 0 0 0]' ]; All transforms are designed to be right multiplied, like this: ctfVox = fsRAS * T.fsRAS2Vox * T.fsVox2ctf; see also freesurfer_surf2voxels, ctf_mri2head
0001 function [ctf_shape,T] = freesurfer_surf2ctf(SurfVertices) 0002 0003 % freesurfer_surf2ctf - convert a freesurfer surface into CTF shape 0004 % 0005 % [ctf_shape,T] = freesurfer_surf2ctf(vertices) 0006 % 0007 % The input 'vertices' are obtained from freesurfer_read_surf; they are Nx3 0008 % vertex coordinates in the freesurfer RAS coordinate framework. This 0009 % function first converts the vertex coordinates into the FreeSurfer MRI 0010 % voxel index coordinate system and then from there into the CTF MRI voxel 0011 % coordinate system. This assumes that a freesurfer MRI volume has been 0012 % loaded into CTF MRI format correctly. 0013 % 0014 % To output the results as a CTF .shape file, use: 0015 % ctf_write_headshape(ctf_shape,'filename.shape'); 0016 % 0017 % Both FreeSurfer and CTF volumes are 256^3 voxels, 1mm^3 each. However, 0018 % they are different orientations, so the same voxel in each format has 0019 % different voxel indices. 0020 % 0021 % CTF MRI default volume index has an origin at the left, anterior, superior 0022 % voxel, such that: 0023 % Sag increases from left to right (+X Right) 0024 % Cor increases from anterior to posterior (+Y Posterior) 0025 % Axi increases from superior to inferior (+Z Inferior) 0026 % 0027 % The origin is at the left, anterior, superior voxel 0028 % CTF volume_index is: Sag, Cor, Axi (256^3, 1mm^3 voxels) 0029 % CTF Sag = 256 - FreeSurfer Sag 0030 % CTF Axi = FreeSurfer Axi 0031 % CTF Cor = 256 - FreeSurfer Cor 0032 % 0033 % FreeSurfer volume_index is: Sag, Axi, Cor (256^3, 1mm^3 voxels) 0034 % FreeSurfer Sag = 256 - CTF Sag 0035 % FreeSurfer Axi = CTF Axi 0036 % FreeSurfer Cor = 256 - CTF Cor 0037 % 0038 % So, we can convert from one to the other with the following 0039 % transformations (T): 0040 % 0041 % T.fsVox2ctf = [ -1 0 0 0; 0 0 1 0; 0 -1 0 0; 256 256 0 1 ]; 0042 % T.ctf2fsVox = [ -1 0 0 0; 0 0 -1 0; 0 1 0 0; 256 0 256 1 ]; 0043 % 0044 % This function calls freesurfer_surf2voxels, which employs the transforms: 0045 % 0046 % T.fsRAS2Vox = [ [-1 0 0 128]' [0 0 -1 128]' [ 0 1 0 128]' [ 0 0 0 1]' ]; 0047 % T.fsVox2RAS = [ [-1 0 0 128]' [0 0 1 -128]' [ 0 -1 0 128]' [ 0 0 0 0]' ]; 0048 % 0049 % All transforms are designed to be right multiplied, like this: 0050 % 0051 % ctfVox = fsRAS * T.fsRAS2Vox * T.fsVox2ctf; 0052 % 0053 % see also freesurfer_surf2voxels, ctf_mri2head 0054 % 0055 0056 % $Revision: 1.2 $ $Date: 2005/06/27 21:24:36 $ 0057 0058 % Licence: GNU GPL, no express or implied warranties 0059 % History: 02/2004, Darren.Weber_at_radiology.ucsf.edu 0060 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 0061 0062 0063 0064 0065 %-------------------------------------------------------------------- 0066 % Convert FreeSurfer Surface Vertices from RAS to voxel indices 0067 VoxVertices = freesurfer_surf2voxels(SurfVertices); 0068 0069 0070 0071 ver = '$Revision: 1.2 $'; 0072 fprintf('FREESURFER_SURF2CTF [v %s]\n',ver(11:15)); tic; 0073 0074 %-------------------------------------------------------------------- 0075 % Pad out the VoxVertices to Nx4 matrix 0076 0077 Nvertices = size(VoxVertices,1); 0078 0079 right_column = [ ones( Nvertices, 1 ); 0 ]; 0080 0081 VoxVertices = [ [VoxVertices; 0 0 0] right_column ]; 0082 0083 %-------------------------------------------------------------------- 0084 % Convert FreeSurfer voxel indices into CTF voxel indices 0085 0086 T.fsVox2ctf = [ -1 0 0 0; 0 0 1 0; 0 -1 0 0; 256 256 0 1 ]; 0087 T.ctf2fsVox = [ -1 0 0 0; 0 0 -1 0; 0 1 0 0; 256 0 256 1 ]; 0088 0089 ctf_shape = VoxVertices * T.fsVox2ctf; 0090 0091 ctf_shape = ctf_shape(1:Nvertices,1:3); 0092 0093 t = toc; fprintf('...done (%6.2f sec).\n\n',t); 0094 0095 return 0096 0097 0098 0099 0100 0101 0102 0103 0104 0105 0106 0107 0108 %-------------------------------------------------------------------------- 0109 % TESTING CODE 0110 0111 0112 % CTF MRI default volume index has an origin at the left, anterior, superior 0113 % voxel, such that Sag slices increase from left to right, Cor 0114 % slices increase from anterior to posterior, and Axi slices 0115 % increase from superior to inferior 0116 0117 % CTF volume is 256^3 voxels, 1mm^3 each 0118 % Sag increases from left to right (+X Right) 0119 % Cor increases from anterior to posterior (+Y Posterior) 0120 % Axi increases from superior to inferior (+Z Inferior) 0121 % The origin is at the left, anterior, superior voxel 0122 % CTF volume_index is: Sag, Cor, Axi (256^3, 1mm^3 voxels) 0123 % CTF Sag = 256 - FreeSurfer Sag 0124 % CTF Axi = FreeSurfer Axi 0125 % CTF Cor = 256 - FreeSurfer Cor 0126 ctf.volume_index.nas = [128 35 130]; % voxels 0127 ctf.volume_index.lpa = [ 53 123 152]; 0128 ctf.volume_index.rpa = [207 123 152]; 0129 0130 ctf.volume_index.mat = [ctf.volume_index.nas; ctf.volume_index.lpa; ctf.volume_index.rpa ]; 0131 0132 ctfVox = [ [ctf.volume_index.mat; 0 0 0] [ 1 1 1 0 ]' ]; 0133 0134 % eg 0135 % ctfmat = 0136 % 0137 % 128 35 130 1 0138 % 53 123 152 1 0139 % 207 123 152 1 0140 % 0 0 0 0 0141 0142 % FreeSurfer volume_index is: Sag, Axi, Cor (256^3, 1mm^3 voxels) 0143 % FreeSurfer Sag = 256 - CTF Sag 0144 % FreeSurfer Axi = CTF Axi 0145 % FreeSurfer Cor = 256 - CTF Cor 0146 fs.volume_index.nas = [128 130 221]; 0147 fs.volume_index.lpa = [203 152 133]; 0148 fs.volume_index.rpa = [ 49 152 133]; 0149 0150 fs.volume_index.mat = [fs.volume_index.nas; fs.volume_index.lpa; fs.volume_index.rpa ]; 0151 0152 fsVox = [ [fs.volume_index.mat; 0 0 0] [1 1 1 0]'] 0153 0154 % eg, 0155 % fsVox = 0156 % 0157 % 128 130 221 1 0158 % 203 152 133 1 0159 % 49 152 133 1 0160 % 0 0 0 0 0161 0162 0163 0164 % This is the transformation matrix from FreeSurfer voxel indices 0165 % into CTF MRI voxel coordinates. 0166 T.fs2ctf = [ -1 0 0 0 ; 0167 0 0 1 0 ; 0168 0 -1 0 0 ; 0169 256 256 0 1 ]; 0170 0171 % This is the transformation matrix from CTF voxel indices into FreeSurfer 0172 % voxel indices 0173 T.ctf2fs = [ -1 0 0 0 ; 0174 0 0 -1 0 ; 0175 0 1 0 0 ; 0176 256 0 256 1 ]; 0177 0178 % or just, T.ctf2fs = inv(T.fs2ctf); 0179 0180 fs2ctf = fsVox * T.fs2ctf; 0181 0182 ctf2fs = ctfVox * T.ctf2fs; 0183 0184 0185 0186 % these .sph values are not the same as ctf.mri.hdr.headOrigin_* 0187 % values; these ones correspond to 0188 % ctf.mri.hdr.HeadModel_Info.defaultSphereXYZ, which are actually 0189 % given in mm, whereas the values below in ctf.volume_xyz.sph are 0190 % in cm (taken from the MRIViewer window 0191 ctf.volume_index.sph = [130 135 103]; 0192 0193 % CTF volume_xyz is: +X nasion, +Y left, +Z superior 0194 % convert cm to mm 0195 ctf.volume_xyz.nas = [18.58 0.00 0.00] * 10; 0196 ctf.volume_xyz.lpa = [ 4.38 9.14 0.00] * 10; 0197 ctf.volume_xyz.rpa = [-0.17 -7.70 0.00] * 10; 0198 0199 ctf.volume_xyz.sph = [ 0.00 0.00 5.00] * 10; 0200 0201 % NOTE 0202 % 02/22/04 Actually do not REALLY know what these values relate to! 0203 % The CTF coordinates have different distances between the 0204 % fiducials from the freesurfer coordinates, despite having 0205 % identical voxel dimensions between freesurfer and CTF!