Move tools to ecmccomgui. Update readmes

This commit is contained in:
Anders Sandstrom
2020-10-13 09:36:01 +02:00
parent ecbf760a51
commit 6dbdc97957
6 changed files with 10 additions and 816 deletions

View File

@@ -273,6 +273,8 @@ static.sineval:=sin(2*pi*${FREQ=5}*static.time);
### FFT GUI (FFT and rawdata plots + controls)
A simple tool, [ecmcFFTMainGui.py](tools/ecmcFFTMainGui.py), to visualize the calculated spectrum, rawdata and also plugin controls can be found in the tools directory. The GUI connects to the plugin records over pypics framwork.
The gui are included in the ecmccomgui repo:
https://github.com/anderssandstrom/ecmccomgui
Example: ecmcFFTMainGui.py help printout
```

8
tools/README.md Normal file
View File

@@ -0,0 +1,8 @@
# FFT tools
## GUI
A python gui for vizualization and control of the FFT plugin can be found in the ecmccomgui repo:
https://github.com/anderssandstrom/ecmccomgui
![ecmcFFTMainGui.py](docs/gui/ecmcFFTMainGui.png)

View File

@@ -1,131 +0,0 @@
#*************************************************************************
# Copyright (c) 2020 European Spallation Source ERIC
# ecmc is distributed subject to a Software License Agreement found
# in file LICENSE that is included with this distribution.
#
# ecmcArrayGui.py
#
# Created on: October 8, 2020
# Author: Anders Sandström
#
# Plots two waveforms (y vs time) updates for each callback on the y-pv
#
#*************************************************************************
import sys
import epics
from PyQt5.QtWidgets import *
from PyQt5 import QtWidgets
from PyQt5.QtCore import *
from PyQt5.QtGui import *
import numpy as np
import matplotlib
matplotlib.use("Qt5Agg")
from matplotlib.figure import Figure
from matplotlib.animation import TimedAnimation
from matplotlib.lines import Line2D
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar
import matplotlib.pyplot as plt
import threading
class comSignal(QObject):
data_signal = pyqtSignal(object)
class ecmcArrayGui(QtWidgets.QDialog):
def __init__(self,yname=None):
super(ecmcArrayGui, self).__init__()
self.comSignalY = comSignal()
self.comSignalY.data_signal.connect(self.callbackFuncY)
self.pause = 0
self.spectY = None
self.figure = plt.figure()
self.plotted_line = None
self.ax = None
self.canvas = FigureCanvas(self.figure)
self.toolbar = NavigationToolbar(self.canvas, self)
self.pauseBtn = QPushButton(text = 'pause')
self.pauseBtn.setFixedSize(100, 50)
self.pauseBtn.clicked.connect(self.pauseBtnAction)
self.pauseBtn.setStyleSheet("background-color: green")
self.pvNameY = yname # "IOC_TEST:Plugin-FFT0-Raw-Data-Act"
self.connectPvs() # Epics
self.setGeometry(300, 300, 900, 700)
self.setWindowTitle("ecmc Array plot: " + self.pvNameY)
layout = QVBoxLayout()
layout.addWidget(self.toolbar)
layout.addWidget(self.canvas)
layout.addWidget(self.pauseBtn)
self.setLayout(layout)
return
def connectPvs(self):
if self.pvNameY is None:
raise RuntimeError("pvname y must not be 'None'")
if len(self.pvNameY)==0:
raise RuntimeError("pvname y must not be ''")
self.pvY = epics.PV(self.pvNameY)
#print('self.pvY: ' + self.pvY.info)
self.pvY.add_callback(self.onChangePvY)
QCoreApplication.processEvents()
def onChangePvY(self,pvname=None, value=None, char_value=None,timestamp=None, **kw):
self.comSignalY.data_signal.emit(value)
def pauseBtnAction(self):
self.pause = not self.pause
if self.pause:
self.pauseBtn.setStyleSheet("background-color: red");
else:
self.pauseBtn.setStyleSheet("background-color: green");
self.comSignalY.data_signal.emit(self.spectY)
return
def callbackFuncY(self, value):
if(np.size(value)) > 0:
self.spectY = value
self.plotSpect()
return
def plotSpect(self):
if self.pause:
return
if self.spectY is None:
return
# create an axis
if self.ax is None:
self.ax = self.figure.add_subplot(111)
# plot data
if self.plotted_line is not None:
self.plotted_line.remove()
self.plotted_line, = self.ax.plot(self.spectY, 'b*-')
self.ax.grid(True)
plt.xlabel('Time []')
plt.ylabel(self.pvNameY +' [' + self.pvY.units + ']')
# refresh canvas
self.canvas.draw()
self.ax.autoscale(enable=True)
def printOutHelp():
print("ecmcArrayGui: Plots waveforms data (updates on data callback). ")
print("python ecmcArrayGui.py <y.pv>")
print("example: python ecmcArrayGui.py IOC_TEST:Plugin-FFT0-Raw-Data-Act")
if __name__ == "__main__":
import sys
if len(sys.argv)!=2:
printOutHelp()
sys.exit()
yname=sys.argv[1]
app = QtWidgets.QApplication(sys.argv)
window=ecmcArrayGui(yname=yname)
window.show()
sys.exit(app.exec_())

View File

@@ -1,157 +0,0 @@
#*************************************************************************
# Copyright (c) 2020 European Spallation Source ERIC
# ecmc is distributed subject to a Software License Agreement found
# in file LICENSE that is included with this distribution.
#
# ecmcFFTGui.py
#
# Created on: October 6, 2020
# Author: Anders Sandström
#
# Plots two waveforms (x vs y) updates for each callback on the y-pv
#
#*************************************************************************
import sys
import epics
from PyQt5.QtWidgets import *
from PyQt5 import QtWidgets
from PyQt5.QtCore import *
from PyQt5.QtGui import *
import numpy as np
import matplotlib
matplotlib.use("Qt5Agg")
from matplotlib.figure import Figure
from matplotlib.animation import TimedAnimation
from matplotlib.lines import Line2D
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar
import matplotlib.pyplot as plt
import threading
class comSignal(QObject):
data_signal = pyqtSignal(object)
class ecmcFFTGui(QtWidgets.QDialog):
def __init__(self,xname=None,yname=None):
super(ecmcFFTGui, self).__init__()
self.comSignalX = comSignal()
self.comSignalX.data_signal.connect(self.callbackFuncX)
self.comSignalY = comSignal()
self.comSignalY.data_signal.connect(self.callbackFuncY)
self.pause = 0
self.spectX = None
self.spectY = None
self.figure = plt.figure()
self.plotted_line = None
self.ax = None
self.canvas = FigureCanvas(self.figure)
self.toolbar = NavigationToolbar(self.canvas, self)
self.pauseBtn = QPushButton(text = 'pause')
self.pauseBtn.setFixedSize(100, 50)
self.pauseBtn.clicked.connect(self.pauseBtnAction)
self.pauseBtn.setStyleSheet("background-color: green");
self.pvNameY = yname # "IOC_TEST:Plugin-FFT1-Spectrum-Amp-Act"
self.pvNameX = xname # "IOC_TEST:Plugin-FFT1-Spectrum-X-Axis-Act"
self.connectPvs() # Epics
self.setGeometry(300, 300, 900, 700)
self.setWindowTitle("ecmc FFT plot: " + self.pvNameY + ' vs ' + self.pvNameX)
layout = QVBoxLayout()
layout.addWidget(self.toolbar)
layout.addWidget(self.canvas)
layout.addWidget(self.pauseBtn)
self.setLayout(layout)
return
def connectPvs(self):
if self.pvNameX is None:
raise RuntimeError("pvname X must not be 'None'")
if len(self.pvNameX)==0:
raise RuntimeError("pvname X must not be ''")
if self.pvNameY is None:
raise RuntimeError("pvname y must not be 'None'")
if len(self.pvNameY)==0:
raise RuntimeError("pvname y must not be ''")
self.pvX = epics.PV(self.pvNameX)
#print('self.pvX: ' + self.pvX.info)
self.pvY = epics.PV(self.pvNameY)
#print('self.pvY: ' + self.pvY.info)
self.pvX.add_callback(self.onChangePvX)
self.pvY.add_callback(self.onChangePvY)
QCoreApplication.processEvents()
def onChangePvX(self,pvname=None, value=None, char_value=None,timestamp=None, **kw):
self.comSignalX.data_signal.emit(value)
def onChangePvY(self,pvname=None, value=None, char_value=None,timestamp=None, **kw):
self.comSignalY.data_signal.emit(value)
def pauseBtnAction(self):
self.pause = not self.pause
if self.pause:
self.pauseBtn.setStyleSheet("background-color: red");
else:
self.pauseBtn.setStyleSheet("background-color: green");
self.comSignalY.data_signal.emit(self.spectY)
return
def callbackFuncX(self, value):
if(np.size(value)) > 0:
self.spectX = value
self.xDataValid = 1
return
def callbackFuncY(self, value):
if(np.size(value)) > 0:
self.spectY = value
self.plotSpect()
return
def plotSpect(self):
if self.pause:
return
if self.spectX is None:
return
if self.spectY is None:
return
# create an axis
if self.ax is None:
self.ax = self.figure.add_subplot(111)
# plot data
if self.plotted_line is not None:
self.plotted_line.remove()
self.plotted_line, = self.ax.plot(self.spectX,self.spectY, 'b*-')
self.ax.grid(True)
plt.xlabel(self.pvNameX +' [' + self.pvX.units + ']')
plt.ylabel(self.pvNameY +' [' + self.pvY.units + ']')
# refresh canvas
self.canvas.draw()
self.ax.autoscale(enable=False)
def printOutHelp():
print("ecmcFFTGui: Plots waveforms of FFT data (updates on Y data callback). ")
print("python ecmcFFTGui.py <x.pv> <y.pv>")
print("example: python ecmcFFTGui.py IOC_TEST:Plugin-FFT1-Spectrum-X-Axis-Act IOC_TEST:Plugin-FFT1-Spectrum-Amp-Act")
if __name__ == "__main__":
import sys
if len(sys.argv)!=3:
printOutHelp()
sys.exit()
xname=sys.argv[1]
yname=sys.argv[2]
app = QtWidgets.QApplication(sys.argv)
window=ecmcFFTGui(xname=xname,yname=yname)
window.show()
sys.exit(app.exec_())

View File

@@ -1,528 +0,0 @@
#*************************************************************************
# Copyright (c) 2020 European Spallation Source ERIC
# ecmc is distributed subject to a Software License Agreement found
# in file LICENSE that is included with this distribution.
#
# ecmcFFTMainGui.py
#
# Created on: October 6, 2020
# Author: Anders Sandström
#
# Plots two waveforms (x vs y) updates for each callback on the y-pv
#
#*************************************************************************
import sys
import epics
from PyQt5.QtWidgets import *
from PyQt5 import QtWidgets
from PyQt5.QtCore import *
from PyQt5.QtGui import *
import numpy as np
import matplotlib
matplotlib.use("Qt5Agg")
from matplotlib.figure import Figure
from matplotlib.animation import TimedAnimation
from matplotlib.lines import Line2D
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar
import matplotlib.pyplot as plt
import threading
# FFT object pvs <prefix>Plugin-FFT<fftPluginId>-<suffixname>
# IOC_TEST:Plugin-FFT0-stat
# IOC_TEST:Plugin-FFT0-NFFT x
# IOC_TEST:Plugin-FFT0-Mode-RB x
# IOC_TEST:Plugin-FFT0-SampleRate-Act x
# IOC_TEST:Plugin-FFT0-Enable x
# IOC_TEST:Plugin-FFT0-Trigg x
# IOC_TEST:Plugin-FFT0-Source x
# IOC_TEST:Plugin-FFT0-Raw-Data-Act x
# IOC_TEST:Plugin-FFT0-PreProc-Data-Act
# IOC_TEST:Plugin-FFT0-Spectrum-Amp-Act x
# IOC_TEST:Plugin-FFT0-Spectrum-X-Axis-Act x
class comSignal(QObject):
data_signal = pyqtSignal(object)
class ecmcFFTMainGui(QtWidgets.QDialog):
def __init__(self,prefix=None,fftPluginId=None):
super(ecmcFFTMainGui, self).__init__()
self.offline = False
self.pvPrefixStr = prefix
self.pvPrefixOrigStr = prefix # save for restore after open datafile
self.fftPluginId = fftPluginId
self.fftPluginOrigId = fftPluginId
self.allowSave = False
if prefix is None or fftPluginId is None:
self.offline = True
self.pause = True
self.enable = False
else:
self.buildPvNames()
self.offline = False
self.pause = False
# Callbacks through signals
self.comSignalSpectX = comSignal()
self.comSignalSpectX.data_signal.connect(self.callbackFuncSpectX)
self.comSignalSpectY = comSignal()
self.comSignalSpectY.data_signal.connect(self.callbackFuncSpectY)
self.comSignalRawData = comSignal()
self.comSignalRawData.data_signal.connect(self.callbackFuncrawData)
self.comSignalEnable = comSignal()
self.comSignalEnable.data_signal.connect(self.callbackFuncEnable)
self.comSignalMode = comSignal()
self.comSignalMode.data_signal.connect(self.callbackFuncMode)
self.pause = 0
# Data
self.spectX = None
self.spectY = None
self.rawdataY = None
self.rawdataX = None
self.enable = None
self.pvMode = None
self.createWidgets()
self.connectPvs()
self.setStatusOfWidgets()
return
def createWidgets(self):
self.figure = plt.figure()
self.plottedLineSpect = None
self.plottedLineRaw = None
self.axSpect = None
self.axRaw = None
self.canvas = FigureCanvas(self.figure)
self.toolbar = NavigationToolbar(self.canvas, self)
self.pauseBtn = QPushButton(text = 'pause')
self.pauseBtn.setFixedSize(100, 50)
self.pauseBtn.clicked.connect(self.pauseBtnAction)
self.pauseBtn.setStyleSheet("background-color: green")
self.openBtn = QPushButton(text = 'open data')
self.openBtn.setFixedSize(100, 50)
self.openBtn.clicked.connect(self.openBtnAction)
self.saveBtn = QPushButton(text = 'save data')
self.saveBtn.setFixedSize(100, 50)
self.saveBtn.clicked.connect(self.saveBtnAction)
self.enableBtn = QPushButton(text = 'enable FFT')
self.enableBtn.setFixedSize(100, 50)
self.enableBtn.clicked.connect(self.enableBtnAction)
self.triggBtn = QPushButton(text = 'trigg FFT')
self.triggBtn.setFixedSize(100, 50)
self.triggBtn.clicked.connect(self.triggBtnAction)
self.modeCombo = QComboBox()
self.modeCombo.setFixedSize(100, 50)
self.modeCombo.currentIndexChanged.connect(self.newModeIndexChanged)
self.modeCombo.addItem("CONT")
self.modeCombo.addItem("TRIGG")
# Fix layout
self.setGeometry(300, 300, 900, 700)
layoutVert = QVBoxLayout()
layoutVert.addWidget(self.toolbar)
layoutVert.addWidget(self.canvas)
layoutControl = QHBoxLayout()
layoutControl.addWidget(self.pauseBtn)
layoutControl.addWidget(self.enableBtn)
layoutControl.addWidget(self.triggBtn)
layoutControl.addWidget(self.modeCombo)
layoutControl.addWidget(self.saveBtn)
layoutControl.addWidget(self.openBtn)
frameControl = QFrame(self)
frameControl.setFixedHeight(70)
frameControl.setLayout(layoutControl)
layoutVert.addWidget(frameControl)
self.setLayout(layoutVert)
def setStatusOfWidgets(self):
self.saveBtn.setEnabled(self.allowSave)
if self.offline:
self.enableBtn.setStyleSheet("background-color: grey")
self.enableBtn.setEnabled(False)
self.pauseBtn.setStyleSheet("background-color: grey")
self.pauseBtn.setEnabled(False)
self.modeCombo.setEnabled(False)
self.triggBtn.setEnabled(False)
self.setWindowTitle("ecmc FFT Main plot: Offline")
else:
self.modeCombo.setEnabled(True)
# Check actual value of pvs
if(self.pvEnable.get()>0):
self.enableBtn.setStyleSheet("background-color: green")
self.enable = True
else:
self.enableBtn.setStyleSheet("background-color: red")
self.enable = False
self.sourceStr = self.pvSource.get(as_string=True)
self.sampleRate = self.pvSampleRate.get()
self.NFFT = self.pvNFFT.get()
self.mode = self.pvMode.get()
self.modeStr = "NO_MODE"
self.triggBtn.setEnabled(False) # Only enable if mode = TRIGG = 2
if self.mode == 1:
self.modeStr = "CONT"
self.modeCombo.setCurrentIndex(self.mode-1) # Index starta t zero
if self.mode == 2:
self.modeStr = "TRIGG"
self.triggBtn.setEnabled(True)
self.modeCombo.setCurrentIndex(self.mode-1) # Index starta t zero
self.setWindowTitle("ecmc FFT Main plot: prefix=" + self.pvPrefixStr + " , fftId=" + str(self.fftPluginId) +
", source=" + self.sourceStr + ", rate=" + str(self.sampleRate) +
", nfft=" + str(self.NFFT))
def buildPvNames(self):
# Pv names based on structure: <prefix>Plugin-FFT<fftPluginId>-<suffixname>
self.pvNameSpectY = self.buildPvName('Spectrum-Amp-Act') # "IOC_TEST:Plugin-FFT1-Spectrum-Amp-Act"
self.pvNameSpectX = self.buildPvName('Spectrum-X-Axis-Act') # "IOC_TEST:Plugin-FFT1-Spectrum-X-Axis-Act"
self.pvNameRawDataY = self.buildPvName('Raw-Data-Act') # IOC_TEST:Plugin-FFT0-Raw-Data-Act
self.pvnNameEnable = self.buildPvName('Enable') # IOC_TEST:Plugin-FFT0-Enable
self.pvnNameTrigg = self.buildPvName('Trigg') # IOC_TEST:Plugin-FFT0-Trigg
self.pvnNameSource = self.buildPvName('Source') # IOC_TEST:Plugin-FFT0-Source
self.pvnNameSampleRate = self.buildPvName('SampleRate-Act') # IOC_TEST:Plugin-FFT0-SampleRate-Act
self.pvnNameNFFT = self.buildPvName('NFFT') # IOC_TEST:Plugin-FFT0-NFFT
self.pvnNameMode = self.buildPvName('Mode-RB') # IOC_TEST:Plugin-FFT0-Mode-RB
def buildPvName(self, suffixname):
return self.pvPrefixStr + 'Plugin-FFT' + str(self.fftPluginId) + '-' + suffixname
def connectPvs(self):
if self.offline:
return
if self.pvNameSpectX is None:
raise RuntimeError("pvname X spect must not be 'None'")
if len(self.pvNameSpectX)==0:
raise RuntimeError("pvname X spect must not be ''")
if self.pvNameSpectY is None:
raise RuntimeError("pvname y spect must not be 'None'")
if len(self.pvNameSpectY)==0:
raise RuntimeError("pvname y spect must not be ''")
if self.pvNameRawDataY is None:
raise RuntimeError("pvname raw data must not be 'None'")
if len(self.pvNameRawDataY)==0:
raise RuntimeError("pvname raw data must not be ''")
if self.pvnNameEnable is None:
raise RuntimeError("pvname enable must not be 'None'")
if len(self.pvnNameEnable)==0:
raise RuntimeError("pvname enable must not be ''")
if self.pvnNameTrigg is None:
raise RuntimeError("pvname trigg must not be 'None'")
if len(self.pvnNameTrigg)==0:
raise RuntimeError("pvname trigg must not be ''")
if self.pvnNameSource is None:
raise RuntimeError("pvname source must not be 'None'")
if len(self.pvnNameSource)==0:
raise RuntimeError("pvname source must not be ''")
if self.pvnNameSampleRate is None:
raise RuntimeError("pvname sample rate must not be 'None'")
if len(self.pvnNameSampleRate)==0:
raise RuntimeError("pvname sample rate must not be ''")
if self.pvnNameNFFT is None:
raise RuntimeError("pvname NFFT must not be 'None'")
if len(self.pvnNameNFFT)==0:
raise RuntimeError("pvname NFFT must not be ''")
if self.pvnNameMode is None:
raise RuntimeError("pvname mode must not be 'None'")
if len(self.pvnNameMode)==0:
raise RuntimeError("pvname mode must not be ''")
self.pvSpectX = epics.PV(self.pvNameSpectX)
self.pvSpectY = epics.PV(self.pvNameSpectY)
self.pvRawData = epics.PV(self.pvNameRawDataY)
self.pvEnable = epics.PV(self.pvnNameEnable)
self.pvTrigg = epics.PV(self.pvnNameTrigg)
self.pvSource = epics.PV(self.pvnNameSource)
self.pvSampleRate = epics.PV(self.pvnNameSampleRate)
self.pvNFFT = epics.PV(self.pvnNameNFFT)
self.pvMode = epics.PV(self.pvnNameMode)
self.pvSpectX.add_callback(self.onChangePvSpectX)
self.pvSpectY.add_callback(self.onChangePvSpectY)
self.pvRawData.add_callback(self.onChangePvrawData)
self.pvEnable.add_callback(self.onChangePvEnable)
self.pvMode.add_callback(self.onChangePvMode)
QCoreApplication.processEvents()
###### Pv monitor callbacks
def onChangePvMode(self,pvname=None, value=None, char_value=None,timestamp=None, **kw):
if self.pause:
return
self.comSignalMode.data_signal.emit(value)
def onChangePvEnable(self,pvname=None, value=None, char_value=None,timestamp=None, **kw):
if self.pause:
return
self.comSignalEnable.data_signal.emit(value)
def onChangePvSpectX(self,pvname=None, value=None, char_value=None,timestamp=None, **kw):
if self.pause:
return
self.comSignalSpectX.data_signal.emit(value)
def onChangePvSpectY(self,pvname=None, value=None, char_value=None,timestamp=None, **kw):
if self.pause:
return
self.comSignalSpectY.data_signal.emit(value)
def onChangePvrawData(self,pvname=None, value=None, char_value=None,timestamp=None, **kw):
if self.pause:
return
self.comSignalRawData.data_signal.emit(value)
###### Signal callbacks
def callbackFuncMode(self, value):
if value < 1 or value> 2:
self.modeStr = "NO_MODE"
print('callbackFuncMode: Error Invalid mode.')
return
self.mode = value
self.modeCombo.setCurrentIndex(self.mode-1) # Index starta t zero
if self.mode == 1:
self.modeStr = "CONT"
self.triggBtn.setEnabled(False) # Only enable if mode = TRIGG = 2
if self.mode == 2:
self.modeStr = "TRIGG"
self.triggBtn.setEnabled(True)
return
def callbackFuncEnable(self, value):
self.enable = value
if self.enable:
self.enableBtn.setStyleSheet("background-color: green")
else:
self.enableBtn.setStyleSheet("background-color: red")
return
def callbackFuncSpectX(self, value):
if(np.size(value)) > 0:
self.spectX = value
self.xDataValid = 1
return
def callbackFuncSpectY(self, value):
if(np.size(value)) > 0:
self.spectY = value
self.plotSpect()
return
def callbackFuncrawData(self, value):
if(np.size(value)) > 0:
if self.rawdataX is None or np.size(value) != np.size(self.rawdataY):
self.rawdataX = np.arange(-np.size(value)/self.sampleRate, 0, 1/self.sampleRate)
self.rawdataY = value
self.plotRaw()
return
###### Widget callbacks
def pauseBtnAction(self):
self.pause = not self.pause
if self.pause:
self.pauseBtn.setStyleSheet("background-color: red")
else:
self.pvPrefixStr = self.pvPrefixOrigStr # Restore if dataset was opened
self.fftPluginId = self.fftPluginOrigId # Restore if dataset was opened
self.buildPvNames()
self.pauseBtn.setStyleSheet("background-color: green")
# Retrigger plots with newest values
self.comSignalSpectY.data_signal.emit(self.spectY)
self.comSignalRawData.data_signal.emit(self.rawdataY)
return
def enableBtnAction(self):
self.enable = not self.enable
self.pvEnable.put(self.enable)
if self.enable:
self.enableBtn.setStyleSheet("background-color: green")
else:
self.enableBtn.setStyleSheet("background-color: red")
return
def triggBtnAction(self):
self.pvTrigg.put(True)
return
def newModeIndexChanged(self,index):
if index==0 or index==1:
if not self.offline and self.pvMode is not None:
self.pvMode.put(index+1)
return
def openBtnAction(self):
if not self.offline:
self.pause = 1 # pause while open if online
self.pauseBtn.setStyleSheet("background-color: red")
QCoreApplication.processEvents()
fname = QFileDialog.getOpenFileName(self, 'Open file', '.', "Data files (*.npz)")
if fname is None:
return
if np.size(fname) != 2:
return
if len(fname[0])<=0:
return
npzfile = np.load(fname[0])
# verify scope plugin
if npzfile['plugin'] != "FFT":
print ("Invalid data type (wrong plugin type)")
return
# File valid
self.rawdataX = npzfile['rawdataX']
self.rawdataY = npzfile['rawdataY']
self.spectX = npzfile['spectX']
self.spectY = npzfile['spectY']
self.sourceStr = str(npzfile['sourceStr'])
self.sampleRate = npzfile['sampleRate']
self.NFFT = npzfile['NFFT']
self.mode = npzfile['mode']
self.pvPrefixStr = str(npzfile['pvPrefixStr'])
self.fftPluginId = npzfile['fftPluginId']
self.buildPvNames()
# trigg draw
self.comSignalMode.data_signal.emit(self.mode)
self.comSignalSpectX.data_signal.emit(self.spectX)
self.comSignalSpectY.data_signal.emit(self.spectY)
self.comSignalRawData.data_signal.emit(self.rawdataY)
self.setStatusOfWidgets()
return
def saveBtnAction(self):
fname = QFileDialog.getSaveFileName(self, 'Save file', '.', "Data files (*.npz)")
if fname is None:
return
if np.size(fname) != 2:
return
if len(fname[0])<=0:
return
# Save all relevant data
np.savez(fname[0],
plugin = "FFT",
rawdataX = self.rawdataX,
rawdataY = self.rawdataY,
spectX = self.spectX,
spectY = self.spectY,
sourceStr = self.sourceStr,
sampleRate = self.sampleRate,
NFFT = self.NFFT,
mode = self.mode,
pvPrefixStr = self.pvPrefixStr,
fftPluginId = self.fftPluginId
)
return
###### Plotting
def plotSpect(self):
if self.spectX is None:
return
if self.spectY is None:
return
# create an axis for spectrum
if self.axSpect is None:
self.axSpect = self.figure.add_subplot(212)
# plot data
if self.plottedLineSpect is not None:
self.plottedLineSpect.remove()
self.plottedLineSpect, = self.axSpect.plot(self.spectX,self.spectY, 'b*-')
self.axSpect.grid(True)
if self.offline: # No units offline
self.axSpect.set_xlabel(self.pvNameSpectX)
self.axSpect.set_ylabel(self.pvNameSpectY)
else:
self.axSpect.set_xlabel(self.pvNameSpectX +' [' + self.pvSpectX.units + ']')
self.axSpect.set_ylabel(self.pvNameSpectY +' [' + self.pvSpectY.units + ']')
# refresh canvas
self.canvas.draw()
self.axSpect.autoscale(enable=False)
def plotRaw(self):
if self.rawdataY is None:
return
# create an axis for spectrum
if self.axRaw is None:
self.axRaw = self.figure.add_subplot(211)
# plot data
if self.plottedLineRaw is not None:
self.plottedLineRaw.remove()
self.plottedLineRaw, = self.axRaw.plot(self.rawdataX,self.rawdataY, 'b*-')
self.axRaw.grid(True)
self.axRaw.set_xlabel('Time [s]')
if self.offline: # No units offline
self.axRaw.set_ylabel(self.pvNameRawDataY)
else:
self.axRaw.set_ylabel(self.pvNameRawDataY +' [' + self.pvRawData.units + ']')
# refresh canvas
self.canvas.draw()
self.allowSave = True
self.axRaw.autoscale(enable=True)
def printOutHelp():
print("ecmcFFTMainGui: Plots waveforms of FFT data (updates on Y data callback). ")
print("python ecmcFFTMainGui.py <prefix> <fftId>")
print("<prefix>: Ioc prefix ('IOC_TEST:')")
print("<fftId> : Id of fft plugin ('0')")
print("example : python ecmcFFTMainGui.py 'IOC_TEST:' '0'")
print("Will connect to Pvs: <prefix>Plugin-FFT<fftId>-*")
if __name__ == "__main__":
import sys
prefix = None
fftid = None
if len(sys.argv) == 1:
prefix = None
fftid = None
elif len(sys.argv) == 3:
prefix = sys.argv[1]
fftid = int(sys.argv[2])
else:
printOutHelp()
sys.exit()
app = QtWidgets.QApplication(sys.argv)
window=ecmcFFTMainGui(prefix=prefix,fftPluginId=fftid)
window.show()
sys.exit(app.exec_())

Binary file not shown.