Skip to content

Commit 44c87cf

Browse files
add fixed_mask device
1 parent 53a9034 commit 44c87cf

6 files changed

Lines changed: 121 additions & 30 deletions

File tree

sim/blop_sim/backends/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,6 @@
33
from .core import SimBackend
44
from .simple import SimpleBackend
55
from .xrt import XRTBackend
6+
from .xrt_xas import XRTXASBackend
67

78
__all__ = ["SimBackend", "SimpleBackend", "XRTBackend", "XRTXASBackend"]

sim/blop_sim/backends/models/xrt_xas_model.py

Lines changed: 44 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -17,19 +17,41 @@
1717

1818
import numpy as np
1919

20-
import xrt.backends.raycing.sources as rsources
20+
# import xrt.backends.raycing.sources as rsources
2121
import xrt.backends.raycing.screens as rscreens
2222
import xrt.backends.raycing.materials as rmats
23-
import xrt.backends.raycing.materials.elemental as rmatsel
24-
import xrt.backends.raycing.materials.compounds as rmatsco
25-
import xrt.backends.raycing.materials.crystals as rmatscr
23+
# import xrt.backends.raycing.materials.elemental as rmatsel
24+
# import xrt.backends.raycing.materials.compounds as rmatsco
25+
# import xrt.backends.raycing.materials.crystals as rmatscr
2626
import xrt.backends.raycing.oes as roes
2727
import xrt.backends.raycing.apertures as rapts
2828
import xrt.backends.raycing.run as rrun
2929
import xrt.backends.raycing as raycing
3030
import xrt.plotter as xrtplot
3131
import xrt.runner as xrtrun
3232

33+
def build_histRGB(lb, gb, limits=None, isScreen=False, shape=None):
34+
if shape is None:
35+
shape = [256, 256]
36+
good = (lb.state == 1) | (lb.state == 2)
37+
if isScreen:
38+
x, y, z = lb.x[good], lb.z[good], lb.y[good]
39+
else:
40+
x, y, z = lb.x[good], lb.y[good], lb.z[good]
41+
goodlen = len(lb.x[good])
42+
hist2dRGB = np.zeros((shape[1], shape[0], 3), dtype=np.float64)
43+
hist2d = np.zeros((shape[1], shape[0]), dtype=np.float64)
44+
45+
if limits is None and goodlen > 0:
46+
limits = np.array([[np.min(x), np.max(x)], [np.min(y), np.max(y)], [np.min(z), np.max(z)]])
47+
48+
if goodlen > 0:
49+
beamLimits = [limits[1], limits[0]] or None
50+
flux = gb.Jss[good] + gb.Jpp[good]
51+
hist2d, _, _ = np.histogram2d(y, x, bins=[shape[1], shape[0]], range=beamLimits, weights=flux)
52+
hist2dRGB = None
53+
return hist2d, hist2dRGB, limits
54+
3355
CVD = rmats.Material(
3456
elements=['C'],
3557
quantities=[1.0],
@@ -51,8 +73,7 @@
5173
V=160.17128543981727,
5274
elements=['Si'],
5375
quantities=[1.0],
54-
name=r"Si220",
55-
kind=r"crystal")
76+
name=r"Si220")
5677

5778
CVDcoating = rmats.Material(
5879
elements=['C'],
@@ -91,20 +112,20 @@
91112
beta=1.5707963267948966,
92113
gamma=1.5707963267948966,
93114
atomsFraction=[1, 1, 1, 1, 1, 1, 1, 1],
94-
d=1.916079064786341,
95-
V=159.1751463370933,
96-
elements=['Si', 'Si', 'Si', 'Si', 'Si', 'Si', 'Si', 'Si'],
97-
quantities=[1, 1, 1, 1, 1, 1, 1, 1],
98-
rho=2.3439368026411915,
99-
kind=r"crystal harmonics")
115+
# V=159.1751463370933,
116+
# elements=['Si', 'Si', 'Si', 'Si', 'Si', 'Si', 'Si', 'Si'],
117+
# quantities=[1, 1, 1, 1, 1, 1, 1, 1],
118+
# rho=2.3439368026411915,
119+
# kind=r"crystal harmonics"
120+
)
100121

101122

102123
def build_beamline():
103124
BioXAS_Main = raycing.BeamLine(
104-
alignE=8000,
105-
name=r"BioXAS_Main")
125+
alignE=8000)
106126

107-
BioXAS_Main.Wiggler = raycing.sources.synchr.Wiggler(
127+
# BioXAS_Main.Wiggler = raycing.sources.synchr.Wiggler(
128+
BioXAS_Main.Wiggler = raycing.sources_synchr.Wiggler(
108129
bl=BioXAS_Main,
109130
name=r"Wiggler",
110131
center=[0, 0, 0],
@@ -202,9 +223,10 @@ def build_beamline():
202223
center=[0, 26000, r"auto"],
203224
x=[1.0, -0.0, 0.0],
204225
z=[0.0, 0.0, 1.0],
205-
limPhysX=[0.0, 0.0],
206-
limPhysY=[0.0, 0.0],
207-
cLimits=[0.0, 0.0])
226+
# limPhysX=[0.0, 0.0],
227+
# limPhysY=[0.0, 0.0],
228+
# cLimits=[0.0, 0.0]
229+
)
208230

209231
BioXAS_Main.Mirror2 = roes.ToroidMirror(
210232
bl=BioXAS_Main,
@@ -266,9 +288,10 @@ def build_beamline():
266288
center=[0, 30650, r"auto"],
267289
x=[1.0, -0.0, 0.0],
268290
z=[0.0, 0.0, 1.0],
269-
limPhysX=[0.0, 0.0],
270-
limPhysY=[0.0, 0.0],
271-
cLimits=[0.0, 0.0])
291+
# limPhysX=[0.0, 0.0],
292+
# limPhysY=[0.0, 0.0],
293+
# cLimits=[0.0, 0.0])
294+
)
272295

273296
return BioXAS_Main
274297

sim/blop_sim/backends/xrt_xas.py

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ def __init__(self, noise: bool = False):
1717
"""Initialize XRT backend."""
1818
super().__init__()
1919
self._beamline = None
20-
# self._limits = [[-0.6, 0.6], [-0.45, 0.45]]
2120
self._noise = noise
2221

2322
def _ensure_beamline(self):
@@ -33,12 +32,13 @@ async def generate_beam(self) -> np.ndarray:
3332
"""
3433
self._ensure_beamline()
3534

36-
# Get KB mirror radii from devices
37-
# mirror_radii = await self._get_mirror_radii()
35+
# Get fixed mask position (x, y, z)
36+
fixed_mask_position = await self._get_fixed_mask_position()
3837

38+
print(fixed_mask_position)
3939
# Update XRT beamline mirror parameters
40-
# self._beamline.toroidMirror01.R = mirror_radii[0] # Vertical mirror
41-
# self._beamline.toroidMirror02.R = mirror_radii[1] # Horizontal mirror
40+
if fixed_mask_position:
41+
self._beamline.FEMask.center = fixed_mask_position
4242

4343
# Run ray tracing
4444
outDict = run_process(self._beamline)
@@ -53,5 +53,17 @@ async def generate_beam(self) -> np.ndarray:
5353
image += 1e-3 * np.abs(np.random.standard_normal(size=image.shape))
5454

5555
return image
56-
57-
__all__ = ["XRTBackend"]
56+
57+
async def _get_fixed_mask_position(self) -> list[float]:
58+
for name, device in self._device_states.items():
59+
# print(name, device)
60+
print(device["type"])
61+
if device["type"] == "fixed_mask_xrt":
62+
state = await self._get_device_state(name)
63+
print(state)
64+
# print("DEBUG STATE: {}".format(state))
65+
position = [state["x"], state["y"], state["z"]]
66+
return position
67+
68+
69+
__all__ = ["XRTXASBackend"]
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
"""XRTBackend-specific devices."""
22

33
from .kb_mirror import KBMirror
4+
from .fixed_mask import FixedMask
45

5-
__all__ = ["KBMirror"]
6+
__all__ = ["KBMirror", "FixedMask"]
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
"""Fixed Mask devices for XRTBackend."""
2+
3+
from ophyd_async.core import StandardReadable, soft_signal_rw
4+
from ophyd_async.core import StandardReadableFormat as Format
5+
6+
from ...backends import SimBackend
7+
8+
9+
class FixedMask(StandardReadable):
10+
"""Fixed mask position control (for XRTBackend).
11+
12+
Exposes the coordinates that directly control the XRT fixed mask position.
13+
Used with XRTBackend for ray-tracing simulation.
14+
15+
Args:
16+
backend: Simulation backend (should be XRTBackend)
17+
position: list of floats that define the [x, y, z] position of the mask
18+
name: Device name
19+
"""
20+
21+
def __init__(
22+
self,
23+
backend: SimBackend,
24+
initial_position: list[float],
25+
name: str = "",
26+
):
27+
self._backend = backend
28+
29+
# Curvature radius signal
30+
with self.add_children_as_readables(Format.HINTED_SIGNAL):
31+
self.x = soft_signal_rw(float, initial_position[0])
32+
self.y = soft_signal_rw(float, initial_position[1])
33+
self.z = soft_signal_rw(float, initial_position[2])
34+
35+
super().__init__(name=name)
36+
37+
# Register with backend
38+
backend.register_device(
39+
device_name=name,
40+
device_type="fixed_mask_xrt",
41+
get_state_callback=self._get_state,
42+
)
43+
44+
async def _get_state(self) -> dict:
45+
"""Get current mirror state for backend (async)."""
46+
# position = self.position.get_value()
47+
return {
48+
"x": await self.x.get_value(),
49+
"y": await self.y.get_value(),
50+
"z": await self.z.get_value(),
51+
}
52+
53+
54+
__all__ = ["FixedMask"]

sim/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ dependencies = [
1818
"numpy",
1919
"scipy",
2020
"matplotlib",
21-
"xrt>=1.6.1,<2",
21+
"xrt==1.6.1",
2222
]
2323

2424
[tool.hatch.build.targets.wheel]

0 commit comments

Comments
 (0)