comparison m-toolbox/classes/@ssmblock/ssmblock.m @ 0:f0afece42f48

Import.
author Daniele Nicolodi <nicolodi@science.unitn.it>
date Wed, 23 Nov 2011 19:22:13 +0100
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:f0afece42f48
1 % SSMBLOCK a helper class for the SSM class.
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 %
4 % SSMBLOCK a helper class for the SSM class.
5 %
6 % SUPERCLASSES: ltpda_nuo < ltpda_obj
7 %
8 % CONSTRUCTORS:
9 %
10 % sb = ssmblock(name);
11 % sb = ssmblock(name, ports);
12 % sb = ssmblock(name, ports, desc);
13 %
14 % VERSION: $Id: ssmblock.m,v 1.29 2011/03/28 17:02:29 ingo Exp $
15 %
16 % SEE ALSO: ltpda_obj, ltpda_nuo, ssm
17 %
18 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
19
20 classdef (Hidden = true) ssmblock < ltpda_nuo
21
22 %% -------- Public (read/write) Properties -------
23 properties
24 end % -------- Public (read/write) Properties -------
25
26 %% -------- Private read-only Properties --------
27 properties (SetAccess = protected)
28 name = ''; % name of the block
29 ports = ssmport.initObjectWithSize(1,0); % empty array of SSMPort objects
30 description = ''; % description of the block
31 end % -------- Private read-only Properties --------
32
33 %% -------- Dependant Properties ---------
34 properties (Dependent)
35
36 end %-------- Dependant Hidden Properties ---------
37
38 %% -------- constructor ------
39 methods
40
41 function sb = ssmblock(varargin)
42 switch nargin
43 case 0
44 % Empty constructor
45 case 1
46 if isstruct(varargin{1})
47 % from struct
48 sb = fromStruct(sb, varargin{1});
49 elseif isa(varargin{1}, 'ssmblock')
50 % copy constructor
51 sb = copy(varargin{1},1);
52 else
53 error('### Unknown single argument constructor: ssmblock(%s)', class(varargin{1}));
54 end
55 case 2
56 if isa(varargin{1}, 'org.apache.xerces.dom.DeferredElementImpl') && ...
57 isa(varargin{2}, 'history')
58 sb = fromDom(sb, varargin{1}, varargin{2});
59 else
60 error('### Unknown two argument constructor: ssmblock(%s, %s)', class(varargin{1}), class(varargin{2}));
61 end
62 otherwise
63 error('### Unknown argument constructor');
64 end
65 end % -------- constructor ------
66
67 end % -------- constructor methods ------
68
69 %% -------- Declaration of Hidden Public methods --------
70 methods(Access = public, Hidden = true)
71
72 varargout = attachToDom(varargin)
73
74 function clearAllUnits(inputs)
75 for kk=1:numel(inputs)
76 inputs(kk).ports.clearAllUnits;
77 end
78 end
79
80 %% counting methods for ssmblock arrays
81 % these methods are for a whole array object, therefore cannot be
82 % implemented as class methods
83 function Nblocks = Nblocks(block)
84 Nblocks = numel(block);
85 end
86
87 function Nports = Nports(block)
88 Nports = zeros(1, numel(block));
89 for i=1:numel(block)
90 Nports(i) = numel(block(i).ports);
91 end
92 end
93
94 %% "properties" methods for ssmblock arrays
95 % these methods are for a whole array object, therefore cannot be
96 % implemented as class methods
97 function blocknames = blockNames(block)
98 blocknames = cell(1, numel(block));
99 for i=1:numel(block)
100 blocknames{i} = block(i).name;
101 end
102 end
103
104 function blockDescriptions = blockDescriptions(block)
105 blockDescriptions = cell(1, numel(block));
106 for i=1:numel(block)
107 blockDescriptions{i} = block(i).description;
108 end
109 end
110
111 function ports = getPorts(varargin)
112 warning('LTPDA:ssmblock', 'This function is outdated and will be deleted');
113 ports = [];
114 for kk=1:nargin
115 if isa(varargin{kk}, 'ssmblock')
116 for ll=1:numel(varargin{kk})
117 ports = [ports varargin{kk}(ll).ports]; %#ok<AGROW>
118 end
119 end
120 end
121 end
122
123 %% "properties" methods for ssmblock.ports in ssmblock arrays
124 % these methods are for a whole array object, therefore cannot be
125 % implemented as class methods
126 function portnames = portNames(block)
127 portnames = cell(1, numel(block));
128 for i=1:numel(block)
129 portnames{i} = block(i).ports.portNames;
130 end
131 end
132
133 function portDescriptions = portDescriptions(block)
134 portDescriptions = cell(1, numel(block));
135 for i=1:numel(block)
136 portDescriptions{i} = block(i).ports.portDescriptions;
137 end
138 end
139
140 function portUnits = portUnits(block)
141 portUnits = cell(1, numel(block));
142 for i=1:numel(block)
143 portUnits{i} = block(i).ports.portUnits;
144 end
145 end
146
147 %% setting methods for ssmblock arrays
148 function block = setBlockNames(block, blockNames)
149 if ischar(blockNames), blockNames = {blockNames}; end
150 % checking name format is correct
151 for i=1:numel(block)
152 blockName = blockNames{i};
153 if numel(strfind(blockName,'.'))>0
154 error('The "." is not allowed in ssmport name')
155 end
156 if numel(strfind(blockName,' '))>0
157 error('The space " " is not allowed in ssmport name')
158 end
159 % modifying the port names so the prefix ("blockName.") is updated
160 block(i).ports.modifyBlockName(block(i).name, upper(blockName));
161 block(i).name = upper(blockName);
162 end
163 end
164
165 function block = setBlockDescriptions(block, desc)
166 if ischar(desc), desc = {desc}; end
167 for i=1:numel(block)
168 block(i).description = desc{i};
169 end
170 end
171
172 function block = setPortsWithSize(block, size)
173 for i=1:numel(block)
174 block(i).ports = ssmport.initObjectWithSize(1, size(i));
175 end
176 end
177
178
179 %% setting methods for ssmblock.ports in ssmblock arrays
180 function block = setPortDescriptions(block, portDesc)
181 for i=1:numel(block)
182 block(i).ports.setDescription(portDesc{i});
183 end
184 end
185
186 function block = setPortUnits(block, portUnits)
187 for i=1:numel(block)
188 block(i).ports.setUnits(portUnits{i});
189 end
190 end
191
192 % function block = setPortNames(block, portNames, blockName)
193 function block = setPortNames(block, portNames)
194 for i=1:numel(block)
195 % block(i).ports.setName(portNames{i}, blockName{i});
196 block(i).ports.setName(portNames{i}, block(i).name);
197 end
198 end
199
200 %% searching functions
201
202 % searching ssmblock with Block names
203 function [pos, logic] = findBlockWithNames(varargin)
204 block = varargin{1};
205 names = varargin{2};
206 if nargin == 2
207 doWarningMSG = true;
208 elseif nargin == 3
209 doWarningMSG = varargin{3};
210 else
211 error('### unknown call')
212 end
213 % returns position of names found in ssmblock
214 if ischar(names), names = {names}; end
215 pos = zeros(1, numel(names));
216 logic = false(1, numel(names));
217 blockNames = block.blockNames;
218 for i=1:numel(names)
219 logic_i = strcmpi(blockNames, names{i});
220 if sum(logic_i)>0;
221 pos(i) = find(logic_i,1);
222 logic(i) = true;
223 else
224 % the case where "blockname" was not found
225 if doWarningMSG
226 display(['### No matching block was found for ' names{i} ' !!!'] )
227 end
228 end
229 end
230 % removing position for not-found entries
231 pos = pos(logic);
232 end
233
234 % searching Ports with Port and Block names
235 function [blockPos portPos logic] = findPortWithMixedNames(block, names)
236 % takes as an input:
237 % 'ALL' / 'NONE' / cellstr(blockNames || blockName.portNames)
238 % returns : position of port/block, and a logical array telling if
239 % the name was found
240 if ischar(names)
241 if strcmpi(names, 'ALL')
242 % case 'ALL'
243 logic = true;
244 blockPos = zeros(1, 0);
245 portPos = zeros(1, 0);
246 Nports = block.Nports;
247 for i=1:numel(block)
248 blockPos = [blockPos ones(1,Nports(i))*i]; %#ok<AGROW>
249 portPos = [portPos 1:Nports(i)]; %#ok<AGROW>
250 end
251 return
252 elseif strcmpi(names, 'NONE')
253 % case 'NONE'
254 logic = true;
255 blockPos = zeros(1, 0);
256 portPos = zeros(1, 0);
257 return
258 else
259 % case 'portName' or 'blockName' with an input string
260 names = {names};
261 end
262 end
263 % case 'portName' or 'blockName'
264 logic = false(1, numel(names));
265 blockPos = zeros(1, 0);
266 portPos = zeros(1, 0);
267 portNames = block.portNames;
268 blockNames = block.blockNames;
269 Nports = block.Nports;
270 for i=1:numel(names)
271 found = strcmpi(blockNames, names{i});
272 if sum(found)>0;
273 % case where the "blockName" is provided
274 position = find(strcmpi(blockNames, names{i}), 1);
275 blockPos = [blockPos ones(1,Nports(position))*position]; %#ok<AGROW>
276 portPos = [portPos 1:Nports(position)]; %#ok<AGROW>
277 logic(i) = true;
278 else
279 % case where a "(*)portname" is provided
280 blockName = ssmblock.splitName(names{i});
281 % case where the "blockName.portname" is provided
282 posBlock = findBlockWithNames(block, blockName, false);
283 if ~posBlock == 0
284 for j=posBlock
285 posPortLogic = strcmpi(portNames{j}, names{i});
286 if sum(posPortLogic)>0;
287 blockPos = [blockPos, j]; %#ok<AGROW>
288 portPos = [portPos find(posPortLogic, 1)]; %#ok<AGROW>
289 logic(i) = true;
290 break;
291 end
292 end
293 end
294 % the case where no (*).portname / blockname was found
295 if ~logic(i)
296 % possibility where the block name is not matching between port and block
297 for jj=1:numel(blockNames)
298 posPortLogic = strcmpi(portNames{jj}, names{i});
299 if sum(posPortLogic)>0;
300 blockPos = [blockPos, jj]; %#ok<AGROW>
301 portPos = [portPos find(posPortLogic, 1)]; %#ok<AGROW>
302 logic(i) = true;
303 break;
304 end
305 end
306 end
307 if ~logic(i)
308 display(['### No matching block/port was found for key "' names{i} '" !!!'] )
309 end
310 end
311 end
312 blockPos = blockPos(blockPos>0);
313 portPos = portPos(portPos>0);
314 end
315
316 % searching Block Names with a given Block
317 function index = makeBlockLogicalIndex(block, names)
318 % returns a binary index for the ssmblock
319 if ischar(names), names = {names}; end
320 blockNames = block.blockNames;
321 index = false(1, numel(block));
322 for i=1:numel(names)
323 found = strcmpi(blockNames, names{i});
324 index = index + found;
325 end
326 index = index>0;
327 end
328
329 % searching in Mixed Names with a given Block/Ports
330 function index = makePortLogicalIndex(block, names)
331 % takes as an input:
332 % 'ALL'/'NONE'/cellstr(portnames)/
333 % cellstr(blockName.portnames)/ cellstr(blockName_portnames)
334 % returns a binary index for the ssmblock
335 Nports = block.Nports;
336 index = cell(1, numel(block));
337 if ischar(names)
338 if strcmpi(names, 'ALL')
339 % case 'ALL'
340 for i=1:numel(block)
341 index{i} = true(1,Nports(i));
342 end
343 return
344 elseif strcmpi(names, 'NONE')
345 % case 'NONE'
346 for i=1:numel(block)
347 index{i} = false(1,Nports(i));
348 end
349 return
350 else
351 % case 'portName' or 'blockName'
352 names = {names};
353 end
354 end
355 if iscellstr(names)
356 % case {'portName' or 'blockName'}
357 [blockPos portPos] = findPortWithMixedNames(block, names);
358 blockPos = blockPos(blockPos>0);
359 portPos = portPos(portPos>0);
360 for i=1:numel(block)
361 index{i} = false(1,Nports(i));
362 end
363 for i=1:numel(blockPos)
364 index{blockPos(i)}(portPos(i)) = true;
365 end
366 else
367 % case {{logical} or {double}}
368 if ~numel(names)==numel(block)
369 error('Number of logical/double does not match the number of blocks')
370 end
371 for i=1:numel(block)
372 if isa(names{i},'logical')
373 index{i} = names{i};
374 elseif isa(names{i},'double')
375 index{i} = false(1,Nports(i));
376 index{i}(names{i}) = true(1, numel(names{i}));
377 if max(names{i})>Nports(i)
378 error(['index is too large for indexed field : ' num2str(max(names{i}))...
379 ' instead of ' num2str(Nports(i)) ' for the block called ' block.blockNames{i}]);
380 end
381 else
382 display(names)
383 error(['input field names is not "ALL", "NONE", not a cellstr, nor a cell with logical/binaries '...
384 'but instead it is of class ' class(names{i}) ' for the block called ' block.blockNames{i}])
385 end
386 end
387 end
388 end
389
390 %% indexing functions
391 function varargout = applyBlockPositionIndex(block, pos)
392 % selects blocks depending on a double array index, order is not modified
393 block = copy(block, nargout);
394 warning('LTPDA:ssmblock', 'this function was modified, check behavior is okay')
395 index = false(1, numel(block));
396 for i=1:numel(pos)
397 index(pos(i)) =true;
398 end
399 varargout = {block(index)};
400 end
401
402 function varargout = applyPortPositionIndex(block, blockPos, portPos)
403 % selects ports depending on a double array index. Order of blocks
404 % and ports are not modified
405 block = copy(block, nargout);
406 Nports = block.Nports;
407 index = cell(1, numel(block));
408 for i=1:numel(block)
409 index{i} = false(1,Nports(i));
410 end
411 for i=1:numel(blockPos)
412 if ~blockPos(i)==0
413 index{blockPos(i)}(portPos(i)) = true;
414 end
415 end
416 for i=1:numel(block)
417 block(i).ports = block(i).ports(index{i});
418 end
419 varargout = {block};
420 end
421
422 function varargout = applyBlockLogicalIndex(block, logic)
423 % selects blocks depending on a double array index, order is not
424 % modified
425 block = copy(block, nargout);
426 varargout = {block(logic)};
427 end
428
429 function varargout = applyPortLogicalIndex(block, logic)
430 % selects ports depending on a double array index. Order of blocks
431 % and ports are not modified
432 block = copy(block, nargout);
433 for i=1:numel(block)
434 block(i).ports = block(i).ports(logic{i});
435 end
436 varargout = {block};
437 end
438
439 %% older search functions
440 % simple block names search
441 % deprecated and replaced by findBlockWithNames
442 function [res, pos] = posBlock(varargin)
443 error('this function is deprecated and replaced by findBlockWithNames');
444 objs = varargin{1};
445 name = varargin{2};
446 if ~ischar(name)
447 error('### The ''name'' must be a string but it is from the class %s.', class(name));
448 end
449 res = 0;
450 pos = 0;
451 for ii = 1:numel(objs)
452 if strcmpi(objs(ii).name, name)
453 res = 1;
454 pos = ii;
455 break
456 end
457 end
458 end
459
460 % logical port indexing using complex entries
461 % deprecated and replaced by makePortLogicalIndex
462 varargout = makePortIndex(varargin) % can be removed now
463
464 % simple block names search
465 % deprecated and replaced by findPortWithMixedNames
466 [blockNumber portNumber] = findPorts(block, data) % can be removed now
467
468 %% older indexing functions
469 % simple block names search
470 % deprecated and replaced by applyPortLogicalIndex
471 function varargout = blocksPrune(sb, id)
472 error('this function is deprecated and replaced by applyPortLogicalIndex');
473 % Check input objects
474 if ~isa(sb, 'ssmblock')
475 error('### The first input must be a ssmblock.');
476 end
477 if ~isa(id, 'cell')
478 error('### The second input must be a cell array.')
479 end
480 % Decide on a deep copy or a modify
481 sb = copy(sb, nargout);
482 for ii=1:numel(sb)
483 sb(ii).ports = sb(ii).ports(id{ii});
484 end
485 varargout{1} = sb;
486 end
487
488 function block2 = mergeBlocksWithPositionIndex(block, blockIndex, portIndex, blockName)
489 % takes as an input indexes of a ssmblock array, and returns one
490 % block with all the selected ports within
491 [groupedBlockIndex, groupedPortIndex, groupSize, nGroups, globalPortIndex] = ssmblock.groupIndexes(blockIndex, portIndex);
492
493 if numel(blockIndex)~=numel(portIndex)
494 error('different lengths of indexes!')
495 end
496 nPorts = numel(blockIndex);
497 block2 = ssmblock;
498 if numel(strfind(blockName,'.'))>0
499 error('The "." is not allowed in ssmport name')
500 end
501 if numel(strfind(blockName,' '))>0
502 error('The space " " is not allowed in ssmport name')
503 end
504 block2.name = upper(blockName);
505
506 block2.ports = ssmport.initObjectWithSize(1,nPorts);
507 for ii=1:nGroups
508 block2.ports(globalPortIndex{ii}) = block(groupedBlockIndex(ii)).ports(groupedPortIndex{ii});
509 end
510 end
511
512 function varargout = combine(varargin)
513 objs = utils.helper.collect_objects(varargin(:), 'ssmblock');
514 pos = findBlockWithNames(objs, objs.blockNames, false);
515 keep = (pos == 1:numel(pos));
516 varargout{1} = objs(keep);
517 end
518
519 end % -------- Declaration of Public Hidden methods --------
520
521 %% -------- Declaration of Private Static methods --------
522 methods (Static=true, Access=private)
523 end % -------- Declaration of Private Static methods --------
524
525 %% -------- Declaration of Public Static methods --------
526 methods (Static=true)
527
528 function out = VEROUT()
529 out = '$Id: ssmblock.m,v 1.29 2011/03/28 17:02:29 ingo Exp $';
530 end
531
532 function ii = getInfo(varargin)
533 ii = utils.helper.generic_getInfo(varargin{:}, 'ssmblock');
534 end
535
536 function out = SETS()
537 out = {'Default'};
538 end
539
540 function out = getDefaultPlist(set)
541 switch lower(set)
542 case 'default'
543 out = plist();
544 otherwise
545 error('### Unknown set [%s]', set);
546 end
547 end
548
549 function obj = initObjectWithSize(n,m)
550 obj = ssmblock.newarray([n m]);
551 end
552
553 end %% -------- Declaration of Public Static methods --------
554
555 %% -------- Declaration of Hidden Static methods --------
556 methods(Static = true, Hidden = true)
557
558 varargout = loadobj(varargin)
559 varargout = update_struct(varargin);
560
561 %% factory constructors
562 function sb = makeBlocksWithSize(sizes, names)
563 if ~isa(sizes,'double')
564 error('### first argument must be a double');
565 end
566 if ischar(names)
567 names = {names};
568 elseif ~iscellstr(names)
569 error('### second argument must be a char/cellstr');
570 end
571 Nsb = numel(sizes);
572 sb = ssmblock.initObjectWithSize(1,Nsb);
573 sb.setBlockNames(names);
574 for ii=1:Nsb
575 sb(ii).ports = ssmport.initObjectWithSize(1,sizes(ii));
576 sb(ii).ports.setName('', sb(ii).name);
577 end
578 end
579
580 function sb = makeBlocksWithData(names, descriptions, varnames, varunits, vardescriptions)
581 if ~iscellstr(names)
582 error('first argument must be a cellstr');
583 end
584 Nsb = numel(names);
585 % checking which parameters to set
586 setdescriptions = Nsb == numel(descriptions);
587 setvarnames = Nsb == numel(varnames);
588 setvarunits = Nsb == numel(varunits);
589 setvardescriptions = Nsb == numel(vardescriptions);
590 sb = ssmblock.initObjectWithSize(1,Nsb);
591 for ii=1:Nsb
592 if setdescriptions
593 sb(ii).description = descriptions{ii};
594 end
595 if setvarnames||setvarunits||setvardescriptions
596 % checking if ports can be initialized
597 if setvarnames
598 Nports = numel(varnames{ii});
599 elseif setvarunits
600 Nports = numel(varunits{ii});
601 elseif setvardescriptions
602 Nports = numel(vardescriptions{ii});
603 else
604 Nports = 0;
605 end
606 sb(ii).ports = ssmport.initObjectWithSize(1,Nports);
607 % setting ports properties
608 if setvarnames
609 sb(ii).ports.setName(varnames{ii}, upper(names{ii}));
610 end
611 if setvarunits
612 sb(ii).ports.setUnits(varunits{ii});
613 end
614 if setvardescriptions
615 sb(ii).ports.setDescription(vardescriptions{ii});
616 end
617 end
618 % setting name in the end so the port name prefixes are modified
619 sb(ii).setBlockNames(names{ii});
620 end
621
622 end
623
624 %% index transformation for ssmports and blockMat in ssm/reshuffle,
625 function [groupedBlockIndex, groupedPortIndex, groupSize, nGroups, globalPortIndex] = groupIndexes(blockIndex, portIndex)
626 % groupedBlockIndex : block # (double array) (same block can be
627 % repeated, but never twice sided-by-side, Preserves the order
628 % provided by user)
629 % groupedPortIndex : port # (cell array of doubles, Preserves the order
630 % provided by user)
631 % groupSize : numel of each double in the cell array groupedPortIndex
632 % nGroups : numel of the cell array
633 % globalPortIndex : first index for each port if aill arrays are concatenated
634 %% detecting groups
635 diffBlock = [[0 find(diff(blockIndex)~=0)]+1 numel(blockIndex)+1];
636 if diffBlock(end)==1
637 nGroups = 0;
638 else
639 nGroups = numel(diffBlock)-1;
640 end
641 %% creating output index arrays
642 groupedPortIndex = cell(1, nGroups);
643 groupedBlockIndex = zeros(1, nGroups);
644 groupSize = zeros(1, nGroups);
645 for kk=1:nGroups
646 groupedPortIndex{kk} = portIndex(diffBlock(kk):diffBlock(kk+1)-1);
647 groupedBlockIndex(kk) = blockIndex(diffBlock(kk));
648 groupSize(kk) = diffBlock(kk+1)-diffBlock(kk);
649 end
650 %% final cumulative index
651 globalPortIndex = cell(1, nGroups);
652 sumGroupedSize = cumsum([1 groupSize]);
653 for kk=1:nGroups
654 globalPortIndex{kk} = sumGroupedSize(kk):(sumGroupedSize(kk+1)-1);
655 end
656 end
657
658
659 %% string support for names
660 function [blockName, portName] = splitName(name)
661 location = strfind(name, '.');
662 if numel(location)>0
663 if numel(location)>1
664 error('There were more than one dot in a name!')
665 end
666 blockName = name(1:(location-1));
667 portName = name((location+1):end);
668 else
669 error(['Could not find the "." in the port named "' name '". ' ...
670 'The indexing has changed! Please copy the portname with a "." as in "BLOCKNAME.portname".' ])
671 end
672 end
673
674 function [blockName, portName, worked] = reSplitName(blockName, portName)
675 warning('This function is deprecated and will be removed. Please report if it was found to be used')
676 location = strfind(portName, '_');
677 worked = numel(location)>0;
678 if worked
679 blockName = [blockName '_' portName(1:(location(1)-1))];
680 portName = portName((location(1)+1):end);
681 else
682 blockName = '';
683 portName = '';
684 end
685 end
686
687 end %% -------- Declaration of Hidden Static methods --------
688
689 %% -------- Declaration of Private methods --------
690 methods(Access = private)
691 end
692
693 methods (Access = protected)
694 varargout = fromStruct(varargin)
695 varargout = fromDom(varargin)
696 end
697
698 end