Files
camserver_sls/configuration/user_scripts/epics_forwarder.py
2025-08-12 11:34:04 +02:00

107 lines
4.9 KiB
Python

from collections import OrderedDict
from cam_server.pipeline.data_processing import functions
from cam_server.utils import create_thread_pvs, epics_lock
from logging import getLogger
import math
_logger = getLogger(__name__)
mean_x_pv, mean_y_pv, sig_x_pv, sig_y_pv = None, None, None, None
mean_x_name, mean_y_name, sig_x_name, sig_y_name = None, None, None, None
ampl_x_pv, ampl_y_pv, integ_x_pv, integ_y_pv = None, None, None, None
ampl_x_name, ampl_y_name, integ_x_name, integ_y_name = None, None, None, None
sent_pid = -1
throw_epics_errors = False
initialized = False
def initialize(parameters):
global initialized
global mean_x_name, mean_y_name, sig_x_name, sig_y_name, ampl_x_name, ampl_y_name, integ_x_name, integ_y_name
prefix = parameters["camera_name"]
mean_x_name = prefix + ":POS-X"
mean_y_name = prefix + ":POS-Y"
sig_x_name = prefix + ":SIG-X"
sig_y_name = prefix + ":SIG-Y"
ampl_x_name = prefix + ":AMPL-X"
ampl_y_name = prefix + ":AMPL-Y"
integ_x_name = prefix + ":INTEG-X"
integ_y_name = prefix + ":INTEG-Y"
initialized = True
def process_image(image, pulse_id, timestamp, x_axis, y_axis, parameters, bsdata):
global initialized, sent_pid
global mean_x_pv, mean_y_pv, sig_x_pv, sig_y_pv, ampl_x_pv, ampl_y_pv, integ_x_pv, integ_y_pv
global mean_x_name, mean_y_name, sig_x_name, sig_y_name, ampl_x_name, ampl_y_name, integ_x_name, integ_y_name
if not initialized:
initialize(parameters)
initialized = True
ret = OrderedDict()
throw_epics_errors = parameters.get("throw_epics_errors", True)
prefix = parameters["camera_name"]
(x_profile, y_profile) = functions.get_x_y_profile(image)
x_fit_gauss_function, x_fit_offset, x_fit_amplitude, x_fit_mean, x_fit_standard_deviation, x_center_of_mass, x_rms = functions.gauss_fit(x_profile, x_axis)
y_fit_gauss_function, y_fit_offset, y_fit_amplitude, y_fit_mean, y_fit_standard_deviation, y_center_of_mass, y_rms = functions.gauss_fit(y_profile, y_axis)
x_fwhm = functions.get_fw(x_axis,x_profile)
y_fwhm = functions.get_fw(y_axis,y_profile)
intensity = x_profile.sum()
x_fit_integ = x_fit_amplitude * x_fit_standard_deviation * math.sqrt(2*math.pi)
y_fit_integ = y_fit_amplitude * y_fit_standard_deviation * math.sqrt(2*math.pi)
ret[prefix+":intensity"] = intensity
ret[prefix+":x_fit_mean"] = x_fit_mean
ret[prefix+":y_fit_mean"] = y_fit_mean
ret[prefix+":x_fit_standard_deviation"] = x_fit_standard_deviation
ret[prefix+":y_fit_standard_deviation"] = y_fit_standard_deviation
ret[prefix+":x_center_of_mass"] = x_center_of_mass
ret[prefix+":y_center_of_mass"] = y_center_of_mass
ret[prefix+":x_rms"] = x_rms
ret[prefix+":y_rms"] = y_rms
ret[prefix+":x_fwhm"] = x_fwhm
ret[prefix+":y_fwhm"] = y_fwhm
ret[prefix+":x_fit_amplitude"] = x_fit_amplitude
ret[prefix+":y_fit_amplitude"] = y_fit_amplitude
ret[prefix+":x_fit_integ"] = x_fit_integ
ret[prefix+":y_fit_integ"] = y_fit_integ
mean_x_pv, mean_y_pv, sig_x_pv, sig_y_pv, ampl_x_pv, ampl_y_pv, integ_x_pv, integ_y_pv = create_thread_pvs([mean_x_name, mean_y_name, sig_x_name, sig_y_name, ampl_x_name, ampl_y_name, integ_x_name, integ_y_name])
epics_error = None
if pulse_id > sent_pid:
sent_pid = pulse_id
if epics_lock.acquire(False):
try:
for (pv, value) in [ (mean_x_pv, x_fit_mean), \
(mean_y_pv, y_fit_mean), \
(sig_x_pv, x_fit_standard_deviation), \
(sig_y_pv, y_fit_standard_deviation), \
(ampl_x_pv, x_fit_amplitude), \
(ampl_y_pv, y_fit_amplitude), \
(integ_x_pv, x_fit_integ), \
(integ_y_pv, y_fit_integ) \
]:
if pv and pv.connected:
pv.put(value)
else:
_logger.warning("PV not connected: %s" % (str(pv),))
#epics_error = "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)
if throw_epics_errors:
raise Exception(epics_error)
return ret
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