From db5ee6670d2831e26469ad20e5f64d8273b77e37 Mon Sep 17 00:00:00 2001
From: Daniel Brown <ddb@star.sr.bham.ac.uk>
Date: Mon, 25 Jan 2016 00:57:39 +0000
Subject: [PATCH] fixing xd and tf inputs

---
 bin/test_const.py  |  4 ++-
 pykat/commands.py  | 56 ++++++++++++++++++++++++++++++++++---
 pykat/detectors.py | 69 +++++++++++++++++++++-------------------------
 pykat/finesse.py   | 14 ++++++++--
 4 files changed, 99 insertions(+), 44 deletions(-)

diff --git a/bin/test_const.py b/bin/test_const.py
index 9722cb3..f4bd68c 100755
--- a/bin/test_const.py
+++ b/bin/test_const.py
@@ -31,11 +31,13 @@ put up_refl f $x1
 put low_refl f $mx1
 
 yaxis log re:im
+
+fsig noise 1
 """
 
 kat = finesse.kat(kat_code=code)
 
-kat.signals.apply(kat.l1.power, 1, 0)
+kat.signals.apply(kat.l1.P, 1, 0)
 kat.signals.apply(kat.m1.phi, 1, 90)
 
 kat.add(xaxis('log', [1, 1000], kat.signals.f, 100))
diff --git a/pykat/commands.py b/pykat/commands.py
index ba6b085..6a9bcf6 100644
--- a/pykat/commands.py
+++ b/pykat/commands.py
@@ -272,12 +272,60 @@ class gauss(object):
             kat.nodes[node].setGauss(kat.components[component], gpx, gpy)
             
 class tf(Command):
-    fQ = namedtuple('fQ', ['f', 'Q'])
     
-    def __init__(self, name, poles, zeros):
+    class fQ(object):
+        def __init__(self, f, Q):
+            self.f = f
+            self.Q = Q
+            
+    def __init__(self, name):
         Command.__init__(self, name, False)
-        pass
-      
+        self.zeros = []
+        self.poles = []
+        self.gain = 1
+        self.phase = 0
+    
+    def addPole(self,f, Q):
+        self.poles.append(tf.fQ(SIfloat(f), SIfloat(Q)))
+    
+    def addZero(self,f, Q):
+        self.zeros.append(tf.fQ(SIfloat(f), SIfloat(Q)))
+        
+    @staticmethod
+    def parseFinesseText(text):
+        values = text.split()
+        
+        if ((len(values)-4) % 3) != 0:
+            raise pkex.BasePyKatException("Transfer function Finesse code format incorrect '{0}'".format(text))
+
+        _tf = tf(values[1])
+        
+        _tf.gain = SIfloat(values[2])
+        _tf.phase = SIfloat(values[3])
+        
+        N = int((len(values)-4) / 3)
+        
+        for i in range(1,N+1):
+            if values[i*3+1] == 'p':
+                _tf.addPole(SIfloat(values[i*3+2]), SIfloat(values[i*3+3]))
+            elif values[i*3+1] == 'z':
+                _tf.addZero(SIfloat(values[i*3+2]), SIfloat(values[i*3+3]))
+            else:
+                raise pkex.BasePyKatException("Transfer function pole/zero Finesse code format incorrect '{0}'".format(text))
+    
+        return _tf
+        
+    def getFinesseText(self):
+        rtn = "tf {name} {gain} {phase} ".format(name=self.name,gain=self.gain,phase=self.phase)
+        
+        for p in self.poles:
+            rtn += "p {f} {Q} ".format(f=p.f, Q=p.Q)
+        
+        for z in self.zeros:
+            rtn += "p {f} {Q} ".format(f=z.f, Q=z.Q)
+        
+        return rtn
+        
 class xaxis(Command):
     """
     The xaxis object is a unique object to each pykat.finesse.kat instance. It provides
diff --git a/pykat/detectors.py b/pykat/detectors.py
index ec28374..285c9a3 100644
--- a/pykat/detectors.py
+++ b/pykat/detectors.py
@@ -191,7 +191,13 @@ class BaseDetector(object) :
                     rtn.append("scale {1} {0}".format(self.name, s))
             else:
                 raise pkex.BasePyKatException("Scale command should either be a list of scales or a single string.")
-                
+
+class Detector0(BaseDetector):
+    """
+    A detector that attaches to no nodes.
+    """
+    pass
+                        
 class Detector1(BaseDetector):
     """
     A detector that attaches to one node.
@@ -269,7 +275,32 @@ class beam(Detector1):
         
         return rtn
         
+class xd(Detector0):
+    
+    def __init__(self, name, component, motion):
+        BaseDetector.__init__(self, name, None)
+        
+        self.component = component
+        self.motion = motion
+
+    @staticmethod
+    def parseFinesseText(text): 
+        values = text.split()
+        
+        if len(values) == 4:
+            return xd(values[1], values[2], values[3])
+        else:
+            raise pkex.BasePyKatException('Motion detector code "{0}" is not a valid FINESSE command'.format(text))
+            
+    def getFinesseText(self) :
+        rtn = []
         
+        rtn.append("xd {name} {component} {motion}".format(name=self.name,
+                                                           component=self.component,
+                                                           motion=self.motion))
+        
+        return rtn
+              
         
 class ad(Detector1):
     
@@ -883,42 +914,6 @@ class qshot(pd):
                 rtn.extend(p.getFinesseText())
             
         return rtn
-        
-def xd(Detector1):
-
-    def __init__(self, name, node_name, component, motion):
-        BaseDetector.__init__(name, None)
-        
-        self.__motion = motion
-        self.__component = component
-        
-    @property
-    def motion(self): return self.__motion
-    
-    @property
-    def component(self): return self.__component
-    
-    @staticmethod
-    def parseFinesseText(text): 
-        values = text.split()
-
-        if len(values) != 4:
-            raise pkex.BasePyKatException("Motion detector command format incorrect '{0}' (2)".format(text))
-            
-        return xd(values[1], values[2], values[3])
-    
-    def getFinesseText(self) :
-        rtn = []
-        
-        if self.enabled:
-            rtn.append("xd {0} {1} {2}".format(self.name, self.component, self.motion))
-
-            self._getScaleCmds(rtn)
-                
-            for p in self._params:
-                rtn.extend(p.getFinesseText())
-            
-        return rtn
     
     
 class hd(Detector2):
diff --git a/pykat/finesse.py b/pykat/finesse.py
index 8742960..b1506b7 100644
--- a/pykat/finesse.py
+++ b/pykat/finesse.py
@@ -356,7 +356,7 @@ class katRun(object):
         detectors.sort()
         
         for det in detectors:
-            if not getattr(kat, det).noplot:
+            if not hasattr(kat, det) or (hasattr(kat, det) and not getattr(kat, det).noplot):
                 if dual_plot:
                     ax = pyplot.subplot(2,1,1)
                     
@@ -381,6 +381,12 @@ class katRun(object):
             if ylabel is None:
                 ylabel = "[au]"
         
+        if xlabel is None:
+            xlabel = self.xlabel
+            
+        if x2label is None:
+            x2label = self.xlabel
+            
         font_label_size = pyplot.rcParams["font.size"]-1
         
         if dual_plot:
@@ -1012,6 +1018,10 @@ class kat(object):
                         obj = pykat.components.modulator.parseFinesseText(line)
                     elif(first[0:2] == "ad"):
                         obj = pykat.detectors.ad.parseFinesseText(line)
+                    elif(first[0:2] == "xd"):
+                        obj = pykat.detectors.xd.parseFinesseText(line)
+                    elif(first[0:2] == "tf"):
+                        obj = pykat.commands.tf.parseFinesseText(line)
                     elif(first[0:2] == "bp"):
                         obj = pykat.detectors.bp.parseFinesseText(line)
                     elif(first[0:4] == "gouy"):
@@ -1109,7 +1119,7 @@ class kat(object):
                         if self.hasNamedObject(obj.name):
                             getattr(self, obj.name).remove()
                             print ("Removed existing object '{0}' of type {1} to add line '{2}'".format(obj.name, obj.__class__, line))
-                    
+
                         self.add(obj, block=self.__currentTag)
                 
                 
-- 
GitLab