Mercurial > hg > ltpda
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 +