Skip to content
Snippets Groups Projects
Select Git revision
  • 9cdbd15a59540e9e7ef0aae30911c2cf631a4d7f
  • master default protected
  • 72-improve-docs-for_optimal_setup
  • os-path-join
  • develop-GA
  • add-higher-spindown-components
  • v1.3
  • v1.2
  • v1.1.2
  • v1.1.0
  • v1.0.1
11 results

sliding_window.py

Blame
  • node_network.py 10.86 KiB
    # -*- coding: utf-8 -*-
    """
    Created on Sun Jan 27 10:02:41 2013
    
    @author: Daniel
    """
    import exceptions
    import pykat.gui.graphics
    import pykat.exceptions as pkex
    from pykat.components import Component
    from pykat.detectors import Detector
    from pykat.utilities.optics.gaussian_beams import gauss_param
    
    class NodeNetwork(object):
        def __init__(self, kat):
            self.__nodes = {}
            self.__kat = kat
            self.__nodeComponents = {} # dictionary of tuples containing which components are connected to a node
            self.__componentNodes = {} # dictionary of tuples containing which nodes are connected to a given component
            self.__componentCallback = {}
            self.__node_id = 1
            
            cls = type(self)
            self.__class__ = type(cls.__name__, (cls,), {})
            
        def registerComponentNodes(self, comp, node_names, change_callback):
            """
            For a given component we create some nodes or get existing ones and 
            attach them to this component. Also specify a callback function that
            is called whenever the nodes attached to this component are changed
            , e.g. connected, disconnected, name change, etc.
            """
            if not isinstance(comp, Component):
                raise exceptions.ValueError("comp argument is not of type Component")
            
            if comp.id in self.__componentNodes:
                raise pkex.BasePyKatException("Component has already been registered")
            
            list = []
            
            for name in node_names:
                n = self.createNode(name)
                self.connectNodeToComp(n, comp, do_callback=False)
                list.append(n)
            
            self.__componentNodes[comp.id] = tuple(list)
            self.__componentCallback[comp.id] = change_callback
            
            change_callback()
        
        def replaceNode(self, comp, node_old, node_new):
            
            if 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:
                raise pkex.BasePyKatException("New node already attached to component")
            
            # add component to new node component list
            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)
            
            # 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)
            
            comp_nodes = list(comp.nodes)
            comp_nodes[comp_nodes.index(node_old)] = node_new
            self.__componentNodes[comp.id] = tuple(comp_nodes)
            
            # if old node is no longer connected to anything then delete it
            if node_old.components.count(None) == 2:
                self.removeNode(node_old)
                
            self.__componentCallback[comp.id]()
                
        def connectNodeToComp(self, node, comp, do_callback=True):
            if node.id in self.__nodeComponents:
                comps = self.__nodeComponents[node.id]
            else:
                comps = (None,) * 2
            
            if len(comps) >= 2 and comps[0] != None and comps[1] != None:
                raise pkex.BasePyKatException("Node is already connected to 2 components")
            
            l = list(comps)
            
            if l[0] == None:
                l[0] = comp
            elif l[1] == None:
                l[1] = comp
            else:
                raise pkex.BasePyKatException("Connected to two coponents already")
            
            self.__nodeComponents[node.id] = tuple(l)
            
            if do_callback: self.__componentCallback[comp.id]()
            
        def createNode(self, node_name):
            if node_name == 'dump':
                return DumpNode()
                
            if node_name in self.__nodes:
                # then this node already exists
                return self.__nodes[node_name]
            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)
                return n
            
        def removeNode(self, node):
            if not isinstance(node,Node):
                raise exceptions.ValueError("node argument is not of type Node")
            
            if node.name not in self.__nodes:
                raise exceptions.RuntimeError("Trying to remove node {0} when it has not been added".format(node.name))
            
            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")
                
            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] 
            
        def hasNode(self, name):
            return (name in self.__nodes)
        
        def getNodes(self):
            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):
            return self.__componentNodes[comp.id]
        
        def getNodeComponents(self, node):
            return self.__nodeComponents[node.id]
        
        def __add_node_attr(self, node):
    
            if not isinstance(node, Node):
                raise exceptions.ValueError("Argument is not of type Node")
            
            name = node.name
            fget = lambda self: self.__get_node_attr(name)
            
            setattr(self.__class__, name, property(fget))
            setattr(self, '__node_' + name, node)                   
        
        def __remove_node_attr(self, node):
            if not isinstance(node, Node):
                raise exceptions.ValueError("Argument is not of type Node")
            
            name = node.name
            delattr(self, '__node_' + name)
            delattr(self.__class__, name)
            
        def __get_node_attr(self, name):
            return getattr(self, '__node_' + name)        
            
        def __getitem__(self, value):
            return self.__nodes[str(value)]
            
        def __contains__(self, value):
            return value in self.__nodes
            
        
    class Node(object):
    
        def __init__(self, name, network, id):
            self._detectors = []
            self.__name = name
            self._item = None
            self._network = network
            self.__q_x = None
            self.__q_y = None
            self.__q_comp = None
            self.__id = id
        
        def __str__(self): return self.__name
        
        @property
        def id(self): return self.__id
        
        @property
        def network(self): return self._network
        
        @property
        def components(self): return self._network.getNodeComponents(self)
        
        @property
        def q(self):
            if self.__q_x == self.__q_y:
                return self.__q_x
            else:
                return (self.__q_x, self.__q_y)
                
        @property
        def qx(self): return self.__q_x
        @property
        def qy(self): return self.__q_y
        
        def removeGauss():
            self.__q_x = None
            self.__q_y = None
            self.__q_comp = None
        
        def setGauss(self, component, *args):
            self.__q_comp = component
            
            if len(args) == 1:
                self.__q_x = gauss_param(q=args[0])
                self.__q_y = gauss_param(q=args[0])
            elif len(args) == 2:
                self.__q_x = gauss_param(q=args[0])
                self.__q_y = gauss_param(q=args[1])
            else:
                raise pkex.BasePyKatException("Must specify either 1 Gaussian beam parameter or 2 for astigmatic beams")
            
        def getFinesseText(self):    
            if self.__q_x is None or self.__q_y is None or self.__q_comp is None:
                return []
                
            rtn = []
            
            if self.__q_x == self.__q_y:
                rtn.append("gauss* g_{node} {comp} {node} {z} {zr}".format(node=self.name, comp=self.__q_comp.name, z=self.__q_x.real, zr=self.__q_x.imag))
            else:
                rtn.append("gauss* g_{node} {comp} {node} {zx} {zrx} {zy} {zry}".format(node=self.name, comp=self.__q_comp.name, zx=self.__q_x.real, zrx=self.__q_x.imag, zy=self.__q_y.real, zry=self.__q_y.imag))
                
            return rtn
            
        def isConnected(self):
            if (self.components[0] is not None) and (self.components[1] is not None):
                return True
            else:
                return False
          
        def remove(self):
            self._network.removeNode(self)
            
            if self._item != None:
                self._item.scene().removeItem(self._item)
        
        def getQGraphicsItem(self,dx=0,dy=0,nsize=8,parent=None):
            if self._item == None:
                self._item = pykat.gui.graphics.NodeQGraphicItem(self,
                                                                 dx,dy,
                                                                 -nsize/2,-nsize/2,
                                                                 nsize, nsize, parent)
                
            return self._item
        
        def getDetectors(self):
            return self._detectors[:]
            
        def amIConnected(self, obj):
            """
            Checks if obj is connected to the node. Returns true or false in tuple
            with None or the other object and the node index which it is attached to
            """ 
            comps = self.components
            
            if obj == comps[0]:
                if comps[1] == None:
                    ix = -1
                else:
                    ix = comps[1].nodes.index(self)
                    
                return [True, comps[1], ix]
                
            elif obj == comps[1]:
                if comps[0] == None:
                    ix = -1
                else:
                    ix = comps[0].nodes.index(self)
                    
                return [True, comps[0], ix]
            else:
                return [False, None]
            
        @property
        def name(self): return self.__name      
        
        
    class DumpNode(Node):
        def __init__(self):
            Node.__init__(self, 'dump', None, -1)