diff --git a/examples/lkat_optimisation.py b/examples/lkat_optimisation.py
index 3ad08c991276efc11410614e719d44c361be330a..089002c03fe4efdb8a8ebf292e43904c98c98de4 100644
--- a/examples/lkat_optimisation.py
+++ b/examples/lkat_optimisation.py
@@ -35,7 +35,7 @@ def callback(lkat, maxphi):
     inter = pylibkat.interferometer.in_dll(lkat, "inter")
     
     m1 = inter.mirror_list[0]
-    m2 = inter.mirror_list[1]
+    m2 = inter.mirror_list[1]   
 
     circ = inter.output_data_list[0]
     
@@ -54,7 +54,6 @@ def callback(lkat, maxphi):
     print "Process: Maximum power =", circ.re
     print "Process: Mirror tuning =", m1.phi
 
-
 cmd = """
 l l1 1 0 n1
 s s1 1 n1 n2
@@ -75,7 +74,7 @@ kat = pykat.finesse.kat()
 
 kat.parseCommands(cmd)
 
-maxphi = Value('d', 100)
+maxphi = Value('d', 0)
 
 p = kat.getProcess(callback, maxphi=maxphi)
 p.start()
diff --git a/pykat/commands.py b/pykat/commands.py
index ebe0db0ab574bb9c544406508cfea3627e45231b..66410e87b8d22e117f0476a40b636cb0570b3b8e 100644
--- a/pykat/commands.py
+++ b/pykat/commands.py
@@ -15,9 +15,10 @@ from collections import namedtuple
 from pykat.utilities.optics.gaussian_beams import gauss_param
 
 class Command(object):
-    def __init__(self):
-        self.tag = None
 
+    tag = None
+    __removed = False
+        
     def getFinesseText(self):
         """ Base class for individual finesse optical components """
         raise NotImplementedError("This function is not implemented")
@@ -32,8 +33,17 @@ class Command(object):
         """
         self._kat = kat
 
+    def remove(self):
+        self._kat.remove(self)
+        self.__removed = True
+    
+    @property
+    def removed(self): return self.__removed
+    
 class cavity(Command):
     def __init__(self, name, c1, n1, c2, n2):
+        super(Command, self).__init__()
+        
         self.__name = name
         self.__c1 = c1
         self.__c2 = c2
@@ -84,6 +94,7 @@ class tf(Command):
     fQ = namedtuple('fQ', ['f', 'Q'])
     
     def __init__(self, name, poles, zeros):
+        super(Command, self).__init__()
         pass
       
 class xaxis(Command):
@@ -92,6 +103,9 @@ class xaxis(Command):
     and interface to the xaxis command in FINESSE.
     """
     
+    @property
+    def name(self): return self._axis_type
+    
     def __init__(self, scale, limits, param, steps, comp=None, axis_type="xaxis"):
         """
         Typical usage:
@@ -102,6 +116,8 @@ class xaxis(Command):
         
         steps is the number of points to compute between upper and lower limits.
         """
+        super(Command, self).__init__()
+        
         self._axis_type = axis_type
 
         self.x = putter("x1")
@@ -140,7 +156,7 @@ class xaxis(Command):
             raise pkex.BasePyKatException("param argument is not of type Param")
         else:
             self.__param = param
-            self.__comp = param._owner.name
+            self.__comp = param._owner().name
 
     @property
     def param(self): return self.__param
@@ -150,7 +166,7 @@ class xaxis(Command):
 		raise pkex.BasePyKatException("param argument is not of type Param")
 	else:
 		self.__param = value
-		self.__comp = value._owner.name
+		self.__comp = value._owner().name
 
     @staticmethod
     def parseFinesseText(text):
diff --git a/pykat/components.py b/pykat/components.py
index faac85779ea310defe1f7d9a5b28883ddfd9a0b0..d5e1f17a32dac5f830b440720587c6a074e93b1d 100644
--- a/pykat/components.py
+++ b/pykat/components.py
@@ -16,41 +16,41 @@ import pykat.gui.graphics
 from pykat.gui.graphics import *
 from pykat.SIfloat import *
 from pykat.param import Param, AttrParam
-
+import weakref
 import pykat.exceptions as pkex
 
 next_component_id = 1
 
 class NodeGaussSetter(object):
     def __init__(self, component, node):                
-        self.__comp = component
-        self.__node = node
+        self.__comp = weakref.ref(component)
+        self.__node = weakref.ref(node)
     
     @property
     def node(self):
-        return self.__node
+        return self.__node()
     
     @property
     def q(self):
-        return self.__node.qx
+        return self.__node().qx
         
     @q.setter
     def q(self, value):
-        self.__node.setGauss(self.__comp, complex(value))
+        self.__node().setGauss(self.__comp(), complex(value))
         
     @property
     def qx(self):
-        return self.__node.qx
+        return self.__node().qx
     @qx.setter
     def qx(self, value):
-        self.__node.setGauss(self.__comp, complex(value))
+        self.__node().setGauss(self.__comp(), complex(value))
     
     @property
     def qy(self):
-        return self.__node.qy
+        return self.__node().qy
     @qy.setter
     def qy(self, value):
-        self.__node.setGauss(self.__comp, self.qx, complex(value))
+        self.__node().setGauss(self.__comp(), self.qx, complex(value))
         
 class Component(object):
     __metaclass__ = abc.ABCMeta
@@ -62,6 +62,7 @@ class Component(object):
         self._kat = None
         self.tag = None
         self._params = []
+        self.__removed = False
         
         # store a unique ID for this component
         global next_component_id
@@ -106,7 +107,7 @@ class Component(object):
             ns = self.__dict__[key]
             delattr(self, '__nodesetter_' + ns.node.name)
             delattr(self.__class__, ns.node.name)
-        
+            
         for node in self.nodes:
             if type(node) != pykat.node_network.DumpNode:
                 ns = NodeGaussSetter(self, node)
@@ -141,6 +142,9 @@ class Component(object):
     def getQGraphicsItem(self):    
         return None      
     
+    @property
+    def removed(self): return self.__removed
+    
     @property
     def nodes(self): return self._kat.nodes.getComponentNodes(self) 
     
@@ -152,6 +156,13 @@ class Component(object):
     
     def __str__(self): return self.name
     
+    def remove(self):
+        self._kat.remove(self)
+        
+        del self._params[:]
+
+        self.__removed = True
+        
 class AbstractMirrorComponent(Component):
     __metaclass__ = abc.ABCMeta
     
diff --git a/pykat/detectors.py b/pykat/detectors.py
index 3f30920e648e3fd47eb265ef9785a80daa6a242c..ae8bde8c7b729491c53d64802b79416af3683c39 100644
--- a/pykat/detectors.py
+++ b/pykat/detectors.py
@@ -27,7 +27,8 @@ class Detector(object) :
         self._params = []
         self._mask = {}
         self.__scale = None
-
+        self.__removed = False
+        
         if node != None:
             if node[-1]=='*':
                 self._alternate_beam = True
@@ -39,9 +40,19 @@ class Detector(object) :
         self._params.append(param)
         
     def _on_kat_add(self, kat):
+        self._kat = kat
+        
         if self.__requested_node != None:
             self.__node = kat.nodes.createNode(self.__requested_node)
     
+    def remove(self):
+        if self.__removed:
+            raise pkex.BasePyKatException("{0} has already been marked as removed".format(self.name))
+        else:
+            self._kat.remove(self)
+    
+        self.__removed = True
+        
     @staticmethod
     def parseFinesseText(text):    
         raise NotImplementedError("This function is not implemented")
@@ -53,6 +64,10 @@ class Detector(object) :
     def getQGraphicsItem(self):    
         return None
 
+        
+    @property
+    def removed(self): return self.__removed
+    
     @property 
     def scale(self): return self.__scale
     @scale.setter
diff --git a/pykat/finesse.py b/pykat/finesse.py
index fd4f0b4872e7046e6bfb641f76250bc095660c99..c4f97dc03d35a4a744993abcccd562ab040f78a9 100644
--- a/pykat/finesse.py
+++ b/pykat/finesse.py
@@ -164,18 +164,27 @@ class Signals(object):
             self.__name = name
             self.__amplitude = Param("amp", self, SIfloat(amplitude))
             self.__phase = Param("phase", self, SIfloat(phase))
+            self.__removed = False
             
             # unfortunatenly the target names for fsig are not the same as the
             # various parameter names of the components, e.g. mirror xbeta is x 
             # for fsig. So we need to check here what type of component we are targetting
             # and then based on the parameter specfied get the name
             if not param.canFsig:
-                raise  pkex.BasePyKatException("Cannot fsig parameter {1} on component {0}".format(str(param._owner), param.name))
-            
+                raise  pkex.BasePyKatException("Cannot fsig parameter {1} on component {0}".format(str(param._owner().name), param.name))
             
         def _register_param(self, param):
             self._params.append(param)
+        
+        @property
+        def removed(self): return self.__removed
   
+        def remove(self):
+            if self.__removed:
+                raise pkex.BasePyKatException("Signal {0} has already been marked as removed".format(self.name))
+            else:
+                self._kat.remove(self)
+        
         @property
         def name(self): return self.__name
 
@@ -194,7 +203,7 @@ class Signals(object):
         def target(self): return self.__target.fsig_name
 
         @property
-        def owner(self): return self.__target._owner.name
+        def owner(self): return self.__target._owner().name
     
         def getFinesseText(self):
             rtn = []
@@ -211,10 +220,18 @@ class Signals(object):
         # so need to get the name of at least one of them
         # as if you tune one you tune them all
         if len(self.targets) == 0:
-            return "signal"
+            return "fsignal"
         else:
             return self.targets[0].name
+            
+    @property
+    def removed(self): return False # we can never remove the Signal object altogethr just the
+                                    # individual fsig targets
 
+    def remove(self):
+        for t in self.targets:
+            self._kat.remove(self)
+            
     @property
     def f(self): return self.__f
     @f.setter
@@ -236,11 +253,10 @@ class Signals(object):
             raise  pkex.BasePyKatException("No target was specified for signal to be applied")
         
         if name == None:
-            name = "sig_" +target._owner.name + "_" + target.name
+            name = "sig_" + target._owner().name + "_" + target.name
         
         self.targets.append(Signals.fsig(target, name, amplitude, phase))
         
-        
     def getFinesseText(self):
         rtn = []
         
@@ -794,6 +810,30 @@ class kat(object):
             if self.verbose: print ""
             if self.verbose: print "Finished in " + str(datetime.datetime.now()-start)
             
+    def remove(self, obj):
+        if not (obj.name in self.__components or obj.name in self.__detectors or obj.name in self.__commands):
+            raise pkex.BasePyKatException("{0} is not currently in the simulation".format(obj.name))
+        
+        if obj.removed:
+            raise pkex.BasePyKatException("{0} has already been removed".format(obj.name))        
+        
+        if isinstance(obj, Component):    
+            del self.__components[obj.name]
+            self.__del_component(obj)
+            self.nodes.removeComponent(obj)
+        elif isinstance(obj, Command):    
+            del self.__commands[obj.name]
+            self.__del_command(obj)
+        elif isinstance(obj, Detector):    
+            del self.__detectors[obj.name]
+            self.__del_detector(obj)
+        
+        for b in self.__blocks:
+            if obj in self.__blocks[b].contents:
+                self.__blocks[b].contents.remove(obj)
+        
+        import gc
+        print gc.get_referrers(obj)
         
     def add(self, obj):
         try:
@@ -1060,8 +1100,18 @@ class kat(object):
         fget = lambda self: self.__get_detector(name)
         
         setattr(self.__class__, name, property(fget))
-        setattr(self, '__det_' + name, det)                   
+        setattr(self, '__det_' + name, det)                
+
+    def __del_detector(self, det):
 
+        if not isinstance(det, Detector):
+            raise exceptions.ValueError("Argument is not of type Detector")
+        
+        name = det.name
+        
+        delattr(self.__class__, name)
+        delattr(self, '__det_' + name) 
+        
     def __get_detector(self, name):
         return getattr(self, '__det_' + name) 
         
@@ -1076,6 +1126,15 @@ class kat(object):
         setattr(self.__class__, name, property(fget))
         setattr(self, '__com_' + name, com)                   
 
+    def __del_command(self, com):
+
+        if not isinstance(com, Command):
+            raise exceptions.ValueError("Argument is not of type Command")
+        
+        name = com.__class__.__name__
+        delattr(self.__class__, name)
+        delattr(self, '__com_' + name)
+        
     def __get_command(self, name):
         return getattr(self, '__com_' + name)            
     
@@ -1088,7 +1147,15 @@ class kat(object):
         
         setattr(self.__class__, comp.name, property(fget))
         setattr(self, '__comp_' + comp.name, comp)                   
+        
+    def __del_component(self, comp):
 
+        if not isinstance(comp, Component):
+            raise exceptions.ValueError("Argument is not of type Component")
+        
+        delattr(self.__class__, comp.name)
+        delattr(self, '__comp_' + comp.name)
+        
     def __get_component(self, name):
         return getattr(self, '__comp_' + name)        
 
diff --git a/pykat/node_network.py b/pykat/node_network.py
index c882dc26b7a99fadd48acbc4dc1851aae557762f..64b875a63e3a83aa7f71ca65c0e16e4d2865de8a 100644
--- a/pykat/node_network.py
+++ b/pykat/node_network.py
@@ -63,15 +63,18 @@ class NodeNetwork(object):
         new_node_comps = list(node_new.components)
         new_node_comps[new_node_comps.index(None)] = comp
         self.__nodeComponents[node_new.id] = tuple(new_node_comps)
+        del new_node_comps
         
         # remove component from old node list
         old_node_comps = list(node_old.components)
         old_node_comps[old_node_comps.index(comp)] = None
         self.__nodeComponents[node_old.id] = tuple(old_node_comps)
+        del old_node_comps
         
         comp_nodes = list(comp.nodes)
         comp_nodes[comp_nodes.index(node_old)] = node_new
         self.__componentNodes[comp.id] = tuple(comp_nodes)
+        del comp_nodes
         
         # if old node is no longer connected to anything then delete it
         if node_old.components.count(None) == 2:
@@ -116,6 +119,23 @@ class NodeNetwork(object):
             self.__nodes[node_name] = n
             self.__nodeComponents[n.id] = (None, None)
             return n
+    
+    def removeComponent(self, comp):
+        C = self.__componentNodes[comp.id]
+        
+        for n in C:
+           if comp in self.__nodeComponents[n.id]:
+               l = list(self.__nodeComponents[n.id])
+               l[l.index(comp)] = None
+               self.__nodeComponents[n.id] = tuple(l)
+               
+               if l.count(None) == 2:
+                   self.removeNode(n) 
+               
+               del l
+               
+        del self.__componentCallback[comp.id]
+        del self.__componentNodes[comp.id]
         
     def removeNode(self, node):
         
@@ -128,13 +148,14 @@ class NodeNetwork(object):
         C = self.getNodeComponents(node)
         
         if C[0] is not None or C[1] is not None:
-            raise exceptions.RuntimeError("Cannot remove a node which is attached to components")
+            raise exceptions.RuntimeError("Cannot remove a node which is attached to components still")
             
         if len(node.getDetectors()) > 0:
             raise exceptions.RuntimeError("Cannot remove a node which is attached to detectors still")
         
         self.__remove_node_attr(node)
         del self.__nodes[node.name] 
+        del self.__nodeComponents[node.id]
         
     def hasNode(self, name):
         return (name in self.__nodes)
diff --git a/pykat/param.py b/pykat/param.py
index c6e0ba0a381ae5c5e05462d9424577123adcac24..2376114f0d36995a467c372ddbb247eb5f260d8b 100644
--- a/pykat/param.py
+++ b/pykat/param.py
@@ -1,6 +1,7 @@
 import abc
 import pykat.exceptions as pkex
-
+import weakref
+    
 class putable(object):
     """
     Objects that inherit this should be able to have something `put` to it.
@@ -59,11 +60,11 @@ class Param(putable, putter):
 
     def __init__(self, name, owner, value, canFsig=False, fsig_name=None, isPutable=True, isPutter=True, isTunable=True, var_name=None):
         self._name = name
-        self._owner = owner
+        self._owner = weakref.ref(owner)
         self._value = value
         self._isPutter = isPutter
         self._isTunable = isTunable
-        self._owner._register_param(self)
+        self._owner()._register_param(self)
         self._canFsig = False
         
         if canFsig:
@@ -96,15 +97,35 @@ class Param(putable, putter):
     def isTuneable(self): return self._isTunable
     
     @property
-    def value(self): return self._value
+    def value(self):
+        if self._owner().removed:
+            raise pkex.BasePyKatException("{0} has been removed from the simulation".format(self._owner().name))
+        else:
+            return self._value
+    
     @value.setter
     def value(self, value):
-        self._value = value
-    
-    def __str__(self): return str(self.value)
-    def __float__(self): return self.value
+        if self._owner().removed:
+            raise pkex.BasePyKatException("{0} has been removed from the simulation".format(self._owner().name))
+        else:
+            self._value = value
+    
+    def __str__(self):
+        if self._owner().removed:
+            raise pkex.BasePyKatException("{0} has been removed from the simulation".format(self._owner().name))
+        else:
+            return str(self.value)
+            
+    def __float__(self):
+        if self._owner().removed:
+            raise pkex.BasePyKatException("{0} has been removed from the simulation".format(self._owner().name))
+        else:
+            return self.value
         
     def getFinesseText(self):
+        if self._owner().removed:
+            raise pkex.BasePyKatException("{0} has been removed from the simulation".format(self._owner().name))
+            
         rtn = []
         
         if self.isPutable: rtn.extend(self._getPutFinesseText())
@@ -112,7 +133,7 @@ class Param(putable, putter):
         # if this parameter is being put somewhere then we need to
         # set it as a variable
         if self.isPutter and self.put_count > 0:
-            rtn.append("set {put_name} {comp} {param}".format(put_name=self.put_name(), comp=self._owner.name, param=self.name))
+            rtn.append("set {put_name} {comp} {param}".format(put_name=self.put_name(), comp=self._owner().name, param=self.name))
         
         return rtn
         
@@ -172,10 +193,13 @@ class AttrParam(Param):
     If the value pf the parameter is not 0 the attr command will be printed.
     """
     def getFinesseText(self):
+        if self._owner().removed:
+            raise pkex.BasePyKatException("{0} has been removed from the simulation".format(self._owner().name))
+
         rtn = []
         
         if self.value != None:
-            rtn.append("attr {0} {1} {2}".format(self._owner.name, self.name, self.value))
+            rtn.append("attr {0} {1} {2}".format(self._owner().name, self.name, self.value))
             
         rtn.extend(super(AttrParam, self).getFinesseText())