diff m-toolbox/classes/@smodel/fromDatafile.m @ 0:f0afece42f48

Import.
author Daniele Nicolodi <nicolodi@science.unitn.it>
date Wed, 23 Nov 2011 19:22:13 +0100
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/m-toolbox/classes/@smodel/fromDatafile.m	Wed Nov 23 19:22:13 2011 +0100
@@ -0,0 +1,294 @@
+% FROMDATAFILE Construct smodel object from filename AND parameter list
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% FUNCTION:    fromDatafile
+%
+% DESCRIPTION: Construct smodel object from filename AND parameter list
+%
+% CALL:        a = fromFilenameAndPlist(a, pli)
+%
+% PARAMETER:   a:   empty ltpda-model-object
+%              pli: plist-object (must contain the filename)
+%
+% FORMAT:      The text file must have the following format:
+%
+%              - Blank lines are ignored
+%              - Lines starting with a hash (#) are ignored
+%                (* see description part
+%              - The first continuous comment block will be put into the
+%                description field
+%              - The values for the model are defined with some keywords
+%              - Use only one line for a value
+%              - A colon after a keyword can be optionally inserted
+%              - The following keywords (inside the quotes) are mandatory
+%                and must be at the beginning of a line.
+%                'expr'   - the expression of the model
+%                'params' - parameters which are used in the model
+%                'values' - default values for the parameters
+%                'xvar'   - X-variable
+%              - The following keywords are optional
+%                'xunits' - units of the x-axis
+%                'yunits' - units of the y-axis
+%                'xvals'  - values for the X-variable
+%              - It is possible to read more than one model from a file.
+%                Use for this the indeces behind the keywords. For example
+%                expr(1,2): ...
+%                expr(3) ...
+%              - It is necessary that each mandatory keyword have an entry
+%                for each index. If a keyword have only one entry then will
+%                be this enty copied to all other models.
+%
+% VERSION:     $Id: fromDatafile.m,v 1.2 2011/08/15 13:12:17 hewitson Exp $
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+function mdl = fromDatafile(mdlin, pli)
+  
+  utils.helper.msg(utils.const.msg.PROC1, 'constructing from filename and/or plist');
+  
+  VERSION = '$Id: fromDatafile.m,v 1.2 2011/08/15 13:12:17 hewitson Exp $';
+  
+  % get ltpda-model info
+  mi = smodel.getInfo('smodel', 'From ASCII File');
+  
+  % Set the method version string in the minfo object
+  mi.setMversion([VERSION '-->' mi.mversion]);
+  
+  % Get filename
+  file_name = find(pli, 'filename');
+  
+  [pathstr, f_name, ext] = fileparts(file_name);
+  
+  %%%%%%%%%%   Get default parameter list   %%%%%%%%%%
+  dpl = smodel.getDefaultPlist('From ASCII File');
+  pl  = applyDefaults(dpl, pli);
+  
+  pl = pset(pl, 'filename', [f_name ext]);
+  pl = pset(pl, 'filepath', pathstr);
+  
+  dxunits = pl.find('xunits');
+  dyunits = pl.find('yunits');
+  dxvals  = pl.find('xvals');
+  ddesc   = pl.find('description');
+  
+  %%%%%%%%%%   read file   %%%%%%%%%%
+  [fid,msg] = fopen (file_name, 'r');
+  if (fid < 0)
+    error ('### can not open file: %s \n### error msg: %s',file_name, msg);
+  end
+  
+  firstCommentBlock = true;
+  
+  desc = '';
+  expr = {};
+  params = {};
+  xvar = {};
+  values = {};
+  
+  xvals  = {};
+  xunits = {};
+  yunits = {};
+  
+  while ~feof(fid)
+    
+    fline = fgetl(fid);
+    fline = strtrim(fline);
+    
+    if isempty(fline)
+      firstCommentBlock = isFirstCommentBlock(desc);
+    elseif fline(1) == '#'
+      if firstCommentBlock && ~isempty(strtrim(fline(2:end)))
+        desc = [desc, strtrim(fline(2:end)), '\n'];
+      end
+      
+    elseif strcmpi(fline(1:4), 'expr')
+      firstCommentBlock = isFirstCommentBlock(desc);
+      [i,j,txt] = parseLine(fline, 'expr');
+      expr{i,j} = txt;
+      
+    elseif strcmpi(fline(1:6), 'params')
+      firstCommentBlock = isFirstCommentBlock(desc);
+      [i,j,txt] = parseLine(fline, 'params');
+      params{i,j} = txt;
+      
+    elseif strcmpi(fline(1:4), 'xvar')
+      firstCommentBlock = isFirstCommentBlock(desc);
+      [i,j,txt] = parseLine(fline, 'xvar');
+      xvar{i,j} = txt;
+      
+    elseif strcmpi(fline(1:6), 'values')
+      firstCommentBlock = isFirstCommentBlock(desc);
+      [i,j,txt] = parseLine(fline, 'values');
+      values{i,j} = txt;
+      
+    elseif strcmpi(fline(1:5), 'xvals')
+      firstCommentBlock = isFirstCommentBlock(desc);
+      [i,j,txt] = parseLine(fline, 'xvals');
+      xvals{i,j} = txt;
+      
+    elseif strcmpi(fline(1:6), 'xunits')
+      firstCommentBlock = isFirstCommentBlock(desc);
+      [i,j,txt] = parseLine(fline, 'xunits');
+      xunits{i,j} = txt;
+      
+    elseif strcmpi(fline(1:6), 'yunits')
+      firstCommentBlock = isFirstCommentBlock(desc);
+      [i,j,txt] = parseLine(fline, 'yunits');
+      yunits{i,j} = txt;
+      
+    end
+    
+  end
+  fclose(fid);
+  
+  % Get maximum size of the smodel matrix
+  maxi = max([size(expr,1), size(params,1), size(xvar,1), size(values,1), size(xvals,1), size(xunits,1), size(yunits,1)]);
+  maxj = max([size(expr,2), size(params,2), size(xvar,2), size(values,2), size(xvals,2), size(xunits,2), size(yunits,2)]);
+  
+  % Make some plausibly checks
+  %   1) Replicate the array to the maximum size of the used indices if the
+  %      array have only one input.
+  %   2) The array must have the same size as the used indices.
+  if isempty(xunits)
+    xunits = {dxunits};
+  end
+  if isempty(yunits)
+    yunits = {dyunits};
+  end
+  if isempty(xvals)
+    xvals = {dxvals};
+  end
+  if ~isempty(ddesc)
+    desc = ddesc;
+  end
+  expr   = checkArray(expr, maxi, maxj);
+  params = checkArray(params, maxi, maxj);
+  xvar   = checkArray(xvar, maxi, maxj);
+  values = checkArray(values, maxi, maxj);
+  xvals  = checkArray(xvals, maxi, maxj);
+  xunits = checkArray(xunits, maxi, maxj);
+  yunits = checkArray(yunits, maxi, maxj);
+  
+  mdl = smodel.newarray([maxi, maxj]);
+  
+  % Check mandatory fields
+  if isempty(expr) || isempty(params) || isempty(xvar) || isempty(values)
+    error('### At least one of the mandatory fields (''expr'', ''params'', ''xvar'', ''values'') is empty.');
+  end
+  
+  % Create Object
+  for ii = 1:numel(mdl)
+    
+    % mandatory fields
+    mdl(ii).expr   = expr{ii};
+    mdl(ii).params = regexp(strtrim(params{ii}), ',', 'split');
+    mdl(ii).xvar   = xvar{ii};
+    mdl(ii).values = cellfun(@str2num, regexp(strtrim(values{ii}), ',', 'split'));
+    
+    % Optional fields
+    if ~isempty(xvals)
+      if ischar(xvals{ii})
+        mdl(ii).xvals  = eval(xvals{ii});
+      else
+        mdl(ii).xvals  = xvals{ii};
+      end
+    end
+    if ~isempty(xunits)
+      mdl(ii).xunits = xunits{ii};
+    end
+    if ~isempty(yunits)
+      mdl(ii).yunits = yunits{ii};
+    end
+    mdl(ii).description = desc(1:end-2); % remove the last break
+    mdl(ii).addHistory(mi, pl, [], []);
+    
+  end
+  
+end
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                               Local Functions                               %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% FUNCTION:    fromDatafile
+%
+% DESCRIPTION:
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+function flag = isFirstCommentBlock(desc)
+  if isempty(desc)
+    flag = true;
+  else
+    flag = false;
+  end
+end
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% FUNCTION:    getIndex
+%
+% DESCRIPTION: Returns the index of the input string.
+%              '(3,2)' -> i=3, j=2
+%              '(3)'   -> i=3, default: j=1
+%              '()'    -> default i=1, default: j=1
+%              ''      -> default i=1, default: j=1
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+function [i,j] = getIndex(token)
+  ij = regexp(token, '\d*', 'match');
+  if numel(ij) == 2
+    i = eval(ij{1});
+    j = eval(ij{2});
+  elseif numel(ij) == 1
+    i = eval(ij{1});
+    j = 1;
+  else
+    i = 1;
+    j = 1;
+  end
+end
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% FUNCTION:    parseLine
+%
+% DESCRIPTION: Returns the indices i,j and the remaining value for the
+%              given field.
+%
+% Example:     expr: a+b*t        -> i=1, j=1, txt=a+b*t
+%              expr a+b*t         -> i=1, j=1, txt=a+b*t
+%              expr(3)    a+b*t   -> i=3, j=1, txt=a+b*t
+%              expr(3,2): a+b*t   -> i=3, j=2, txt=a+b*t
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+function [i,j,txt] = parseLine(lineIn, field)
+  exp = [field '(?<idx>\(\d*(,\d*)?\))?:? *'];
+  idx = regexp(lineIn, exp, 'end');
+  ij  = regexp(lineIn, exp, 'names');
+  [i,j] = getIndex(ij(1).idx);
+  txt = lineIn(idx+1:end);
+end
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% FUNCTION:    checkArray
+%
+% DESCRIPTION: There are the following rules
+%              1) If the array have only one input then replicate this
+%                 input to the maximum size of the used indices.
+%              2) Throw an error if the inputs are more than one but not so
+%                 much as the maximum of the used indices.
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+function array = checkArray(array, maxi, maxj)
+  if numel(array) == 0
+    % Do nothing
+  elseif numel(array) == 1
+    array = repmat(array, maxi, maxj);
+  elseif size(array,1) ~= maxi || size(array,2) ~= maxj
+    error('### One model is not well defined. Max (i,j) = (%d,%d) but only used (%d,%d)', maxi, maxj, size(array,1), size(array,2));
+  end
+end
+