1
0
Fork 0
mirror of https://github.com/gwm17/spspy.git synced 2024-09-21 15:07:25 -04:00
spspy/spsplot/SPSPlotGUI.py

295 lines
9.9 KiB
Python
Raw Normal View History

2021-12-06 15:37:47 -05:00
#!/usr/bin/env python3
import SPSPlot as spsplt
import sys
from qtpy.QtWidgets import QApplication, QWidget, QMainWindow
from qtpy.QtWidgets import QLabel, QMenuBar, QAction
from qtpy.QtWidgets import QHBoxLayout, QVBoxLayout, QGroupBox
from qtpy.QtWidgets import QPushButton, QButtonGroup, QRadioButton
from qtpy.QtWidgets import QSpinBox, QDoubleSpinBox, QComboBox
from qtpy.QtWidgets import QDialog, QFileDialog, QDialogButtonBox
from qtpy.QtCore import Signal
import matplotlib as mpl
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg
from matplotlib.figure import Figure
class MPLCanvas(FigureCanvasQTAgg):
def __init__(self, parent=None, width=5, height=4, dpi=100):
self.fig = Figure(figsize=(width, height), dpi=dpi, edgecolor="black",linewidth=0.5)
self.axes = self.fig.add_subplot(111)
self.axes.spines['top'].set_visible(False)
super(MPLCanvas, self).__init__(self.fig)
class ReactionDialog(QDialog):
new_reaction = Signal(int, int, int, int, int, int)
def __init__(self, parent=None):
super().__init__(parent)
self.setWindowTitle("Add A Reaction")
QBtn = QDialogButtonBox.Ok | QDialogButtonBox.Cancel
self.buttonBox = QDialogButtonBox(QBtn)
self.buttonBox.accepted.connect(self.accept)
self.buttonBox.accepted.connect(self.SendReaction)
self.buttonBox.rejected.connect(self.reject)
self.layout = QVBoxLayout()
self.setLayout(self.layout)
self.CreateReactionInputs()
self.layout.addWidget(self.buttonBox)
def SendReaction(self) :
self.new_reaction.emit(self.ztInput.value(),self.atInput.value(),self.zpInput.value(),self.apInput.value(),self.zeInput.value(),self.aeInput.value())
def CreateReactionInputs(self) :
self.nucleiGroupBox = QGroupBox("Reaction Nuclei",self)
inputLayout = QVBoxLayout()
ztLabel = QLabel("ZT",self.nucleiGroupBox)
self.ztInput = QSpinBox(self.nucleiGroupBox)
self.ztInput.setRange(1, 110)
atLabel = QLabel("AT",self.nucleiGroupBox)
self.atInput = QSpinBox(self.nucleiGroupBox)
self.atInput.setRange(1,270)
zpLabel = QLabel("ZP",self.nucleiGroupBox)
self.zpInput = QSpinBox(self.nucleiGroupBox)
self.zpInput.setRange(1, 110)
apLabel = QLabel("AP",self.nucleiGroupBox)
self.apInput = QSpinBox(self.nucleiGroupBox)
self.apInput.setRange(1,270)
zeLabel = QLabel("ZE",self.nucleiGroupBox)
self.zeInput = QSpinBox(self.nucleiGroupBox)
self.zeInput.setRange(1, 110)
aeLabel = QLabel("AE",self.nucleiGroupBox)
self.aeInput = QSpinBox(self.nucleiGroupBox)
self.aeInput.setRange(1,270)
inputLayout.addWidget(ztLabel)
inputLayout.addWidget(self.ztInput)
inputLayout.addWidget(atLabel)
inputLayout.addWidget(self.atInput)
inputLayout.addWidget(zpLabel)
inputLayout.addWidget(self.zpInput)
inputLayout.addWidget(apLabel)
inputLayout.addWidget(self.apInput)
inputLayout.addWidget(zeLabel)
inputLayout.addWidget(self.zeInput)
inputLayout.addWidget(aeLabel)
inputLayout.addWidget(self.aeInput)
self.nucleiGroupBox.setLayout(inputLayout)
self.layout.addWidget(self.nucleiGroupBox)
class LevelDialog(QDialog):
new_level = Signal(str,float)
def __init__(self, parent) :
super().__init__(parent)
self.setWindowTitle("Add a Level")
QBtn = QDialogButtonBox.Ok | QDialogButtonBox.Cancel
self.buttonBox = QDialogButtonBox(QBtn)
self.buttonBox.accepted.connect(self.accept)
self.buttonBox.accepted.connect(self.SendLevel)
self.buttonBox.rejected.connect(self.reject)
self.layout = QVBoxLayout()
self.setLayout(self.layout)
rxnLabel = QLabel("Choose a reaction",self)
self.reactionList = QComboBox(self)
for rxnName in parent.sps.reactions:
self.reactionList.addItem(rxnName)
stateLabel = QLabel("New state energy",self)
self.stateInput = QDoubleSpinBox(self)
self.stateInput.setRange(0.0,40.0)
self.stateInput.setSuffix(" MeV")
self.layout.addWidget(rxnLabel)
self.layout.addWidget(self.reactionList)
self.layout.addWidget(stateLabel)
self.layout.addWidget(self.stateInput)
self.layout.addWidget(self.buttonBox)
def SendLevel(self):
self.new_level.emit(self.reactionList.currentText(),self.stateInput.value())
class SPSPlotGUI(QMainWindow):
def __init__(self, parent=None) :
super().__init__(parent)
self.setWindowTitle("SPSPlot")
self.sps = spsplt.SPSPlot()
self.generalLayout = QVBoxLayout()
self.centralWidget = QWidget(self)
self.setCentralWidget(self.centralWidget)
self.centralWidget.setLayout(self.generalLayout)
self.energyFlag = True #True = ex False = ke
self.CreateCanvas()
self.CreateMenus()
self.CreateInputs()
self.show()
def CreateCanvas(self):
self.canvas = MPLCanvas(self, width=14, height=5, dpi=100)
self.generalLayout.addWidget(self.canvas, 5)
def CreateMenus(self):
self.fileMenu = self.menuBar().addMenu("&File")
saveAction = QAction("&Save...",self)
openAction = QAction("&Open...",self)
self.fileMenu.addAction(saveAction)
self.fileMenu.addAction(openAction)
self.fileMenu.addAction("&Exit", self.close)
saveAction.triggered.connect(self.HandleSave)
openAction.triggered.connect(self.HandleOpen)
self.addMenu = self.menuBar().addMenu("&New")
newStateAction = QAction("New state...", self)
newReactionAction = QAction("New reaction...", self)
self.addMenu.addAction(newStateAction)
self.addMenu.addAction(newReactionAction)
newStateAction.triggered.connect(self.HandleNewState)
newReactionAction.triggered.connect(self.HandleNewReaction)
def CreateInputs(self):
inputLayout = QHBoxLayout()
self.inputGroupBox = QGroupBox("Adjustable Inputs", self)
rhoMinLabel = QLabel("Rho Min", self.inputGroupBox)
self.rhoMinInput = QDoubleSpinBox(self.inputGroupBox)
self.rhoMinInput.setRange(0.0, 150.0)
self.rhoMinInput.setSuffix(" cm")
rhoMaxLabel = QLabel("RhoMax", self.inputGroupBox)
self.rhoMaxInput = QDoubleSpinBox(self.inputGroupBox)
self.rhoMaxInput.setRange(0.0,150.0)
self.rhoMaxInput.setSuffix(" cm")
bkeLabel = QLabel("Beam KE", self.inputGroupBox)
self.bkeInput = QDoubleSpinBox(self.inputGroupBox)
self.bkeInput.setRange(0.0, 500.0)
self.bkeInput.setSuffix(" MeV")
bfieldLabel = QLabel("B-field", self.inputGroupBox)
self.bfieldInput = QDoubleSpinBox(self.inputGroupBox)
self.bfieldInput.setRange(0.0, 17.0)
self.bfieldInput.setSuffix(" kG")
angleLabel = QLabel("Angle", self.inputGroupBox)
self.angleInput = QDoubleSpinBox(self.inputGroupBox)
self.angleInput.setRange(0.0, 180.0)
self.angleInput.setSuffix(" deg")
self.runButton = QPushButton("Run", self.inputGroupBox)
self.runButton.clicked.connect(self.HandleRun)
self.energyButtonGroup = QGroupBox("Ex/KE switch",self)
buttonLayout = QHBoxLayout()
self.exButton = QRadioButton("Excitation energy", self.energyButtonGroup)
self.exButton.toggled.connect(self.HandleExSwitch)
self.keButton = QRadioButton("Ejectile Kinetic energy", self.energyButtonGroup)
self.keButton.toggled.connect(self.HandleKESwitch)
buttonLayout.addWidget(self.exButton)
buttonLayout.addWidget(self.keButton)
self.energyButtonGroup.setLayout(buttonLayout)
inputLayout.addWidget(rhoMinLabel)
inputLayout.addWidget(self.rhoMinInput)
inputLayout.addWidget(rhoMaxLabel)
inputLayout.addWidget(self.rhoMaxInput)
inputLayout.addWidget(bkeLabel)
inputLayout.addWidget(self.bkeInput)
inputLayout.addWidget(bfieldLabel)
inputLayout.addWidget(self.bfieldInput)
inputLayout.addWidget(angleLabel)
inputLayout.addWidget(self.angleInput)
inputLayout.addWidget(self.runButton)
self.inputGroupBox.setLayout(inputLayout)
inputLayout.addWidget(self.energyButtonGroup)
self.generalLayout.addWidget(self.inputGroupBox, 1)
def HandleSave(self):
fileName = QFileDialog.getSaveFileName(self, "Save Input","./","Text Files (*.txt *.inp)")
if fileName[0]:
self.sps.WriteConfig(fileName[0])
def HandleOpen(self):
fileName = QFileDialog.getOpenFileName(self, "Open Input","./","Text Files (*.txt *.inp)")
if fileName[0]:
self.sps.ReadConfig(fileName[0])
self.UpdateInputs()
self.UpdatePlot()
def HandleNewState(self):
stDlg = LevelDialog(self)
stDlg.new_level.connect(self.sps.AddLevel)
if stDlg.exec():
self.UpdatePlot()
def HandleNewReaction(self):
rxnDlg = ReactionDialog(self)
rxnDlg.new_reaction.connect(self.sps.AddReaction)
if rxnDlg.exec():
self.UpdatePlot()
def HandleRun(self):
self.sps.ChangeReactionParameters(self.bkeInput.value(), self.angleInput.value(), self.bfieldInput.value())
self.sps.rhoMin = self.rhoMinInput.value()
self.sps.rhoMax = self.rhoMaxInput.value()
self.UpdatePlot()
def HandleExSwitch(self):
if self.exButton.isChecked() and (not self.energyFlag):
self.energyFlag = True
self.UpdatePlot()
def HandleKESwitch(self):
if self.keButton.isChecked() and self.energyFlag:
self.energyFlag = False
self.UpdatePlot()
def UpdatePlot(self):
rxnNumber = 0
rhos = []
exs = []
kes = []
rxns = []
for rxnName in self.sps.reactions:
rxnNumber += 1
rxn = self.sps.reactions[rxnName]
for i in range(len(rxn.residLevels)):
rxns.append(rxnNumber)
rhos.append(rxn.ejectRhovals[i])
exs.append(rxn.residLevels[i])
kes.append(rxn.ejectKEvals[i])
self.canvas.axes.cla()
self.canvas.axes.plot(rhos, rxns, marker="o", linestyle="None")
for i in range(len(rxns)):
y = rxns[i]
x = rhos[i]
label = ''
if self.energyFlag:
label = "{:.2f}".format(exs[i])
else:
label = "{:.2f}".format(kes[i])
self.canvas.axes.annotate(label, (x,y), textcoords="offset points",xytext=(0,10),ha="center",rotation="90")
self.canvas.axes.set_xlim(self.sps.rhoMin, self.sps.rhoMax)
self.canvas.axes.set_yticks(range(1,rxnNumber+1))
self.canvas.axes.set_yticklabels(self.sps.reactions)
self.canvas.draw()
def UpdateInputs(self):
self.rhoMinInput.setValue(self.sps.rhoMin)
self.rhoMaxInput.setValue(self.sps.rhoMax)
self.bfieldInput.setValue(self.sps.Bfield)
self.bkeInput.setValue(self.sps.beamKE)
self.angleInput.setValue(self.sps.angle)
def main() :
mpl.use("Qt5Agg")
myapp = QApplication(sys.argv)
window = SPSPlotGUI()
sys.exit(myapp.exec_())
if __name__ == '__main__':
main()