October 2025

This commit is contained in:
root
2025-10-06 10:43:36 +02:00
parent dc80177db2
commit 850628cc56
10 changed files with 156 additions and 128 deletions

View File

@@ -0,0 +1,26 @@
{
"camera_calibration": {
"reference_marker": [
100,
100,
1999,
1999
],
"reference_marker_width": 30000.0,
"reference_marker_height": 30000.0,
"angle_horizontal": 0.0,
"angle_vertical": 0.0
},
"mirror_x": false,
"mirror_y": false,
"rotate": 0,
"roi": null,
"image_background": null,
"source_type": "epics",
"prefix": "ABODI-SRM-6",
"name": "ABODI-SRM-6",
"source": "ABODI-SRM-6",
"group": [
"Booster"
]
}

View File

@@ -3,11 +3,11 @@
"reference_marker": [
10,
10,
72,
72
134,
134
],
"reference_marker_width": 170.0,
"reference_marker_height": 170.0,
"reference_marker_width": 340.0,
"reference_marker_height": 340.0,
"angle_horizontal": 0.0,
"angle_vertical": 0.0
},

View File

@@ -0,0 +1,12 @@
{
"image_background_enable": false,
"image_background": null,
"image_threshold": null,
"image_region_of_interest": null,
"image_good_region": null,
"image_slices": null,
"pipeline_type": "processing",
"camera_name": "ABODI-SRM-6",
"name": "ABODI-SRM-6_sp",
"max_frame_rate": 10.1
}

View File

@@ -11,16 +11,16 @@
"camera_name": "X01DD-ES-CAM1",
"function": "sp_pipolar",
"fit": {
"height": 2181,
"width": 2832,
"delta_height": 40000,
"height": 1532,
"width": 2112,
"delta_height": 60000,
"bg_range_low": [
0,
200
],
"bg_range_high": [
2631,
2831
1921,
2121
],
"peak_search_rel_range": [
-2,

View File

@@ -12,7 +12,8 @@
"camera_name": "X01DD-FE-CAM1",
"function": "epics_forwarder_gr.py",
"name": "X01DD-FE-CAM1_proc",
"max_frame_rate": 10.1,
"max_output_rate": 10.1,
"throw_epics_errors": true,
"single_optics": true,
"reload": true
}

View File

@@ -14,5 +14,6 @@
"name": "X08DB-FE-CAM1_proc",
"max_frame_rate": 10.1,
"throw_epics_errors": true,
"single_optics": true,
"reload": true
}

View File

@@ -53,7 +53,8 @@
"ARS05-RCAM-0230",
"ARS05-RCAM-0310",
"X08DB-FE-CAM1",
"X08DB-FE-CAM2"
"X08DB-FE-CAM2",
"ABODI-SRM-6"
],
"enabled": true,
"expanding": false,

View File

@@ -1,6 +1,6 @@
import sys
import os
from cam_server.pipeline.data_processing import functions, processor
from cam_server.pipeline.data_processing import functions, processor
from collections import OrderedDict
from cam_server.pipeline.data_processing import functions
from cam_server.utils import create_thread_pvs, epics_lock
@@ -16,8 +16,11 @@ 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
PSF = 2.91 # um
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
@@ -25,84 +28,100 @@ def initialize(parameters):
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"
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 hypot_diff(a, b):
return math.sqrt(a**2 - b**2)
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
prefix = parameters["camera_name"]
single_optics = parameters.get("single_optics", False)
if not initialized:
initialize(parameters)
initialized = True
r = processor.process_image(image, pulse_id, timestamp, x_axis, y_axis, parameters, bsdata)
r = processor.process_image(image, pulse_id, timestamp, x_axis, y_axis, parameters, bsdata)
ret = OrderedDict()
x_fit_integ = r["gr_x_fit_amplitude"] * r["gr_x_fit_standard_deviation"] * math.sqrt(2*math.pi)
y_fit_integ = r["gr_y_fit_amplitude"] * r["gr_y_fit_standard_deviation"] * math.sqrt(2*math.pi)
ret[prefix+":intensity"] = r["intensity"]
ret[prefix+":x_fit_mean"] = r["x_fit_mean"]
ret[prefix+":y_fit_mean"] = r["y_fit_mean"]
ret[prefix+":x_fit_standard_deviation"] = r["x_fit_standard_deviation"]
ret[prefix+":y_fit_standard_deviation"] = r["y_fit_standard_deviation"]
ret[prefix+":x_center_of_mass"] = r["x_center_of_mass"]
ret[prefix+":y_center_of_mass"] = r["y_center_of_mass"]
ret[prefix+":x_rms"] = r["x_rms"]
ret[prefix+":y_rms"] = r["y_rms"]
ret[prefix+":x_fwhm"] = r["x_fwhm"]
ret[prefix+":y_fwhm"] = r["y_fwhm"]
ret[prefix+":x_fit_amplitude"] = r["x_fit_amplitude"]
ret[prefix+":y_fit_amplitude"] = r["y_fit_amplitude"]
ret[prefix+":x_fit_integ"] = x_fit_integ
ret[prefix+":y_fit_integ"] = y_fit_integ
ret[prefix+":gr_x_fit_mean"] = r["gr_x_fit_mean"]
ret[prefix+":gr_y_fit_mean"] = r["gr_y_fit_mean"]
ret[prefix+":gr_x_fit_standard_deviation"] = r["gr_x_fit_standard_deviation"]
ret[prefix+":gr_y_fit_standard_deviation"] = r["gr_y_fit_standard_deviation"]
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])
x_fit_integ = r["gr_x_fit_amplitude"] * r["gr_x_fit_standard_deviation"] * math.sqrt(2 * math.pi)
y_fit_integ = r["gr_y_fit_amplitude"] * r["gr_y_fit_standard_deviation"] * math.sqrt(2 * math.pi)
ret[prefix + ":intensity"] = r["intensity"]
ret[prefix + ":x_fit_mean"] = r["x_fit_mean"]
ret[prefix + ":y_fit_mean"] = r["y_fit_mean"]
if single_optics:
ret[prefix + ":x_fit_standard_deviation"] = hypot_diff(r["x_fit_standard_deviation"], PSF)
else:
ret[prefix + ":x_fit_standard_deviation"] = r["x_fit_standard_deviation"]
if single_optics:
ret[prefix + ":y_fit_standard_deviation"] = hypot_diff(r["y_fit_standard_deviation"], PSF)
else:
ret[prefix + ":y_fit_standard_deviation"] = r["y_fit_standard_deviation"]
ret[prefix + ":x_center_of_mass"] = r["x_center_of_mass"]
ret[prefix + ":y_center_of_mass"] = r["y_center_of_mass"]
ret[prefix + ":x_rms"] = r["x_rms"]
ret[prefix + ":y_rms"] = r["y_rms"]
ret[prefix + ":x_fwhm"] = r["x_fwhm"]
ret[prefix + ":y_fwhm"] = r["y_fwhm"]
ret[prefix + ":x_fit_amplitude"] = r["x_fit_amplitude"]
ret[prefix + ":y_fit_amplitude"] = r["y_fit_amplitude"]
ret[prefix + ":x_fit_integ"] = x_fit_integ
ret[prefix + ":y_fit_integ"] = y_fit_integ
ret[prefix + ":gr_x_fit_mean"] = r["gr_x_fit_mean"]
ret[prefix + ":gr_y_fit_mean"] = r["gr_y_fit_mean"]
if single_optics:
ret[prefix + ":gr_x_fit_standard_deviation"] = hypot_diff(r["gr_x_fit_standard_deviation"], PSF)
else:
ret[prefix + ":gr_x_fit_standard_deviation"] = r["gr_x_fit_standard_deviation"]
if single_optics:
ret[prefix + ":gr_y_fit_standard_deviation"] = hypot_diff(r["gr_y_fit_standard_deviation"], PSF)
else:
ret[prefix + ":gr_y_fit_standard_deviation"] = r["gr_y_fit_standard_deviation"]
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, r["gr_x_fit_mean"]), \
(mean_y_pv, r["gr_y_fit_mean"]), \
(sig_x_pv, r["gr_x_fit_standard_deviation"]), \
(sig_y_pv, r["gr_y_fit_standard_deviation"]), \
(ampl_x_pv, r["gr_x_fit_amplitude"]), \
(ampl_y_pv, r["gr_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
sent_pid = pulse_id
if epics_lock.acquire(False):
try:
for (pv, value) in [(mean_x_pv, r["gr_x_fit_mean"]), \
(mean_y_pv, r["gr_y_fit_mean"]), \
(sig_x_pv, ret[prefix + ":gr_x_fit_standard_deviation"]), \
(sig_y_pv, ret[prefix + ":gr_y_fit_standard_deviation"]), \
(ampl_x_pv, r["gr_x_fit_amplitude"]), \
(ampl_y_pv, r["gr_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

View File

@@ -22,50 +22,13 @@ class PpolPeakValley():
self.x, self.y = self.ppol_interpol()
def ppol_interpol(self, plot_flag=False):
# ipv = [32.98,20.85,15.31,12.12,10.05,8.60,7.52,6.69,6.028,5.49,5.047,4.67,4.35,4.078,3.84,3.44,3.12,2.87,2.65,2.47,2.32]
#ipv = [0.0, 32.976, 20.848, 15.306, 12.121, 10.050, 8.595, 7.518, 6.687, 6.028, 5.491, 5.047, 4.673, 4.353, 4.078, 3.837, 3.439, 3.122, 2.865, 2.652, 2.473, 2.320]
#sig = [0.0, 3.659, 5.175, 6.338, 7.318, 8.182, 8.963, 9.681, 10.350, 10.978, 11.572, 12.136, 12.676, 13.194, 13.692, 14.172, 15.087, 15.950, 16.769, 17.549, 18.296, 19.014]
ipv = [0.032771623, 0.045653159, 0.058377743, 0.070933335, 0.083347283, 0.095648417, 0.107858216, 0.119990516,
0.132053213, 0.144050065, 0.155982387, 0.167849814, 0.179651077, 0.19138435, 0.203047604, 0.22615558,
0.248958238, 0.271440041, 0.293587065, 0.315386908, 0.33682858]
sig = [3.66, 5.18, 6.34, 7.32, 8.18, 8.96, 9.68, 10.35, 10.98, 11.57, 12.14, 12.68, 13.19, 13.69, 14.17, 15.09,
15.95, 16.77, 17.55, 18.30, 19.014]
sig2 = [element * element for element in sig]
x = np.linspace(0, 999999, 999999)
x = [(1 + val) / 1000000 * max(ipv) for val in x]
interpfunc = interpolate.interp1d(ipv, sig2, kind='quadratic')
inter_x = interpfunc(x)
sqrt_val = [math.sqrt(val) for val in inter_x]
y = [0]
y.extend(sqrt_val)
y.append(max(sig))
xf = [0]
xf.extend(x)
xf.append(max(ipv))
return xf, y
def get_emittance(self, ratio):
emittance = 0
for i in range(0, len(self.x)):
if self.x[i] > ratio:
self.y[i - 1]
return self.y[i - 1]
# For peak search - delta(h) to max peak value
DELTA_HEIGHT = 400 # 400
BG_XRANGE_LOW = [340, 400] # 100 160 [340, 400]
BG_XRANGE_HIGH = [460, 520] # 840 900 [460, 520]
PEAK_SEARCH_REL_RANGE = [-1, 2]
VALLEY_SEARCH_REL_RANGE = [-2, 3]
class PpolPeakValley():
def __init__(self):
self.x, self.y = self.ppol_interpol()
def ppol_interpol(self, plot_flag=False):
ipv = [0.0, 32.976, 20.848, 15.306, 12.121, 10.050, 8.595, 7.518, 6.687, 6.028, 5.491, 5.047, 4.673, 4.353, 4.078, 3.837, 3.439, 3.122, 2.865, 2.652, 2.473, 2.320]
sig = [0.0, 3.659, 5.175, 6.338, 7.318, 8.182, 8.963, 9.681, 10.350, 10.978, 11.572, 12.136, 12.676, 13.194, 13.692, 14.172, 15.087, 15.950, 16.769, 17.549, 18.296, 19.014]
15.95, 16.77, 17.55, 18.30, 19.014]
sig2 = [element * element for element in sig]
x = np.linspace(0, 999999, 999999)
x = [(1+val)/1000000*max(ipv) for val in x]
@@ -88,11 +51,11 @@ class PpolPeakValley():
return self.y[i-1]
#For peak search - delta(h) to max peak value
DELTA_HEIGHT = 400
BG_XRANGE_LOW = [340, 400] #100 160
BG_XRANGE_HIGH = [460, 520] #840 900
DELTA_HEIGHT = 60000
BG_XRANGE_LOW = [0, 400]
BG_XRANGE_HIGH = [1921, 2112]
PEAK_SEARCH_REL_RANGE = [-1, 2]
PEAK_SEARCH_REL_RANGE = [-2, 3]
VALLEY_SEARCH_REL_RANGE = [-2, 3]
ppol = PpolPeakValley()
@@ -226,7 +189,7 @@ def calculate_emittance(image, fit_pars):
poly = np.polyfit(valley_array, proj_valley, deg=4)
valley_subarray = np.linspace(valley_array[0], valley_array[-1], 800)
valley_subarray = np.linspace(valley_array[0], valley_array[-1], 800)
poly_array = np.polyval(poly, valley_subarray)
valley_fitted_value = min(poly_array)
@@ -242,11 +205,15 @@ def calculate_emittance(image, fit_pars):
# raise Exception("valley_fitted_value < valley_bg")
# #return
ratio_corrected = 2 * (valley_fitted_value - valley_bg) / (
abs((peak_value[0] - peak_bg[0]) + (peak_value[1] - peak_bg[1])))
#ratio_corrected = 2 * (valley_fitted_value - valley_bg) / (
# abs((peak_value[0] - peak_bg[0]) + (peak_value[1] - peak_bg[1])))
idx = 0 if abs(peak_value[0] - peak_bg[0]) > abs(peak_value[1] - peak_bg[1]) else 1
ratio_max = (valley_fitted_value - valley_bg) / abs(peak_value[idx] - peak_bg[idx])
#idx = 0 if abs(peak_value[0] - peak_bg[0]) > abs(peak_value[1] - peak_bg[1]) else 1
#ratio_max = (valley_fitted_value - valley_bg) / abs(peak_value[idx] - peak_bg[idx])
ratio_corrected = 2 * (valley_fitted_value) / (abs(peak_value[0] + peak_value[1]))
idx = 0 if abs(peak_value[0] ) > abs(peak_value[1] ) else 1
ratio_max = 0.33 # abs(peak_value[idx]) #valley_fitted_value /
emittance = ppol.get_emittance(ratio_corrected)
emittance2 = ppol.get_emittance(ratio_max)
@@ -276,4 +243,5 @@ def process_image(image, pulse_id, timestamp, x_axis, y_axis, parameters, bsdata
ret[channel_prefix + ":emmitance"] = emittance
ret[channel_prefix + ":emmitance2"] = emittance2
ret[channel_prefix + ":status"] = str(status)
return ret

View File

@@ -28,5 +28,5 @@ def process_image(image, pulse_id, timestamp, x_axis, y_axis, parameters, bsdata
ret["y_fit_standard_deviation_orig"] = ret["y_fit_standard_deviation"]
ret["y_fit_standard_deviation"] = emittance
return ret