diff --git a/bin/test_const.py b/bin/test_const.py
index 9722cb38e6aafcf860023bd6068a75a38534df1d..f4bd68cf11d7c758a1ce903fc7040ce2f46501c9 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 ba6b085282a70f4a29db3b5637300867cf3c1031..6a9bcf60a9e53f6df9b369d8a8bdde64f81ef9c2 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 ec283741e638ee4de32b95df76d784dc87bc6822..285c9a3f6ef50058d7b4fa9c12fdadf1946a410b 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 874296096783287e58c6d3e293cc66ac4683fe36..b1506b7bdc32aa8aad3ab25de90c4e6fd636a195 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)