From 5247e53fb7a889ff35c64eebfb6487b6cdcaafed Mon Sep 17 00:00:00 2001
From: Federico Felici <federico.felici@epfl.ch>
Date: Wed, 24 Nov 2021 13:10:58 +0100
Subject: [PATCH] Class cleanups to allow adding arrays of parameters

---
 code/classes/SCDclass_algo.m            |   7 +-
 code/classes/SCDclass_expcode.m         |   4 +-
 code/classes/SCDclass_mdsobjcontainer.m | 134 ++++++++++--------------
 code/classes/SCDclass_mdspar.m          |  42 +++++---
 4 files changed, 88 insertions(+), 99 deletions(-)

diff --git a/code/classes/SCDclass_algo.m b/code/classes/SCDclass_algo.m
index 468a794..8a72158 100644
--- a/code/classes/SCDclass_algo.m
+++ b/code/classes/SCDclass_algo.m
@@ -484,15 +484,11 @@ classdef SCDclass_algo
           end
           
           for ii=1:numel(param)
-            param(ii).bind(obj.modelname, obj.datadictionary, tpname);
+            param(ii) = param(ii).bind(obj.modelname, obj.datadictionary, tpname);
           end
           obj.mdscontainer=obj.mdscontainer.addparameter(param);
         end
         
-        function obj = bindparameters(obj)
-            obj.mdscontainer=obj.mdscontainer.bindparameters(obj.modelname, obj.datadictionary, obj.exportedtps);        
-        end
-        
         function obj = printparameters(obj)
             obj.mdscontainer=obj.mdscontainer.printparameters;
         end
@@ -636,7 +632,6 @@ classdef SCDclass_algo
           % an algorithm block diagram
           % should pass ctrl-d (instandalone opening)
           % after this call
-          obj.bindparameters; % bind mds parameters
           obj.updatetemplatetp;
           obj.buildworkspacetpstruct;
           SCDconf_setConf('sim');
diff --git a/code/classes/SCDclass_expcode.m b/code/classes/SCDclass_expcode.m
index f69343e..55baaa0 100644
--- a/code/classes/SCDclass_expcode.m
+++ b/code/classes/SCDclass_expcode.m
@@ -378,7 +378,7 @@ classdef SCDclass_expcode
           if(numel(obj.exportedtps)>0)
             for ii=1:numel(obj.exportedtps), fprintf('  ''%s''\n', char(obj.exportedtps{ii})); end
           end
-          fprintf('* Configured MDS tunparams objects: %d (use printparameters method for details)\n', obj.mdscontainer.numparams);
+          fprintf('* Configured MDS tunparams objects: %d (use printparameters method for details)\n', obj.mdscontainer.getnumparams);
           fprintf('* Configured MDS wavegens objects: %d (use printwavegens method for details)\n', obj.mdscontainer.numwavegens);
           fprintf('* Configured general purpose tasks: %d (use printtasks method for details)\n', obj.taskcontainer.numtasks);
           fprintf('* Configured init scripts: %d (use printinits method for details)\n', numel(obj.algoobjlist));
@@ -489,6 +489,8 @@ classdef SCDclass_expcode
           % Importing algorithm MDS objects into the main mdscontainer,
           % filling base structure name
           algomdscontainer = algoObj.getmdscontainer;
+          
+          % import wavegens
           basewgstruct     = sprintf('SCDsimdata.SCDnode%02d%02d_simdata.wavegen', node, cpu);
           algomdscontainer = algomdscontainer.setwavegenbasestruct(basewgstruct);
           obj.mdscontainer = obj.mdscontainer.importmdswavegens(algomdscontainer);
diff --git a/code/classes/SCDclass_mdsobjcontainer.m b/code/classes/SCDclass_mdsobjcontainer.m
index fd1b6b9..9198a32 100644
--- a/code/classes/SCDclass_mdsobjcontainer.m
+++ b/code/classes/SCDclass_mdsobjcontainer.m
@@ -9,9 +9,7 @@ classdef SCDclass_mdsobjcontainer
     % SCDclass_mdswavegen (and childrens)
     
     properties
-        numparams           % number of configured params objects
         mdsparams           % params objects array
-        numwavegens         % number of configured wavegens objects
         mdswavegens         % wavegens objects array
         simstructlist       % list of names of simstructs to be transferred to
                             % base workspace upon expcode setup
@@ -22,18 +20,15 @@ classdef SCDclass_mdsobjcontainer
     methods
         function obj = SCDclass_mdsobjcontainer()
             % contructor, empty container
-            obj.numparams=0;
-            obj.numwavegens=0;  
             obj.modeltoactualize='all';
             obj.modeltogenerate='all';
         end
         
         function obj = addparameter(obj, param)
             % Adds one or more parameter objects to list of params
-            obj.mdsparams = [obj.mdsparams; param];
-            obj.numparams = obj.numparams + numel(param);  
+            obj.mdsparams = [obj.mdsparams, param];
         end
-        
+
         function obj = printparameters(obj)
             % prints the parameters object list
             if obj.numparams>0
@@ -59,33 +54,13 @@ classdef SCDclass_mdsobjcontainer
             end
         end
 
-        function obj = bindparameters(obj, modelname, datadictionary, exportedtps)
-          % bind mds parameters to their model, data dictionary and tunable parameter
-            if obj.numparams>0   
-                for ii=1:obj.numparams
-                    obj.mdsparams(ii)=obj.mdsparams(ii).setmodelname(modelname);
-                    obj.mdsparams(ii)=obj.mdsparams(ii).setdatadictionary(datadictionary);
-                end
-                if numel(exportedtps)>0
-                    for ii=1:obj.numparams
-                        obj.mdsparams(ii)=obj.mdsparams(ii).setparamstructure(exportedtps{end});
-                    end
-                end        
-            end
-        end
-         
         function obj = addwavegen(obj, wavegen)
-            % adds a wavegen object
-            if obj.numwavegens==0
-                obj.mdswavegens=wavegen;
-            else
-                obj.mdswavegens=[obj.mdswavegens; wavegen];
-            end 
-            obj.numwavegens=obj.numwavegens+1;
+            % adds one or more wavegen objects
+            obj.mdswavegens=[obj.mdswavegens; wavegen];
         end
         
         function obj = bindlastwavegen(obj, modelname, datadictionary, timingsrc)
-            if obj.numwavegens>0
+            if obj.getnumwavegens>0
                 obj.mdswavegens(end)=obj.mdswavegens(end).setmodelname(modelname);
                 obj.mdswavegens(end)=obj.mdswavegens(end).setdatadictionary(datadictionary);
                 obj.mdswavegens(end)=obj.mdswavegens(end).settiminginfo(timingsrc);                
@@ -93,8 +68,8 @@ classdef SCDclass_mdsobjcontainer
         end
         
         function obj = setwavegenbasestruct(obj, basestruct)
-            if obj.numwavegens>0
-                for ii=1:obj.numwavegens
+            if obj.getnumwavegens>0
+                for ii=1:obj.getnumwavegens
                     obj.mdswavegens(ii)=obj.mdswavegens(ii).setbasestruct(basestruct);
                 end
             end    
@@ -102,8 +77,8 @@ classdef SCDclass_mdsobjcontainer
         
         function obj = printwavegens(obj)
             % prints the wavegen list
-            if obj.numwavegens>0
-               for ii=1:obj.numwavegens
+            if obj.getnumwavegens>0
+               for ii=1:obj.getnumwavegens
                   obj.mdswavegens(ii).printinfo();
                end
             end
@@ -112,8 +87,8 @@ classdef SCDclass_mdsobjcontainer
         function obj = actualizewavegens(obj, shot)
             % actualize the wavegen waves timeseries
             % naive version, a mds connection is called for every object
-            if obj.numwavegens>0
-               for ii=1:obj.numwavegens
+            if obj.getnumwavegens>0
+               for ii=1:obj.getnumwavegens
                   if(strcmp(obj.modeltoactualize,'all'))
                     obj.mdswavegens(ii).actualizedata(shot);
                   else
@@ -128,8 +103,8 @@ classdef SCDclass_mdsobjcontainer
         function obj = cleanwavegens(obj)
             % clean wavegens leaving a consistent (with model buses)
             % empty timeseries data structure
-            if obj.numwavegens>0
-               for ii=1:obj.numwavegens
+            if obj.getnumwavegens>0
+               for ii=1:obj.getnumwavegens
                   obj.mdswavegens(ii).cleandata;
                end
             end
@@ -138,47 +113,44 @@ classdef SCDclass_mdsobjcontainer
         function obj = importmdsparams(obj, source)
             % parameters import
 
-            destparamtargets={};
-            if obj.numparams>0             
-                for ii=1:obj.numparams
-                    destparamtargets{end+1}=obj.mdsparams(ii).gettargetparam;
-                end
-            end
-                           
-            numparamstoimport = source.numparams;
-            paramstoimport = source.mdsparams;
+            numparamstoimport = source.getnumparams;
+            paramstoimport    = source.mdsparams;
             
-            if numparamstoimport>0
-                for ii=1:numparamstoimport
-                    if ~ismember(paramstoimport(ii).gettargetparam, destparamtargets)
-                        obj=obj.addparameter(paramstoimport(ii));
-                    else
-                        warning('SCDclass_mdsobjcontainer:importmdsobjects','A mds object driving ''%s'' is already present in the dest. expcode, skipping!',paramstoimport(ii).gettargetparam);
-                    end
+            
+            exclusionlist = false(size(paramstoimport));
+            if ~isempty(obj.mdsparams)
+              destparamlist = obj.mdsparams.gettargetparam; % existing destination parameter names
+              for ii=1:numparamstoimport
+                targetparam = paramstoimport(ii).gettargetparam;
+                if ismember(destparamlist,targetparam)
+                  warning('SCDclass_mdsobjcontainer:importmdsobjects',...
+                  'An mds object driving ''%s'' is already present in the destination expcode, skipping!',...
+                  targetparam);
+                  exclusionlist(ii) = true;
                 end
+              end  
             end
-        end   
+            
+            % add non-excluded parameters
+            obj=obj.addparameter(paramstoimport(~exclusionlist));
+        end
            
         function obj = importmdswavegens(obj, source)        
             % wavegens import     
-            destwavegentargets={};
-            if obj.numwavegens>0             
-                for ii=1:obj.numwavegens
-                    destwavegentargets{end+1}=obj.mdswavegens(ii).gettargetwavegen;
-                end
+            destwavegentargets=cell(1,obj.getnumwavegens);
+            for ii=1:obj.getnumwavegens
+              destwavegentargets{ii}=obj.mdswavegens(ii).gettargetwavegen;
             end
                            
-            numwavegenstoimport = source.numwavegens;
+            numwavegenstoimport = source.getnumwavegens;
             wavegenstoimport = source.mdswavegens;
             
-            if numwavegenstoimport>0
-                for ii=1:numwavegenstoimport
-                    if ~ismember(wavegenstoimport(ii).gettargetwavegen, destwavegentargets)
-                        obj=obj.addwavegen(wavegenstoimport(ii));
-                    else
-                        warning('SCDclass_mdsobjcontainer:importmdsobjects','A mds object driving ''%s'' is already present in the dest. expcode, skipping!',wavegenstoimport(ii).gettargetwavegen);
-                    end
-                end
+            for ii=1:numwavegenstoimport
+              if ~ismember(wavegenstoimport(ii).gettargetwavegen, destwavegentargets)
+                obj=obj.addwavegen(wavegenstoimport(ii));
+              else
+                warning('SCDclass_mdsobjcontainer:importmdsobjects','A mds object driving ''%s'' is already present in the dest. expcode, skipping!',wavegenstoimport(ii).gettargetwavegen);
+              end
             end
          
         end
@@ -197,7 +169,7 @@ classdef SCDclass_mdsobjcontainer
               loaderStr = sprintf('\n\n+MDSParameters = {\n Class=MDSObjLoader\n Shot=MDSSRCSHOT\n');              
               fprintf("%s",loaderStr);
          
-              for ii=1:obj.numparams
+              for ii=1:obj.getnumparams
                 mymdsparam = obj.mdsparams(iorder(ii));
 
                 currentServer = mymdsparam.getMDSserver;
@@ -220,7 +192,7 @@ classdef SCDclass_mdsobjcontainer
               fprintf(" }\n}\n\n");
 
             otherwise
-              for ii=1:obj.numparams
+              for ii=1:obj.getnumparams
                 if(strcmp(obj.modeltogenerate,obj.mdsparams(ii).getmodelname))
                   str=obj.mdsparams(ii).genMARTe2entry(shot);
                   fprintf("  %s\n",str);
@@ -232,14 +204,14 @@ classdef SCDclass_mdsobjcontainer
           for ii=2:numel(marteparlist)
              for jj=1:ii-1
                  if strcmp(marteparlist(ii), marteparlist(jj))
-                     fprintf("WARNING: found identical MARTe par. names here: %s", marteparlist(ii));
+                     fprintf("WARNING: found identical MARTe par. names here: %s", marteparlist{ii});
                  end
              end
           end
         end
         
         function autopopulateMDSparams(obj, shot)
-              for ii=1:obj.numparams
+              for ii=1:obj.getnumparams
                 if(strcmp(obj.modeltogenerate,obj.mdsparams(ii).getmodelname))
                   obj.mdsparams(ii).autopopulatemds(shot);
                 end
@@ -247,7 +219,7 @@ classdef SCDclass_mdsobjcontainer
         end
         
         function autopopulateMDSwavegens(obj, shot)
-              for ii=1:obj.numwavegens
+              for ii=1:obj.getnumwavegens
                 if(strcmp(obj.modeltogenerate,obj.mdswavegens(ii).getmodelname))
                   obj.mdswavegens(ii).autopopulatemds(shot);
                 end
@@ -275,7 +247,7 @@ classdef SCDclass_mdsobjcontainer
         end
                
         function printMARTe2wgconfig(obj, shot)
-          for ii=1:obj.numwavegens
+          for ii=1:obj.getnumwavegens
             if(strcmp(obj.modeltogenerate,'all'))
               str=obj.mdswavegens(ii).genMARTe2entry(shot);
               fprintf("   %s\n",str);
@@ -309,7 +281,7 @@ classdef SCDclass_mdsobjcontainer
             for elem=1:nelems
                 signame=bus.Elements(elem).Name;
                 found=false;
-                for wgs=1:obj.numwavegens
+                for wgs=1:obj.getnumwavegens
                     if(strcmp(obj.mdswavegens(wgs).gettarget,signame))
                         found=true;
                         break;
@@ -388,5 +360,15 @@ classdef SCDclass_mdsobjcontainer
           end
           [~,iorder] = sortrows(mdsservertree);
         end
+        
+        function num = getnumparams(obj)
+          % get number or parameters
+          num = numel(obj.mdsparams);
+        end
+        
+         function num = getnumwavegens(obj)
+          % get number or parameters
+          num = numel(obj.mdswavegens);
+        end
     end
 end
diff --git a/code/classes/SCDclass_mdspar.m b/code/classes/SCDclass_mdspar.m
index e0bb098..9797b84 100644
--- a/code/classes/SCDclass_mdspar.m
+++ b/code/classes/SCDclass_mdspar.m
@@ -227,17 +227,9 @@ classdef SCDclass_mdspar < matlab.mixin.Heterogeneous
         end
         
         function obj = bind(obj,modelname,datadictionary,exportedtp)
-          obj.setmodelname(modelname);
-          obj.setdatadictionary(datadictionary);
-          obj.setparamstructure(exportedtp);
-        end
-          
-        function out = gettargetparam(obj)
-            out = obj.modelparam;
-        end
-        
-        function out = gettargetparammarte(obj)
-            out = obj.modelparammarte;            
+          obj = obj.setmodelname(modelname);
+          obj = obj.setdatadictionary(datadictionary);
+          obj = obj.setparamstructure(exportedtp);
         end
         
         function [mdsserver] = getMDSserver(obj)
@@ -249,6 +241,8 @@ classdef SCDclass_mdspar < matlab.mixin.Heterogeneous
         end
         
         function obj = setparamstructure(obj, structname)
+            assert(nargout==1,'must set out argument for set method')
+
             %obj.modelparam = [structname '.' obj.modelparam];
             if(isempty(obj.modeltpstruct))
                 obj.modeltpstruct = structname;
@@ -258,16 +252,32 @@ classdef SCDclass_mdspar < matlab.mixin.Heterogeneous
         end
         
         function obj = setmodelname(obj, modelname)
-            if(isempty(obj.modelname))
-                obj.modelname = modelname;
-            end
+          assert(nargout==1,'must set out argument for set method')
+          obj.modelname = modelname;
         end
         
         function obj = setdatadictionary(obj, ddname)
-            if(isempty(obj.datadictionary))
-                obj.datadictionary = ddname;
+          assert(nargout==1,'must set out argument for set method')
+          obj.datadictionary = ddname;
+        end
+    end
+    
+    methods(Sealed) % works for heterogeneous class arrays
+        function out = gettargetparam(obj)
+            if numel(obj) == 1
+              out = obj.modelparam;
+            else
+              out = {obj.modelparam}';
             end
         end
+        
+        function out = gettargetparammarte(obj)
+          if numel(obj) == 1
+            out = obj.modelparammarte; 
+          else
+            out = {obj.modelparammarte}';
+          end
+        end
     end
     
     methods 
-- 
GitLab