]> Creatis software - CreaPhase.git/blobdiff - octave_packages/io-1.0.19/parsecell.m
Add a useful package (from Source forge) for octave
[CreaPhase.git] / octave_packages / io-1.0.19 / parsecell.m
diff --git a/octave_packages/io-1.0.19/parsecell.m b/octave_packages/io-1.0.19/parsecell.m
new file mode 100644 (file)
index 0000000..770242a
--- /dev/null
@@ -0,0 +1,171 @@
+## Copyright (C) 2009,2010,2011,2012 Philip Nienhuis <prnienhuis at users.sf.net>
+##
+## 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{numarr}, @var{txtarr}, @var{lim} ] = parsecell (@var{rawarr})
+## @deftypefnx {Function File} [ @var{numarr}, @var{txtarr}, @var{lim} ] = parsecell (@var{rawarr}, @var{limits})
+##
+## Divide a heterogeneous 2D cell array into a 2D numeric array and a
+## 2D cell array containing only strings. Both returned arrays are
+## trimmed from empty outer rows and columns.
+## This function is particularly useful for parsing cell arrays returned
+## by functions reading spreadsheets (e.g., xlsread, odsread).
+##
+## Optional return argument @var{lim} contains two field with the outer
+## column and row numbers of @var{numarr} and @var{txtarr} in the
+## original array @var{rawarr}.
+## Optional input argument @var{limits} can either be the spreadsheet
+## data limits returned in the spreadsheet file pointer struct
+## (field xls.limits or ods.limits), or the file ptr struct itself.
+## If one of these is specified, optional return argument @var{lim}
+## will contain the real spreadsheet row & column numbers enclosing
+## the origins of the numerical and text data returned in @var{numarr}
+## and @var{txtarr}.
+##
+## Examples:
+##
+## @example
+##   [An, Tn] = parsecell (Rn);
+##   (which returns the numeric contents of Rn into array An and the
+##    text data into array Tn)
+## @end example
+##
+## @example
+##   [An, Tn, lims] = parsecell (Rn, xls.limits);
+##   (which returns the numeric contents of Rn into array An and the
+##    text data into array Tn.)
+## @end example
+##
+## @seealso {xlsread, odsread, xls2oct, ods2oct}
+##
+## @end deftypefn
+
+## Author: Philip Nienhuis
+## Created: 2009-12-13
+## Updates:
+## 2009-12-29
+## 2010-08-25 Added option for second argument to be a file ptr
+## 2010-10-15 Simplified code for numerical array
+## 2011-05-17 Fixed subscript indexing bug in cropping section when rawarr is
+##      "     numeric scalar
+## 2011-09-08 Copyright string updated
+## 2012-01-26 Fixed "seealso" help string
+
+function [ numarr, txtarr, lim ] = parsecell (rawarr, arg2=[])
+
+       if (isstruct (arg2))
+               # Assume a file ptr has been supplied
+               if (isfield (arg2, 'limits'))
+                       rawlimits = arg2.limits;
+               else
+                       warning ("Invalid file ptr supplied to parsecell() - limits ignored.");
+               endif
+       else
+               rawlimits = arg2;
+       endif
+
+       lim = struct ( "numlimits", [], "txtlimits", []);
+
+       numarr = [];
+       txtarr = {};
+       
+       if (~isempty (rawarr))
+               # Valid data returned. Divide into numeric & text arrays
+               no_txt = 0; no_num = 0;
+               if (isnumeric ([rawarr{:}]))
+                       numarr = num2cell (rawarr); 
+                       no_txt = 1;
+               elseif (iscellstr (rawarr))
+                       txtarr = cellstr (rawarr);
+                       no_num = 1;
+               endif
+               # Prepare parsing
+               [nrows, ncols] = size (rawarr);
+       
+               # Find text entries in raw data cell array
+               txtptr = cellfun ('isclass', rawarr, 'char');
+               if (~no_txt)
+                       # Prepare text array. Create placeholder for text cells
+                       txtarr = cell (size (rawarr));
+                       txtarr(:) = {''};
+                       if (any (any (txtptr)))
+                               # Copy any text cells found into place holder
+                               txtarr(txtptr) = rawarr(txtptr);
+                               # Clean up text array (find leading / trailing empty
+                               # rows & columns)
+                               irowt = 1;
+                               while (~any (txtptr(irowt, :))) irowt++; endwhile
+                               irowb = nrows;
+                               while (~any (txtptr(irowb, :))) irowb--; endwhile
+                               icoll = 1;
+                               while (~any (txtptr(:, icoll))) icoll++; endwhile
+                               icolr = ncols;
+                               while (~any (txtptr(:, icolr))) icolr--; endwhile
+                               # Crop textarray
+                               txtarr = txtarr(irowt:irowb, icoll:icolr);
+                               lim.txtlimits = [icoll, icolr; irowt, irowb];
+                               if (~isempty (rawlimits))
+                                       correction = [1; 1];
+                                       lim.txtlimits (:,1) = lim.txtlimits(:,1) + rawlimits(:,1) - correction;
+                                       lim.txtlimits (:,2) = lim.txtlimits(:,2) + rawlimits(:,1) - correction;
+                               endif
+                       else
+                               # If no text cells found return empty text array
+                               txtarr = {};
+                       endif
+               endif
+               
+               if (~no_num)
+                       # Prepare numeric array. Set all text & empty cells to
+                       # NaN. First get their locations
+                       emptr = cellfun ('isempty', rawarr);
+                       emptr(find (txtptr)) = 1;
+                       if (all (all (emptr)))
+                               numarr= [];
+                       else
+                               # Find leading & trailing empty rows
+                               irowt = 1;
+                               while (all(emptr(irowt, :))) irowt++; endwhile
+                               irowb = nrows;
+                               while (all(emptr(irowb, :))) irowb--; endwhile
+                               icoll = 1;
+                               while (all(emptr(:, icoll))) icoll++; endwhile
+                               icolr = ncols;
+                               while (all(emptr(:, icolr))) icolr--; endwhile
+
+                               # Pre-crop rawarr
+                               rawarr = rawarr (irowt:irowb, icoll:icolr);
+                               # Build numerical array
+                               numarr = zeros (irowb-irowt+1, icolr-icoll+1);
+                               # Watch out for scalar (non-empty) numarr where emptr = 0
+                               if (sum (emptr(:)) > 0)
+                                       numarr (emptr(irowt:irowb, icoll:icolr)) = NaN;
+                               endif
+                               numarr(~emptr(irowt:irowb, icoll:icolr)) = cell2mat (rawarr(~emptr(irowt:irowb, icoll:icolr)));
+                               # Save limits
+                               lim.numlimits = [icoll, icolr; irowt, irowb];
+                               if (~isempty (rawlimits))
+                                       correction = [1; 1];
+                                       lim.numlimits(:,1) = lim.numlimits(:,1) + rawlimits(:,1) - correction(:);
+                                       lim.numlimits(:,2) = lim.numlimits(:,2) + rawlimits(:,1) - correction(:);
+                               endif
+                       endif
+               endif
+
+               lim.rawlimits = rawlimits;
+       
+       endif
+
+endfunction