diff m-toolbox/classes/@ssm/ssm2dot.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/@ssm/ssm2dot.m	Wed Nov 23 19:22:13 2011 +0100
@@ -0,0 +1,253 @@
+% SSM2DOT converts a statespace model object a DOT file.
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% DESCRIPTION: SSM2DOT converts a statespace model object a DOT file.
+%
+% CALL:        ssm2dot(ssm, options);
+%
+% INPUTS:      ssm     - ssm object
+%              options - plist of options
+%
+% <a href="matlab:utils.helper.displayMethodInfo('ssm', 'ssm2dot')">Parameters Description</a>
+%
+% VERSION: $Id: ssm2dot.m,v 1.15 2011/04/08 08:56:24 hewitson Exp $
+% 
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+function varargout = ssm2dot(varargin)
+  
+  % Check if this is a call for parameters
+  if utils.helper.isinfocall(varargin{:})
+    varargout{1} = getInfo(varargin{3});
+    return
+  end
+  
+  % starting initial checks
+  utils.helper.msg(utils.const.msg.MNAME, ['running ', mfilename]);
+  
+  in_names = cell(size(varargin));
+  for ii = 1:nargin,in_names{ii} = inputname(ii);end
+  
+  [inputSSMs, ssm_invars, rest] = utils.helper.collect_objects(varargin(:), 'ssm', in_names);
+  [pl, pl_invars, rest] = utils.helper.collect_objects(rest, 'plist');
+  if ~isempty(rest)
+    pl = combine(pl, plist(rest{:}));
+  end
+  options = combine(pl, getDefaultPlist());
+  
+  
+  filename = find(options, 'filename');
+  if isempty(filename)
+    error('### Please specify an output filename in the plist');
+  end
+  
+  statesOn = find(options, 'States');
+  if strcmpi(statesOn, 'yes')
+    statesOn = true;
+  else
+    statesOn = false;
+  end
+  
+  if numel(inputSSMs) ~= 1
+    error('### please input (only) one SSM object.');
+  end
+  
+  % Find the last assemble in the history
+  [n,a, nodes] = getNodes(inputSSMs.hist, '');
+  ssmNodes = findAssembleInputs(nodes, 1);
+  % if we only get one node there must not be any assemble blocks so we can
+  % just use the first node.
+  if length(ssmNodes)==1 || isempty(ssmNodes)
+    ssmNodes = 1;
+  end
+  
+  colors = {'blueviolet', 'chartreuse4', 'firebrick3', 'darkorange', 'navyblue', 'aquamarine3', 'deepskyblue'};
+  
+  % What info do we need?
+  sss(length(ssmNodes),1) = ssm;
+  for j=1:length(ssmNodes)
+    node = nodes(ssmNodes(j));
+    % Collect the nodes to execute
+    % and convert to commands
+    cmds = hist2m(node.h);
+    % execute each command
+    for kk=numel(cmds):-1:1
+      eval(cmds{kk});
+    end
+    % add to outputs
+    sss(j) = a_out;
+  end
+  % Write .dot file
+  fd = fopen(filename, 'w+');
+  % write header
+  fprintf(fd, 'digraph G \n{\n');
+  fprintf(fd, '\trankdir="LR";\n');
+  fprintf(fd, '\tnode [style=filled, fillcolor=white fixedsize=false width=0.5 fontsize=16 shape=rectangle];\n');
+  fprintf(fd, '\tedge [penwidth=5];\n');
+  fprintf(fd, '\n\n');
+  % Write block set
+  for j=1:length(ssmNodes)
+    % get the object
+    ss = sss(j);
+    inputblocks  = ss.inputnames;
+    inputvars    = ss.inputvarnames;
+    outputblocks = ss.outputnames;
+    outputvars   = ss.outputvarnames;
+    ssnames      = ss.ssnames;
+    ssvarnames   = ss.ssvarnames;
+    % Create sub graphs
+    fprintf(fd, '\tsubgraph cluster%d {\n', j);
+    fprintf(fd, '\t\tlabel="%s";\n', ss.name);
+    fprintf(fd, '\t\tfontcolor=black;\n');
+    fprintf(fd, '\t\tcolor=gray60;\n');
+    fprintf(fd, '\t\tstyle=filled;\n');
+    for k=1:numel(inputblocks)
+      fprintf(fd, '\t\tsubgraph cluster%d%d_in {\n', j, k);
+      fprintf(fd, '\t\t\tlabel="%s";\n', inputblocks{k});
+      fprintf(fd, '\t\t\tstyle=filled;\n');
+      fprintf(fd, '\t\t\tcolor=yellow1;\n');
+      fprintf(fd, '\t\t\tfontcolor=black;\n');
+      for l=1:numel(inputvars{k})
+        fprintf(fd, '\t\t\tssm_in_%d_%d_%d [label="%s"];\n', j,k,l,inputvars{k}{l});
+      end
+      fprintf(fd, '\t\t}\n');
+    end
+    for k=1:numel(outputblocks)
+      fprintf(fd, '\t\tsubgraph cluster%d%d_out {\n', j, k);
+      fprintf(fd, '\t\t\tlabel="%s";\n', outputblocks{k});
+      fprintf(fd, '\t\t\tstyle=filled;\n');
+      fprintf(fd, '\t\t\tcolor=lightblue1;\n');
+      for l=1:numel(outputvars{k})
+        fprintf(fd, '\t\t\tssm_out_%d_%d_%d [label="%s"];\n', j,k,l,outputvars{k}{l});
+      end
+      fprintf(fd, '\t\t}\n');
+    end
+    if statesOn
+      for k=1:numel(ssnames)
+        fprintf(fd, '\t\tsubgraph cluster%d%d_state {\n', j, k);
+        fprintf(fd, '\t\t\tlabel="%s";\n', ssnames{k});
+        fprintf(fd, '\t\t\tstyle=filled;\n');
+        fprintf(fd, '\t\t\tcolor=wheat1;\n');
+        for l=1:numel(ssvarnames{k})
+          fprintf(fd, '\t\t\tssm_state_%d_%d_%d [label="%s"];\n', j,k,l,ssvarnames{k}{l});
+        end
+        fprintf(fd, '\t\t}\n');
+      end
+    end
+    fprintf(fd, '\t}\n');
+    fprintf(fd, '\n\n');
+  end
+  % Write node list
+  fprintf(fd, '\n');
+  fprintf(fd, '\n');
+  nl = 1;
+  for j=1:length(ssmNodes)
+    % get the object
+    ss = sss(j);
+    inputblocks  = ss.inputnames;
+    inputvars    = ss.inputvarnames;
+    % Now join outputs to inputs
+    for k=1:numel(inputblocks)
+      iblock = inputblocks{k};
+      % look for a matching output block
+      for oj = 1:length(ssmNodes)
+        oss = sss(oj);
+        outputblocks = oss.outputnames;
+        outputvars   = oss.outputvarnames;
+        for ok=1:numel(outputblocks)
+          if strcmp(outputblocks{ok}, iblock)
+            % make a connection from each output to each input
+            for ol = 1:numel(outputvars{ok})
+              col = colors{mod(nl, numel(colors))+1};
+              % draw a line
+              fprintf(fd, 'ssm_out_%d_%d_%d -> ssm_in_%d_%d_%d [color="%s"];\n', oj, ok, ol, j, k, ol, col);
+              nl = nl + 1;
+            end
+          end
+        end
+      end
+    end
+  end
+  fprintf(fd, '\n');
+  fprintf(fd, '\n');
+  % close graph
+  fprintf(fd, '}\n');
+  % Close
+  fclose(fd);
+  
+end
+
+%--------- Get the input SSMs to all assemble blocks
+function idx = findAssembleInputs(nodes, an)
+  idx = [];
+  % get children
+  children = findChildNodes(nodes, an, '');
+  % find all sub-assembles or ssm end points
+  for j=1:numel(children)
+    ch = children(j);
+    subasmbl = findChildNodes(nodes, ch, 'assemble');
+    if isempty(subasmbl)
+      idx = [idx ch];
+    else
+      idx = [idx findAssembleInputs(nodes, ch)];
+    end
+  end
+end
+
+%---- Find particular child nodes
+function idx = findChildNodes(nodes, pn, name)
+  
+  idx = [];
+  if strcmp(nodes(pn).names, name)
+    idx = [idx pn];
+  end
+  Nnodes = numel(nodes);
+  for j=pn:Nnodes
+    if nodes(j).pn == pn
+      if isempty(name)
+        idx = [idx j];
+      else
+        if strcmp(nodes(j).names, name)
+          idx = [idx j]; % we have what we want
+        else
+          if j<Nnodes
+            idx = [idx findChildNodes(nodes, nodes(j).n, name)]; % check below
+          end
+        end
+      end
+    end
+  end
+end
+
+
+
+%--------------------------------------------------------------------------
+% Get Info Object
+%--------------------------------------------------------------------------
+function ii = getInfo(varargin)
+  
+  if nargin == 1 && strcmpi(varargin{1}, 'None')
+    sets = {};
+    pl   = [];
+  else
+    sets = {'Default'};
+    pl   = getDefaultPlist;
+  end
+  % Build info object
+  ii = minfo(mfilename, 'ssm', 'ltpda', utils.const.categories.internal, '$Id: ssm2dot.m,v 1.15 2011/04/08 08:56:24 hewitson Exp $', sets, pl);
+end
+
+%--------------------------------------------------------------------------
+% Get Default Plist
+%--------------------------------------------------------------------------
+function pl = getDefaultPlist()
+  pl = plist();
+  
+  p = param({'filename', 'The output filename to save the graphic to.'}, paramValue.EMPTY_STRING);
+  pl.append(p);
+  
+  p = param({'states', 'Draw the states of each model.'}, paramValue.TRUE_FALSE);
+  p.val.setValIndex(2);
+  pl.append(p);
+end
+