diff --git a/debye_bec/bec_widgets/widgets/scan_control_advanced/scan_control_advanced.py b/debye_bec/bec_widgets/widgets/scan_control_advanced/scan_control_advanced.py
index 44a4020..ddf3659 100644
--- a/debye_bec/bec_widgets/widgets/scan_control_advanced/scan_control_advanced.py
+++ b/debye_bec/bec_widgets/widgets/scan_control_advanced/scan_control_advanced.py
@@ -11,7 +11,7 @@ from bec_widgets.utils.bec_dispatcher import BECDispatcher
from bec_widgets.utils.colors import Colors, apply_theme, get_accent_colors
from bec_widgets.utils.error_popups import SafeSlot
from bec_widgets.widgets.control.scan_control.scan_control import ScanControl
-from qtpy.QtCore import Qt
+from qtpy.QtCore import Qt, Signal
# pylint: disable=E0611
from qtpy.QtWidgets import (
@@ -41,7 +41,7 @@ SHOW_MOTION_PROFILE = [
"xas_advanced_scan_with_xrd",
]
-# TODO: Changing edge trigger change self.edge_energy. Theme change edge marker. Name of edge marker label should be element and edge
+# TODO: Theme change edge marker. Show edge energy next to edge selector. Bugfix edge selector
class ScanControlAdvanced(ScanControl):
@@ -51,7 +51,9 @@ class ScanControlAdvanced(ScanControl):
motion_profile_layout = QVBoxLayout(self._motion_profile_group)
self.motion_profile_widget = MotionProfileWidget(self)
motion_profile_layout.addWidget(self.motion_profile_widget)
- super().__init__(*args, **kwargs)
+ super().__init__(
+ allowed_scans=SHOW_MOTION_PROFILE, default_scan="xas_simple_scan", *args, **kwargs
+ )
self.show_motion_profile(self._selected_scan)
self.d_spacing = 0
@@ -165,7 +167,7 @@ ELEMENTS = {
# period 6
"Cs": (6, 1),
"Ba": (6, 2),
- "La": (6, 3),
+ "La": (8, 3),
"Ce": (8, 4),
"Pr": (8, 5),
"Nd": (8, 6),
@@ -199,6 +201,8 @@ class PeriodicTableDialog(QDialog):
self.selected = None
layout = QGridLayout(self)
+ layout.setContentsMargins(0, 0, 0, 0)
+ layout.setSpacing(1)
for element, (row, col) in ELEMENTS.items():
button = QPushButton(element)
@@ -212,6 +216,9 @@ class PeriodicTableDialog(QDialog):
class ElementSelector(QWidget):
+
+ dialogClosed = Signal()
+
def __init__(self):
super().__init__()
self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
@@ -225,21 +232,39 @@ class ElementSelector(QWidget):
self.button.setStyleSheet(
f"QPushButton {{background-color: {get_accent_colors().default.name()}; color: white;}}"
)
- self.selection = QLabel("")
+ # self.selection = QLabel("")
layout_selection.addWidget(self.button)
- layout_selection.addWidget(self.selection)
+ # layout_selection.addWidget(self.selection)
layout.addWidget(self.label)
layout.addLayout(layout_selection)
+ self.current_element = ""
self.button.clicked.connect(self.open_table)
def open_table(self):
dialog = PeriodicTableDialog(self)
if dialog.exec_():
- self.selection.setText(dialog.selected)
+ self.current_element = dialog.selected
+ # self.selection.setText(dialog.selected)
+ self.dialogClosed.emit()
- def currentText(self):
- return self.selection.text()
+ def currentElement(self):
+ return self.current_element
+
+ def apply_theme(self, theme: Optional[Literal["dark", "light"]] = None):
+ """
+ Apply the theme
+
+ Args:
+ theme (Optional[str]): Theme, either "dark", "light", or None. Defaults to None.
+ """
+ if theme is None:
+ app = QApplication.instance()
+ theme = app.theme.theme # type: ignore
+
+ self.button.setStyleSheet(
+ f"QPushButton {{background-color: {get_accent_colors().default.name()}; color: white;}}"
+ )
class MotionProfileWidget(QWidget):
@@ -252,9 +277,10 @@ class MotionProfileWidget(QWidget):
self.element = ElementSelector()
self.edge = ComboBox("Edge", "Edge", ["K", "L1", "L2", "L3"])
+ self.edge_text = TextIndicator("", "Selected Edge", "No edge selected")
plot_container = QWidget()
- plot_layout = QVBoxLayout(plot_container)
+ plot_layout = QHBoxLayout(plot_container)
plot_layout.setContentsMargins(0, 0, 0, 0)
self.plot_pos = self._make_plot(left_label="Energy
[eV]", bottom_label="Time [s]")
@@ -262,13 +288,13 @@ class MotionProfileWidget(QWidget):
left_label="Scan Velocity
[eV/s]", bottom_label="Energy [eV]"
)
- self.edge_energy = 8000
+ self.edge_energy = None
plot_layout.addWidget(self.plot_pos)
plot_layout.addWidget(self.plot_vel)
plot_container.setMinimumHeight(
- self.plot_pos.minimumHeight() + self.plot_vel.minimumHeight()
+ int(np.max([self.plot_pos.minimumHeight(), self.plot_vel.minimumHeight()]))
)
scroll = QScrollArea()
scroll.setWidgetResizable(True)
@@ -279,6 +305,7 @@ class MotionProfileWidget(QWidget):
self.edge_selection = QHBoxLayout()
self.edge_selection.addWidget(self.element)
self.edge_selection.addWidget(self.edge)
+ self.edge_selection.addWidget(self.edge_text)
self.edge_selection.addStretch(1)
outer_layout.addLayout(self.edge_selection)
@@ -288,6 +315,9 @@ class MotionProfileWidget(QWidget):
self.scan_parameters = None
self.d_spacing = None
+ self.element.dialogClosed.connect(self._update_edge_selection)
+ self.edge.activated_connect(self._update_edge_selection)
+
@staticmethod
def _make_plot(left_label: str, bottom_label: str) -> pg.PlotWidget:
plot = pg.PlotWidget()
@@ -298,28 +328,54 @@ class MotionProfileWidget(QWidget):
plot.hideButtons()
plot.getAxis("left").enableAutoSIPrefix(False)
plot.getAxis("bottom").enableAutoSIPrefix(False)
- plot.setMinimumHeight(220)
+ plot.setMinimumHeight(180)
plot.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.MinimumExpanding)
return plot
- def _add_edge_marker(self, plot, x_arr, y_arr, energy_arr):
+ def _add_edge_marker(self, plot, x_arr, y_arr, energy_arr, edge_marker):
if self.edge_energy is None:
return
idx = int(np.argmin(np.abs(np.asarray(energy_arr) - self.edge_energy)))
+ if idx == 0 or idx == len(energy_arr) - 1:
+ return
x_marker = x_arr[idx]
y_marker = y_arr[idx]
scatter = pg.ScatterPlotItem(
- [x_marker], [y_marker], symbol="star", size=14, brush=pg.mkBrush("r"), pen=pg.mkPen("r")
+ [x_marker],
+ [y_marker],
+ symbol=edge_marker,
+ size=20,
+ brush=pg.mkBrush("r"),
+ pen=pg.mkPen("r"),
)
plot.addItem(scatter, ignoreBounds=True)
- label = pg.TextItem("edge", anchor=(0, 1), color="r")
+ text = f"{self.element.currentElement()}, {self.edge.currentText()}-edge, {self.edge_energy:0.1f} eV"
+ label = pg.TextItem(text, anchor=(0.5, 1.5), color="r")
label.setPos(x_marker, y_marker)
plot.addItem(label, ignoreBounds=True)
- def update_plot(self, scan_name=None, scan_parameters=None, d_spacing=None):
+ @SafeSlot()
+ def _update_edge_selection(self, *_, **__):
+ if self.element.currentElement() == "":
+ return
+ if self.edge.currentText() == "":
+ return
+ self.edge_energy = xraydb.xray_edge(
+ self.element.currentElement(), self.edge.currentText(), True
+ )
+ if self.edge_energy is not None:
+ self.edge_text.setText(
+ f"{self.element.currentElement()}, {self.edge.currentText()}-edge, {self.edge_energy:0.1f} eV"
+ )
+ else:
+ self.edge_text.setText("No valid edge selected!")
+ self.update_plot()
+
+ @SafeSlot()
+ def update_plot(self, scan_name=None, scan_parameters=None, d_spacing=None, *_, **__):
if scan_name is not None:
self.scan_name = scan_name
if scan_parameters is not None:
@@ -351,10 +407,10 @@ class MotionProfileWidget(QWidget):
vel_e = self.velocity_to_energy_per_s(pos, vel)
self.plot_pos.plot(x_time, energy)
- self._add_edge_marker(self.plot_pos, x_time, energy, energy)
+ self._add_edge_marker(self.plot_pos, x_time, energy, energy, "_")
self.plot_vel.plot(energy, -vel_e)
- self._add_edge_marker(self.plot_vel, energy, -vel_e, energy)
+ self._add_edge_marker(self.plot_vel, energy, -vel_e, energy, "|")
if "xas_advanced_scan" in self.scan_name:
if (
@@ -379,10 +435,10 @@ class MotionProfileWidget(QWidget):
time_flipped = -np.flip(x_time) + x_time[-1]
energy_flipped = np.flip(energy)
self.plot_pos.plot(time_flipped, energy_flipped)
- self._add_edge_marker(self.plot_pos, time_flipped, energy_flipped, energy_flipped)
+ self._add_edge_marker(self.plot_pos, time_flipped, energy_flipped, energy_flipped, "_")
self.plot_vel.plot(energy, -vel_e)
- self._add_edge_marker(self.plot_vel, energy, -vel_e, energy)
+ self._add_edge_marker(self.plot_vel, energy, -vel_e, energy, "|")
self.apply_theme()
@@ -393,7 +449,6 @@ class MotionProfileWidget(QWidget):
Args:
theme (Optional[str]): Theme, either "dark", "light", or None. Defaults to None.
"""
- logger.info(f"theme update called with theme: {theme}")
if theme is None:
app = QApplication.instance()
theme = app.theme.theme # type: ignore
@@ -411,7 +466,9 @@ class MotionProfileWidget(QWidget):
curves = plot.listDataItems()
colors = Colors.golden_angle_color(colormap="plasma", num=len(curves), format="HEX")
for curve, color in zip(curves, colors):
- curve.setPen(pg.mkPen(color=color, width=2))
+ if not isinstance(curve, pg.ScatterPlotItem):
+ curve.setPen(pg.mkPen(color=color, width=2))
+ self.element.apply_theme(theme)
def energy_to_angle(self, energy: int | float):
if self.d_spacing is None:
@@ -486,19 +543,40 @@ 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(),
- )
- )
+ self.value.activated.connect(func)
def setDisabled(self, disable):
self.value.setDisabled(disable)
+class TextIndicator(QWidget):
+ def __init__(self, identifier="", label="", text=""):
+ super().__init__()
+
+ layout = QVBoxLayout(self)
+ layout.setContentsMargins(*ROW_MARGINS)
+ layout.setSpacing(ROW_SPACING)
+
+ self.identifier = identifier
+
+ self.label = QLabel(label)
+ self.label.setFixedWidth(LABEL_WIDTH)
+ self.label.setWordWrap(True)
+ self.label.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Preferred)
+ layout.addWidget(self.label)
+
+ self.value = QLabel(text)
+ self.value.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
+
+ layout.addWidget(self.value)
+
+ def setText(self, text):
+ self.value.setText(text)
+
+ def text(self) -> str:
+ return self.value.text()
+
+
if __name__ == "__main__":
app = QApplication(sys.argv)
apply_theme("light")