diff --git a/bin/test_pass_though.py b/bin/test_pass_though.py
new file mode 100644
index 0000000000000000000000000000000000000000..3a8c020228b49bd1cccb137632c57d6a19eacb6b
--- /dev/null
+++ b/bin/test_pass_though.py
@@ -0,0 +1,30 @@
+# -*- coding: utf-8 -*-
+"""
+Created on Thu Dec 12 15:29:19 2013
+
+Takes a set of Finesse commands as input, parses it and outputs it again.
+Used to check whether Finesse components, detectors, etc. are properly
+reproducing the parameters they are given.
+
+@author: Sean Leavey
+"""
+
+from pykat import finesse
+
+code = """
+l l1 1 0 0 n1
+s s1 10 1 n1 n2
+m m1 1 0 0 n2 n3
+gr4 grating 1500 n4 n5 n6 n7
+
+pd refl n2
+
+xaxis m1 r_ap lin 0.1e-3 2e-3 10
+"""
+
+kat = finesse.kat()
+kat.parseCommands(code)
+
+scriptList = kat.generateKatScript()
+
+print ''.join(scriptList)
\ No newline at end of file
diff --git a/pykat/components.py b/pykat/components.py
index 2cbc48edc8ab9ae7a96f9b8b2c0364eaec75859e..d914b06dcb81b633e4eaebde115c89de63dfaf89 100644
--- a/pykat/components.py
+++ b/pykat/components.py
@@ -341,14 +341,13 @@ class beamSplitter(AbstractMirrorComponent):
    
 class space(Component):
     def __init__(self, name, node1, node2, L=0, n=1):
-        Component.__init__(self,name,)
+        Component.__init__(self, name)
         
         self._requested_node_names.append(node1)
         self._requested_node_names.append(node2)
         
         self.__L = SIfloat(L)
         self.__n = SIfloat(n)
-        self._QItem = None
         
     @property
     def L(self): return Param('L', self.__L)
@@ -385,7 +384,141 @@ class space(Component):
         if self._QItem == None:
             self._QItem = pykat.gui.graphics.SpaceQGraphicsItem(self)
         
-        return self._QItem          
+        return self._QItem
+
+class grating(Component):
+    def __init__(self, name, node1, node2, node3 = None, node4 = None, n = 2, d = 0, eta_0 = 0, eta_1 = 0, eta_2 = 0, eta_3 = 0, rho_0 = 0, alpha = 0): # TODO: implement Rcx, Rcy and Rc
+        Component.__init__(self, name)
+        
+        self._requested_node_names.append(node1)
+        self._requested_node_names.append(node2)
+
+        if n > 2:
+            if node3 != None:
+                self._requested_node_names.append(node3)
+            else:
+                raise exceptions.RuntimeError("Grating node 3 not specified")
+
+        if n > 3:
+            if node4 != None:
+                self._requested_node_names.append(node4)
+            else:
+                raise exceptions.RuntimeError("Grating node 4 not specified")
+
+        if n > 4 or n < 2:
+            raise exceptions.RuntimeError("Grating must have between 2 and 4 ports")
+        
+        self.__n = n
+        self.__d = SIfloat(d)
+        self.__eta_0 = SIfloat(eta_0)
+        self.__eta_1 = SIfloat(eta_1)
+        self.__eta_2 = SIfloat(eta_2)
+        self.__eta_3 = SIfloat(eta_3)
+        self.__rho_0 = SIfloat(rho_0)
+        self.__alpha = SIfloat(alpha)
+    
+    @property
+    def n(self): return Param('n', self.__n)
+    @n.setter
+    def n(self, value):
+        if value < 2 or value > 4:
+            raise exceptions.RuntimeError("Grating must have between 2 and 4 ports")
+        else:
+            self.__n = value
+    
+    @property
+    def d(self): return Param('d', self.__d)
+    @d.setter
+    def d(self, value): self.__d = SIfloat(value)
+    
+    @property
+    def eta_0(self): return Param('eta_0', self.__eta_0)
+    @eta_0.setter
+    def eta_0(self, value): self.__eta_0 = SIfloat(value)
+    
+    @property
+    def eta_1(self): return Param('eta_1', self.__eta_1)
+    @eta_1.setter
+    def eta_1(self, value): self.__eta_1 = SIfloat(value)
+    
+    @property
+    def eta_2(self): return Param('eta_2', self.__eta_2)
+    @eta_2.setter
+    def eta_2(self, value): self.__eta_2 = SIfloat(value)
+    
+    @property
+    def eta_3(self): return Param('eta_3', self.__eta_3)
+    @eta_3.setter
+    def eta_3(self, value): self.__eta_3 = SIfloat(value)
+    
+    @property
+    def rho_0(self): return Param('rho_0', self.__rho_0)
+    @rho_0.setter
+    def rho_0(self, value): self.__rho_0 = SIfloat(value)
+    
+    @property
+    def alpha(self): return Param('alpha', self.__alpha)
+    @alpha.setter
+    def alpha(self, value): self.__alpha = SIfloat(value)
+    
+    @staticmethod
+    def parseFinesseText(text):
+        values = text.split(" ")
+
+        if values[0][0 : 2] != "gr":
+            raise exceptions.RuntimeError("'{0}' not a valid Finesse grating command".format(text))
+
+        if len(values[0]) > 2:
+            if int(values[0][2]) > 4 or int(values[0][2]) < 2:
+                raise exceptions.RuntimeError("Grating must have between 2 and 4 ports")
+            else:
+                n = int(values[0][2])
+        else:
+            n = 2
+
+        values.pop(0) # remove initial value
+        
+        if n == 2:
+            if len(values) != 4:
+                raise exceptions.RuntimeError("Two port grating must have 2 nodes defined")
+
+            return grating(values[0], values[2], values[3], None, None, n, values[1])
+        elif n == 3:
+            if len(values) != 5:
+                raise exceptions.RuntimeError("Three port grating must have 3 nodes defined")
+            
+            return grating(values[0], values[2], values[3], values[4], None, n, values[1])
+        else:
+            if len(values) != 6:
+                raise exceptions.RuntimeError("Four port grating must have 4 nodes defined")
+            
+            return grating(values[0], values[2], values[3], values[4], values[5], n, values[1])
+        
+    def getFinesseText(self):
+        rtn = []
+        
+        if self.__n == 2:
+            rtn.append('gr{0} {1} {2} {3} {4}'.format(self.__n, self.name, self.__d, self.nodes[0].name, self.nodes[1].name))
+        elif self.__n == 3:
+            rtn.append('gr{0} {1} {2} {3} {4} {5}'.format(self.__n, self.name, self.__d, self.nodes[0].name, self.nodes[1].name, self.nodes[2].name))
+        else:
+            rtn.append('gr{0} {1} {2} {3} {4} {5} {6}'.format(self.__n, self.name, self.__d, self.nodes[0].name, self.nodes[1].name, self.nodes[2].name, self.nodes[3].name))
+        
+        if self.eta_0 != 0: rtn.append("attr {0} eta_0 {1}".format(self.name,self.__eta_0))
+        if self.eta_1 != 0: rtn.append("attr {0} eta_1 {1}".format(self.name,self.__eta_1))
+        if self.eta_2 != 0: rtn.append("attr {0} eta_2 {1}".format(self.name,self.__eta_2))
+        if self.eta_3 != 0: rtn.append("attr {0} eta_3 {1}".format(self.name,self.__eta_3))
+        if self.rho_0 != 0: rtn.append("attr {0} rho_0 {1}".format(self.name,self.__rho_0))
+        if self.alpha != 0: rtn.append("attr {0} alpha {1}".format(self.name,self.__alpha))
+        # TODO: implement Rcx, Rcy, Rc
+        
+        return rtn
+       
+    def getQGraphicsItem(self):
+        if self._QItem == None:
+            self._QItem = pykat.gui.graphics.SpaceQGraphicsItem(self) # TODO: make SVG graphic for grating
+        
+        return self._QItem
     
 class laser(Component):
     def __init__(self,name,node,P=1,f_offset=0,phase=0):
diff --git a/pykat/finesse.py b/pykat/finesse.py
index 16b819ff4db647bced489edd0340d5c2f93d6dbd..36415248855bce3cfbd6b738f6405e4eab28ef5b 100644
--- a/pykat/finesse.py
+++ b/pykat/finesse.py
@@ -205,6 +205,8 @@ class kat(object):
                     obj = pykat.components.laser.parseFinesseText(line)
                 elif(first[0:2] == "bs"):
                     obj = pykat.components.beamSplitter.parseFinesseText(line)
+                elif(first[0:2] == "gr"):
+                    obj = pykat.components.grating.parseFinesseText(line)
                 elif(first[0:2] == "pd"):
                     obj = pykat.detectors.photodiode.parseFinesseText(line)
                 elif(first == "xaxis" or first == "x2axis" or first == "xaxis*" or first == "x2axis*"):