From 9c8fab641d3b965e49ae4b484621839ba1378c62 Mon Sep 17 00:00:00 2001 From: x10sa Date: Wed, 24 Jun 2026 12:37:40 +0200 Subject: [PATCH 1/9] adds method to save new device positions --- pxii_bec/device_configs/pxii-devices.yaml | 16 +- pxii_bec/macros/APscripts.py | 139 +++++----- pxii_bec/macros/KB_Class.py | 13 +- pxii_bec/macros/build_devices.py | 298 +++++++++++++++++++--- pxii_bec/macros/devices_manager.py | 6 +- pxii_bec/macros/init_beamline.py | 5 +- pxii_bec/macros/pxii_energy.py | 40 ++- pxii_bec/macros/pxii_parameters.py | 1 + 8 files changed, 386 insertions(+), 132 deletions(-) diff --git a/pxii_bec/device_configs/pxii-devices.yaml b/pxii_bec/device_configs/pxii-devices.yaml index 6159d25..26a654b 100644 --- a/pxii_bec/device_configs/pxii-devices.yaml +++ b/pxii_bec/device_configs/pxii-devices.yaml @@ -70,8 +70,8 @@ aerotech: out: -10 safe: -50 y: - mount: 0 - work: 0 + mount: -0.0 + work: -0.16 z: mount: 0 work: 0 @@ -292,7 +292,7 @@ bs_x: onFailure: buffer readoutPriority: baseline userParameter: - in: 1.64 + in: 1.9 bs_y: description: Beamstop Y deviceClass: ophyd_devices.EpicsMotor @@ -433,6 +433,8 @@ coll_x: enabled: true onFailure: buffer readoutPriority: baseline + userParameter: + in: 0.0 coll_y: description: Collimator Y deviceClass: ophyd_devices.EpicsMotor @@ -444,9 +446,9 @@ coll_y: onFailure: buffer readoutPriority: baseline userParameter: - in: 40.9 + in: 40.834 intermediate: 32 - out: 20.0 + out: 19.0 park: 1 tol: 0.05 type: continuous @@ -1248,7 +1250,7 @@ samcam_x: enabled: true onFailure: buffer readOnly: true - readoutPriority: baseline + readoutPriority: monitored samcam_xsig: description: Sample Camera X Sigma deviceClass: ophyd.EpicsSignalRO @@ -1272,7 +1274,7 @@ samcam_y: enabled: true onFailure: buffer readOnly: true - readoutPriority: baseline + readoutPriority: monitored samcam_ysig: description: Sample Camera Y Sigma deviceClass: ophyd.EpicsSignalRO diff --git a/pxii_bec/macros/APscripts.py b/pxii_bec/macros/APscripts.py index 53378c8..f585989 100644 --- a/pxii_bec/macros/APscripts.py +++ b/pxii_bec/macros/APscripts.py @@ -240,11 +240,8 @@ def rock(**kwargs): - - - ################################ -### Help PROGRAMS +### Helper PROGRAMS ############################# ### just reconfigure beaml @@ -276,46 +273,41 @@ def justfit(data_x, data_y, model="gauss", ibg=0): from lmfit.models import LinearModel, GaussianModel, VoigtModel, QuadraticModel, LorentzianModel import matplotlib.pyplot as plt - peak = GaussianModel() + peak = GaussianModel(prefix = 'g_') + pre='g' if model == "voigt": - peak = VoigtModel() + peak = VoigtModel(prefix = 'v_') + pre='v' if model == "lorentz": - peak = LorentzianModel() - model = peak + peak = LorentzianModel(prefix = 'l_') + pre='l' + model = peak + ypeak = data_y + pars = model.guess(data_y, x = data_x) + indmax = np.argmax(ypeak) + xm = data_x[indmax] + if ibg: - # add a BG - background = LinearModel() - if ibg > 1: - background = QuadraticModel() + background = LinearModel(prefix = 'bg_') model = peak + background - ### define data_x and data_y: - maxy = max(data_y) - indmax = np.argmax(data_y) - xm = data_x[indmax] - sigma = 1.0 - gamma = 0.2 # blurring/widening of the sigma ; the larger, the more of a Lorentzian profile + ### estimate initial params separately for both parts of the model + # 1) BG + n = len(data_x) + edge= n//10 + idx=np.r_[0:edge, n-edge:n] # first and last part of the range + #m0, b0 = np.polyfit(data_x[idx], data_y[idx],1) + #ypeak= data_y - (m0*data_x + b0) # subtract linear part - ## possible, but not necessarily better ... : - # sl = 0.00001 * (data_y[-2]-data_y[2])/(data_x[-2]-data_x[2]) # small slope - # ic = min(data_y) - # print(f'slope and intercept initial conds= {sl, ic}') - ## - print("maxy, indmax, xm = ", maxy, indmax, xm) + pars = background.guess(data_y[idx], x = data_x[idx]) + + # 2) Function - BG + ypeak= data_y - (pars['bg_slope']*data_x + pars['bg_intercept'])# subtract linear part + pars.update( peak.guess(ypeak, x= data_x) ) + - p = model.make_params(amplitude=maxy, center=xm) - # other possibilities ... : - # p = model.make_params(amplitude = maxy, center=xm , slope=0, intercept = ic) - # p = model.make_params(amplitude = max(data_y), center=xm, slope=0, intercept = min(data_y)) - - p["center"].set(min=min(data_x), max=max(data_x)) - p["sigma"].set(min=0, max=(max(data_x) - min(data_x)) / 2.0) - # other possibilities ... : - # p['amplitude'].set(min=min(data_y), max=max(data_y)) - # p['intercept'].set(max=(max(data_y)-min(data_y))/2.) - - g = model.fit(data_y, p, x=data_x) + g = model.fit(data_y, pars, x=data_x) # diagnostics # print(f'Gfit: {g.params}') @@ -421,39 +413,41 @@ def fit_plot(data_x, data_y, model="gauss", ibg=1, fitrange=0, fitclick=0): print("dy=", data_y) ##### - peak = GaussianModel() + peak = GaussianModel(prefix = 'g_') + pre='g' if model == "voigt": - peak = VoigtModel() + peak = VoigtModel(prefix = 'v_') + pre='v' if model == "lorentz": - peak = LorentzianModel() + peak = LorentzianModel(prefix = 'l_') + pre='l' + model = peak + ypeak = data_y + pars = model.guess(data_y, x = data_x) + indmax = np.argmax(ypeak) + xm = data_x[indmax] + if ibg: - background = LinearModel() + background = LinearModel(prefix = 'bg_') model = peak + background - ### define data_x and data_y: - maxy = max(data_y) - indmax = np.argmax(data_y) - xm = data_x[indmax] - sigma = 1.0 - gamma = 0.2 # blurring/widening of the sigma ; the larger, the more of a Lorentzian profile - print("maxy, indmax, xm = ", maxy, indmax, xm) - # p = model.make_params( - # amplitude=max(data_y), center=xm, slope=0, intercept=min(data_y) - # ) - p = model.make_params(amplitude=maxy, center=xm) - p["center"].set(min=min(data_x), max=max(data_x)) - p["sigma"].set(min=0, max=(max(data_x) - min(data_x)) / 2.0) + ### estimate initial params separately for both parts of the model + # 1) BG + n = len(data_x) + edge= n//10 + idx=np.r_[0:edge, n-edge:n] # first and last part of the range + #m0, b0 = np.polyfit(data_x[idx], data_y[idx],1) + #ypeak= data_y - (m0*data_x + b0) # subtract linear part - g = model.fit(data_y, p, x=data_x) + pars = background.guess(data_y[idx], x = data_x[idx]) + + # 2) Function - BG + ypeak= data_y - (pars['bg_slope']*data_x + pars['bg_intercept'])# subtract linear part + pars.update( peak.guess(ypeak, x= data_x) ) + - # diagnostics - # print(f'Gfit: {g.params}') - - print(f'Center of {model} fit: {g.params["center"].value:.5f}') - print(f'Sigma: {g.params["sigma"].value:.5f}') - print(f'FWHM: {g.params["fwhm"].value:.5f}') - print(f"Position of maximum: {xm}") + g = model.fit(data_y, pars, x=data_x) ##### @@ -499,9 +493,13 @@ def fit_plot(data_x, data_y, model="gauss", ibg=1, fitrange=0, fitclick=0): plt.ylabel("signal") plt.show() - gcen = g.params["center"].value + #gcen = g.params["center"].value + print(g.fit_report()) - return gcen, xm + fit_id = pre+'_center' + + center = g.params[fit_id].value + return center, xm #################################### @@ -710,16 +708,15 @@ def read_mon(): vbpitch = dev.vfm_pitch.read()["vfm_pitch"]["value"] vbyaw = dev.vfm_yaw.read()["vfm_yaw"]["value"] vbroll = dev.vfm_roll.read()["vfm_roll"]["value"] - vblat = dev.vfm_lat.read()["vfm_lat"]["value"] - vbvert = dev.vfm_vert.read()["vfm_vert"]["value"] + #vbvert = dev.vfm_vert.read()["vfm_vert"]["value"] # KB H hbu = dev.hfm_bu.read()["hfm_bu"]["value"] hbd = dev.hfm_bd.read()["hfm_bd"]["value"] hbpitch = dev.hfm_pitch.read()["hfm_pitch"]["value"] hbyaw = dev.hfm_yaw.read()["hfm_yaw"]["value"] hbroll = dev.hfm_roll.read()["hfm_roll"]["value"] - hblat = dev.hfm_lat.read()["hfm_lat"]["value"] - hbvert = dev.hfm_vert.read()["hfm_vert"]["value"] + + #hbvert = dev.hfm_vert.read()["hfm_vert"]["value"] ## FE slits centre and size fe_sx_cen = dev.fe_sxcen.read()["fe_sxcen"]["value"] @@ -972,7 +969,7 @@ def slitscan(device_location: str, direction: str, range: 1, nsteps=50, centre=0 default_h = 1.0 ## 1.4 or 0.4 or ??? default_v = 1.0 ## 1.2 det = dev.lu_bpmsum - if direction == "h": + if direction in ["x","h"]: mot = dev.fe_sxcen size = dev.fe_sxsize s_closed = 0.1 @@ -989,7 +986,7 @@ def slitscan(device_location: str, direction: str, range: 1, nsteps=50, centre=0 default_v = 3.0 # ??? close more ???? # 8149.8 det = dev.lu_bpmsum # det = dev.ss_bpmsum or #det = dev.bcu_bpmsum would also work - if direction == "h": + if direction in ["x", "h"]: mot = dev.bsf_sl_xcen size = dev.bsf_sl_xsize s_closed = 0.1 @@ -1006,7 +1003,7 @@ def slitscan(device_location: str, direction: str, range: 1, nsteps=50, centre=0 default_h = 6.0 # ??? default_v = 5.0 # ??? close more ???? # 8149.8 det = dev.bcu_bpmsum - if direction == "h": + if direction in ["x", "h"]: mot = dev.ss_sl_xcen size = dev.ss_sl_xsize s_closed = 0.1 @@ -1030,7 +1027,7 @@ def slitscan(device_location: str, direction: str, range: 1, nsteps=50, centre=0 # print("moving diode i1 in") # umv(dev.scin_y, dposm) - if direction == "h": + if direction in ["x", "h"]: mot = dev.bcu_sl_xcen size = dev.bcu_sl_xsize s_closed = 3.0 ## very large, else does not work ! diff --git a/pxii_bec/macros/KB_Class.py b/pxii_bec/macros/KB_Class.py index 5e3bbda..7c5dccb 100644 --- a/pxii_bec/macros/KB_Class.py +++ b/pxii_bec/macros/KB_Class.py @@ -56,23 +56,24 @@ class KBMirror: curv0 = curv / self.curv_approx_fact / 1000 R = 1 / curv0 s2 = self.s1 / (2 * self.s1 / (R * np.sin(th_mrad / 1000)) - 1) - return s2 + return s2, R - def get_benders(self, th=2.0, defocus_mm=0.0, user_asymmetry=0.0): - asym = self.asym0 + user_asymmetry + def get_benders(self, th=3.0, defocus_mm=0.0, user_asymmetry=0.0): + asym = self.asym0 - user_asymmetry #### sign is important! s2_target = self.s2 + defocus_mm / 1000 curv = self.ellipse_to_curvature(s2_target, th) BU, BD = self.curvature_to_bend(curv, asym) return BU, BD - def readback(self, BU, BD, th=2.0): + def readback(self, BU, BD, th=3.0): curv, asym = self.bend_to_curvature(BU, BD) - s2_rb = self.curvature_to_ellipse(curv, th) + s2_rb, R0 = self.curvature_to_ellipse(curv, th) defocus_mm = (s2_rb - self.s2) * 1000 bend_rad_m = 1/curv *1000 return { "curvature": curv, - "bend_rad_m": bend_rad_m, + "bend_rad_m": bend_rad_m, + "bend_rad0_m": R0, "asymmetry": asym, "s2": s2_rb, "defocus_mm": defocus_mm diff --git a/pxii_bec/macros/build_devices.py b/pxii_bec/macros/build_devices.py index 12bb5fd..f731107 100755 --- a/pxii_bec/macros/build_devices.py +++ b/pxii_bec/macros/build_devices.py @@ -87,58 +87,276 @@ def build_devices(yaml_file, mock_devices): return state_devices -# def update_position(device, position, value, axis=None): -# """Update the user parameter saved positions for a device""" -# params = device.user_parameter -# if axis is None: -# # Is this a nested structure? -# nested_keys = [k for k, v in params.items() if isinstance(v, dict)] +def update_position( + device, + position, + value, + axis=None, + force=False, + max_delta=0.5, +): + """ + Update a single saved position in memory. -# if nested_keys: -# raise ValueError( -# f"{device.name} has nested parameters " -# f"({nested_keys}); specify axis=..." -# ) + Does NOT save or reload. Use save_and_reload() or + update_positions() afterwards. + """ -# device.update_user_parameter({position: value}) -# return - -# axis_params = params[axis].copy() -# axis_params[position] = value -# device.update_user_parameter({axis: axis_params}) - - -# # Save the updated values to the device yaml file -# # and re-initialise -# beamline = os.environ["BEAMLINE"] -# env = Environment(beamline = beamline) -# bec.config.save_current_session(env.devices_file) -# return init_beamline_environment() - - -def update_position(device, position, value, axis=None): - """Update the user parameter saved positions for a device""" params = device.user_parameter - if axis is None: - nested_keys = [k for k, v in params.items() if isinstance(v, dict)] + # ------------------------------------------------------------------ + # Nested device (e.g. aerotech.x.in) + # ------------------------------------------------------------------ + if axis is not None: - if nested_keys: - raise ValueError( - f"{device.name} has nested parameters " f"({nested_keys}); specify axis=..." + if axis not in params: + raise KeyError( + f"Unknown axis '{axis}'. " + f"Valid axes: {list(params.keys())}" ) - device.update_user_parameter({position: value}) - - else: axis_params = params[axis].copy() - axis_params[position] = value - device.update_user_parameter({axis: axis_params}) - # Save the updated values to the device yaml file + if position not in axis_params: + raise KeyError( + f"Unknown position '{position}'. " + f"Valid positions: {list(axis_params.keys())}" + ) + + old_value = axis_params[position] + + delta = abs(value - old_value) + + if delta > max_delta and not force: + raise ValueError( + f"Refusing to change " + f"{device.name}.{axis}.{position} " + f"from {old_value} to {value} " + f"(Δ={delta:.3f} > {max_delta}). " + f"Use force=True if intentional." + ) + + axis_params[position] = value + + device.update_user_parameter( + {axis: axis_params} + ) + + print( + f"Updated {device.name}.{axis}.{position}: " + f"{old_value} -> {value}" + ) + + return + + # ------------------------------------------------------------------ + # Flat device (e.g. bs_z) + # ------------------------------------------------------------------ + nested_keys = [ + k for k, v in params.items() + if isinstance(v, dict) + ] + + if nested_keys: + raise ValueError( + f"{device.name} has nested parameters " + f"({nested_keys}); specify axis=..." + ) + + if position not in params: + raise KeyError( + f"Unknown position '{position}'. " + f"Valid positions: {list(params.keys())}" + ) + + old_value = params[position] + + delta = abs(value - old_value) + + if delta > max_delta and not force: + raise ValueError( + f"Refusing to change " + f"{device.name}.{position} " + f"from {old_value} to {value} " + f"(Δ={delta:.3f} > {max_delta}). " + f"Use force=True if intentional." + ) + + device.update_user_parameter( + {position: value} + ) + + print( + f"Updated {device.name}.{position}: " + f"{old_value} -> {value}" + ) + + +def save_and_reload(): + """ + Save current configuration to YAML and rebuild + the beamline environment. + """ + beamline = os.environ["BEAMLINE"] + env = Environment(beamline=beamline) + + print(f"(saving changes to {env.devices_file})") + bec.config.save_current_session(env.devices_file) return init_beamline_environment() + + +def update_positions(updates): + """ + Apply many updates, then save and reload once. + + updates = [ + { + "device": dev.aerotech, + "axis": "x", + "position": "in", + "value": 0, + }, + { + "device": dev.bs_z, + "position": "max_blout", + "value": 68, + }, + ] + """ + + for update in updates: + + update_position( + device=update["device"], + position=update["position"], + value=update["value"], + axis=update.get("axis"), + force=update.get("force", False), + max_delta=update.get("max_delta", 0.5), + ) + + return save_and_reload() + + +def save_current_position( + device, + position, + axis=None, + force=False, + max_delta=0.5, +): + """ + Save the current motor position as a named position. + """ + print(f"Saving current postion for {device}") + + params = device.user_parameter + + if axis is not None: + + if axis not in params: + raise KeyError( + f"Unknown axis '{axis}'. " + f"Valid axes: {list(params.keys())}" + ) + + axis_params = params[axis].copy() + + if position not in axis_params: + raise KeyError( + f"Unknown position '{position}'. " + f"Valid positions: {list(axis_params.keys())}" + ) + + old_value = axis_params[position] + print(f"Old value is {old_value}") + + current_value = get_current_value(device, axis=None) + + delta = abs(current_value - old_value) + + if delta > max_delta and not force: + raise ValueError( + f"Current position differs from saved value:\n" + f" saved = {old_value}\n" + f" current = {current_value}\n" + f" delta = {delta:.3f}\n" + f"Use force=True if intentional." + ) + + axis_params[position] = current_value + + device.update_user_parameter( + {axis: axis_params} + ) + + print( + f"Updated {device.name}.{axis}.{position}: " + f"{old_value} -> {current_value}" + ) + + return + # ------------------------------------------------------------------ + # Flat device (e.g. bs_z) + # ------------------------------------------------------------------ + nested_keys = [ + k for k, v in params.items() + if isinstance(v, dict) + ] + + if nested_keys: + raise ValueError( + f"{device.name} has nested parameters " + f"({nested_keys}); specify axis=..." + ) + + if position not in params: + raise KeyError( + f"Unknown position '{position}'. " + f"Valid positions: {list(params.keys())}" + ) + + old_value = params[position] + current_value = get_current_value(device, axis=None) + + delta = abs(current_value - old_value) + + if delta > max_delta and not force: + raise ValueError( + f"Refusing to change " + f"{device.name}.{position} " + f"from {old_value} to {current_value} " + f"(Δ={delta:.3f} > {max_delta}). " + f"Use force=True if intentional." + ) + + device.update_user_parameter( + {position: current_value} + ) + + print( + f"Updated {device.name}.{position}: " + f"{old_value} -> {current_value}" + ) + + +def get_current_value(device, axis=None): + """ + Return current motor position. + """ + + if axis is not None: + motor = getattr(device, axis) + else: + motor = device + + data = motor.read() + + signal_name = next(iter(data)) + + return round(data[signal_name]["value"],3) \ No newline at end of file diff --git a/pxii_bec/macros/devices_manager.py b/pxii_bec/macros/devices_manager.py index 47dddaf..cc201db 100755 --- a/pxii_bec/macros/devices_manager.py +++ b/pxii_bec/macros/devices_manager.py @@ -1,9 +1,9 @@ """ This module manages the initialization of devices.""" -# from guards import attach_guards -# from policies import attach_policies -# from build_devices import build_devices +#from guards import attach_guards +#from policies import attach_policies +#from build_devices import build_devices class DeviceManager: diff --git a/pxii_bec/macros/init_beamline.py b/pxii_bec/macros/init_beamline.py index cae0630..edf1a33 100755 --- a/pxii_bec/macros/init_beamline.py +++ b/pxii_bec/macros/init_beamline.py @@ -30,8 +30,7 @@ class Environment: }, "x06da": { "devdir": "/sls/x06da/config/bec/production/pxiii_bec/pxiii_bec/device_configs/", - "state": "pxiii-state-devices.yaml", - "rest": "pxiii-rest-devices.yaml", + "state": "pxiii-devices.yaml", "states": "pxiii-beamline-states.yaml", }, } @@ -85,7 +84,7 @@ class Environment: "aerotech_u": "mount", "bl_bright": "off", "bl_pos": "out", - "bs_pos": "out", + "bs_pos": "in", "bs_z": "safe", "coll_y": "park", "cryo_pos": "in", diff --git a/pxii_bec/macros/pxii_energy.py b/pxii_bec/macros/pxii_energy.py index 3b40325..ad6cd50 100755 --- a/pxii_bec/macros/pxii_energy.py +++ b/pxii_bec/macros/pxii_energy.py @@ -85,7 +85,10 @@ def mono_pitch_scan(plot=True): energy = get_current_energy() pos = get_dcm_motors_positions(energy) print(f"Setting DCM Pitch to default value of {pos['dcm_pitch']}") - # scans.umv(EnergyDefaults.mono_pitch, pos["dcm_pitch"], relative=False) + # Set fine pitch to middle of its' travel range + scans.umv(EnergyDefaults.mono_fpitch, pos["dcm_fine_pitch"], relative=False) + # Move DCM pitch to starting value + scans.umv(EnergyDefaults.mono_pitch, pos["dcm_pitch"], relative=False) # Go to peak using default parameters from EnergyDefaults if plot: print("Scanning monochromator pitch and moving to peak, with plotting.") @@ -164,11 +167,12 @@ def get_dcm_motors_positions(energy_ev): dcm_motor_values = {} # pitch = float(np.poly1d(Calibration.pitch)(energy_ev)) pitch = -5.5 + fpitch = 5.0 roll = EnergyDefaults.mono_roll_value perp = calc_perp_position(energy_ev, print_result=False) bragg_angle = convert_from_energy(energy_ev, print_result=False)["bragg_angle_mrad"] dcm_motor_values.update( - {"bragg_angle": bragg_angle, "perp": perp, "dcm_pitch": pitch, "dcm_roll": roll} + {"bragg_angle": bragg_angle, "perp": perp, "dcm_pitch": pitch, "dcm_roll": roll, "dcm_fine_pitch": fpitch} ) return dcm_motor_values @@ -192,6 +196,7 @@ def move_dcm_motors(energy_ev): # umv(EnergyDefaults.mono_pitch, dcm_pos["dcm_pitch"]) # umv(EnergyDefaults.mono_roll, dcm_pos["dcm_roll"]) # print("\n***DCM Roll movement is currently disabled ***\n") + scans.umv(EnergyDefaults.mono_fpitch,dcm_pos["dcm_fine_pitch"], relative=False ) scans.umv( EnergyDefaults.energy, dcm_pos["bragg_angle"], @@ -247,3 +252,34 @@ def bl_energy(energy_ev, move_gap=True, mono_scan=True, plot=True): mono_pitch_scan(plot=True) else: mono_pitch_scan(plot=False) + +def new_calc_gap(energy_ev): + """ + Calculates the gap based on the given energy + """ + gapval = Gap() + harmonic_values = gapval.get_harmonic_values(energy_ev) + if harmonic_values is not None: + fit = np.poly1d(harmonic_values)(energy_ev) + gap_value = fit * 0.9994 + return gap_value + return None + +def set_gap(energy_ev, print_result=True): + """ + set the gap + """ + gap = new_calc_gap(energy_ev) + # else: + # gap = calc_gap(energy_kev) + if gap is not None and Harmonics.min_gap_value <= gap <= 20: + umv(dev.id_gap, gap) + if print_result: + print(f"Setting gap to {gap:.3f} mm") + else: + msg = ( + f"Position {gap: .3f} mm is outside the allowed scan range of " + f"4.5 to 20 mm. Not changing the gap." + ) + raise ValueError(msg) + return gap diff --git a/pxii_bec/macros/pxii_parameters.py b/pxii_bec/macros/pxii_parameters.py index 5a1f2d7..aa87fb3 100755 --- a/pxii_bec/macros/pxii_parameters.py +++ b/pxii_bec/macros/pxii_parameters.py @@ -15,6 +15,7 @@ class EnergyDefaults: signals = {"sig1": dev.lu_bpmsum, "sig2": dev.ss_bpmsum, "sig3": dev.bcu_bpmsum} energy = dev.dcm_bragg mono_pitch = dev.dcm_pitch + mono_fpitch = dev.dcm_fpitch mono_perp = dev.dcm_perp mono_roll = dev.dcm_froll mono_roll_value = 4.65 -- 2.54.0 From 9ad30e3a92e4eb08ad2a51431bc77c6c65de6937 Mon Sep 17 00:00:00 2001 From: x10sa Date: Wed, 24 Jun 2026 15:38:54 +0200 Subject: [PATCH 2/9] improvements to planner --- pxii_bec/macros/beamline_planner.py | 69 +++++++++++++++++++++++++++-- 1 file changed, 65 insertions(+), 4 deletions(-) diff --git a/pxii_bec/macros/beamline_planner.py b/pxii_bec/macros/beamline_planner.py index aa99268..f56c21f 100755 --- a/pxii_bec/macros/beamline_planner.py +++ b/pxii_bec/macros/beamline_planner.py @@ -95,20 +95,81 @@ class StateChangePlanner: def available_states(self): """Return a list of available states""" return list(self.states.keys()) + + def state_devices(self): + """Return the set of devices that participate in + beamline state definitions""" + + devices = set() + + for state in self.states.values(): + devices.update(state.keys()) + + return sorted(devices) def get_positions(self): - """Return current positions of all SE devices""" - return {name: dev.pos for name, dev in self.devices.items()} + """Return current positions of devices that are used + in state transitions""" + return {name: self.devices[name].pos + for name in self.state_devices()} def print_positions(self): """Return current state of all devices""" - for name, device in self.devices.items(): - print(f"{name:10s} : {device.pos:10s} value: {device.actual}") + for name in self.state_devices(): + device = self.devices[name] + + print(f"{name:10s} : {device.pos:10s} value: {device.actual:.5g}") def diff_states(self, before): """Return a dict of {device: (before, after)} pairs for devices that changed state""" after = self.get_positions() return {k: (before[k], after[k]) for k in before if before[k] != after[k]} + + def get_closest_states(self): + """ + Return states ordered by number of mismatches. + """ + + results = [] + + for state in self.states: + + config = self._merged_state(state, None) + + mismatches = [] + + for dev, expected in config.items(): + + if not self.devices[dev].is_at(expected): + mismatches.append( + ( + dev, + self.devices[dev].pos, + expected, + ) + ) + + results.append( + ( + state.name, + len(mismatches), + mismatches, + ) + ) + + return sorted(results, key=lambda x: x[1]) + + def closest_states(self, n=5): + + for state, count, mismatches in self.get_closest_states()[:n]: + + print(f"\n{state}: {count} mismatch(es)") + + for dev, actual, expected in mismatches: + print( + f" {dev:15s} " + f"{actual:10s} -> {expected}" + ) def current_state(self): """Return all current matching BeamlineState and TemperatureMode combinations, -- 2.54.0 From acc9df84ffd9ab7e3f238f09a390723d04e6d305 Mon Sep 17 00:00:00 2001 From: x10sa Date: Mon, 29 Jun 2026 12:25:48 +0200 Subject: [PATCH 3/9] Updates from the beamline Mo 29.06.2026 --- .../device_configs/pxii-beamline-states.yaml | 1 + pxii_bec/device_configs/pxii-devices.yaml | 67 +- pxii_bec/macros/APscripts.py | 35 +- pxii_bec/macros/Undu_Helpers.py | 23 +- pxii_bec/macros/beamline_planner.py | 4 +- pxii_bec/macros/chmirrh.py | 167 ++++ pxii_bec/macros/chmirrh.py~ | 142 +++ pxii_bec/macros/katscripts.py | 865 ++++++++---------- .../macros/luts/27061952_vfm_pitch_energy.csv | 96 ++ .../macros/luts/27062057_vfm_pitch_energy.csv | 51 ++ .../macros/luts/27062107_vfm_pitch_energy.csv | 46 + pxii_bec/macros/luts/27062148_lut.csv | 5 + pxii_bec/macros/luts/27062203_lut.csv | 78 ++ pxii_bec/macros/luts/2706_dcm_lut.csv | 83 ++ pxii_bec/macros/luts/roll_20000.csv | 10 + pxii_bec/macros/luts/roll_6000.csv | 12 + pxii_bec/macros/luts/vfm_pitch_energy.csv | 96 ++ pxii_bec/macros/mx_basics.py | 2 +- pxii_bec/macros/mx_methods.py | 2 + pxii_bec/macros/pxii_energy.py | 4 +- pxii_bec/macros/pxii_parameters.py | 11 +- 21 files changed, 1284 insertions(+), 516 deletions(-) create mode 100644 pxii_bec/macros/chmirrh.py create mode 100644 pxii_bec/macros/chmirrh.py~ create mode 100644 pxii_bec/macros/luts/27061952_vfm_pitch_energy.csv create mode 100644 pxii_bec/macros/luts/27062057_vfm_pitch_energy.csv create mode 100644 pxii_bec/macros/luts/27062107_vfm_pitch_energy.csv create mode 100644 pxii_bec/macros/luts/27062148_lut.csv create mode 100644 pxii_bec/macros/luts/27062203_lut.csv create mode 100644 pxii_bec/macros/luts/2706_dcm_lut.csv create mode 100644 pxii_bec/macros/luts/roll_20000.csv create mode 100644 pxii_bec/macros/luts/roll_6000.csv create mode 100644 pxii_bec/macros/luts/vfm_pitch_energy.csv diff --git a/pxii_bec/device_configs/pxii-beamline-states.yaml b/pxii_bec/device_configs/pxii-beamline-states.yaml index 2011edf..496ceb7 100644 --- a/pxii_bec/device_configs/pxii-beamline-states.yaml +++ b/pxii_bec/device_configs/pxii-beamline-states.yaml @@ -92,6 +92,7 @@ states: coll_y: park cryo_pos: in det_cov: 'close' + det_z: 'mse' diag_y: park fl_bright: 'off' aerotech_x: in diff --git a/pxii_bec/device_configs/pxii-devices.yaml b/pxii_bec/device_configs/pxii-devices.yaml index 26a654b..2d0ab75 100644 --- a/pxii_bec/device_configs/pxii-devices.yaml +++ b/pxii_bec/device_configs/pxii-devices.yaml @@ -433,8 +433,6 @@ coll_x: enabled: true onFailure: buffer readoutPriority: baseline - userParameter: - in: 0.0 coll_y: description: Collimator Y deviceClass: ophyd_devices.EpicsMotor @@ -446,9 +444,9 @@ coll_y: onFailure: buffer readoutPriority: baseline userParameter: - in: 40.834 + in: 39.393 intermediate: 32 - out: 19.0 + out: 20.002 park: 1 tol: 0.05 type: continuous @@ -614,6 +612,9 @@ det_z: enabled: true onFailure: buffer readoutPriority: baseline + userParameter: + mse: 800 + vis: 1198 diag_y: description: Scintillator/diode Y deviceClass: ophyd_devices.EpicsMotor @@ -625,10 +626,10 @@ diag_y: onFailure: buffer readoutPriority: baseline userParameter: - i1: 43.4 + i1: 41 out: 20.0 park: 1 - scint: 38.0 + scint: 36.004 tol: 0.3 type: continuous diag_z: @@ -1287,6 +1288,18 @@ samcam_ysig: onFailure: buffer readOnly: true readoutPriority: monitored +samcam_ecc: + description: Sample Camera Eccentricity + deviceClass: ophyd.EpicsSignalRO + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-MS:Stats5:Eccentricity_RBV + deviceTags: + - scam + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: monitored scam_zoom: description: Sample Camera Zoom deviceClass: ophyd_devices.EpicsMotor @@ -1757,6 +1770,48 @@ vfm_yw: enabled: true onFailure: buffer readoutPriority: baseline +xi_focus: + description: Xeye Zoom + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-XEYE:FOCUS + deviceTags: + - xeye + enabled: true + onFailure: buffer + readoutPriority: baseline +xi_x: + description: Xeye X + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-XEYE:TRX + deviceTags: + - xeye + enabled: true + onFailure: buffer + readoutPriority: baseline +xi_zoom: + description: Xeye Zoom + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-XEYE:ZOOM + deviceTags: + - xeye + enabled: true + onFailure: buffer + readoutPriority: baseline +xidiode: + description: Xeye Diode + deviceClass: ophyd.EpicsSignalRO + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-XEYEDI:READOUT + deviceTags: + - xeye + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: monitored xrf_pos: description: XRF Positioner deviceClass: ophyd.EpicsSignal diff --git a/pxii_bec/macros/APscripts.py b/pxii_bec/macros/APscripts.py index f585989..871c3c0 100644 --- a/pxii_bec/macros/APscripts.py +++ b/pxii_bec/macros/APscripts.py @@ -9,6 +9,7 @@ import numpy as np import math import matplotlib.pyplot as plt +import sys ################################ @@ -312,9 +313,9 @@ def justfit(data_x, data_y, model="gauss", ibg=0): # diagnostics # print(f'Gfit: {g.params}') - print(f'Center of {model} fit: {g.params["center"].value:.5f}') - print(f'Sigma: {g.params["sigma"].value:.5f}') - print(f'FWHM: {g.params["fwhm"].value:.5f}') + print(f'Center of {model} fit: {g.pars["center"].value:.5f}') + print(f'Sigma: {g.pars["sigma"].value:.5f}') + print(f'FWHM: {g.pars["fwhm"].value:.5f}') print(f"Position of maximum: {xm}") return g, xm @@ -361,7 +362,7 @@ def fit_plothist(hindex: int, signal_name: str, model="gauss", ibg=0): plt.ylabel(signal_name) plt.show() - gcen = g.params["center"].value + gcen = g.pars["center"].value return gcen, xm, data_x, data_y @@ -498,14 +499,14 @@ def fit_plot(data_x, data_y, model="gauss", ibg=1, fitrange=0, fitclick=0): fit_id = pre+'_center' - center = g.params[fit_id].value + center = g.pars[fit_id].value return center, xm #################################### ### just SAVE DATA #################################### -def save_data(hindex: int, device_name: str, signal_name: str): +def save_data(hindex: int, device_name: str, signal_name: str, isave = 1): """ Get data for a completed scan from the BEC history, and plot all the results, store in a CSV file @@ -532,15 +533,16 @@ def save_data(hindex: int, device_name: str, signal_name: str): plt.ylabel(f"{signal_name} / AU") plt.show() - ans = "n" - ans = input("Store data in csv file? y/n ") - if ans == "y": - dirname = "/sls/x10sa/config/commissioning/Data/" - # writing output to simple data file for later analysis: - combined = np.column_stack((data_x, data_y)) - filename = dirname + "Scan" + str(hindex) + device_name + ".txt" - with open(filename, "w") as f: - np.savetxt(f, combined, delimiter=",", fmt="%5f") + if isave: + ans = "n" + ans = input("Store data in csv file? y/n ") + if ans == "y": + dirname = "/sls/x10sa/config/commissioning/Data/" + # writing output to simple data file for later analysis: + combined = np.column_stack((data_x, data_y)) + filename = dirname + "Scan" + str(hindex) + device_name + ".txt" + with open(filename, "w") as f: + np.savetxt(f, combined, delimiter=",", fmt="%5f") return data_x, data_y @@ -1319,7 +1321,8 @@ def detxeye_out(): def measure_samcam(zoom=1000): - scinti_inpos = 38.6 # mm + import sys + scinti_inpos = 36.4 # mm sc_rb = dev.diag_y.user_readback.get() if abs(scinti_inpos - sc_rb) > 0.3: print("Scinti not in, please move") diff --git a/pxii_bec/macros/Undu_Helpers.py b/pxii_bec/macros/Undu_Helpers.py index eaf056c..baf31a1 100755 --- a/pxii_bec/macros/Undu_Helpers.py +++ b/pxii_bec/macros/Undu_Helpers.py @@ -214,19 +214,22 @@ def gap_harm(e=12.4): # test with estart = 6, end_en = 7.5 # should be 3 files , estimated time: 90 min -def long_gscan(estart=7, end_en=20.5, g_low=4.5, g_high=9.0, nsteps=1500): +def long_gscan(estart=6, end_en=30.5, g_low=4.5, g_high=9.0, nsteps=1500): import time import numpy as np dirname = "/sls/x10sa/config/commissioning/Data/" - enstep = 0.5 + enstep = 1.0 print( f"scanning the U19 gap from {estart} keV to {end_en} keV, for a gapsize from {g_low} to {g_high} in {enstep} keV energy intervals" ) - resol = (g_high - g_low) / nsteps - print(f"nsteps = {nsteps}; resolution is {resol} mm") + fe_h_size0 = dev.fe_sl_xsize.user_readback.get() + fe_v_size0 = dev.fe_sl_ysize.user_readback.get() + umv(dev.fe_sl_xsize, 0.5) + umv(dev.fe_sl_ysize, 0.3) + dock_area = bec.gui.new("LongGapScan", geometry = [4000, 900, 1200, 700]) wr = dock_area.new(bec.gui.available_widgets.Waveform) mot = dev.id_gap @@ -248,10 +251,16 @@ def long_gscan(estart=7, end_en=20.5, g_low=4.5, g_high=9.0, nsteps=1500): en = estart while en < end_en: + if en >= 17: + nsteps = 1000 + g_high = 7.5 #sete(en) #time.sleep(0.2) #rock() # maybe use + resol = (g_high - g_low) / nsteps + print(f"nsteps = {nsteps}; resolution is {resol} mm") + bl_energy(en, move_gap = False, plot = False) print(f"setting energy to {en}") @@ -288,6 +297,12 @@ def long_gscan(estart=7, end_en=20.5, g_low=4.5, g_high=9.0, nsteps=1500): elapsed_time = time.perf_counter()-tstart print(f"Runtime: {elapsed_time: .6f} seconds, i.e., {elapsed_time: .6f}/60 min") + # moving slits back + umv(dev.fe_sl_xsize, fe_h_size0) + umv(dev.fe_sl_ysize, fe_v_size0) + # move back to standard En + bl_energy(12400) + return diff --git a/pxii_bec/macros/beamline_planner.py b/pxii_bec/macros/beamline_planner.py index f56c21f..e96f01d 100755 --- a/pxii_bec/macros/beamline_planner.py +++ b/pxii_bec/macros/beamline_planner.py @@ -125,7 +125,7 @@ class StateChangePlanner: after = self.get_positions() return {k: (before[k], after[k]) for k in before if before[k] != after[k]} - def get_closest_states(self): + def __get_closest_states(self): """ Return states ordered by number of mismatches. """ @@ -161,7 +161,7 @@ class StateChangePlanner: def closest_states(self, n=5): - for state, count, mismatches in self.get_closest_states()[:n]: + for state, count, mismatches in self.__get_closest_states()[:n]: print(f"\n{state}: {count} mismatch(es)") diff --git a/pxii_bec/macros/chmirrh.py b/pxii_bec/macros/chmirrh.py new file mode 100644 index 0000000..7131fb5 --- /dev/null +++ b/pxii_bec/macros/chmirrh.py @@ -0,0 +1,167 @@ +import numpy as np +import math, time +import matplotlib.pyplot as plt +import scipy +######################################### +### just retrieve the saved data from csv +######################################## +def read_data(filename: str): + """ + Get data stored in a CSV file + + Args: + filename (str): the csv file, eg, of a Scan + e.g., dat = read_data("/home/e18747/SLS2/Data/gaps/gaps10.txt") + """ + + # dirname = '/home/gac-x10sa/Data/' + # read output to simple data file for later analysis: + + with open(filename, "r") as f: + combined_data = np.loadtxt(f, delimiter=",") # no header and fmt for load + + rows, cols = combined_data.shape + + print("No of Rows =", rows) + print("No of Colums =", cols) + ind1 = 0 + ind2 = 1 + if cols > 2: + print( + "only first 2 colums (data[:, 0] and data[:, 1]) are plotted, please consider the other columns as well!" + ) + index1 = 0 + index2 = 1 + index1, index2 = input( + "please enter the columns to be plotted vs first one [eg: 1,2] : " + ).split(",") + ind1 = int(index1) + ind2 = int(index2) + + if ind2 > cols - 1: + print(" no valid index") + + data_x = combined_data[:, ind1] + data_y = combined_data[:, ind2] + + plt.ion() + plt.figure() + plt.plot(data_x, data_y, ".") + + plt.title(f"Scan from {filename}") + plt.xlabel(f"data column {ind1}") + plt.ylabel(f"data column {ind2}") + + plt.show() + + return combined_data + + +def gaussfit(x,y,p): +# define a gaussian fitting function where +# p[0] = amplitude +# p[1] = mean +# p[2] = sigma +# p[3] = const offset + + fitfct = lambda p, x0: p[0]*np.exp(-(x0-p[1])**2/(2.0*p[2]**2))+p[3] + #fitfct = lambda p, x0: p[0]*np.exp(-(x0-p[1])**2/(2.0*p[2]**2)) + errfct = lambda p, x0,y0: fitfct(p,x0)-y0 + + # guess fit parameters + ind0 = np.where(y==max(y))[0] + p0=np.c_[max(y), x[ind0], np.std(y), np.mean(y[0:5])] + #p0=scipy.c_[max(y), np.where(y==max(y))[0], np.std(y)] + # array generation [[]], and taking only one dimens + # fit a gaussian to the correlation function + + #print('p0 = ' , p0) + p1, success = scipy.optimize.leastsq(errfct, p0.copy()[0], + args=(x,y)) + + #plt.figure() + bestfit=fitfct(p1,x) + #print('************************', x,y) + plt.plot(x,y,'r*') + plt.plot(x,bestfit,'r-') + + # different fit fct + #popt, pcov = curve_fit(fitfct, x, y) + #newfit=fitfct(popt,x) + #plt.plot(x,newfit,'g+') + + + plt.show() + + return bestfit, p1 + +def scan_fe_sl(): + fe_v_size0 = dev.fe_sl_ysize.user_readback.get() + umv(dev.fe_sl_xsize, 0.1) + s = scans.line_scan(dev.fe_sl_ycen,-1,1, exp_time=02., steps=21, relative=True) + time.sleep(0.1) + umv(dev.fe_sl_xsize, fe_v_size0) + +def mirrh(): + + #dat_ss = read_data("/home/anuschka/SS_pitch2p94.csv") + #dat_bcu = read_data("/home/anuschka/BCU_pitch2p94.csv") + + scan_fe_sl() + ind = -1 + dat_ss = save_data(ind, 'fe_sl_ycen', 'ss_bpmsum', isave = 0) + dat_bcu = save_data(ind, 'fe_sl_ycen', 'bcu_bpmsum', isave = 0) + + + data_xs = dat_ss[0] # csv would be: dat_ss[:, 0] + data_ys = dat_ss[1] + + data_xb = dat_bcu[0] + data_yb = dat_bcu[1] + + #plt.figure() + + #plt.plot(data_xs, data_ys, "*") + #plt.plot(data_xb, data_yb, "+") + + data_ys_norm = data_ys/max(data_ys) + data_yb_norm = data_yb/max(data_yb) + + plt.figure() + + plt.plot(data_xs, data_ys_norm, "*") + plt.plot(data_xb, data_yb_norm, "+") + + + y= data_ys_norm + xm = np.where(y==max(y))[0] + xmi = data_xs[xm] + #print('xm, xmi', xm, xmi) + + pf1 = [1, xmi , np.std(data_ys_norm),0] + fit_s, ps = gaussfit(data_xs,data_ys_norm, pf1) + + y= data_yb_norm + xm = np.where(y==max(y))[0] + xmi = data_xb[xm] + #print('xm, xmi', xm, xmi) + + pf2 = [1, xmi, np.std(data_yb_norm),-11] + fit_b, pb = gaussfit(data_xb,data_yb_norm, pf2) + + + plt.figure() + + plt.plot(data_xs, fit_s-ps[3], "*") + plt.plot(data_xs, fit_s-ps[3]) + plt.plot(data_xb, fit_b-pb[3], "+") + plt.plot(data_xb, fit_b-pb[3]) + + print('Fit Params of First BPM, SS, ps', ps) + print('Fit Params of Second BPM, BCU, pb', pb) + print() + if abs(ps[1]-pb[1]) > 0.05: + print('***** WARNING ******, mirror height not ok') + if abs(ps[2]-pb[2]) > 0.05: + print('***** WARNING ******, mirror not catching full beam') + diff --git a/pxii_bec/macros/chmirrh.py~ b/pxii_bec/macros/chmirrh.py~ new file mode 100644 index 0000000..664ab60 --- /dev/null +++ b/pxii_bec/macros/chmirrh.py~ @@ -0,0 +1,142 @@ +import numpy as np +import math +import matplotlib.pyplot as plt +import scipy +######################################### +### just retrieve the saved data from csv +######################################## +def read_data(filename: str): + """ + Get data stored in a CSV file + + Args: + filename (str): the csv file, eg, of a Scan + e.g., dat = read_data("/home/e18747/SLS2/Data/gaps/gaps10.txt") + """ + + # dirname = '/home/gac-x10sa/Data/' + # read output to simple data file for later analysis: + + with open(filename, "r") as f: + combined_data = np.loadtxt(f, delimiter=",") # no header and fmt for load + + rows, cols = combined_data.shape + + print("No of Rows =", rows) + print("No of Colums =", cols) + ind1 = 0 + ind2 = 1 + if cols > 2: + print( + "only first 2 colums (data[:, 0] and data[:, 1]) are plotted, please consider the other columns as well!" + ) + index1 = 0 + index2 = 1 + index1, index2 = input( + "please enter the columns to be plotted vs first one [eg: 1,2] : " + ).split(",") + ind1 = int(index1) + ind2 = int(index2) + + if ind2 > cols - 1: + print(" no valid index") + + data_x = combined_data[:, ind1] + data_y = combined_data[:, ind2] + + plt.ion() + plt.figure() + plt.plot(data_x, data_y, ".") + + plt.title(f"Scan from {filename}") + plt.xlabel(f"data column {ind1}") + plt.ylabel(f"data column {ind2}") + + plt.show() + + return combined_data + + +def gaussfit(x,y,p): +# define a gaussian fitting function where +# p[0] = amplitude +# p[1] = mean +# p[2] = sigma +# p[3] = const offset + + fitfct = lambda p, x0: p[0]*np.exp(-(x0-p[1])**2/(2.0*p[2]**2))+p[3] + #fitfct = lambda p, x0: p[0]*np.exp(-(x0-p[1])**2/(2.0*p[2]**2)) + errfct = lambda p, x0,y0: fitfct(p,x0)-y0 + + # guess fit parameters + ind0 = np.where(y==max(y))[0] + p0=scipy.c_[max(y), x[ind0], np.std(y), np.mean(y[0:5])] + #p0=scipy.c_[max(y), np.where(y==max(y))[0], np.std(y)] + # array generation [[]], and taking only one dimens + # fit a gaussian to the correlation function + + print('p0 = ' , p0) + p1, success = scipy.optimize.leastsq(errfct, p0.copy()[0], + args=(x,y)) + + plt.figure() + bestfit=fitfct(p1,x) + #print('************************', x,y) + plt.plot(x,y,'r*') + plt.plot(x,bestfit,'r-') + + # different fit fct + #popt, pcov = curve_fit(fitfct, x, y) + #newfit=fitfct(popt,x) + #plt.plot(x,newfit,'g+') + + + plt.show() + #time.sleep(1) + #plt.close() + return bestfit, p1 + +def mirh(): + + dat_ss = read_data("/home/anuschka/SS_pitch2p94.csv") + dat_bcu = read_data("/home/anuschka/BCU_pitch2p94.csv") + + data_xs = dat_ss[:, 0] + data_ys = dat_ss[:, 1] + + data_xb = dat_bcu[:, 0] + data_yb = dat_bcu[:, 1] + + plt.figure() + + plt.plot(data_xs, data_ys, "*") + plt.plot(data_xb, data_yb, "+") + + data_ys_norm = data_ys/max(data_ys) + data_yb_norm = data_yb/max(data_yb) + + plt.figure() + + plt.plot(data_xs, data_ys_norm, "*") + plt.plot(data_xb, data_yb_norm, "+") + + + pf1 = [1, 0.8 , np.std(data_ys_norm),0] + + y= data_ys_norm + xm = np.where(y==max(y))[0] + xmi = data_xs[xm] + print('xm, xmi', xm, xmi) + + fit_s, ps = gaussfit(data_xs,data_ys_norm, pf1) + + pf2 = [1, 0.8, np.std(data_yb_norm),-11] + fit_b, pb = gaussfit(data_xb,data_yb_norm, pf2) + + + plt.figure() + + plt.plot(data_xs, fit_s-ps[3], "*") + plt.plot(data_xb, fit_b-pb[3], "+") + + diff --git a/pxii_bec/macros/katscripts.py b/pxii_bec/macros/katscripts.py index 3d36c69..ed9f6cf 100755 --- a/pxii_bec/macros/katscripts.py +++ b/pxii_bec/macros/katscripts.py @@ -193,18 +193,24 @@ def beam_centre_from_bsc(): return beampos -def generate_dcm_lut(start_energy=26500, end_energy=30500, step=500): +def generate_dcm_lut(start_energy=6000, end_energy=30000, step=300): """Generate a lookup table for the dcm from start_energy to end_energy in steps of step""" now = datetime.now() fnow = now.strftime("%d%m%H%M") filename = f"luts/{fnow}_lut.csv" + zoom = dev.scam_zoom.read()['scam_zoom']['value'] with open(filename, "w", encoding="utf-8") as f: - f.write("energy,harmonic,gap,pitch,roll,perp,ss_xicam_x,ss_xicam_y\n") + f.write(f"energy,harmonic,gap,pitch,roll,perp,samcam_x,samcam_y,zoom={zoom}\n") for energy in range(start_energy, end_energy, step): print(f"Moving to {energy: .0f}eV") bl_energy(energy, mono_scan=False) - scan_gap() + try: + scan_gap() + except Exception as exc: + print(f"Gap scan failed at {energy:.0f} eV: {exc}") + set_gap(energy) # set fallback gap here + mono_pitch_scan() gap = dev.id_gap.read()["id_gap"]["value"] harm = Gap() @@ -212,13 +218,17 @@ def generate_dcm_lut(start_energy=26500, end_energy=30500, step=500): pitch = dev.dcm_pitch.read()["dcm_pitch"]["value"] roll = dev.dcm_froll.read()["dcm_froll"]["value"] perp = dev.dcm_perp.read()["dcm_perp"]["value"] - auto_exposure(cam="ss_xicam", max_iter=25) - x = dev.ss_xicam_x.read()["ss_xicam_x"]["value"] - y = dev.ss_xicam_y.read()["ss_xicam_y"]["value"] + # auto_exposure(cam="ss_xicam", max_iter=25) + # x = dev.ss_xicam_x.read()["ss_xicam_x"]["value"] + # y = dev.ss_xicam_y.read()["ss_xicam_y"]["value"] + auto_exposure(cam="samcam", max_iter=20) + x = dev.samcam_x.read()['samcam_x']['value'] + y = dev.samcam_y.read()['samcam_y']['value'] with open(filename, "a", encoding="utf-8") as f: f.write( f"{energy:.0f},{h},{gap:.5g},{pitch:.5g},{roll:.4g},{perp:.5g},{x:.4g},{y:.4g}\n" ) + bl_energy(12400) umv(dev.id_gap, 20.0) @@ -1035,486 +1045,100 @@ def compute_norm(): yn = ((readings["bpm1"] + readings["bpm3"]) - (readings["bpm2"] + readings["bpm4"])) / total return xn, yn - -# def vfm_pscan(): -# start_pitch = 3.0 -# scan_width = 0.03 -# start_vfm_y = -0.7 -# vfm_y = dev.vfm_y.read()['vfm_y']['value'] -# name = f"VFM-{vfm_y:.3g}" -# bpmsum, y = [], [] - -# scanpoints = np.linspace((start_pitch-scan_width), (start_pitch+scan_width), 20) -# umv(dev.vfm_y, start_vfm_y) -# for repeat in range(0,8): -# filename = f"./luts/pitch{name}.csv" -# with open(filename, "w") as f: -# f.write("BCUsum, BCU-Y\n") -# for i in scanpoints: -# umv(dev.vfm_pitch,i) -# time.sleep(0.2) -# bcu = dev.bcu_bpmsum.read()['bcu_bpmsum']['value'] -# xn, yn = compute_norm() -# bpmsum.append(bcu) -# ypos = y.append(yn) -# with open(filename, "a") as f: -# f.write(f"{i:.4g},{bcu:.4g},{yn:.4g}\n") -# umv(dev.vfm_pitch,start_pitch) -# sum_array = np.array(bpmsum) -# y_array = np.array(y) -# # --- Plot --- -# plt.figure(figsize=(7,5)) -# plt.plot(scanpoints, sum_array, color='red', label=f'BCU bpmsum') -# plt.xlabel('VFM pitch') -# plt.ylabel('BCU') -# plt.title(f"{name}") -# plt.legend() -# plt.grid(True) -# plt.tight_layout() -# plt.savefig(f"luts/{name}_sum.png") -# # plt.show() -# plt.figure(figsize=(7,5)) -# plt.plot(scanpoints, y_array, color='blue', label=f'BCU Y') -# plt.xlabel('VFM pitch') -# plt.ylabel('BCU') -# plt.title(f"{name}") -# plt.legend() -# plt.grid(True) -# plt.tight_layout() -# plt.savefig(f"luts/{name}_y.png") -# # plt.show() - - -def hfm_pscan2(): - - # ----------------------- - # Settings - # ----------------------- - start_pitch = 3.0 - pitch_width = 0.03 - n_pitch = 15 - - start_hfm_x = 1.5 - hfm_x_width = 0.2 - n_hfm_x = 7 - - settle = 0.2 - - output_dir = "./luts" - os.makedirs(output_dir, exist_ok=True) - - # ----------------------- - # Save initial positions - # ----------------------- - initial_pitch = dev.hfm_pitch.read()["hfm_pitch"]["value"] - initial_hfmx = dev.hfm_x.read()["hfm_x"]["value"] - - # ----------------------- - # Scan points - # ----------------------- - pitch_points = np.linspace(start_pitch - pitch_width, start_pitch + pitch_width, n_pitch) - - hfmx_points = np.linspace(start_hfm_x - hfm_x_width, start_hfm_x + hfm_x_width, n_hfm_x) - - summary = [] - - # ----------------------- - # Loop over hFM X - # ----------------------- - for hfmx in hfmx_points: - - print(f"\nScanning HFM X = {hfmx:.4f}") - - umv(dev.hfm_x, hfmx) - time.sleep(settle) - - bpmsum = [] - - name = f"HFMX_{hfmx:.4f}" - - csvfile = os.path.join(output_dir, f"{name}.csv") - - with open(csvfile, "w") as f: - - f.write("pitch,bpmsum,bpmsum_std\n") - - for pitch in pitch_points: - - umv(dev.hfm_pitch, pitch) - time.sleep(settle) - - # Average several BPM readings - vals = [] - for _ in range(5): - vals.append(dev.bcu_bpmsum.read()["bcu_bpmsum"]["value"]) - time.sleep(0.1) - - bcu = np.mean(vals) - bcu_std = np.std(vals) - - bpmsum.append(bcu) - - f.write(f"{pitch:.6f},{bcu:.6f}, {bcu_std:.6f}\n") - - # Return pitch to nominal - umv(dev.hfm_pitch, start_pitch) - - bpmsum = np.array(bpmsum) - - # Find maximum transmission - imax = np.argmax(bpmsum) - - pitch_peak = pitch_points[imax] - sum_peak = bpmsum[imax] - - summary.append([hfmx, pitch_peak, sum_peak]) - - print(f"Peak pitch = {pitch_peak:.5f}, " f"Max BPM sum = {sum_peak:.1f}") - - # Plot this pitch scan - plt.figure(figsize=(7, 5)) - - plt.plot(pitch_points, bpmsum, marker="o") - - plt.axvline(pitch_peak, linestyle="--", label=f"Peak = {pitch_peak:.5f}") - - plt.xlabel("HFM pitch") - plt.ylabel("BPM sum") - plt.title(name) - - plt.grid(True) - plt.legend() - plt.tight_layout() - - plt.savefig(os.path.join(output_dir, f"{name}.png")) - - plt.close() - - # ----------------------- - # Summary analysis - # ----------------------- - summary = np.array(summary) - - hfmx = summary[:, 0] - pitch_peak = summary[:, 1] - sum_peak = summary[:, 2] - - # Save summary CSV - summary_file = os.path.join(output_dir, "hfm_summary.csv") - - with open(summary_file, "w") as f: - - f.write("hfmx,pitch_peak,sum_peak\n") - - for row in summary: - f.write(",".join(f"{x:.6f}" for x in row) + "\n") - - # ----------------------- - # Summary plots - # ----------------------- - - plt.figure(figsize=(7, 5)) - - plt.plot(hfmx, sum_peak, marker="o") - - plt.xlabel("HFM X") - plt.ylabel("Maximum BPM sum") - plt.title("Transmission vs HFM X") - - plt.grid(True) - plt.tight_layout() - - plt.savefig(os.path.join(output_dir, "summary_sum_vs_hfmx.png")) - - plt.close() - - plt.figure(figsize=(7, 5)) - - plt.plot(hfmx, pitch_peak, marker="o") - - plt.xlabel("HFM X") - plt.ylabel("Pitch at maximum transmission") - plt.title("Optimum pitch vs HFM X") - - plt.grid(True) - plt.tight_layout() - - plt.savefig(os.path.join(output_dir, "summary_pitch_vs_hfmx.png")) - - plt.close() - - # ----------------------- - # Find best HFM X - # ----------------------- - ibest = np.argmax(sum_peak) - - best_vfmy = hfmx[ibest] - best_pitch = pitch_peak[ibest] - - print("\nBest alignment:") - print(f"HFM X = {best_hfmx:.5f}") - print(f"HFM pitch = {best_pitch:.5f}") - - # Move to optimum - umv(dev.hfm_x, best_hfmx) - umv(dev.hfm_pitch, best_pitch) - - print("\nMoved mirrors to optimum values.") - - return summary - - -def vfm_pscan(): - - # ------------------------------- - # User settings - # ------------------------------- - start_pitch = 3.0 # nominal pitch - pitch_width = 0.03 # +/- pitch scan range - n_pitch = 20 - - start_vfm_y = -0.900 # nominal VFM Y - vfm_y_width = 0.05 # +/- VFM Y scan range - n_vfm_y = 8 - - settle_time = 0.2 - - output_dir = "./luts" - os.makedirs(output_dir, exist_ok=True) - - # ------------------------------- - # Save initial positions - # ------------------------------- - initial_pitch = dev.vfm_pitch.read()["vfm_pitch"]["value"] - initial_vfm_y = dev.vfm_y.read()["vfm_y"]["value"] - - # ------------------------------- - # Generate scan points - # ------------------------------- - pitch_points = np.linspace(start_pitch - pitch_width, start_pitch + pitch_width, n_pitch) - - vfm_y_points = np.linspace(start_vfm_y - vfm_y_width, start_vfm_y + vfm_y_width, n_vfm_y) - - summary = [] - - # ------------------------------- - # Loop over VFM Y - # ------------------------------- - for vfm_y in vfm_y_points: - - print(f"\nScanning VFM Y = {vfm_y:.4f}") - - umv(dev.vfm_y, vfm_y) - time.sleep(settle_time) - - bpmsum = [] - bpm_y = [] - - name = f"VFMY_{vfm_y:.4f}" - - csvfile = os.path.join(output_dir, f"{name}.csv") - - with open(csvfile, "w") as f: - - f.write("pitch,bpmsum,bpm_y\n") - - # ------------------------------- - # Pitch scan - # ------------------------------- - for pitch in pitch_points: - - umv(dev.vfm_pitch, pitch) - time.sleep(settle_time) - - bcu = dev.bcu_bpmsum.read()["bcu_bpmsum"]["value"] - - xn, yn = compute_norm() - - bpmsum.append(bcu) - bpm_y.append(yn) - - f.write(f"{pitch:.6f},{bcu:.6f},{yn:.6f}\n") - - # Return pitch to nominal - umv(dev.vfm_pitch, start_pitch) - - # Convert to arrays - bpmsum = np.array(bpmsum) - bpm_y = np.array(bpm_y) - - # ------------------------------- - # Find optimum pitch - # ------------------------------- - imax = np.argmax(bpmsum) - - pitch_peak = pitch_points[imax] - sum_peak = bpmsum[imax] - y_peak = bpm_y[imax] - - summary.append([vfm_y, pitch_peak, sum_peak, y_peak]) - - print(f"Peak at pitch={pitch_peak:.5f}, " f"BPM sum={sum_peak:.1f}, " f"BPM Y={y_peak:.4f}") - - # ------------------------------- - # Plot BPM sum - # ------------------------------- - plt.figure(figsize=(7, 5)) - - plt.plot(pitch_points, bpmsum, marker="o") - - plt.axvline(pitch_peak, linestyle="--") - - plt.xlabel("VFM pitch") - plt.ylabel("BCU BPM sum") - plt.title(name) - - plt.grid(True) - plt.tight_layout() - - plt.savefig(os.path.join(output_dir, f"{name}_sum.png")) - - plt.close() - - # ------------------------------- - # Plot BPM Y - # ------------------------------- - plt.figure(figsize=(7, 5)) - - plt.plot(pitch_points, bpm_y, marker="o") - - plt.axvline(pitch_peak, linestyle="--") - - plt.xlabel("VFM pitch") - plt.ylabel("BCU BPM Y") - plt.title(name) - - plt.grid(True) - plt.tight_layout() - - plt.savefig(os.path.join(output_dir, f"{name}_y.png")) - - plt.close() - - # ------------------------------- - # Summary arrays - # ------------------------------- - summary = np.array(summary) - - vfm_y_vals = summary[:, 0] - pitch_peaks = summary[:, 1] - sum_peaks = summary[:, 2] - y_peaks = summary[:, 3] - - # Save summary CSV - summary_file = os.path.join(output_dir, "vfm_summary.csv") - - with open(summary_file, "w") as f: - - f.write("vfm_y,pitch_peak,sum_peak,bpm_y_peak\n") - - for row in summary: - f.write(",".join(f"{x:.6f}" for x in row) + "\n") - - # ------------------------------- - # Summary plots - # ------------------------------- - - plt.figure(figsize=(7, 5)) - plt.plot(vfm_y_vals, pitch_peaks, marker="o") - - plt.xlabel("VFM Y") - plt.ylabel("Pitch at max BPM sum") - plt.title("Optimum pitch vs VFM Y") - - plt.grid(True) - plt.tight_layout() - - plt.savefig(os.path.join(output_dir, "summary_pitch_vs_vfmy.png")) - - plt.close() - - plt.figure(figsize=(7, 5)) - plt.plot(vfm_y_vals, sum_peaks, marker="o") - - plt.xlabel("VFM Y") - plt.ylabel("Maximum BPM sum") - plt.title("Maximum transmission vs VFM Y") - - plt.grid(True) - plt.tight_layout() - - plt.savefig(os.path.join(output_dir, "summary_sum_vs_vfmy.png")) - - plt.close() - - plt.figure(figsize=(7, 5)) - plt.plot(vfm_y_vals, y_peaks, marker="o") - - plt.xlabel("VFM Y") - plt.ylabel("BPM Y at optimum pitch") - plt.title("Beam position vs VFM Y") - - plt.grid(True) - plt.tight_layout() - - plt.savefig(os.path.join(output_dir, "summary_bpmy_vs_vfmy.png")) - - plt.close() - - # ------------------------------- - # Restore original positions - # ------------------------------- - umv(dev.vfm_pitch, initial_pitch) - umv(dev.vfm_y, initial_vfm_y) - - print("\nScan complete.") - print(f"Summary written to {summary_file}") - - return summary - - -def find_best_roll(low=6000, high=20000): - low_scanpoints = np.linspace(0.5, 5.5, 11) - high_scanpoints = np.linspace(1.0, 9.0, 9) +def mirror_pitch(mirror = 'vfm'): + + if mirror == 'vfm': + pitch = dev.vfm_pitch.position + mot = dev.vfm_pitch + start = 2.94 + else: + pitch = dev.hfm_pitch.position + mot = dev.hfm_pitch + start = 3.3 + print(f"Scanning {mirror}_pitch from 10-29 keV") + pitch_range = [start - 0.25, start - 0.2, start -0.15, start - 0.1, start -0.05] + + umv(mot,start) + + results = [] + now = datetime.now() + fnow = now.strftime("%d%m%H%M") + csvfile = f"luts/{fnow}_{mirror}_pitch_energy.csv" + + with open(csvfile, "w") as f: + f.write("energy,pitch,diode\n") + + # for p in pitch_range: + for energy in range(17, 26): + bl_energy(energy) + time.sleep(1) + + for p in pitch_range: + umv(mot, p) + print(f"{mirror}_pitch = {p}") + time.sleep(0.2) + vals_diode = [] + + for _ in range(5): + vals_diode.append(dev.xidiode.read()['xidiode']['value']) + time.sleep(0.1) + + diode = np.mean(vals_diode) + + results.append([ + energy, + p, + diode, + ]) + + with open(csvfile, "a") as f: + f.write( + f"{energy:.2f},{p:.5f},{diode:.5g}\n" + ) + umv(mot,start) + bl_energy(12400) + results = np.array(results) + +def find_best_roll(low = 6000, high = 20000): + low_scanpoints = np.linspace(2.0, 7.0, 11) + high_scanpoints = np.linspace(1.0, 9.0,9) highs_y, lows_y = [], [] - # low energy - bl_energy(low) - energy = get_current_energy() - filename = f"./luts/roll_{energy:.0f}.csv" - with open(filename, "w", encoding="utf-8") as f: - f.write("Roll, Y pos\n") - auto_exposure("bsccam", max_iter=25) - for i in low_scanpoints: - umv(dev.dcm_froll, i) - time.sleep(0.2) - low_y = dev.bsccam_y.read()["bsccam_y"]["value"] - print(f"Ypos at BSC cam is {low_y}") - lows_y.append(low_y) - with open(filename, "a", encoding="utf-8") as f: - f.write(f"{i:.4g},{low_y:.4g} \n") - # high energy bl_energy(high) - energy = get_current_energy() - if 19999 < energy < 200001: - umv(dev.id_gap, 4.718) - filename = f"./luts/roll_{energy:.0f}.csv" + filename = f"./luts/roll_{high:.0f}.csv" with open(filename, "w", encoding="utf-8") as f: - f.write("Roll, Y pos\n") - auto_exposure("bsccam", max_iter=25) + f.write("Roll, Y pos\n") + auto_exposure("samcam", max_iter=25) for i in high_scanpoints: umv(dev.dcm_froll, i) time.sleep(0.2) - high_y = dev.bsccam_y.read()["bsccam_y"]["value"] - print(f"Ypos at BSC cam is {high_y}") + high_y = dev.samcam_y.read()['samcam_y']['value'] + print(f"Ypos at sample cam is {high_y}") highs_y.append(high_y) with open(filename, "a", encoding="utf-8") as f: - f.write(f"{i:.4g},{low_y:4g.} \n") + f.write(f"{i:.4g},{high_y:.4g} \n") + # low energy + bl_energy(low) + filename = f"./luts/roll_{low:.0f}.csv" + with open(filename, "w", encoding="utf-8") as f: + f.write("Roll, Y pos\n") + auto_exposure("samcam", max_iter=25) + for i in low_scanpoints: + umv(dev.dcm_froll, i) + time.sleep(0.2) + low_y = dev.samcam_y.read()['samcam_y']['value'] + print(f"Ypos at sample cam is {low_y}") + lows_y.append(low_y) + with open(filename, "a", encoding="utf-8") as f: + f.write(f"{i:.4g},{low_y:.4g} \n") + + y_high = np.array(highs_y) y_low = np.array(lows_y) + # # Fit linear models: y = m*x + b m_high, b_high = np.polyfit(high_scanpoints, y_high, 1) m_low, b_low = np.polyfit(low_scanpoints, y_low, 1) @@ -1525,23 +1149,300 @@ def find_best_roll(low=6000, high=20000): print(f"\nIntersection at:") print(f" DCM Roll = {x_intersect:.5f}") - print(f" BSCcam Y = {y_intersect:.2f}") + print(f" samcam Y = {y_intersect:.2f}") # # --- Plot --- - plt.figure(figsize=(7, 5)) - plt.scatter(high_scanpoints, y_high, color="red", label=f"High energy") - plt.scatter(low_scanpoints, y_low, color="blue", label=f"Low energy") + plt.figure(figsize=(7,5)) + plt.scatter(high_scanpoints, y_high, color='red', label=f'High energy') + plt.scatter(low_scanpoints, y_low, color='blue', label=f'Low energy') x_fit = np.linspace(min(high_scanpoints), max(high_scanpoints), 100) - plt.plot(x_fit, m_high * x_fit + b_high, "r--", label=f"High energy") - plt.plot(x_fit, m_low * x_fit + b_low, "b--", label=f"Low energy") + plt.plot(x_fit, m_high*x_fit + b_high, 'r--', label=f'High energy') + plt.plot(x_fit, m_low*x_fit + b_low, 'b--', label=f'Low energy') - plt.scatter(x_intersect, y_intersect, color="green", s=80, zorder=5, label="Intersection") + plt.scatter(x_intersect, y_intersect, color='green', s=80, zorder=5, label='Intersection') - plt.xlabel("DCM fine roll") - plt.ylabel("BSCcam Y pos") - plt.title("Roll Calibration") + plt.xlabel('DCM fine roll') + plt.ylabel('samcam Y pos') + plt.title('Roll Calibration') plt.legend() plt.grid(True) plt.tight_layout() plt.show() + +def vfm_yaw_check(): + slit_size = 0.02 + slit_point1 = -1.2 + slit_point2 = -0.12 + mirror_start = 0.5 + mirror_end = -5 + yaw_values = [-1.5, -0.5, 0, 0.5, 1] + point1 = [] + point2 = [] + + umv(dev.ss_sl_ysize, slit_size) + + for yaw in yaw_values: + print(f"Moving VFM yaw to {yaw}") + umv(dev.vfm_yaw, yaw) + # Point 1 + print(f"Moving slits to position 1") + umv(dev.ss_sl_ycen, slit_point1) + scans.line_scan(dev.vfm_x, mirror_start, mirror_end, steps = 20, relative=False) + fit_result = fit_history(-1, "xidiode", deriv=True) + centre = fit_result['centre'] + print(f'Yaw = {yaw}, position = {slit_point1}, centre = {centre}') + point1.append(centre) + # Point 2 + print(f"Moving slits to position 2") + umv(dev.ss_sl_ycen, slit_point2) + scans.line_scan(dev.vfm_x, mirror_start, mirror_end, steps = 20, relative=False) + fit_result = fit_history(-1, "xidiode", deriv=True) + centre = fit_result['centre'] + print(f'Yaw = {yaw}, position = {slit_point2}, centre = {centre}') + point2.append(centre) + print(f"Point 1 values are {point1}") + print(f"Point 2 values are {point2}") + go_to_peak(dev.ss_sl_ycen, dev.xidiode, -2, 2, 100) + umv(dev.ss_sl_ysize, 2) + y_point1 = np.array(point1) + y_point2 = np.array(point2) + + + # # Fit linear models: y = m*x + b + m_point1, b_point1 = np.polyfit(yaw_values, y_point1, 1) + m_point2, b_point2 = np.polyfit(yaw_values, y_point2, 1) + + # # Intersection point + x_intersect = (b_point2 - b_point1) / (m_point1 - m_point1) + y_intersect = m_point1 * x_intersect + b_point1 + + print(f"\nIntersection at:") + print(f" Mirror yaw = {x_intersect:.5f}") + print(f" Y = {y_intersect:.2f}") + + # # --- Plot --- + plt.figure(figsize=(7,5)) + plt.scatter(yaw_values, y_point1, color='red', label=f'point1') + plt.scatter(yaw_values, y_point2, color='blue', label=f'point2') + + x_fit = np.linspace(min(yaw_values), max(yaw_values), 100) + plt.plot(x_fit, m_point1*x_fit + b_point1, 'r--', label=f'point1') + plt.plot(x_fit, m_point2*x_fit + b_point2, 'b--', label=f'point2') + + plt.scatter(x_intersect, y_intersect, color='green', s=80, zorder=5, label='Intersection') + + plt.xlabel('VFM yaw') + plt.ylabel('Edge') + plt.title('VFM Yaw Calibration') + plt.legend() + plt.grid(True) + plt.tight_layout() + plt.show() + +from dataclasses import dataclass +import time + + +@dataclass +class SlitAxis: + name: str + centre_motor: object # e.g. dev.slit1_x + size_motor: object # e.g. dev.slit1_xsize + scan_func: callable # your existing peak scan function + scan_range: float = 2.0 + open_size: float = 2.0 + min_size: float = -0.4 + max_size: float = 5.0 + + +@dataclass +class Slit: + name: str + x: SlitAxis + y: SlitAxis + + +def read_intensity(detector, n=5, delay=0.1): + values = [] + for _ in range(n): + values.append(detector.read()[detector.name]["value"]) + time.sleep(delay) + return sum(values) / len(values) + + + +def reduce_to_transmission(axis, detector, baseline, target=0.15, step=0.05): + """ + Close slit size until intensity is around target * baseline. + """ + size = axis.size_motor.position + + while size > axis.min_size: + intensity = read_intensity(detector) + transmission = intensity / baseline + + print( + f"{axis.name}: size={size:.4f}, " + f"I={intensity:.3g}, transmission={transmission:.3f}" + ) + + if transmission <= target: + return size, intensity + + size -= step + umv(axis.size_motor, size) + + raise RuntimeError(f"{axis.name}: reached minimum slit size without reaching target") + + +def open_to_transmission(axis, detector, baseline, target=0.99, step=0.05): + """ + Open slit until intensity is close to the original baseline. + """ + size = axis.size_motor.position + + while size < axis.max_size: + intensity = read_intensity(detector) + transmission = intensity / baseline + + print( + f"{axis.name}: size={size:.4f}, " + f"I={intensity:.3g}, transmission={transmission:.3f}" + ) + + if transmission >= target: + return size, intensity + + size += step + umv(axis.size_motor, size) + # final_size = axis.size.motor.position + # fudge = 0.5 + # umv(axis.size_motor,final_size + fudge) + + raise RuntimeError(f"{axis.name}: reached maximum slit size without restoring intensity") + +# def approx_centre_axis(axis, detector, slitsize=0.5): +# umv(axis.size_motor, slitsize) +# go_to_peak(axis.centre_motor, detector, -4, 4, 50, confirm=False) + + +def centre_axis(axis, detector, close_fraction=0.10, open_fraction=0.95): + print(f"\nAligning {axis.name}") + + # approx_centre_axis(axis, detector, slitsize=0.5) + + umv(axis.size_motor, axis.open_size) + + baseline = read_intensity(detector) + print(f"{axis.name}: baseline intensity = {baseline:.3g}") + + # if baseline <= 0: + # raise RuntimeError(f"{axis.name}: invalid baseline intensity") + + reduce_to_transmission( + axis, + detector, + baseline, + target=close_fraction, + ) + + go_to_peak(axis.centre_motor, detector, axis.centre_motor.position - axis.scan_range, + axis.centre_motor.position + axis.scan_range, + 50, + confirm=False) + print(f"{axis.name}: moving centre to peak position") + + open_to_transmission( + axis, + detector, + baseline, + target=open_fraction, + ) + + final_intensity = read_intensity(detector) + print( + f"{axis.name}: final intensity = {final_intensity:.3g}, " + f"transmission = {final_intensity / baseline:.3f}" + ) + +def open_slits(size=3): + slits = define_slits() + for slit in slits: + umv(slit.x.size_motor, size) + umv(slit.y.size_motor, size) + + +def centre_slit(slit, detector): + print(f"\n=== Aligning {slit.name} ===") + + centre_axis(slit.x, detector) + centre_axis(slit.y, detector) + + print(f"=== Finished {slit.name} ===") + + +def centre_all_slits(slits, detector): + for slit in slits: + try: + centre_slit(slit, detector) + except Exception as exc: + print(f"WARNING: failed to align {slit.name}: {exc}") + print("Continuing with next slit.") + +def centre_one(name, detector): + slits = define_slits() + for slit in slits: + if slit.name == name: + centre_slit(slit, detector) + +def define_slits(): + slits = [ + Slit( + name="bsf", + x=SlitAxis( + name="bsf_sl_x", + centre_motor=dev.bsf_sl_xcen, + size_motor=dev.bsf_sl_xsize, + scan_func=go_to_peak, + ), + y=SlitAxis( + name="bsf_sl_y", + centre_motor=dev.bsf_sl_ycen, + size_motor=dev.bsf_sl_ysize, + scan_func=go_to_peak, + ), + ), + Slit( + name="ss", + x=SlitAxis( + name="ss_sl_x", + centre_motor=dev.ss_sl_xcen, + size_motor=dev.ss_sl_xsize, + scan_func=go_to_peak, + ), + y=SlitAxis( + name="ss_sl_y", + centre_motor=dev.ss_sl_ycen, + size_motor=dev.ss_sl_ysize, + scan_func=go_to_peak, + ), + ), + Slit( + name="bcu", + x=SlitAxis( + name="bcu_sl_x", + centre_motor=dev.bcu_sl_xcen, + size_motor=dev.bcu_sl_xsize, + scan_func=go_to_peak, + ), + y=SlitAxis( + name="ss_sl_y", + centre_motor=dev.bcu_sl_ycen, + size_motor=dev.bcu_sl_ysize, + scan_func=go_to_peak, + ), + ), + ] + return slits + diff --git a/pxii_bec/macros/luts/27061952_vfm_pitch_energy.csv b/pxii_bec/macros/luts/27061952_vfm_pitch_energy.csv new file mode 100644 index 0000000..37b4f12 --- /dev/null +++ b/pxii_bec/macros/luts/27061952_vfm_pitch_energy.csv @@ -0,0 +1,96 @@ +energy,pitch,diode +10.00,2.79003,2.5101e-05 +10.00,2.86503,2.7481e-05 +10.00,2.94003,2.7441e-05 +10.00,3.01503,2.7531e-05 +10.00,3.09003,2.7429e-05 +11.00,2.79003,6.7964e-05 +11.00,2.86503,7.9833e-05 +11.00,2.94003,7.9545e-05 +11.00,3.01503,7.9683e-05 +11.00,3.09003,7.9548e-05 +12.00,2.79003,6.4495e-05 +12.00,2.86503,7.3507e-05 +12.00,2.94003,7.3534e-05 +12.00,3.01503,7.3641e-05 +12.00,3.09003,7.292e-05 +13.00,2.79003,5.1657e-05 +13.00,2.86503,5.6129e-05 +13.00,2.94003,5.5938e-05 +13.00,3.01503,5.5935e-05 +13.00,3.09003,5.5824e-05 +14.00,2.79003,5.0019e-05 +14.00,2.86503,5.4959e-05 +14.00,2.94003,5.4717e-05 +14.00,3.01503,5.4711e-05 +14.00,3.09003,5.4572e-05 +15.00,2.79003,3.8514e-05 +15.00,2.86503,4.2182e-05 +15.00,2.94003,4.2072e-05 +15.00,3.01503,4.2056e-05 +15.00,3.09003,4.1897e-05 +16.00,2.79003,2.6391e-05 +16.00,2.86503,2.8237e-05 +16.00,2.94003,2.8187e-05 +16.00,3.01503,2.8078e-05 +16.00,3.09003,2.7934e-05 +17.00,2.79003,1.9654e-05 +17.00,2.86503,2.0669e-05 +17.00,2.94003,2.0592e-05 +17.00,3.01503,2.0495e-05 +17.00,3.09003,2.0409e-05 +18.00,2.79003,1.6418e-05 +18.00,2.86503,1.7321e-05 +18.00,2.94003,1.7276e-05 +18.00,3.01503,1.7201e-05 +18.00,3.09003,1.7058e-05 +19.00,2.79003,1.1114e-05 +19.00,2.86503,1.1688e-05 +19.00,2.94003,1.1616e-05 +19.00,3.01503,1.1486e-05 +19.00,3.09003,1.1229e-05 +20.00,2.79003,1.0067e-05 +20.00,2.86503,1.0474e-05 +20.00,2.94003,1.0233e-05 +20.00,3.01503,9.7442e-06 +20.00,3.09003,8.7702e-06 +21.00,2.79003,6.6035e-06 +21.00,2.86503,6.4392e-06 +21.00,2.94003,5.6891e-06 +21.00,3.01503,4.6277e-06 +21.00,3.09003,3.4547e-06 +22.00,2.79003,3.4235e-06 +22.00,2.86503,2.8148e-06 +22.00,2.94003,2.0854e-06 +22.00,3.01503,1.413e-06 +22.00,3.09003,1.0058e-06 +23.00,2.79003,1.3978e-06 +23.00,2.86503,9.5583e-07 +23.00,2.94003,6.9829e-07 +23.00,3.01503,5.3073e-07 +23.00,3.09003,4.8376e-07 +24.00,2.79003,5.5859e-07 +24.00,2.86503,4.3102e-07 +24.00,2.94003,3.3977e-07 +24.00,3.01503,2.7979e-07 +24.00,3.09003,2.2912e-07 +25.00,2.79003,2.3919e-07 +25.00,2.86503,1.9166e-07 +25.00,2.94003,1.5672e-07 +25.00,3.01503,1.2674e-07 +25.00,3.09003,9.9158e-08 +26.00,2.79003,1.7634e-07 +26.00,2.86503,1.4523e-07 +26.00,2.94003,1.1948e-07 +26.00,3.01503,9.6605e-08 +26.00,3.09003,8.3358e-08 +27.00,2.79003,7.4085e-08 +27.00,2.86503,6.2851e-08 +27.00,2.94003,5.1639e-08 +27.00,3.01503,4.5493e-08 +27.00,3.09003,4.1044e-08 +28.00,2.79003,4.757e-08 +28.00,2.86503,4.0306e-08 +28.00,2.94003,3.6045e-08 +28.00,3.01503,3.1936e-08 +28.00,3.09003,2.5395e-08 diff --git a/pxii_bec/macros/luts/27062057_vfm_pitch_energy.csv b/pxii_bec/macros/luts/27062057_vfm_pitch_energy.csv new file mode 100644 index 0000000..6849861 --- /dev/null +++ b/pxii_bec/macros/luts/27062057_vfm_pitch_energy.csv @@ -0,0 +1,51 @@ +energy,pitch,diode +17.00,2.49006,6.9998e-08 +17.00,2.54006,8.0892e-08 +17.00,2.59006,9.3759e-08 +17.00,2.64006,1.1324e-07 +17.00,2.69006,1.4562e-07 +18.00,2.49006,6.122e-08 +18.00,2.54006,7.1592e-08 +18.00,2.59006,8.4016e-08 +18.00,2.64006,1.0291e-07 +18.00,2.69006,1.3362e-07 +19.00,2.49006,3.8423e-08 +19.00,2.54006,4.5515e-08 +19.00,2.59006,5.3896e-08 +19.00,2.64006,6.6516e-08 +19.00,2.69006,8.8274e-08 +20.00,2.49006,2.9234e-08 +20.00,2.54006,3.5421e-08 +20.00,2.59006,4.3305e-08 +20.00,2.64006,5.5004e-08 +20.00,2.69006,7.3772e-08 +21.00,2.49006,1.7361e-08 +21.00,2.54006,2.0553e-08 +21.00,2.59006,2.5132e-08 +21.00,2.64006,3.2485e-08 +21.00,2.69006,4.5865e-08 +22.00,2.49006,1.0198e-08 +22.00,2.54006,1.1792e-08 +22.00,2.59006,1.4037e-08 +22.00,2.64006,1.7411e-08 +22.00,2.69006,2.4266e-08 +23.00,2.49006,7.7011e-09 +23.00,2.54006,8.4929e-09 +23.00,2.59006,9.5513e-09 +23.00,2.64006,1.1054e-08 +23.00,2.69006,1.4002e-08 +24.00,2.49006,5.3858e-09 +24.00,2.54006,5.698e-09 +24.00,2.59006,6.161e-09 +24.00,2.64006,6.804e-09 +24.00,2.69006,8.1435e-09 +25.00,2.49006,4.2137e-09 +25.00,2.54006,4.3605e-09 +25.00,2.59006,4.5837e-09 +25.00,2.64006,4.8794e-09 +25.00,2.69006,5.3341e-09 +26.00,2.49006,4.1207e-09 +26.00,2.54006,4.2034e-09 +26.00,2.59006,4.3481e-09 +26.00,2.64006,4.4824e-09 +26.00,2.69006,4.9786e-09 diff --git a/pxii_bec/macros/luts/27062107_vfm_pitch_energy.csv b/pxii_bec/macros/luts/27062107_vfm_pitch_energy.csv new file mode 100644 index 0000000..f5c08e6 --- /dev/null +++ b/pxii_bec/macros/luts/27062107_vfm_pitch_energy.csv @@ -0,0 +1,46 @@ +energy,pitch,diode +17.00,2.69000,1.5377e-07 +17.00,2.74000,5.5058e-07 +17.00,2.79000,2.8742e-05 +17.00,2.84000,2.992e-05 +17.00,2.89000,2.9921e-05 +18.00,2.69000,1.3257e-07 +18.00,2.74000,6.2784e-07 +18.00,2.79000,2.3012e-05 +18.00,2.84000,2.4082e-05 +18.00,2.89000,2.3995e-05 +19.00,2.69000,8.7067e-08 +19.00,2.74000,5.28e-07 +19.00,2.79000,1.4786e-05 +19.00,2.84000,1.5433e-05 +19.00,2.89000,1.5369e-05 +20.00,2.69000,7.5571e-08 +20.00,2.74000,5.949e-07 +20.00,2.79000,1.3098e-05 +20.00,2.84000,1.3572e-05 +20.00,2.89000,1.3423e-05 +21.00,2.69000,4.5569e-08 +21.00,2.74000,4.6722e-07 +21.00,2.79000,8.2723e-06 +21.00,2.84000,8.1305e-06 +21.00,2.89000,7.7839e-06 +22.00,2.69000,2.4394e-08 +22.00,2.74000,3.137e-07 +22.00,2.79000,4.103e-06 +22.00,2.84000,3.6481e-06 +22.00,2.89000,3.0803e-06 +23.00,2.69000,1.4056e-08 +23.00,2.74000,2.2905e-07 +23.00,2.79000,1.6164e-06 +23.00,2.84000,1.2537e-06 +23.00,2.89000,9.8993e-07 +24.00,2.69000,8.1539e-09 +24.00,2.74000,8.9029e-08 +24.00,2.79000,6.3203e-07 +24.00,2.84000,5.3339e-07 +24.00,2.89000,4.4881e-07 +25.00,2.69000,5.483e-09 +25.00,2.74000,4.3057e-08 +25.00,2.79000,2.6918e-07 +25.00,2.84000,2.318e-07 +25.00,2.89000,2.0125e-07 diff --git a/pxii_bec/macros/luts/27062148_lut.csv b/pxii_bec/macros/luts/27062148_lut.csv new file mode 100644 index 0000000..21e7b3f --- /dev/null +++ b/pxii_bec/macros/luts/27062148_lut.csv @@ -0,0 +1,5 @@ +energy,harmonic,gap,pitch,roll,perp,samcam_x,samcam_y,zoom=501.0 +6000,H3,5.9369,-5.5214,4.651,0.178,1091,483.8 +6300,H3,6.2143,-5.5161,4.648,0.15925,1091,484.7 +6600,H3,6.5006,-5.513,4.651,0.14414,1089,482.2 +6900,H3,6.8005,-5.5102,4.65,0.1312,1089,482.3 diff --git a/pxii_bec/macros/luts/27062203_lut.csv b/pxii_bec/macros/luts/27062203_lut.csv new file mode 100644 index 0000000..4d82a61 --- /dev/null +++ b/pxii_bec/macros/luts/27062203_lut.csv @@ -0,0 +1,78 @@ +energy,harmonic,gap,pitch,roll,perp,samcam_x,samcam_y,zoom=501.0 +7000,H3,6.9059,-5.5096,4.651,0.12717,1089,480.7 +7300,H5,4.551,-5.5071,4.649,0.11594,1088,479.5 +7600,H5,4.697,-5.5057,4.647,0.10671,1087,478.8 +7900,H5,4.8454,-5.5028,4.65,0.09833,1084,478.9 +8200,H5,4.9952,-5.5026,4.649,0.09104,1085,481.3 +8500,H5,5.1461,-5.5018,4.648,0.084215,1086,481.8 +8800,H5,5.2989,-5.5,4.649,0.07845,1086,480.4 +9100,H5,5.4534,-5.5001,4.649,0.0732,1089,479.5 +9400,H5,5.6102,-5.4982,4.651,0.068385,1086,478.2 +9700,H5,5.7706,-5.497,4.651,0.064125,1086,477.8 +10000,H5,5.9309,-5.4964,4.651,0.06021,1085,475.8 +10300,H7,4.5766,-5.4954,4.651,0.056655,1086,474.8 +10600,H7,4.6797,-5.4945,4.651,0.0534,1085,474.5 +10900,H7,4.7853,-5.4938,4.651,0.050445,1085,473.1 +11200,H7,4.8916,-5.4933,4.651,0.04773,1084,472.4 +11500,H7,4.9984,-5.4927,4.651,0.04519,1084,471.9 +11800,H7,5.106,-5.4923,4.648,0.042885,1084,471.5 +12100,H7,5.2144,-5.4917,4.65,0.04069,1084,471.1 +12400,H7,5.3238,-5.491,4.65,0.03866,1083,469.9 +12700,H7,5.434,-5.4907,4.65,0.0369,1084,470 +13000,H7,5.5453,-5.4902,4.65,0.035145,1083,469 +13300,H9,4.5975,-5.4899,4.651,0.033575,1083,470.3 +13600,H9,4.6739,-5.4896,4.65,0.03209,1083,468.8 +13900,H9,4.7564,-5.4892,4.648,0.03027,1083,468.6 +14200,H9,4.8387,-5.4888,4.646,0.0302,1083,467.8 +14500,H9,4.9214,-5.4885,4.651,0.02818,1083,467.8 +14800,H9,5.0041,-5.4885,4.649,0.02704,1085,467.4 +15100,H9,5.0875,-5.488,4.651,0.02703,1084,466.9 +15400,H9,5.1711,-5.4876,4.649,0.024565,1083,466.7 +15700,H9,5.2554,-5.487,4.65,0.024555,1083,466.5 +16000,H9,5.3397,-5.4871,4.648,0.023035,1083,466.1 +16300,H11,4.6154,-5.4868,4.648,0.023025,1083,467.3 +16600,H11,4.6825,-5.4866,4.649,0.021305,1083,467.6 +16900,H11,4.7494,-5.4858,4.649,0.02127,1082,466.9 +17200,H11,4.8184,-5.4858,4.649,0.01983,1083,468.4 +17500,H11,4.8873,-5.4856,4.648,0.01976,1082,467.8 +17800,H11,4.9557,-5.4854,4.65,0.018535,1082,467.9 +18100,H11,5.0243,-5.4853,4.65,0.01849,1083,467.2 +18400,H11,5.0929,-5.4846,4.649,0.017295,1083,466.8 +18700,H11,5.1629,-5.4847,4.648,0.017285,1083,466.9 +19000,H11,5.2347,-5.4846,4.65,0.017285,1083,466.1 +19300,H13,4.6243,-5.4842,4.65,0.015695,1082,465.7 +19600,H13,4.6808,-5.484,4.651,0.01564,1082,465.4 +19900,H13,4.7387,-5.4838,4.649,0.015625,1082,465 +20200,H13,4.7961,-5.4836,4.648,0.0144,1083,464.9 +20500,H13,4.8537,-5.4833,4.649,0.01437,1083,464.2 +20800,H13,4.9126,-5.4829,4.648,0.01436,1083,463.6 +21100,H13,4.971,-5.4833,4.649,0.01317,1082,464.1 +21400,H13,5.0299,-5.4823,4.651,0.01313,1082,464.2 +21700,H13,5.0894,-5.4829,4.649,0.013145,1081,463.8 +22000,H13,5.1481,-5.4828,4.65,0.013135,1083,463.6 +22300,H15,4.6281,-5.4829,4.649,0.01175,1083,463.9 +22600,H15,4.6771,-5.4826,4.651,0.011735,1083,464.4 +22900,H15,4.7273,-5.4825,4.65,0.01174,1082,463.7 +23200,H15,4.7774,-5.4824,4.648,0.01174,1083,463.7 +23500,H15,4.8264,-5.4822,4.649,0.010605,1082,463.8 +23800,H15,4.8783,-5.4821,4.65,0.010585,1082,463.6 +24100,H15,4.9262,-5.482,4.649,0.01058,1082,463.8 +24400,H15,4.9759,-5.4818,4.649,0.010585,1082,463.4 +24700,H15,5.0255,-5.4818,4.649,0.010595,1082,463.4 +25000,H15,5.078,-5.4818,4.648,0.0094,1082,463 +25300,H17,4.6289,-5.482,4.649,0.00939,1082,462.7 +25600,H17,4.6718,-5.4819,4.648,0.009385,1082,462.9 +25900,H17,4.7168,-5.4819,4.649,0.00939,1080,463.4 +26200,H17,4.7603,-5.4819,4.649,0.009385,1082,463.2 +26500,H17,4.803,-5.4817,4.649,0.0094,1081,463.5 +26800,H17,4.8495,-5.4814,4.651,0.00814,1082,463.7 +27100,H17,4.8965,-5.4815,4.649,0.008145,1080,464.1 +27400,H17,4.9377,-5.4816,4.65,0.008145,1081,463.1 +27700,H19,4.5375,-5.4817,4.649,0.008155,1081,461.8 +28000,H19,4.5909,-5.4818,4.65,0.008135,1082,462 +28300,H19,4.6433,-5.4815,4.649,0.00815,1081,463.5 +28600,H19,4.677,-5.4813,4.649,0.008155,1081,462.6 +28900,H19,4.7062,-5.4813,4.651,0.007025,1081,461.5 +29200,H19,4.7429,-5.4812,4.649,0.00701,1081,461.8 +29500,H19,4.7828,-5.4811,4.65,0.00702,1080,461.9 +29800,H19,4.822,-5.4814,4.651,0.007015,1081,462.6 diff --git a/pxii_bec/macros/luts/2706_dcm_lut.csv b/pxii_bec/macros/luts/2706_dcm_lut.csv new file mode 100644 index 0000000..a1d612c --- /dev/null +++ b/pxii_bec/macros/luts/2706_dcm_lut.csv @@ -0,0 +1,83 @@ +energy,harmonic,gap,pitch,roll,perp,samcam_x,samcam_y,zoom=501.0 +6000,H3,5.9369,-5.5214,4.651,0.178,1091,483.8 +6300,H3,6.2143,-5.5161,4.648,0.15925,1091,484.7 +6600,H3,6.5006,-5.513,4.651,0.14414,1089,482.2 +6900,H3,6.8005,-5.5102,4.65,0.1312,1089,482.3 +energy,harmonic,gap,pitch,roll,perp,samcam_x,samcam_y,zoom=501.0 +7000,H3,6.9059,-5.5096,4.651,0.12717,1089,480.7 +7300,H5,4.551,-5.5071,4.649,0.11594,1088,479.5 +7600,H5,4.697,-5.5057,4.647,0.10671,1087,478.8 +7900,H5,4.8454,-5.5028,4.65,0.09833,1084,478.9 +8200,H5,4.9952,-5.5026,4.649,0.09104,1085,481.3 +8500,H5,5.1461,-5.5018,4.648,0.084215,1086,481.8 +8800,H5,5.2989,-5.5,4.649,0.07845,1086,480.4 +9100,H5,5.4534,-5.5001,4.649,0.0732,1089,479.5 +9400,H5,5.6102,-5.4982,4.651,0.068385,1086,478.2 +9700,H5,5.7706,-5.497,4.651,0.064125,1086,477.8 +10000,H5,5.9309,-5.4964,4.651,0.06021,1085,475.8 +10300,H7,4.5766,-5.4954,4.651,0.056655,1086,474.8 +10600,H7,4.6797,-5.4945,4.651,0.0534,1085,474.5 +10900,H7,4.7853,-5.4938,4.651,0.050445,1085,473.1 +11200,H7,4.8916,-5.4933,4.651,0.04773,1084,472.4 +11500,H7,4.9984,-5.4927,4.651,0.04519,1084,471.9 +11800,H7,5.106,-5.4923,4.648,0.042885,1084,471.5 +12100,H7,5.2144,-5.4917,4.65,0.04069,1084,471.1 +12400,H7,5.3238,-5.491,4.65,0.03866,1083,469.9 +12700,H7,5.434,-5.4907,4.65,0.0369,1084,470 +13000,H7,5.5453,-5.4902,4.65,0.035145,1083,469 +13300,H9,4.5975,-5.4899,4.651,0.033575,1083,470.3 +13600,H9,4.6739,-5.4896,4.65,0.03209,1083,468.8 +13900,H9,4.7564,-5.4892,4.648,0.03027,1083,468.6 +14200,H9,4.8387,-5.4888,4.646,0.0302,1083,467.8 +14500,H9,4.9214,-5.4885,4.651,0.02818,1083,467.8 +14800,H9,5.0041,-5.4885,4.649,0.02704,1085,467.4 +15100,H9,5.0875,-5.488,4.651,0.02703,1084,466.9 +15400,H9,5.1711,-5.4876,4.649,0.024565,1083,466.7 +15700,H9,5.2554,-5.487,4.65,0.024555,1083,466.5 +16000,H9,5.3397,-5.4871,4.648,0.023035,1083,466.1 +16300,H11,4.6154,-5.4868,4.648,0.023025,1083,467.3 +16600,H11,4.6825,-5.4866,4.649,0.021305,1083,467.6 +16900,H11,4.7494,-5.4858,4.649,0.02127,1082,466.9 +17200,H11,4.8184,-5.4858,4.649,0.01983,1083,468.4 +17500,H11,4.8873,-5.4856,4.648,0.01976,1082,467.8 +17800,H11,4.9557,-5.4854,4.65,0.018535,1082,467.9 +18100,H11,5.0243,-5.4853,4.65,0.01849,1083,467.2 +18400,H11,5.0929,-5.4846,4.649,0.017295,1083,466.8 +18700,H11,5.1629,-5.4847,4.648,0.017285,1083,466.9 +19000,H11,5.2347,-5.4846,4.65,0.017285,1083,466.1 +19300,H13,4.6243,-5.4842,4.65,0.015695,1082,465.7 +19600,H13,4.6808,-5.484,4.651,0.01564,1082,465.4 +19900,H13,4.7387,-5.4838,4.649,0.015625,1082,465 +20200,H13,4.7961,-5.4836,4.648,0.0144,1083,464.9 +20500,H13,4.8537,-5.4833,4.649,0.01437,1083,464.2 +20800,H13,4.9126,-5.4829,4.648,0.01436,1083,463.6 +21100,H13,4.971,-5.4833,4.649,0.01317,1082,464.1 +21400,H13,5.0299,-5.4823,4.651,0.01313,1082,464.2 +21700,H13,5.0894,-5.4829,4.649,0.013145,1081,463.8 +22000,H13,5.1481,-5.4828,4.65,0.013135,1083,463.6 +22300,H15,4.6281,-5.4829,4.649,0.01175,1083,463.9 +22600,H15,4.6771,-5.4826,4.651,0.011735,1083,464.4 +22900,H15,4.7273,-5.4825,4.65,0.01174,1082,463.7 +23200,H15,4.7774,-5.4824,4.648,0.01174,1083,463.7 +23500,H15,4.8264,-5.4822,4.649,0.010605,1082,463.8 +23800,H15,4.8783,-5.4821,4.65,0.010585,1082,463.6 +24100,H15,4.9262,-5.482,4.649,0.01058,1082,463.8 +24400,H15,4.9759,-5.4818,4.649,0.010585,1082,463.4 +24700,H15,5.0255,-5.4818,4.649,0.010595,1082,463.4 +25000,H15,5.078,-5.4818,4.648,0.0094,1082,463 +25300,H17,4.6289,-5.482,4.649,0.00939,1082,462.7 +25600,H17,4.6718,-5.4819,4.648,0.009385,1082,462.9 +25900,H17,4.7168,-5.4819,4.649,0.00939,1080,463.4 +26200,H17,4.7603,-5.4819,4.649,0.009385,1082,463.2 +26500,H17,4.803,-5.4817,4.649,0.0094,1081,463.5 +26800,H17,4.8495,-5.4814,4.651,0.00814,1082,463.7 +27100,H17,4.8965,-5.4815,4.649,0.008145,1080,464.1 +27400,H17,4.9377,-5.4816,4.65,0.008145,1081,463.1 +27700,H19,4.5375,-5.4817,4.649,0.008155,1081,461.8 +28000,H19,4.5909,-5.4818,4.65,0.008135,1082,462 +28300,H19,4.6433,-5.4815,4.649,0.00815,1081,463.5 +28600,H19,4.677,-5.4813,4.649,0.008155,1081,462.6 +28900,H19,4.7062,-5.4813,4.651,0.007025,1081,461.5 +29200,H19,4.7429,-5.4812,4.649,0.00701,1081,461.8 +29500,H19,4.7828,-5.4811,4.65,0.00702,1080,461.9 +29800,H19,4.822,-5.4814,4.651,0.007015,1081,462.6 diff --git a/pxii_bec/macros/luts/roll_20000.csv b/pxii_bec/macros/luts/roll_20000.csv new file mode 100644 index 0000000..aed035c --- /dev/null +++ b/pxii_bec/macros/luts/roll_20000.csv @@ -0,0 +1,10 @@ +Roll, Y pos +1,313.4 +2,351.5 +3,388.1 +4,425 +5,460 +6,494.7 +7,526.9 +8,558.8 +9,590.4 diff --git a/pxii_bec/macros/luts/roll_6000.csv b/pxii_bec/macros/luts/roll_6000.csv new file mode 100644 index 0000000..35bd5d2 --- /dev/null +++ b/pxii_bec/macros/luts/roll_6000.csv @@ -0,0 +1,12 @@ +Roll, Y pos +2,125.4 +2.5,194.1 +3,260.1 +3.5,325.8 +4,387.4 +4.5,446.9 +5,504.4 +5.5,558.2 +6,609.9 +6.5,658.1 +7,705.2 diff --git a/pxii_bec/macros/luts/vfm_pitch_energy.csv b/pxii_bec/macros/luts/vfm_pitch_energy.csv new file mode 100644 index 0000000..fa5bcae --- /dev/null +++ b/pxii_bec/macros/luts/vfm_pitch_energy.csv @@ -0,0 +1,96 @@ +energy,pitch,diode +10.00,2.89010,2.778e-05 +10.00,2.91510,2.7708e-05 +10.00,2.94010,2.7698e-05 +10.00,2.96510,2.7769e-05 +10.00,2.99010,2.7757e-05 +11.00,2.89010,7.9613e-05 +11.00,2.91510,7.9352e-05 +11.00,2.94010,7.9336e-05 +11.00,2.96510,7.9483e-05 +11.00,2.99010,7.9565e-05 +12.00,2.89010,7.449e-05 +12.00,2.91510,7.4458e-05 +12.00,2.94010,7.4567e-05 +12.00,2.96510,7.4801e-05 +12.00,2.99010,7.4712e-05 +13.00,2.89010,5.6131e-05 +13.00,2.91510,5.6056e-05 +13.00,2.94010,5.5966e-05 +13.00,2.96510,5.5828e-05 +13.00,2.99010,5.5948e-05 +14.00,2.89010,5.5324e-05 +14.00,2.91510,5.5195e-05 +14.00,2.94010,5.5113e-05 +14.00,2.96510,5.5187e-05 +14.00,2.99010,5.508e-05 +15.00,2.89010,4.1622e-05 +15.00,2.91510,4.1965e-05 +15.00,2.94010,4.2153e-05 +15.00,2.96510,4.2094e-05 +15.00,2.99010,4.2148e-05 +16.00,2.89010,2.8267e-05 +16.00,2.91510,2.8252e-05 +16.00,2.94010,2.8214e-05 +16.00,2.96510,2.8193e-05 +16.00,2.99010,2.8145e-05 +17.00,2.89010,2.1235e-05 +17.00,2.91510,2.1204e-05 +17.00,2.94010,2.1172e-05 +17.00,2.96510,2.1117e-05 +17.00,2.99010,2.1088e-05 +18.00,2.89010,1.7443e-05 +18.00,2.91510,1.7463e-05 +18.00,2.94010,1.7414e-05 +18.00,2.96510,1.7132e-05 +18.00,2.99010,1.7091e-05 +19.00,2.89010,1.1583e-05 +19.00,2.91510,1.1553e-05 +19.00,2.94010,1.1521e-05 +19.00,2.96510,1.1486e-05 +19.00,2.99010,1.144e-05 +20.00,2.89010,1.0526e-05 +20.00,2.91510,1.0445e-05 +20.00,2.94010,1.036e-05 +20.00,2.96510,1.0243e-05 +20.00,2.99010,1.0096e-05 +21.00,2.89010,6.2969e-06 +21.00,2.91510,6.0377e-06 +21.00,2.94010,5.7381e-06 +21.00,2.96510,5.4072e-06 +21.00,2.99010,5.0424e-06 +22.00,2.89010,2.5998e-06 +22.00,2.91510,2.3461e-06 +22.00,2.94010,2.0986e-06 +22.00,2.96510,1.8549e-06 +22.00,2.99010,1.6269e-06 +23.00,2.89010,8.4958e-07 +23.00,2.91510,7.6319e-07 +23.00,2.94010,6.9276e-07 +23.00,2.96510,6.2826e-07 +23.00,2.99010,5.6922e-07 +24.00,2.89010,3.8721e-07 +24.00,2.91510,3.5652e-07 +24.00,2.94010,3.3073e-07 +24.00,2.96510,3.0885e-07 +24.00,2.99010,2.892e-07 +25.00,2.89010,1.7873e-07 +25.00,2.91510,1.6681e-07 +25.00,2.94010,1.5642e-07 +25.00,2.96510,1.4637e-07 +25.00,2.99010,1.3626e-07 +26.00,2.89010,1.3718e-07 +26.00,2.91510,1.2827e-07 +26.00,2.94010,1.1991e-07 +26.00,2.96510,1.1148e-07 +26.00,2.99010,1.0365e-07 +27.00,2.89010,5.8959e-08 +27.00,2.91510,5.5025e-08 +27.00,2.94010,5.1655e-08 +27.00,2.96510,4.9044e-08 +27.00,2.99010,4.715e-08 +28.00,2.89010,3.8685e-08 +28.00,2.91510,3.7246e-08 +28.00,2.94010,3.6209e-08 +28.00,2.96510,3.5094e-08 +28.00,2.99010,3.3689e-08 diff --git a/pxii_bec/macros/mx_basics.py b/pxii_bec/macros/mx_basics.py index 492234c..132c8a9 100755 --- a/pxii_bec/macros/mx_basics.py +++ b/pxii_bec/macros/mx_basics.py @@ -61,7 +61,7 @@ def get_data_from_history( """Read data from the BEC history and return the X and Y data as arrays.""" scan = bec.history[history_index] md = scan.metadata["bec"] - motor_name = md["scan_motors"][0].decode() + motor_name = md["scan_report_devices"][0].decode() scan_number = md["scan_number"] x_data = scan.devices[motor_name][motor_name].read()["value"] y_data = scan.devices[signal_name][signal_name].read()["value"] diff --git a/pxii_bec/macros/mx_methods.py b/pxii_bec/macros/mx_methods.py index 8631d0f..54d99cb 100755 --- a/pxii_bec/macros/mx_methods.py +++ b/pxii_bec/macros/mx_methods.py @@ -231,10 +231,12 @@ def fit_history( # Perform fit and plot the data fit_result = fit(data, fit_params) plot_fitted_data_bec(data, fit_result) + # Optionally move the motor to the peak position if move_to_peak: move_to_position(data["motor_device"], data["motor_name"], fit_result["centre"], data) + return fit_result def scan_bpm(bpmname): diff --git a/pxii_bec/macros/pxii_energy.py b/pxii_bec/macros/pxii_energy.py index ad6cd50..9c36cef 100755 --- a/pxii_bec/macros/pxii_energy.py +++ b/pxii_bec/macros/pxii_energy.py @@ -165,8 +165,8 @@ def get_dcm_motors_positions(energy_ev): """ # dcm_motor_values = get_value_from_lut(energy_ev) dcm_motor_values = {} - # pitch = float(np.poly1d(Calibration.pitch)(energy_ev)) - pitch = -5.5 + pitch = float(np.poly1d(Calibration.pitch_calib)(energy_ev)) + # pitch = -5.5 fpitch = 5.0 roll = EnergyDefaults.mono_roll_value perp = calc_perp_position(energy_ev, print_result=False) diff --git a/pxii_bec/macros/pxii_parameters.py b/pxii_bec/macros/pxii_parameters.py index aa87fb3..e0a54df 100755 --- a/pxii_bec/macros/pxii_parameters.py +++ b/pxii_bec/macros/pxii_parameters.py @@ -18,7 +18,7 @@ class EnergyDefaults: mono_fpitch = dev.dcm_fpitch mono_perp = dev.dcm_perp mono_roll = dev.dcm_froll - mono_roll_value = 4.65 + mono_roll_value = 4.56 LUT_table = "luts/energy_lut.csv" stripe_thresholds = {"silicon": 9000, "rhodium": 20000, "platinum": 40000} pitch_scan = {"halfwidth": 0.075, "steps": 20} @@ -28,8 +28,13 @@ class EnergyDefaults: class Calibration: """Calibration parameters for PXII optics""" - pitch = np.array([4.61823701e-14, -1.97330772e-09, 2.89694543e-05, -5.34468669e00]) - roll = np.array([2.28291039e-03, -2.41928101e01]) + # pitch = np.array([4.61823701e-14, -1.97330772e-09, 2.89694543e-05, -5.34468669e00]) + pitch_calib = [-5.89030403e-19, + 4.85665619e-14, + -1.49364459e-09, + 2.08652765e-05, + -5.59843072e+00] + # roll = np.array([2.28291039e-03, -2.41928101e01]) @dataclass(frozen=True) -- 2.54.0 From f520456a39d4926fff68bd613febcde30aa8e58f Mon Sep 17 00:00:00 2001 From: appel_c Date: Mon, 29 Jun 2026 12:39:33 +0200 Subject: [PATCH 4/9] feat(stats_signal): Test device to get sigma_x and y and eccentricity from stats module --- pxii_bec/devices/stats_signal.py | 62 ++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 pxii_bec/devices/stats_signal.py diff --git a/pxii_bec/devices/stats_signal.py b/pxii_bec/devices/stats_signal.py new file mode 100644 index 0000000..92dbc86 --- /dev/null +++ b/pxii_bec/devices/stats_signal.py @@ -0,0 +1,62 @@ +from ophyd_devices import AsyncMultiSignal + +from ophyd_devices.interfaces.base_classes.psi_device_base import PSIDeviceBase +from ophyd import Component as Cpt +from ophyd import EpicsSignalRO, Kind +from collections import defaultdict +from threading import RLock +import time + + +class StatsSignal(PSIDeviceBase, AsyncMultiSignal): + + data = Cpt( + AsyncMultiSignal, + name="data", + signals=["sigma_x", "sigma_y", "eccentricity"], + ndim=1, + async_update={"type": "add", "max_shape": [None]}, + max_size=1000, + kind=Kind.normal, + doc="Stats data signal containing sigma_x, sigma_y, and eccentricity values", + ) + + sigma_x_raw = Cpt(EpicsSignalRO, "Stats1:SigmaX_RBV", kind=Kind.omitted) + sigma_y_raw = Cpt(EpicsSignalRO, "Stats1:SigmaY_RBV", kind=Kind.omitted) + eccentricity_raw = Cpt(EpicsSignalRO, "Stats1:Eccentricity_RBV", kind=Kind.omitted) + + def on_init(self): + self._rlock = RLock() + self._cached_average_data = defaultdict(float) + + def on_connected(self): + self._cached_average_data.clear() + for sig in (self.sigma_x_raw, self.sigma_y_raw, self.eccentricity_raw): + sig.subscribe(self._update_average_data, run=False) + + def _update_average_data(self, value, obj, **kwargs): + if value is None: + return + sig_name = obj.name + + with self._rlock: + self._cached_average_data[sig_name] += value + + def on_trigger(self): + with self._rlock: + self._cached_average_data.clear() + time.sleep( + self.scan_info.msg.scan_parameters.get("exp_time") + ) # Wait for the exposure time to finish + + with self._rlock: + sigma_x = self._cached_average_data.get("sigma_x_raw", 0.0) + sigma_y = self._cached_average_data.get("sigma_y_raw", 0.0) + eccentricity = self._cached_average_data.get("eccentricity_raw", 0.0) + + ret = { + "sigma_x": {"value": sigma_x}, + "sigma_y": {"value": sigma_y}, + "eccentricity": {"value": eccentricity}, + } + self.data.put(ret) -- 2.54.0 From 7360329b9145404e52608dfb4ece02fca821fbc9 Mon Sep 17 00:00:00 2001 From: x10sa Date: Tue, 30 Jun 2026 14:07:09 +0200 Subject: [PATCH 5/9] updates to fitting routines --- pxii_bec/macros/katscripts.py | 26 ++++++++++ pxii_bec/macros/mx_basics.py | 93 +++++++++++++++++++++++++---------- pxii_bec/macros/mx_methods.py | 3 +- 3 files changed, 96 insertions(+), 26 deletions(-) diff --git a/pxii_bec/macros/katscripts.py b/pxii_bec/macros/katscripts.py index ed9f6cf..9dff871 100755 --- a/pxii_bec/macros/katscripts.py +++ b/pxii_bec/macros/katscripts.py @@ -1446,3 +1446,29 @@ def define_slits(): ] return slits +def get_mirror_data(history_index: int): + """Read data from the BEC history and return the X and Y data as arrays.""" + motor1 = "vfm_bu" + motor2 = "vfm_bd" + + scan = bec.history[history_index] + md = scan.metadata["bec"] + x1_data = scan.devices[motor1][motor1].read()["value"] + x2_data = scan.devices[motor2][motor2].read()["value"] + y1_data = scan.devices['microscope_stats']['microscope_stats_data_sigma_y'].read()['value'] + y2_data = scan.devices['microscope_stats']['microscope_stats_data_eccentricity'].read()['value'] + np.savetxt("luts/x1_data", x1_data) + np.savetxt("luts/x2_data", x2_data) + np.savetxt("luts/y1_data", y1_data) + np.savetxt("luts/y2_data", y2_data) + + + # plt.imshow(y1_data, cmap="hot") + # plt.clf + # return { + # "signal_name": signal_name, + # "x_data": x_data, + # "y_data": y_data, + # "motor_name": motor_name, + # "scan_number": scan_number, + # } \ No newline at end of file diff --git a/pxii_bec/macros/mx_basics.py b/pxii_bec/macros/mx_basics.py index 132c8a9..7577658 100755 --- a/pxii_bec/macros/mx_basics.py +++ b/pxii_bec/macros/mx_basics.py @@ -15,6 +15,7 @@ import matplotlib.pyplot as plt def create_fit_parameters( deriv: bool = False, + negative: bool = False, model: str = "Voigt", baseline: str = "Linear", smoothing: None = None, @@ -30,6 +31,7 @@ def create_fit_parameters( } return { "deriv": deriv, + "negative": negative, "model": model_mappings[model], "baseline": model_mappings[baseline], "smoothing": smoothing, @@ -53,23 +55,39 @@ def get_data_from_h5(signal_name: str = "lu_bpmsum"): "scan_number": str(scan_number), } +def get_history(scan): + if isinstance(scan, int): + if scan < 0: + return bec.history[scan] + return bec.history.get_by_scan_number(scan) + # return bec.history.get_by_dataset_number(scan) + return scan + def get_data_from_history( - history_index: int, + scan: int, signal_name: str = "lu_bpmsum", ): """Read data from the BEC history and return the X and Y data as arrays.""" - scan = bec.history[history_index] - md = scan.metadata["bec"] + + data = get_history(scan) + md = data.metadata["bec"] motor_name = md["scan_report_devices"][0].decode() + mot_name = motor_name.replace(".","_") + if "." in motor_name: + root_name = motor_name.split(".")[0] + x_data = data.devices[root_name][mot_name].read()["value"] + else: + x_data = data.devices[mot_name][mot_name].read()["value"] + scan_number = md["scan_number"] - x_data = scan.devices[motor_name][motor_name].read()["value"] - y_data = scan.devices[signal_name][signal_name].read()["value"] + + y_data = data.devices[signal_name][signal_name].read()["value"] return { "signal_name": signal_name, "x_data": x_data, "y_data": y_data, - "motor_name": motor_name, + "motor_name": mot_name, "scan_number": scan_number, } @@ -78,31 +96,56 @@ def process_data(data, fit_params): """ Process the signal data for fitting based on derivative or smoothing. """ - smoothing, deriv = fit_params["smoothing"], fit_params["deriv"] + smoothing = fit_params["smoothing"] + deriv = fit_params["deriv"] + negative = fit_params["negative"] + signal_name = data["signal_name"] y_data = data["y_data"] - if deriv: - if smoothing: - y_smooth = gaussian_filter1d(y_data, smoothing) - fitting_data = np.gradient(y_smooth) - signal_name = f"Derivative of smoothed {signal_name}" - else: - fitting_data = np.gradient(y_data) - signal_name = f"Derivative of {signal_name}" - elif smoothing and smoothing > 0.01: + if smoothing and smoothing > 0.01: fitting_data = gaussian_filter1d(y_data, smoothing) signal_name = f"Smoothed {signal_name}" else: - fitting_data = y_data + fitting_data = y_data.copy() - updated_data = { - "y_to_fit": fitting_data, - "signal_name": signal_name, - } - data.update(updated_data) + if deriv: + fitting_data = np.gradient(fitting_data) + signal_name = f"Derivative of {signal_name}" + + if negative: + fitting_data = -fitting_data + signal_name = f"Negative {signal_name}" + + data.update( + { + "y_to_fit": fitting_data, + "signal_name": signal_name, + } + ) return data + # if deriv: + # if smoothing: + # y_smooth = gaussian_filter1d(y_data, smoothing) + # fitting_data = np.gradient(y_smooth) + # signal_name = f"Derivative of smoothed {signal_name}" + # else: + # fitting_data = np.gradient(y_data) + # signal_name = f"Derivative of {signal_name}" + # elif smoothing and smoothing > 0.01: + # fitting_data = gaussian_filter1d(y_data, smoothing) + # signal_name = f"Smoothed {signal_name}" + # else: + # fitting_data = y_data + + # updated_data = { + # "y_to_fit": fitting_data, + # "signal_name": signal_name, + # } + # data.update(updated_data) + # return data + def fit(data, fit_params): """Fit a signal to a model and return the fitting results.""" @@ -234,9 +277,9 @@ def plot_fitted_data_bec( """ wf, text_box = select_bec_window() fit_text = ( - f"Fit parameters: Centre = {fit_result['centre']:.4f}, " - f"FWHM = {fit_result['fwhm']:.3f}, " - f"Height = {fit_result['height']:.4f}\n" + f"Fit parameters: Centre = {fit_result['centre']:.5g}, " + f"FWHM = {fit_result['fwhm']:.5f}, " + f"Height = {fit_result['height']:.4g}\n" f"Model = {fit_result['model']}\n" f"Chi sq = {fit_result['chi_sq']:.3g}" ) diff --git a/pxii_bec/macros/mx_methods.py b/pxii_bec/macros/mx_methods.py index 54d99cb..38cc6ed 100755 --- a/pxii_bec/macros/mx_methods.py +++ b/pxii_bec/macros/mx_methods.py @@ -198,6 +198,7 @@ def fit_history( history_index: int, signal_name: str, deriv: bool = False, + negative: bool = False, model: str = FitDefaults.MODEL, move_to_peak: bool = False, ): @@ -226,7 +227,7 @@ def fit_history( data = get_data_from_history(history_index, signal_name) # Define fitting parameters - fit_params = create_fit_parameters(deriv, model, FitDefaults.BASELINE) + fit_params = create_fit_parameters(deriv, negative, model, FitDefaults.BASELINE) # Perform fit and plot the data fit_result = fit(data, fit_params) -- 2.54.0 From 6e0916cce13db9fa35e20d27f170e555481030c3 Mon Sep 17 00:00:00 2001 From: x10sa Date: Tue, 7 Jul 2026 13:53:54 +0200 Subject: [PATCH 6/9] changes made during commissioning --- pxii_bec/device_configs/pxii-devices.yaml | 90 ++- .../device_configs/x10sa_device_config.yaml | 12 + pxii_bec/devices/stats_signal.py | 66 +- pxii_bec/macros/APscripts.py | 78 +- pxii_bec/macros/KB_Class.py | 12 +- pxii_bec/macros/calculator.py | 8 +- pxii_bec/macros/calibrate_bpm.py | 484 +++++++++++ pxii_bec/macros/chmirrh.py | 107 +-- pxii_bec/macros/chmirrh.py~ | 142 ---- pxii_bec/macros/katscripts.py | 764 ++++++++++-------- pxii_bec/macros/mx_methods.py | 7 +- 11 files changed, 1136 insertions(+), 634 deletions(-) create mode 100644 pxii_bec/macros/calibrate_bpm.py delete mode 100644 pxii_bec/macros/chmirrh.py~ diff --git a/pxii_bec/device_configs/pxii-devices.yaml b/pxii_bec/device_configs/pxii-devices.yaml index 2d0ab75..782114e 100644 --- a/pxii_bec/device_configs/pxii-devices.yaml +++ b/pxii_bec/device_configs/pxii-devices.yaml @@ -55,8 +55,8 @@ aerotech: deviceConfig: prefix: http://mx-x10sa-queue-01:5234 deviceTags: - - aerotech - motors + - aerotech enabled: true onFailure: buffer readoutPriority: baseline @@ -64,14 +64,13 @@ aerotech: u: mount: 0 work: 0 - work: null x: in: 0 out: -10 safe: -50 y: mount: -0.0 - work: -0.16 + work: -0.0 z: mount: 0 work: 0 @@ -292,7 +291,7 @@ bs_x: onFailure: buffer readoutPriority: baseline userParameter: - in: 1.9 + in: 0.2 bs_y: description: Beamstop Y deviceClass: ophyd_devices.EpicsMotor @@ -304,7 +303,7 @@ bs_y: onFailure: buffer readoutPriority: baseline userParameter: - in: -0.6 + in: -3.154 bs_z: description: Beamstop Z deviceClass: ophyd_devices.EpicsMotor @@ -320,7 +319,7 @@ bs_z: max_blout: 70 min: 13 safe: 45.1 - samp: 15.3 + samp: 16.408 type: continuous work_min: 20 bsf_f1_y: @@ -433,6 +432,8 @@ coll_x: enabled: true onFailure: buffer readoutPriority: baseline + userParameter: + in: -3.080 coll_y: description: Collimator Y deviceClass: ophyd_devices.EpicsMotor @@ -444,7 +445,7 @@ coll_y: onFailure: buffer readoutPriority: baseline userParameter: - in: 39.393 + in: 39.16 intermediate: 32 out: 20.002 park: 1 @@ -602,6 +603,9 @@ det_y: enabled: true onFailure: buffer readoutPriority: baseline + userParameter: + work: 70 + xi: 214 det_z: description: Detector Z deviceClass: ophyd_devices.EpicsMotor @@ -614,7 +618,7 @@ det_z: readoutPriority: baseline userParameter: mse: 800 - vis: 1198 + vis: 800 diag_y: description: Scintillator/diode Y deviceClass: ophyd_devices.EpicsMotor @@ -1206,6 +1210,26 @@ mag_ref: onFailure: buffer readOnly: true readoutPriority: baseline +microscope_stats: + description: Stats Signal of MS camera + deviceClass: pxii_bec.devices.stats_signal.StatsSignal + deviceConfig: + prefix: 'X10SA-ES-MS:' + enabled: true + readoutPriority: async + softwareTrigger: true +samcam_ecc: + description: Sample Camera Eccentricity + deviceClass: ophyd.EpicsSignalRO + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-MS:Stats5:Eccentricity_RBV + deviceTags: + - scam + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: monitored samcam_exp: description: Sample Camera Exposure deviceClass: ophyd.EpicsSignal @@ -1240,6 +1264,30 @@ samcam_max: onFailure: buffer readOnly: true readoutPriority: monitored +samcam_mean: + description: Sample Camera Mean + deviceClass: ophyd.EpicsSignalRO + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-MS:Stats1:MeanValue_RBV + deviceTags: + - scam + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: monitored +samcam_sigma: + description: Sample Camera Sigma + deviceClass: ophyd.EpicsSignalRO + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-MS:Stats1:Sigma_RBV + deviceTags: + - scam + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: monitored samcam_x: description: Sample Camera X deviceClass: ophyd.EpicsSignalRO @@ -1288,18 +1336,6 @@ samcam_ysig: onFailure: buffer readOnly: true readoutPriority: monitored -samcam_ecc: - description: Sample Camera Eccentricity - deviceClass: ophyd.EpicsSignalRO - deviceConfig: - auto_monitor: true - read_pv: X10SA-ES-MS:Stats5:Eccentricity_RBV - deviceTags: - - scam - enabled: true - onFailure: buffer - readOnly: true - readoutPriority: monitored scam_zoom: description: Sample Camera Zoom deviceClass: ophyd_devices.EpicsMotor @@ -1328,8 +1364,8 @@ smargon: deviceConfig: prefix: http://x10sa-smargopolo.psi.ch:3000 deviceTags: - - smargon - motors + - smargon enabled: true onFailure: buffer readoutPriority: baseline @@ -1424,6 +1460,18 @@ ss_bpmsum: onFailure: buffer readOnly: true readoutPriority: monitored +transm: + description: Beam Transmission + deviceClass: ophyd_devices.EpicsSignal + deviceConfig: + read_pv: 'X10SA-ES-SSFI:TRANSM-SET' + write_pv: 'X10SA-ES-SSFI:TRANSM-SET' + deviceTags: + - transm + enabled: true + onFailure: retry + readOnly: false + readoutPriority: baseline ss_f1_x: description: SS Filter 1 X deviceClass: ophyd_devices.EpicsMotor diff --git a/pxii_bec/device_configs/x10sa_device_config.yaml b/pxii_bec/device_configs/x10sa_device_config.yaml index 8e54df4..6778a92 100644 --- a/pxii_bec/device_configs/x10sa_device_config.yaml +++ b/pxii_bec/device_configs/x10sa_device_config.yaml @@ -1,5 +1,17 @@ base_config: - !include ./pxii-devices.yaml + +microscope_stats: + readoutPriority: async + description: Stats Signal of MS camera + deviceClass: pxii_bec.devices.stats_signal.StatsSignal + deviceConfig: + prefix: 'X10SA-ES-MS:' + onFailure: retry + enabled: true + readOnly: false + softwareTrigger: true + # sample_env: # - !include ./pxii-state-devices.yaml # id_gap: diff --git a/pxii_bec/devices/stats_signal.py b/pxii_bec/devices/stats_signal.py index 92dbc86..f9ac6da 100644 --- a/pxii_bec/devices/stats_signal.py +++ b/pxii_bec/devices/stats_signal.py @@ -1,14 +1,18 @@ -from ophyd_devices import AsyncMultiSignal - -from ophyd_devices.interfaces.base_classes.psi_device_base import PSIDeviceBase -from ophyd import Component as Cpt -from ophyd import EpicsSignalRO, Kind +import time from collections import defaultdict from threading import RLock -import time + +import numpy as np +from bec_lib.logger import bec_logger +from ophyd import Component as Cpt +from ophyd import EpicsSignalRO, Kind, Signal +from ophyd_devices import AsyncMultiSignal, StatusBase, TransitionStatus +from ophyd_devices.interfaces.base_classes.psi_device_base import PSIDeviceBase + +logger = bec_logger.logger -class StatsSignal(PSIDeviceBase, AsyncMultiSignal): +class StatsSignal(PSIDeviceBase): data = Cpt( AsyncMultiSignal, @@ -27,7 +31,7 @@ class StatsSignal(PSIDeviceBase, AsyncMultiSignal): def on_init(self): self._rlock = RLock() - self._cached_average_data = defaultdict(float) + self._cached_average_data = defaultdict(list) def on_connected(self): self._cached_average_data.clear() @@ -37,26 +41,44 @@ class StatsSignal(PSIDeviceBase, AsyncMultiSignal): def _update_average_data(self, value, obj, **kwargs): if value is None: return + if self.scan_info.msg is None: + return + if self.scan_info.msg.status != "open": + return + sig_name = obj.name + logger.info(f"Received update from signal {sig_name} with value{ value}") with self._rlock: - self._cached_average_data[sig_name] += value + self._cached_average_data[sig_name].append(value) def on_trigger(self): with self._rlock: self._cached_average_data.clear() - time.sleep( - self.scan_info.msg.scan_parameters.get("exp_time") - ) # Wait for the exposure time to finish + status = StatusBase(obj=self) # TransitionStatus(self.acquiring, transitions=[1, 0]) + status.add_callback(self._publish_data) + time.sleep(self.scan_info.msg.scan_parameters.get("exp_time", 0)) + status.set_finished() + return status - with self._rlock: - sigma_x = self._cached_average_data.get("sigma_x_raw", 0.0) - sigma_y = self._cached_average_data.get("sigma_y_raw", 0.0) - eccentricity = self._cached_average_data.get("eccentricity_raw", 0.0) + def _publish_data(self, status, **kwargs): + if status.done: + with self._rlock: - ret = { - "sigma_x": {"value": sigma_x}, - "sigma_y": {"value": sigma_y}, - "eccentricity": {"value": eccentricity}, - } - self.data.put(ret) + sigma_x = float( + np.average(self._cached_average_data.get(self.sigma_x_raw.name, [0])) + ) + sigma_y = float( + np.average(self._cached_average_data.get(self.sigma_y_raw.name, [0])) + ) + eccentricity = float( + np.average(self._cached_average_data.get(self.eccentricity_raw.name, [0])) + ) + + ret = { + "sigma_x": {"value": sigma_x}, + "sigma_y": {"value": sigma_y}, + "eccentricity": {"value": eccentricity}, + } + logger.info(f"Setting data for {self.name} data signal to {ret}.") + self.data.put(ret) diff --git a/pxii_bec/macros/APscripts.py b/pxii_bec/macros/APscripts.py index 871c3c0..1dd036e 100644 --- a/pxii_bec/macros/APscripts.py +++ b/pxii_bec/macros/APscripts.py @@ -313,9 +313,10 @@ def justfit(data_x, data_y, model="gauss", ibg=0): # diagnostics # print(f'Gfit: {g.params}') - print(f'Center of {model} fit: {g.pars["center"].value:.5f}') - print(f'Sigma: {g.pars["sigma"].value:.5f}') - print(f'FWHM: {g.pars["fwhm"].value:.5f}') + #print(f'Center of {model} fit: {g.pars["center"].value:.5f}') + #print(f'Sigma: {g.pars["sigma"].value:.5f}') + #print(f'FWHM: {g.pars["fwhm"].value:.5f}') + print(g.fit_report()) print(f"Position of maximum: {xm}") return g, xm @@ -338,13 +339,21 @@ def fit_plothist(hindex: int, signal_name: str, model="gauss", ibg=0): from lmfit.models import LinearModel, GaussianModel, VoigtModel, QuadraticModel, LorentzianModel import matplotlib.pyplot as plt - h = bec.history[hindex] + if hindex < 0: + h = bec.history[hindex] + print('by scan number') + else: + h = bec.history.get_by_scan_number(hindex) + print('by scan number') md = h.metadata["bec"] scanvar = list(md["args"].keys())[0] # string, returns the variable of the last performed scan # data = h.devices[device_name][signal].read()["value"] # data_x = h.devices.dcm_pitch.dcm_pitch.read()["value"] # data_y = h.devices.lu_bpmsum.lu_bpmsum.read()["value"] - # data_x = h.devices[device_name][device_name].read()["value"] + + ## that should work in any case: + device_name = scanvar + #data_x = h.devices[device_name][device_name].read()["value"] data_xd = md["positions"] # last scan knows which device ... however, double array data_x = data_xd.flatten() @@ -352,6 +361,10 @@ def fit_plothist(hindex: int, signal_name: str, model="gauss", ibg=0): data_y = h.devices[signal_name][signal_name].read()["value"] print("dy = ", data_y) + prefix='v_' + if model == 'gauss': + prefix='g_' + g, xm = justfit(data_x, data_y, model=model, ibg=ibg) plt.ion() @@ -362,7 +375,9 @@ def fit_plothist(hindex: int, signal_name: str, model="gauss", ibg=0): plt.ylabel(signal_name) plt.show() - gcen = g.pars["center"].value + # g.params + returncenvar = prefix+"center" + gcen = g.params[returncenvar].value return gcen, xm, data_x, data_y @@ -499,7 +514,7 @@ def fit_plot(data_x, data_y, model="gauss", ibg=1, fitrange=0, fitclick=0): fit_id = pre+'_center' - center = g.pars[fit_id].value + center = g.params[fit_id].value return center, xm @@ -550,7 +565,7 @@ def save_data(hindex: int, device_name: str, signal_name: str, isave = 1): ######################################### ### just retrieve the saved data from csv ######################################## -def read_data(filename: str): +def read_data_csv(filename: str): """ Get data stored in a CSV file @@ -872,7 +887,7 @@ def colliscan(direction: str, range=0.3, nsteps=30, stime=0.5, centre=1): settling time: default = 0.5 move to centre or not [0/1] - Example: colliscan("h", centre=1) + Example: colliscan("h", range=0.2, nsteps=30, stime=0.5,centre=1) """ import sys @@ -972,13 +987,14 @@ def slitscan(device_location: str, direction: str, range: 1, nsteps=50, centre=0 default_v = 1.0 ## 1.2 det = dev.lu_bpmsum if direction in ["x","h"]: - mot = dev.fe_sxcen - size = dev.fe_sxsize + mot = dev.fe_sl_xcen + size = dev.fe_sl_xsize s_closed = 0.1 s_open = default_h else: - mot = dev.fe_sycen - size = dev.fe_sysize + mot = dev.fe_sl_ycen + size = dev.fe_sl_ysize + s_closed = 0.1 s_open = default_v @@ -1072,9 +1088,9 @@ def slitscan(device_location: str, direction: str, range: 1, nsteps=50, centre=0 # FE slits ================================ data_y = s.scan.live_data.lu_bpmsum.lu_bpmsum.val - if mot.name == "fe_sxcen": + if mot.name == "fe_sl_xcen": data_x = s.scan.live_data.fe_sxcen.fe_sxcen.val - if mot.name == "fe_sycen": + if mot.name == "fe_sl_ycen": data_x = s.scan.live_data.fe_sycen.fe_sycen.val # BSF slits ================================ if mot.name == "bsf_sl_xcen": @@ -1486,7 +1502,7 @@ def scan_eg(erange, nsteps=50, fit=True): data_e = energy_data data_y = bpm_data - dirname = "/home/gac-x10sa/Data/" + dirname = "/sls/x10sa/config/commissioning/Data" # writing output to simple data file for later analysis: combined = np.column_stack((data_x, data_e, data_y)) tname = f"Scan_{timestamp}.txt" @@ -1533,3 +1549,33 @@ def scan_window(wname="Scan", fit=True): ### if done, remove #w2.remove() +################################################ +### beam centre on detector with distance +################################################ + +#/sls/x10sa/config/commissioning/Data + +def readdist(filename): + with open(filename, "r") as f: + combined_data = np.loadtxt(f, delimiter=",") + + ind1 = 0 + ind2 = 1 + ind3 = 2 + detdist = combined_data[:, ind1] + bposx = combined_data[:, ind2] + bposy = combined_data[:, ind3] + + plt.ion() + plt.figure(1) + plt.plot(detdist,bposx, ".") + plt.title("Bpos X vs Detectordist") + plt.xlabel("dist / mm") + plt.ylabel("bpos X in det pix ") + + plt.figure(2) + plt.plot(detdist,bposy, ".") + plt.title("Bpos Y vs Detectordist") + plt.xlabel("dist / mm") + plt.ylabel("bpos Y in det pix ") + plt.show() diff --git a/pxii_bec/macros/KB_Class.py b/pxii_bec/macros/KB_Class.py index 7c5dccb..51e2c7f 100644 --- a/pxii_bec/macros/KB_Class.py +++ b/pxii_bec/macros/KB_Class.py @@ -13,10 +13,10 @@ class KBMirror: self.P2 = 0.583490 self.P3 = -0.372950 self.L1 = -0.955798 - self.curv_approx_fact = 1.0121 - self.s1 = 24.15 #24.35 + self.curv_approx_fact = 0.9550 # 0.9550 # origin: 1.0121 + self.s1 = 24.15 self.s2 = 1.45 - self.asym0 = 0.08 + self.asym0 = 0.114 ## origin: 0.0.08 + 0.034 # user asymm, eg 0.4750, will be added ( - sign) elif self.mirror_type == "PXII_HFM": self.C0 = 0.060453 @@ -24,10 +24,10 @@ class KBMirror: self.P2 = 0.586057 self.P3 = -0.088093 self.L1 = -0.999445 - self.curv_approx_fact = 0.995 - self.s1 = 24.90 #25.10 + self.curv_approx_fact = 0.8810 # origin: # 0.995 + self.s1 = 24.90 self.s2 = 0.7 - self.asym0 = -0.0107 + self.asym0 = 0.06455 ## origin: -0.0107 + 0.07525 # added user asymm 2.75 (-sign) else: raise ValueError(f"Unknown mirror type: {self.mirror_type}") diff --git a/pxii_bec/macros/calculator.py b/pxii_bec/macros/calculator.py index b10a22a..a6278e8 100755 --- a/pxii_bec/macros/calculator.py +++ b/pxii_bec/macros/calculator.py @@ -17,6 +17,10 @@ class Constants: # d-spacings d_spacing = {120: 3.13481, 298: 3.13562} + # offset + # bragg_offset = -0.1457 + bragg_offset = 0 + def speed_of_light_ang(): """ @@ -116,7 +120,9 @@ def calculate_wavelength_from_angle(bragg_angle_mrad: float, temp=120) -> float: The calculated wavelength as a float value. """ d = Constants.d_spacing[temp] - return 2 * d * np.sin(bragg_angle_mrad / 1000) + fudge = bragg_angle_mrad + Constants.bragg_offset + # return 2 * d * np.sin((bragg_angle_mrad / 1000) + return 2 * d * np.sin(fudge / 1000) def calculate_energy_from_wavelength(wavelength: float) -> float: diff --git a/pxii_bec/macros/calibrate_bpm.py b/pxii_bec/macros/calibrate_bpm.py new file mode 100644 index 0000000..f041273 --- /dev/null +++ b/pxii_bec/macros/calibrate_bpm.py @@ -0,0 +1,484 @@ +""" +BPM calibration using inverse PCHIP spline. + +Calibration concept: + BPM signal -> beam position relative to BPM + +Final beam position: + beam_absolute = bpm_motor_position + local_beam_position + beam_relative_to_camera_crosshair = beam_absolute - camera_crosshair_position +""" + +import time +import os +from datetime import datetime, timedelta +import numpy as np +import matplotlib.pyplot as plt +from pyparsing import results +from scipy.optimize import curve_fit +import scipy.special as special +from scipy.interpolate import PchipInterpolator + + +def read_currents(): + """Read the individual bpm channels""" + vals_bpm1 = [] + vals_bpm2 = [] + vals_bpm3 = [] + vals_bpm4 = [] + + for _ in range(5): + vals_bpm1.append(dev.bcu_bpm1.read()["bcu_bpm1"]["value"]) + time.sleep(0.1) + for _ in range(5): + vals_bpm2.append(dev.bcu_bpm2.read()["bcu_bpm2"]["value"]) + time.sleep(0.1) + for _ in range(5): + vals_bpm3.append(dev.bcu_bpm3.read()["bcu_bpm3"]["value"]) + time.sleep(0.1) + for _ in range(5): + vals_bpm4.append(dev.bcu_bpm4.read()["bcu_bpm4"]["value"]) + time.sleep(0.1) + bpm1 = np.mean(vals_bpm1) + bpm2 = np.mean(vals_bpm2) + bpm3 = np.mean(vals_bpm3) + bpm4 = np.mean(vals_bpm4) + + # bpm1 = dev.bcu_bpm1.read()["bcu_bpm1"]["value"] + # bpm2 = dev.bcu_bpm2.read()["bcu_bpm2"]["value"] + # bpm3 = dev.bcu_bpm3.read()["bcu_bpm3"]["value"] + # bpm4 = dev.bcu_bpm4.read()["bcu_bpm4"]["value"] + # print(f"bpm1 = {bpm1:.3f}, bpm2 = {bpm2:.3f}, bpm3 = {bpm3:.3f}, bpm4 = {bpm4:.3f}") + return {"bpm1": bpm1, "bpm2": bpm2, "bpm3": bpm3, "bpm4": bpm4} + + +def compute_norm(): + """Compute normalised x and y positions""" + readings = read_currents() + total = readings["bpm1"] + readings["bpm2"] + readings["bpm3"] + readings["bpm4"] + # print(f"Sum is {total:.2f}") + xn = ( + (readings["bpm1"] + readings["bpm2"]) - (readings["bpm3"] + readings["bpm4"]) + ) / total + yn = ( + (readings["bpm1"] + readings["bpm3"]) - (readings["bpm2"] + readings["bpm4"]) + ) / total + # return xn, yn, readings["bpm1"], readings["bpm2"], readings["bpm3"], readings["bpm4"] + return xn, yn + + +# def compute_pos(): +# """Compute the beam x and y positions""" +# cal = { +# "bcu_bpm": { +# "x_slope": 7.778, +# "x_off": -1.019, +# "y_slope": -8.625, +# "y_off": -1.935, +# } +# } +# xn, yn, bpm1, bpm2, bpm3, bpm4 = compute_norm() +# # print(f"Normalised positions are {xn}, {yn}") +# x_pos = (xn - cal["bcu_bpm"]["x_off"]) / cal["bcu_bpm"]["x_slope"] +# y_pos = (yn - cal["bcu_bpm"]["y_off"]) / cal["bcu_bpm"]["y_slope"] +# return x_pos, y_pos + + +def run_calibration(): + """Scan bpm in x and y and record normalised x and y positions""" + # centred_x = 0.749 + # centred_y = -0.660 + now = datetime.now() + fnow = now.strftime("%d%m%H%M") + centred_x = 0.46 + centred_y = -1.51 + print(f"moving bpm to {centred_x}, {centred_y}") + umv(dev.bcu_bpm_y, centred_y) + umv(dev.bcu_bpm_x, centred_x) + + # # Calibrate in X + umv(dev.ss_sl_xsize,0.02) + umv(dev.ss_sl_xsize, 3.0) + filename = f"luts/bpm_calib/{fnow}_bcu_bpm_x.csv" + xn_data = [] + x_positions = np.linspace(centred_x - 0.6, centred_x + 0.6, 101) + with open(filename, "w", encoding="utf-8") as f: + f.write(f"Xpos,Xnorm,BPM1,BPM2,BPM3,BPM4\n") + for x in x_positions: + umv(dev.bcu_bpm_x, x) + print(f"Moving BPM to {x} mm") + time.sleep(0.2) + xn, yn, bpm1, bpm2, bpm3, bpm4 = compute_norm() + xn_data.append(xn) + with open(filename, "a", encoding="utf-8") as f: + f.write(f"{x},{xn},{bpm1},{bpm2},{bpm3},{bpm4}\n") + + # Calibrate in Y + umv(dev.bcu_bpm_x, centred_x) + umv(dev.ss_sl_xsize, 3.0) + umv(dev.ss_sl_ysize, 0.03) + filename = f"luts/bpm_calib/{fnow}_bcu_bpm_y.csv" + y_positions = np.linspace(centred_y - 0.1, centred_y + 0.1, 251) + yn_data = [] + with open(filename, "w", encoding="utf-8") as f: + f.write(f"Ypos,Ynorm,BPM1,BPM2,BPM3,BPM4\n") + for y in y_positions: + umv(dev.bcu_bpm_y, y) + print(f"Moving BPM to {y} mm") + time.sleep(0.2) + xn, yn, bpm1, bpm2, bpm3, bpm4 = compute_norm() + yn_data.append(yn) + with open(filename, "a", encoding="utf-8") as f: + f.write(f"{y},{yn},{bpm1},{bpm2},{bpm3},{bpm4}\n") + + umv(dev.bcu_bpm_x, centred_x) + umv(dev.bcu_bpm_y, centred_y) + umv(dev.ss_sl_ysize, 3.0) + + +# Read data from BPM calibration files +# def fit_bpm_data(x_y): +# """ +# Read data from bpm calibration files. +# """ +# filedir = "luts/bpm_calib/" +# rundate= "02072130_" +# name = f"bcu_bpm_{x_y}.csv" +# filename = filedir + rundate + name +# data = np.loadtxt(filename, delimiter=",", skiprows=1) +# xdata = data[:, 0] +# ydata = data[:, 1] +# return xdata, ydata + + + +def fit_bpm_data(x_y, rundate="02072130_", bpm_name="bcu_bpm"): + CALIB_DIR = "luts/bpm_calib/" + filename = os.path.join(CALIB_DIR, f"{rundate}{bpm_name}_{x_y}.csv") + data = np.loadtxt(filename, delimiter=",", skiprows=1) + + xdata = data[:, 0] # scan / motor position + ydata = data[:, 1] # normalised BPM signal + + return xdata, ydata + +def linear_calibration( + x_y, + bpm_motor_position, + crosshair_bpm_signal, + rundate = "05071923_", + bpm_name = "bcu_bpm", + sanity_limit = 0.2, + plot = True +): + calib_dir = "luts/bpm_calib" + xdata, ydata = fit_bpm_data(x_y, rundate = rundate, bpm_name = bpm_name) + # Remove non-linear region + if x_y == 'x': + mask_limit = 0.65 + else: + mask_limit = 0.9 + mask = np.abs(ydata) < mask_limit + xdata = xdata[mask] + ydata = ydata[mask] + + m, c = np.polyfit(xdata, ydata, 1) + + # --- Plot --- + plt.figure(figsize=(7, 5)) + plt.scatter(xdata, ydata, color="red", label=f"BPM {x_y} data") + + x_fit = np.linspace(min(xdata), max(xdata), 100) + plt.plot(x_fit, m * x_fit + c, "r--", label=f"Fit: Linear") + + plt.xlabel("HFM Lat Position") + plt.ylabel("SamCam X") + plt.title("Zoom Calibration") + plt.legend() + plt.grid(True) + plt.tight_layout() + plt.show() + +def make_inverse_spline_calibration( + x_y, + bpm_motor_position, + crosshair_bpm_signal, + rundate="05071923_", + bpm_name="bcu_bpm", + sanity_limit=0.2, + plot=True, +): + """ + Create and save inverse BPM calibration. + + Parameters + ---------- + x_y : str + "x" or "y" + bpm_motor_position : float + Current physical BPM motor position during calibration. + crosshair_bpm_signal : float + Normalised BPM reading when the beam is on the sample-camera crosshair. + mask_limit : float + Ignore saturated BPM readings outside +/- mask_limit. + sanity_limit : float + Warn later if BPM motor has moved by more than this. + """ + CALIB_DIR = "luts/bpm_calib/" + xdata, ydata = fit_bpm_data(x_y, rundate=rundate, bpm_name=bpm_name) + + # Remove saturated BPM response + if x_y == 'x': + mask_limit = 0.98 + else: + mask_limit = 0.91 + mask = np.abs(ydata) < mask_limit + xdata = xdata[mask] + ydata = ydata[mask] + + # For inverse calibration: BPM signal -> beam position + order = np.argsort(ydata) + bpm_signal = ydata[order] + local_position = xdata[order] + + # Remove duplicate BPM signal values + bpm_signal, unique_idx = np.unique(bpm_signal, return_index=True) + local_position = local_position[unique_idx] + + spline = PchipInterpolator(bpm_signal, local_position) + + # Local beam position when beam is visually on camera crosshair + crosshair_local_position = float(spline(crosshair_bpm_signal)) + + # Absolute beamline coordinate of camera crosshair + crosshair_absolute_position = bpm_motor_position + crosshair_local_position + + save_file = os.path.join(CALIB_DIR, f"{bpm_name}_{x_y}_inverse_spline.npz") + + np.savez( + save_file, + bpm_signal=bpm_signal, + local_position=local_position, + bpm_motor_position=bpm_motor_position, + crosshair_bpm_signal=crosshair_bpm_signal, + crosshair_local_position=crosshair_local_position, + crosshair_absolute_position=crosshair_absolute_position, + mask_limit=mask_limit, + sanity_limit=sanity_limit, + ) + + print(f"Saved {x_y} BPM calibration to:") + print(save_file) + print() + print(f"Calibration BPM motor position: {bpm_motor_position:.6f}") + print(f"Crosshair BPM signal: {crosshair_bpm_signal:.6f}") + print(f"Crosshair local position: {crosshair_local_position:.6f}") + print(f"Crosshair absolute position: {crosshair_absolute_position:.6f}") + + if plot: + signal_fit = np.linspace(np.min(bpm_signal), np.max(bpm_signal), 1000) + pos_fit = spline(signal_fit) + + plt.figure() + plt.scatter(ydata, xdata, label="calibration data") + plt.plot(signal_fit, pos_fit, label="inverse PCHIP spline", color='red') + plt.axvline(crosshair_bpm_signal, linestyle="--", label="camera crosshair") + plt.xlabel(f"{bpm_name}_{x_y} normalised signal") + plt.ylabel(f"{x_y} local beam position") + plt.title(f"{bpm_name}_{x_y} inverse calibration") + plt.grid(True) + plt.legend() + plt.show() + + return save_file + +class BPMCalibration: + def __init__(self, filename): + data = np.load(filename) + + self.bpm_signal = data["bpm_signal"] + self.local_position = data["local_position"] + + self.bpm_motor_position_calib = float(data["bpm_motor_position"]) + self.crosshair_absolute_position = float(data["crosshair_absolute_position"]) + self.sanity_limit = float(data["sanity_limit"]) + + self.spline = PchipInterpolator( + self.bpm_signal, + self.local_position, + ) + + def beam_position(self, bpm_signal, bpm_motor_position, warn=True): + """ + Return beam position relative to the sample-camera crosshair. + """ + + motor_shift = bpm_motor_position - self.bpm_motor_position_calib + + if warn and abs(motor_shift) > self.sanity_limit: + print( + "Warning: BPM motor has moved since calibration: " + f"delta = {motor_shift:.3f} mm" + ) + + local_beam_position = float(self.spline(bpm_signal)) + absolute_beam_position = bpm_motor_position + local_beam_position + + relative_to_crosshair = ( + absolute_beam_position - self.crosshair_absolute_position + ) + + return relative_to_crosshair + +def get_beampos(): + x_cal = BPMCalibration("luts/bpm_calib/bcu_bpm_x_inverse_spline.npz") + y_cal = BPMCalibration("luts/bpm_calib/bcu_bpm_y_inverse_spline.npz") + + bpm_x_signal, bpm_y_signal = compute_norm() + + beam_x = x_cal.beam_position( + bpm_signal=bpm_x_signal, + bpm_motor_position=dev.bcu_bpm_x.position, + ) + + beam_y = y_cal.beam_position( + bpm_signal=bpm_y_signal, + bpm_motor_position=dev.bcu_bpm_y.position, + ) + + beam_x_mic = 1000 * beam_x + beam_y_mic = 1000 * beam_y + + print(f"Beam relative to camera crosshair:") + print(f"X = {beam_x_mic:.4f} um") + print(f"Y = {beam_y_mic:.4f} um") + + return beam_x_mic, beam_y_mic + +#!/usr/bin/env python +"""Calculate photon flux from a Si diode current.""" + +import math +from dataclasses import dataclass + +import numpy as np + + +@dataclass +class PXIIDiodeConfig: + """Diode/beamline-specific constants.""" + + si_thickness_um: float = 12.0 + al_thickness_um: float = 20.0 + diode_offset_mm: float = 15.0 + + si_density: float = 2.33 # g/cm^3 + al_density: float = 2.699 # g/cm^3 + air_density: float = 1.205e-3 # g/cm^3 + + eps_si: float = 3.62 # eV per electron-hole pair + + +def flux( + current_a: float, + energy_kev: float | None = None, + det_z: float | None = None, + config = PXIIDiodeConfig, +) -> float: + """ + Calculate photon flux from Si diode current. + + Parameters + ---------- + current_a: + Diode current in A. + energy_kev: + Beam energy in keV. Will use the current energy if + not specified. + det_z: + Detector distance (dev.det_z) (mm). Will use the current + detector distance if not specified. + config: + DiodeConfig containing Si/Al thicknesses and material constants. + + Returns + ------- + float + Flux in photons/s. + """ + if energy_kev is None: + energy_kev = get_current_energy() / 1000 + + if det_z is None: + det_z = dev.det_z.position + + air_path_mm = det_z + config.diode_offset_mm + + si_thickness_cm = config.si_thickness_um / 10_000.0 + al_thickness_cm = config.al_thickness_um / 10_000.0 + + log_energy = math.log10(energy_kev) + + # Photoelectric mass attenuation coefficient fits + si_poly = np.poly1d([0.0789, -0.477, -2.238, 4.158]) + al_poly = np.poly1d([0.0638, -0.413, -2.349, 4.106]) + air_poly = np.poly1d([0.928, -2.348, -1.026, 3.153]) + + a_si = 10 ** si_poly(log_energy) + a_al = 10 ** al_poly(log_energy) + a_air = 10 ** air_poly(log_energy) + + # Fraction of beam absorbed in active Si layer + si_absorbed_fraction = -np.expm1( + -a_si * config.si_density * si_thickness_cm + ) + + if si_absorbed_fraction <= 0: + raise ValueError("Calculated Si absorption fraction is zero or negative.") + + # Flux before Al/air correction + flux = ( + 1000.0 + * current_a + * config.eps_si + / 1.602 + / energy_kev + / si_absorbed_fraction + * 1.0e13 + ) + + # Transmission through Al and air + al_transmission = np.exp( + -a_al * config.al_density * al_thickness_cm + ) + + air_transmission = np.exp( + -a_air * config.air_density * air_path_mm / 10.0 + ) + + flux /= al_transmission + flux /= air_transmission + + print(f"The flux is {flux: .3g} ph/s") + + return float(flux) + +def calibrate_bpm_flux(): + # d['det_z'].move('mse') + # d['det_y'].move('xi') + # d['det_z'].move(200) + + flux = flux(dev.xidiode.read()['xidiode']['value']) + + +def zero_xidiode(): + vals = [] + for i in range(1,101): + reading = dev.xidiode.read()['xidiode']['value'] + vals.append(reading) + + zero = np.mean(vals) + print(zero) + + + diff --git a/pxii_bec/macros/chmirrh.py b/pxii_bec/macros/chmirrh.py index 7131fb5..94b58ce 100644 --- a/pxii_bec/macros/chmirrh.py +++ b/pxii_bec/macros/chmirrh.py @@ -2,60 +2,9 @@ import numpy as np import math, time import matplotlib.pyplot as plt import scipy -######################################### -### just retrieve the saved data from csv -######################################## -def read_data(filename: str): - """ - Get data stored in a CSV file - - Args: - filename (str): the csv file, eg, of a Scan - e.g., dat = read_data("/home/e18747/SLS2/Data/gaps/gaps10.txt") - """ - - # dirname = '/home/gac-x10sa/Data/' - # read output to simple data file for later analysis: - - with open(filename, "r") as f: - combined_data = np.loadtxt(f, delimiter=",") # no header and fmt for load - - rows, cols = combined_data.shape - - print("No of Rows =", rows) - print("No of Colums =", cols) - ind1 = 0 - ind2 = 1 - if cols > 2: - print( - "only first 2 colums (data[:, 0] and data[:, 1]) are plotted, please consider the other columns as well!" - ) - index1 = 0 - index2 = 1 - index1, index2 = input( - "please enter the columns to be plotted vs first one [eg: 1,2] : " - ).split(",") - ind1 = int(index1) - ind2 = int(index2) - - if ind2 > cols - 1: - print(" no valid index") - - data_x = combined_data[:, ind1] - data_y = combined_data[:, ind2] - - plt.ion() - plt.figure() - plt.plot(data_x, data_y, ".") - - plt.title(f"Scan from {filename}") - plt.xlabel(f"data column {ind1}") - plt.ylabel(f"data column {ind2}") - - plt.show() - - return combined_data - +######################################################## +### scan FE slits and check BPMs before and after mirror +######################################################## def gaussfit(x,y,p): # define a gaussian fitting function where @@ -95,22 +44,42 @@ def gaussfit(x,y,p): return bestfit, p1 -def scan_fe_sl(): - fe_v_size0 = dev.fe_sl_ysize.user_readback.get() - umv(dev.fe_sl_xsize, 0.1) - s = scans.line_scan(dev.fe_sl_ycen,-1,1, exp_time=02., steps=21, relative=True) - time.sleep(0.1) - umv(dev.fe_sl_xsize, fe_v_size0) +def scan_fe_sl(dir = "y"): + if dir in ["y","v"]: + sdir ="vertical" + fe_size0 = dev.fe_sl_ysize.user_readback.get() + print('Closing vertical FE slits to 0.1') + umv(dev.fe_sl_ysize, 0.1) + s = scans.line_scan(dev.fe_sl_ycen,-1,1, exp_time=02., steps=21, relative=True) + time.sleep(0.1) + umv(dev.fe_sl_ysize, fe_size0) + print(f'Opening {sdir} FE slits to {fe_size0}') + if dir in ["x","h"]: + sdir ="horizontal" + fe_size0 = dev.fe_sl_xsize.user_readback.get() + print('Closing horizontal FE slits to 0.1') + umv(dev.fe_sl_xsize, 0.1) + s = scans.line_scan(dev.fe_sl_xcen,-1,1, exp_time=02., steps=21, relative=True) + time.sleep(0.1) + umv(dev.fe_sl_xsize, fe_size0) + print(f'Opening {sdir} FE slits to {fe_size0}') + else: + print('no valid direction, doing nothing') -def mirrh(): +def mirrh(dir='y'): - #dat_ss = read_data("/home/anuschka/SS_pitch2p94.csv") - #dat_bcu = read_data("/home/anuschka/BCU_pitch2p94.csv") + #dat_ss = read_data_csv("/home/anuschka/SS_pitch2p94.csv") + #dat_bcu = read_data_csv("/home/anuschka/BCU_pitch2p94.csv") - scan_fe_sl() + scan_fe_sl(dir=dir) ind = -1 - dat_ss = save_data(ind, 'fe_sl_ycen', 'ss_bpmsum', isave = 0) - dat_bcu = save_data(ind, 'fe_sl_ycen', 'bcu_bpmsum', isave = 0) + if dir in ["x","h"]: + slitmot = 'fe_sl_xcen' + if dir in ["y","v"]: + slitmot = 'fe_sl_ycen' + + dat_ss = save_data(ind, slitmot, 'ss_bpmsum', isave = 0) + dat_bcu = save_data(ind, slitmot, 'bcu_bpmsum', isave = 0) data_xs = dat_ss[0] # csv would be: dat_ss[:, 0] @@ -124,7 +93,7 @@ def mirrh(): #plt.plot(data_xs, data_ys, "*") #plt.plot(data_xb, data_yb, "+") - data_ys_norm = data_ys/max(data_ys) + data_ys_norm = data_ys/max(data_ys) # looks better than data_ys/sum(data_ys) data_yb_norm = data_yb/max(data_yb) plt.figure() @@ -138,7 +107,7 @@ def mirrh(): xmi = data_xs[xm] #print('xm, xmi', xm, xmi) - pf1 = [1, xmi , np.std(data_ys_norm),0] + pf1 = [1, xmi , np.std(data_ys_norm), np.mean(y[0:5])] # bg = 0 fit_s, ps = gaussfit(data_xs,data_ys_norm, pf1) y= data_yb_norm @@ -146,7 +115,7 @@ def mirrh(): xmi = data_xb[xm] #print('xm, xmi', xm, xmi) - pf2 = [1, xmi, np.std(data_yb_norm),-11] + pf2 = [1, xmi, np.std(data_yb_norm), np.mean(y[0:5])] # bg = -11 fit_b, pb = gaussfit(data_xb,data_yb_norm, pf2) diff --git a/pxii_bec/macros/chmirrh.py~ b/pxii_bec/macros/chmirrh.py~ deleted file mode 100644 index 664ab60..0000000 --- a/pxii_bec/macros/chmirrh.py~ +++ /dev/null @@ -1,142 +0,0 @@ -import numpy as np -import math -import matplotlib.pyplot as plt -import scipy -######################################### -### just retrieve the saved data from csv -######################################## -def read_data(filename: str): - """ - Get data stored in a CSV file - - Args: - filename (str): the csv file, eg, of a Scan - e.g., dat = read_data("/home/e18747/SLS2/Data/gaps/gaps10.txt") - """ - - # dirname = '/home/gac-x10sa/Data/' - # read output to simple data file for later analysis: - - with open(filename, "r") as f: - combined_data = np.loadtxt(f, delimiter=",") # no header and fmt for load - - rows, cols = combined_data.shape - - print("No of Rows =", rows) - print("No of Colums =", cols) - ind1 = 0 - ind2 = 1 - if cols > 2: - print( - "only first 2 colums (data[:, 0] and data[:, 1]) are plotted, please consider the other columns as well!" - ) - index1 = 0 - index2 = 1 - index1, index2 = input( - "please enter the columns to be plotted vs first one [eg: 1,2] : " - ).split(",") - ind1 = int(index1) - ind2 = int(index2) - - if ind2 > cols - 1: - print(" no valid index") - - data_x = combined_data[:, ind1] - data_y = combined_data[:, ind2] - - plt.ion() - plt.figure() - plt.plot(data_x, data_y, ".") - - plt.title(f"Scan from {filename}") - plt.xlabel(f"data column {ind1}") - plt.ylabel(f"data column {ind2}") - - plt.show() - - return combined_data - - -def gaussfit(x,y,p): -# define a gaussian fitting function where -# p[0] = amplitude -# p[1] = mean -# p[2] = sigma -# p[3] = const offset - - fitfct = lambda p, x0: p[0]*np.exp(-(x0-p[1])**2/(2.0*p[2]**2))+p[3] - #fitfct = lambda p, x0: p[0]*np.exp(-(x0-p[1])**2/(2.0*p[2]**2)) - errfct = lambda p, x0,y0: fitfct(p,x0)-y0 - - # guess fit parameters - ind0 = np.where(y==max(y))[0] - p0=scipy.c_[max(y), x[ind0], np.std(y), np.mean(y[0:5])] - #p0=scipy.c_[max(y), np.where(y==max(y))[0], np.std(y)] - # array generation [[]], and taking only one dimens - # fit a gaussian to the correlation function - - print('p0 = ' , p0) - p1, success = scipy.optimize.leastsq(errfct, p0.copy()[0], - args=(x,y)) - - plt.figure() - bestfit=fitfct(p1,x) - #print('************************', x,y) - plt.plot(x,y,'r*') - plt.plot(x,bestfit,'r-') - - # different fit fct - #popt, pcov = curve_fit(fitfct, x, y) - #newfit=fitfct(popt,x) - #plt.plot(x,newfit,'g+') - - - plt.show() - #time.sleep(1) - #plt.close() - return bestfit, p1 - -def mirh(): - - dat_ss = read_data("/home/anuschka/SS_pitch2p94.csv") - dat_bcu = read_data("/home/anuschka/BCU_pitch2p94.csv") - - data_xs = dat_ss[:, 0] - data_ys = dat_ss[:, 1] - - data_xb = dat_bcu[:, 0] - data_yb = dat_bcu[:, 1] - - plt.figure() - - plt.plot(data_xs, data_ys, "*") - plt.plot(data_xb, data_yb, "+") - - data_ys_norm = data_ys/max(data_ys) - data_yb_norm = data_yb/max(data_yb) - - plt.figure() - - plt.plot(data_xs, data_ys_norm, "*") - plt.plot(data_xb, data_yb_norm, "+") - - - pf1 = [1, 0.8 , np.std(data_ys_norm),0] - - y= data_ys_norm - xm = np.where(y==max(y))[0] - xmi = data_xs[xm] - print('xm, xmi', xm, xmi) - - fit_s, ps = gaussfit(data_xs,data_ys_norm, pf1) - - pf2 = [1, 0.8, np.std(data_yb_norm),-11] - fit_b, pb = gaussfit(data_xb,data_yb_norm, pf2) - - - plt.figure() - - plt.plot(data_xs, fit_s-ps[3], "*") - plt.plot(data_xb, fit_b-pb[3], "+") - - diff --git a/pxii_bec/macros/katscripts.py b/pxii_bec/macros/katscripts.py index 9dff871..9b76ed9 100755 --- a/pxii_bec/macros/katscripts.py +++ b/pxii_bec/macros/katscripts.py @@ -1,7 +1,7 @@ """Some simple scripts for commissioning""" import time, os -from datetime import datetime +from datetime import datetime, timedelta from dataclasses import dataclass import numpy as np import matplotlib.pyplot as plt @@ -10,15 +10,6 @@ import pandas as pd from scipy.optimize import linear_sum_assignment -def goto1a(): - """Set beamline to 1A position""" - bragg_angle = 160.117 - perp_dist = 0.0389 - gap = 5.319 - umv(dev.dcm_bragg, bragg_angle) - umv(dev.dcm_perp, perp_dist) - umv(dev.id_gap, gap) - def bragg_scan(): """Energy scans from 6 to 18 keV at various gap positions""" @@ -59,26 +50,10 @@ def energy_checks(start_energy=8000, end_energy=20000): """Check gap, pitch and intensities at different energies""" f = open("luts/test.csv", "a", encoding="utf-8") - gaps = { - 8000: 8.04, - 9000: 9.55, - 10000: 7.45, - 11000: 8.46, - 12000: 7.09, - 13000: 7.77, - 14000: 8.61, - 15000: 9.57, - 16000: 8.09, - 17000: 7.18, - 18000: 7.67, - 19000: 8.24, - 20000: 7.52, - } for energy in range(start_energy, end_energy, 1000): f = open("luts/test.csv", "a", encoding="utf-8") print(f"Moving to {energy} eV") - umv(dev.id_gap, gaps[energy]) - move_and_set_dcm(energy) + bl_energy if energy < 16000: close_fe_slits(True) go_to_peak( @@ -277,86 +252,75 @@ def write_beamsize(): f.write(f"{lens_config},{sx:.4g},{sy:.4g},{i1_reading:.4g}\n") -def beamsize(size): - """WIP to dial up different beam sizes""" - # Set mirror trans and pitch to default settings for 12.4 keV - # vlaues from a 2025 - # umv(dev.vfm_vert,2.136) - # umv(dev.vfm_pitch, 2.695) - # umv(dev.hfm_lat, 1.64) - # umv(dev.hfm_pitch, 2.9844) - umv(dev.vfm_vert, 2.5301) - umv(dev.vfm_pitch, 2.60) - umv(dev.hfm_lat, 1.6586) - umv(dev.hfm_pitch, 2.9964) - print(f"changing beam size to {size}") - - # values = {"xs": {"vbu": -0.9095, "vbd": -1.246, "hbu": -2.9375, "hbd": -5.698}, - # "s": {"vbu": -0.8365, "vbd": -1.22, "hbu": -2.804, "hbd": -5.473}, - # "m": {"vbu": -0.7865, "vbd": -1.17, "hbu": -2.604, "hbd": -5.273}, - # "l": {"vbu": -0.7459, "vbd": -1.13, "hbu": -2.504, "hbd": -5.173}} - # values = {"xs": {"vbu": -0.9095, "vbd": -1.246, "hbu": -2.8075, "hbd": -5.668}, - # "s": {"vbu": -0.8606, "vbd": -1.195, "hbu": -2.6975, "hbd": -5.5585}, - # "m": {"vbu": -0.8410, "vbd": -1.465, "hbu": -2.5575, "hbd": -5.418}, - # "l": {"vbu": -0.762, "vbd": -1.094, "hbu": -2.4582, "hbd": -5.3187}} - values = { - "xs": {"vbu": -0.741, "vbd": -1.206, "hbu": -2.869, "hbd": -5.819}, - "s": {"vbu": -0.7101, "vbd": -1.176, "hbu": -2.7133, "hbd": -5.5535}, - "m": {"vbu": -0.6601, "vbd": -1.126, "hbu": -2.5133, "hbd": -5.3535}, - "l": {"vbu": -0.6196, "vbd": -1.086, "hbu": -2.4133, "hbd": -5.2535}, - } - umv( - dev.vfm_bu, - values[size]["vbu"], - dev.vfm_bd, - values[size]["vbd"], - dev.hfm_bu, - values[size]["hbu"], - dev.hfm_bd, - values[size]["hbd"], - ) - print("Setting camera exposure time") - auto_exposure() - xsig = dev.samcam_xsig.read()["samcam_xsig"]["value"] - ysig = dev.samcam_ysig.read()["samcam_ysig"]["value"] - print(f"Beam has Xsigma = {xsig:.3g}, Ysigma = {ysig:.3g}") - - # if size == 'm': - # move_to_x() - # print(f"Beam has Xsigma = {xsig:.3g}, Ysigma = {ysig:.3g}") - # return - # if size == 'l': - # move_to_x() - # move_to_y() - # umv(dev.hfm_pitch, 2.9684) - # print(f"Beam has Xsigma = {xsig:.3g}, Ysigma = {ysig:.3g}") - # return - # else: - # move_to_x() - # move_to_y() - # print(f"Beam has Xsigma = {xsig:.3g}, Ysigma = {ysig:.3g}") - def scan_Ge(): scanbefore = 30 # eV scanafter = 30 # eV - stepsize = 0.5 # eV - edge_Ge = 11103.1 # eV - - scanstart = edge_Ge + scanafter - scanend = edge_Ge - scanbefore - bragg_start = convert_from_energy(scanstart)["bragg_angle_mrad"] - bragg_end = convert_from_energy(scanend)["bragg_angle_mrad"] - stepnumber = abs(int((scanend - scanstart) / stepsize)) - - print(f"Changing energy to {scanstart}") + stepsize = 0.2 # eV + # Edge sgould be at 11103.1 + actual_edge_Ge = 11103.1 # eV + actual_bragg = convert_from_energy(actual_edge_Ge)["bragg_angle_mrad"] + current_edge = 11095 + current_bragg = convert_from_energy(current_edge)["bragg_angle_mrad"] + print(f"Ge edge should be at a bragg angle of {actual_bragg:.5g} mrad\n") + print(f"Current estimate of edge is {current_bragg:.5g} mrad\n") + xdata = [] + ydata = [] + filedir, fname = fnow() + filename = f"{filedir}{fname}_ge_edge.csv" + print(filename) + with open(filename, 'w') as f: + f.write(f"Energy,Bragg,bcu_bpmsum\n") + + # scanstart = edge_Ge + scanafter + # scanend = edge_Ge - scanbefore + # bragg_start = convert_from_energy(scanstart)["bragg_angle_mrad"] + # bragg_end = convert_from_energy(scanend)["bragg_angle_mrad"] + # stepnumber = abs(int((scanend - scanstart) / stepsize)) + # print(f"Changing energy to {scanstart}") # bl_energy(scanstart) - # scan_gap() - umv(dev.bsc_f4_x, 6) # Put Ge filter in place - print(f"scanning from {bragg_start} to {bragg_end} with {stepnumber} steps") - s = scans.line_scan(dev.dcm_bragg, bragg_start, bragg_end, steps=stepnumber, relative=False) - print(s) - umv(dev.bsc_f4_x, 2) + # # scan_gap() + # umv(dev.ss_f4_x, 6) # Put Ge filter in place + # print(f"scanning from {bragg_start} to {bragg_end} with {stepnumber} steps") + # s = scans.line_scan(dev.dcm_bragg, bragg_start, bragg_end, steps=stepnumber, relative=False) + # print(s) + # umv(dev.ss_f4_x, 2) + + plot_live_data_bec(dev.dcm_bragg,dev.bcu_bpmsum) + scanpoints = np.linspace(current_bragg - 0.5, current_bragg + 0.5, 300) + start_energy = convert_from_bragg(current_bragg+0.5)["energy_ev"] + bl_energy(start_energy) + umv(dev.ss_f4_x, 6) # Put Ge filter in place + + for bragg in scanpoints: + scans.umv(dev.dcm_bragg, bragg, relative=False) + energy = convert_from_bragg(bragg)["energy_ev"] + inten = average_inten() + xdata.append(energy) + ydata.append(inten) + with open(filename, 'a') as f: + f.write(f"{energy:.2f},{bragg:.2f},{inten:.2f}\n") + data = { + "x_data": np.array(xdata), + "y_data": np.array(ydata), + "motor_name": "dcm_bragg", + "signal_name": "bcu_bpmsum", + "motor_device": dev.dcm_bragg, + "scan_number": "Current", + } + + # Define and fit model to scan data + fit_params = create_fit_parameters(deriv = True, + negative = False, + model = FitDefaults.MODEL, + baseline = FitDefaults.BASELINE) + fit_result = fit(data, fit_params) + + # Plot the fitted data if plot = True + + plot_fitted_data_bec(data, fit_result) + + def cal_samcam_fixed_x(): @@ -434,79 +398,79 @@ def cal_samcam_fixed_x(): plt.show() -def cal_samcam_fixed_y(): - vert = dev.vfm_vert.read()["vfm_vert"]["value"] - pitch = dev.vfm_pitch.read()["vfm_pitch"]["value"] - scanpoints = np.linspace(vert - 0.1, vert + 0.1, 7) - zoom_high = 800 - zoom_low = 200 - highs, lows = [], [] - high_vert, low_vert = [], [] +# def cal_samcam_fixed_y(): +# vert = dev.vfm_vert.read()["vfm_vert"]["value"] +# pitch = dev.vfm_pitch.read()["vfm_pitch"]["value"] +# scanpoints = np.linspace(vert - 0.1, vert + 0.1, 7) +# zoom_high = 800 +# zoom_low = 200 +# highs, lows = [], [] +# high_vert, low_vert = [], [] - # high zoom - umv(dev.scam_zoom, zoom_high) - auto_exposure("samcam") - for i in scanpoints: - umv(dev.vfm_vert, i) - umv(dev.vfm_pitch, pitch) - time.sleep(0.2) - high_y = dev.samcam_y.read()["samcam_y"]["value"] - high_x = dev.vfm_vert.read()["vfm_vert"]["value"] - print(f"Ypos at zoom {zoom_high} is {high_y}") - highs.append(high_y) - high_vert.append(high_x) +# # high zoom +# umv(dev.scam_zoom, zoom_high) +# auto_exposure("samcam") +# for i in scanpoints: +# umv(dev.vfm_vert, i) +# umv(dev.vfm_pitch, pitch) +# time.sleep(0.2) +# high_y = dev.samcam_y.read()["samcam_y"]["value"] +# high_x = dev.vfm_vert.read()["vfm_vert"]["value"] +# print(f"Ypos at zoom {zoom_high} is {high_y}") +# highs.append(high_y) +# high_vert.append(high_x) - umv(dev.scam_zoom, zoom_low) - auto_exposure("samcam") - for i in scanpoints: - umv(dev.vfm_vert, i) - umv(dev.vfm_pitch, pitch) - time.sleep(0.2) - low_y = dev.samcam_y.read()["samcam_y"]["value"] - low_x = dev.vfm_vert.read()["vfm_vert"]["value"] - print(f"Ypos at zoom {zoom_low} is {low_y}") - lows.append(low_y) - low_vert.append(low_x) +# umv(dev.scam_zoom, zoom_low) +# auto_exposure("samcam") +# for i in scanpoints: +# umv(dev.vfm_vert, i) +# umv(dev.vfm_pitch, pitch) +# time.sleep(0.2) +# low_y = dev.samcam_y.read()["samcam_y"]["value"] +# low_x = dev.vfm_vert.read()["vfm_vert"]["value"] +# print(f"Ypos at zoom {zoom_low} is {low_y}") +# lows.append(low_y) +# low_vert.append(low_x) - umv(dev.vfm_vert, vert) - umv(dev.vfm_pitch, pitch) +# umv(dev.vfm_vert, vert) +# umv(dev.vfm_pitch, pitch) - # Convert to numpy arrays - x_high = np.array(high_vert) - x_low = np.array(low_vert) - y_high = np.array(highs) - y_low = np.array(lows) +# # Convert to numpy arrays +# x_high = np.array(high_vert) +# x_low = np.array(low_vert) +# y_high = np.array(highs) +# y_low = np.array(lows) - # Fit linear models: y = m*x + b - m_high, b_high = np.polyfit(x_high, y_high, 1) - m_low, b_low = np.polyfit(x_low, y_low, 1) +# # Fit linear models: y = m*x + b +# m_high, b_high = np.polyfit(x_high, y_high, 1) +# m_low, b_low = np.polyfit(x_low, y_low, 1) - # Intersection point - x_intersect = (b_low - b_high) / (m_high - m_low) - y_intersect = m_high * x_intersect + b_high +# # Intersection point +# x_intersect = (b_low - b_high) / (m_high - m_low) +# y_intersect = m_high * x_intersect + b_high - print(f"\nIntersection at:") - print(f" VFM_vert = {x_intersect:.5f}") - print(f" SamCam_y = {y_intersect:.2f}") +# print(f"\nIntersection at:") +# print(f" VFM_vert = {x_intersect:.5f}") +# print(f" SamCam_y = {y_intersect:.2f}") - # --- Plot --- - plt.figure(figsize=(7, 5)) - plt.scatter(x_high, y_high, color="red", label=f"Zoom = {zoom_high} data") - plt.scatter(x_low, y_low, color="blue", label=f"Zoom = {zoom_low} data") +# # --- Plot --- +# plt.figure(figsize=(7, 5)) +# plt.scatter(x_high, y_high, color="red", label=f"Zoom = {zoom_high} data") +# plt.scatter(x_low, y_low, color="blue", label=f"Zoom = {zoom_low} data") - x_fit = np.linspace(min(x_high), max(x_high), 100) - plt.plot(x_fit, m_high * x_fit + b_high, "r--", label=f"Fit: Zoom {zoom_high}") - plt.plot(x_fit, m_low * x_fit + b_low, "b--", label=f"Fit: Zoom {zoom_low}") +# x_fit = np.linspace(min(x_high), max(x_high), 100) +# plt.plot(x_fit, m_high * x_fit + b_high, "r--", label=f"Fit: Zoom {zoom_high}") +# plt.plot(x_fit, m_low * x_fit + b_low, "b--", label=f"Fit: Zoom {zoom_low}") - plt.scatter(x_intersect, y_intersect, color="green", s=80, zorder=5, label="Intersection") +# plt.scatter(x_intersect, y_intersect, color="green", s=80, zorder=5, label="Intersection") - plt.xlabel("VFM Vert Position") - plt.ylabel("SamCam Y") - plt.title("Zoom Calibration") - plt.legend() - plt.grid(True) - plt.tight_layout() - plt.show() +# plt.xlabel("VFM Vert Position") +# plt.ylabel("SamCam Y") +# plt.title("Zoom Calibration") +# plt.legend() +# plt.grid(True) +# plt.tight_layout() +# plt.show() def correlate_froll(): @@ -620,37 +584,37 @@ def correlate_hfm_lat(): plt.show() -def correlate_vfm_vert(): - y_correlation = [] - vert = dev.vfm_vert.read()["vfm_vert"]["value"] - scanpoints = np.linspace(vert - 0.06, vert + 0.06, 10) - for pos in scanpoints: - umv(dev.vfm_vert, pos) - xpos, ypos = compute_pos() - y_correlation.append(ypos) - umv(dev.vfm_vert, vert) +# def correlate_vfm_vert(): +# y_correlation = [] +# vert = dev.vfm_vert.read()["vfm_vert"]["value"] +# scanpoints = np.linspace(vert - 0.06, vert + 0.06, 10) +# for pos in scanpoints: +# umv(dev.vfm_vert, pos) +# xpos, ypos = compute_pos() +# y_correlation.append(ypos) +# umv(dev.vfm_vert, vert) - x = np.array(scanpoints) - y1 = np.array(y_correlation) +# x = np.array(scanpoints) +# y1 = np.array(y_correlation) - yslope, yint = np.polyfit(x, y1, 1) +# yslope, yint = np.polyfit(x, y1, 1) - print(f"Fit for xpos is: y = {yslope}.x + {yint}") - plt.figure(figsize=(7, 5)) - # plt.scatter(x, y1, label='xpos') - plt.scatter(x, y1, label="beam y position", color="rebeccapurple") +# print(f"Fit for xpos is: y = {yslope}.x + {yint}") +# plt.figure(figsize=(7, 5)) +# # plt.scatter(x, y1, label='xpos') +# plt.scatter(x, y1, label="beam y position", color="rebeccapurple") - x_fit = np.linspace(min(x), max(x), 100) - # plt.plot(x_fit, xslope*x_fit + xint, 'r--', label=f'y = {xslope}*x + {xint}') - plt.plot( - x_fit, yslope * x_fit + yint, label=f"y = {yslope:.5g}*x + ({yint:.5g})", color="lightcoral" - ) - plt.xlabel("VFM vertical (mm)") - plt.ylabel("beam Y(from BCU BPM)") - plt.legend() - plt.grid(True) - plt.tight_layout() - plt.show() +# x_fit = np.linspace(min(x), max(x), 100) +# # plt.plot(x_fit, xslope*x_fit + xint, 'r--', label=f'y = {xslope}*x + {xint}') +# plt.plot( +# x_fit, yslope * x_fit + yint, label=f"y = {yslope:.5g}*x + ({yint:.5g})", color="lightcoral" +# ) +# plt.xlabel("VFM vertical (mm)") +# plt.ylabel("beam Y(from BCU BPM)") +# plt.legend() +# plt.grid(True) +# plt.tight_layout() +# plt.show() def correlate_hfm_pitch(): @@ -703,21 +667,21 @@ def move_to_x(targetx=0.13): umv(dev.hfm_lat, mot_new) -def move_to_y(targety=-0.033): - # Calibration and drift compensation - # target from previous run = -0.283 - slope = -1.2779 - intercept = 2.4374 +# def move_to_y(targety=-0.033): +# # Calibration and drift compensation +# # target from previous run = -0.283 +# slope = -1.2779 +# intercept = 2.4374 - xpos, ypos = compute_pos() +# xpos, ypos = compute_pos() - beam_drift = ypos - targety # beam moved +0.1 mm (100 µm) - mot_current = dev.vfm_vert.read()["vfm_vert"]["value"] # current motor position (example) +# beam_drift = ypos - targety # beam moved +0.1 mm (100 µm) +# mot_current = dev.vfm_vert.read()["vfm_vert"]["value"] # current motor position (example) - # Compute correction - delta = -beam_drift / slope - mot_new = mot_current + delta - umv(dev.vfm_vert, mot_new) +# # Compute correction +# delta = -beam_drift / slope +# mot_new = mot_current + delta +# umv(dev.vfm_vert, mot_new) from epics import caget, caput @@ -792,34 +756,34 @@ def auto_exposure( return exposure -def get_new_beamsizes(mirror): - filename = f"luts/{mirror}_size.csv" - if mirror == "hfm": - bu = dev.hfm_bu - bd = dev.hfm_bd - step = 0.2 - else: - bu = dev.vfm_bu - bd = dev.vfm_bd - step = 0.05 - beamsize("xs") - move_targetx_with_hfm_lat() - move_targety_with_vfm_vert() - with open(filename, "w") as f: - for _ in range(4): - curr_bu = bu.user_readback.get() - curr_bd = bd.user_readback.get() - auto_exposure() - umv(bu, curr_bu + step) - umv(bd, curr_bd + step) - move_targetx_with_hfm_lat() - move_targety_with_vfm_vert() - xpos = dev.samcam_x.read()["samcam_x"]["value"] - ypos = dev.samcam_y.read()["samcam_y"]["value"] - xsig = dev.samcam_xsig.read()["samcam_xsig"]["value"] - ysig = dev.samcam_ysig.read()["samcam_ysig"]["value"] - f.write(f"{curr_bu}, {curr_bd}, {xpos}, {ypos}, {xsig}, {ysig}\n") - print(f"{curr_bu}, {curr_bd}, {xpos}, {ypos}, {xsig}, {ysig}") +# def get_new_beamsizes(mirror): +# filename = f"luts/{mirror}_size.csv" +# if mirror == "hfm": +# bu = dev.hfm_bu +# bd = dev.hfm_bd +# step = 0.2 +# else: +# bu = dev.vfm_bu +# bd = dev.vfm_bd +# step = 0.05 +# beamsize("xs") +# move_targetx_with_hfm_lat() +# move_targety_with_vfm_vert() +# with open(filename, "w") as f: +# for _ in range(4): +# curr_bu = bu.user_readback.get() +# curr_bd = bd.user_readback.get() +# auto_exposure() +# umv(bu, curr_bu + step) +# umv(bd, curr_bd + step) +# move_targetx_with_hfm_lat() +# move_targety_with_vfm_vert() +# xpos = dev.samcam_x.read()["samcam_x"]["value"] +# ypos = dev.samcam_y.read()["samcam_y"]["value"] +# xsig = dev.samcam_xsig.read()["samcam_xsig"]["value"] +# ysig = dev.samcam_ysig.read()["samcam_ysig"]["value"] +# f.write(f"{curr_bu}, {curr_bd}, {xpos}, {ypos}, {xsig}, {ysig}\n") +# print(f"{curr_bu}, {curr_bd}, {xpos}, {ypos}, {xsig}, {ysig}") def filters(pos="out"): @@ -832,6 +796,11 @@ def filters(pos="out"): if SE.scin.checkpos(): auto_exposure(cam="samcam", max_iter=20) +def fnow(): + now = datetime.now() + fnow = now.strftime("%Y%m%d-%H%M") + filedir = "luts/" + return filedir, fnow def energy_vs_height(start_energy=11000, end_energy=25000, step=1000): """Correlate beam height with energy from start_energy to end_energy in steps of step""" @@ -867,111 +836,6 @@ def energy_vs_height(start_energy=11000, end_energy=25000, step=1000): # umv(dev.id_gap, 20.0) -@dataclass -class SlitParameters: - small: float - large: float - scanwidth: float - steps: any - x_size: any - x_cen: any - y_size: any - y_cen: any - mon: any - - -# Generic scan function -def scan_slits(name="s1", x=True, y=True): - # Define parameters for all slits - s1_params = SlitParameters( - small=0.075, - large=2.5, - scanwidth=2.5, - steps=40, - x_size=dev.s1_xsize, - y_size=dev.s1_ysize, - x_cen=dev.s1_xcen, - y_cen=dev.s1_ycen, - mon=dev.lu_bpmsum, - ) - s2_params = SlitParameters( - small=0.075, - large=3.0, - scanwidth=2.5, - steps=50, - x_size=dev.s2_xsize, - y_size=dev.s2_ysize, - x_cen=dev.s2_xcen, - y_cen=dev.s2_ycen, - mon=dev.bcu_bpmsum, - ) - s3_params = SlitParameters( - small=0.05, - large=0.5, - scanwidth=0.7, - steps=50, - x_size=dev.s3_xsize, - y_size=dev.s3_ysize, - x_cen=dev.s3_xcen, - y_cen=dev.s3_ycen, - mon=dev.i1, - ) - - # Map slit names to their parameters - slit_parameters = {"s1": s1_params, "s2": s2_params, "s3": s3_params} - - if name not in slit_parameters: - raise ValueError(f"Unknown slit name: {name}") - - params = slit_parameters[name] - print("Moving filters out") - filters("out") - - print("Moving i1 diode into position") - SE.i1.mvin() - - if x and y: - scan_in_x( - xsize=params.x_size, - xcen=params.x_cen, - mon=params.mon, - small=params.small, - large=params.large, - width=params.scanwidth, - steps=params.steps, - ) - scan_in_y( - ysize=params.y_size, - ycen=params.y_cen, - mon=params.mon, - small=params.small, - large=params.large, - width=params.scanwidth, - steps=params.steps, - ) - if x and not y: - scan_in_x( - xsize=params.x_size, - xcen=params.x_cen, - mon=params.mon, - small=params.small, - large=params.large, - width=params.scanwidth, - steps=params.steps, - ) - else: - scan_in_y( - ysize=params.y_size, - ycen=params.y_cen, - mon=params.mon, - small=params.small, - large=params.large, - width=params.scanwidth, - steps=params.steps, - ) - - filters("in") - def scan_in_x(xsize, xcen, mon, small, large, width, steps): umv(xsize, small) @@ -1015,35 +879,43 @@ def calc_from_centre(cam="samcam"): return read, diff_px -def get_cam(): - umv(dev.scam_zoom, 100) +def get_cam(low_zoom, high_zoom): + umv(dev.scam_zoom, low_zoom) x = dev.samcam_x.read()["samcam_x"]["value"] y = dev.samcam_y.read()["samcam_y"]["value"] print(f"Low zoom: x = {x}, y = {y}") - umv(dev.scam_zoom, 500) + umv(dev.scam_zoom, high_zoom) x = dev.samcam_x.read()["samcam_x"]["value"] y = dev.samcam_y.read()["samcam_y"]["value"] print(f"High zoom: x = {x}, y = {y}") -def read_currents(): - """Read the individual bpm channels""" - bpm1 = dev.bcu_bpm1.read()["bcu_bpm1"]["value"] - bpm2 = dev.bcu_bpm2.read()["bcu_bpm2"]["value"] - bpm3 = dev.bcu_bpm3.read()["bcu_bpm3"]["value"] - bpm4 = dev.bcu_bpm4.read()["bcu_bpm4"]["value"] - # print(f"bpm1 = {bpm1:.3f}, bpm2 = {bpm2:.3f}, bpm3 = {bpm3:.3f}, bpm4 = {bpm4:.3f}") - return {"bpm1": bpm1, "bpm2": bpm2, "bpm3": bpm3, "bpm4": bpm4} +# def read_currents(): +# """Read the individual bpm channels""" +# bpm1 = dev.bcu_bpm1.read()["bcu_bpm1"]["value"] +# bpm2 = dev.bcu_bpm2.read()["bcu_bpm2"]["value"] +# bpm3 = dev.bcu_bpm3.read()["bcu_bpm3"]["value"] +# bpm4 = dev.bcu_bpm4.read()["bcu_bpm4"]["value"] +# # print(f"bpm1 = {bpm1:.3f}, bpm2 = {bpm2:.3f}, bpm3 = {bpm3:.3f}, bpm4 = {bpm4:.3f}") +# return {"bpm1": bpm1, "bpm2": bpm2, "bpm3": bpm3, "bpm4": bpm4} -def compute_norm(): - """Compute normalised x and y positions""" - readings = read_currents() - total = readings["bpm1"] + readings["bpm2"] + readings["bpm3"] + readings["bpm4"] - # print(f"Sum is {total:.2f}") - xn = ((readings["bpm1"] + readings["bpm2"]) - (readings["bpm3"] + readings["bpm4"])) / total - yn = ((readings["bpm1"] + readings["bpm3"]) - (readings["bpm2"] + readings["bpm4"])) / total - return xn, yn +# def compute_norm(): +# """Compute normalised x and y positions""" +# readings = read_currents() +# total = readings["bpm1"] + readings["bpm2"] + readings["bpm3"] + readings["bpm4"] +# # print(f"Sum is {total:.2f}") +# xn = ((readings["bpm1"] + readings["bpm2"]) - (readings["bpm3"] + readings["bpm4"])) / total +# yn = ((readings["bpm1"] + readings["bpm3"]) - (readings["bpm2"] + readings["bpm4"])) / total +# return xn, yn + +def average_inten(): + vals_inten = [] + for _ in range(5): + vals_inten.append(dev.bcu_bpmsum.read()['bcu_bpmsum']['value']) + time.sleep(0.1) + inten = np.mean(vals_inten) + return inten def mirror_pitch(mirror = 'vfm'): @@ -1471,4 +1343,184 @@ def get_mirror_data(history_index: int): # "y_data": y_data, # "motor_name": motor_name, # "scan_number": scan_number, - # } \ No newline at end of file + # } + + +def record_beampos_until(stop_time_str, interval_minutes=10): + """ + Runs `record_beam()` every `interval_minutes` minutes + until the next occurrence of the given stop time (HH:MM). + """ + + # Prepare the file + now = datetime.now() + fnow = now.strftime("%d%m%H%M") + filename = f"luts/beampos/beam_pos_record_{fnow}.csv" + scam_zoom = dev.scam_zoom.read()['scam_zoom']['value'] + umv(dev.scam_zoom, 1000) + beam_size = "25 x 25" + + energy = get_current_energy() + + + # Write the header to the file + with open(filename, "w", encoding="utf-8") as f: + f.write(f"Beam size: {beam_size}, Energy: {energy:.0f} eV, Zoom: {scam_zoom}\n") + # f.write("Time,BPM_x,BPM_y,Scin_x,Scin_y,BPM_x,BPM_y\n") + f.write("Time,Scin_x,Scin_y,BPM_x,BPM_y\n") + + + # Parse the stop time (HH:MM) + stop_hour, stop_minute = map(int, stop_time_str.split(":")) + end_time = now.replace(hour=stop_hour, minute=stop_minute, second=0, microsecond=0) + + # If that time already passed today, set it for tomorrow + if end_time <= now: + end_time += timedelta(days=1) + + print(f"Starting now ({now:%Y-%m-%d %H:%M}), running until {end_time:%Y-%m-%d %H:%M}") + print(f"Interval: {interval_minutes} minutes\n") + + while datetime.now() < end_time: + record_beam(filename) + next_run = datetime.now() + timedelta(minutes=interval_minutes) + if next_run > end_time: + break + print(f"Next run at {next_run:%H:%M:%S}") + time.sleep(interval_minutes * 60) + + print(f"Finished — reached {end_time:%H:%M}.") + + + +def record_beam(filename): + """ + Record the beam position to file. + """ + + # Perform the usual recording steps + umv(dev.ss_f4_x, 10) + auto_exposure(cam="samcam") + time.sleep(2) + now = datetime.now() + + # Append data to the file + with open(filename, "a", encoding="utf-8") as f: + fnow = now.strftime("%H:%M:%S") + xpos_cam = dev.samcam_x.read()["samcam_x"]["value"] + ypos_cam = dev.samcam_y.read()["samcam_y"]["value"] + x_bpm, y_bpm = get_beampos() + print(f"Time is {fnow}, X position is {xpos_cam:.5g}, Y position is {ypos_cam:.5g}") + # xpos, ypos = compute_pos() + f.write( + # f"{fnow}, {xpos: .5g}, {ypos: .4g}, {xpos_cam: .5g}, {ypos_cam: .4g}\n" + f"{fnow},{xpos_cam: .5g},{ypos_cam: .4g},{x_bpm: .5g},{y_bpm: .5g}\n" + ) + + umv(dev.ss_f4_x, 16) + + +def analyse_beampos(file): + """Plot the recorded beam position data""" + # Load the CSV file into a Pandas DataFrame + filedir = "luts/beampos/" + filename = filedir + file + data = pd.read_csv(filename, skiprows=1) + print(data.head()) + + # ref_bpmx = 0.110 + # ref_bmpy = -0.175 + ref_scinx = 1024 + ref_sciny = 980 + scam_zoom = 116 + + # Extract the first column (time) as the x-axis + meas_time = data["Time"] + + # subtract the reference positions from the measures position + # data["bpm_x"] = data["bpm_x"] - ref_bpmx + # data["bpm_y"] = data["bpm_y"] - ref_bmpy + data["Scin_x"] = (data["Scin_x"] - ref_scinx) * calc_scam_microns(1) + data["Scin_y"] = (data["Scin_y"] - ref_sciny) * calc_scam_microns(1) + + + # Extract Y-position columns (all columns except the first column) + y_positions = data.iloc[:, 1:] # Exclude the first column + + fig, axs = plt.subplots( + 2, 2, figsize=(12, 8), layout="constrained" + ) # Create a 2x2 grid for subplots + # Flatten axs for easy iteration (if axs is a 2D array of axes) + axs = axs.flatten() + # Specify which columns to color differently + red_columns = ["bpm_x", "scin_x"] + + for idx, column in enumerate(y_positions.columns): + ax = axs[idx] # Select the current subplot + + # Determine the color based on the column name + color = "red" if column in red_columns else "blue" + + # Plot the line and scatter with the chosen color + ax.plot(meas_time, y_positions[column], color=color, linewidth=0.5) # Line plot + ax.scatter( + meas_time, y_positions[column], color=color, label=column + ) # Scatter plot + + # Set x-axis tick positions and labels + tick_positions = range(0, len(meas_time), 7) # Adjust the step size as needed + ax.set_xticks(tick_positions) + ax.set_xticklabels([meas_time[i] for i in tick_positions], rotation=45) + + # Add labels, title, legend, and grid to each subplot + ax.set_xlabel("Time") + ax.set_ylabel("beam displacement (microns)") + ax.set_title(f"Beam position at {column}") + ax.legend() + ax.grid(True) + + # Show the resulting figure + plt.show() + +import time +import numpy as np +import matplotlib.pyplot as plt +from epics import caget + + +def scan_scin_focus(): + z0 = dev.diag_z.position + + z_positions = np.linspace(-4,4,30) + contrasts = [] + + + + for z in z_positions: + umv(dev.diag_z, z) + time.sleep(0.1) + + sigma = dev.samcam_sigma.read()['samcam_sigma']['value'] + mean = dev.samcam_mean.read()['samcam_mean']['value'] + + contrast = sigma / mean if mean > 0 else 0 + contrasts.append(contrast) + + print(f"z = {z:.4f}, sigma = {sigma:.3f}, mean = {mean:.3f}, contrast = {contrast:.5f}") + + contrasts = np.asarray(contrasts) + + best_idx = np.argmax(contrasts) + best_z = z_positions[best_idx] + + print(f"\nBest scintillator focus z = {best_z:.4f}") + + umv(dev.diag_z,best_z) + + plt.plot(z_positions, contrasts, "o-") + plt.axvline(best_z, linestyle="--") + plt.xlabel("Scintillator z") + plt.ylabel("Sigma / Mean") + plt.show() + + return best_z, z_positions, contrasts \ No newline at end of file diff --git a/pxii_bec/macros/mx_methods.py b/pxii_bec/macros/mx_methods.py index 38cc6ed..9e012d9 100755 --- a/pxii_bec/macros/mx_methods.py +++ b/pxii_bec/macros/mx_methods.py @@ -105,6 +105,7 @@ def go_to_peak( settle: float = FitDefaults.SETTLE_TIME, confirm: bool = True, gomax: bool = False, + negative: bool = False ): """ Go to the peak of a signal by scanning a motor within a specified range and @@ -177,7 +178,10 @@ def go_to_peak( } # Define and fit model to scan data - fit_params = create_fit_parameters(False, FitDefaults.MODEL, FitDefaults.BASELINE) + fit_params = create_fit_parameters(deriv = False, + negative = False, + model = FitDefaults.MODEL, + baseline = FitDefaults.BASELINE) fit_result = fit(data, fit_params) # Plot the fitted data if plot = True @@ -199,6 +203,7 @@ def fit_history( signal_name: str, deriv: bool = False, negative: bool = False, + smoothing: bool = False, model: str = FitDefaults.MODEL, move_to_peak: bool = False, ): -- 2.54.0 From 9c27e6dd8e4cd7b303d9464419e3f5c4753f1b4f Mon Sep 17 00:00:00 2001 From: x10sa Date: Thu, 9 Jul 2026 12:24:39 +0200 Subject: [PATCH 7/9] changes from BL commissioning --- .../device_configs/pxii-beamline-states.yaml | 1 + pxii_bec/device_configs/pxii-devices.yaml | 40 ++- pxii_bec/macros/APscripts.py | 249 ++++++++++++------ pxii_bec/macros/calculator.py | 4 +- pxii_bec/macros/calibrate_bpm.py | 161 ++++++++++- pxii_bec/macros/flux_di.py | 45 ++-- pxii_bec/macros/katscripts.py | 232 ++++++++-------- pxii_bec/macros/pxii_parameters.py | 2 +- pxii_bec/macros/set_kbox.sh | 4 +- 9 files changed, 488 insertions(+), 250 deletions(-) diff --git a/pxii_bec/device_configs/pxii-beamline-states.yaml b/pxii_bec/device_configs/pxii-beamline-states.yaml index 496ceb7..70c5c96 100644 --- a/pxii_bec/device_configs/pxii-beamline-states.yaml +++ b/pxii_bec/device_configs/pxii-beamline-states.yaml @@ -16,6 +16,7 @@ states: aerotech_u: mount smargon_x: mount smargon_y: mount + smargon_z: mount smargon_chi: mount smargon_phi: mount xrf_pos: out diff --git a/pxii_bec/device_configs/pxii-devices.yaml b/pxii_bec/device_configs/pxii-devices.yaml index 782114e..20237d9 100644 --- a/pxii_bec/device_configs/pxii-devices.yaml +++ b/pxii_bec/device_configs/pxii-devices.yaml @@ -55,8 +55,8 @@ aerotech: deviceConfig: prefix: http://mx-x10sa-queue-01:5234 deviceTags: - - motors - aerotech + - motors enabled: true onFailure: buffer readoutPriority: baseline @@ -70,7 +70,7 @@ aerotech: safe: -50 y: mount: -0.0 - work: -0.0 + work: -0.022 z: mount: 0 work: 0 @@ -291,7 +291,7 @@ bs_x: onFailure: buffer readoutPriority: baseline userParameter: - in: 0.2 + in: 0.4 bs_y: description: Beamstop Y deviceClass: ophyd_devices.EpicsMotor @@ -303,7 +303,7 @@ bs_y: onFailure: buffer readoutPriority: baseline userParameter: - in: -3.154 + in: -2.654 bs_z: description: Beamstop Z deviceClass: ophyd_devices.EpicsMotor @@ -433,7 +433,7 @@ coll_x: onFailure: buffer readoutPriority: baseline userParameter: - in: -3.080 + in: -2.72 coll_y: description: Collimator Y deviceClass: ophyd_devices.EpicsMotor @@ -445,7 +445,7 @@ coll_y: onFailure: buffer readoutPriority: baseline userParameter: - in: 39.16 + in: 39.188 intermediate: 32 out: 20.002 park: 1 @@ -605,7 +605,7 @@ det_y: readoutPriority: baseline userParameter: work: 70 - xi: 214 + xi: 213.601 det_z: description: Detector Z deviceClass: ophyd_devices.EpicsMotor @@ -618,7 +618,7 @@ det_z: readoutPriority: baseline userParameter: mse: 800 - vis: 800 + vis: 800 diag_y: description: Scintillator/diode Y deviceClass: ophyd_devices.EpicsMotor @@ -1364,8 +1364,8 @@ smargon: deviceConfig: prefix: http://x10sa-smargopolo.psi.ch:3000 deviceTags: - - motors - smargon + - motors enabled: true onFailure: buffer readoutPriority: baseline @@ -1460,18 +1460,6 @@ ss_bpmsum: onFailure: buffer readOnly: true readoutPriority: monitored -transm: - description: Beam Transmission - deviceClass: ophyd_devices.EpicsSignal - deviceConfig: - read_pv: 'X10SA-ES-SSFI:TRANSM-SET' - write_pv: 'X10SA-ES-SSFI:TRANSM-SET' - deviceTags: - - transm - enabled: true - onFailure: retry - readOnly: false - readoutPriority: baseline ss_f1_x: description: SS Filter 1 X deviceClass: ophyd_devices.EpicsMotor @@ -1698,6 +1686,16 @@ ss_xicam_ysig: onFailure: buffer readOnly: true readoutPriority: baseline +transm: + description: Beam Transmission + deviceClass: ophyd_devices.EpicsSignal + deviceConfig: + read_pv: X10SA-ES-SSFI:TRANSM-SET + write_pv: X10SA-ES-SSFI:TRANSM-SET + deviceTags: + - transm + enabled: true + readoutPriority: baseline vfm_bd: description: VFM Downstream Bender deviceClass: ophyd_devices.EpicsMotorEC diff --git a/pxii_bec/macros/APscripts.py b/pxii_bec/macros/APscripts.py index 1dd036e..b596c46 100644 --- a/pxii_bec/macros/APscripts.py +++ b/pxii_bec/macros/APscripts.py @@ -10,7 +10,7 @@ import numpy as np import math import matplotlib.pyplot as plt import sys - +import time, datetime ################################ ### BASIC BL PROGRAMS @@ -692,7 +692,7 @@ def getdiodepos(diode="i1"): diode_in = 0 # sys.exit(0) if diode == "i2": - detpos_diode = 214.5 + detpos_diode = 213.6 detpos_rb = dev.det_z.user_readback.get() print("using Det diode requires det up and close and beamstop out") if abs(detpos_diode - detpos_rb) > 0.5: @@ -706,7 +706,7 @@ def read_mon(): from datetime import datetime e = getenergy() - fesum = dev.fe_bpmsum.read()["fe_bpmsum"]["value"] + #fesum = dev.fe_bpmsum.read()["fe_bpmsum"]["value"] lusum = dev.lu_bpmsum.read()["lu_bpmsum"]["value"] sssum = dev.ss_bpmsum.read()["ss_bpmsum"]["value"] @@ -725,27 +725,30 @@ def read_mon(): vbpitch = dev.vfm_pitch.read()["vfm_pitch"]["value"] vbyaw = dev.vfm_yaw.read()["vfm_yaw"]["value"] vbroll = dev.vfm_roll.read()["vfm_roll"]["value"] - #vbvert = dev.vfm_vert.read()["vfm_vert"]["value"] + vfm_x= dev.vfm_x.read()["vfm_x"]["value"] + vfm_y= dev.vfm_y.read()["vfm_y"]["value"] + # KB H hbu = dev.hfm_bu.read()["hfm_bu"]["value"] hbd = dev.hfm_bd.read()["hfm_bd"]["value"] hbpitch = dev.hfm_pitch.read()["hfm_pitch"]["value"] hbyaw = dev.hfm_yaw.read()["hfm_yaw"]["value"] hbroll = dev.hfm_roll.read()["hfm_roll"]["value"] - - #hbvert = dev.hfm_vert.read()["hfm_vert"]["value"] + hfm_x= dev.hfm_x.read()["hfm_x"]["value"] + hfm_y= dev.hfm_y.read()["hfm_y"]["value"] + ## FE slits centre and size - fe_sx_cen = dev.fe_sxcen.read()["fe_sxcen"]["value"] - fe_sx_size = dev.fe_sxsize.read()["fe_sxsize"]["value"] - fe_sy_cen = dev.fe_sycen.read()["fe_sycen"]["value"] - fe_sy_size = dev.fe_sysize.read()["fe_sysize"]["value"] + fe_sl_xcen = dev.fe_sl_xcen.read()["fe_sl_xcen"]["value"] + fe_sl_xsize = dev.fe_sl_xsize.read()["fe_sl_xsize"]["value"] + fe_sl_ycen = dev.fe_sl_ycen.read()["fe_sl_ycen"]["value"] + fe_sl_ysize = dev.fe_sl_ysize.read()["fe_sl_ysize"]["value"] ## BSF slits centre and size - bsf_xcen = dev.bsf_sl_xcen.read()["bsf_sl_xcen"]["value"] - bsf_xsize = dev.bsf_sl_xsize.read()["bsf_sl_xsize"]["value"] - bsf_ycen = dev.bsf_sl_ycen.read()["bsf_sl_ycen"]["value"] - bsf_ysize = dev.bsf_sl_ysize.read()["bsf_sl_ysize"]["value"] + bsf_sl_xcen = dev.bsf_sl_xcen.read()["bsf_sl_xcen"]["value"] + bsf_sl_xsize = dev.bsf_sl_xsize.read()["bsf_sl_xsize"]["value"] + bsf_sl_ycen = dev.bsf_sl_ycen.read()["bsf_sl_ycen"]["value"] + bsf_sl_ysize = dev.bsf_sl_ysize.read()["bsf_sl_ysize"]["value"] ## SS slits centre and size ss_sl_xcen = dev.ss_sl_xcen.read()["ss_sl_xcen"]["value"] @@ -775,30 +778,31 @@ def read_mon(): ## move out again - xeye_x_pos = dev.xeye_x.read()["xeye_x"]["value"] + xeye_x_pos = dev.xi_x.read()["xi_x"]["value"] bcusum = 0 i1signal = 0 - if xeye_x_pos < 0: - bcusum = dev.bcu_bpmsum.read()["bcu_bpmsum"]["value"] - i1signal = dev.i1.read()["i1"]["value"] + #if xeye_x_pos < 0: + bcusum = dev.bcu_bpmsum.read()["bcu_bpmsum"]["value"] + i1signal = dev.i1.read()["i1"]["value"] print("Energy = ", e, " keV") - print(f"fesum,lusum,sssum,bcusum,i1signal = {fesum,lusum,sssum,bcusum,i1signal}") + #print(f"fesum,lusum,sssum,bcusum,i1signal = {fesum,lusum,sssum,bcusum,i1signal}") + print(f"lusum,sssum,bcusum,i1signal = {lusum,sssum,bcusum,i1signal}") print(f"bragg, pitch, perp, fpitch, froll, gap = {bragg, pitch,perp, fpitch, froll, gap}") # return e, fesum,lusum,sssum,bcusum,i1signal print("KB VERT") print( - f"vbu, vbd, vbpitch,vbyaw,vbroll,vblat,vbvert = {vbu, vbd, vbpitch,vbyaw,vbroll,vblat,vbvert}" + f"vbu, vbd, vbpitch,vbyaw,vbroll,vbvert = {vbu, vbd, vbpitch,vbyaw,vbroll,vfm_x, vfm_y}" ) # return vbu, vbd, vbpitch,vbyaw,vbroll,vblat,vbvert print("KB HORI") print( - f"hbu, hbd, hbpitch,hbyaw,hbroll,hblat,hbvert = {hbu, hbd, hbpitch,hbyaw,hbroll,hblat,hbvert}" + f"hbu, hbd, hbpitch,hbyaw,hbroll,hblat,hbvert = {hbu, hbd, hbpitch,hbyaw,hbroll,hfm_x, hfm_y}" ) # return hbu, hbd, hbpitch,hbyaw,hbroll,hblat,hbvert ## dump status in CSV - timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") + timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S") dirname = "/sls/x10sa/config/commissioning/Data/" filename = dirname + f"BLstatus_{timestamp}.txt" with open(filename, "w") as f: @@ -810,16 +814,16 @@ def read_mon(): combined = np.column_stack((bragg, pitch, perp, fpitch, froll)) np.savetxt(f, combined, delimiter=",", fmt="%5f") - f.write("vbu, vbd, vbpitch,vbyaw,vbroll,vblat,vbvert\n") - combined = np.column_stack((vbu, vbd, vbpitch, vbyaw, vbroll, vblat, vbvert)) + f.write("vbu, vbd, vbpitch,vbyaw,vbroll,vbvert\n") + combined = np.column_stack((vbu, vbd, vbpitch, vbyaw, vbroll, vfm_x, vfm_y)) np.savetxt(f, combined, delimiter=",", fmt="%5f") f.write("hbu, hbd, hbpitch,hbyaw,hbroll,hblat,hbvert\n") - combined = np.column_stack((hbu, hbd, hbpitch, hbyaw, hbroll, hblat, hbvert)) + combined = np.column_stack((hbu, hbd, hbpitch, hbyaw, hbroll, hfm_x, hfm_y)) np.savetxt(f, combined, delimiter=",", fmt="%5f") f.write("FE slits\n") - combined = np.column_stack((fe_sx_cen, fe_sx_size, fe_sy_cen, fe_sy_size)) + combined = np.column_stack((fe_sl_xcen, fe_sl_xsize, fe_sl_ycen, fe_sl_ysize)) np.savetxt(f, combined, delimiter=",", fmt="%5f") f.write("BSF slits\n") @@ -834,8 +838,10 @@ def read_mon(): combined = np.column_stack((bcu_sl_xcen, bcu_sl_xsize, bcu_sl_ycen, bcu_sl_ysize)) np.savetxt(f, combined, delimiter=",", fmt="%5f") - f.write("fesum,lusum,sssum,bcusum,i1signal\n") - combined = np.column_stack((fesum, lusum, sssum, bcusum, i1signal)) + #f.write("fesum,lusum,sssum,bcusum,i1signal\n") + #combined = np.column_stack((fesum, lusum, sssum, bcusum, i1signal)) + f.write("lusum,sssum,bcusum,i1signal\n") + combined = np.column_stack((lusum, sssum, bcusum, i1signal)) np.savetxt(f, combined, delimiter=",", fmt="%5f") return @@ -1219,42 +1225,6 @@ def kbfocus(sizex, sizey): return -##### ====================== -##### goto several energies with about the right gap opening - - -def goto7(): - perp_dist = 0.0389 - umv(dev.dcm_perp, perp_dist) - gap = 6.9 # 3rd harm - umv(dev.id_gap, gap) - sete(7) - - -def goto20(): - perp_dist = 0.0389 - umv(dev.dcm_perp, perp_dist) - gap = 4.736 # 13th harm - umv(dev.id_gap, gap) - sete(20) - - -def goto27(): - perp_dist = 0.0389 - umv(dev.dcm_perp, perp_dist) - gap = 4.86 # 17th harm - umv(dev.id_gap, gap) - sete(27) - - -def goto30(): - perp_dist = 0.0389 - umv(dev.dcm_perp, perp_dist) - gap = 4.842 # 19th harm - umv(dev.id_gap, gap) - sete(30) - - ######################### ### Status of the BEC ######################### @@ -1278,22 +1248,23 @@ def bstatus(): ########################### -def detxeye_in(): +def detxeye_in(setdetzpos = 200, setdetypos = 213.6): """ moves in the Xray eye and the Diode below detector """ # setfoc = 1.0 setzoom = 0.1 - setxrpos = 2.0 + setxrpos = 0.0 - setdetzpos = 260 # 200 better? - setdetypos = 214.5 + #setdetzpos = 200 # 200 better? + #setdetypos = 213.6 detzpos = dev.det_z.user_readback.get() detypos = dev.det_y.user_readback.get() print(f"detector position now: z = {detzpos}, y = {detypos}") + print(f"... moving to detector position: z = {setdetzpos}, y = {setdetypos}") ans = "n" ans = input("Is it ok to move detector in and up? y/n ") @@ -1308,15 +1279,15 @@ def detxeye_in(): print("moving X-ray eye below Eiger in") - xrpos = dev.det_xi_x.user_readback.get() - if abs(setxrpos - xrpos) > 1: - umv(dev.det_xi_x, setxrpos) - zoompos = dev.det_xi_zoom.user_readback.get() - if abs(setzoom - zoompos) > 1: - umv(dev.det_xi_zoom, setzoom) - focpos = dev.det_xi_focus.user_readback.get() - if abs(setfoc - focpos) > 1: - umv(dev.det_xi_focus, setfoc) + #xrpos = dev.det_xi_x.user_readback.get() + #if abs(setxrpos - xrpos) > 1: + # umv(dev.det_xi_x, setxrpos) + #zoompos = dev.det_xi_zoom.user_readback.get() + #if abs(setzoom - zoompos) > 1: + # umv(dev.det_xi_zoom, setzoom) + #focpos = dev.det_xi_focus.user_readback.get() + #if abs(setfoc - focpos) > 1: + # umv(dev.det_xi_focus, setfoc) def detxeye_out(): @@ -1324,7 +1295,7 @@ def detxeye_out(): moves det back and down """ setdetzpos = 500 - setdetypos = 0 + setdetypos = 70 umv(dev.det_z, setdetzpos) detzpos = dev.det_z.user_readback.get() if detzpos > 300: @@ -1579,3 +1550,125 @@ def readdist(filename): plt.xlabel("dist / mm") plt.ylabel("bpos Y in det pix ") plt.show() + + return + +################################################ +### flux cal +################################################ + +def read_av(signal, avlen): + #signal = dev.lu_bpmsum + + buf = [] + count =0 + while count < avlen: + new_value = signal.read()[signal.name]['value'] + #new_value = dev.lu_bpmsum.read()['lu_bpmsum']["value"] + buf.append(new_value) + count+=1 + return sum(buf) / len(buf) + + + +def fitpoly(x,y, order): + from scipy.optimize import curve_fit + + coeff = np.polyfit(x, y, order) + polynomial = np.poly1d(coeff) + + print("Polynomial coefficients of the fit fct: ", order, coeff) + x_fit = np.linspace(min(x), max(x), 100) + y_fit = polynomial(x_fit) + + plt.ion() + plt.figure() + plt.title("X10SA Fl cal") + plt.ylabel("fl/bcubpmsum") + plt.title("E / keV") + + plt.plot(x, y, "*") + plt.plot(x_fit, y_fit, color="blue") + + + +def prepare_fluxmeas(): +# check all slits + read_mon() +# + print("preparing devices ...") + ans = "n" + ans = input("Is it safe to move det in and up and BS down? y/n ") + if ans == "y": + detxeye_in() + bs_in = d["bs_y"].positions["in"] + umv(dev.bs_y, bs_in +1) + return + +def fluxcal(start_en=13, stop_en=14, step =1): + import time + # + tstart = time.perf_counter() # time logging + avlen= 10 + + dat_en=[] + dat_lubpm=[] + dat_ssbpm=[] + dat_bcubpm=[] + dat_xi=[] + dat_fluxi=[] + dat_quot_flbsum=[] + + for ei in range(start_en,stop_en+1, step): + bl_energy(ei*1000, plot = False) # in ev + time.sleep(0.2) + #lusum = dev.lu_bpmsum.read()["lu_bpmsum"]["value"] + signal = dev.lu_bpmsum # "lu_bpmsum" + lusum = read_av(signal, avlen) + + #sssum = dev.ss_bpmsum.read()["ss_bpmsum"]["value"] + signal = dev.ss_bpmsum # "ss_bpmsum" + sssum = read_av(signal, avlen) + + #bcusum = dev.bcu_bpmsum.read()["bcu_bpmsum"]["value"] + signal = dev.bcu_bpmsum #"bcu_bpmsum" + bcusum = read_av(signal, avlen) + + + #xi = dev.xidiode.read()["xidiode"]["value"] + signal = dev.xidiode + xi = read_av(signal, avlen) + + fluxi = flux_x10sa(xi, ei, silent =1) + quot = fluxi/bcusum + + dat_en.append(ei) + dat_lubpm.append(lusum) + dat_ssbpm.append(sssum) + dat_bcubpm.append(bcusum) + dat_xi.append(xi) + dat_fluxi.append(fluxi) + dat_quot_flbsum.append(quot) + + combined = np.column_stack((dat_en, dat_lubpm,dat_ssbpm,dat_bcubpm,dat_xi,dat_fluxi,dat_quot_flbsum)) + + # open file for output + timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S") + dirname = "/sls/x10sa/config/commissioning/Data/" + filename = dirname + f"FLUX_x10sa_{timestamp}.txt" + + with open(filename, "w") as f: + np.savetxt(f, combined, delimiter=",", fmt="%9f") + + + elapsed_time = time.perf_counter()-tstart + print(f"Runtime: {elapsed_time: .6f} seconds, i.e., {elapsed_time: .6f}/60 min") + # CLOSE AND MOVE BACK ############ + # close shutter ! + + print("close the shutter !") + + # move beamstop back ! + #umv(dev.bs_y, bs_in) + + fitpoly(dat_en, dat_quot_flbsum, 3) diff --git a/pxii_bec/macros/calculator.py b/pxii_bec/macros/calculator.py index a6278e8..c988c7e 100755 --- a/pxii_bec/macros/calculator.py +++ b/pxii_bec/macros/calculator.py @@ -355,7 +355,7 @@ def calc_scam_microns(pixels, zoom=1000): """Convert pixels to microns for the sample camera""" return float(pixels / (CamConversion.a * np.exp(CamConversion.b * zoom))) -def calc_bsccam_microns(pixels): - """Convert pixels to microns for the BSC camera""" +def calc_sscam_microns(pixels): + """Convert pixels to microns for the ss camera""" return pixels*20 diff --git a/pxii_bec/macros/calibrate_bpm.py b/pxii_bec/macros/calibrate_bpm.py index f041273..12484d5 100644 --- a/pxii_bec/macros/calibrate_bpm.py +++ b/pxii_bec/macros/calibrate_bpm.py @@ -12,12 +12,14 @@ Final beam position: import time import os from datetime import datetime, timedelta +from pathlib import Path import numpy as np +import pandas as pd import matplotlib.pyplot as plt from pyparsing import results from scipy.optimize import curve_fit import scipy.special as special -from scipy.interpolate import PchipInterpolator +from scipy.interpolate import PchipInterpolator, CubicSpline def read_currents(): @@ -175,7 +177,7 @@ def linear_calibration( xdata, ydata = fit_bpm_data(x_y, rundate = rundate, bpm_name = bpm_name) # Remove non-linear region if x_y == 'x': - mask_limit = 0.65 + mask_limit = 0.59 else: mask_limit = 0.9 mask = np.abs(ydata) < mask_limit @@ -459,26 +461,159 @@ def flux( flux /= al_transmission flux /= air_transmission - print(f"The flux is {flux: .3g} ph/s") + + print(f"Flux = {flux: .3g} ph/s") return float(flux) -def calibrate_bpm_flux(): +def calibrate_bpm_flux(ave = 5): # d['det_z'].move('mse') # d['det_y'].move('xi') # d['det_z'].move(200) - flux = flux(dev.xidiode.read()['xidiode']['value']) + dir = "luts/bpm_calib/" + filename = dir + "bpm_flux_20260708b.csv" + with open(filename, 'w', encoding="utf-8") as f: + f.write("Energy,Transmission,BPMSum,Flux\n") + print("Energy,Transmission,BPMSum,Flux\n") + energies = [12400,7000,8000,9000,10000,11000,13000,14000,15000,16000,18000,20000,25000] + # energies = [7000,8000,9000,10000] + # transmissions = [1, 0.5, 0.2, 0.1, 0.05, 0.01] + transmissions = [1, 0.9, 0.8, 0.7, 0.6, 0.5,0.4,0.3,0.2,0.1] + + for energy in energies: + print(f"Moving to energy {energy}") + bl_energy(energy) + + for set_trans in transmissions: + print(f"Setting transmission to {set_trans}") + dev.transm.put(set_trans) + time.sleep(5) + + flux_values = [] + bpm_values = [] + + print(f"Measuring flux and bpmsum") + for _ in range(ave): + diode_current = dev.xidiode.read()['xidiode']['value'] + fl = flux(diode_current) + bpmsum = dev.bcu_bpmsum.read()['bcu_bpmsum']['value'] + flux_values.append(fl) + bpm_values. append(bpmsum) + + actual_trans = dev.transm.read()['transm']['value'] + flux_ave = np.mean(flux_values) + bpmsum_ave = np.mean(bpm_values) + print(f"{energy:.5g},{actual_trans:.3g},{bpmsum_ave:.4g},{flux_ave:.4f}\n") + + with open(filename, 'a') as f: + f.write(f"{energy:.5g},{actual_trans:.3g},{bpmsum_ave:.4g},{flux_ave:.4f}\n") + bl_energy(12400) + umv(dev.det_y, 70) + umv(dev.id_gap, 20) + +def analyse_bpm_flux_calibration( + filename="luts/bpm_calib/bpm_flux_comb.csv", + force_zero_intercept=False, +): + data = pd.read_csv(filename) + + results = [] + with open("luts/bpm_calib/bpm_flux_fits.csv", "w") as f: + f.write("Energy,Slope,Intercept\n") + for energy, group in data.groupby("Energy"): + x = group["BPMSum"].to_numpy(dtype=float) + print(f"x is {x}") + y = group["Flux"].to_numpy(dtype=float) + + if force_zero_intercept: + # y = m*x + slope = np.sum(x * y) / np.sum(x * x) + intercept = 0.0 + else: + # y = m*x + c + slope, intercept = np.polyfit(x, y, deg=1) + + y_fit = slope * x + intercept + + # --- Plot --- + plt.figure(figsize=(7, 5)) + plt.scatter(x, y, color="red") + + x_fit = np.linspace(min(x), max(x), 100) + plt.plot(x_fit, slope * x_fit + intercept, + "r--", label=f"Fit: Slope = {slope:.5g}, Intercept = {intercept:.5g}") + + plt.xlabel("BPMSUm") + plt.ylabel("Flux") + plt.title(f"{energy} eV") + plt.legend() + plt.grid(True) + plt.tight_layout() + plt.savefig(f"luts/bpm_calib/{energy}_bpm_flux") + # plt.show() + + residuals = y - y_fit + ss_res = np.sum(residuals**2) + ss_tot = np.sum((y - np.mean(y))**2) + + r2 = 1 - ss_res / ss_tot if ss_tot > 0 else np.nan + + results.append( + { + "Energy": energy, + "Slope": f"{slope:.5g}", + "Intercept": f"{intercept:.5g}", + "R2": f"{r2:.3g}", + # "N": len(group), + } + ) + + results = pd.DataFrame(results) + + results.to_csv("luts/bpm_calib/bpm_flux_fits.csv", index=False) + dict = results.to_dict() + print(dict) + return results + +def get_flux_calibration(energy): + filename = "luts/bpm_calib/bpm_flux_fits_zero.csv" + default_slope = 4.42e8 + default_intercept = -1.66e11 + + try: + df = pd.read_csv(filename) + energies = df["Energy"].to_numpy() + intercepts = df["Intercept"].to_numpy() + slopes = df["Slope"].to_numpy() + slope_interp = CubicSpline(energies, slopes) + intercept_interp = CubicSpline(energies, intercepts) + slope = slope_interp(energy) + intercept = intercept_interp(energy) + print(f"Using data from calibration file") + except FileNotFoundError: + print("Cannot access calibration file, using default parameters") + slope = default_slope + intercept = default_intercept + + return slope, intercept + +def bpm2flux(energy=None,bpmsum=None): + if energy is None: + energy = get_current_energy() + if bpmsum is None: + bpmsum = dev.bcu_bpmsum.read()['bcu_bpmsum']['value'] + + print(f"BCU_bpmsum = {bpmsum}") + + slope, intercept = get_flux_calibration(energy) + + calc = slope * bpmsum + intercept + flux = f"{calc:.5g}" + print(flux) + return float(calc) -def zero_xidiode(): - vals = [] - for i in range(1,101): - reading = dev.xidiode.read()['xidiode']['value'] - vals.append(reading) - - zero = np.mean(vals) - print(zero) diff --git a/pxii_bec/macros/flux_di.py b/pxii_bec/macros/flux_di.py index a22a174..7d39470 100755 --- a/pxii_bec/macros/flux_di.py +++ b/pxii_bec/macros/flux_di.py @@ -89,38 +89,43 @@ def fluxcalc(curr, en, t_air, t_si, t_al): # Main # -def flux_x10sa(): - curr = input('Please enter the current [in A] ') +def flux_x10sa(curr, en, silent = 0): + # curr = input('Please enter the current [in A] ') curr = float(curr) - print('Current = ', curr) - en = input('Please enter the energy [in keV] ') - en = float(en) - print('Energy = ', en) + if not silent: + print('Current = ', curr) + # en = input('Please enter the energy [in keV] ') + en = float(en) + if not silent: + print('Energy = ', en) ## d_det = input('Please enter the detector distance [in mm] ') d_det = dev.det_z.user_readback.get() d_off = 15 ## at X10SA ### input('Please enter the OFFSET of the diode to det surface [in mm] ') t_air = float(d_det) + float(d_off) - print('Air path length (CARE ! add det distance and offset of diode) = ', t_air) # include additional diode distance - # t_si = input('Please enter the Si thickness of diode [in um] ') - # t_si = float(t_si) / 10000. # to cm - - t_si = 12 # um ## at X10SA - # t_al = input('Please enter the Al thickness of diode [in um] ') - # t_al = float(t_al) / 10000. # to cm + t_si = 12 # um ## at X10SA + # t_si = input('Please enter the Si thickness of diode [in um] ') # if not silent: + t_si = float(t_si) / 10000. # to cm t_al = 20 # um ## at X10SA + # t_al = input('Please enter the Al thickness of diode [in um] ') + t_al = float(t_al) / 10000. # to cm + + if not silent: + print('Air path length (CARE ! add det distance and offset of diode) = ', t_air) # include additional diode distance + + fl = fluxcalc(curr, en, t_air,t_si, t_al) + if not silent: + print( " Diode Current = %.6f A " % curr) + print( " Energy = %.4f keV " % en ) - print( " Diode Current = %.6f A " % curr) - print( " Energy = %.4f keV " % en ) + #print( " Thickness of active Si layer = %.4f\t cm " % t_si) #*10000. + #print( " Thickness of Al layer in front of diode = %.4f\t cm " % t_al) #*10000. + print( " Length of path of air in front of diode = %.4f\t mm " % t_air) #*10000. - print( " Thickness of active Si layer = %.4f\t cm " % t_si) #*10000. - print( " Thickness of Al layer in front of diode = %.4f\t cm " % t_al) #*10000. - print( " Length of path of air in front of diode = %.4f\t mm " % t_air) #*10000. - - print (" Flux = %6.2e\t ph/s " % fl) + print (" Flux = %6.2e\t ph/s " % fl) return fl diff --git a/pxii_bec/macros/katscripts.py b/pxii_bec/macros/katscripts.py index 9b76ed9..2838e09 100755 --- a/pxii_bec/macros/katscripts.py +++ b/pxii_bec/macros/katscripts.py @@ -92,11 +92,11 @@ def energy_checks(start_energy=8000, end_energy=20000): fe_x = dev.fe_sxcen.read()["fe_sxcen"]["value"] fe_y = dev.fe_sycen.read()["fe_sycen"]["value"] lu_read = dev.lu_bpmsum.read()["lu_bpmsum"]["value"] - bsc_read = dev.bsc_bpmsum.read()["bsc_bpmsum"]["value"] + ss_read = dev.ss_bpmsum.read()["ss_bpmsum"]["value"] bcu_read = dev.bcu_bpmsum.read()["bcu_bpmsum"]["value"] f.write( f"{energy}, {gap: .5g}, {pitch: .5g}, {lu_read: .5g}, " - f"{bsc_read: .5g}, {bcu_read: .5g}, " + f"{ss_read: .5g}, {bcu_read: .5g}, " f"{fe_x: .5g}, {fe_y: .5g}\n" ) @@ -159,8 +159,8 @@ def record_perp(): f.close() -def beam_centre_from_bsc(): - """Compute the beam centre from the bsc_cam""" +def beam_centre_from_ss(): + """Compute the beam centre from the ss_cam""" y = dev.ss_xicam_x.read()["ss_xicam_x"]["value"] x = dev.ss_xicam_y.read()["ss_xicam_y"]["value"] beampos = {"xpos": x, "ypos": y} @@ -324,45 +324,51 @@ def scan_Ge(): def cal_samcam_fixed_x(): - lat = dev.hfm_lat.read()["hfm_lat"]["value"] - pitch = dev.hfm_pitch.read()["hfm_pitch"]["value"] - scanpoints = np.linspace(lat - 0.1, lat + 0.1, 7) + # lat = dev.hfm_x.read()["hfm_x"]["value"] + # pitch = dev.hfm_pitch.read()["hfm_pitch"]["value"] + fpitch = dev.dcm_fpitch.read()['dcm_fpitch']['value'] + scanpoints = np.linspace(3.75, 4.75, 7) zoom_high = 800 zoom_low = 200 highs, lows = [], [] - high_lat, low_lat = [], [] + high_fpitch, low_fpitch = [], [] + av_high = [] + av_low = [] # high zoom umv(dev.scam_zoom, zoom_high) auto_exposure("samcam") for i in scanpoints: - umv(dev.hfm_lat, i) - umv(dev.hfm_pitch, pitch) + umv(dev.dcm_fpitch, i) time.sleep(0.2) - high_y = dev.samcam_x.read()["samcam_x"]["value"] - high_x = dev.hfm_lat.read()["hfm_lat"]["value"] + for _ in range(5): + reading = dev.samcam_x.read()["samcam_x"]["value"] + av_high.append(reading) + high_y = np.mean(av_high) + high_x = dev.dcm_fpitch.read()["dcm_fpitch"]["value"] print(f"Xpos at zoom {zoom_high} is {high_y}") highs.append(high_y) - high_lat.append(high_x) + high_fpitch.append(high_x) umv(dev.scam_zoom, zoom_low) auto_exposure("samcam") for i in scanpoints: - umv(dev.hfm_lat, i) - umv(dev.hfm_pitch, pitch) + umv(dev.dcm_fpitch, i) time.sleep(0.2) - low_y = dev.samcam_x.read()["samcam_x"]["value"] - low_x = dev.hfm_lat.read()["hfm_lat"]["value"] + for i in range(5): + reading = dev.samcam_x.read()["samcam_x"]["value"] + av_low.append(reading) + low_y = np.mean(av_low) + low_x = dev.dcm_fpitch.read()["dcm_fpitch"]["value"] print(f"Xpos at zoom {zoom_low} is {low_y}") lows.append(low_y) - low_lat.append(low_x) + low_fpitch.append(low_x) - umv(dev.hfm_lat, lat) - umv(dev.hfm_pitch, 2.9844) + umv(dev.dcm_fpitch, 5) # Convert to numpy arrays - x_high = np.array(high_lat) - x_low = np.array(low_lat) + x_high = np.array(high_fpitch) + x_low = np.array(low_fpitch) y_high = np.array(highs) y_low = np.array(lows) @@ -375,7 +381,7 @@ def cal_samcam_fixed_x(): y_intersect = m_high * x_intersect + b_high print(f"\nIntersection at:") - print(f" HFM_lat = {x_intersect:.5f}") + print(f" dcm_fpitch = {x_intersect:.5f}") print(f" SamCam_x = {y_intersect:.2f}") # --- Plot --- @@ -389,7 +395,7 @@ def cal_samcam_fixed_x(): plt.scatter(x_intersect, y_intersect, color="green", s=80, zorder=5, label="Intersection") - plt.xlabel("HFM Lat Position") + plt.xlabel("DCM Fine Pitch Position") plt.ylabel("SamCam X") plt.title("Zoom Calibration") plt.legend() @@ -398,79 +404,79 @@ def cal_samcam_fixed_x(): plt.show() -# def cal_samcam_fixed_y(): -# vert = dev.vfm_vert.read()["vfm_vert"]["value"] -# pitch = dev.vfm_pitch.read()["vfm_pitch"]["value"] -# scanpoints = np.linspace(vert - 0.1, vert + 0.1, 7) -# zoom_high = 800 -# zoom_low = 200 -# highs, lows = [], [] -# high_vert, low_vert = [], [] +def cal_samcam_fixed_y(): + vert = dev.vfm_y.read()["vfm_y"]["value"] + pitch = dev.vfm_pitch.read()["vfm_pitch"]["value"] + scanpoints = np.linspace(vert - 0.1, vert + 0.1, 7) + zoom_high = 800 + zoom_low = 200 + highs, lows = [], [] + high_vert, low_vert = [], [] -# # high zoom -# umv(dev.scam_zoom, zoom_high) -# auto_exposure("samcam") -# for i in scanpoints: -# umv(dev.vfm_vert, i) -# umv(dev.vfm_pitch, pitch) -# time.sleep(0.2) -# high_y = dev.samcam_y.read()["samcam_y"]["value"] -# high_x = dev.vfm_vert.read()["vfm_vert"]["value"] -# print(f"Ypos at zoom {zoom_high} is {high_y}") -# highs.append(high_y) -# high_vert.append(high_x) + # high zoom + umv(dev.scam_zoom, zoom_high) + auto_exposure("samcam") + for i in scanpoints: + umv(dev.vfm_y, i) + umv(dev.vfm_pitch, pitch) + time.sleep(0.2) + high_y = dev.samcam_y.read()["samcam_y"]["value"] + high_x = dev.vfm_y.read()["vfm_y"]["value"] + print(f"Ypos at zoom {zoom_high} is {high_y}") + highs.append(high_y) + high_vert.append(high_x) -# umv(dev.scam_zoom, zoom_low) -# auto_exposure("samcam") -# for i in scanpoints: -# umv(dev.vfm_vert, i) -# umv(dev.vfm_pitch, pitch) -# time.sleep(0.2) -# low_y = dev.samcam_y.read()["samcam_y"]["value"] -# low_x = dev.vfm_vert.read()["vfm_vert"]["value"] -# print(f"Ypos at zoom {zoom_low} is {low_y}") -# lows.append(low_y) -# low_vert.append(low_x) + umv(dev.scam_zoom, zoom_low) + auto_exposure("samcam") + for i in scanpoints: + umv(dev.vfm_y, i) + umv(dev.vfm_pitch, pitch) + time.sleep(0.2) + low_y = dev.samcam_y.read()["samcam_y"]["value"] + low_x = dev.vfm_y.read()["vfm_y"]["value"] + print(f"Ypos at zoom {zoom_low} is {low_y}") + lows.append(low_y) + low_vert.append(low_x) -# umv(dev.vfm_vert, vert) -# umv(dev.vfm_pitch, pitch) + umv(dev.vfm_y, vert) + umv(dev.vfm_pitch, pitch) -# # Convert to numpy arrays -# x_high = np.array(high_vert) -# x_low = np.array(low_vert) -# y_high = np.array(highs) -# y_low = np.array(lows) + # Convert to numpy arrays + x_high = np.array(high_vert) + x_low = np.array(low_vert) + y_high = np.array(highs) + y_low = np.array(lows) -# # Fit linear models: y = m*x + b -# m_high, b_high = np.polyfit(x_high, y_high, 1) -# m_low, b_low = np.polyfit(x_low, y_low, 1) + # Fit linear models: y = m*x + b + m_high, b_high = np.polyfit(x_high, y_high, 1) + m_low, b_low = np.polyfit(x_low, y_low, 1) -# # Intersection point -# x_intersect = (b_low - b_high) / (m_high - m_low) -# y_intersect = m_high * x_intersect + b_high + # Intersection point + x_intersect = (b_low - b_high) / (m_high - m_low) + y_intersect = m_high * x_intersect + b_high -# print(f"\nIntersection at:") -# print(f" VFM_vert = {x_intersect:.5f}") -# print(f" SamCam_y = {y_intersect:.2f}") + print(f"\nIntersection at:") + print(f" vfm_y = {x_intersect:.5f}") + print(f" SamCam_y = {y_intersect:.2f}") -# # --- Plot --- -# plt.figure(figsize=(7, 5)) -# plt.scatter(x_high, y_high, color="red", label=f"Zoom = {zoom_high} data") -# plt.scatter(x_low, y_low, color="blue", label=f"Zoom = {zoom_low} data") + # --- Plot --- + plt.figure(figsize=(7, 5)) + plt.scatter(x_high, y_high, color="red", label=f"Zoom = {zoom_high} data") + plt.scatter(x_low, y_low, color="blue", label=f"Zoom = {zoom_low} data") -# x_fit = np.linspace(min(x_high), max(x_high), 100) -# plt.plot(x_fit, m_high * x_fit + b_high, "r--", label=f"Fit: Zoom {zoom_high}") -# plt.plot(x_fit, m_low * x_fit + b_low, "b--", label=f"Fit: Zoom {zoom_low}") + x_fit = np.linspace(min(x_high), max(x_high), 100) + plt.plot(x_fit, m_high * x_fit + b_high, "r--", label=f"Fit: Zoom {zoom_high}") + plt.plot(x_fit, m_low * x_fit + b_low, "b--", label=f"Fit: Zoom {zoom_low}") -# plt.scatter(x_intersect, y_intersect, color="green", s=80, zorder=5, label="Intersection") + plt.scatter(x_intersect, y_intersect, color="green", s=80, zorder=5, label="Intersection") -# plt.xlabel("VFM Vert Position") -# plt.ylabel("SamCam Y") -# plt.title("Zoom Calibration") -# plt.legend() -# plt.grid(True) -# plt.tight_layout() -# plt.show() + plt.xlabel("VFM Vert Position") + plt.ylabel("SamCam Y") + plt.title("Zoom Calibration") + plt.legend() + plt.grid(True) + plt.tight_layout() + plt.show() def correlate_froll(): @@ -551,15 +557,15 @@ def correlate_fpitch(): plt.show() -def correlate_hfm_lat(): +def correlate_hfm_x(): x_correlation = [] - lat = dev.hfm_lat.read()["hfm_lat"]["value"] + lat = dev.hfm_x.read()["hfm_x"]["value"] scanpoints = np.linspace(lat - 0.1, lat + 0.1, 10) for pos in scanpoints: - umv(dev.hfm_lat, pos) + umv(dev.hfm_x, pos) xpos, ypos = compute_pos() x_correlation.append(xpos) - umv(dev.hfm_lat, lat) + umv(dev.hfm_x, lat) x = np.array(scanpoints) y1 = np.array(x_correlation) @@ -584,15 +590,15 @@ def correlate_hfm_lat(): plt.show() -# def correlate_vfm_vert(): +# def correlate_vfm_y(): # y_correlation = [] -# vert = dev.vfm_vert.read()["vfm_vert"]["value"] +# vert = dev.vfm_y.read()["vfm_y"]["value"] # scanpoints = np.linspace(vert - 0.06, vert + 0.06, 10) # for pos in scanpoints: -# umv(dev.vfm_vert, pos) +# umv(dev.vfm_y, pos) # xpos, ypos = compute_pos() # y_correlation.append(ypos) -# umv(dev.vfm_vert, vert) +# umv(dev.vfm_y, vert) # x = np.array(scanpoints) # y1 = np.array(y_correlation) @@ -659,12 +665,12 @@ def move_to_x(targetx=0.13): xpos, ypos = compute_pos() beam_drift = xpos - targetx # beam moved +0.1 mm (100 µm) - mot_current = dev.hfm_lat.read()["hfm_lat"]["value"] # current motor position (example) + mot_current = dev.hfm_x.read()["hfm_x"]["value"] # current motor position (example) # Compute correction delta = -beam_drift / slope mot_new = mot_current + delta - umv(dev.hfm_lat, mot_new) + umv(dev.hfm_x, mot_new) # def move_to_y(targety=-0.033): @@ -676,12 +682,12 @@ def move_to_x(targetx=0.13): # xpos, ypos = compute_pos() # beam_drift = ypos - targety # beam moved +0.1 mm (100 µm) -# mot_current = dev.vfm_vert.read()["vfm_vert"]["value"] # current motor position (example) +# mot_current = dev.vfm_y.read()["vfm_y"]["value"] # current motor position (example) # # Compute correction # delta = -beam_drift / slope # mot_new = mot_current + delta -# umv(dev.vfm_vert, mot_new) +# umv(dev.vfm_y, mot_new) from epics import caget, caput @@ -767,8 +773,8 @@ def auto_exposure( # bd = dev.vfm_bd # step = 0.05 # beamsize("xs") -# move_targetx_with_hfm_lat() -# move_targety_with_vfm_vert() +# move_targetx_with_hfm_x() +# move_targety_with_vfm_y() # with open(filename, "w") as f: # for _ in range(4): # curr_bu = bu.user_readback.get() @@ -776,8 +782,8 @@ def auto_exposure( # auto_exposure() # umv(bu, curr_bu + step) # umv(bd, curr_bd + step) -# move_targetx_with_hfm_lat() -# move_targety_with_vfm_vert() +# move_targetx_with_hfm_x() +# move_targety_with_vfm_y() # xpos = dev.samcam_x.read()["samcam_x"]["value"] # ypos = dev.samcam_y.read()["samcam_y"]["value"] # xsig = dev.samcam_xsig.read()["samcam_xsig"]["value"] @@ -788,11 +794,11 @@ def auto_exposure( def filters(pos="out"): if pos == "out": - umv(dev.bsc_f1_x, 2.0, dev.bsc_f2_x, 2.0, dev.bsc_f3_x, 12.0, dev.bsc_f4_x, 8.0) + umv(dev.ss_f1_x, 2.0, dev.ss_f2_x, 2.0, dev.ss_f3_x, 12.0, dev.ss_f4_x, 8.0) if SE.scin.checkpos(): auto_exposure(cam="samcam", max_iter=20) else: - umv(dev.bsc_f1_x, 2.0, dev.bsc_f2_x, 2.0, dev.bsc_f3_x, 8.0, dev.bsc_f4_x, 8.0) + umv(dev.ss_f1_x, 2.0, dev.ss_f2_x, 2.0, dev.ss_f3_x, 8.0, dev.ss_f4_x, 8.0) if SE.scin.checkpos(): auto_exposure(cam="samcam", max_iter=20) @@ -850,18 +856,18 @@ def scan_in_y(ysize, ycen, mon, small, large, width, steps): def trans_fils(inc): - x1 = dev.bsc_f1_x.read()["bsc_f1_x"]["value"] - x2 = dev.bsc_f2_x.read()["bsc_f2_x"]["value"] - x3 = dev.bsc_f3_x.read()["bsc_f3_x"]["value"] - x4 = dev.bsc_f4_x.read()["bsc_f4_x"]["value"] + x1 = dev.ss_f1_x.read()["ss_f1_x"]["value"] + x2 = dev.ss_f2_x.read()["ss_f2_x"]["value"] + x3 = dev.ss_f3_x.read()["ss_f3_x"]["value"] + x4 = dev.ss_f4_x.read()["ss_f4_x"]["value"] umv( - dev.bsc_f1_x, + dev.ss_f1_x, x1 + inc, - dev.bsc_f2_x, + dev.ss_f2_x, x2 + inc, - dev.bsc_f3_x, + dev.ss_f3_x, x3 + inc, - dev.bsc_f4_x, + dev.ss_f4_x, x4 + inc, ) @@ -1491,7 +1497,7 @@ from epics import caget def scan_scin_focus(): z0 = dev.diag_z.position - z_positions = np.linspace(-4,4,30) + z_positions = np.linspace(-9,9,30) contrasts = [] diff --git a/pxii_bec/macros/pxii_parameters.py b/pxii_bec/macros/pxii_parameters.py index e0a54df..c21b95b 100755 --- a/pxii_bec/macros/pxii_parameters.py +++ b/pxii_bec/macros/pxii_parameters.py @@ -153,7 +153,7 @@ class BPMScans: "x_device": dev.lu_bpm_x, "y_device": dev.lu_bpm_y, } - bsc = { + ss = { "x_name": dev.ss_bpm_x.name, "y_name": dev.ss_bpm_y.name, "z1_name": dev.ss_bpm1.name, diff --git a/pxii_bec/macros/set_kbox.sh b/pxii_bec/macros/set_kbox.sh index fa30fd9..c071ac1 100755 --- a/pxii_bec/macros/set_kbox.sh +++ b/pxii_bec/macros/set_kbox.sh @@ -13,7 +13,7 @@ usage() { echo "Usage: $(basename "$0") " echo echo "Example:" - echo " $(basename "$0") colli_in 41.5" + echo " $(basename "$0") colli_in 39.5" echo " $(basename "$0") colli_out 20." echo " $(basename "$0") scinti_in 40." echo " $(basename "$0") diode_in 44." @@ -33,7 +33,7 @@ fi DEVICE_NAME="$1" SET_VALUE="$2" -if ! [[ "$SET_VALUE" =~ ^[0-9]+$ ]]; then +if ! [[ "$SET_VALUE" =~ ^[0-9]+([.][0-9]+)?$ ]]; then echo "Error: set_value must be numeric" exit 1 fi -- 2.54.0 From 710e61f5db59f7b704d639703aa9befe84e3680a Mon Sep 17 00:00:00 2001 From: x10sa Date: Fri, 10 Jul 2026 15:05:21 +0200 Subject: [PATCH 8/9] friday updates --- .../device_configs/pxii-beamline-states.yaml | 2 - pxii_bec/device_configs/pxii-devices.yaml | 12 +- pxii_bec/macros/APscripts.py | 2 +- pxii_bec/macros/calibrate_bpm.py | 157 ++++++++++++------ pxii_bec/macros/katscripts.py | 29 +++- 5 files changed, 137 insertions(+), 65 deletions(-) diff --git a/pxii_bec/device_configs/pxii-beamline-states.yaml b/pxii_bec/device_configs/pxii-beamline-states.yaml index 70c5c96..4ff9e35 100644 --- a/pxii_bec/device_configs/pxii-beamline-states.yaml +++ b/pxii_bec/device_configs/pxii-beamline-states.yaml @@ -54,8 +54,6 @@ states: diag_y: out fl_bright: 'on' aerotech_x: in - aerotech_y: work - aerotech_z: work # aerotech_u: mount # smargon_x: mount # smargon_y: mount diff --git a/pxii_bec/device_configs/pxii-devices.yaml b/pxii_bec/device_configs/pxii-devices.yaml index 20237d9..48d4d9b 100644 --- a/pxii_bec/device_configs/pxii-devices.yaml +++ b/pxii_bec/device_configs/pxii-devices.yaml @@ -70,7 +70,7 @@ aerotech: safe: -50 y: mount: -0.0 - work: -0.022 + work: -0.016 z: mount: 0 work: 0 @@ -303,7 +303,7 @@ bs_y: onFailure: buffer readoutPriority: baseline userParameter: - in: -2.654 + in: -2.454 bs_z: description: Beamstop Z deviceClass: ophyd_devices.EpicsMotor @@ -433,7 +433,7 @@ coll_x: onFailure: buffer readoutPriority: baseline userParameter: - in: -2.72 + in: -2.889 coll_y: description: Collimator Y deviceClass: ophyd_devices.EpicsMotor @@ -445,7 +445,7 @@ coll_y: onFailure: buffer readoutPriority: baseline userParameter: - in: 39.188 + in: 39.139 intermediate: 32 out: 20.002 park: 1 @@ -630,10 +630,10 @@ diag_y: onFailure: buffer readoutPriority: baseline userParameter: - i1: 41 + i1: 40.8 out: 20.0 park: 1 - scint: 36.004 + scint: 35.74 tol: 0.3 type: continuous diag_z: diff --git a/pxii_bec/macros/APscripts.py b/pxii_bec/macros/APscripts.py index b596c46..f1387ab 100644 --- a/pxii_bec/macros/APscripts.py +++ b/pxii_bec/macros/APscripts.py @@ -1658,7 +1658,7 @@ def fluxcal(start_en=13, stop_en=14, step =1): filename = dirname + f"FLUX_x10sa_{timestamp}.txt" with open(filename, "w") as f: - np.savetxt(f, combined, delimiter=",", fmt="%9f") + np.savetxt(f, combined, delimiter=",", fmt=".9f") elapsed_time = time.perf_counter()-tstart diff --git a/pxii_bec/macros/calibrate_bpm.py b/pxii_bec/macros/calibrate_bpm.py index 12484d5..e25b0db 100644 --- a/pxii_bec/macros/calibrate_bpm.py +++ b/pxii_bec/macros/calibrate_bpm.py @@ -46,11 +46,6 @@ def read_currents(): bpm3 = np.mean(vals_bpm3) bpm4 = np.mean(vals_bpm4) - # bpm1 = dev.bcu_bpm1.read()["bcu_bpm1"]["value"] - # bpm2 = dev.bcu_bpm2.read()["bcu_bpm2"]["value"] - # bpm3 = dev.bcu_bpm3.read()["bcu_bpm3"]["value"] - # bpm4 = dev.bcu_bpm4.read()["bcu_bpm4"]["value"] - # print(f"bpm1 = {bpm1:.3f}, bpm2 = {bpm2:.3f}, bpm3 = {bpm3:.3f}, bpm4 = {bpm4:.3f}") return {"bpm1": bpm1, "bpm2": bpm2, "bpm3": bpm3, "bpm4": bpm4} @@ -138,21 +133,6 @@ def run_calibration(): umv(dev.ss_sl_ysize, 3.0) -# Read data from BPM calibration files -# def fit_bpm_data(x_y): -# """ -# Read data from bpm calibration files. -# """ -# filedir = "luts/bpm_calib/" -# rundate= "02072130_" -# name = f"bcu_bpm_{x_y}.csv" -# filename = filedir + rundate + name -# data = np.loadtxt(filename, delimiter=",", skiprows=1) -# xdata = data[:, 0] -# ydata = data[:, 1] -# return xdata, ydata - - def fit_bpm_data(x_y, rundate="02072130_", bpm_name="bcu_bpm"): CALIB_DIR = "luts/bpm_calib/" @@ -193,9 +173,9 @@ def linear_calibration( x_fit = np.linspace(min(xdata), max(xdata), 100) plt.plot(x_fit, m * x_fit + c, "r--", label=f"Fit: Linear") - plt.xlabel("HFM Lat Position") - plt.ylabel("SamCam X") - plt.title("Zoom Calibration") + plt.xlabel("label") + plt.ylabel("label") + plt.title("title") plt.legend() plt.grid(True) plt.tight_layout() @@ -477,8 +457,6 @@ def calibrate_bpm_flux(ave = 5): f.write("Energy,Transmission,BPMSum,Flux\n") print("Energy,Transmission,BPMSum,Flux\n") energies = [12400,7000,8000,9000,10000,11000,13000,14000,15000,16000,18000,20000,25000] - # energies = [7000,8000,9000,10000] - # transmissions = [1, 0.5, 0.2, 0.1, 0.05, 0.01] transmissions = [1, 0.9, 0.8, 0.7, 0.6, 0.5,0.4,0.3,0.2,0.1] for energy in energies: @@ -513,7 +491,7 @@ def calibrate_bpm_flux(ave = 5): umv(dev.id_gap, 20) def analyse_bpm_flux_calibration( - filename="luts/bpm_calib/bpm_flux_comb.csv", + filename="luts/bpm_calib/bpm_flux_20260708b.csv", force_zero_intercept=False, ): data = pd.read_csv(filename) @@ -576,44 +554,117 @@ def analyse_bpm_flux_calibration( print(dict) return results -def get_flux_calibration(energy): - filename = "luts/bpm_calib/bpm_flux_fits_zero.csv" - default_slope = 4.42e8 - default_intercept = -1.66e11 +def linear_bpm_flux_calib(): + filename = 'luts/bpm_calib/fits-25.csv' + df = pd.read_csv(filename) + energies = df["Energy"].to_numpy() + intercepts = df["Intercept"].to_numpy() + slopes = df["Slope"].to_numpy() + # --- Plot --- + plt.figure(figsize=(7, 5)) + plt.scatter(energies, slopes, color="red") - try: - df = pd.read_csv(filename) - energies = df["Energy"].to_numpy() - intercepts = df["Intercept"].to_numpy() - slopes = df["Slope"].to_numpy() - slope_interp = CubicSpline(energies, slopes) - intercept_interp = CubicSpline(energies, intercepts) - slope = slope_interp(energy) - intercept = intercept_interp(energy) - print(f"Using data from calibration file") - except FileNotFoundError: - print("Cannot access calibration file, using default parameters") - slope = default_slope - intercept = default_intercept + x_fit = np.linspace(min(energies), max(energies), 100) + coeffs = np.polyfit(energies, slopes,1) + y_fit = np.poly1d(coeffs) + plt.plot(x_fit, y_fit(x_fit)), + plt.xlabel("Energy eV") + plt.ylabel("Slope") + plt.title(f"Energies vs slopes, coeffs = {coeffs}") + # plt.legend() + plt.grid(True) + plt.tight_layout() + plt.savefig(f"luts/bpm_calib/slopes_vs_energy") + plt.show() + return coeffs + + +# def get_flux_calibration(energy): +# # filename = "luts/bpm_calib/bpm_flux_fits.csv" +# filename = 'luts/bpm_calib/fits-25.csv' +# default_slope = 4.42e8 +# default_intercept = -1.66e11 + +# try: +# df = pd.read_csv(filename) +# energies = df["Energy"].to_numpy() +# intercepts = df["Intercept"].to_numpy() +# slopes = df["Slope"].to_numpy() +# slope_interp = CubicSpline(energies, slopes) +# intercept_interp = CubicSpline(energies, intercepts) +# slope = slope_interp(energy) +# intercept = intercept_interp(energy) +# print(f"Using data from calibration file") +# # --- Plot --- +# plt.figure(figsize=(7, 5)) +# plt.scatter(energies, slopes, color="red") + +# x_fit = np.linspace(min(energies), max(energies), 100) +# coeffs = np.polyfit(energies, slopes,1) +# print("linear co-efficients: ", coeffs) +# y_fit = np.poly1d(coeffs) +# plt.plot(x_fit, y_fit(x_fit)), +# # "r--", label=f"Fit: Slope = {slope:.5g}, Intercept = {intercept:.5g}") + +# plt.xlabel("Energy") +# plt.ylabel("Slope") +# plt.title(f"{energy} eV") +# # plt.legend() +# plt.grid(True) +# plt.tight_layout() +# plt.show() +# except FileNotFoundError: +# print("Cannot access calibration file, using default parameters") +# slope = default_slope +# intercept = default_intercept - return slope, intercept +# return coeffs + + +def bpm2flux(energy=None, bpmsum=None, transm=None): + """ + Calculate the flux from BCU BPM reading. + Option to provide energy, bpmsum reading and transmission. + If these are not given, the current values are used. + + Returns the flux at the sample (after attenuators) and a calculated + value of the full flux if attenuation was 0. + + """ + calibration_min_energy = 6500 + calibration_max_energy = 21000 -def bpm2flux(energy=None,bpmsum=None): if energy is None: energy = get_current_energy() + if bpmsum is None: - bpmsum = dev.bcu_bpmsum.read()['bcu_bpmsum']['value'] + bpmsum = dev.bcu_bpmsum.read()["bcu_bpmsum"]["value"] - print(f"BCU_bpmsum = {bpmsum}") + if transm is None: + transm = dev.transm.read()['transm']['value'] - slope, intercept = get_flux_calibration(energy) + if not calibration_min_energy <= energy <= calibration_max_energy: + raise ValueError( + f"Energy {energy:.0f} eV is outside the calibrated range " + f"{calibration_min_energy:.0f}–" + f"{calibration_max_energy:.0f} eV" + ) - calc = slope * bpmsum + intercept - flux = f"{calc:.5g}" - print(flux) - return float(calc) + coeffs = [ + 1.06436277e5, + -6.38943746e8, + ] + calibration_factor = np.polyval(coeffs, energy) + flux = calibration_factor * bpmsum + full_flux = flux/transm + if transm == 1: + print(f"Transmission = {transm*100:.5g} %, Flux = {flux: .3g} ph/s,\n") + else: + print(f"Transmission = {transm*100: .5g} %, Flux = {flux: .3g} ph/s,\n" + f"Flux with 100 % transmission would be {full_flux: .3g} ph/s") + return float(flux), float(full_flux) diff --git a/pxii_bec/macros/katscripts.py b/pxii_bec/macros/katscripts.py index 2838e09..b456dd3 100755 --- a/pxii_bec/macros/katscripts.py +++ b/pxii_bec/macros/katscripts.py @@ -1494,12 +1494,35 @@ import matplotlib.pyplot as plt from epics import caget -def scan_scin_focus(): +def scan_scin_focus(type = 'fine'): z0 = dev.diag_z.position - z_positions = np.linspace(-9,9,30) - contrasts = [] + if z0-5 <= -10: + min = -9.5 + else: + min = z0-5 + + if z0+5 >=10: + max = 9.5 + else: + max = z0+5 + if type == 'fine': + steps = 100 + elif type == 'coarse': + steps = 30 + else: + steps = 60 + umv(dev.scam_zoom, 1000) + dev.transm.put(0.1) + + auto_exposure("samcam", target=200, max_iter=20) + time.sleep(0.2) + + z_positions = np.linspace(min,max,steps) + + + contrasts = [] for z in z_positions: -- 2.54.0 From 85f792ebf592e63901c9b85252d09e0d50d377bc Mon Sep 17 00:00:00 2001 From: x10sa Date: Mon, 27 Jul 2026 17:05:53 +0200 Subject: [PATCH 9/9] Changes at beamline as of 260727 --- .../device_configs/pxii-beamline-states.yaml | 20 +- pxii_bec/device_configs/pxii-devices.yaml | 35 +- .../device_configs/pxii-devices.yaml.broken | 1893 +++++++++++++++++ pxii_bec/device_configs/pxii-devices.yaml.old | 1875 ++++++++++++++++ pxii_bec/devices/contrast.py | 75 + pxii_bec/devices/optics_shutter.py | 107 + pxii_bec/macros/.nfs000000000001101900000001 | Bin 0 -> 12288 bytes pxii_bec/macros/APscripts.py | 59 +- pxii_bec/macros/EvalFlux.py | 69 + pxii_bec/macros/beampos_with_en.py | 19 + pxii_bec/macros/beampos_with_en.py~ | 9 + pxii_bec/macros/calibrate_bpm.py | 530 +---- pxii_bec/macros/calibrate_bpm.py.bak | 670 ++++++ pxii_bec/macros/enScan.py | 83 + pxii_bec/macros/katscripts.py | 89 +- pxii_bec/macros/knifehist.py | 79 + .../macros/luts/20260704-1508_ge_edge.csv | 6 + .../macros/luts/20260704-1509_ge_edge.csv | 301 +++ .../macros/luts/20260704-1520_ge_edge.csv | 301 +++ .../macros/luts/20260704-1531_ge_edge.csv | 301 +++ pxii_bec/macros/luts/I1flcalf.csv | 22 + .../luts/beampos/beam_pos_record_0107.csv | 10 + .../luts/beampos/beam_pos_record_0207.csv | 12 + .../luts/beampos/beam_pos_record_02072247.csv | 2 + .../luts/beampos/beam_pos_record_02072249.csv | 2 + .../luts/beampos/beam_pos_record_0307.csv | 38 + .../luts/beampos/beam_pos_record_05072309.csv | 3 + .../luts/beampos/beam_pos_record_05072312.csv | 54 + .../luts/beampos/beam_pos_record_10072258.csv | 3 + .../luts/beampos/beam_pos_record_10072259.csv | 65 + .../luts/beampos/beam_pos_record_11072251.csv | 66 + .../beampos/beampos17_18Jul12p4_16_12p4.csv | 214 ++ pxii_bec/macros/luts/beampos/beampos_0207.csv | 57 + .../macros/luts/beampos/beampos_17071707.csv | 71 + .../macros/luts/beampos/beampos_17072256.csv | 74 + .../macros/luts/beampos/beampos_18070501.csv | 73 + .../macros/luts/beampos/beampos_18071135.csv | 78 + .../macros/luts/beampos/beampos_18071800.csv | 73 + .../macros/luts/beampos/beampos_19070000.csv | 73 + .../macros/luts/beampos/beampos_19070559.csv | 73 + .../macros/luts/beampos/beampos_19071158.csv | 73 + .../macros/luts/beampos/beampos_19071756.csv | 41 + .../macros/luts/beampos/beampos_19072236.csv | 14 + .../macros/luts/beampos/beampos_19072303.csv | 29 + .../macros/luts/beampos/beampos_20070000.csv | 31 + .../macros/luts/beampos/beampos_20070100.csv | 31 + .../macros/luts/beampos/beampos_20070200.csv | 30 + .../macros/luts/beampos/beampos_20070258.csv | 31 + .../macros/luts/beampos/beampos_20070359.csv | 31 + .../macros/luts/beampos/beampos_20070459.csv | 31 + .../macros/luts/beampos/beampos_20070559.csv | 31 + ...ampos_20260718-19_10-7-9-12p67-15-12p4.csv | 365 ++++ .../beampos_20260719_20_12p4_6to18.csv | 243 +++ .../macros/luts/beampos/beampos_3rdJul.csv | 50 + .../macros/luts/bpm_calib/10000_bpm_flux.png | Bin 0 -> 28879 bytes .../macros/luts/bpm_calib/11000_bpm_flux.png | Bin 0 -> 27618 bytes .../macros/luts/bpm_calib/12400_bpm_flux.png | Bin 0 -> 26355 bytes .../macros/luts/bpm_calib/13000_bpm_flux.png | Bin 0 -> 28127 bytes .../macros/luts/bpm_calib/14000_bpm_flux.png | Bin 0 -> 25792 bytes .../macros/luts/bpm_calib/15000_bpm_flux.png | Bin 0 -> 31322 bytes .../macros/luts/bpm_calib/16000_bpm_flux.png | Bin 0 -> 27908 bytes .../macros/luts/bpm_calib/18000_bpm_flux.png | Bin 0 -> 31526 bytes .../macros/luts/bpm_calib/20000_bpm_flux.png | Bin 0 -> 28372 bytes .../macros/luts/bpm_calib/25000_bpm_flux.png | Bin 0 -> 24825 bytes .../macros/luts/bpm_calib/26000_bpm_flux.png | Bin 0 -> 29889 bytes .../macros/luts/bpm_calib/7000_bpm_flux.png | Bin 0 -> 27658 bytes .../macros/luts/bpm_calib/8000_bpm_flux.png | Bin 0 -> 30207 bytes .../macros/luts/bpm_calib/9000_bpm_flux.png | Bin 0 -> 27562 bytes .../luts/bpm_calib/bpm_flux_20260708b.csv | 131 ++ .../macros/luts/bpm_calib/bpm_flux_fits.csv | 13 + pxii_bec/macros/luts/bpm_calib/fits-25.csv | 13 + .../luts/bpm_calib/slopes_vs_energy.png | Bin 0 -> 32884 bytes pxii_bec/macros/luts/x1_data | 441 ++++ pxii_bec/macros/luts/x2_data | 441 ++++ pxii_bec/macros/luts/y1_data | 441 ++++ pxii_bec/macros/luts/y2_data | 441 ++++ pxii_bec/macros/mx_basics.bak | 313 +++ pxii_bec/macros/mx_basics.py | 110 +- pxii_bec/macros/mx_methods.py | 22 +- pxii_bec/macros/pxii_energy.py | 2 + 80 files changed, 10310 insertions(+), 673 deletions(-) create mode 100644 pxii_bec/device_configs/pxii-devices.yaml.broken create mode 100644 pxii_bec/device_configs/pxii-devices.yaml.old create mode 100644 pxii_bec/devices/contrast.py create mode 100644 pxii_bec/devices/optics_shutter.py create mode 100644 pxii_bec/macros/.nfs000000000001101900000001 create mode 100644 pxii_bec/macros/EvalFlux.py create mode 100644 pxii_bec/macros/beampos_with_en.py create mode 100644 pxii_bec/macros/beampos_with_en.py~ create mode 100644 pxii_bec/macros/calibrate_bpm.py.bak create mode 100644 pxii_bec/macros/enScan.py create mode 100644 pxii_bec/macros/knifehist.py create mode 100644 pxii_bec/macros/luts/20260704-1508_ge_edge.csv create mode 100644 pxii_bec/macros/luts/20260704-1509_ge_edge.csv create mode 100644 pxii_bec/macros/luts/20260704-1520_ge_edge.csv create mode 100644 pxii_bec/macros/luts/20260704-1531_ge_edge.csv create mode 100644 pxii_bec/macros/luts/I1flcalf.csv create mode 100644 pxii_bec/macros/luts/beampos/beam_pos_record_0107.csv create mode 100644 pxii_bec/macros/luts/beampos/beam_pos_record_0207.csv create mode 100644 pxii_bec/macros/luts/beampos/beam_pos_record_02072247.csv create mode 100644 pxii_bec/macros/luts/beampos/beam_pos_record_02072249.csv create mode 100644 pxii_bec/macros/luts/beampos/beam_pos_record_0307.csv create mode 100644 pxii_bec/macros/luts/beampos/beam_pos_record_05072309.csv create mode 100644 pxii_bec/macros/luts/beampos/beam_pos_record_05072312.csv create mode 100644 pxii_bec/macros/luts/beampos/beam_pos_record_10072258.csv create mode 100644 pxii_bec/macros/luts/beampos/beam_pos_record_10072259.csv create mode 100644 pxii_bec/macros/luts/beampos/beam_pos_record_11072251.csv create mode 100644 pxii_bec/macros/luts/beampos/beampos17_18Jul12p4_16_12p4.csv create mode 100644 pxii_bec/macros/luts/beampos/beampos_0207.csv create mode 100644 pxii_bec/macros/luts/beampos/beampos_17071707.csv create mode 100644 pxii_bec/macros/luts/beampos/beampos_17072256.csv create mode 100644 pxii_bec/macros/luts/beampos/beampos_18070501.csv create mode 100644 pxii_bec/macros/luts/beampos/beampos_18071135.csv create mode 100644 pxii_bec/macros/luts/beampos/beampos_18071800.csv create mode 100644 pxii_bec/macros/luts/beampos/beampos_19070000.csv create mode 100644 pxii_bec/macros/luts/beampos/beampos_19070559.csv create mode 100644 pxii_bec/macros/luts/beampos/beampos_19071158.csv create mode 100644 pxii_bec/macros/luts/beampos/beampos_19071756.csv create mode 100644 pxii_bec/macros/luts/beampos/beampos_19072236.csv create mode 100644 pxii_bec/macros/luts/beampos/beampos_19072303.csv create mode 100644 pxii_bec/macros/luts/beampos/beampos_20070000.csv create mode 100644 pxii_bec/macros/luts/beampos/beampos_20070100.csv create mode 100644 pxii_bec/macros/luts/beampos/beampos_20070200.csv create mode 100644 pxii_bec/macros/luts/beampos/beampos_20070258.csv create mode 100644 pxii_bec/macros/luts/beampos/beampos_20070359.csv create mode 100644 pxii_bec/macros/luts/beampos/beampos_20070459.csv create mode 100644 pxii_bec/macros/luts/beampos/beampos_20070559.csv create mode 100644 pxii_bec/macros/luts/beampos/beampos_20260718-19_10-7-9-12p67-15-12p4.csv create mode 100644 pxii_bec/macros/luts/beampos/beampos_20260719_20_12p4_6to18.csv create mode 100644 pxii_bec/macros/luts/beampos/beampos_3rdJul.csv create mode 100644 pxii_bec/macros/luts/bpm_calib/10000_bpm_flux.png create mode 100644 pxii_bec/macros/luts/bpm_calib/11000_bpm_flux.png create mode 100644 pxii_bec/macros/luts/bpm_calib/12400_bpm_flux.png create mode 100644 pxii_bec/macros/luts/bpm_calib/13000_bpm_flux.png create mode 100644 pxii_bec/macros/luts/bpm_calib/14000_bpm_flux.png create mode 100644 pxii_bec/macros/luts/bpm_calib/15000_bpm_flux.png create mode 100644 pxii_bec/macros/luts/bpm_calib/16000_bpm_flux.png create mode 100644 pxii_bec/macros/luts/bpm_calib/18000_bpm_flux.png create mode 100644 pxii_bec/macros/luts/bpm_calib/20000_bpm_flux.png create mode 100644 pxii_bec/macros/luts/bpm_calib/25000_bpm_flux.png create mode 100644 pxii_bec/macros/luts/bpm_calib/26000_bpm_flux.png create mode 100644 pxii_bec/macros/luts/bpm_calib/7000_bpm_flux.png create mode 100644 pxii_bec/macros/luts/bpm_calib/8000_bpm_flux.png create mode 100644 pxii_bec/macros/luts/bpm_calib/9000_bpm_flux.png create mode 100644 pxii_bec/macros/luts/bpm_calib/bpm_flux_20260708b.csv create mode 100644 pxii_bec/macros/luts/bpm_calib/bpm_flux_fits.csv create mode 100644 pxii_bec/macros/luts/bpm_calib/fits-25.csv create mode 100644 pxii_bec/macros/luts/bpm_calib/slopes_vs_energy.png create mode 100644 pxii_bec/macros/luts/x1_data create mode 100644 pxii_bec/macros/luts/x2_data create mode 100644 pxii_bec/macros/luts/y1_data create mode 100644 pxii_bec/macros/luts/y2_data create mode 100755 pxii_bec/macros/mx_basics.bak diff --git a/pxii_bec/device_configs/pxii-beamline-states.yaml b/pxii_bec/device_configs/pxii-beamline-states.yaml index 4ff9e35..1f2e19b 100644 --- a/pxii_bec/device_configs/pxii-beamline-states.yaml +++ b/pxii_bec/device_configs/pxii-beamline-states.yaml @@ -33,8 +33,8 @@ states: diag_y: out fl_bright: 'on' aerotech_x: in - aerotech_y: work - aerotech_z: work + # aerotech_y: work + # aerotech_z: work # aerotech_u: mount # smargon_x: mount # smargon_y: mount @@ -115,9 +115,9 @@ states: diag_y: scint fl_bright: 'off' aerotech_x: out - aerotech_y: mount - aerotech_z: mount - aerotech_u: mount + # aerotech_y: mount + # aerotech_z: mount + # aerotech_u: mount smargon_x: mount smargon_y: mount smargon_chi: mount @@ -135,9 +135,9 @@ states: diag_y: i1 fl_bright: 'off' aerotech_x: out - aerotech_y: mount - aerotech_z: mount - aerotech_u: mount + # aerotech_y: mount + # aerotech_z: mount + # aerotech_u: mount smargon_x: mount smargon_y: mount smargon_chi: mount @@ -155,8 +155,8 @@ states: diag_y: out fl_bright: 'on' aerotech_x: out - aerotech_y: mount - aerotech_z: mount + # aerotech_y: mount + # aerotech_z: mount aerotech_u: mount smargon_x: mount smargon_y: mount diff --git a/pxii_bec/device_configs/pxii-devices.yaml b/pxii_bec/device_configs/pxii-devices.yaml index 48d4d9b..3358c3a 100644 --- a/pxii_bec/device_configs/pxii-devices.yaml +++ b/pxii_bec/device_configs/pxii-devices.yaml @@ -70,10 +70,10 @@ aerotech: safe: -50 y: mount: -0.0 - work: -0.016 + work: -0.031 z: mount: 0 - work: 0 + work: -0.01 bcu_bpm1: description: BCU BPM Channel 1 deviceClass: ophyd.EpicsSignalRO @@ -154,6 +154,17 @@ bcu_bpmsum: onFailure: buffer readOnly: true readoutPriority: monitored +bcu_shutter: + description: Fast Shutter + deviceClass: ophyd_devices.EpicsSignal + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-SHUTTER:SET + deviceTags: + - state + enabled: true + onFailure: buffer + readoutPriority: baseline bcu_sl_xcen: description: BCU Slit X Centre deviceClass: ophyd_devices.EpicsMotor @@ -291,7 +302,7 @@ bs_x: onFailure: buffer readoutPriority: baseline userParameter: - in: 0.4 + in: 0.3 bs_y: description: Beamstop Y deviceClass: ophyd_devices.EpicsMotor @@ -303,7 +314,7 @@ bs_y: onFailure: buffer readoutPriority: baseline userParameter: - in: -2.454 + in: -3.35 bs_z: description: Beamstop Z deviceClass: ophyd_devices.EpicsMotor @@ -433,7 +444,7 @@ coll_x: onFailure: buffer readoutPriority: baseline userParameter: - in: -2.889 + in: -1.275 coll_y: description: Collimator Y deviceClass: ophyd_devices.EpicsMotor @@ -445,7 +456,7 @@ coll_y: onFailure: buffer readoutPriority: baseline userParameter: - in: 39.139 + in: 39.06 intermediate: 32 out: 20.002 park: 1 @@ -630,7 +641,7 @@ diag_y: onFailure: buffer readoutPriority: baseline userParameter: - i1: 40.8 + i1: 40.696 out: 20.0 park: 1 scint: 35.74 @@ -1336,6 +1347,16 @@ samcam_ysig: onFailure: buffer readOnly: true readoutPriority: monitored +scam: + description: Sample camera image contrast + deviceClass: pxii_bec.devices.contrast.CameraContrast + deviceConfig: + prefix: 'X10SA-ES-MS:Stats1:' + deviceTags: + - detector + enabled: true + readOnly: true + readoutPriority: monitored scam_zoom: description: Sample Camera Zoom deviceClass: ophyd_devices.EpicsMotor diff --git a/pxii_bec/device_configs/pxii-devices.yaml.broken b/pxii_bec/device_configs/pxii-devices.yaml.broken new file mode 100644 index 0000000..99d2d16 --- /dev/null +++ b/pxii_bec/device_configs/pxii-devices.yaml.broken @@ -0,0 +1,1893 @@ +# BEC Device Configuration File +# +# The device config consists of a mapping of device names to their configurations. +# +# The following fields are required for each device: +# - deviceClass: The class of the device (e.g., ophyd_devices.SimPositioner). +# - enabled: A boolean indicating if the device is enabled. +# - readoutPriority: Determines how the device is read out during a scan. Possible values are ["monitored", "baseline", "async", "on_request", "continuous"]. +# +# Optional fields (defaults shown): +# - connectionTimeout: Connection timeout in seconds. Default is 5. +# - description: A string description of the device. Default is "" (empty string). +# - deviceConfig: A dictionary of configuration parameters specific to the device class. Default is None. +# - deviceTags: A list/set of tags associated with the device. Default is an empty list/set. +# - needs: A list of other device names that this device depends on. Default is []. +# - onFailure: The action to take on failure. Possible values are ["buffer", "retry", "raise"]. Default is "retry". +# - readOnly: A boolean indicating if the device is read-only. Default is false. +# - softwareTrigger: A boolean indicating if the device uses software triggering. Default is false. +# - userParameter: A dictionary of user-defined parameters. Default is {}. +# +# Default values may be omitted for brevity. +########################################################################################################################## + + +# An example device configuration with all fields: + +# device1: +# deviceClass: ophyd_devices.SimPositioner +# description: Sample positioner device +# deviceConfig: +# delay: 1 +# update_frequency: 10 +# deviceTags: +# - frontend +# - motor +# enabled: true +# connectionTimeout: 20 +# readoutPriority: baseline +# needs: +# - device2 +# - device3 +# onFailure: retry +# readOnly: false +# softwareTrigger: false +# userParameter: +# in: 23.1 +# out: -50 + +########################################################################################################################## +optics_shutter: + description: Optics Shutter + deviceClass: ophyd_devices.optics_shutter.OpticsShutter + deviceConfig: {prefix: 'X10SA-EH1-PSYS:SH-A-'} + enabled: true + onFailure: retry + readoutPriority: baseline + softwareTrigger: false + userParameter: +aerotech: + description: REST-based device which connects to AareScan and Aerotech + deviceClass: pxii_bec.devices.aerotech.Aerotech + deviceConfig: + prefix: http://mx-x10sa-queue-01:5234 + deviceTags: + - aerotech + - motors + enabled: true + onFailure: buffer + readoutPriority: baseline + userParameter: + u: + mount: 0 + work: 0 + x: + in: 0 + out: -10 + safe: -50 + y: + mount: -0.0 + work: -0.016 + z: + mount: 0 + work: 0 +bcu_bpm1: + description: BCU BPM Channel 1 + deviceClass: ophyd.EpicsSignalRO + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-BCBPM:Current1:MeanValue_RBV + deviceTags: + - bpm + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: monitored +bcu_bpm2: + description: BCU BPM Channel 2 + deviceClass: ophyd.EpicsSignalRO + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-BCBPM:Current2:MeanValue_RBV + deviceTags: + - bpm + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: monitored +bcu_bpm3: + description: BCU BPM Channel 3 + deviceClass: ophyd.EpicsSignalRO + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-BCBPM:Current3:MeanValue_RBV + deviceTags: + - bpm + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: monitored +bcu_bpm4: + description: BCU BPM Channel 4 + deviceClass: ophyd.EpicsSignalRO + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-BCBPM:Current4:MeanValue_RBV + deviceTags: + - bpm + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: monitored +bcu_bpm_x: + description: BCU BPM X + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-BCBPM:TRX + deviceTags: + - bcu + enabled: true + onFailure: buffer + readoutPriority: baseline +bcu_bpm_y: + description: BCU BPM Y + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-BCBPM:TRY + deviceTags: + - bcu + enabled: true + onFailure: buffer + readoutPriority: baseline +bcu_bpmsum: + description: BCU BPM Summed + deviceClass: ophyd.EpicsSignalRO + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-BCBPM:SumAll:MeanValue_RBV + deviceTags: + - bpm + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: monitored +bcu_sl_xcen: + description: BCU Slit X Centre + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-BCSLH:CENTER + deviceTags: + - bcu + enabled: true + onFailure: buffer + readoutPriority: baseline +bcu_sl_xr: + description: BCU Slit Ring + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-BCSLH:TRXR + deviceTags: + - bcu + enabled: true + onFailure: buffer + readoutPriority: baseline +bcu_sl_xsize: + description: BCU Slit X Size + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-BCSLH:SIZE + deviceTags: + - bcu + enabled: true + onFailure: buffer + readoutPriority: baseline +bcu_sl_xw: + description: BCU Slit Wall + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-BCSLH:TRXW + deviceTags: + - bcu + enabled: true + onFailure: buffer + readoutPriority: baseline +bcu_sl_yb: + description: BCU Slit Bottom + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-BCSLV:TRYB + deviceTags: + - bcu + enabled: true + onFailure: buffer + readoutPriority: baseline +bcu_sl_ycen: + description: BCU Slit Y Centre + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-BCSLV:CENTER + deviceTags: + - bcu + enabled: true + onFailure: buffer + readoutPriority: baseline +bcu_sl_ysize: + description: BCU Slit Y Size + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-BCSLV:SIZE + deviceTags: + - bcu + enabled: true + onFailure: buffer + readoutPriority: baseline +bcu_sl_yt: + description: BCU Slit Top + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-BCSLV:TRYT + deviceTags: + - bcu + enabled: true + onFailure: buffer + readoutPriority: baseline +bcu_shutter: + description: Fast Shutter + deviceClass: ophyd_devices.EpicsSignal + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-SHUTTER:SET + deviceTags: + - state + enabled: true + onFailure: buffer + readoutPriority: baseline +bl_bright: + description: Backlight Brightness + deviceClass: ophyd.EpicsSignal + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-BL:SET + deviceTags: + - state + enabled: true + onFailure: buffer + readoutPriority: baseline + userParameter: + 'off': 0.0 + 'on': 1.3 + tol: 0.01 + type: continuous +bl_pos: + description: Backlight Positioner + deviceClass: ophyd.EpicsSignal + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-BL:POS-SET + deviceTags: + - state + enabled: true + onFailure: buffer + readoutPriority: baseline + userParameter: + in: 1 + out: 0 + type: discrete +bs_pos: + description: Beamstop Positioner + deviceClass: ophyd.EpicsSignal + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-BS:POS-SET + deviceTags: + - state + enabled: true + onFailure: buffer + readoutPriority: baseline + userParameter: + in: 1 + out: 0 + type: discrete +bs_x: + description: Beamstop X + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-BS:TRX + deviceTags: + - se + enabled: true + onFailure: buffer + readoutPriority: baseline + userParameter: + in: 0.4 +bs_y: + description: Beamstop Y + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-BS:TRY + deviceTags: + - se + enabled: true + onFailure: buffer + readoutPriority: baseline + userParameter: + in: -2.454 +bs_z: + description: Beamstop Z + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-BS:TRZ + deviceTags: + - state + enabled: true + onFailure: buffer + readoutPriority: baseline + userParameter: + max_blin: 45.4 + max_blout: 70 + min: 13 + safe: 45.1 + samp: 16.408 + type: continuous + work_min: 20 +bsf_f1_y: + description: BSF Filter 1 Y + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-OP-BSFFI1:TRY + deviceTags: + - bsf + enabled: true + onFailure: buffer + readoutPriority: baseline +bsf_f2_y: + description: BSF Filter 2 Y + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-OP-BSFFI2:TRY + deviceTags: + - bsf + enabled: true + onFailure: buffer + readoutPriority: baseline +bsf_sl_xcen: + description: BSF X Centre + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-OP-BSFSLH:CENTER + deviceTags: + - bsf + enabled: true + onFailure: buffer + readoutPriority: baseline +bsf_sl_xr: + description: BSF Slit Ring + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-OP-BSFSLH:TRXR + deviceTags: + - bsf + enabled: true + onFailure: buffer + readoutPriority: baseline +bsf_sl_xsize: + description: BSF X Size + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-OP-BSFSLH:SIZE + deviceTags: + - bsf + enabled: true + onFailure: buffer + readoutPriority: baseline +bsf_sl_xw: + description: BSF Slit Wall + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-OP-BSFSLH:TRXW + deviceTags: + - bsf + enabled: true + onFailure: buffer + readoutPriority: baseline +bsf_sl_yb: + description: BSF Slit Bottom + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-OP-BSFSLV:TRYB + deviceTags: + - bsf + enabled: true + onFailure: buffer + readoutPriority: baseline +bsf_sl_ycen: + description: BSF Y Centre + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-OP-BSFSLV:CENTER + deviceTags: + - bsf + enabled: true + onFailure: buffer + readoutPriority: baseline +bsf_sl_ysize: + description: BSF Y Size + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-OP-BSFSLV:SIZE + deviceTags: + - bsf + enabled: true + onFailure: buffer + readoutPriority: baseline +bsf_sl_yt: + description: BSF Slit Top + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-OP-BSFSLV:TRYT + deviceTags: + - bsf + enabled: true + onFailure: buffer + readoutPriority: baseline +coll_x: + description: Collimator X + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-COL:TRX + deviceTags: + - se + enabled: true + onFailure: buffer + readoutPriority: baseline + userParameter: + in: -2.889 +coll_y: + description: Collimator Y + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-COL:TRY + deviceTags: + - state + enabled: true + onFailure: buffer + readoutPriority: baseline + userParameter: + in: 39.139 + intermediate: 32 + out: 20.002 + park: 1 + tol: 0.05 + type: continuous +cryo_pos: + description: Cryo positioner + deviceClass: ophyd.EpicsSignal + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-CS:POS-SET + deviceTags: + - state + enabled: true + onFailure: buffer + readoutPriority: baseline + userParameter: + in: 1 + out: 0 + type: discrete +cryo_temp: + description: Cryo Temperature + deviceClass: ophyd.EpicsSignal + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-CS:TEMP_RBV + deviceTags: + - se + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: baseline +cryo_x: + description: Cryo X + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-CS:TRX + deviceTags: + - se + enabled: true + onFailure: buffer + readoutPriority: baseline +dcm_bragg: + description: DCM Bragg Angle + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-OP-DCM:ROTY + deviceTags: + - dcm + enabled: true + onFailure: buffer + readoutPriority: baseline +dcm_fpitch: + description: DCM 2nd Crystal Fine Pitch + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-OP-DCM:ROTY-CR2-FINEPITCH + deviceTags: + - dcm + enabled: true + onFailure: buffer + readoutPriority: baseline +dcm_froll: + description: DCM 2nd Crystal Fine roll + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-OP-DCM:ROTZ-CR2-FINEROLL + deviceTags: + - dcm + enabled: true + onFailure: buffer + readoutPriority: baseline +dcm_perp: + description: DCM Perpendicular + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-OP-DCM:TRX-CR2 + deviceTags: + - dcm + enabled: true + onFailure: buffer + readoutPriority: baseline +dcm_pitch: + description: DCM 2nd Crystal Pitch + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-OP-DCM:ROTY-CR2-PITCH + deviceTags: + - dcm + enabled: true + onFailure: buffer + readoutPriority: baseline +dcm_x: + description: DCM Lateral + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-OP-DCM:TRX + deviceTags: + - dcm + enabled: true + onFailure: buffer + readoutPriority: baseline +det_cov: + description: Detector cover + deviceClass: ophyd.EpicsSignal + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-DETCOV:SET + deviceTags: + - state + enabled: true + onFailure: buffer + readoutPriority: baseline + userParameter: + close: 1 + open: 2 + type: discrete +det_xi_focus: + description: X-ray Eye 2 Focus + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-XEYE:FOCUS + deviceTags: + - det + enabled: true + onFailure: buffer + readoutPriority: baseline +det_xi_x: + description: X-ray Eye X + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-XEYE:TRX + deviceTags: + - det + enabled: true + onFailure: buffer + readoutPriority: baseline +det_xi_zoom: + description: X-ray Eye 2 Zoom + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-XEYE:ZOOM + deviceTags: + - det + enabled: true + onFailure: buffer + readoutPriority: baseline +det_y: + description: Detector Y + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-DET:TRY + deviceTags: + - det + enabled: true + onFailure: buffer + readoutPriority: baseline + userParameter: + work: 70 + xi: 213.601 +det_z: + description: Detector Z + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-DET:TRZ + deviceTags: + - det + enabled: true + onFailure: buffer + readoutPriority: baseline + userParameter: + mse: 800 + vis: 800 +diag_y: + description: Scintillator/diode Y + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-SCL:TRY + deviceTags: + - state + enabled: true + onFailure: buffer + readoutPriority: baseline + userParameter: + i1: 40.8 + out: 20.0 + park: 1 + scint: 35.74 + tol: 0.3 + type: continuous +diag_z: + description: Scintillator/diode Z + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-SCL:TRZ + deviceTags: + - se + enabled: true + onFailure: buffer + readoutPriority: baseline +fe_bpm1: + description: FE XBPM Channel 1 + deviceClass: ophyd.EpicsSignalRO + deviceConfig: + auto_monitor: true + read_pv: X10SA-FE-XBPM1:Current1:MeanValue_RBV + deviceTags: + - bpm + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: monitored +fe_bpm2: + description: FE XBPM Channel 2 + deviceClass: ophyd.EpicsSignalRO + deviceConfig: + auto_monitor: true + read_pv: X10SA-FE-XBPM1:Current2:MeanValue_RBV + deviceTags: + - bpm + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: monitored +fe_bpm3: + description: FE XBPM Channel 3 + deviceClass: ophyd.EpicsSignalRO + deviceConfig: + auto_monitor: true + read_pv: X10SA-FE-XBPM1:Current3:MeanValue_RBV + deviceTags: + - bpm + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: monitored +fe_bpm4: + description: FE XBPM Channel 4 + deviceClass: ophyd.EpicsSignalRO + deviceConfig: + auto_monitor: true + read_pv: X10SA-FE-XBPM1:Current4:MeanValue_RBV + deviceTags: + - bpm + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: monitored +fe_bpm_x: + description: FE BPM X + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-FE-XBPM1:TRX + deviceTags: + - fe + enabled: true + onFailure: buffer + readoutPriority: baseline +fe_bpm_y: + description: FE BPM Y + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-FE-XBPM1:TRY + deviceTags: + - fe + enabled: true + onFailure: buffer + readoutPriority: baseline +fe_bpmsum: + description: FE XBPM Summed + deviceClass: ophyd.EpicsSignalRO + deviceConfig: + auto_monitor: true + read_pv: X10SA-FE-XBPM1:SumAll:MeanValue_RBV + deviceTags: + - bpm + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: monitored +fe_sl_xcen: + description: FE Slit X Centre + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-FE-SL1:CENTERX + deviceTags: + - fe + enabled: true + onFailure: buffer + readoutPriority: baseline +fe_sl_xr: + description: FE Slit X Ring + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-FE-SL1:TRXR + deviceTags: + - fe + enabled: true + onFailure: buffer + readoutPriority: baseline +fe_sl_xsize: + description: FE Slit X Size + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-FE-SL1:SIZEX + deviceTags: + - fe + enabled: true + onFailure: buffer + readoutPriority: baseline +fe_sl_xw: + description: FE Slit X Wall + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-FE-SL1:TRXW + deviceTags: + - fe + enabled: true + onFailure: buffer + readoutPriority: baseline +fe_sl_yb: + description: FE Slit Y Bottom + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-FE-SL1:TRYB + deviceTags: + - fe + enabled: true + onFailure: buffer + readoutPriority: baseline +fe_sl_ycen: + description: FE Slit Y Centre + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-FE-SL1:CENTERY + deviceTags: + - fe + enabled: true + onFailure: buffer + readoutPriority: baseline +fe_sl_ysize: + description: FE Slit Y Size + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-FE-SL1:SIZEY + deviceTags: + - fe + enabled: true + onFailure: buffer + readoutPriority: baseline +fe_sl_yt: + description: FE Slit Y Top + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-FE-SL1:TRYT + deviceTags: + - fe + enabled: true + onFailure: buffer + readoutPriority: baseline +fl_bright: + description: Frontlight Brightness + deviceClass: ophyd.EpicsSignal + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-FL:SET + deviceTags: + - state + enabled: true + onFailure: buffer + readoutPriority: baseline + userParameter: + 'off': 0.0 + 'on': 3.0 + tol: 0.01 + type: continuous +hfm_bd: + description: HFM Downstream Bender + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-ES-HFM:BNDD + deviceTags: + - hfm + enabled: true + onFailure: buffer + readoutPriority: baseline +hfm_bu: + description: HFM Upstream Bender + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-ES-HFM:BNDU + deviceTags: + - hfm + enabled: true + onFailure: buffer + readoutPriority: baseline +hfm_pitch: + description: HFM Virtual Pitch + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-ES-HFM:PITCH + deviceTags: + - hfm + enabled: true + onFailure: buffer + readoutPriority: baseline +hfm_roll: + description: HFM Virtual Roll + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-ES-HFM:ROLL + deviceTags: + - hfm + enabled: true + onFailure: buffer + readoutPriority: baseline +hfm_x: + description: HFM Virtual X + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-ES-HFM:TRX + deviceTags: + - hfm + enabled: true + onFailure: buffer + readoutPriority: baseline +hfm_xd: + description: HFM Downstream X + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-ES-HFM:TRXD + deviceTags: + - hfm + enabled: true + onFailure: buffer + readoutPriority: baseline +hfm_xu: + description: HFM Upstream X + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-ES-HFM:TRXU + deviceTags: + - hfm + enabled: true + onFailure: buffer + readoutPriority: baseline +hfm_y: + description: HFM Virtual Y + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-ES-HFM:TRY + deviceTags: + - hfm + enabled: true + onFailure: buffer + readoutPriority: baseline +hfm_yaw: + description: HFM Virtual Yaw + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-ES-HFM:YAW + deviceTags: + - hfm + enabled: true + onFailure: buffer + readoutPriority: baseline +hfm_ydw: + description: HFM Downstream Wall Y + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-ES-HFM:TRYDW + deviceTags: + - hfm + enabled: true + onFailure: buffer + readoutPriority: baseline +hfm_yr: + description: HFM Ring Y + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-ES-HFM:TRYR + deviceTags: + - hfm + enabled: true + onFailure: buffer + readoutPriority: baseline +hfm_yuw: + description: HFM Upstream Wall Y + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-ES-HFM:TRYUW + deviceTags: + - hfm + enabled: true + onFailure: buffer + readoutPriority: baseline +i1: + description: I1 Diode + deviceClass: ophyd.EpicsSignalRO + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-SCLDI:READOUT + deviceTags: + - bpm + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: monitored +i2: + description: I2 Diode + deviceClass: ophyd.EpicsSignalRO + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-XEYEDI:READOUT + deviceTags: + - bpm + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: monitored +id_gap: + description: undulator gap + deviceClass: pxii_bec.devices.undulator.UndulatorGap + deviceConfig: + prefix: 'X10SA-UIND:' + enabled: true + onFailure: buffer + readoutPriority: baseline +lu_bpm1: + description: LU BPM Channel 1 + deviceClass: ophyd.EpicsSignalRO + deviceConfig: + auto_monitor: true + read_pv: X10SA-OP-LUBPM:Current1:MeanValue_RBV + deviceTags: + - bpm + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: monitored +lu_bpm2: + description: LU BPM Channel 2 + deviceClass: ophyd.EpicsSignalRO + deviceConfig: + auto_monitor: true + read_pv: X10SA-OP-LUBPM:Current2:MeanValue_RBV + deviceTags: + - bpm + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: monitored +lu_bpm3: + description: LU BPM Channel 3 + deviceClass: ophyd.EpicsSignalRO + deviceConfig: + auto_monitor: true + read_pv: X10SA-OP-LUBPM:Current3:MeanValue_RBV + deviceTags: + - bpm + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: monitored +lu_bpm4: + description: LU BPM Channel 4 + deviceClass: ophyd.EpicsSignalRO + deviceConfig: + auto_monitor: true + read_pv: X10SA-OP-LUBPM:Current4:MeanValue_RBV + deviceTags: + - bpm + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: monitored +lu_bpm_x: + description: BPM2 X + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-OP-LUBPM:TRX + deviceTags: + - lu + enabled: true + onFailure: buffer + readoutPriority: baseline +lu_bpm_y: + description: BPM2 Y + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-OP-LUBPM:TRY + deviceTags: + - lu + enabled: true + onFailure: buffer + readoutPriority: baseline +lu_bpmsum: + description: LU BPM Summed + deviceClass: ophyd.EpicsSignalRO + deviceConfig: + auto_monitor: true + read_pv: X10SA-OP-LUBPM:SumAll:MeanValue_RBV + deviceTags: + - bpm + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: monitored +lu_pod1_rotx: + description: SmarPod1 RX + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-OP-LUPOD1:ROTX + deviceTags: + - lu + enabled: true + onFailure: buffer + readoutPriority: baseline +lu_pod1_roty: + description: SmarPod1 RY + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-OP-LUPOD1:ROTY + deviceTags: + - lu + enabled: true + onFailure: buffer + readoutPriority: baseline +lu_pod1_rotz: + description: SmarPod1 RZ + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-OP-LUPOD1:ROTZ + deviceTags: + - lu + enabled: true + onFailure: buffer + readoutPriority: baseline +lu_pod1_y: + description: SmarPod1 Y + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-OP-LUPOD1:TRY + deviceTags: + - lu + enabled: true + onFailure: buffer + readoutPriority: baseline +lu_pod1_z: + description: SmarPod1 Z + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-OP-LUPOD1:TRZ + deviceTags: + - lu + enabled: true + onFailure: buffer + readoutPriority: baseline +lu_pod2_rotx: + description: SmarPod2 RX + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-OP-LUPOD2:ROTX + deviceTags: + - lu + enabled: true + onFailure: buffer + readoutPriority: baseline +lu_pod2_roty: + description: SmarPod2 RY + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-OP-LUPOD2:ROTY + deviceTags: + - lu + enabled: true + onFailure: buffer + readoutPriority: baseline +lu_pod2_rotz: + description: SmarPod2 RZ + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-OP-LUPOD2:ROTZ + deviceTags: + - lu + enabled: true + onFailure: buffer + readoutPriority: baseline +lu_pod2_y: + description: SmarPod2 Y + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-OP-LUPOD2:TRY + deviceTags: + - lu + enabled: true + onFailure: buffer + readoutPriority: baseline +lu_pod2_z: + description: SmarPod2 Z + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-OP-LUPOD2:TRZ + deviceTags: + - lu + enabled: true + onFailure: buffer + readoutPriority: baseline +lu_z1: + description: Lens Z1 + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-OP-LUTRZ1:TRZ + deviceTags: + - lu + enabled: true + onFailure: buffer + readoutPriority: baseline +lu_z2: + description: Lens Z2 + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-OP-LUTRZ2:TRZ + deviceTags: + - lu + enabled: true + onFailure: buffer + readoutPriority: baseline +mag_ok: + description: Sample Sensor Check + deviceClass: ophyd.EpicsSignalRO + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-DFS:CBOX-CMP1 + deviceTags: + - se + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: baseline +mag_rbv: + description: Sample Sensor RBV + deviceClass: ophyd.EpicsSignalRO + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-DFS:CBOX-USER1 + deviceTags: + - se + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: baseline +mag_ref: + description: Sample Sensor Reference + deviceClass: ophyd.EpicsSignalRO + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-DFS:CBOX-REFVAL1 + deviceTags: + - se + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: baseline +microscope_stats: + description: Stats Signal of MS camera + deviceClass: pxii_bec.devices.stats_signal.StatsSignal + deviceConfig: + prefix: 'X10SA-ES-MS:' + enabled: true + readoutPriority: async + softwareTrigger: true +samcam_ecc: + description: Sample Camera Eccentricity + deviceClass: ophyd.EpicsSignalRO + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-MS:Stats5:Eccentricity_RBV + deviceTags: + - scam + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: monitored +samcam_exp: + description: Sample Camera Exposure + deviceClass: ophyd.EpicsSignal + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-MS:cam1:AcquireTime + deviceTags: + - scam + enabled: true + onFailure: buffer + readoutPriority: baseline +samcam_gain: + description: Sample Camera Gain + deviceClass: ophyd.EpicsSignal + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-MS:cam1:Gain + deviceTags: + - scam + enabled: true + onFailure: buffer + readoutPriority: baseline +samcam_max: + description: Sample Camera Max + deviceClass: ophyd.EpicsSignalRO + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-MS:Stats5:MaxValue_RBV + deviceTags: + - scam + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: monitored +samcam_mean: + description: Sample Camera Mean + deviceClass: ophyd.EpicsSignalRO + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-MS:Stats1:MeanValue_RBV + deviceTags: + - scam + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: monitored +samcam_sigma: + description: Sample Camera Sigma + deviceClass: ophyd.EpicsSignalRO + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-MS:Stats1:Sigma_RBV + deviceTags: + - scam + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: monitored +samcam_x: + description: Sample Camera X + deviceClass: ophyd.EpicsSignalRO + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-MS:Stats5:CentroidX_RBV + deviceTags: + - scam + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: monitored +samcam_xsig: + description: Sample Camera X Sigma + deviceClass: ophyd.EpicsSignalRO + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-MS:Stats5:SigmaX_RBV + deviceTags: + - scam + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: monitored +samcam_y: + description: Sample Camera Y + deviceClass: ophyd.EpicsSignalRO + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-MS:Stats5:CentroidY_RBV + deviceTags: + - scam + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: monitored +samcam_ysig: + description: Sample Camera Y Sigma + deviceClass: ophyd.EpicsSignalRO + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-MS:Stats5:SigmaY_RBV + deviceTags: + - scam + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: monitored +scam_zoom: + description: Sample Camera Zoom + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-MS:ZOOM + deviceTags: + - scam + enabled: true + onFailure: buffer + readoutPriority: baseline +sls_current: + description: SLS Current + deviceClass: ophyd.EpicsSignalRO + deviceConfig: + auto_monitor: true + read_pv: ARS07-DPCT-0100:CURR + deviceTags: + - SLS + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: monitored +smargon: + description: REST-based device which connects to Smargopolo + deviceClass: pxii_bec.devices.smargopolo_smargon.Smargon + deviceConfig: + prefix: http://x10sa-smargopolo.psi.ch:3000 + deviceTags: + - smargon + - motors + enabled: true + onFailure: buffer + readoutPriority: baseline + userParameter: + chi: + mount: 0 + phi: + mount: 0 + x: + mount: 0 + y: + mount: 0 + z: + mount: 18 +ss_bpm1: + description: SS BPM Channel 1 + deviceClass: ophyd.EpicsSignalRO + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-SSBPM:Current1:MeanValue_RBV + deviceTags: + - bpm + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: monitored +ss_bpm2: + description: SS BPM Channel 2 + deviceClass: ophyd.EpicsSignalRO + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-SSBPM:Current2:MeanValue_RBV + deviceTags: + - bpm + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: monitored +ss_bpm3: + description: SS BPM Channel 3 + deviceClass: ophyd.EpicsSignalRO + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-SSBPM:Current3:MeanValue_RBV + deviceTags: + - bpm + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: monitored +ss_bpm4: + description: SS BPM Channel 4 + deviceClass: ophyd.EpicsSignalRO + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-SSBPM:Current4:MeanValue_RBV + deviceTags: + - bpm + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: monitored +ss_bpm_x: + description: SS BPM X + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-SSBPM:TRX + deviceTags: + - ss + enabled: true + onFailure: buffer + readoutPriority: baseline +ss_bpm_y: + description: SS BPM Y + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-SSBPM:TRY + deviceTags: + - ss + enabled: true + onFailure: buffer + readoutPriority: baseline +ss_bpmsum: + description: SS BPM Summed + deviceClass: ophyd.EpicsSignalRO + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-SSBPM:SumAll:MeanValue_RBV + deviceTags: + - bpm + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: monitored +ss_f1_x: + description: SS Filter 1 X + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-SSFI1:TRX + deviceTags: + - ss + enabled: true + onFailure: buffer + readoutPriority: baseline +ss_f2_x: + description: SS Filter 2 X + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-SSFI2:TRX + deviceTags: + - ss + enabled: true + onFailure: buffer + readoutPriority: baseline +ss_f3_x: + description: SS Filter 2 X + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-SSFI3:TRX + deviceTags: + - ss + enabled: true + onFailure: buffer + readoutPriority: baseline +ss_f4_x: + description: SS Filter 4 X + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-SSFI4:TRX + deviceTags: + - ss + enabled: true + onFailure: buffer + readoutPriority: baseline +ss_sl_xcen: + description: SS Slit X Centre + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-SSSLH:CENTER + deviceTags: + - ss + enabled: true + onFailure: buffer + readoutPriority: baseline +ss_sl_xr: + description: SS Slit Ring + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-SSSLH:TRXR + deviceTags: + - ss + enabled: true + onFailure: buffer + readoutPriority: baseline +ss_sl_xsize: + description: SS Slit X Size + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-SSSLH:SIZE + deviceTags: + - ss + enabled: true + onFailure: buffer + readoutPriority: baseline +ss_sl_xw: + description: SS Slit Wall + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-SSSLH:TRXW + deviceTags: + - ss + enabled: true + onFailure: buffer + readoutPriority: baseline +ss_sl_yb: + description: SS Slit Bottom + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-SSSLV:TRYB + deviceTags: + - ss + enabled: true + onFailure: buffer + readoutPriority: baseline +ss_sl_ycen: + description: SS Slit Y Centre + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-SSSLV:CENTER + deviceTags: + - ss + enabled: true + onFailure: buffer + readoutPriority: baseline +ss_sl_ysize: + description: SS Slit Y Size + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-SSSLV:SIZE + deviceTags: + - ss + enabled: true + onFailure: buffer + readoutPriority: baseline +ss_sl_yt: + description: SS Slit Top + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-SSSLV:TRYT + deviceTags: + - ss + enabled: true + onFailure: buffer + readoutPriority: baseline +ss_xi_x: + description: SS X-ray Eye X + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-SSXI:TRX + deviceTags: + - ss + enabled: true + onFailure: buffer + readoutPriority: baseline + userParameter: + in: 7 + out: -2.1 + type: multi-position +ss_xi_y: + description: SS X-ray Eye Y + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-SSXI:TRY + deviceTags: + - ss + enabled: true + onFailure: buffer + readoutPriority: baseline +ss_xicam_exp: + description: SS Camera Exposure + deviceClass: ophyd.EpicsSignal + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-SSCAM:cam1:AcquireTime + deviceTags: + - ss + enabled: true + onFailure: buffer + readoutPriority: baseline +ss_xicam_gain: + description: SS Camera Gain + deviceClass: ophyd.EpicsSignal + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-SSCAM:cam1:Gain + deviceTags: + - ss + enabled: true + onFailure: buffer + readoutPriority: baseline +ss_xicam_max: + description: SS Cam Max + deviceClass: ophyd.EpicsSignalRO + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-SSCAM:Stats5:MaxValue_RBV + deviceTags: + - ss + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: monitored +ss_xicam_x: + description: SS Camera X + deviceClass: ophyd.EpicsSignalRO + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-SSCAM:Stats5:CentroidX_RBV + deviceTags: + - ss + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: baseline +ss_xicam_xsig: + description: SS Camera X Sigma + deviceClass: ophyd.EpicsSignal + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-SSCAM:Stats5:SigmaX_RBV + deviceTags: + - ss + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: baseline +ss_xicam_y: + description: SS Camera Y + deviceClass: ophyd.EpicsSignalRO + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-SSCAM:Stats5:CentroidY_RBV + deviceTags: + - ss + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: baseline +ss_xicam_ysig: + description: SS Camera Y Sigma + deviceClass: ophyd.EpicsSignal + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-SSCAM:Stats5:SigmaY_RBV + deviceTags: + - ss + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: baseline +transm: + description: Beam Transmission + deviceClass: ophyd_devices.EpicsSignal + deviceConfig: + read_pv: X10SA-ES-SSFI:TRANSM-SET + write_pv: X10SA-ES-SSFI:TRANSM-SET + deviceTags: + - transm + enabled: true + readoutPriority: baseline +vfm_bd: + description: VFM Downstream Bender + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-ES-VFM:BNDD + deviceTags: + - vfm + enabled: true + onFailure: buffer + readoutPriority: baseline +vfm_bu: + description: VFM Upstream Bender + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-ES-VFM:BNDU + deviceTags: + - vfm + enabled: true + onFailure: buffer + readoutPriority: baseline +vfm_pitch: + description: VFM Virtual Pitch + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-ES-VFM:PITCH + deviceTags: + - vfm + enabled: true + onFailure: buffer + readoutPriority: baseline +vfm_roll: + description: VFM Virtual Roll + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-ES-VFM:ROLL + deviceTags: + - vfm + enabled: true + onFailure: buffer + readoutPriority: baseline +vfm_x: + description: VFM Virtual X + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-ES-VFM:TRX + deviceTags: + - vfm + enabled: true + onFailure: buffer + readoutPriority: baseline +vfm_xd: + description: VFM Downstream X + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-ES-VFM:TRXD + deviceTags: + - vfm + enabled: true + onFailure: buffer + readoutPriority: baseline +vfm_xu: + description: VFM Upstream X + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-ES-VFM:TRXU + deviceTags: + - vfm + enabled: true + onFailure: buffer + readoutPriority: baseline +vfm_y: + description: VFM Virtual Y + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-ES-VFM:TRY + deviceTags: + - vfm + enabled: true + onFailure: buffer + readoutPriority: baseline +vfm_yaw: + description: VFM Virtual Yaw + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-ES-VFM:YAW + deviceTags: + - vfm + enabled: true + onFailure: buffer + readoutPriority: baseline +vfm_ydr: + description: VFM Downstream Ring Y + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-ES-VFM:TRYDR + deviceTags: + - vfm + enabled: true + onFailure: buffer + readoutPriority: baseline +vfm_yur: + description: VFM Upstream Ring Y + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-ES-VFM:TRYUR + deviceTags: + - vfm + enabled: true + onFailure: buffer + readoutPriority: baseline +vfm_yw: + description: VFM Wall Y + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-ES-VFM:TRYW + deviceTags: + - vfm + enabled: true + onFailure: buffer + readoutPriority: baseline +xi_focus: + description: Xeye Zoom + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-XEYE:FOCUS + deviceTags: + - xeye + enabled: true + onFailure: buffer + readoutPriority: baseline +xi_x: + description: Xeye X + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-XEYE:TRX + deviceTags: + - xeye + enabled: true + onFailure: buffer + readoutPriority: baseline +xi_zoom: + description: Xeye Zoom + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-XEYE:ZOOM + deviceTags: + - xeye + enabled: true + onFailure: buffer + readoutPriority: baseline +xidiode: + description: Xeye Diode + deviceClass: ophyd.EpicsSignalRO + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-XEYEDI:READOUT + deviceTags: + - xeye + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: monitored +xrf_pos: + description: XRF Positioner + deviceClass: ophyd.EpicsSignal + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-XRF:POS-SET + deviceTags: + - state + enabled: true + onFailure: buffer + readoutPriority: baseline + userParameter: + in: 1 + out: 0 + type: discrete diff --git a/pxii_bec/device_configs/pxii-devices.yaml.old b/pxii_bec/device_configs/pxii-devices.yaml.old new file mode 100644 index 0000000..48d4d9b --- /dev/null +++ b/pxii_bec/device_configs/pxii-devices.yaml.old @@ -0,0 +1,1875 @@ +# BEC Device Configuration File +# +# The device config consists of a mapping of device names to their configurations. +# +# The following fields are required for each device: +# - deviceClass: The class of the device (e.g., ophyd_devices.SimPositioner). +# - enabled: A boolean indicating if the device is enabled. +# - readoutPriority: Determines how the device is read out during a scan. Possible values are ["monitored", "baseline", "async", "on_request", "continuous"]. +# +# Optional fields (defaults shown): +# - connectionTimeout: Connection timeout in seconds. Default is 5. +# - description: A string description of the device. Default is "" (empty string). +# - deviceConfig: A dictionary of configuration parameters specific to the device class. Default is None. +# - deviceTags: A list/set of tags associated with the device. Default is an empty list/set. +# - needs: A list of other device names that this device depends on. Default is []. +# - onFailure: The action to take on failure. Possible values are ["buffer", "retry", "raise"]. Default is "retry". +# - readOnly: A boolean indicating if the device is read-only. Default is false. +# - softwareTrigger: A boolean indicating if the device uses software triggering. Default is false. +# - userParameter: A dictionary of user-defined parameters. Default is {}. +# +# Default values may be omitted for brevity. +########################################################################################################################## + + +# An example device configuration with all fields: + +# device1: +# deviceClass: ophyd_devices.SimPositioner +# description: Sample positioner device +# deviceConfig: +# delay: 1 +# update_frequency: 10 +# deviceTags: +# - frontend +# - motor +# enabled: true +# connectionTimeout: 20 +# readoutPriority: baseline +# needs: +# - device2 +# - device3 +# onFailure: retry +# readOnly: false +# softwareTrigger: false +# userParameter: +# in: 23.1 +# out: -50 + +########################################################################################################################## + + +aerotech: + description: REST-based device which connects to AareScan and Aerotech + deviceClass: pxii_bec.devices.aerotech.Aerotech + deviceConfig: + prefix: http://mx-x10sa-queue-01:5234 + deviceTags: + - aerotech + - motors + enabled: true + onFailure: buffer + readoutPriority: baseline + userParameter: + u: + mount: 0 + work: 0 + x: + in: 0 + out: -10 + safe: -50 + y: + mount: -0.0 + work: -0.016 + z: + mount: 0 + work: 0 +bcu_bpm1: + description: BCU BPM Channel 1 + deviceClass: ophyd.EpicsSignalRO + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-BCBPM:Current1:MeanValue_RBV + deviceTags: + - bpm + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: monitored +bcu_bpm2: + description: BCU BPM Channel 2 + deviceClass: ophyd.EpicsSignalRO + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-BCBPM:Current2:MeanValue_RBV + deviceTags: + - bpm + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: monitored +bcu_bpm3: + description: BCU BPM Channel 3 + deviceClass: ophyd.EpicsSignalRO + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-BCBPM:Current3:MeanValue_RBV + deviceTags: + - bpm + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: monitored +bcu_bpm4: + description: BCU BPM Channel 4 + deviceClass: ophyd.EpicsSignalRO + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-BCBPM:Current4:MeanValue_RBV + deviceTags: + - bpm + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: monitored +bcu_bpm_x: + description: BCU BPM X + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-BCBPM:TRX + deviceTags: + - bcu + enabled: true + onFailure: buffer + readoutPriority: baseline +bcu_bpm_y: + description: BCU BPM Y + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-BCBPM:TRY + deviceTags: + - bcu + enabled: true + onFailure: buffer + readoutPriority: baseline +bcu_bpmsum: + description: BCU BPM Summed + deviceClass: ophyd.EpicsSignalRO + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-BCBPM:SumAll:MeanValue_RBV + deviceTags: + - bpm + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: monitored +bcu_sl_xcen: + description: BCU Slit X Centre + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-BCSLH:CENTER + deviceTags: + - bcu + enabled: true + onFailure: buffer + readoutPriority: baseline +bcu_sl_xr: + description: BCU Slit Ring + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-BCSLH:TRXR + deviceTags: + - bcu + enabled: true + onFailure: buffer + readoutPriority: baseline +bcu_sl_xsize: + description: BCU Slit X Size + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-BCSLH:SIZE + deviceTags: + - bcu + enabled: true + onFailure: buffer + readoutPriority: baseline +bcu_sl_xw: + description: BCU Slit Wall + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-BCSLH:TRXW + deviceTags: + - bcu + enabled: true + onFailure: buffer + readoutPriority: baseline +bcu_sl_yb: + description: BCU Slit Bottom + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-BCSLV:TRYB + deviceTags: + - bcu + enabled: true + onFailure: buffer + readoutPriority: baseline +bcu_sl_ycen: + description: BCU Slit Y Centre + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-BCSLV:CENTER + deviceTags: + - bcu + enabled: true + onFailure: buffer + readoutPriority: baseline +bcu_sl_ysize: + description: BCU Slit Y Size + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-BCSLV:SIZE + deviceTags: + - bcu + enabled: true + onFailure: buffer + readoutPriority: baseline +bcu_sl_yt: + description: BCU Slit Top + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-BCSLV:TRYT + deviceTags: + - bcu + enabled: true + onFailure: buffer + readoutPriority: baseline +bl_bright: + description: Backlight Brightness + deviceClass: ophyd.EpicsSignal + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-BL:SET + deviceTags: + - state + enabled: true + onFailure: buffer + readoutPriority: baseline + userParameter: + 'off': 0.0 + 'on': 1.3 + tol: 0.01 + type: continuous +bl_pos: + description: Backlight Positioner + deviceClass: ophyd.EpicsSignal + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-BL:POS-SET + deviceTags: + - state + enabled: true + onFailure: buffer + readoutPriority: baseline + userParameter: + in: 1 + out: 0 + type: discrete +bs_pos: + description: Beamstop Positioner + deviceClass: ophyd.EpicsSignal + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-BS:POS-SET + deviceTags: + - state + enabled: true + onFailure: buffer + readoutPriority: baseline + userParameter: + in: 1 + out: 0 + type: discrete +bs_x: + description: Beamstop X + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-BS:TRX + deviceTags: + - se + enabled: true + onFailure: buffer + readoutPriority: baseline + userParameter: + in: 0.4 +bs_y: + description: Beamstop Y + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-BS:TRY + deviceTags: + - se + enabled: true + onFailure: buffer + readoutPriority: baseline + userParameter: + in: -2.454 +bs_z: + description: Beamstop Z + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-BS:TRZ + deviceTags: + - state + enabled: true + onFailure: buffer + readoutPriority: baseline + userParameter: + max_blin: 45.4 + max_blout: 70 + min: 13 + safe: 45.1 + samp: 16.408 + type: continuous + work_min: 20 +bsf_f1_y: + description: BSF Filter 1 Y + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-OP-BSFFI1:TRY + deviceTags: + - bsf + enabled: true + onFailure: buffer + readoutPriority: baseline +bsf_f2_y: + description: BSF Filter 2 Y + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-OP-BSFFI2:TRY + deviceTags: + - bsf + enabled: true + onFailure: buffer + readoutPriority: baseline +bsf_sl_xcen: + description: BSF X Centre + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-OP-BSFSLH:CENTER + deviceTags: + - bsf + enabled: true + onFailure: buffer + readoutPriority: baseline +bsf_sl_xr: + description: BSF Slit Ring + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-OP-BSFSLH:TRXR + deviceTags: + - bsf + enabled: true + onFailure: buffer + readoutPriority: baseline +bsf_sl_xsize: + description: BSF X Size + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-OP-BSFSLH:SIZE + deviceTags: + - bsf + enabled: true + onFailure: buffer + readoutPriority: baseline +bsf_sl_xw: + description: BSF Slit Wall + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-OP-BSFSLH:TRXW + deviceTags: + - bsf + enabled: true + onFailure: buffer + readoutPriority: baseline +bsf_sl_yb: + description: BSF Slit Bottom + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-OP-BSFSLV:TRYB + deviceTags: + - bsf + enabled: true + onFailure: buffer + readoutPriority: baseline +bsf_sl_ycen: + description: BSF Y Centre + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-OP-BSFSLV:CENTER + deviceTags: + - bsf + enabled: true + onFailure: buffer + readoutPriority: baseline +bsf_sl_ysize: + description: BSF Y Size + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-OP-BSFSLV:SIZE + deviceTags: + - bsf + enabled: true + onFailure: buffer + readoutPriority: baseline +bsf_sl_yt: + description: BSF Slit Top + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-OP-BSFSLV:TRYT + deviceTags: + - bsf + enabled: true + onFailure: buffer + readoutPriority: baseline +coll_x: + description: Collimator X + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-COL:TRX + deviceTags: + - se + enabled: true + onFailure: buffer + readoutPriority: baseline + userParameter: + in: -2.889 +coll_y: + description: Collimator Y + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-COL:TRY + deviceTags: + - state + enabled: true + onFailure: buffer + readoutPriority: baseline + userParameter: + in: 39.139 + intermediate: 32 + out: 20.002 + park: 1 + tol: 0.05 + type: continuous +cryo_pos: + description: Cryo positioner + deviceClass: ophyd.EpicsSignal + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-CS:POS-SET + deviceTags: + - state + enabled: true + onFailure: buffer + readoutPriority: baseline + userParameter: + in: 1 + out: 0 + type: discrete +cryo_temp: + description: Cryo Temperature + deviceClass: ophyd.EpicsSignal + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-CS:TEMP_RBV + deviceTags: + - se + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: baseline +cryo_x: + description: Cryo X + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-CS:TRX + deviceTags: + - se + enabled: true + onFailure: buffer + readoutPriority: baseline +dcm_bragg: + description: DCM Bragg Angle + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-OP-DCM:ROTY + deviceTags: + - dcm + enabled: true + onFailure: buffer + readoutPriority: baseline +dcm_fpitch: + description: DCM 2nd Crystal Fine Pitch + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-OP-DCM:ROTY-CR2-FINEPITCH + deviceTags: + - dcm + enabled: true + onFailure: buffer + readoutPriority: baseline +dcm_froll: + description: DCM 2nd Crystal Fine roll + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-OP-DCM:ROTZ-CR2-FINEROLL + deviceTags: + - dcm + enabled: true + onFailure: buffer + readoutPriority: baseline +dcm_perp: + description: DCM Perpendicular + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-OP-DCM:TRX-CR2 + deviceTags: + - dcm + enabled: true + onFailure: buffer + readoutPriority: baseline +dcm_pitch: + description: DCM 2nd Crystal Pitch + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-OP-DCM:ROTY-CR2-PITCH + deviceTags: + - dcm + enabled: true + onFailure: buffer + readoutPriority: baseline +dcm_x: + description: DCM Lateral + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-OP-DCM:TRX + deviceTags: + - dcm + enabled: true + onFailure: buffer + readoutPriority: baseline +det_cov: + description: Detector cover + deviceClass: ophyd.EpicsSignal + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-DETCOV:SET + deviceTags: + - state + enabled: true + onFailure: buffer + readoutPriority: baseline + userParameter: + close: 1 + open: 2 + type: discrete +det_xi_focus: + description: X-ray Eye 2 Focus + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-XEYE:FOCUS + deviceTags: + - det + enabled: true + onFailure: buffer + readoutPriority: baseline +det_xi_x: + description: X-ray Eye X + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-XEYE:TRX + deviceTags: + - det + enabled: true + onFailure: buffer + readoutPriority: baseline +det_xi_zoom: + description: X-ray Eye 2 Zoom + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-XEYE:ZOOM + deviceTags: + - det + enabled: true + onFailure: buffer + readoutPriority: baseline +det_y: + description: Detector Y + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-DET:TRY + deviceTags: + - det + enabled: true + onFailure: buffer + readoutPriority: baseline + userParameter: + work: 70 + xi: 213.601 +det_z: + description: Detector Z + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-DET:TRZ + deviceTags: + - det + enabled: true + onFailure: buffer + readoutPriority: baseline + userParameter: + mse: 800 + vis: 800 +diag_y: + description: Scintillator/diode Y + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-SCL:TRY + deviceTags: + - state + enabled: true + onFailure: buffer + readoutPriority: baseline + userParameter: + i1: 40.8 + out: 20.0 + park: 1 + scint: 35.74 + tol: 0.3 + type: continuous +diag_z: + description: Scintillator/diode Z + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-SCL:TRZ + deviceTags: + - se + enabled: true + onFailure: buffer + readoutPriority: baseline +fe_bpm1: + description: FE XBPM Channel 1 + deviceClass: ophyd.EpicsSignalRO + deviceConfig: + auto_monitor: true + read_pv: X10SA-FE-XBPM1:Current1:MeanValue_RBV + deviceTags: + - bpm + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: monitored +fe_bpm2: + description: FE XBPM Channel 2 + deviceClass: ophyd.EpicsSignalRO + deviceConfig: + auto_monitor: true + read_pv: X10SA-FE-XBPM1:Current2:MeanValue_RBV + deviceTags: + - bpm + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: monitored +fe_bpm3: + description: FE XBPM Channel 3 + deviceClass: ophyd.EpicsSignalRO + deviceConfig: + auto_monitor: true + read_pv: X10SA-FE-XBPM1:Current3:MeanValue_RBV + deviceTags: + - bpm + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: monitored +fe_bpm4: + description: FE XBPM Channel 4 + deviceClass: ophyd.EpicsSignalRO + deviceConfig: + auto_monitor: true + read_pv: X10SA-FE-XBPM1:Current4:MeanValue_RBV + deviceTags: + - bpm + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: monitored +fe_bpm_x: + description: FE BPM X + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-FE-XBPM1:TRX + deviceTags: + - fe + enabled: true + onFailure: buffer + readoutPriority: baseline +fe_bpm_y: + description: FE BPM Y + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-FE-XBPM1:TRY + deviceTags: + - fe + enabled: true + onFailure: buffer + readoutPriority: baseline +fe_bpmsum: + description: FE XBPM Summed + deviceClass: ophyd.EpicsSignalRO + deviceConfig: + auto_monitor: true + read_pv: X10SA-FE-XBPM1:SumAll:MeanValue_RBV + deviceTags: + - bpm + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: monitored +fe_sl_xcen: + description: FE Slit X Centre + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-FE-SL1:CENTERX + deviceTags: + - fe + enabled: true + onFailure: buffer + readoutPriority: baseline +fe_sl_xr: + description: FE Slit X Ring + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-FE-SL1:TRXR + deviceTags: + - fe + enabled: true + onFailure: buffer + readoutPriority: baseline +fe_sl_xsize: + description: FE Slit X Size + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-FE-SL1:SIZEX + deviceTags: + - fe + enabled: true + onFailure: buffer + readoutPriority: baseline +fe_sl_xw: + description: FE Slit X Wall + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-FE-SL1:TRXW + deviceTags: + - fe + enabled: true + onFailure: buffer + readoutPriority: baseline +fe_sl_yb: + description: FE Slit Y Bottom + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-FE-SL1:TRYB + deviceTags: + - fe + enabled: true + onFailure: buffer + readoutPriority: baseline +fe_sl_ycen: + description: FE Slit Y Centre + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-FE-SL1:CENTERY + deviceTags: + - fe + enabled: true + onFailure: buffer + readoutPriority: baseline +fe_sl_ysize: + description: FE Slit Y Size + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-FE-SL1:SIZEY + deviceTags: + - fe + enabled: true + onFailure: buffer + readoutPriority: baseline +fe_sl_yt: + description: FE Slit Y Top + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-FE-SL1:TRYT + deviceTags: + - fe + enabled: true + onFailure: buffer + readoutPriority: baseline +fl_bright: + description: Frontlight Brightness + deviceClass: ophyd.EpicsSignal + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-FL:SET + deviceTags: + - state + enabled: true + onFailure: buffer + readoutPriority: baseline + userParameter: + 'off': 0.0 + 'on': 3.0 + tol: 0.01 + type: continuous +hfm_bd: + description: HFM Downstream Bender + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-ES-HFM:BNDD + deviceTags: + - hfm + enabled: true + onFailure: buffer + readoutPriority: baseline +hfm_bu: + description: HFM Upstream Bender + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-ES-HFM:BNDU + deviceTags: + - hfm + enabled: true + onFailure: buffer + readoutPriority: baseline +hfm_pitch: + description: HFM Virtual Pitch + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-ES-HFM:PITCH + deviceTags: + - hfm + enabled: true + onFailure: buffer + readoutPriority: baseline +hfm_roll: + description: HFM Virtual Roll + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-ES-HFM:ROLL + deviceTags: + - hfm + enabled: true + onFailure: buffer + readoutPriority: baseline +hfm_x: + description: HFM Virtual X + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-ES-HFM:TRX + deviceTags: + - hfm + enabled: true + onFailure: buffer + readoutPriority: baseline +hfm_xd: + description: HFM Downstream X + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-ES-HFM:TRXD + deviceTags: + - hfm + enabled: true + onFailure: buffer + readoutPriority: baseline +hfm_xu: + description: HFM Upstream X + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-ES-HFM:TRXU + deviceTags: + - hfm + enabled: true + onFailure: buffer + readoutPriority: baseline +hfm_y: + description: HFM Virtual Y + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-ES-HFM:TRY + deviceTags: + - hfm + enabled: true + onFailure: buffer + readoutPriority: baseline +hfm_yaw: + description: HFM Virtual Yaw + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-ES-HFM:YAW + deviceTags: + - hfm + enabled: true + onFailure: buffer + readoutPriority: baseline +hfm_ydw: + description: HFM Downstream Wall Y + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-ES-HFM:TRYDW + deviceTags: + - hfm + enabled: true + onFailure: buffer + readoutPriority: baseline +hfm_yr: + description: HFM Ring Y + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-ES-HFM:TRYR + deviceTags: + - hfm + enabled: true + onFailure: buffer + readoutPriority: baseline +hfm_yuw: + description: HFM Upstream Wall Y + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-ES-HFM:TRYUW + deviceTags: + - hfm + enabled: true + onFailure: buffer + readoutPriority: baseline +i1: + description: I1 Diode + deviceClass: ophyd.EpicsSignalRO + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-SCLDI:READOUT + deviceTags: + - bpm + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: monitored +i2: + description: I2 Diode + deviceClass: ophyd.EpicsSignalRO + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-XEYEDI:READOUT + deviceTags: + - bpm + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: monitored +id_gap: + description: undulator gap + deviceClass: pxii_bec.devices.undulator.UndulatorGap + deviceConfig: + prefix: 'X10SA-UIND:' + enabled: true + onFailure: buffer + readoutPriority: baseline +lu_bpm1: + description: LU BPM Channel 1 + deviceClass: ophyd.EpicsSignalRO + deviceConfig: + auto_monitor: true + read_pv: X10SA-OP-LUBPM:Current1:MeanValue_RBV + deviceTags: + - bpm + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: monitored +lu_bpm2: + description: LU BPM Channel 2 + deviceClass: ophyd.EpicsSignalRO + deviceConfig: + auto_monitor: true + read_pv: X10SA-OP-LUBPM:Current2:MeanValue_RBV + deviceTags: + - bpm + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: monitored +lu_bpm3: + description: LU BPM Channel 3 + deviceClass: ophyd.EpicsSignalRO + deviceConfig: + auto_monitor: true + read_pv: X10SA-OP-LUBPM:Current3:MeanValue_RBV + deviceTags: + - bpm + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: monitored +lu_bpm4: + description: LU BPM Channel 4 + deviceClass: ophyd.EpicsSignalRO + deviceConfig: + auto_monitor: true + read_pv: X10SA-OP-LUBPM:Current4:MeanValue_RBV + deviceTags: + - bpm + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: monitored +lu_bpm_x: + description: BPM2 X + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-OP-LUBPM:TRX + deviceTags: + - lu + enabled: true + onFailure: buffer + readoutPriority: baseline +lu_bpm_y: + description: BPM2 Y + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-OP-LUBPM:TRY + deviceTags: + - lu + enabled: true + onFailure: buffer + readoutPriority: baseline +lu_bpmsum: + description: LU BPM Summed + deviceClass: ophyd.EpicsSignalRO + deviceConfig: + auto_monitor: true + read_pv: X10SA-OP-LUBPM:SumAll:MeanValue_RBV + deviceTags: + - bpm + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: monitored +lu_pod1_rotx: + description: SmarPod1 RX + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-OP-LUPOD1:ROTX + deviceTags: + - lu + enabled: true + onFailure: buffer + readoutPriority: baseline +lu_pod1_roty: + description: SmarPod1 RY + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-OP-LUPOD1:ROTY + deviceTags: + - lu + enabled: true + onFailure: buffer + readoutPriority: baseline +lu_pod1_rotz: + description: SmarPod1 RZ + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-OP-LUPOD1:ROTZ + deviceTags: + - lu + enabled: true + onFailure: buffer + readoutPriority: baseline +lu_pod1_y: + description: SmarPod1 Y + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-OP-LUPOD1:TRY + deviceTags: + - lu + enabled: true + onFailure: buffer + readoutPriority: baseline +lu_pod1_z: + description: SmarPod1 Z + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-OP-LUPOD1:TRZ + deviceTags: + - lu + enabled: true + onFailure: buffer + readoutPriority: baseline +lu_pod2_rotx: + description: SmarPod2 RX + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-OP-LUPOD2:ROTX + deviceTags: + - lu + enabled: true + onFailure: buffer + readoutPriority: baseline +lu_pod2_roty: + description: SmarPod2 RY + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-OP-LUPOD2:ROTY + deviceTags: + - lu + enabled: true + onFailure: buffer + readoutPriority: baseline +lu_pod2_rotz: + description: SmarPod2 RZ + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-OP-LUPOD2:ROTZ + deviceTags: + - lu + enabled: true + onFailure: buffer + readoutPriority: baseline +lu_pod2_y: + description: SmarPod2 Y + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-OP-LUPOD2:TRY + deviceTags: + - lu + enabled: true + onFailure: buffer + readoutPriority: baseline +lu_pod2_z: + description: SmarPod2 Z + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-OP-LUPOD2:TRZ + deviceTags: + - lu + enabled: true + onFailure: buffer + readoutPriority: baseline +lu_z1: + description: Lens Z1 + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-OP-LUTRZ1:TRZ + deviceTags: + - lu + enabled: true + onFailure: buffer + readoutPriority: baseline +lu_z2: + description: Lens Z2 + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-OP-LUTRZ2:TRZ + deviceTags: + - lu + enabled: true + onFailure: buffer + readoutPriority: baseline +mag_ok: + description: Sample Sensor Check + deviceClass: ophyd.EpicsSignalRO + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-DFS:CBOX-CMP1 + deviceTags: + - se + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: baseline +mag_rbv: + description: Sample Sensor RBV + deviceClass: ophyd.EpicsSignalRO + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-DFS:CBOX-USER1 + deviceTags: + - se + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: baseline +mag_ref: + description: Sample Sensor Reference + deviceClass: ophyd.EpicsSignalRO + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-DFS:CBOX-REFVAL1 + deviceTags: + - se + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: baseline +microscope_stats: + description: Stats Signal of MS camera + deviceClass: pxii_bec.devices.stats_signal.StatsSignal + deviceConfig: + prefix: 'X10SA-ES-MS:' + enabled: true + readoutPriority: async + softwareTrigger: true +samcam_ecc: + description: Sample Camera Eccentricity + deviceClass: ophyd.EpicsSignalRO + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-MS:Stats5:Eccentricity_RBV + deviceTags: + - scam + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: monitored +samcam_exp: + description: Sample Camera Exposure + deviceClass: ophyd.EpicsSignal + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-MS:cam1:AcquireTime + deviceTags: + - scam + enabled: true + onFailure: buffer + readoutPriority: baseline +samcam_gain: + description: Sample Camera Gain + deviceClass: ophyd.EpicsSignal + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-MS:cam1:Gain + deviceTags: + - scam + enabled: true + onFailure: buffer + readoutPriority: baseline +samcam_max: + description: Sample Camera Max + deviceClass: ophyd.EpicsSignalRO + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-MS:Stats5:MaxValue_RBV + deviceTags: + - scam + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: monitored +samcam_mean: + description: Sample Camera Mean + deviceClass: ophyd.EpicsSignalRO + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-MS:Stats1:MeanValue_RBV + deviceTags: + - scam + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: monitored +samcam_sigma: + description: Sample Camera Sigma + deviceClass: ophyd.EpicsSignalRO + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-MS:Stats1:Sigma_RBV + deviceTags: + - scam + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: monitored +samcam_x: + description: Sample Camera X + deviceClass: ophyd.EpicsSignalRO + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-MS:Stats5:CentroidX_RBV + deviceTags: + - scam + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: monitored +samcam_xsig: + description: Sample Camera X Sigma + deviceClass: ophyd.EpicsSignalRO + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-MS:Stats5:SigmaX_RBV + deviceTags: + - scam + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: monitored +samcam_y: + description: Sample Camera Y + deviceClass: ophyd.EpicsSignalRO + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-MS:Stats5:CentroidY_RBV + deviceTags: + - scam + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: monitored +samcam_ysig: + description: Sample Camera Y Sigma + deviceClass: ophyd.EpicsSignalRO + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-MS:Stats5:SigmaY_RBV + deviceTags: + - scam + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: monitored +scam_zoom: + description: Sample Camera Zoom + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-MS:ZOOM + deviceTags: + - scam + enabled: true + onFailure: buffer + readoutPriority: baseline +sls_current: + description: SLS Current + deviceClass: ophyd.EpicsSignalRO + deviceConfig: + auto_monitor: true + read_pv: ARS07-DPCT-0100:CURR + deviceTags: + - SLS + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: monitored +smargon: + description: REST-based device which connects to Smargopolo + deviceClass: pxii_bec.devices.smargopolo_smargon.Smargon + deviceConfig: + prefix: http://x10sa-smargopolo.psi.ch:3000 + deviceTags: + - smargon + - motors + enabled: true + onFailure: buffer + readoutPriority: baseline + userParameter: + chi: + mount: 0 + phi: + mount: 0 + x: + mount: 0 + y: + mount: 0 + z: + mount: 18 +ss_bpm1: + description: SS BPM Channel 1 + deviceClass: ophyd.EpicsSignalRO + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-SSBPM:Current1:MeanValue_RBV + deviceTags: + - bpm + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: monitored +ss_bpm2: + description: SS BPM Channel 2 + deviceClass: ophyd.EpicsSignalRO + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-SSBPM:Current2:MeanValue_RBV + deviceTags: + - bpm + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: monitored +ss_bpm3: + description: SS BPM Channel 3 + deviceClass: ophyd.EpicsSignalRO + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-SSBPM:Current3:MeanValue_RBV + deviceTags: + - bpm + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: monitored +ss_bpm4: + description: SS BPM Channel 4 + deviceClass: ophyd.EpicsSignalRO + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-SSBPM:Current4:MeanValue_RBV + deviceTags: + - bpm + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: monitored +ss_bpm_x: + description: SS BPM X + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-SSBPM:TRX + deviceTags: + - ss + enabled: true + onFailure: buffer + readoutPriority: baseline +ss_bpm_y: + description: SS BPM Y + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-SSBPM:TRY + deviceTags: + - ss + enabled: true + onFailure: buffer + readoutPriority: baseline +ss_bpmsum: + description: SS BPM Summed + deviceClass: ophyd.EpicsSignalRO + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-SSBPM:SumAll:MeanValue_RBV + deviceTags: + - bpm + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: monitored +ss_f1_x: + description: SS Filter 1 X + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-SSFI1:TRX + deviceTags: + - ss + enabled: true + onFailure: buffer + readoutPriority: baseline +ss_f2_x: + description: SS Filter 2 X + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-SSFI2:TRX + deviceTags: + - ss + enabled: true + onFailure: buffer + readoutPriority: baseline +ss_f3_x: + description: SS Filter 2 X + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-SSFI3:TRX + deviceTags: + - ss + enabled: true + onFailure: buffer + readoutPriority: baseline +ss_f4_x: + description: SS Filter 4 X + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-SSFI4:TRX + deviceTags: + - ss + enabled: true + onFailure: buffer + readoutPriority: baseline +ss_sl_xcen: + description: SS Slit X Centre + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-SSSLH:CENTER + deviceTags: + - ss + enabled: true + onFailure: buffer + readoutPriority: baseline +ss_sl_xr: + description: SS Slit Ring + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-SSSLH:TRXR + deviceTags: + - ss + enabled: true + onFailure: buffer + readoutPriority: baseline +ss_sl_xsize: + description: SS Slit X Size + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-SSSLH:SIZE + deviceTags: + - ss + enabled: true + onFailure: buffer + readoutPriority: baseline +ss_sl_xw: + description: SS Slit Wall + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-SSSLH:TRXW + deviceTags: + - ss + enabled: true + onFailure: buffer + readoutPriority: baseline +ss_sl_yb: + description: SS Slit Bottom + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-SSSLV:TRYB + deviceTags: + - ss + enabled: true + onFailure: buffer + readoutPriority: baseline +ss_sl_ycen: + description: SS Slit Y Centre + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-SSSLV:CENTER + deviceTags: + - ss + enabled: true + onFailure: buffer + readoutPriority: baseline +ss_sl_ysize: + description: SS Slit Y Size + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-SSSLV:SIZE + deviceTags: + - ss + enabled: true + onFailure: buffer + readoutPriority: baseline +ss_sl_yt: + description: SS Slit Top + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-SSSLV:TRYT + deviceTags: + - ss + enabled: true + onFailure: buffer + readoutPriority: baseline +ss_xi_x: + description: SS X-ray Eye X + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-SSXI:TRX + deviceTags: + - ss + enabled: true + onFailure: buffer + readoutPriority: baseline + userParameter: + in: 7 + out: -2.1 + type: multi-position +ss_xi_y: + description: SS X-ray Eye Y + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-SSXI:TRY + deviceTags: + - ss + enabled: true + onFailure: buffer + readoutPriority: baseline +ss_xicam_exp: + description: SS Camera Exposure + deviceClass: ophyd.EpicsSignal + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-SSCAM:cam1:AcquireTime + deviceTags: + - ss + enabled: true + onFailure: buffer + readoutPriority: baseline +ss_xicam_gain: + description: SS Camera Gain + deviceClass: ophyd.EpicsSignal + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-SSCAM:cam1:Gain + deviceTags: + - ss + enabled: true + onFailure: buffer + readoutPriority: baseline +ss_xicam_max: + description: SS Cam Max + deviceClass: ophyd.EpicsSignalRO + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-SSCAM:Stats5:MaxValue_RBV + deviceTags: + - ss + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: monitored +ss_xicam_x: + description: SS Camera X + deviceClass: ophyd.EpicsSignalRO + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-SSCAM:Stats5:CentroidX_RBV + deviceTags: + - ss + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: baseline +ss_xicam_xsig: + description: SS Camera X Sigma + deviceClass: ophyd.EpicsSignal + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-SSCAM:Stats5:SigmaX_RBV + deviceTags: + - ss + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: baseline +ss_xicam_y: + description: SS Camera Y + deviceClass: ophyd.EpicsSignalRO + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-SSCAM:Stats5:CentroidY_RBV + deviceTags: + - ss + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: baseline +ss_xicam_ysig: + description: SS Camera Y Sigma + deviceClass: ophyd.EpicsSignal + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-SSCAM:Stats5:SigmaY_RBV + deviceTags: + - ss + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: baseline +transm: + description: Beam Transmission + deviceClass: ophyd_devices.EpicsSignal + deviceConfig: + read_pv: X10SA-ES-SSFI:TRANSM-SET + write_pv: X10SA-ES-SSFI:TRANSM-SET + deviceTags: + - transm + enabled: true + readoutPriority: baseline +vfm_bd: + description: VFM Downstream Bender + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-ES-VFM:BNDD + deviceTags: + - vfm + enabled: true + onFailure: buffer + readoutPriority: baseline +vfm_bu: + description: VFM Upstream Bender + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-ES-VFM:BNDU + deviceTags: + - vfm + enabled: true + onFailure: buffer + readoutPriority: baseline +vfm_pitch: + description: VFM Virtual Pitch + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-ES-VFM:PITCH + deviceTags: + - vfm + enabled: true + onFailure: buffer + readoutPriority: baseline +vfm_roll: + description: VFM Virtual Roll + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-ES-VFM:ROLL + deviceTags: + - vfm + enabled: true + onFailure: buffer + readoutPriority: baseline +vfm_x: + description: VFM Virtual X + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-ES-VFM:TRX + deviceTags: + - vfm + enabled: true + onFailure: buffer + readoutPriority: baseline +vfm_xd: + description: VFM Downstream X + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-ES-VFM:TRXD + deviceTags: + - vfm + enabled: true + onFailure: buffer + readoutPriority: baseline +vfm_xu: + description: VFM Upstream X + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-ES-VFM:TRXU + deviceTags: + - vfm + enabled: true + onFailure: buffer + readoutPriority: baseline +vfm_y: + description: VFM Virtual Y + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-ES-VFM:TRY + deviceTags: + - vfm + enabled: true + onFailure: buffer + readoutPriority: baseline +vfm_yaw: + description: VFM Virtual Yaw + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-ES-VFM:YAW + deviceTags: + - vfm + enabled: true + onFailure: buffer + readoutPriority: baseline +vfm_ydr: + description: VFM Downstream Ring Y + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-ES-VFM:TRYDR + deviceTags: + - vfm + enabled: true + onFailure: buffer + readoutPriority: baseline +vfm_yur: + description: VFM Upstream Ring Y + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-ES-VFM:TRYUR + deviceTags: + - vfm + enabled: true + onFailure: buffer + readoutPriority: baseline +vfm_yw: + description: VFM Wall Y + deviceClass: ophyd_devices.EpicsMotorEC + deviceConfig: + prefix: X10SA-ES-VFM:TRYW + deviceTags: + - vfm + enabled: true + onFailure: buffer + readoutPriority: baseline +xi_focus: + description: Xeye Zoom + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-XEYE:FOCUS + deviceTags: + - xeye + enabled: true + onFailure: buffer + readoutPriority: baseline +xi_x: + description: Xeye X + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-XEYE:TRX + deviceTags: + - xeye + enabled: true + onFailure: buffer + readoutPriority: baseline +xi_zoom: + description: Xeye Zoom + deviceClass: ophyd_devices.EpicsMotor + deviceConfig: + prefix: X10SA-ES-XEYE:ZOOM + deviceTags: + - xeye + enabled: true + onFailure: buffer + readoutPriority: baseline +xidiode: + description: Xeye Diode + deviceClass: ophyd.EpicsSignalRO + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-XEYEDI:READOUT + deviceTags: + - xeye + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: monitored +xrf_pos: + description: XRF Positioner + deviceClass: ophyd.EpicsSignal + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-XRF:POS-SET + deviceTags: + - state + enabled: true + onFailure: buffer + readoutPriority: baseline + userParameter: + in: 1 + out: 0 + type: discrete diff --git a/pxii_bec/devices/contrast.py b/pxii_bec/devices/contrast.py new file mode 100644 index 0000000..270a04a --- /dev/null +++ b/pxii_bec/devices/contrast.py @@ -0,0 +1,75 @@ +import math +import time + +from ophyd import Component as Cpt +from ophyd import EpicsSignalRO, Kind, SignalRO +from ophyd_devices.interfaces.base_classes.psi_device_base import PSIDeviceBase + + +class ContrastSignal(SignalRO): + """Read-only signal calculated as sigma / mean.""" + + def __init__( + self, + *args, + minimum_mean: float = 1e-12, + **kwargs, + ): + super().__init__(*args, **kwargs) + self.minimum_mean = minimum_mean + + def get(self, **kwargs) -> float: + mean = float(self.parent.mean.get()) + sigma = float(self.parent.sigma.get()) + + if ( + not math.isfinite(mean) + or not math.isfinite(sigma) + or abs(mean) <= self.minimum_mean + ): + return math.nan + + return sigma / mean + + def read(self): + return { + self.name: { + "value": self.get(), + "timestamp": time.time(), + } + } + + def describe(self): + return { + self.name: { + "source": ( + f"calculated:{self.parent.sigma.pvname}/" + f"{self.parent.mean.pvname}" + ), + "dtype": "number", + "shape": [], + "units": "", + } + } + + +class CameraContrast(PSIDeviceBase): + """Camera statistics and calculated contrast.""" + + mean = Cpt( + EpicsSignalRO, + "MeanValue_RBV", + kind=Kind.normal, + ) + + sigma = Cpt( + EpicsSignalRO, + "Sigma_RBV", + kind=Kind.normal, + ) + + contrast = Cpt( + ContrastSignal, + kind=Kind.hinted, + ) + diff --git a/pxii_bec/devices/optics_shutter.py b/pxii_bec/devices/optics_shutter.py new file mode 100644 index 0000000..8e33e06 --- /dev/null +++ b/pxii_bec/devices/optics_shutter.py @@ -0,0 +1,107 @@ +""" +Module for the optics shutter device at PSI beamlines. + +Example config: +shutter: + description: Optics Shutter A + deviceClass: ophyd_devices.optics_shutter.OpticsShutter + deviceConfig: {prefix: 'X10SA-EH1-PSYS:SH-A-'} + enabled: true + onFailure: retry + readOnly: false + readoutPriority: baseline + softwareTrigger: false + userParameter: {} +""" + +from enum import IntEnum + +from ophyd import Component as Cpt +from ophyd import Device, EpicsSignal, EpicsSignalRO, Kind, Signal + +from ophyd_devices import CompareStatus + + +class ShutterOpenState(IntEnum): + """Enum for shutter open state.""" + + OPEN = 1 + CLOSED = 0 + + +class ShutterEnabled(IntEnum): + """Enum for shutter enabled state.""" + + ENABLED = 1 + DISABLED = 0 + + +class ShutterControl(Device): + """Control interface for the PVs related to the shutter.""" + + is_open = Cpt(EpicsSignalRO, "OPEN", kind=Kind.config, auto_monitor=True) + is_closed = Cpt(EpicsSignalRO, "CLOSE", kind=Kind.omitted) + is_enabled = Cpt(EpicsSignalRO, "ENABLE", kind=Kind.config, auto_monitor=True) + is_ok = Cpt(EpicsSignalRO, "OK", kind=Kind.omitted, auto_monitor=True) + alarm = Cpt(EpicsSignalRO, "ALARM", kind=Kind.omitted, auto_monitor=True) + set_open = Cpt(EpicsSignal, "OPEN-SET", kind=Kind.omitted) + set_closed = Cpt(EpicsSignal, "CLOSE-SET", kind=Kind.omitted) + + +class ShutterOpenSignal(Signal): + """ + ShutterOpenSignal. When called with 1, it will try to open the shutter. + If called with 0, it will try to close the shutter. + """ + + def enabled(self) -> ShutterEnabled: + """Check if the shutter is enabled.""" + return ShutterEnabled(self.parent.epics_control.is_enabled.get()) + + def _check_enabled(self): + if self.enabled() != ShutterEnabled.ENABLED: + dev_name = self.parent.name if self.parent else "unknown" + raise RuntimeError(f"The shutter {dev_name} is disabled!") + + def get(self) -> int: + return self.parent.epics_control.is_open.get() + + def put(self, value: int, **kwargs) -> None: + self._check_enabled() + if value == ShutterOpenState.OPEN: + self.parent.epics_control.set_open.put(1, **kwargs) + elif value == ShutterOpenState.CLOSED: + self.parent.epics_control.set_closed.put(1, **kwargs) + else: + raise ValueError("Invalid value for ShutterOpenSignal. Use 0 (CLOSED) or 1 (OPEN).") + + def set(self, value: int, **kwargs) -> CompareStatus: + self.put(value, **kwargs) + return CompareStatus(self.parent.epics_control.is_open, value) + + +class OpticsShutter(Device): + """A shutter device with shutter open signal, and sub-device with full control PVs of the Epics implementation.""" + + set_open = Cpt( + ShutterOpenSignal, + name="open", + kind=Kind.omitted, + doc="Signal to open/close the shutter. Use 0 (CLOSED) or 1 (OPEN).", + ) + is_open = Cpt( + EpicsSignalRO, + "OPEN", + kind=Kind.normal, + auto_monitor=True, + doc="Readback of the shutter open state. 0 (CLOSED) or 1 (OPEN).", + ) + epics_control = Cpt(ShutterControl, suffix="", name="epics_control", kind=Kind.omitted) + + +if __name__ == "__main__": + prefix = "X10SA-EH1-PSYS:SH-A-" + print(f"Testing shutter device with prefix {prefix}") + shutter = OpticsShutter(name="shutter", prefix=prefix) + shutter.wait_for_connection() + print(shutter.read()) diff --git a/pxii_bec/macros/.nfs000000000001101900000001 b/pxii_bec/macros/.nfs000000000001101900000001 new file mode 100644 index 0000000000000000000000000000000000000000..1b30d5e970bdf8e3c8237388300e2274d6b60906 GIT binary patch literal 12288 zcmeI&F;Buk7zW_O9YvkoDlU*fdo3VH!fYHIF(wYAvC0p)nDYKgNv*2 zm-rRRVn8B^gXX>D&B5{UrT3Jj;kx|nUD;k|DE*NVamy8+ zvQ=@~q3h9MYZ3J)1=Ff>K3iPUwz5{+8eh@YTC1&fSm(vWV7iSZS8T4+`Y5^JRh{`d ho$D(otRD!^Zlc!GY8rDzPn-V+()06$^zIj%>=W7e@wos1 literal 0 HcmV?d00001 diff --git a/pxii_bec/macros/APscripts.py b/pxii_bec/macros/APscripts.py index f1387ab..94a7d59 100644 --- a/pxii_bec/macros/APscripts.py +++ b/pxii_bec/macros/APscripts.py @@ -252,8 +252,16 @@ def loadmac(): bec.macros.load_all_user_macros() # d, planner = init_beamline_environment() - +############################# +### plotenv +############################# +def plotset(y): + import matplotlib.pyplot as plt + plt.ion() + plt.figure() + plt.plot(y) + ################################ ### FITTING PROGRAMS @@ -430,13 +438,13 @@ def fit_plot(data_x, data_y, model="gauss", ibg=1, fitrange=0, fitclick=0): ##### peak = GaussianModel(prefix = 'g_') - pre='g' + pre='g_' if model == "voigt": peak = VoigtModel(prefix = 'v_') - pre='v' + pre='v_' if model == "lorentz": peak = LorentzianModel(prefix = 'l_') - pre='l' + pre='l_' model = peak ypeak = data_y @@ -509,13 +517,18 @@ def fit_plot(data_x, data_y, model="gauss", ibg=1, fitrange=0, fitclick=0): plt.ylabel("signal") plt.show() - #gcen = g.params["center"].value + + # g.params + returncenvar = pre+"center" + gcen = g.params[returncenvar].value + + print('gcen =', gcen) print(g.fit_report()) - fit_id = pre+'_center' + # fit_id = pre+'_center' - center = g.params[fit_id].value - return center, xm + #center = g.pars[fit_id].value + return gcen, xm #################################### @@ -703,7 +716,7 @@ def getdiodepos(diode="i1"): def read_mon(): - from datetime import datetime + #from datetime import datetime e = getenergy() #fesum = dev.fe_bpmsum.read()["fe_bpmsum"]["value"] @@ -1602,7 +1615,7 @@ def prepare_fluxmeas(): if ans == "y": detxeye_in() bs_in = d["bs_y"].positions["in"] - umv(dev.bs_y, bs_in +1) + #umv(dev.bs_y, bs_in +1) return def fluxcal(start_en=13, stop_en=14, step =1): @@ -1618,10 +1631,13 @@ def fluxcal(start_en=13, stop_en=14, step =1): dat_xi=[] dat_fluxi=[] dat_quot_flbsum=[] - + dat_i1=[] + + diode_inpos = dev.diag_y.user_parameter["i1"] + diode_outpos = dev.diag_y.user_parameter["out"] for ei in range(start_en,stop_en+1, step): bl_energy(ei*1000, plot = False) # in ev - time.sleep(0.2) + time.sleep(0.5) #lusum = dev.lu_bpmsum.read()["lu_bpmsum"]["value"] signal = dev.lu_bpmsum # "lu_bpmsum" lusum = read_av(signal, avlen) @@ -1640,7 +1656,16 @@ def fluxcal(start_en=13, stop_en=14, step =1): xi = read_av(signal, avlen) fluxi = flux_x10sa(xi, ei, silent =1) - quot = fluxi/bcusum + quot = fluxi/bcusum + + + #i1diode = dev.i1.read()["i1"]["value"] + umv(dev.diag_y,diode_inpos) + signal = dev.i1 + i1diode = read_av(signal, avlen) + umv(dev.diag_y,diode_outpos) + + print(f'En {ei}, BCUSUM {bcusum}, xi {xi}, flux {fluxi}') dat_en.append(ei) dat_lubpm.append(lusum) @@ -1649,8 +1674,9 @@ def fluxcal(start_en=13, stop_en=14, step =1): dat_xi.append(xi) dat_fluxi.append(fluxi) dat_quot_flbsum.append(quot) + dat_i1.append(i1diode) - combined = np.column_stack((dat_en, dat_lubpm,dat_ssbpm,dat_bcubpm,dat_xi,dat_fluxi,dat_quot_flbsum)) + combined = np.column_stack((dat_en, dat_lubpm,dat_ssbpm,dat_bcubpm,dat_xi,dat_fluxi,dat_quot_flbsum, dat_i1)) # open file for output timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S") @@ -1658,15 +1684,16 @@ def fluxcal(start_en=13, stop_en=14, step =1): filename = dirname + f"FLUX_x10sa_{timestamp}.txt" with open(filename, "w") as f: - np.savetxt(f, combined, delimiter=",", fmt=".9f") + np.savetxt(f, combined, delimiter=",", fmt="%.9f") # fmt for savetxt elapsed_time = time.perf_counter()-tstart - print(f"Runtime: {elapsed_time: .6f} seconds, i.e., {elapsed_time: .6f}/60 min") + print(f"Runtime: {elapsed_time: .6f} seconds, i.e., {elapsed_time/60: .6f} min") # CLOSE AND MOVE BACK ############ # close shutter ! print("close the shutter !") + dev.bcu_shutter.put(0) # move beamstop back ! #umv(dev.bs_y, bs_in) diff --git a/pxii_bec/macros/EvalFlux.py b/pxii_bec/macros/EvalFlux.py new file mode 100644 index 0000000..c8df98a --- /dev/null +++ b/pxii_bec/macros/EvalFlux.py @@ -0,0 +1,69 @@ +def evalflux(): + + from APscripts import read_data_csv, fitpoly + + data=read_data_csv('FLUX_x10sa_20260709_174259.txt') + + einv=data[:, 0] + fcalfinv = data[:, 6] # if energy top down + + + e = einv[::-1] + flcf = fcalfinv[::-1] + + # omit the last values (>= 27 keV) + + len(e) # = 25 + e = e[0:21] + flcf =flcf[0:21]/1.e9 ## divide by 1e9 for better readability + + fitpoly(e, flcf, 3) + + # Polynomial coefficients of the fit fct: 3 [-0.00026213 0.01171065 -0.05379571 0.04478851] + + +def csplinex(x,y,en): + from scipy.interpolate import CubicSpline + + # Create spline + cs = CubicSpline(x, y) + y_cs = cs(en) + return y_cs + + +def flux_bcu(): + e = get_current_energy()/1000. + bcusum = read_av(dev.bcu_bpmsum,10) + flux = fl_bcubpm(e,bcusum) + return f"{flux:.2e}" + +def flux_i1(): + e = get_current_energy()/1000 + i1 = read_av(dev.i1,10) + flux = fl_i1(e, i1) + return f"{flux:.2e}" + +def fl_bcubpm(e,bcusum): + import numpy as np + fact = 1.e9 + coeff = [-0.00026213, 0.01171065, -0.05379571, 0.04478851] + if e > 24 : + coeff = [4.83704287e-05, -3.17174523e-03, 7.33131161e-02, -5.91926617e-01, 1.66572494e+00] + polynomial = np.poly1d(coeff) + fl = polynomial(e) * bcusum * fact + #print(f'flux from {bcusum} with en {e} is {fl:.2e} ph/s') + + return fl + +def fl_i1(e,i1): + import pandas as pd + + file = "luts/I1flcalf.csv" + df = pd.read_csv(file) + a = df["En"] + b = df["Fl/I1"] + + fl_i1 = csplinex(a,b,e) *i1 + print(f'flux from {i1} with en {e} is {fl_i1:.2} ph/s ') + + return fl_i1 diff --git a/pxii_bec/macros/beampos_with_en.py b/pxii_bec/macros/beampos_with_en.py new file mode 100644 index 0000000..39da1dd --- /dev/null +++ b/pxii_bec/macros/beampos_with_en.py @@ -0,0 +1,19 @@ +def beampos_with_en(planner): + deltat = 2 + record_beampos_until("23:00",planner,interval_minutes=deltat) + bl_energy(6000) + record_beampos_until("00:00",planner,interval_minutes=deltat) + bl_energy(8000) + record_beampos_until("01:00",planner,interval_minutes=deltat) + bl_energy(10000) + record_beampos_until("02:00",planner,interval_minutes=deltat) + bl_energy(12000) + record_beampos_until("03:00",planner,interval_minutes=deltat) + bl_energy(12400) + record_beampos_until("04:00",planner,interval_minutes=deltat) + bl_energy(14000) + record_beampos_until("05:00",planner,interval_minutes=deltat) + bl_energy(16000) + record_beampos_until("06:00",planner,interval_minutes=deltat) + bl_energy(18000) + record_beampos_until("07:00",planner,interval_minutes=deltat) diff --git a/pxii_bec/macros/beampos_with_en.py~ b/pxii_bec/macros/beampos_with_en.py~ new file mode 100644 index 0000000..6d89248 --- /dev/null +++ b/pxii_bec/macros/beampos_with_en.py~ @@ -0,0 +1,9 @@ +def beampos_with_en(planner): + deltat = 5 + record_beampos_until("23:00",planner,interval_minutes=deltat) + bl_energy(16000) + record_beampos_until("05:00",planner,interval_minutes=deltat) + bl_energy(12400) + record_beampos_until("11:00",planner,interval_minutes=deltat) + + diff --git a/pxii_bec/macros/calibrate_bpm.py b/pxii_bec/macros/calibrate_bpm.py index e25b0db..ff6c2dc 100644 --- a/pxii_bec/macros/calibrate_bpm.py +++ b/pxii_bec/macros/calibrate_bpm.py @@ -61,7 +61,7 @@ def compute_norm(): (readings["bpm1"] + readings["bpm3"]) - (readings["bpm2"] + readings["bpm4"]) ) / total # return xn, yn, readings["bpm1"], readings["bpm2"], readings["bpm3"], readings["bpm4"] - return xn, yn + return float(xn), float(yn) # def compute_pos(): @@ -83,12 +83,6 @@ def compute_norm(): def run_calibration(): """Scan bpm in x and y and record normalised x and y positions""" - # centred_x = 0.749 - # centred_y = -0.660 - now = datetime.now() - fnow = now.strftime("%d%m%H%M") - centred_x = 0.46 - centred_y = -1.51 print(f"moving bpm to {centred_x}, {centred_y}") umv(dev.bcu_bpm_y, centred_y) umv(dev.bcu_bpm_x, centred_x) @@ -144,527 +138,5 @@ def fit_bpm_data(x_y, rundate="02072130_", bpm_name="bcu_bpm"): return xdata, ydata -def linear_calibration( - x_y, - bpm_motor_position, - crosshair_bpm_signal, - rundate = "05071923_", - bpm_name = "bcu_bpm", - sanity_limit = 0.2, - plot = True -): - calib_dir = "luts/bpm_calib" - xdata, ydata = fit_bpm_data(x_y, rundate = rundate, bpm_name = bpm_name) - # Remove non-linear region - if x_y == 'x': - mask_limit = 0.59 - else: - mask_limit = 0.9 - mask = np.abs(ydata) < mask_limit - xdata = xdata[mask] - ydata = ydata[mask] - m, c = np.polyfit(xdata, ydata, 1) - # --- Plot --- - plt.figure(figsize=(7, 5)) - plt.scatter(xdata, ydata, color="red", label=f"BPM {x_y} data") - - x_fit = np.linspace(min(xdata), max(xdata), 100) - plt.plot(x_fit, m * x_fit + c, "r--", label=f"Fit: Linear") - - plt.xlabel("label") - plt.ylabel("label") - plt.title("title") - plt.legend() - plt.grid(True) - plt.tight_layout() - plt.show() - -def make_inverse_spline_calibration( - x_y, - bpm_motor_position, - crosshair_bpm_signal, - rundate="05071923_", - bpm_name="bcu_bpm", - sanity_limit=0.2, - plot=True, -): - """ - Create and save inverse BPM calibration. - - Parameters - ---------- - x_y : str - "x" or "y" - bpm_motor_position : float - Current physical BPM motor position during calibration. - crosshair_bpm_signal : float - Normalised BPM reading when the beam is on the sample-camera crosshair. - mask_limit : float - Ignore saturated BPM readings outside +/- mask_limit. - sanity_limit : float - Warn later if BPM motor has moved by more than this. - """ - CALIB_DIR = "luts/bpm_calib/" - xdata, ydata = fit_bpm_data(x_y, rundate=rundate, bpm_name=bpm_name) - - # Remove saturated BPM response - if x_y == 'x': - mask_limit = 0.98 - else: - mask_limit = 0.91 - mask = np.abs(ydata) < mask_limit - xdata = xdata[mask] - ydata = ydata[mask] - - # For inverse calibration: BPM signal -> beam position - order = np.argsort(ydata) - bpm_signal = ydata[order] - local_position = xdata[order] - - # Remove duplicate BPM signal values - bpm_signal, unique_idx = np.unique(bpm_signal, return_index=True) - local_position = local_position[unique_idx] - - spline = PchipInterpolator(bpm_signal, local_position) - - # Local beam position when beam is visually on camera crosshair - crosshair_local_position = float(spline(crosshair_bpm_signal)) - - # Absolute beamline coordinate of camera crosshair - crosshair_absolute_position = bpm_motor_position + crosshair_local_position - - save_file = os.path.join(CALIB_DIR, f"{bpm_name}_{x_y}_inverse_spline.npz") - - np.savez( - save_file, - bpm_signal=bpm_signal, - local_position=local_position, - bpm_motor_position=bpm_motor_position, - crosshair_bpm_signal=crosshair_bpm_signal, - crosshair_local_position=crosshair_local_position, - crosshair_absolute_position=crosshair_absolute_position, - mask_limit=mask_limit, - sanity_limit=sanity_limit, - ) - - print(f"Saved {x_y} BPM calibration to:") - print(save_file) - print() - print(f"Calibration BPM motor position: {bpm_motor_position:.6f}") - print(f"Crosshair BPM signal: {crosshair_bpm_signal:.6f}") - print(f"Crosshair local position: {crosshair_local_position:.6f}") - print(f"Crosshair absolute position: {crosshair_absolute_position:.6f}") - - if plot: - signal_fit = np.linspace(np.min(bpm_signal), np.max(bpm_signal), 1000) - pos_fit = spline(signal_fit) - - plt.figure() - plt.scatter(ydata, xdata, label="calibration data") - plt.plot(signal_fit, pos_fit, label="inverse PCHIP spline", color='red') - plt.axvline(crosshair_bpm_signal, linestyle="--", label="camera crosshair") - plt.xlabel(f"{bpm_name}_{x_y} normalised signal") - plt.ylabel(f"{x_y} local beam position") - plt.title(f"{bpm_name}_{x_y} inverse calibration") - plt.grid(True) - plt.legend() - plt.show() - - return save_file - -class BPMCalibration: - def __init__(self, filename): - data = np.load(filename) - - self.bpm_signal = data["bpm_signal"] - self.local_position = data["local_position"] - - self.bpm_motor_position_calib = float(data["bpm_motor_position"]) - self.crosshair_absolute_position = float(data["crosshair_absolute_position"]) - self.sanity_limit = float(data["sanity_limit"]) - - self.spline = PchipInterpolator( - self.bpm_signal, - self.local_position, - ) - - def beam_position(self, bpm_signal, bpm_motor_position, warn=True): - """ - Return beam position relative to the sample-camera crosshair. - """ - - motor_shift = bpm_motor_position - self.bpm_motor_position_calib - - if warn and abs(motor_shift) > self.sanity_limit: - print( - "Warning: BPM motor has moved since calibration: " - f"delta = {motor_shift:.3f} mm" - ) - - local_beam_position = float(self.spline(bpm_signal)) - absolute_beam_position = bpm_motor_position + local_beam_position - - relative_to_crosshair = ( - absolute_beam_position - self.crosshair_absolute_position - ) - - return relative_to_crosshair - -def get_beampos(): - x_cal = BPMCalibration("luts/bpm_calib/bcu_bpm_x_inverse_spline.npz") - y_cal = BPMCalibration("luts/bpm_calib/bcu_bpm_y_inverse_spline.npz") - - bpm_x_signal, bpm_y_signal = compute_norm() - - beam_x = x_cal.beam_position( - bpm_signal=bpm_x_signal, - bpm_motor_position=dev.bcu_bpm_x.position, - ) - - beam_y = y_cal.beam_position( - bpm_signal=bpm_y_signal, - bpm_motor_position=dev.bcu_bpm_y.position, - ) - - beam_x_mic = 1000 * beam_x - beam_y_mic = 1000 * beam_y - - print(f"Beam relative to camera crosshair:") - print(f"X = {beam_x_mic:.4f} um") - print(f"Y = {beam_y_mic:.4f} um") - - return beam_x_mic, beam_y_mic - -#!/usr/bin/env python -"""Calculate photon flux from a Si diode current.""" - -import math -from dataclasses import dataclass - -import numpy as np - - -@dataclass -class PXIIDiodeConfig: - """Diode/beamline-specific constants.""" - - si_thickness_um: float = 12.0 - al_thickness_um: float = 20.0 - diode_offset_mm: float = 15.0 - - si_density: float = 2.33 # g/cm^3 - al_density: float = 2.699 # g/cm^3 - air_density: float = 1.205e-3 # g/cm^3 - - eps_si: float = 3.62 # eV per electron-hole pair - - -def flux( - current_a: float, - energy_kev: float | None = None, - det_z: float | None = None, - config = PXIIDiodeConfig, -) -> float: - """ - Calculate photon flux from Si diode current. - - Parameters - ---------- - current_a: - Diode current in A. - energy_kev: - Beam energy in keV. Will use the current energy if - not specified. - det_z: - Detector distance (dev.det_z) (mm). Will use the current - detector distance if not specified. - config: - DiodeConfig containing Si/Al thicknesses and material constants. - - Returns - ------- - float - Flux in photons/s. - """ - if energy_kev is None: - energy_kev = get_current_energy() / 1000 - - if det_z is None: - det_z = dev.det_z.position - - air_path_mm = det_z + config.diode_offset_mm - - si_thickness_cm = config.si_thickness_um / 10_000.0 - al_thickness_cm = config.al_thickness_um / 10_000.0 - - log_energy = math.log10(energy_kev) - - # Photoelectric mass attenuation coefficient fits - si_poly = np.poly1d([0.0789, -0.477, -2.238, 4.158]) - al_poly = np.poly1d([0.0638, -0.413, -2.349, 4.106]) - air_poly = np.poly1d([0.928, -2.348, -1.026, 3.153]) - - a_si = 10 ** si_poly(log_energy) - a_al = 10 ** al_poly(log_energy) - a_air = 10 ** air_poly(log_energy) - - # Fraction of beam absorbed in active Si layer - si_absorbed_fraction = -np.expm1( - -a_si * config.si_density * si_thickness_cm - ) - - if si_absorbed_fraction <= 0: - raise ValueError("Calculated Si absorption fraction is zero or negative.") - - # Flux before Al/air correction - flux = ( - 1000.0 - * current_a - * config.eps_si - / 1.602 - / energy_kev - / si_absorbed_fraction - * 1.0e13 - ) - - # Transmission through Al and air - al_transmission = np.exp( - -a_al * config.al_density * al_thickness_cm - ) - - air_transmission = np.exp( - -a_air * config.air_density * air_path_mm / 10.0 - ) - - flux /= al_transmission - flux /= air_transmission - - - print(f"Flux = {flux: .3g} ph/s") - - return float(flux) - -def calibrate_bpm_flux(ave = 5): - # d['det_z'].move('mse') - # d['det_y'].move('xi') - # d['det_z'].move(200) - - dir = "luts/bpm_calib/" - filename = dir + "bpm_flux_20260708b.csv" - with open(filename, 'w', encoding="utf-8") as f: - f.write("Energy,Transmission,BPMSum,Flux\n") - print("Energy,Transmission,BPMSum,Flux\n") - energies = [12400,7000,8000,9000,10000,11000,13000,14000,15000,16000,18000,20000,25000] - transmissions = [1, 0.9, 0.8, 0.7, 0.6, 0.5,0.4,0.3,0.2,0.1] - - for energy in energies: - print(f"Moving to energy {energy}") - bl_energy(energy) - - for set_trans in transmissions: - print(f"Setting transmission to {set_trans}") - dev.transm.put(set_trans) - time.sleep(5) - - flux_values = [] - bpm_values = [] - - print(f"Measuring flux and bpmsum") - for _ in range(ave): - diode_current = dev.xidiode.read()['xidiode']['value'] - fl = flux(diode_current) - bpmsum = dev.bcu_bpmsum.read()['bcu_bpmsum']['value'] - flux_values.append(fl) - bpm_values. append(bpmsum) - - actual_trans = dev.transm.read()['transm']['value'] - flux_ave = np.mean(flux_values) - bpmsum_ave = np.mean(bpm_values) - print(f"{energy:.5g},{actual_trans:.3g},{bpmsum_ave:.4g},{flux_ave:.4f}\n") - - with open(filename, 'a') as f: - f.write(f"{energy:.5g},{actual_trans:.3g},{bpmsum_ave:.4g},{flux_ave:.4f}\n") - bl_energy(12400) - umv(dev.det_y, 70) - umv(dev.id_gap, 20) - -def analyse_bpm_flux_calibration( - filename="luts/bpm_calib/bpm_flux_20260708b.csv", - force_zero_intercept=False, -): - data = pd.read_csv(filename) - - results = [] - with open("luts/bpm_calib/bpm_flux_fits.csv", "w") as f: - f.write("Energy,Slope,Intercept\n") - for energy, group in data.groupby("Energy"): - x = group["BPMSum"].to_numpy(dtype=float) - print(f"x is {x}") - y = group["Flux"].to_numpy(dtype=float) - - if force_zero_intercept: - # y = m*x - slope = np.sum(x * y) / np.sum(x * x) - intercept = 0.0 - else: - # y = m*x + c - slope, intercept = np.polyfit(x, y, deg=1) - - y_fit = slope * x + intercept - - # --- Plot --- - plt.figure(figsize=(7, 5)) - plt.scatter(x, y, color="red") - - x_fit = np.linspace(min(x), max(x), 100) - plt.plot(x_fit, slope * x_fit + intercept, - "r--", label=f"Fit: Slope = {slope:.5g}, Intercept = {intercept:.5g}") - - plt.xlabel("BPMSUm") - plt.ylabel("Flux") - plt.title(f"{energy} eV") - plt.legend() - plt.grid(True) - plt.tight_layout() - plt.savefig(f"luts/bpm_calib/{energy}_bpm_flux") - # plt.show() - - residuals = y - y_fit - ss_res = np.sum(residuals**2) - ss_tot = np.sum((y - np.mean(y))**2) - - r2 = 1 - ss_res / ss_tot if ss_tot > 0 else np.nan - - results.append( - { - "Energy": energy, - "Slope": f"{slope:.5g}", - "Intercept": f"{intercept:.5g}", - "R2": f"{r2:.3g}", - # "N": len(group), - } - ) - - results = pd.DataFrame(results) - - results.to_csv("luts/bpm_calib/bpm_flux_fits.csv", index=False) - dict = results.to_dict() - print(dict) - return results - -def linear_bpm_flux_calib(): - filename = 'luts/bpm_calib/fits-25.csv' - df = pd.read_csv(filename) - energies = df["Energy"].to_numpy() - intercepts = df["Intercept"].to_numpy() - slopes = df["Slope"].to_numpy() - # --- Plot --- - plt.figure(figsize=(7, 5)) - plt.scatter(energies, slopes, color="red") - - x_fit = np.linspace(min(energies), max(energies), 100) - coeffs = np.polyfit(energies, slopes,1) - y_fit = np.poly1d(coeffs) - plt.plot(x_fit, y_fit(x_fit)), - plt.xlabel("Energy eV") - plt.ylabel("Slope") - plt.title(f"Energies vs slopes, coeffs = {coeffs}") - # plt.legend() - plt.grid(True) - plt.tight_layout() - plt.savefig(f"luts/bpm_calib/slopes_vs_energy") - plt.show() - return coeffs - - -# def get_flux_calibration(energy): -# # filename = "luts/bpm_calib/bpm_flux_fits.csv" -# filename = 'luts/bpm_calib/fits-25.csv' -# default_slope = 4.42e8 -# default_intercept = -1.66e11 - -# try: -# df = pd.read_csv(filename) -# energies = df["Energy"].to_numpy() -# intercepts = df["Intercept"].to_numpy() -# slopes = df["Slope"].to_numpy() -# slope_interp = CubicSpline(energies, slopes) -# intercept_interp = CubicSpline(energies, intercepts) -# slope = slope_interp(energy) -# intercept = intercept_interp(energy) -# print(f"Using data from calibration file") -# # --- Plot --- -# plt.figure(figsize=(7, 5)) -# plt.scatter(energies, slopes, color="red") - -# x_fit = np.linspace(min(energies), max(energies), 100) -# coeffs = np.polyfit(energies, slopes,1) -# print("linear co-efficients: ", coeffs) -# y_fit = np.poly1d(coeffs) -# plt.plot(x_fit, y_fit(x_fit)), -# # "r--", label=f"Fit: Slope = {slope:.5g}, Intercept = {intercept:.5g}") - -# plt.xlabel("Energy") -# plt.ylabel("Slope") -# plt.title(f"{energy} eV") -# # plt.legend() -# plt.grid(True) -# plt.tight_layout() -# plt.show() -# except FileNotFoundError: -# print("Cannot access calibration file, using default parameters") -# slope = default_slope -# intercept = default_intercept - -# return coeffs - - -def bpm2flux(energy=None, bpmsum=None, transm=None): - """ - Calculate the flux from BCU BPM reading. - Option to provide energy, bpmsum reading and transmission. - If these are not given, the current values are used. - - Returns the flux at the sample (after attenuators) and a calculated - value of the full flux if attenuation was 0. - - """ - calibration_min_energy = 6500 - calibration_max_energy = 21000 - - if energy is None: - energy = get_current_energy() - - if bpmsum is None: - bpmsum = dev.bcu_bpmsum.read()["bcu_bpmsum"]["value"] - - if transm is None: - transm = dev.transm.read()['transm']['value'] - - if not calibration_min_energy <= energy <= calibration_max_energy: - raise ValueError( - f"Energy {energy:.0f} eV is outside the calibrated range " - f"{calibration_min_energy:.0f}–" - f"{calibration_max_energy:.0f} eV" - ) - - coeffs = [ - 1.06436277e5, - -6.38943746e8, - ] - - calibration_factor = np.polyval(coeffs, energy) - flux = calibration_factor * bpmsum - full_flux = flux/transm - if transm == 1: - print(f"Transmission = {transm*100:.5g} %, Flux = {flux: .3g} ph/s,\n") - else: - print(f"Transmission = {transm*100: .5g} %, Flux = {flux: .3g} ph/s,\n" - f"Flux with 100 % transmission would be {full_flux: .3g} ph/s") - - return float(flux), float(full_flux) - - - diff --git a/pxii_bec/macros/calibrate_bpm.py.bak b/pxii_bec/macros/calibrate_bpm.py.bak new file mode 100644 index 0000000..7ad0ad5 --- /dev/null +++ b/pxii_bec/macros/calibrate_bpm.py.bak @@ -0,0 +1,670 @@ +""" +BPM calibration using inverse PCHIP spline. + +Calibration concept: + BPM signal -> beam position relative to BPM + +Final beam position: + beam_absolute = bpm_motor_position + local_beam_position + beam_relative_to_camera_crosshair = beam_absolute - camera_crosshair_position +""" + +import time +import os +from datetime import datetime, timedelta +from pathlib import Path +import numpy as np +import pandas as pd +import matplotlib.pyplot as plt +from pyparsing import results +from scipy.optimize import curve_fit +import scipy.special as special +from scipy.interpolate import PchipInterpolator, CubicSpline + + +def read_currents(): + """Read the individual bpm channels""" + vals_bpm1 = [] + vals_bpm2 = [] + vals_bpm3 = [] + vals_bpm4 = [] + + for _ in range(5): + vals_bpm1.append(dev.bcu_bpm1.read()["bcu_bpm1"]["value"]) + time.sleep(0.1) + for _ in range(5): + vals_bpm2.append(dev.bcu_bpm2.read()["bcu_bpm2"]["value"]) + time.sleep(0.1) + for _ in range(5): + vals_bpm3.append(dev.bcu_bpm3.read()["bcu_bpm3"]["value"]) + time.sleep(0.1) + for _ in range(5): + vals_bpm4.append(dev.bcu_bpm4.read()["bcu_bpm4"]["value"]) + time.sleep(0.1) + bpm1 = np.mean(vals_bpm1) + bpm2 = np.mean(vals_bpm2) + bpm3 = np.mean(vals_bpm3) + bpm4 = np.mean(vals_bpm4) + + return {"bpm1": bpm1, "bpm2": bpm2, "bpm3": bpm3, "bpm4": bpm4} + + +def compute_norm(): + """Compute normalised x and y positions""" + readings = read_currents() + total = readings["bpm1"] + readings["bpm2"] + readings["bpm3"] + readings["bpm4"] + # print(f"Sum is {total:.2f}") + xn = ( + (readings["bpm1"] + readings["bpm2"]) - (readings["bpm3"] + readings["bpm4"]) + ) / total + yn = ( + (readings["bpm1"] + readings["bpm3"]) - (readings["bpm2"] + readings["bpm4"]) + ) / total + # return xn, yn, readings["bpm1"], readings["bpm2"], readings["bpm3"], readings["bpm4"] + return float(xn), float(yn) + + +# def compute_pos(): +# """Compute the beam x and y positions""" +# cal = { +# "bcu_bpm": { +# "x_slope": 7.778, +# "x_off": -1.019, +# "y_slope": -8.625, +# "y_off": -1.935, +# } +# } +# xn, yn, bpm1, bpm2, bpm3, bpm4 = compute_norm() +# # print(f"Normalised positions are {xn}, {yn}") +# x_pos = (xn - cal["bcu_bpm"]["x_off"]) / cal["bcu_bpm"]["x_slope"] +# y_pos = (yn - cal["bcu_bpm"]["y_off"]) / cal["bcu_bpm"]["y_slope"] +# return x_pos, y_pos + + +def run_calibration(): + """Scan bpm in x and y and record normalised x and y positions""" + # centred_x = 0.749 + # centred_y = -0.660 + now = datetime.now() + fnow = now.strftime("%d%m%H%M") + centred_x = 0.46 + centred_y = -1.51 + print(f"moving bpm to {centred_x}, {centred_y}") + umv(dev.bcu_bpm_y, centred_y) + umv(dev.bcu_bpm_x, centred_x) + + # # Calibrate in X + umv(dev.ss_sl_xsize,0.02) + umv(dev.ss_sl_xsize, 3.0) + filename = f"luts/bpm_calib/{fnow}_bcu_bpm_x.csv" + xn_data = [] + x_positions = np.linspace(centred_x - 0.6, centred_x + 0.6, 101) + with open(filename, "w", encoding="utf-8") as f: + f.write(f"Xpos,Xnorm,BPM1,BPM2,BPM3,BPM4\n") + for x in x_positions: + umv(dev.bcu_bpm_x, x) + print(f"Moving BPM to {x} mm") + time.sleep(0.2) + xn, yn, bpm1, bpm2, bpm3, bpm4 = compute_norm() + xn_data.append(xn) + with open(filename, "a", encoding="utf-8") as f: + f.write(f"{x},{xn},{bpm1},{bpm2},{bpm3},{bpm4}\n") + + # Calibrate in Y + umv(dev.bcu_bpm_x, centred_x) + umv(dev.ss_sl_xsize, 3.0) + umv(dev.ss_sl_ysize, 0.03) + filename = f"luts/bpm_calib/{fnow}_bcu_bpm_y.csv" + y_positions = np.linspace(centred_y - 0.1, centred_y + 0.1, 251) + yn_data = [] + with open(filename, "w", encoding="utf-8") as f: + f.write(f"Ypos,Ynorm,BPM1,BPM2,BPM3,BPM4\n") + for y in y_positions: + umv(dev.bcu_bpm_y, y) + print(f"Moving BPM to {y} mm") + time.sleep(0.2) + xn, yn, bpm1, bpm2, bpm3, bpm4 = compute_norm() + yn_data.append(yn) + with open(filename, "a", encoding="utf-8") as f: + f.write(f"{y},{yn},{bpm1},{bpm2},{bpm3},{bpm4}\n") + + umv(dev.bcu_bpm_x, centred_x) + umv(dev.bcu_bpm_y, centred_y) + umv(dev.ss_sl_ysize, 3.0) + + + +def fit_bpm_data(x_y, rundate="02072130_", bpm_name="bcu_bpm"): + CALIB_DIR = "luts/bpm_calib/" + filename = os.path.join(CALIB_DIR, f"{rundate}{bpm_name}_{x_y}.csv") + data = np.loadtxt(filename, delimiter=",", skiprows=1) + + xdata = data[:, 0] # scan / motor position + ydata = data[:, 1] # normalised BPM signal + + return xdata, ydata + +def linear_calibration( + x_y, + bpm_motor_position, + crosshair_bpm_signal, + rundate = "05071923_", + bpm_name = "bcu_bpm", + sanity_limit = 0.2, + plot = True +): + calib_dir = "luts/bpm_calib" + xdata, ydata = fit_bpm_data(x_y, rundate = rundate, bpm_name = bpm_name) + # Remove non-linear region + if x_y == 'x': + mask_limit = 0.59 + else: + mask_limit = 0.9 + mask = np.abs(ydata) < mask_limit + xdata = xdata[mask] + ydata = ydata[mask] + + m, c = np.polyfit(xdata, ydata, 1) + + # --- Plot --- + plt.figure(figsize=(7, 5)) + plt.scatter(xdata, ydata, color="red", label=f"BPM {x_y} data") + + x_fit = np.linspace(min(xdata), max(xdata), 100) + plt.plot(x_fit, m * x_fit + c, "r--", label=f"Fit: Linear") + + plt.xlabel("label") + plt.ylabel("label") + plt.title("title") + plt.legend() + plt.grid(True) + plt.tight_layout() + plt.show() + +def make_inverse_spline_calibration( + x_y, + bpm_motor_position, + crosshair_bpm_signal, + rundate="05071923_", + bpm_name="bcu_bpm", + sanity_limit=0.2, + plot=True, +): + """ + Create and save inverse BPM calibration. + + Parameters + ---------- + x_y : str + "x" or "y" + bpm_motor_position : float + Current physical BPM motor position during calibration. + crosshair_bpm_signal : float + Normalised BPM reading when the beam is on the sample-camera crosshair. + mask_limit : float + Ignore saturated BPM readings outside +/- mask_limit. + sanity_limit : float + Warn later if BPM motor has moved by more than this. + """ + CALIB_DIR = "luts/bpm_calib/" + xdata, ydata = fit_bpm_data(x_y, rundate=rundate, bpm_name=bpm_name) + + # Remove saturated BPM response + if x_y == 'x': + mask_limit = 0.98 + else: + mask_limit = 0.91 + mask = np.abs(ydata) < mask_limit + xdata = xdata[mask] + ydata = ydata[mask] + + # For inverse calibration: BPM signal -> beam position + order = np.argsort(ydata) + bpm_signal = ydata[order] + local_position = xdata[order] + + # Remove duplicate BPM signal values + bpm_signal, unique_idx = np.unique(bpm_signal, return_index=True) + local_position = local_position[unique_idx] + + spline = PchipInterpolator(bpm_signal, local_position) + + # Local beam position when beam is visually on camera crosshair + crosshair_local_position = float(spline(crosshair_bpm_signal)) + + # Absolute beamline coordinate of camera crosshair + crosshair_absolute_position = bpm_motor_position + crosshair_local_position + + save_file = os.path.join(CALIB_DIR, f"{bpm_name}_{x_y}_inverse_spline.npz") + + np.savez( + save_file, + bpm_signal=bpm_signal, + local_position=local_position, + bpm_motor_position=bpm_motor_position, + crosshair_bpm_signal=crosshair_bpm_signal, + crosshair_local_position=crosshair_local_position, + crosshair_absolute_position=crosshair_absolute_position, + mask_limit=mask_limit, + sanity_limit=sanity_limit, + ) + + print(f"Saved {x_y} BPM calibration to:") + print(save_file) + print() + print(f"Calibration BPM motor position: {bpm_motor_position:.6f}") + print(f"Crosshair BPM signal: {crosshair_bpm_signal:.6f}") + print(f"Crosshair local position: {crosshair_local_position:.6f}") + print(f"Crosshair absolute position: {crosshair_absolute_position:.6f}") + + if plot: + signal_fit = np.linspace(np.min(bpm_signal), np.max(bpm_signal), 1000) + pos_fit = spline(signal_fit) + + plt.figure() + plt.scatter(ydata, xdata, label="calibration data") + plt.plot(signal_fit, pos_fit, label="inverse PCHIP spline", color='red') + plt.axvline(crosshair_bpm_signal, linestyle="--", label="camera crosshair") + plt.xlabel(f"{bpm_name}_{x_y} normalised signal") + plt.ylabel(f"{x_y} local beam position") + plt.title(f"{bpm_name}_{x_y} inverse calibration") + plt.grid(True) + plt.legend() + plt.show() + + return save_file + +class BPMCalibration: + def __init__(self, filename): + data = np.load(filename) + + self.bpm_signal = data["bpm_signal"] + self.local_position = data["local_position"] + + self.bpm_motor_position_calib = float(data["bpm_motor_position"]) + self.crosshair_absolute_position = float(data["crosshair_absolute_position"]) + self.sanity_limit = float(data["sanity_limit"]) + + self.spline = PchipInterpolator( + self.bpm_signal, + self.local_position, + ) + + def beam_position(self, bpm_signal, bpm_motor_position, warn=True): + """ + Return beam position relative to the sample-camera crosshair. + """ + + motor_shift = bpm_motor_position - self.bpm_motor_position_calib + + if warn and abs(motor_shift) > self.sanity_limit: + print( + "Warning: BPM motor has moved since calibration: " + f"delta = {motor_shift:.3f} mm" + ) + + local_beam_position = float(self.spline(bpm_signal)) + absolute_beam_position = bpm_motor_position + local_beam_position + + relative_to_crosshair = ( + absolute_beam_position - self.crosshair_absolute_position + ) + + return relative_to_crosshair + +def get_beampos(): + x_cal = BPMCalibration("luts/bpm_calib/bcu_bpm_x_inverse_spline.npz") + y_cal = BPMCalibration("luts/bpm_calib/bcu_bpm_y_inverse_spline.npz") + + bpm_x_signal, bpm_y_signal = compute_norm() + + beam_x = x_cal.beam_position( + bpm_signal=bpm_x_signal, + bpm_motor_position=dev.bcu_bpm_x.position, + ) + + beam_y = y_cal.beam_position( + bpm_signal=bpm_y_signal, + bpm_motor_position=dev.bcu_bpm_y.position, + ) + + beam_x_mic = 1000 * beam_x + beam_y_mic = 1000 * beam_y + + print(f"Beam relative to camera crosshair:") + print(f"X = {beam_x_mic:.4f} um") + print(f"Y = {beam_y_mic:.4f} um") + + return beam_x_mic, beam_y_mic + +#!/usr/bin/env python +"""Calculate photon flux from a Si diode current.""" + +import math +from dataclasses import dataclass + +import numpy as np + + +@dataclass +class PXIIDiodeConfig: + """Diode/beamline-specific constants.""" + + si_thickness_um: float = 12.0 + al_thickness_um: float = 20.0 + diode_offset_mm: float = 15.0 + + si_density: float = 2.33 # g/cm^3 + al_density: float = 2.699 # g/cm^3 + air_density: float = 1.205e-3 # g/cm^3 + + eps_si: float = 3.62 # eV per electron-hole pair + + +def flux( + current_a: float, + energy_kev: float | None = None, + det_z: float | None = None, + config = PXIIDiodeConfig, +) -> float: + """ + Calculate photon flux from Si diode current. + + Parameters + ---------- + current_a: + Diode current in A. + energy_kev: + Beam energy in keV. Will use the current energy if + not specified. + det_z: + Detector distance (dev.det_z) (mm). Will use the current + detector distance if not specified. + config: + DiodeConfig containing Si/Al thicknesses and material constants. + + Returns + ------- + float + Flux in photons/s. + """ + if energy_kev is None: + energy_kev = get_current_energy() / 1000 + + if det_z is None: + det_z = dev.det_z.position + + air_path_mm = det_z + config.diode_offset_mm + + si_thickness_cm = config.si_thickness_um / 10_000.0 + al_thickness_cm = config.al_thickness_um / 10_000.0 + + log_energy = math.log10(energy_kev) + + # Photoelectric mass attenuation coefficient fits + si_poly = np.poly1d([0.0789, -0.477, -2.238, 4.158]) + al_poly = np.poly1d([0.0638, -0.413, -2.349, 4.106]) + air_poly = np.poly1d([0.928, -2.348, -1.026, 3.153]) + + a_si = 10 ** si_poly(log_energy) + a_al = 10 ** al_poly(log_energy) + a_air = 10 ** air_poly(log_energy) + + # Fraction of beam absorbed in active Si layer + si_absorbed_fraction = -np.expm1( + -a_si * config.si_density * si_thickness_cm + ) + + if si_absorbed_fraction <= 0: + raise ValueError("Calculated Si absorption fraction is zero or negative.") + + # Flux before Al/air correction + flux = ( + 1000.0 + * current_a + * config.eps_si + / 1.602 + / energy_kev + / si_absorbed_fraction + * 1.0e13 + ) + + # Transmission through Al and air + al_transmission = np.exp( + -a_al * config.al_density * al_thickness_cm + ) + + air_transmission = np.exp( + -a_air * config.air_density * air_path_mm / 10.0 + ) + + flux /= al_transmission + flux /= air_transmission + + + print(f"Flux = {flux: .3g} ph/s") + + return float(flux) + +def calibrate_bpm_flux(ave = 5): + # d['det_z'].move('mse') + # d['det_y'].move('xi') + # d['det_z'].move(200) + + dir = "luts/bpm_calib/" + filename = dir + "bpm_flux_20260708b.csv" + with open(filename, 'w', encoding="utf-8") as f: + f.write("Energy,Transmission,BPMSum,Flux\n") + print("Energy,Transmission,BPMSum,Flux\n") + energies = [12400,7000,8000,9000,10000,11000,13000,14000,15000,16000,18000,20000,25000] + transmissions = [1, 0.9, 0.8, 0.7, 0.6, 0.5,0.4,0.3,0.2,0.1] + + for energy in energies: + print(f"Moving to energy {energy}") + bl_energy(energy) + + for set_trans in transmissions: + print(f"Setting transmission to {set_trans}") + dev.transm.put(set_trans) + time.sleep(5) + + flux_values = [] + bpm_values = [] + + print(f"Measuring flux and bpmsum") + for _ in range(ave): + diode_current = dev.xidiode.read()['xidiode']['value'] + fl = flux(diode_current) + bpmsum = dev.bcu_bpmsum.read()['bcu_bpmsum']['value'] + flux_values.append(fl) + bpm_values. append(bpmsum) + + actual_trans = dev.transm.read()['transm']['value'] + flux_ave = np.mean(flux_values) + bpmsum_ave = np.mean(bpm_values) + print(f"{energy:.5g},{actual_trans:.3g},{bpmsum_ave:.4g},{flux_ave:.4f}\n") + + with open(filename, 'a') as f: + f.write(f"{energy:.5g},{actual_trans:.3g},{bpmsum_ave:.4g},{flux_ave:.4f}\n") + bl_energy(12400) + umv(dev.det_y, 70) + umv(dev.id_gap, 20) + +def analyse_bpm_flux_calibration( + filename="luts/bpm_calib/bpm_flux_20260708b.csv", + force_zero_intercept=False, +): + data = pd.read_csv(filename) + + results = [] + with open("luts/bpm_calib/bpm_flux_fits.csv", "w") as f: + f.write("Energy,Slope,Intercept\n") + for energy, group in data.groupby("Energy"): + x = group["BPMSum"].to_numpy(dtype=float) + print(f"x is {x}") + y = group["Flux"].to_numpy(dtype=float) + + if force_zero_intercept: + # y = m*x + slope = np.sum(x * y) / np.sum(x * x) + intercept = 0.0 + else: + # y = m*x + c + slope, intercept = np.polyfit(x, y, deg=1) + + y_fit = slope * x + intercept + + # --- Plot --- + plt.figure(figsize=(7, 5)) + plt.scatter(x, y, color="red") + + x_fit = np.linspace(min(x), max(x), 100) + plt.plot(x_fit, slope * x_fit + intercept, + "r--", label=f"Fit: Slope = {slope:.5g}, Intercept = {intercept:.5g}") + + plt.xlabel("BPMSUm") + plt.ylabel("Flux") + plt.title(f"{energy} eV") + plt.legend() + plt.grid(True) + plt.tight_layout() + plt.savefig(f"luts/bpm_calib/{energy}_bpm_flux") + # plt.show() + + residuals = y - y_fit + ss_res = np.sum(residuals**2) + ss_tot = np.sum((y - np.mean(y))**2) + + r2 = 1 - ss_res / ss_tot if ss_tot > 0 else np.nan + + results.append( + { + "Energy": energy, + "Slope": f"{slope:.5g}", + "Intercept": f"{intercept:.5g}", + "R2": f"{r2:.3g}", + # "N": len(group), + } + ) + + results = pd.DataFrame(results) + + results.to_csv("luts/bpm_calib/bpm_flux_fits.csv", index=False) + dict = results.to_dict() + print(dict) + return results + +def linear_bpm_flux_calib(): + filename = 'luts/bpm_calib/fits-25.csv' + df = pd.read_csv(filename) + energies = df["Energy"].to_numpy() + intercepts = df["Intercept"].to_numpy() + slopes = df["Slope"].to_numpy() + # --- Plot --- + plt.figure(figsize=(7, 5)) + plt.scatter(energies, slopes, color="red") + + x_fit = np.linspace(min(energies), max(energies), 100) + coeffs = np.polyfit(energies, slopes,1) + y_fit = np.poly1d(coeffs) + plt.plot(x_fit, y_fit(x_fit)), + plt.xlabel("Energy eV") + plt.ylabel("Slope") + plt.title(f"Energies vs slopes, coeffs = {coeffs}") + # plt.legend() + plt.grid(True) + plt.tight_layout() + plt.savefig(f"luts/bpm_calib/slopes_vs_energy") + plt.show() + return coeffs + + +# def get_flux_calibration(energy): +# # filename = "luts/bpm_calib/bpm_flux_fits.csv" +# filename = 'luts/bpm_calib/fits-25.csv' +# default_slope = 4.42e8 +# default_intercept = -1.66e11 + +# try: +# df = pd.read_csv(filename) +# energies = df["Energy"].to_numpy() +# intercepts = df["Intercept"].to_numpy() +# slopes = df["Slope"].to_numpy() +# slope_interp = CubicSpline(energies, slopes) +# intercept_interp = CubicSpline(energies, intercepts) +# slope = slope_interp(energy) +# intercept = intercept_interp(energy) +# print(f"Using data from calibration file") +# # --- Plot --- +# plt.figure(figsize=(7, 5)) +# plt.scatter(energies, slopes, color="red") + +# x_fit = np.linspace(min(energies), max(energies), 100) +# coeffs = np.polyfit(energies, slopes,1) +# print("linear co-efficients: ", coeffs) +# y_fit = np.poly1d(coeffs) +# plt.plot(x_fit, y_fit(x_fit)), +# # "r--", label=f"Fit: Slope = {slope:.5g}, Intercept = {intercept:.5g}") + +# plt.xlabel("Energy") +# plt.ylabel("Slope") +# plt.title(f"{energy} eV") +# # plt.legend() +# plt.grid(True) +# plt.tight_layout() +# plt.show() +# except FileNotFoundError: +# print("Cannot access calibration file, using default parameters") +# slope = default_slope +# intercept = default_intercept + +# return coeffs + + +def bpm2flux(energy=None, bpmsum=None, transm=None): + """ + Calculate the flux from BCU BPM reading. + Option to provide energy, bpmsum reading and transmission. + If these are not given, the current values are used. + + Returns the flux at the sample (after attenuators) and a calculated + value of the full flux if attenuation was 0. + + """ + calibration_min_energy = 6500 + calibration_max_energy = 21000 + + if energy is None: + energy = get_current_energy() + + if bpmsum is None: + bpmsum = dev.bcu_bpmsum.read()["bcu_bpmsum"]["value"] + + if transm is None: + transm = dev.transm.read()['transm']['value'] + + if not calibration_min_energy <= energy <= calibration_max_energy: + raise ValueError( + f"Energy {energy:.0f} eV is outside the calibrated range " + f"{calibration_min_energy:.0f}–" + f"{calibration_max_energy:.0f} eV" + ) + + coeffs = [ + 1.06436277e5, + -6.38943746e8, + ] + + calibration_factor = np.polyval(coeffs, energy) + flux = calibration_factor * bpmsum + full_flux = flux/transm + if transm == 1: + print(f"Transmission = {transm*100:.5g} %, Flux = {flux: .3g} ph/s,\n") + else: + print(f"Transmission = {transm*100: .5g} %, Flux = {flux: .3g} ph/s,\n" + f"Flux with 100 % transmission would be {full_flux: .3g} ph/s") + + return float(flux), float(full_flux) + + + diff --git a/pxii_bec/macros/enScan.py b/pxii_bec/macros/enScan.py new file mode 100644 index 0000000..e81b00d --- /dev/null +++ b/pxii_bec/macros/enScan.py @@ -0,0 +1,83 @@ +def en_plothist(hindex: int, signal_name: str, isave=1): + """ + Get data for a completed scan from the BEC history, + and plot all the results. + + Args: + history_index (int): scan to fetch, e.g. -1 for the most recent scan + signal_name (str): the monitor + + Example: + s=scans.line_scan(dev.dcm_bragg, 178.5, 179.5, steps=240, relative=False + data_x, data_y = en_plothist(-1,"bcu_bpmsum") + + scanned with + scans.line_scan(dev.aerotech.y,-0.05,0.05, steps=101, settling_time=0.5, relative=True) + """ + + from lmfit.models import LinearModel, GaussianModel, VoigtModel, QuadraticModel, LorentzianModel + import matplotlib.pyplot as plt + import numpy as np + + if hindex < 0: + h = bec.history[hindex] + print('by scan number') + else: + h = bec.history.get_by_scan_number(hindex) + print('by scan number') + + md = h.metadata["bec"] + sno = md['dataset_number'] + print(f"number of scan = {sno}") + scanvar = list(md["args"].keys())[0] # string, returns the variable of the last performed scan + # data = h.devices[device_name][signal].read()["value"] + # data_x = h.devices.dcm_pitch.dcm_pitch.read()["value"] + # data_y = h.devices.lu_bpmsum.lu_bpmsum.read()["value"] + # data_x = h.devices[device_name][device_name].read()["value"] + + # that works ... + #print(list(md['args'].keys())) + val = list(md['args'].keys()) + #val[0] = 'aerotech.x' + devicenam = val[0] + print('device = ', devicenam) + data_xd = md["positions"] # last scan knows which device ... however, double array + data_x = data_xd.flatten() + print("dx = ", data_x) + #data_y = h.devices[signal_name][signal_name].read()["value"] + data_y1 = h.devices["bcu_bpmsum"]["bcu_bpmsum"].read()["value"] + data_y2 = h.devices["ss_bpmsum"]["ss_bpmsum"].read()["value"] + + #print("dy = ", data_y) + + data_y = data_y1/data_y2 + rev = 0 + #if val[0][9] == 'x': + # rev = 1 + smoothplotgrad(data_x, data_y, reverse = rev) + # g, xm = justfit(data_x, data_y, model=model, ibg=ibg) + +# plt.ion() +# plt.figure() +# plt.plot(data_x, data_y, "*") +# plt.plot(data_x, g.best_fit) +# plt.xlabel(scanvar) +# plt.ylabel(signal_name) +# plt.show() + +# gcen = g.pars["center"].value + + + if isave: + ans = "n" + ans = input("Store data in csv file? y/n ") + if ans == "y": + dirname = "/sls/x10sa/config/commissioning/Data/" + # writing output to simple data file for later analysis: + combined = np.column_stack((data_x, data_y)) + filename = dirname + "Scan" + str(sno) + devicenam + ".txt" + with open(filename, "w") as f: + np.savetxt(f, combined, delimiter=",", fmt="%.9e") + + + return data_x, data_y diff --git a/pxii_bec/macros/katscripts.py b/pxii_bec/macros/katscripts.py index b456dd3..451fb84 100755 --- a/pxii_bec/macros/katscripts.py +++ b/pxii_bec/macros/katscripts.py @@ -1352,7 +1352,7 @@ def get_mirror_data(history_index: int): # } -def record_beampos_until(stop_time_str, interval_minutes=10): +def record_beampos_until(stop_time_str, planner, interval_minutes=10): """ Runs `record_beam()` every `interval_minutes` minutes until the next occurrence of the given stop time (HH:MM). @@ -1361,9 +1361,12 @@ def record_beampos_until(stop_time_str, interval_minutes=10): # Prepare the file now = datetime.now() fnow = now.strftime("%d%m%H%M") - filename = f"luts/beampos/beam_pos_record_{fnow}.csv" + fdir = "/sls/x10sa/config/bec/production/pxii_bec/pxii_bec/macros/" + fname = f"luts/beampos/beampos_{fnow}.csv" + filename = fdir + fname scam_zoom = dev.scam_zoom.read()['scam_zoom']['value'] umv(dev.scam_zoom, 1000) + dev.transm.put(0.1) beam_size = "25 x 25" energy = get_current_energy() @@ -1384,6 +1387,11 @@ def record_beampos_until(stop_time_str, interval_minutes=10): if end_time <= now: end_time += timedelta(days=1) + # Change to beam visualisation state, ensure shutter is closed first + dev.bcu_shutter.put(0) + planner.move_to(BeamlineState.BEAM_VISUALISATION) + + # Start recording beam position print(f"Starting now ({now:%Y-%m-%d %H:%M}), running until {end_time:%Y-%m-%d %H:%M}") print(f"Interval: {interval_minutes} minutes\n") @@ -1396,6 +1404,8 @@ def record_beampos_until(stop_time_str, interval_minutes=10): time.sleep(interval_minutes * 60) print(f"Finished — reached {end_time:%H:%M}.") + planner.move_to(BeamlineState.MANUAL_SAMPLE_EXCHANGE) + @@ -1403,9 +1413,13 @@ def record_beam(filename): """ Record the beam position to file. """ + # Set transmission and bpm position + dev.transm.put(0.1) + umv(dev.bcu_bpm_x, 0.43) + umv(dev.bcu_bpm_y, -1.543 ) - # Perform the usual recording steps - umv(dev.ss_f4_x, 10) + # Open shutter and record positions + dev.bcu_shutter.put(1) auto_exposure(cam="samcam") time.sleep(2) now = datetime.now() @@ -1415,21 +1429,21 @@ def record_beam(filename): fnow = now.strftime("%H:%M:%S") xpos_cam = dev.samcam_x.read()["samcam_x"]["value"] ypos_cam = dev.samcam_y.read()["samcam_y"]["value"] - x_bpm, y_bpm = get_beampos() + # x_bpm, y_bpm = get_beampos() print(f"Time is {fnow}, X position is {xpos_cam:.5g}, Y position is {ypos_cam:.5g}") - # xpos, ypos = compute_pos() + x_bpm, y_bpm = compute_norm() f.write( # f"{fnow}, {xpos: .5g}, {ypos: .4g}, {xpos_cam: .5g}, {ypos_cam: .4g}\n" f"{fnow},{xpos_cam: .5g},{ypos_cam: .4g},{x_bpm: .5g},{y_bpm: .5g}\n" ) - - umv(dev.ss_f4_x, 16) + # Close shutter + dev.bcu_shutter.put(0) def analyse_beampos(file): """Plot the recorded beam position data""" # Load the CSV file into a Pandas DataFrame - filedir = "luts/beampos/" + filedir = "/sls/x10sa/config/bec/production/pxii_bec/pxii_bec/macros/luts/beampos/" filename = filedir + file data = pd.read_csv(filename, skiprows=1) print(data.head()) @@ -1438,7 +1452,7 @@ def analyse_beampos(file): # ref_bmpy = -0.175 ref_scinx = 1024 ref_sciny = 980 - scam_zoom = 116 + scam_zoom = 1000 # Extract the first column (time) as the x-axis meas_time = data["Time"] @@ -1494,18 +1508,16 @@ import matplotlib.pyplot as plt from epics import caget -def scan_scin_focus(type = 'fine'): + +def scan_scin_focus(planner, type = 'fine'): + dev.bcu_shutter.put(0) + planner.move_to(BeamlineState.BEAM_VISUALISATION) + dev.bcu_shutter.put(1) z0 = dev.diag_z.position - if z0-5 <= -10: - min = -9.5 - else: - min = z0-5 - - if z0+5 >=10: - max = 9.5 - else: - max = z0+5 + min = 0.1 + max = 9.9 + if type == 'fine': steps = 100 @@ -1513,43 +1525,12 @@ def scan_scin_focus(type = 'fine'): steps = 30 else: steps = 60 + umv(dev.scam_zoom, 1000) dev.transm.put(0.1) auto_exposure("samcam", target=200, max_iter=20) time.sleep(0.2) - z_positions = np.linspace(min,max,steps) - - - contrasts = [] - - - for z in z_positions: - umv(dev.diag_z, z) - time.sleep(0.1) - - sigma = dev.samcam_sigma.read()['samcam_sigma']['value'] - mean = dev.samcam_mean.read()['samcam_mean']['value'] - - contrast = sigma / mean if mean > 0 else 0 - contrasts.append(contrast) - - print(f"z = {z:.4f}, sigma = {sigma:.3f}, mean = {mean:.3f}, contrast = {contrast:.5f}") - - contrasts = np.asarray(contrasts) - - best_idx = np.argmax(contrasts) - best_z = z_positions[best_idx] - - print(f"\nBest scintillator focus z = {best_z:.4f}") - - umv(dev.diag_z,best_z) - - plt.plot(z_positions, contrasts, "o-") - plt.axvline(best_z, linestyle="--") - plt.xlabel("Scintillator z") - plt.ylabel("Sigma / Mean") - plt.show() - - return best_z, z_positions, contrasts \ No newline at end of file + go_to_peak(dev.diag_z, dev.scam, min, max, steps, relative=True, gomax=True, confirm=False) + dev.bcu_shutter.put(0) diff --git a/pxii_bec/macros/knifehist.py b/pxii_bec/macros/knifehist.py new file mode 100644 index 0000000..bea8744 --- /dev/null +++ b/pxii_bec/macros/knifehist.py @@ -0,0 +1,79 @@ +def knife_plothist(hindex: int, signal_name: str, isave=1): + """ + Get data for a completed scan from the BEC history, + and plot all the results. + + Args: + history_index (int): scan to fetch, e.g. -1 for the most recent scan + signal_name (str): the monitor + + Example: + data_x, data_y = knife_plothist(-1,"xidode") + + scanned with + scans.line_scan(dev.aerotech.y,-0.05,0.05, steps=101, settling_time=0.5, relative=True) + """ + + from lmfit.models import LinearModel, GaussianModel, VoigtModel, QuadraticModel, LorentzianModel + import matplotlib.pyplot as plt + import numpy as np + + if hindex < 0: + h = bec.history[hindex] + print('by scan number') + else: + h = bec.history.get_by_scan_number(hindex) + print('by scan number') + + md = h.metadata["bec"] + sno = md['dataset_number'] + print(f"number of scan = {sno}") + scanvar = list(md["args"].keys())[0] # string, returns the variable of the last performed scan + # data = h.devices[device_name][signal].read()["value"] + # data_x = h.devices.dcm_pitch.dcm_pitch.read()["value"] + # data_y = h.devices.lu_bpmsum.lu_bpmsum.read()["value"] + # data_x = h.devices[device_name][device_name].read()["value"] + + # that works ... + #print(list(md['args'].keys())) + val = list(md['args'].keys()) + #val[0] = 'aerotech.x' + devicenam = val[0] + print('device = ', devicenam) + data_xd = md["positions"] # last scan knows which device ... however, double array + data_x = data_xd.flatten() + print("dx = ", data_x) + #data_y = h.devices[signal_name][signal_name].read()["value"] + data_y = h.devices["xidiode"]["xidiode"].read()["value"] + print("dy = ", data_y) + + rev = 0 + if val[0][9] == 'x': + rev = 1 + smoothplotgrad(data_x, data_y, reverse = rev) + # g, xm = justfit(data_x, data_y, model=model, ibg=ibg) + +# plt.ion() +# plt.figure() +# plt.plot(data_x, data_y, "*") +# plt.plot(data_x, g.best_fit) +# plt.xlabel(scanvar) +# plt.ylabel(signal_name) +# plt.show() + +# gcen = g.pars["center"].value + + + if isave: + ans = "n" + ans = input("Store data in csv file? y/n ") + if ans == "y": + dirname = "/sls/x10sa/config/commissioning/Data/" + # writing output to simple data file for later analysis: + combined = np.column_stack((data_x, data_y)) + filename = dirname + "Scan" + str(sno) + devicenam + ".txt" + with open(filename, "w") as f: + np.savetxt(f, combined, delimiter=",", fmt="%.9e") + + + return data_x, data_y diff --git a/pxii_bec/macros/luts/20260704-1508_ge_edge.csv b/pxii_bec/macros/luts/20260704-1508_ge_edge.csv new file mode 100644 index 0000000..b3dc9f1 --- /dev/null +++ b/pxii_bec/macros/luts/20260704-1508_ge_edge.csv @@ -0,0 +1,6 @@ +Energy,bcu_bpmsum +11125.712083383152,25032.909677419353 +11125.50607729644,25067.271582181264 +11125.300078962937,25072.67158218126 +11125.094088382204,25096.84485407066 +11124.888105553806,25110.599078341016 diff --git a/pxii_bec/macros/luts/20260704-1509_ge_edge.csv b/pxii_bec/macros/luts/20260704-1509_ge_edge.csv new file mode 100644 index 0000000..cdbf09b --- /dev/null +++ b/pxii_bec/macros/luts/20260704-1509_ge_edge.csv @@ -0,0 +1,301 @@ +Energy,bcu_bpmsum +11125.712083383152,24961.620890937025 +11125.50607729644,24981.217204301076 +11125.300078962937,25013.287557603682 +11125.094088382204,24953.832258064514 +11124.888105553806,24968.10261136713 +11124.682130477306,24990.521351766514 +11124.476163152269,25005.63993855607 +11124.270203578264,25063.171121351766 +11124.064251754857,25083.887864823348 +11123.858307681605,25034.484178187406 +11123.652371358077,25157.456528417817 +11123.44644278384,25144.93886328725 +11123.240521958456,25170.029185867897 +11123.034608881491,25149.173271889398 +11122.828703552512,25147.52995391705 +11122.622805971081,25149.71213517665 +11122.416916136766,25137.73179723502 +11122.211034049127,25144.390783410137 +11122.005159707736,25135.905683563746 +11121.799293112155,25120.55483870968 +11121.593434261951,25120.90721966206 +11121.387583156686,25113.126267281106 +11121.181739795926,25118.79569892473 +11120.97590417924,25090.185560675884 +11120.770076306191,25087.841167434715 +11120.564256176345,25096.89216589862 +11120.358443789264,25089.46850998464 +11120.152639144519,25089.52841781874 +11119.94684224167,25083.528725038406 +11119.74105308029,25073.67465437788 +11119.535271659937,25073.420583717358 +11119.329497980181,25054.83686635945 +11119.123732040585,25056.012596006145 +11118.917973840717,25045.988632872504 +11118.71222338014,25045.18986175115 +11118.506480658425,25016.631643625187 +11118.300745675135,25002.86850998464 +11118.095018429833,24996.630721966205 +11117.889298922086,24984.850998463902 +11117.683587151465,24961.41075268817 +11117.477883117528,24945.807680491554 +11117.272186819848,24942.026113671272 +11117.066498257986,24904.69155145929 +11116.86081743151,24881.899539170507 +11116.655144339988,24854.092165898615 +11116.44947898298,24841.642703533023 +11116.243821360062,24813.291858678953 +11116.038171470791,24788.921044546852 +11115.832529314735,24756.357296466977 +11115.626894891466,24730.055913978496 +11115.421268200545,24695.38371735791 +11115.215649241538,24672.803993855607 +11115.010038014014,24645.320122887864 +11114.804434517539,24609.837173579108 +11114.598838751675,24570.704454685103 +11114.393250715995,24540.299539170508 +11114.187670410061,24512.862365591398 +11113.98209783344,24481.463594470042 +11113.776532985701,24439.637788018434 +11113.570975866407,24422.38801843318 +11113.365426475126,24386.79385560676 +11113.159884811428,24343.7490015361 +11112.954350874874,24314.71766513057 +11112.748824665035,24270.78033794163 +11112.543306181473,24226.929032258064 +11112.337795423762,24210.717972350227 +11112.132292391467,24173.96221198157 +11111.926797084147,24127.41904761905 +11111.721309501376,24086.8623655914 +11111.51582964272,24052.819662058373 +11111.310357507742,24007.22488479263 +11111.104893096015,23978.518586789556 +11110.899436407102,23937.069431643624 +11110.69398744057,23899.32073732719 +11110.48854619599,23866.146850998462 +11110.283112672922,23825.924423963133 +11110.077686870938,23772.336098310294 +11109.872268789606,23744.446082949307 +11109.66685842849,23700.824270353303 +11109.461455787161,23664.30261136713 +11109.256060865184,23605.98617511521 +11109.050673662123,23567.78371735791 +11108.84529417755,23519.990476190476 +11108.63992241103,23482.546850998464 +11108.434558362133,23440.4777265745 +11108.229202030421,23395.72995391705 +11108.023853415469,23352.320737327187 +11107.818512516837,23301.611367127498 +11107.613179334096,23238.146543778807 +11107.407853866816,23187.311520737327 +11107.20253611456,23136.582795698923 +11106.997226076897,23094.012903225805 +11106.791923753395,23042.810752688172 +11106.586629143627,22982.24178187404 +11106.381342247152,22935.69677419355 +11106.17606306354,22877.125652841783 +11105.970791592361,22833.17757296467 +11105.765527833179,22774.91490015361 +11105.560271785567,22723.342242703533 +11105.35502344909,22676.00768049155 +11105.149782823313,22625.849462365593 +11104.94454990781,22568.53425499232 +11104.739324702148,22524.754531490013 +11104.534107205889,22470.708448540707 +11104.328897418609,22409.773886328723 +11104.123695339871,22340.58586789555 +11103.918500969243,22287.800307219662 +11103.7133143063,22235.65806451613 +11103.508135350598,22183.634715821812 +11103.302964101713,22136.050076804917 +11103.097800559211,22079.589247311826 +11102.892644722659,22030.722273425497 +11102.68749659163,21976.06451612903 +11102.482356165689,21925.1757296467 +11102.277223444404,21860.220583717357 +11102.072098427347,21797.601228878648 +11101.86698111408,21735.278648233485 +11101.661871504177,21669.325960061444 +11101.456769597204,21605.887250384025 +11101.25167539273,21537.3133640553 +11101.046588890322,21468.863901689707 +11100.841510089553,21406.59385560676 +11100.63643898999,21343.04915514593 +11100.431375591197,21285.82980030722 +11100.226319892747,21227.479877112135 +11100.021271894206,21169.571428571428 +11099.816231595145,21105.507219662057 +11099.61119899513,21048.31397849462 +11099.406174093734,20998.815053763443 +11099.201156890525,20949.363133640552 +11098.996147385067,20881.60460829493 +11098.791145576935,20814.03256528418 +11098.586151465694,20760.72258064516 +11098.381165050916,20693.347772657453 +11098.176186332168,20627.89861751152 +11097.971215309017,20562.247004608296 +11097.766251981036,20511.227342549922 +11097.561296347792,20441.706912442394 +11097.356348408854,20377.72596006144 +11097.15140816379,20314.96712749616 +11096.946475612174,20254.152995391705 +11096.741550753568,20193.33456221198 +11096.536633587546,20144.413824884792 +11096.331724113677,20077.50967741936 +11096.126822331531,20008.412288786483 +11095.921928240674,19947.427035330264 +11095.717041840675,19876.160061443934 +11095.512163131112,19804.747158218124 +11095.307292111545,19742.05407066052 +11095.102428781545,19680.705990783412 +11094.897573140684,19619.92165898617 +11094.692725188532,19553.37296466974 +11094.487884924658,19492.235330261137 +11094.283052348626,19420.636251920125 +11094.078227460015,19350.31182795699 +11093.873410258386,19277.65560675883 +11093.668600743315,19214.026420890936 +11093.463798914368,19148.83010752688 +11093.259004771118,19077.906605222735 +11093.054218313131,19008.508141321046 +11092.849439539978,18938.75207373272 +11092.644668451232,18875.631950844858 +11092.439905046458,18810.22549923195 +11092.235149325232,18742.97726574501 +11092.030401287118,18675.09585253456 +11091.825660931689,18619.70875576037 +11091.620928258511,18552.845468509982 +11091.41620326716,18476.046697388632 +11091.211485957203,18415.681720430108 +11091.006776328208,18351.75483870968 +11090.80207437975,18285.768356374807 +11090.597380111396,18222.803379416284 +11090.392693522715,18161.50015360983 +11090.188014613283,18094.434715821808 +11089.983343382662,18031.838402457757 +11089.77867983043,17980.873118279567 +11089.574023956155,17916.964362519204 +11089.369375759405,17851.590476190475 +11089.16473523975,17793.384024577572 +11088.960102396763,17731.770814132105 +11088.755477230014,17665.738556067587 +11088.55085973907,17520.424577572965 +11088.346249923507,17459.977880184335 +11088.141647782893,17435.752995391704 +11087.9370533168,17330.449462365592 +11087.732466524796,17303.65560675883 +11087.527887406453,17200.102918586792 +11087.323315961341,17137.39385560676 +11087.11875218903,17119.217204301076 +11086.914196089094,17019.40614439324 +11086.7096476611,17000.34746543779 +11086.505106904624,16892.53640552995 +11086.30057381923,16877.686328725038 +11086.096048404497,16832.635637480802 +11085.891530659987,16743.092473118282 +11085.687020585274,16697.56651305683 +11085.482518179933,16640.899231950847 +11085.27802344353,16601.66113671275 +11085.07353637564,16589.250384024577 +11084.869056975831,16498.01935483871 +11084.664585243674,16441.842089093705 +11084.460121178743,16443.15330261137 +11084.255664780607,16393.89400921659 +11084.05121604884,16308.20307219662 +11083.846774983007,16296.853456221197 +11083.642341582687,16274.386789554532 +11083.437915847444,16226.037788018433 +11083.233497776855,16156.294316436251 +11083.029087370489,16101.73241167435 +11082.824684627914,16029.325038402458 +11082.62028954871,15956.540399385562 +11082.415902132438,15896.660215053762 +11082.211522378679,15839.601228878648 +11082.007150286998,15779.243625192012 +11081.80278585697,15706.726267281105 +11081.598429088164,15646.545622119816 +11081.394079980157,15589.870353302613 +11081.189738532512,15530.167741935486 +11080.985404744806,15474.692165898616 +11080.78107861661,15419.292473118277 +11080.576760147496,15361.777265745006 +11080.372449337041,15306.882949308754 +11080.168146184806,15246.281105990784 +11079.963850690367,15194.35821812596 +11079.759562853296,15138.713056835637 +11079.55528267317,15083.790476190476 +11079.351010149554,15032.803993855608 +11079.146745282025,14971.027342549922 +11078.94248807015,14909.13456221198 +11078.738238513504,14853.784024577573 +11078.53399661166,14785.384639016896 +11078.32976236419,14732.271274961598 +11078.125535770665,14669.355145929341 +11077.921316830652,14611.881105990784 +11077.717105543732,14553.368970814132 +11077.512901909475,14498.884485407067 +11077.30870592745,14437.40122887865 +11077.104517597232,14386.752688172044 +11076.900336918388,14324.829185867897 +11076.6961638905,14276.689708141323 +11076.491998513131,14218.912442396313 +11076.287840785859,14165.363133640552 +11076.083690708254,14099.826420890939 +11075.879548279892,14046.362826420891 +11075.675413500341,13996.261751152075 +11075.471286369175,13935.55975422427 +11075.267166885968,13883.652841781874 +11075.063055050288,13827.098003072195 +11074.858950861715,13767.941935483872 +11074.654854319815,13715.851920122888 +11074.450765424166,13658.257450076804 +11074.246684174335,13605.813824884792 +11074.0426105699,13559.395391705068 +11073.838544610431,13502.741628264212 +11073.634486295503,13445.49062980031 +11073.430435624683,13397.154531490014 +11073.226392597553,13350.433486943166 +11073.022357213678,13300.770199692779 +11072.818329472635,13239.17726574501 +11072.614309373996,13200.020890937021 +11072.410296917333,13152.479877112137 +11072.206292102223,13092.494316436252 +11072.002294928232,13044.951459293396 +11071.798305394937,13004.251612903225 +11071.594323501917,12956.027035330262 +11071.390349248735,12899.447004608295 +11071.186382634969,12856.325038402458 +11070.982423660193,12790.753302611367 +11070.778472323978,12740.55821812596 +11070.574528625899,12694.003379416283 +11070.37059256553,12629.975422427036 +11070.166664142442,12595.487250384025 +11069.96274335621,12535.743164362519 +11069.758830206405,12492.46267281106 +11069.5549246926,12443.222734254992 +11069.351026814378,12390.796620583718 +11069.1471365713,12335.095852534561 +11068.943253962947,12279.6777265745 +11068.73937898889,12236.273732718893 +11068.535511648703,12190.829185867895 +11068.331651941962,12147.52534562212 +11068.127799868234,12092.882642089095 +11067.9239554271,12042.002150537633 +11067.72011861813,12000.626420890938 +11067.516289440899,11955.539170506912 +11067.31246789498,11911.956067588326 +11067.108653979947,11875.755453149002 +11066.904847695374,11817.003072196621 +11066.701049040837,11777.791090629802 +11066.497258015903,11729.952995391704 +11066.293474620155,11679.727496159754 +11066.089698853162,11632.814746543778 +11065.885930714501,11592.792933947772 +11065.68217020374,11555.847311827956 +11065.47841732046,11496.157603686635 +11065.27467206423,11453.51950844854 +11065.070934434627,11411.927188940092 +11064.867204431224,11361.943471582183 +11064.663482053596,11323.37910906298 +11064.459767301316,11278.171121351766 diff --git a/pxii_bec/macros/luts/20260704-1520_ge_edge.csv b/pxii_bec/macros/luts/20260704-1520_ge_edge.csv new file mode 100644 index 0000000..724c610 --- /dev/null +++ b/pxii_bec/macros/luts/20260704-1520_ge_edge.csv @@ -0,0 +1,301 @@ +Energy,bcu_bpmsum +11064.46,2897.81 +11064.66,2896.50 +11064.87,2894.71 +11065.07,2896.02 +11065.27,2900.33 +11065.48,2904.01 +11065.68,2912.61 +11065.89,2918.20 +11066.09,2909.84 +11066.29,2923.48 +11066.50,2922.04 +11066.70,2927.25 +11066.90,2941.69 +11067.11,2942.27 +11067.31,2956.41 +11067.52,2958.01 +11067.72,2973.48 +11067.92,2982.97 +11068.13,2986.73 +11068.33,3003.69 +11068.54,3008.42 +11068.74,3026.35 +11068.94,3030.74 +11069.15,3043.02 +11069.35,3052.27 +11069.55,3072.51 +11069.76,3084.80 +11069.96,3090.84 +11070.17,3101.38 +11070.37,3119.29 +11070.57,3124.13 +11070.78,3134.87 +11070.98,3147.15 +11071.19,3166.17 +11071.39,3184.50 +11071.59,3190.73 +11071.80,3201.91 +11072.00,3210.77 +11072.21,3221.14 +11072.41,3232.82 +11072.61,3240.12 +11072.82,3250.71 +11073.02,3260.58 +11073.23,3270.65 +11073.43,3281.65 +11073.63,3291.68 +11073.84,3301.08 +11074.04,3311.16 +11074.25,3320.93 +11074.45,3331.94 +11074.65,3342.25 +11074.86,3350.51 +11075.06,3358.85 +11075.27,3367.26 +11075.47,3377.53 +11075.68,3386.17 +11075.88,3394.92 +11076.08,3403.03 +11076.29,3411.25 +11076.49,3417.66 +11076.70,3426.54 +11076.90,3432.92 +11077.10,3440.91 +11077.31,3446.72 +11077.51,3453.68 +11077.72,3461.62 +11077.92,3467.82 +11078.13,3474.07 +11078.33,3479.91 +11078.53,3487.37 +11078.74,3494.45 +11078.94,3500.53 +11079.15,3505.75 +11079.35,3510.20 +11079.56,3515.00 +11079.76,3520.72 +11079.96,3525.45 +11080.17,3529.48 +11080.37,3532.28 +11080.58,3537.22 +11080.78,3541.03 +11080.99,3542.33 +11081.19,3546.71 +11081.39,3548.56 +11081.60,3549.09 +11081.80,3550.41 +11082.01,3547.99 +11082.21,3544.12 +11082.42,3538.71 +11082.62,3532.49 +11082.82,3526.98 +11083.03,3517.45 +11083.23,3510.66 +11083.44,3506.55 +11083.64,3504.35 +11083.85,3505.10 +11084.05,3505.04 +11084.26,3504.01 +11084.46,3503.11 +11084.66,3500.16 +11084.87,3496.80 +11085.07,3490.23 +11085.28,3482.80 +11085.48,3475.13 +11085.69,3465.94 +11085.89,3457.79 +11086.10,3449.43 +11086.30,3439.50 +11086.51,3432.11 +11086.71,3419.52 +11086.91,3405.64 +11087.12,3390.66 +11087.32,3375.07 +11087.53,3358.38 +11087.73,3342.76 +11087.94,3321.23 +11088.14,3299.54 +11088.35,3277.19 +11088.55,3254.78 +11088.76,3230.88 +11088.96,3204.79 +11089.16,3177.80 +11089.37,3145.85 +11089.57,3114.52 +11089.78,3078.40 +11089.98,3039.81 +11090.19,2998.05 +11090.39,2954.85 +11090.60,2908.30 +11090.80,2859.42 +11091.01,2809.61 +11091.21,2752.69 +11091.42,2692.73 +11091.62,2630.09 +11091.83,2563.42 +11092.03,2491.06 +11092.24,2413.64 +11092.44,2332.69 +11092.64,2247.11 +11092.85,2156.08 +11093.05,2060.02 +11093.26,1957.93 +11093.46,1849.54 +11093.67,1733.77 +11093.87,1614.56 +11094.08,1491.44 +11094.28,1357.39 +11094.49,1233.96 +11094.69,1104.59 +11094.90,977.21 +11095.10,856.60 +11095.31,737.75 +11095.51,624.13 +11095.72,518.62 +11095.92,423.13 +11096.13,340.15 +11096.33,265.78 +11096.54,203.49 +11096.74,151.53 +11096.95,111.34 +11097.15,78.72 +11097.36,54.76 +11097.56,36.50 +11097.77,24.18 +11097.97,15.86 +11098.18,10.17 +11098.38,6.81 +11098.59,4.61 +11098.79,3.60 +11099.00,2.97 +11099.20,2.51 +11099.41,2.40 +11099.61,2.19 +11099.82,2.07 +11100.02,1.91 +11100.23,1.78 +11100.43,1.62 +11100.64,1.54 +11100.84,1.51 +11101.05,1.36 +11101.25,1.26 +11101.46,1.25 +11101.66,1.17 +11101.87,1.12 +11102.07,1.27 +11102.28,1.23 +11102.48,1.23 +11102.69,1.23 +11102.89,1.14 +11103.10,1.11 +11103.30,1.00 +11103.51,1.13 +11103.71,1.08 +11103.92,0.94 +11104.12,0.88 +11104.33,0.81 +11104.53,0.78 +11104.74,0.69 +11104.94,0.75 +11105.15,0.75 +11105.36,0.68 +11105.56,0.59 +11105.77,0.66 +11105.97,0.72 +11106.18,0.64 +11106.38,0.69 +11106.59,0.59 +11106.79,0.65 +11107.00,0.66 +11107.20,0.60 +11107.41,0.57 +11107.61,0.59 +11107.82,0.57 +11108.02,0.63 +11108.23,0.55 +11108.43,0.48 +11108.64,0.57 +11108.85,0.51 +11109.05,0.60 +11109.26,0.64 +11109.46,0.68 +11109.67,0.76 +11109.87,0.84 +11110.08,0.90 +11110.28,1.03 +11110.49,1.10 +11110.69,1.21 +11110.90,1.36 +11111.10,1.41 +11111.31,1.43 +11111.52,1.39 +11111.72,1.52 +11111.93,1.49 +11112.13,1.62 +11112.34,1.45 +11112.54,1.69 +11112.75,1.74 +11112.95,1.73 +11113.16,1.80 +11113.37,1.82 +11113.57,1.79 +11113.78,1.80 +11113.98,1.71 +11114.19,1.67 +11114.39,1.60 +11114.60,1.53 +11114.80,1.57 +11115.01,1.43 +11115.22,1.48 +11115.42,1.55 +11115.63,1.45 +11115.83,1.49 +11116.04,1.41 +11116.24,1.52 +11116.45,1.50 +11116.66,1.41 +11116.86,1.42 +11117.07,1.41 +11117.27,1.49 +11117.48,1.46 +11117.68,1.46 +11117.89,1.38 +11118.10,1.43 +11118.30,1.42 +11118.51,1.43 +11118.71,1.36 +11118.92,1.34 +11119.12,1.36 +11119.33,1.33 +11119.54,1.29 +11119.74,1.27 +11119.95,1.25 +11120.15,1.30 +11120.36,1.30 +11120.56,1.28 +11120.77,1.29 +11120.98,1.20 +11121.18,1.22 +11121.39,1.28 +11121.59,1.17 +11121.80,1.18 +11122.01,1.18 +11122.21,1.16 +11122.42,1.15 +11122.62,1.14 +11122.83,1.25 +11123.03,1.28 +11123.24,1.36 +11123.45,1.42 +11123.65,1.37 +11123.86,1.21 +11124.06,1.44 +11124.27,1.48 +11124.48,1.36 +11124.68,1.12 +11124.89,1.16 +11125.09,1.25 +11125.30,1.31 +11125.51,1.28 +11125.71,1.31 diff --git a/pxii_bec/macros/luts/20260704-1531_ge_edge.csv b/pxii_bec/macros/luts/20260704-1531_ge_edge.csv new file mode 100644 index 0000000..67eafd2 --- /dev/null +++ b/pxii_bec/macros/luts/20260704-1531_ge_edge.csv @@ -0,0 +1,301 @@ +Energy,Bragg,bcu_bpmsum +11064.46,179.69,6338.84 +11064.66,179.69,6315.93 +11064.87,179.69,6314.91 +11065.07,179.68,6308.85 +11065.27,179.68,6286.39 +11065.48,179.68,6262.82 +11065.68,179.67,6242.13 +11065.89,179.67,6221.71 +11066.09,179.67,6204.17 +11066.29,179.66,6187.03 +11066.50,179.66,6171.42 +11066.70,179.66,6155.21 +11066.90,179.65,6140.00 +11067.11,179.65,6119.68 +11067.31,179.65,6101.24 +11067.52,179.64,6080.76 +11067.72,179.64,6064.97 +11067.92,179.64,6047.24 +11068.13,179.63,6026.49 +11068.33,179.63,6007.70 +11068.54,179.63,5988.31 +11068.74,179.62,5964.32 +11068.94,179.62,5941.86 +11069.15,179.62,5917.88 +11069.35,179.61,5889.14 +11069.55,179.61,5860.76 +11069.76,179.61,5828.84 +11069.96,179.60,5797.76 +11070.17,179.60,5768.76 +11070.37,179.60,5744.78 +11070.57,179.59,5721.05 +11070.78,179.59,5696.69 +11070.98,179.59,5681.88 +11071.19,179.58,5667.07 +11071.39,179.58,5652.59 +11071.59,179.58,5639.00 +11071.80,179.57,5627.42 +11072.00,179.57,5620.14 +11072.21,179.57,5610.42 +11072.41,179.56,5600.85 +11072.61,179.56,5590.35 +11072.82,179.56,5575.33 +11073.02,179.55,5560.40 +11073.23,179.55,5545.10 +11073.43,179.55,5528.90 +11073.63,179.54,5512.11 +11073.84,179.54,5496.70 +11074.04,179.54,5480.03 +11074.25,179.53,5464.12 +11074.45,179.53,5445.84 +11074.65,179.53,5427.15 +11074.86,179.52,5410.26 +11075.06,179.52,5392.25 +11075.27,179.52,5368.51 +11075.47,179.51,5349.75 +11075.68,179.51,5333.24 +11075.88,179.51,5312.39 +11076.08,179.50,5293.59 +11076.29,179.50,5272.28 +11076.49,179.50,5254.44 +11076.70,179.49,5233.09 +11076.90,179.49,5209.18 +11077.10,179.49,5188.50 +11077.31,179.48,5161.29 +11077.51,179.48,5142.19 +11077.72,179.48,5119.16 +11077.92,179.47,5099.02 +11078.13,179.47,5074.12 +11078.33,179.47,5049.41 +11078.53,179.46,5024.90 +11078.74,179.46,4998.89 +11078.94,179.46,4975.46 +11079.15,179.45,4951.22 +11079.35,179.45,4924.91 +11079.56,179.45,4895.95 +11079.76,179.44,4868.90 +11079.96,179.44,4840.06 +11080.17,179.44,4810.41 +11080.37,179.43,4779.62 +11080.58,179.43,4750.45 +11080.78,179.43,4714.91 +11080.99,179.42,4686.31 +11081.19,179.42,4652.54 +11081.39,179.42,4620.98 +11081.60,179.41,4591.66 +11081.80,179.41,4559.03 +11082.01,179.41,4526.56 +11082.21,179.40,4495.77 +11082.42,179.40,4463.20 +11082.62,179.40,4429.03 +11082.82,179.39,4394.22 +11083.03,179.39,4361.12 +11083.23,179.39,4326.11 +11083.44,179.38,4290.80 +11083.64,179.38,4257.57 +11083.85,179.38,4220.73 +11084.05,179.37,4183.46 +11084.26,179.37,4145.25 +11084.46,179.37,4110.61 +11084.66,179.36,4069.91 +11084.87,179.36,4029.76 +11085.07,179.36,3984.08 +11085.28,179.35,3943.96 +11085.48,179.35,3901.39 +11085.69,179.35,3858.28 +11085.89,179.34,3817.69 +11086.10,179.34,3775.01 +11086.30,179.34,3731.37 +11086.51,179.33,3690.29 +11086.71,179.33,3647.42 +11086.91,179.33,3603.98 +11087.12,179.32,3560.13 +11087.32,179.32,3514.08 +11087.53,179.32,3467.54 +11087.73,179.31,3417.80 +11087.94,179.31,3370.47 +11088.14,179.31,3321.76 +11088.35,179.30,3272.59 +11088.55,179.30,3220.68 +11088.76,179.30,3167.67 +11088.96,179.29,3113.14 +11089.16,179.29,3059.07 +11089.37,179.29,3002.97 +11089.57,179.28,2944.78 +11089.78,179.28,2886.59 +11089.98,179.28,2825.41 +11090.19,179.27,2764.63 +11090.39,179.27,2699.15 +11090.60,179.27,2636.67 +11090.80,179.26,2568.71 +11091.01,179.26,2500.84 +11091.21,179.26,2430.58 +11091.42,179.25,2356.01 +11091.62,179.25,2279.98 +11091.83,179.25,2200.14 +11092.03,179.24,2119.91 +11092.24,179.24,2039.42 +11092.44,179.24,1949.58 +11092.64,179.23,1863.21 +11092.85,179.23,1767.06 +11093.05,179.23,1675.31 +11093.26,179.22,1574.66 +11093.46,179.22,1473.24 +11093.67,179.22,1373.95 +11093.87,179.21,1267.36 +11094.08,179.21,1161.16 +11094.28,179.21,1055.16 +11094.49,179.20,944.31 +11094.69,179.20,839.72 +11094.90,179.20,733.85 +11095.10,179.19,634.54 +11095.31,179.19,537.95 +11095.51,179.19,447.37 +11095.72,179.18,366.14 +11095.92,179.18,292.72 +11096.13,179.18,229.37 +11096.33,179.17,175.79 +11096.54,179.17,130.77 +11096.74,179.17,94.72 +11096.95,179.16,66.02 +11097.15,179.16,45.88 +11097.36,179.16,30.84 +11097.56,179.15,20.47 +11097.77,179.15,13.23 +11097.97,179.15,9.07 +11098.18,179.14,6.11 +11098.38,179.14,4.50 +11098.59,179.14,3.44 +11098.79,179.13,2.70 +11099.00,179.13,2.18 +11099.20,179.13,2.00 +11099.41,179.12,1.83 +11099.61,179.12,1.76 +11099.82,179.12,1.58 +11100.02,179.11,1.49 +11100.23,179.11,1.50 +11100.43,179.11,1.28 +11100.64,179.10,1.23 +11100.84,179.10,0.93 +11101.05,179.10,0.90 +11101.25,179.09,0.75 +11101.46,179.09,0.72 +11101.66,179.09,0.71 +11101.87,179.08,0.69 +11102.07,179.08,0.61 +11102.28,179.08,0.58 +11102.48,179.07,0.80 +11102.69,179.07,0.77 +11102.89,179.07,0.74 +11103.10,179.06,0.64 +11103.30,179.06,0.61 +11103.51,179.06,0.67 +11103.71,179.05,0.61 +11103.92,179.05,0.57 +11104.12,179.05,0.60 +11104.33,179.04,0.51 +11104.53,179.04,0.44 +11104.74,179.04,0.50 +11104.94,179.03,0.48 +11105.15,179.03,0.49 +11105.36,179.03,0.48 +11105.56,179.02,0.46 +11105.77,179.02,0.54 +11105.97,179.02,0.48 +11106.18,179.01,0.51 +11106.38,179.01,0.53 +11106.59,179.01,0.50 +11106.79,179.00,0.52 +11107.00,179.00,0.58 +11107.20,179.00,0.50 +11107.41,178.99,0.40 +11107.61,178.99,0.54 +11107.82,178.99,0.59 +11108.02,178.98,0.61 +11108.23,178.98,0.52 +11108.43,178.98,0.49 +11108.64,178.97,0.33 +11108.85,178.97,0.41 +11109.05,178.97,0.40 +11109.26,178.96,0.37 +11109.46,178.96,0.38 +11109.67,178.96,0.36 +11109.87,178.95,0.38 +11110.08,178.95,0.45 +11110.28,178.95,0.52 +11110.49,178.94,0.54 +11110.69,178.94,0.66 +11110.90,178.94,0.48 +11111.10,178.93,0.40 +11111.31,178.93,0.19 +11111.52,178.93,0.37 +11111.72,178.92,0.14 +11111.93,178.92,0.47 +11112.13,178.92,0.63 +11112.34,178.91,0.57 +11112.54,178.91,0.65 +11112.75,178.91,0.50 +11112.95,178.90,0.65 +11113.16,178.90,0.67 +11113.37,178.90,0.81 +11113.57,178.89,0.74 +11113.78,178.89,0.95 +11113.98,178.89,0.98 +11114.19,178.88,0.80 +11114.39,178.88,0.46 +11114.60,178.88,0.51 +11114.80,178.87,0.45 +11115.01,178.87,0.48 +11115.22,178.87,0.51 +11115.42,178.86,0.48 +11115.63,178.86,0.44 +11115.83,178.85,0.18 +11116.04,178.85,-0.21 +11116.24,178.85,-0.17 +11116.45,178.84,-0.15 +11116.66,178.84,0.41 +11116.86,178.84,0.41 +11117.07,178.83,0.43 +11117.27,178.83,0.37 +11117.48,178.83,0.36 +11117.68,178.82,0.43 +11117.89,178.82,0.54 +11118.10,178.82,0.97 +11118.30,178.81,0.84 +11118.51,178.81,0.84 +11118.71,178.81,0.26 +11118.92,178.80,0.25 +11119.12,178.80,0.27 +11119.33,178.80,0.38 +11119.54,178.79,0.24 +11119.74,178.79,0.32 +11119.95,178.79,0.08 +11120.15,178.78,0.04 +11120.36,178.78,-0.23 +11120.56,178.78,-0.33 +11120.77,178.77,-0.14 +11120.98,178.77,0.12 +11121.18,178.77,0.10 +11121.39,178.76,0.12 +11121.59,178.76,0.10 +11121.80,178.76,0.05 +11122.01,178.75,0.15 +11122.21,178.75,0.26 +11122.42,178.75,0.57 +11122.62,178.74,0.59 +11122.83,178.74,0.50 +11123.03,178.74,0.04 +11123.24,178.73,0.02 +11123.45,178.73,0.03 +11123.65,178.73,0.06 +11123.86,178.72,0.10 +11124.06,178.72,0.07 +11124.27,178.72,0.06 +11124.48,178.71,0.02 +11124.68,178.71,-0.11 +11124.89,178.71,-0.15 +11125.09,178.70,-0.19 +11125.30,178.70,-0.43 +11125.51,178.70,-0.37 +11125.71,178.69,-0.41 diff --git a/pxii_bec/macros/luts/I1flcalf.csv b/pxii_bec/macros/luts/I1flcalf.csv new file mode 100644 index 0000000..ee9d3b4 --- /dev/null +++ b/pxii_bec/macros/luts/I1flcalf.csv @@ -0,0 +1,22 @@ +En,Fl/I1 +8.0,2.8080492027877764e+16 +9.0,1.4927860624483272e+16 +10.0,8417877926653679.0 +12.0,7019853850369172.0 +14.0,7386772914557876.0 +15.0,6750736409573591.0 +16.0,6297543245612219.0 +17.0,5735864463671363.0 +18.0,5573419238195645.0 +19.0,5194271286110376.0 +20.0,5117190891126464.0 +21.0,5255398865151842.0 +22.0,5322717678656602.0 +23.0,5341775365764245.0 +24.0,5666291945190874.0 +25.0,5921432928105373.0 +26.0,6205608339975513.0 +27.0,6811217757122517.0 +28.0,7298249384420157.0 +29.0,7974072533533950.0 +30.0,8936735941779119.0 diff --git a/pxii_bec/macros/luts/beampos/beam_pos_record_0107.csv b/pxii_bec/macros/luts/beampos/beam_pos_record_0107.csv new file mode 100644 index 0000000..3cc7ec4 --- /dev/null +++ b/pxii_bec/macros/luts/beampos/beam_pos_record_0107.csv @@ -0,0 +1,10 @@ +Beam size: focus, Energy: 12400 eV, Zoom: 1000.0 +Time, Scin_x, Scin_y +22:44:24, 1047.8, 984.4 +22:54:27, 1042.3, 990.1 +23:04:31, 1039.3, 993.6 +23:14:34, 1036, 996.9 +23:24:38, 1033.6, 998.3 +23:34:41, 1033.2, 998.5 +23:44:44, 1032.5, 1000 +23:54:48, 1030.5, 1001 diff --git a/pxii_bec/macros/luts/beampos/beam_pos_record_0207.csv b/pxii_bec/macros/luts/beampos/beam_pos_record_0207.csv new file mode 100644 index 0000000..7f079c8 --- /dev/null +++ b/pxii_bec/macros/luts/beampos/beam_pos_record_0207.csv @@ -0,0 +1,12 @@ +Beam size: focus, Energy: 12400 eV, Zoom: 116.0 +Time,Scin_x,Scin_y +22:42:33, 1004.4, 975.1 +22:47:51, 1004.2, 974.9 +22:49:25, 1004, 975.1 +22:59:29, 1004.3, 974.9 +23:09:32, 1004, 974.9 +23:19:35, 1004, 975 +23:29:40, 1003.8, 975 +23:39:43, 1004, 975.1 +23:49:46, 1003.8, 975.1 +23:59:50, 1003.9, 975 diff --git a/pxii_bec/macros/luts/beampos/beam_pos_record_02072247.csv b/pxii_bec/macros/luts/beampos/beam_pos_record_02072247.csv new file mode 100644 index 0000000..9de9b28 --- /dev/null +++ b/pxii_bec/macros/luts/beampos/beam_pos_record_02072247.csv @@ -0,0 +1,2 @@ +Beam size: focus, Energy: 12400 eV, Zoom: 116.0 +Time,Scin_x,Scin_y diff --git a/pxii_bec/macros/luts/beampos/beam_pos_record_02072249.csv b/pxii_bec/macros/luts/beampos/beam_pos_record_02072249.csv new file mode 100644 index 0000000..9de9b28 --- /dev/null +++ b/pxii_bec/macros/luts/beampos/beam_pos_record_02072249.csv @@ -0,0 +1,2 @@ +Beam size: focus, Energy: 12400 eV, Zoom: 116.0 +Time,Scin_x,Scin_y diff --git a/pxii_bec/macros/luts/beampos/beam_pos_record_0307.csv b/pxii_bec/macros/luts/beampos/beam_pos_record_0307.csv new file mode 100644 index 0000000..104b64a --- /dev/null +++ b/pxii_bec/macros/luts/beampos/beam_pos_record_0307.csv @@ -0,0 +1,38 @@ +00:09:53, 1004.1, 974.8 +00:19:56, 1004.1, 975.4 +00:29:59, 1003.8, 975.2 +00:40:02, 1003.7, 975 +00:50:06, 1003.9, 975.1 +01:00:09, 1003.7, 975 +01:10:13, 1003.9, 975.4 +01:20:17, 1003.8, 975.2 +01:30:20, 1003.5, 975.2 +01:40:24, 1003.6, 975.4 +01:50:27, 1003.6, 975.5 +02:00:30, 1003.6, 975.3 +02:10:34, 1003.6, 975.3 +02:20:37, 1003.4, 975.1 +02:30:40, 1003.3, 975 +02:40:43, 1003.6, 975.5 +02:50:46, 1003.4, 975.4 +03:00:50, 1003.6, 975.7 +03:10:53, 1003.4, 975.3 +03:20:56, 1003.3, 975.5 +03:30:59, 1003.3, 975.6 +03:41:03, 1003.1, 975.4 +03:51:06, 1003.2, 975.5 +04:01:09, 1003.3, 975.8 +04:11:12, 1003.2, 975.4 +04:21:17, 1003.2, 976.1 +04:31:20, 1003.1, 975.8 +04:41:24, 1003.3, 975.7 +04:51:27, 1003.1, 975.8 +05:01:30, 1003.3, 975.7 +05:11:33, 1003.1, 975.9 +05:21:37, 1003.5, 975.7 +05:31:40, 1003, 975.9 +05:41:44, 1003, 975.9 +05:51:47, 1003, 975.9 +06:01:51, 1002.8, 975.8 +06:11:54, 1002.9, 976 +06:21:58, 1002.9, 976 diff --git a/pxii_bec/macros/luts/beampos/beam_pos_record_05072309.csv b/pxii_bec/macros/luts/beampos/beam_pos_record_05072309.csv new file mode 100644 index 0000000..d247544 --- /dev/null +++ b/pxii_bec/macros/luts/beampos/beam_pos_record_05072309.csv @@ -0,0 +1,3 @@ +Beam size: 25 x 25, Energy: 12411 eV, Zoom: 1000.0 +Time,Scin_x,Scin_y,BPM_x,BPM_y +23:09:51, 996.26, 969.7 diff --git a/pxii_bec/macros/luts/beampos/beam_pos_record_05072312.csv b/pxii_bec/macros/luts/beampos/beam_pos_record_05072312.csv new file mode 100644 index 0000000..45df2e2 --- /dev/null +++ b/pxii_bec/macros/luts/beampos/beam_pos_record_05072312.csv @@ -0,0 +1,54 @@ +Beam size: 25 x 25, Energy: 12411 eV, Zoom: 1000.0 +Time,Scin_x,Scin_y,BPM_x,BPM_y +23:12:35, 995.39, 971.2, 0.0014257, 0.00020213 +23:22:43, 994.25, 969.4,-0.00056244, 4.803e-05 +23:32:50, 996.45, 969.9, 0.0019919, 0.00012447 +23:42:57, 994.51, 968.8, 0.0023343, 0.00015683 +23:53:04, 995.05, 968.3, 0.0015905,-8.5494e-05 +00:03:11, 995.28, 968.7, 0.0020666, 5.3318e-05 +00:13:18, 992.49, 967.4, 0.0018273, 1.0159e-05 +00:23:25, 993.87, 968.1, 0.0026699, 0.00014545 +00:33:32, 993.18, 967.1, 0.0021102, 0.00016397 +00:43:39, 989.84, 964.4, 0.0019726, 6.7481e-05 +00:53:46, 992.51, 964.3, 0.0025941,-7.7352e-05 +01:03:53, 990.62, 964.3, 0.0019351,-0.00018901 +01:14:00, 990.84, 963.9, 0.00034531,-7.0021e-05 +01:24:07, 990.38, 964.8, 0.0028551,-1.0148e-05 +01:34:14, 989.93, 963.9, 0.00096758,-8.6709e-05 +01:44:22, 989.6, 962.5, 0.00083318, 7.822e-05 +01:54:29, 988.24, 962.7, 0.0021182, 2.3366e-06 +02:04:36, 990.03, 961.3, 0.0034334,-9.2628e-05 +02:14:43, 992.94, 961.8, 0.0035394, 3.7763e-05 +02:24:50, 988.24, 963.2, 0.0020132,-3.7238e-05 +02:34:57, 988.7, 960.8, 0.0026131, 0.00013091 +02:45:04, 987.48, 962.2, 0.0019253,-4.9263e-05 +02:55:12, 989.1, 959.2, 0.0026772,-0.00010874 +03:05:19, 990.06, 960.4, 0.0029965,-6.3675e-05 +03:15:25, 989.04, 960.9, 0.001467, 7.606e-05 +03:25:32, 988.1, 958.4, 0.0029762,-6.4314e-05 +03:35:40, 987.12, 960.3, 0.0023346, 1.2619e-05 +03:45:47, 987.53, 958.1, 0.0019049,-9.9284e-05 +03:55:54, 988.66, 957.7, 0.0023903,-0.00017489 +04:06:01, 989.69, 957.7, 0.0031516,-2.9577e-05 +04:16:08, 988.28, 959.3, 0.0018509,-0.00016916 +04:26:15, 989.55, 961.4, 0.0042292,-7.6532e-05 +04:36:22, 990.65, 960, 0.0032345,-0.00024955 +04:46:29, 986.18, 958.9, 0.0018287,-0.00011167 +04:56:36, 990.08, 958, 0.0029748,-0.00014368 +05:06:43, 988.35, 959.3, 0.0027624,-7.6409e-05 +05:16:51, 989.79, 959.2, 0.0034944,-0.00016686 +05:26:58, 988.99, 959.5, 0.0011134,-0.00010152 +05:37:06, 988.61, 956.7, 0.0021961,-0.00012383 +05:47:13, 991.01, 959.1, 0.0031364,-0.00015889 +05:57:20, 986.32, 957, 0.0023368,-4.4888e-05 +06:07:27, 985.51, 957,-3.7126e-05,-0.0001149 +06:17:34, 987.44, 955.2, 0.0021771,-0.0002745 +06:27:42, 985.5, 952.4, 0.0002006,-0.00031063 +06:37:48, 986.71, 955, 0.00048996,-0.00024164 +06:47:55, 986.27, 952.7, 0.00035522,-0.00030352 +06:58:02, 986.41, 953.1, 0.0014466,-0.00024274 +07:08:09, 987.99, 953.3, 0.0017522,-0.00020756 +07:18:17, 983.72, 952, 0.00073741,-0.00034075 +07:28:25, 984.45, 952.7, 0.0022291,-0.00026963 +07:38:32, 985.52, 952.8, 0.00060054,-0.00021836 +07:48:39, 984.86, 953.4, 0.00070529,-0.00021755 diff --git a/pxii_bec/macros/luts/beampos/beam_pos_record_10072258.csv b/pxii_bec/macros/luts/beampos/beam_pos_record_10072258.csv new file mode 100644 index 0000000..9b2375c --- /dev/null +++ b/pxii_bec/macros/luts/beampos/beam_pos_record_10072258.csv @@ -0,0 +1,3 @@ +Beam size: 25 x 25, Energy: 12400 eV, Zoom: 1000.0 +Time,Scin_x,Scin_y,BPM_x,BPM_y +22:58:50, 901.07, 932.5,-135.46,-33.566 diff --git a/pxii_bec/macros/luts/beampos/beam_pos_record_10072259.csv b/pxii_bec/macros/luts/beampos/beam_pos_record_10072259.csv new file mode 100644 index 0000000..e7e1187 --- /dev/null +++ b/pxii_bec/macros/luts/beampos/beam_pos_record_10072259.csv @@ -0,0 +1,65 @@ +Beam size: 25 x 25, Energy: 12400 eV, Zoom: 1000.0 +Time,Scin_x,Scin_y,BPM_x,BPM_y +22:59:30, 900.3, 932.4,-135.68,-33.54 +23:09:36, 899.46, 935.9,-135.67,-33.426 +23:19:42, 903.28, 939.3,-136.19,-33.427 +23:29:47, 906.99, 939.6,-134.18,-33.394 +23:39:53, 904.28, 939.3,-134.4,-33.401 +23:49:59, 908.28, 942.9,-133.11,-33.27 +00:00:05, 907.44, 942.7,-133.88,-33.317 +00:10:11, 909.51, 946.1,-133.69,-33.263 +00:20:16, 908.09, 946.6,-134.91,-33.245 +00:30:22, 907.67, 946.4,-133.5,-33.199 +00:40:27, 910.28, 948.7,-133.62,-33.194 +00:50:33, 910.87, 947.3,-133.73,-33.238 +01:00:39, 910.72, 951.6,-133.14,-33.176 +01:10:45, 916.55, 954.1,-131.75,-33.078 +01:20:50, 914.82, 955.5,-133.03,-33.043 +01:30:56, 915.33, 954.3,-132.77,-33.046 +01:41:02, 916.54, 956.1,-131.25,-33.013 +01:51:07, 914.7, 954.1,-134.45,-33.303 +02:01:13, 915.45, 957.5,-132.93,-32.918 +02:11:22, 822.1, 1182,-131.95,-32.936 +02:21:32, 914.39, 963.1,-132.37,-32.873 +02:31:40, 918.37, 960.1,-130.84,-32.881 +02:41:46, 913.44, 961.6,-133.11,-32.841 +02:51:52, 917.49, 961.6,-132.04,-32.873 +03:01:57, 919.4, 959.6,-130.23,-32.912 +03:12:03, 914.79, 960.1,-133.3,-32.864 +03:22:09, 921.98, 963.7,-130.45,-32.799 +03:32:14, 919.15, 962.6,-131.58,-32.889 +03:42:20, 920.76, 963.4,-131.93,-32.822 +03:52:25, 921.81, 963.9,-131.49,-32.856 +04:02:31, 922.4, 965.7,-130.76,-32.751 +04:12:37, 922.48, 965.7,-131.37,-32.79 +04:22:42, 920.98, 966.2,-131.43,-32.776 +04:32:48, 921.29, 968.2,-131.39,-32.645 +04:42:54, 921.63, 968.6,-130.67,-32.693 +04:52:59, 919.05, 968.9,-131.49,-32.698 +05:03:05, 918.8, 969.1,-131.46,-32.654 +05:13:11, 923.71, 970.4,-131.43,-32.673 +05:23:17, 921.72, 971.2,-131.18,-32.652 +05:33:24, 924.3, 973.8,-130.42,-32.543 +05:43:30, 921.72, 973.5,-131.78,-32.553 +05:53:39, 918.24, 972.7,-132.13,-32.617 +06:03:45, 923.67, 972.5,-130.48,-32.604 +06:13:52, 918.82, 975.2,-132.09,-32.525 +06:23:57, 921.6, 976,-131.13,-32.515 +06:34:03, 923.18, 971.2,-131.09,-32.595 +06:44:08, 923.42, 974.4,-131.62,-32.586 +06:54:14, 921.03, 974.3,-131.22,-32.576 +07:04:20, 922.16, 973.7,-131.06,-32.528 +07:14:25, 920.54, 975.6,-131.66,-32.506 +07:24:31, 921.7, 973.4,-131.76,-32.51 +07:34:36, 922.2, 973.6,-131.19,-32.527 +07:44:42, 921.8, 974.2,-131.18,-32.569 +07:54:48, 921.01, 976.9,-131.15,-32.462 +08:04:53, 919.45, 978.1,-131.82,-32.442 +08:14:59, 924.14, 978.6,-130.17,-32.435 +08:25:04, 925.78, 978.5,-130.74,-32.45 +08:35:10, 925.13, 982.2,-130.34,-32.358 +08:45:16, 925.54, 980.5,-131.56,-32.412 +08:55:21, 925.67, 979.4,-131.03,-32.429 +09:05:27, 921.16, 981,-131.76,-32.395 +09:15:33, 926.87, 982.5,-130.06,-32.37 +09:25:39, 923.88, 983.4,-131.8,-32.344 diff --git a/pxii_bec/macros/luts/beampos/beam_pos_record_11072251.csv b/pxii_bec/macros/luts/beampos/beam_pos_record_11072251.csv new file mode 100644 index 0000000..43fdaf2 --- /dev/null +++ b/pxii_bec/macros/luts/beampos/beam_pos_record_11072251.csv @@ -0,0 +1,66 @@ +Beam size: 25 x 25, Energy: 12400 eV, Zoom: 94.0 +Time,Scin_x,Scin_y,BPM_x,BPM_y +22:51:07, 986.29, 876.8,-47.074,-35.425 +23:01:13, 991.37, 878.3,-45.402,-35.493 +23:11:19, 995.69, 878.9,-44.623,-35.533 +23:21:24, 1000.4, 880.2,-43.2,-35.545 +23:31:30, 1003.1, 883.6,-40.409,-35.466 +23:41:36, 1001.2, 883.5,-42.882,-35.435 +23:51:41, 1006.7, 885.6,-40.094,-35.418 +00:01:47, 1004.9, 888.9,-42.943,-35.231 +00:11:53, 1009.1, 887.6,-40.042,-35.311 +00:21:58, 1007.9, 888.4,-41.53,-35.283 +00:32:04, 1008.5, 888.4,-41.989,-35.212 +00:42:10, 1012.2, 891.2,-40.149,-35.148 +00:52:16, 1014.8, 889.6,-37.801,-35.275 +01:02:21, 1011.1, 889.2,-37.705,-35.241 +01:12:27, 1011.8, 888.9,-37.258,-35.237 +01:22:33, 1012.6, 890.5,-36.993,-35.113 +01:32:38, 1012, 887.7,-38.477,-35.231 +01:42:44, 1012.9, 888,-36.955,-35.338 +01:52:50, 1010.9, 887.2,-38.356,-35.322 +02:02:55, 1012.9, 887.9,-38.797,-35.219 +02:13:01, 1010.9, 884.9,-38.837,-35.37 +02:23:06, 1012.1, 884.9,-38.442,-35.442 +02:33:12, 1011.5, 883.5,-38.277,-35.494 +02:43:18, 1011.5, 882.7,-40.89,-35.484 +02:53:24, 1010.2, 882.2,-38.828,-35.452 +03:03:31, 1009.4, 882.3,-40.958,-35.474 +03:13:37, 1009.3, 882.1,-41.712,-35.514 +03:23:42, 1007.8, 879.8,-40.447,-35.54 +03:33:48, 1007.9, 881.4,-41.661,-35.474 +03:43:53, 1009.3, 881.3,-42.593,-35.556 +03:53:59, 1011.3, 883.2,-39.725,-35.429 +04:04:05, 1009.1, 881.3,-42.053,-35.438 +04:14:10, 1007.9, 878.6,-40.73,-35.686 +04:24:16, 1007.7, 877.4,-42.042,-35.619 +04:34:21, 1005.4, 878.9,-41.025,-35.617 +04:44:27, 1009.1, 876.7,-43.857,-35.628 +04:54:32, 1009.2, 875.6,-42.432,-35.566 +05:04:38, 1005.9, 874.2,-43.239,-35.754 +05:14:44, 1006.9, 876,-41.49,-35.704 +05:24:50, 1008.6, 873.3,-41.177,-35.812 +05:34:56, 1008.6, 878,-42.466,-35.584 +05:45:01, 1010.5, 876.7,-40.377,-35.582 +05:55:07, 1005.8, 875.5,-42.045,-35.707 +06:05:13, 1009.8, 875,-41.514,-35.707 +06:15:18, 1006.9, 874.5,-44.042,-35.713 +06:25:24, 1009.8, 873.4,-41.465,-35.758 +06:35:30, 1006.2, 874.8,-44.756,-35.694 +06:45:36, 1010.3, 852.9,-37.377,-36.678 +06:55:42, 1000.7, 872.6,-46.719,-35.754 +07:05:47, 1000.9, 872.3,-46.029,-35.767 +07:15:53, 1002.1, 869.5,-45.783,-35.829 +07:25:59, 1003.5, 870.2,-45.012,-35.827 +07:36:05, 1002.7, 868.8,-45.994,-35.83 +07:46:14, 1001.5, 870.7,-44.573,-35.802 +07:56:20, 1002.7, 869.2,-44.488,-35.91 +08:06:28, 999.99, 868.7,-46.775,-35.785 +08:16:35, 1002.5, 867.4,-44.101,-35.951 +08:26:40, 1001.9, 867.5,-45.003,-35.914 +08:36:48, 999.38, 864.3,-46.274,-35.987 +08:46:54, 1000.8, 867.3,-46.094,-35.836 +08:57:00, 1000.8, 867,-46.843,-35.864 +09:07:05, 1001.5, 866.2,-45.95,-35.854 +09:17:11, 1002, 868.7,-45.469,-35.84 +09:27:16, 1002.6, 867.5,-43.781,-35.9 diff --git a/pxii_bec/macros/luts/beampos/beampos17_18Jul12p4_16_12p4.csv b/pxii_bec/macros/luts/beampos/beampos17_18Jul12p4_16_12p4.csv new file mode 100644 index 0000000..3236d6c --- /dev/null +++ b/pxii_bec/macros/luts/beampos/beampos17_18Jul12p4_16_12p4.csv @@ -0,0 +1,214 @@ +Beam size: 25 x 25, Energy: 12400 eV, Zoom: 1000.0 +Time,Scin_x,Scin_y,BPM_x,BPM_y +17:07:55, 1081.5, 865.8,-0.10403, 0.046367 +17:13:03, 1082.7, 866.4,-0.11939, 0.050761 +17:18:09, 1085.1, 870.1,-0.11518, 0.046755 +17:23:14, 1087.3, 871.1,-0.094016, 0.046281 +17:28:20, 1085.3, 872,-0.10154, 0.043894 +17:33:27, 1086.7, 871.3,-0.098555, 0.048176 +17:38:32, 1090.3, 874.1,-0.091664, 0.043092 +17:43:40, 1087.9, 873,-0.11371, 0.043823 +17:48:46, 1087.3, 874.7,-0.095203, 0.040304 +17:53:55, 1087.9, 875.3,-0.08925, 0.044265 +17:59:04, 1061.6, 872.7,-0.10805, 0.037891 +18:04:14, 1091.5, 876.4,-0.093787, 0.043133 +18:09:20, 1088.4, 877.4,-0.096473, 0.041942 +18:14:27, 1090.8, 877.3,-0.11096, 0.0401 +18:19:37, 1090.5, 880.1,-0.099086, 0.038092 +18:24:43, 1090.9, 879.8,-0.11313, 0.036666 +18:29:50, 1091.5, 881.2,-0.096125, 0.03569 +18:34:56, 1089.2, 880.3,-0.10161, 0.038647 +18:40:02, 1091.5, 883.7,-0.096326, 0.03126 +18:45:08, 1091.5, 882,-0.093638, 0.037376 +18:50:15, 1093.6, 883.5,-0.10822, 0.03282 +18:55:22, 1092.2, 880.7,-0.097546, 0.036702 +19:00:28, 1091.7, 882.1,-0.099781, 0.038295 +19:05:34, 1091.1, 882.5,-0.10108, 0.036448 +19:10:40, 1091.8, 884.3,-0.098202, 0.032866 +19:15:46, 1091.8, 883.2,-0.096186, 0.032321 +19:20:53, 1092.8, 883.4,-0.11828, 0.029995 +19:26:01, 1091.5, 885,-0.095478, 0.031696 +19:31:07, 1094.2, 885.1,-0.094126, 0.031878 +19:36:13, 1094.2, 883.9,-0.094852, 0.035436 +19:41:21, 1093.2, 884.2,-0.11022, 0.031471 +19:46:27, 1093.4, 884.6,-0.093274, 0.031055 +19:51:34, 1092.1, 883.2,-0.11996, 0.030071 +19:56:40, 1094.7, 883.5,-0.090561, 0.032072 +20:01:46, 1090.9, 883.1,-0.093273, 0.034408 +20:06:53, 1091.3, 880.8,-0.10919, 0.036667 +20:12:01, 1095.9, 882.3,-0.087907, 0.033331 +20:17:08, 1093.4, 883.8,-0.11177, 0.027881 +20:22:16, 1090.5, 883.4,-0.099112, 0.029205 +20:27:21, 1091.5, 883.1,-0.093811, 0.029466 +20:32:27, 1091, 883.2,-0.096633, 0.030197 +20:37:35, 1089.9, 881.2,-0.11515, 0.031255 +20:42:43, 1091.8, 883.1,-0.096172, 0.030463 +20:47:50, 1092.4, 884.6,-0.10933, 0.028769 +20:52:56, 1092.8, 880.8,-0.10945, 0.033085 +20:58:02, 1091.9, 883.7,-0.11175, 0.029983 +21:03:11, 1091.2, 880.8,-0.091632, 0.030885 +21:08:17, 1091.7, 883.6,-0.10002, 0.030234 +21:13:24, 1090, 880.9,-0.11468, 0.033629 +21:18:33, 1092, 880.4,-0.089628, 0.033297 +21:23:38, 1094.2, 882.4,-0.087731, 0.033577 +21:28:44, 1092.7, 881.6,-0.096102, 0.03349 +21:33:50, 1094.8, 883.8,-0.090251, 0.02944 +21:38:56, 1096.3, 883.9,-0.090513, 0.03052 +21:44:03, 1093, 882.9,-0.11005, 0.030832 +21:49:09, 1092.4, 882.5,-0.087522, 0.03369 +21:54:15, 1094.1, 884.4,-0.091044, 0.030247 +21:59:22, 1095.2, 886.1,-0.10962, 0.024788 +22:04:30, 1094.6, 883.9,-0.089036, 0.031714 +22:09:36, 1090.9, 883.6,-0.095784, 0.028957 +22:14:44, 1091.7, 885.4,-0.10729, 0.027359 +22:19:51, 1092.7, 884.2,-0.091738, 0.029183 +22:24:59, 1092.9, 882.2,-0.11385, 0.030234 +22:30:08, 1093.3, 884.4,-0.093892, 0.029451 +22:35:14, 1095.9, 884.5,-0.086609, 0.029973 +22:40:19, 1094.8, 885.4,-0.086979, 0.026603 +22:45:25, 1092.6, 885.5,-0.093908, 0.028651 +22:50:33, 1095, 883.2,-0.10473, 0.028907 +22:55:39, 1094.6, 883.6,-0.10637, 0.030962 +22:57:15, 1098, 878.9,-0.073165, 0.035505 +23:02:23, 1097.6, 879.1,-0.064012, 0.034825 +23:07:29, 1101.1, 878.5,-0.053059, 0.036454 +23:12:35, 1096.5, 879.9,-0.056435, 0.032432 +23:17:41, 1097.2, 878.2,-0.061311, 0.032143 +23:22:48, 1100, 879.4,-0.060269, 0.03079 +23:27:54, 1098.7, 878.3,-0.051592, 0.03348 +23:33:02, 1096.6, 879,-0.066266, 0.031853 +23:38:09, 1097.7, 878.8,-0.048859, 0.032677 +23:43:15, 1098.5, 877.5,-0.05091, 0.036148 +23:48:21, 1101.6, 878.2,-0.046499, 0.033352 +23:53:26, 1097.4, 878.7,-0.057467, 0.032821 +23:58:32, 1099.4, 876.8,-0.049522, 0.037438 +00:03:38, 1098.7, 877.7,-0.052748, 0.034827 +00:08:46, 1098.4, 877.9,-0.062436, 0.031424 +00:13:54, 1096.8, 877.8,-0.056041, 0.03579 +00:19:01, 1098.5, 879,-0.058908, 0.03372 +00:24:06, 1097.7, 879.9,-0.058404, 0.030124 +00:29:12, 1097.9, 877.7,-0.060684, 0.036442 +00:34:18, 1097.2, 878.2,-0.064929, 0.034695 +00:39:24, 1097.9, 878.6,-0.058925, 0.032791 +00:44:30, 1099.8, 878.8,-0.052343, 0.03565 +00:49:37, 1095.6, 875.9,-0.072043, 0.035027 +00:54:43, 1099.6, 879.7,-0.051911, 0.03431 +00:59:50, 1096.5, 880.1,-0.068103, 0.032352 +01:04:55, 1096.7, 877.9,-0.063349, 0.036794 +01:10:03, 1098.3, 878.9,-0.063479, 0.035299 +01:15:08, 1097.7, 877.5,-0.06252, 0.036833 +01:20:16, 1096.9, 880.2,-0.059832, 0.033268 +01:25:22, 1096.6, 878.3,-0.062183, 0.035198 +01:30:29, 1099.5, 877.6,-0.065986, 0.034114 +01:35:36, 1097.2, 879.4,-0.062591, 0.034039 +01:40:42, 1098.8, 878.7,-0.057664, 0.03431 +01:45:48, 1098, 878.6,-0.056329, 0.035506 +01:50:54, 1097.2, 877.7,-0.059495, 0.03825 +01:56:00, 1097.1, 878.8,-0.06187, 0.035319 +02:01:06, 1100.4, 877.8,-0.050598, 0.039153 +02:06:13, 1095.9, 879.8,-0.072556, 0.033639 +02:11:19, 1093.3, 877.8,-0.066548, 0.036513 +02:16:26, 1096.2, 877.9,-0.070999, 0.035202 +02:21:32, 1095.1, 879.1,-0.075426, 0.03017 +02:26:39, 1096.6, 878.4,-0.06107, 0.034835 +02:31:47, 1094.6, 877,-0.079564, 0.034497 +02:36:52, 1093.4, 876.3,-0.074446, 0.03348 +02:41:58, 1094.7, 876.8,-0.060807, 0.036994 +02:47:04, 1093.1, 876.6,-0.068357, 0.037341 +02:52:10, 1096.6, 877.6,-0.064314, 0.038357 +02:57:18, 1096.6, 878,-0.069532, 0.036905 +03:02:24, 1095, 878.6,-0.062256, 0.037013 +03:07:31, 1095.6, 878.8,-0.067727, 0.036823 +03:12:37, 1093.3, 878.9,-0.077432, 0.034467 +03:17:43, 1094.7, 877.6,-0.065401, 0.034343 +03:22:50, 1096.1, 879.2,-0.070851, 0.034334 +03:27:57, 1094.1, 879,-0.067534, 0.0343 +03:33:05, 1096.7, 877.7,-0.067384, 0.036214 +03:38:13, 1092, 879.3,-0.07331, 0.031179 +03:43:20, 1091.2, 877.8,-0.084606, 0.033658 +03:48:26, 1094.1, 877.5,-0.076603, 0.034474 +03:53:32, 1096.2, 877.8,-0.06236, 0.035214 +03:58:38, 1092.8, 877.2,-0.067829, 0.038182 +04:03:43, 1091.7, 878.3,-0.077367, 0.03589 +04:08:49, 1093.5, 876.9,-0.062241, 0.035776 +04:13:55, 1093.2, 877.5,-0.068524, 0.03702 +04:19:01, 1092.1, 877.7,-0.070266, 0.038713 +04:24:06, 1091.4, 877.3,-0.068818, 0.037419 +04:29:14, 1092.1, 876.6,-0.076505, 0.037539 +04:34:21, 1091, 877.8,-0.074625, 0.036015 +04:39:29, 1093, 876.5,-0.078857, 0.036288 +04:44:37, 1090.3, 878,-0.075081, 0.03482 +04:49:43, 1089.5, 876.3,-0.075537, 0.03662 +04:54:48, 1089, 876.2,-0.072292, 0.037192 +04:59:54, 1088.9, 876.1,-0.069099, 0.036205 +05:01:19, 1085.2, 879.8,-0.089858, 0.029898 +05:06:27, 1084.8, 878.6,-0.11746, 0.032844 +05:11:35, 1085.8, 880.1,-0.095173, 0.034515 +05:16:42, 1085.8, 880,-0.11522, 0.03181 +05:21:48, 1085.3, 880.2,-0.096485, 0.028819 +05:26:54, 1085.4, 879.2,-0.10018, 0.033464 +05:31:59, 1083.6, 877.8,-0.10519, 0.035801 +05:37:05, 1083.9, 876.7,-0.10184, 0.037695 +05:42:13, 1084.8, 878.7,-0.11544, 0.031789 +05:47:18, 1082.4, 878.3,-0.12281, 0.0355 +05:52:24, 1085.2, 879.5,-0.11633, 0.035254 +05:57:30, 1083.6, 879.3,-0.10228, 0.034844 +06:02:36, 1084.9, 878.1,-0.10548, 0.039 +06:07:43, 1086.7, 879.4,-0.11735, 0.035257 +06:12:51, 1084.7, 879,-0.096472, 0.036453 +06:17:57, 1082, 881.2,-0.10718, 0.032353 +06:23:05, 1083.2, 879.9,-0.12451, 0.033221 +06:28:10, 1084.5, 879.9,-0.10073, 0.037029 +06:33:16, 1086.2, 880.4,-0.099724, 0.034742 +06:38:23, 1085.8, 880.2,-0.11435, 0.034298 +06:43:29, 1084.4, 879.8,-0.11895, 0.034462 +06:48:35, 1081.6, 880.9,-0.10867, 0.030497 +06:53:41, 1082, 879.8,-0.10593, 0.033209 +06:58:47, 1085, 878.8,-0.10886, 0.036345 +07:03:54, 1081.9, 877.9,-0.12135, 0.035835 +07:09:00, 1088.1, 879.9,-0.10444, 0.031292 +07:14:07, 1080.5, 879.9,-0.12658, 0.031595 +07:19:13, 1080.3, 879.5,-0.12783, 0.031302 +07:24:21, 1082, 880.1,-0.1034, 0.033087 +07:29:27, 1080.1, 878.6,-0.1072, 0.034435 +07:34:34, 1082.7, 879.1,-0.12635, 0.032225 +07:39:39, 1080.4, 879.7,-0.11149, 0.033945 +07:44:45, 1081.6, 878,-0.11343, 0.033964 +07:49:51, 1080.8, 877.5,-0.11568, 0.036602 +07:54:57, 1082.1, 877.4,-0.10876, 0.036709 +08:00:02, 1083.3, 879.8,-0.10757, 0.032981 +08:05:09, 1083.4, 878.2,-0.10264, 0.036 +08:10:14, 1080.8, 879.2,-0.11003, 0.03398 +08:15:20, 1082.4, 878.3,-0.1161, 0.03375 +08:20:26, 1081.1, 878.7,-0.10953, 0.033336 +08:25:32, 1081.5, 875.8,-0.12031, 0.036639 +08:30:37, 1081.9, 878.1,-0.11083, 0.036778 +08:35:43, 1081.2, 878.5,-0.11116, 0.034261 +08:40:51, 1083.7, 878.7,-0.12381, 0.034651 +08:45:57, 1081.6, 880,-0.11309, 0.033298 +08:51:04, 1081.9, 878.6,-0.12726, 0.033666 +08:56:10, 1082.3, 880,-0.10964, 0.031341 +09:01:16, 1081, 880.7,-0.11554, 0.030422 +09:06:22, 1081.9, 878.7,-0.11291, 0.035648 +09:11:28, 1082.8, 879.4,-0.10992, 0.035585 +09:16:34, 1081.7, 882,-0.114, 0.032917 +09:21:42, 1081, 879.7,-0.12921, 0.033436 +09:26:47, 1083, 879.6,-0.10846, 0.033416 +09:31:53, 1079.4, 877.3,-0.11919, 0.036546 +09:36:59, 1081.3, 878,-0.11206, 0.034952 +09:42:05, 1082.3, 877.4,-0.10946, 0.037359 +09:47:11, 1080.8, 878.4,-0.11578, 0.033721 +09:52:17, 1082.6, 877.5,-0.11174, 0.034509 +09:57:24, 1079.7, 879.5,-0.1327, 0.032061 +10:02:30, 1079.3, 876.9,-0.12054, 0.035242 +10:07:35, 1078.6, 876.5,-0.11343, 0.03723 +10:12:41, 1078.1, 874.7,-0.11949, 0.03935 +10:17:47, 1076.4, 877.4,-0.12557, 0.034068 +10:22:52, 1077.2, 876.5,-0.11696, 0.03674 +10:27:58, 1076, 876.6,-0.11708, 0.037681 +10:33:06, 1075.2, 874.9,-0.13592, 0.03779 +10:38:12, 1074.8, 878.8,-0.11876, 0.034751 +10:43:18, 1072.8, 877,-0.12729, 0.035958 +10:48:24, 1073.6, 874.5,-0.12293, 0.038995 +10:53:32, 1073.9, 876.6,-0.14351, 0.031106 +10:58:38, 1075.3, 876.3,-0.14305, 0.035249 diff --git a/pxii_bec/macros/luts/beampos/beampos_0207.csv b/pxii_bec/macros/luts/beampos/beampos_0207.csv new file mode 100644 index 0000000..900d77c --- /dev/null +++ b/pxii_bec/macros/luts/beampos/beampos_0207.csv @@ -0,0 +1,57 @@ +Beam size: focus, Energy: 12400 eV, Zoom: 1000.0 +Time,Scin_x,Scin_y +22:44:24, 1047.8, 984.4 +22:54:27, 1042.3, 990.1 +23:04:31, 1039.3, 993.6 +23:14:34, 1036, 996.9 +23:24:38, 1033.6, 998.3 +23:34:41, 1033.2, 998.5 +23:44:44, 1032.5, 1000 +23:54:48, 1030.5, 1001 +00:04:51, 1029.6, 1003 +00:14:54, 1029.4, 1003 +00:24:57, 1028.2, 1004 +00:35:00, 1028.4, 1005 +00:45:04, 1030, 1008 +00:55:07, 1027.9, 1006 +01:05:10, 1027.5, 1009 +01:15:13, 1029.1, 1008 +01:25:17, 1028, 1008 +01:35:20, 1027.3, 1010 +01:45:23, 1029.6, 1011 +01:55:27, 1029, 1011 +02:05:30, 1026, 1011 +02:15:33, 1029.5, 1011 +02:25:36, 1028.3, 1011 +02:35:40, 1027.9, 1012 +02:45:43, 1027.7, 1013 +02:55:46, 1028.2, 1012 +03:05:49, 1027.2, 1014 +03:15:53, 1028.5, 1012 +03:25:56, 1025.8, 1014 +03:35:59, 1030.8, 1015 +03:46:02, 1028.3, 1015 +03:56:05, 1025.8, 1016 +04:06:09, 1027, 1015 +04:16:12, 1029.3, 1018 +04:26:15, 1029.9, 1018 +04:36:19, 1029.3, 1015 +04:46:22, 1029.2, 1018 +04:56:25, 1029.5, 1015 +05:06:28, 1031.8, 1016 +05:16:31, 1032.3, 1015 +05:26:35, 1030.7, 1017 +05:36:38, 1030.7, 1018 +05:46:41, 1030.2, 1017 +05:56:44, 1031.5, 1019 +06:06:48, 1029.3, 1018 +06:16:52, 1030.7, 1021 +06:26:55, 1031.5, 1019 +06:36:58, 1028.6, 1023 +06:47:01, 1027.9, 1021 +06:57:05, 1029.2, 1022 +07:07:08, 1028.6, 1022 +07:17:11, 1026.2, 1021 +07:27:14, 1028.7, 1022 +07:37:18, 1028.1, 1022 +07:47:21, 1029.4, 1020 diff --git a/pxii_bec/macros/luts/beampos/beampos_17071707.csv b/pxii_bec/macros/luts/beampos/beampos_17071707.csv new file mode 100644 index 0000000..ccbc557 --- /dev/null +++ b/pxii_bec/macros/luts/beampos/beampos_17071707.csv @@ -0,0 +1,71 @@ +Beam size: 25 x 25, Energy: 12400 eV, Zoom: 1000.0 +Time,Scin_x,Scin_y,BPM_x,BPM_y +17:07:55, 1081.5, 865.8,-0.10403, 0.046367 +17:13:03, 1082.7, 866.4,-0.11939, 0.050761 +17:18:09, 1085.1, 870.1,-0.11518, 0.046755 +17:23:14, 1087.3, 871.1,-0.094016, 0.046281 +17:28:20, 1085.3, 872,-0.10154, 0.043894 +17:33:27, 1086.7, 871.3,-0.098555, 0.048176 +17:38:32, 1090.3, 874.1,-0.091664, 0.043092 +17:43:40, 1087.9, 873,-0.11371, 0.043823 +17:48:46, 1087.3, 874.7,-0.095203, 0.040304 +17:53:55, 1087.9, 875.3,-0.08925, 0.044265 +17:59:04, 1061.6, 872.7,-0.10805, 0.037891 +18:04:14, 1091.5, 876.4,-0.093787, 0.043133 +18:09:20, 1088.4, 877.4,-0.096473, 0.041942 +18:14:27, 1090.8, 877.3,-0.11096, 0.0401 +18:19:37, 1090.5, 880.1,-0.099086, 0.038092 +18:24:43, 1090.9, 879.8,-0.11313, 0.036666 +18:29:50, 1091.5, 881.2,-0.096125, 0.03569 +18:34:56, 1089.2, 880.3,-0.10161, 0.038647 +18:40:02, 1091.5, 883.7,-0.096326, 0.03126 +18:45:08, 1091.5, 882,-0.093638, 0.037376 +18:50:15, 1093.6, 883.5,-0.10822, 0.03282 +18:55:22, 1092.2, 880.7,-0.097546, 0.036702 +19:00:28, 1091.7, 882.1,-0.099781, 0.038295 +19:05:34, 1091.1, 882.5,-0.10108, 0.036448 +19:10:40, 1091.8, 884.3,-0.098202, 0.032866 +19:15:46, 1091.8, 883.2,-0.096186, 0.032321 +19:20:53, 1092.8, 883.4,-0.11828, 0.029995 +19:26:01, 1091.5, 885,-0.095478, 0.031696 +19:31:07, 1094.2, 885.1,-0.094126, 0.031878 +19:36:13, 1094.2, 883.9,-0.094852, 0.035436 +19:41:21, 1093.2, 884.2,-0.11022, 0.031471 +19:46:27, 1093.4, 884.6,-0.093274, 0.031055 +19:51:34, 1092.1, 883.2,-0.11996, 0.030071 +19:56:40, 1094.7, 883.5,-0.090561, 0.032072 +20:01:46, 1090.9, 883.1,-0.093273, 0.034408 +20:06:53, 1091.3, 880.8,-0.10919, 0.036667 +20:12:01, 1095.9, 882.3,-0.087907, 0.033331 +20:17:08, 1093.4, 883.8,-0.11177, 0.027881 +20:22:16, 1090.5, 883.4,-0.099112, 0.029205 +20:27:21, 1091.5, 883.1,-0.093811, 0.029466 +20:32:27, 1091, 883.2,-0.096633, 0.030197 +20:37:35, 1089.9, 881.2,-0.11515, 0.031255 +20:42:43, 1091.8, 883.1,-0.096172, 0.030463 +20:47:50, 1092.4, 884.6,-0.10933, 0.028769 +20:52:56, 1092.8, 880.8,-0.10945, 0.033085 +20:58:02, 1091.9, 883.7,-0.11175, 0.029983 +21:03:11, 1091.2, 880.8,-0.091632, 0.030885 +21:08:17, 1091.7, 883.6,-0.10002, 0.030234 +21:13:24, 1090, 880.9,-0.11468, 0.033629 +21:18:33, 1092, 880.4,-0.089628, 0.033297 +21:23:38, 1094.2, 882.4,-0.087731, 0.033577 +21:28:44, 1092.7, 881.6,-0.096102, 0.03349 +21:33:50, 1094.8, 883.8,-0.090251, 0.02944 +21:38:56, 1096.3, 883.9,-0.090513, 0.03052 +21:44:03, 1093, 882.9,-0.11005, 0.030832 +21:49:09, 1092.4, 882.5,-0.087522, 0.03369 +21:54:15, 1094.1, 884.4,-0.091044, 0.030247 +21:59:22, 1095.2, 886.1,-0.10962, 0.024788 +22:04:30, 1094.6, 883.9,-0.089036, 0.031714 +22:09:36, 1090.9, 883.6,-0.095784, 0.028957 +22:14:44, 1091.7, 885.4,-0.10729, 0.027359 +22:19:51, 1092.7, 884.2,-0.091738, 0.029183 +22:24:59, 1092.9, 882.2,-0.11385, 0.030234 +22:30:08, 1093.3, 884.4,-0.093892, 0.029451 +22:35:14, 1095.9, 884.5,-0.086609, 0.029973 +22:40:19, 1094.8, 885.4,-0.086979, 0.026603 +22:45:25, 1092.6, 885.5,-0.093908, 0.028651 +22:50:33, 1095, 883.2,-0.10473, 0.028907 +22:55:39, 1094.6, 883.6,-0.10637, 0.030962 diff --git a/pxii_bec/macros/luts/beampos/beampos_17072256.csv b/pxii_bec/macros/luts/beampos/beampos_17072256.csv new file mode 100644 index 0000000..c3105d4 --- /dev/null +++ b/pxii_bec/macros/luts/beampos/beampos_17072256.csv @@ -0,0 +1,74 @@ +Beam size: 25 x 25, Energy: 16000 eV, Zoom: 1000.0 +Time,Scin_x,Scin_y,BPM_x,BPM_y +22:57:15, 1098, 878.9,-0.073165, 0.035505 +23:02:23, 1097.6, 879.1,-0.064012, 0.034825 +23:07:29, 1101.1, 878.5,-0.053059, 0.036454 +23:12:35, 1096.5, 879.9,-0.056435, 0.032432 +23:17:41, 1097.2, 878.2,-0.061311, 0.032143 +23:22:48, 1100, 879.4,-0.060269, 0.03079 +23:27:54, 1098.7, 878.3,-0.051592, 0.03348 +23:33:02, 1096.6, 879,-0.066266, 0.031853 +23:38:09, 1097.7, 878.8,-0.048859, 0.032677 +23:43:15, 1098.5, 877.5,-0.05091, 0.036148 +23:48:21, 1101.6, 878.2,-0.046499, 0.033352 +23:53:26, 1097.4, 878.7,-0.057467, 0.032821 +23:58:32, 1099.4, 876.8,-0.049522, 0.037438 +00:03:38, 1098.7, 877.7,-0.052748, 0.034827 +00:08:46, 1098.4, 877.9,-0.062436, 0.031424 +00:13:54, 1096.8, 877.8,-0.056041, 0.03579 +00:19:01, 1098.5, 879,-0.058908, 0.03372 +00:24:06, 1097.7, 879.9,-0.058404, 0.030124 +00:29:12, 1097.9, 877.7,-0.060684, 0.036442 +00:34:18, 1097.2, 878.2,-0.064929, 0.034695 +00:39:24, 1097.9, 878.6,-0.058925, 0.032791 +00:44:30, 1099.8, 878.8,-0.052343, 0.03565 +00:49:37, 1095.6, 875.9,-0.072043, 0.035027 +00:54:43, 1099.6, 879.7,-0.051911, 0.03431 +00:59:50, 1096.5, 880.1,-0.068103, 0.032352 +01:04:55, 1096.7, 877.9,-0.063349, 0.036794 +01:10:03, 1098.3, 878.9,-0.063479, 0.035299 +01:15:08, 1097.7, 877.5,-0.06252, 0.036833 +01:20:16, 1096.9, 880.2,-0.059832, 0.033268 +01:25:22, 1096.6, 878.3,-0.062183, 0.035198 +01:30:29, 1099.5, 877.6,-0.065986, 0.034114 +01:35:36, 1097.2, 879.4,-0.062591, 0.034039 +01:40:42, 1098.8, 878.7,-0.057664, 0.03431 +01:45:48, 1098, 878.6,-0.056329, 0.035506 +01:50:54, 1097.2, 877.7,-0.059495, 0.03825 +01:56:00, 1097.1, 878.8,-0.06187, 0.035319 +02:01:06, 1100.4, 877.8,-0.050598, 0.039153 +02:06:13, 1095.9, 879.8,-0.072556, 0.033639 +02:11:19, 1093.3, 877.8,-0.066548, 0.036513 +02:16:26, 1096.2, 877.9,-0.070999, 0.035202 +02:21:32, 1095.1, 879.1,-0.075426, 0.03017 +02:26:39, 1096.6, 878.4,-0.06107, 0.034835 +02:31:47, 1094.6, 877,-0.079564, 0.034497 +02:36:52, 1093.4, 876.3,-0.074446, 0.03348 +02:41:58, 1094.7, 876.8,-0.060807, 0.036994 +02:47:04, 1093.1, 876.6,-0.068357, 0.037341 +02:52:10, 1096.6, 877.6,-0.064314, 0.038357 +02:57:18, 1096.6, 878,-0.069532, 0.036905 +03:02:24, 1095, 878.6,-0.062256, 0.037013 +03:07:31, 1095.6, 878.8,-0.067727, 0.036823 +03:12:37, 1093.3, 878.9,-0.077432, 0.034467 +03:17:43, 1094.7, 877.6,-0.065401, 0.034343 +03:22:50, 1096.1, 879.2,-0.070851, 0.034334 +03:27:57, 1094.1, 879,-0.067534, 0.0343 +03:33:05, 1096.7, 877.7,-0.067384, 0.036214 +03:38:13, 1092, 879.3,-0.07331, 0.031179 +03:43:20, 1091.2, 877.8,-0.084606, 0.033658 +03:48:26, 1094.1, 877.5,-0.076603, 0.034474 +03:53:32, 1096.2, 877.8,-0.06236, 0.035214 +03:58:38, 1092.8, 877.2,-0.067829, 0.038182 +04:03:43, 1091.7, 878.3,-0.077367, 0.03589 +04:08:49, 1093.5, 876.9,-0.062241, 0.035776 +04:13:55, 1093.2, 877.5,-0.068524, 0.03702 +04:19:01, 1092.1, 877.7,-0.070266, 0.038713 +04:24:06, 1091.4, 877.3,-0.068818, 0.037419 +04:29:14, 1092.1, 876.6,-0.076505, 0.037539 +04:34:21, 1091, 877.8,-0.074625, 0.036015 +04:39:29, 1093, 876.5,-0.078857, 0.036288 +04:44:37, 1090.3, 878,-0.075081, 0.03482 +04:49:43, 1089.5, 876.3,-0.075537, 0.03662 +04:54:48, 1089, 876.2,-0.072292, 0.037192 +04:59:54, 1088.9, 876.1,-0.069099, 0.036205 diff --git a/pxii_bec/macros/luts/beampos/beampos_18070501.csv b/pxii_bec/macros/luts/beampos/beampos_18070501.csv new file mode 100644 index 0000000..02babb8 --- /dev/null +++ b/pxii_bec/macros/luts/beampos/beampos_18070501.csv @@ -0,0 +1,73 @@ +Beam size: 25 x 25, Energy: 12400 eV, Zoom: 1000.0 +Time,Scin_x,Scin_y,BPM_x,BPM_y +05:01:19, 1085.2, 879.8,-0.089858, 0.029898 +05:06:27, 1084.8, 878.6,-0.11746, 0.032844 +05:11:35, 1085.8, 880.1,-0.095173, 0.034515 +05:16:42, 1085.8, 880,-0.11522, 0.03181 +05:21:48, 1085.3, 880.2,-0.096485, 0.028819 +05:26:54, 1085.4, 879.2,-0.10018, 0.033464 +05:31:59, 1083.6, 877.8,-0.10519, 0.035801 +05:37:05, 1083.9, 876.7,-0.10184, 0.037695 +05:42:13, 1084.8, 878.7,-0.11544, 0.031789 +05:47:18, 1082.4, 878.3,-0.12281, 0.0355 +05:52:24, 1085.2, 879.5,-0.11633, 0.035254 +05:57:30, 1083.6, 879.3,-0.10228, 0.034844 +06:02:36, 1084.9, 878.1,-0.10548, 0.039 +06:07:43, 1086.7, 879.4,-0.11735, 0.035257 +06:12:51, 1084.7, 879,-0.096472, 0.036453 +06:17:57, 1082, 881.2,-0.10718, 0.032353 +06:23:05, 1083.2, 879.9,-0.12451, 0.033221 +06:28:10, 1084.5, 879.9,-0.10073, 0.037029 +06:33:16, 1086.2, 880.4,-0.099724, 0.034742 +06:38:23, 1085.8, 880.2,-0.11435, 0.034298 +06:43:29, 1084.4, 879.8,-0.11895, 0.034462 +06:48:35, 1081.6, 880.9,-0.10867, 0.030497 +06:53:41, 1082, 879.8,-0.10593, 0.033209 +06:58:47, 1085, 878.8,-0.10886, 0.036345 +07:03:54, 1081.9, 877.9,-0.12135, 0.035835 +07:09:00, 1088.1, 879.9,-0.10444, 0.031292 +07:14:07, 1080.5, 879.9,-0.12658, 0.031595 +07:19:13, 1080.3, 879.5,-0.12783, 0.031302 +07:24:21, 1082, 880.1,-0.1034, 0.033087 +07:29:27, 1080.1, 878.6,-0.1072, 0.034435 +07:34:34, 1082.7, 879.1,-0.12635, 0.032225 +07:39:39, 1080.4, 879.7,-0.11149, 0.033945 +07:44:45, 1081.6, 878,-0.11343, 0.033964 +07:49:51, 1080.8, 877.5,-0.11568, 0.036602 +07:54:57, 1082.1, 877.4,-0.10876, 0.036709 +08:00:02, 1083.3, 879.8,-0.10757, 0.032981 +08:05:09, 1083.4, 878.2,-0.10264, 0.036 +08:10:14, 1080.8, 879.2,-0.11003, 0.03398 +08:15:20, 1082.4, 878.3,-0.1161, 0.03375 +08:20:26, 1081.1, 878.7,-0.10953, 0.033336 +08:25:32, 1081.5, 875.8,-0.12031, 0.036639 +08:30:37, 1081.9, 878.1,-0.11083, 0.036778 +08:35:43, 1081.2, 878.5,-0.11116, 0.034261 +08:40:51, 1083.7, 878.7,-0.12381, 0.034651 +08:45:57, 1081.6, 880,-0.11309, 0.033298 +08:51:04, 1081.9, 878.6,-0.12726, 0.033666 +08:56:10, 1082.3, 880,-0.10964, 0.031341 +09:01:16, 1081, 880.7,-0.11554, 0.030422 +09:06:22, 1081.9, 878.7,-0.11291, 0.035648 +09:11:28, 1082.8, 879.4,-0.10992, 0.035585 +09:16:34, 1081.7, 882,-0.114, 0.032917 +09:21:42, 1081, 879.7,-0.12921, 0.033436 +09:26:47, 1083, 879.6,-0.10846, 0.033416 +09:31:53, 1079.4, 877.3,-0.11919, 0.036546 +09:36:59, 1081.3, 878,-0.11206, 0.034952 +09:42:05, 1082.3, 877.4,-0.10946, 0.037359 +09:47:11, 1080.8, 878.4,-0.11578, 0.033721 +09:52:17, 1082.6, 877.5,-0.11174, 0.034509 +09:57:24, 1079.7, 879.5,-0.1327, 0.032061 +10:02:30, 1079.3, 876.9,-0.12054, 0.035242 +10:07:35, 1078.6, 876.5,-0.11343, 0.03723 +10:12:41, 1078.1, 874.7,-0.11949, 0.03935 +10:17:47, 1076.4, 877.4,-0.12557, 0.034068 +10:22:52, 1077.2, 876.5,-0.11696, 0.03674 +10:27:58, 1076, 876.6,-0.11708, 0.037681 +10:33:06, 1075.2, 874.9,-0.13592, 0.03779 +10:38:12, 1074.8, 878.8,-0.11876, 0.034751 +10:43:18, 1072.8, 877,-0.12729, 0.035958 +10:48:24, 1073.6, 874.5,-0.12293, 0.038995 +10:53:32, 1073.9, 876.6,-0.14351, 0.031106 +10:58:38, 1075.3, 876.3,-0.14305, 0.035249 diff --git a/pxii_bec/macros/luts/beampos/beampos_18071135.csv b/pxii_bec/macros/luts/beampos/beampos_18071135.csv new file mode 100644 index 0000000..767fc02 --- /dev/null +++ b/pxii_bec/macros/luts/beampos/beampos_18071135.csv @@ -0,0 +1,78 @@ +Beam size: 25 x 25, Energy: 10000 eV, Zoom: 1000.0 +Time,Scin_x,Scin_y,BPM_x,BPM_y +11:35:45, 1062.5, 868.9,-0.11896, 0.01887 +11:40:52, 1063, 871.8,-0.12142, 0.014688 +11:45:58, 1066.9, 874.7,-0.12046, 0.0086598 +11:51:04, 1068, 876.4,-0.1167, 0.017193 +11:56:10, 1068.1, 874.4,-0.12148, 0.018058 +12:01:16, 1068.2, 878.5,-0.11942, 0.008117 +12:06:22, 1068.7, 878,-0.12182, 0.0070722 +12:11:28, 1070.3, 876.5,-0.12096, 0.013999 +12:16:34, 1070.5, 874.9,-0.11751, 0.020493 +12:21:40, 1075.6, 877.7,-0.11723, 0.018245 +12:26:46, 1071.5, 881.7,-0.12407, 0.0088893 +12:31:51, 1071, 879.9,-0.1276, 0.01151 +12:36:58, 1070.4, 882.6,-0.12483, 0.0062113 +12:42:04, 1072.2, 880.9,-0.11932, 0.0076498 +12:47:09, 1073.2, 882.1,-0.11921, 0.0075093 +12:52:15, 1071.3, 881.3,-0.12551, 0.015369 +12:57:21, 1073.9, 880.4,-0.11533, 0.011686 +13:02:27, 1074.1, 879.6,-0.12139, 0.012885 +13:07:33, 1073.4, 881.4,-0.12404, 0.009902 +13:12:39, 1076.1, 881.6,-0.12028, 0.011644 +13:17:45, 1077.2, 883.2,-0.11862, 0.0070691 +13:22:51, 1075, 879.1,-0.1205, 0.016371 +13:27:57, 1077, 879.8,-0.11828, 0.013926 +13:33:03, 1077.7, 882.4,-0.11576, 0.008192 +13:38:09, 1076, 880.3,-0.12159, 0.014465 +13:43:15, 1077.1, 881.2,-0.12135, 0.013428 +13:48:21, 1077.2, 882.7,-0.11629, 0.0082309 +13:53:27, 1078.9, 883.6,-0.12406, 0.0064463 +13:58:33, 1076.2, 882.8,-0.11756, 0.0078457 +14:03:38, 1076.6, 881.5,-0.11809, 0.012274 +14:08:44, 1077.1, 883.7,-0.12376, 0.0075757 +14:13:50, 1075, 883.6,-0.11847, 0.0069435 +14:18:56, 1075.7, 881.3,-0.1204, 0.011577 +14:24:01, 1076.4, 881,-0.12215, 0.012281 +14:29:07, 1075.7, 881.6,-0.12133, 0.0040628 +14:34:13, 1075.9, 882.5,-0.11678, 0.0065513 +14:39:19, 1077.6, 880.5,-0.11551, 0.011332 +14:44:24, 1075.9, 881.1,-0.12023, 0.013476 +14:49:31, 1076.8, 881.9,-0.11705, 0.011102 +14:54:37, 1076.8, 881.6,-0.11483, 0.016159 +14:59:42, 1077.6, 880.7,-0.1214, 0.013621 +15:04:48, 1077.1, 884.1,-0.11704, 0.0070347 +15:09:54, 1076.7, 882.3,-0.11226, 0.011983 +15:15:00, 1076.1, 884.4,-0.11965, 0.0086288 +15:20:05, 1077, 883.2,-0.1144, 0.0095036 +15:25:11, 1077, 884,-0.11607, 0.0082163 +15:30:17, 1076.5, 883.6,-0.12069, 0.0088895 +15:35:23, 1075.8, 883.5,-0.11596, 0.011014 +15:40:29, 1079, 885.1,-0.11446, 0.011612 +15:45:35, 1078.8, 886.3,-0.11167, 0.0078587 +15:50:40, 1079.9, 884.1,-0.11666, 0.01034 +15:55:46, 1080.4, 883.7,-0.11024, 0.010066 +16:00:52, 1079.9, 883.7,-0.10819, 0.012905 +16:05:58, 1080.4, 888,-0.11271, 0.0021722 +16:11:03, 1079.3, 886.7,-0.11757, 0.0040589 +16:16:09, 1080.2, 888.7,-0.11446,-0.00084994 +16:21:15, 1082.1, 885.8,-0.10947, 0.0059782 +16:26:21, 1079, 887.4,-0.11827, 0.0029425 +16:31:27, 1078.7, 884.6,-0.11141, 0.011771 +16:36:33, 1077.1, 884.2,-0.11274, 0.01089 +16:41:38, 1074.7, 885.6,-0.11916, 0.009934 +16:46:44, 1080.6, 885.5,-0.11678, 0.0076036 +16:51:50, 1079.1, 885.6,-0.11783, 0.011119 +16:56:56, 1078, 887.1,-0.11665, 0.002222 +17:02:01, 1076.9, 890.7,-0.11545,-0.0045117 +17:07:07, 1079.2, 888.5,-0.11464,-0.00083601 +17:12:13, 1082.5, 888.5,-0.12047, 0.0023168 +17:17:19, 1082.7, 887.6,-0.1125, 0.0030391 +17:22:25, 1080, 887.3,-0.11396, 0.0045574 +17:27:30, 1078.2, 885.6,-0.12064, 0.0084515 +17:32:36, 1077.3, 887.1,-0.11613, 0.0062257 +17:37:42, 1077.5, 887.9,-0.11352, 0.0050877 +17:42:47, 1078.6, 886.5,-0.11666, 0.0073078 +17:47:53, 1078.3, 888.1,-0.1172, 0.0044806 +17:52:59, 1078.8, 887,-0.11465, 0.0042768 +17:58:05, 1080, 887.5,-0.11797, 0.0057352 diff --git a/pxii_bec/macros/luts/beampos/beampos_18071800.csv b/pxii_bec/macros/luts/beampos/beampos_18071800.csv new file mode 100644 index 0000000..c1d67cb --- /dev/null +++ b/pxii_bec/macros/luts/beampos/beampos_18071800.csv @@ -0,0 +1,73 @@ +Beam size: 25 x 25, Energy: 7000 eV, Zoom: 1000.0 +Time,Scin_x,Scin_y,BPM_x,BPM_y +18:00:23, 1087.2, 898.9,-0.11289,-0.056702 +18:05:30, 1088, 898.7,-0.111,-0.051116 +18:10:37, 1087.9, 896,-0.11463,-0.044413 +18:15:43, 1090, 896,-0.11563,-0.048558 +18:20:52, 1089.9, 896.9,-0.11147,-0.044115 +18:25:58, 1085.8, 892.7,-0.10464,-0.0304 +18:31:05, 1086.2, 895.8,-0.12132,-0.050184 +18:36:14, 1089.8, 893.1,-0.10226,-0.02751 +18:41:21, 1087, 894.2,-0.13051,-0.030585 +18:46:28, 1088.4, 895.3,-0.10238,-0.033711 +18:51:35, 1083.4, 890,-0.13426,-0.022771 +18:56:44, 1085.7, 893,-0.11405,-0.025597 +19:01:50, 1083.2, 890.6,-0.10936,-0.021125 +19:06:57, 1083.4, 890.7,-0.13996,-0.018376 +19:12:03, 1080.4, 889.6,-0.14768,-0.015343 +19:17:11, 1083.1, 888,-0.13984,-0.010937 +19:22:17, 1085.1, 887.1,-0.13604,-0.0098507 +19:27:24, 1078.1, 886.3,-0.14872,-0.0083533 +19:32:29, 1081.7, 887.3,-0.14793,-0.0020641 +19:37:37, 1083.5, 886.1,-0.1435,-0.0031823 +19:42:44, 1081.8, 885.3,-0.14713, 0.00076525 +19:47:51, 1085.6, 886,-0.12325,-0.005586 +19:52:57, 1082.8, 884.8,-0.13169, 0.002535 +19:58:03, 1083.1, 886.6,-0.1433, 0.0036532 +20:03:10, 1081.4, 886.2,-0.14891, 0.0065452 +20:08:16, 1078, 886.3,-0.15479, 0.0044528 +20:13:22, 1080.5, 886.9,-0.15429, 0.00013618 +20:18:28, 1079, 884.5,-0.1563, 0.0046595 +20:23:35, 1081.3, 880.9,-0.12887, 0.023665 +20:28:45, 1074.5, 882.4,-0.14363, 0.01673 +20:33:52, 1081.6, 884.1,-0.14379, 0.011203 +20:38:59, 1078.5, 884.7,-0.16287, 0.0078645 +20:44:06, 1081.8, 883.3,-0.13597, 0.014495 +20:49:13, 1079.5, 879.7,-0.16022, 0.030429 +20:54:21, 1081.8, 883.6,-0.14835, 0.010793 +20:59:27, 1082.5, 882.8,-0.15187, 0.020659 +21:04:33, 1080.6, 880.2,-0.15458, 0.022691 +21:09:38, 1080.4, 881,-0.154, 0.022332 +21:14:44, 1080.6, 880.7,-0.13678, 0.021345 +21:19:51, 1080, 882.2,-0.16281, 0.022404 +21:25:01, 1081.1, 880.2,-0.15382, 0.029244 +21:30:07, 1081.6, 883.1,-0.15009, 0.021002 +21:35:12, 1079.6, 884.4,-0.13683, 0.013609 +21:40:19, 1079.3, 884.6,-0.16139, 0.013444 +21:45:27, 1082.5, 882.3,-0.13616, 0.028945 +21:50:33, 1080.2, 884.9,-0.14429, 0.014658 +21:55:40, 1079.5, 883.2,-0.15799, 0.023379 +22:00:46, 1077.2, 883.1,-0.15915, 0.020498 +22:05:52, 1077.9, 881,-0.16593, 0.021929 +22:10:59, 1080.8, 885.5,-0.13688, 0.012467 +22:16:06, 1079.8, 881.1,-0.16093, 0.034882 +22:21:15, 1081.7, 882.1,-0.13768, 0.026467 +22:26:24, 1078.9, 883.5,-0.15947, 0.025523 +22:31:30, 1078.6, 885.7,-0.16555, 0.017603 +22:36:37, 1077.1, 883.2,-0.17131, 0.023058 +22:41:43, 1078.5, 883.6,-0.16515, 0.030139 +22:46:51, 1079.4, 883.7,-0.16058, 0.026854 +22:51:58, 1077, 882.1,-0.16906, 0.030297 +22:57:06, 1081.5, 885.3,-0.15947, 0.016286 +23:02:13, 1075.3, 882.7,-0.17468, 0.021457 +23:07:20, 1078.5, 879.2,-0.15431, 0.036046 +23:12:26, 1081.2, 881.6,-0.1613, 0.0279 +23:17:32, 1079.9, 880.4,-0.16349, 0.030523 +23:22:39, 1074, 878.5,-0.17429, 0.047282 +23:27:46, 1079.2, 878.6,-0.14555, 0.041583 +23:32:54, 1078.3, 879.2,-0.16937, 0.037788 +23:38:01, 1078.4, 881,-0.15078, 0.029148 +23:43:07, 1077.3, 880.5,-0.16738, 0.030062 +23:48:13, 1074.1, 882.3,-0.16877, 0.021855 +23:53:20, 1078.4, 883.4,-0.16899, 0.017587 +23:58:28, 1080.1, 881.1,-0.16262, 0.025849 diff --git a/pxii_bec/macros/luts/beampos/beampos_19070000.csv b/pxii_bec/macros/luts/beampos/beampos_19070000.csv new file mode 100644 index 0000000..d2f25ff --- /dev/null +++ b/pxii_bec/macros/luts/beampos/beampos_19070000.csv @@ -0,0 +1,73 @@ +Beam size: 25 x 25, Energy: 9000 eV, Zoom: 1000.0 +Time,Scin_x,Scin_y,BPM_x,BPM_y +00:00:27, 1096.2, 878.9,-0.10422, 0.051015 +00:05:33, 1102.6, 878.8,-0.10089, 0.047783 +00:10:40, 1094, 881.1,-0.10438, 0.042959 +00:15:47, 1094.1, 878.8,-0.088006, 0.042954 +00:20:53, 1095.7, 877.4,-0.095532, 0.047889 +00:25:59, 1094, 874.9,-0.090727, 0.046443 +00:31:05, 1098, 878,-0.081301, 0.046345 +00:36:11, 1094.9, 877.2,-0.084523, 0.045295 +00:41:17, 1093.3, 877.6,-0.083545, 0.041377 +00:46:23, 1095.3, 876.7,-0.084554, 0.04756 +00:51:29, 1098.2, 877.2,-0.075455, 0.047755 +00:56:35, 1098.1, 880.7,-0.076532, 0.037133 +01:01:41, 1099, 878.5,-0.080367, 0.044453 +01:06:47, 1097.9, 880.6,-0.071593, 0.038292 +01:11:54, 1099.6, 879.6,-0.069253, 0.044711 +01:17:00, 1097.4, 881.9,-0.072625, 0.040504 +01:22:06, 1099.9, 880.7,-0.075477, 0.041547 +01:27:12, 1102.9, 878.4,-0.069703, 0.045874 +01:32:18, 1108.7, 880.2,-0.072999, 0.035963 +01:37:25, 1101.4, 880.8,-0.071325, 0.039413 +01:42:31, 1096.4, 879.2,-0.080792, 0.045308 +01:47:39, 1102.2, 880.6,-0.078503, 0.042056 +01:52:44, 1099.1, 883.1,-0.068643, 0.03505 +01:57:50, 1099.6, 881.2,-0.075927, 0.042831 +02:02:57, 1097.3, 881.7,-0.075821, 0.043285 +02:08:02, 1097.4, 879.1,-0.077765, 0.048317 +02:13:08, 1098, 878.6,-0.080888, 0.046227 +02:18:16, 1103, 882.1,-0.069456, 0.042083 +02:23:21, 1100.2, 882.2,-0.07461, 0.042027 +02:28:27, 1099.5, 879.6,-0.072908, 0.045414 +02:33:34, 1098.6, 881.3,-0.072111, 0.045849 +02:38:42, 1101, 883.2,-0.075653, 0.037313 +02:43:48, 1100.5, 882.6,-0.074713, 0.042508 +02:48:56, 1100.7, 882.2,-0.068493, 0.04146 +02:54:03, 1099.2, 880.7,-0.073816, 0.043851 +02:59:09, 1100.2, 880.2,-0.071329, 0.045464 +03:04:16, 1099.9, 880.3,-0.074841, 0.044893 +03:09:23, 1101.3, 880,-0.068119, 0.046967 +03:14:29, 1097.2, 884.4,-0.073234, 0.03653 +03:19:35, 1096.5, 882.6,-0.076674, 0.036552 +03:24:40, 1096, 878.9,-0.0746, 0.046635 +03:29:46, 1096.7, 880.2,-0.073988, 0.039682 +03:34:52, 1096.3, 877.9,-0.072519, 0.042302 +03:39:58, 1099, 878.2,-0.074265, 0.044691 +03:45:05, 1094.7, 879.3,-0.084827, 0.043503 +03:50:13, 1094.5, 876.9,-0.076947, 0.043621 +03:55:20, 1096.3, 877,-0.077052, 0.046556 +04:00:26, 1096.1, 875.4,-0.081599, 0.049468 +04:05:32, 1095.8, 879.7,-0.08487, 0.044777 +04:10:38, 1099.5, 877.9,-0.078693, 0.046543 +04:15:44, 1094.8, 874.8,-0.077996, 0.046238 +04:20:51, 1098.3, 875.9,-0.071925, 0.050462 +04:25:59, 1096.8, 875.8,-0.074895, 0.042541 +04:31:08, 1097.6, 876.7,-0.080193, 0.047458 +04:36:17, 1060.5, 874.7,-0.07387, 0.046123 +04:41:25, 1094.3, 877.1,-0.07925, 0.046501 +04:46:31, 1093.3, 877.2,-0.082028, 0.043891 +04:51:36, 1094.5, 874.9,-0.082283, 0.046545 +04:56:42, 1095.8, 878.3,-0.07603, 0.044235 +05:01:49, 1096.9, 879.6,-0.08036, 0.046302 +05:06:56, 1096.5, 878,-0.080912, 0.047365 +05:12:02, 1099.7, 877.8,-0.075186, 0.047222 +05:17:09, 1096.9, 879.2,-0.085779, 0.045361 +05:22:15, 1096.3, 876.7,-0.085266, 0.0484 +05:27:25, 1105.3, 879.2,-0.078254, 0.049087 +05:32:34, 1055.9, 875.9,-0.078914, 0.046331 +05:37:43, 1096.4, 878.3,-0.078052, 0.044381 +05:42:48, 1095.1, 877.8,-0.082107, 0.045591 +05:47:55, 1094.4, 877.6,-0.082593, 0.047571 +05:53:02, 1095.1, 877.7,-0.078357, 0.044259 +05:58:08, 1096.3, 878.5,-0.080765, 0.041253 diff --git a/pxii_bec/macros/luts/beampos/beampos_19070559.csv b/pxii_bec/macros/luts/beampos/beampos_19070559.csv new file mode 100644 index 0000000..79e742e --- /dev/null +++ b/pxii_bec/macros/luts/beampos/beampos_19070559.csv @@ -0,0 +1,73 @@ +Beam size: 25 x 25, Energy: 12670 eV, Zoom: 1000.0 +Time,Scin_x,Scin_y,BPM_x,BPM_y +06:00:03, 1089.8, 870.1,-0.075726, 0.057242 +06:05:12, 1090.6, 870.9,-0.054504, 0.056696 +06:10:18, 1090.4, 872.6,-0.056052, 0.050934 +06:15:24, 1090.8, 869.6,-0.056711, 0.056018 +06:20:29, 1093.2, 872.5,-0.048436, 0.052689 +06:25:35, 1092.2, 873.8,-0.046384, 0.048112 +06:30:42, 1090.7, 872.3,-0.064578, 0.047664 +06:35:50, 1095.3, 873.3,-0.039321, 0.049451 +06:40:57, 1094.3, 872.4,-0.061085, 0.051917 +06:46:03, 1096, 875.1,-0.053488, 0.045762 +06:51:11, 1094.1, 875,-0.038676, 0.047646 +06:56:17, 1093.7, 874.8,-0.035873, 0.045234 +07:01:23, 1095.8, 874.1,-0.032996, 0.047143 +07:06:29, 1094.1, 875.8,-0.060449, 0.038967 +07:11:35, 1093.5, 875.3,-0.064064, 0.041099 +07:16:41, 1097, 874.2,-0.034394, 0.045616 +07:21:48, 1097.3, 875.6,-0.045313, 0.042338 +07:26:54, 1098.6, 878.8,-0.025292, 0.039332 +07:32:01, 1096.2, 875.6,-0.051904, 0.044109 +07:37:07, 1096.8, 879.8,-0.040263, 0.036713 +07:42:13, 1097.7, 879.3,-0.047349, 0.03665 +07:47:18, 1098.4, 879.1,-0.032718, 0.03625 +07:52:24, 1096.7, 878.6,-0.059916, 0.036537 +07:57:34, 1096.2, 878,-0.057346, 0.036411 +08:02:43, 1076.4, 873.3,-0.05637, 0.037097 +08:07:52, 1097.4, 876.4,-0.03254, 0.043524 +08:13:00, 1094.7, 875.4,-0.059477, 0.044236 +08:18:06, 1096.5, 874.3,-0.054567, 0.042628 +08:23:12, 1094.3, 873.6,-0.060655, 0.047918 +08:28:17, 1094.9, 872.7,-0.045298, 0.046942 +08:33:25, 1095.2, 873,-0.052788, 0.046684 +08:38:32, 1094.7, 874,-0.040514, 0.046534 +08:43:38, 1093, 876.4,-0.040237, 0.042712 +08:48:44, 1094.2, 874.1,-0.035634, 0.048417 +08:53:50, 1091.6, 874.4,-0.04272, 0.048589 +08:58:55, 1093.5, 873.2,-0.039836, 0.048642 +09:04:02, 1093.9, 874.2,-0.041484, 0.046145 +09:09:07, 1094.3, 872.9,-0.038794, 0.049678 +09:14:13, 1093.6, 870.4,-0.039772, 0.054932 +09:19:20, 1094.6, 874.5,-0.06241, 0.043971 +09:24:26, 1094.6, 873.2,-0.06635, 0.045956 +09:29:34, 1092.5, 874.4,-0.046905, 0.045537 +09:34:40, 1092.5, 874,-0.045189, 0.046929 +09:39:47, 1093.9, 873.1,-0.064249, 0.049993 +09:44:53, 1090.7, 872.7,-0.064463, 0.049656 +09:49:59, 1090.2, 872.5,-0.042274, 0.050164 +09:55:07, 1094.9, 874.7,-0.062986, 0.047024 +10:00:13, 1094.5, 873.9,-0.047026, 0.050467 +10:05:19, 1090.1, 867.9,-0.072768, 0.055509 +10:10:25, 1089.2, 870.2,-0.051434, 0.047583 +10:15:33, 1087.2, 870.8,-0.07974, 0.047684 +10:20:39, 1088.5, 869.3,-0.077472, 0.050213 +10:25:46, 1088.5, 869.5,-0.052469, 0.047447 +10:30:53, 1085.6, 866.3,-0.079447, 0.053265 +10:35:59, 1084.5, 870.2,-0.062915, 0.048998 +10:41:05, 1087.2, 868.8,-0.072563, 0.052968 +10:46:11, 1088.3, 869.2,-0.073626, 0.050495 +10:51:18, 1086.3, 870.4,-0.061491, 0.051031 +10:56:24, 1085.6, 869.1,-0.058558, 0.051483 +11:01:32, 1087.7, 867.3,-0.075988, 0.053007 +11:06:38, 1085.5, 868.4,-0.076915, 0.053232 +11:11:43, 1084.4, 867,-0.063152, 0.054525 +11:16:49, 1084.9, 869.4,-0.057951, 0.049182 +11:21:57, 1084.6, 869.9,-0.082062, 0.049092 +11:27:03, 1086.5, 867.3,-0.057374, 0.057174 +11:32:09, 1084.8, 868,-0.065534, 0.056068 +11:37:15, 1086.3, 869.3,-0.063686, 0.05045 +11:42:22, 1086.8, 870.5,-0.075117, 0.050376 +11:47:28, 1084.7, 869.6,-0.065606, 0.051288 +11:52:35, 1083.2, 866.5,-0.084646, 0.053896 +11:57:43, 1084.1, 867.9,-0.06012, 0.05496 diff --git a/pxii_bec/macros/luts/beampos/beampos_19071158.csv b/pxii_bec/macros/luts/beampos/beampos_19071158.csv new file mode 100644 index 0000000..3065e45 --- /dev/null +++ b/pxii_bec/macros/luts/beampos/beampos_19071158.csv @@ -0,0 +1,73 @@ +Beam size: 25 x 25, Energy: 15000 eV, Zoom: 1000.0 +Time,Scin_x,Scin_y,BPM_x,BPM_y +11:59:00, 1088.4, 868.8,-0.076482, 0.065731 +12:04:06, 1088.6, 868.5,-0.075798, 0.065046 +12:09:11, 1086.2, 870.3,-0.083481, 0.060803 +12:14:17, 1088.2, 869.6,-0.070638, 0.062346 +12:19:23, 1088.7, 868.2,-0.069533, 0.065481 +12:24:29, 1090.7, 868.3,-0.06659, 0.065482 +12:29:35, 1092.7, 866.8,-0.061025, 0.06676 +12:34:41, 1090.2, 869.7,-0.069311, 0.063017 +12:39:47, 1092.2, 869.8,-0.056527, 0.062016 +12:44:52, 1112.3, 850.5, 0.04966, 0.10371 +12:49:58, 1111.8, 863.2, 0.051658, 0.077989 +12:55:04, 1109.4, 874, 0.027556, 0.055713 +13:00:09, 1109.5, 873.1, 0.032834, 0.058692 +13:05:15, 1113.5, 874.5, 0.036455, 0.054885 +13:10:21, 1111, 873.8, 0.031303, 0.056003 +13:15:27, 1109, 872.5, 0.038276, 0.058991 +13:20:33, 1109.9, 873.1, 0.031477, 0.05798 +13:25:39, 1111.4, 872.8, 0.031182, 0.057984 +13:30:44, 1111.1, 874.9, 0.033867, 0.055528 +13:35:50, 1112.4, 874.2, 0.034476, 0.05649 +13:40:56, 1114.4, 874.4, 0.041443, 0.057118 +13:46:02, 1112.6, 875.9, 0.034084, 0.055139 +13:51:08, 1111.4, 874.8, 0.032731, 0.053112 +13:56:14, 1113.4, 876.6, 0.035743, 0.05341 +14:01:19, 1115.8, 875.6, 0.039268, 0.056284 +14:06:25, 1113.9, 878, 0.036519, 0.051352 +14:11:31, 1111.9, 876.5, 0.036827, 0.053118 +14:16:37, 1114.5, 876, 0.041577, 0.054167 +14:21:43, 1116.7, 876.5, 0.044925, 0.053997 +14:26:48, 1115.2, 876.3, 0.036758, 0.053849 +14:31:54, 1114.4, 878.8, 0.037616, 0.050496 +14:37:00, 1115.5, 878.4, 0.043492, 0.051726 +14:42:05, 1116.4, 877, 0.046624, 0.054037 +14:47:11, 1113.7, 877.5, 0.039416, 0.050736 +14:52:17, 1116.1, 879.7, 0.044124, 0.049925 +14:57:22, 1117.3, 877.9, 0.053136, 0.052914 +15:02:28, 1113.6, 878, 0.044115, 0.052158 +15:07:34, 1113.9, 878.2, 0.040034, 0.047948 +15:12:40, 1111.9, 876.8, 0.034813, 0.051975 +15:17:46, 1117, 876, 0.050279, 0.054367 +15:22:52, 1115.9, 877.4, 0.045172, 0.053026 +15:27:58, 1112.4, 876.5, 0.039972, 0.053036 +15:33:03, 1114, 875.6, 0.046774, 0.052996 +15:38:09, 1114, 875.7, 0.042843, 0.054435 +15:43:15, 1115.9, 875.7, 0.044451, 0.054752 +15:48:20, 1115.5, 875.3, 0.044003, 0.052915 +15:53:26, 1111.7, 874.5, 0.036981, 0.055973 +15:58:32, 1112.2, 876.2, 0.03839, 0.0529 +16:03:37, 1114.5, 875, 0.041577, 0.054337 +16:08:43, 1115, 874.1, 0.038677, 0.056231 +16:13:49, 1115.8, 876.1, 0.044489, 0.055163 +16:18:54, 1113.5, 876.8, 0.035821, 0.054732 +16:24:00, 1116, 876.5, 0.042683, 0.056534 +16:29:06, 1115.7, 878, 0.040596, 0.054578 +16:34:12, 1113.8, 877.2, 0.035674, 0.054329 +16:39:18, 1116.2, 876.4, 0.043127, 0.057105 +16:44:24, 1113.8, 875.9, 0.041567, 0.059277 +16:49:29, 1113.8, 875.3, 0.037544, 0.05579 +16:54:35, 1113.3, 875.3, 0.042273, 0.05777 +16:59:41, 1112.7, 876.9, 0.029153, 0.053549 +17:04:47, 1112.3, 875.6, 0.029099, 0.060035 +17:09:52, 1115.1, 876, 0.043104, 0.057382 +17:14:58, 1113.5, 876.1, 0.033973, 0.056598 +17:20:04, 1112.1, 876.2, 0.040206, 0.055084 +17:25:10, 1112.8, 875.9, 0.035065, 0.056058 +17:30:15, 1112.9, 876.9, 0.028595, 0.057244 +17:35:21, 1115.9, 876.1, 0.038115, 0.056979 +17:40:27, 1111.7, 877, 0.028549, 0.056126 +17:45:32, 1109.7, 875.4, 0.033823, 0.054598 +17:50:38, 1112, 875.7, 0.035057, 0.056551 +17:55:44, 1110.9, 876.6, 0.026614, 0.056027 diff --git a/pxii_bec/macros/luts/beampos/beampos_19071756.csv b/pxii_bec/macros/luts/beampos/beampos_19071756.csv new file mode 100644 index 0000000..caa4b96 --- /dev/null +++ b/pxii_bec/macros/luts/beampos/beampos_19071756.csv @@ -0,0 +1,41 @@ +Beam size: 25 x 25, Energy: 12400 eV, Zoom: 1000.0 +Time,Scin_x,Scin_y,BPM_x,BPM_y +17:57:03, 1081.3, 875.8,-0.11122, 0.045013 +18:02:09, 1079.9, 873.8,-0.12293, 0.050853 +18:07:14, 1078.2, 874.4,-0.12417, 0.04782 +18:12:21, 1080, 872.9,-0.13328, 0.047685 +18:17:28, 1078.5, 873.4,-0.12336, 0.047952 +18:22:34, 1080.7, 875.3,-0.11877, 0.048252 +18:27:41, 1079.7, 875,-0.1316, 0.049279 +18:32:48, 1080.9, 874.7,-0.12823, 0.049914 +18:37:53, 1079.3, 873.8,-0.1343, 0.0506 +18:42:59, 1080.2, 875.2,-0.11865, 0.049372 +18:48:07, 1082.7, 873.6,-0.12981, 0.050035 +18:53:12, 1083.1, 876.8,-0.13422, 0.043321 +18:58:18, 1077.3, 876.4,-0.13903, 0.044899 +19:03:26, 1049.6, 976.6,-0.25672,-0.19651 +19:08:32, 1079.1, 876.7,-0.11786, 0.045326 +19:13:38, 1082.3, 875.9,-0.11708, 0.043901 +19:18:44, 1083.4, 878.8,-0.10999, 0.042962 +19:23:49, 1079.8, 878.1,-0.11641, 0.0409 +19:28:55, 1081.9, 877.9,-0.11094, 0.040306 +19:34:01, 1081.7, 877.5,-0.1086, 0.043686 +19:39:08, 1081.6, 878.2,-0.13015, 0.039693 +19:44:14, 1081.8, 880.1,-0.13167, 0.036952 +19:49:20, 1081.7, 898.1,-0.11858,-0.0037615 +19:54:26, 1080.5, 897.3,-0.13063,-0.0029066 +19:59:34, 1080.8, 898.1,-0.11391,-0.0041038 +20:04:42, 1082.3, 897.6,-0.13463,-0.0057737 +20:09:47, 1086, 898.2,-0.12315,-0.0030449 +20:14:53, 1086.3, 898.9,-0.1259,-0.0036708 +20:20:01, 1084.7, 901.5,-0.11375,-0.010266 +20:25:06, 1083.1, 900.8,-0.11676,-0.0083519 +20:30:12, 1084.8, 901.8,-0.11506,-0.0089971 +20:35:18, 1084.8, 898.6,-0.10809,-0.0043314 +20:40:23, 1083.8, 900.4,-0.11612,-0.0042361 +20:45:29, 1085.1, 900.5,-0.10516,-0.008494 +20:50:35, 1085.9, 901.4,-0.10048,-0.0093025 +20:55:42, 1087.5, 900.3,-0.12276,-0.0065716 +21:00:48, 1087.5, 902,-0.11076,-0.0088263 +21:05:54, 1088, 899.7,-0.099168,-0.0042224 +21:11:01, 1088.2, 900.1,-0.11814,-0.0081361 diff --git a/pxii_bec/macros/luts/beampos/beampos_19072236.csv b/pxii_bec/macros/luts/beampos/beampos_19072236.csv new file mode 100644 index 0000000..69e3515 --- /dev/null +++ b/pxii_bec/macros/luts/beampos/beampos_19072236.csv @@ -0,0 +1,14 @@ +Beam size: 25 x 25, Energy: 12400 eV, Zoom: 1000.0 +Time,Scin_x,Scin_y,BPM_x,BPM_y +22:36:25, 1060.4, 878.9,-0.10583,-0.0084627 +22:38:31, 1063.3, 881.9,-0.1066,-0.0073115 +22:40:37, 1063.9, 881.4,-0.10975,-0.0055692 +22:42:43, 1065, 883.9,-0.1324,-0.0099198 +22:44:49, 1066.7, 884.9,-0.13217,-0.0094756 +22:46:55, 1067.1, 885.5,-0.11527,-0.0077712 +22:49:03, 1069.5, 886.4,-0.12735,-0.0080743 +22:51:09, 1072.6, 886.3,-0.12191,-0.0092353 +22:53:15, 1072, 888.3,-0.11964,-0.0056324 +22:55:22, 1074.4, 889.6,-0.1025,-0.010078 +22:57:29, 1073.6, 889.6,-0.11851,-0.010061 +22:59:35, 1075.4, 889.1,-0.12013,-0.010561 diff --git a/pxii_bec/macros/luts/beampos/beampos_19072303.csv b/pxii_bec/macros/luts/beampos/beampos_19072303.csv new file mode 100644 index 0000000..21ca183 --- /dev/null +++ b/pxii_bec/macros/luts/beampos/beampos_19072303.csv @@ -0,0 +1,29 @@ +Beam size: 25 x 25, Energy: 6000 eV, Zoom: 1000.0 +Time,Scin_x,Scin_y,BPM_x,BPM_y +23:03:39, 1086.1, 878.6,-0.10838, 0.0059334 +23:05:44, 1088.5, 890.3,-0.11136,-0.01826 +23:07:50, 1090.2, 886.6,-0.11445,-0.0036606 +23:09:56, 1089.8, 888.5,-0.11115,-0.0081606 +23:12:02, 1088.9, 886.5,-0.10979,-9.9095e-05 +23:14:07, 1091.4, 886.4,-0.11265,-0.00089106 +23:16:13, 1091.9, 889.5,-0.11494,-0.0021195 +23:18:19, 1093, 887.9,-0.11659, 0.0020202 +23:20:25, 1093.7, 887.8,-0.11693,-0.00030628 +23:22:31, 1093.9, 891.1,-0.11816,-0.0057121 +23:24:37, 1091.7, 886.6,-0.12128, 0.0051707 +23:26:42, 1090.3, 887.7,-0.11649, 0.0031412 +23:28:48, 1090.4, 887,-0.11383, 0.0019807 +23:30:54, 1091, 888.7,-0.11061, 0.001034 +23:33:00, 1092.5, 890,-0.11252,-0.0065677 +23:35:06, 1093.6, 889.7,-0.11642,-0.0025576 +23:37:12, 1090.8, 891.6,-0.12155,-0.0063002 +23:39:18, 1091.4, 890.6,-0.12272,-0.0048353 +23:41:24, 1093.8, 890.1,-0.12113,-0.0013978 +23:43:30, 1094.6, 891.6,-0.11878,-0.0034721 +23:45:36, 1094.7, 888.1,-0.11605, 0.0064705 +23:47:42, 1096.6, 890.6,-0.11813,-0.0016227 +23:49:48, 1094.8, 890.5,-0.11452, 0.0015881 +23:51:54, 1094.8, 891.3,-0.1147,-0.0027561 +23:53:59, 1093.4, 891.4,-0.11232,-0.0017604 +23:56:05, 1095.8, 889.5,-0.11213, 0.0012026 +23:58:11, 1091.7, 890.9,-0.11552,-4.8605e-05 diff --git a/pxii_bec/macros/luts/beampos/beampos_20070000.csv b/pxii_bec/macros/luts/beampos/beampos_20070000.csv new file mode 100644 index 0000000..22aca30 --- /dev/null +++ b/pxii_bec/macros/luts/beampos/beampos_20070000.csv @@ -0,0 +1,31 @@ +Beam size: 25 x 25, Energy: 8000 eV, Zoom: 1000.0 +Time,Scin_x,Scin_y,BPM_x,BPM_y +00:00:30, 1088.3, 894.7,-0.10247,-0.022685 +00:02:35, 1091.7, 890.6,-0.091432,-0.0026408 +00:04:41, 1090.4, 893.2,-0.091495,-0.010632 +00:06:47, 1092.1, 893.1,-0.088456,-0.0092543 +00:08:53, 1093.2, 895.7,-0.08548,-0.013679 +00:10:59, 1095.5, 892,-0.08163,-0.0053854 +00:13:04, 1093, 895.9,-0.085617,-0.01478 +00:15:10, 1092.1, 893,-0.087674,-0.0047268 +00:17:16, 1092.7, 897.5,-0.090985,-0.016994 +00:19:22, 1091.5, 895.4,-0.088027,-0.013004 +00:21:28, 1092.7, 893.4,-0.084513,-0.0078035 +00:23:33, 1093.4, 895.6,-0.081424,-0.013122 +00:25:39, 1095, 895.1,-0.077877,-0.007636 +00:27:45, 1095.7, 895.4,-0.080481,-0.010022 +00:29:51, 1093.9, 895.8,-0.084139,-0.01127 +00:31:57, 1095.9, 895.8,-0.083969,-0.0097662 +00:34:03, 1095.8, 895.1,-0.083824,-0.0075766 +00:36:08, 1096.1, 895.4,-0.081804,-0.0069044 +00:38:14, 1096.8, 895.7,-0.079827,-0.0087801 +00:40:21, 1097.8, 895.1,-0.078845,-0.0060065 +00:42:26, 1094.9, 898.4,-0.083426,-0.014225 +00:44:32, 1096.5, 897.1,-0.085291,-0.012956 +00:46:38, 1095.4, 894.4,-0.086194,-0.0030342 +00:48:44, 1091.8, 894.4,-0.091819,-0.007776 +00:50:50, 1096.9, 895,-0.086827,-0.006593 +00:52:55, 1093.8, 896.5,-0.083934,-0.010891 +00:55:02, 1095.9, 892.6,-0.078386,-0.00066634 +00:57:08, 1094.8, 895.5,-0.080492,-0.0060498 +00:59:14, 1095.4, 893.8,-0.079348,-0.0010273 diff --git a/pxii_bec/macros/luts/beampos/beampos_20070100.csv b/pxii_bec/macros/luts/beampos/beampos_20070100.csv new file mode 100644 index 0000000..1a872f4 --- /dev/null +++ b/pxii_bec/macros/luts/beampos/beampos_20070100.csv @@ -0,0 +1,31 @@ +Beam size: 25 x 25, Energy: 10000 eV, Zoom: 1000.0 +Time,Scin_x,Scin_y,BPM_x,BPM_y +01:00:57, 1086.2, 886.6,-0.065065,-0.00013186 +01:03:03, 1084.7, 887.7,-0.074515,-0.0017025 +01:05:08, 1086, 889.3,-0.077061,-0.00024336 +01:07:14, 1084.6, 887.9,-0.08186, 0.0007312 +01:09:20, 1084.7, 887.2,-0.078934, 0.0048637 +01:11:25, 1083.8, 889.2,-0.083071,-0.0023657 +01:13:31, 1083.6, 889.9,-0.082672,-0.0024003 +01:15:37, 1084.6, 888.5,-0.082158,-0.0016185 +01:17:43, 1084.7, 888.3,-0.078614, 0.0024562 +01:19:49, 1084.5, 891.1,-0.076958,-0.0058177 +01:21:56, 1083.9, 889.6,-0.07548, 0.0016631 +01:24:02, 1084.4, 891.3,-0.078394,-0.0033353 +01:26:08, 1085, 887.4,-0.081657, 0.0040334 +01:28:14, 1084.2, 890,-0.080469,-0.00024043 +01:30:20, 1085.4, 889.7,-0.085927,-0.0057618 +01:32:27, 1086.8, 891.8,-0.083425,-0.0068752 +01:34:33, 1085.6, 890.1,-0.086878,-0.0048822 +01:36:39, 1084.6, 892.9,-0.083786,-0.0098233 +01:38:44, 1083.4, 889.8,-0.081551,-0.0053882 +01:40:50, 1085.7, 890.6,-0.075925,-0.0068812 +01:42:56, 1084.1, 890.1,-0.075559,-0.0051225 +01:45:02, 1085.4, 892.2,-0.076528,-0.010656 +01:47:08, 1083.2, 890.7,-0.077802,-0.0069342 +01:49:13, 1083.7, 892.8,-0.082591,-0.013723 +01:51:19, 1083.3, 890.7,-0.084526,-0.0091534 +01:53:25, 1081.9, 892.1,-0.089283,-0.012845 +01:55:32, 1083.8, 892.4,-0.087885,-0.0087082 +01:57:38, 1080.9, 893.3,-0.088293,-0.013436 +01:59:44, 1082.4, 891.9,-0.084131,-0.0047178 diff --git a/pxii_bec/macros/luts/beampos/beampos_20070200.csv b/pxii_bec/macros/luts/beampos/beampos_20070200.csv new file mode 100644 index 0000000..a7b2ffb --- /dev/null +++ b/pxii_bec/macros/luts/beampos/beampos_20070200.csv @@ -0,0 +1,30 @@ +Beam size: 25 x 25, Energy: 12000 eV, Zoom: 1000.0 +Time,Scin_x,Scin_y,BPM_x,BPM_y +02:01:24, 1089.8, 885.8,-0.076, 0.032848 +02:03:30, 1092.4, 889.2,-0.054165, 0.028047 +02:05:37, 1090.5, 884.4,-0.071597, 0.033274 +02:07:43, 1093.4, 887.4,-0.068904, 0.028838 +02:09:49, 1094.7, 885.9,-0.066548, 0.029639 +02:11:55, 1091.4, 885.9,-0.06624, 0.031237 +02:14:01, 1091.6, 885.3,-0.065731, 0.032068 +02:16:06, 1092.3, 885.7,-0.066224, 0.03011 +02:18:12, 1094.7, 886,-0.044613, 0.031121 +02:20:18, 1093.7, 886.2,-0.041754, 0.029849 +02:22:26, 1091.9, 886.8,-0.060506, 0.029507 +02:24:33, 1096.3, 888.9,-0.03123, 0.026509 +02:26:40, 1095.2, 888.2,-0.053696, 0.029404 +02:28:46, 1094.1, 888.1,-0.03567, 0.027089 +02:30:52, 1094.2, 888,-0.03523, 0.028663 +02:32:58, 1097.2, 887.2,-0.028733, 0.030174 +02:35:03, 1097.3, 887.9,-0.047942, 0.029229 +02:37:09, 1096, 887.4,-0.05307, 0.029778 +02:39:14, 1095.8, 886.7,-0.031823, 0.031276 +02:41:21, 1095.8, 887.2,-0.035524, 0.030281 +02:43:27, 1095, 889.2,-0.052045, 0.024124 +02:45:34, 1095.8, 885.9,-0.025722, 0.03354 +02:47:40, 1097.2, 889,-0.026883, 0.025967 +02:49:46, 1095.3, 886.4,-0.028725, 0.030098 +02:51:54, 1097.8, 886.4,-0.051672, 0.031952 +02:54:00, 1097.6, 889.5,-0.036, 0.026482 +02:56:05, 1095.1, 887.3,-0.033187, 0.028698 +02:58:13, 1095.2, 887.6,-0.049451, 0.024264 diff --git a/pxii_bec/macros/luts/beampos/beampos_20070258.csv b/pxii_bec/macros/luts/beampos/beampos_20070258.csv new file mode 100644 index 0000000..3b7fd19 --- /dev/null +++ b/pxii_bec/macros/luts/beampos/beampos_20070258.csv @@ -0,0 +1,31 @@ +Beam size: 25 x 25, Energy: 12400 eV, Zoom: 1000.0 +Time,Scin_x,Scin_y,BPM_x,BPM_y +02:59:19, 1088.8, 886.1,-0.066777, 0.023394 +03:01:24, 1088.8, 886.9,-0.067831, 0.023045 +03:03:32, 1086.6, 888.1,-0.093135, 0.01838 +03:05:37, 1087.2, 886.5,-0.086424, 0.022722 +03:07:43, 1086.9, 888.1,-0.066847, 0.01881 +03:09:50, 1087.6, 888.3,-0.083542, 0.020706 +03:11:58, 1088, 889.2,-0.066662, 0.018156 +03:14:03, 1086.7, 888.5,-0.067556, 0.016385 +03:16:09, 1088.7, 886.2,-0.067532, 0.023735 +03:18:15, 1087.9, 890.6,-0.069117, 0.018238 +03:20:21, 1088.5, 889.6,-0.086728, 0.016721 +03:22:28, 1087.7, 887.9,-0.063337, 0.021393 +03:24:35, 1091, 889.3,-0.061427, 0.021218 +03:26:42, 1090.3, 890.7,-0.081099, 0.016934 +03:28:47, 1089.3, 889.5,-0.06018, 0.019599 +03:30:54, 1090.4, 889.2,-0.078334, 0.017338 +03:33:02, 1089.4, 890.2,-0.063479, 0.019633 +03:35:08, 1088.8, 889.7,-0.064698, 0.019546 +03:37:14, 1086.7, 890.7,-0.06736, 0.016639 +03:39:20, 1088.3, 886.7,-0.063542, 0.023539 +03:41:26, 1088.8, 890.6,-0.06362, 0.01551 +03:43:33, 1091.6, 889.1,-0.078626, 0.02067 +03:45:39, 1090.6, 889.2,-0.081025, 0.018433 +03:47:46, 1090.8, 889,-0.064292, 0.018227 +03:49:54, 1088.1, 889.5,-0.086955, 0.015797 +03:51:59, 1089.2, 889.9,-0.067474, 0.015368 +03:54:05, 1090.6, 889.3,-0.063786, 0.015413 +03:56:11, 1090.3, 889.4,-0.060395, 0.015081 +03:58:17, 1092.3, 889.1,-0.058559, 0.015406 diff --git a/pxii_bec/macros/luts/beampos/beampos_20070359.csv b/pxii_bec/macros/luts/beampos/beampos_20070359.csv new file mode 100644 index 0000000..36e08bd --- /dev/null +++ b/pxii_bec/macros/luts/beampos/beampos_20070359.csv @@ -0,0 +1,31 @@ +Beam size: 25 x 25, Energy: 14000 eV, Zoom: 1000.0 +Time,Scin_x,Scin_y,BPM_x,BPM_y +03:59:44, 1085.5, 885.7,-0.098346, 0.028605 +04:01:51, 1084.7, 883.6,-0.10983, 0.028994 +04:03:59, 1084.1, 885.9,-0.099608, 0.028806 +04:06:06, 1084.4, 885.7,-0.11286, 0.026572 +04:08:12, 1084.9, 885.4,-0.11494, 0.028373 +04:10:17, 1084.4, 887.4,-0.10967, 0.026349 +04:12:23, 1087.1, 885.4,-0.10401, 0.028785 +04:14:29, 1086.8, 887.3,-0.10464, 0.024945 +04:16:34, 1086, 885.7,-0.10224, 0.030138 +04:18:40, 1085.9, 888.1,-0.10274, 0.023789 +04:20:49, 1085.7, 886.4,-0.088085, 0.030793 +04:22:54, 1087.2, 887.6,-0.090379, 0.024066 +04:25:01, 1083.9, 886.8,-0.10515, 0.031232 +04:27:08, 1083.1, 887.3,-0.099723, 0.02765 +04:29:14, 1083.1, 885.8,-0.10305, 0.026765 +04:31:20, 1084, 884.6,-0.1004, 0.02838 +04:33:27, 1084.7, 886.5,-0.11276, 0.025315 +04:35:33, 1086.1, 884.7,-0.10571, 0.029943 +04:37:39, 1086.2, 888.2,-0.10983, 0.021139 +04:39:47, 1087.4, 885.4,-0.096865, 0.031181 +04:41:53, 1086.2, 888.6,-0.099061, 0.025925 +04:43:58, 1084.5, 886.2,-0.0989, 0.029481 +04:46:06, 1082.1, 886.6,-0.1155, 0.026603 +04:48:12, 1084.4, 885.1,-0.11323, 0.028742 +04:50:18, 1083, 884.7,-0.10087, 0.031223 +04:52:24, 1082.3, 883.4,-0.097488, 0.032156 +04:54:30, 1085.1, 886.6,-0.10599, 0.026845 +04:56:36, 1085.5, 884.1,-0.092027, 0.031292 +04:58:43, 1086.1, 886.5,-0.10409, 0.026272 diff --git a/pxii_bec/macros/luts/beampos/beampos_20070459.csv b/pxii_bec/macros/luts/beampos/beampos_20070459.csv new file mode 100644 index 0000000..9111b53 --- /dev/null +++ b/pxii_bec/macros/luts/beampos/beampos_20070459.csv @@ -0,0 +1,31 @@ +Beam size: 25 x 25, Energy: 16000 eV, Zoom: 1000.0 +Time,Scin_x,Scin_y,BPM_x,BPM_y +05:00:07, 1085, 883.8,-0.076696, 0.025634 +05:02:13, 1086.9, 882.4,-0.074979, 0.025503 +05:04:19, 1086, 883.1,-0.081743, 0.024614 +05:06:25, 1085.9, 882.8,-0.075776, 0.026175 +05:08:31, 1083.8, 883.9,-0.082228, 0.026293 +05:10:38, 1084.2, 883.9,-0.091544, 0.024279 +05:12:44, 1080.9, 882.6,-0.082779, 0.025366 +05:14:51, 1083.2, 883.9,-0.092996, 0.022878 +05:16:59, 1082.3, 884.5,-0.082728, 0.024254 +05:19:05, 1085.8, 883.8,-0.078074, 0.025324 +05:21:11, 1083.4, 883,-0.08049, 0.025883 +05:23:17, 1083.2, 883.2,-0.082627, 0.025098 +05:25:23, 1083.2, 882,-0.083604, 0.027314 +05:27:30, 1083.6, 885,-0.096756, 0.020698 +05:29:36, 1084.8, 883.2,-0.076157, 0.027332 +05:31:42, 1084.2, 884.5,-0.077174, 0.022879 +05:33:48, 1086, 883.2,-0.077332, 0.027437 +05:35:54, 1083.3, 885.4,-0.095597, 0.019258 +05:38:00, 1083.3, 884,-0.094601, 0.025104 +05:40:06, 1084.8, 885.3,-0.09063, 0.020397 +05:42:12, 1085.4, 883.9,-0.082295, 0.025197 +05:44:17, 1084.7, 884.8,-0.08566, 0.022262 +05:46:25, 1084.3, 883.8,-0.084293, 0.026268 +05:48:33, 1082, 883.5,-0.098464, 0.025377 +05:50:39, 1081.4, 884,-0.10101, 0.022308 +05:52:45, 1082.2, 884.8,-0.099798, 0.022877 +05:54:51, 1082.4, 883.3,-0.08863, 0.026499 +05:56:58, 1084.4, 885.2,-0.091666, 0.023724 +05:59:03, 1083.6, 884,-0.091715, 0.022943 diff --git a/pxii_bec/macros/luts/beampos/beampos_20070559.csv b/pxii_bec/macros/luts/beampos/beampos_20070559.csv new file mode 100644 index 0000000..5d7b3e9 --- /dev/null +++ b/pxii_bec/macros/luts/beampos/beampos_20070559.csv @@ -0,0 +1,31 @@ +Beam size: 25 x 25, Energy: 18000 eV, Zoom: 1000.0 +Time,Scin_x,Scin_y,BPM_x,BPM_y +06:00:07, 1082, 883.4,-0.11192, 0.037721 +06:02:12, 1083, 885,-0.11957, 0.038156 +06:04:18, 1084.8, 886,-0.11856, 0.036642 +06:06:26, 1084.5, 885.7,-0.10789, 0.037436 +06:08:33, 1084.9, 884.5,-0.11389, 0.037365 +06:10:39, 1085.3, 885.9,-0.1102, 0.035751 +06:12:47, 1087.5, 883.5,-0.089998, 0.040013 +06:14:53, 1085.4, 884.6,-0.093043, 0.038193 +06:16:59, 1084.4, 883.8,-0.098512, 0.039186 +06:19:05, 1084.4, 885,-0.098786, 0.037087 +06:21:11, 1083.1, 885,-0.10092, 0.038601 +06:23:16, 1085.7, 883.8,-0.097485, 0.038191 +06:25:22, 1085.6, 884.7,-0.090524, 0.039356 +06:27:28, 1086.8, 884.1,-0.09521, 0.041347 +06:29:34, 1086.8, 885.6,-0.101, 0.040327 +06:31:42, 1086, 884.6,-0.094068, 0.04094 +06:33:49, 1084.9, 887,-0.10728, 0.037482 +06:35:55, 1084.7, 885.9,-0.10485, 0.041545 +06:38:02, 1084.7, 886.1,-0.098321, 0.036696 +06:40:08, 1085.7, 882.4,-0.089756, 0.040941 +06:42:14, 1084.9, 884.1,-0.099562, 0.036133 +06:44:20, 1086.9, 882.9,-0.091885, 0.040227 +06:46:28, 1085.8, 883.8,-0.08283, 0.035471 +06:48:36, 1087.2, 884.2,-0.089415, 0.039128 +06:50:43, 1087.9, 884.6,-0.08288, 0.037156 +06:52:51, 1086.9, 884.7,-0.096839, 0.040378 +06:54:58, 1087.4, 885,-0.091789, 0.036039 +06:57:05, 1086.7, 885.2,-0.10133, 0.039144 +06:59:11, 1088.2, 885.9,-0.10203, 0.038694 diff --git a/pxii_bec/macros/luts/beampos/beampos_20260718-19_10-7-9-12p67-15-12p4.csv b/pxii_bec/macros/luts/beampos/beampos_20260718-19_10-7-9-12p67-15-12p4.csv new file mode 100644 index 0000000..c700ac3 --- /dev/null +++ b/pxii_bec/macros/luts/beampos/beampos_20260718-19_10-7-9-12p67-15-12p4.csv @@ -0,0 +1,365 @@ +Beam size: 25 x 25, Energy: 10000 eV, Zoom: 1000.0 +Time,Scin_x,Scin_y,BPM_x,BPM_y +11:35:45, 1062.5, 868.9,-0.11896, 0.01887 +11:40:52, 1063, 871.8,-0.12142, 0.014688 +11:45:58, 1066.9, 874.7,-0.12046, 0.0086598 +11:51:04, 1068, 876.4,-0.1167, 0.017193 +11:56:10, 1068.1, 874.4,-0.12148, 0.018058 +12:01:16, 1068.2, 878.5,-0.11942, 0.008117 +12:06:22, 1068.7, 878,-0.12182, 0.0070722 +12:11:28, 1070.3, 876.5,-0.12096, 0.013999 +12:16:34, 1070.5, 874.9,-0.11751, 0.020493 +12:21:40, 1075.6, 877.7,-0.11723, 0.018245 +12:26:46, 1071.5, 881.7,-0.12407, 0.0088893 +12:31:51, 1071, 879.9,-0.1276, 0.01151 +12:36:58, 1070.4, 882.6,-0.12483, 0.0062113 +12:42:04, 1072.2, 880.9,-0.11932, 0.0076498 +12:47:09, 1073.2, 882.1,-0.11921, 0.0075093 +12:52:15, 1071.3, 881.3,-0.12551, 0.015369 +12:57:21, 1073.9, 880.4,-0.11533, 0.011686 +13:02:27, 1074.1, 879.6,-0.12139, 0.012885 +13:07:33, 1073.4, 881.4,-0.12404, 0.009902 +13:12:39, 1076.1, 881.6,-0.12028, 0.011644 +13:17:45, 1077.2, 883.2,-0.11862, 0.0070691 +13:22:51, 1075, 879.1,-0.1205, 0.016371 +13:27:57, 1077, 879.8,-0.11828, 0.013926 +13:33:03, 1077.7, 882.4,-0.11576, 0.008192 +13:38:09, 1076, 880.3,-0.12159, 0.014465 +13:43:15, 1077.1, 881.2,-0.12135, 0.013428 +13:48:21, 1077.2, 882.7,-0.11629, 0.0082309 +13:53:27, 1078.9, 883.6,-0.12406, 0.0064463 +13:58:33, 1076.2, 882.8,-0.11756, 0.0078457 +14:03:38, 1076.6, 881.5,-0.11809, 0.012274 +14:08:44, 1077.1, 883.7,-0.12376, 0.0075757 +14:13:50, 1075, 883.6,-0.11847, 0.0069435 +14:18:56, 1075.7, 881.3,-0.1204, 0.011577 +14:24:01, 1076.4, 881,-0.12215, 0.012281 +14:29:07, 1075.7, 881.6,-0.12133, 0.0040628 +14:34:13, 1075.9, 882.5,-0.11678, 0.0065513 +14:39:19, 1077.6, 880.5,-0.11551, 0.011332 +14:44:24, 1075.9, 881.1,-0.12023, 0.013476 +14:49:31, 1076.8, 881.9,-0.11705, 0.011102 +14:54:37, 1076.8, 881.6,-0.11483, 0.016159 +14:59:42, 1077.6, 880.7,-0.1214, 0.013621 +15:04:48, 1077.1, 884.1,-0.11704, 0.0070347 +15:09:54, 1076.7, 882.3,-0.11226, 0.011983 +15:15:00, 1076.1, 884.4,-0.11965, 0.0086288 +15:20:05, 1077, 883.2,-0.1144, 0.0095036 +15:25:11, 1077, 884,-0.11607, 0.0082163 +15:30:17, 1076.5, 883.6,-0.12069, 0.0088895 +15:35:23, 1075.8, 883.5,-0.11596, 0.011014 +15:40:29, 1079, 885.1,-0.11446, 0.011612 +15:45:35, 1078.8, 886.3,-0.11167, 0.0078587 +15:50:40, 1079.9, 884.1,-0.11666, 0.01034 +15:55:46, 1080.4, 883.7,-0.11024, 0.010066 +16:00:52, 1079.9, 883.7,-0.10819, 0.012905 +16:05:58, 1080.4, 888,-0.11271, 0.0021722 +16:11:03, 1079.3, 886.7,-0.11757, 0.0040589 +16:16:09, 1080.2, 888.7,-0.11446,-0.00084994 +16:21:15, 1082.1, 885.8,-0.10947, 0.0059782 +16:26:21, 1079, 887.4,-0.11827, 0.0029425 +16:31:27, 1078.7, 884.6,-0.11141, 0.011771 +16:36:33, 1077.1, 884.2,-0.11274, 0.01089 +16:41:38, 1074.7, 885.6,-0.11916, 0.009934 +16:46:44, 1080.6, 885.5,-0.11678, 0.0076036 +16:51:50, 1079.1, 885.6,-0.11783, 0.011119 +16:56:56, 1078, 887.1,-0.11665, 0.002222 +17:02:01, 1076.9, 890.7,-0.11545,-0.0045117 +17:07:07, 1079.2, 888.5,-0.11464,-0.00083601 +17:12:13, 1082.5, 888.5,-0.12047, 0.0023168 +17:17:19, 1082.7, 887.6,-0.1125, 0.0030391 +17:22:25, 1080, 887.3,-0.11396, 0.0045574 +17:27:30, 1078.2, 885.6,-0.12064, 0.0084515 +17:32:36, 1077.3, 887.1,-0.11613, 0.0062257 +17:37:42, 1077.5, 887.9,-0.11352, 0.0050877 +17:42:47, 1078.6, 886.5,-0.11666, 0.0073078 +17:47:53, 1078.3, 888.1,-0.1172, 0.0044806 +17:52:59, 1078.8, 887,-0.11465, 0.0042768 +17:58:05, 1080, 887.5,-0.11797, 0.0057352 +18:00:23, 1087.2, 898.9,-0.11289,-0.056702 +18:05:30, 1088, 898.7,-0.111,-0.051116 +18:10:37, 1087.9, 896,-0.11463,-0.044413 +18:15:43, 1090, 896,-0.11563,-0.048558 +18:20:52, 1089.9, 896.9,-0.11147,-0.044115 +18:25:58, 1085.8, 892.7,-0.10464,-0.0304 +18:31:05, 1086.2, 895.8,-0.12132,-0.050184 +18:36:14, 1089.8, 893.1,-0.10226,-0.02751 +18:41:21, 1087, 894.2,-0.13051,-0.030585 +18:46:28, 1088.4, 895.3,-0.10238,-0.033711 +18:51:35, 1083.4, 890,-0.13426,-0.022771 +18:56:44, 1085.7, 893,-0.11405,-0.025597 +19:01:50, 1083.2, 890.6,-0.10936,-0.021125 +19:06:57, 1083.4, 890.7,-0.13996,-0.018376 +19:12:03, 1080.4, 889.6,-0.14768,-0.015343 +19:17:11, 1083.1, 888,-0.13984,-0.010937 +19:22:17, 1085.1, 887.1,-0.13604,-0.0098507 +19:27:24, 1078.1, 886.3,-0.14872,-0.0083533 +19:32:29, 1081.7, 887.3,-0.14793,-0.0020641 +19:37:37, 1083.5, 886.1,-0.1435,-0.0031823 +19:42:44, 1081.8, 885.3,-0.14713, 0.00076525 +19:47:51, 1085.6, 886,-0.12325,-0.005586 +19:52:57, 1082.8, 884.8,-0.13169, 0.002535 +19:58:03, 1083.1, 886.6,-0.1433, 0.0036532 +20:03:10, 1081.4, 886.2,-0.14891, 0.0065452 +20:08:16, 1078, 886.3,-0.15479, 0.0044528 +20:13:22, 1080.5, 886.9,-0.15429, 0.00013618 +20:18:28, 1079, 884.5,-0.1563, 0.0046595 +20:23:35, 1081.3, 880.9,-0.12887, 0.023665 +20:28:45, 1074.5, 882.4,-0.14363, 0.01673 +20:33:52, 1081.6, 884.1,-0.14379, 0.011203 +20:38:59, 1078.5, 884.7,-0.16287, 0.0078645 +20:44:06, 1081.8, 883.3,-0.13597, 0.014495 +20:49:13, 1079.5, 879.7,-0.16022, 0.030429 +20:54:21, 1081.8, 883.6,-0.14835, 0.010793 +20:59:27, 1082.5, 882.8,-0.15187, 0.020659 +21:04:33, 1080.6, 880.2,-0.15458, 0.022691 +21:09:38, 1080.4, 881,-0.154, 0.022332 +21:14:44, 1080.6, 880.7,-0.13678, 0.021345 +21:19:51, 1080, 882.2,-0.16281, 0.022404 +21:25:01, 1081.1, 880.2,-0.15382, 0.029244 +21:30:07, 1081.6, 883.1,-0.15009, 0.021002 +21:35:12, 1079.6, 884.4,-0.13683, 0.013609 +21:40:19, 1079.3, 884.6,-0.16139, 0.013444 +21:45:27, 1082.5, 882.3,-0.13616, 0.028945 +21:50:33, 1080.2, 884.9,-0.14429, 0.014658 +21:55:40, 1079.5, 883.2,-0.15799, 0.023379 +22:00:46, 1077.2, 883.1,-0.15915, 0.020498 +22:05:52, 1077.9, 881,-0.16593, 0.021929 +22:10:59, 1080.8, 885.5,-0.13688, 0.012467 +22:16:06, 1079.8, 881.1,-0.16093, 0.034882 +22:21:15, 1081.7, 882.1,-0.13768, 0.026467 +22:26:24, 1078.9, 883.5,-0.15947, 0.025523 +22:31:30, 1078.6, 885.7,-0.16555, 0.017603 +22:36:37, 1077.1, 883.2,-0.17131, 0.023058 +22:41:43, 1078.5, 883.6,-0.16515, 0.030139 +22:46:51, 1079.4, 883.7,-0.16058, 0.026854 +22:51:58, 1077, 882.1,-0.16906, 0.030297 +22:57:06, 1081.5, 885.3,-0.15947, 0.016286 +23:02:13, 1075.3, 882.7,-0.17468, 0.021457 +23:07:20, 1078.5, 879.2,-0.15431, 0.036046 +23:12:26, 1081.2, 881.6,-0.1613, 0.0279 +23:17:32, 1079.9, 880.4,-0.16349, 0.030523 +23:22:39, 1074, 878.5,-0.17429, 0.047282 +23:27:46, 1079.2, 878.6,-0.14555, 0.041583 +23:32:54, 1078.3, 879.2,-0.16937, 0.037788 +23:38:01, 1078.4, 881,-0.15078, 0.029148 +23:43:07, 1077.3, 880.5,-0.16738, 0.030062 +23:48:13, 1074.1, 882.3,-0.16877, 0.021855 +23:53:20, 1078.4, 883.4,-0.16899, 0.017587 +23:58:28, 1080.1, 881.1,-0.16262, 0.025849 +00:00:27, 1096.2, 878.9,-0.10422, 0.051015 +00:05:33, 1102.6, 878.8,-0.10089, 0.047783 +00:10:40, 1094, 881.1,-0.10438, 0.042959 +00:15:47, 1094.1, 878.8,-0.088006, 0.042954 +00:20:53, 1095.7, 877.4,-0.095532, 0.047889 +00:25:59, 1094, 874.9,-0.090727, 0.046443 +00:31:05, 1098, 878,-0.081301, 0.046345 +00:36:11, 1094.9, 877.2,-0.084523, 0.045295 +00:41:17, 1093.3, 877.6,-0.083545, 0.041377 +00:46:23, 1095.3, 876.7,-0.084554, 0.04756 +00:51:29, 1098.2, 877.2,-0.075455, 0.047755 +00:56:35, 1098.1, 880.7,-0.076532, 0.037133 +01:01:41, 1099, 878.5,-0.080367, 0.044453 +01:06:47, 1097.9, 880.6,-0.071593, 0.038292 +01:11:54, 1099.6, 879.6,-0.069253, 0.044711 +01:17:00, 1097.4, 881.9,-0.072625, 0.040504 +01:22:06, 1099.9, 880.7,-0.075477, 0.041547 +01:27:12, 1102.9, 878.4,-0.069703, 0.045874 +01:32:18, 1108.7, 880.2,-0.072999, 0.035963 +01:37:25, 1101.4, 880.8,-0.071325, 0.039413 +01:42:31, 1096.4, 879.2,-0.080792, 0.045308 +01:47:39, 1102.2, 880.6,-0.078503, 0.042056 +01:52:44, 1099.1, 883.1,-0.068643, 0.03505 +01:57:50, 1099.6, 881.2,-0.075927, 0.042831 +02:02:57, 1097.3, 881.7,-0.075821, 0.043285 +02:08:02, 1097.4, 879.1,-0.077765, 0.048317 +02:13:08, 1098, 878.6,-0.080888, 0.046227 +02:18:16, 1103, 882.1,-0.069456, 0.042083 +02:23:21, 1100.2, 882.2,-0.07461, 0.042027 +02:28:27, 1099.5, 879.6,-0.072908, 0.045414 +02:33:34, 1098.6, 881.3,-0.072111, 0.045849 +02:38:42, 1101, 883.2,-0.075653, 0.037313 +02:43:48, 1100.5, 882.6,-0.074713, 0.042508 +02:48:56, 1100.7, 882.2,-0.068493, 0.04146 +02:54:03, 1099.2, 880.7,-0.073816, 0.043851 +02:59:09, 1100.2, 880.2,-0.071329, 0.045464 +03:04:16, 1099.9, 880.3,-0.074841, 0.044893 +03:09:23, 1101.3, 880,-0.068119, 0.046967 +03:14:29, 1097.2, 884.4,-0.073234, 0.03653 +03:19:35, 1096.5, 882.6,-0.076674, 0.036552 +03:24:40, 1096, 878.9,-0.0746, 0.046635 +03:29:46, 1096.7, 880.2,-0.073988, 0.039682 +03:34:52, 1096.3, 877.9,-0.072519, 0.042302 +03:39:58, 1099, 878.2,-0.074265, 0.044691 +03:45:05, 1094.7, 879.3,-0.084827, 0.043503 +03:50:13, 1094.5, 876.9,-0.076947, 0.043621 +03:55:20, 1096.3, 877,-0.077052, 0.046556 +04:00:26, 1096.1, 875.4,-0.081599, 0.049468 +04:05:32, 1095.8, 879.7,-0.08487, 0.044777 +04:10:38, 1099.5, 877.9,-0.078693, 0.046543 +04:15:44, 1094.8, 874.8,-0.077996, 0.046238 +04:20:51, 1098.3, 875.9,-0.071925, 0.050462 +04:25:59, 1096.8, 875.8,-0.074895, 0.042541 +04:31:08, 1097.6, 876.7,-0.080193, 0.047458 +04:36:17, 1060.5, 874.7,-0.07387, 0.046123 +04:41:25, 1094.3, 877.1,-0.07925, 0.046501 +04:46:31, 1093.3, 877.2,-0.082028, 0.043891 +04:51:36, 1094.5, 874.9,-0.082283, 0.046545 +04:56:42, 1095.8, 878.3,-0.07603, 0.044235 +05:01:49, 1096.9, 879.6,-0.08036, 0.046302 +05:06:56, 1096.5, 878,-0.080912, 0.047365 +05:12:02, 1099.7, 877.8,-0.075186, 0.047222 +05:17:09, 1096.9, 879.2,-0.085779, 0.045361 +05:22:15, 1096.3, 876.7,-0.085266, 0.0484 +05:27:25, 1105.3, 879.2,-0.078254, 0.049087 +05:32:34, 1055.9, 875.9,-0.078914, 0.046331 +05:37:43, 1096.4, 878.3,-0.078052, 0.044381 +05:42:48, 1095.1, 877.8,-0.082107, 0.045591 +05:47:55, 1094.4, 877.6,-0.082593, 0.047571 +05:53:02, 1095.1, 877.7,-0.078357, 0.044259 +05:58:08, 1096.3, 878.5,-0.080765, 0.041253 +06:00:03, 1089.8, 870.1,-0.075726, 0.057242 +06:05:12, 1090.6, 870.9,-0.054504, 0.056696 +06:10:18, 1090.4, 872.6,-0.056052, 0.050934 +06:15:24, 1090.8, 869.6,-0.056711, 0.056018 +06:20:29, 1093.2, 872.5,-0.048436, 0.052689 +06:25:35, 1092.2, 873.8,-0.046384, 0.048112 +06:30:42, 1090.7, 872.3,-0.064578, 0.047664 +06:35:50, 1095.3, 873.3,-0.039321, 0.049451 +06:40:57, 1094.3, 872.4,-0.061085, 0.051917 +06:46:03, 1096, 875.1,-0.053488, 0.045762 +06:51:11, 1094.1, 875,-0.038676, 0.047646 +06:56:17, 1093.7, 874.8,-0.035873, 0.045234 +07:01:23, 1095.8, 874.1,-0.032996, 0.047143 +07:06:29, 1094.1, 875.8,-0.060449, 0.038967 +07:11:35, 1093.5, 875.3,-0.064064, 0.041099 +07:16:41, 1097, 874.2,-0.034394, 0.045616 +07:21:48, 1097.3, 875.6,-0.045313, 0.042338 +07:26:54, 1098.6, 878.8,-0.025292, 0.039332 +07:32:01, 1096.2, 875.6,-0.051904, 0.044109 +07:37:07, 1096.8, 879.8,-0.040263, 0.036713 +07:42:13, 1097.7, 879.3,-0.047349, 0.03665 +07:47:18, 1098.4, 879.1,-0.032718, 0.03625 +07:52:24, 1096.7, 878.6,-0.059916, 0.036537 +07:57:34, 1096.2, 878,-0.057346, 0.036411 +08:02:43, 1076.4, 873.3,-0.05637, 0.037097 +08:07:52, 1097.4, 876.4,-0.03254, 0.043524 +08:13:00, 1094.7, 875.4,-0.059477, 0.044236 +08:18:06, 1096.5, 874.3,-0.054567, 0.042628 +08:23:12, 1094.3, 873.6,-0.060655, 0.047918 +08:28:17, 1094.9, 872.7,-0.045298, 0.046942 +08:33:25, 1095.2, 873,-0.052788, 0.046684 +08:38:32, 1094.7, 874,-0.040514, 0.046534 +08:43:38, 1093, 876.4,-0.040237, 0.042712 +08:48:44, 1094.2, 874.1,-0.035634, 0.048417 +08:53:50, 1091.6, 874.4,-0.04272, 0.048589 +08:58:55, 1093.5, 873.2,-0.039836, 0.048642 +09:04:02, 1093.9, 874.2,-0.041484, 0.046145 +09:09:07, 1094.3, 872.9,-0.038794, 0.049678 +09:14:13, 1093.6, 870.4,-0.039772, 0.054932 +09:19:20, 1094.6, 874.5,-0.06241, 0.043971 +09:24:26, 1094.6, 873.2,-0.06635, 0.045956 +09:29:34, 1092.5, 874.4,-0.046905, 0.045537 +09:34:40, 1092.5, 874,-0.045189, 0.046929 +09:39:47, 1093.9, 873.1,-0.064249, 0.049993 +09:44:53, 1090.7, 872.7,-0.064463, 0.049656 +09:49:59, 1090.2, 872.5,-0.042274, 0.050164 +09:55:07, 1094.9, 874.7,-0.062986, 0.047024 +10:00:13, 1094.5, 873.9,-0.047026, 0.050467 +10:05:19, 1090.1, 867.9,-0.072768, 0.055509 +10:10:25, 1089.2, 870.2,-0.051434, 0.047583 +10:15:33, 1087.2, 870.8,-0.07974, 0.047684 +10:20:39, 1088.5, 869.3,-0.077472, 0.050213 +10:25:46, 1088.5, 869.5,-0.052469, 0.047447 +10:30:53, 1085.6, 866.3,-0.079447, 0.053265 +10:35:59, 1084.5, 870.2,-0.062915, 0.048998 +10:41:05, 1087.2, 868.8,-0.072563, 0.052968 +10:46:11, 1088.3, 869.2,-0.073626, 0.050495 +10:51:18, 1086.3, 870.4,-0.061491, 0.051031 +10:56:24, 1085.6, 869.1,-0.058558, 0.051483 +11:01:32, 1087.7, 867.3,-0.075988, 0.053007 +11:06:38, 1085.5, 868.4,-0.076915, 0.053232 +11:11:43, 1084.4, 867,-0.063152, 0.054525 +11:16:49, 1084.9, 869.4,-0.057951, 0.049182 +11:21:57, 1084.6, 869.9,-0.082062, 0.049092 +11:27:03, 1086.5, 867.3,-0.057374, 0.057174 +11:32:09, 1084.8, 868,-0.065534, 0.056068 +11:37:15, 1086.3, 869.3,-0.063686, 0.05045 +11:42:22, 1086.8, 870.5,-0.075117, 0.050376 +11:47:28, 1084.7, 869.6,-0.065606, 0.051288 +11:52:35, 1083.2, 866.5,-0.084646, 0.053896 +11:57:43, 1084.1, 867.9,-0.06012, 0.05496 +11:59:00, 1088.4, 868.8,-0.076482, 0.065731 +12:04:06, 1088.6, 868.5,-0.075798, 0.065046 +12:09:11, 1086.2, 870.3,-0.083481, 0.060803 +12:14:17, 1088.2, 869.6,-0.070638, 0.062346 +12:19:23, 1088.7, 868.2,-0.069533, 0.065481 +12:24:29, 1090.7, 868.3,-0.06659, 0.065482 +12:29:35, 1092.7, 866.8,-0.061025, 0.06676 +12:34:41, 1090.2, 869.7,-0.069311, 0.063017 +12:39:47, 1092.2, 869.8,-0.056527, 0.062016 +12:44:52, 1112.3, 850.5, 0.04966, 0.10371 +12:49:58, 1111.8, 863.2, 0.051658, 0.077989 +12:55:04, 1109.4, 874, 0.027556, 0.055713 +13:00:09, 1109.5, 873.1, 0.032834, 0.058692 +13:05:15, 1113.5, 874.5, 0.036455, 0.054885 +13:10:21, 1111, 873.8, 0.031303, 0.056003 +13:15:27, 1109, 872.5, 0.038276, 0.058991 +13:20:33, 1109.9, 873.1, 0.031477, 0.05798 +13:25:39, 1111.4, 872.8, 0.031182, 0.057984 +13:30:44, 1111.1, 874.9, 0.033867, 0.055528 +13:35:50, 1112.4, 874.2, 0.034476, 0.05649 +13:40:56, 1114.4, 874.4, 0.041443, 0.057118 +13:46:02, 1112.6, 875.9, 0.034084, 0.055139 +13:51:08, 1111.4, 874.8, 0.032731, 0.053112 +13:56:14, 1113.4, 876.6, 0.035743, 0.05341 +14:01:19, 1115.8, 875.6, 0.039268, 0.056284 +14:06:25, 1113.9, 878, 0.036519, 0.051352 +14:11:31, 1111.9, 876.5, 0.036827, 0.053118 +14:16:37, 1114.5, 876, 0.041577, 0.054167 +14:21:43, 1116.7, 876.5, 0.044925, 0.053997 +14:26:48, 1115.2, 876.3, 0.036758, 0.053849 +14:31:54, 1114.4, 878.8, 0.037616, 0.050496 +14:37:00, 1115.5, 878.4, 0.043492, 0.051726 +14:42:05, 1116.4, 877, 0.046624, 0.054037 +14:47:11, 1113.7, 877.5, 0.039416, 0.050736 +14:52:17, 1116.1, 879.7, 0.044124, 0.049925 +14:57:22, 1117.3, 877.9, 0.053136, 0.052914 +15:02:28, 1113.6, 878, 0.044115, 0.052158 +15:07:34, 1113.9, 878.2, 0.040034, 0.047948 +15:12:40, 1111.9, 876.8, 0.034813, 0.051975 +15:17:46, 1117, 876, 0.050279, 0.054367 +15:22:52, 1115.9, 877.4, 0.045172, 0.053026 +15:27:58, 1112.4, 876.5, 0.039972, 0.053036 +15:33:03, 1114, 875.6, 0.046774, 0.052996 +15:38:09, 1114, 875.7, 0.042843, 0.054435 +15:43:15, 1115.9, 875.7, 0.044451, 0.054752 +15:48:20, 1115.5, 875.3, 0.044003, 0.052915 +15:53:26, 1111.7, 874.5, 0.036981, 0.055973 +15:58:32, 1112.2, 876.2, 0.03839, 0.0529 +16:03:37, 1114.5, 875, 0.041577, 0.054337 +16:08:43, 1115, 874.1, 0.038677, 0.056231 +16:13:49, 1115.8, 876.1, 0.044489, 0.055163 +16:18:54, 1113.5, 876.8, 0.035821, 0.054732 +16:24:00, 1116, 876.5, 0.042683, 0.056534 +16:29:06, 1115.7, 878, 0.040596, 0.054578 +16:34:12, 1113.8, 877.2, 0.035674, 0.054329 +16:39:18, 1116.2, 876.4, 0.043127, 0.057105 +16:44:24, 1113.8, 875.9, 0.041567, 0.059277 +16:49:29, 1113.8, 875.3, 0.037544, 0.05579 +16:54:35, 1113.3, 875.3, 0.042273, 0.05777 +16:59:41, 1112.7, 876.9, 0.029153, 0.053549 +17:04:47, 1112.3, 875.6, 0.029099, 0.060035 +17:09:52, 1115.1, 876, 0.043104, 0.057382 +17:14:58, 1113.5, 876.1, 0.033973, 0.056598 +17:20:04, 1112.1, 876.2, 0.040206, 0.055084 +17:25:10, 1112.8, 875.9, 0.035065, 0.056058 +17:30:15, 1112.9, 876.9, 0.028595, 0.057244 +17:35:21, 1115.9, 876.1, 0.038115, 0.056979 +17:40:27, 1111.7, 877, 0.028549, 0.056126 +17:45:32, 1109.7, 875.4, 0.033823, 0.054598 +17:50:38, 1112, 875.7, 0.035057, 0.056551 +17:55:44, 1110.9, 876.6, 0.026614, 0.056027 +17:57:03, 1081.3, 875.8,-0.11122, 0.045013 +18:02:09, 1079.9, 873.8,-0.12293, 0.050853 +18:07:14, 1078.2, 874.4,-0.12417, 0.04782 diff --git a/pxii_bec/macros/luts/beampos/beampos_20260719_20_12p4_6to18.csv b/pxii_bec/macros/luts/beampos/beampos_20260719_20_12p4_6to18.csv new file mode 100644 index 0000000..995ea5d --- /dev/null +++ b/pxii_bec/macros/luts/beampos/beampos_20260719_20_12p4_6to18.csv @@ -0,0 +1,243 @@ +Beam size: 25 x 25, Energy: 12400 eV, Zoom: 1000.0 +Time,Scin_x,Scin_y,BPM_x,BPM_y +22:36:25, 1060.4, 878.9,-0.10583,-0.0084627 +22:38:31, 1063.3, 881.9,-0.1066,-0.0073115 +22:40:37, 1063.9, 881.4,-0.10975,-0.0055692 +22:42:43, 1065, 883.9,-0.1324,-0.0099198 +22:44:49, 1066.7, 884.9,-0.13217,-0.0094756 +22:46:55, 1067.1, 885.5,-0.11527,-0.0077712 +22:49:03, 1069.5, 886.4,-0.12735,-0.0080743 +22:51:09, 1072.6, 886.3,-0.12191,-0.0092353 +22:53:15, 1072, 888.3,-0.11964,-0.0056324 +22:55:22, 1074.4, 889.6,-0.1025,-0.010078 +22:57:29, 1073.6, 889.6,-0.11851,-0.010061 +22:59:35, 1075.4, 889.1,-0.12013,-0.010561 +23:03:39, 1086.1, 878.6,-0.10838, 0.0059334 +23:05:44, 1088.5, 890.3,-0.11136,-0.01826 +23:07:50, 1090.2, 886.6,-0.11445,-0.0036606 +23:09:56, 1089.8, 888.5,-0.11115,-0.0081606 +23:12:02, 1088.9, 886.5,-0.10979,-9.9095e-05 +23:14:07, 1091.4, 886.4,-0.11265,-0.00089106 +23:16:13, 1091.9, 889.5,-0.11494,-0.0021195 +23:18:19, 1093, 887.9,-0.11659, 0.0020202 +23:20:25, 1093.7, 887.8,-0.11693,-0.00030628 +23:22:31, 1093.9, 891.1,-0.11816,-0.0057121 +23:24:37, 1091.7, 886.6,-0.12128, 0.0051707 +23:26:42, 1090.3, 887.7,-0.11649, 0.0031412 +23:28:48, 1090.4, 887,-0.11383, 0.0019807 +23:30:54, 1091, 888.7,-0.11061, 0.001034 +23:33:00, 1092.5, 890,-0.11252,-0.0065677 +23:35:06, 1093.6, 889.7,-0.11642,-0.0025576 +23:37:12, 1090.8, 891.6,-0.12155,-0.0063002 +23:39:18, 1091.4, 890.6,-0.12272,-0.0048353 +23:41:24, 1093.8, 890.1,-0.12113,-0.0013978 +23:43:30, 1094.6, 891.6,-0.11878,-0.0034721 +23:45:36, 1094.7, 888.1,-0.11605, 0.0064705 +23:47:42, 1096.6, 890.6,-0.11813,-0.0016227 +23:49:48, 1094.8, 890.5,-0.11452, 0.0015881 +23:51:54, 1094.8, 891.3,-0.1147,-0.0027561 +23:53:59, 1093.4, 891.4,-0.11232,-0.0017604 +23:56:05, 1095.8, 889.5,-0.11213, 0.0012026 +23:58:11, 1091.7, 890.9,-0.11552,-4.8605e-05 +00:00:30, 1088.3, 894.7,-0.10247,-0.022685 +00:02:35, 1091.7, 890.6,-0.091432,-0.0026408 +00:04:41, 1090.4, 893.2,-0.091495,-0.010632 +00:06:47, 1092.1, 893.1,-0.088456,-0.0092543 +00:08:53, 1093.2, 895.7,-0.08548,-0.013679 +00:10:59, 1095.5, 892,-0.08163,-0.0053854 +00:13:04, 1093, 895.9,-0.085617,-0.01478 +00:15:10, 1092.1, 893,-0.087674,-0.0047268 +00:17:16, 1092.7, 897.5,-0.090985,-0.016994 +00:19:22, 1091.5, 895.4,-0.088027,-0.013004 +00:21:28, 1092.7, 893.4,-0.084513,-0.0078035 +00:23:33, 1093.4, 895.6,-0.081424,-0.013122 +00:25:39, 1095, 895.1,-0.077877,-0.007636 +00:27:45, 1095.7, 895.4,-0.080481,-0.010022 +00:29:51, 1093.9, 895.8,-0.084139,-0.01127 +00:31:57, 1095.9, 895.8,-0.083969,-0.0097662 +00:34:03, 1095.8, 895.1,-0.083824,-0.0075766 +00:36:08, 1096.1, 895.4,-0.081804,-0.0069044 +00:38:14, 1096.8, 895.7,-0.079827,-0.0087801 +00:40:21, 1097.8, 895.1,-0.078845,-0.0060065 +00:42:26, 1094.9, 898.4,-0.083426,-0.014225 +00:44:32, 1096.5, 897.1,-0.085291,-0.012956 +00:46:38, 1095.4, 894.4,-0.086194,-0.0030342 +00:48:44, 1091.8, 894.4,-0.091819,-0.007776 +00:50:50, 1096.9, 895,-0.086827,-0.006593 +00:52:55, 1093.8, 896.5,-0.083934,-0.010891 +00:55:02, 1095.9, 892.6,-0.078386,-0.00066634 +00:57:08, 1094.8, 895.5,-0.080492,-0.0060498 +00:59:14, 1095.4, 893.8,-0.079348,-0.0010273 +01:00:57, 1086.2, 886.6,-0.065065,-0.00013186 +01:03:03, 1084.7, 887.7,-0.074515,-0.0017025 +01:05:08, 1086, 889.3,-0.077061,-0.00024336 +01:07:14, 1084.6, 887.9,-0.08186, 0.0007312 +01:09:20, 1084.7, 887.2,-0.078934, 0.0048637 +01:11:25, 1083.8, 889.2,-0.083071,-0.0023657 +01:13:31, 1083.6, 889.9,-0.082672,-0.0024003 +01:15:37, 1084.6, 888.5,-0.082158,-0.0016185 +01:17:43, 1084.7, 888.3,-0.078614, 0.0024562 +01:19:49, 1084.5, 891.1,-0.076958,-0.0058177 +01:21:56, 1083.9, 889.6,-0.07548, 0.0016631 +01:24:02, 1084.4, 891.3,-0.078394,-0.0033353 +01:26:08, 1085, 887.4,-0.081657, 0.0040334 +01:28:14, 1084.2, 890,-0.080469,-0.00024043 +01:30:20, 1085.4, 889.7,-0.085927,-0.0057618 +01:32:27, 1086.8, 891.8,-0.083425,-0.0068752 +01:34:33, 1085.6, 890.1,-0.086878,-0.0048822 +01:36:39, 1084.6, 892.9,-0.083786,-0.0098233 +01:38:44, 1083.4, 889.8,-0.081551,-0.0053882 +01:40:50, 1085.7, 890.6,-0.075925,-0.0068812 +01:42:56, 1084.1, 890.1,-0.075559,-0.0051225 +01:45:02, 1085.4, 892.2,-0.076528,-0.010656 +01:47:08, 1083.2, 890.7,-0.077802,-0.0069342 +01:49:13, 1083.7, 892.8,-0.082591,-0.013723 +01:51:19, 1083.3, 890.7,-0.084526,-0.0091534 +01:53:25, 1081.9, 892.1,-0.089283,-0.012845 +01:55:32, 1083.8, 892.4,-0.087885,-0.0087082 +01:57:38, 1080.9, 893.3,-0.088293,-0.013436 +01:59:44, 1082.4, 891.9,-0.084131,-0.0047178 +02:01:24, 1089.8, 885.8,-0.076, 0.032848 +02:03:30, 1092.4, 889.2,-0.054165, 0.028047 +02:05:37, 1090.5, 884.4,-0.071597, 0.033274 +02:07:43, 1093.4, 887.4,-0.068904, 0.028838 +02:09:49, 1094.7, 885.9,-0.066548, 0.029639 +02:11:55, 1091.4, 885.9,-0.06624, 0.031237 +02:14:01, 1091.6, 885.3,-0.065731, 0.032068 +02:16:06, 1092.3, 885.7,-0.066224, 0.03011 +02:18:12, 1094.7, 886,-0.044613, 0.031121 +02:20:18, 1093.7, 886.2,-0.041754, 0.029849 +02:22:26, 1091.9, 886.8,-0.060506, 0.029507 +02:24:33, 1096.3, 888.9,-0.03123, 0.026509 +02:26:40, 1095.2, 888.2,-0.053696, 0.029404 +02:28:46, 1094.1, 888.1,-0.03567, 0.027089 +02:30:52, 1094.2, 888,-0.03523, 0.028663 +02:32:58, 1097.2, 887.2,-0.028733, 0.030174 +02:35:03, 1097.3, 887.9,-0.047942, 0.029229 +02:37:09, 1096, 887.4,-0.05307, 0.029778 +02:39:14, 1095.8, 886.7,-0.031823, 0.031276 +02:41:21, 1095.8, 887.2,-0.035524, 0.030281 +02:43:27, 1095, 889.2,-0.052045, 0.024124 +02:45:34, 1095.8, 885.9,-0.025722, 0.03354 +02:47:40, 1097.2, 889,-0.026883, 0.025967 +02:49:46, 1095.3, 886.4,-0.028725, 0.030098 +02:51:54, 1097.8, 886.4,-0.051672, 0.031952 +02:54:00, 1097.6, 889.5,-0.036, 0.026482 +02:56:05, 1095.1, 887.3,-0.033187, 0.028698 +02:58:13, 1095.2, 887.6,-0.049451, 0.024264 +02:59:19, 1088.8, 886.1,-0.066777, 0.023394 +03:01:24, 1088.8, 886.9,-0.067831, 0.023045 +03:03:32, 1086.6, 888.1,-0.093135, 0.01838 +03:05:37, 1087.2, 886.5,-0.086424, 0.022722 +03:07:43, 1086.9, 888.1,-0.066847, 0.01881 +03:09:50, 1087.6, 888.3,-0.083542, 0.020706 +03:11:58, 1088, 889.2,-0.066662, 0.018156 +03:14:03, 1086.7, 888.5,-0.067556, 0.016385 +03:16:09, 1088.7, 886.2,-0.067532, 0.023735 +03:18:15, 1087.9, 890.6,-0.069117, 0.018238 +03:20:21, 1088.5, 889.6,-0.086728, 0.016721 +03:22:28, 1087.7, 887.9,-0.063337, 0.021393 +03:24:35, 1091, 889.3,-0.061427, 0.021218 +03:26:42, 1090.3, 890.7,-0.081099, 0.016934 +03:28:47, 1089.3, 889.5,-0.06018, 0.019599 +03:30:54, 1090.4, 889.2,-0.078334, 0.017338 +03:33:02, 1089.4, 890.2,-0.063479, 0.019633 +03:35:08, 1088.8, 889.7,-0.064698, 0.019546 +03:37:14, 1086.7, 890.7,-0.06736, 0.016639 +03:39:20, 1088.3, 886.7,-0.063542, 0.023539 +03:41:26, 1088.8, 890.6,-0.06362, 0.01551 +03:43:33, 1091.6, 889.1,-0.078626, 0.02067 +03:45:39, 1090.6, 889.2,-0.081025, 0.018433 +03:47:46, 1090.8, 889,-0.064292, 0.018227 +03:49:54, 1088.1, 889.5,-0.086955, 0.015797 +03:51:59, 1089.2, 889.9,-0.067474, 0.015368 +03:54:05, 1090.6, 889.3,-0.063786, 0.015413 +03:56:11, 1090.3, 889.4,-0.060395, 0.015081 +03:58:17, 1092.3, 889.1,-0.058559, 0.015406 +03:59:44, 1085.5, 885.7,-0.098346, 0.028605 +04:01:51, 1084.7, 883.6,-0.10983, 0.028994 +04:03:59, 1084.1, 885.9,-0.099608, 0.028806 +04:06:06, 1084.4, 885.7,-0.11286, 0.026572 +04:08:12, 1084.9, 885.4,-0.11494, 0.028373 +04:10:17, 1084.4, 887.4,-0.10967, 0.026349 +04:12:23, 1087.1, 885.4,-0.10401, 0.028785 +04:14:29, 1086.8, 887.3,-0.10464, 0.024945 +04:16:34, 1086, 885.7,-0.10224, 0.030138 +04:18:40, 1085.9, 888.1,-0.10274, 0.023789 +04:20:49, 1085.7, 886.4,-0.088085, 0.030793 +04:22:54, 1087.2, 887.6,-0.090379, 0.024066 +04:25:01, 1083.9, 886.8,-0.10515, 0.031232 +04:27:08, 1083.1, 887.3,-0.099723, 0.02765 +04:29:14, 1083.1, 885.8,-0.10305, 0.026765 +04:31:20, 1084, 884.6,-0.1004, 0.02838 +04:33:27, 1084.7, 886.5,-0.11276, 0.025315 +04:35:33, 1086.1, 884.7,-0.10571, 0.029943 +04:37:39, 1086.2, 888.2,-0.10983, 0.021139 +04:39:47, 1087.4, 885.4,-0.096865, 0.031181 +04:41:53, 1086.2, 888.6,-0.099061, 0.025925 +04:43:58, 1084.5, 886.2,-0.0989, 0.029481 +04:46:06, 1082.1, 886.6,-0.1155, 0.026603 +04:48:12, 1084.4, 885.1,-0.11323, 0.028742 +04:50:18, 1083, 884.7,-0.10087, 0.031223 +04:52:24, 1082.3, 883.4,-0.097488, 0.032156 +04:54:30, 1085.1, 886.6,-0.10599, 0.026845 +04:56:36, 1085.5, 884.1,-0.092027, 0.031292 +04:58:43, 1086.1, 886.5,-0.10409, 0.026272 +05:00:07, 1085, 883.8,-0.076696, 0.025634 +05:02:13, 1086.9, 882.4,-0.074979, 0.025503 +05:04:19, 1086, 883.1,-0.081743, 0.024614 +05:06:25, 1085.9, 882.8,-0.075776, 0.026175 +05:08:31, 1083.8, 883.9,-0.082228, 0.026293 +05:10:38, 1084.2, 883.9,-0.091544, 0.024279 +05:12:44, 1080.9, 882.6,-0.082779, 0.025366 +05:14:51, 1083.2, 883.9,-0.092996, 0.022878 +05:16:59, 1082.3, 884.5,-0.082728, 0.024254 +05:19:05, 1085.8, 883.8,-0.078074, 0.025324 +05:21:11, 1083.4, 883,-0.08049, 0.025883 +05:23:17, 1083.2, 883.2,-0.082627, 0.025098 +05:25:23, 1083.2, 882,-0.083604, 0.027314 +05:27:30, 1083.6, 885,-0.096756, 0.020698 +05:29:36, 1084.8, 883.2,-0.076157, 0.027332 +05:31:42, 1084.2, 884.5,-0.077174, 0.022879 +05:33:48, 1086, 883.2,-0.077332, 0.027437 +05:35:54, 1083.3, 885.4,-0.095597, 0.019258 +05:38:00, 1083.3, 884,-0.094601, 0.025104 +05:40:06, 1084.8, 885.3,-0.09063, 0.020397 +05:42:12, 1085.4, 883.9,-0.082295, 0.025197 +05:44:17, 1084.7, 884.8,-0.08566, 0.022262 +05:46:25, 1084.3, 883.8,-0.084293, 0.026268 +05:48:33, 1082, 883.5,-0.098464, 0.025377 +05:50:39, 1081.4, 884,-0.10101, 0.022308 +05:52:45, 1082.2, 884.8,-0.099798, 0.022877 +05:54:51, 1082.4, 883.3,-0.08863, 0.026499 +05:56:58, 1084.4, 885.2,-0.091666, 0.023724 +05:59:03, 1083.6, 884,-0.091715, 0.022943 +06:00:07, 1082, 883.4,-0.11192, 0.037721 +06:02:12, 1083, 885,-0.11957, 0.038156 +06:04:18, 1084.8, 886,-0.11856, 0.036642 +06:06:26, 1084.5, 885.7,-0.10789, 0.037436 +06:08:33, 1084.9, 884.5,-0.11389, 0.037365 +06:10:39, 1085.3, 885.9,-0.1102, 0.035751 +06:12:47, 1087.5, 883.5,-0.089998, 0.040013 +06:14:53, 1085.4, 884.6,-0.093043, 0.038193 +06:16:59, 1084.4, 883.8,-0.098512, 0.039186 +06:19:05, 1084.4, 885,-0.098786, 0.037087 +06:21:11, 1083.1, 885,-0.10092, 0.038601 +06:23:16, 1085.7, 883.8,-0.097485, 0.038191 +06:25:22, 1085.6, 884.7,-0.090524, 0.039356 +06:27:28, 1086.8, 884.1,-0.09521, 0.041347 +06:29:34, 1086.8, 885.6,-0.101, 0.040327 +06:31:42, 1086, 884.6,-0.094068, 0.04094 +06:33:49, 1084.9, 887,-0.10728, 0.037482 +06:35:55, 1084.7, 885.9,-0.10485, 0.041545 +06:38:02, 1084.7, 886.1,-0.098321, 0.036696 +06:40:08, 1085.7, 882.4,-0.089756, 0.040941 +06:42:14, 1084.9, 884.1,-0.099562, 0.036133 +06:44:20, 1086.9, 882.9,-0.091885, 0.040227 +06:46:28, 1085.8, 883.8,-0.08283, 0.035471 +06:48:36, 1087.2, 884.2,-0.089415, 0.039128 +06:50:43, 1087.9, 884.6,-0.08288, 0.037156 +06:52:51, 1086.9, 884.7,-0.096839, 0.040378 +06:54:58, 1087.4, 885,-0.091789, 0.036039 +06:57:05, 1086.7, 885.2,-0.10133, 0.039144 +06:59:11, 1088.2, 885.9,-0.10203, 0.038694 diff --git a/pxii_bec/macros/luts/beampos/beampos_3rdJul.csv b/pxii_bec/macros/luts/beampos/beampos_3rdJul.csv new file mode 100644 index 0000000..b0fba7a --- /dev/null +++ b/pxii_bec/macros/luts/beampos/beampos_3rdJul.csv @@ -0,0 +1,50 @@ +Beam size: focus, Energy: 12400 eV, Zoom: 116.0 +Time,Scin_x,Scin_y +22:42:33, 1004.4, 975.1 +22:47:51, 1004.2, 974.9 +22:49:25, 1004, 975.1 +22:59:29, 1004.3, 974.9 +23:09:32, 1004, 974.9 +23:19:35, 1004, 975 +23:29:40, 1003.8, 975 +23:39:43, 1004, 975.1 +23:49:46, 1003.8, 975.1 +23:59:50, 1003.9, 975 +00:09:53, 1004.1, 974.8 +00:19:56, 1004.1, 975.4 +00:29:59, 1003.8, 975.2 +00:40:02, 1003.7, 975 +00:50:06, 1003.9, 975.1 +01:00:09, 1003.7, 975 +01:10:13, 1003.9, 975.4 +01:20:17, 1003.8, 975.2 +01:30:20, 1003.5, 975.2 +01:40:24, 1003.6, 975.4 +01:50:27, 1003.6, 975.5 +02:00:30, 1003.6, 975.3 +02:10:34, 1003.6, 975.3 +02:20:37, 1003.4, 975.1 +02:30:40, 1003.3, 975 +02:40:43, 1003.6, 975.5 +02:50:46, 1003.4, 975.4 +03:00:50, 1003.6, 975.7 +03:10:53, 1003.4, 975.3 +03:20:56, 1003.3, 975.5 +03:30:59, 1003.3, 975.6 +03:41:03, 1003.1, 975.4 +03:51:06, 1003.2, 975.5 +04:01:09, 1003.3, 975.8 +04:11:12, 1003.2, 975.4 +04:21:17, 1003.2, 976.1 +04:31:20, 1003.1, 975.8 +04:41:24, 1003.3, 975.7 +04:51:27, 1003.1, 975.8 +05:01:30, 1003.3, 975.7 +05:11:33, 1003.1, 975.9 +05:21:37, 1003.5, 975.7 +05:31:40, 1003, 975.9 +05:41:44, 1003, 975.9 +05:51:47, 1003, 975.9 +06:01:51, 1002.8, 975.8 +06:11:54, 1002.9, 976 +06:21:58, 1002.9, 976 diff --git a/pxii_bec/macros/luts/bpm_calib/10000_bpm_flux.png b/pxii_bec/macros/luts/bpm_calib/10000_bpm_flux.png new file mode 100644 index 0000000000000000000000000000000000000000..6803900195b505210a7c036c4fce37d1da391567 GIT binary patch literal 28879 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 b35-RUSQphCGj(ycAk%@pntKv|H@^B`I$?gt literal 0 HcmV?d00001 diff --git a/pxii_bec/macros/luts/bpm_calib/11000_bpm_flux.png b/pxii_bec/macros/luts/bpm_calib/11000_bpm_flux.png new file mode 100644 index 0000000000000000000000000000000000000000..81e7d24f91489afd0b7a1930a10e58461aabf525 GIT binary patch literal 27618 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 literal 0 HcmV?d00001 diff --git a/pxii_bec/macros/luts/bpm_calib/12400_bpm_flux.png b/pxii_bec/macros/luts/bpm_calib/12400_bpm_flux.png new file mode 100644 index 0000000000000000000000000000000000000000..c64e1e7f81c22ca805d1e12f864337d9af1e33bd GIT binary patch literal 26355 zcmb@uby$|`*DVSnA_5|zBB@A9N;fLqDo99ocQ;5IARt`^h$!7D?JJF>bc1x4)R_Q2hGCQh#U4#sE-`c8IMwoX>&2De>|9URSVZ8%x)-)CiKzHR2@ zWalWr#%BFLKEZ11V9FMQ%CLp2VB1M+IHIB9>m&c7e-X_zM?*8wl@Wia;+DKR=B}mE ze}>u|^t)U!X~X*7WX*idlP-}gS0dI}w1c*&u+QpA(NiWS&3@*#zV_GIxFzx|j*NYM z?b?oV9eA#o*ZtAg)+3ILuRS!nRnFOXbm(^A=ed?3NVS$w-$mYOz=_-VKpg%wiMeY~ z_=UnBX~m}vOw{m)QUN;;`3pBL+G^zgr+>ZMc!~Ull=A;?A7DxAM-L4xf7KX*Ut~Wc zd3TtMa{8c6EQHe!Ahtr91Tde)&v;--yP5WxuM5;-Ou;*UB zX&2?o8!WQh^BtSJyERk09Ll_$F6-kRd#fYny`S;Q#yu<(opBo{kJf85ofdm8Vq)^o zxl4!_$_m3v@!ofwmrvxemQCWZCgHQY-6eYFmADIEMS1U!NhNR?lkhvxC}%2W$VAf> zTlBvit8&deBA1I}rRC#`525mjpKFWD6!4vEy&hO+EA>P)&T6E?1|f^&O)!pVOaf zaK&2vnm1&;g|-tSr^nk$$iK178V#o>NBo|9%oKtyvrGNo%th8lD;#mj`QGwa507pP zD+%usPfbl(ja9}_`5s5Ej+7CRlegFGkGF*p(HCm*G9ho7BH(; z#^&bKFDa^yz3s42qc}nxg2*Jdzl)jX!^MjV%l$c;an8#Fzw-6Pq%^XgW{?OtF`&XJ zW+FsSrMK;sL=I^($xTR6`KX;y}&_UWia==qw!) zbBa$h6)9d4Ge&(KwJF26MnRFXG&-p3tDvqSZ&!&pTl$t4 z`sR&s_xp#u-mC2aB5|S8HZ4Th>zgwuTLJy1TZ1z4^0OOLjauKm z_(!^EsZ*zdZtCa_=4w~(^vJ!t_pJ4a4audGqy0>ymZ;ZMq9S9KG$)FT>iK$K9Wilk z%=To+X?#tJg^*5;rdQf(p-+39t$ttXuvbY`0YWoD!1?PZD|qQ96e{!2;aI*thM?=3 zQJo*UoBLeYnSpo{p4(2L(W{$mCJ>t0+EuZEffo%73>;uHu)m*I>ma@^PHRr8`F8l{t zT3TNn?d|PhCycXfo)6^dM&#w?8Om@rvXh@(xyjnznIcHx9Pr}Bm**w-icC5T`o28z zboF*KL1lK+I{J%r3DcbK~};d8_SNle4ezCq_IEl#uV=7hfv zSaLaD_$u$#{)BIDo~|gsZTVcRCOdAxEl!hkb(K?-LG$ry{*EMGSMr-|I>`?MF7cm^ zx_$~{pq@_nelU%b>aoOF>9X1i-;aRw{we_IIS((wtX1CqB=%jp%}D7RND#+CZPzF1 z(gcazmY3pd^VYr}*+`wl$CDt*lBZKcZk&*n6npR4*L>J6lg{LX`TWr3-Q~duH68b$ z1Wr?j$vSja?aK5P3+ic)*FuxqU81~@A<8jn!kz;R8inbb5N0G{VPV1gBtLj3ybOt1 zwSM#Y9J>YQMaRN&cV51H`KQh#^|ZrRwLF_qdlUt)5EUt@g`2zkE$vFD`v!)FoX)F& z8)Sa>t%r+M7M2F{Y>|&iYH1~ZT8UN?xsP^NNJyy7Id31{luSoQ=SLe`ZSsvx$|lnb3Ha#IaKfC+C5vxie$$7LWc z51^R*87Z@k&8>nGB=YyqU6F%H40?wm(^s~GLtKdP&%<9Tf<(fYrsW%``_ zMa$NyN&N18^t8}OhSF=}VM9a1Q>{$>#$c74=iGAly*8U~7F&)=C|1O(4f4Sj#s;{{4T(tqN4h$ zn$wEFI-r|!|N8HOy8ue`0s@IBDqkV7t~=CGNmdXKs#uY|ChhU{fIle~&OsllXI47hKfw_VZ-l0S%ok&C>koHs6wcQQG`@pj~%D$nDb2lV7;zXVa8UxM!S{Q z@17tDu8_pzwA2>{Il?e>9g2xP0cFYtC8RvU9j2SGaU1nu%U4D#qT!7%*ug9J!a4}J zuF0F3F_7_C>2)UabHNk91DhTQgy2(shV@eUruxP-%{vx~z2Fj{qvlr8E96;PK80{q zZ#3XAYgckTbB7DKj=R&N6%-W6rwGKrjwCRt(M94HymCm&980>-q5Zc ze|ep$e0M-IWrrvXt|M*Y?(~m9P5%-jMaY-U{(NwB zq)Gl}xnN}V`0sL_)1Pj1*r{)gk<5?DJT8@dGJPyqDO&Pj`PIvp)NrB58RJ;EtV|;b zP_USd&-FHC%I_bb!~g95a8b4p>w539gKHtRpULAyr9tuatBfV`WdA24?6`~CFcCK} zpaxu54bjK08dLo4br>2J25DKpWJiP37o1xE)n#XMvwmbma4=O#yvf3yW9rSTS2Nuo z#AxW~o>RP}#cg~qpTI#b?4hzuT*X-O!8E^+;uUZ_;A1;~2_l8=bkSA^>t7=v@GmRl z_4oJJcwYT`jFyfLVT)I;-+M>z>!b9ZX9ric_>(?~xRjLR-yL(b)>xJ#rYeS|ZA!%u8QM9}n$QMgypiW(=TkOqb)UGTJ<_!%+wK<+C z)4hpqOB1bajtmV|r(eXV9kVIpBP57Sj$0rcry(t)qjpd5!FnmJ6J<)IqeMtb+FEGb zCbU+8>{0Tat~XQ8YB)Dpjg|*;vRbilNghB5J^QNi0qO}_dx~Hj6zpEe3VBf_aq)|_ z$6Gi+Q|9+ZY%`&LG4ADjKdlg|AFuH|1b(x*we?Xdg7V_Ui=+8#zy>vHJe*$^UckJv zG5v~7AUsn(p#e&fvT*715{sR+u@QT(;{*FxHr>t&#|5ZLr1kanvu$x(EVl><>fyHh z-ha7(5`2P`B4&BcWhrV#2g_EZSAQX#oF5_Ie|~)m={3Z`!I{~bYui~J;cbj)>9icV zx4F4lz4?O-mxSF97Jl}RBL%-hAi_T(-3W<^#b)v4fQKD{_u>+ zF2EgaY08-hS&Y4vA@kH_NVS(2oq*9Iv6|o$Zd-eTR3W5}!V@2?Rjq$f%cBG?(rNLV z)%N&clgq5z4~n7V!G=C$b34#!TXo;vrG9`cCgm;yBBI8F&6%O^-c_Hhmin@aEeFF( zEC&%pNcCLfhXq5yWyzg=4(D##RITzLycBXZ0oYi~y=Mj^rPc{&5A*K3u8lhR{@7mV z>izQM?zs29wqmMK%g@NW6;R25F*;jV>FevaCvejD7MRYJSZ5p@xc!Kr>WaK8<*?%p zWJl%=DYtro0VY(CPk>a_00I1elc}Rnfk6*5WV=7(?W|e*X z_#z-c`89sBuqO{fDuEUThJ-}N$4dijDzk(TU%%e`QQ{RJfJ+RM+Gi*#z`Vw|*0O=} zr@5_`462t{Tz8%D=0!6^h0nozEsEp~^k(9tVc}C64HX(UH8=nI?(Ml&J`+xCPr+yB2YsV{ z*@*e?{0}oF7v@6}$|ii0fIt;MM}qJkKmoT&e=KN*&?kWspd-BY81n8Nt9D{$s>eOK z{XddWNPsHu026}OzUT*(u)EAw7dVClfQ{KMYh+Aqi)(ZX2Ep7{yL?#uj3Wp%ah0Z6CS;TV^uWl&pclB8gWFts03XLaF zh?oeGzdwI5CBNJ0OchQ7t{L_A?E_djcs(3QDnn>9fDL2#L7nRy`CE0#gkj^u?nqov{_^+^f|P6AUCI27z)YloGMV+H zV?)HsmYu@hV_&%zXiyK76_^W$tcV$(HrZD@E+8St={#XG z4+QqT?ZkItX7y`+9LBBP8FDx0yVBOB-8cy~O*-Hm;N2oceSL<@Y`cJi+!FTS(k!)- z;ni>ZX-U604A;Mig{2H+3hlE((hul*pcNzoY!}-4c^Bz-gbpSH(B#uZQjqL|IzF?$ z-Uaj)>F#vBHZk9hdct2$C|5d}BiRkiqdhatr}gWzZyY6~gMC@b&^oW+b?J&a%|D0x zPEFPa0BF@c*{j3A-{@0TDlq#+o$9?ego^^YBKzn9E?KO=5N1)kNx)R&2PynGit+b> zye%;K(Z?90^_ zlo&(s5PCXJuY(OPqH)NKo=Rs+$v33U0MW3_A0Y;_epu_YvEw2n-eZ5QV`s4!-EFO6 z;fqdXWgwW~OQ zaDP@zNlX}drw=4&axPBSWUSH|zyMhv*fGc_`N{}r2dJQk%t2fV?T^*JG5pjSw2f`_SC|9FP{i!i<4GI}60og9Em_(wQJ(pp;OO{gWBwl&R22o`mTysE7g-5+zM z0;HZD(6m)}b_Re6y!mc(`~YO&HNZ+Jz{)h$utAPHUxxr-ff+!X3aua1{Q~2*8_!Fv zTF7jx{q;#mg8j#AOdEsocwd)kSGh1og|~-BL@dB-GppzOt=FEVmRgS#LeCnENA?4t z-mLetLSlsH!BmL*Zoe8u(nX=&KIKv8L2W<*|5Rbm&tFAB{{nU@DJ|eT9|j~0o+X*j z{>7g^W+<#EC^8O9eT>lHff7N(!xIb9;IP<33yMs`RAUII(?sq%wy51Cnp`Zi%&(;Q zJ|dqvU#jlh^(>a>#SC$5x-R6IH#MQdvNcwURAc{EARO$J|XK56Dp78={MZMbXzUavgk)F>_rl;wbA(W*zhnENQ(mtW8 zK+1Dk9(V&1)aL^T%<7!?Gj?NASKR0K>wc z3|V=3`69(%A0-m_?5UAm0k8u`|L&%)S7ZPd{ub<8`d43I3b%I$(gEBJ0d*N$bJw|9 zG)tN9-@l&>%4FzS%|nndl%VPSqzKAmFNJ4v${oDJt+~6tr^n)wl7)t-t0=cNDN6T1 zSf~lRt!EIh%H+J31FtKcmkTZWzp7x{K6-RP*XNMd`)E%gvWXUQ^7SX-39oGhAS{iR zc{M+eC}H`Zx4@RQ_}<4IXE~Z4uQKUQ|E8HJUGp-tlK@fuh>09eJ0U`huuvE%6}cpNU%Eul@Kv9^QGnwWq;@ zigGT&Tr^{4U%q@Hrcwo=J6nC2_IbGsOCi(s zUM8R6!$as7e?cXL{-g;JmYkfNzUIWY#V}#ThdqS#pqLw^!U&&T85Z#I@gWA`0s;)f zgw5_T>nUTpNk`(S`$9^%(arZzq63W`O0$5kXa1V01?eoDO0*N&Uzc7>s3~vh6cY1c zP3u;6$DmXEBo(3fWPO;1)7)#RV{K$tcnYE-6Dq3t9>WcW$9{En4^U~l(JK?R6Ok*X zG^NQ7CzgVOc`0ynM<9<*UAi?M+!7I|Z_;=FDth?N{$SW#UBfO2wxjrNFDd`?z8fJpfz= zsQo8so*7%AdzOR7TA8*A4Maz%KOxYg@|{Ktd+acPe5??2z^qdpUu4=P@MEJB+H9bC zdPPHs(B-_;HwA*kd~Vg6!)vneu&^m;EkA(bV1AlBbgKt#V=@4r!?crp#ii=*B7gu3 zkO+r9jS2@^(6AkLvVo=PLJS zTigrT{XDt8)~3597~M6Vu29e<%*?(Rde5fcujaNKNQct$no>9s5sI5b0`5wMPp+<} zOpA>H#6x+kHz~4*w#?`6B0cQwMZdf}Hi(d{@#w*}&bPr(MU*QXj3Geg+}M1evV#Vi zKq>5DbXZAE?KiZ^>t0wv8qg8Tv8eF(v8Z`eo1!`fFs&@;-d~gR6Z-o4Ub(^i6KLxY zl-kPZ0ibWdthLJR{Gk9TSG(DlS`9sNb1OHL{JU$#Lzd>Xg$>&HG(a=ZrXZ-xM8w4J z3<5Cy0Lf$KJCX!d&3~6#lUWYtIw#}f;UVfjP}^=O@2pzob;Bi=?sG9}g~{b(?Z8|P z4;RuvLT3a*21J@7TenuEIc-)A#803kOVVyA=n+6g%7Tu@v@>}M8BBm4&G>^U;Ba9J zQhCCTV+87!te2M%#1btCDF}mr;}zPU&2b|MwAg6Pvg(IA?1qO=H!}2Mn+#{$N_)J1)M@h zY^qqK2Hl)X(=ktb|85&WBMs}ORKPq0tfh4zM>8xu+~iO92XdI+NZ{M5s1To?o@Sk@ zQ~}RG#wnd?qDsKk{=j~}oXhF)$b~wP4-61dh@lQE=QNUmpbfy=jDasy2Z8T-UUK*19x0yVYC0%Fkya$pTt;DE3)e6&yr#^3vP< zxfA9r<~gIl3IvuAz(MLdhyL5YCEC?)n@QhYdMaI_K>I2Jyamw(p%fkm^(((1h8RI* zPKTTZd9CF>-4V2)h|~{bDTn#?1mfilouhgVBr<&t{2>$~;O8JKT8?a*G}3WQ*Pfj^ zt`rXdlXr4`?l?FRl>5`BtOz7T=+%=ALf@6+m*`&-mr4@5!DGu4F;W_&rqfcAGSJhu z%JB%>mU4FG%*d9Gamst<4X?v-#n#JFo5t*T4&y5rmvGA$D}SspGftf>=hfO&QaV1* zwvswwb)uw|TT`-*f9U_$Bejh!gac*D%F9r<>L8qs zUFT@8gF7oj7!ks;-&%4x%higfV*zyH=F_4iMpM$#s33DYHb3yfh+*l^lk$C?@^ujs z0j`Q_BN=H!Z6DY7GL}&@#mrG|_n@FM=e=P8Nqc%me@VsBYHhCVEgMx|wz&<^86{@uY2KGgEH%mEq8X+T*|OyuZewz&%X-b*_{$Qn8U)wt z>ilhZ6?ui-d8T&jni<8#IaVY!U%!&3G%TtY-ha^ivO7D0|9*!8YVk8Yh+!fkBG8$G zmMI3Uu!Hf4k{Z(WYiS|*!djIcldfd_=T^3vR3m#Ra6BM9ptomK5WER>EB_=lH4~xV zaM97q#{a_n+hEIqr~6#)tW&#tdvv#N`@u5UgU0f$u^>>NM61RlM$@K(R*CL7^#O84 zD-=jhFa*Q&)+20@BP47WcWozeeEK}-%G=`YPgwL-Z?TAU{6Is1PWKrUto{$`4K`)l zkSKP*i7oxD|D(2jf({eNLT?CdWVO+@iR07Z3Ew0X%k#Q1S4}cy*4Aijw)onOnlZ1i zH`!b8U?L)vqN1X-ayGK?6n){;Q8TQ%!D_leEzun^<`OUKn!?!4-byLRRwW1}osX>D zsztopDSFW;J$@#?Q~mrpXYMf2L?|;R0U{)qqc!@a;~C1v zyx^S(4880~8+-vX`%Oo4#VE=6@89Y$tRp`|XcSXkbpv!eIad{s2O!lfebDG+3Fpvif7>XxLW|Ak3N8Hg5`>NbD8>u9 zJ5=t%lm`YD&g4=O66ktmBOp=plYSDEt)#EyU6VWC(bR{le@?Y>@gk^Do=umlZ!n|P zeNhPuWK?DsaOUW$l1;8)sIoQ$?}FV^W<_4J?%T*{(H{dVKV#e61S&l;4n3FXF}ZTj z7gqXk!;ZA(Oe9Q4=Xm53mM4`*=tW)KZ;gd2PEK4kp8Iqh9KagR)LgwNibBvpJ{J-yqeU8x;C3Y$(YRVgr`>II3(%gZbKs#GD83w`1Lp7|qQo|gX$ z%#L+DjJ#i;WLCz=)~b6G-L&MP2tkL_?$EGYC`S7IXiX4i{<6?Z+dLl}9K1QfC31Lh zaPTKiNx;c>G;O$>^9zM=!0@jVjhODyV-)*Hi!*nPkE6Syky$Lf1T7=!X_BbnDThr%JL#Lz6p;vpPC0&P)G5^h-YbpCL};LL9qezENLM zT+)l&mY-AKeKs0=`kzmP23{;$;K@<2h;B7$XRqZkztEd$`84s>V|>KuA}tvhlDRgd z(3Y>CZ<7+Gee)w20mQ{=pl#w%%`;b4kafKOFHbo>T4^i{L~DKe&j+5D27Z*V^%^$` zsC!`6e{b+n)axhb6CMZ7k+Q}y*T&{o=4oX^?Rn93=6nG-|NJ#ksf)cI9%881QeL?k z?2qxm>+qfPg$wN&KOa5H4tvs*VcY^Y7w_q0Wa*7ow1LTZ7Q3wY*8Y@kca2b%Z7X8!5L zDz%mqakVaFvXMFmyQqajDv{T&%LDoP0UF)q1;Gq%*Ul|JQLfq*F9v@X6rXO0RTB~c zxY~ZlRuahy91J)wT#?m`_X(aC*LfbfY;TNvZYBzF?_R;3-s1{J7H*4T4{_DC2 z1GPJZ*c0BFMuTGK4;)#2=RSeR5w2>sG^^(l<8+zzj7l`!Kr=1B;`utNX?1sHKq01yS;@p69+*jhS@G#XQQZBeT|59 zDRnVUx4r+yRSJ%X^(y?&^7qToV}&Hn-Arz&yUQPx>9>y{kOZ!K?Bw&%6}&#L(3?UE zNr~7tbFJ(?)fL}!XEjLAueD~op!jD1uQQc9!kXtYP5{2h<3gtMFlc(CU2}!4=Hl*h z<8(8-iToBnTL!;D&)Z9|+V)Dd#}|}@F|qIyQTt<9dDRBi^3zc}zocMYM%!AVyQ|9h z8CNGCLaA#An!k1_r|!1-cilqXk`< zS4Ob%YOmsvJtvDR$2{Mt>B?LkZlV$Ek#-q#9x`I4OLDR56ba=7|9+V0bJ9P`$N~jz zslWU4n~XbQo;@T8DY0kCRII-n@cXi5XCPo$~j6LI3b!K7LHU z5w5#GZt3ha{evt0A-scDz}VIGTKt=AiDWYJX;W)X z7MD%(w<+22bV_7hS}Hd-`h=?nIdJ(rh^Z51mLz#TMPoCl(x12ifgr^tJ^$D6`i?duDQXq4lHqUZtx)9Fr=81c0q47*#Qp` zHFea{-a2pG^{VfV_t?ATUBn(SW6RNm$OmxxgdmjBs98NAl)WL zkn!4(gO^9?86_#HEX*ey1gwBZ3(@)-(UbwzHHx`s^3Z@fqttdmeynmaV(xm&N9b=r zKUXj^qJf4l!KWHt3(QKH;$ehb<~@P%T10GYY|!aIUk%Qbcu-dOJ5U+@jbtPwKf!`f z{!@81K0b7{jct=snDoj`I-g}#M{RB1xXj^h1qlg>Cxu2W z%=Fc)-02_OHmAX!^%DBNnK@(D+xkUAm#7cV&LHCc?3oZKZ zeG?;sVAt$S3o+?ve@22<>Es_F8vOEl&Ko(JXsz6kGEi9&Mjl3 zuS9?gX=yUt?7t|ZMro~2y$%-XX{)AV;Y&B)Lq~v1%JuWyoUnDH(GOB&Qm=ehwa99i zYhyQvS|a<60u32_6sZ!-`KI{A<`^eOjgDQkadE6UMrxy}NNPt`Gt*uA5gsJC9ysC4 zOP|sI&2(??rQ2mlo!bz{6?z~`PKV9Pn5PIPMfco$R>;LnV5*E@Xw*&b-RnE6mOi?r z%<`$Y!k!kHT$|G8n7#FJZS2l%G>;uWY$7g2HKD|Rchc*kjOQmBcSo%>vpl`%vL4(J zloKvbgEH?)gao6173Ob0)1J~Z?%Ac~!W9){ zV}N;1S=N!PZsOG;b-owS1Z@*8U;k_BekGRMYjqkffG1ma@7L+r|lBs2}!(=Nq6-%R%^(_p~hTzpKHYpN_)3~B17ll0&WmZeVVep$N?~jQS1<{&o ztte~xi+bPidW+$?y@#*yXJl5iHZY#~TieSlW%0{P;UphA?ut8vomVnb@X5_Plkx_; zZ$o6##GSvqw9PFMt(M$S%=1gk#yZSphd-cE`nQL;8M0#s$sL#c{lVR})_j-x>UoS8 z-sOq4nDCbR9vWKQHDWbCC=*==UYiEONTYv0x0n#w;_-y zdqGS(l>7e6P*sF5wiG(dO}1V)cu9O`LW(MK{p=KNzq^J_-s27i7%Qe(z~LR>u_1`1mzqBjE|jY;|-WpKBD>&MMSV|5n-I?$i{!8~gEgg!|}s zVfmy>WfL~mTGUaD=lLYl2D?Azn$%*m*t4-axY5QY>mo7w_B^+Xi>)mcACPff-dph> zuZbS)yG~H{@w`(`Kpg@lqpCd*)8(y8Xd7ddz@fpp@i=S4q~-<5inxqEd9zZI=5xgQqVTcOo( zgjkWi4jrI~t}`&{ey<=pSuP#|G0<^P^}{8>u4RiTsZ9h-9gl%%|_n2Vp3)wZI#4 zzb_lx_gH^#>)z1yO*3fdj(`Ca{AZd15+gG6f~jJS{>lGcHDCVk)!dLZ>{a7(BmVv8 zB@Jf38korhh*RBv$omwzpY?}>*7oOb;Rp{;BRejA^E5Gx=H7$%akkBLei|9aBi?Q( z-|6so<|6-VLw<$$=P$^?CgGk!rMO2kmLsBfF#3MsTkDWhUU77!T$##{;-TB4lQep4fvwQI+i&)3vk%wAOi*Lm+M1E4radGms5F3mcbFt5ov4o)pxnd&s zktnz?robgsEKTYPgv;S>?WqMTi_2dwVAHi{SAoA?rLUr%9@hFAGRTe#^1UP!^NN{p zK|Y7s%V2Atjg+GN0JT;%gr1r@H&+bnPY-4ycL22CT&I8Osof*wb~onR;v#^c^@7%p zc#?9;##>>wg~dEs7{XVsg3lIj$b~Q@(5Z8- z0upNV2jQ@LaCz+|xF7!@1L1Ujf9WR z8iA1}VRE6%(Bae`8&D2@K~M9!lA{TVW@x!k+4V7;ukjc}k=Lol4;r1)}oy!t&U{Hc_h8%dQ)k(qhN{@6F z(*n2{-;b^a#pDw+IgF>qMCR0n;KMtNUQUjs!o3g zT{Y*0Mp63*oPvV+^x`-jjyTfZc>?O`i{~#ws;@ua9b|}#YV-2$z@vdEuPhgDnlY0O zfO81n^S-}0T31R~c`?)|Xr;a-&P_l-e_qZiQ0$XQw(oUocb4&}Y_7UqBe1`KJZ6+& z6kW#d8eUi!Z>}kc-3~)w$byd5f4q{?orNR%)8ZhKsh8qz8QcAp78mdQK}+o(jDS@O ze-f`)WAOY-9JRbhNj&V1CO;^_t;MYH5-7ld2N`72fKF6(dT{r)~CWHUx8 zazbp;_w)BmP0bw!22=wP0Xk9_BC|a-bUFTEL}QKZ-Z^)+M&b%i+6u^V;dlqE*@ zQhN6#zZkwmW~ zdo+!sUh^FCrknzaTWMKT_`_(r`QdUsMOn{%ZH8y9Kq$luf0_$dgUrq=49532PUf) zJID+1oG9|v?$Vr+0%UJ`3C97ld(&lzM2G$oYcF7PuULBHa?g<14LzO6a~Y;m2cS` z_|2`4ANATv4h{?*w?jc%~kxsi3`Q{26G{%5g0cEe38Sr6a^k4#L#a0{g4hkd*?6O5)Mju zs&I!!HK2nT~^2Yuim<{@*91B)X-U+nwr1U9D5x=Rs+t)fJwvgo%3Q(5HvWG>+9>t!bG+oEVH?t zx;rvpJP0EMi%RugB3(w9bm~-b;65CqsWU0cxW@)YZrBT#fnEqENpXpU8K)#3Zqx#( zU0W5JHU-E^;_zAb41==VBdnVtd)-tR8t&0h{kj*J8||DRnw+kmO|De|9~EzU1h4W< zH79Y+{qACyIp6?iIJtjjT5y^VM}%!H1%&=^Nf8fR@)bYJl(5sE$1i7^n#A|kC%Ry& zp7(}cT-+g1|3L(0zBALoLEX_|L!rY~h6*A?tM;~vW_aE2*98u_Rz$t7kjGeCSF@+;Rl1_xMlMupOTSn$K3Bn1M} z>+q@Wy*qdOVcxgh!8>stMq9aerP{^!QB)l>Beo&ty;0HH1OzhC@af`#VHVYF64z0C zte`8`TYI=8CT%c}Ji1V9g$>g**HL{Si_|uEHL=$V3{f0f zyl_-Ud61IR1h@a|v%7S3bVd4Mq2;v)ZqlUpRKMMLO@&`J4)a7mweT+98w8sSL$Yod z7#N&dyqsi8hzS`v%>xRzU6~6OVPv&Q{ROu@4fW#7O9R|(Ivz4aJ&^efn%K6A%)Bm; z_kZ`-yTCacQd{dAOi4sWCTC@pJ;QhJ-W9Z}vG6e)SC7|gtc$6C#>?4&QAqcPOGQiz zd-3U4b>7Bj#I`930eSa+J zo!t@vAp(Ln2`Q=GDpyLGUnCPS()=**E%#j0sxGy`yj>uHLnv~p9^EqDgrN_9MOffzkKS{IFF(Ub(< z(kt)g4I+xdr<-s#<9`yhBc=k=h=i3JELYaQzZ!&7Z01iBHG7VJon+x@tGSHOO1VC7 z%La&oxy=!=@vU3XyG^S?LrO@C#z#UfpYt?hgOaCRD+tuhWW}+|P=4lq--p4k*)TC^ zt8LXaGV;$I@6 zH`4qVLFT+rCLEufoOFt~;|P;;%Z5N~4Ugo|P`QI6TN0t)$5-Z!it}oD1_%2IK`E@D z9>KO17Z2o|zDBUgytz5=Qm6d+0UW$L%+>BLVFE#8tWx7u(ut zdnU2WRiw`Vq#ddQX@&g%sX$9phc8OA-*%XmQ{R6K3VgI&L8#2&qu!gsW?6%XVuEqlgPgrzQ+6Basq z1)*@}6<)VMd6J24=XQQYeBV{6?FuqYaWHWLSjR?4WA1*h61$N!FbJI*5Hy~x&zA@64(yg31g2Zgr-_fOAGV9O_@SsC9GV!)XKCfzS^)3W=8QysQd?8zt~~E)JJ`YyK4`eNWIOUhI0Qm4Axh)ZR$P7Ffk{ z0e%ZCjf+!(Thf(-2Lh~QlQ4&YagQW&B<}U=V)lCkGPDAuk`X+vvPauWjwFqpDdvML znmmSs?PkJ2V&&~BD0PtY#srj?$1l+z#F~{6Ae3lzCM$=Pru2C7$Aw zEu3+&5CcJ{%YIFi!qNvDVvfy0#Re7wxL;NLiRgPMQIn4EMcMNzK!H-l6s)r1w&Tm13*Cjx7mzVWOXC^m$P3|D(V%4e&1+i z^G`NW{6ocA&Hj)n^soMRO~_tW#QtA1S^+aY_>R+ntUM=4kftQ2 zz=K)sdJPuXGCnIz&R~514n%Gs51R3Z4?ABz1>E|qb#JOUU@b<@7lE8JVR>r(kHRrwj zt)gsC*X=a8S~^lS)+Q@u%*R34q#(0I+8t_}hw$Xz-~nE|&;#$R9r{xL-6<56%m&bX zs9pqR@VhLUo;5esG37m|@wi5L74u3Rn1ghE_02GW!$souf)7Bg#PX(mJX$cib`@ah z)|@Xh=<}A5C!rC z$wB3PPL$!NhHets`3|%~n-^CmY$;tAFHrd=3n6hRo-B!-Cv77q?PvS_e)Je2t==%# zpCRQLr~g!)$Wc9#`O-SeK?oJQm3R%GHS*Ua=;Pz_vbb>DX(y=TQN4RB_g!Tz`+jQK z-(eh5a5yd>Y9za1BI5?1NL7T(D~5&n7Z`$g1N(@I$kgs)Z_jHCNou5k`!{8QLOB~4 z!_*rFVj$}D0$?Sb~q5+JGc)e_j%t!OQs5{p)&o9)IZ zIwhXkTA!M+^cmo>9>^M~00}BI=)dPEH<>PD4ySOuf`Z;&ix;J8jZ@N~yrvgxNrB8= z$v;5MC)n>X3!Mph9cH*|ea4kfh}ul)d2~*hxr4!K$RPerbqP6g--1{dIhJ4}19wOH zIV-%kWa8P;U*6~#b*`@Ic*6h-N23OV%9byr+>k~9A&b4r5xt1(H4Y96Q1cR!;Y@f% zdude`^SkV?*CIqC^xU{&u2C}#l3x`svsS#8P8lmq8LuOD2O|(IBP~;eaZZlJl6dl6 z^B~2ETH!vU$S{|kH{f7P&M|pyWeAaH4zVhoiv$GVZY`G-o)e+NnLl}_dZ4RArrp&Q z;Dmt-Is%=(I9ZQ16|1Q?E$;X<5y?b?h^Z*yYPCEaV>q`2XQd-Zxh?G4SjyBXqTCWE zd_$t?Kd7;7^YQ&2Wyx_emumz_BUo_EqSR?*N6wxhXL*0Vy#r_JLg19w1{_V)q)2po z>A287h4b(s^ip;(MBqP970MO>VZ6ro(vj51P?m`Asa*Dh-z*R!;{CV#qXbTC9Gk6u z;B+Zy-+!;bZ_v;RLvN==T_Mg#q$GkCd)EHO<+-_LIE6>v!dmw!LPXZeiWyEY7qN5L zTORE_1i=Ty-$KnQo@{NL-p|H9ntJd(dqMbKQY?(}(I12Jglqr|nY27S1NP+CuVea+ z*`RF77Oebi7#34!!#o}Lm=Bi*Q8y^w*tfCJd_U$0gPcf`D&GWa#c+2()<35rltW#Y zksl@`!Bgq#$uNX?fvA@-p)jFmxfK&^Kl9_h&+&oE9HbS5$ z$r&8@LF|JnOHsQ`h}U6z2aQmmRGB{IN0vig z8i!X$PRfDy3fBMk{ddB?jnq=5x?NC(N%nd<#<*ASCl3U@XqJHhz;8hK1ce*XQR8%d z5;ivMP!({vfauyaJ$Y6j!~5i`$-}q9lR?D{~!b6H9*(RFWuHX&@saLY&|5 z+XRTg(&GNou}kDAn@~q)v5jr2U#(+Z(1|_n7BT^kN4_x!-&ls@vv86l`>L2$f<6uY zGZJ>R8_ev3gRA{=VkGb(8U@yp&A^{{w5#u2_Q&QoFxk~~)GLW8J*1Ip8j8$T?Y)oo z#g6v6%h<9tFw(qD&f$Gp5W+^C+ywEJ;oy6aV^wJ%d`Oyajky6F56s%yOP1b_@6^ zFrAoWqMN3FfWS%Khu7X)OnGgD&B{x7OtI;Ho(O zepEL&2vacllM5zSj)ewH5+RbcN*tF}j*$E0e0t~XgPJ!Te)a39R(F|{0He(L5c&iXs%gy z_4uSi{N`l8ntmPH7uAmQHxlOn?i1A$gtO5^)LocSVK4sZg@(?1v{4_yY#rB+z7@GQO;~Hd|q;!?$VVTT!VuYJh)&H^pSsn2Kw2ZJF$VxaMLKH zaPqlbdl4`-6#@)Y60Zo$bs&4zsLZtM9f0ZPjETE?Jgq+R+h5=q$2f9?qr<+k_BhJn zDJV7bhhQf*9b|th%9CYvV0Yef68vAKoe4CRYum>)oQ5~rZK-yd3YCsBw9S-Krkr$e zN+g6tMTSfvmcI^dy^q#NQOc~3U0dj+jSd}#&vrhCDk*N~^JHrU z{CM{i{m)Mn@NaA~fT%C3?)enm47=3564$r%)Gb>s93Xu(!9+&cn?K1+p}y1m1Y4vd z?OMUQ@=$*3IKKG{>PRLaCat?PYcq>=uk*#^S zoG5nkW%rv++KOwJ-PRf~vhn-W>2+9B`_d&eHwI2ZF%CuPq0D9$8q8wS2bN}~$nvuC zrm{)_U#QIqS=CcEuWIm)-Sl*8lMRmO^@x0XE?`fPRn-c&cuIuKGPAcW@rM9EAz>h6<^y{lWzgmD?34*%tjhUfb^TcJ;_|%kr zX^%WEdryYfh@4w8*Wg31d?m!6+I#mt0MrPZ!OZ2Asvc?(9yF)@pdW>Hjva{w!M4#g z8;fAnyp487GXQ%agb|B(`koy2r>TZiD)dqX#u!^D!J&4<-DHS4kp+cpmD5dR6i+|5 za+hokX2`cSJ2pNxznJLd60NWd{q1!M+`1XUXnyCNhwzKeLm5Nv)Pn3Me>kEHI56Y) zIX0qc-?bc4LPKgl;JWn8p$ayeUr=yFnHdr?zsxDm#xqDR%OvYD#7Qre&M@0*WNdOz zUT#bdH63_;Ys1jZ{L131^7r`2?ic=qF4z>Nj^{a^4!oM%eeIMA0C@m5kR513Lc-Y* zrl1lN*n^ZGVVJzT>*9PBfn(F{y?ys!>OQz;>#G^h?w;YyJTu{Na$RcR*!xcN;j@=A z4)euYIqOTLkrDz+uj<*quH20a7d$Pf)cdvB`1x#}@rxacDdEs0-dE527un|i05|>b zkVSra{>4v!4AbQ{4*phO_MMaItkR{?*+MC&Xix>rbe9)eY81J7r^sI~(g@%3-5VTj zcU*&)cWED{sejEa*eGky4g9*&&M@a7$r}Z*0KHEh;!&RHuhBubEA{8ZfXc?>&j#v{ zd_DXTlBK^}m)HY6#SMi=E^g_{O*{=b$Ms9TP9GtEVEqSwZ^2fkbVP3-LOa$IbrJfa zkktx4-e13Ln@g&dH!JDL_htyh|jDyca@-48=E_& zDCDhK^~0VZO&EUMrG!)$`plR?$cGK+O^kC>xXvOEu{Qa>zv|tYg62uLOHfNAH|Us3 zE8Y2Xo0fKL_1FQ87|y}8vXomVx!*Z>8H%2C0cqY7^%ue@+@@?IcbTrxN)1vfnmxw^SJk}3#KCc*89!5Zyw-bR>Qoq;;+VX^Uw`qkA+wW zvQWg~tC|P%caKg?2PUjfPa?jHtAca7Na{O#?38doMbeyUgBmucwck4@LPh5B|34t= z=`fFLz%d#RSV5*jzn#kI7z4Oz<*HSeQPFDY(OsST-DKU^e^yV$!p=3uCP{-GA*U%wu9;j3q!A1!rM;xr++&<%NqDxxW9)5QK%y?_E#L zf%l*OE2Hd7uzA>M&(y?(*!uNl!?NZ#OG`_;pF0`+k53A(*e123P*2{0jOp(#!Q^^N zOG}uLeg_P)B~f?vckyP@`!%`|za;1K=Yt-19;a@EWbd6JW8RS(uWR z2gTf*;u(tlI9x(vRxym7(?c<0E;Hw5=j;eZ$RxOh$ zLNWm^3^*FL_-w+gLo0F;SlHxG#UmN2u5OTKd_i3rerxf%mpAk@_v|469QfJ$AGTSD ztE#?eQnlW&r}GK$Hw=)mXpmMU6R;l*2#LE?>=ND&w@7IfLlsDa8R8#d_U2NpOf#X_{4=ZpegnBI?RNQ$s zqB~H@X0LPg8cb3OS{c z&g?XIc7D(Zcbm|gHdv5v&^Z^6SZW^#A^z$Ej7AK*wuMN+_wsi4UqsJq5@F#@k z=jRI?2Q6+pPahCqfybhk8tmG2LC*EHuFefW2xy9Nb;MzkHhw=Kx~chIi$2+&F~({%wwSRPfIblvCr`Q)bK%=dI~+2fanq7 zWOq3!&7VJ?0i=yeG1ImiUyrx!IocgbrvY+emLKOX54E_h~`1q(Ew7#!0^rB;NobX(ky6BDt#m^OMC%mYkw!=dPulB z7B4o0xgGX~LCGU5J3f#KlTlOW5;0K;2ZeMv^%E z_Ilc!ZW4y7h;lc*z*HwA9HmKa^U64!Aiz!Tdfie< zVk+x6&1$56lj{1F-$H2y*iHhg2Fz?klGQQBbI*fO09dQgVEjRy9705vfO8sDgqIJX z{Wvh$z4?Zlop7}}Sco`FI9fJKOEU>j6|)TJqA*#9CJ7zk2A{@j?PDGU9{C&pMz8VW z8MG)V`Cq3y2=+yIWn$Ag%I;xBS8ZVzW~cA?(AOc6$hVKO0oawbVe=Ag1b7p|{a_O; zuC+)!g?y38zj2@PL#AyV3JTR2)()*1YtcOG12$=X0wPOowA=#OaeuQJ5#2`Z`c(0l z!I2UDKLdVnXilX9h;RposDB=1@vhwt<83m}&$;%7fS@+{Q7|`c34EjCr6-(1OkZf z2{=NZS0`f7+lh(ZdbRPh zX#Qwf8xa`V8tGA8t9A1BFqf$VQQ_YF5pzMsf3~P^RxKU(zv*ky^bRbnm5|5?4Z5AGT7kS}S??cF{^d0_QkC2N^wN_7{1Oa2cK@((p@$=|(-ojt z;G|@+7}|7tbT~2(x?#X>AJk5l$4LMQ^{0J%&Rv_9NJO%=pwcM-lW|5*I6DesJ|g#$ z0h&n+4B6xlc^LdU#VBzJ?%usy8)1k6AV-~~S#BzI_3Efzv-&jg_UnfpBdrd%M$t|l z;xc>SNClx-KJaj16q(EfD#LxHs{1evUM=mQ<-$gt9Uv&$yehjGh^5~U9NltQqoZYy zX@;Cq#*nK6l+_M=%H~w_f*e8=NcuTZldN>NZWF1S4G1P(D1k*9CjYcH2~(F1C8FCM zW@jh(b|>T=Uo-=66FZLv?~@{6=qI6sWE&1*jnIZLlN;T!d(p;)3?+o-N_X7j!!>ra zHoi^#*FC^L^MDp>pa4M49*EL!k7A`qG&4%l=HnRYwYecMKEf4Y0ooob?+|d^%YTV|4+XE9G%}Q067LGw=~bI{(ddg8SNVq=4pip6dWrC4dOEH zeW==a5xwOjHnWCkZ3~2T!wurbP)dc=g@_i5sHfLGhf>4qmlp)b9o-3V`p#f(jVs$LG5zEBu08`}LYU{-50g{pB2_y}?p9L+?W1lXzM*#TI&A#hui z*X1F|0{~IcOt+8v*Z0r1Sf2-;&J=r9tSZ%))g;8Mg^5(zB^)UoQMf|w$H8Rqf?A&@ zXI;TJ0_0gRoFUnGPq6P_Df@$PF^MG)YQPc6&-lItXNUN4&YqDsupS{C(;?xTo&9_U zV5SOGya}NVhZrUISwjD+!xY+p3Oek1r1g(wg9i{KQKU82z>UR}pa$DQ)GiW1zhoQ+ zp+P3)NXqH<91QYE(0){(#44SsN7bAtX(>D2ui&BE)xH9Roe%&#nt{3&#n9|@d%9!G zeE^b1wpOYEp>VP_1KKeTaUvWBRtow|2}#LdA|giXV+GCv*-VVQgHhB?$j$yi_A>Fd zFH8JDN~e^|k|!64`n{*Z%Ah|Zr&lhD8HPKH-7JAflcg9!TYlhNu}~RF6p^b9A3^#i0G(e!&?06R%%dmd0TF2yM%G`j9HVVKd8h+2f!0Sauv zJI8>(B_|G_%-xUinB0Jy$77~FK!hcDpwVm&Tp__pp6$>p$M6USUaYgzHw1}Mjx(be z$0sU!OW=4(NeK@gfM7eCjH$!5V5{5#?E$GP(ws1XrDIdSy$dA|iohU)?4=4ilq*hM z)|DZR$kDJn(FFkmJsBofOBfFXZi|hh(9DXHabLYb&wu*q@ZmP5u$t>j zzZs%PHGE+8=P!dY&?+FL8DHa6RFD*b;{x>mVc;`DPTCI&Gads1Pz%viK%%4+d5y|d~9oCkc5*7foq0<7t$vOx}_b~Ts%G^4l^uV z#&Rdo{G#199G$Re1wX$gfuE~eg0u@7uC8G#GS$q6^J+nvUB@P4DtLK9z89Cz4tY(0{#hy=6ff>P2Aih$BcH&TM6f=YKw_ofjQP(ebZQ$$dZ5T!drqy(h9HcEHL zoeR(Tp5J-yz0dvU`uOpqu=m<)z3-f3jydLdd2vro0sk`fWef}q{JV;B8WD$31m|DRWIIl5SJzir8KgsWU~Qq*z9z#ue1{=>|X%C^D4uvfk-C;b4GygcTK zB7Hd0vhL`ObLHjN+cK-wci)WXT3@&y!^IeiBUreG;lUAcm0WH(GxYMUK*sdI^s6tg zRx7PmW8qx7>oG2c?r4ZMz-wg@8#_q|0i zh~QUL*!v(Yy2%|3sHsFjU?Ui^nqz_Glw z_08pxQqQ5);cvEfBPHQ8EfJbut?z$&n0v>`sj%&&(qq|lAm3oNBPlKzpN5!}H0H10 zYSU{vvB57ExSYCQ)19Uo)D9_w>qpC7Ss&zF=|~dtY;%{F>ruL1#mIPSI{ekxkJ+j3Q0vo28*SVP{X(2vMm6n?gi`I#E|KW(=+yX%NO*5e7Sx`&v!V#&%K3#g42RyUq3%8e(NhDF0+ND`-g{{gJuz! zg_a%EK8NcwEeQg)&?tLHpss!=pINo?X?=EAn2l48Ky4Ntsd>f~ z-QEh1&R12ymlkj$azj0J_Kmt^5k;l3+Tu-v3VsH^t*C1I$+{;@EG(j7NBIVovGyY+ z-L(M$zJA5c1(Zas=c*2}yBnV4+KiNN!j-Z;mWQc!#OJ%x<`b+^uLYbOAuB2K{Bn1Z znF8cPZ0edk)2mPV<-8NVoA^>kYv&JlSF?4BE#>aq*?@o@JiKu6;yI_|gKg4?TL0sU zMqW#*zJUa()1x=(=~v<6@(&)6y3Ti6z+ulK8hP49c&m%;-)slg zHaCkS)B<+LJmnM=_#DT@f5vgEzarW$u+rDc|Y5oNEY*ay|X;RXa3^~ zEOBGhbp_OF^)70y9$Uo!2vw2l0}1r(`SXv1WUY79QpNwevDFJr_{!?*(=HExD=zKJ zH%QX`_V||lFh4Od@zOG%W&2ewuFjemojW`3mUV%cfPt_aDbxBI8pH~(X`QXv^~-n+ zD%`HIvAw+ehUNZyMWPC~zb+%Tkg_Fq2H_ov0843~fcvQSiQ(ji>@zQOvoJcrVdvBYbo*Y*J%2us4 z;PN|+3TqyWe}dcaJ=vefqZf~_Jv~W+B#h>>QrlS?Y7D}{MXi+2YlKZo?hKkiG!)zP zvfO!1`%!93zRBgwwt5y6IG3FzoeK9w^siJgPlxH5ncl5rh{tq@>8+Kqq#J3zJ#;27 zLqqJxs}j=u4=x3=s3v0Y1f2L{hlzS{wXDP>_2aE!; z?q}X%O)b3>PQ5f(^z?6U_9iS$^bK`-s48;sNPM3Q_>K>EvmroyH#>yv#wy+h24eht z%ie+@C_s|Nmg7J^9i$$Be{2gwfcV1!sDUbyfc2>ajG3w_qHi-~Lx?FT=6^}r4e~rH zFzkSp?%5V^Me-6N{?D(B^MHi`%l4Z)Nk>i+4a0aCwTtt|xY{^`#AuL5gEd2yt~-VFZR5zAsgO=3d9l4*HO zmmuLIXgiQU_lmnF-J~&iX{h){Uzh9Jq_l2{-QE3-IjUQx7hshNckimGZ2g$$VuW8T z1*tu2N1I*6P$Ef}i>{s31nIu#{r>zt6x z@@v=3U(?|~eg^#O<|-&QgqG z{FxSNjyse;DS-DB&~I{n9uQJ4k(^tNJ*ne6R57HI!DSZy^Hz;F6pcKg;o);ze|s?i zj4Uie85!xLmM@PtHOZNpnX&4Ay$Oq#;JrL+Lt0;7f57ZVGS@6J*DNsiz5F+t8E^+9 zS<){N%94%u(@<2k-EI=2m!Y1qaeBygAePCqQhV^Y;o5)~ge>QV?Sw?1sL4b)29Ngz|Pj z=ias95__MP0TJiv3sT2hB-!d|K;(G8+K=>`Of2XXynXApHx-gB6(A|^12Ok^s5rZ= z#eSkDWy1e3{QY~Tg}z(`KqUPg38zVn)5D3=9NlkhV-@bjr3L!s(Xd3KTd?0#&nXNG z8PtJ7z*1fzC7tD=-gR6rm$kFw*hF{CtW7n>a2usU9iLuZ-J6+idO^ZrSQQTh5}~sz z)w_lpP)HYS0lQp*Y#{)<(85$(qF3qwe?jS*nlb{36h&YJGKtFjb7Kf0pH(L<1|)Mm zz*0)a07;bHO|RC*oSQhfPgzv2;*Mgc6OD72o*eDBCyVs{El-v35hYD8w(OV&h_0Ej z^*vlJjp5Xb{qx5f$WTkNh-;2cF$*pQmx}G6juOy^7O!xMS>_@ zw20RR({+W{?;qwqYHDd2IXv3xRgYnN_;P=9-gSLi{)1}Loz`gPp(-!ePcxyfU!wtN z%4P<8H->lKLwo_~woEmK@NJ3K9&O;lx}yP#XCO~A00OJF`}L^2Rf$?H-(_a#3T)0` zo==y@y{Xe?8+6NN1XqQgVjuJlmbYMPUqxFUtI>8FH z{0#~^1-IeRfYI-k2!{E?)!KQWj!5kzpc54iQ-s?52EL$~ej5|m>hliEOxPmUSlO2^ zUQC5B_)h`~#c&xUav4-yp`|@4aL(>4G-;%LU3;*=?(6HTPhN;28;q9$3Ai&;<9Dc0 z>yNP8xnBfp)33NS%3Unt%DD}z_Uvm@)g`t`Z{0!wWqNUOk+&v3o|2qHJ9424Da^28 zm9z=|aJPzzipH?Kz$)KR82LtBCS&8V_(_`Ty}*j`J%T|!gn%wy$dTTd%l%=chrQ&{ znk=j`dSkfs&5(=c?nK5j87BgCFMmV0j;`Hp$1?DLT3_-w75O1FjIFCdm~AuRABA$@zg^wYhrfD^L-6^IflAqQG$)4EgM zv#P@Lb^)Q=U&t+3`Qv>5{(Wc#srjvq9mN3h0JLvF|7UWt`T6Mh7@BSz3NHQ0A*-}3 ztpdXx@ehJE07#onB<(%0==oz>G7^+ zk*R$DXFUbT2)b#-S5To4pbZKN!pPApjayj5Goyz z3=t6#gxocIjL2O<6aOCC8HAsQQSk+z93S?UInTJwwY-HbKQHV%1_H#*`|q9|Cxy?VO%X1o53Db$X8Lv+_6JR;UaTzRSK9-b}gw{08u-e;%@*=dqR#4seZF-&oho@`g z;lX?Q?Ae9>e1k>aaaiBVWpoxmSroUCB;)Gjay&d1A8O4Qi1(c=rMDQaQ>VaTV}PwE z1Mx5ST|z{kfRjyzL-ZNKJI{Pa7{(O3WTd$?;M8BxVf2T@?x^cX)tD%84MZ3;2eUkh z@#4h(+oz|uE8X7EF5tYAp?+QROpfR+2h*;1X$8Gd!V_pTQ_;NE> ze8I?5Y{H7Av|(Bdh|^ZXrE^G@ox{33_{xCi6zA@VE*Jb8u2|$WCF8$0g>^#nqG6S~c;KLNnG zug>)&Fk%5c2Z6o(OHyZH0$kkdz-OVYcAY-0l|Fa=JhTj7cWnj>r|jqHD{Ylzp-Dxk z)*n#5WQ*Lz5Um2>@vH5?YuN9J@fy^+DYQYVPcPyx8Rb^{>=M(`whtDWAvGKaA3qC< z3PIOEy7c+SzjNwelCf)$R^?AC+m1WjD8E|e_BUGg5afnd_g;qQgi=R50LbXgE~(Pe zZ&1?epJH#$bOg|jXXuw6P5oV64HyY0T4BO&4RB%>^E=?5nwl#0TbZ0R4w=XLGf-gk zvX3yiy5{s~Q$4P0S;hMUKhr!X3(I$tPp$9~%UD$q{#hQlF1U^l^MizjmhVVAq(p3- z`uq}eU-U>73RfGlE1?m(Hsr&2m8O5Jl6t27l~}MVniTe>N21h9a{T)KXE4MxT^djYH<0@OS~+ z*hcXVjVz^GuonEy5cx%F<04LEMlR#f??;Y|ktN5) z8zaS55!H%-7<) zgC0)psOC*ewsfkv7wvfevw&I~PUyq{kACIp@P+I^2ELIBI3aE3x($+0-=~LWpw#Tp zW`ke``sFtjAy2fbC0}w7qGuHx6_HO`t zbGJ4EX5M&n3gEOAXbPpIFX|;Fh+r%HH7;{M?|;@6823N4rxtQZUZ^@w!lp+BI@TV? z#u<9Qfb~TZ8oFO=qw4ECJdvPZxOBsO>@&!#8ar{GxPKFYYJnKfG@(rfLe#Z<8J~W@t8DRz<|nt zLqMRmF5#8CrDBuwFqa&33rht4vwomEQ`&$@{{eL@F-=SE0uS~HiyFU{S=n~P-t5dJ z5)Pk6>YT}KCE#%8vp=E$5)jD+Fz`FjNC%(ZL=#HTK4W3soq*rN?wsKqsPjvn?(Bk4v7E}FAtKzU=$6b>!*fXY48OO*@P$pF*&|R`_vg3%bU%fg>8)_L z<sszee{`Z58>f~t+nNMi^w z@D4i0BOo`x8=gu(y*PBJk}MoWFX8P3FosY+s6>M$_B2orzwPQktpwP!f_1TZ*_bdp z;IT4VzP`IVUp}9z>`DN_R~-xi{*07zLj!nSTs#>TdIMqkA2paksqBK`!cWkAffOp| zJorcq=m^O~$J+m495^;C_Oa+9@!@xwKpyuFHEE5UQZfF>P96gN)aoTLhjXK()6rTDX<>)7u$2n$d4p(L% zU(~v`mxg*xYNlr*q|}hU>#NP1W6q6$N*hiHN;39G2x|wPMc4@)9AFZX2eh%J72CQ9 zUP9cP)CXbdSD~Uo1nUV{qtvX{w2}2OhLMk4-?U2=J&~g}McO<9np;J5ES8 z>#rv8S-AkgFL9jc1U*m~8Xtf(>cPsbNq!xPmy~Ai@_E8)Rf~_~GiisxtV^J1!$G?w|+HvFel*1}8F9TZXZN7~a6-EyAIsTRz zukS*5XsAM-A->;XqR{C1+4j5B-@}i3GqK;hP^stsqBU%F(j~uJ^>E|hCn#cbM_!a7 zJ;@CizjBC}R+kdxvr#$!Mvkr&g9SA~R;f?;tlCRj==tKVw@p7-dkLD5xu?%g-DG{C zZ@Cu;i@rNl{0>V)Wur_Zom1Nl&8%{A8p~>N10+P;0|jY1OBb;lX&mdmhZ|}x$q3R; z;p5=c0crtc+$%J$R~g#jO8{jNn%$=6W{Xyf54H0fcwsrkLw*&@(RYwcivADL%CriuWI{9ri3g9l;| zG+QFP-+q;d{zoMfYgJZM#DV=8V8CM>>K-Zv^%Tuzb6RUJ?!Hj>PChl9{k%nG5XDts z^vHST^d;Dc%8Lb6=LBpUK0Ulb zd~UUtu-M8+lvlZ%78zehU6&#u`JTd zi!Wzh^V_vp^r|S$JR5E^u@?@3unHS0?!RYJ=7j0J8$4PrL6g*MLvSYB_SuhIR86dt z*o~Lxiq9-pm;7idME37iwIAAXgi&LCdt9F=;Iz$VH~Qyq&KKH$ANc4i>ehpgrVd!i z@i@B^gkqjDZLz7ZIokf+ED`%%m1hd{PefeXXF_pYx1am0ZrkbW#NRoS!t{W}jG#_{$y#bQbTx2hHOVrsWL_JAg2zo z|510o&L_eGbZ0Fh~=^b5&cd z@0zE9wBzyOeemgm4##e) zcgOo(Z^_^(yXY5Iw9vtZhT_0TrFE#->Z4JuB!Kh`kXjCdiWul*MEypg&jIa0|K$$6 zV4~z6IjmmmP5G0fHw$S2YOh`A2R8=IX#b23^9k0M@H85WGO>4 zj1S|6RDu@X{|p5FO%&jtJt=Wid}}nk7bZ??Pk*efUt_(B(Rg|~p?$icycztB;@SDlofD1|@2-C1 zc(`^BnQ%kbDE1YoeJYT1ubYfWz&$`sUjlGB+DrABe4{>jwEr8bFV#;MtW^*)tbgYa zrHHyugAj_44~V;9U_>ZUet0L*K&toUnp665)cK2e7)Htto{^k7E9}Sw75oN>fC%bx zhC!tV>{^KKu%SAnWL^VLJ6-R%-|ii~aB8PNSMX?aOb1Lkgc@+KP*eY$tbZzTHkDFT z!X`|t%sSr76p_!6#m>>~6ZhPVHaDd@*px*QTY#9jooI~hVY{i&RSZM_p;0**j*e)= z%EHJPyD^`}V|~SL$dq2l-rH;wr%3!C#FUbdoL?SJIGu2(sM@99`s->o&;LK)qrO~F zb2&*cL6iD2>6)9IOUOUW8nrw1r>;6+la!YJRZ~4AXcvFSt(a#F_z5E;*aSqYw#iQf zY&B4g7mreXI`#eW9xPcpQ=j3zPWA98tNo#eZy;aar>Nbw&Bc;1Dg>S^y*SO&s zO>;hq`D`VokNpqvANN7TO#QhZFVfpfbeBcrtY(Zaj*3w7U?d7WO%cnucWrNh9fhV+ zS71p{Je$d(z$lS!DjzR7CQi?fQ67WZppKNlP4WXQ-inE6`0BYm7*{7jXaKba}^dI@E!&FTb@cu!s~Z@KI^i1 zF!%k7lx=`Ai^*1@2*COIiHK=4pCqbh+x+W{;UUrR#>>!7cy0wE0E(`FJ1>nGiS)- z{u$~$sx`k`JVus;FM0gCiuJQP1E@{kMaU|rEzj(1Ov`7J1!3>sMaP4;ipO-iD=l7? ze^`mUc7^1;`@(HwV{{YyQ1lsVxtsK!33Xt@6BaWcJrYbPbcm^6eVMz;IKQIMgLAgi zzO(muhA>B0ptm7*Nx>DV)lBw}J}ZfQ@!@L>yspshubR{#v0I1kK$km=88=+G`G`YP z=IxT|zaSTcl2nscz%70vOv+6lb%fzM|7q~8O6FOB-%Tnk6k8Osj`Vt}+nG#7@g|hy zEbF4a+Vos#XzXxzHCW%|b5v43(T2DW{CB%FQd054-A98DyTyzHU+S+5pQS^zM^w}m zGOYbgv6A^8n3~xQR%r>Fp7P>~1-BtO@20(zpBfd}oC(4*IYO2B4$+R06=D1XfWN)z zPs-c1%U#xfvR@&d{u?Ss`;U37v{$(Qst|w~Z>D`GEoxJhtkU%EzvXo|H8mdO$uVMp z-RjPCOs*VL!e^xaz={tM>*5oP+1+hfxH8k*fAM9DP1x`&V{Ik^ z?F?nQ^~SFc;R=n!CK}&HuOw&iEr-I{B2M4DMRaspD@Q3r@S2V< zoBP41*`YGI9>ss*Re>T3#(T1}+~HM;;k8jWS`N{y+=~M|PSL}Pa&5Vk$5%L6+@|FC zL=3uz?n1dyc?1U(1<74DnEZFgaixyU1!K4g-`vO@BrAA_5JV<1CB?ek6i;htllKg3 z37$NGsS3|y(hFE#qM}5lUq)%i5lJ6vL`VQA9=mSZ@Z96gJZr}b>__=VE&WyHxPA?LxsF_1hgo3@7-~E7Qze`hm$J9o?gKx1(9qEnVIC`zE}wC+coP z_D7qXl@nz2+~6}{;OQmGgs|N<9^)Om9BrbL!wH%Wd>WUp^0@Z69EM%dSgSCxUA=#)svLNn3=sq*`ib|%31M2YC*$j4pB)E>II__ z=PrreLKyhC%>J0#y0yN(jtq7q%uG!&U@!^f=$huVTKKGX9_bshoBwTF0P})H+h|kE z%;Cx5Ud=YSbCfyae&FK(1k zlcT48$n~&*%LazwE`NKNL33E$TL*HOf*1jjQNn7~=Ih?g&O4~S!1}?u9)w6_V1~+u`ALml;eC>T@hCEWx12 zzb~KsHX0MG2b|!{!3x9UI6p*}bNLdcbo+K7vr*2Y@V4InlU7v;3I$^Z9Aj-SCbc}w zZSb6^m)M<5pTv$4{|To9-XVNFSL!z&Ll2kYE!kLh>a!&ZF z3r#F10+LNHfZ32yKx(FlP1R$6(@gwPTR3`FE6ZE+4V=(;{5Gcagp?TD3)11#2t?p^ zBS{-d1`TMy$@#wAq>*z*<)$Tv2cHJX%4N@hu_$q_4NA|>iaE5q(MiJm)6NNp9*7_IAH8*ZKGMpqZ8qnjS7gen%M^QBuPIx}L)D zPoctRyulPp{*_FUV4))e=nTI@r!@xg^eAqu6GDo`lO1(lQb!x-49doS?Rt&CmP@EfD#rzDue}J_dY{V-o%cJ zZ*ItDDM4b^)bN;ISQ^AMsPqPODabxUQ7ZdsIiM|@GZpUez>f!Z>{J+sLeI+g=rz_$ zkMf@t)C!)eD^)nJ6t$$gSj6*RIyus8&R1ml2Yuf13XQ<3x-*4_Wn?A;PMKv7$vuLWNXC&7#Vp-1dzRqCVrEY4_vRMmR0*Xa8f<$8$`5t}EHl2?dKc1VaK&WP5ABQXgm-L9Nt z`Q66n8#3io^`0ifw@YO4Fw4JrXTd92E-BWeuueBEyB`nw;B ze}?5`qxpq3dVWA!(E5bRuU2qbd*Zcsx*Oj_9aSAeb{^8-i^d>riJT>%v>e-{4 zQ*e*Rf4cVpPbKjJv(oJ(!PGD%xt_acJb{>G>Ug(ltcJIa_veEY zI8{F1p44O64n&>tA8%pusc^d#Oz=Dy-(=JBM;gNi)u&yOn{MXt?ZigNx1p}xiAECj z(ZP*Ubq3U~!A{GZkm>A zA6bp)@=OB*Hjoi z?b(e4tD7=PR(e4FAX>*bV`QtQlxrPANO_gS5B%(C6kBR{HwodVNuj7`NT@dX0L4Gt zL6461W@nhnYnMmAXVp~1!QXas1C{aY=6o(-Nk2J^wjx?Zz$_RGE_3Fh-v->ZrWGM_#Cp_*1yK{t2gRJX!E~sXPC%>AL}yNWUqRLn~k~x6Qj;EG$K?Aq)6Cu zaatB9w1~JiFa*>^Gs9-jzCPnodCfe=Xcg3nm#`n<>oLboT#f?ehlJ!m%SzP?q*!YnKo17Xq+Rh^fq^Q+?PW~Ey?PyVAX zWNm;Q{#P!=pxxei$v{jdtc#|069kI`Rtqe|u|LC~|D!SgO-(3+lT7alHS$=4ffsz> zlYLr7Sm`jh;ddNQzC^-O=KH_Y8ib$RpMuTj3&xa`+-c;+C6AnGr}B{4z6L`foK?)U{95m5_u#uRcy(co&F*;O|mIGCE6 zf?4QxBCesbs?AO9!mD7QwjBCmu~PzmcGo|@t|5l6u2hK>@+xU*=?hp`S=NL&IEAyg zeg8|WQP^Qs`6Im;nx_sxxtx755*hJ0XQMO>^F9u7S|oXTWXK&~=Cz9z8$ zn1D#X^k1!s@Tg4ln=pO>=<_z#wl)FuL|5Bn3qWgoW*^m_Ja)iZn#b;vuySDQ&U)n~?)+|O zzW<%jKC0mY)Fwri!rw6$t&jeb7Q-ZkrmaV?ZYjTwk(s4YdKjUe3CJ9lwnFBj&W_nsbRm^=M zrjiTNma3x#ThN|&ep%2Cheoh&Z$167#FY`hl=kNrd!Pr6FKvhaw+$NY3>Ak7Lt3D=Rvg8F0o5M{Oh@Q zRrnp1X!yR5Dl%TJt72WAi@T;k01Xl2w1mx3H?_Jd)p+g)O>H}1Qs zYA2XD4o2STq@ey()Zf&A6EAS~X?&#se+6`06^p!} z>F8n;%FK8E0^r_g4c|!=0F_Ezo|!TF@2E%bF!;wDeQMw?S1Ld}9#xY$2Nf`k4tF45 z+Bki`78+ONNx%wJD&fdfuzVBZfn_4!V6S%LvfYTKAipg_ESq1Z;;YCtJso|tMlbAC zH#KNkTx8Wnk61zN#ji0&U-G@7lKwa6KDyq(v;J^Zc6A*6s2&JLJVXV|us>L{LoW&T zo~fc1dNVk=bapSoCbr$@7^I|7vqZj-4x^kfFdFsjO=P$D8DoN&==`XNqL!>CB=;sx z9cTw~>c6N)dd5r&_<3z_I2Mv_xhR_5GiB zGzTtI>=+v}GWO4wu;QPbu%@xGvc7;*SDV`dMwQ6Y4UH`HfiAiE8c9d zdpf3!zjLiRhp=3!8~4^DrD~A~ZDs6vxCSx8-{;rZ*x2jJ3Xjz`!2n9}2bCwF!F>;x zpo zAQ$?Gm9cvzdF5uh_pa>iC!7M5z0S&={G9WdO6xTKC0I%7#STR zSKLuF6TER8Y;0`R>a2{>ew4vFvybvnnS*}Qmj=J#(t9hi^MHe1xiZl?@1UJ;7?4e_x&H9i7#tXf7LhS82u z0KRfu!}oC3LjfDp{O^;G=lK~JKt(!MEDQ~Oj~u3r`Z`?F!Ep~8Kj;-jhKK#$BKPL0 z-u`}qa)k8He?@7mkOdwX;i#h@Z3m2h-^_W4+n@JDzr5YleOcGFgy z=cuLm4GYR!=N9_-UX72IPyMI~~1F^2}FnOfvgh3M=qq%hX@)rgnhtYVjg(1Es@EXk5|Bz#9 z%Qa%K>&!P5__9W&BT z)7@=jK?BX#urKdlrULiJ3Wq)|Nia*=C^IWZ3J6aCQbxan6Di3dXbX^%+i`wefb#;`?Br zf-`wP-~{L7*N9@GahR7P9Qnh0^BCauvA~?62RVZ$;n<9`c`TY=2%B(P$XB@L6*;DH z45xC>`@58%b-j3c+Or12Y=4Hk{(J?$ZBu`$s;J;$T_#m@t+#Du#TVM#-e!igwE6%- z7HR3}>7=d!nBZ*Y*q8bCSU>f{*~KlpI!=!76|*#bm${8mwZ|yQT@xDMRG2Nhg;Q<$ z@9YZ@%D7D_jE7&Q&Xw5s**H2Reu9pi#H{4&Ab z$p2Eg%ae!*m^Kj+wG}<6hchH?>;+W~%G}jWPtIfi0E0Ymi|-1xb#fQ#c#Jz~kKjna zQtO*Rm${&V8s4tC&gG#&kmSBV1HuBUkOg-6R03JKJo8h3O5O`_K$2n7rO0&l&p?;% z<`;NjG=~nL)Sy8v0T?b|r0DE?g;cKRM^s+kqwt-ML_`ILL(BZaP^ks|#jCcWb(Tu( zF6osR`^=HqRk-Q`eBK2#(H!LafY8yz@>+%iI&Lbr-T}ZdM1R_K@f?iet+j0 z>8MNwYj4lYb=;xaJD;H!+BNFNBD2o<^@F|m`6T|<_;`6aCcR%E)V}ZfW(yM|Fx->} zJA7%Ouk%^4&ozVoE_u)5>V;o3(bnwe114bN4$Q8{*M`fZxGUYk z0MTq1UG!jEW_L`@Oiulgsr!84w(8MiG6od$}4r&r;UrfM0w$(@G?PO9s=EEZEvQ~zuHT`w#G|S_e_9?t3HLw z+Dbsq5eW2xNl2X@b!cC_x80W{4)<~lt7(qSsVCF@?pN6@=t)RfkzpYe&hTJQxhgn; z3rAkU%gf7M8$YPR27&@6$20=FKdnkk(m^z;^mcN4zy#e6hgK`v%uJw;qoRQTpkBEz z8vnYwiRKTy6P|7;aaK@GF+pB$T{xREy7oN}r@7{67|)9Zo}f<;CFoLML0dp#XUg^Y zb4|Ny@MteeVG@*9d?vV?3jh?++u>C3BM}-E7^D~bQ(xbKO+}_l}O5)OR^RXDQ2@wr@f zL+AE4fpE&KPp7^{HbNOmhKE!a<+TdFpT4*;IeWJl#?k*J&K4mPI7H~oTiA1c9I$sy za-cwVe*@e?U#+M9=D_WqS;rok7C%`%?c!&96qX|4qru8}t~SmnIQ?qZcep#4Zh$H6 z;n9iM?>w86)6<e{Ba)oRT=B9vOVSrz#hVg116c2}A4pf0b<##x1 z1ZG3z%p91a8)2AOHn3Wo)a-EYN*KNUN+LNW7~hbKMQ2?$Y~(@x&5Dbc^b=)Pin$6S zIne9YTW_TOf-WD1PtlST+%n@;Xi%WR1p?Ei7|zAkvp1(^q1UK`kwXH5rH%{%$J-Qe zQhjEBJ}n#U^Dvfd@11(_zN6gL(nRkYn|_6P$^KrQo+DBbh*~eivZ4Ioho69@9tKih zO1J;^hQI+EIC`@Lq^qZnXYv*InbCvpHQm$ZR}yq@fv=aCePqS&1Pjo`Kp=#bOaD(o zqF|j^B<-uWreDq#w70E{?ZM&A8g{L7#t%Nq^t3RT@jt%s@kqRym)qgp|KSY#KiLzd z!^`GnwPa!BFs~|Dz7j-SKeYLSBiv%N%$ao<&a0`yMD^mGn=ZJG=?$e58eD9bYn$YV z&z~PU{w2Fqxoe0Q(01y_3e@`U|IPGeR}ZH#bdYoZV7bzU9}Hrz_1NkE!{b%O$qg#u z%wdPn;PAKWHq&x94MbJDX6(J3Z_IuFccdHsME>%>#+RBz8fJ9m4F z2Tn3ctCbjnyY{~nLfzPowgkS&m<#eR<6%Hkcf30@QY}^^Df!p`fFmhRCH;S|QtVJU z;^lJhrA7vv$iUKTW7eemojfvogfJ7fqC|ICld(5MUPCY~7@L7#%M?gCQAF`?oYn2c z0mQq89Or$jWoQBp#2r^SGsrA1KKiu##i;qb8aToBmW4J^6Oyj2MdDuKFtvn4G5#1N z1gDhXhf8P_8cR!_9=V3NUcVCtV3F#%OkK6l62{<|Ujh!(neX+z>QBdaAQg(3K+A+_ zD&i3DH3=0iwWV*`8!Y zUO84FLSBi{@;YI;yE`@X5j@ojGOOZ=qrt^{Ms(e{g#cz`$=}zudeN^Rmnu2XNRBSS zP?<3{D@f~0Hm9EP@K>4^s8X4gr^npjnko7GU#taF;dMMhaGJh6SX0_T6y&vYzw_~* zVk2$@cHQ4as|a1`JfkZ_5x-Pzqy0Gaae%30$fDQ%b^#jl4?~`3t$1l7UAdgN%=N12 z<7h{o#hzvkk5?2zo_AlpR1*2*Q_P~;PBW-)&oeb+wo=po{_giCPPjjZj3BKlJ$+iB z(i47G`ALW1z*e9L@vQwdh-{(gIhj;MJ$SH2g& zUxx831idFk+=m=38;J?l*lTmHrJY@>hnzZ#8HR5lqHh~{;!N~eiCNi&{=c?$izUFQNRx#+w zFuuP?@BrZtj9ed;t}KeV{m>_0dV+1-coDp1XS9h?2YyONQGSyg>eMese`xfwFxVEo znvak$h*km#p#Q4}Cm!{MB%!1h)kJvahi5(=sF7_j+1Ku!ZG};ml$1)+MRqM1=>r+z zN51~l-SCHe1jR4Z;zQy zj)flN{Xsegxu!O2f&%k=*unkz4l)Xi%cNJGk5K)yUFt2D$;4rV3H*dPd`$_xu^VF1 z)*f-V8)8t&LC;rfwiwZ^Mcnll}f=;c%Xo!peab*_Ua+i{|Ril&5eA zLcz&%DNyG5WNyJ#wx7rh5`^C@k*aA)<=EQ=hE6+qUU0T)ZD%BsJMFA)N7;d3Ri@tk z&S~l#c+k1TJh~)OUn|0s%4t$F(M``da@@KI%@~KlWg5X8Wci8O0R3!=U6_C8VA6@! z^?w!`*89p6$DmhETyrvfB*oe)D-9qPnlt%U%zcMrYuT2(q|#IN$vLNm-{G6x-S@t{ z_p13XqqzrMj))Mh_tA`!$CU*b@abV%Io~jx-Eh6})xmxTyn7B~lYj2Fw9tdIJogXs z`N-=}J9*M=wV?6T_sH{h*Dn4(s>0}KSgfu=EPniTXkcgtGnjB->&#*4#)g`k*x$RI z`v^G*P<0-r|4%Qz_WNI6JXl1=1jV-K7p`q_vc~D<_&jyLGT@*!v?-e>V8#1y7->?4 z&3UbsCMXmEnQ^cyREl-cbq-4ljw5PoFQiI+Lm*3T6wbZG!>I+)J|Kqu9In(b%#MtY zuV@jnIX5+ho=IL`e-au>bN&0-$HI&2c9wtTQQ^^Auf#mcCC@X!eZwN1um919;Gbu2 z?|-IKu$^F6O&VJs{J(lT^Kh#3zK^ShCdpFCkx)u0qYknqG$Tq2tBLE`md&9e@tqcYAXQVm99;GrDms+*}AV85bzND958IMxP27KntbXJQ_yh zSb6#`3lg25TV(ea>JCfgH@xQTS6%Gp>L%>hKKbSCaTbQ{g4l4m#xc~?=EZskp^sa` zqj8xN;>bj$xy=txKaXhVhX?H0oo#uoCHAuC&j0d5N|9MWzhP3&wZ=)J zqDm?%Dki?)C1-Abe0VO+(B#ELN1yrW>QzkofLB+Hvd+PK9hD?TBUsQs|I&YG=tGWo zZp+l1>T(IA3#X-ASttPm{QOVK_K#3BIYs(r#rH@t$IqV|7%y5`Z|GkQR0wbao_0+ z3(-K;t_r697{(AI#Nw?3XSLZ35kG#0UXX8tzoeW?=J4R&v|q>deEKACR!Y^! zMYnm?awH)3i#2%ra=xc(WBdw1%7mOLA*j+e*)Bw<;pm;sZ(HMvf9rp>1qvkHN$xBTN?0w(TygGg z>Rq7 z)}|kRw|;?l#k(gH`UO9Onn;k2+T+J{f&i0_QR?qIl|QkGc=YNs>mPC2KOY5OU(Pz2 z*0$C#mib5!0V^pa1nDFx&7QSD^!v%pKOthMvQyLXuc6^blWlQoV;;k7?bLR@c1mDM zC$4`Ky)7W1G$;FJJmof0GT%k^|0i75LEj~Z!g0Va1Vf~7;>mh67$U2D^5lu+{|-bm zOKy*H$5$02-+l;e zo04tz;+dPqcM8HxSv(?lwXgfdSGorw~tFQHMM`BmnAfEj0eS7hTq`#9?FDDb+0tn;@ru ze$vn~J%E2Oe);jqJX^0fI{?(-y{$vtK`byZuqi^Po=NzYcoZ>A&o0;;j>+cqr-q>i zeEK0MQUY~H9t`d(#&(O)*zueJ>V?*{g*HwAjn<$Trvo@eOP`@7n!^I8qvoXna+^K4 zTSXTPd^5}LIT(i+F3RZ%It6qC3sN~An4+wsAt7>T#4p5ir9#^uQu!R6fnpEA`i#mg z0ZS=jhTc8~@FZFoa7Ti}nSulmf%qpoH*#}lLw*AgELsQqI-Lc7M|0PS^?80i@fh4b zL+$8dtgLKw4oqSJ9mBhBb~+s0eoYk?M*Dpg6F~-D43MWnJXANPZ1(+6P$tOX2vPIT z10Op|-7)Z{Uy`*ywCOm6>#_rABo$0c{4&M&l z+M0fY_8tv(R#w*3hL_YFuotZr)sdBVx3YwIz=?M5QS|FMdiE#Tp}==(QAoVU@#pteir9}{%yKGI8pi|#iq#Ef zEF*r|;jw)M*@=;xM}|J6h}eS(T3mksHhCNqz?2<~U9 zi|npC0AUn`pn4+UiM*jAZFVe+5Plv+rGo%e+*%(WoVy1(dEvhPY2X3TIM9iY}{b@fw(%B%gI#0H#Z9so{#nb?Q=eiDFkl2MszWc{YBU;$3*O+YlFTD86T#z8FV+Zz%@Vb^{t zDxqpQFpRIiWq}7kj9My2zc#eo+f}D01ZduFcLMdIF@FSMwE#s2ESs)h5-5CT=-lbF zbMfjeT(iLYjfzj~o8m>+o12h`Y10{gOnS*p0t|U}b+VMfKX3#@f(U-*CA(U?6JXinplTq3IHBEOg{m@K z&hv8;yT@>uy8D_#t%t3if-)_Hp(M82{oSv^z_?ga^wxmgCW$s6@nf<1`9{Y?rT2Lo zWW`5rMlW?3crPLFBsH}#{!d`d+=dMrlMO95BwDJ$fIUO^(+a#Gw$M*<+O8fd_ig+o z=EQmKQcNUR9_XTeBcBTTGN}^?J>URu|LomeVke#BcE)d`F|35KFW?HDt#z*o?gStS zBd#5IEGipsh}nPJarw-dGuyYEgCP@Yd3KXLC3kYm@kL1G5&a>nr|@h(Fi~Vaxj(-tj$$3?%gE~;o|Ef;7shNZ0G?B1WeY(%egUIN zU>D$J!g3?iQ}%!EfB12mgfsjM=!if@ka)K=&)*mPu&029fXs7_FLN`!Wc-Fag}SnW zJH*4ph&h#CKc1`hAYc*Do8cJL8uumSpY*_42M{JI*W$p)wgn)m+u_Wdh<(tr{f+h9 z{rax+sC-9KiY$!^EW8kyI*p|PSXq>dW0_yG3m7~`lUupXHv;6V+FE}w1*3Hq0o&=- z7Kk4N!o+Odx|6loJ>ZPsStfuw)`A_`l8>q_cHFq4l-{Jc5)dm=t6jxY#(Tm0-@2tT zdCC-7U5_jL6QA)+%>5mk(9u4jZa~4~e@3hMb>+S9UEgeP>zCD)O9uBmugz5`FE3bt z=J3ekoh-nB2+fS9>K^E-(LN{stv`RXde{an57EUfJyq6r5?yU96IfjGsSa$JqT7V9 z;P4eZwkWDzWIBu$!V4vvonk z$Y54tMk6(swRCC@1BPNT=(V}qPps>5&LnDY7j`G_s}T6Q3Nx@yY> zj`BIVC747#|DpTb{^MAzWw2Rmw{KShAngF@v#-DqaroKo_>g^|0Duns&O_1U^M}@! zxO^B+Fxmd9--XA<;@psXa6cBvCA1!5ajk^qh5CD9hy)r;qO}R+FOS$HB&8R262R7U zzRSmC!;1?l+)sZQn{4R}5A0N(mQZ%zdE;=@3iJrZP=GNkDgo;vo&RkpQEKw!?WF5m zI9wEKPzyelHbD%zOfeQr6H!qR1MMUySQM>Og6QoC$@Y2RR3*ZrPMEE(URG}jad8u( zPc1Pn6FBb(M9O+~6Yv<8Ev{#SA(&@CW2%mR9Mo$Z)?8ll3cPsFtc~>)d4i$C155T} z0VKLwaLDrK&JSZ7OoA6;At3>Hn+Ls8I83uFfVFI2MO6e}5rDTy5DbRC4HSbIz@99e za0NSDP}Ku5ic8MxV}l()-kM=Di`+)_I`A-T>{U5L(pM@x6$1vYo&pzq*d+kypkUDL zKLOGucuNp^Ay{GtjPkv>%%YSJ@YuVWpPzk^=hy-_5)Kf%TuN>qa9hC?Cd5NfEWVlz zFMSqqGB@wfa-6w^!;Z)TdYPUQ;K&Fjp67I+)9&{RVgsnlLX_L;Ud>Ct)tEaD*eV^| z1mO;V%wIy`h_z%fjXDH_@QuU!GT;Zb!6SA-<${4~oi+*6LR$B3QA|Wa$3){|I7UH# z8E zI^bH1!7jBlC^9IRI1YR^ALTI`jL`qin;yVcsiY4&Ea>#L*Kz%xHO17yc zvUQjdK%ez{Hr?4&h*pO~Qq!jGgv$7_!)-$^L@9t#Fb<`n=ytR9bW~J0!N3CDM1+N9 zn|Ki~5Ewh8SBHaW%77m-#bibxz?uFuOnUYDm_^78=mP}{b@AetPQaY)MOr`!2CjWj zr}qZLiUIe(xGR4&AY?};Rxku?E?`kUAsetB_$(S09#Q~}>lQodQkG{Ud*9z}$0Y-^D z?O!Oi!&C%=bUIlEfLMm`m*K4510b$Py zIHMWoN}q=!H~}6n*)HE4VT?^cgI)H%V-V`C18V#HMoE~hRTLyZy@xqUZD6o9xy&j+ zx^73Qu(i%^UFYGI5Z;?0 zN!b|V4q0JX#LU+zb|sMH18kqhWg*chg3ZiA^$&~g25wamj|6RgA@=5Vgu>zmPU zGHRHmr79syxMr6hu;v1D)>>T7@aZR7FK(alQIN?spil-l zl09Z0G{nBlNVC{)>p=Dn>BF>X`VX-c4z|sL;%p_Gy%_t7t>O&Bf+&Kg%J%+%GrfYt5^*WrmLJg-Jc$d(p!Mk7)wP&5RqG zLUe%=!V-^`K=_JN8kio~ z+0;abA;#7amk1%CzP%b-U6}B2h19Gz7hom;{EM$%$<1IM*ntaBz(JZ4U2KZA=3YyE z9|V)d{TWDrULd^tDC~Yp$wb$)WldNCT~Tlkn2n(r94IS&UuT8x!#DRQyP(9AHTrFs zvV=m!>|tM^#BBylaefUHzy|K>?tg9VPDPs< zj(Z8^M<~nM`S(g==hD&1T2$^Gm7yP5UUvnPG-IjvN#wr}dvj4$dP;C&+OHvJr{LEu z;I!O_m*Q`D_~c>I`o7>QDtpB9n3Ir6a@vwIGArO#$Zi8~o?%3W3$q!GmrldwDgarx zSEeYUN|f4gMMP3o){L%JO0Gmv5_MSl8X()RN>7K>txTY5fMH#Xo(_Edzg!{)6$-w7 hRGa<&3^k);%EuZe%swjp9Cxh=nVFa`PyWq5=wAr8Z8ZP@ literal 0 HcmV?d00001 diff --git a/pxii_bec/macros/luts/bpm_calib/14000_bpm_flux.png b/pxii_bec/macros/luts/bpm_calib/14000_bpm_flux.png new file mode 100644 index 0000000000000000000000000000000000000000..4c556f2768a5c81e1cccd26a0d19e2f52b25dd54 GIT binary patch literal 25792 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 literal 0 HcmV?d00001 diff --git a/pxii_bec/macros/luts/bpm_calib/16000_bpm_flux.png b/pxii_bec/macros/luts/bpm_calib/16000_bpm_flux.png new file mode 100644 index 0000000000000000000000000000000000000000..3542b7beac0b609a8920bf3af8850c86e5188016 GIT binary patch literal 27908 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 literal 0 HcmV?d00001 diff --git a/pxii_bec/macros/luts/bpm_calib/18000_bpm_flux.png b/pxii_bec/macros/luts/bpm_calib/18000_bpm_flux.png new file mode 100644 index 0000000000000000000000000000000000000000..6e622029cd7937183103c6a238193f2b0cd49d0e GIT binary patch literal 31526 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 XFH!00EeRM|&7`_>uX4hl`kwy->n+zP literal 0 HcmV?d00001 diff --git a/pxii_bec/macros/luts/bpm_calib/20000_bpm_flux.png b/pxii_bec/macros/luts/bpm_calib/20000_bpm_flux.png new file mode 100644 index 0000000000000000000000000000000000000000..d1f3c53c718911827851aee865ea42d062c09287 GIT binary patch literal 28372 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 literal 0 HcmV?d00001 diff --git a/pxii_bec/macros/luts/bpm_calib/26000_bpm_flux.png b/pxii_bec/macros/luts/bpm_calib/26000_bpm_flux.png new file mode 100644 index 0000000000000000000000000000000000000000..e2c28f6dbb61a2fe40df79454cbc7cb5a8742131 GIT binary patch literal 29889 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 bb7Gcwoc}JghEs5wD2w_wZRKP|Q{VprOB!4y literal 0 HcmV?d00001 diff --git a/pxii_bec/macros/luts/bpm_calib/7000_bpm_flux.png b/pxii_bec/macros/luts/bpm_calib/7000_bpm_flux.png new file mode 100644 index 0000000000000000000000000000000000000000..1c8223bb93444d5db011093366169cad87e067b1 GIT binary patch literal 27658 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 E03YM#E&u=k literal 0 HcmV?d00001 diff --git a/pxii_bec/macros/luts/bpm_calib/9000_bpm_flux.png b/pxii_bec/macros/luts/bpm_calib/9000_bpm_flux.png new file mode 100644 index 0000000000000000000000000000000000000000..6f2c69ea034528fd4e6893df0555c5676befa225 GIT binary patch literal 27562 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