diff --git a/src/analysis.py b/src/analysis.py
index 1952e9e..4288224 100644
--- a/src/analysis.py
+++ b/src/analysis.py
@@ -1,6 +1,7 @@
"""
Analysis class
"""
+from collections import OrderedDict
from datetime import datetime
import inspect
import logging
@@ -8,6 +9,7 @@ import math
import os
from statistics import mean
import time
+import timeit
import matplotlib
@@ -44,7 +46,9 @@ class AnalysisProcedure(QObject):
self.settings = self.parent.settings
self.cafe = self.parent.cafe
self.cyca = self.parent.cyca
-
+ self.check_status = self.parent.check_status
+ self.check_status_list = self.parent.check_status_list
+ self.daq_timeout = 10
self.logging = self.parent.logging
self.logger = self.logging.getLogger(__name__)
self.logger.debug("Logging activated in analysis procedure")
@@ -52,6 +56,9 @@ class AnalysisProcedure(QObject):
self.abort = False
self.trigger_abort.connect(self.receive_abort)
+ #Hold PV names and their values
+ self.pv_value_dict = OrderedDict()
+ self.pv_dict = {}
#Package the data as so:
self.all_data = {}
self.all_data['Input data'] = {}
@@ -76,7 +83,7 @@ class AnalysisProcedure(QObject):
self.N_turns = None
#self.t_stepsize = 0.000000019750043 #0.00000002
self.rf_freq = 50.6328 #10**6
- self.rf_sample =2.5 #10**6
+ self.rf_sample =3.0 #10**6
self.pulse_stepsize = 1/(self.rf_freq*10**6)
self.t_stepsize = 1/(self.rf_sample*10**9)
self.t_interval = math.ceil(self.pulse_stepsize/self.t_stepsize)
@@ -120,27 +127,22 @@ class AnalysisProcedure(QObject):
self.simulation = bool(self.input_data['simulation'])
- print("INPUT:", self.input_data)
self.rf_freq = float(self.input_data['freqrf'])
- self.rf_sample = float(self.input_data['freqsampling'])
-
+
+ #2.5 MHz if oscilloscpe
+ if self.simulation:
+ self.rf_sample = 2.5
+ mess = 'Sampling rate changed to 2.5 MHz for oscilloscope data'
+ self.parent.trigger_log_message.emit(
+ MsgSeverity.INFO.name, _pymodule, utils.line_no(), mess, {})
+ else:
+ self.rf_sample = float(self.input_data['freqsampling'])
+
try:
self.accelerator = self.input_data['accelerator']
- print("self.accelerator -1 ", self.accelerator, flush=True)
- except KeyError as ex:
- self.logger.debug("KeyError {0}".format(ex))
- print("self.accelerator-2", self.accelerator, flush=True)
- try:
- self.accelerator = self.input_data['qtabdata']
- print("self.accelerator-3", self.accelerator, flush=True)
- except KeyError as ex:
- self.logger.debug("KeyError {0}".format(ex))
-
- try:
-
- print("self.accelerator-F", self.accelerator, flush=True)
+
self.harmonic_no = float(
self.input_data[self.accelerator]['harmonic'])
self.dTcable = float(
@@ -154,13 +156,10 @@ class AnalysisProcedure(QObject):
self.duty_cycle = float(
self.input_data[self.accelerator]['dutycycle']) # * 0.01
-
- print("logging info level==>", self.logger.getEffectiveLevel(),
- flush=True)
+
self.loglevel = self.input_data['loggingLevel']
self.logger.setLevel(self.logging.getLevelName(self.loglevel))
- print("logging info level==>", self.logger.getEffectiveLevel(),
- flush=True)
+
self.logger.info("INPUT PARAMETERS")
self.logger.info("Accelerator: {0}".format(self.accelerator))
@@ -231,7 +230,7 @@ class AnalysisProcedure(QObject):
input_data = all_data['Input_data']
#Read the input parameters
self.initialize_input_parameters(input_data)
- print("initiliaze", flush=True)
+
ambient_data = all_data['Ambient_data']
self.raw_data = all_data['Raw_data']
@@ -259,6 +258,19 @@ class AnalysisProcedure(QObject):
self.time_stamp = datetime.fromtimestamp(
time_in_seconds).strftime('%a %d-%m-%Y %H:%M:%S')
+
+ ambient_data = {
+ 'Time in seconds': int(time_in_seconds),
+ 'Time stamp': self.time_stamp,
+ }
+
+
+ self.logger.debug("{0}".format(ambient_data))
+
+ #if self.simulation:
+ # return ambient_data
+
+
#EPICS...
handles = self.cafe.getHandles()[0]
status = self.cafe.attachContext(handles[0])
@@ -274,20 +286,62 @@ class AnalysisProcedure(QObject):
"Scan will not be initiated!"), _options)
if self.abort:
- self.aborting(_line())
+ self.aborting(utils.line_no())
return {}
self.parent.trigger_progressbar.emit(PROGRESS_THREAD_ERROR)
return {}
- ambient_data = {
- 'Time in seconds': int(time_in_seconds),
- 'Time stamp': self.time_stamp,
- }
+ pv_list = []
+
+ for key, value in self.settings.data['PV'][self.accelerator].items():
+ self.pv_value_dict[key] = OrderedDict()
+ self.pv_value_dict[key][value] =0
+ self.pv_dict[key] = value
+ pv_list.append(value)
-
- self.logger.debug("{0}".format(ambient_data))
+
+ self.cafe.openPrepare()
+ handle_list = self.cafe.open(pv_list)
+ self.cafe.openNowAndWait(1.0)
+
+ self.cafe.setGetActionWhenMonitorPolicyAllHandles(
+ self.cyca.GET_FROM_CACHE)
+
+ value_list, status, status_list = self.cafe.getScalarList(handle_list)
+
+ if self.debug:
+ for pv, val, stat in zip(pv_list, value_list, status_list):
+ print(pv, val, stat)
+
+ if status != self.cyca.ICAFE_NORMAL:
+ self.check_status_list(_pymodule, "getScalarList",
+ pv_list, status_list, utils.line_no())
+
+
+ '''
+ if status != self.cyca.ICAFE_NORMAL:
+ _options = {}
+ for pv, stat in zip(pv_list, status_list):
+ if stat != self.cyca.ICAFE_NORMAL:
+ _mess = ("Error in 'get' for pv " + pv + ".")
+ _options['statusCode'] = (
+ str(stat) + " " + self.cafe.getStatusCodeAsString(stat))
+ _options['statusInfo'] = self.cafe.getStatusInfo(stat)
+ self.parent.trigger_log_message.emit(
+ MsgSeverity.ERROR.name, _pymodule, utils.line_no(),
+ _mess, _options)
+ '''
+
+ #Put values in dictionary for inspection
+ for i, (dict_key) in enumerate(self.pv_value_dict.keys()):
+ self.pv_value_dict[dict_key] = value_list[i]
+
+ if self.debug:
+ print ("EPICS PVS==>", self.pv_value_dict, flush=True)
+ print ("No of turns", self.pv_value_dict['nturns'])
+
return ambient_data
@@ -310,7 +364,7 @@ class AnalysisProcedure(QObject):
#sys.exit()
self.y1_pulse = (y1_peaks[1]['peak_heights'])
self.y2_pulse = (y2_peaks[1]['peak_heights'])
- print(type(self.y1_pulse), flush=True)
+
def measure(self):
@@ -344,7 +398,58 @@ class AnalysisProcedure(QObject):
self.y2_sample.append(float(val[2]))
t_inc += self.t_stepsize
- if self.simulation:
+ if not self.simulation:
+ #start DAQ
+ #Set
+ pv_daq_start = self.pv_dict['daqStart']
+ pv_daq_state = self.pv_dict['daqState']
+ pv_wf_entry = self.pv_dict['wfEntry']
+ pv_wf_exit = self.pv_dict['wfExit']
+ pv_wf = [pv_wf_entry, pv_wf_exit]
+
+ stat = self.cafe.set(pv_daq_start, 1)
+ self.check_status(_pymodule, "set", pv_daq_start, stat,
+ utils.line_no())
+
+ #Monitor DAQ State
+ start = time.time()
+
+ finished = False
+ while (time.time() - start) < self.daq_timeout:
+ value = self.cafe.getCache(pv_daq_state)
+ if value is None:
+ stat = self.cafe.getStatus(pv_daq_state)
+ self.check_status(_pymodule, "getCache", pv_daq_state, stat,
+ utils.line_no())
+ elif value == "DONE":
+ finished = True
+ break
+ if self.abort:
+ self.aborting(utils.line_no())
+ return None
+
+ time.sleep(1.0)
+
+ if not finished:
+ mess = ("DAQ not completed. Exceeded allowed " +
+ "time limit of {0}s".format(self.daq_timeout))
+ self.parent.trigger_log_message.emit(
+ MsgSeverity.ERROR.name, _pymodule, utils.line_no(),
+ mess, {})
+ return None
+
+ #Read WF from EPICS and fill sample y1_sample, y2_sample
+ (self.y1_sample, self.y2_sample), status, status_list = self.cafe.getCompoundList(
+ pv_wf, cacheFlag=True)
+ if status != self.cyca.ICAFE_NORMAL:
+ self.check_status_list(_pymodule, "getCompoundListCache",
+ pv_wf, status_list, utils.line_no())
+
+ return None
+
+
+
+ else:
self.parent.trigger_progressbar.emit(20)
print("open File", flush=True)
file = open('/hipa/bd/data/measurements/tina/20240710-223007_2000.txt','r')
@@ -361,6 +466,7 @@ class AnalysisProcedure(QObject):
print("close File", flush=True)
self.parent.trigger_progressbar.emit(60)
extract_raw_data()
+
self.extract_peak_data()
diff --git a/src/gui.py b/src/gui.py
index d44d142..6a9f73d 100644
--- a/src/gui.py
+++ b/src/gui.py
@@ -6,8 +6,8 @@ from qtpy.QtCore import __version__ as QT_VERSION_STR
from qtpy.QtCore import QEventLoop, Qt, QTimer, Slot
from qtpy.QtWidgets import (
QApplication, QGridLayout, QGroupBox, QHBoxLayout, QLabel, QMessageBox,
- QPushButton, QTabBar, QTabWidget, QTableWidgetItem, QTextEdit, QVBoxLayout,
- QWidget)
+ QPushButton, QStackedWidget, QTabBar, QTabWidget, QTableWidgetItem,
+ QTextEdit, QVBoxLayout, QWidget)
from common.packages import elog
@@ -30,10 +30,14 @@ class AppGui(QWidget):
self.parent = parent
self.cafe = self.parent.cafe
self.cyca = self.parent.cyca
+ self.settings = self.parent.settings
self.check_status = self.parent.check_status
self.check_status_list = self.parent.check_status_list
self.elog_enum = self.parent.elog_enum
+ self.accelerator_list = [self.parent.injector_2,
+ self.parent.ring_cyclotron]
+
self.send_to_log_window = self.parent.send_to_log_window
self.show_log_message = self.parent.show_log_message
self.statusbar = self.parent.statusbar
@@ -52,3 +56,81 @@ class AppGui(QWidget):
self.gui_frame.measurement_tab_wgt.setFixedHeight(460)
self.gui_frame.operator_wgt.setFixedHeight(640)
self.gui_frame.expert_wgt.setFixedHeight(240)
+
+ self.daq_wgt = self.daq_group_qtabwidget(widget_type="QStackedWidget")
+ self.gui_frame.measurement_layout.addWidget(
+ self.daq_wgt, 0, 1, 1, 1, alignment=Qt.AlignTop)
+
+ self.daq_wgt.setCurrentIndex(self.parent.default_idx)
+ self.daq_wgt.currentChanged.emit(self.parent.default_idx)
+
+ self.gui_frame.line_sender_dict[
+ 'accelerator'].currentChanged.connect(self.cb_accelerator)
+
+
+ def cb_accelerator(self, idx):
+ self.daq_wgt.setCurrentIndex(idx)
+
+ def daq_group_qtabwidget(self, widget_type="QStackedWidget"):
+ accel_wgt_dict = {}
+
+ if "QTabWidget" in widget_type:
+ accel_tab_widget = QTabWidget()
+ accel_tab_widget.setFont(self.font_gui)
+ accel_tab_widget.setStyleSheet("QTabBar {font-size: 10pt;}")
+ accel_tab_widget.tabBar().setShape(QTabBar.TriangularNorth)
+
+ for i, accel in enumerate(self.accelerator_list):
+ accel_wgt_dict[accel] = self.daq_group(accel)
+
+ accel_tab_widget.addTab(accel_wgt_dict[accel], accel)
+ color = self.settings.data['Parameters']['accelerator'][data][
+ 'color'][i]
+ accel_tab_widget.tabBar().setTabTextColor(i, QColor(color))
+
+ else:
+ accel_tab_widget = QStackedWidget()
+
+ for i, accel in enumerate(self.accelerator_list):
+ accel_wgt_dict[accel] = self.daq_group(accel)
+ accel_tab_widget.addWidget(accel_wgt_dict[accel])
+
+ accel_tab_widget.setFixedWidth(300)
+ accel_tab_widget.setFixedHeight(160)
+ return accel_tab_widget
+
+ def daq_group(self, accel):
+ group_box = QGroupBox("{0} DAQ".format(accel))
+ obj_name = "CYCLOTRON" if self.parent.ring_cyclotron in accel else \
+ "INJECTOR"
+ group_box.setObjectName(obj_name)
+ vbox = QGridLayout()
+ pv_daq = []
+ pv_daq.append(self.settings.data['PV'][accel]['daqStart'])
+ pv_daq.append(self.settings.data['PV'][accel]['daqState'])
+
+ self.cafe.openPrepare()
+ self.cafe.open(pv_daq)
+ self.cafe.openNowAndWait(1.0)
+
+ pv1 = CAQLabel(self, pv_name=pv_daq[0])
+ pv2 = CAQLabel(self, pv_name=pv_daq[1])
+ vbox.addWidget(QLabel('Start/Stop Status:'), 0, 0)
+ vbox.addWidget(QLabel('Acquisition State:'), 1, 0)
+ vbox.addWidget(pv1, 0, 1)
+ vbox.addWidget(pv2, 1, 1)
+ vbox.setContentsMargins(9, 19, 9, 9)
+ vbox.setSpacing(5)
+ vbox.setAlignment(Qt.AlignTop | Qt.AlignHCenter)
+ group_box.setFixedWidth(268)
+ group_box.setFixedHeight(100)
+ group_box.setFont(self.font_gui)
+ group_box.setAlignment(int(Qt.AlignTop | Qt.AlignHCenter))
+ group_box.setLayout(vbox)
+
+ qw = QWidget()
+ grid = QGridLayout()
+ grid.addWidget(group_box, 0, 0)
+ qw.setLayout(grid)
+
+ return qw
diff --git a/tina.json b/tina.json
index 0ec32d4..8f7a045 100755
--- a/tina.json
+++ b/tina.json
@@ -14,7 +14,19 @@
"addDateToDir" : 0
},
"header" : ["SHIFT", "INJ2", "IP2", "IW2", "PK1", "PK2", "SINQ", "UCN"],
- "PVnturns" : {"Injector": "PV-INJ:NTURNS", "Cyclotron": "PV-CYC:NTURNS"},
+ "PV" : {"Injector": {"nturns": "PV-INJ:NTURNS",
+ "daqStart": "PV-INJ:DAQ-START",
+ "daqState": "PV-INJ:DAQ-STATE",
+ "wfEntry": "PV-INJ:WF-ENTRY",
+ "wfExit": "PV-INJ:WF-EXIT"
+ },
+ "Cyclotron": {"nturns": "PV-CYC:NTURNS",
+ "daqStart": "PV-CYC:DAQ-START",
+ "daqState": "PV-CYC:DAQ-STATE",
+ "wfEntry": "PV-CYC:WF-ENTRY",
+ "wfExit": "PV-CYC:WF-EXIT"
+ }
+ },
"HIPA": ["Injector", "Ring"],
"HIPA2": {"test": ["Injector", "Ring"]},
"QTabAccelerator":{
@@ -35,18 +47,18 @@
"facility": {"flag": 0, "data" : {"widget": "QComboBox", "text" : "Facility:",
"link": ["HIPA"],"layout" : "Horizontal"}},
"freqrf" : {"flag": 1, "data":{ "widget": "QLineEdit", "text" :"RF Freq (10^6/s):", "value" : 50.6328 }},
- "freqsampling" : {"flag": 1, "data":{ "widget": "QLineRead", "text" :"Sampling Freq (GHz):", "value" : 2.5 }},
+ "freqsampling" : {"flag": 1, "data":{ "widget": "QLineRead", "text" :"Sampling Freq (GHz):", "value" : 3.0 }},
"drawLine" : {"flag" : 1, "data":{ "widget": "QHLine", "text" : "None", "value" : "None"}},
"accelerator" : {"flag" : 1, "data":{ "widget": "QTabWidget", "text" : "Accelerator: ",
"link" : "QTabAccelerator", "value" : 1,
- "color" : ["#0080aa", "#0000ff"]}}
+ "color" : ["#008b8b", "#0047ab" ]}}
},
"Expert":{
"debug": {"flag" : 1, "data":{ "widget": "None", "text" : "Debug", "value" : 0}},
- "simulation": {"flag" : 1, "data":{ "widget": "None", "text" : "Simulation", "value" : 1}}
+ "simulation": {"flag" : 1, "data":{ "widget": "None", "text" : "Oscilloscope", "value" : 1}}
},
"GUI": {
"resultsTabTitle" : "Plots",
diff --git a/tina.py b/tina.py
index 5ac9cba..9283740 100644
--- a/tina.py
+++ b/tina.py
@@ -13,7 +13,6 @@ from qtpy.QtWidgets import QApplication, QMessageBox
from apps4ops.bdbase.base import BaseWindow
from apps4ops.bdbase import h5_storage, utils
-#from apps4ops.bdbase.utils import _line
from apps4ops.bdbase.enumkind import Facility, MsgSeverity, UserMode
from apps4ops.bdbase.helpbrowser import HelpBrowser
from apps4ops.hipa.sendeloghipa import QSendToELOG
@@ -46,8 +45,11 @@ class StartMain(BaseWindow):
self.appname = _appname
self.source_file = _abspath #required for HDF
self.elog_enum = ElogHIPA()
-
- self.accelerator = self.ring_cyclotron #default
+ self.message_elog = None
+ self.default_idx = self.settings.data['Parameters']['accelerator'][
+ 'data']['value']
+ self.accelerator = self.ring_cyclotron if self.default_idx else \
+ self.injector_2
#self.from_hdf = False in base class
self.message = ""
self.gui = AppGui(self)
@@ -61,6 +63,7 @@ class StartMain(BaseWindow):
delay = self.all_data["Processed data"]["delay"]
except KeyError:
self.message = ""
+ self.message_elog = ""
return
try:
@@ -74,13 +77,22 @@ class StartMain(BaseWindow):
_mess = "Reanalysis from HDF5. " if self.from_hdf else ""
-
- self.message = (_mess +
+
+ self.message_elog = (
+ _mess +
'''
- The number of turns measured in the {0} = {1} ({2:.2f})
- lag = {3}, delay = {4:.3f} (\u00B5s)
- '''.format(self.accelerator, int(self.no_turns), self.no_turns,
- lag_full, delay*10**6))
+ No. turns measured in the {0} = {1} ({2:.2f})
+ lag = {3}, delay = {4:.3f} \u00B5s
'''.format(
+ self.accelerator, int(self.no_turns), self.no_turns,
+ lag_full, delay*10**6))
+
+ self.message = (
+ _mess +
+ '''
+ No. turns measured in the {0} = {1} ({2:.2f})
+ lag = {3}, delay = {4:.3f} \u00B5s'''.format(
+ self.accelerator, int(self.no_turns), self.no_turns,
+ lag_full, delay*10**6))
@@ -244,14 +256,14 @@ class StartMain(BaseWindow):
ortIdx=self.ort_idx,
effektIdx=self.effekt_idx,
title=self.title,
- message=self.message,
+ message=self.message_elog,
attachFile=self.attach_files)
time.sleep(0.5)
self.prepare_elog_message()
-
- print(self.message, flush=True)
+
+ print(self.message_elog, flush=True)
if not self.all_data:
QSendToELOG(self, logbook=self.logbook,
@@ -262,7 +274,7 @@ class StartMain(BaseWindow):
ortIdx=self.ort_idx,
effektIdx=self.effekt_idx,
title=self.title,
- message=self.message,
+ message=self.message_elog,
attachFile=self.attach_files)
return
@@ -303,7 +315,7 @@ class StartMain(BaseWindow):
debug = True
dry_run = False
nturns = int(self.no_turns)
- pv = self.settings.data["PVnturns"]["Cyclotron"]
+ pv = self.settings.data["PV"]["Cyclotron"]["nturns"]
dict_bunch[pv] = nturns
if not dry_run:
status, status_list = self.send_to_epics(dict_bunch)
@@ -372,7 +384,7 @@ if __name__ == "__main__":
app = QApplication(sys.argv)
splash = BaseWindow.initialize_application(
- app, appname=_appname, delay=20, facility=Facility.HIPA)
+ app, appname=_appname, delay=5, facility=Facility.HIPA)
myapp = StartMain()
diff --git a/tina.sh b/tina.sh
index 384de19..bbc3cb1 100755
--- a/tina.sh
+++ b/tina.sh
@@ -30,19 +30,19 @@ if [ "$1" ]; then
echo "Using default version $PYTHON_VERSION"
elif [ "$1" == "3.7" -o "$1" == "37" ]; then
PYTHON_VERSION=3.7
- PYTHON_PATH=.:/opt/gfa/cafe/python/pycafe/cafe-1.20.0-gcc-7.3.0/lib/${_EPICS_HOST_ARCH}:/hipa/bd/applications/deps/apps4ops/v1.11.0
+ PYTHON_PATH=.:/opt/gfa/cafe/python/pycafe/cafe-1.20.0-gcc-7.3.0/lib/${_EPICS_HOST_ARCH}:/hipa/bd/applications/deps/apps4ops/v1.12.0
module unload gcc
module load gcc/7.3.0
elif [ "$1" == "3.8" -o "$1" == "38" ]; then
PYTHON_VERSION=3.8
- PYTHON_PATH=.:/opt/gfa/cafe/python/pycafe/cafe-1.19.3/lib/${_EPICS_HOST_ARCH}:/hipa/bd/applications/deps/apps4ops/v1.11.0
+ PYTHON_PATH=.:/opt/gfa/cafe/python/pycafe/cafe-1.19.3/lib/${_EPICS_HOST_ARCH}:/hipa/bd/applications/deps/apps4ops/v1.12.0
module unload gcc
module load gcc/7.5.0
elif [ "$1" == "3.10" -o "$1" == "310" ]; then
PYTHON_VERSION=3.10
- PYTHON_PATH=.:/opt/gfa/cafe/python/pycafe/cafe-1.20.0-gcc-7.5.0/lib/${_EPICS_HOST_ARCH}:/hipa/bd/applications/deps/apps4ops/v1.11.0
+ PYTHON_PATH=.:/opt/gfa/cafe/python/pycafe/cafe-1.20.0-gcc-7.5.0/lib/${_EPICS_HOST_ARCH}:/hipa/bd/applications/deps/apps4ops/v1.12.0
module unload gcc
module load gcc/7.5.0
else