TEAP (Toolbox for Emotion Analysis using Physiological Signals) doc
finputcheck.m
Go to the documentation of this file.
1 % finputcheck() - check Matlab function {'key','value'} input argument pairs
2 %
3 % Usage: >> result = finputcheck( varargin, fieldlist );
4 % >> [result varargin] = finputcheck( varargin, fieldlist, ...
5 % callingfunc, mode, verbose );
6 % Input:
7 % varargin - Cell array 'varargin' argument from a function call using 'key',
8 % 'value' argument pairs. See Matlab function 'varargin'.
9 % May also be a structure such as struct(varargin{:})
10 % fieldlist - A 4-column cell array, one row per 'key'. The first
11 % column contains the key string, the second its type(s),
12 % the third the accepted value range, and the fourth the
13 % default value. Allowed types are 'boolean', 'integer',
14 % 'real', 'string', 'cell' or 'struct'. For example,
15 % {'key1' 'string' { 'string1' 'string2' } 'defaultval_key1'}
16 % {'key2' {'real' 'integer'} { minint maxint } 'defaultval_key2'}
17 % callingfunc - Calling function name for error messages. {default: none}.
18 % mode - ['ignore'|'error'] ignore keywords that are either not specified
19 % in the fieldlist cell array or generate an error.
20 % {default: 'error'}.
21 % verbose - ['verbose', 'quiet'] print information. Default: 'verbose'.
22 %
23 % Outputs:
24 % result - If no error, structure with 'key' as fields and 'value' as
25 % content. If error this output contain the string error.
26 % varargin - residual varagin containing unrecognized input arguments.
27 % Requires mode 'ignore' above.
28 %
29 % Note: In case of error, a string is returned containing the error message
30 % instead of a structure.
31 %
32 % Example (insert the following at the beginning of your function):
33 % result = finputcheck(varargin, ...
34 % { 'title' 'string' [] ''; ...
35 % 'percent' 'real' [0 1] 1 ; ...
36 % 'elecamp' 'integer' [1:10] [] });
37 % if isstr(result)
38 % error(result);
39 % end
40 %
41 % Note:
42 % The 'title' argument should be a string. {no default value}
43 % The 'percent' argument should be a real number between 0 and 1. {default: 1}
44 % The 'elecamp' argument should be an integer between 1 and 10 (inclusive).
45 %
46 % Now 'g.title' will contain the title arg (if any, else the default ''), etc.
47 %
48 % Author: Arnaud Delorme, CNL / Salk Institute, 10 July 2002
49 
50 % Copyright (C) Arnaud Delorme, CNL / Salk Institute, 10 July 2002, arno@salk.edu
51 %
52 % This program is free software; you can redistribute it and/or modify
53 % it under the terms of the GNU General Public License as published by
54 % the Free Software Foundation; either version 2 of the License, or
55 % (at your option) any later version.
56 %
57 % This program is distributed in the hope that it will be useful,
58 % but WITHOUT ANY WARRANTY; without even the implied warranty of
59 % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
60 % GNU General Public License for more details.
61 %
62 % You should have received a copy of the GNU General Public License
63 % along with this program; if not, write to the Free Software
64 % Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
65 
66 function [g, varargnew] = finputcheck( vararg, fieldlist, callfunc, mode, verbose )
67 
68  if nargin < 2
69  help finputcheck;
70  return;
71  end;
72  if nargin < 3
73  callfunc = '';
74  else
75  callfunc = [callfunc ' ' ];
76  end;
77  if nargin < 4
78  mode = 'do not ignore';
79  end;
80  if nargin < 5
81  verbose = 'verbose';
82  end;
83  NAME = 1;
84  TYPE = 2;
85  VALS = 3;
86  DEF = 4;
87  SIZE = 5;
88 
89  varargnew = {};
90  % create structure
91  % ----------------
92  if ~isempty(vararg)
93  if isstruct(vararg)
94  g = vararg;
95  else
96  for index=1:length(vararg)
97  if iscell(vararg{index})
98  vararg{index} = {vararg{index}};
99  end;
100  end;
101  try
102  g = struct(vararg{:});
103  catch
104  vararg = removedup(vararg, verbose);
105  try
106  g = struct(vararg{:});
107  catch
108  g = [ callfunc 'error: bad ''key'', ''val'' sequence' ]; return;
109  end;
110  end;
111  end;
112  else
113  g = [];
114  end;
115 
116  for index = 1:size(fieldlist,NAME)
117  % check if present
118  % ----------------
119  if ~isfield(g, fieldlist{index, NAME})
120  g = setfield( g, fieldlist{index, NAME}, fieldlist{index, DEF});
121  end;
122  tmpval = getfield( g, {1}, fieldlist{index, NAME});
123 
124  % check type
125  % ----------
126  if ~iscell( fieldlist{index, TYPE} )
127  res = fieldtest( fieldlist{index, NAME}, fieldlist{index, TYPE}, ...
128  fieldlist{index, VALS}, tmpval, callfunc );
129  if isstr(res), g = res; return; end;
130  else
131  testres = 0;
132  tmplist = fieldlist;
133  for it = 1:length( fieldlist{index, TYPE} )
134  if ~iscell(fieldlist{index, VALS})
135  res{it} = fieldtest( fieldlist{index, NAME}, fieldlist{index, TYPE}{it}, ...
136  fieldlist{index, VALS}, tmpval, callfunc );
137  else res{it} = fieldtest( fieldlist{index, NAME}, fieldlist{index, TYPE}{it}, ...
138  fieldlist{index, VALS}{it}, tmpval, callfunc );
139  end;
140  if ~isstr(res{it}), testres = 1; end;
141  end;
142  if testres == 0,
143  g = res{1};
144  for tmpi = 2:length(res)
145  g = [ g 10 'or ' res{tmpi} ];
146  end;
147  return;
148  end;
149  end;
150  end;
151 
152  % check if fields are defined
153  % ---------------------------
154  allfields = fieldnames(g);
155  for index=1:length(allfields)
156  if isempty(strmatch(allfields{index}, fieldlist(:, 1)', 'exact'))
157  if ~strcmpi(mode, 'ignore')
158  g = [ callfunc 'error: undefined argument ''' allfields{index} '''']; return;
159  end;
160  varargnew{end+1} = allfields{index};
161  varargnew{end+1} = getfield(g, {1}, allfields{index});
162  end;
163  end;
164 
165 
166 function g = fieldtest( fieldname, fieldtype, fieldval, tmpval, callfunc );
167  NAME = 1;
168  TYPE = 2;
169  VALS = 3;
170  DEF = 4;
171  SIZE = 5;
172  g = [];
173 
174  switch fieldtype
175  case { 'integer' 'real' 'boolean' 'float' },
176  if ~isnumeric(tmpval) && ~islogical(tmpval)
177  g = [ callfunc 'error: argument ''' fieldname ''' must be numeric' ]; return;
178  end;
179  if strcmpi(fieldtype, 'boolean')
180  if tmpval ~=0 && tmpval ~= 1
181  g = [ callfunc 'error: argument ''' fieldname ''' must be 0 or 1' ]; return;
182  end;
183  else
184  if strcmpi(fieldtype, 'integer')
185  if ~isempty(fieldval)
186  if (any(isnan(tmpval(:))) && ~any(isnan(fieldval))) ...
187  && (~ismember(tmpval, fieldval))
188  g = [ callfunc 'error: wrong value for argument ''' fieldname '''' ]; return;
189  end;
190  end;
191  else % real or float
192  if ~isempty(fieldval) && ~isempty(tmpval)
193  if any(tmpval < fieldval(1)) || any(tmpval > fieldval(2))
194  g = [ callfunc 'error: value out of range for argument ''' fieldname '''' ]; return;
195  end;
196  end;
197  end;
198  end;
199 
200 
201  case 'string'
202  if ~isstr(tmpval)
203  g = [ callfunc 'error: argument ''' fieldname ''' must be a string' ]; return;
204  end;
205  if ~isempty(fieldval)
206  if isempty(strmatch(lower(tmpval), lower(fieldval), 'exact'))
207  g = [ callfunc 'error: wrong value for argument ''' fieldname '''' ]; return;
208  end;
209  end;
210 
211 
212  case 'cell'
213  if ~iscell(tmpval)
214  g = [ callfunc 'error: argument ''' fieldname ''' must be a cell array' ]; return;
215  end;
216 
217 
218  case 'struct'
219  if ~isstruct(tmpval)
220  g = [ callfunc 'error: argument ''' fieldname ''' must be a structure' ]; return;
221  end;
222 
223 
224  case '';
225  otherwise, error([ 'finputcheck error: unrecognized type ''' fieldname '''' ]);
226  end;
227 
228 % remove duplicates in the list of parameters
229 % -------------------------------------------
230 function cella = removedup(cella, verbose)
231 % make sure if all the values passed to unique() are strings, if not, exist
232 %try
233  [tmp indices] = unique(cella(1:2:end));
234  if length(tmp) ~= length(cella)/2
235  myfprintf(verbose,'Note: duplicate ''key'', ''val'' parameter(s), keeping the last one(s)\n');
236  end;
237  cella = cella(sort(union(indices*2-1, indices*2)));
238 %catch
239  % some elements of cella were not string
240 % error('some ''key'' values are not string.');
241 %end;
242 
243 function myfprintf(verbose, varargin)
244 
245 if strcmpi(verbose, 'verbose')
246  fprintf(varargin{:});
247 end;
fieldtest
function fieldtest(in fieldname, in fieldtype, in fieldval, in tmpval, in callfunc)
myfprintf
function myfprintf(in verbose, in varargin)
finputcheck
function finputcheck(in vararg, in fieldlist, in callfunc, in mode, in verbose)
removedup
function removedup(in cella, in verbose)