Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 77 additions & 0 deletions examples/ESRF_tune_example/esrf_tune_example_no_yaml.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
from pyaml.instrument import Instrument,ConfigModel as InstrumentConfigModel
from pyaml.magnet.quadrupole import Quadrupole,ConfigModel as QuadrupoleConfig
from pyaml.configuration.csvcurve import CSVCurve,ConfigModel as CSVCureveConfig
from pyaml.magnet.linear_model import LinearMagnetModel,ConfigModel as LinearMagnetModelConfig
from pyaml.lattice.simulator import Simulator,ConfigModel as SimulatorConfigModel
from pyaml.arrays.magnet import Magnet,ConfigModel as MagnetArrayConfigModel
from tango.pyaml.controlsystem import TangoControlSystem,ConfigModel as ControlSystemConfig
from tango.pyaml.attribute import Attribute,ConfigModel as AttributeConfig
from tango.pyaml.attribute_read_only import AttributeReadOnly,ConfigModel as AttributeReadOnlyConfig


import numpy as np
import time

# Configuration

tangocs = ControlSystemConfig(name="live",tango_host="ebs-simu-3:10000")
control = TangoControlSystem(tangocs)
control.init_cs()

qfCurve = CSVCurve(CSVCureveConfig(file="config/sr/magnet_models/QF1_strength.csv"))
qdCurve = CSVCurve(CSVCureveConfig(file="config/sr/magnet_models/QD2_strength.csv"))

elemConfig = [ {"name":"QF1A-C01", "attname":"srmag/vps-qf1/c01-a/current", "calibration_factor":1.00504, "curve":qfCurve},
{"name":"QF1E-C01", "attname":"srmag/vps-qf1/c01-e/current", "calibration_factor":0.998212, "curve":qfCurve},
{"name":"QD2A-C01", "attname":"srmag/vps-qd2/c01-a/current", "calibration_factor":1.00504, "curve":qdCurve},
{"name":"QD2E-C01", "attname":"srmag/vps-qd2/c01-e/current", "calibration_factor":1.003485189, "curve":qdCurve} ]

devices=[]
names=[]
for cfg in elemConfig:
qAtt = Attribute(AttributeConfig(attribute=cfg["attname"],unit="A"))
qModel = LinearMagnetModel(LinearMagnetModelConfig(curve=cfg["curve"],calibration_factor=cfg["calibration_factor"],powerconverter=qAtt,unit="1/m"))
devices.append( Quadrupole(QuadrupoleConfig(name=cfg["name"],model=qModel)) )
names.append(cfg["name"])


simulator = Simulator(SimulatorConfigModel(name="design",lattice="config/sr/lattices/ebs.mat"))

quads = Magnet(MagnetArrayConfigModel(name="quadsForTune",elements=names))

sr = Instrument(InstrumentConfigModel(name="sr",energy=6e9,controls=[control],simulators=[simulator],devices=devices,arrays=[quads],data_folder="/tmp"))



# Usage exmaple

quadForTuneDesign = sr.design.get_magnets("quadsForTune")
quadForTuneLive = sr.live.get_magnets("quadsForTune")

# Compute tune response matrix for the 4 quads from simulator
sr.design.get_lattice().disable_6d()
tune = sr.design.get_lattice().get_tune()
tunemat = np.zeros((len(quadForTuneDesign),2))
for idx,m in enumerate(quadForTuneDesign):
str = m.strength.get()
m.strength.set(str+1e-4)
dq = sr.design.get_lattice().get_tune() - tune
tunemat[idx] = dq*1e4
m.strength.set(str)

# Compute correction matrix
correctionmat = np.linalg.pinv(tunemat.T)

# Correct tune on live
qxAtt = AttributeReadOnly(AttributeReadOnlyConfig(attribute="sys/ringsimulator/ebs/Tune_h",unit=""))
qyAtt = AttributeReadOnly(AttributeReadOnlyConfig(attribute="sys/ringsimulator/ebs/Tune_v",unit=""))

print(f"Tune={qxAtt.readback()}, {qyAtt.readback()}")

strs = quadForTuneLive.strengths.get()
strs += np.matmul(correctionmat,[0.1,0.05]) # Ask for correction [dqx,dqy]
quadForTuneLive.strengths.set(strs)
time.sleep(3)
print(f"Tune={qxAtt.readback()}, {qyAtt.readback()}")


13 changes: 0 additions & 13 deletions pyaml/arrays/array.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,3 @@ def fill_array(self,holder:ElementHolder):
def init_aggregator(self,holder:ElementHolder):
raise "Array.init_aggregator() is not subclassed"

class MagnetArrayConfig(ArrayConfig):

def __init__(self, cfg: ArrayConfigModel):
super().__init__(cfg)

def init_aggregator(self,holder:ElementHolder):
if self._cfg.aggregator is not None and len(self._cfg.aggregator)==0:
# Construct dynamically aggregator for magnets
mag = holder.get_magnets(self._cfg.name)
for m in mag:
devs = m.model.get_devices()
self._cfg.aggregator.add_devices(devs)
mag.set_aggregator(self._cfg.aggregator)
24 changes: 24 additions & 0 deletions pyaml/arrays/magnet.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
from .array import ArrayConfigModel,ArrayConfig
from ..lattice.element_holder import ElementHolder

# Define the main class name for this module
PYAMLCLASS = "Magnet"

class ConfigModel(ArrayConfigModel):...

class Magnet(ArrayConfig):

def __init__(self, cfg: ArrayConfigModel):
super().__init__(cfg)

def fill_array(self,holder:ElementHolder):
holder.fill_magnet_array(self._cfg.name,self._cfg.elements)

def init_aggregator(self,holder:ElementHolder):
if self._cfg.aggregator is not None and len(self._cfg.aggregator)==0:
# Construct dynamically aggregator for magnets
mag = holder.get_magnets(self._cfg.name)
for m in mag:
devs = m.model.get_devices()
self._cfg.aggregator.add_devices(devs)
mag.set_aggregator(self._cfg.aggregator)
14 changes: 0 additions & 14 deletions pyaml/arrays/octupole.py

This file was deleted.

13 changes: 0 additions & 13 deletions pyaml/arrays/quadrupole.py

This file was deleted.

14 changes: 0 additions & 14 deletions pyaml/arrays/sextupole.py

This file was deleted.

14 changes: 0 additions & 14 deletions pyaml/arrays/skewoctu.py

This file was deleted.

14 changes: 0 additions & 14 deletions pyaml/arrays/skewquad.py

This file was deleted.

14 changes: 0 additions & 14 deletions pyaml/arrays/skewsext.py

This file was deleted.

13 changes: 0 additions & 13 deletions pyaml/arrays/vcorrector.py

This file was deleted.

2 changes: 1 addition & 1 deletion pyaml/configuration/factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ def depth_first_build(self, d):

def register_element(self, elt):
if isinstance(elt,Element):
name = str(elt)
name = elt.get_name()
if name in self._elements:
raise PyAMLException(f"element {name} already defined")
self._elements[name] = elt
Expand Down
2 changes: 1 addition & 1 deletion pyaml/control/abstract_impl.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ def __init__(self, model:MagnetModel):
# Gets the value
def get(self) -> float:
currents = self.__model.read_hardware_values()
return self.__model.compute_strengths(currents)
return self.__model.compute_strengths(currents)[0]

# Sets the value
def set(self, value:float):
Expand Down
6 changes: 3 additions & 3 deletions pyaml/control/controlsystem.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,12 @@ def fill_device(self,elements:list[Element]):
strength = RWStrengthScalar(e.model) if e.model.has_physics() else None
# Create a unique ref for this control system
m = e.attach(strength, current)
self.add_magnet(str(m),m)
self.add_magnet(m.get_name(),m)
elif isinstance(e,CombinedFunctionMagnet):
self.add_magnet(str(e),e)
self.add_magnet(e.get_name(),e)
currents = RWHardwareArray(e.model) if e.model.has_hardware() else None
strengths = RWStrengthArray(e.model) if e.model.has_physics() else None
# Create unique refs of each function for this control system
ms = e.attach(strengths,currents)
for m in ms:
self.add_magnet(str(m),m)
self.add_magnet(m.get_name(),m)
2 changes: 1 addition & 1 deletion pyaml/lattice/attribute_linker.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ def __init__(self, config_model:ConfigModel):
super().__init__(config_model)

def get_element_identifier(self, element: Element) -> LinkerIdentifier:
return PyAtAttributeIdentifier(self.linker_config_model.attribute_name, element.name)
return PyAtAttributeIdentifier(self.linker_config_model.attribute_name, element.get_name())

def _test_at_element(self, identifier: PyAtAttributeIdentifier, element: at.Element) -> bool:
attr_value = getattr(element, identifier.attribute_name, None)
Expand Down
13 changes: 9 additions & 4 deletions pyaml/lattice/element.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,19 @@ class Element(object):
name (str): The name identifying the element in the configuration file
"""
def __init__(self,name:str):
self.name: str = name
self.__name: str = name

def get_name(self):
"""
Returns the name of the element
"""
return self.__name

def set_energy(self,E:float):
pass

# TODO: _repr_ is used for identifying element in various array. Use a get_id() method instead

def __repr__(self):
return "%s(%s)" % (
self.__class__.__name__,
self.name
self.__name
)
35 changes: 6 additions & 29 deletions pyaml/lattice/element_holder.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,28 +5,6 @@
from ..magnet.magnet import Magnet
from ..arrays.magnet_array import MagnetArray

class MagnetType:
COMBINED = 0
HCORRECTOR = 1
VCORRECTOR = 2
QUADRUPOLE = 3
SKEWQUAD = 4
SEXTUPOLE = 5
SKEWSEXT = 6
OCTUPOLE = 7
SKEWOCTU = 8

_mmap:list = [
"CombinedFunctionMagnet",
"HCorrector",
"VCorrector",
"Quadrupole",
"SkewQuad",
"Sextupole",
"SkewSext",
"Octupole",
"SkewOctu"]


class ElementHolder(object):
"""
Expand All @@ -46,20 +24,19 @@ def __init__(self):
def fill_device(self,elements:list[Element]):
raise "ElementHolder.fill_device() is not subclassed"

def fill_magnet_array(self,type:MagnetType,arrayName:str,elementNames:list[str]):
def fill_magnet_array(self,arrayName:str,elementNames:list[str]):
a = []
for name in elementNames:
try:
a.append(self.get_magnet(type,name))
a.append(self.get_magnet(name))
except Exception as err:
raise Exception(f"MagnetArray {arrayName} : {err}")
self.__MAGNET_ARRAYS[arrayName] = MagnetArray(arrayName,a)

def get_magnet(self,type:MagnetType,name:str) -> Magnet:
fName = f"{_mmap[type]}({name})"
if fName not in self.__MAGNETS:
raise Exception(f"Magnet {fName} not defined")
return self.__MAGNETS[fName]
def get_magnet(self,name:str) -> Magnet:
if name not in self.__MAGNETS:
raise Exception(f"Magnet {name} not defined")
return self.__MAGNETS[name]

def add_magnet(self,name:str,m:Magnet):
self.__MAGNETS[name] = m
Expand Down
8 changes: 4 additions & 4 deletions pyaml/lattice/simulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,16 +66,16 @@ def fill_device(self,elements:list[Element]):
strength = RWStrengthScalar(self.get_at_elems(e),e.polynom,e.model) if e.model.has_physics() else None
# Create a unique ref for this simulator
m = e.attach(strength,current)
self.add_magnet(str(m),m)
self.add_magnet(m.get_name(),m)
elif isinstance(e,CombinedFunctionMagnet):
self.add_magnet(str(e),e)
self.add_magnet(e.get_name(),e)
currents = RWHardwareArray(self.get_at_elems(e),e.polynoms,e.model) if e.model.has_physics() else None
strengths = RWStrengthArray(self.get_at_elems(e),e.polynoms,e.model) if e.model.has_physics() else None
# Create unique refs of each function for this simulator
ms = e.attach(strengths,currents)
for m in ms:
self.add_magnet(str(m),m)
self.add_magnet(str(m),m)
self.add_magnet(m.get_name(),m)
self.add_magnet(m.get_name(),m)

def get_at_elems(self,element:Element) -> list[at.Element]:
identifier = self._linker.get_element_identifier(element)
Expand Down
2 changes: 1 addition & 1 deletion tests/config/EBSTune.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ instruments:
name: live
data_folder: /data/store
arrays:
- type: pyaml.arrays.quadrupole
- type: pyaml.arrays.magnet
name: QForTune
aggregator:
type: tango.pyaml.multi_attribute
Expand Down
4 changes: 2 additions & 2 deletions tests/config/bad_conf.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ instruments:
name: design
data_folder: /data/store
arrays:
- type: pyaml.arrays.hcorrector
- type: pyaml.arrays.magnet
name: HCORR
elements:
- SH1A-C01-H
- SH1A-C02-H
- type: pyaml.arrays.vcorrector
- type: pyaml.arrays.magnet
name: VCORR
elements:
- SH1A-C01-V
Expand Down
Loading
Loading