Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
finesse
pykat
Commits
847ec1e5
Commit
847ec1e5
authored
Jan 27, 2017
by
Andreas Freise
Browse files
Merge branch 'master' of gitlab.aei.uni-hannover.de:finesse/pykat
parents
18729b12
8e2b56af
Changes
12
Hide whitespace changes
Inline
Side-by-side
README.rst
View file @
847ec1e5
...
...
@@ -6,6 +6,8 @@ It aims to provide a Python toolset for automating more complex tasks
as well as providing a GUI for manipulating and viewing simulation
setups.
Source code is hosted at https://git.ligo.org/finesse/pykat
Installation
-------------
...
...
pykat/__init__.py
View file @
847ec1e5
...
...
@@ -3,7 +3,7 @@ from __future__ import division
from
__future__
import
print_function
from
__future__
import
unicode_literals
__version__
=
"1.0.1
4
"
__version__
=
"1.0.1
7
"
# This flag is used to switch on the gui features in pkat at import time
USE_GUI
=
False
...
...
@@ -20,7 +20,7 @@ except ImportError:
import
pykat.exceptions
as
pkex
NoGUIException
=
pkex
.
BasePyKatException
(
"No PyQt4 module was found so cannot open a GUI"
)
import
pykat.finesse
as
finesse
import
pykat.components
as
components
import
pykat.detectors
as
detectors
...
...
@@ -30,4 +30,3 @@ from pykat.optics.gaussian_beams import BeamParam
from
pykat.plotting
import
init_pykat_plotting
pykat/commands.py
View file @
847ec1e5
...
...
@@ -10,6 +10,8 @@ from __future__ import print_function
from
__future__
import
unicode_literals
import
numpy
import
warnings
import
pykat
import
pykat.external.six
as
six
import
pykat.exceptions
as
pkex
...
...
@@ -22,35 +24,38 @@ from numpy import min, max
from
pykat.param
import
Param
,
putter
from
collections
import
namedtuple
from
pykat.optics.gaussian_beams
import
BeamParam
from
pykat.freeze
import
canFreeze
@
canFreeze
class
Command
(
object
):
__metaclass__
=
abc
.
ABCMeta
def
__init__
(
self
,
name
,
unique
):
self
.
__dict__
[
"____FROZEN____"
]
=
False
self
.
_kat
=
None
self
.
__unique
=
unique
self
.
tag
=
None
self
.
__removed
=
False
self
.
__name
=
name
.
strip
(
"*"
)
self
.
_putters
=
[]
def
__deepcopy__
(
self
,
memo
):
"""
When deep copying a kat object we need to take into account
the instance specific properties.
"""
cls
=
self
.
__class__
result
=
cls
.
__new__
(
cls
)
result
.
_unfreeze
()
result
.
__dict__
=
copy
.
deepcopy
(
self
.
__dict__
,
memo
)
for
_
in
result
.
_putters
:
_
.
_updateOwner
(
result
)
result
.
_freeze
()
return
result
def
getFinesseText
(
self
):
""" Base class for individual finesse optical components """
raise
NotImplementedError
(
"This function is not implemented"
)
...
...
@@ -103,7 +108,8 @@ class variable(Command):
def
__init__
(
self
,
name
,
value
):
Command
.
__init__
(
self
,
name
,
False
)
self
.
__value
=
value
self
.
_freeze
()
def
getFinesseText
(
self
):
return
"variable {name} {value}"
.
format
(
name
=
self
.
name
,
value
=
self
.
value
)
...
...
@@ -135,6 +141,8 @@ class func(Command):
self
.
output
=
putter
(
name
,
self
)
self
.
_putters
.
append
(
self
.
output
)
self
.
_freeze
()
def
getFinesseText
(
self
):
rtn
=
[]
...
...
@@ -175,7 +183,8 @@ class lock(Command):
self
.
output
=
putter
(
name
,
self
)
self
.
_putters
.
append
(
self
.
output
)
self
.
_freeze
()
@
staticmethod
def
parseFinesseText
(
line
,
kat
):
v
=
line
.
split
()
...
...
@@ -228,6 +237,8 @@ class cavity(Command):
self
.
enabled
=
True
self
.
_freeze
()
def
getFinesseText
(
self
):
if
self
.
enabled
:
return
'cav {0} {1} {2} {3} {4}'
.
format
(
self
.
name
,
self
.
__c1
.
name
,
self
.
__n1
.
name
,
self
.
__c2
.
name
,
self
.
__n2
.
name
);
...
...
@@ -405,6 +416,8 @@ class tf(Command):
self
.
poles
=
[]
self
.
gain
=
1
self
.
phase
=
0
self
.
_freeze
()
def
addPole
(
self
,
f
,
Q
):
self
.
poles
.
append
(
tf
.
fQ
(
SIfloat
(
f
),
SIfloat
(
Q
)))
...
...
@@ -504,6 +517,8 @@ class xaxis(Command):
self
.
__param
=
param
self
.
__comp
=
param
.
_owner
()
self
.
_freeze
()
def
_set_variables
(
self
):
self
.
x
=
putter
(
"x1"
,
self
)
self
.
mx
=
putter
(
"mx1"
,
self
)
...
...
pykat/components.py
View file @
847ec1e5
...
...
@@ -16,6 +16,7 @@ import pykat.external.six as six
if
six
.
PY2
:
import
exceptions
import
warnings
import
pykat.exceptions
as
pkex
import
pykat
from
pykat.node_network
import
*
...
...
@@ -36,6 +37,7 @@ from pykat.param import Param, AttrParam
import
weakref
import
pykat.exceptions
as
pkex
from
copy
import
deepcopy
from
pykat.freeze
import
canFreeze
next_component_id
=
1
...
...
@@ -85,7 +87,8 @@ class NodeGaussSetter(object):
self
.
__node
().
setGauss
(
self
.
__comp
(),
self
.
qx
,
complex
(
value
))
id_____pykat_class
=
0
@
canFreeze
class
Component
(
object
):
__metaclass__
=
abc
.
ABCMeta
...
...
@@ -99,9 +102,11 @@ class Component(object):
cnew
=
type
(
cnew_name
,
(
cls
,),
{})
return
object
.
__new__
(
cnew
)
o
=
object
.
__new__
(
cnew
)
return
o
def
__init__
(
self
,
name
=
None
):
self
.
_unfreeze
()
self
.
_optivis_component
=
None
self
.
__name
=
name
...
...
@@ -118,21 +123,22 @@ class Component(object):
global
next_component_id
self
.
__id
=
next_component_id
next_component_id
+=
1
def
__deepcopy__
(
self
,
memo
):
"""
When deep copying a kat object we need to take into account
the instance specific properties.
"""
# Here we create a copy of this object based of the base class
# of this one, otherwise we're making a copy of a copy of a copy...
result
=
self
.
__class__
.
__new__
(
self
.
__class__
.
__base__
)
result
.
_unfreeze
()
result
.
__dict__
=
copy
.
deepcopy
(
self
.
__dict__
,
memo
)
for
_
in
result
.
_params
:
_
.
_updateOwner
(
result
)
result
.
_freeze
()
return
result
def
_register_param
(
self
,
param
):
...
...
@@ -204,7 +210,8 @@ class Component(object):
self
.
__add_node_setter
(
ns
)
def
__add_node_setter
(
self
,
ns
):
self
.
_unfreeze
()
if
not
isinstance
(
ns
,
NodeGaussSetter
):
raise
exceptions
.
ValueError
(
"Argument is not of type NodeGaussSetter"
)
...
...
@@ -214,6 +221,8 @@ class Component(object):
setattr
(
self
.
__class__
,
name
,
property
(
fget
))
setattr
(
self
,
'__nodesetter_'
+
name
,
ns
)
self
.
_freeze
()
def
__get_node_setter
(
self
,
name
):
return
getattr
(
self
,
'__nodesetter_'
+
name
)
...
...
@@ -500,7 +509,8 @@ class mirror(AbstractMirrorComponent):
self
.
_requested_node_names
.
append
(
node1
)
self
.
_requested_node_names
.
append
(
node2
)
self
.
_freeze
()
def
parseAttributes
(
self
,
values
):
for
key
in
values
.
keys
():
...
...
@@ -592,6 +602,8 @@ class beamSplitter(AbstractMirrorComponent):
self
.
_requested_node_names
.
append
(
node3
)
self
.
_requested_node_names
.
append
(
node4
)
self
.
__alpha
=
Param
(
"alpha"
,
self
,
SIfloat
(
alpha
))
self
.
_freeze
()
@
property
def
alpha
(
self
):
return
self
.
__alpha
...
...
@@ -704,6 +716,8 @@ class space(Component):
self
.
__gy
=
AttrParam
(
"gy"
,
self
,
gy
)
self
.
_default_fsig_param
=
self
.
__L
self
.
_freeze
()
@
property
def
L
(
self
):
return
self
.
__L
...
...
@@ -830,6 +844,8 @@ class grating(Component):
self
.
__rho_0
=
AttrParam
(
"rho_0"
,
self
,
SIfloat
(
rho_0
))
self
.
__alpha
=
AttrParam
(
"alpha"
,
self
,
SIfloat
(
alpha
))
self
.
_svgItem
=
None
self
.
_freeze
()
@
property
def
n
(
self
):
return
Param
(
'n'
,
self
.
__n
)
...
...
@@ -959,6 +975,7 @@ class isolator(Component):
self
.
__S
=
Param
(
"S"
,
self
,
SIfloat
(
S
))
self
.
__L
=
Param
(
"L"
,
self
,
SIfloat
(
L
))
self
.
_freeze
()
@
property
def
S
(
self
):
return
self
.
__S
...
...
@@ -1064,6 +1081,8 @@ class isolator1(Component):
self
.
_requested_node_names
.
append
(
node4
)
self
.
_svgItem
=
None
self
.
_freeze
()
@
staticmethod
def
parseFinesseText
(
text
):
values
=
text
.
split
()
...
...
@@ -1104,6 +1123,8 @@ class lens(Component):
self
.
_svgItem
=
None
self
.
__f
=
Param
(
"f"
,
self
,
SIfloat
(
f
))
self
.
__p
=
Param
(
"p"
,
self
,
SIfloat
(
p
))
self
.
_freeze
()
@
property
def
f
(
self
):
return
self
.
__f
...
...
@@ -1200,6 +1221,8 @@ class modulator(Component):
self
.
type
=
modulation_type
self
.
_default_fsig_param
=
self
.
__phase
self
.
_freeze
()
@
property
def
f
(
self
):
return
self
.
__f
...
...
@@ -1316,6 +1339,8 @@ class laser(Component):
self
.
_svgItem
=
None
self
.
_default_fsig_param
=
self
.
__f_offset
self
.
_freeze
()
@
property
def
P
(
self
):
return
self
.
__power
...
...
@@ -1413,6 +1438,9 @@ class squeezer(Component):
self
.
__angle
=
Param
(
"angle"
,
self
,
SIfloat
(
angle
),
canFsig
=
False
,
fsig_name
=
"angle"
)
self
.
_svgItem
=
None
self
.
entangled_carrier
=
entangled_carrier
self
.
_freeze
()
@
property
def
db
(
self
):
return
self
.
__db
...
...
pykat/detectors.py
View file @
847ec1e5
...
...
@@ -26,6 +26,7 @@ import warnings
import
copy
from
pykat
import
USE_GUI
,
NoGUIException
from
pykat.freeze
import
canFreeze
if
USE_GUI
:
import
pykat.gui.resources
...
...
@@ -33,6 +34,7 @@ if USE_GUI:
id_____pykat_class
=
0
@
canFreeze
class
BaseDetector
(
object
)
:
"""
This is a base class for all detectors. Classes Detector1 and Detector2 should be used directly.
...
...
@@ -51,9 +53,12 @@ class BaseDetector(object) :
cnew
=
type
(
cnew_name
,
(
cls
,),
{})
return
object
.
__new__
(
cnew
)
o
=
object
.
__new__
(
cnew
)
return
o
def
__init__
(
self
,
name
,
nodes
=
None
,
max_nodes
=
1
):
self
.
_unfreeze
()
self
.
__name
=
name
self
.
_svgItem
=
None
...
...
@@ -106,8 +111,10 @@ class BaseDetector(object) :
# Here we create a copy of this object based of the base class
# of this one, otherwise we're making a copy of a copy of a copy...
result
=
self
.
__class__
.
__new__
(
self
.
__class__
.
__base__
)
result
.
_unfreeze
()
result
.
__dict__
=
copy
.
deepcopy
(
self
.
__dict__
,
memo
)
result
.
_freeze
()
return
result
def
_register_param
(
self
,
param
):
...
...
@@ -243,6 +250,8 @@ class beam(Detector1):
self
.
alternate_beam
=
alternate_beam
self
.
__f
=
Param
(
"f"
,
self
,
frequency
)
self
.
_freeze
()
@
property
def
f
(
self
):
return
self
.
__f
...
...
@@ -291,6 +300,8 @@ class cp(Detector0):
self
.
cavity
=
str
(
cavity
)
self
.
direction
=
direction
self
.
parameter
=
parameter
self
.
_freeze
()
@
property
def
direction
(
self
):
return
self
.
__direction
...
...
@@ -345,6 +356,8 @@ class xd(Detector0):
self
.
component
=
component
self
.
motion
=
motion
self
.
_freeze
()
@
staticmethod
def
parseFinesseText
(
text
):
...
...
@@ -373,6 +386,8 @@ class ad(Detector1):
self
.
alternate_beam
=
alternate_beam
self
.
__f
=
Param
(
"f"
,
self
,
frequency
)
self
.
_freeze
()
@
property
def
mode
(
self
):
return
self
.
__mode
@
mode
.
setter
...
...
@@ -426,6 +441,8 @@ class gouy(Detector1):
self
.
spaces
=
copy
.
copy
(
spaces
)
self
.
direction
=
direction
self
.
alternate_beam
=
False
self
.
_freeze
()
@
property
def
direction
(
self
):
return
self
.
__dir
...
...
@@ -475,6 +492,8 @@ class bp(Detector1):
self
.
parameter
=
parameter
self
.
direction
=
direction
self
.
alternate_beam
=
alternate_beam
self
.
_freeze
()
@
property
def
direction
(
self
):
return
self
.
__dir
...
...
@@ -598,9 +617,10 @@ class pd(Detector1):
ps
[
i
].
value
=
kwargs
[
p
]
elif
i
<
num_demods
-
1
:
raise
pkex
.
BasePyKatException
(
"Missing demodulation phase {0} (phase{0})"
.
format
(
i
+
1
))
self
.
__set_demod_attrs
()
self
.
_freeze
()
@
property
def
senstype
(
self
):
return
self
.
__senstype
...
...
@@ -655,6 +675,7 @@ class pd(Detector1):
For the set number of demodulations the correct number of
Parameters are created.
"""
self
.
_unfreeze
()
# if there are demodulations present then we want to add
# the various parameters so they are available for users
...
...
@@ -678,8 +699,8 @@ class pd(Detector1):
if
hasattr
(
self
,
"phase"
+
name
):
delattr
(
self
.
__class__
,
"phase"
+
name
)
else
:
return
self
.
_freeze
()
@
staticmethod
def
parseFinesseText
(
text
):
...
...
@@ -776,7 +797,11 @@ class qnoised(pd):
def
__init__
(
self
,
name
,
num_demods
,
node_name
,
alternate_beam
=
False
,
pdtype
=
None
,
**
kwargs
):
super
(
qnoised
,
self
).
__init__
(
name
,
num_demods
,
node_name
,
alternate_beam
=
alternate_beam
,
pdtype
=
pdtype
,
**
kwargs
)
self
.
_unfreeze
()
self
.
__homangle
=
AttrParam
(
"homangle"
,
self
,
None
)
self
.
_freeze
()
@
property
def
homangle
(
self
):
return
self
.
__homangle
...
...
@@ -985,7 +1010,9 @@ class hd(Detector2):
BaseDetector
.
__init__
(
self
,
name
,
(
node1_name
,
node2_name
),
max_nodes
=
2
)
self
.
__phase
=
Param
(
"phase"
,
self
,
phase
)
self
.
_freeze
()
@
property
def
phase
(
self
):
return
self
.
__phase
@
phase
.
setter
...
...
@@ -1026,6 +1053,8 @@ class qhd(Detector2):
self
.
__phase
=
Param
(
"phase"
,
self
,
phase
)
self
.
sensitivity
=
sensitivity
self
.
_freeze
()
@
property
def
phase
(
self
):
return
self
.
__phase
...
...
pykat/finesse.py
View file @
847ec1e5
...
...
@@ -87,14 +87,13 @@ from pykat.commands import Command, xaxis
from
pykat.SIfloat
import
*
from
pykat.param
import
Param
,
AttrParam
from
pykat.external
import
progressbar
from
pykat.freeze
import
canFreeze
import
pykat.external.six
as
six
import
pykat.exceptions
as
pkex
from
pykat
import
USE_GUI
,
HAS_OPTIVIS
,
NoGUIException
if
HAS_OPTIVIS
:
from
optivis.bench.labels
import
Label
as
optivis_label
from
optivis.geometry
import
Coordinates
as
optivis_coord
...
...
@@ -210,6 +209,16 @@ class BlockedKatFile(object):
bkf.write("mytest.kat")
"""
def
__str__
(
self
):
rtn
=
""
for
block
in
self
.
ordering
:
rtn
+=
"
\n
%%% FTblock "
+
block
+
"
\n
"
rtn
+=
self
.
blocks
[
block
]
rtn
+=
"%%% FTend "
+
block
+
"
\n
"
return
rtn
def
__init__
(
self
,
NO_BLOCK
=
"NO_BLOCK"
):
self
.
__NO_BLOCK
=
NO_BLOCK
self
.
ordering
=
[
self
.
__NO_BLOCK
]
...
...
@@ -265,12 +274,14 @@ class BlockedKatFile(object):
if
len
(
values
)
>=
3
and
values
[
0
]
==
"%%%"
:
if
values
[
1
]
==
"FTblock"
:
newTag
=
values
[
2
]
if
self
.
__currentBlock
!=
None
and
self
.
__currentBlock
!=
self
.
__NO_BLOCK
:
warnings
.
warn
(
"found block {0} before block {1} ended"
.
format
(
newTag
,
self
.
__currentBlock
))
if
newTag
in
self
.
blocks
:
raise
pkex
.
BasePyKatException
(
"Block `{0}` has already been read"
.
format
(
newTag
))
#raise pkex.BasePyKatException("Block `{0}` has already been read".format(newTag))
self
.
__currentBlock
=
newTag
continue
self
.
blocks
[
newTag
]
=
""
self
.
__currentBlock
=
newTag
...
...
@@ -330,18 +341,24 @@ def GUILength(L):
Should scale the lengths in some way to handle km and mm for time being
"""
return
L
# * ( 40 * erfc(L/400.0) + 0.01)
@
canFreeze
class
KatRun
(
object
):
def
__init__
(
self
):
self
.
_unfreeze
()
self
.
runtime
=
None
self
.
StartDateTime
=
datetime
.
datetime
.
now
()
self
.
x
=
None
self
.
stdout
=
None
self
.
stderr
=
None
self
.
runDateTime
=
None
self
.
y
=
None
self
.
xlabel
=
None
self
.
ylabels
=
None
self
.
katScript
=
None
self
.
katVersion
=
None
self
.
yaxis
=
None
self
.
_freeze
()
def
info
(
self
):
...
...
@@ -623,9 +640,11 @@ class KatRun(object):
return
out
.
squeeze
()
else
:
raise
pkex
.
BasePyKatException
(
"No output by the name '{0}' found in the output"
.
format
(
str
(
value
)))
@
canFreeze
class
KatRun2D
(
object
):
def
__init__
(
self
):
self
.
_unfreeze
()
self
.
runtime
=
None
self
.
startDateTime
=
datetime
.
datetime
.
now
()
self
.
x
=
None
...
...
@@ -638,6 +657,7 @@ class KatRun2D(object):
self
.
katVersion
=
None
self
.
stderr
=
None
self
.
stdout
=
None
self
.
_freeze
()
def
saveKatRun
(
self
,
filename
):
with
open
(
filename
,
'w'
)
as
outfile
:
...
...
@@ -658,10 +678,13 @@ class KatRun2D(object):
else
:
raise
pkex
.
BasePyKatException
(
"No output by the name {0} found"
.
format
(
str
(
value
)))
@
canFreeze
class
Signals
(
object
):
@
canFreeze
class
fsig
(
object
):
def
__init__
(
self
,
param
,
name
,
amplitude
,
phase
,
signal
):
self
.
_unfreeze
()
self
.
_params
=
[]
self
.
__target
=
param
self
.
__name
=
name
...
...
@@ -669,6 +692,7 @@ class Signals(object):
self
.
__phase
=
Param
(
"phase"
,
self
,
SIfloat
(
phase
))
self
.
__removed
=
False
self
.
__signal
=
signal
self
.
_freeze
()
# unfortunatenly the target names for fsig are not the same as the
# various parameter names of the components, e.g. mirror xbeta is x
...
...
@@ -691,7 +715,7 @@ class Signals(object):
raise
pkex
.
BasePyKatException
(
"Signal {0} has already been marked as removed"
.
format
(
self
.
name
))
else
:
self
.
__signal
.
targets
.
remove
(
self
)
self
.
__remove
=
True
self
.
__remove
d
=
True
@
property
def
name
(
self
):
return
self
.
__name
...
...
@@ -742,29 +766,36 @@ class Signals(object):
del
self
.
targets
[:]
self
.
f
=
None
@
property
def
f
(
self
):
return
self
.
__f
@
f
.
setter
def
f
(
self
,
value
):
if
value
is
None
:
self
.
__f
.
value
=
None
return
v
=
SIfloat
(
value
)
if
v
<=
0
:
raise
pkex
.
BasePyKatException
(
"Signal frequency must be greater than 0."
)
self
.
__f
.
value
=
SIfloat
(
value
)
def
__init__
(
self
,
kat
):
self
.
_unfreeze
()
self
.
_default_name
=
"fsignal"
self
.
targets
=
[]
self
.
_params
=
[]
self
.
__f
=
Param
(
"f"
,
self
,
None
)
self
.
_kat
=
kat
self
.
_freeze
()
def
_register_param
(
self
,
param
):
self
.
_params
.
append
(
param
)
def
apply
(
self
,
target
,
amplitude
,
phase
,
name
=
None
):
if
target
is
None
:
raise
pkex
.
BasePyKatException
(
"No target was specified for signal to be applied"
)
...
...
@@ -811,6 +842,7 @@ Constant = namedtuple('Constant', 'name, value, usedBy')
id___
=
0
@
canFreeze
class
kat
(
object
):
def
__new__
(
cls
,
*
args
,
**
kwargs
):
...
...
@@ -828,7 +860,7 @@ class kat(object):
return
object
.
__new__
(
cnew
)
def
__init__
(
self
,
kat_file
=
None
,
kat_code
=
None
,
katdir
=
""
,
katname
=
""
,
tempdir
=
None
,
tempname
=
None
):
self
.
_unfreeze
()
self
.
__looking
=
False
self
.
scene
=
None
# scene object for GUI
self
.
verbose
=
True
...
...
@@ -866,6 +898,7 @@ class kat(object):
self
.
__time_code
=
None
self
.
__yaxis
=
"abs"
# default yaxis
self
.
__lambda0
=
1064e-9
self
.
__finesse_dir
=
None