From f16c95b69b21befae0e98b60c99b8e440dbffe07 Mon Sep 17 00:00:00 2001
From: Daniel Brown <ddb@star.sr.bham.ac.uk>
Date: Tue, 16 Aug 2016 18:11:38 -0700
Subject: [PATCH] Adding parsing for put commands. This reads in put commands
 and links them to the objects now. Disabling the object that is being put to
 or the thing that is putting will ensure that the put command isn't
 generated, so no need to use removeLines for puts now

---
 pykat/commands.py              | 41 ++++++++++++++++++-------
 pykat/finesse.py               | 55 ++++++++++++++++++++++++++++++++--
 pykat/param.py                 | 45 +++++++++++++++++++++-------
 work_in_progress/optivis_ex.py |  1 +
 4 files changed, 119 insertions(+), 23 deletions(-)

diff --git a/pykat/commands.py b/pykat/commands.py
index 241f7b7..5df7a6b 100644
--- a/pykat/commands.py
+++ b/pykat/commands.py
@@ -34,6 +34,7 @@ class Command(object):
         self.tag = None
         self.__removed = False
         self.__name = name.strip("*")
+        self._putters_to_register = []
         
     def getFinesseText(self):
         """ Base class for individual finesse optical components """
@@ -48,10 +49,16 @@ class Command(object):
         Called when this component has been added to a kat object
         """
         self._kat = kat
+        
+        for _ in self._putters_to_register:
+            kat.registerVariable(_.name, _)
 
     def remove(self):
         self._kat.remove(self)
         self.__removed = True
+        
+        for _ in self._putters_to_register:
+            kat.unregisterVariable(_.name)
     
     @property
     def name(self): return self.__name
@@ -95,14 +102,19 @@ class func(Command):
         
         self.value = value
         self.noplot = False
+        self.enabled = True
+        
+        self.output = putter(name, self)
+        self._putters_to_register.append(self.output)
         
     def getFinesseText(self):
         rtn = []
 
-        if self.noplot:
-            rtn.append("noplot " + self.name)
+        if self.enabled:
+            if self.noplot:
+                rtn.append("noplot " + self.name)
         
-        rtn.append("func {name} = {value}".format(name=self.name, value=str(self.value)))
+            rtn.append("func {name} = {value}".format(name=self.name, value=str(self.value)))
 
         return rtn
 
@@ -118,10 +130,7 @@ class func(Command):
             return func(v2[0].split()[1], v2[1]) 
         else:
             raise pkex.BasePyKatException("'{0}' not a valid Finesse func command".format(line))
-        
-        
-        
-
+            
 
 class lock(Command):
     def __init__(self, name, variable, gain, accuracy, singleLock=False):
@@ -132,6 +141,10 @@ class lock(Command):
         self.__accuracy = accuracy
         self.singleLock = singleLock
         self.enabled = True
+        
+        
+        self.output = putter(name, self)
+        self._putters_to_register.append(self.output)
 
 
     @staticmethod
@@ -354,9 +367,12 @@ class xaxis(Command):
         
         self._axis_type = axis_type
 
-        self.x = putter("x1")
-        self.mx = putter("mx1")
+        self.x = putter("x1", self)
+        self.mx = putter("mx1", self)
 
+        self._putters_to_register.append(self.x)
+        self._putters_to_register.append(self.mx)
+        
         if scale == "lin":
             scale = Scale.linear
         elif scale == "log":
@@ -433,8 +449,11 @@ class xaxis(Command):
 class x2axis(xaxis):
     def __init__(self, scale, limits, param, steps, comp=None, axis_type="x2axis"):
         xaxis.__init__(self, scale, limits, param, steps, comp=comp, axis_type=axis_type)
-        self.x = putter("x2")
-        self.mx = putter("mx2")
+        self.x = putter("x2", self)
+        self.mx = putter("mx2", self)
+
+        self._putters_to_register.append(self.x)
+        self._putters_to_register.append(self.mx)
 
     @staticmethod
     def parseFinesseText(text):
diff --git a/pykat/finesse.py b/pykat/finesse.py
index cdb5a2a..94403c9 100644
--- a/pykat/finesse.py
+++ b/pykat/finesse.py
@@ -745,6 +745,7 @@ class kat(object):
         self.vacuum = []
         self.__prevrunfilename = None
         self.printmatrix = None
+        self.__variables = {}
         
         # initialise default block
         self.__currentTag= NO_BLOCK
@@ -1005,6 +1006,31 @@ class kat(object):
     def __str__(self):
          return "".join(self.generateKatScript())
          
+    def getVariable(self, name):
+        if name not in self.__variables:
+            raise pkex.BasePyKatException("Finesse variable `$%s` does not exist." % name)
+            
+        return self.__variables[name]
+    
+    def registerVariable(self, name, putter):
+        if '$' in name:
+            raise pkex.BasePyKatException("Finesse variable name `%s` should not include the `$` symbol as it is added internally." % name)
+            
+        assert(putter is not None)
+        assert(name == putter.name)
+        
+        if name in self.__variables:
+            raise pkex.BasePyKatException("Finesse variable name `%s` already exists." % name)
+            
+        self.__variables[name] = putter
+        
+    def unregisterVariable(self, name):
+        del self.__variables[name]
+    
+    def printVariables(self):
+        for key in self.__variables:
+            print("$" + key, "::::", "owner =", self.__variables[key].owner.name, ", use count =", self.__variables[key].putCount)
+    
     def parseCommands(self, commands, blocks=None, addToBlock=None):
         try:
             if addToBlock is not None and blocks is not None:
@@ -1182,6 +1208,8 @@ class kat(object):
                         after_process.append((line, self.__currentTag))
                     elif(first == "noplot"):
                         after_process.append((line, self.__currentTag))
+                    elif(first == "put" or first == "put*"):
+                        after_process.append((line, self.__currentTag))
                     else:
                         if self.verbose:
                             print ("Parsing `{0}` into pykat object not implemented yet, added as extra line.".format(line))
@@ -1231,7 +1259,30 @@ class kat(object):
                         raise pkex.BasePyKatException("noplot command `{0}` refers to non-existing detector".format(line))
                         
                     getattr(self, rest).noplot = True
+                
+                elif (first == "put" or first =="put*"):
+                    alt = first == "put*"
+                    
+                    values = line.split()
+                    obj = values[1]
+                    target = values[2]
+                    variable = values[3]
+                    
+                    if not hasattr(self, obj):
+                        raise pkex.BasePyKatException("put command `{0}` refers to non-existing component".format(line))
+                    
+                    obj = getattr(self, obj)
                     
+                    if not hasattr(obj, target):
+                        raise pkex.BasePyKatException("put command component `{0}` does not have a parameter `{1}`".format(line, target))
+                        
+                    target = getattr(obj, target)
+                    
+                    if not target.isPutable:
+                        raise pkex.BasePyKatException("put command `{0}` parameter `{1}` cannot be put to".format(line, target))
+                        
+                    target.put(self.getVariable(variable.replace('$', '')), alt)
+                 
                 elif (first == "scale"):
                     v = line.split()
                     accepted = ["psd","psd_hf","asd","asd_hf","meter", "ampere", "deg", "rad", "1/deg", "1/rad",]
@@ -1641,14 +1692,14 @@ class kat(object):
             #if len(self.detectors.keys()) > 0: 
             
             if hasattr(self, "x2axis") and self.noxaxis == False:
-                [r.x,r.y,r.z,hdr] = self.readOutFile(outfile)
+                [r.x, r.y, r.z, hdr] = self.readOutFile(outfile)
             
                 r.xlabel = hdr[0]
                 r.ylabel = hdr[1]
                 r.zlabels = [s.strip() for s in hdr[2:]]
                 #r.zlabels = map(str.strip, hdr[2:])
             else:
-                [r.x,r.y,hdr] = self.readOutFile(outfile)
+                [r.x, r.y, hdr] = self.readOutFile(outfile)
                 
                 r.xlabel = hdr[0]
                 r.ylabels = [s.strip() for s in hdr[1:]]
diff --git a/pykat/param.py b/pykat/param.py
index 264de77..72740a8 100644
--- a/pykat/param.py
+++ b/pykat/param.py
@@ -12,7 +12,8 @@ class putable(object):
     Objects that inherit this should be able to have something `put` to it.
     Essentially this means you could write Finesse commands like
     
-    put this parameter value
+    param.put(kat.xaxis.x)
+    
     """
     __metaclass__ = abc.ABCMeta
     
@@ -20,31 +21,44 @@ class putable(object):
         self._parameter_name = parameter_name
         self._component_name = component_name
         self._putter = None
+        self._alt = False
         self._isPutable  = isPutable
     
     @property
     def isPutable(self): return self._isPutable
     
-    def put(self, var):
-    
+    def put(self, var, alt):
         if not isinstance(var, putter):
-            raise pkex.BasePyKatException("var was not something that can be `put` as a value")
+            raise pkex.BasePyKatException("`%s` was not something that can be `put` to a parameter" % str(var))
         
-        if self._putter != None:
+        if self._putter is not None:
             self._putter.put_count -= 1
             self._putter.putees.remove(self)
         
         self._putter = var
+        self._alt = alt
         
-        if var != None:
+        if var is not None:
             self._putter.put_count += 1
             self._putter.putees.append(self)
         
     def _getPutFinesseText(self):
         rtn = []
-        # if something is being put to this 
-        if self._putter != None:
-            rtn.append("put {comp} {param} ${value}".format(comp=self._component_name, param=self._parameter_name, value=self._putter.put_name()))
+        
+        if self._putter is not None:
+            putter_enabled = True
+            
+            if hasattr(self._putter.owner, 'enabled'):
+                putter_enabled = self._putter.owner.enabled
+                                
+            if putter_enabled:
+                if self._alt:
+                    alt = '*'
+                else:
+                    alt = ''
+    
+                # if something is being put to this 
+                rtn.append("put{alt} {comp} {param} ${value}".format(alt=alt, comp=self._component_name, param=self._parameter_name, value=self._putter.put_name()))
         
         return rtn
             
@@ -54,11 +68,22 @@ class putter(object):
     object.
     """
     
-    def __init__(self, put_name, isPutter=True):
+    def __init__(self, put_name, owner, isPutter=True):
         self._put_name = put_name
         self.put_count = 0
         self._isPutter = isPutter
         self.putees = [] # list of params that this puts to
+        self.__owner = owner
+        assert(owner is not None)
+    
+    @property
+    def owner(self): return self.__owner
+    
+    @property
+    def name(self): return self._put_name
+    
+    @property
+    def putCount(self): return self.put_count
     
     @property
     def isPutter(self): return self._isPutter
diff --git a/work_in_progress/optivis_ex.py b/work_in_progress/optivis_ex.py
index a0806ee..d291127 100644
--- a/work_in_progress/optivis_ex.py
+++ b/work_in_progress/optivis_ex.py
@@ -22,6 +22,7 @@ attr m1 Rc -500
 attr m2 Rc 500
 cav c1 m1 n4b m2 n7a
 
+pd P n5b
 maxtem 0
 noxaxis
 """)
-- 
GitLab