ctf_read_mri.m
来自「含有多种ICA算法的eeglab工具箱」· M 代码 · 共 326 行
M
326 行
function mri = ctf_read_mri(file)% ctf_read_mri - read a CTF .mri file%% mri = ctf_read_mri(fileName)%% The CTF MRI File format used by MRIViewer consists of a binary file with% a 1,028 byte header. The MRI data can be in 8-bit (unsigned character) or% 16-bit (unsigned short integer) format and consists of 256 x 256 pixel% slices, stored as 256 contiguous sagittal slices from left to right (or% right to left if head orientation is left-on-right). Each slice is stored% as individual pixels starting at the left, anterior, superior% corner and scanning downwards row by row. Therefore the coronal% position is fastest changing, axial position second fastest% changing and sagittal position slowest changing value in the% file, always in the positive direction for each axis (see section% on Head Coordinate System for axis definitions). By default CTF% MRI files have the file extension .mri %% $Revision: 1.4 $ $Date: 2004/07/18 06:10:17 $% Copyright (C) 2003 Darren L. Weber% % This program is free software; you can redistribute it and/or% modify it under the terms of the GNU General Public License% as published by the Free Software Foundation; either version 2% of the License, or (at your option) any later version.% % This program is distributed in the hope that it will be useful,% but WITHOUT ANY WARRANTY; without even the implied warranty of% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the% GNU General Public License for more details.% % You should have received a copy of the GNU General Public License% along with this program; if not, write to the Free Software% Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.% History: 08/2003, Darren.Weber_at_radiology.ucsf.edu% - adapted from an appendex to CTF document% MRIConverter.pdf, which is copied at the end of this% function.%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%ver = '[$Revision: 1.4 $]';fprintf('\nCTF_READ_MRI [v%s]\n',ver(12:16)); tic;fprintf('...checking file input parameter\n');if ~exist('file','var'), [fileName, filePath, filterIndex] = uigetfile('*.mri', 'Locate CTF .mri file'); file = fullfile(filePath, fileName);elseif isempty(file), fprintf('...file is empty\n'); [fileName, filePath, filterIndex] = uigetfile('*.mri', 'Locate CTF .mri file'); file = fullfile(filePath, fileName);endif ~exist(file,'file'), fprintf('...file does not exist\n'); [fileName, filePath, filterIndex] = uigetfile('*.mri', 'Locate CTF .mri file'); file = fullfile(filePath, fileName);endmri.file = file;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% open the file for reading% 'ieee-be.l64' or 's' - IEEE floating point with big-endian byte% ordering and 64 bit long data type.[fid,message] = fopen(mri.file,'rb','s');if fid < 0, error('cannot open file'); end%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% read the file headerfprintf('...reading header ');mri.hdr = Version_2_Header_read(fid);%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% check header size, header should be 1028 bytesheader_bytes = ftell(fid);fprintf('(%d bytes)\n',header_bytes);if header_bytes ~= 1028, msg = sprintf('failed to read 1028 bytes from the header, read %d bytes',header_bytes); error(msg);end%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% seek beyond the header, to the beginning of the data matrixfseek(fid,1028,'bof');%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% check if the data is 8 or 16 bitsswitch mri.hdr.dataSize, case 1, % we have 8 bit data fprintf('...reading 8 bit image data\n'); precision = 'uchar'; case 2, % we have 16 bit data fprintf('...reading 16 bit image data\n'); precision = 'int16'; otherwise, msg = sprintf('unknown mri.hdr.dataSize: %g',mri.hdr.dataSize); error(msg);end%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% read the image data array% adjust for matlab versionver = version;ver = str2num(ver(1));if ver < 6, data = fread(fid,inf,sprintf('%s',precision));else, data = fread(fid,inf,sprintf('%s=>double',precision));endfclose(fid);%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% now we have the data array, allocate it to a 3D matrix% The CTF MRI File format used by MRIViewer consists of a binary file with a% 1,028 byte header. The MRI data can be in 8-bit (unsigned character) or 16-bit% (unsigned short integer) format and consists of 256 x 256 pixel slices, stored as% 256 contiguous sagittal slices from left to right (or right to left if head orientation% is "left-on-right"). Each slice is stored as individual pixels starting at the% top left corner and scanning downwards row by row. Therefore the coronal% position is fastest changing, axial position second fastest changing and sagittal% position slowest changing value in the file, always in the positive direction for% each axis (see section on Head Coordinate System for axis definitions). By% default CTF MRI files have the file extension ".mri"% MRIViewer uses these cardinal directions as axes in an internal coordinate system% where sagittal = X, coronal = Y and axial = Z forming an additional% right-handed coordinate system which is translated and rotated with respect to% the Head Coordinate System and has its origin at the upper left anterior corner% of the volume.PixelDim = 256;RowDim = 256;SliceDim = 256;% imageOrientation, 0 = left on left, 1 = left on rightswitch mri.hdr.imageOrientation, case 0, fprintf('...sagittal slices are neurological orientation (left is on the left)\n'); fprintf('...+X left to right, +Y anterior to posterior, +Z superior to inferior\n'); case 1, fprintf('...sagittal slices are radiological orientation (left is on the right)\n'); fprintf('...+X right to left, +Y anterior to posterior, +Z superior to inferior\n'); otherwise, msg = sprintf('...unknown mri.hdr.imageOrientation: %d\n',mri.hdr.imageOrientation); error(msg);endmri.img = zeros(SliceDim,PixelDim,RowDim);n = 1;y = 1:PixelDim; % +Y is from anterior to posteriorfor x = 1:SliceDim, % +X is from left to right for z = 1:RowDim, % +Z is from superior to inferior mri.img(x,y,z) = data(n:n+(PixelDim-1)); n = n + PixelDim; endendt=toc; fprintf('...done (%5.2f sec).\n\n',t);return%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%function Version_2_Header = Version_2_Header_read(fid),tmp = fread(fid,[1,32],'char');tmp(find(tmp<0)) = 0;Version_2_Header.identifierString = char( tmp );% check the header format version is 2.2if strmatch('CTF_MRI_FORMAT VER 2.2',Version_2_Header.identifierString), % OK this function should read thiselse msg = sprintf('this function is not designed to read this format:\n%s\n',Version_2_Header.identifierString); warning(msg);endVersion_2_Header.imageSize = fread(fid,1,'short'); % always = 256Version_2_Header.dataSize = fread(fid,1,'short'); % 1 or 2 (bytes), 8 or 16 bitsVersion_2_Header.clippingRange = fread(fid,1,'short'); % max. integer value of dataVersion_2_Header.imageOrientation = fread(fid,1,'short'); % eg., 0 = left on left, 1 = left on right% voxel dimensions in mmVersion_2_Header.mmPerPixel_sagittal = fread(fid,1,'float');Version_2_Header.mmPerPixel_coronal = fread(fid,1,'float');Version_2_Header.mmPerPixel_axial = fread(fid,1,'float');Version_2_Header.HeadModel_Info = headModel(fid); % defined below...Version_2_Header.Image_Info = imageInfo(fid); % defined below...% voxel location of head originVersion_2_Header.headOrigin_sagittal = fread(fid,1,'float');Version_2_Header.headOrigin_coronal = fread(fid,1,'float');Version_2_Header.headOrigin_axial = fread(fid,1,'float');% euler angles to align MR to head coordinate system (angles in degrees!)% 1. rotate in coronal plane by this angle% 2. rotate in sagittal plane by this angle% 3. rotate in axial plane by this angleVersion_2_Header.rotate_coronal = fread(fid,1,'float');Version_2_Header.rotate_sagittal = fread(fid,1,'float');Version_2_Header.rotate_axial = fread(fid,1,'float');Version_2_Header.orthogonalFlag = fread(fid,1,'short'); % if set then image is orthogonalVersion_2_Header.interpolatedFlag = fread(fid,1,'short'); % if set than image was interpolated% original spacing between slices before interpolation to CTF formatVersion_2_Header.originalSliceThickness = fread(fid,1,'float');% transformation matrix head->MRI [column][row]Version_2_Header.transformMatrix = fread(fid,[4 4],'float')';Version_2_Header.transformMatrixHead2MRI = Version_2_Header.transformMatrix;Version_2_Header.transformMatrixMRI2Head = inv(Version_2_Header.transformMatrix);% padding to 1028 bytes%tmp = fread(fid,[1,202],'uchar'); % according to CTF manual, this should%be 202, but it reads out to the 1028 bytes with 204. So maybe there are a%few bytes in the file read operations above that are missed?tmp = fread(fid,[1,204],'uchar');tmp = zeros(size(tmp));Version_2_Header.unused = char( tmp ); % ucharreturn%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%function HeadModel_Info = headModel(fid),% this function is called from Version_2_Header_read% fid. point coordinate (in voxels)HeadModel_Info.Nasion_Sag = fread(fid,1,'short'); % nasion - sagittalHeadModel_Info.Nasion_Cor = fread(fid,1,'short'); % nasion - coronalHeadModel_Info.Nasion_Axi = fread(fid,1,'short'); % nasion - axialHeadModel_Info.LeftEar_Sag = fread(fid,1,'short'); % left ear - sagittalHeadModel_Info.LeftEar_Cor = fread(fid,1,'short'); % left ear - coronalHeadModel_Info.LeftEar_Axi = fread(fid,1,'short'); % left ear - axialHeadModel_Info.RightEar_Sag = fread(fid,1,'short'); % right ear - sagittalHeadModel_Info.RightEar_Cor = fread(fid,1,'short'); % right ear - coronalHeadModel_Info.RightEar_Axi = fread(fid,1,'short'); % right ear - axialfread(fid,2,'char'); % padding to 4 byte boundary - from Robert Oostenveld% default sphere originHeadModel_Info.defaultSphereX = fread(fid,1,'float'); % sphere origin x coordinate ( in mm )HeadModel_Info.defaultSphereY = fread(fid,1,'float'); % sphere origin y coordinate ( in mm )HeadModel_Info.defaultSphereZ = fread(fid,1,'float'); % sphere origin z coordinate ( in mm )HeadModel_Info.defaultSphereRadius = fread(fid,1,'float'); % default sphere radius ( in mm )return%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%function Image_Info = imageInfo(fid),% this function is called from Version_2_Header_readImage_Info.modality = fread(fid,1,'short'); % 0 = MRI, 1 = CT, 2 = PET, 3 = SPECT, 4 = OTHERImage_Info.manufacturerName = char( fread(fid,[1,64],'char') );Image_Info.instituteName = char( fread(fid,[1,64],'char') );Image_Info.patientID = char( fread(fid,[1,32],'char') );Image_Info.dateAndTime = char( fread(fid,[1,32],'char') );Image_Info.scanType = char( fread(fid,[1,32],'char') );Image_Info.contrastAgent = char( fread(fid,[1,32],'char') );Image_Info.imagedNucleus = char( fread(fid,[1,32],'char') );fread(fid,2,'char'); % padding to 4 byte boundary - from Robert OostenveldImage_Info.Frequency = fread(fid,1,'float');Image_Info.FieldStrength = fread(fid,1,'float');Image_Info.EchoTime = fread(fid,1,'float');Image_Info.RepetitionTime = fread(fid,1,'float');Image_Info.InversionTime = fread(fid,1,'float');Image_Info.FlipAngle = fread(fid,1,'float');Image_Info.NoExcitations = fread(fid,1,'short');Image_Info.NoAcquisitions = fread(fid,1,'short');tmp = fread(fid,[1,256],'char');tmp = zeros(size(tmp));Image_Info.commentString = char( tmp );tmp = fread(fid,[1,64],'char');tmp = zeros(size(tmp));Image_Info.forFutureUse = char( tmp );return% The CTF MRI File format used by MRIViewer consists of a binary file with a% 1,028 byte header. The MRI data can be in 8-bit (unsigned character) or 16-bit% (unsigned short integer) format and consists of 256 x 256 pixel slices, stored as% 256 contiguous sagittal slices from left to right (or right to left if head orientation% is 搇eft-on-right
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?