wolffd@0: function [sS, ok, msgs] = som_set(sS, varargin) wolffd@0: wolffd@0: %SOM_SET Create and check SOM Toolbox structs, give values to their fields. wolffd@0: % wolffd@0: % [sS, ok, msgs] = som_set(sS, [field, contents, ...]) wolffd@0: % wolffd@0: % sM = som_set(sM,'name','SOM#1.1'); wolffd@0: % [dummy,ok,msgs] = som_set(sData); wolffd@0: % sT = som_set('som_topol','msize',[10 10],'lattice','hexa'); wolffd@0: % [sTrain,ok] = som_set(sTrain,'algorithm','lininit'); wolffd@0: % [sN,ok,msgs] = som_set('som_norm'); wolffd@0: % wolffd@0: % Input and output arguments ([]'s are optional): wolffd@0: % sS the target struct wolffd@0: % (struct) a SOM Toolbox structure (not visualization struct) wolffd@0: % (string) structure identifier (see below) wolffd@0: % the updated/created structure is returned wolffd@0: % [field, (string) field to be given value to (see below) wolffd@0: % contents] (varies) the contents for the field wolffd@0: % wolffd@0: % ok (vector) status for each field-contents pair (1=ok) wolffd@0: % msgs (cellstr) status string for each field-contents pair (''=ok) wolffd@0: % wolffd@0: % There can be arbitrarily many field-contents pairs. If there wolffd@0: % are _no_ field-content pairs, and the first argument is a struct, wolffd@0: % the fields of the struct are checked for validity. wolffd@0: % wolffd@0: % Valid struct and corresponding field identifiers: wolffd@0: % 'som_map' : 'codebook', 'labels', 'mask', 'neigh', 'name', wolffd@0: % 'topol', 'msize, 'lattice', 'shape', wolffd@0: % 'trainhist', 'comp_names', 'comp_norm', wolffd@0: % 'som_data' : 'data', 'labels', 'name', 'comp_names', 'comp_norm', wolffd@0: % 'label_names' wolffd@0: % 'som_topol' : 'msize', 'lattice', 'shape' wolffd@0: % 'som_norm' : 'method', 'params', 'status' wolffd@0: % 'som_train' : 'algorithm', 'data_name', 'mask', 'neigh', wolffd@0: % 'radius_ini', 'radius_fin', 'alpha_ini', 'alpha_type', wolffd@0: % 'trainlen', 'time' wolffd@0: % 'som_grid' : 'lattice', 'shape', 'msize', 'coord', wolffd@0: % 'line', 'linecolor', 'linewidth', wolffd@0: % 'marker', 'markersize', 'markercolor', 'surf', wolffd@0: % 'label', 'labelcolor', 'labelsize' wolffd@0: % checking given values has not been implemented yet! wolffd@0: % wolffd@0: % For more help, try 'type som_set' or check out online documentation. wolffd@0: % See also SOM_INFO, SOM_MAP_STRUCT, SOM_DATA_STRUCT, SOM_VS1TO2. wolffd@0: wolffd@0: %%%%%%%%%%%%% DETAILED DESCRIPTION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% wolffd@0: % wolffd@0: % som_set wolffd@0: % wolffd@0: % PURPOSE wolffd@0: % wolffd@0: % Create and set values for fields of SOM Toolbox structs (except wolffd@0: % visualization struct). Can also be used to check the validity of structs. wolffd@0: % wolffd@0: % SYNTAX wolffd@0: % wolffd@0: % sMap = som_set('som_map'); wolffd@0: % sData = som_set(sData); wolffd@0: % sNorm = som_set(...,'field',contents,...); wolffd@0: % [sTopol,ok] = som_set(sTopol,...); wolffd@0: % [sTrain,ok,msgs] = som_set('som_train',...); wolffd@0: % wolffd@0: % DESCRIPTION wolffd@0: % wolffd@0: % The function is used to create and set values for fields of SOM wolffd@0: % Toolbox structs, except visualization structs. The given values are wolffd@0: % first checked for validity, and if they are not valid, an error wolffd@0: % message is returned. The function can also be used to check the wolffd@0: % validity of all the fields of the struct by supplying a struct as wolffd@0: % the first and only argument. wolffd@0: % wolffd@0: % NOTE: Using SOM_SET to create structures does _not_ guarantee that the wolffd@0: % structs are valid (try e.g. sM = som_set('som_map'); som_set(sM)). The wolffd@0: % initial values that the function gives to the fields of the structs are wolffd@0: % typically invalid. It is recommended that when creating map or data wolffd@0: % structs, the corresponding functions SOM_MAP_STRUCT and SOM_DATA_STRUCT wolffd@0: % are used instead of SOM_SET. However, when giving values for the fields, wolffd@0: % SOM_SET tries to guarantee that the values are valid. wolffd@0: % wolffd@0: % If a string is given as the first argument, the corresponding wolffd@0: % structure is first created and the field-content pairs are then wolffd@0: % applied to it. wolffd@0: % wolffd@0: % There can be arbitrarily many field-contents pairs. The pairs wolffd@0: % are processed sequentially one pair at a time. For each pair, wolffd@0: % the validity of the contents is checked and the corresponding wolffd@0: % items in the returned 'ok'-vector and 'msgs'-cellstring are set. wolffd@0: % - if the contents is ok, the status is set to 1 and message to '' wolffd@0: % - if the contents is suspicious, status is set to 1, but a wolffd@0: % message is produced wolffd@0: % - if the contents is invalid, status is set to 0 and an error wolffd@0: % message is produced. The contents are _not_ given to the field. wolffd@0: % If there is only one output argument, the status and messages wolffd@0: % for each pair are printed to standard output. wolffd@0: % wolffd@0: % The different field-contents pairs have no effect on each other. wolffd@0: % If a field is given a value multiple times, the last valid one wolffd@0: % stays in effect. wolffd@0: % wolffd@0: % In some cases, the order of the given fields is significant. wolffd@0: % For example in the case of 'som_map', the validity of some fields, wolffd@0: % like '.comp_names', depends on the input space dimension, which is wolffd@0: % checked from the '.data' field (dim = size(sD.data,2) to be specific). wolffd@0: % Therefore, the '.data' field (or '.codebook' field in case of map wolffd@0: % struct) should always be given a value first. Below is a list of wolffd@0: % this kind of dependancies: wolffd@0: % wolffd@0: % som_map: 'comp_names', 'comp_norm', 'msize', 'topol.msize', wolffd@0: % 'labels' and 'mask' depend on 'codebook' wolffd@0: % new value for 'codebook' should have equal size to the old wolffd@0: % one (unless the old one was empty) wolffd@0: % som_data: 'comp_names' and 'comp_norm' depend on 'data' wolffd@0: % new value for 'data' should have equal dimension (size(data,2)) wolffd@0: % as the old one (unless the old one was empty) wolffd@0: % wolffd@0: % KNOWN BUGS wolffd@0: % wolffd@0: % Checking the values given to som_grid struct has not been wolffd@0: % implemented. Use SOM_GRID function to give the values. wolffd@0: % wolffd@0: % REQUIRED INPUT ARGUMENTS wolffd@0: % wolffd@0: % sS The struct. wolffd@0: % (struct) A SOM Toolbox struct. wolffd@0: % (string) Identifier of a SOM Toolbox struct: 'som_map', wolffd@0: % 'som_data', 'som_topol', 'som_norm' or 'som_train' wolffd@0: % wolffd@0: % OPTIONAL INPUT ARGUMENTS wolffd@0: % wolffd@0: % field (string) Field identifier string (see below). wolffd@0: % contents (varies) Value for the field (see below). wolffd@0: % wolffd@0: % Below is the list of valid field identifiers for the different wolffd@0: % SOM Toolbox structs. wolffd@0: % wolffd@0: % 'som_map' (map struct) wolffd@0: % 'codebook' : matrix, size [munits, dim] wolffd@0: % 'labels' : cell array of strings, wolffd@0: % size [munits, maximum_number_of_labels] wolffd@0: % 'topol' : topology struct (prod(topol.msize)=munits) wolffd@0: % 'mask' : vector, size [dim, 1] wolffd@0: % 'neigh' : string ('gaussian' or 'cutgauss' or 'bubble' or 'ep') wolffd@0: % 'trainhist' : struct array of train structs wolffd@0: % 'name' : string wolffd@0: % 'comp_names' : cellstr, size [dim, 1], e.g. {'c1','c2','c3'} wolffd@0: % 'comp_norm' : cell array, size [dim, 1], of cell arrays wolffd@0: % of normalization structs wolffd@0: % Also the following can be used (although they are fields wolffd@0: % of the topology struct) wolffd@0: % 'msize' : vector (prod(msize)=munits) wolffd@0: % 'lattice' : string ('rect' or 'hexa') wolffd@0: % 'shape' : string ('sheet' or 'cyl' or 'toroid') wolffd@0: % wolffd@0: % 'som_data' (data struct) wolffd@0: % 'data' : matrix, size [dlen, dim] wolffd@0: % 'name' : string wolffd@0: % 'labels' : cell array of strings, wolffd@0: % size [dlen, m] wolffd@0: % 'comp_names' : cellstr, size [dim, 1], e.g. {'c1','c2','c3'} wolffd@0: % 'comp_norm' : cell array, size [dim, 1], of cell arrays wolffd@0: % of normalization structs wolffd@0: % 'label_names' : cellstr, size [m, 1] wolffd@0: % wolffd@0: % 'som_topol' (topology struct) wolffd@0: % 'msize' : vector wolffd@0: % 'lattice' : string ('rect' or 'hexa') wolffd@0: % 'shape' : string ('sheet' or 'cyl' or 'toroid') wolffd@0: % wolffd@0: % 'som_norm' (normalization struct) wolffd@0: % 'method' : string wolffd@0: % 'params' : varies wolffd@0: % 'status' : string ('done' or 'undone' or 'uninit') wolffd@0: % wolffd@0: % 'som_train' (train struct) wolffd@0: % 'algorithm' : string ('seq' or 'batch' or 'lininit' or 'randinit') wolffd@0: % 'data_name' : string wolffd@0: % 'mask' : vector, size [dim, 1] wolffd@0: % 'neigh' : string ('gaussian' or 'cutgauss' or 'bubble' or 'ep') wolffd@0: % 'radius_ini' : scalar wolffd@0: % 'radius_fin' : scalar wolffd@0: % 'alpha_ini' : scalar wolffd@0: % 'alpha_type' : string ('linear' or 'inv' or 'power') wolffd@0: % 'trainlen' : scalar wolffd@0: % 'time' : string wolffd@0: % wolffd@0: % 'som_grid' (grid struct) : checking the values has not been implemented yet! wolffd@0: % 'lattice' : string ('rect' or 'hexa') or wolffd@0: % (sparce) matrix, size munits x munits wolffd@0: % 'shape' : string ('sheet' or 'cyl' or 'toroid') wolffd@0: % 'msize' : vector, size 1x2 wolffd@0: % 'coord' : matrix, size munits x 2 or munits x 3 wolffd@0: % 'line' : string (linespec, e.g. '-', or 'none') wolffd@0: % 'linecolor' : RGB triple or string (colorspec, e.g. 'k') or wolffd@0: % munits x munits x 3 (sparce) matrix or cell wolffd@0: % array of RGB triples wolffd@0: % 'linewidth' : scalar or munits x munits (sparce) matrix wolffd@0: % 'marker' : string (markerspec, e.g. 'o', or 'none') or wolffd@0: % munits x 1 cell or char array of these wolffd@0: % 'markersize' : scalar or munits x 1 vector wolffd@0: % 'markercolor' : RGB triple or string (colorspec, e.g. 'k') wolffd@0: % 'surf' : [], munits x 1 or munits x 3 matrix of RGB triples wolffd@0: % 'label' : [] or munits x 1 char array or wolffd@0: % munits x l cell array of strings wolffd@0: % 'labelcolor' : RGB triple or string (colorspec, e.g. 'g' or 'none') wolffd@0: % 'labelsize' : scalar wolffd@0: % wolffd@0: % OUTPUT ARGUMENTS wolffd@0: % wolffd@0: % sS (struct) the created / updated struct wolffd@0: % ok (vector) length = number of field-contents pairs, gives wolffd@0: % validity status for each pair (0=invalid, 1 otherwise) wolffd@0: % msgs (cellstr) length = number of field-contents pairs, gives wolffd@0: % error/warning message for each pair ('' if ok) wolffd@0: % wolffd@0: % EXAMPLES wolffd@0: % wolffd@0: % To create a struct: wolffd@0: % sM = som_set('som_map'); wolffd@0: % sD = som_set('som_data'); wolffd@0: % sTo = som_set('som_topol'); wolffd@0: % sTr = som_set('som_train'); wolffd@0: % sN = som_set('som_norm'); wolffd@0: % sG = som_set('som_grid'); wolffd@0: % wolffd@0: % To check the the contents of a struct: wolffd@0: % som_set(sS); wolffd@0: % [dummy,ok] = som_set(sS); wolffd@0: % [dummy,ok,msgs] = som_set(sS); wolffd@0: % wolffd@0: % To give values to fields: wolffd@0: % sTo = som_set(sTo,'msize',[10 10],'lattice','hexa','shape','toroid'); wolffd@0: % sM = som_set('som_map','codebook',rand(100,4),'topol',sTo); wolffd@0: % wolffd@0: % SEE ALSO wolffd@0: % wolffd@0: % som_info Prints information the given struct. wolffd@0: % som_map_struct Create map struct. wolffd@0: % som_data_struct Create data struct. wolffd@0: % som_topol_struct Create topology struct. wolffd@0: % som_train_struct Create training struct. wolffd@0: % som_grid Create and visualize grid struct. wolffd@0: % som_vs1to2 Conversion from version 1.0 structs to 2.0. wolffd@0: % som_vs2to1 Conversion from version 2.0 structs to 1.0. wolffd@0: wolffd@0: % Copyright (c) 1999-2000 by the SOM toolbox programming team. wolffd@0: % http://www.cis.hut.fi/projects/somtoolbox/ wolffd@0: wolffd@0: % Version 2.0beta juuso 101199 130300 wolffd@0: wolffd@0: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% wolffd@0: %% create struct if necessary wolffd@0: wolffd@0: if ischar(sS), wolffd@0: switch sS wolffd@0: case 'som_map', wolffd@0: sS=struct('type', 'som_map', ... wolffd@0: 'codebook', [], ... wolffd@0: 'topol', som_set('som_topol'), ... wolffd@0: 'labels', cell(1), ... wolffd@0: 'neigh', 'gaussian', ... wolffd@0: 'mask', [], ... wolffd@0: 'trainhist', cell(1), ... wolffd@0: 'name', '',... wolffd@0: 'comp_names', {''}, ... wolffd@0: 'comp_norm', cell(1)); wolffd@0: case 'som_data', wolffd@0: sS=struct('type', 'som_data', ... wolffd@0: 'data', [], ... wolffd@0: 'labels', cell(1), ... wolffd@0: 'name', '', ... wolffd@0: 'comp_names', {''}, ... wolffd@0: 'comp_norm', cell(1), ... wolffd@0: 'label_names', []); wolffd@0: case 'som_topol', wolffd@0: sS=struct('type', 'som_topol', ... wolffd@0: 'msize', 0, ... wolffd@0: 'lattice', 'hexa', ... wolffd@0: 'shape', 'sheet'); wolffd@0: case 'som_train', wolffd@0: sS=struct('type', 'som_train', ... wolffd@0: 'algorithm', '', ... wolffd@0: 'data_name', '', ... wolffd@0: 'neigh', 'gaussian', ... wolffd@0: 'mask', [], ... wolffd@0: 'radius_ini', NaN, ... wolffd@0: 'radius_fin', NaN, ... wolffd@0: 'alpha_ini', NaN, ... wolffd@0: 'alpha_type', 'inv', ... wolffd@0: 'trainlen', NaN, ... wolffd@0: 'time', ''); wolffd@0: case 'som_norm', wolffd@0: sS=struct('type', 'som_norm', ... wolffd@0: 'method', 'var', ... wolffd@0: 'params', [], ... wolffd@0: 'status', 'uninit'); wolffd@0: case 'som_grid', wolffd@0: sS=struct('type','som_grid',... wolffd@0: 'lattice','hexa',... wolffd@0: 'shape','sheet',... wolffd@0: 'msize',[1 1],... wolffd@0: 'coord',[],... wolffd@0: 'line','-',... wolffd@0: 'linecolor',[.9 .9 .9],... wolffd@0: 'linewidth',0.5,... wolffd@0: 'marker','o',... wolffd@0: 'markersize',6,... wolffd@0: 'markercolor','k',... wolffd@0: 'surf',[],... wolffd@0: 'label',[],... wolffd@0: 'labelcolor','g',... wolffd@0: 'labelsize',12); wolffd@0: otherwise wolffd@0: ok=0; msgs = {['Unrecognized struct type: ' sS]}; sS = []; wolffd@0: return; wolffd@0: end wolffd@0: wolffd@0: elseif isstruct(sS) & length(varargin)==0, wolffd@0: wolffd@0: % check all fields wolffd@0: fields = fieldnames(sS); wolffd@0: if ~any(strcmp('type',fields)), wolffd@0: error('The struct has no ''type'' field.'); wolffd@0: end wolffd@0: k = 0; wolffd@0: for i=1:length(fields), wolffd@0: contents = getfield(sS,fields{i}); wolffd@0: if ~strcmp(fields{i},'type'), wolffd@0: varargin{k+1} = fields{i}; wolffd@0: varargin{k+2} = contents; wolffd@0: k = k + 2; wolffd@0: else wolffd@0: if ~any(strcmp(contents, ... wolffd@0: {'som_map','som_data','som_topol','som_train','som_norm'})), wolffd@0: error(['Unknown struct type: ' contents]); wolffd@0: end wolffd@0: end wolffd@0: end wolffd@0: wolffd@0: end wolffd@0: wolffd@0: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% wolffd@0: %% set field values wolffd@0: wolffd@0: p = ceil(length(varargin)/2); wolffd@0: ok = ones(p,1); wolffd@0: msgs = cell(p,1); wolffd@0: wolffd@0: for i=1:p, wolffd@0: field = varargin{2*i-1}; wolffd@0: content = varargin{2*i}; wolffd@0: msg = ''; wolffd@0: isok = 0; wolffd@0: wolffd@0: si = size(content); wolffd@0: isscalar = (prod(si)==1); wolffd@0: isvector = (sum(si>1)==1); wolffd@0: isrowvector = (isvector & si(1)==1); wolffd@0: if isnumeric(content), wolffd@0: iscomplete = all(~isnan(content(:))); wolffd@0: ispositive = all(content(:)>0); wolffd@0: isinteger = all(content(:)==ceil(content(:))); wolffd@0: isrgb = all(content(:)>=0 & content(:)<=1) & size(content,2)==3; wolffd@0: end wolffd@0: wolffd@0: switch sS.type, wolffd@0: case 'som_map', wolffd@0: [munits dim] = size(sS.codebook); wolffd@0: switch field, wolffd@0: case 'codebook', wolffd@0: if ~isnumeric(content), wolffd@0: msg = '''codebook'' should be a numeric matrix'; wolffd@0: elseif size(content) ~= size(sS.codebook) & ~isempty(sS.codebook), wolffd@0: msg = 'New ''codebook'' must be equal in size to the old one.'; wolffd@0: elseif ~iscomplete, wolffd@0: msg = 'Map codebook must not contain NaN''s.'; wolffd@0: else wolffd@0: sS.codebook = content; isok=1; wolffd@0: end wolffd@0: case 'labels', wolffd@0: if isempty(content), wolffd@0: sS.labels = cell(munits,1); isok = 1; wolffd@0: elseif size(content,1) ~= munits, wolffd@0: msg = 'Length of labels array must be equal to the number of map units.'; wolffd@0: elseif ~iscell(content) & ~ischar(content), wolffd@0: msg = '''labels'' must be a string array or a cell array/matrix.'; wolffd@0: else wolffd@0: isok = 1; wolffd@0: if ischar(content), content = cellstr(content); wolffd@0: elseif ~iscellstr(content), wolffd@0: l = prod(size(content)); wolffd@0: for j=1:l, wolffd@0: if ischar(content{j}), wolffd@0: if ~isempty(content{j}), wolffd@0: msg = 'Invalid ''labels'' array.'; wolffd@0: isok = 0; wolffd@0: break; wolffd@0: else wolffd@0: content{j} = ''; wolffd@0: end wolffd@0: end wolffd@0: end wolffd@0: end wolffd@0: if isok, sS.labels = content; end wolffd@0: end wolffd@0: case 'topol', wolffd@0: if ~isstruct(content), wolffd@0: msg = '''topol'' should be a topology struct.'; wolffd@0: elseif ~isfield(content,'msize') | ... wolffd@0: ~isfield(content,'lattice') | ... wolffd@0: ~isfield(content,'shape'), wolffd@0: msg = '''topol'' is not a valid topology struct.'; wolffd@0: elseif prod(content.msize) ~= munits, wolffd@0: msg = '''topol''.msize does not match the number of map units.'; wolffd@0: else wolffd@0: sS.topol = content; isok = 1; wolffd@0: end wolffd@0: case 'msize', wolffd@0: if ~isnumeric(content) | ~isvector | ~ispositive | ~isinteger, wolffd@0: msg = '''msize'' should be a vector with positive integer elements.'; wolffd@0: elseif prod(content) ~= munits, wolffd@0: msg = '''msize'' does not match the map size.'; wolffd@0: else wolffd@0: sS.topol.msize = content; isok = 1; wolffd@0: end wolffd@0: case 'lattice', wolffd@0: if ~ischar(content), wolffd@0: msg = '''lattice'' should be a string'; wolffd@0: elseif ~strcmp(content,'rect') & ~strcmp(content,'hexa'), wolffd@0: msg = ['Unknown lattice type: ' content]; wolffd@0: sS.topol.lattice = content; isok = 1; wolffd@0: else wolffd@0: sS.topol.lattice = content; isok = 1; wolffd@0: end wolffd@0: case 'shape', wolffd@0: if ~ischar(content), wolffd@0: msg = '''shape'' should be a string'; wolffd@0: elseif ~strcmp(content,'sheet') & ~strcmp(content,'cyl') & ... wolffd@0: ~strcmp(content,'toroid'), wolffd@0: msg = ['Unknown shape type:' content]; wolffd@0: sS.topol.shape = content; isok = 1; wolffd@0: else wolffd@0: sS.topol.shape = content; isok = 1; wolffd@0: end wolffd@0: case 'neigh', wolffd@0: if ~ischar(content), wolffd@0: msg = '''neigh'' should be a string'; wolffd@0: elseif ~strcmp(content,'gaussian') & ~strcmp(content,'ep') & ... wolffd@0: ~strcmp(content,'cutgauss') & ~strcmp(content,'bubble'), wolffd@0: msg = ['Unknown neighborhood function: ' content]; wolffd@0: sS.neigh = content; isok = 1; wolffd@0: else wolffd@0: sS.neigh = content; isok = 1; wolffd@0: end wolffd@0: case 'mask', wolffd@0: if size(content,1) == 1, content = content'; end wolffd@0: if ~isnumeric(content) | size(content) ~= [dim 1], wolffd@0: msg = '''mask'' should be a column vector (size dim x 1).'; wolffd@0: else wolffd@0: sS.mask = content; isok = 1; wolffd@0: end wolffd@0: case 'name', wolffd@0: if ~ischar(content), wolffd@0: msg = '''name'' should be a string.'; wolffd@0: else wolffd@0: sS.name = content; isok = 1; wolffd@0: end wolffd@0: case 'comp_names', wolffd@0: if ~iscell(content) & ~ischar(content), wolffd@0: msg = '''comp_names'' should be a cell string or a string array.'; wolffd@0: elseif length(content) ~= dim, wolffd@0: msg = 'Length of ''comp_names'' should be equal to dim.'; wolffd@0: else wolffd@0: if ischar(content), content = cellstr(content); end wolffd@0: if size(content,1)==1, content = content'; end wolffd@0: sS.comp_names = content; wolffd@0: isok = 1; wolffd@0: end wolffd@0: case 'comp_norm', wolffd@0: if ~iscell(content) & length(content)>0, wolffd@0: msg = '''comp_norm'' should be a cell array.'; wolffd@0: elseif length(content) ~= dim, wolffd@0: msg = 'Length of ''comp_norm'' should be equal to dim.'; wolffd@0: else wolffd@0: isok = 1; wolffd@0: for j=1:length(content), wolffd@0: if ~isempty(content{j}) & (~isfield(content{j}(1),'type') | ... wolffd@0: ~strcmp(content{j}(1).type,'som_norm')), wolffd@0: msg = 'Each cell in ''comp_norm'' should be either empty or type ''som_norm''.'; wolffd@0: isok = 0; wolffd@0: break; wolffd@0: end wolffd@0: end wolffd@0: if isok, sS.comp_norm = content; end wolffd@0: end wolffd@0: case 'trainhist', wolffd@0: if ~isstruct(content) & ~isempty(content), wolffd@0: msg = '''trainhist'' should be a struct array or empty.'; wolffd@0: else wolffd@0: isok = 1; wolffd@0: for j=1:length(content), wolffd@0: if ~isfield(content(j),'type') | ~strcmp(content(j).type,'som_train'), wolffd@0: msg = 'Each cell in ''trainhist'' should be of type ''som_train''.'; wolffd@0: isok = 0; wolffd@0: break; wolffd@0: end wolffd@0: end wolffd@0: if isok, sS.trainhist = content; end wolffd@0: end wolffd@0: otherwise, wolffd@0: msg = ['Invalid field for map struct: ' field]; wolffd@0: end wolffd@0: wolffd@0: case 'som_data', wolffd@0: [dlen dim] = size(sS.data); wolffd@0: switch field, wolffd@0: case 'data', wolffd@0: [dummy dim2] = size(content); wolffd@0: if prod(si)==0, wolffd@0: msg = '''data'' is empty'; wolffd@0: elseif ~isnumeric(content), wolffd@0: msg = '''data'' should be numeric matrix.'; wolffd@0: elseif dim ~= dim2 & ~isempty(sS.data), wolffd@0: msg = 'New ''data'' must have the same dimension as old one.'; wolffd@0: else wolffd@0: sS.data = content; isok = 1; wolffd@0: end wolffd@0: case 'labels', wolffd@0: if isempty(content), wolffd@0: sS.labels = cell(dlen,1); isok = 1; wolffd@0: elseif size(content,1) ~= dlen, wolffd@0: msg = 'Length of ''labels'' must be equal to the number of data vectors.'; wolffd@0: elseif ~iscell(content) & ~ischar(content), wolffd@0: msg = '''labels'' must be a string array or a cell array/matrix.'; wolffd@0: else wolffd@0: isok = 1; wolffd@0: if ischar(content), content = cellstr(content); wolffd@0: elseif ~iscellstr(content), wolffd@0: l = prod(size(content)); wolffd@0: for j=1:l, wolffd@0: if ~ischar(content{j}), wolffd@0: if ~isempty(content{j}), wolffd@0: msg = 'Invalid ''labels'' array.'; wolffd@0: isok = 0; j wolffd@0: break; wolffd@0: else wolffd@0: content{j} = ''; wolffd@0: end wolffd@0: end wolffd@0: end wolffd@0: end wolffd@0: if isok, sS.labels = content; end wolffd@0: end wolffd@0: case 'name', wolffd@0: if ~ischar(content), wolffd@0: msg = '''name'' should be a string.'; wolffd@0: else wolffd@0: sS.name = content; isok = 1; wolffd@0: end wolffd@0: case 'comp_names', wolffd@0: if ~iscell(content) & ~ischar(content), wolffd@0: msg = '''comp_names'' should be a cell string or a string array.'; wolffd@0: elseif length(content) ~= dim, wolffd@0: msg = 'Length of ''comp_names'' should be equal to dim.'; wolffd@0: else wolffd@0: if ischar(content), content = cellstr(content); end wolffd@0: if size(content,1)==1, content = content'; end wolffd@0: sS.comp_names = content; wolffd@0: isok = 1; wolffd@0: end wolffd@0: case 'comp_norm', wolffd@0: if ~iscell(content) & length(content)>0, wolffd@0: msg = '''comp_norm'' should be a cell array.'; wolffd@0: elseif length(content) ~= dim, wolffd@0: msg = 'Length of ''comp_norm'' should be equal to dim.'; wolffd@0: else wolffd@0: isok = 1; wolffd@0: for j=1:length(content), wolffd@0: if ~isempty(content{j}) & (~isfield(content{j}(1),'type') | ... wolffd@0: ~strcmp(content{j}(1).type,'som_norm')), wolffd@0: msg = 'Each cell in ''comp_norm'' should be either empty or type ''som_norm''.'; wolffd@0: isok = 0; wolffd@0: break; wolffd@0: end wolffd@0: end wolffd@0: if isok, sS.comp_norm = content; end wolffd@0: end wolffd@0: case 'label_names', wolffd@0: if ~iscell(content) & ~ischar(content) & ~isempty(content), wolffd@0: msg = ['''label_names'' should be a cell string, a string array or' ... wolffd@0: ' empty.']; wolffd@0: else wolffd@0: if ~isempty(content), wolffd@0: if ischar(content), content = cellstr(content); end wolffd@0: if size(content,1)==1, content = content'; end wolffd@0: end wolffd@0: sS.label_names = content; wolffd@0: isok = 1; wolffd@0: end wolffd@0: otherwise, wolffd@0: msg = ['Invalid field for data struct: ' field]; wolffd@0: end wolffd@0: wolffd@0: case 'som_topol', wolffd@0: switch field, wolffd@0: case 'msize', wolffd@0: if ~isnumeric(content) | ~isvector | ~ispositive | ~isinteger, wolffd@0: msg = '''msize'' should be a vector with positive integer elements.'; wolffd@0: else wolffd@0: sS.msize = content; isok=1; wolffd@0: end wolffd@0: case 'lattice', wolffd@0: if ~ischar(content), wolffd@0: msg = '''lattice'' should be a string'; wolffd@0: elseif ~strcmp(content,'rect') & ~strcmp(content,'hexa'), wolffd@0: msg = ['Unknown lattice type: ' content]; wolffd@0: sS.lattice = content; isok = 1; wolffd@0: else wolffd@0: sS.lattice = content; isok = 1; wolffd@0: end wolffd@0: case 'shape', wolffd@0: if ~ischar(content), wolffd@0: msg = '''shape'' should be a string'; wolffd@0: elseif ~strcmp(content,'sheet') & ~strcmp(content,'cyl') & ... wolffd@0: ~strcmp(content,'toroid'), wolffd@0: msg = ['Unknown shape type: ' content]; wolffd@0: sS.shape = content; isok = 1; wolffd@0: else wolffd@0: sS.shape = content; isok = 1; wolffd@0: end wolffd@0: otherwise, wolffd@0: msg = ['Invalid field for topology struct: ' field]; wolffd@0: end wolffd@0: wolffd@0: case 'som_train', wolffd@0: switch field, wolffd@0: case 'algorithm', wolffd@0: if ~ischar(content), wolffd@0: msg = '''algorithm'' should be a string.'; wolffd@0: else wolffd@0: sS.algorithm = content; isok = 1; wolffd@0: end wolffd@0: case 'data_name', wolffd@0: if ~ischar(content), wolffd@0: msg = '''data_name'' should be a string'; wolffd@0: else wolffd@0: sS.data_name = content; isok = 1; wolffd@0: end wolffd@0: case 'neigh', wolffd@0: if ~ischar(content), wolffd@0: msg = '''neigh'' should be a string'; wolffd@0: elseif ~isempty(content) & ~strcmp(content,'gaussian') & ~strcmp(content,'ep') & ... wolffd@0: ~strcmp(content,'cutgauss') & ~strcmp(content,'bubble'), wolffd@0: msg = ['Unknown neighborhood function: ' content]; wolffd@0: sS.neigh = content; isok = 1; wolffd@0: else wolffd@0: sS.neigh = content; isok = 1; wolffd@0: end wolffd@0: case 'mask', wolffd@0: if size(content,1) == 1, content = content'; end wolffd@0: dim = size(content,1); %[munits dim] = size(sS.data); wolffd@0: if ~isnumeric(content) | size(content) ~= [dim 1], wolffd@0: msg = '''mask'' should be a column vector (size dim x 1).'; wolffd@0: else wolffd@0: sS.mask = content; isok = 1; wolffd@0: end wolffd@0: case 'radius_ini', wolffd@0: if ~isnumeric(content) | ~isscalar, wolffd@0: msg = '''radius_ini'' should be a scalar.'; wolffd@0: else wolffd@0: sS.radius_ini = content; isok = 1; wolffd@0: end wolffd@0: case 'radius_fin', wolffd@0: if ~isnumeric(content) | ~isscalar, wolffd@0: msg = '''radius_fin'' should be a scalar.'; wolffd@0: else wolffd@0: sS.radius_fin = content; isok = 1; wolffd@0: end wolffd@0: case 'alpha_ini', wolffd@0: if ~isnumeric(content) | ~isscalar, wolffd@0: msg = '''alpha_ini'' should be a scalar.'; wolffd@0: else wolffd@0: sS.alpha_ini = content; isok = 1; wolffd@0: end wolffd@0: case 'alpha_type', wolffd@0: if ~ischar(content), wolffd@0: msg = '''alpha_type'' should be a string'; wolffd@0: elseif ~strcmp(content,'linear') & ~strcmp(content,'inv') & ... wolffd@0: ~strcmp(content,'power') & ~strcmp(content,'constant') & ~strcmp(content,''), wolffd@0: msg = ['Unknown alpha type: ' content]; wolffd@0: sS.alpha_type = content; isok = 1; wolffd@0: else wolffd@0: sS.alpha_type = content; isok = 1; wolffd@0: end wolffd@0: case 'trainlen', wolffd@0: if ~isnumeric(content) | ~isscalar, wolffd@0: msg = '''trainlen'' should be a scalar.'; wolffd@0: else wolffd@0: sS.trainlen = content; isok = 1; wolffd@0: end wolffd@0: case 'time', wolffd@0: if ~ischar(content), wolffd@0: msg = '''time'' should be a string'; wolffd@0: else wolffd@0: sS.time = content; isok = 1; wolffd@0: end wolffd@0: otherwise, wolffd@0: msg = ['Invalid field for train struct: ' field]; wolffd@0: end wolffd@0: wolffd@0: case 'som_norm', wolffd@0: switch field, wolffd@0: case 'method', wolffd@0: if ~ischar(field), wolffd@0: msg = '''method'' should be a string.'; wolffd@0: else wolffd@0: sS.method = content; isok = 1; wolffd@0: end wolffd@0: case 'params', wolffd@0: sS.params = content; isok = 1; wolffd@0: case 'status', wolffd@0: if ~ischar(content), wolffd@0: msg = '''status'' should be a string'; wolffd@0: elseif ~strcmp(content,'done') & ~strcmp(content,'undone') & ... wolffd@0: ~strcmp(content,'uninit'), wolffd@0: msg = ['Unknown status type: ' content]; wolffd@0: sS.status = content; isok = 1; wolffd@0: else wolffd@0: sS.status = content; isok = 1; wolffd@0: end wolffd@0: otherwise, wolffd@0: msg = ['Invalid field for normalization struct: ' field]; wolffd@0: end wolffd@0: wolffd@0: case 'som_grid', wolffd@0: if any(strcmp(field,{'lattice', 'shape', 'msize', 'coord',... wolffd@0: 'line', 'linecolor', 'linewidth', ... wolffd@0: 'marker', 'markersize', 'markercolor', 'surf', ... wolffd@0: 'label', 'labelcolor', 'labelsize'})), wolffd@0: warning('No checking done on field identifier or content.'); wolffd@0: sS = setfield(sS,field,content); wolffd@0: isok = 1; wolffd@0: else wolffd@0: msg = ['Invalid field for grid struct: ' field]; wolffd@0: end wolffd@0: wolffd@0: otherwise, wolffd@0: error('Unrecognized structure.'); wolffd@0: wolffd@0: end wolffd@0: wolffd@0: msgs{i} = msg; wolffd@0: ok(i) = isok; wolffd@0: wolffd@0: end wolffd@0: wolffd@0: wolffd@0: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% wolffd@0: %% return wolffd@0: wolffd@0: if nargout < 2, wolffd@0: for i=1:p, wolffd@0: if ~isempty(msgs{i}), wolffd@0: if ~ok(i), fprintf(1,'[Error! '); wolffd@0: else fprintf(1,'[Notice '); wolffd@0: end wolffd@0: fprintf(1,'in setting %s] ',varargin{2*i-1}); wolffd@0: fprintf(1,'%s\n',msgs{i}); wolffd@0: end wolffd@0: end wolffd@0: end wolffd@0: wolffd@0: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% wolffd@0: wolffd@0: wolffd@0: