save.m 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. function save(this,filename,encoding)
  2. % Save GIfTI object in a GIfTI format file
  3. % FORMAT save(this,filename,encoding)
  4. % this - GIfTI object
  5. % filename - name of GIfTI file to be created [Default: 'untitled.gii']
  6. % encoding - optional argument to specify encoding format, among
  7. % ASCII, Base64Binary, GZipBase64Binary, ExternalFileBinary.
  8. % [Default: 'GZipBase64Binary']
  9. %__________________________________________________________________________
  10. % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging
  11. % Guillaume Flandin
  12. % $Id: save.m 6516 2015-08-07 17:28:33Z guillaume $
  13. % Check filename
  14. %--------------------------------------------------------------------------
  15. ext = '.gii';
  16. if nargin == 1
  17. filename = 'untitled';
  18. end
  19. [p,f,e] = fileparts(filename);
  20. if ~ismember(lower(e),{ext})
  21. e = ext;
  22. end
  23. filename = fullfile(p,[f e]);
  24. % Open file for writing
  25. %--------------------------------------------------------------------------
  26. fid = fopen(filename,'wt');
  27. if fid == -1
  28. error('Unable to write file %s: permission denied.',filename);
  29. end
  30. % Write file
  31. %--------------------------------------------------------------------------
  32. if nargin < 3, encoding = 'GZipBase64Binary'; end
  33. switch encoding
  34. case {'ASCII','Base64Binary','GZipBase64Binary','ExternalFileBinary'}
  35. otherwise
  36. error('Unknown encoding.');
  37. end
  38. fid = save_gii(fid,this,encoding);
  39. % Close file
  40. %--------------------------------------------------------------------------
  41. fclose(fid);
  42. %==========================================================================
  43. % function fid = save_gii(fid,this,encoding)
  44. %==========================================================================
  45. function fid = save_gii(fid,this,encoding)
  46. % Defaults for DataArray's attributes
  47. %--------------------------------------------------------------------------
  48. [unused,unused,mach] = fopen(fid);
  49. if strncmp('ieee-be',mach,7)
  50. def.Endian = 'BigEndian';
  51. elseif strncmp('ieee-le',mach,7)
  52. def.Endian = 'LittleEndian';
  53. else
  54. error('[GIFTI] Unknown byte order "%s".',mach);
  55. end
  56. def.Encoding = encoding;
  57. def.Intent = 'NIFTI_INTENT_NONE';
  58. def.DataType = 'NIFTI_TYPE_FLOAT32';
  59. def.ExternalFileName = '';
  60. def.ExternalFileOffset = '';
  61. def.offset = 0;
  62. % Edit object DataArray attributes
  63. %--------------------------------------------------------------------------
  64. for i=1:length(this.data)
  65. % Revert the dimension storage
  66. d = this.data{i}.attributes.Dim;
  67. if numel(d) > 1 && d(end) == 1
  68. d = d(1:end-1);
  69. end
  70. this.data{i}.attributes = rmfield(this.data{i}.attributes,'Dim');
  71. this.data{i}.attributes.Dimensionality = num2str(length(d));
  72. for j=1:length(d)
  73. this.data{i}.attributes.(sprintf('Dim%d',j-1)) = num2str(d(j));
  74. end
  75. % Enforce some conventions
  76. this.data{i}.attributes.ArrayIndexingOrder = 'ColumnMajorOrder';
  77. if ~isfield(this.data{i}.attributes,'DataType') || ...
  78. isempty(this.data{i}.attributes.DataType)
  79. warning('DataType set to default: %s', def.DataType);
  80. this.data{i}.attributes.DataType = def.DataType;
  81. end
  82. if ~isfield(this.data{i}.attributes,'Intent') || ...
  83. isempty(this.data{i}.attributes.Intent)
  84. warning('Intent code set to default: %s', def.Intent);
  85. this.data{i}.attributes.Intent = def.Intent;
  86. end
  87. this.data{i}.attributes.Encoding = def.Encoding;
  88. this.data{i}.attributes.Endian = def.Endian;
  89. this.data{i}.attributes.ExternalFileName = def.ExternalFileName;
  90. this.data{i}.attributes.ExternalFileOffset = def.ExternalFileOffset;
  91. switch this.data{i}.attributes.Encoding
  92. case {'ASCII', 'Base64Binary','GZipBase64Binary' }
  93. case 'ExternalFileBinary'
  94. extfilename = this.data{i}.attributes.ExternalFileName;
  95. if isempty(extfilename)
  96. [p,f] = fileparts(fopen(fid));
  97. extfilename = [f '.dat'];
  98. end
  99. [p,f,e] = fileparts(extfilename);
  100. this.data{i}.attributes.ExternalFileName = fullfile(fileparts(fopen(fid)),[f e]);
  101. this.data{i}.attributes.ExternalFileOffset = num2str(def.offset);
  102. otherwise
  103. error('[GIFTI] Unknown data encoding: %s.',this.data{i}.attributes.Encoding);
  104. end
  105. end
  106. % Prolog
  107. %--------------------------------------------------------------------------
  108. fprintf(fid,'<?xml version="1.0" encoding="UTF-8"?>\n');
  109. fprintf(fid,'<!DOCTYPE GIFTI SYSTEM "http://www.nitrc.org/frs/download.php/115/gifti.dtd">\n');
  110. fprintf(fid,'<GIFTI Version="1.0" NumberOfDataArrays="%d">\n',numel(this.data));
  111. o = @(x) blanks(x*3);
  112. % MetaData
  113. %--------------------------------------------------------------------------
  114. fprintf(fid,'%s<MetaData',o(1));
  115. if isempty(this.metadata)
  116. fprintf(fid,'/>\n');
  117. else
  118. fprintf(fid,'>\n');
  119. for i=1:length(this.metadata)
  120. fprintf(fid,'%s<MD>\n',o(2));
  121. fprintf(fid,'%s<Name><![CDATA[%s]]></Name>\n',o(3),...
  122. this.metadata(i).name);
  123. fprintf(fid,'%s<Value><![CDATA[%s]]></Value>\n',o(3),...
  124. this.metadata(i).value);
  125. fprintf(fid,'%s</MD>\n',o(2));
  126. end
  127. fprintf(fid,'%s</MetaData>\n',o(1));
  128. end
  129. % LabelTable
  130. %--------------------------------------------------------------------------
  131. fprintf(fid,'%s<LabelTable',o(1));
  132. if isempty(this.label)
  133. fprintf(fid,'/>\n');
  134. else
  135. fprintf(fid,'>\n');
  136. for i=1:length(this.label.name)
  137. if ~all(isnan(this.label.rgba(i,:)))
  138. label_rgba = sprintf(' Red="%f" Green="%f" Blue="%f" Alpha="%f"',...
  139. this.label.rgba(i,:));
  140. else
  141. label_rgba = '';
  142. end
  143. fprintf(fid,'%s<Label Key="%d"%s><![CDATA[%s]]></Label>\n',o(2),...
  144. this.label.key(i), label_rgba, this.label.name{i});
  145. end
  146. fprintf(fid,'%s</LabelTable>\n',o(1));
  147. end
  148. % DataArray
  149. %--------------------------------------------------------------------------
  150. for i=1:length(this.data)
  151. fprintf(fid,'%s<DataArray',o(1));
  152. if def.offset
  153. this.data{i}.attributes.ExternalFileOffset = num2str(def.offset);
  154. end
  155. fn = sort(fieldnames(this.data{i}.attributes));
  156. oo = repmat({o(5) '\n'},length(fn),1); oo{1} = ' '; oo{end} = '';
  157. for j=1:length(fn)
  158. if strcmp(fn{j},'ExternalFileName')
  159. [p,f,e] = fileparts(this.data{i}.attributes.(fn{j}));
  160. attval = [f e];
  161. else
  162. attval = this.data{i}.attributes.(fn{j});
  163. end
  164. fprintf(fid,'%s%s="%s"%s',oo{j,1},...
  165. fn{j},attval,sprintf(oo{j,2}));
  166. end
  167. fprintf(fid,'>\n');
  168. % MetaData
  169. %----------------------------------------------------------------------
  170. fprintf(fid,'%s<MetaData>\n',o(2));
  171. for j=1:length(this.data{i}.metadata)
  172. fprintf(fid,'%s<MD>\n',o(3));
  173. fprintf(fid,'%s<Name><![CDATA[%s]]></Name>\n',o(4),...
  174. this.data{i}.metadata(j).name);
  175. fprintf(fid,'%s<Value><![CDATA[%s]]></Value>\n',o(4),...
  176. this.data{i}.metadata(j).value);
  177. fprintf(fid,'%s</MD>\n',o(3));
  178. end
  179. fprintf(fid,'%s</MetaData>\n',o(2));
  180. % CoordinateSystemTransformMatrix
  181. %----------------------------------------------------------------------
  182. for j=1:length(this.data{i}.space)
  183. fprintf(fid,'%s<CoordinateSystemTransformMatrix>\n',o(2));
  184. fprintf(fid,'%s<DataSpace><![CDATA[%s]]></DataSpace>\n',o(3),...
  185. this.data{i}.space(j).DataSpace);
  186. fprintf(fid,'%s<TransformedSpace><![CDATA[%s]]></TransformedSpace>\n',o(3),...
  187. this.data{i}.space(j).TransformedSpace);
  188. fprintf(fid,'%s<MatrixData>%s</MatrixData>\n',o(3),...
  189. sprintf('%f ',this.data{i}.space(j).MatrixData'));
  190. fprintf(fid,'%s</CoordinateSystemTransformMatrix>\n',o(2));
  191. end
  192. % Data (saved using MATLAB's ColumnMajorOrder)
  193. %----------------------------------------------------------------------
  194. fprintf(fid,'%s<Data>',o(2));
  195. tp = getdict;
  196. try
  197. tp = tp.(this.data{i}.attributes.DataType);
  198. catch
  199. error('[GIFTI] Unknown DataType.');
  200. end
  201. switch this.data{i}.attributes.Encoding
  202. case 'ASCII'
  203. fprintf(fid, [tp.format ' '], this.data{i}.data);
  204. case 'Base64Binary'
  205. fprintf(fid,base64encode(typecast(this.data{i}.data(:),'uint8')));
  206. % uses native machine format
  207. case 'GZipBase64Binary'
  208. fprintf(fid,base64encode(zstream('C',typecast(this.data{i}.data(:),'uint8'))));
  209. % uses native machine format
  210. case 'ExternalFileBinary'
  211. extfilename = this.data{i}.attributes.ExternalFileName;
  212. dat = this.data{i}.data;
  213. if isa(dat,'file_array')
  214. dat = subsref(dat,substruct('()',repmat({':'},1,numel(dat.dim))));
  215. end
  216. if ~def.offset
  217. fide = fopen(extfilename,'w'); % uses native machine format
  218. else
  219. fide = fopen(extfilename,'a'); % uses native machine format
  220. end
  221. if fide == -1
  222. error('Unable to write file %s: permission denied.',extfilename);
  223. end
  224. fseek(fide,0,1);
  225. fwrite(fide,dat,tp.class);
  226. def.offset = ftell(fide);
  227. fclose(fide);
  228. otherwise
  229. error('[GIFTI] Unknown data encoding.');
  230. end
  231. fprintf(fid,'</Data>\n');
  232. fprintf(fid,'%s</DataArray>\n',o(1));
  233. end
  234. fprintf(fid,'</GIFTI>\n');