From 850628cc569edb7d0d2ceab5e0153c6be4b9a0cc Mon Sep 17 00:00:00 2001 From: root Date: Mon, 6 Oct 2025 10:43:36 +0200 Subject: [PATCH] October 2025 --- configuration/camera_config/ABODI-SRM-6.json | 26 +++ .../camera_config/X01DD-ES-CAM1.json | 8 +- .../pipeline_config/ABODI-SRM-6_sp.json | 12 ++ .../pipeline_config/X01DD-ES-CAM1_sp.json | 10 +- .../pipeline_config/X01DD-FE-CAM1_proc.json | 3 +- .../pipeline_config/X08DB-FE-CAM1_proc.json | 1 + configuration/pipeline_config/servers.json | 3 +- .../user_scripts/epics_forwarder_gr.py | 153 ++++++++++-------- configuration/user_scripts/pipolar.py | 66 ++------ configuration/user_scripts/sp_pipolar.py | 2 +- 10 files changed, 156 insertions(+), 128 deletions(-) create mode 100644 configuration/camera_config/ABODI-SRM-6.json create mode 100644 configuration/pipeline_config/ABODI-SRM-6_sp.json diff --git a/configuration/camera_config/ABODI-SRM-6.json b/configuration/camera_config/ABODI-SRM-6.json new file mode 100644 index 0000000..1e43720 --- /dev/null +++ b/configuration/camera_config/ABODI-SRM-6.json @@ -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" + ] +} \ No newline at end of file diff --git a/configuration/camera_config/X01DD-ES-CAM1.json b/configuration/camera_config/X01DD-ES-CAM1.json index 4a7cdac..2c93a67 100644 --- a/configuration/camera_config/X01DD-ES-CAM1.json +++ b/configuration/camera_config/X01DD-ES-CAM1.json @@ -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 }, diff --git a/configuration/pipeline_config/ABODI-SRM-6_sp.json b/configuration/pipeline_config/ABODI-SRM-6_sp.json new file mode 100644 index 0000000..75f7f73 --- /dev/null +++ b/configuration/pipeline_config/ABODI-SRM-6_sp.json @@ -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 +} \ No newline at end of file diff --git a/configuration/pipeline_config/X01DD-ES-CAM1_sp.json b/configuration/pipeline_config/X01DD-ES-CAM1_sp.json index cfcd6bb..f16fd88 100644 --- a/configuration/pipeline_config/X01DD-ES-CAM1_sp.json +++ b/configuration/pipeline_config/X01DD-ES-CAM1_sp.json @@ -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, diff --git a/configuration/pipeline_config/X01DD-FE-CAM1_proc.json b/configuration/pipeline_config/X01DD-FE-CAM1_proc.json index c686c04..a8a5a27 100644 --- a/configuration/pipeline_config/X01DD-FE-CAM1_proc.json +++ b/configuration/pipeline_config/X01DD-FE-CAM1_proc.json @@ -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 } \ No newline at end of file diff --git a/configuration/pipeline_config/X08DB-FE-CAM1_proc.json b/configuration/pipeline_config/X08DB-FE-CAM1_proc.json index 14b2da6..75e3e26 100644 --- a/configuration/pipeline_config/X08DB-FE-CAM1_proc.json +++ b/configuration/pipeline_config/X08DB-FE-CAM1_proc.json @@ -14,5 +14,6 @@ "name": "X08DB-FE-CAM1_proc", "max_frame_rate": 10.1, "throw_epics_errors": true, + "single_optics": true, "reload": true } \ No newline at end of file diff --git a/configuration/pipeline_config/servers.json b/configuration/pipeline_config/servers.json index ebf9f40..139714c 100644 --- a/configuration/pipeline_config/servers.json +++ b/configuration/pipeline_config/servers.json @@ -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, diff --git a/configuration/user_scripts/epics_forwarder_gr.py b/configuration/user_scripts/epics_forwarder_gr.py index c2bfab3..c8b4d9a 100644 --- a/configuration/user_scripts/epics_forwarder_gr.py +++ b/configuration/user_scripts/epics_forwarder_gr.py @@ -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 diff --git a/configuration/user_scripts/pipolar.py b/configuration/user_scripts/pipolar.py index 45312d3..34514f8 100644 --- a/configuration/user_scripts/pipolar.py +++ b/configuration/user_scripts/pipolar.py @@ -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 diff --git a/configuration/user_scripts/sp_pipolar.py b/configuration/user_scripts/sp_pipolar.py index b48c69b..6ae9a5f 100644 --- a/configuration/user_scripts/sp_pipolar.py +++ b/configuration/user_scripts/sp_pipolar.py @@ -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 \ No newline at end of file