spm_mnc2nifti.m 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. function [N,cdf] = spm_mnc2nifti(fname,opts)
  2. % Import MINC images into NIfTI
  3. % FORMAT spm_mnc2nifti(fname)
  4. % fname - a MINC filename
  5. % opts - options structure
  6. %
  7. % N - NIfTI object (written in current directory)
  8. % cdf - NetCDF data structure
  9. %
  10. % The MINC file format was developed by Peter Neelin at the Montreal
  11. % Neurological Institute, and is based upon the NetCDF libraries.
  12. % The NetCDF documentation specifically recommends that people do not
  13. % write their own libraries for accessing the data. This suggestion
  14. % was ignored.
  15. %
  16. % See: http://en.wikibooks.org/wiki/MINC
  17. %__________________________________________________________________________
  18. % Copyright (C) 2005-2011 Wellcome Trust Centre for Neuroimaging
  19. % John Ashburner
  20. % $Id: spm_mnc2nifti.m 4927 2012-09-14 16:15:10Z ged $
  21. if nargin==1
  22. opts = struct('dtype',4, 'ext',spm_file_ext);
  23. else
  24. if opts.ext(1) ~= '.', opts.ext = ['.' opts.ext]; end
  25. end
  26. cdf = spm_read_netcdf(fname);
  27. if isempty(cdf)
  28. error(['"' fname '" does not appear to be MINC.']);
  29. end
  30. %-Create file_array object
  31. %--------------------------------------------------------------------------
  32. idat = file_array;
  33. d_types = [2 2 512 768 16 64 ; 256 256 4 8 16 64];
  34. %dsizes = [1 1 2 4 4 8 ];
  35. mxs = [255 255 65535 2^32-1 Inf Inf; 127 127 32767 2^31-1 Inf Inf];
  36. mns = [0 0 0 0 -Inf -Inf;-128 -128 -32768 -2^31 -Inf -Inf];
  37. %space_names= {'xspace','yspace','zspace'};
  38. img = findvar(cdf.var_array,'image');
  39. nd = length(img.dimid);
  40. idat.fname = fname;
  41. idat.dim = fliplr(cat(2,cdf.dim_array(:).dim_length));
  42. signed = findvar(img.vatt_array,'signtype');
  43. signed = strcmp(signed.val,'signed__');
  44. idat.dtype = [d_types(signed+1,img.nc_type) 1];
  45. range = [mns(signed+1,img.nc_type) mxs(signed+1,img.nc_type)];
  46. idat.offset = img.begin;
  47. if img.nc_type <=4
  48. tmp = findvar(img.vatt_array,'valid_range');
  49. if isempty(tmp)
  50. disp(['Can''t get valid_range for "' fname '" - having to guess']);
  51. else
  52. range = tmp.val;
  53. end
  54. fp = fopen(fname,'r','ieee-be');
  55. imax = get_imax(fp, cdf, 'image-max', 1, idat.dim);
  56. imin = get_imax(fp, cdf, 'image-min', 0, idat.dim);
  57. fclose(fp);
  58. scale = (imax-imin)/(range(2)-range(1));
  59. dcoff = imin-range(1)*scale;
  60. else
  61. scale = 1;
  62. dcoff = 0;
  63. end
  64. %-Extract affine transformation from voxel to world co-ordinates
  65. %--------------------------------------------------------------------------
  66. step = [1 1 1];
  67. start = [0 0 0]';
  68. dircos = eye(3);
  69. for j=1:3
  70. nam = cdf.dim_array(img.dimid(nd+1-j)).name;
  71. space = findvar(cdf.var_array,nam);
  72. tmp = findvar(space.vatt_array,'step');
  73. if ~isempty(tmp), step(j) = tmp.val; end
  74. tmp = findvar(space.vatt_array,'start');
  75. if ~isempty(tmp), start(j) = tmp.val; else start(j) = -dim(j)/2*step(j); end
  76. tmp = findvar(space.vatt_array,'direction_cosines');
  77. if ~isempty(tmp)
  78. if tmp.nc_type == 6
  79. dircos(:,j) = tmp.val(:);
  80. elseif tmp.nc_type == 2
  81. dircos(:,j) = sscanf(tmp.val,'%g');
  82. end
  83. end
  84. end
  85. shiftm = [1 0 0 -1; 0 1 0 -1; 0 0 1 -1; 0 0 0 1];
  86. mat = [[dircos*diag(step) dircos*start] ; [0 0 0 1]] * shiftm;
  87. %-Create NIfTI object
  88. %--------------------------------------------------------------------------
  89. N = nifti;
  90. dat = file_array;
  91. nam = spm_file(fname,'basename');
  92. dat.fname = fullfile(pwd,[nam opts.ext]);
  93. dat.dim = idat.dim;
  94. dat.dtype = [opts.dtype spm_platform('bigend')];
  95. dat.offset = 0;
  96. if ~spm_type(opts.dtype,'intt')
  97. dat.scl_slope = 1;
  98. dat.scl_inter = 0;
  99. else
  100. mn = Inf;
  101. mx = -Inf;
  102. for i6=1:size(idat,6)
  103. for i5=1:size(idat,5)
  104. for i4=1:size(idat,4)
  105. for i3=1:size(idat,3)
  106. if size(scale,3)==1
  107. scale1 = scale(:,:,1,i4,i5,i6);
  108. dcoff1 = dcoff(:,:,1,i4,i5,i6);
  109. else
  110. scale1 = scale(:,:,i3,i4,i5,i6);
  111. dcoff1 = dcoff(:,:,i3,i4,i5,i6);
  112. end
  113. if numel(scale1)==1
  114. img = double(idat(:,:,i3,i4,i5,i6))*scale1 + dcoff1;
  115. elseif size(scale1,1)>1 && size(scale1,2)>1
  116. img = double(idat(:,:,i3,i4,i5,i6)).*scale1 + dcoff1;
  117. elseif size(scale1,1)==1
  118. img = double(idat(:,:,i3,i4,i5,i6)).*repmat(scale1,[size(idat,1) 1]) +...
  119. repmat(dcoff1,[size(idat,1) 1]);
  120. else
  121. img = double(idat(:,:,i3,i4,i5,i6)).*repmat(scale1,[1 size(idat,2)]) +...
  122. repmat(dcoff1,[1 size(idat,2)]);
  123. end
  124. img = img(isfinite(img));
  125. if ~isempty(img)
  126. mx = max(mx,max(img));
  127. mn = min(mn,min(img));
  128. end
  129. end
  130. end
  131. end
  132. end
  133. dat.scl_slope = mx/spm_type(opts.dtype,'maxval');
  134. if spm_type(opts.dtype,'minval')~=0
  135. dat.scl_slope = max(dat.scl_slope,mn/spm_type(opts.dtype,'minval'));
  136. end
  137. dat.scl_inter = 0;
  138. end
  139. N.dat = dat;
  140. flp = false;
  141. if det(mat)>0
  142. flp = true;
  143. mat = mat*[diag([-1 1 1]) [size(dat,1)+1 0 0]' ; 0 0 0 1];
  144. end
  145. N.mat = mat;
  146. N.mat0 = mat;
  147. create(N);
  148. for i6=1:size(idat,6)
  149. for i5=1:size(idat,5)
  150. for i4=1:size(idat,4)
  151. for i3=1:size(idat,3)
  152. if size(scale,3)==1
  153. scale1 = scale(:,:,1,i4,i5,i6);
  154. dcoff1 = dcoff(:,:,1,i5,i5,i6);
  155. else
  156. scale1 = scale(:,:,i3,i4,i5,i6);
  157. dcoff1 = dcoff(:,:,i3,i4,i5,i6);
  158. end
  159. if numel(scale1)==1
  160. slice = double(idat(:,:,i3,i4,i5,i6))*scale1 + dcoff1;
  161. elseif size(scale1,1)>1 && size(scale1,2)>1
  162. slice = double(idat(:,:,i3,i4,i5,i6)).*scale1 + dcoff1;
  163. elseif size(scale1,1)==1
  164. slice = double(idat(:,:,i3,i4,i5,i6)).*repmat(scale1,[size(idat,1) 1]) +...
  165. repmat(dcoff1,[size(idat,1) 1]);
  166. else
  167. slice = double(idat(:,:,i3,i4,i5,i6)).*repmat(scale1,[1 size(idat,2)]) +...
  168. repmat(dcoff1,[1 size(idat,2)]);
  169. end
  170. if flp, slice = flipud(slice); end
  171. N.dat(:,:,i3,i4,i5,i6) = slice;
  172. end
  173. end
  174. end
  175. end
  176. %==========================================================================
  177. % function var = findvar(varlist, name)
  178. %==========================================================================
  179. function var = findvar(varlist, name)
  180. % Finds the structure in a list of structures that has a name element
  181. % matching the second argument.
  182. for i=1:numel(varlist)
  183. if strcmp(varlist(i).name,name)
  184. var = varlist(i);
  185. return;
  186. end
  187. end
  188. var = [];
  189. %error(['Can''t find "' name '".']);
  190. %==========================================================================
  191. % function str = dtypestr(i)
  192. %==========================================================================
  193. function str = dtypestr(i)
  194. % Returns a string appropriate for reading or writing the CDF data-type.
  195. types = char('uint8','uint8','int16','int32','float32','float64');
  196. str = deblank(types(i,:));
  197. %==========================================================================
  198. % function imax = get_imax(fp, cdf, strng, def, dim)
  199. %==========================================================================
  200. function imax = get_imax(fp, cdf, strng, def, dim)
  201. dim = fliplr(dim);
  202. str = findvar(cdf.var_array,strng);
  203. if ~isempty(str) && str.nc_type == 6
  204. fseek(fp,str.begin,'bof');
  205. nel = str.vsize/(spm_type(dtypestr(str.nc_type),'bits')/8);
  206. imax = fread(fp,nel,dtypestr(str.nc_type))';
  207. resh = ones(1,numel(dim));
  208. resh(numel(dim)+1-str.dimid) = dim(str.dimid);
  209. imax = reshape(imax,resh);
  210. else
  211. imax = def;
  212. end