Mercurial > hg > ltpda
diff m-toolbox/classes/@LTPDAworkbench/cmds2pipeline.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/@LTPDAworkbench/cmds2pipeline.m Wed Nov 23 19:22:13 2011 +0100 @@ -0,0 +1,363 @@ +% CMDS2PIPELINE builds new pipelines in the given workbench from the +% set of LTPDA commands. +% +% CALL: cmds2pipeline(wb, name, cmds) +% cmds2pipeline(wb, name, cmds, blockpositions) +% +% M Hewitson 12-11-10 +% +% $Id: cmds2pipeline.m,v 1.2 2011/04/08 08:56:32 hewitson Exp $ +% +function cmds2pipeline(wb, docname, cmds, varargin) + + if numel(varargin) > 0 + blockPositions = varargin{1}; + else + blockPositions = {}; + end + + % create new diagram + awtinvoke(wb.mp, 'createNewBlockDiagram', docname); + % logical array for checking that we only place + % each block once + blockplaced = zeros(size(cmds)); + + % Go through each command and place its block + cn = 1; + dX = 100; + dY = 150; + sX = 100; + X = sX; % starting X coord + Y = 50; % starting Y coord + % loop until all blocks are placed + blockNames = {}; + while ~all(blockplaced) && cn <=numel(cmds) + if ~blockplaced(cn) + % parse this command + srcblock = LTPDAworkbench.parseCmd(cmds{cn}); + %--------- build a block + % to do this we need an minfo object; we have the + % the method name but we need the class. Either this + % is a constructor or it must have an input object + ecmd = sprintf('%s.getInfo(''%s'');', srcblock.class, srcblock.method); + ii = eval(ecmd); + % override auto-generated positions if the user supplies them + if ~isempty(blockPositions) + pos = blockPositions{cn}; + X = pos(1); + Y = pos(2); + end + name = wb.addBlock(srcblock.outname, ii, X,Y); + blockNames = [blockNames {name}]; + blockplaced(cn) = 1; + % look for commands which take this output as an input + [blockplaced,blockNames] = placeBlock(wb, blockplaced, ... + blockPositions, srcblock.outname, cmds, X, dX, Y, cn, blockNames); + % reset X + X = sX+floor(utils.math.rand(10,20)); + % increment in Y + Y = Y + dY; + end + % check next block + cn = cn + 1; + end + + % Build a connection list + connections = struct('src', {}, 'srcport', {}, 'dst',{}, 'dstport', {}); + cc = 1; + for cn =1:numel(cmds) + conn = cmd2conn(cmds{cn}); + % deal with block-to-block connections + if numel(conn.srcports)==numel(conn.dstports) + for kk=1:numel(conn.srcblocks) + if numel(conn.srcblocks) == 1 + % one-to-many + srcb = conn.srcblocks{1}; + else + % one-to-one + srcb = conn.srcblocks{kk}; + end + if numel(conn.dstblocks) == 1 + % many-to-one + dstb = conn.dstblocks{1}; + else + % one-to-one + dstb = conn.dstblocks{kk}; + end + if ~isempty(srcb) && ~isempty(dstb) + % make connection + if ~isempty(dstb) + connections(cc) = struct('src', srcb, ... + 'srcport', conn.srcports(kk), ... + 'dst', dstb, ... + 'dstport', conn.dstports(kk)); + connections(end) + wb.connectBlocks(connections(cc).src, connections(cc).srcport+1, ... + connections(cc).dst, connections(cc).dstport+1); + cc = cc + 1; + end + end + end % End loop over src blocks + end + end % End first loop over commands + + % also deal with connections to the plist + for kk=1:numel(cmds) + cconn = cmd2conn(cmds{kk}); + conn = connFromPlist(cconn, blockNames); + if ~isempty(conn) + for ll=1:numel(conn) + % we need to know what destination port to use + % - look for max in connections for this dst block + b = wb.getBlockByName(conn(ll).dst); + p = b.getNextFreeInput(); + connections(cc) = struct('src', conn(ll).src, ... + 'srcport', conn(ll).srcport, ... + 'dst', conn(ll).dst, ... + 'dstport', p); + wb.connectBlocks(conn(ll).src, conn(ll).srcport+1, conn(ll).dst, p+1) + cc = cc + 1; + end + end + end + + % upload plists + for cn =1:numel(cmds) + block = LTPDAworkbench.parseCmd(cmds{cn}); + dstblock = block.outname; + % get src block name(s) and ports from each plist + for pp=1:numel(block.plists) + pl = block.plists{pp}; + mtchs = regexp(pl, '(\w*)_PORT(\d*)', 'tokens'); + % for each match, we look for a corresponding connection + % so that we can determine the destination port + if ~isempty(mtchs) + for kk=1:numel(mtchs) + srcblock = mtchs{kk}{1}; + srcport = str2double(mtchs{kk}{2}); + % look for srcblock/srcport/dstblock in connection list + % and get the dstport + dstport = -1; + for cc=1:numel(connections) + % if this matches... + if strcmp(connections(cc).src, srcblock) && ... + strcmp(connections(cc).dst, dstblock) && ... + connections(cc).srcport == srcport + % ... then we set the dstport + dstport = connections(cc).dstport; + end + end + % now we can fix up the plist + if dstport >= 0 + pl = regexprep(pl, [srcblock '_PORT\d*'], ['''PORT_' num2str(dstport) '''']); + end + end + else + % Try also for any block name in the plist + for kk=1:numel(blockNames) + srcblock = blockNames{kk}; + % look for this srcblock in the plist but we need a clever + % regular expression to check this is an argument of the plist and + % not part of a key, for example. + tks = regexp(pl, ['[\s\[,]+(' srcblock ')[\s,\]]+'], 'tokens'); + dstport = -1; + for ll=1:numel(tks) + % To get the destination port, we need to find this + % connection in the connections list + for cc=1:numel(connections) + cnc = connections(cc); + if strcmp(cnc.src, srcblock) && ... + strcmp(cnc.dst, dstblock) && ... + cnc.srcport == 0 + dstport = cnc.dstport; + end + end + end + if dstport >= 0 + pl = regexprep(pl, srcblock, ['''PORT_' num2str(dstport) '''']); + end + end + end + % now we can upload the plist + wb.uploadPlist(dstblock, eval(pl)); + end + end + + +end + +%-------------------------------------------------------------------------- +% Create a connection structure from a plist. +% +% This deals with those plists that have BLOCK_PORT# type entries. +% +function conn = connFromPlist(iconn, blocks) + + conn = struct('src', {}, 'srcport', {}, 'dst',{}, 'dstport', {}); + cc = 1; + + for jj=1:numel(iconn.plist) + pl = iconn.plist{jj}; + dsts = regexp(pl, '\w*_PORT\d*','match'); + if ~isempty(dsts) + for kk=1:numel(dsts) + % parse dst string + tks = regexp(dsts{kk}, '(\w*)_PORT(\d*)', 'tokens'); + for ll=1:numel(tks) + % make a connection + src = tks{ll}{1}; + srcp = tks{ll}{2}; + conn(cc).src = src; + conn(cc).srcport = str2double(srcp); + conn(cc).dst = iconn.dstblocks{1}; + conn(cc).dstport = -1; % next free port + cc = cc + 1; + end + end + else + % also look for any input variables which are block names but have + % no _PORT# suffix + for kk=1:numel(blocks) + srcblock = blocks{kk}; + % look for this srcblock in the plist but we need a clever + % regular expression to check this is an argument of the plist and + % not part of a key, for example. + tks = regexp(pl, ['[\s\[,]+(' srcblock ')[\s,\]]+'], 'tokens'); + for ll=1:numel(tks) + conn(cc).src = tks{ll}{1}; + conn(cc).srcport = 0; + conn(cc).dst = iconn.dstblocks{1}; + conn(cc).dstport = -1; % next free port + cc = cc + 1; + end + end + end + end +end + +%-------------------------------------------------------------------------- +% Convert a connection to a command. +% +function conn = cmd2conn(cmd) + + block = LTPDAworkbench.parse(cmd); + + % first get block name from end + [s,r] = strtok(block.comment, '|'); + if ~isempty(r) + blockname = {strrep(strtrim(r(2:end)), ' ', '_')}; + else + blockname = ''; + end + + [outname,outports] = fixBlockdiagramName(block.outvars{1}); + + if isempty(blockname) + blockname = block.outvars(1); + end + + innames = {}; + srcports = []; + for kk=1:numel(block.invars) + [s,p] = fixBlockdiagramName(block.invars{kk}); + if isempty(p) + p = 0; + end + innames = [innames s]; + srcports = [srcports p]; + end + + % trim all strings and build output struct + conn.srcblocks = innames; + conn.srcports = srcports; + conn.dstblocks = blockname; + conn.dstports = [1:numel(innames)]-1; + conn.plist = block.pls; + +end + +%-------------------------------------------------------------------------- +% Do some parsing of block diagram names to make sensible variable names. +% +function [name, ports] = fixBlockdiagramName(name) + + name = strtrim(name); + if name(1) == '[' && name(end) == ']' + name = name(2:end-1); + end + % match the last occurance of '_PORT' and check there is a + % number behind it + pstrs = regexp(name, '_PORT(\d*)', 'tokens'); + ports = []; + for kk=1:numel(pstrs) + ports(kk) = str2double(pstrs{kk}{1}); + end + + name = regexprep(name, '_PORT\d*', ''); +end + +%-------------------------------------------------------------------------- +% Place a block on the canvas +% +function [blockplaced,blockNames] = placeBlock(wb, blockplaced, blockPositions, ... + outname, cmds, X, dX, Y, cn, blockNames) + + % look for commands which take this output as an input + for kk=1:numel(cmds) + dstblock = LTPDAworkbench.parseCmd(cmds{kk}); + if any(strcmp(outname, dstblock.innames)) %|| ~isempty(idx) + if ~blockplaced(kk) + blockplaced(kk) = 1; + %--------- build a block + % to do this we need an minfo object; we have the + % the method name but we need the class. Either this + % is a constructor or it must have an input object + ecmd = sprintf('%s.getInfo(''%s'');', dstblock.class, dstblock.method); + ii = eval(ecmd); + X = X + dX; + Y = Y + 30; + if ~isempty(blockPositions) + pos = blockPositions{kk}; + X = pos(1); + Y = pos(2); + end + name = wb.addBlock(dstblock.outname, ii, X,Y); + blockNames = [blockNames {name}]; + % name = wb.addBlock(doutname, ii, X,Y+ (mod(cn+kk-1,2))*50); + % recursively call for this block + [blockplaced,blockNames] = placeBlock(wb, blockplaced, blockPositions, ... + dstblock.outname, cmds, X, dX, Y, cn, blockNames); + end + end + end + +end + +%-------------------------------------------------------------------------- +% Replace other block names with PORT_# +% +% #### OLD CODE ##### +% +function [pl, newconnections] = fixpl(pl,connections) + + % first we need to replace all BLOCK_PORT# with PORT_# + pl = regexprep(pl, '(\w*)_PORT(\d*)', '''PORT_$2'''); + + cn = 1; + % go through all connections + for kk=1:numel(connections) + conn = connections(kk); + % check if the plist has a token matching the src + rstr = ['[' conn.src ']']; + nstr = sprintf('''PORT_%d''', conn.dstport-1); + idx = strfind(pl, rstr); + pl = strrep(pl, rstr, nstr); + if ~isempty(idx) + newconnections(cn) = struct('src', conn.src, 'dst', conn.dst, ... + 'srcport', conn.srcport, 'dstport', conn.dstport-1); + end + end + +end + +% END