diff --git a/bin/test_dump.py b/bin/test_dump.py
index 8fdb9ed16e5d11890124ba4a79bf94cf52707e31..135ff96e2508fa863b5bba754dd50cb72317e7d8 100644
--- a/bin/test_dump.py
+++ b/bin/test_dump.py
@@ -12,5 +12,12 @@ print "".join(kat.generateKatScript())
 kat.nodes.replaceNode(kat.bs1, kat.bs1.nodes[3], kat.nodes.createNode("test4"))
 kat.nodes.replaceNode(kat.bs1, kat.bs1.nodes[1], kat.nodes.createNode("test2"))
 
+kat.nodes.replaceNode(kat.bs1, "n1", kat.nodes.createNode("test1"))
+kat.nodes.replaceNode(kat.bs1, "n3", kat.nodes.createNode("dump"))
+kat.nodes.replaceNode(kat.bs1, "test1", kat.nodes.createNode("dump"))
+
 print "AFTER"
 print "".join(kat.generateKatScript())
+
+
+
diff --git a/pykat/commands.py b/pykat/commands.py
index a8d95cf0c209004085216a03ea7a04b401044e74..8300b1805ec06a2ac5691e1e0d8c0f3bfd86111a 100644
--- a/pykat/commands.py
+++ b/pykat/commands.py
@@ -235,3 +235,7 @@ class x2axis(xaxis):
             raise pkex.BasePyKatException("xaxis Finesse code format incorrect '{0}'".format(text))
 
         return x2axis(values[2], [values[3], values[4]], values[1], values[5], comp=values[0],axis_type=axis_type)
+
+
+class lock(Command):
+    pass
diff --git a/pykat/detectors.py b/pykat/detectors.py
index 9cff75f72fa83630673a4188b868caf81c925275..df246f0c9cd5b047e586a4fd3c03e87fba94cf17 100644
--- a/pykat/detectors.py
+++ b/pykat/detectors.py
@@ -22,6 +22,8 @@ class BaseDetector(object) :
     This base class can handled detectors connected to multiple nodes.
     """
     
+    __metaclass__ = abc.ABCMeta
+    
     def __init__(self, name, nodes=None, max_nodes=1):
         
         self.__name = name
diff --git a/pykat/finesse.py b/pykat/finesse.py
index b3c222920acdc3fe066ea4a773220e164e2a41f8..c545945354dfefac0433f20687e161ba94e92d70 100644
--- a/pykat/finesse.py
+++ b/pykat/finesse.py
@@ -1046,7 +1046,7 @@ class kat(object):
         if isinstance(obj, Component):    
             del self.__components[obj.name]
             self.__del_component(obj)
-            self.nodes.removeComponent(obj)
+            self.nodes._removeComponent(obj)
         elif isinstance(obj, Command):    
             del self.__commands[obj.name]
             self.__del_command(obj)
@@ -1111,7 +1111,7 @@ class kat(object):
         
             return (Mcarrier, Msignal)
 
-        
+    
     def hasNamedObject(self, name):
         return name in self.__components or name in self.__detectors or name in self.__commands
         
@@ -1186,6 +1186,13 @@ class kat(object):
             return [x, y, hdr]
 
     def removeLine(self, fragment) :
+        """
+        This will search all blocks by default and search for the string
+        fragment specified and remove it. This will only remove non-parsed
+        commands, it will not remove commands that have already been parsed
+        into the pykat structure, such as mirrors and beamsplitters, use the
+        kat.remove(...) function for that purpose.
+        """
         for key in self.__blocks:
             objs = self.__blocks[key].contents
             for obj in objs:
@@ -1194,7 +1201,15 @@ class kat(object):
                         print "  ** removing line '{0}'".format(obj)
                         objs.remove(obj)
 
-                    
+    def addLine(self, line, block=NO_BLOCK) :
+        """
+        This will forcefully add a line of FINESSE code to a particular block
+        if specfied. This command will not undergo any parsing so it will remain
+        as just a string. This of course can create possible conflicts with other
+        pykat object that create similar commands so becareful.
+        """
+        self.__blocks[key].contents.append(line)
+                        
     def generateKatScript(self) :
         """ Generates the kat file which can then be run """
 
diff --git a/pykat/node_network.py b/pykat/node_network.py
index 81f7189b0d3a4c866e7563db98f126f16f2b7762..ea1509b22ab899e4cdfa7d93596c47e4b8fe8f57 100644
--- a/pykat/node_network.py
+++ b/pykat/node_network.py
@@ -43,7 +43,7 @@ class NodeNetwork(object):
         
         for name in node_names:
             n = self.createNode(name)
-            self.connectNodeToComp(n, comp, do_callback=False)
+            self.__connectNodeToComp(n, comp, do_callback=False)
             list.append(n)
         
         self.__componentNodes[comp.id] = tuple(list)
@@ -52,14 +52,39 @@ class NodeNetwork(object):
         change_callback()
     
     def replaceNode(self, comp, node_old, node_new):
+        """
+        For a particular pykat component this will replace a node that is currently
+        connected to it with another. This can be used to dynamically change layouts
+        once components have been read into the pykat.finesse.kat object.
+        
+        node_old is the node that is attached to the component. This will accept
+             str - name of a node
+             pykat.node_network.Node - The direct node object
+             pykat.components.NodeGaussSetter - the node object that is used to set gaussian parameters
+             
+        This will call a components __on_node_change callback function to let it know that the nodes
+        connected to it have changed.
+        """
         
-        if node_new.components.count(None) == 0:
+        if isinstance(node_old, str):
+            node_old = self.__kat.nodes[node_old]
+        
+        if isinstance(node_new, str):
+            node_new = self.__kat.nodes[node_new]
+            
+        if isinstance(node_old, pykat.components.NodeGaussSetter):
+            node_old = node_old.node
+        
+        if isinstance(node_new, pykat.components.NodeGaussSetter):
+            node_new = node_new.node
+            
+        if not node_new.isDump and node_new.components.count(None) == 0:
             raise pkex.BasePyKatException("New node already connected to two components")
             
         if comp not in node_old.components:
             raise pkex.BasePyKatException("Old node not attached to component")
         
-        if comp in node_new.components:
+        if not node_new.isDump and comp in node_new.components:
             raise pkex.BasePyKatException("New node already attached to component")
         
         # add component to new node component list
@@ -82,11 +107,15 @@ class NodeNetwork(object):
         # if old node is no longer connected to anything then delete it
         if node_old.components.count(None) == 2:
             self.removeNode(node_old)
-            
+        
+        # Call component callback to let it know that we have changed the 
+        # nodes attached to it
         self.__componentCallback[comp.id]()
             
-    def connectNodeToComp(self, node, comp, do_callback=True):
-
+    def __connectNodeToComp(self, node, comp, do_callback=True):
+        """
+        This is an internal function used to create connections between nodes
+        """
         if node.id in self.__nodeComponents:
             comps = self.__nodeComponents[node.id]
         else:
@@ -109,22 +138,41 @@ class NodeNetwork(object):
         if do_callback: self.__componentCallback[comp.id]()
         
     def createNode(self, node_name):
-        if node_name == 'dump':
-            return DumpNode(self)
+        """
+        This creates a new node object. It won't be connected to anything or added to a
+        pykat.finesse.kat object until it is specifically attached to a particular 
+        component. This should be used in conjunction with kat.nodes.replaceNode to 
+        add a new node into a system, as every component will already have the nodes
+        setup, including dump nodes.
+        
+        This will return a dump node if the name of the node is "dump" (case senstive)
+        """
             
-        if node_name in self.__nodes:
+        if node_name != 'dump' and node_name in self.__nodes:
             # then this node already exists
             return self.__nodes[node_name]
         else:
-            n = Node(node_name, self, self.__node_id)
+            if node_name == 'dump':
+                n = DumpNode(self)
+            else:
+                n = Node(node_name, self, self.__node_id)
             
             self.__node_id += 1
-            self.__add_node_attr(n) # add node as a member of this object, e.g. kat.nodes.n
-            self.__nodes[node_name] = n
             self.__nodeComponents[n.id] = (None, None)
+            
+            if not n.isDump:
+                self.__add_node_attr(n) # add node as a member of this object, e.g. kat.nodes.n
+                self.__nodes[node_name] = n
+                
+            
             return n
     
-    def removeComponent(self, comp):
+    def _removeComponent(self, comp):
+        """
+        This is an internal function that shouldn't be used directly. This removes
+        a particular component from the node network. For this to work it has to be 
+        detached from all other connections first.
+        """
         C = self.__componentNodes[comp.id]
         
         for n in C:
@@ -142,7 +190,25 @@ class NodeNetwork(object):
         del self.__componentNodes[comp.id]
         
     def removeNode(self, node):
+        """
+        This will remove a particular node object from the network. The node in question
+        must be fully detached from all components and connections first. This function is 
+        called by replaceNode directly so a replaced node, that is no longer connected to 
+        anything, is removed automatically.
+        
+        node_old is the node that is attached to the component. This will accept
+             str - name of a node
+             pykat.node_network.Node - The direct node object
+             pykat.components.NodeGaussSetter - the node object that is used to set gaussian parameters
+              
+        """
         
+        if isinstance(node, str):
+            node = self.__kat.nodes[node]
+            
+        if isinstance(node, pykat.components.NodeGaussSetter):
+            node = node.node
+            
         if not isinstance(node, Node):
             raise pkex.BasePyKatException("node argument is not of type Node")
         
@@ -160,49 +226,32 @@ class NodeNetwork(object):
         if not isinstance(node, DumpNode):
             self.__remove_node_attr(node)
             del self.__nodes[node.name] 
-            del self.__nodeComponents[node.id]
+            
+        del self.__nodeComponents[node.id]
         
     def hasNode(self, name):
+        ""
         return (name in self.__nodes)
     
     def getNodes(self):
+        """
+        Returns a copy of the node dictionary, this is for infomration purposes any edits won't make
+        any changes to the node network.
+        """
         return self.__nodes.copy()
     
-    def dumpInfo(self):
-        
-        for name in self.__nodes:
-            
-            n = self.__nodes[name]
-            
-            items = n.getComponents()
-            comp = items[0][:]
-            det = items[1]
-            
-            if comp[0] == None:
-                comp1 = 'dump'
-            else:
-                comp1 = comp[0].name
-            
-            if comp[1] == None:
-                comp2 = 'dump'
-            else:
-                comp2 = comp[1].name    
-            
-            detectors = ""
-            
-            if len(det) > 0:
-                detectors = "Detectors: "
-                
-                for d in det:
-                    detectors = detectors + d.name + " "
-                
-            print "node: {0} connected:{1} {2}->{3} {4}".format(
-                    n.name,n.isConnected(),comp1, comp2, detectors)
-    
     def getComponentNodes(self, comp):
+        """
+        This function returns a tuple of the nodes connected to the component specified.
+        For information only, you cannot edit the connections using this function.
+        """
         return self.__componentNodes[comp.id]
     
     def getNodeComponents(self, node):
+        """
+        This function returns a tuple of the components connected to the node specified.
+        For information only, you cannot edit the connections using this function.
+        """
         return self.__nodeComponents[node.id]
     
     def __add_node_attr(self, node):
@@ -218,7 +267,7 @@ class NodeNetwork(object):
     
     def __remove_node_attr(self, node):
         if not isinstance(node, Node):
-            raise pkex.BasePyKatException("Argument is not of type Node")
+            kat.nodes.replaceNode(kat.bs1, "n1", kat.nodes.createNode("test1"))
         
         name = node.name
         delattr(self, '__node_' + name)
@@ -228,7 +277,10 @@ class NodeNetwork(object):
         return getattr(self, '__node_' + name)        
         
     def __getitem__(self, value):
-        return self.__nodes[str(value)]
+        if str(value) in self.__nodes:
+            return self.__nodes[str(value)]
+        else:
+            raise pkex.BasePyKatException("The node '%s' could not be found in the network." % str(value))
         
     def __contains__(self, value):
         return value in self.__nodes
@@ -334,7 +386,26 @@ class NodeNetwork(object):
             return self.__nodeSearch(nextnode, nextcomp, branches, tnode)
             
     def getComponentsBetween(self, from_node, to_node):
-    
+        """
+        This function will trace the path between the two nodes specified and return a list
+        of the components it finds between them.
+        """
+        
+        if isinstance(from_node, str):
+            from_node = self.__kat.nodes[from_node]
+            
+        if isinstance(from_node, pykat.components.NodeGaussSetter):
+            from_node = from_node.node
+            
+        if isinstance(to_node, str):
+            to_node = self.__kat.nodes[to_node]
+            
+        if isinstance(to_node, pykat.components.NodeGaussSetter):
+            to_node = to_node.node
+            
+        if to_node == from_node:
+            return []
+        
         if from_node not in self.__nodes:
             raise pkex.BasePyKatException("Node {0} cannot be found in this kat object".format(from_node))