diff --git a/bin/test_put.py b/bin/test_put.py
index 41155e42ee9d2c3d14016783c1c13e7ca3b68e42..e7cba00696a53f7f2b5eaac224a613bb7f5d8ac6 100644
--- a/bin/test_put.py
+++ b/bin/test_put.py
@@ -17,14 +17,18 @@ kat = finesse.kat()
 
 kat.parseCommands(code)
 
-kat.add(photodiode('pd_ref','n3', num_demods=1, demods=[10,0]))
+kat.add(pd('pdp',1,'n3'))
+kat.add(pd('pdm',1,'n3'))
 
-kat.add(xaxis("lin", [0, 1000], "pd_ref", "f1", 100))
+kat.add(xaxis("lin", [0, 1000], kat.eom, "f", 100))
+
+kat.pdp.f1.put(kat.xaxis.x)
+kat.pdm.f1.put(kat.xaxis.mx)
 
 out = kat.run(printout=0, printerr=0)
 
 pl.figure()
-pl.plot(out.x, out["pd_ref"])
+pl.plot(out.x, out["pdp"], out.x, out["pdm"])
 pl.xlabel(out.xlabel)
 pl.ylabel("Intensity [W]")
 pl.legend(out.ylabels)
diff --git a/pykat/detectors.py b/pykat/detectors.py
index ffe3076be50915d0550ec0413fe1aea3d8618476..30e46004ead75389d95c476d32db7ee9d524200b 100644
--- a/pykat/detectors.py
+++ b/pykat/detectors.py
@@ -20,13 +20,17 @@ class Detector(object) :
         self.enabled = True
         self.tag = None
         self.__node = None
+        self._params = []
         
         if node.find('*'):
             self._alternate_beam = True
             node.replace('*','')
         
         self.__requested_node = node
-
+    
+    def _register_param(self, param):
+        self._params.append(param)
+        
     def _on_kat_add(self, kat):
         self.__node = kat.nodes.createNode(self.__requested_node)
     
@@ -43,12 +47,140 @@ class Detector(object) :
     
     @property 
     def node(self): return self.__node
+    @node.setter
+    def node(self, value):
+        if value in self._kat.nodes:
+            self.__node = self._kat.nodes[value]
+        else:
+            raise pkex.BasePyKatException("There is no node called " + value)
     
     @property
     def name(self): return self.__name        
 
     def __str__(self): return self.name
+
+class pd(Detector):
+    
+    def __init__(self, name, num_demods, node_name, senstype=None, alternate_beam=False, **kwargs):
+        Detector.__init__(self, name, node_name)
+        
+        self.__num_demods = num_demods
+        self.__senstype = senstype
+        self.__alternate_beam = alternate_beam
+        # create the parameters for all 5 demodulations regardless
+        # of how many the user specifies. Later we add properties to
+        # those which correspond to the number of demodulations
+        
+        self.__f1 = Param("f1", self, 0)
+        self.__f2 = Param("f2", self, 0)
+        self.__f3 = Param("f3", self, 0)
+        self.__f4 = Param("f4", self, 0)
+        self.__f5 = Param("f5", self, 0)
+        
+        self.__phi1 = Param("phi1", self, None)
+        self.__phi2 = Param("phi2", self, None)
+        self.__phi3 = Param("phi3", self, None)
+        self.__phi4 = Param("phi4", self, None)
+        self.__phi5 = Param("phi5", self, None)
+        
+        # define new class for assigning new attributes
+        cls = type(self)
+        self.__class__ = type(cls.__name__, (cls,), {})
+    
+        self.__set_demod_attrs()
+        
+    @property
+    def senstype(self): return self.__senstype
+    @senstype.setter
+    def senstype(self,value):
+        if value == "": value = None
+        
+        if value != "S" and value != "N" and value != None: 
+            raise pkex.BasePyKatException("Photodiode sensitivity type can either be 'N', 'S' or None.")
+            
+        self.__senstype = value
+        
+    @property
+    def num_demods(self): return self.__num_demods
+    @num_demods.setter
+    def num_demods(self, value): 
+        if value < 0 or value > 5:
+            raise pkex.BasePyKatException("Number of demodulations must be between 0 and 5")
+        
+        self.__num_demods = value
+        self.__set_demod_attrs()
+    
+    def __get_fphi(self, name):
+        return getattr(self, '_'+ self.__class__.__name__ +'__' + name)
+    
+    def __set_f(self, num, value):
+        setattr(self, '_'+ self.__class__.__name__ +'__f' + name, float(value))
     
+    def __set_phi(self, num, value):
+        if value == None and num != self.num_demods:
+            # check if we are setting no phase that this is only on the last
+            # demodulation phase.
+            raise pkex.BasePyKatException("Only last demodulation phase can be set to None")
+        elif isinstance(value, str) and not isinstance(value,float) and value.lower() != "max":
+            raise pkex.BasePyKatException("Demodulation phase can only be set to a 'max' or a number (or None if the last demodulation phase)")
+            
+        setattr(self, '_'+ self.__class__.__name__ +'__phi' + name, value)
+        
+    def __set_demod_attrs(self):
+        """
+        For the set number of demodulations the correct number of 
+        Parameters are created.
+        """
+        
+        # if there are demodulations present then we want to add
+        # the various parameters so they are available for users
+        # to play with.
+        if self.__num_demods > 0:
+            for i in range(1,6):
+                name = str(i)
+                if i <= self.num_demods:
+                    if not hasattr(self, "f"+name):
+                        setattr(self.__class__, "f"+name, property(fget=lambda self, i=i: self.__get_fphi('f'+str(i)), fset=lambda self, value, i=i: self.__set_f(str(i), value)))
+                    
+                    if not hasattr(self, "phi"+name):
+                        setattr(self.__class__, "phi"+name, property(fget=lambda self, i=i: self.__get_fphi('phi'+str(i)), fset=lambda self, value, i=i: self.__set_phi(str(i), value)))
+                else:
+                    if hasattr(self, "f"+name):
+                        delattr(self.__class__, "f"+name)
+                    if hasattr(self, "phi"+name):
+                        delattr(self.__class__, "phi"+name)
+        else:
+            return
+    
+    def getFinesseText(self) :
+        rtn = []
+        
+        if self.enabled:
+            alt_str = ""
+            fphi_str = ""
+            
+            if self.__alternate_beam:
+                alt_str = "*"
+                
+            for n in range(1, 1+self.num_demods):
+                fphi_str += str(self.__getattribute__("f"+str(n)))
+                phi_val = self.__getattribute__("phi"+str(n))
+                
+                if phi_val != None:
+                    fphi_str += " " + str(phi_val)
+            
+            senstype = self.senstype
+            
+            if senstype == None:
+                senstype = ""
+                
+            rtn.append("pd{0}{1} {2} {3} {4}{5}".format(senstype, self.num_demods, self.name, fphi_str, self.node.name, alt_str))
+        
+        for p in self._params:
+            rtn.extend(p.getFinesseText())
+            
+        return rtn
+            
 class photodiode(Detector):
 
     class __F(list):
@@ -83,8 +215,10 @@ class photodiode(Detector):
         
     def __init__(self, name, node, senstype="", num_demods=0, demods=[]):        
         Detector.__init__(self, name, node)
+        
         if num_demods>2:
             raise NotImplementedError("pd with more than two demodulations not implemented yet")   
+            
         self.num_demods = num_demods
         self.senstype = senstype
 
diff --git a/pykat/finesse.py b/pykat/finesse.py
index cd4fd21db2dcf3808fc40a132e167a565b1e4941..b0493a24f1531f2669fcbc9eef7ae891aa42b64f 100644
--- a/pykat/finesse.py
+++ b/pykat/finesse.py
@@ -77,7 +77,7 @@ class katRun(object):
             else:
                 return self.y[:, idx]
         else:
-            raise  pkex.BasePyKatException("No output by the name {0} found", value)
+            raise  pkex.BasePyKatException("No output by the name {0} found".format(value))
       
 class katRun2D(object):
     def __init__(self):
@@ -156,7 +156,6 @@ class kat(object):
         
         cls = type(self)
         self.__class__ = type(cls.__name__, (cls,), {})
-        #self.logo()
         
     @property
     def maxtem(self): return self.__maxtem
@@ -503,7 +502,7 @@ class kat(object):
                 self.__add_command(obj)
                 
             else :
-                raise BasePyKatException("Object {0} could not be added".format(obj))
+                raise pkex.BasePyKatException("Object {0} could not be added".format(obj))
                 
             obj._on_kat_add(self)
             
@@ -683,7 +682,6 @@ class kat(object):
     def __get_detector(self, name):
         return getattr(self, '__det_' + name) 
         
-        
     def __add_command(self, com):
 
         if not isinstance(com, Command):
diff --git a/pykat/node_network.py b/pykat/node_network.py
index 8c6a50addaec89f7423f56b616a853a12c9534e9..2ad607f0a2a8ea30120a176c8340a5b4ead071fd 100644
--- a/pykat/node_network.py
+++ b/pykat/node_network.py
@@ -200,6 +200,13 @@ class NodeNetwork(object):
     def __get_node_attr(self, name):
         return getattr(self, '__node_' + name)        
         
+    def __getitem__(self, value):
+        return self.__nodes[str(value)]
+        
+    def __contains__(self, value):
+        return value in self.__nodes
+        
+    
 class Node(object):
 
     def __init__(self, name, network, id):
@@ -211,7 +218,9 @@ class Node(object):
         self.__q_y = None
         self.__q_comp = None
         self.__id = id
-        
+    
+    def __str__(self): return self.__name
+    
     @property
     def id(self): return self.__id
     
diff --git a/pykat/param.py b/pykat/param.py
index eb9c7fbdfe417f0bfe7619fa5411a79ce1e805b1..6ae1f9a9b29c52d565ec0b6054329c31fa6a072e 100644
--- a/pykat/param.py
+++ b/pykat/param.py
@@ -21,7 +21,7 @@ class putable(object):
     def isPutable(self): return self._isPutable
     
     def put(self, var):
-        print "put"
+    
         if not isinstance(var, putter):
             raise pkex.BasePyKatException("var was not something that can be `put` as a value")
         
@@ -103,31 +103,31 @@ class Param(putable, putter):
         return rtn
         
     def __mul__(self, a):
-        return float(self) * a
+        return self.value * a
     
     def __imul__(self, a):
-        return self.value * float(a)
+        return self.value * (a)
         
     __rmul__ = __mul__
     
     def __add__(self, a):
-        return self.value + flota(a)
+        return self.value + (a)
     
     def __iadd__(self, a):
-        return self.value + float(a)
+        return self.value + (a)
         
     __radd__ = __add__
     
     def __sub__(self, a):
-        return self.value - float(a)
+        return self.value - (a)
     
     def __isub__(self, a):
-        return self.value - float(a)
+        return self.value - (a)
         
     __rsub__ = __sub__
     
     def __div__(self, a):
-        return self.value / float(a)
+        return self.value / (a)
     
     def __idiv__(self, a):
         return self.value / complex(a)
@@ -139,13 +139,13 @@ class Param(putable, putter):
         return -self.value
         
     def __eq__(self, q):
-        return float(q) == self.value
+        return (q) == self.value
     def __ne__(self, q):
-        return float(q) != self.value
+        return (q) != self.value
     def __lt__(self, q):
-        return float(q) > self.value
+        return (q) > self.value
     def __gt__(self, q):
-        return float(q) < self.value        
+        return (q) < self.value        
         
 class AttrParam(Param):
     """