line source
+ − % 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