barc4shadow 2026.6.17__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- barc4shadow/__init__.py +8 -0
- barc4shadow/beamline.py +119 -0
- barc4shadow/viz.py +782 -0
- barc4shadow-2026.6.17.dist-info/METADATA +572 -0
- barc4shadow-2026.6.17.dist-info/RECORD +8 -0
- barc4shadow-2026.6.17.dist-info/WHEEL +5 -0
- barc4shadow-2026.6.17.dist-info/licenses/LICENSE +517 -0
- barc4shadow-2026.6.17.dist-info/top_level.txt +1 -0
barc4shadow/__init__.py
ADDED
barc4shadow/beamline.py
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def s4_beamline_to_layout(beamline) -> dict:
|
|
7
|
+
"""
|
|
8
|
+
Convert a SHADOW4 S4Beamline into a normalized beamline layout dictionary.
|
|
9
|
+
"""
|
|
10
|
+
from shadow4.beamline.optical_elements.absorbers.s4_screen import S4Screen
|
|
11
|
+
from shadow4.beamline.optical_elements.compound.s4_compound import S4Compound
|
|
12
|
+
from shadow4.beamline.optical_elements.crystals.s4_crystal import S4Crystal
|
|
13
|
+
from shadow4.beamline.optical_elements.gratings.s4_grating import S4Grating
|
|
14
|
+
from shadow4.beamline.optical_elements.ideal_elements.s4_empty import S4Empty
|
|
15
|
+
from shadow4.beamline.optical_elements.ideal_elements.s4_ideal_lens import S4IdealLens
|
|
16
|
+
from shadow4.beamline.optical_elements.mirrors.s4_mirror import S4Mirror
|
|
17
|
+
from shadow4.beamline.optical_elements.multilayers.s4_multilayer import S4Multilayer
|
|
18
|
+
from shadow4.beamline.optical_elements.refractors.s4_crl import S4CRL
|
|
19
|
+
from shadow4.beamline.optical_elements.refractors.s4_lens import S4Lens
|
|
20
|
+
from shadow4.beamline.optical_elements.refractors.s4_transfocator import S4Transfocator
|
|
21
|
+
|
|
22
|
+
def _kind_from_oe(oe) -> str:
|
|
23
|
+
if isinstance(oe, S4Empty):
|
|
24
|
+
return "E"
|
|
25
|
+
if isinstance(oe, S4Multilayer):
|
|
26
|
+
return "ML"
|
|
27
|
+
if isinstance(oe, S4Mirror):
|
|
28
|
+
return "M"
|
|
29
|
+
if isinstance(oe, S4Crystal):
|
|
30
|
+
return "C"
|
|
31
|
+
if isinstance(oe, S4Grating):
|
|
32
|
+
return "G"
|
|
33
|
+
if isinstance(oe, S4Screen):
|
|
34
|
+
boundary_shape = oe.get_boundary_shape()
|
|
35
|
+
if oe._i_abs > 0:
|
|
36
|
+
return "F" # filter
|
|
37
|
+
if boundary_shape is None:
|
|
38
|
+
return "O" # screen
|
|
39
|
+
if oe._i_stop == 0:
|
|
40
|
+
return "SL" # slit/aperture
|
|
41
|
+
if oe._i_stop == 1:
|
|
42
|
+
return "BS" # obstruction
|
|
43
|
+
return "O"
|
|
44
|
+
if isinstance(oe, (S4CRL, S4Transfocator)):
|
|
45
|
+
return "CRL"
|
|
46
|
+
if isinstance(oe, (S4Lens,S4IdealLens)):
|
|
47
|
+
return "L"
|
|
48
|
+
if isinstance(oe, S4Compound):
|
|
49
|
+
return "CMP"
|
|
50
|
+
return "O"
|
|
51
|
+
|
|
52
|
+
positions = beamline.syspositions()
|
|
53
|
+
n_oe = beamline.get_beamline_elements_number()
|
|
54
|
+
|
|
55
|
+
if n_oe == 0:
|
|
56
|
+
return {
|
|
57
|
+
"x": np.array([0.0]),
|
|
58
|
+
"y": np.array([0.0]),
|
|
59
|
+
"z": np.array([0.0]),
|
|
60
|
+
"elements": {
|
|
61
|
+
"labels": ["Source"],
|
|
62
|
+
"kinds": ["SRC"],
|
|
63
|
+
},
|
|
64
|
+
"meta": {
|
|
65
|
+
"source": "shadow4",
|
|
66
|
+
"n_oe": 0,
|
|
67
|
+
"has_final_image": False,
|
|
68
|
+
},
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
labels = ["Source"]
|
|
72
|
+
kinds = ["SRC"]
|
|
73
|
+
|
|
74
|
+
for i, element in enumerate(beamline.get_beamline_elements()):
|
|
75
|
+
oe = element.get_optical_element()
|
|
76
|
+
# print(f"OE {i + 1}: {oe.get_name()} ({_kind_from_oe(oe)})")
|
|
77
|
+
|
|
78
|
+
try:
|
|
79
|
+
label = str(oe.get_name()).strip()
|
|
80
|
+
except Exception:
|
|
81
|
+
label = f"OE {i + 1}"
|
|
82
|
+
|
|
83
|
+
labels.append(label if label else f"OE {i + 1}")
|
|
84
|
+
kinds.append(_kind_from_oe(oe))
|
|
85
|
+
|
|
86
|
+
x = np.asarray(positions["optical_axis_x"], dtype=float)
|
|
87
|
+
y = np.asarray(positions["optical_axis_y"], dtype=float)
|
|
88
|
+
z = np.asarray(positions["optical_axis_z"], dtype=float)
|
|
89
|
+
|
|
90
|
+
mirr = np.asarray(positions["mirr"], dtype=float)
|
|
91
|
+
star = np.asarray(positions["star"], dtype=float)
|
|
92
|
+
|
|
93
|
+
last_mirr = mirr[:, -1]
|
|
94
|
+
last_star = star[:, -1]
|
|
95
|
+
|
|
96
|
+
append_final_image = not np.allclose(last_mirr, last_star)
|
|
97
|
+
|
|
98
|
+
if append_final_image:
|
|
99
|
+
labels.append("Final image")
|
|
100
|
+
kinds.append("O")
|
|
101
|
+
else:
|
|
102
|
+
x = x[:-1]
|
|
103
|
+
y = y[:-1]
|
|
104
|
+
z = z[:-1]
|
|
105
|
+
|
|
106
|
+
return {
|
|
107
|
+
"x": x,
|
|
108
|
+
"y": y,
|
|
109
|
+
"z": z,
|
|
110
|
+
"elements": {
|
|
111
|
+
"labels": labels,
|
|
112
|
+
"kinds": kinds,
|
|
113
|
+
},
|
|
114
|
+
"meta": {
|
|
115
|
+
"source": "shadow4",
|
|
116
|
+
"n_oe": n_oe,
|
|
117
|
+
"has_final_image": append_final_image,
|
|
118
|
+
},
|
|
119
|
+
}
|