wip: digital twin
This commit is contained in:
@@ -11,7 +11,7 @@ from qtpy.QtWidgets import (
|
||||
)
|
||||
# pylint: disable=E0611
|
||||
from qtpy.QtCore import Qt, QTimer
|
||||
from qtpy.QtGui import QColor, QFont
|
||||
from qtpy.QtGui import QColor, QFont, QBrush
|
||||
import pyqtgraph as pg
|
||||
|
||||
from xrt.backends.raycing.physconsts import CHeVcm, AVOGADRO
|
||||
@@ -133,9 +133,9 @@ class DigitalTwin(BECWidget, QWidget):
|
||||
dE_over_E = fwhm_rad / np.tan(theta_B)
|
||||
dE = dE_over_E * E
|
||||
|
||||
logger.info(f"DCM FWHM : {r2-r1:.2f} µrad")
|
||||
logger.info(f"ΔE/E : {dE_over_E:.2e}")
|
||||
logger.info(f"ΔE : {dE:.3f} eV at {E} eV")
|
||||
# logger.info(f"DCM FWHM : {r2-r1:.2f} µrad")
|
||||
# logger.info(f"ΔE/E : {dE_over_E:.2e}")
|
||||
# logger.info(f"ΔE : {dE:.3f} eV at {E} eV")
|
||||
|
||||
self.input.mo1_eres.setValue(dE)
|
||||
|
||||
@@ -146,13 +146,17 @@ class DigitalTwin(BECWidget, QWidget):
|
||||
np.sin(-self.input.cm_pitch.value() * 1e-3)
|
||||
)[0:2]
|
||||
self.input.cm_refl.setValue(100 * abs(rs)**2)
|
||||
self.input.cm_refl.setLabel(f"Refl. at {self.input.energy.value():.0f} eV")
|
||||
self.input.cm_refl.setLabel(f"Reflectivity at \n{self.input.energy.value():.0f} eV")
|
||||
rs, rp = bl.cm.material[index].get_amplitude(
|
||||
2 * self.input.energy.value(),
|
||||
np.sin(-self.input.cm_pitch.value() * 1e-3)
|
||||
)[0:2]
|
||||
self.input.cm_refl_harm.setValue(100 * abs(rs)**2)
|
||||
self.input.cm_refl_harm.setLabel(f"Refl. at {2 * self.input.energy.value():.0f} eV")
|
||||
self.input.cm_refl_harm.setLabel(f"Reflectivity at \n{3 * self.input.energy.value():.0f} eV")
|
||||
|
||||
harm_suppr = (self.input.cm_refl.value() * self.input.fm_refl.value()) / (self.input.cm_refl_harm.value() * self.input.fm_refl_harm.value())
|
||||
self.input.cm_fm_harm_suppr.setValue(harm_suppr)
|
||||
self.input.cm_fm_harm_suppr.setLabel(f"Total Suppression Factor at {3 * self.input.energy.value():.0f} eV")
|
||||
|
||||
def calc_fm_reflectivity(self, *args):
|
||||
if self.input.fm_stripe.currentText() in ('Rh (toroid)', 'Pt (toroid)'):
|
||||
@@ -170,7 +174,17 @@ class DigitalTwin(BECWidget, QWidget):
|
||||
np.sin(-self.input.fm_pitch.value() * 1e-3)
|
||||
)[0:2]
|
||||
self.input.fm_refl.setValue(100 * abs(rs)**2)
|
||||
self.input.fm_refl.setLabel(f"Refl. at {self.input.energy.value():.0f} eV")
|
||||
self.input.fm_refl.setLabel(f"Reflectivity at \n{self.input.energy.value():.0f} eV")
|
||||
rs, rp = material[index].get_amplitude(
|
||||
2 * self.input.energy.value(),
|
||||
np.sin(-self.input.fm_pitch.value() * 1e-3)
|
||||
)[0:2]
|
||||
self.input.fm_refl_harm.setValue(100 * abs(rs)**2)
|
||||
self.input.fm_refl_harm.setLabel(f"Reflectivity at \n{3 * self.input.energy.value():.0f} eV")
|
||||
|
||||
harm_suppr = (self.input.cm_refl.value() * self.input.fm_refl.value()) / (self.input.cm_refl_harm.value() * self.input.fm_refl_harm.value())
|
||||
self.input.cm_fm_harm_suppr.setValue(harm_suppr)
|
||||
self.input.cm_fm_harm_suppr.setLabel(f"Total Suppression Factor at {3 * self.input.energy.value():.0f} eV")
|
||||
|
||||
def get_assistant_config(self):
|
||||
config = { # Config in SI units!
|
||||
@@ -387,8 +401,8 @@ class InputPanel(QWidget):
|
||||
self.cm_stripe = ComboBox('Stripe', ['Si', 'Rh', 'Pt'])
|
||||
self.cm_pitch_critical = NumberIndicator('Critical Pitch', 'mrad', decimals=3)
|
||||
self.cm_pitch = InputNumberField('Pitch [mrad]', init=-2.391, decimals=3, single_step=0.01, ll=-4.6, hl=-1.2)
|
||||
self.cm_refl = NumberIndicator('Refl. at x eV', '%', decimals=0)
|
||||
self.cm_refl_harm = NumberIndicator('Refl. at x eV', '%', decimals=0)
|
||||
self.cm_refl = NumberIndicator('Reflectivity at x eV', '%', decimals=0)
|
||||
self.cm_refl_harm = NumberIndicator('Reflectivity at x eV', '%', decimals=0)
|
||||
self.cm_ass_group = Group(
|
||||
'Collimating Mirror',
|
||||
[
|
||||
@@ -419,7 +433,8 @@ class InputPanel(QWidget):
|
||||
self.fm_stripe = ComboBox('Stripe', ['Rh (toroid)', 'Rh (flat)', 'Pt (toroid)', 'Pt (flat)'])
|
||||
self.fm_pitch_ideal = NumberIndicator('Ideal Pitch', 'mrad', decimals=3)
|
||||
self.fm_pitch = InputNumberField('Pitch [mrad]', init=-2.391, decimals=3, single_step=0.01, ll=-10, hl=2)
|
||||
self.fm_refl = NumberIndicator('Refl. at x eV', '%', decimals=0)
|
||||
self.fm_refl = NumberIndicator('Reflectivity at x eV', '%', decimals=0)
|
||||
self.fm_refl_harm = NumberIndicator('Reflectivity at x eV', '%', decimals=0)
|
||||
self.fm_ass_group = Group(
|
||||
'Focusing Mirror',
|
||||
[
|
||||
@@ -427,10 +442,12 @@ class InputPanel(QWidget):
|
||||
self.fm_pitch_ideal,
|
||||
self.fm_pitch,
|
||||
self.fm_refl,
|
||||
self.fm_refl_harm,
|
||||
]
|
||||
)
|
||||
|
||||
# Sample
|
||||
self.cm_fm_harm_suppr = NumberIndicator('Total Suppression Factor at x eV', '', decimals=0)
|
||||
self.smpl = InputNumberField('Sample Position [mm]', init=23511, decimals=0, single_step=100, ll=23000, hl=30000)
|
||||
|
||||
# Assemble complete assitant group
|
||||
@@ -442,6 +459,7 @@ class InputPanel(QWidget):
|
||||
self.cm_ass_group,
|
||||
self.mo1_ass_group,
|
||||
self.fm_ass_group,
|
||||
self.cm_fm_harm_suppr,
|
||||
self.smpl,
|
||||
]
|
||||
)
|
||||
@@ -458,8 +476,8 @@ class PositionsPanel(QWidget):
|
||||
self._layout.setSizeConstraint(QLayout.SetFixedSize) # type: ignore
|
||||
|
||||
# FE Slits
|
||||
self.sldi_gapx = NumberIndicator('GAPX', 'mm', decimals=3)
|
||||
self.sldi_gapy = NumberIndicator('GAPY', 'mm', decimals=3)
|
||||
self.sldi_gapx = NumberIndicator('GAPX', 'mm', decimals=2)
|
||||
self.sldi_gapy = NumberIndicator('GAPY', 'mm', decimals=2)
|
||||
self.sldi_pos_group = Group(
|
||||
'FE Slits',
|
||||
[
|
||||
@@ -469,8 +487,8 @@ class PositionsPanel(QWidget):
|
||||
)
|
||||
|
||||
# Collimating mirror
|
||||
self.cm_trx = NumberIndicator('TRX', 'mm', decimals=1)
|
||||
self.cm_try = NumberIndicator('TRY', 'mm', decimals=3)
|
||||
self.cm_trx = NumberIndicator('TRX', 'mm', decimals=2)
|
||||
self.cm_try = NumberIndicator('TRY', 'mm', decimals=2)
|
||||
self.cm_bnd = NumberIndicator('BENDER', 'km', decimals=2)
|
||||
self.cm_rotx = NumberIndicator('PITCH', 'mrad', decimals=3)
|
||||
self.cm_pos_group = Group(
|
||||
@@ -485,8 +503,8 @@ class PositionsPanel(QWidget):
|
||||
|
||||
# Monochromator
|
||||
self.mo1_bragg_angle = NumberIndicator('Bragg Angle', 'deg', decimals=3)
|
||||
self.mo1_trx = NumberIndicator('TRX', 'mm', decimals=1)
|
||||
self.mo1_try = NumberIndicator('TRY', 'mm', decimals=3)
|
||||
self.mo1_trx = NumberIndicator('TRX', 'mm', decimals=2)
|
||||
self.mo1_try = NumberIndicator('TRY', 'mm', decimals=2)
|
||||
self.mo1_pos_group = Group(
|
||||
'Monochromator',
|
||||
[
|
||||
@@ -497,7 +515,7 @@ class PositionsPanel(QWidget):
|
||||
)
|
||||
|
||||
# OP Slits 1
|
||||
self.sl1_centery = NumberIndicator('CENTERY', 'mm', decimals=1)
|
||||
self.sl1_centery = NumberIndicator('CENTERY', 'mm', decimals=2)
|
||||
self.sl1_pos_group = Group(
|
||||
'OP Slits 1',
|
||||
[
|
||||
@@ -506,7 +524,7 @@ class PositionsPanel(QWidget):
|
||||
)
|
||||
|
||||
# OP Beam Monitor 1
|
||||
self.bm1_try = NumberIndicator('TRY', 'mm', decimals=1)
|
||||
self.bm1_try = NumberIndicator('TRY', 'mm', decimals=2)
|
||||
self.bm1_pos_group = Group(
|
||||
'OP Beam Monitor 1',
|
||||
[
|
||||
@@ -515,8 +533,8 @@ class PositionsPanel(QWidget):
|
||||
)
|
||||
|
||||
# Focusing Mirror
|
||||
self.fm_trx = NumberIndicator('TRX', 'mm', decimals=1)
|
||||
self.fm_try = NumberIndicator('TRY', 'mm', decimals=3)
|
||||
self.fm_trx = NumberIndicator('TRX', 'mm', decimals=2)
|
||||
self.fm_try = NumberIndicator('TRY', 'mm', decimals=2)
|
||||
self.fm_bnd = NumberIndicator('BENDER', 'km', decimals=2)
|
||||
self.fm_rotx = NumberIndicator('PITCH', 'mrad', decimals=3)
|
||||
self.fm_pos_group = Group(
|
||||
@@ -530,7 +548,7 @@ class PositionsPanel(QWidget):
|
||||
)
|
||||
|
||||
# OP Slits 2
|
||||
self.sl2_centery = NumberIndicator('CENTERY', 'mm', decimals=1)
|
||||
self.sl2_centery = NumberIndicator('CENTERY', 'mm', decimals=2)
|
||||
self.sl2_pos_group = Group(
|
||||
'OP Slits 2',
|
||||
[
|
||||
@@ -539,7 +557,7 @@ class PositionsPanel(QWidget):
|
||||
)
|
||||
|
||||
# OP Beam Monitor 2
|
||||
self.bm2_try = NumberIndicator('TRY', 'mm', decimals=1)
|
||||
self.bm2_try = NumberIndicator('TRY', 'mm', decimals=2)
|
||||
self.bm2_pos_group = Group(
|
||||
'OP Beam Monitor 2',
|
||||
[
|
||||
@@ -548,7 +566,7 @@ class PositionsPanel(QWidget):
|
||||
)
|
||||
|
||||
# Optical Table
|
||||
self.ot_try = NumberIndicator('TRY', 'mm', decimals=0)
|
||||
self.ot_try = NumberIndicator('TRY', 'mm', decimals=2)
|
||||
self.ot_rotx = NumberIndicator('ROTX', 'mrad', decimals=3)
|
||||
self.ot_es1_trz = NumberIndicator('ES1 TRZ', 'mm', decimals=0)
|
||||
self.ot_pos_group = Group(
|
||||
@@ -585,7 +603,6 @@ class SurfacePlots(QWidget):
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
self._layout = QHBoxLayout(self)
|
||||
# self._layout.setSizeConstraint(QLayout.SetFixedSize) # type: ignore
|
||||
|
||||
self.surfaces = {
|
||||
'assistant': {
|
||||
@@ -614,10 +631,11 @@ class SurfacePlots(QWidget):
|
||||
if theme == "light":
|
||||
self.color_impenetrable = (30, 30, 30)
|
||||
self.colors = [(79, 163, 224), (240, 128, 60)]
|
||||
self.text_color = (255, 255, 255)
|
||||
else: # dark theme
|
||||
self.color_impenetrable = (220, 220, 220)
|
||||
self.colors = [(26, 111, 173), (212, 83, 10)]
|
||||
|
||||
self.text_color = (0, 0, 0)
|
||||
|
||||
# Create plot widgets
|
||||
for name, widget in self.plots.items():
|
||||
@@ -634,8 +652,6 @@ class SurfacePlots(QWidget):
|
||||
plot_widget.setLabel('left', 'Z [mm]')
|
||||
plot_widget.setLabel('bottom', 'X [mm]')
|
||||
plot_widget.setMouseEnabled(x=False, y=False)
|
||||
# plot_widget.setXRange(0, 25000, padding=0.1)
|
||||
# plot_widget.setYRange(-20, 120, padding=0.1)
|
||||
plot_widget.setMenuEnabled(False)
|
||||
plot_widget.hideButtons()
|
||||
|
||||
@@ -645,25 +661,26 @@ class SurfacePlots(QWidget):
|
||||
# Create surfaces
|
||||
for idx, scene in enumerate(self.surfaces):
|
||||
for name, device in self.surfaces[scene].items():
|
||||
brush = pg.mkBrush(color=self.colors[idx] + (150,))
|
||||
if scene in 'assistant':
|
||||
brush = QBrush(QColor(*self.colors[idx], 255), Qt.DiagCrossPattern)
|
||||
pen = pg.mkPen(QColor(*self.colors[idx], 255), width=1, style=Qt.DashLine)
|
||||
z_value = 2
|
||||
else:
|
||||
brush = QBrush(QColor(*self.colors[idx], 255))
|
||||
pen = pg.mkPen(QColor(*self.colors[idx], 255), width=1)
|
||||
z_value = 1
|
||||
widget = self.plots[name]
|
||||
self.plots[name][scene] = widget['widget'].plot(
|
||||
[],
|
||||
[],
|
||||
pen=None,
|
||||
pen=pen,
|
||||
name=scene,
|
||||
brush=brush,
|
||||
fillLevel=0,
|
||||
)
|
||||
self.plots[name][scene].setZValue(1)
|
||||
|
||||
# self._layout.addStretch()
|
||||
|
||||
logger.info(f'Created surfaces: {self.surfaces}')
|
||||
logger.info(f'Created plots: {self.plots}')
|
||||
self.plots[name][scene].setZValue(z_value)
|
||||
|
||||
self.plot_walls()
|
||||
# self.update_curves()
|
||||
|
||||
def plot_walls(self):
|
||||
|
||||
@@ -678,10 +695,10 @@ class SurfacePlots(QWidget):
|
||||
rect.setBrush(pg.QtGui.QBrush(pg.QtGui.QColor(*self.color_impenetrable))) # pylint: disable=E1101
|
||||
rect.setPen(pg.mkPen(color=self.color_impenetrable, width=2))
|
||||
widget.addItem(rect)
|
||||
text = pg.TextItem(sf, color='w', anchor=(0.5, 0.5)) # TODO: CHange color according to theme
|
||||
text = pg.TextItem(sf, color=self.text_color, anchor=(0.5, 0.5)) # TODO: CHange color according to theme
|
||||
widget.addItem(text)
|
||||
text.setPos((hx+lx)/2, (hy+ly)/2)
|
||||
text.setZValue(2)
|
||||
text.setZValue(10)
|
||||
|
||||
def plot_mono_surface(widget, xtal, xtalWidth, xtalOffsetX, xtalLength):
|
||||
for sf, w, offx, len in zip(xtal, xtalWidth, xtalOffsetX, xtalLength):
|
||||
@@ -694,10 +711,10 @@ class SurfacePlots(QWidget):
|
||||
rect.setBrush(pg.QtGui.QBrush(pg.QtGui.QColor(*self.color_impenetrable))) # pylint: disable=E1101
|
||||
rect.setPen(pg.mkPen(color=self.color_impenetrable, width=2))
|
||||
widget.addItem(rect)
|
||||
text = pg.TextItem(sf, color='w', anchor=(0.5, 0.5)) # TODO: CHange color according to theme
|
||||
text = pg.TextItem(sf, color=self.text_color, anchor=(0.5, 0.5)) # TODO: CHange color according to theme
|
||||
widget.addItem(text)
|
||||
text.setPos(offx, 0)
|
||||
text.setZValue(2)
|
||||
text.setZValue(10)
|
||||
|
||||
for name, plot in self.plots.items():
|
||||
if name in 'cm':
|
||||
@@ -714,95 +731,6 @@ class SurfacePlots(QWidget):
|
||||
for name, plot in self.plots.items():
|
||||
plot['widget'].disableAutoRange()
|
||||
|
||||
def impenetrable_color(self):
|
||||
app = QApplication.instance()
|
||||
theme = app.theme.theme # type: ignore
|
||||
if theme == "light":
|
||||
return (30, 30, 30)
|
||||
else:
|
||||
return (220, 220, 220)
|
||||
|
||||
def golden_angle_color(
|
||||
self,
|
||||
colormap: str,
|
||||
num: int,
|
||||
format="QColor",
|
||||
theme_offset=0.2,
|
||||
theme=None,
|
||||
) -> list:
|
||||
"""
|
||||
Extract num colors from the specified colormap following golden angle distribution and return them in the specified format.
|
||||
|
||||
Args:
|
||||
colormap (str): Name of the colormap.
|
||||
num (int): Number of requested colors.
|
||||
format (Literal["QColor","HEX","RGB"]): The format of the returned colors ('RGB', 'HEX', 'QColor').
|
||||
theme_offset (float): Has to be between 0-1. Offset to avoid colors too close to white or black with light or dark theme respectively for pyqtgraph plot background.
|
||||
|
||||
Returns:
|
||||
list: List of colors in the specified format.
|
||||
|
||||
Raises:
|
||||
ValueError: If theme_offset is not between 0 and 1.
|
||||
"""
|
||||
|
||||
cmap = pg.colormap.get(colormap)
|
||||
phi = (1 + np.sqrt(5)) / 2 # Golden ratio
|
||||
golden_angle_conjugate = 1 - (1 / phi) # Approximately 0.38196601125
|
||||
|
||||
min_pos, max_pos = self.set_theme_offset(theme, theme_offset)
|
||||
|
||||
# Generate positions within the acceptable range
|
||||
positions = np.mod(np.arange(num) * golden_angle_conjugate, 1)
|
||||
positions = min_pos + positions * (max_pos - min_pos)
|
||||
|
||||
# Sample colors from the colormap at the calculated positions
|
||||
colors = cmap.map(positions, mode="float") # type: ignore
|
||||
color_list = []
|
||||
|
||||
for color in colors: # type: ignore
|
||||
if format.upper() == "HEX":
|
||||
color_list.append(QColor.fromRgbF(*color).name())
|
||||
elif format.upper() == "RGB":
|
||||
color_list.append(tuple((np.array(color) * 255).astype(int)))
|
||||
elif format.upper() == "QCOLOR":
|
||||
color_list.append(QColor.fromRgbF(*color))
|
||||
else:
|
||||
raise ValueError("Unsupported format. Please choose 'RGB', 'HEX', or 'QColor'.")
|
||||
return color_list
|
||||
|
||||
def set_theme_offset(self, theme = None, offset=0.2) -> tuple:
|
||||
"""
|
||||
Set the theme offset to avoid colors too close to white or black with light or dark theme respectively for pyqtgraph plot background.
|
||||
|
||||
Args:
|
||||
theme(str): The theme to be applied.
|
||||
offset(float): Offset to avoid colors too close to white or black with light or dark theme respectively for pyqtgraph plot background.
|
||||
|
||||
Returns:
|
||||
tuple: Tuple of min_pos and max_pos.
|
||||
|
||||
Raises:
|
||||
ValueError: If theme_offset is not between 0 and 1.
|
||||
"""
|
||||
|
||||
if offset < 0 or offset > 1:
|
||||
raise ValueError("theme_offset must be between 0 and 1")
|
||||
|
||||
if theme is None:
|
||||
app = QApplication.instance()
|
||||
if hasattr(app, "theme"):
|
||||
theme = app.theme.theme # type: ignore
|
||||
|
||||
if theme == "light":
|
||||
min_pos = 0.0
|
||||
max_pos = 1 - offset
|
||||
else:
|
||||
min_pos = 0.0 + offset
|
||||
max_pos = 1.0
|
||||
|
||||
return min_pos, max_pos
|
||||
|
||||
def update_surfaces(self, scene, data):
|
||||
self.surfaces[scene] = data
|
||||
for name, device in self.surfaces[scene].items():
|
||||
@@ -810,9 +738,6 @@ class SurfacePlots(QWidget):
|
||||
x = np.array(device['x'] + [device['x'][0]]) if len(device['x']) != 0 else np.array([])
|
||||
y = np.array(device['y'] + [device['y'][0]]) if len(device['y']) != 0 else np.array([])
|
||||
plot.setData(x=x, y=y)
|
||||
# fill = pg.FillBetweenItem(curve, widget.plot(device['x'], np.zeros(len(device['x'])), pen=None), brush=pg.mkBrush('b'))
|
||||
# widget.addItem(fill)
|
||||
logger.info(self.surfaces)
|
||||
|
||||
class SideviewPlot(QWidget):
|
||||
"""Plot widget with two curves and legend."""
|
||||
@@ -907,95 +832,6 @@ class SideviewPlot(QWidget):
|
||||
rect.setPen(pg.mkPen(color=self.color_impenetrable, width=2))
|
||||
self.plot_widget.addItem(rect)
|
||||
|
||||
def impenetrable_color(self):
|
||||
app = QApplication.instance()
|
||||
theme = app.theme.theme # type: ignore
|
||||
if theme == "light":
|
||||
return (30, 30, 30)
|
||||
else:
|
||||
return (220, 220, 220)
|
||||
|
||||
def golden_angle_color(
|
||||
self,
|
||||
colormap: str,
|
||||
num: int,
|
||||
format="QColor",
|
||||
theme_offset=0.2,
|
||||
theme=None,
|
||||
) -> list:
|
||||
"""
|
||||
Extract num colors from the specified colormap following golden angle distribution and return them in the specified format.
|
||||
|
||||
Args:
|
||||
colormap (str): Name of the colormap.
|
||||
num (int): Number of requested colors.
|
||||
format (Literal["QColor","HEX","RGB"]): The format of the returned colors ('RGB', 'HEX', 'QColor').
|
||||
theme_offset (float): Has to be between 0-1. Offset to avoid colors too close to white or black with light or dark theme respectively for pyqtgraph plot background.
|
||||
|
||||
Returns:
|
||||
list: List of colors in the specified format.
|
||||
|
||||
Raises:
|
||||
ValueError: If theme_offset is not between 0 and 1.
|
||||
"""
|
||||
|
||||
cmap = pg.colormap.get(colormap)
|
||||
phi = (1 + np.sqrt(5)) / 2 # Golden ratio
|
||||
golden_angle_conjugate = 1 - (1 / phi) # Approximately 0.38196601125
|
||||
|
||||
min_pos, max_pos = self.set_theme_offset(theme, theme_offset)
|
||||
|
||||
# Generate positions within the acceptable range
|
||||
positions = np.mod(np.arange(num) * golden_angle_conjugate, 1)
|
||||
positions = min_pos + positions * (max_pos - min_pos)
|
||||
|
||||
# Sample colors from the colormap at the calculated positions
|
||||
colors = cmap.map(positions, mode="float") # type: ignore
|
||||
color_list = []
|
||||
|
||||
for color in colors: # type: ignore
|
||||
if format.upper() == "HEX":
|
||||
color_list.append(QColor.fromRgbF(*color).name())
|
||||
elif format.upper() == "RGB":
|
||||
color_list.append(tuple((np.array(color) * 255).astype(int)))
|
||||
elif format.upper() == "QCOLOR":
|
||||
color_list.append(QColor.fromRgbF(*color))
|
||||
else:
|
||||
raise ValueError("Unsupported format. Please choose 'RGB', 'HEX', or 'QColor'.")
|
||||
return color_list
|
||||
|
||||
def set_theme_offset(self, theme = None, offset=0.2) -> tuple:
|
||||
"""
|
||||
Set the theme offset to avoid colors too close to white or black with light or dark theme respectively for pyqtgraph plot background.
|
||||
|
||||
Args:
|
||||
theme(str): The theme to be applied.
|
||||
offset(float): Offset to avoid colors too close to white or black with light or dark theme respectively for pyqtgraph plot background.
|
||||
|
||||
Returns:
|
||||
tuple: Tuple of min_pos and max_pos.
|
||||
|
||||
Raises:
|
||||
ValueError: If theme_offset is not between 0 and 1.
|
||||
"""
|
||||
|
||||
if offset < 0 or offset > 1:
|
||||
raise ValueError("theme_offset must be between 0 and 1")
|
||||
|
||||
if theme is None:
|
||||
app = QApplication.instance()
|
||||
if hasattr(app, "theme"):
|
||||
theme = app.theme.theme # type: ignore
|
||||
|
||||
if theme == "light":
|
||||
min_pos = 0.0
|
||||
max_pos = 1 - offset
|
||||
else:
|
||||
min_pos = 0.0 + offset
|
||||
max_pos = 1.0
|
||||
|
||||
return min_pos, max_pos
|
||||
|
||||
def update_curves(self):
|
||||
for idx, element in enumerate(self.data):
|
||||
self.curves[idx].setData(
|
||||
@@ -1004,8 +840,6 @@ class SideviewPlot(QWidget):
|
||||
)
|
||||
|
||||
|
||||
# --------------------------------------------------------- Standalone run ---
|
||||
|
||||
if __name__ == "__main__":
|
||||
from qtpy.QtWidgets import QApplication
|
||||
from bec_widgets.utils.bec_dispatcher import BECDispatcher
|
||||
|
||||
@@ -6,6 +6,7 @@ from qtpy.QtWidgets import (
|
||||
QPushButton, QGroupBox, QComboBox, QApplication, QDoubleSpinBox
|
||||
)
|
||||
from qtpy.QtGui import QFont
|
||||
from qtpy.QtCore import Qt
|
||||
|
||||
class Group(QGroupBox):
|
||||
def __init__(self, label, widgets):
|
||||
@@ -47,9 +48,12 @@ class NumberIndicator(QWidget):
|
||||
layout.setContentsMargins(10, 0, 0, 0)
|
||||
layout.setSpacing(0)
|
||||
self.label = QLabel(label)
|
||||
self.label.setFixedWidth(150)
|
||||
self.label.setFixedWidth(140)
|
||||
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.setFixedWidth(140)
|
||||
layout.addWidget(self.val)
|
||||
self.unit = unit
|
||||
@@ -84,7 +88,9 @@ class InputTextField(QWidget):
|
||||
layout.setContentsMargins(10, 0, 0, 0)
|
||||
layout.setSpacing(0)
|
||||
self.label = QLabel(label)
|
||||
self.label.setFixedWidth(150)
|
||||
self.label.setFixedWidth(140)
|
||||
self.label.setContentsMargins(0, 0, 10, 0)
|
||||
self.label.setWordWrap(True)
|
||||
layout.addWidget(self.label)
|
||||
self.val = QLineEdit()
|
||||
self.val.setPlaceholderText('0')
|
||||
@@ -113,7 +119,9 @@ class InputNumberField(QWidget):
|
||||
layout.setContentsMargins(10, 0, 0, 0)
|
||||
layout.setSpacing(0)
|
||||
self.label = QLabel(label)
|
||||
self.label.setFixedWidth(150)
|
||||
self.label.setFixedWidth(140)
|
||||
self.label.setContentsMargins(0, 0, 10, 0)
|
||||
self.label.setWordWrap(True)
|
||||
layout.addWidget(self.label)
|
||||
self.val = QDoubleSpinBox()
|
||||
self.val.setRange(ll, hl)
|
||||
@@ -204,10 +212,11 @@ class ComboBox(QWidget):
|
||||
layout.setContentsMargins(10, 0, 0, 0)
|
||||
layout.setSpacing(0)
|
||||
self.label = QLabel(label)
|
||||
self.label.setFixedWidth(150)
|
||||
self.label.setFixedWidth(140)
|
||||
self.label.setContentsMargins(0, 0, 10, 0)
|
||||
self.label.setWordWrap(True)
|
||||
layout.addWidget(self.label)
|
||||
self.value = QComboBox()
|
||||
# self.value.setFixedWidth(140)
|
||||
for entry in enums:
|
||||
self.value.addItem(entry)
|
||||
layout.addWidget(self.value)
|
||||
|
||||
Reference in New Issue
Block a user