diff --git a/bin/test_put.py b/bin/test_put.py index 41155e42ee9d2c3d14016783c1c13e7ca3b68e42..e7cba00696a53f7f2b5eaac224a613bb7f5d8ac6 100644 --- a/bin/test_put.py +++ b/bin/test_put.py @@ -17,14 +17,18 @@ kat = finesse.kat() kat.parseCommands(code) -kat.add(photodiode('pd_ref','n3', num_demods=1, demods=[10,0])) +kat.add(pd('pdp',1,'n3')) +kat.add(pd('pdm',1,'n3')) -kat.add(xaxis("lin", [0, 1000], "pd_ref", "f1", 100)) +kat.add(xaxis("lin", [0, 1000], kat.eom, "f", 100)) + +kat.pdp.f1.put(kat.xaxis.x) +kat.pdm.f1.put(kat.xaxis.mx) out = kat.run(printout=0, printerr=0) pl.figure() -pl.plot(out.x, out["pd_ref"]) +pl.plot(out.x, out["pdp"], out.x, out["pdm"]) pl.xlabel(out.xlabel) pl.ylabel("Intensity [W]") pl.legend(out.ylabels) diff --git a/pykat/detectors.py b/pykat/detectors.py index ffe3076be50915d0550ec0413fe1aea3d8618476..30e46004ead75389d95c476d32db7ee9d524200b 100644 --- a/pykat/detectors.py +++ b/pykat/detectors.py @@ -20,13 +20,17 @@ class Detector(object) : self.enabled = True self.tag = None self.__node = None + self._params = [] if node.find('*'): self._alternate_beam = True node.replace('*','') self.__requested_node = node - + + def _register_param(self, param): + self._params.append(param) + def _on_kat_add(self, kat): self.__node = kat.nodes.createNode(self.__requested_node) @@ -43,12 +47,140 @@ class Detector(object) : @property def node(self): return self.__node + @node.setter + def node(self, value): + if value in self._kat.nodes: + self.__node = self._kat.nodes[value] + else: + raise pkex.BasePyKatException("There is no node called " + value) @property def name(self): return self.__name def __str__(self): return self.name + +class pd(Detector): + + def __init__(self, name, num_demods, node_name, senstype=None, alternate_beam=False, **kwargs): + Detector.__init__(self, name, node_name) + + self.__num_demods = num_demods + self.__senstype = senstype + self.__alternate_beam = alternate_beam + # create the parameters for all 5 demodulations regardless + # of how many the user specifies. Later we add properties to + # those which correspond to the number of demodulations + + self.__f1 = Param("f1", self, 0) + self.__f2 = Param("f2", self, 0) + self.__f3 = Param("f3", self, 0) + self.__f4 = Param("f4", self, 0) + self.__f5 = Param("f5", self, 0) + + self.__phi1 = Param("phi1", self, None) + self.__phi2 = Param("phi2", self, None) + self.__phi3 = Param("phi3", self, None) + self.__phi4 = Param("phi4", self, None) + self.__phi5 = Param("phi5", self, None) + + # define new class for assigning new attributes + cls = type(self) + self.__class__ = type(cls.__name__, (cls,), {}) + + self.__set_demod_attrs() + + @property + def senstype(self): return self.__senstype + @senstype.setter + def senstype(self,value): + if value == "": value = None + + if value != "S" and value != "N" and value != None: + raise pkex.BasePyKatException("Photodiode sensitivity type can either be 'N', 'S' or None.") + + self.__senstype = value + + @property + def num_demods(self): return self.__num_demods + @num_demods.setter + def num_demods(self, value): + if value < 0 or value > 5: + raise pkex.BasePyKatException("Number of demodulations must be between 0 and 5") + + self.__num_demods = value + self.__set_demod_attrs() + + def __get_fphi(self, name): + return getattr(self, '_'+ self.__class__.__name__ +'__' + name) + + def __set_f(self, num, value): + setattr(self, '_'+ self.__class__.__name__ +'__f' + name, float(value)) + def __set_phi(self, num, value): + if value == None and num != self.num_demods: + # check if we are setting no phase that this is only on the last + # demodulation phase. + raise pkex.BasePyKatException("Only last demodulation phase can be set to None") + elif isinstance(value, str) and not isinstance(value,float) and value.lower() != "max": + raise pkex.BasePyKatException("Demodulation phase can only be set to a 'max' or a number (or None if the last demodulation phase)") + + setattr(self, '_'+ self.__class__.__name__ +'__phi' + name, value) + + def __set_demod_attrs(self): + """ + For the set number of demodulations the correct number of + Parameters are created. + """ + + # if there are demodulations present then we want to add + # the various parameters so they are available for users + # to play with. + if self.__num_demods > 0: + for i in range(1,6): + name = str(i) + if i <= self.num_demods: + if not hasattr(self, "f"+name): + setattr(self.__class__, "f"+name, property(fget=lambda self, i=i: self.__get_fphi('f'+str(i)), fset=lambda self, value, i=i: self.__set_f(str(i), value))) + + if not hasattr(self, "phi"+name): + setattr(self.__class__, "phi"+name, property(fget=lambda self, i=i: self.__get_fphi('phi'+str(i)), fset=lambda self, value, i=i: self.__set_phi(str(i), value))) + else: + if hasattr(self, "f"+name): + delattr(self.__class__, "f"+name) + if hasattr(self, "phi"+name): + delattr(self.__class__, "phi"+name) + else: + return + + def getFinesseText(self) : + rtn = [] + + if self.enabled: + alt_str = "" + fphi_str = "" + + if self.__alternate_beam: + alt_str = "*" + + for n in range(1, 1+self.num_demods): + fphi_str += str(self.__getattribute__("f"+str(n))) + phi_val = self.__getattribute__("phi"+str(n)) + + if phi_val != None: + fphi_str += " " + str(phi_val) + + senstype = self.senstype + + if senstype == None: + senstype = "" + + rtn.append("pd{0}{1} {2} {3} {4}{5}".format(senstype, self.num_demods, self.name, fphi_str, self.node.name, alt_str)) + + for p in self._params: + rtn.extend(p.getFinesseText()) + + return rtn + class photodiode(Detector): class __F(list): @@ -83,8 +215,10 @@ class photodiode(Detector): def __init__(self, name, node, senstype="", num_demods=0, demods=[]): Detector.__init__(self, name, node) + if num_demods>2: raise NotImplementedError("pd with more than two demodulations not implemented yet") + self.num_demods = num_demods self.senstype = senstype diff --git a/pykat/finesse.py b/pykat/finesse.py index cd4fd21db2dcf3808fc40a132e167a565b1e4941..b0493a24f1531f2669fcbc9eef7ae891aa42b64f 100644 --- a/pykat/finesse.py +++ b/pykat/finesse.py @@ -77,7 +77,7 @@ class katRun(object): else: return self.y[:, idx] else: - raise pkex.BasePyKatException("No output by the name {0} found", value) + raise pkex.BasePyKatException("No output by the name {0} found".format(value)) class katRun2D(object): def __init__(self): @@ -156,7 +156,6 @@ class kat(object): cls = type(self) self.__class__ = type(cls.__name__, (cls,), {}) - #self.logo() @property def maxtem(self): return self.__maxtem @@ -503,7 +502,7 @@ class kat(object): self.__add_command(obj) else : - raise BasePyKatException("Object {0} could not be added".format(obj)) + raise pkex.BasePyKatException("Object {0} could not be added".format(obj)) obj._on_kat_add(self) @@ -683,7 +682,6 @@ class kat(object): def __get_detector(self, name): return getattr(self, '__det_' + name) - def __add_command(self, com): if not isinstance(com, Command): diff --git a/pykat/node_network.py b/pykat/node_network.py index 8c6a50addaec89f7423f56b616a853a12c9534e9..2ad607f0a2a8ea30120a176c8340a5b4ead071fd 100644 --- a/pykat/node_network.py +++ b/pykat/node_network.py @@ -200,6 +200,13 @@ class NodeNetwork(object): 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): @@ -211,7 +218,9 @@ class Node(object): self.__q_y = None self.__q_comp = None self.__id = id - + + def __str__(self): return self.__name + @property def id(self): return self.__id diff --git a/pykat/param.py b/pykat/param.py index eb9c7fbdfe417f0bfe7619fa5411a79ce1e805b1..6ae1f9a9b29c52d565ec0b6054329c31fa6a072e 100644 --- a/pykat/param.py +++ b/pykat/param.py @@ -21,7 +21,7 @@ class putable(object): def isPutable(self): return self._isPutable def put(self, var): - print "put" + if not isinstance(var, putter): raise pkex.BasePyKatException("var was not something that can be `put` as a value") @@ -103,31 +103,31 @@ class Param(putable, putter): return rtn def __mul__(self, a): - return float(self) * a + return self.value * a def __imul__(self, a): - return self.value * float(a) + return self.value * (a) __rmul__ = __mul__ def __add__(self, a): - return self.value + flota(a) + return self.value + (a) def __iadd__(self, a): - return self.value + float(a) + return self.value + (a) __radd__ = __add__ def __sub__(self, a): - return self.value - float(a) + return self.value - (a) def __isub__(self, a): - return self.value - float(a) + return self.value - (a) __rsub__ = __sub__ def __div__(self, a): - return self.value / float(a) + return self.value / (a) def __idiv__(self, a): return self.value / complex(a) @@ -139,13 +139,13 @@ class Param(putable, putter): return -self.value def __eq__(self, q): - return float(q) == self.value + return (q) == self.value def __ne__(self, q): - return float(q) != self.value + return (q) != self.value def __lt__(self, q): - return float(q) > self.value + return (q) > self.value def __gt__(self, q): - return float(q) < self.value + return (q) < self.value class AttrParam(Param): """