From 14b5de020c16a8b847d92437796ff32918220fdd Mon Sep 17 00:00:00 2001
From: Daniel Brown <ddb@star.sr.bham.ac.uk>
Date: Tue, 4 Feb 2014 16:30:31 +0000
Subject: [PATCH] added in const parsing. Each constant is read processed and
 added to the kat.constants dictionary. The key is the name of the constant
 and the value is a namedtuple containing the value and a list of all the
 lines that reference the constant. Once a constant has been read it replaces
 the value in any string it finds, so once the command has been parsed you can
 not change the value of the constant and expect it to change the value of the
 previously parsed parameters

---
 bin/test_const.py | 40 ++++++++++++++++++++++++++++++++++
 pykat/finesse.py  | 55 ++++++++++++++++++++++++++++++++++++++++++++---
 2 files changed, 92 insertions(+), 3 deletions(-)
 create mode 100644 bin/test_const.py

diff --git a/bin/test_const.py b/bin/test_const.py
new file mode 100644
index 0000000..3dc33b3
--- /dev/null
+++ b/bin/test_const.py
@@ -0,0 +1,40 @@
+from pykat import finesse
+from pykat.detectors import *
+from pykat.components import *
+from pykat.commands import *
+from pykat.structs import *
+
+import numpy as np
+import pylab as pl
+
+code = """
+l l1 2 0 n1
+m m1 0.99 0.01 0 n1 n2
+s cav1 $test n2 n3
+m m2 0.99 0.01 -0.1 n3 n4
+
+attr m2 m 1  # mech sus1
+
+const test 1200
+ad up_refl 0 n1
+ad low_refl 0 n1
+
+qd refl_A 0 0 n1
+qd refl_Q 0 90 n1
+qd tran_A 0 0 n4
+qd tran_Q 0 90 n4
+
+put up_refl f $x1
+put low_refl f $mx1
+
+yaxis log re:im
+"""
+
+kat = finesse.kat(kat_code=code)
+
+kat.signals.apply(kat.l1.power, 1, 0)
+kat.signals.apply(kat.m1.phi, 1, 90)
+
+kat.add(xaxis('log', [1, 1000], kat.signals.f, 100))
+
+out = kat.run(printout=0, printerr=0)
diff --git a/pykat/finesse.py b/pykat/finesse.py
index 1a7d3af..508a578 100644
--- a/pykat/finesse.py
+++ b/pykat/finesse.py
@@ -34,6 +34,8 @@ import pykat
 import warnings
 import re
 
+from collections import namedtuple
+
 from pykat.node_network import NodeNetwork
 from pykat.detectors import Detector
 from pykat.components import Component
@@ -49,7 +51,6 @@ from PyQt4.QtGui import QApplication
 
 NO_GUI = False
 NO_BLOCK = "NO_BLOCK"
-pykat_version = "0.1"
 pykat_web = "www.gwoptics.org/pykat"
 
 
@@ -236,7 +237,9 @@ class Block:
     @property
     def name(self): return self.__name
     
-class kat(object):                    
+Constant = namedtuple('Constant', 'name, value, usedBy')
+    
+class kat(object):  
         
     def __init__(self, kat_file=None, kat_code=None, katdir="", katname="", tempdir=None, tempname=None):
         
@@ -254,6 +257,7 @@ class kat(object):
         self.__tempname = tempname
         self.pykatgui = None
         self.__signals = Signals()
+        self.constants = {}
         
         # initialise default block
         self.__currentTag= NO_BLOCK
@@ -327,16 +331,61 @@ class kat(object):
     def parseKatCode(self, code):
         #commands = code.split("\n")
         self.parseCommands(code)
+
+    def processConstants(self, commands):
+        """
+        Before fully parsing a bunch of commands firstly any constants or variables
+        to be recorded and replaced.
+        """
+        constants = self.constants
+        
+        for line in commands:
+            values = line.split(' ')
+            
+            if len(values)>0 and values[0] == 'const':
+                
+                if len(values) == 3:
+                    if values[1] in constants:
+                        raise pkex.BasePyKatException('const command with the name "{0}" already used'.format(values[1]))
+                    else:
+                        constants[str(values[1])] = Constant(values[1], SIfloat(values[2]), [])
+                else:
+                    raise pkex.BasePyKatException('const command "{0}" was not the correct format'.format(line))
+        
+        commands_new = []
+        
+        print constants
+        for line in commands:
+            values = line.split(' ')
+            
+            if values[0] != 'const':
+                # check if we have a var/constant in this line
+                if line.find('$') >= 0:
+                    for key in constants.keys():
+                        if line.find('$'+key) > -1:
+                            constants[key].usedBy.append(line)
+                            line = line.replace('$'+key, str(constants[key].value))
+                        
+                        
+                commands_new.append(line)
+    
+        self.constants = constants
+        
+        return commands_new
         
     def parseCommands(self, commands):
         blockComment = False
         
         commands=self.remove_comments(commands)
+        # convert block of strings to list of lines
+        commands = commands.split('\n')
+        
+        commands=self.processConstants(commands)
         
         after_process = [] # list of commands that should be processed after 
                            # objects have been set and created
         
-        for line in commands.split("\n"):
+        for line in commands:
             #for line in commands:
             if len(line.strip()) >= 2:
                 line = line.strip()
-- 
GitLab