diff --git a/pykat/commands.py b/pykat/commands.py
index 76d803f71b0de709662925f48cc944e5de0dcced..772c0039220a6707e99c98929ff3ecfac783bff8 100644
--- a/pykat/commands.py
+++ b/pykat/commands.py
@@ -10,6 +10,7 @@ from __future__ import print_function
 from __future__ import unicode_literals
 
 import numpy
+import warnings
 import pykat.external.six as six
 import pykat.exceptions as pkex
 
@@ -24,18 +25,19 @@ from collections import namedtuple
 from pykat.optics.gaussian_beams import BeamParam
 
 
-
-
 class Command(object):
     __metaclass__ = abc.ABCMeta
     
     def __init__(self, name, unique):
+        self.__dict__["____FROZEN____"] = False
+        self._kat = None
         self.__unique = unique
         self.tag = None
         self.__removed = False
         self.__name = name.strip("*")
         self._putters = []
     
+        
     def __deepcopy__(self, memo):
         """
         When deep copying a kat object we need to take into account
@@ -50,7 +52,23 @@ class Command(object):
             _._updateOwner(result)
         
         return result
+    
+    def _freeze(self): self.__dict__["____FROZEN____"] = True
+    def _unfreeze(self): self.__dict__["____FROZEN____"] = False
+        
+    def __setattr__(self, name, value):
+        if self.__dict__["____FROZEN____"] and not hasattr(self, name):
+            warnings.warn("'%s' does not have attribute called '%s'" % (self.__name, name), stacklevel=2)
+            
+        if hasattr(self, name) and hasattr(self.__class__, name):
+            prop = getattr(self.__class__, name)
             
+            if isinstance(prop, property):
+                prop.fset(self, value)
+                return
+                
+        self.__dict__[name] = value
+                       
     def getFinesseText(self):
         """ Base class for individual finesse optical components """
         raise NotImplementedError("This function is not implemented")
@@ -103,7 +121,8 @@ class variable(Command):
     def __init__(self, name, value):
         Command.__init__(self, name, False)
         self.__value = value
-    
+        self._freeze()
+        
     def getFinesseText(self):
         return "variable {name} {value}".format(name=self.name, value=self.value)
     
@@ -135,6 +154,8 @@ class func(Command):
         
         self.output = putter(name, self)
         self._putters.append(self.output)
+
+        self._freeze()
         
     def getFinesseText(self):
         rtn = []
@@ -175,7 +196,8 @@ class lock(Command):
         self.output = putter(name, self)
         self._putters.append(self.output)
 
-
+        self._freeze()
+        
     @staticmethod
     def parseFinesseText(line, kat):
         v = line.split()
@@ -228,6 +250,8 @@ class cavity(Command):
         
         self.enabled = True
 
+        self._freeze()
+        
     def getFinesseText(self):
         if self.enabled:
             return 'cav {0} {1} {2} {3} {4}'.format(self.name, self.__c1.name, self.__n1.name, self.__c2.name, self.__n2.name);
@@ -405,6 +429,8 @@ class tf(Command):
         self.poles = []
         self.gain = 1
         self.phase = 0
+        
+        self._freeze()
     
     def addPole(self,f, Q):
         self.poles.append(tf.fQ(SIfloat(f), SIfloat(Q)))
@@ -504,6 +530,8 @@ class xaxis(Command):
             self.__param = param
             self.__comp = param._owner()
 
+        self._freeze()
+        
     def _set_variables(self):
         self.x = putter("x1", self)
         self.mx = putter("mx1", self)
diff --git a/pykat/components.py b/pykat/components.py
index 07ecaa376ac62df5c22be95274960e7b743230e4..4c0f953e467f1b0b434c0b0f75e5ebeb16faebf4 100644
--- a/pykat/components.py
+++ b/pykat/components.py
@@ -16,6 +16,7 @@ import pykat.external.six as six
 if six.PY2:
 	import exceptions
 
+import warnings
 import pykat.exceptions as pkex
 import pykat
 from pykat.node_network import *
@@ -102,6 +103,7 @@ class Component(object):
         return object.__new__(cnew)
         
     def __init__(self, name=None):
+        self._unfreeze()
         
         self._optivis_component = None
         self.__name = name
@@ -118,7 +120,23 @@ class Component(object):
         global next_component_id
         self.__id = next_component_id
         next_component_id += 1    
-       
+     
+    def _freeze(self): self.__dict__["____FROZEN____"] = True
+    def _unfreeze(self): self.__dict__["____FROZEN____"] = False
+        
+    def __setattr__(self, name, value):
+        if self.__dict__["____FROZEN____"] and not hasattr(self, name):
+            warnings.warn("'%s' does not have attribute called '%s'" % (self.__name, name), stacklevel=2)
+            
+        if hasattr(self, name) and hasattr(self.__class__, name):
+            prop = getattr(self.__class__, name)
+            
+            if isinstance(prop, property):
+                prop.fset(self, value)
+                return
+                
+        self.__dict__[name] = value
+         
     def __deepcopy__(self, memo):
         """
         When deep copying a kat object we need to take into account
@@ -204,7 +222,8 @@ class Component(object):
                 self.__add_node_setter(ns)
         
     def __add_node_setter(self, ns):
-
+        self._unfreeze()
+        
         if not isinstance(ns, NodeGaussSetter):
             raise exceptions.ValueError("Argument is not of type NodeGaussSetter")
         
@@ -214,6 +233,8 @@ class Component(object):
         setattr(self.__class__, name, property(fget))
         setattr(self, '__nodesetter_' + name, ns)                   
 
+        self._freeze()
+        
     def __get_node_setter(self, name):
         return getattr(self, '__nodesetter_' + name)   
         
@@ -480,7 +501,8 @@ class mirror(AbstractMirrorComponent):
         
         self._requested_node_names.append(node1)
         self._requested_node_names.append(node2)
-
+        self._freeze()
+        
     def parseAttributes(self, values):
         
         for key in values.keys():
@@ -572,6 +594,8 @@ class beamSplitter(AbstractMirrorComponent):
         self._requested_node_names.append(node3)
         self._requested_node_names.append(node4)
         self.__alpha = Param("alpha", self, SIfloat(alpha))
+
+        self._freeze()
         
     @property
     def alpha(self): return self.__alpha
@@ -684,6 +708,8 @@ class space(Component):
         self.__gy = AttrParam("gy", self, gy)
         
         self._default_fsig_param = self.__L
+
+        self._freeze()
         
     @property
     def L(self): return self.__L
@@ -810,6 +836,8 @@ class grating(Component):
         self.__rho_0 = AttrParam("rho_0", self, SIfloat(rho_0))
         self.__alpha = AttrParam("alpha", self, SIfloat(alpha))
         self._svgItem = None
+
+        self._freeze()
         
     @property
     def n(self): return Param('n', self.__n)
@@ -939,6 +967,7 @@ class isolator(Component):
         self.__S = Param("S",self,SIfloat(S))
         self.__L = Param("L",self,SIfloat(L))
 
+        self._freeze()
         
     @property
     def S(self): return self.__S
@@ -1044,6 +1073,8 @@ class isolator1(Component):
         self._requested_node_names.append(node4)
         self._svgItem = None
 
+        self._freeze()
+        
     @staticmethod
     def parseFinesseText(text):
         values = text.split()
@@ -1084,6 +1115,8 @@ class lens(Component):
         self._svgItem = None
         self.__f = Param("f", self, SIfloat(f))
         self.__p = Param("p", self, SIfloat(p))
+
+        self._freeze()
         
     @property
     def f(self): return self.__f
@@ -1180,6 +1213,8 @@ class modulator(Component):
         self.type = modulation_type
         
         self._default_fsig_param = self.__phase
+        
+        self._freeze()
             
     @property 
     def f(self): return self.__f
@@ -1296,6 +1331,8 @@ class laser(Component):
         self._svgItem = None
         
         self._default_fsig_param = self.__f_offset
+
+        self._freeze()
         
     @property
     def P(self): return self.__power
@@ -1393,6 +1430,9 @@ class squeezer(Component):
         self.__angle = Param("angle", self, SIfloat(angle), canFsig=False, fsig_name="angle")
         self._svgItem = None
         self.entangled_carrier = entangled_carrier
+
+        self._freeze()
+        
         
     @property
     def db(self): return self.__db
diff --git a/pykat/detectors.py b/pykat/detectors.py
index f3195d08a753f2eb8fd448da9a4192c4b96786ea..a957cd6f14749e82d5d86e11a922401c300a62b8 100644
--- a/pykat/detectors.py
+++ b/pykat/detectors.py
@@ -54,6 +54,8 @@ class BaseDetector(object) :
         return object.__new__(cnew)
         
     def __init__(self, name, nodes=None, max_nodes=1):
+
+        self.__dict__["____FROZEN____"] = False
         
         self.__name = name
         self._svgItem = None
@@ -97,6 +99,22 @@ class BaseDetector(object) :
             else:
                 raise pkex.BasePyKatException("Nodes should be a list or tuple of node names or a singular node name as a string.")
     
+    def _freeze(self): self.__dict__["____FROZEN____"] = True
+    def _unfreeze(self): self.__dict__["____FROZEN____"] = False
+        
+    def __setattr__(self, name, value):
+        if self.__dict__["____FROZEN____"] and not hasattr(self, name):
+            warnings.warn("'%s' does not have attribute called '%s'" % (self.__name, name), stacklevel=2)
+            
+        if hasattr(self, name) and hasattr(self.__class__, name):
+            prop = getattr(self.__class__, name)
+            
+            if isinstance(prop, property):
+                prop.fset(self, value)
+                return
+                
+        self.__dict__[name] = value
+    
     def __deepcopy__(self, memo):
         """
         When deep copying a kat object we need to take into account
@@ -243,6 +261,8 @@ class beam(Detector1):
         self.alternate_beam = alternate_beam
         self.__f = Param("f", self, frequency)        
     
+        self._freeze()
+        
     @property
     def f(self): return self.__f
     
@@ -291,6 +311,8 @@ class cp(Detector0):
         self.cavity = str(cavity)
         self.direction = direction
         self.parameter = parameter
+        
+        self._freeze()
 
     @property
     def direction(self): return self.__direction
@@ -345,6 +367,8 @@ class xd(Detector0):
         
         self.component = component
         self.motion = motion
+    
+        self._freeze()
 
     @staticmethod
     def parseFinesseText(text): 
@@ -373,6 +397,8 @@ class ad(Detector1):
         self.alternate_beam = alternate_beam
         self.__f = Param("f", self, frequency)
     
+        self._freeze()
+    
     @property
     def mode(self): return self.__mode
     @mode.setter
@@ -426,6 +452,8 @@ class gouy(Detector1):
         self.spaces = copy.copy(spaces)
         self.direction = direction
         self.alternate_beam = False
+    
+        self._freeze()
         
     @property
     def direction(self): return self.__dir
@@ -475,6 +503,8 @@ class bp(Detector1):
         self.parameter = parameter
         self.direction = direction
         self.alternate_beam = alternate_beam
+    
+        self._freeze()
         
     @property
     def direction(self): return self.__dir
@@ -598,9 +628,10 @@ class pd(Detector1):
                 ps[i].value = kwargs[p]
             elif i<num_demods-1:
                 raise pkex.BasePyKatException("Missing demodulation phase {0} (phase{0})".format(i+1))
-        
    
         self.__set_demod_attrs()
+    
+        self._freeze()
                 
     @property
     def senstype(self): return self.__senstype
@@ -655,6 +686,7 @@ class pd(Detector1):
         For the set number of demodulations the correct number of 
         Parameters are created.
         """
+        self._unfreeze()
         
         # if there are demodulations present then we want to add
         # the various parameters so they are available for users
@@ -678,8 +710,8 @@ class pd(Detector1):
                         
                     if hasattr(self, "phase"+name):
                         delattr(self.__class__, "phase"+name)
-        else:
-            return
+        
+        self._freeze()
     
     @staticmethod
     def parseFinesseText(text): 
@@ -776,7 +808,11 @@ class qnoised(pd):
     def __init__(self, name, num_demods, node_name, alternate_beam=False, pdtype=None, **kwargs):
         super(qnoised, self).__init__(name, num_demods, node_name, alternate_beam=alternate_beam, pdtype=pdtype, **kwargs)
     
+        self._unfreeze()
+        
         self.__homangle = AttrParam("homangle", self, None)
+        
+        self._freeze()
     
     @property
     def homangle(self): return self.__homangle
@@ -985,7 +1021,9 @@ class hd(Detector2):
         BaseDetector.__init__(self, name, (node1_name, node2_name), max_nodes=2)
     
         self.__phase = Param("phase", self, phase)
-    
+
+        self._freeze()
+        
     @property
     def phase(self): return self.__phase
     @phase.setter
@@ -1026,6 +1064,8 @@ class qhd(Detector2):
     
         self.__phase = Param("phase", self, phase)
         self.sensitivity = sensitivity
+    
+        self._freeze()
         
     @property
     def phase(self): return self.__phase
diff --git a/pykat/finesse.py b/pykat/finesse.py
index 53bc695572ca162fef29343bc6e7150576bd44c1..93bf52fd9a143e37f84d1260880cede526ddb284 100644
--- a/pykat/finesse.py
+++ b/pykat/finesse.py
@@ -1149,6 +1149,9 @@ class kat(object):
             print("$" + key, "::::", "owner =", self.__variables[key].owner.name, ", use count =", self.__variables[key].putCount)
     
     def parseCommands(self, commands, blocks=None, addToBlock=None, preserve=False):
+        
+        commands = str(commands)
+        
         try:
             if addToBlock is not None and blocks is not None:
                 raise pkex.BasePyKatException("When parsing commands you cannot set both blocks and addToBlock arguments")