Loading Makefile +2 −0 Original line number Diff line number Diff line Loading @@ -24,6 +24,8 @@ build: build-ui build-docs build-dist: build @$(PYTHON) setup.py bdist install: install-global install-global: build-ui pip install . Loading pysen/inout/converters.py +7 −2 Original line number Diff line number Diff line Loading @@ -41,8 +41,13 @@ def main(): loglevel = kwargs.pop('loglevel') filenames = kwargs.pop('filename') outdir = kwargs.pop('out') setup_logger(loglevel) log = setup_logger(loglevel) try: convert_files(filenames, outdir, **kwargs) except OSError as exc: log.error("OS Error: %s", exc) except RuntimeError as exc: log.error("%s", exc) if __name__ == "__main__": Loading pysen/inout/hdf.py +6 −11 Original line number Diff line number Diff line Loading @@ -254,7 +254,7 @@ def convert_to_taco(filename, outdir, **kwargs): file_type = get_nsefiletype(filename) writer_class = WriterClassType.get(file_type, None) if not isinstance(writer_class, type): raise RuntimeError(f"Unknown file type {file_type}") raise RuntimeError(f"{filename}: unknown file type {file_type}") writer = writer_class() if not writer.read_nexus(filename, **kwargs): return None Loading @@ -266,17 +266,12 @@ ConverterType = { 'to_taco' : convert_to_taco, def convert_files(filenames, outdir, **kwargs): """convert *.nxs.h5 file to/from old TACO style files""" log = logging.getLogger() converter = ConverterType.get(kwargs.pop('converter', 'from_taco')) results = [] log = logging.getLogger() for filename in filenames: try: basename = os.path.basename(filename) outfile = converter(filename, outdir, **kwargs) log.info('converted %s to %s', basename, outfile) results.append(outfile) except RuntimeError as exc: log.warning("error converting %s: (%s)", basename, exc) except OSError as exc: log.warning("error converting %s: (%s)", basename, exc.strerror) return results pysen/revision.py +2 −2 Original line number Diff line number Diff line Loading @@ -3,8 +3,8 @@ PySEN revision module """ import sys __version__ = "2.1" __release__ = "a3" __date__ = "Mar 24, 2025" __release__ = "a4" __date__ = "Mar 25, 2025" def version(full=False): "get pysen version number" Loading pysen/ui/SimpleEchoSimulator.py +108 −82 Original line number Diff line number Diff line """ Main GUI window module. """ #import os #import time #pylint: disable=invalid-name import numpy as np try: from PyQt5.QtCore import pyqtSlot from PyQt5.QtWidgets import qApp, QMainWindow, QMessageBox #,QVBoxLayout #, QTabWidget, QWidget) from PyQt5.QtGui import QDoubleValidator from matplotlib.backends.backend_qt5agg import FigureCanvas except ImportError: pass from matplotlib.figure import Figure from numpy import pi, exp, log10 from ..config import wavelength_bandwidth from ..constants import ANGSTROM, OMEGA_N from ..echo.fit import flux_weighted_eshape as echo_shape #pylint: disable=import-error from .ui_SimpleEchoSimulator import Ui_SimpleEchoSimMainWindow as Ui_MainWindow MICRO=1e-6 def f_exp(t, t0=1, beta=1): "Stretched exp" return np.exp(-(t/t0)**beta) def f_exp(t, t0=1): "stretched exponential" return exp(-(t/t0)) def sqt(t, coh, tcoh, inc, tinc, beta=1): def sqt(t, coh, tcoh, inc, tinc, bgr=0): "S(Q,t)/S(Q,0)" return coh*f_exp(t,tcoh,beta)-1/3*inc*f_exp(t,tinc,beta) return coh*f_exp(t,tcoh)-1/3*(inc*f_exp(t,tinc)+bgr) class MainWindow(QMainWindow, Ui_MainWindow): """Main for viewing and deleting available groups.""" #pylint: disable=too-many-instance-attributes def __init__(self, parent=None): def __init__(self, parent=None, **kwargs): """init MainWindow""" super().__init__(parent) self.setupUi(self) self.menuBar.setNativeMenuBar(False) #self.menuBar.setCornerWidget(self.menuHelp, Qt.TopRightCorner) # self.pos = kwargs.pop('pos', 'p2') self.lmax = kwargs.pop('lmax', 8.000) self.lmin = self.lmax - wavelength_bandwidth(pos=self.pos) self.ntbin = kwargs.pop('ntbin', 42) # number of TOF bins self.tmin, self.tmax = 1e-3, 1e+3 #print(self.pos, self.lmax, self.lmin, self.ntbin) # dynamic_canvas = FigureCanvas(Figure(figsize=(5, 3))) Loading @@ -50,121 +60,137 @@ class MainWindow(QMainWindow, Ui_MainWindow): self.dblSpinBoxBgr.valueChanged.connect(self.handleSpinBoxBgr) # self.hSliderTauCoh.valueChanged.connect(self.handleSliderTauCoh) self.dblSpinBoxTcoh.valueChanged.connect(self.handleSpinBoxTauCoh) # self.hSliderTauInc.valueChanged.connect(self.handleSliderTauInc) self.dblSpinBoxTinc.valueChanged.connect(self.handleSpinBoxTauInc) # self.hSliderTauEcho.valueChanged.connect(self.handleSliderTauEcho) self.dblSpinBoxTecho.valueChanged.connect(self.handleSpinBoxTauEcho) # #self.dblSpinBoxTcoh.valueChanged.connect(self.handleSpinBoxTauCoh) #self.dblSpinBoxTinc.valueChanged.connect(self.handleSpinBoxTauInc) #self.dblSpinBoxTecho.valueChanged.connect(self.handleSpinBoxTauEcho) # self.inpTauCoh.setValidator(QDoubleValidator(1e-6, 1e6, 3)) self.inpTauInc.setValidator(QDoubleValidator(1e-6, 1e6, 3)) self.inpTauEcho.setValidator(QDoubleValidator(1e-3, 1e3, 3)) # self.inpTauCoh.returnPressed.connect(self.handleInpTauCoh) self.inpTauInc.returnPressed.connect(self.handleInpTauInc) self.inpTauEcho.returnPressed.connect(self.handleInpTauEcho) # File menu actions self.actionExit.triggered.connect(qApp.quit) self.actionReset.triggered.connect(self.reset) self.actionAbout.triggered.connect(self.about_box) # self._reset_values() def _fmt_time(self, label, value): "format time" if value>=1e6: label.setText("{0:8.1f} ms".format(value/1e6)) label.setText(f"{value/1e6:8.1f} ms") elif value>=1e3: label.setText("{0:8.1f} us".format(value/1e3)) label.setText(f"{value/1e3:8.1f} us") elif value>=1: label.setText("{0:8.1f} ns".format(value)) label.setText(f"{value:8.1f} ns") elif value>=1e-3: label.setText("{0:8.1f} ps".format(value*1e3)) label.setText(f"{value*1e3:8.1f} ps") else: label.setText("{0:8.1f} fs".format(value*1e6)) #elif value>1e-6: #else: # label.setText("{0:8.3g} ns".format(value)) label.setText(f"{value*1e6:8.1f} fs") # Intensities @pyqtSlot(float) def handleSpinBoxCoh(self, _value): "handler" "Icoh handler" self._update_canvas() @pyqtSlot(float) def handleSpinBoxInc(self, _value): "handler" "Iinc handler" self._update_canvas() @pyqtSlot(float) def handleSpinBoxBgr(self, _value): "handler" "Ibgr handler" self._update_canvas() # Tau sliders @pyqtSlot(int) def handleSliderTauCoh(self, value): "handler" #val = 10**(value/1000.0) #self.dblSpinBoxTcoh.setValue(val) self.dblSpinBoxTcoh.setValue(value/1000.0) self._update_canvas() @pyqtSlot(float) def handleSpinBoxTauCoh(self, value): "handler" #val = int(np.log10(value)*1000) #self.hSliderTauCoh.setValue(val) self.hSliderTauCoh.setValue(int(value*1000)) "tau coh slider handler" tau = 10**(value/1000.0) self.inpTauCoh.setText(f"{tau:.4g}") self._update_canvas() @pyqtSlot(int) def handleSliderTauInc(self, value): "handler" self.dblSpinBoxTinc.setValue(value/1000.0) "tau inc slider handler" tau = 10**(value/1000.0) self.inpTauInc.setText(f"{tau:.4g}") self._update_canvas() @pyqtSlot(float) def handleSpinBoxTauInc(self, value): "handler" self.hSliderTauInc.setValue(int(value*1000)) self._update_canvas() @pyqtSlot(int) def handleSliderTauEcho(self, value): "handler" self.dblSpinBoxTecho.setValue(value/1000.0) "tau echo slider handler" tau = 10**(value/1000.0) self.inpTauEcho.setText(f"{tau:.4g}") self._update_canvas() @pyqtSlot(float) def handleSpinBoxTauEcho(self, value): "handler" self.hSliderTauEcho.setValue(int(value*1000)) def handleInpTauCoh(self): "input tau coh handler" text = self.inpTauCoh.text() slider = int(log10(float(text))*1000) self.hSliderTauCoh.setValue(slider) self._update_canvas() def handleInpTauInc(self): "input tau inc handler" text = self.inpTauInc.text() slider = int(log10(float(text))*1000) self.hSliderTauInc.setValue(slider) self._update_canvas() def handleInpTauEcho(self): "input tau echo handler" text = self.inpTauEcho.text() slider = int(log10(float(text))*1000) self.hSliderTauEcho.setValue(slider) self._update_canvas() def _reset_values(self): "reset simulator values" self.dblSpinBoxCoh.setValue(90) self.dblSpinBoxInc.setValue(30) self.dblSpinBoxCoh.setValue(104) self.dblSpinBoxInc.setValue(12) self.dblSpinBoxBgr.setValue(0) self.hSliderTauCoh.setValue(10000) self.hSliderTauInc.setValue(0) self.hSliderTauEcho.setValue(1000) #self.inpTauCoh.setText("100.000") #self.inpTauInc.setText("0.010") #self.inpTauEcho.setText("1.00") self.hSliderTauCoh.setValue( 2000) self.hSliderTauInc.setValue(-3000) self.hSliderTauEcho.setValue(1) def _init_canvas(self): "initialize canvas" tmin, tmax = 1e-3, 1e+3 ntbin = 42 # number of TOF bins lbin = np.linspace(5,8,ntbin+1)*ANGSTROM # neutron wavelength bins lbin = np.linspace(self.lmin,self.lmax,self.ntbin+1)*ANGSTROM # neutron wavelength bins xt = np.logspace(log10(self.tmin), log10(self.tmax), 201) # for S(Q,t) djmax = 3*pi/(self.lmax*ANGSTROM)/OMEGA_N # field integral range (-3pi,+3pi) self.lave = (lbin[1:]+lbin[:-1])/2 # average wavelength self.dlam = (lbin[1:]-lbin[:-1])/2 # delta-lambda self.flux = (self.lave[0]/self.lave)**2 self.djmax = 3*np.pi/np.average(lbin)/OMEGA_N # field integral range (-3pi,+3pi) self.dj = np.linspace(-self.djmax, self.djmax, 201) # for plotting dj points self.xt = np.logspace(np.log10(tmin), np.log10(tmax), 201) # for plotting tau points 10^{-3},10^{+3} self.dj = np.linspace(-djmax, djmax, 201) # for plotting dj points self.dj2 = np.linspace(-djmax, djmax, 11) # for plotting dj points self.xt = xt ax = self._ax[0] self.lines = {} self.lines['sqt'], = ax.plot(self.xt, np.zeros_like(self.xt), 'r-', lw=2, label='I(Q,t)') self.lines['coh'], = ax.plot(self.xt, np.zeros_like(self.xt), 'g--', lw=1, label=r'$f_{coh}$') self.lines['inc'], = ax.plot(self.xt, np.zeros_like(self.xt), 'b-.', lw=1, label=r'$f_{inc}$') self.lines['sqt'], = ax.plot(xt, np.zeros_like(xt), 'r-', lw=2, label='I(Q,t)') self.lines['coh'], = ax.plot(xt, np.zeros_like(xt), 'g--', lw=1, label=r'$f_{coh}$') self.lines['inc'], = ax.plot(xt, np.zeros_like(xt), 'b-.', lw=1, label=r'$f_{inc}$') self.lines['tau'] = ax.axvline(0, lw=1.0, ls='-', color='k') #self.lines['1/e'] = ax.axhline(exp(-1), lw=0.5, ls='--', color='k') ax.set_xscale('log') ax.set_xlim(min(self.xt), max(self.xt)) ax.set_xlim(min(xt), max(xt)) ax.set_xlabel(r'$\tau$ [ns]') ax.set_ylabel(r'$I(Q,\tau)$') ax.legend(loc=0) Loading @@ -172,6 +198,7 @@ class MainWindow(QMainWindow, Ui_MainWindow): ax = self._ax[1] self.lines['echo'], = ax.plot(self.dj/MICRO, np.zeros_like(self.dj), 'k-', lw=2) self.lines['echo2'], = ax.plot(self.dj2/MICRO, np.zeros_like(self.dj2),'ro', lw=2) self.lines['up'] = ax.axhline(2.0, lw=1, ls='--', color='red') self.lines['dn'] = ax.axhline(1.0, lw=1, ls='--', color='blue') self.lines['ave'] = ax.axhline(1.5, lw=2, ls='-', color='k') Loading @@ -184,7 +211,6 @@ class MainWindow(QMainWindow, Ui_MainWindow): "draw all figures" #pylint: disable=too-many-statements #FIXME: refactor beta = 1 coh = self.dblSpinBoxCoh.value() inc = self.dblSpinBoxInc.value() bgr = self.dblSpinBoxBgr.value() Loading @@ -192,34 +218,29 @@ class MainWindow(QMainWindow, Ui_MainWindow): tinc = 10**(self.hSliderTauInc.value()/1000.0) techo = 10**(self.hSliderTauEcho.value()/1000.0) #self._fmt_time(self.lblTauCoh, tcoh) #self._fmt_time(self.lblTauInc, tinc) #self._fmt_time(self.lblTauEcho, techo) ax = self._ax[1] # check inputs if inc<0 or coh<0: ax.set_title('!!! Coherent or Incoherent cannot be negative !!!') ax.figure.canvas.draw() return dn = 2/3*inc+bgr up = coh+1/3*inc+bgr dn = 2/3*(inc+bgr) up = coh+1/3*(inc+bgr) if up>0 and dn>0: fratio = up/dn else: ax.set_title('!!! Up and Down counts must be positive') ax.figure.canvas.draw() return norm = coh - 1/3*inc + bgr if norm==0: if (up-dn)==0: ax.set_title('!!! Invalid input') ax.figure.canvas.draw() return ax.set_title(r'FR=%.3g (U=%.0f/D=%.0f)' % (fratio,up,dn)) ax.set_title(rf'FR={fratio:.3g} (U={up:.0f}/D={dn:.0f})') ave = (up+dn)/2 amp = (up-dn)/2*sqt(techo,coh,tcoh,inc,tinc,beta)/norm amp = (up-dn)/2*sqt(techo,coh,tcoh,inc,tinc,bgr)/(up-dn) dj = self.dj lave = self.lave Loading @@ -229,6 +250,10 @@ class MainWindow(QMainWindow, Ui_MainWindow): yecho = echo_shape(dj, lave, dlam,flux)*amp + ave self.lines['echo'].set_data(dj/MICRO, yecho) yecho2 = echo_shape(self.dj2, lave, dlam,flux)*amp + ave self.lines['echo2'].set_data(self.dj2/MICRO, yecho2) self.lines['up'].set_data(dj/MICRO,up*np.ones_like(dj)) self.lines['dn'].set_data(dj/MICRO,dn*np.ones_like(dj)) self.lines['ave'].set_data(dj/MICRO,ave*np.ones_like(dj)) Loading @@ -237,9 +262,10 @@ class MainWindow(QMainWindow, Ui_MainWindow): top = max(np.amax(yecho), up, dn)*1.1 ax.set_ylim(bottom=bot, top=top) ysqt = sqt(xt, coh, tcoh, inc, tinc,beta)/norm ysqt = sqt(xt, coh, tcoh, inc, tinc)/(up-dn) ycoh = f_exp(xt, tcoh) yinc = f_exp(xt, tinc) self.lines['sqt'].set_data(xt, ysqt) self.lines['coh'].set_data(xt, ycoh) self.lines['inc'].set_data(xt, yinc) Loading Loading
Makefile +2 −0 Original line number Diff line number Diff line Loading @@ -24,6 +24,8 @@ build: build-ui build-docs build-dist: build @$(PYTHON) setup.py bdist install: install-global install-global: build-ui pip install . Loading
pysen/inout/converters.py +7 −2 Original line number Diff line number Diff line Loading @@ -41,8 +41,13 @@ def main(): loglevel = kwargs.pop('loglevel') filenames = kwargs.pop('filename') outdir = kwargs.pop('out') setup_logger(loglevel) log = setup_logger(loglevel) try: convert_files(filenames, outdir, **kwargs) except OSError as exc: log.error("OS Error: %s", exc) except RuntimeError as exc: log.error("%s", exc) if __name__ == "__main__": Loading
pysen/inout/hdf.py +6 −11 Original line number Diff line number Diff line Loading @@ -254,7 +254,7 @@ def convert_to_taco(filename, outdir, **kwargs): file_type = get_nsefiletype(filename) writer_class = WriterClassType.get(file_type, None) if not isinstance(writer_class, type): raise RuntimeError(f"Unknown file type {file_type}") raise RuntimeError(f"{filename}: unknown file type {file_type}") writer = writer_class() if not writer.read_nexus(filename, **kwargs): return None Loading @@ -266,17 +266,12 @@ ConverterType = { 'to_taco' : convert_to_taco, def convert_files(filenames, outdir, **kwargs): """convert *.nxs.h5 file to/from old TACO style files""" log = logging.getLogger() converter = ConverterType.get(kwargs.pop('converter', 'from_taco')) results = [] log = logging.getLogger() for filename in filenames: try: basename = os.path.basename(filename) outfile = converter(filename, outdir, **kwargs) log.info('converted %s to %s', basename, outfile) results.append(outfile) except RuntimeError as exc: log.warning("error converting %s: (%s)", basename, exc) except OSError as exc: log.warning("error converting %s: (%s)", basename, exc.strerror) return results
pysen/revision.py +2 −2 Original line number Diff line number Diff line Loading @@ -3,8 +3,8 @@ PySEN revision module """ import sys __version__ = "2.1" __release__ = "a3" __date__ = "Mar 24, 2025" __release__ = "a4" __date__ = "Mar 25, 2025" def version(full=False): "get pysen version number" Loading
pysen/ui/SimpleEchoSimulator.py +108 −82 Original line number Diff line number Diff line """ Main GUI window module. """ #import os #import time #pylint: disable=invalid-name import numpy as np try: from PyQt5.QtCore import pyqtSlot from PyQt5.QtWidgets import qApp, QMainWindow, QMessageBox #,QVBoxLayout #, QTabWidget, QWidget) from PyQt5.QtGui import QDoubleValidator from matplotlib.backends.backend_qt5agg import FigureCanvas except ImportError: pass from matplotlib.figure import Figure from numpy import pi, exp, log10 from ..config import wavelength_bandwidth from ..constants import ANGSTROM, OMEGA_N from ..echo.fit import flux_weighted_eshape as echo_shape #pylint: disable=import-error from .ui_SimpleEchoSimulator import Ui_SimpleEchoSimMainWindow as Ui_MainWindow MICRO=1e-6 def f_exp(t, t0=1, beta=1): "Stretched exp" return np.exp(-(t/t0)**beta) def f_exp(t, t0=1): "stretched exponential" return exp(-(t/t0)) def sqt(t, coh, tcoh, inc, tinc, beta=1): def sqt(t, coh, tcoh, inc, tinc, bgr=0): "S(Q,t)/S(Q,0)" return coh*f_exp(t,tcoh,beta)-1/3*inc*f_exp(t,tinc,beta) return coh*f_exp(t,tcoh)-1/3*(inc*f_exp(t,tinc)+bgr) class MainWindow(QMainWindow, Ui_MainWindow): """Main for viewing and deleting available groups.""" #pylint: disable=too-many-instance-attributes def __init__(self, parent=None): def __init__(self, parent=None, **kwargs): """init MainWindow""" super().__init__(parent) self.setupUi(self) self.menuBar.setNativeMenuBar(False) #self.menuBar.setCornerWidget(self.menuHelp, Qt.TopRightCorner) # self.pos = kwargs.pop('pos', 'p2') self.lmax = kwargs.pop('lmax', 8.000) self.lmin = self.lmax - wavelength_bandwidth(pos=self.pos) self.ntbin = kwargs.pop('ntbin', 42) # number of TOF bins self.tmin, self.tmax = 1e-3, 1e+3 #print(self.pos, self.lmax, self.lmin, self.ntbin) # dynamic_canvas = FigureCanvas(Figure(figsize=(5, 3))) Loading @@ -50,121 +60,137 @@ class MainWindow(QMainWindow, Ui_MainWindow): self.dblSpinBoxBgr.valueChanged.connect(self.handleSpinBoxBgr) # self.hSliderTauCoh.valueChanged.connect(self.handleSliderTauCoh) self.dblSpinBoxTcoh.valueChanged.connect(self.handleSpinBoxTauCoh) # self.hSliderTauInc.valueChanged.connect(self.handleSliderTauInc) self.dblSpinBoxTinc.valueChanged.connect(self.handleSpinBoxTauInc) # self.hSliderTauEcho.valueChanged.connect(self.handleSliderTauEcho) self.dblSpinBoxTecho.valueChanged.connect(self.handleSpinBoxTauEcho) # #self.dblSpinBoxTcoh.valueChanged.connect(self.handleSpinBoxTauCoh) #self.dblSpinBoxTinc.valueChanged.connect(self.handleSpinBoxTauInc) #self.dblSpinBoxTecho.valueChanged.connect(self.handleSpinBoxTauEcho) # self.inpTauCoh.setValidator(QDoubleValidator(1e-6, 1e6, 3)) self.inpTauInc.setValidator(QDoubleValidator(1e-6, 1e6, 3)) self.inpTauEcho.setValidator(QDoubleValidator(1e-3, 1e3, 3)) # self.inpTauCoh.returnPressed.connect(self.handleInpTauCoh) self.inpTauInc.returnPressed.connect(self.handleInpTauInc) self.inpTauEcho.returnPressed.connect(self.handleInpTauEcho) # File menu actions self.actionExit.triggered.connect(qApp.quit) self.actionReset.triggered.connect(self.reset) self.actionAbout.triggered.connect(self.about_box) # self._reset_values() def _fmt_time(self, label, value): "format time" if value>=1e6: label.setText("{0:8.1f} ms".format(value/1e6)) label.setText(f"{value/1e6:8.1f} ms") elif value>=1e3: label.setText("{0:8.1f} us".format(value/1e3)) label.setText(f"{value/1e3:8.1f} us") elif value>=1: label.setText("{0:8.1f} ns".format(value)) label.setText(f"{value:8.1f} ns") elif value>=1e-3: label.setText("{0:8.1f} ps".format(value*1e3)) label.setText(f"{value*1e3:8.1f} ps") else: label.setText("{0:8.1f} fs".format(value*1e6)) #elif value>1e-6: #else: # label.setText("{0:8.3g} ns".format(value)) label.setText(f"{value*1e6:8.1f} fs") # Intensities @pyqtSlot(float) def handleSpinBoxCoh(self, _value): "handler" "Icoh handler" self._update_canvas() @pyqtSlot(float) def handleSpinBoxInc(self, _value): "handler" "Iinc handler" self._update_canvas() @pyqtSlot(float) def handleSpinBoxBgr(self, _value): "handler" "Ibgr handler" self._update_canvas() # Tau sliders @pyqtSlot(int) def handleSliderTauCoh(self, value): "handler" #val = 10**(value/1000.0) #self.dblSpinBoxTcoh.setValue(val) self.dblSpinBoxTcoh.setValue(value/1000.0) self._update_canvas() @pyqtSlot(float) def handleSpinBoxTauCoh(self, value): "handler" #val = int(np.log10(value)*1000) #self.hSliderTauCoh.setValue(val) self.hSliderTauCoh.setValue(int(value*1000)) "tau coh slider handler" tau = 10**(value/1000.0) self.inpTauCoh.setText(f"{tau:.4g}") self._update_canvas() @pyqtSlot(int) def handleSliderTauInc(self, value): "handler" self.dblSpinBoxTinc.setValue(value/1000.0) "tau inc slider handler" tau = 10**(value/1000.0) self.inpTauInc.setText(f"{tau:.4g}") self._update_canvas() @pyqtSlot(float) def handleSpinBoxTauInc(self, value): "handler" self.hSliderTauInc.setValue(int(value*1000)) self._update_canvas() @pyqtSlot(int) def handleSliderTauEcho(self, value): "handler" self.dblSpinBoxTecho.setValue(value/1000.0) "tau echo slider handler" tau = 10**(value/1000.0) self.inpTauEcho.setText(f"{tau:.4g}") self._update_canvas() @pyqtSlot(float) def handleSpinBoxTauEcho(self, value): "handler" self.hSliderTauEcho.setValue(int(value*1000)) def handleInpTauCoh(self): "input tau coh handler" text = self.inpTauCoh.text() slider = int(log10(float(text))*1000) self.hSliderTauCoh.setValue(slider) self._update_canvas() def handleInpTauInc(self): "input tau inc handler" text = self.inpTauInc.text() slider = int(log10(float(text))*1000) self.hSliderTauInc.setValue(slider) self._update_canvas() def handleInpTauEcho(self): "input tau echo handler" text = self.inpTauEcho.text() slider = int(log10(float(text))*1000) self.hSliderTauEcho.setValue(slider) self._update_canvas() def _reset_values(self): "reset simulator values" self.dblSpinBoxCoh.setValue(90) self.dblSpinBoxInc.setValue(30) self.dblSpinBoxCoh.setValue(104) self.dblSpinBoxInc.setValue(12) self.dblSpinBoxBgr.setValue(0) self.hSliderTauCoh.setValue(10000) self.hSliderTauInc.setValue(0) self.hSliderTauEcho.setValue(1000) #self.inpTauCoh.setText("100.000") #self.inpTauInc.setText("0.010") #self.inpTauEcho.setText("1.00") self.hSliderTauCoh.setValue( 2000) self.hSliderTauInc.setValue(-3000) self.hSliderTauEcho.setValue(1) def _init_canvas(self): "initialize canvas" tmin, tmax = 1e-3, 1e+3 ntbin = 42 # number of TOF bins lbin = np.linspace(5,8,ntbin+1)*ANGSTROM # neutron wavelength bins lbin = np.linspace(self.lmin,self.lmax,self.ntbin+1)*ANGSTROM # neutron wavelength bins xt = np.logspace(log10(self.tmin), log10(self.tmax), 201) # for S(Q,t) djmax = 3*pi/(self.lmax*ANGSTROM)/OMEGA_N # field integral range (-3pi,+3pi) self.lave = (lbin[1:]+lbin[:-1])/2 # average wavelength self.dlam = (lbin[1:]-lbin[:-1])/2 # delta-lambda self.flux = (self.lave[0]/self.lave)**2 self.djmax = 3*np.pi/np.average(lbin)/OMEGA_N # field integral range (-3pi,+3pi) self.dj = np.linspace(-self.djmax, self.djmax, 201) # for plotting dj points self.xt = np.logspace(np.log10(tmin), np.log10(tmax), 201) # for plotting tau points 10^{-3},10^{+3} self.dj = np.linspace(-djmax, djmax, 201) # for plotting dj points self.dj2 = np.linspace(-djmax, djmax, 11) # for plotting dj points self.xt = xt ax = self._ax[0] self.lines = {} self.lines['sqt'], = ax.plot(self.xt, np.zeros_like(self.xt), 'r-', lw=2, label='I(Q,t)') self.lines['coh'], = ax.plot(self.xt, np.zeros_like(self.xt), 'g--', lw=1, label=r'$f_{coh}$') self.lines['inc'], = ax.plot(self.xt, np.zeros_like(self.xt), 'b-.', lw=1, label=r'$f_{inc}$') self.lines['sqt'], = ax.plot(xt, np.zeros_like(xt), 'r-', lw=2, label='I(Q,t)') self.lines['coh'], = ax.plot(xt, np.zeros_like(xt), 'g--', lw=1, label=r'$f_{coh}$') self.lines['inc'], = ax.plot(xt, np.zeros_like(xt), 'b-.', lw=1, label=r'$f_{inc}$') self.lines['tau'] = ax.axvline(0, lw=1.0, ls='-', color='k') #self.lines['1/e'] = ax.axhline(exp(-1), lw=0.5, ls='--', color='k') ax.set_xscale('log') ax.set_xlim(min(self.xt), max(self.xt)) ax.set_xlim(min(xt), max(xt)) ax.set_xlabel(r'$\tau$ [ns]') ax.set_ylabel(r'$I(Q,\tau)$') ax.legend(loc=0) Loading @@ -172,6 +198,7 @@ class MainWindow(QMainWindow, Ui_MainWindow): ax = self._ax[1] self.lines['echo'], = ax.plot(self.dj/MICRO, np.zeros_like(self.dj), 'k-', lw=2) self.lines['echo2'], = ax.plot(self.dj2/MICRO, np.zeros_like(self.dj2),'ro', lw=2) self.lines['up'] = ax.axhline(2.0, lw=1, ls='--', color='red') self.lines['dn'] = ax.axhline(1.0, lw=1, ls='--', color='blue') self.lines['ave'] = ax.axhline(1.5, lw=2, ls='-', color='k') Loading @@ -184,7 +211,6 @@ class MainWindow(QMainWindow, Ui_MainWindow): "draw all figures" #pylint: disable=too-many-statements #FIXME: refactor beta = 1 coh = self.dblSpinBoxCoh.value() inc = self.dblSpinBoxInc.value() bgr = self.dblSpinBoxBgr.value() Loading @@ -192,34 +218,29 @@ class MainWindow(QMainWindow, Ui_MainWindow): tinc = 10**(self.hSliderTauInc.value()/1000.0) techo = 10**(self.hSliderTauEcho.value()/1000.0) #self._fmt_time(self.lblTauCoh, tcoh) #self._fmt_time(self.lblTauInc, tinc) #self._fmt_time(self.lblTauEcho, techo) ax = self._ax[1] # check inputs if inc<0 or coh<0: ax.set_title('!!! Coherent or Incoherent cannot be negative !!!') ax.figure.canvas.draw() return dn = 2/3*inc+bgr up = coh+1/3*inc+bgr dn = 2/3*(inc+bgr) up = coh+1/3*(inc+bgr) if up>0 and dn>0: fratio = up/dn else: ax.set_title('!!! Up and Down counts must be positive') ax.figure.canvas.draw() return norm = coh - 1/3*inc + bgr if norm==0: if (up-dn)==0: ax.set_title('!!! Invalid input') ax.figure.canvas.draw() return ax.set_title(r'FR=%.3g (U=%.0f/D=%.0f)' % (fratio,up,dn)) ax.set_title(rf'FR={fratio:.3g} (U={up:.0f}/D={dn:.0f})') ave = (up+dn)/2 amp = (up-dn)/2*sqt(techo,coh,tcoh,inc,tinc,beta)/norm amp = (up-dn)/2*sqt(techo,coh,tcoh,inc,tinc,bgr)/(up-dn) dj = self.dj lave = self.lave Loading @@ -229,6 +250,10 @@ class MainWindow(QMainWindow, Ui_MainWindow): yecho = echo_shape(dj, lave, dlam,flux)*amp + ave self.lines['echo'].set_data(dj/MICRO, yecho) yecho2 = echo_shape(self.dj2, lave, dlam,flux)*amp + ave self.lines['echo2'].set_data(self.dj2/MICRO, yecho2) self.lines['up'].set_data(dj/MICRO,up*np.ones_like(dj)) self.lines['dn'].set_data(dj/MICRO,dn*np.ones_like(dj)) self.lines['ave'].set_data(dj/MICRO,ave*np.ones_like(dj)) Loading @@ -237,9 +262,10 @@ class MainWindow(QMainWindow, Ui_MainWindow): top = max(np.amax(yecho), up, dn)*1.1 ax.set_ylim(bottom=bot, top=top) ysqt = sqt(xt, coh, tcoh, inc, tinc,beta)/norm ysqt = sqt(xt, coh, tcoh, inc, tinc)/(up-dn) ycoh = f_exp(xt, tcoh) yinc = f_exp(xt, tinc) self.lines['sqt'].set_data(xt, ysqt) self.lines['coh'].set_data(xt, ycoh) self.lines['inc'].set_data(xt, yinc) Loading