Skip to content

Commit e13e693

Browse files
committed
Merge branch 'main' into doc
2 parents 4f3643d + 0b359b1 commit e13e693

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

72 files changed

+13549
-523
lines changed

pyaml/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@
1414

1515
import logging.config
1616
import os
17-
from pyaml.exception import PyAMLException
18-
from pyaml.configuration.config_exception import PyAMLConfigException
17+
from pyaml.common.exception import PyAMLException
18+
from pyaml.common.exception import PyAMLConfigException
1919

2020
__all__ = [__version__, PyAMLException, PyAMLConfigException]
2121

pyaml/arrays/array.py

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
"""
22
Magnet array configuration
33
"""
4+
from ..common.element_holder import ElementHolder
45

5-
import numpy as np
66
from pydantic import BaseModel,ConfigDict
7-
from ..lattice.element_holder import ElementHolder
8-
from ..control.deviceaccesslist import DeviceAccessList
97

108
class ArrayConfigModel(BaseModel):
119

@@ -15,11 +13,6 @@ class ArrayConfigModel(BaseModel):
1513
"""Family name"""
1614
elements: list[str]
1715
"""List of pyaml element names"""
18-
aggregator: DeviceAccessList | None = None
19-
"""
20-
Aggregator object. If none specified, writings and readings are serialized.
21-
If no device list is specified, it is dynamically constructed.
22-
"""
2316

2417
class ArrayConfig(object):
2518
"""
@@ -30,7 +23,3 @@ def __init__(self, cfg: ArrayConfigModel):
3023

3124
def fill_array(self,holder:ElementHolder):
3225
raise "Array.fill_array() is not subclassed"
33-
34-
def init_aggregator(self,holder:ElementHolder):
35-
raise "Array.init_aggregator() is not subclassed"
36-

pyaml/arrays/bpm.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
from .array import ArrayConfigModel,ArrayConfig
2+
from ..common.element_holder import ElementHolder
3+
4+
# Define the main class name for this module
5+
PYAMLCLASS = "BPM"
6+
7+
class ConfigModel(ArrayConfigModel):...
8+
9+
class BPM(ArrayConfig):
10+
11+
def __init__(self, cfg: ArrayConfigModel):
12+
super().__init__(cfg)
13+
14+
def fill_array(self,holder:ElementHolder):
15+
holder.fill_bpm_array(self._cfg.name,self._cfg.elements)

pyaml/arrays/bpm_array.py

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
from ..common.abstract import ReadFloatArray
2+
from ..bpm.bpm import BPM
3+
from ..control.deviceaccesslist import DeviceAccessList
4+
5+
import numpy as np
6+
7+
class RWBPMPosition(ReadFloatArray):
8+
9+
def __init__(self, name:str, bpms:list[BPM]):
10+
self.__bpms = bpms
11+
self.__name = name
12+
self.__aggregator:DeviceAccessList = None
13+
14+
# Gets the values
15+
def get(self) -> np.array:
16+
if not self.__aggregator:
17+
return np.array([b.positions.get() for b in self.__bpms])
18+
else:
19+
return self.__aggregator.get().reshape(len(self.__bpms),2)
20+
21+
# Gets the unit of the values
22+
def unit(self) -> list[str]:
23+
return [b.positions.unit() for b in self.__bpms]
24+
25+
# Set the aggregator (Control system only)
26+
def set_aggregator(self,agg:DeviceAccessList):
27+
self.__aggregator = agg
28+
29+
30+
class RWBPMSinglePosition(ReadFloatArray):
31+
32+
def __init__(self, name:str, bpms:list[BPM],idx: int):
33+
self.__bpms = bpms
34+
self.__name = name
35+
self.__idx = idx
36+
self.__aggregator:DeviceAccessList = None
37+
38+
# Gets the values
39+
def get(self) -> np.array:
40+
if not self.__aggregator:
41+
return np.array([b.positions.get()[self.__idx] for b in self.__bpms])
42+
else:
43+
return self.__aggregator.get()
44+
45+
# Gets the unit of the values
46+
def unit(self) -> list[str]:
47+
return [b.positions.unit() for b in self.__bpms]
48+
49+
# Set the aggregator (Control system only)
50+
def set_aggregator(self,agg:DeviceAccessList):
51+
self.__aggregator = agg
52+
53+
54+
55+
class BPMArray(list[BPM]):
56+
"""
57+
Class that implements access to a BPM array
58+
"""
59+
60+
def __init__(self,arrayName:str,bpms:list[BPM],holder = None):
61+
"""
62+
Construct a BPM array
63+
64+
Parameters
65+
----------
66+
arrayName : str
67+
Array name
68+
bpms: list[BPM]
69+
BPM iterator
70+
holder : Element holder
71+
Holder (Simulator or Control System) that contains element of this array used for aggregator
72+
"""
73+
super().__init__(i for i in bpms)
74+
self.__name = arrayName
75+
self.__hvpos = RWBPMPosition(arrayName,bpms)
76+
self.__hpos = RWBPMSinglePosition(arrayName,bpms,0)
77+
self.__vpos = RWBPMSinglePosition(arrayName,bpms,1)
78+
79+
if holder is not None:
80+
aggs = holder.create_bpm_aggregators(bpms)
81+
self.__hvpos.set_aggregator(aggs[0])
82+
self.__hpos.set_aggregator(aggs[1])
83+
self.__vpos.set_aggregator(aggs[2])
84+
85+
@property
86+
def positions(self) -> RWBPMPosition:
87+
"""
88+
Give access to bpm posttions of each bpm of this array
89+
"""
90+
return self.__hvpos
91+
92+
@property
93+
def h(self) -> RWBPMSinglePosition:
94+
"""
95+
Give access to bpm H posttions of each bpm of this array
96+
"""
97+
return self.__hpos
98+
99+
@property
100+
def v(self) -> RWBPMSinglePosition:
101+
"""
102+
Give access to bpm V posttions of each bpm of this array
103+
"""
104+
return self.__vpos
105+
106+
107+
108+
109+

pyaml/arrays/magnet.py

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from .array import ArrayConfigModel,ArrayConfig
2-
from ..lattice.element_holder import ElementHolder
2+
from ..common.element_holder import ElementHolder
33

44
# Define the main class name for this module
55
PYAMLCLASS = "Magnet"
@@ -13,12 +13,3 @@ def __init__(self, cfg: ArrayConfigModel):
1313

1414
def fill_array(self,holder:ElementHolder):
1515
holder.fill_magnet_array(self._cfg.name,self._cfg.elements)
16-
17-
def init_aggregator(self,holder:ElementHolder):
18-
if self._cfg.aggregator is not None and len(self._cfg.aggregator)==0:
19-
# Construct dynamically aggregator for magnets
20-
mag = holder.get_magnets(self._cfg.name)
21-
for m in mag:
22-
devs = m.model.get_devices()
23-
self._cfg.aggregator.add_devices(devs)
24-
mag.set_aggregator(self._cfg.aggregator)

pyaml/arrays/magnet_array.py

Lines changed: 39 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,32 @@
1-
from ..control.abstract import ReadWriteFloatArray
1+
from ..common.abstract import ReadWriteFloatArray
22
from ..magnet.magnet import Magnet
3+
from ..common.abstract_aggregator import ScalarAggregator
4+
35
import numpy as np
4-
from ..control.deviceaccesslist import DeviceAccessList
56

67
class RWMagnetStrength(ReadWriteFloatArray):
78

89
def __init__(self, name:str, magnets:list[Magnet]):
9-
self.__magnets = magnets
1010
self.__name = name
11-
self.aggregator:DeviceAccessList = None
11+
self.__magnets = magnets
12+
self.__nb = len(self.__magnets)
13+
self.__aggregator:ScalarAggregator = None
1214

1315
# Gets the values
1416
def get(self) -> np.array:
15-
if not self.aggregator:
17+
if not self.__aggregator:
1618
return np.array([m.strength.get() for m in self.__magnets])
1719
else:
18-
allHardwareValues = self.aggregator.get() # Read all hardware setpoints
19-
allStrength = np.zeros(len(self.__magnets))
20-
mIdx = 0
21-
idx = 0
22-
for m in self.__magnets:
23-
nbDev = len(m.model.get_devices())
24-
allStrength[idx] = m.model.compute_strengths(allHardwareValues[idx:idx+nbDev])[m.strength.index()]
25-
mIdx += 1
26-
idx += nbDev
27-
return allStrength
20+
return self.__aggregator.get()
2821

2922
# Sets the values
3023
def set(self, value:np.array):
31-
if not self.aggregator:
24+
nvalue = np.ones(self.__nb) * value if isinstance(value,float) else value
25+
if not self.__aggregator:
3226
for idx,m in enumerate(self.__magnets):
33-
m.strength.set(value[idx])
27+
m.strength.set(nvalue[idx])
3428
else:
35-
# TODO: if the array does not contains mappings to combined function
36-
# magnets, the algorithm below can be optimized
37-
allHardwareValues = self.aggregator.get() # Read all hardware setpoints
38-
newHardwareValues = np.zeros(len(self.aggregator))
39-
mIdx = 0
40-
idx = 0
41-
for m in self.__magnets:
42-
# m is a single function magnet or a mapping to a
43-
# combined function magnet (RWMapper)
44-
nbDev = len(m.model.get_devices())
45-
mStrengths = m.model.compute_strengths( allHardwareValues[idx:idx+nbDev] )
46-
mStrengths[m.strength.index()] = value[mIdx]
47-
newHardwareValues[idx:idx+nbDev] = m.model.compute_hardware_values(mStrengths)
48-
mIdx += 1
49-
idx += nbDev
50-
self.aggregator.set(newHardwareValues)
29+
self.__aggregator.set(nvalue)
5130

5231
# Sets the values and waits that the read values reach their setpoint
5332
def set_and_wait(self, value:np.array):
@@ -58,37 +37,32 @@ def unit(self) -> list[str]:
5837
return [m.strength.unit() for m in self.__magnets]
5938

6039
# Set the aggregator (Control system only)
61-
def set_aggregator(self,agg:DeviceAccessList):
62-
self.aggregator = agg
40+
def set_aggregator(self,agg:ScalarAggregator):
41+
self.__aggregator = agg
6342

6443
class RWMagnetHardware(ReadWriteFloatArray):
6544

6645
def __init__(self, name:str, magnets:list[Magnet]):
6746
self.__name = name
6847
self.__magnets = magnets
69-
self.aggregator:DeviceAccessList = None
70-
self.hasHardwareMapping = True
48+
self.__nb = len(self.__magnets)
49+
self.__aggregator:ScalarAggregator = None
7150

7251
# Gets the values
7352
def get(self) -> np.array:
74-
if not self.aggregator:
53+
if not self.__aggregator:
7554
return np.array([m.hardware.get() for m in self.__magnets])
7655
else:
77-
if not self.hasHardwareMapping:
78-
raise Exception(f"Array {self.__name} contains elements that that do not support hardware units")
79-
else:
80-
return self.aggregator.get()
56+
return self.__aggregator.get()
8157

8258
# Sets the values
8359
def set(self, value:np.array):
84-
if not self.aggregator:
60+
nvalue = np.ones(self.__nb) * value if isinstance(value,float) else value
61+
if not self.__aggregator:
8562
for idx,m in enumerate(self.__magnets):
8663
m.hardware.set(value[idx])
8764
else:
88-
if not self.hasHardwareMapping:
89-
raise Exception(f"Array {self.__name} contains elements that that do not support hardware units")
90-
else:
91-
self.aggregator.set(value)
65+
self.__aggregator.set(value)
9266

9367
# Sets the values and waits that the read values reach their setpoint
9468
def set_and_wait(self, value:np.array):
@@ -98,44 +72,38 @@ def set_and_wait(self, value:np.array):
9872
def unit(self) -> list[str]:
9973
return [m.hardware.unit() for m in self.__magnets]
10074

101-
# Set the aggregator (Control system only)
102-
def set_aggregator(self,agg:DeviceAccessList):
103-
self.aggregator = agg
104-
for m in self.__magnets:
105-
self.hasHardwareMapping |= m.model.has_hardware()
75+
# Set the aggregator
76+
def set_aggregator(self,agg:ScalarAggregator):
77+
self.__aggregator = agg
10678

10779
class MagnetArray(list[Magnet]):
10880
"""
10981
Class that implements access to a magnet array
11082
"""
11183

112-
def __init__(self,arrayName:str,iterable):
84+
def __init__(self,arrayName:str,magnets:list[Magnet],holder = None):
11385
"""
11486
Construct a magnet array
11587
11688
Parameters
11789
----------
118-
iterable
90+
arrayName : str
91+
Array name
92+
magnets: list[Magnet]
11993
Magnet iterator
94+
holder : Element holder
95+
Holder (Simulator or Control System) that contains element of this array used for aggregator
12096
"""
121-
super().__init__(i for i in iterable)
97+
super().__init__(i for i in magnets)
12298
self.__name = arrayName
123-
self.__rwstrengths = RWMagnetStrength(arrayName,iterable)
124-
self.__rwhardwares = RWMagnetHardware(arrayName,iterable)
125-
126-
def set_aggregator(self,agg:DeviceAccessList):
127-
"""
128-
Set an aggregator for this array.
129-
Aggregator allow fast control system access by parallelizing
130-
call to underlying hardware.
131-
132-
Parameters
133-
----------
134-
agg : DeviceAccessList
135-
List of device access
136-
"""
137-
self.__rwstrengths.set_aggregator(agg)
138-
self.__rwhardwares.set_aggregator(agg)
99+
self.__rwstrengths = RWMagnetStrength(arrayName,magnets)
100+
self.__rwhardwares = RWMagnetHardware(arrayName,magnets)
101+
102+
if holder is not None:
103+
aggs = holder.create_magnet_strength_aggregator(magnets)
104+
aggh = holder.create_magnet_harddware_aggregator(magnets)
105+
self.__rwstrengths.set_aggregator(aggs)
106+
self.__rwhardwares.set_aggregator(aggh)
139107

140108
@property
141109
def strengths(self) -> RWMagnetStrength:

0 commit comments

Comments
 (0)