Files
camserver_sls/configuration/user_scripts/epics_forwarder.py

105 lines
3.8 KiB
Python

from cam_server.utils import create_thread_pvs, epics_lock
from logging import getLogger
import math
import json
_logger = getLogger(__name__)
#Relevant parameters
# good_region #if False does not use values of good region, even if present
#Output PVs
x_pos_pv, y_pos_pv, x_sig_pv, y_sig_pv = None, None, None, None
x_amp_pv, y_amp_pv, x_int_pv, y_int_pv = None, None, None, None
#Channel names
x_pos_name, y_pos_name, x_sig_name, y_sig_name = None, None, None, None
x_amp_name, y_amp_name, x_int_name, y_int_name = None, None, None, None
sent_pid = -1
initialized = False
run_once = False
GAUSS_INT_FACTOR = math.sqrt(2 * math.pi)
def hypot_diff(a, b):
try:
return math.sqrt(a ** 2 - b ** 2)
except:
return 0.0
def initialize(parameters, data):
global initialized
global x_pos_name, y_pos_name, x_sig_name, y_sig_name, x_amp_name, y_amp_name, x_int_name, y_int_name
processing_parameters = json.loads(data["processing_parameters"])
prefix = processing_parameters["camera_name"]
x_pos_name = prefix + ":POS-X"
y_pos_name = prefix + ":POS-Y"
x_sig_name = prefix + ":SIG-X"
y_sig_name = prefix + ":SIG-Y"
x_amp_name = prefix + ":AMPL-X"
y_amp_name = prefix + ":AMPL-Y"
x_int_name = prefix + ":INTEG-X"
y_int_name = prefix + ":INTEG-Y"
initialized = True
def process(data, pulse_id, timestamp, parameters):
global initialized, sent_pid, run_once
global x_pos_pv, y_pos_pv, x_sig_pv, y_sig_pv, x_amp_pv, y_amp_pv, x_int_pv, y_int_pv
global x_pos_name, y_pos_name, x_sig_name, y_sig_name, x_amp_name, y_amp_name, x_int_name, y_int_name
ret = data
if not initialized:
initialize(parameters, data)
initialized = True
good_region = parameters.get("good_region", True) and "gr_x_fit_mean" in ret
if good_region:
x_pos_key, y_pos_key = "gr_x_fit_mean", "gr_y_fit_mean"
x_sig_key, y_sig_key = "gr_x_fit_standard_deviation", "gr_y_fit_standard_deviation"
x_amp_key, y_amp_key = "gr_x_fit_amplitude", "gr_y_fit_amplitude"
else:
x_pos_key, y_pos_key = "x_fit_mean", "y_fit_mean"
x_sig_key, y_sig_key = "x_fit_standard_deviation", "y_fit_standard_deviation"
x_amp_key, y_amp_key = "x_fit_amplitude", "y_fit_amplitude"
x_pos, y_pos = ret[x_pos_key], ret[y_pos_key]
x_sig, y_sig = ret[x_sig_key], ret[y_sig_key]
x_amp, y_amp = ret[x_amp_key], ret[y_amp_key]
x_int, y_int = x_amp * x_sig * GAUSS_INT_FACTOR, y_amp * y_sig * GAUSS_INT_FACTOR
x_pos_pv, y_pos_pv, x_sig_pv, y_sig_pv, x_amp_pv, y_amp_pv, x_int_pv, y_int_pv = create_thread_pvs(
[x_pos_name, y_pos_name, x_sig_name, y_sig_name, x_amp_name, y_amp_name, x_int_name, y_int_name])
epics_error = None
if pulse_id > sent_pid:
sent_pid = pulse_id
if epics_lock.acquire(False):
try:
for (pv, value) in [(x_pos_pv, x_pos), (y_pos_pv, y_pos), (x_sig_pv, x_sig), (y_sig_pv, y_sig),
(x_amp_pv, x_amp), (y_amp_pv, y_amp), (x_int_pv, x_int), (y_int_pv, y_int)]:
if pv and pv.connected:
pv.put(value)
else:
if not run_once:
_logger.warning("PV not connected: %s" % (str(pv),))
except Exception as e:
epics_error = "Error writing PVs: %s" % (str(e),)
finally:
epics_lock.release()
else:
_logger.warning("Cannot aquire EPICS lock")
if epics_error:
_logger.warning(epics_error)
raise Exception(epics_error)
run_once = True
else:
_logger.warning("Invalid PID: %s last:%s" % (str(pulse_id), str(sent_pid),))
sent_pid = 0 # It should be single threaded, assumes the camera instance restarted
return ret