refactoring
CI for debye_bec / test (pull_request) Successful in 1m6s
CI for debye_bec / test (push) Successful in 1m7s

This commit is contained in:
x01da
2026-05-19 10:45:42 +02:00
parent 5a54675f1e
commit ef4c82262c
6 changed files with 411 additions and 299 deletions
@@ -12,16 +12,19 @@ from bec_lib import bec_logger
from bec_lib.endpoints import MessageEndpoints
from bec_widgets.utils.bec_dispatcher import BECDispatcher
from bec_widgets.utils.bec_widget import BECWidget
from bec_widgets.utils.colors import apply_theme
from bec_widgets.utils.colors import apply_theme, get_accent_colors
from bec_widgets.utils.error_popups import SafeSlot
# pylint: disable=E0611
from qtpy.QtCore import Qt, QTimer
from qtpy.QtGui import QFont
from qtpy.QtWidgets import (
QApplication,
QDialog,
QDialogButtonBox,
QHBoxLayout,
QLabel,
QPlainTextEdit,
QPushButton,
QStyle,
QVBoxLayout,
@@ -113,8 +116,8 @@ class DigitalTwin(BECWidget, QWidget):
self.input.smpl.value_changed_connect(self.calc_assistant)
self.input.adapt_reality.clicked_connect(self.adapt_reality)
self.settings.reload_offsets.clicked_connect(self.load_offsets)
self.settings.unload_offsets.clicked_connect(self.unload_offsets)
self.settings.load_offsets.clicked_connect(self.load_offsets)
self.settings.show_offsets.clicked_connect(self.show_offsets)
self.bragg_angle = 0.0
self.qy = 0.0
@@ -294,13 +297,16 @@ class DigitalTwin(BECWidget, QWidget):
self.calc_assistant_sideview()
self.calc_assistant_surfaces()
def get_assistant_config(self, apply_offset: bool = False):
def get_assistant_config(self, apply_offset: bool = False) -> ConfigDict:
"""
Assembles the digital twin config from the assistants input.
Args:
apply_offset(bool): Applies the offset values to the config.
Defaults to False
Returns:
ConfigDict: config of the assistant
"""
fm_focus = self.input.fm_focus.currentText()
if fm_focus in "Manual":
@@ -361,9 +367,12 @@ class DigitalTwin(BECWidget, QWidget):
# logger.info(f'Config created: {config}')
return config
def get_reality_config(self):
def get_reality_config(self) -> ConfigDict:
"""
Assembles the digital twin config based on the real axis positions.
Returns:
ConfigDict: config of the reality
"""
mo1_trx = self.dev.mo1_trx.read(cached=True)["mo1_trx"]["value"]
if abs(mo1_trx) > 5:
@@ -505,34 +514,85 @@ class DigitalTwin(BECWidget, QWidget):
@SafeSlot()
def load_offsets(self, *_, recalculate: bool = True):
"""
Loads the offsets from the file
Loads or unloads the offsets from the file
Args:
recalculate(bool): Recalculates the assistant values.
recalculate(bool): Recalculates the assistant values after loading.
Defaults to True
"""
file = Path(OFFSET_FILE)
if not file.exists():
raise FileNotFoundError(f"Offset file not found: {OFFSET_FILE}")
with file.open("r", encoding="utf-8") as f:
data = yaml.safe_load(f)
if self.offsets == {}:
# Load offsets
file = Path(OFFSET_FILE)
if not file.exists():
raise FileNotFoundError(f"Offset file not found: {OFFSET_FILE}")
if not isinstance(data, dict):
raise ValueError(f"Expected a YAML mapping, got {type(data).__name__}")
with file.open("r", encoding="utf-8") as f:
data = yaml.safe_load(f)
self.offsets = data
if not isinstance(data, dict):
raise ValueError(f"Expected a YAML mapping, got {type(data).__name__}")
if recalculate:
self.offsets = data
if recalculate:
self.calc_assistant(identifier="init")
self.settings.load_offsets.setText("Unload")
self.settings.offsets_status.setText("Loaded and applied")
self.settings.offsets_status.setColor(get_accent_colors().success.name())
self.settings.show_offsets.enable_button(True)
else:
# Unload offsets
self.offsets = {}
self.calc_assistant(identifier="init")
self.settings.load_offsets.setText("Load")
self.settings.offsets_status.setText("No offsets")
self.settings.offsets_status.setColor(get_accent_colors().default.name())
self.settings.show_offsets.enable_button(False)
@SafeSlot()
def unload_offsets(self, *_):
def show_offsets(self, *_):
"""
Removes the offsets and recalculates the assistant values.
Shows the offsets in a popup window
"""
self.offsets = {}
self.calc_assistant(identifier="init")
dialog = QDialog()
dialog.setWindowTitle("Digital Twin - Offsets")
dialog.setFixedWidth(500)
layout = QVBoxLayout(dialog)
layout.setSpacing(12)
layout.setContentsMargins(20, 20, 20, 20)
intro_label = QLabel("The offsets are saved in the digital twin BEC widget folder:")
intro_label.setWordWrap(True)
layout.addWidget(intro_label)
file = QLabel(OFFSET_FILE)
file.setWordWrap(True)
font = QFont()
font.setItalic(True)
file.setFont(font)
layout.addWidget(file)
text_edit = QPlainTextEdit()
text_edit.setReadOnly(True)
text_edit.setFont(QFont("Consolas", 9))
class InlineListDumper(yaml.Dumper):
"""YAML dumper that renders all sequences on a single line."""
def represent_sequence(self, tag, sequence, *_):
return super().represent_sequence(tag, sequence, flow_style=True)
text_edit.setPlainText(yaml.dump(self.offsets, Dumper=InlineListDumper, sort_keys=False))
layout.addWidget(text_edit)
buttons = QDialogButtonBox(QDialogButtonBox.StandardButton.Close)
buttons.rejected.connect(dialog.reject)
layout.addWidget(buttons)
dialog.exec()
def update_fm_mode(self):
"""
@@ -62,8 +62,13 @@ class StatusIcon(QWidget):
self.set_status(Status.NOT_IN_POSITION)
def get_rotation(self):
"""Return the current rotation angle in degrees."""
def get_rotation(self) -> float:
"""
Return the current rotation angle in degrees.
Returns:
float: Rotation angle in deg
"""
return self._rotation
def set_rotation(self, angle: float):
@@ -2,7 +2,7 @@
Two plot classes to plot side-view and surface-view
"""
from typing import Literal, Optional, TypedDict, cast
from typing import Literal, Optional, cast
import numpy as np
import pyqtgraph as pg
@@ -13,7 +13,7 @@ from qtpy.QtCore import Qt
from qtpy.QtGui import QBrush, QColor
# pylint: disable=E0611
from qtpy.QtWidgets import QApplication, QHBoxLayout, QVBoxLayout, QWidget
from qtpy.QtWidgets import QApplication, QGraphicsRectItem, QHBoxLayout, QVBoxLayout, QWidget
from debye_bec.bec_widgets.widgets.digital_twin.calc_varia import (
mirror_surface_geometries,
@@ -153,8 +153,8 @@ class SurfacePlots(QWidget):
def plot_surface(widget, surfaces):
for name, surface in surfaces.items():
rect = pg.QtWidgets.QGraphicsRectItem(*surface) # pylint: disable=E1101
rect.setBrush(QBrush(QColor(*self.color_impenetrable))) # pylint: disable=E1101
rect = QGraphicsRectItem(*surface)
rect.setBrush(QBrush(QColor(*self.color_impenetrable)))
rect.setPen(pg.mkPen(color=self.color_impenetrable, width=2))
widget.addItem(rect)
text = pg.TextItem(name, color=self.text_color, anchor=(0.5, 0.5))
@@ -292,7 +292,7 @@ class SideviewPlot(QWidget):
for wall in self.walls:
wall.setPen(pg.mkPen(color=self.color_impenetrable, width=3))
wall.setBrush(QBrush(QColor(*self.color_impenetrable))) # pylint: disable=E1101
wall.setBrush(QBrush(QColor(*self.color_impenetrable)))
for pipe in self.pipes:
pipe.setPen(pg.mkPen(color=self.color_impenetrable, width=3))
@@ -311,8 +311,8 @@ class SideviewPlot(QWidget):
"""Plot walls"""
walls = wall_geometries()
for wall in walls:
rect = pg.QtWidgets.QGraphicsRectItem(*wall) # pylint: disable=E1101
rect.setBrush(QBrush(QColor(*self.color_impenetrable))) # pylint: disable=E1101
rect = QGraphicsRectItem(wall[0], wall[1], wall[2], wall[3])
rect.setBrush(QBrush(QColor(*self.color_impenetrable)))
rect.setPen(pg.mkPen(color=self.color_impenetrable, width=2))
self.plot_widget.addItem(rect)
self.walls.append(rect)
@@ -5,7 +5,7 @@ Settings panel for the digital twin widget
# pylint: disable=E0611
from qtpy.QtWidgets import QLayout, QVBoxLayout, QWidget
from debye_bec.bec_widgets.widgets.qt_widgets import Button, Group
from debye_bec.bec_widgets.widgets.qt_widgets import Button, Group, TextIndicator
class SettingsPanel(QWidget):
@@ -17,11 +17,14 @@ class SettingsPanel(QWidget):
self._layout.setSizeConstraint(QLayout.SetFixedSize) # type: ignore
# Reload offsets
self.reload_offsets = Button(label="Reload Offsets", label_button="Reload", enabled=True)
self.unload_offsets = Button(label="Unload Offsets", label_button="Unload", enabled=True)
self.load_offsets = Button(label="Load Offsets", label_button="Load", enabled=True)
self.offsets_status = TextIndicator(label="Offsets")
self.show_offsets = Button(label="Show Offsets", label_button="Show", enabled=True)
# Assemble complete offset group
self.offset_group = Group("Axes Offsets", [self.reload_offsets, self.unload_offsets])
self.offset_group = Group(
"Axes Offsets", [self.load_offsets, self.offsets_status, self.show_offsets]
)
self._layout.addWidget(self.offset_group)
self._layout.addStretch()
+80 -46
View File
@@ -1,24 +1,37 @@
"""
Universal Qt widgets
"""
from functools import partial
# pylint: disable=E0611
from qtpy.QtWidgets import (
QWidget, QVBoxLayout, QHBoxLayout, QLabel, QLineEdit,
QPushButton, QGroupBox, QComboBox, QApplication, QDoubleSpinBox
)
from qtpy.QtGui import QFont
from qtpy.QtCore import Qt
from bec_widgets.utils.colors import get_accent_colors
from qtpy.QtCore import Qt
# pylint: disable=E0611
from qtpy.QtGui import QFont
from qtpy.QtWidgets import (
QApplication,
QComboBox,
QDoubleSpinBox,
QGroupBox,
QHBoxLayout,
QLabel,
QPushButton,
QVBoxLayout,
QWidget,
)
class Group(QGroupBox):
def __init__(self, label, widgets):
super().__init__(label)
self.layout = QVBoxLayout(self) # type: ignore
self.layout = QVBoxLayout(self) # type: ignore
for widget in widgets:
self.layout.addWidget(widget) # type: ignore
self.layout.addWidget(widget) # type: ignore
class NumberIndicator(QWidget):
def __init__(self, label='', unit=None, highlight=False, decimals=3):
def __init__(self, label="", unit=None, highlight=False, decimals=3):
super().__init__()
layout = QHBoxLayout(self)
layout.setContentsMargins(10, 0, 0, 0)
@@ -28,8 +41,8 @@ class NumberIndicator(QWidget):
self.label.setContentsMargins(0, 0, 10, 0)
self.label.setWordWrap(True)
layout.addWidget(self.label)
self.val = QLabel('-')
self.val.setAlignment(Qt.AlignTop) # type: ignore
self.val = QLabel("-")
self.val.setAlignment(Qt.AlignTop) # type: ignore
# self.val.setFixedWidth(140)
layout.addWidget(self.val)
self.unit = unit
@@ -51,13 +64,25 @@ class NumberIndicator(QWidget):
def setValue(self, number):
self.number = number
text = f'{number:.{int(self.decimals)}f}'
text = f"{number:.{int(self.decimals)}f}"
if self.unit is not None:
text = text + ' ' + self.unit
text = text + " " + self.unit
self.val.setText(text)
class InputNumberField(QWidget):
def __init__(self, identifier='', label='', unit=None, prefix=None, init=0.0, decimals=1, single_step=0.1, ll=-1e6, hl=1e6):
def __init__(
self,
identifier="",
label="",
unit=None,
prefix=None,
init=0.0,
decimals=1,
single_step=0.1,
ll=-1e6,
hl=1e6,
):
super().__init__()
layout = QHBoxLayout(self)
layout.setContentsMargins(10, 0, 0, 0)
@@ -74,9 +99,9 @@ class InputNumberField(QWidget):
self.val.setSingleStep(single_step)
self.val.setValue(init)
if unit is not None:
self.val.setSuffix(' ' + unit)
self.val.setSuffix(" " + unit)
if prefix is not None:
self.val.setPrefix(prefix + ' ')
self.val.setPrefix(prefix + " ")
# self.val.setFixedWidth(140)
layout.addWidget(self.val)
@@ -85,18 +110,21 @@ class InputNumberField(QWidget):
def has_focus(self) -> bool:
return self.val.hasFocus()
def value(self) -> float:
return self.val.value()
def value_changed_connect(self, func):
"""Connect a function to the Enter/Return key press."""
self.val.valueChanged.connect(
partial(func, identifier=self.identifier, value_obj=self.val, value=lambda: self.val.value())
partial(
func, identifier=self.identifier, value_obj=self.val, value=lambda: self.val.value()
)
)
class ComboBox(QWidget):
def __init__(self, identifier='', label='', enums=[]):
def __init__(self, identifier="", label="", enums=[]):
super().__init__()
layout = QHBoxLayout(self)
layout.setContentsMargins(10, 0, 0, 0)
@@ -124,14 +152,20 @@ class ComboBox(QWidget):
def activated_connect(self, func):
"""Connect a function to the Enter/Return key press."""
self.value.activated.connect(
partial(func, identifier=self.identifier, value_obj=self.value, value=lambda: self.value.currentText())
partial(
func,
identifier=self.identifier,
value_obj=self.value,
value=lambda: self.value.currentText(),
)
)
def setDisabled(self, disable):
self.value.setDisabled(disable)
class Button(QWidget):
def __init__(self, label=None, label_button:str='', enabled=False):
def __init__(self, label=None, label_button: str = "", enabled=False):
super().__init__()
layout = QHBoxLayout(self)
layout.setContentsMargins(10, 0, 0, 0)
@@ -165,31 +199,31 @@ class Button(QWidget):
def setText(self, text):
self.button.setText(text)
# class TextIndicator(QWidget):
# def __init__(self, label, unit=None, highlight=False):
# super().__init__()
# layout = QHBoxLayout(self)
# layout.setContentsMargins(10, 0, 0, 0)
# layout.setSpacing(0)
# self.label = QLabel(label)
# self.label.setFixedWidth(150)
# layout.addWidget(self.label)
# self.value = QLabel('-')
# self.value.setFixedWidth(160)
# layout.addWidget(self.value)
# self.unit = unit
# self.highlight = highlight
# if highlight:
# font = QFont()
# font.setBold(True)
# font.setPointSize(14)
# self.label.setFont(font)
# self.value.setFont(font)
# def set_text(self, text):
# if self.unit is not None:
# text = text + ' ' + self.unit
# self.value.setText(text)
class TextIndicator(QWidget):
def __init__(self, label):
super().__init__()
layout = QHBoxLayout(self)
layout.setContentsMargins(10, 0, 0, 0)
layout.setSpacing(0)
self.label = QLabel(label)
self.label.setFixedWidth(140)
self.label.setContentsMargins(0, 0, 10, 0)
self.label.setWordWrap(True)
layout.addWidget(self.label)
self.text = QLabel("-")
self.text.setAlignment(Qt.AlignTop) # type: ignore
layout.addWidget(self.text)
def setLabel(self, label) -> None:
self.label.setText(label)
def setText(self, text):
self.text.setText(text)
def setColor(self, color: str):
self.text.setStyleSheet(f"QLabel {{color:{color}}}")
# class Button(QWidget):
# def __init__(self, label, label_button):
+230 -220
View File
@@ -4,138 +4,123 @@ This file describes the parameter of each component of the Debye beamline
to be used for raytracing and geometrical calculations.
"""
import os
import numpy as np
from collections import namedtuple
import numpy as np
import xrt.backends.raycing.materials as rm
# if os.environ.get("USE_XRT", "True").lower() in ("1", "true", "yes"):
# import xrt.backends.raycing.materials as rm # type: ignore
# else:
# class _DummyClass:
# def __init__(self, *args, **kwargs):
# pass
# class _DummyMaterials:
# Material = _DummyClass
# CrystalSi = _DummyClass
# rm = _DummyMaterials()
# XRT definitions
filterBeryl = rm.Material('Be', rho=1.85, kind='plate') # pyright: ignore[reportArgumentType]
filterDiamond = rm.Material('C', rho=3.52, kind='plate') # pyright: ignore[reportArgumentType]
filterGraphite = rm.Material('C', rho=2.266, kind='plate') # pyright: ignore[reportArgumentType]
filterBeryl = rm.Material("Be", rho=1.85, kind="plate") # pyright: ignore[reportArgumentType]
filterDiamond = rm.Material("C", rho=3.52, kind="plate") # pyright: ignore[reportArgumentType]
filterGraphite = rm.Material("C", rho=2.266, kind="plate") # pyright: ignore[reportArgumentType]
stripeSi = rm.Material('Si', rho=2.33) # pyright: ignore[reportArgumentType]
stripePt = rm.Material('Pt', rho=21.45) # pyright: ignore[reportArgumentType]
stripeRh = rm.Material('Rh', rho=12.41) # pyright: ignore[reportArgumentType]
stripeCr = rm.Material('Cr', rho=7.14) # pyright: ignore[reportArgumentType]
stripePyrex = rm.Material('Si', rho=2.20) # Use Si as bare element and the density of SiO2 # pyright: ignore[reportArgumentType]
stripeSi = rm.Material("Si", rho=2.33) # pyright: ignore[reportArgumentType]
stripePt = rm.Material("Pt", rho=21.45) # pyright: ignore[reportArgumentType]
stripeRh = rm.Material("Rh", rho=12.41) # pyright: ignore[reportArgumentType]
stripeCr = rm.Material("Cr", rho=7.14) # pyright: ignore[reportArgumentType]
stripePyrex = rm.Material(
"Si", rho=2.20
) # Use Si as bare element and the density of SiO2 # pyright: ignore[reportArgumentType]
si111_1 = rm.CrystalSi(hkl=(1, 1, 1), tK=77) # first xtal surface
si311_1 = rm.CrystalSi(hkl=(3, 1, 1), tK=77) # first xtal surface
si333_1 = rm.CrystalSi(hkl=(3, 3, 3), tK=77) # first xtal surface
si511_1 = rm.CrystalSi(hkl=(5, 1, 1), tK=77) # first xtal surface
si111_2 = rm.CrystalSi(hkl=(1, 1, 1), tK=77) # second xtal surface
si311_2 = rm.CrystalSi(hkl=(3, 1, 1), tK=77) # second xtal surface
si333_2 = rm.CrystalSi(hkl=(3, 3, 3), tK=77) # second xtal surface
si511_2 = rm.CrystalSi(hkl=(5, 1, 1), tK=77) # second xtal surface
si111_1 = rm.CrystalSi(hkl=(1, 1, 1), tK=77) # first xtal surface
si311_1 = rm.CrystalSi(hkl=(3, 1, 1), tK=77) # first xtal surface
si333_1 = rm.CrystalSi(hkl=(3, 3, 3), tK=77) # first xtal surface
si511_1 = rm.CrystalSi(hkl=(5, 1, 1), tK=77) # first xtal surface
si111_2 = rm.CrystalSi(hkl=(1, 1, 1), tK=77) # second xtal surface
si311_2 = rm.CrystalSi(hkl=(3, 1, 1), tK=77) # second xtal surface
si333_2 = rm.CrystalSi(hkl=(3, 3, 3), tK=77) # second xtal surface
si511_2 = rm.CrystalSi(hkl=(5, 1, 1), tK=77) # second xtal surface
filterDiamond = rm.Material('C', rho=3.52, kind='plate') # pyright: ignore[reportArgumentType]
filterBe = rm.Material('Be', rho=1.85, kind='plate') # pyright: ignore[reportArgumentType]
filterSi3N4 = rm.Material(['Si', 'N'], quantities=[3, 4], rho=3.44, kind='plate') # pyright: ignore[reportArgumentType]
filterAl = rm.Material('Al', rho=2.69, kind='plate') # pyright: ignore[reportArgumentType]
filterGraphite = rm.Material('C', rho=2.266, kind='plate') # pyright: ignore[reportArgumentType]
filterDiamond = rm.Material("C", rho=3.52, kind="plate") # pyright: ignore[reportArgumentType]
filterBe = rm.Material("Be", rho=1.85, kind="plate") # pyright: ignore[reportArgumentType]
filterSi3N4 = rm.Material(
["Si", "N"], quantities=[3, 4], rho=3.44, kind="plate"
) # pyright: ignore[reportArgumentType]
filterAl = rm.Material("Al", rho=2.69, kind="plate") # pyright: ignore[reportArgumentType]
filterGraphite = rm.Material("C", rho=2.266, kind="plate") # pyright: ignore[reportArgumentType]
# General parameters
sourceHeight = 0
#Synchrotron
synchrotron = namedtuple('synchrotron', ['eE', 'eI', 'eEspread',
'eEpsilonX', 'eEpsilonZ', 'betaX', 'betaZ'])
# Synchrotron
synchrotron = namedtuple(
"synchrotron", ["eE", "eI", "eEspread", "eEpsilonX", "eEpsilonZ", "betaX", "betaZ"]
)
sls1 = synchrotron(
eE = 2.4,
eI = 0.4,
eEspread=0.878e-3,
eEpsilonX=5.63,
eEpsilonZ=0.007,
betaX=0.45,
betaZ=14.4,
)
sls2 = synchrotron(
eE=2.7,
eI=0.4,
eEspread=1.147e-3,
eEpsilonX=0.156,
eEpsilonZ=0.01,
betaX=0.18,
betaZ=4.6,
)
# Source
bendingMagnet = namedtuple('bendingMagnet', ['name', 'center', 'sync', 'B0'])
eE=2.4, eI=0.4, eEspread=0.878e-3, eEpsilonX=5.63, eEpsilonZ=0.007, betaX=0.45, betaZ=14.4
)
sls2 = synchrotron(
eE=2.7, eI=0.4, eEspread=1.147e-3, eEpsilonX=0.156, eEpsilonZ=0.01, betaX=0.18, betaZ=4.6
)
# Source
bendingMagnet = namedtuple("bendingMagnet", ["name", "center", "sync", "B0"])
sls1_14t = bendingMagnet(name="FE-BM-SLS1-1.4T", center=(0, 0, 0), sync=sls1, B0=1.4)
sls2_21t = bendingMagnet(name="FE-BM-SLS2-2.1T", center=(0, 0, 0), sync=sls2, B0=2.1)
sls2_35t = bendingMagnet(name="FE-BM-SLS2-3.5T", center=(0, 0, 0), sync=sls2, B0=3.5)
sls2_50t = bendingMagnet(name="FE-BM-SLS2-5.0T", center=(0, 0, 0), sync=sls2, B0=5.0)
sls1_14t = bendingMagnet(
name='FE-BM-SLS1-1.4T',
center=(0, 0, 0),
sync=sls1,
B0=1.4,)
sls2_21t = bendingMagnet(
name='FE-BM-SLS2-2.1T',
center=(0, 0, 0),
sync=sls2,
B0=2.1,)
sls2_35t = bendingMagnet(
name='FE-BM-SLS2-3.5T',
center=(0, 0, 0),
sync=sls2,
B0=3.5,)
sls2_50t = bendingMagnet(
name='FE-BM-SLS2-5.0T',
center=(0, 0, 0),
sync=sls2,
B0=5.0,)
# FE slits
fe_slits = namedtuple('slits', ['name', 'center', 'center1', 'center2', 'maxDivH', 'maxDivV'])
fe_slits = namedtuple("slits", ["name", "center", "center1", "center2", "maxDivH", "maxDivV"])
feSlits = fe_slits(
name='FE-SLITS',
name="FE-SLITS",
center=(0, 6117, sourceHeight),
center1=(0, 5045, sourceHeight),
center2=(0, 5289.5, sourceHeight),
maxDivH=1.8e-3,
maxDivV=0.8e-3,)
maxDivV=0.8e-3,
)
# FE Window
filt = namedtuple('filt', ['name', 'center', 'pitch', 'limPhysX', 'limPhysY', 'surface', 'material', 'thickness'])
filt = namedtuple(
"filt", ["name", "center", "pitch", "limPhysX", "limPhysY", "surface", "material", "thickness"]
)
feWindow = filt(
name='FE-WINDOW',
center=(0., 7020, sourceHeight),
pitch=np.pi/2,
name="FE-WINDOW",
center=(0.0, 7020, sourceHeight),
pitch=np.pi / 2,
limPhysX=(-6, 6),
limPhysY=(-3., 3.),
surface='None',
limPhysY=(-3.0, 3.0),
surface="None",
material=filterDiamond,
thickness=0.1,)
feWindow = feWindow._replace(surface=f'CVD Diamond window {feWindow.thickness*1e3:0.0f} $\\mu$m')
thickness=0.1,
)
feWindow = feWindow._replace(surface=f"CVD Diamond window {feWindow.thickness*1e3:0.0f} $\\mu$m")
# Collimating mirror
collimatingMirror = namedtuple(
"collimatingMirror",
[
"name",
"center",
"surface",
"material",
"limPhysX",
"limPhysY",
"limOptX",
"limOptY",
"R",
"pitch",
"jack1",
"jack2",
"jack3",
"tx1",
"tx2",
],
)
# Collimating mirror
collimatingMirror = namedtuple('collimatingMirror', ['name',
'center', 'surface', 'material', 'limPhysX', 'limPhysY',
'limOptX', 'limOptY', 'R', 'pitch', 'jack1', 'jack2', 'jack3',
'tx1', 'tx2'])
cm = collimatingMirror(
name='FE-CM',
name="FE-CM",
center=[0, 6890, sourceHeight],
surface=('Si','Pt','Rh'),
surface=("Si", "Pt", "Rh"),
material=(stripeSi, stripePt, stripeRh),
limPhysX=(-34, 34),
limPhysY=(-600, 600),
@@ -143,169 +128,194 @@ cm = collimatingMirror(
limOptY=((-500, -500, -500), (500, 500, 500)),
R=[3e6, 15e6],
pitch=[-5.0e-3, -0.0e-3],
jack1=[0., 7210., 0.], #Tripod X, Y, Z (global)
jack2=[-210., 8310., 0.],
jack3=[210., 8310., 0.],
tx1=[0.0, -575.5], # X-Stage 1 [x, y] (local)
tx2=[0.0, 575],) # X-Stage 2
apertures = namedtuple('apertures', ['name', 'center', 'opening'])
jack1=[0.0, 7210.0, 0.0], # Tripod X, Y, Z (global)
jack2=[-210.0, 8310.0, 0.0],
jack3=[210.0, 8310.0, 0.0],
tx1=[0.0, -575.5], # X-Stage 1 [x, y] (local)
tx2=[0.0, 575],
) # X-Stage 2
apertures = namedtuple("apertures", ["name", "center", "opening"])
fePS = apertures(
name='FE-PS',
center=[0, 8815, sourceHeight],
opening=[-20., 20., -20.+12.5, 20.+12.5]) # left, right, bottom, top
name="FE-PS", center=[0, 8815, sourceHeight], opening=[-20.0, 20.0, -20.0 + 12.5, 20.0 + 12.5]
) # left, right, bottom, top
opWbBsBlock = apertures(
name='OP-WB-BS-BLOCK',
center=[0., 13860, sourceHeight],
opening=[-18., 18., 25, 85.5]) # left, right, bottom, top
# opening=[-18., 18., 42, 76], # X10DA
name="OP-WB-BS-BLOCK", center=[0.0, 13860, sourceHeight], opening=[-18.0, 18.0, 25, 85.5]
) # left, right, bottom, top
# opening=[-18., 18., 42, 76], # X10DA
# Monochromator
monochromator = namedtuple('monochromator', ['name', 'center',
'xtal', 'material1', 'material2', 'xtalWidth', 'xtalOffsetX',
'xtalLength1', 'xtalLength2', 'xtalGap', 'rotOffset',
'heightOffset', 'braggLim', 'jack1', 'jack2', 'jack3', 'tx'])
monochromator = namedtuple(
"monochromator",
[
"name",
"center",
"xtal",
"material1",
"material2",
"xtalWidth",
"xtalOffsetX",
"xtalLength1",
"xtalLength2",
"xtalGap",
"rotOffset",
"heightOffset",
"braggLim",
"jack1",
"jack2",
"jack3",
"tx",
],
)
mo1 = monochromator(
name='OP-MO1',
center=[0., 11750, sourceHeight],
xtal=('Si311','Si111'),
name="OP-MO1",
center=[0.0, 11750, sourceHeight],
xtal=("Si311", "Si111"),
material1=(si311_1, si111_1),
material2=(si311_2, si111_2),
xtalWidth = (24, 24),
xtalWidth=(24, 24),
xtalOffsetX=(-21.2, 21.2),
xtalLength1 = (55, 55),
xtalLength2 = (105, 105),
xtalGap = (8, 8),
rotOffset = 6,
heightOffset = 8.5,
braggLim = [3.6, 33],
jack1=[0., 11350., 0.], #Tripod maybe not available!
jack2=[-400., 12350., 0.],
jack3=[400., 12350., 0.],
tx=0.0,) # X-Stage [x]
xtalLength1=(55, 55),
xtalLength2=(105, 105),
xtalGap=(8, 8),
rotOffset=6,
heightOffset=8.5,
braggLim=[3.6, 33],
jack1=[0.0, 11350.0, 0.0], # Tripod maybe not available!
jack2=[-400.0, 12350.0, 0.0],
jack3=[400.0, 12350.0, 0.0],
tx=0.0,
) # X-Stage [x]
mo2 = monochromator(
name='OP-CCM2',
center=[0., 13250, sourceHeight],
xtal=('Si311','Si111'),
name="OP-CCM2",
center=[0.0, 13250, sourceHeight],
xtal=("Si311", "Si111"),
material1=(si311_1, si111_1),
material2=(si311_2, si111_2),
xtalWidth = (24, 24),
xtalWidth=(24, 24),
xtalOffsetX=(-21, 21),
xtalLength1 = (55, 55),
xtalLength2 = (105, 105),
xtalGap = (8, 8),
rotOffset = 6,
heightOffset = 8.5,
braggLim = [3.6, 33],
jack1=[0., 13350., 0.], #Tripod maybe not available!
jack2=[-400., 14350., 0.],
jack3=[400., 14350., 0.],
tx=0.0,) # X-Stage [x]
xtalLength1=(55, 55),
xtalLength2=(105, 105),
xtalGap=(8, 8),
rotOffset=6,
heightOffset=8.5,
braggLim=[3.6, 33],
jack1=[0.0, 13350.0, 0.0], # Tripod maybe not available!
jack2=[-400.0, 14350.0, 0.0],
jack3=[400.0, 14350.0, 0.0],
tx=0.0,
) # X-Stage [x]
# OP Slits
op_slits = namedtuple('op_slits', ['name', 'center'])
op_slits = namedtuple("op_slits", ["name", "center"])
opSlits1 = op_slits(
name='OP-SLITS 1',
center=(0, 14349.6, sourceHeight),
)
opSlits1 = op_slits(name="OP-SLITS 1", center=(0, 14349.6, sourceHeight))
opSlits2 = op_slits(
name='OP-SLITS 2',
center=(0, 18134.8, sourceHeight),
)
opSlits2 = op_slits(name="OP-SLITS 2", center=(0, 18134.8, sourceHeight))
# OP Beam Monitors
op_bm = namedtuple('op_bm', ['name', 'center'])
op_bm = namedtuple("op_bm", ["name", "center"])
opBM1 = op_bm(
name='OP Beam Monitor 1',
center=(0, 14599.6, sourceHeight),
opBM1 = op_bm(name="OP Beam Monitor 1", center=(0, 14599.6, sourceHeight))
opBM2 = op_bm(name="OP Beam Monitor 2", center=(0, 18384.8, sourceHeight))
# Focusing mirror
focusingMirror = namedtuple(
"focusingMirror",
[
"name",
"center",
"surfaceToroid",
"materialToroid",
"surfaceFlat",
"materialFlat",
"limPhysXToroid",
"limPhysYToroid",
"limPhysXFlat",
"limPhysYFlat",
"limOptXToroid",
"limOptYToroid",
"limOptXFlat",
"limOptYFlat",
"R",
"pitch",
"r",
"xToroid",
"xFlat",
"hToroid",
"jack1",
"jack2",
"jack3",
"tx1",
"tx2",
],
)
opBM2 = op_bm(
name='OP Beam Monitor 2',
center=(0, 18384.8, sourceHeight),
)
# Focusing mirror
focusingMirror = namedtuple('focusingMirror', ['name', 'center',
'surfaceToroid', 'materialToroid', 'surfaceFlat', 'materialFlat',
'limPhysXToroid', 'limPhysYToroid', 'limPhysXFlat', 'limPhysYFlat',
'limOptXToroid', 'limOptYToroid', 'limOptXFlat', 'limOptYFlat',
'R', 'pitch', 'r', 'xToroid', 'xFlat', 'hToroid', 'jack1', 'jack2', 'jack3',
'tx1', 'tx2'])
fm = focusingMirror(
name='OP-FM',
center=[0., 15670, sourceHeight], # nominal height 58 mm above ring, SLS1!
surfaceToroid=('Rh', 'Pt'),
name="OP-FM",
center=[0.0, 15670, sourceHeight], # nominal height 58 mm above ring, SLS1!
surfaceToroid=("Rh", "Pt"),
materialToroid=(stripeRh, stripePt),
surfaceFlat=('Rh', 'Pt'),
surfaceFlat=("Rh", "Pt"),
materialFlat=(stripeRh, stripePt),
limPhysXToroid=(-79., 79.),
limPhysYToroid=(-575., 575.),
limPhysXFlat=(-79., 79.),
limPhysYFlat=(-575., 575.),
limPhysXToroid=(-79.0, 79.0),
limPhysYToroid=(-575.0, 575.0),
limPhysXFlat=(-79.0, 79.0),
limPhysYFlat=(-575.0, 575.0),
limOptXToroid=((-38, 66), (-66, 31)),
limOptYToroid=((-500., -500.), (500., 500.)),
limOptYToroid=((-500.0, -500.0), (500.0, 500.0)),
limOptXFlat=((-11.45, 23.55), (-30.45, -6.45)),
limOptYFlat=((-500., -500.), (500., 500.)),
limOptYFlat=((-500.0, -500.0), (500.0, 500.0)),
R=[3e6, 15e6],
pitch=[-5.0e-3, 0e-3],
r=[35.510, 24.986],
xToroid=[-52, 48.5], # offset in local x
xFlat = [-20.95, 8.55],
hToroid=[2.88, 7.15], # depth of the cylinder at x = xCylinder1 and x = xCylinder2.
jack1=[-130., 15535-538., 0.],
jack2=[130., 15535+538., 0.],
jack3=[0., 15535+538., 0.],
tx1=[0., -575.], # X-Stage 1 [x, y]
tx2=[0., 575.],) # X-Stage 2 [x, y]
xToroid=[-52, 48.5], # offset in local x
xFlat=[-20.95, 8.55],
hToroid=[2.88, 7.15], # depth of the cylinder at x = xCylinder1 and x = xCylinder2.
jack1=[-130.0, 15535 - 538.0, 0.0],
jack2=[130.0, 15535 + 538.0, 0.0],
jack3=[0.0, 15535 + 538.0, 0.0],
tx1=[0.0, -575.0], # X-Stage 1 [x, y]
tx2=[0.0, 575.0],
) # X-Stage 2 [x, y]
# EH Window
ehWindow = filt(
name='EH-WINDOW',
center=(0., 19998.3, sourceHeight),
pitch=np.pi/2,
limPhysX=(-20., 20.),
name="EH-WINDOW",
center=(0.0, 19998.3, sourceHeight),
pitch=np.pi / 2,
limPhysX=(-20.0, 20.0),
limPhysY=(-4, 4),
surface='None',
surface="None",
material=filterSi3N4,
thickness=0.002,)
ehWindow = ehWindow._replace(surface=f'Beryllium window {ehWindow.thickness*1e3:0.0f} $\\mu$m')
thickness=0.002,
)
ehWindow = ehWindow._replace(surface=f"Beryllium window {ehWindow.thickness*1e3:0.0f} $\\mu$m")
# Sample
sample = namedtuple('sample', ['name', 'center'])
sample = namedtuple("sample", ["name", "center"])
smpl = sample(
name='EH-SMPL',
center=[0, 23365, sourceHeight],)
smpl = sample(name="EH-SMPL", center=[0, 23365, sourceHeight])
smpl2 = sample(
name='EH-SMPL2',
center=[0, 27500, sourceHeight],)
smpl2 = sample(name="EH-SMPL2", center=[0, 27500, sourceHeight])
# Vacuum pipes
# DN40CF ID = 35 mm oder 37 mm
# DN50CF ID = 47.5 mm
# DN63CF ID = 60.2 mm oder 66 mm
# DN100CF ID = 97.4 mm oder 104 mm
pipe = namedtuple('pipes', ['center', 'diameter', 'start', 'end'])
pipe = namedtuple("pipes", ["center", "diameter", "start", "end"])
vacuum_pipes = pipe(
center= [27.5, (37.5+27.5)/2, 37.5, 62.5, 72.5],
diameter=[97.4, 97.4, 97.4, 97.4, 97.4],
start= [10952.88, 11750+250, mo2.center[1]+250, 14000, fm.center[1]],
end= [11750-250, mo2.center[1]-250, 14000, fm.center[1], ehWindow.center[1]],
center=[27.5, (37.5 + 27.5) / 2, 37.5, 62.5, 72.5],
diameter=[97.4, 97.4, 97.4, 97.4, 97.4],
start=[10952.88, 11750 + 250, mo2.center[1] + 250, 14000, fm.center[1]],
end=[11750 - 250, mo2.center[1] - 250, 14000, fm.center[1], ehWindow.center[1]],
)
Walls = namedtuple('walls', ['start', 'end', 'height'])
walls = Walls(
start= [13999.30],
end= [13999+75.5+30],
height= [[-20, 25]],
)
Walls = namedtuple("walls", ["start", "end", "height"])
walls = Walls(start=[13999.30], end=[13999 + 75.5 + 30], height=[[-20, 25]])