Mercurial > hg > ltpda
view m-toolbox/classes/@ssmblock/ssmblock.m @ 44:409a22968d5e default
Add unit tests
author | Daniele Nicolodi <nicolodi@science.unitn.it> |
---|---|
date | Tue, 06 Dec 2011 18:42:11 +0100 |
parents | f0afece42f48 |
children |
line wrap: on
line source
% SSMBLOCK a helper class for the SSM class. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % SSMBLOCK a helper class for the SSM class. % % SUPERCLASSES: ltpda_nuo < ltpda_obj % % CONSTRUCTORS: % % sb = ssmblock(name); % sb = ssmblock(name, ports); % sb = ssmblock(name, ports, desc); % % VERSION: $Id: ssmblock.m,v 1.29 2011/03/28 17:02:29 ingo Exp $ % % SEE ALSO: ltpda_obj, ltpda_nuo, ssm % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% classdef (Hidden = true) ssmblock < ltpda_nuo %% -------- Public (read/write) Properties ------- properties end % -------- Public (read/write) Properties ------- %% -------- Private read-only Properties -------- properties (SetAccess = protected) name = ''; % name of the block ports = ssmport.initObjectWithSize(1,0); % empty array of SSMPort objects description = ''; % description of the block end % -------- Private read-only Properties -------- %% -------- Dependant Properties --------- properties (Dependent) end %-------- Dependant Hidden Properties --------- %% -------- constructor ------ methods function sb = ssmblock(varargin) switch nargin case 0 % Empty constructor case 1 if isstruct(varargin{1}) % from struct sb = fromStruct(sb, varargin{1}); elseif isa(varargin{1}, 'ssmblock') % copy constructor sb = copy(varargin{1},1); else error('### Unknown single argument constructor: ssmblock(%s)', class(varargin{1})); end case 2 if isa(varargin{1}, 'org.apache.xerces.dom.DeferredElementImpl') && ... isa(varargin{2}, 'history') sb = fromDom(sb, varargin{1}, varargin{2}); else error('### Unknown two argument constructor: ssmblock(%s, %s)', class(varargin{1}), class(varargin{2})); end otherwise error('### Unknown argument constructor'); end end % -------- constructor ------ end % -------- constructor methods ------ %% -------- Declaration of Hidden Public methods -------- methods(Access = public, Hidden = true) varargout = attachToDom(varargin) function clearAllUnits(inputs) for kk=1:numel(inputs) inputs(kk).ports.clearAllUnits; end end %% counting methods for ssmblock arrays % these methods are for a whole array object, therefore cannot be % implemented as class methods function Nblocks = Nblocks(block) Nblocks = numel(block); end function Nports = Nports(block) Nports = zeros(1, numel(block)); for i=1:numel(block) Nports(i) = numel(block(i).ports); end end %% "properties" methods for ssmblock arrays % these methods are for a whole array object, therefore cannot be % implemented as class methods function blocknames = blockNames(block) blocknames = cell(1, numel(block)); for i=1:numel(block) blocknames{i} = block(i).name; end end function blockDescriptions = blockDescriptions(block) blockDescriptions = cell(1, numel(block)); for i=1:numel(block) blockDescriptions{i} = block(i).description; end end function ports = getPorts(varargin) warning('LTPDA:ssmblock', 'This function is outdated and will be deleted'); ports = []; for kk=1:nargin if isa(varargin{kk}, 'ssmblock') for ll=1:numel(varargin{kk}) ports = [ports varargin{kk}(ll).ports]; %#ok<AGROW> end end end end %% "properties" methods for ssmblock.ports in ssmblock arrays % these methods are for a whole array object, therefore cannot be % implemented as class methods function portnames = portNames(block) portnames = cell(1, numel(block)); for i=1:numel(block) portnames{i} = block(i).ports.portNames; end end function portDescriptions = portDescriptions(block) portDescriptions = cell(1, numel(block)); for i=1:numel(block) portDescriptions{i} = block(i).ports.portDescriptions; end end function portUnits = portUnits(block) portUnits = cell(1, numel(block)); for i=1:numel(block) portUnits{i} = block(i).ports.portUnits; end end %% setting methods for ssmblock arrays function block = setBlockNames(block, blockNames) if ischar(blockNames), blockNames = {blockNames}; end % checking name format is correct for i=1:numel(block) blockName = blockNames{i}; if numel(strfind(blockName,'.'))>0 error('The "." is not allowed in ssmport name') end if numel(strfind(blockName,' '))>0 error('The space " " is not allowed in ssmport name') end % modifying the port names so the prefix ("blockName.") is updated block(i).ports.modifyBlockName(block(i).name, upper(blockName)); block(i).name = upper(blockName); end end function block = setBlockDescriptions(block, desc) if ischar(desc), desc = {desc}; end for i=1:numel(block) block(i).description = desc{i}; end end function block = setPortsWithSize(block, size) for i=1:numel(block) block(i).ports = ssmport.initObjectWithSize(1, size(i)); end end %% setting methods for ssmblock.ports in ssmblock arrays function block = setPortDescriptions(block, portDesc) for i=1:numel(block) block(i).ports.setDescription(portDesc{i}); end end function block = setPortUnits(block, portUnits) for i=1:numel(block) block(i).ports.setUnits(portUnits{i}); end end % function block = setPortNames(block, portNames, blockName) function block = setPortNames(block, portNames) for i=1:numel(block) % block(i).ports.setName(portNames{i}, blockName{i}); block(i).ports.setName(portNames{i}, block(i).name); end end %% searching functions % searching ssmblock with Block names function [pos, logic] = findBlockWithNames(varargin) block = varargin{1}; names = varargin{2}; if nargin == 2 doWarningMSG = true; elseif nargin == 3 doWarningMSG = varargin{3}; else error('### unknown call') end % returns position of names found in ssmblock if ischar(names), names = {names}; end pos = zeros(1, numel(names)); logic = false(1, numel(names)); blockNames = block.blockNames; for i=1:numel(names) logic_i = strcmpi(blockNames, names{i}); if sum(logic_i)>0; pos(i) = find(logic_i,1); logic(i) = true; else % the case where "blockname" was not found if doWarningMSG display(['### No matching block was found for ' names{i} ' !!!'] ) end end end % removing position for not-found entries pos = pos(logic); end % searching Ports with Port and Block names function [blockPos portPos logic] = findPortWithMixedNames(block, names) % takes as an input: % 'ALL' / 'NONE' / cellstr(blockNames || blockName.portNames) % returns : position of port/block, and a logical array telling if % the name was found if ischar(names) if strcmpi(names, 'ALL') % case 'ALL' logic = true; blockPos = zeros(1, 0); portPos = zeros(1, 0); Nports = block.Nports; for i=1:numel(block) blockPos = [blockPos ones(1,Nports(i))*i]; %#ok<AGROW> portPos = [portPos 1:Nports(i)]; %#ok<AGROW> end return elseif strcmpi(names, 'NONE') % case 'NONE' logic = true; blockPos = zeros(1, 0); portPos = zeros(1, 0); return else % case 'portName' or 'blockName' with an input string names = {names}; end end % case 'portName' or 'blockName' logic = false(1, numel(names)); blockPos = zeros(1, 0); portPos = zeros(1, 0); portNames = block.portNames; blockNames = block.blockNames; Nports = block.Nports; for i=1:numel(names) found = strcmpi(blockNames, names{i}); if sum(found)>0; % case where the "blockName" is provided position = find(strcmpi(blockNames, names{i}), 1); blockPos = [blockPos ones(1,Nports(position))*position]; %#ok<AGROW> portPos = [portPos 1:Nports(position)]; %#ok<AGROW> logic(i) = true; else % case where a "(*)portname" is provided blockName = ssmblock.splitName(names{i}); % case where the "blockName.portname" is provided posBlock = findBlockWithNames(block, blockName, false); if ~posBlock == 0 for j=posBlock posPortLogic = strcmpi(portNames{j}, names{i}); if sum(posPortLogic)>0; blockPos = [blockPos, j]; %#ok<AGROW> portPos = [portPos find(posPortLogic, 1)]; %#ok<AGROW> logic(i) = true; break; end end end % the case where no (*).portname / blockname was found if ~logic(i) % possibility where the block name is not matching between port and block for jj=1:numel(blockNames) posPortLogic = strcmpi(portNames{jj}, names{i}); if sum(posPortLogic)>0; blockPos = [blockPos, jj]; %#ok<AGROW> portPos = [portPos find(posPortLogic, 1)]; %#ok<AGROW> logic(i) = true; break; end end end if ~logic(i) display(['### No matching block/port was found for key "' names{i} '" !!!'] ) end end end blockPos = blockPos(blockPos>0); portPos = portPos(portPos>0); end % searching Block Names with a given Block function index = makeBlockLogicalIndex(block, names) % returns a binary index for the ssmblock if ischar(names), names = {names}; end blockNames = block.blockNames; index = false(1, numel(block)); for i=1:numel(names) found = strcmpi(blockNames, names{i}); index = index + found; end index = index>0; end % searching in Mixed Names with a given Block/Ports function index = makePortLogicalIndex(block, names) % takes as an input: % 'ALL'/'NONE'/cellstr(portnames)/ % cellstr(blockName.portnames)/ cellstr(blockName_portnames) % returns a binary index for the ssmblock Nports = block.Nports; index = cell(1, numel(block)); if ischar(names) if strcmpi(names, 'ALL') % case 'ALL' for i=1:numel(block) index{i} = true(1,Nports(i)); end return elseif strcmpi(names, 'NONE') % case 'NONE' for i=1:numel(block) index{i} = false(1,Nports(i)); end return else % case 'portName' or 'blockName' names = {names}; end end if iscellstr(names) % case {'portName' or 'blockName'} [blockPos portPos] = findPortWithMixedNames(block, names); blockPos = blockPos(blockPos>0); portPos = portPos(portPos>0); for i=1:numel(block) index{i} = false(1,Nports(i)); end for i=1:numel(blockPos) index{blockPos(i)}(portPos(i)) = true; end else % case {{logical} or {double}} if ~numel(names)==numel(block) error('Number of logical/double does not match the number of blocks') end for i=1:numel(block) if isa(names{i},'logical') index{i} = names{i}; elseif isa(names{i},'double') index{i} = false(1,Nports(i)); index{i}(names{i}) = true(1, numel(names{i})); if max(names{i})>Nports(i) error(['index is too large for indexed field : ' num2str(max(names{i}))... ' instead of ' num2str(Nports(i)) ' for the block called ' block.blockNames{i}]); end else display(names) error(['input field names is not "ALL", "NONE", not a cellstr, nor a cell with logical/binaries '... 'but instead it is of class ' class(names{i}) ' for the block called ' block.blockNames{i}]) end end end end %% indexing functions function varargout = applyBlockPositionIndex(block, pos) % selects blocks depending on a double array index, order is not modified block = copy(block, nargout); warning('LTPDA:ssmblock', 'this function was modified, check behavior is okay') index = false(1, numel(block)); for i=1:numel(pos) index(pos(i)) =true; end varargout = {block(index)}; end function varargout = applyPortPositionIndex(block, blockPos, portPos) % selects ports depending on a double array index. Order of blocks % and ports are not modified block = copy(block, nargout); Nports = block.Nports; index = cell(1, numel(block)); for i=1:numel(block) index{i} = false(1,Nports(i)); end for i=1:numel(blockPos) if ~blockPos(i)==0 index{blockPos(i)}(portPos(i)) = true; end end for i=1:numel(block) block(i).ports = block(i).ports(index{i}); end varargout = {block}; end function varargout = applyBlockLogicalIndex(block, logic) % selects blocks depending on a double array index, order is not % modified block = copy(block, nargout); varargout = {block(logic)}; end function varargout = applyPortLogicalIndex(block, logic) % selects ports depending on a double array index. Order of blocks % and ports are not modified block = copy(block, nargout); for i=1:numel(block) block(i).ports = block(i).ports(logic{i}); end varargout = {block}; end %% older search functions % simple block names search % deprecated and replaced by findBlockWithNames function [res, pos] = posBlock(varargin) error('this function is deprecated and replaced by findBlockWithNames'); objs = varargin{1}; name = varargin{2}; if ~ischar(name) error('### The ''name'' must be a string but it is from the class %s.', class(name)); end res = 0; pos = 0; for ii = 1:numel(objs) if strcmpi(objs(ii).name, name) res = 1; pos = ii; break end end end % logical port indexing using complex entries % deprecated and replaced by makePortLogicalIndex varargout = makePortIndex(varargin) % can be removed now % simple block names search % deprecated and replaced by findPortWithMixedNames [blockNumber portNumber] = findPorts(block, data) % can be removed now %% older indexing functions % simple block names search % deprecated and replaced by applyPortLogicalIndex function varargout = blocksPrune(sb, id) error('this function is deprecated and replaced by applyPortLogicalIndex'); % Check input objects if ~isa(sb, 'ssmblock') error('### The first input must be a ssmblock.'); end if ~isa(id, 'cell') error('### The second input must be a cell array.') end % Decide on a deep copy or a modify sb = copy(sb, nargout); for ii=1:numel(sb) sb(ii).ports = sb(ii).ports(id{ii}); end varargout{1} = sb; end function block2 = mergeBlocksWithPositionIndex(block, blockIndex, portIndex, blockName) % takes as an input indexes of a ssmblock array, and returns one % block with all the selected ports within [groupedBlockIndex, groupedPortIndex, groupSize, nGroups, globalPortIndex] = ssmblock.groupIndexes(blockIndex, portIndex); if numel(blockIndex)~=numel(portIndex) error('different lengths of indexes!') end nPorts = numel(blockIndex); block2 = ssmblock; if numel(strfind(blockName,'.'))>0 error('The "." is not allowed in ssmport name') end if numel(strfind(blockName,' '))>0 error('The space " " is not allowed in ssmport name') end block2.name = upper(blockName); block2.ports = ssmport.initObjectWithSize(1,nPorts); for ii=1:nGroups block2.ports(globalPortIndex{ii}) = block(groupedBlockIndex(ii)).ports(groupedPortIndex{ii}); end end function varargout = combine(varargin) objs = utils.helper.collect_objects(varargin(:), 'ssmblock'); pos = findBlockWithNames(objs, objs.blockNames, false); keep = (pos == 1:numel(pos)); varargout{1} = objs(keep); end end % -------- Declaration of Public Hidden methods -------- %% -------- Declaration of Private Static methods -------- methods (Static=true, Access=private) end % -------- Declaration of Private Static methods -------- %% -------- Declaration of Public Static methods -------- methods (Static=true) function out = VEROUT() out = '$Id: ssmblock.m,v 1.29 2011/03/28 17:02:29 ingo Exp $'; end function ii = getInfo(varargin) ii = utils.helper.generic_getInfo(varargin{:}, 'ssmblock'); end function out = SETS() out = {'Default'}; end function out = getDefaultPlist(set) switch lower(set) case 'default' out = plist(); otherwise error('### Unknown set [%s]', set); end end function obj = initObjectWithSize(n,m) obj = ssmblock.newarray([n m]); end end %% -------- Declaration of Public Static methods -------- %% -------- Declaration of Hidden Static methods -------- methods(Static = true, Hidden = true) varargout = loadobj(varargin) varargout = update_struct(varargin); %% factory constructors function sb = makeBlocksWithSize(sizes, names) if ~isa(sizes,'double') error('### first argument must be a double'); end if ischar(names) names = {names}; elseif ~iscellstr(names) error('### second argument must be a char/cellstr'); end Nsb = numel(sizes); sb = ssmblock.initObjectWithSize(1,Nsb); sb.setBlockNames(names); for ii=1:Nsb sb(ii).ports = ssmport.initObjectWithSize(1,sizes(ii)); sb(ii).ports.setName('', sb(ii).name); end end function sb = makeBlocksWithData(names, descriptions, varnames, varunits, vardescriptions) if ~iscellstr(names) error('first argument must be a cellstr'); end Nsb = numel(names); % checking which parameters to set setdescriptions = Nsb == numel(descriptions); setvarnames = Nsb == numel(varnames); setvarunits = Nsb == numel(varunits); setvardescriptions = Nsb == numel(vardescriptions); sb = ssmblock.initObjectWithSize(1,Nsb); for ii=1:Nsb if setdescriptions sb(ii).description = descriptions{ii}; end if setvarnames||setvarunits||setvardescriptions % checking if ports can be initialized if setvarnames Nports = numel(varnames{ii}); elseif setvarunits Nports = numel(varunits{ii}); elseif setvardescriptions Nports = numel(vardescriptions{ii}); else Nports = 0; end sb(ii).ports = ssmport.initObjectWithSize(1,Nports); % setting ports properties if setvarnames sb(ii).ports.setName(varnames{ii}, upper(names{ii})); end if setvarunits sb(ii).ports.setUnits(varunits{ii}); end if setvardescriptions sb(ii).ports.setDescription(vardescriptions{ii}); end end % setting name in the end so the port name prefixes are modified sb(ii).setBlockNames(names{ii}); end end %% index transformation for ssmports and blockMat in ssm/reshuffle, function [groupedBlockIndex, groupedPortIndex, groupSize, nGroups, globalPortIndex] = groupIndexes(blockIndex, portIndex) % groupedBlockIndex : block # (double array) (same block can be % repeated, but never twice sided-by-side, Preserves the order % provided by user) % groupedPortIndex : port # (cell array of doubles, Preserves the order % provided by user) % groupSize : numel of each double in the cell array groupedPortIndex % nGroups : numel of the cell array % globalPortIndex : first index for each port if aill arrays are concatenated %% detecting groups diffBlock = [[0 find(diff(blockIndex)~=0)]+1 numel(blockIndex)+1]; if diffBlock(end)==1 nGroups = 0; else nGroups = numel(diffBlock)-1; end %% creating output index arrays groupedPortIndex = cell(1, nGroups); groupedBlockIndex = zeros(1, nGroups); groupSize = zeros(1, nGroups); for kk=1:nGroups groupedPortIndex{kk} = portIndex(diffBlock(kk):diffBlock(kk+1)-1); groupedBlockIndex(kk) = blockIndex(diffBlock(kk)); groupSize(kk) = diffBlock(kk+1)-diffBlock(kk); end %% final cumulative index globalPortIndex = cell(1, nGroups); sumGroupedSize = cumsum([1 groupSize]); for kk=1:nGroups globalPortIndex{kk} = sumGroupedSize(kk):(sumGroupedSize(kk+1)-1); end end %% string support for names function [blockName, portName] = splitName(name) location = strfind(name, '.'); if numel(location)>0 if numel(location)>1 error('There were more than one dot in a name!') end blockName = name(1:(location-1)); portName = name((location+1):end); else error(['Could not find the "." in the port named "' name '". ' ... 'The indexing has changed! Please copy the portname with a "." as in "BLOCKNAME.portname".' ]) end end function [blockName, portName, worked] = reSplitName(blockName, portName) warning('This function is deprecated and will be removed. Please report if it was found to be used') location = strfind(portName, '_'); worked = numel(location)>0; if worked blockName = [blockName '_' portName(1:(location(1)-1))]; portName = portName((location(1)+1):end); else blockName = ''; portName = ''; end end end %% -------- Declaration of Hidden Static methods -------- %% -------- Declaration of Private methods -------- methods(Access = private) end methods (Access = protected) varargout = fromStruct(varargin) varargout = fromDom(varargin) end end