]> Creatis software - CreaPhase.git/blob - 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
1 ## Copyright (C) 2009,2010,2011,2012 Philip Nienhuis <prnienhuis at users.sf.net>
2 ##
3 ## This program is free software; you can redistribute it and/or modify it under
4 ## the terms of the GNU General Public License as published by the Free Software
5 ## Foundation; either version 3 of the License, or (at your option) any later
6 ## version.
7 ##
8 ## This program is distributed in the hope that it will be useful, but WITHOUT
9 ## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 ## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
11 ## details.
12 ##
13 ## You should have received a copy of the GNU General Public License along with
14 ## this program; if not, see <http://www.gnu.org/licenses/>.
15
16 ## -*- texinfo -*-
17 ## @deftypefn {Function File} [ @var{numarr}, @var{txtarr}, @var{lim} ] = parsecell (@var{rawarr})
18 ## @deftypefnx {Function File} [ @var{numarr}, @var{txtarr}, @var{lim} ] = parsecell (@var{rawarr}, @var{limits})
19 ##
20 ## Divide a heterogeneous 2D cell array into a 2D numeric array and a
21 ## 2D cell array containing only strings. Both returned arrays are
22 ## trimmed from empty outer rows and columns.
23 ## This function is particularly useful for parsing cell arrays returned
24 ## by functions reading spreadsheets (e.g., xlsread, odsread).
25 ##
26 ## Optional return argument @var{lim} contains two field with the outer
27 ## column and row numbers of @var{numarr} and @var{txtarr} in the
28 ## original array @var{rawarr}.
29 ## Optional input argument @var{limits} can either be the spreadsheet
30 ## data limits returned in the spreadsheet file pointer struct
31 ## (field xls.limits or ods.limits), or the file ptr struct itself.
32 ## If one of these is specified, optional return argument @var{lim}
33 ## will contain the real spreadsheet row & column numbers enclosing
34 ## the origins of the numerical and text data returned in @var{numarr}
35 ## and @var{txtarr}.
36 ##
37 ## Examples:
38 ##
39 ## @example
40 ##   [An, Tn] = parsecell (Rn);
41 ##   (which returns the numeric contents of Rn into array An and the
42 ##    text data into array Tn)
43 ## @end example
44 ##
45 ## @example
46 ##   [An, Tn, lims] = parsecell (Rn, xls.limits);
47 ##   (which returns the numeric contents of Rn into array An and the
48 ##    text data into array Tn.)
49 ## @end example
50 ##
51 ## @seealso {xlsread, odsread, xls2oct, ods2oct}
52 ##
53 ## @end deftypefn
54
55 ## Author: Philip Nienhuis
56 ## Created: 2009-12-13
57 ## Updates:
58 ## 2009-12-29
59 ## 2010-08-25 Added option for second argument to be a file ptr
60 ## 2010-10-15 Simplified code for numerical array
61 ## 2011-05-17 Fixed subscript indexing bug in cropping section when rawarr is
62 ##      "     numeric scalar
63 ## 2011-09-08 Copyright string updated
64 ## 2012-01-26 Fixed "seealso" help string
65
66 function [ numarr, txtarr, lim ] = parsecell (rawarr, arg2=[])
67
68         if (isstruct (arg2))
69                 # Assume a file ptr has been supplied
70                 if (isfield (arg2, 'limits'))
71                         rawlimits = arg2.limits;
72                 else
73                         warning ("Invalid file ptr supplied to parsecell() - limits ignored.");
74                 endif
75         else
76                 rawlimits = arg2;
77         endif
78
79         lim = struct ( "numlimits", [], "txtlimits", []);
80
81         numarr = [];
82         txtarr = {};
83         
84         if (~isempty (rawarr))
85                 # Valid data returned. Divide into numeric & text arrays
86                 no_txt = 0; no_num = 0;
87                 if (isnumeric ([rawarr{:}]))
88                         numarr = num2cell (rawarr); 
89                         no_txt = 1;
90                 elseif (iscellstr (rawarr))
91                         txtarr = cellstr (rawarr);
92                         no_num = 1;
93                 endif
94                 # Prepare parsing
95                 [nrows, ncols] = size (rawarr);
96         
97                 # Find text entries in raw data cell array
98                 txtptr = cellfun ('isclass', rawarr, 'char');
99                 if (~no_txt)
100                         # Prepare text array. Create placeholder for text cells
101                         txtarr = cell (size (rawarr));
102                         txtarr(:) = {''};
103                         if (any (any (txtptr)))
104                                 # Copy any text cells found into place holder
105                                 txtarr(txtptr) = rawarr(txtptr);
106                                 # Clean up text array (find leading / trailing empty
107                                 # rows & columns)
108                                 irowt = 1;
109                                 while (~any (txtptr(irowt, :))) irowt++; endwhile
110                                 irowb = nrows;
111                                 while (~any (txtptr(irowb, :))) irowb--; endwhile
112                                 icoll = 1;
113                                 while (~any (txtptr(:, icoll))) icoll++; endwhile
114                                 icolr = ncols;
115                                 while (~any (txtptr(:, icolr))) icolr--; endwhile
116                                 # Crop textarray
117                                 txtarr = txtarr(irowt:irowb, icoll:icolr);
118                                 lim.txtlimits = [icoll, icolr; irowt, irowb];
119                                 if (~isempty (rawlimits))
120                                         correction = [1; 1];
121                                         lim.txtlimits (:,1) = lim.txtlimits(:,1) + rawlimits(:,1) - correction;
122                                         lim.txtlimits (:,2) = lim.txtlimits(:,2) + rawlimits(:,1) - correction;
123                                 endif
124                         else
125                                 # If no text cells found return empty text array
126                                 txtarr = {};
127                         endif
128                 endif
129                 
130                 if (~no_num)
131                         # Prepare numeric array. Set all text & empty cells to
132                         # NaN. First get their locations
133                         emptr = cellfun ('isempty', rawarr);
134                         emptr(find (txtptr)) = 1;
135                         if (all (all (emptr)))
136                                 numarr= [];
137                         else
138                                 # Find leading & trailing empty rows
139                                 irowt = 1;
140                                 while (all(emptr(irowt, :))) irowt++; endwhile
141                                 irowb = nrows;
142                                 while (all(emptr(irowb, :))) irowb--; endwhile
143                                 icoll = 1;
144                                 while (all(emptr(:, icoll))) icoll++; endwhile
145                                 icolr = ncols;
146                                 while (all(emptr(:, icolr))) icolr--; endwhile
147
148                                 # Pre-crop rawarr
149                                 rawarr = rawarr (irowt:irowb, icoll:icolr);
150                                 # Build numerical array
151                                 numarr = zeros (irowb-irowt+1, icolr-icoll+1);
152                                 # Watch out for scalar (non-empty) numarr where emptr = 0
153                                 if (sum (emptr(:)) > 0)
154                                         numarr (emptr(irowt:irowb, icoll:icolr)) = NaN;
155                                 endif
156                                 numarr(~emptr(irowt:irowb, icoll:icolr)) = cell2mat (rawarr(~emptr(irowt:irowb, icoll:icolr)));
157                                 # Save limits
158                                 lim.numlimits = [icoll, icolr; irowt, irowb];
159                                 if (~isempty (rawlimits))
160                                         correction = [1; 1];
161                                         lim.numlimits(:,1) = lim.numlimits(:,1) + rawlimits(:,1) - correction(:);
162                                         lim.numlimits(:,2) = lim.numlimits(:,2) + rawlimits(:,1) - correction(:);
163                                 endif
164                         endif
165                 endif
166
167                 lim.rawlimits = rawlimits;
168         
169         endif
170
171 endfunction