v_paramsetch

PURPOSE ^

V_PARAMSETCH update and check parameter values p=(d,q,m,c,t)

SYNOPSIS ^

function p=v_paramsetch(d,q,m,c,t)

DESCRIPTION ^

V_PARAMSETCH update and check parameter values p=(d,q,m,c,t)
 Usage: (1) function x=func(y,q)
            d=struct('a',1,'b',2,'c',3);   % default parameters
            p=v_paramsetch(d,q);           % update selected parameters

        (2) function x=func(y,q)
            d=struct('a',1,'b',2,'c',3);   % default parameters
            c={'p.a>0 && p.a<5','Message 1';'p.b>0','b must be positive'};
            p=v_paramsetch(d,q,'E',c);     % check parameter ranges

        (3) t={'a','description of parameter a';'c','and of parameter c'}
            p=v_paramsetch(d,q,'l',c,t);   % list values with optional descrpitions
                                           % '-','=','*','+' indicates default, unchanged, updated and new fields

  Inputs:
       d  default parameter structure
       q  new parameter values either a struct or alternatively matrix with
          each row being the value of the variables in the same order as the
          fields of d. If q is a matrix then all updated values will be row
          vectors with the same number of elements.
       m  mode string: any combination of the following
           'a' include additional fields in q that are not in d
           'A' additional fields in q constitute an error
           'e' print errors (but don't exit unless 'E' given as well)
           'E' exit if there are any errors
           'l' list fields and their values (default if no output)
       c  cell array with parameter checking conditions (use p for structure name) and error
               message; one row per check. All results of command c{*,1) must be true.
               e.g. {'p.a>3' 'parameter a must be > 3'; 'p.b<2' 'parameter b must be < 2'}
       t  cell array with descriptive text for each field in a new row. Either in
          the form t(:,*)={'field' 'description'} or a single column of
          descriptions in the same order as the fields of d

 Outputs:
       p  output parameter structure

 Bugs/Suggestions:
 (1) When printing include "=" to show an updated parameter has not changed (might waste a lot of computation)
 (2) If input d has few entries, it would be faster to loop through d rather than q

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SOURCE CODE ^

0001 function p=v_paramsetch(d,q,m,c,t)
0002 %V_PARAMSETCH update and check parameter values p=(d,q,m,c,t)
0003 % Usage: (1) function x=func(y,q)
0004 %            d=struct('a',1,'b',2,'c',3);   % default parameters
0005 %            p=v_paramsetch(d,q);           % update selected parameters
0006 %
0007 %        (2) function x=func(y,q)
0008 %            d=struct('a',1,'b',2,'c',3);   % default parameters
0009 %            c={'p.a>0 && p.a<5','Message 1';'p.b>0','b must be positive'};
0010 %            p=v_paramsetch(d,q,'E',c);     % check parameter ranges
0011 %
0012 %        (3) t={'a','description of parameter a';'c','and of parameter c'}
0013 %            p=v_paramsetch(d,q,'l',c,t);   % list values with optional descrpitions
0014 %                                           % '-','=','*','+' indicates default, unchanged, updated and new fields
0015 %
0016 %  Inputs:
0017 %       d  default parameter structure
0018 %       q  new parameter values either a struct or alternatively matrix with
0019 %          each row being the value of the variables in the same order as the
0020 %          fields of d. If q is a matrix then all updated values will be row
0021 %          vectors with the same number of elements.
0022 %       m  mode string: any combination of the following
0023 %           'a' include additional fields in q that are not in d
0024 %           'A' additional fields in q constitute an error
0025 %           'e' print errors (but don't exit unless 'E' given as well)
0026 %           'E' exit if there are any errors
0027 %           'l' list fields and their values (default if no output)
0028 %       c  cell array with parameter checking conditions (use p for structure name) and error
0029 %               message; one row per check. All results of command c{*,1) must be true.
0030 %               e.g. {'p.a>3' 'parameter a must be > 3'; 'p.b<2' 'parameter b must be < 2'}
0031 %       t  cell array with descriptive text for each field in a new row. Either in
0032 %          the form t(:,*)={'field' 'description'} or a single column of
0033 %          descriptions in the same order as the fields of d
0034 %
0035 % Outputs:
0036 %       p  output parameter structure
0037 %
0038 % Bugs/Suggestions:
0039 % (1) When printing include "=" to show an updated parameter has not changed (might waste a lot of computation)
0040 % (2) If input d has few entries, it would be faster to loop through d rather than q
0041 
0042 %      Copyright (C) Mike Brookes 2017
0043 %      Version: $Id: v_paramsetch.m 10865 2018-09-21 17:22:45Z dmb $
0044 %
0045 %   VOICEBOX is a MATLAB toolbox for speech processing.
0046 %   Home page: http://www.ee.ic.ac.uk/hp/staff/dmb/voicebox/voicebox.html
0047 %
0048 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
0049 %   This program is free software; you can redistribute it and/or modify
0050 %   it under the terms of the GNU General Public License as published by
0051 %   the Free Software Foundation; either version 2 of the License, or
0052 %   (at your option) any later version.
0053 %
0054 %   This program is distributed in the hope that it will be useful,
0055 %   but WITHOUT ANY WARRANTY; without even the implied warranty of
0056 %   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0057 %   GNU General Public License for more details.
0058 %
0059 %   You can obtain a copy of the GNU General Public License from
0060 %   http://www.gnu.org/copyleft/gpl.html or by writing to
0061 %   Free Software Foundation, Inc.,675 Mass Ave, Cambridge, MA 02139, USA.
0062 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
0063 p=d;                                            % initialize output structure to the default values
0064 numerr=0;                                       % initialize error count
0065 dn=fieldnames(d);                               % list of parameter default fields
0066 ndn=length(dn);                                 % number of default parameter fields
0067 nq=0;                                           % default value for size(q,1)
0068 % handle common case efficiently with 1 or 2 input arguments and an output argument
0069 if nargin<=2 && nargout>0
0070     if nargin==2 && numel(q)>0                  % if update argument exists
0071         if isstruct(q)                          % if update argument is a structure
0072             qn=fieldnames(q);                   % field names to update
0073             nq=length(qn);                      % number of fields to update
0074             if nq<ndn                           % relatively few entries in q
0075                 for i=1:nq                      % loop through list of fields to update
0076                     fi=qn{i};                   % get field name to update
0077                     if isfield(p,fi);           % is this an existing field ?
0078                         p.(fi)=q.(fi);          % set new field value
0079                     end
0080                 end
0081             else                                % more entries in q than in d
0082                 for i=1:ndn                     % loop through list of existing fields
0083                     fi=dn{i};                   % get field name to potentially update
0084                     if isfield(q,fi);           % is there a replacement value for this field ?
0085                         p.(fi)=q.(fi);          % set new field value
0086                     end
0087                 end
0088             end
0089         else                                    % else update argument is a matrix
0090             nq=size(q,1);                       % number of fields to update
0091             for i=1:min(nq,ndn)
0092                 p.(dn{i})=q(i,:);
0093             end
0094         end
0095     end
0096 else                                            % we have >2 arguments or else no output arguments
0097     % sort out input arguments
0098     if nargin<5
0099         t={'' ''};                              % define an empty description array
0100         if nargin<4
0101             c=cell(0,2);                        % define an empty check condition array
0102             if nargin<3
0103                 m='';                           % define an empty check mode string
0104             end
0105         end
0106     end
0107     % now update the selected fields
0108     adderr=any(m=='A');                         % new fields constitute an error
0109     addnew=any(m=='a');                         % new fields should be added into p
0110     printerr=any(m=='e');                       % print error messages
0111     numerr=0;                                   % initialize count of errors
0112     if numel(q)>0                               % if update argument is non-empty
0113         if isstruct(q)                          % if update argument is a structure
0114             qn=fieldnames(q);                   % field names to update
0115             nq=length(qn);                      % number of fields to update
0116             if addnew                           % we are including all fields in q(n)
0117                 for i=1:nq                      % loop through list of fields to update
0118                     fi=qn{i};                   % get field name to update
0119                     p.(fi)=q.(fi);              % set new field value
0120                 end
0121             else
0122                 for i=1:length(qn)              % loop through list of fields to update
0123                     fi=qn{i};                   % get field name to update
0124                     if isfield(p,fi)            % if this is an existing field ...
0125                         p.(fi)=q.(fi);          % set new field value
0126                     elseif adderr               % if this is an non-existant field ...
0127                         numerr=numerr+1;        % increment error count
0128                         if printerr
0129                             fprintf(2,'Unknown parameter: %s\n',fi);
0130                         end
0131                     end
0132                 end
0133             end
0134         else                                    % else update argument is a matrix
0135             nq=size(q,1);                       % number of fields to update
0136             for i=1:min(nq,ndn)
0137                 p.(dn{i})=q(i,:);
0138             end
0139             if nq>ndn
0140                 numerr=numerr+nq-ndn;
0141                 if printerr
0142                     if  nq==ndn+1
0143                         fprintf(2,'1 extra parameter specified\n');
0144                     else
0145                         fprintf(2,'%d extra parameters specified\n',nq-ndn);
0146                     end
0147                 end
0148             end
0149         end
0150     end
0151     % Apply parameter checks
0152     if numel(c)>0                               % check if any checks are specified
0153         for i=1:size(c,1)                       % one check per row of c
0154             if ~all(eval(c{i,1}),'all')               % perform the check
0155                 numerr=numerr+1;
0156                 if size(c,1)==1
0157                     fprintf(2,'Parameter check failed: %s\n',c{i});
0158                 else
0159                     fprintf(2,c{i,2});
0160                     fprintf(2,'\n');
0161                 end
0162             end
0163         end
0164     end
0165     % print out a list of the parameters if requested
0166     if ~nargout || any(m=='l')
0167            fprintf('Key: - default value, = updated to default value, * updated to new value, + additional field\n');
0168         pn=fieldnames(p);
0169         nf=length(pn);                          % length of updated structure
0170         st=size(t);
0171         for i=1:nf                              % loop through field in output p
0172             fi=pn{i};                           % field name
0173             vi=p.(fi);                          % field value
0174             if i>ndn                            % if this field was added to structure d
0175                 cat='+';                        % new field
0176             else
0177                 if nq>0 && isstruct(q)          % if update argument is a structure
0178                     if isfield(q,fi)            % was this field updated ?
0179                         if isequal(p.(fi),d.(fi))
0180                             cat='=';            % updated to existing value
0181                         else
0182                             cat='*';            % updated to new value
0183                         end
0184                     else                        % not an updated field
0185                         cat='-';                % not updated
0186                     end
0187                 else                            % if update argument is a matrix
0188                     if i>nq                     % beyond list of updated fields
0189                         cat='-';                % not updated
0190                     else
0191                         if isequal(p.(fi),d.(fi))
0192                             cat='=';            % updated to existing value
0193                         else
0194                             cat='*';            % updated to new value
0195                         end
0196                     end
0197                 end
0198             end
0199             if st(2)>1                          % description are field-based
0200                 jti=find(strcmp(fi,t(:,1)),1);  % find description for this field
0201                 if ~isempty(jti)
0202                     jti=t{jti,2};               % description string
0203                 end
0204             elseif i<=st(1)
0205                 jti=t{i,1};                     % description string
0206             else
0207                 jti=[];                         % empty description
0208             end
0209             if isnumeric(vi) && length(vi)==numel(vi) && isreal(vi) % can print vector on one line
0210                 fit=fi;
0211                 if size(vi,1)>1
0212                     fit=[fi '''']; % transposed vector
0213                 end
0214                 fprintf('%3d%c %s:',i,cat,fit);
0215                 fprintf(' %g',vi);
0216                 if isempty(jti)
0217                     fprintf('\n');
0218                 else
0219                     fprintf(' = %s\n',jti);
0220                 end
0221             elseif numel(vi)<6
0222                 fprintf('%3d%c %s:',i,cat,fi);
0223                 if isempty(jti)
0224                     fprintf('\n');
0225                 else
0226                     fprintf(' %s:\n',jti);
0227                 end
0228                 disp(vi);
0229             else
0230                 fprintf('%3d%c %s: [large]',i,cat,fi);
0231                 if isempty(jti)
0232                     fprintf('\n');
0233                 else
0234                     fprintf(' = %s\n',jti);
0235                 end
0236             end
0237         end
0238     end
0239     if numerr>0 && any(m=='E')
0240         error('%d error%c in parameter specification',numerr,(' '+(numerr>1)*('s'-' ')));
0241     end
0242 end

Generated by m2html © 2003