somtoolbox2/som_write_cod.m
4dbef185
 function som_write_cod(sMap, filename)
 
 %SOM_WRITE_COD Writes a map struct to ascii file in SOM_PAK format.
 %
 % som_write_cod(sMap,filename)
 %
 %  som_write_cod(sMap,'map1.cod');
 %
 %  Input and output arguments: 
 %   sMap        (struct) self-organizing map structure
 %   filename    (string) name of input file
 %
 % Note that much of the information in the map struct is lost.
 % Typically, when saving map structs into files use the 'save' command.
 %
 % For more help, try 'type som_write_cod' or check out online documentation.
 % See also SOM_READ_COD, SOM_READ_DATA, SOM_WRITE_DATA.
 
 %%%%%%%%%%%%% DETAILED DESCRIPTION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %
 % som_write_cod
 %
 % PURPOSE
 %
 % Writes a self-organizing map struct to a file in SOM_PAK format.
 %
 % SYNTAX
 %
 %  som_write_cod(sMap,filename); 
 %
 % DESCRIPTION
 %
 % This function is offered for compatibility with SOM_PAK, a SOM 
 % software package in C. It writes map struct to files in SOM_PAK format.
 %
 % See SOM_READ_COD for description of the SOM_PAK map file format.
 % Because the SOM_PAK package does not support many of the features and
 % options of the SOM Toolbox, some of the information is changed, or even
 % lost. 
 %
 % SOM_PAK does not support 3- or higher dimensional map grids. These cannot
 %         be exported using this function.  
 % SOM_PAK always supposes that the map has 'sheet' shape. 
 % SOM_PAK only supports 'bubble' and 'gaussian' neighborhood functions.
 %         Any other neighborhood function is changed to 'gaussian'.
 % SOM_PAK doesn't support component names. However, the component names are
 %         written on a comment line which begins with '#n '. Any spaces (' ') 
 %         in the component names are replaced with underscores ('_').      
 % Information on map name, mask, training history and normalizations is lost.
 %
 % This function is only offered for compatibility with SOM_PAK. In general,
 % when saving map structs in files, use 'save filename.mat sMap'. This is
 % faster and retains all information of the map.
 % 
 % REQUIRED INPUT ARGUMENTS
 %
 %  sMap       (struct) the SOM struct to be written
 %  filename   (string) the name of the input file
 %
 % EXAMPLES
 %
 %  som_write_cod(sMap,'map1.cod');
 %
 % SEE ALSO
 % 
 %  som_read_cod     Read a map from a file in SOM_PAK format.
 %  som_read_data    Reads data from an ascii file.
 %  som_write_data   Writes data struct into a file in SOM_PAK format.
 
 % Copyright (c) 1997-2000 by the SOM toolbox programming team.
 % http://www.cis.hut.fi/projects/somtoolbox/
 
 % Version 1.0beta ecco 221097
 % Version 2.0beta ecco 030899, juuso 151199
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %% check arguments and initialize
 
 error(nargchk(2, 2, nargin))  % check no. of input args is correct
 
 % sMap
 msize = sMap.topol.msize;           % map grid size
 mdim  = length(msize);              % map grid dimension
 [munits dim] = size(sMap.codebook); % input space dimension
 
 % map dimension check:
 % map dimensions higher than 2 are not supported by SOM_PAK
 if mdim > 2,      
   error('Cannot write maps with higher dimension than two');
 end
 
 % in SOM_PAK the xy-indexing is used, while in Matlab ij-indexing
 % therefore, the codebook vectors have to be reorganized 
 order = reshape([1:munits],msize);
 order = reshape(order',[munits 1]);
 msize = fliplr(msize);
 
 % open output file
 fid = fopen(filename, 'w');
 if fid < 0,
   error(['Cannot open file ' filename]);
 end
 
 % check version
 v = version;
 ver_53_or_newer = (str2num(v(1:3)) >= 5.3);
 
 
 [lines numlabs] = size(sMap.labels);
 has_labels = zeros(lines, 1);
 if ver_53_or_newer
   has_labels = sum((~(cellfun('isempty', sMap.labels))), 2);
 else
   for i = 1:lines
     for j = 1:numlabs
       if ~isempty(sMap.labels{i,j}) 
 	has_labels(i) = 1; break; 
       end
     end
   end
 end
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %% write map into a file
 
 % write header
 
 fprintf(fid, '%d %s ', dim, sMap.topol.lattice); % dimension and lattice
 fprintf(fid, '%d ', msize);                      % map size
 % neighborhood type ('ep' and 'cutgauss' are not supported by SOM_PAK; 
 % they are converted to 'gaussian')
 if strcmp(sMap.neigh,'bubble'), fprintf(fid, 'bubble\n');
 else 
   if ~strcmp(sMap.neigh,'gaussian'), 
     warning(['Neighborhood type ''' sMap.neigh ''' converted to ''gaussian''']);
   end
   fprintf(fid,'gaussian\n'); 
 end
 
 % write the component names as a SOM_PAK comment line
 
 fprintf(fid,'#n ');
 for i=1:dim, fprintf(fid, '%s ', strrep(sMap.comp_names{i},' ','_')); end
 fprintf(fid,'\n');
 
 % write codebook
 
 form  = [repmat('%g ',[1 dim]) '\n'];
 if ~has_labels  % no labels; fast
   fprintf(fid, form, sMap.codebook(order,:)');
 else            % has labels; slow
   for i=1:munits, 
     fprintf(fid, '%g ', sMap.codebook(order(i),:));
 
     if has_labels(order(i))
       temp = '';
       if ver_53_or_newer
 	nonempty = ~(cellfun('isempty', sMap.labels(i,:)));
       else
 	for j = 1:numlabs, nonempty(j) = ~isempty(sMap.labels{i, j}); end
       end
       labs = char(sMap.labels{order(i), nonempty});
       labs(:,end + 1) = ' ';
       temp = reshape(labs',[1 prod(size(labs))]);
       temp(findstr('  ', temp))='';
       fprintf(fid, '%s\n', temp(1:end-1));
     else
       fprintf(fid, '\n');
     end
   end
 end
 
 % close file
 
 if fclose(fid) 
   error(['Cannot close file ' filename]);
 else
   fprintf(2, 'map write ok\n');
 end
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%