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