changeset 480:ed19b5ad9718

image: new utility functions iptcheckstrs, iptnum2ordinal, iptcheckmap and iptchecknargin
author carandraug
date Tue, 01 Nov 2011 14:21:15 +0000
parents c88e984fd5d1
children b62b5ac9dffc
files INDEX inst/iptcheckmap.m inst/iptchecknargin.m inst/iptcheckstrs.m inst/iptnum2ordinal.m
diffstat 5 files changed, 270 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/INDEX
+++ b/INDEX
@@ -109,3 +109,8 @@
  rangefilt
  stdfilt
  entropyfilt
+Utilities
+ iptnum2ordinal
+ iptcheckstrs
+ iptchecknargin
+ iptcheckmap
new file mode 100644
--- /dev/null
+++ b/inst/iptcheckmap.m
@@ -0,0 +1,49 @@
+## Copyright (C) 2011 Carnë Draug <carandraug+dev@gmail.com>
+##
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 3 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn {Function File} {} iptcheckmap (@var{in}, @var{func_name}, @var{var_name}, @var{pos})
+## Check if argument is valid colormap.
+##
+## If @var{in} is not a valid colormap, gives a properly formatted error message.
+## @var{func_name} is the name of the function to be used on the error message,
+## @var{var_name} the name of the argument being checked (for the error message),
+## and @var{pos} the position of the argument in the input.
+##
+## A valid colormap is a 2-D matrix with 3 columns of doubles with values between
+## 0 and 1 (inclusive), that refer to the intensity levels of red, green and blue.
+##
+## @seealso{colormap}
+## @end deftypefn
+
+function iptcheckmap (in, func_name, var_name, pos)
+
+  if (nargin != 4)
+    print_usage;
+  elseif (!ischar (func_name))
+    error ("Argument func_name must be a string");
+  elseif (!ischar (var_name))
+    error ("Argument var_name must be a string");
+  elseif (!isnumeric (pos) || !isscalar (pos) || !isreal (pos) || pos <= 0 || rem (pos, 1) != 0)
+    error ("Argument pos must be a real positive integer");
+  endif
+
+  if (!strcmp (class(in), "double") || columns (in) != 3 || ndims (in) != 2 || !isreal (in) || min (in(:) < 0 || max (in(:) > 1)
+    error ("Function %s expected input number %d, %s, to be a valid colormap.\n ...
+      Valid colormaps must be nonempty, double, 2-D matrices with 3 columns.", ...
+      func_name, pos, var_name);
+  endif
+
+endfunction
new file mode 100644
--- /dev/null
+++ b/inst/iptchecknargin.m
@@ -0,0 +1,56 @@
+## Copyright (C) 2011 Carnë Draug <carandraug+dev@gmail.com>
+##
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 3 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn {Function File} {} iptchecknargin (@var{low}, @var{high}, @var{in}, @var{func_name})
+## Checks for correct number of arguments.
+##
+## This function returns an error unless @var{in} is between the values of
+## @var{low} and @var{high}. It does nothing otherwise. They all must be non
+## negative scalar integers. @var{high} can also be Inf.
+##
+## @var{func_name} is the name of the function to be used on the error message.
+##
+## @seealso{error, nargin, nargout, narginchk, nargoutchk}
+## @end deftypefn
+
+function iptchecknargin (low, high, in, func_name)
+
+  if (nargin != 4)
+    print_usage;
+  elseif (!isnumeric (low) || !isscalar (low) || !isreal (low) || low < 0 || !isfinite (low) || rem (low, 1) != 0)
+    error ("Argument 'low' must be a non-negative scalar integer");
+  elseif (!isnumeric (high) || !isscalar (high) || !isreal (high) || low < 0 || (isfinite (high) && rem (low, 1) != 0))
+    error ("Argument 'high' must be a non-negative scalar integer or Inf");
+  elseif (!isnumeric (in) || !isscalar (in) || !isreal (in) || in < 0 || !isfinite (in) || rem (in, 1) != 0)
+    error ("Argument 'in' must be a non-negative scalar integer");
+  elseif (!ischar (func_name))
+    error ("Argument 'func_name' must be a string");
+  elseif (low > high)
+    error ("Minimun number of arguments cannot be larger than maximum number of arguments")
+  endif
+
+  if (in < low)
+    error ("Not enough input arguments.");
+  elseif (in > high)
+    error ("Too many input arguments.");
+  endif
+
+endfunction
+
+%!test ('iptchecknargin (0, 2, 1, "func")');    # check simple works
+%!test ('iptchecknargin (0, Inf, 1, "func")');  # check Inf on max
+%!fail ('iptchecknargin (3, 2, 1, "func")');    # check fail min >max
+%!fail ('iptchecknargin (2, 3, 1, "func")');    # check fail in out of range
new file mode 100644
--- /dev/null
+++ b/inst/iptcheckstrs.m
@@ -0,0 +1,64 @@
+## Copyright (C) 2011 Carnë Draug <carandraug+dev@gmail.com>
+##
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 3 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn {Function File} {@var{valid} =} iptcheckstrs (@var{in}, @var{valid_str}, @var{func_name}, @var{var_name}, @var{pos})
+## Check if argument is a valid string.
+##
+## If @var{in} is not a string, present in the cell array of strings
+## @var{valid_str} gives a properly formatted error message. Otherwise,
+## @var{valid} is the matched string. The performed matching is case-insensitive.
+##
+## @var{func_name} is the name of the function to be used on the error message,
+## @var{var_name} the name of the argument being checked (for the error message),
+## and @var{pos} the position of the argument in the input.
+##
+## @seealso{strcmp, strcmpi, find}
+## @end deftypefn
+
+function out = iptcheckstrs (in, valid_str, func_name, var_name, pos)
+
+  if (nargin != 5)
+    print_usage;
+  elseif (!ischar (in))
+    error ("Argument 'in' must be a string.");
+  elseif (!iscellstr (valid_str))
+    error ("Argument 'valid_str' must be a cell array of strings.");
+  elseif (!ischar (func_name))
+    error ("Argument 'func_name' must be a string");
+  elseif (!ischar (var_name))
+    error ("Argument 'var_name' must be a string");
+  elseif (!isnumeric (pos) || !isscalar (pos) || !isreal (pos) || pos <= 0 || rem (pos, 1) != 0)
+    error ("Argument 'pos' must be a real positive integer");
+  endif
+
+  idx = find (strcmpi (valid_str, in) == 1, 1, "first");
+
+  if (isempty (idx))
+    valid_str = cellfun (@(x) cstrcat (x, ", "), valid_str, "UniformOutput", false);
+    valid_str = cstrcat (valid_str{:});
+    error("Function %s expected its %s input argument, %s, to match one of these strings:\n...
+         %s\n...
+       The input, '%s', did not match any of the valid strings.", ...
+      func_name, iptnum2ordinal (pos), var_name, valid_str(1:end-2), in);
+  else
+    out = valid_str{idx};
+  endif
+
+endfunction
+
+%!assert (iptcheckstrs ("two", {"one", "two", "three"}, "func", "var", 1) == "two" );    # check simple works
+%!assert (iptcheckstrs ("Two", {"one", "two", "three"}, "func", "var", 1) == "two" );    # check case insensitive
+%!fail ('iptcheckstrs ("four", {"one", "two", "three"}, "func", "var", 1)');             # check failure if not found
new file mode 100644
--- /dev/null
+++ b/inst/iptnum2ordinal.m
@@ -0,0 +1,96 @@
+## Copyright (C) 2011 Carnë Draug <carandraug+dev@gmail.com>
+##
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 3 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn {Function File} {@var{ord} =} iptnum2ordinal (@var{num})
+## Convert number to ordinal string.
+##
+## @var{num} must be a real positive integer which will be converted to a string
+## with its ordinal form @var{ord}.
+##
+## @example
+## @group
+## iptnum2ordinal (1)
+##       @result{} first
+## iptnum2ordinal (12)
+##      @result{} twelfth
+## iptnum2ordinal (21)
+##      @result{} 21st
+## @end group
+## @end example
+##
+## @seealso{num2str, sprintf, int2str, mat2str}
+## @end deftypefn
+
+function ord = iptnum2ordinal (num)
+
+  ## thanks to Skei in ##matlab for checking the grammar of ordinals and that it
+  ## is after number 20 that it starts using the suffixes only
+
+  ## thanks to porten in ##matlab for help checking these corner-cases
+  ## the following were test and failed: Inf, 0, -1, 3.4, 1e-7
+  ## using a string kind of succeeded as the character position in the ascii
+  ## table as used for the conversion
+
+  if (nargin != 1)
+    print_usage;
+  elseif (!isnumeric (num) || !isscalar (num) || !isreal (num) || num <= 0 || rem (num, 1) != 0)
+    error ("num must be a real positive integer");
+  endif
+
+  switch num
+    case {1}  ord = "first";
+    case {2}  ord = "second";
+    case {3}  ord = "third";
+    case {4}  ord = "fourth";
+    case {5}  ord = "fifth";
+    case {6}  ord = "sixth";
+    case {7}  ord = "seventh";
+    case {8}  ord = "eighth";
+    case {9}  ord = "ninth";
+    case {10} ord = "tenth";
+    case {11} ord = "eleventh";
+    case {12} ord = "twelfth";
+    case {13} ord = "thirteenth";
+    case {14} ord = "fourteenth";
+    case {15} ord = "fifteenth";
+    case {16} ord = "sixteenth";
+    case {17} ord = "seventeenth";
+    case {18} ord = "eighteenth";
+    case {19} ord = "nineteenth";
+    case {20} ord = "twentieth";
+    otherwise
+      ## if we ever want to mimic matlab's defective behaviour of accepting a
+      ## string and return the ordinal of position on the ascii table, we must
+      ## check here if it's a string, and if so, use:
+      ## ord = sprintf ("%dth", num);
+      num = num2str (num);
+      switch num(end)
+        case {"1"} ord = strcat (num, "st");
+        case {"2"} ord = strcat (num, "nd");
+        case {"3"} ord = strcat (num, "rd");
+        otherwise  ord = strcat (num, "th");
+      endswitch
+  endswitch
+
+endfunction
+
+%!assert (strcmp (iptnum2ordinal (1), 'first'));    # simple works
+%!assert (strcmp (iptnum2ordinal (21), '21st'));    # after 20, goes stupid
+%!assert (strcmp (iptnum2ordinal (100), '100th'));  # use th correctly
+%!fail ("iptnum2ordinal (inf)");                    # must be real
+%!fail ("iptnum2ordinal (0)");                      # must be positive
+%!fail ("iptnum2ordinal (-1)");                     # must be positive
+%!fail ("iptnum2ordinal (3.4)");                    # must be integer