forked from SwissFEL/c365
210 lines
7.8 KiB
Python
Executable File
210 lines
7.8 KiB
Python
Executable File
from collections import deque
|
|
import random
|
|
import wx
|
|
import numpy as np
|
|
import epics
|
|
|
|
from datetime import datetime
|
|
|
|
#from epics.wx import MotorPanel
|
|
|
|
from slic.gui.widgets import LabeledMathEntry
|
|
from slic.gui.widgets import make_filled_hbox, make_filled_vbox, EXPANDING
|
|
from slic.gui.widgets.plotting import PlotPanel
|
|
|
|
from bstrd import BS, bsstream
|
|
|
|
|
|
# config
|
|
nshots = 100
|
|
qlength = 100
|
|
histlength = 100
|
|
quantile = 0.8
|
|
|
|
# channels
|
|
chname_pbpsint = "SAROP11-PBPS122:INTENSITY"
|
|
chname_pbpsx = "SAROP11-PBPS122:XPOS"
|
|
chname_pbpsy = "SAROP11-PBPS122:YPOS"
|
|
chname_events = "SAR-CVME-TIFALL4:EvtSet"
|
|
|
|
# create channels
|
|
ch_int = BS(chname_pbpsint)
|
|
ch_x = BS(chname_pbpsx)
|
|
ch_y = BS(chname_pbpsy)
|
|
ch_events = BS(chname_events)
|
|
|
|
iso_format = "%Y-%m-%d %H:%M:%S"
|
|
|
|
def filter_outliers(quantile, a):
|
|
low = np.nanquantile(a, 0.5 - quantile/2)
|
|
high = np.nanquantile(a, 0.5 + quantile/2)
|
|
|
|
cond_low = a > low
|
|
cond_high = a < high
|
|
cond = cond_low & cond_high
|
|
|
|
return a[cond]
|
|
|
|
|
|
|
|
class MainPanel(wx.Panel):
|
|
|
|
def __init__(self, parent):
|
|
super().__init__(parent)
|
|
|
|
self.evts = np.empty((nshots,256))
|
|
self.int = np.empty(nshots)
|
|
self.x = np.empty(nshots)
|
|
self.y = np.empty(nshots)
|
|
|
|
self.ints = deque(maxlen=qlength)
|
|
self.intstds = deque(maxlen=qlength)
|
|
self.inthist = deque(maxlen=histlength)
|
|
self.xs = deque(maxlen=qlength)
|
|
self.xstds = deque(maxlen=qlength)
|
|
self.xhist = deque(maxlen=histlength)
|
|
self.ys = deque(maxlen=qlength)
|
|
self.ystds = deque(maxlen=qlength)
|
|
self.yhist = deque(maxlen=histlength)
|
|
|
|
self.plot_ints = plot_ints = PlotPanel(self, figsize=(6,3))
|
|
self.plot_histI = plot_histI = PlotPanel(self, figsize=(2,3))
|
|
self.plot_posXs = plot_posXs = PlotPanel(self, figsize=(6,3))
|
|
self.plot_histX = plot_histX = PlotPanel(self, figsize=(2,3))
|
|
self.plot_posYs = plot_posYs = PlotPanel(self, figsize=(6,3))
|
|
self.plot_histY = plot_histY = PlotPanel(self, figsize=(2,3))
|
|
|
|
plots1 = (plot_ints, plot_histI)
|
|
plots2 = (plot_posXs, plot_histX)
|
|
plots3 = (plot_posYs, plot_histY)
|
|
|
|
hb_plot1 = make_filled_hbox(plots1)
|
|
hb_plot2 = make_filled_hbox(plots2)
|
|
hb_plot3 = make_filled_hbox(plots3)
|
|
|
|
btn_clearQ = wx.Button(self, label="Clear plots")
|
|
btns = (btn_clearQ,)
|
|
hb_btns = make_filled_hbox(btns)
|
|
|
|
widgets = (hb_plot1, hb_plot2, hb_plot3, hb_btns)
|
|
box = make_filled_vbox(widgets, border=1)
|
|
self.SetSizerAndFit(box)
|
|
|
|
btn_clearQ.Bind(wx.EVT_BUTTON, self.on_click_clearQ)
|
|
|
|
self.timer = wx.Timer(self)
|
|
self.Bind(wx.EVT_TIMER, self.on_update, self.timer)
|
|
self.timer.Start(100)
|
|
|
|
|
|
def on_update(self, _event):
|
|
|
|
self.time = datetime.now().strftime(iso_format)
|
|
|
|
self.evts = np.empty((nshots,256))
|
|
self.int = np.empty(nshots, dtype=object)
|
|
self.x = np.empty(nshots, dtype=object)
|
|
self.y = np.empty(nshots, dtype=object)
|
|
|
|
for i in range(nshots):
|
|
tempa = ch_events.get()
|
|
self.evts[i] = tempa
|
|
tempb = ch_int.get()
|
|
self.int[i] = tempb
|
|
tempc = ch_x.get()
|
|
self.x[i] = tempc
|
|
tempd = ch_y.get()
|
|
self.y[i] = tempd
|
|
next(bsstream)
|
|
wx.GetApp().Yield()
|
|
|
|
self.x = filter_outliers(quantile, self.x)
|
|
self.y = filter_outliers(quantile, self.y)
|
|
|
|
self.ints.append(np.mean(self.int))
|
|
self.intstds.append(np.std(self.int))
|
|
self.xs.append(np.mean(self.x))
|
|
self.xstds.append(np.std(self.x))
|
|
self.ys.append(np.mean(self.y))
|
|
self.ystds.append(np.std(self.y))
|
|
|
|
self.inthist.extend(self.int)
|
|
self.xhist.extend(self.x)
|
|
self.yhist.extend(self.y)
|
|
|
|
self.draw_plot()
|
|
|
|
|
|
def draw_plot(self):
|
|
self.plot_ints.clear()
|
|
self.plot_histI.clear()
|
|
self.plot_posXs.clear()
|
|
self.plot_histX.clear()
|
|
self.plot_posYs.clear()
|
|
self.plot_histY.clear()
|
|
|
|
self.plot_ints.set_xlabel('time ago, a.u.')
|
|
self.plot_ints.set_ylabel('intensity, a.u.')
|
|
self.plot_histI.set_xlabel('intensity, a.u.')
|
|
self.plot_histI.set_xlim(-0.1, 3)
|
|
self.plot_posXs.set_xlabel('time ago, a.u.')
|
|
self.plot_posXs.set_ylabel('position X, mm')
|
|
self.plot_histX.set_xlabel('position X, mm')
|
|
self.plot_histX.set_xlim(-0.2, 0.2)
|
|
self.plot_posYs.set_xlabel('time ago, a.u.')
|
|
self.plot_posYs.set_ylabel('position Y, mm')
|
|
self.plot_histY.set_xlabel('position Y, mm')
|
|
self.plot_histY.set_xlim(-0.2, 0.2)
|
|
|
|
self.plot_ints.fill_between(np.arange(0, len(self.ints)), np.asarray(self.intstds)+np.asarray(self.ints), -np.asarray(self.intstds)+np.asarray(self.ints), color='gold')
|
|
self.plot_ints.plot(np.arange(0, len(self.ints)), self.ints, '-', color='orangered')
|
|
self.plot_ints.axhline(y=1, color='k', linestyle="--")
|
|
|
|
self.plot_posXs.fill_between(np.arange(0, len(self.xs)), np.asarray(self.xstds)+np.asarray(self.xs), -np.asarray(self.xstds)+np.asarray(self.xs), color='lightskyblue')
|
|
self.plot_posXs.plot(np.arange(0, len(self.xs)), self.xs, '-', color='dodgerblue')
|
|
self.plot_posXs.axhline(y=0, color='k', linestyle="--")
|
|
|
|
self.plot_posYs.fill_between(np.arange(0, len(self.ys)), np.asarray(self.ystds)+np.asarray(self.ys), -np.asarray(self.ystds)+np.asarray(self.ys), color='lightgreen')
|
|
self.plot_posYs.plot(np.arange(0, len(self.ys)), self.ys, '-', color='green')
|
|
self.plot_posYs.axhline(y=0, color='k', linestyle="--")
|
|
|
|
#if (len(self.int) > 0):
|
|
#self.plot_histI.hist(self.int, facecolor='orangered')#, edgecolor='black')
|
|
|
|
#self.plot_histI.hist(np.ravel(self.inthist), facecolor='orangered', edgecolor='black')
|
|
self.inthist2plot = np.array(self.inthist, dtype=object)
|
|
self.xhist2plot = np.array(self.xhist, dtype=object)
|
|
self.yhist2plot = np.array(self.yhist, dtype=object)
|
|
|
|
self.plot_histI.hist(np.ravel(self.inthist2plot), facecolor='orangered', edgecolor='black')
|
|
self.plot_histI.axvline(x=np.mean(self.inthist), color='k', linestyle="--")
|
|
self.plot_histI.set_title('Intensity: {:.4f} a.u.'.format(np.mean(np.ravel(self.inthist2plot))))
|
|
#self.plot_histX.hist(np.ravel(self.xhist), facecolor='dodgerblue', edgecolor='black')
|
|
self.plot_histX.hist(np.ravel(self.xhist2plot), facecolor='dodgerblue', edgecolor='black')
|
|
self.plot_histX.set_title('Position X: {:.2f} +/- {:.2f} um'.format(np.mean(np.ravel(self.xhist2plot))*1000, np.std(self.xhist)*1000))
|
|
self.plot_histX.axvline(x=np.mean(self.xhist), color='k', linestyle="--")
|
|
#self.plot_histY.hist(np.ravel(self.yhist), facecolor='green', edgecolor='black')
|
|
self.plot_histY.hist(np.ravel(self.yhist2plot), facecolor='green', edgecolor='black')
|
|
self.plot_histY.set_title('Position Y: {:.2f} +/- {:.2f} um'.format(np.mean(np.ravel(self.yhist2plot))*1000, np.std(self.yhist)*1000))
|
|
self.plot_histY.axvline(x=np.mean(self.yhist), color='k', linestyle="--")
|
|
|
|
self.plot_ints.draw()
|
|
self.plot_posXs.draw()
|
|
self.plot_posYs.draw()
|
|
|
|
self.plot_histI.draw()
|
|
self.plot_histX.draw()
|
|
self.plot_histY.draw()
|
|
|
|
print ('{} -- X = {:.2f} -- Y = {:.2f} -- Int = {:.4f}'.format(self.time, np.mean(np.ravel(self.xhist2plot))*1000, np.mean(np.ravel(self.yhist2plot))*1000, np.mean(np.ravel(self.inthist2plot))))
|
|
|
|
|
|
def on_click_clearQ(self, _event):
|
|
|
|
self.ints.clear()
|
|
self.intstds.clear()
|
|
self.xs.clear()
|
|
self.xstds.clear()
|
|
self.ys.clear()
|
|
self.ystds.clear()
|