diff --git a/examples/optivis_ex.py b/examples/optivis_ex.py
new file mode 100644
index 0000000000000000000000000000000000000000..0259beb855d60b81a86335a02d13dff549d0a618
--- /dev/null
+++ b/examples/optivis_ex.py
@@ -0,0 +1,16 @@
+import pykat
+
+kat = pykat.finesse.kat()
+
+kat.parseCommands("""
+l l1 1 0 n0
+s s1 100 n0 n1
+m m1 1 0 0 n1 n2
+s s2 200 n2 n3
+bs bs1 1 0 45 45 n3 dump n4 dump
+s s3 200 n4 n5
+m m2 1 0 0 n5 n6
+""")
+
+kat.optivis().show()
+
diff --git a/pykat/__init__.py b/pykat/__init__.py
index 9b14f735d2213da106e9b1cd22c2b5be53a8cd38..44967d63970b0eac551f4968d7692b10457e3944 100644
--- a/pykat/__init__.py
+++ b/pykat/__init__.py
@@ -2,6 +2,14 @@ __version__ = "0.6.2"
 
 # This flag is used to switch on the gui features in pkat at import time
 USE_GUI = False
+HAS_OPTIVIS = False
+
+import imp
+try:
+    imp.find_module('optivis')
+    HAS_OPTIVIS = True
+except ImportError:
+    HAS_OPTIVIS = False
 
 import pykat.exceptions as pkex
 
diff --git a/pykat/components.py b/pykat/components.py
index 7193049e4a4ec5df00b4b3f0fb7b35ceb1eca3bb..413a0123341ca964ef036a336b565617a8c5c798 100644
--- a/pykat/components.py
+++ b/pykat/components.py
@@ -5,6 +5,9 @@ Created on Mon Jan 28 11:10:01 2013
 @author: Daniel
 """
 from __future__ import print_function
+
+from pykat import USE_GUI, HAS_OPTIVIS, NoGUIException
+
 import pykat.external.six as six
 if six.PY2:
 	import exceptions
@@ -15,6 +18,9 @@ from pykat.exceptions import *
 import abc
 import copy
 
+if HAS_OPTIVIS:
+    import optivis.bench.components as optivis_components
+
 from pykat.SIfloat import *
 from pykat.param import Param, AttrParam
 import weakref
@@ -22,8 +28,6 @@ import pykat.exceptions as pkex
 
 next_component_id = 1
 
-from pykat import USE_GUI, NoGUIException
-
 if USE_GUI:
     import pykat.gui.resources
     import pykat.gui.graphics
@@ -80,6 +84,7 @@ class Component(object):
         
     def __init__(self, name=None):
         
+        self._optivis_component = None
         self.__name = name
         self._svgItem = None
         self._requested_node_names = []
@@ -444,6 +449,31 @@ class mirror(AbstractMirrorComponent):
             rtn.extend(p.getFinesseText())
                     
         return rtn
+    
+    def getOptivisComponent(self):
+        if self._optivis_component is None:
+            self._optivis_component = optivis_components.CavityMirror(name=self.name, aoi=0)
+        
+        return self._optivis_component
+    
+    def getOptivisNode(self, mode, kat_node):
+        mode = mode.lower()
+        
+        if mode != "input" and mode.lower() != "output":
+            raise pkex.BasePyKatException("Mode must be either input or output not %s" % mode)
+        
+        if mode == "input":
+            if kat_node is self.nodes[0]:
+                return self._optivis_component.getInputNode("fr")
+            else:
+                return self._optivis_component.getInputNode("bk")
+                
+        elif mode == "output":
+            if kat_node is self.nodes[0]:
+                return self._optivis_component.getOutputNode("fr")
+            else:
+                return self._optivis_component.getOutputNode("bk")
+          
         
     def getQGraphicsItem(self):
         if not USE_GUI:
@@ -477,7 +507,38 @@ class beamSplitter(AbstractMirrorComponent):
                     self.alpha = values[key]
                 else:
                     raise pkex.BasePyKatException("No attribute {0} for mirrors".format(key))
-                
+    
+    def getOptivisComponent(self):
+        if self._optivis_component is None:
+            self._optivis_component = optivis_components.BeamSplitter(name=self.name, aoi=self.alpha)
+        
+        return self._optivis_component
+    
+    def getOptivisNode(self, mode, kat_node):
+        mode = mode.lower()
+        
+        if mode != "input" and mode.lower() != "output":
+            raise pkex.BasePyKatException("Mode must be either input or output")
+        
+        if mode == "input":
+            if kat_node is self.nodes[0]:
+                return self._optivis_component.getInputNode("frA")
+            elif kat_node is self.nodes[1]:
+                return self._optivis_component.getInputNode("frB")
+            elif kat_node is self.nodes[2]:
+                return self._optivis_component.getInputNode("bkA")
+            elif kat_node is self.nodes[3]:
+                return self._optivis_component.getInputNode("bkB")
+        elif mode == "output":
+            if kat_node is self.nodes[0]:
+                return self._optivis_component.getOutputNode("frA")
+            elif kat_node is self.nodes[1]:
+                return self._optivis_component.getOutputNode("frB")
+            elif kat_node is self.nodes[2]:
+                return self._optivis_component.getOutputNode("bkA")
+            elif kat_node is self.nodes[3]:
+                return self._optivis_component.getOutputNode("bkB")
+                     
     @staticmethod
     def parseFinesseText(text):
         values = text.split()
@@ -574,6 +635,18 @@ class space(Component):
     @gy.setter
     def gy(self,value): self.__gy.value = SIfloat(value)
     
+    def connectingComponents(self):
+        """
+        Returns the two components that this space connects.
+        """
+        a = list(self.nodes[0].components + self.nodes[1].components)
+        a = [value for value in a if value != self]
+        
+        if len(a) != 2:
+            raise pkex.BasePyKatException("Space should only connect 2 components")
+            
+        return a
+        
     def parseAttributes(self, values):
         
         for key in values.keys():
@@ -993,7 +1066,24 @@ class laser(Component):
             rtn.extend(p.getFinesseText())
         
         return rtn
-         
+
+    def getOptivisComponent(self):
+        if self._optivis_component is None:
+            self._optivis_component = optivis_components.Laser(name=self.name)
+        
+        return self._optivis_component
+    
+    def getOptivisNode(self, mode, kat_node):
+        mode = mode.lower()
+        
+        if mode != "input" and mode.lower() != "output":
+            raise pkex.BasePyKatException("Mode must be either input or output")
+        
+        if mode == "input":
+            return None
+        elif mode == "output":
+            return self._optivis_component.getOutputNode("out")
+                
     def getQGraphicsItem(self):
         if not USE_GUI:
             raise NoGUIException
diff --git a/pykat/finesse.py b/pykat/finesse.py
index b33974a86b1c22a9c636f7eae24f2722b77d3d24..a6d1085899c69262d00da823a6145c5c141d3f61 100644
--- a/pykat/finesse.py
+++ b/pykat/finesse.py
@@ -53,7 +53,7 @@ from pykat.param import Param, AttrParam
 
 import pykat.exceptions as pkex
 
-from pykat import USE_GUI, NoGUIException
+from pykat import USE_GUI, HAS_OPTIVIS, NoGUIException
 
 if USE_GUI:
     from pykat.gui.gui import pyKatGUI
@@ -1444,6 +1444,49 @@ class kat(object):
         #out.append("pyterm no\n")
         
         return out
+    
+    def optivis(self):
+        if not HAS_OPTIVIS:
+            print("Optivis is not installed")
+            return None
+        
+        import optivis.scene as scene
+        import optivis.bench.links as links
+        import optivis.view.canvas as canvas
+        
+        scene = scene.Scene(title="Example 2", azimuth=180)
+        
+        # Run through once to add components, ignoring spaces
+        for c in self.getComponents():
+            if isinstance(c, pykat.components.space): continue
+            print("Adding %s" % c.name)
+            optivis_op = getattr(c, "getOptivisComponent", None)
+            
+            if callable(optivis_op):
+                scene.addComponent(c.getOptivisComponent())
+
+        # Run through again to add links
+        for c in self.getComponents():
+            if not isinstance(c, pykat.components.space):
+                continue
+            
+            a = c.connectingComponents()
+            
+            c1 = a[0].getOptivisComponent()
+            c2 = a[1].getOptivisComponent()
+            
+            no = a[0].getOptivisNode("Output", c.nodes[0])
+            ni = a[1].getOptivisNode("Input", c.nodes[1])
+            
+            if no is None or ni is None:
+                raise pkex.BasePyKatException("Optivis node is None")
+            
+            print("Link %s (%s) -> %s (%s)" %(a[0].name, no.name, a[1].name, ni.name))
+            scene.addLink(links.Link(no, ni, c.L.value))
+                
+        gui = canvas.Simple(scene=scene)
+        
+        return gui
         
     def openGUI(self):
         if not USE_GUI:
@@ -1451,17 +1494,17 @@ class kat(object):
         else:
             self.app = QCoreApplication.instance() 
             created = False
-            
+        
             if self.app == None:
                 created = True
                 self.app = QApplication([""])
-                
+            
             if self.pykatgui == None:
                 self.pykatgui = pyKatGUI(self)
                 self.pykatgui.main()
             else:
                 self.pykatgui.show()
-                
+            
             if created: self.app.exec_()
     
     def getComponents(self):