diff --git a/pykat/components.py b/pykat/components.py index e6a9a7d8ebe736b361820562f79933cdde08cd49..783aa5535f196c792218f1d3f946305a6bc8083b 100644 --- a/pykat/components.py +++ b/pykat/components.py @@ -5,6 +5,7 @@ Created on Mon Jan 28 11:10:01 2013 @author: Daniel """ import exceptions +import pykat.exceptions as pkex import pykat from pykat.node_network import * @@ -12,22 +13,83 @@ import pykat.gui.resources import pykat.gui.graphics from pykat.gui.graphics import * +next_component_id = 1 + +class NodeGaussSetter: + def __init__(self, component, node): + + if not isinstance(component, Component): + raise pkex.BasePyKatException("Value passed is not a Component") + + if not isinstance(node, Node): + raise pkex.BasePyKatException("Value passed is not a Node") + + self._comp = component + self._node = node + class Component(object) : def __init__(self, name): self.__name = name self._svgItem = None - self._nodes = [] + self._nodes = None self._requested_node_names = [] self._kat = None - - def _on_kat_add(self, kat): + + # store a unique ID for this component + global next_component_id + self.__id = next_component_id + next_component_id += 1 + + def _on_kat_add(self, kat, node_array): """ - Called when this component has been added to a kat object + Called when this component has been added to a kat object. + kat is the finesse.kat object which it now belongs to and + node_array is an array specific to this object which contains + references to the nodes that are attached to it. """ + if self._kat != None: + raise pkex.BasePyKatException("Component has already been added to a finesse.kat object") + self._kat = kat for node_name in self._requested_node_names: - self._addNode(node_name) + node = self.__addNode(node_name) + + # now that we have changed what our nodes are we need to + # update stuff... + self._on_node_change() + + def _on_node_change(): + # need to update the node gauss parameter setter members + self.__update_node_setters() + + def __update_node_setters(self): + # check if any node setters have already been added. If so we + # need to remove them. This function should get called if the nodes + # are updated, either by some function call or the GUI + key_rm = [k for k in self.__dict__ if k.startswith("__nodesetter_", 0, 13)] + # now we have a list of which to remove + for key in key_rm: + ns = self.__dict__[key] + detattr(self, '__nodesetter_' + ns._node.name) + delattr(self.__class__, ns._node.name) + + for node_name in self.getNodes(): + self.__add_node_setter(NodeGaussSetter(self, node)) + + def __add_node_setter(self, ns): + + if not isinstance(ns, NodeGaussSetter): + raise exceptions.ValueError("Argument is not of type NodeGaussSetter") + + name = ns.__class__.__name__ + fget = lambda self: self.__get_node_setter(name) + + setattr(self.__class__, name, property(fget)) + setattr(self, '__nodesetter_' + name, ns) + + def __get_node_setter(self, name): + return getattr(self, '__nodesetter_' + name) @staticmethod def parseFinesseText(text): @@ -43,29 +105,27 @@ class Component(object) : def getQGraphicsItem(self): return None - def _addNode(self, name): - """ Adds a node in sequential order to the component, i.e. add them - n1, n2, n3, n4... etc. by the name of the node""" - + def __addNode(self, name): n = self._kat.nodes.createNode(name) if n == None: raise exceptions.RuntimeError("createNode did not return a node for '{0}'".format(name)) else: n.connect(self) - - self._nodes.append(n) - + return n def getNodes(self): """ Returns a copy of the nodes the component has """ - return self._nodes[:] - - def __getname(self): - return self.__name - - name = property(__getname) + return self._kat.nodes.getComponentNodes(self) + + @property + def name(self): return self.__name + + @property + def id(self): return self.__id + + class Param(float): def __new__(self,name,value): diff --git a/pykat/finesse.py b/pykat/finesse.py index 5522cfd478d88af068557d1f331eb01681913bb0..d0f9ac22405f07cc970ef925cececfd425b8ddb7 100644 --- a/pykat/finesse.py +++ b/pykat/finesse.py @@ -52,12 +52,9 @@ class katRun(object): self.katScript = None self.katVersion = None - def saveKatRun(self, run, filename): - if not isinstance(run, katRun): - raise BasePyKatException("run object must be a katRun type") - + def saveKatRun(self, filename): with open(filename,'w') as outfile: - pickle.dump(run, outfile, pickle.HIGHEST_PROTOCOL) + pickle.dump(self, outfile) @staticmethod def loadKatRun(filename): @@ -65,11 +62,21 @@ class katRun(object): return pickle.load(infile) +class Block: + def __init__(self, name): + self.__name = name + self.contents = {} # dictionary of objects and strings of finesse code + self.enabled = True + + @property + def name(self): return self.__name + class kat(object): def __init__(self, kat_file=None, kat_code=None, katdir="", katname=""): self.scene = None # scene object for GUI + self.__blocks = {} # dictionary of blocks that are used self.__components = {} # dictionary of optical components self.__detectors = {} # dictionary of detectors self.__commands = {} # dictionary of commands @@ -79,7 +86,9 @@ class kat(object): self.__katdir = katdir self.__katname = katname self.pykatgui = None - # Various + + # Various options for running finesse, typicaly the commands with just 1 input + # and have no name attached to them. self.__phase = None self.__maxtem = None self.__noxaxis = None diff --git a/pykat/node_network.py b/pykat/node_network.py index 715bc654570da1f5a96bff6d52ad4d68dd9024b3..850e5fcf428cc5905c148f5bfe8ac9f58dfb21e4 100644 --- a/pykat/node_network.py +++ b/pykat/node_network.py @@ -14,6 +14,7 @@ class NodeNetwork(object): def __init__(self, kat): self._nodes = {} self.__kat = kat + self.__componentNodes = {} def createNode(self, node_name): if node_name == 'dump': @@ -81,7 +82,14 @@ class NodeNetwork(object): print "node: {0} connected:{1} {2}->{3} {4}".format( n.name,n.isConnected(),comp1, comp2, detectors) - + + def getComponentNodes(self, comp): + + if not isinstance(comp, Component): + raise pkex.BasePyKatException("Passed object was not a component") + + return self.__componentNodes[comp.id] + def __add_node(self, node): if not isinstance(node, Node): @@ -98,7 +106,7 @@ class NodeNetwork(object): raise exceptions.ValueError("Argument is not of type Node") name = node.name - setattr(self, '__node_' + name) + detattr(self, '__node_' + name) delattr(self.__class__, name) def __get_node(self, name):