wip: digital twin
This commit is contained in:
@@ -24,6 +24,9 @@ def calc_surfaces(cfg):
|
||||
index = bl.cm.surface.index(cfg['cm_stripe'])
|
||||
cen = (bl.cm.limOptX[0][index] + bl.cm.limOptX[1][index]) / 2
|
||||
|
||||
if cfg['cm_trx'] is not None:
|
||||
cen = cfg['cm_trx']
|
||||
|
||||
out['cm']['x'] = [cen-w1/2, cen-w2/2, cen+w2/2, cen+w1/2]
|
||||
out['cm']['y'] = [-l/2, l/2, l/2, -l/2]
|
||||
|
||||
@@ -70,6 +73,8 @@ def calc_surfaces(cfg):
|
||||
index = surface.index(stripe)
|
||||
off = (bl.fm.limOptXFlat[0][index] + bl.fm.limOptXFlat[1][index]) / 2
|
||||
r = bl.fm.r[index]
|
||||
if cfg['fm_trx'] is not None:
|
||||
off = cfg['fm_trx']
|
||||
|
||||
widthBeam = 2 * bl.fm.center[1] * np.tan(cfg['h_acc'])
|
||||
|
||||
|
||||
@@ -148,9 +148,8 @@ class DigitalTwin(BECWidget, QWidget):
|
||||
def calc_reality(self):
|
||||
config = self.get_reality_config()
|
||||
beam = calc_sideview(config)
|
||||
self.sideview_plot.data['reality']['x'] = beam['Z']
|
||||
self.sideview_plot.data['reality']['y'] = beam['Y']
|
||||
self.sideview_plot.update_curves()
|
||||
data = {'x': beam['Z'], 'y': beam['Y']}
|
||||
self.sideview_plot.update_curves('reality', data)
|
||||
surfaces = calc_surfaces(config)
|
||||
self.surface_plots.update_surfaces(scene='reality', data=surfaces)
|
||||
|
||||
@@ -233,11 +232,13 @@ class DigitalTwin(BECWidget, QWidget):
|
||||
'v_acc' : self.input.sldi_vacc.value() * 1e-3,
|
||||
'cm_pitch' : -self.input.cm_pitch.value() * 1e-3,
|
||||
'cm_stripe' : self.input.cm_stripe.currentText(),
|
||||
'cm_trx' : None,
|
||||
'mo1_mode' : self.input.mo1_mode.currentText(),
|
||||
'mo1_xtal' : self.input.mo1_xtal.currentText(),
|
||||
'mo1_bragg' : self.bragg_angle,
|
||||
'fm_pitch' : -self.input.fm_pitch.value() * 1e-3,
|
||||
'fm_stripe' : self.input.fm_stripe.currentText(),
|
||||
'fm_trx' : None,
|
||||
'fm_gain_height' : 1,
|
||||
'smpl' : self.input.smpl.value(),
|
||||
}
|
||||
@@ -277,11 +278,13 @@ class DigitalTwin(BECWidget, QWidget):
|
||||
'v_acc' : v_acc,
|
||||
'cm_pitch' : cm_pitch,
|
||||
'cm_stripe' : cm_stripe,
|
||||
'cm_trx' : cm_trx,
|
||||
'mo1_mode' : mo1_mode,
|
||||
'mo1_xtal' : mo1_bragg['mo1_bragg_crystal_current_xtal_string']['value'],
|
||||
'mo1_bragg' : mo1_bragg['mo1_bragg_angle']['value']/180*np.pi,
|
||||
'fm_pitch' : fm_pitch_real,
|
||||
'fm_stripe' : fm_stripe,
|
||||
'fm_trx' : fm_trx,
|
||||
'fm_gain_height' : 1,
|
||||
'smpl' : self.dev.ot_es1_trz.read()['ot_es1_trz']['value'],
|
||||
}
|
||||
@@ -291,9 +294,8 @@ class DigitalTwin(BECWidget, QWidget):
|
||||
@SafeSlot()
|
||||
def calc_assistant_sideview(self):
|
||||
beam = calc_sideview(self.get_assistant_config())
|
||||
self.sideview_plot.data['assistant']['x'] = beam['Z']
|
||||
self.sideview_plot.data['assistant']['y'] = beam['Y']
|
||||
self.sideview_plot.update_curves()
|
||||
data = {'x': beam['Z'], 'y': beam['Y']}
|
||||
self.sideview_plot.update_curves('assistant', data)
|
||||
|
||||
@SafeSlot()
|
||||
def calc_assistant_surfaces(self):
|
||||
@@ -453,8 +455,8 @@ class InputPanel(QWidget):
|
||||
|
||||
# Focusing Mirror
|
||||
self.fm_stripe = ComboBox('fm_stripe', 'Stripe', ['Rh (toroid)', 'Rh (flat)', 'Pt (toroid)', 'Pt (flat)'])
|
||||
self.fm_pitch_ideal = NumberIndicator('Ideal Pitch', 'mrad', decimals=3)
|
||||
self.fm_pitch = InputNumberField('fm_pitch', 'Pitch [mrad]', init=-2.391, decimals=3, single_step=0.01, ll=-10, hl=2)
|
||||
self.fm_pitch_ideal = NumberIndicator('Ideal Incidence Angle', 'mrad', decimals=3)
|
||||
self.fm_pitch = InputNumberField('fm_pitch', 'Incidence Angle [mrad]', init=-2.391, decimals=3, single_step=0.01, ll=-10, hl=2)
|
||||
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(
|
||||
@@ -656,11 +658,11 @@ class MoverPanel(QWidget):
|
||||
self._layout .addWidget(self.mover_group)
|
||||
self._layout .addStretch()
|
||||
|
||||
class SurfacePlots(QWidget):
|
||||
class SurfacePlots(BECWidget, QWidget):
|
||||
"""Plot widget with two curves and legend."""
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
def __init__(self, parent=None, *arg, **kwargs):
|
||||
super().__init__(parent=parent, theme_update=True, *arg, **kwargs)
|
||||
self._layout = QHBoxLayout(self)
|
||||
|
||||
self.surfaces = {
|
||||
@@ -685,16 +687,9 @@ class SurfacePlots(QWidget):
|
||||
'fm': {},
|
||||
}
|
||||
|
||||
app = QApplication.instance()
|
||||
theme = app.theme.theme # type: ignore
|
||||
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)
|
||||
self.color_impenetrable = (0, 0, 0)
|
||||
self.colors = [(255, 255, 0), (255, 0, 255)]
|
||||
self.text_color = (255, 255, 255)
|
||||
|
||||
# Create plot widgets
|
||||
for name, widget in self.plots.items():
|
||||
@@ -739,8 +734,57 @@ class SurfacePlots(QWidget):
|
||||
)
|
||||
self.plots[name][scene].setZValue(z_value)
|
||||
|
||||
self.walls = []
|
||||
self.texts = []
|
||||
|
||||
self.plot_walls()
|
||||
|
||||
self.apply_theme()
|
||||
|
||||
def apply_theme(self, theme=None):
|
||||
|
||||
if theme is None:
|
||||
app = QApplication.instance()
|
||||
theme = app.theme.theme # type: ignore
|
||||
|
||||
bg_color = pg.getConfigOption("background")
|
||||
fg_color = pg.getConfigOption("foreground")
|
||||
for _, plot in self.plots.items():
|
||||
# Background
|
||||
plot['widget'].setBackground(bg_color)
|
||||
# Axes (tick marks, tick labels, axis line)
|
||||
for axis in ["left", "bottom", "right", "top"]:
|
||||
ax = plot['widget'].getAxis(axis)
|
||||
ax.setPen(pg.mkPen(color=fg_color))
|
||||
ax.setTextPen(pg.mkPen(color=fg_color))
|
||||
|
||||
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)
|
||||
|
||||
for idx, scene in enumerate(self.surfaces):
|
||||
for name, device in self.surfaces[scene].items():
|
||||
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)
|
||||
else:
|
||||
brush = QBrush(QColor(*self.colors[idx], 255))
|
||||
pen = pg.mkPen(QColor(*self.colors[idx], 255), width=1)
|
||||
self.plots[name][scene].setPen(pen)
|
||||
self.plots[name][scene].setBrush(brush)
|
||||
|
||||
for wall in self.walls:
|
||||
wall.setPen(pg.mkPen(color=self.color_impenetrable, width=2))
|
||||
wall.setBrush(pg.QtGui.QBrush(pg.QtGui.QColor(*self.color_impenetrable))) # pylint: disable=E1101
|
||||
|
||||
for text in self.texts:
|
||||
text.setColor(self.text_color)
|
||||
|
||||
def plot_walls(self):
|
||||
|
||||
def plot_mirror_stripe(widget, surface, limOptX, limOptY):
|
||||
@@ -758,6 +802,8 @@ class SurfacePlots(QWidget):
|
||||
widget.addItem(text)
|
||||
text.setPos((hx+lx)/2, (hy+ly)/2)
|
||||
text.setZValue(10)
|
||||
self.walls.append(rect)
|
||||
self.texts.append(text)
|
||||
|
||||
def plot_mono_surface(widget, xtal, xtalWidth, xtalOffsetX, xtalLength):
|
||||
for sf, w, offx, len in zip(xtal, xtalWidth, xtalOffsetX, xtalLength):
|
||||
@@ -774,6 +820,8 @@ class SurfacePlots(QWidget):
|
||||
widget.addItem(text)
|
||||
text.setPos(offx, 0)
|
||||
text.setZValue(10)
|
||||
self.walls.append(rect)
|
||||
self.texts.append(text)
|
||||
|
||||
for name, plot in self.plots.items():
|
||||
if name in 'cm':
|
||||
@@ -798,11 +846,11 @@ class SurfacePlots(QWidget):
|
||||
y = np.array(device['y'] + [device['y'][0]]) if len(device['y']) != 0 else np.array([])
|
||||
plot.setData(x=x, y=y)
|
||||
|
||||
class SideviewPlot(QWidget):
|
||||
class SideviewPlot(BECWidget, QWidget):
|
||||
"""Plot widget with two curves and legend."""
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
def __init__(self, parent=None, *arg, **kwargs):
|
||||
super().__init__(parent=parent, theme_update=True, *arg, **kwargs)
|
||||
self._layout = QVBoxLayout(self)
|
||||
# self._layout.setSizeConstraint(QLayout.SetFixedSize) # type: ignore
|
||||
|
||||
@@ -810,36 +858,29 @@ class SideviewPlot(QWidget):
|
||||
self.plot_widget.getAxis('bottom').enableAutoSIPrefix(False)
|
||||
self.plot_widget.addLegend()
|
||||
|
||||
app = QApplication.instance()
|
||||
theme = app.theme.theme # type: ignore
|
||||
if theme == "light":
|
||||
self.color_impenetrable = (30, 30, 30)
|
||||
self.colors = [(26, 111, 173), (212, 83, 10)]
|
||||
else: # dark theme
|
||||
self.color_impenetrable = (220, 220, 220)
|
||||
self.colors = [(79, 163, 224), (240, 128, 60)]
|
||||
|
||||
self.curves = []
|
||||
self.color_impenetrable = (0, 0, 0)
|
||||
self.colors = [(255, 255, 0), (255, 0, 255)]
|
||||
|
||||
self.data = {
|
||||
'assistant': {'x': [0, 1000, 2000], 'y': [0, 20, 30]},
|
||||
'reality': {'x': [0, 1000, 2000], 'y': [0, 15, 50]},
|
||||
}
|
||||
|
||||
self.plots = {}
|
||||
|
||||
self.pipes = []
|
||||
self.walls = []
|
||||
|
||||
for idx, name in enumerate(self.data.keys()):
|
||||
if name in "assistant":
|
||||
for idx, scene in enumerate(self.data.keys()):
|
||||
if scene in "assistant":
|
||||
pen = pg.mkPen(color=self.colors[idx], width=2, style=Qt.DashLine)
|
||||
else:
|
||||
pen = pg.mkPen(color=self.colors[idx], width=2)
|
||||
self.curves.append(
|
||||
self.plot_widget.plot(
|
||||
[],
|
||||
[],
|
||||
pen=pen,
|
||||
name=name,
|
||||
)
|
||||
self.plots[scene] = self.plot_widget.plot(
|
||||
[],
|
||||
[],
|
||||
pen=pen,
|
||||
name=scene,
|
||||
)
|
||||
|
||||
self.plot_group = Group(
|
||||
@@ -862,7 +903,50 @@ class SideviewPlot(QWidget):
|
||||
|
||||
self.plot_vacuum_pipes()
|
||||
self.plot_walls()
|
||||
self.update_curves()
|
||||
|
||||
self.apply_theme()
|
||||
|
||||
def apply_theme(self, theme=None):
|
||||
|
||||
if theme is None:
|
||||
app = QApplication.instance()
|
||||
theme = app.theme.theme # type: ignore
|
||||
|
||||
bg_color = pg.getConfigOption("background")
|
||||
fg_color = pg.getConfigOption("foreground")
|
||||
# Background
|
||||
self.plot_widget.setBackground(bg_color)
|
||||
# Axes (tick marks, tick labels, axis line)
|
||||
for axis in ["left", "bottom", "right", "top"]:
|
||||
ax = self.plot_widget.getAxis(axis)
|
||||
ax.setPen(pg.mkPen(color=fg_color))
|
||||
ax.setTextPen(pg.mkPen(color=fg_color))
|
||||
|
||||
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)
|
||||
|
||||
for idx, scene in enumerate(self.data):
|
||||
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)
|
||||
else:
|
||||
brush = QBrush(QColor(*self.colors[idx], 255))
|
||||
pen = pg.mkPen(QColor(*self.colors[idx], 255), width=1)
|
||||
self.plots[scene].setPen(pen)
|
||||
self.plots[scene].setBrush(brush)
|
||||
|
||||
for wall in self.walls:
|
||||
wall.setPen(pg.mkPen(color=self.color_impenetrable, width=2))
|
||||
wall.setBrush(pg.QtGui.QBrush(pg.QtGui.QColor(*self.color_impenetrable))) # pylint: disable=E1101
|
||||
|
||||
for pipe in self.pipes:
|
||||
pipe.setPen(pg.mkPen(color=self.color_impenetrable, width=2))
|
||||
|
||||
def plot_vacuum_pipes(self):
|
||||
for i, _ in enumerate(bl.vacuum_pipes.center):
|
||||
@@ -890,13 +974,12 @@ class SideviewPlot(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))
|
||||
self.plot_widget.addItem(rect)
|
||||
self.walls.append(rect)
|
||||
|
||||
def update_curves(self):
|
||||
for idx, element in enumerate(self.data):
|
||||
self.curves[idx].setData(
|
||||
x=np.array(self.data[element]['x']),
|
||||
y=np.array(self.data[element]['y']),
|
||||
)
|
||||
def update_curves(self, scene, data):
|
||||
self.data[scene] = data
|
||||
plot = self.plots[scene]
|
||||
plot.setData(x=self.data[scene]['x'], y=self.data[scene]['y'])
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
@@ -911,4 +994,4 @@ if __name__ == "__main__":
|
||||
|
||||
# win.resize(1000, 800)
|
||||
win.show()
|
||||
sys.exit(app.exec_())
|
||||
sys.exit(app.exec_())
|
||||
|
||||
Reference in New Issue
Block a user