From 5f0d1fddeb6ce080a23e4ee1aee91ab698afab38 Mon Sep 17 00:00:00 2001 From: x10sa Date: Wed, 9 Sep 2026 16:42:46 +0200 Subject: [PATCH] changes as of 260909 --- pxii_bec/device_configs/__init__.py | 0 .../device_configs/pxii-beamline-states.yaml | 0 pxii_bec/device_configs/pxii-devices.yaml | 53 +- .../device_configs/pxii-devices.yaml.broken | 0 pxii_bec/device_configs/pxii-devices.yaml.old | 0 .../device_configs/x10sa_device_config.yaml | 0 pxii_bec/macros/APscripts.py | 28 +- pxii_bec/macros/Undu_Helpers.py | 120 +++- pxii_bec/macros/check.py | 3 + pxii_bec/macros/daily.py | 633 +++++++++++------- .../macros/luts/dcm_calibration_20260902.csv | 65 ++ .../macros/luts/dcm_calibration_20260903.csv | 2 + .../dcm_calibration_failures_20260902.csv | 7 + .../dcm_calibration_failures_20260903.csv | 3 + pxii_bec/macros/pxii_parameters.py | 4 +- 15 files changed, 602 insertions(+), 316 deletions(-) mode change 100644 => 100755 pxii_bec/device_configs/__init__.py mode change 100644 => 100755 pxii_bec/device_configs/pxii-beamline-states.yaml mode change 100644 => 100755 pxii_bec/device_configs/pxii-devices.yaml mode change 100644 => 100755 pxii_bec/device_configs/pxii-devices.yaml.broken mode change 100644 => 100755 pxii_bec/device_configs/pxii-devices.yaml.old mode change 100644 => 100755 pxii_bec/device_configs/x10sa_device_config.yaml create mode 100644 pxii_bec/macros/luts/dcm_calibration_20260902.csv create mode 100644 pxii_bec/macros/luts/dcm_calibration_20260903.csv create mode 100644 pxii_bec/macros/luts/dcm_calibration_failures_20260902.csv create mode 100644 pxii_bec/macros/luts/dcm_calibration_failures_20260903.csv diff --git a/pxii_bec/device_configs/__init__.py b/pxii_bec/device_configs/__init__.py old mode 100644 new mode 100755 diff --git a/pxii_bec/device_configs/pxii-beamline-states.yaml b/pxii_bec/device_configs/pxii-beamline-states.yaml old mode 100644 new mode 100755 diff --git a/pxii_bec/device_configs/pxii-devices.yaml b/pxii_bec/device_configs/pxii-devices.yaml old mode 100644 new mode 100755 index 7fa50c9..28383a5 --- 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 @@ -65,15 +65,15 @@ aerotech: mount: 0 work: 0 x: - in: -8.1e-06 + in: 0.05999397 out: -10 safe: -50 y: mount: -0.0 - work: -0.02600108 + work: -0.02799609 z: mount: 0 - work: -0.00900383 + work: -0.0090036 bcu_bpm1: description: BCU BPM Channel 1 deviceClass: ophyd.EpicsSignalRO @@ -302,7 +302,7 @@ bs_x: onFailure: buffer readoutPriority: baseline userParameter: - in: 0.39119736 + in: 0.2038985 bs_y: description: Beamstop Y deviceClass: ophyd_devices.EpicsMotor @@ -314,7 +314,7 @@ bs_y: onFailure: buffer readoutPriority: baseline userParameter: - in: 0.76699895 + in: 0.9064885 bs_z: description: Beamstop Z deviceClass: ophyd_devices.EpicsMotor @@ -330,7 +330,7 @@ bs_z: max_blout: 70 min: 13 safe: 45.1 - samp: 16.408 + samp: 16.80557617 type: continuous work_min: 20 bsf_f1_y: @@ -444,7 +444,7 @@ coll_x: onFailure: buffer readoutPriority: baseline userParameter: - in: 0.67471002 + in: 0.68249115 coll_y: description: Collimator Y deviceClass: ophyd_devices.EpicsMotor @@ -456,7 +456,7 @@ coll_y: onFailure: buffer readoutPriority: baseline userParameter: - in: 39.02 + in: 39.01884961 intermediate: 32 out: 20.002 park: 1 @@ -1322,6 +1322,29 @@ samcam_x: onFailure: buffer readOnly: true readoutPriority: monitored +samcam_xcurs: + description: Sample Camera X Cursor + deviceClass: ophyd.EpicsSignal + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-MS:Stats5:CursorX + deviceTags: + - scam + enabled: true + onFailure: buffer + readoutPriority: baseline +samcam_xcursprof: + description: Sample Camera X Cursor Profile + deviceClass: ophyd.EpicsSignalRO + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-MS:Stats5:ProfileCursorX_RBV + deviceTags: + - scam + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: monitored samcam_xsig: description: Sample Camera X Sigma deviceClass: ophyd.EpicsSignalRO @@ -1346,6 +1369,18 @@ samcam_y: onFailure: buffer readOnly: true readoutPriority: monitored +samcam_ycursprof: + description: Sample Camera Y Cursor Profile + deviceClass: ophyd.EpicsSignalRO + deviceConfig: + auto_monitor: true + read_pv: X10SA-ES-MS:Stats5:ProfileCursorY_RBV + deviceTags: + - scam + enabled: true + onFailure: buffer + readOnly: true + readoutPriority: monitored samcam_ysig: description: Sample Camera Y Sigma deviceClass: ophyd.EpicsSignalRO diff --git a/pxii_bec/device_configs/pxii-devices.yaml.broken b/pxii_bec/device_configs/pxii-devices.yaml.broken old mode 100644 new mode 100755 diff --git a/pxii_bec/device_configs/pxii-devices.yaml.old b/pxii_bec/device_configs/pxii-devices.yaml.old old mode 100644 new mode 100755 diff --git a/pxii_bec/device_configs/x10sa_device_config.yaml b/pxii_bec/device_configs/x10sa_device_config.yaml old mode 100644 new mode 100755 diff --git a/pxii_bec/macros/APscripts.py b/pxii_bec/macros/APscripts.py index 56b7a4e..d5ac618 100644 --- a/pxii_bec/macros/APscripts.py +++ b/pxii_bec/macros/APscripts.py @@ -428,7 +428,7 @@ def fit_plothist(hindex: int, signal_name: str, model="gauss", ibg=0): ######################### -def fit_plot(data_x, data_y, model="gauss", ibg=1, silent=0,fitrange=0, fitclick=0): +def fit_plot(data_x, data_y, model="gauss", ibg=1, silent=0, iplot=1, fitrange=0, fitclick=0): """ Get data for a completed scan, gaussian, voigt or lorentzian fit, default = gauss, plus linear background @@ -507,16 +507,16 @@ def fit_plot(data_x, data_y, model="gauss", ibg=1, silent=0,fitrange=0, fitclic g = model.fit(data_y, pars, x=data_x) ##### + if (iplot): + plt.ion() + plt.figure() + plt.plot(data_x, data_y, "*") + plt.plot(data_x, g.best_fit) + plt.xlabel("x-axis") + plt.ylabel("signal") + plt.show() - plt.ion() - plt.figure() - plt.plot(data_x, data_y, "*") - plt.plot(data_x, g.best_fit) - plt.xlabel("x-axis") - plt.ylabel("signal") - plt.show() - - if fitclick: + if (fitclick*iplot): print("Please define the x-range of the fit via click of graph") print("First click for start: ") x1 = plt.ginput(1) @@ -1013,7 +1013,7 @@ def colliscan(direction: str, range=0.3, nsteps=30, stime=0.5, centre=1): ##################### ### SLITSCANS ##################### -def slitscan(device_location: str, direction: str, range: 1, nsteps=50, centre=0): +def slitscan(device_location: str, direction: str, range= 1, nsteps=50, centre=0): """ Slit scan, and possible centre and plot all the results. @@ -1024,7 +1024,7 @@ def slitscan(device_location: str, direction: str, range: 1, nsteps=50, centre=0 nsteps: default = 50 move to centre or not [0/1] - Example: slitscan("fe","h", 30, centre=1) + Example: slitscan("fe","h",1, 30, centre=1) """ @@ -1142,9 +1142,9 @@ def slitscan(device_location: str, direction: str, range: 1, nsteps=50, centre=0 data_y = s.scan.live_data.lu_bpmsum.lu_bpmsum.val if mot.name == "fe_sl_xcen": - data_x = s.scan.live_data.fe_sxcen.fe_sxcen.val + data_x = s.scan.live_data.fe_sl_xcen.fe_sl_xcen.val if mot.name == "fe_sl_ycen": - data_x = s.scan.live_data.fe_sycen.fe_sycen.val + data_x = s.scan.live_data.fe_sl_ycen.fe_sl_ycen.val # BSF slits ================================ if mot.name == "bsf_sl_xcen": data_x = s.scan.live_data.bsf_sl_xcen.bsf_sl_xcen.val diff --git a/pxii_bec/macros/Undu_Helpers.py b/pxii_bec/macros/Undu_Helpers.py index 0302550..eceb07c 100755 --- a/pxii_bec/macros/Undu_Helpers.py +++ b/pxii_bec/macros/Undu_Helpers.py @@ -97,7 +97,7 @@ def plot_harmon(e_start, e_end, h_no, pr_out=False): plt.show() -def setu19(en, *harm_no, detune=0): +def setu19(en, *harm_no, detune=0, simul = 0): """ set the U19 to the gaps defined in Jul2025, or the "theoretical" ones for higher harmonics @@ -128,10 +128,10 @@ def setu19(en, *harm_no, detune=0): harm = 9 elif 16 < en <= 19: harm = 11 - elif 19 < en <= 22: + elif 19 < en <= 22: ## 22 harm = 13 - if en <= 22: + if (en <= 22 and harm <=13): h = h_all[harm] print(f"harmonics is {harm}.") @@ -146,32 +146,41 @@ def setu19(en, *harm_no, detune=0): # 29: 15, 17, 19 # 30: 19 ## - if 23 < en <= 25: - n = 15 - enorm = en / n - g = exponential_func0(enorm, fitpar_u19[0], fitpar_u19[1], fitpar_u19[2]) - elif 25 < en <= 29: - n = 17 - enorm = en / n - g = exponential_func0(enorm, fitpar_u19[0], fitpar_u19[1], fitpar_u19[2]) - elif 29 < en: - n = 19 + if (en > 22 and harm_no): + harm = int(harm_no[0]) + print("Selected harmonics is:", harm) + n= harm enorm = en / n g = exponential_func0(enorm, fitpar_u19[0], fitpar_u19[1], fitpar_u19[2]) + else: + if 22 < en <= 25: + n = 15 + enorm = en / n + g = exponential_func0(enorm, fitpar_u19[0], fitpar_u19[1], fitpar_u19[2]) + elif 25 < en <= 29: + n = 17 + enorm = en / n + g = exponential_func0(enorm, fitpar_u19[0], fitpar_u19[1], fitpar_u19[2]) + elif 29 < en: + n = 19 + enorm = en / n + g = exponential_func0(enorm, fitpar_u19[0], fitpar_u19[1], fitpar_u19[2]) - print("Undulator has been ", g0, " mm") - if 4.5 <= g <= 20: - print("Moving Undulator gap to ", g, " mm") - else: - print("not a valid gap, do nothing") + + if not simul: + print("Undulator has been ", g0, " mm") + if 4.5 <= g <= 20: + print("Moving Undulator gap to ", g, " mm") + else: + print("not a valid gap, do nothing") - if detune: - g = g * 0.996 - print("moving to detuned gap value, slightly below max, about 0.15 % ") + if detune: + g = g * 0.996 + print("moving to detuned gap value, slightly below max, about 0.15 % ") # print("move disabled!!") - res = scans.umv(dev.id_gap, g, relative=False) + scans.umv(dev.id_gap, g, relative=False) - return + return g ################################## @@ -305,9 +314,26 @@ def long_gscan(estart=6, end_en=30.5, g_low=4.5, g_high=9.0, nsteps=1000, sett = return +def plottest(wname): + #wname="GapScan" + existing_docks = bec.gui.windows + if existing_docks.get(wname) is None: + dock_area = bec.gui.new(name=wname, geometry = [4000, 900, 700, 700]) + wr = dock_area.new(bec.gui.available_widgets.Waveform, object_name="Plot") + mot = dev.id_gap + det = dev.lu_bpmsum + else: + dock_area = open_docks[wname] + wr= dock_area.Plot + wr.plot(device_x=mot, device_y=det) ## names first ! + # wr.plot(x=mot.name,y=det.name) ### this comes later + wr.x_label = mot.name + wr.y_label = det.name + + ################################## -def gscan(centre=0, gomax=0, detune=0,sett=1): +def gscan(deltag = 0.05,centre=0, gomax=0, detune=0,sett=1, silent=0, iplot=1, isave=0): """ Scan the ID GAP and go to the max of lu_bpm intensity @@ -319,34 +345,58 @@ def gscan(centre=0, gomax=0, detune=0,sett=1): """ import time - dock_area = bec.gui.new(name="GapScan", geometry = [4000, 900, 700, 700]) - wr = dock_area.new(bec.gui.available_widgets.Waveform) + wname="GapScan" + mot = dev.id_gap - det = dev.lu_bpmsum + det = dev.lu_bpmsum + + existing_docks = bec.gui.windows + if existing_docks.get(wname) is None: + dock_area = bec.gui.new(name=wname, geometry = [4000, 900, 700, 700]) + wr = dock_area.new(bec.gui.available_widgets.Waveform, object_name="Plot") + else: + dock_area = existing_docks[wname] + wr= dock_area.Plot + wr.clear_all() wr.plot(device_x=mot, device_y=det) ## names first ! # wr.plot(x=mot.name,y=det.name) ### this comes later wr.x_label = mot.name wr.y_label = det.name g0 = dev.id_gap.readback.get() - deltag = 0.05 + #deltag = 0.05 steps = 30 resol = 2*deltag/steps + if resol < 0.002: + resol = 0.003 + steps = round(2*deltag/resol) + + start=-deltag + stop = deltag print(f"Gap resol is {resol} mm ") - - ds = scans.line_scan(dev.id_gap, -deltag, deltag, steps=steps, settling_time=sett,exp_time=0.5, relative=True) + if (g0-deltag < 4.5): + start=g0-4.5 + ds = scans.line_scan(dev.id_gap, start, stop, steps=steps, settling_time=sett,exp_time=0.1, relative=True) gap_data = ds.scan.live_data.id_gap.id_gap.val bpm_data = ds.scan.live_data.lu_bpmsum.lu_bpmsum.val gap_data=np.array(gap_data) bpm_data = np.array(bpm_data) - + + if isave: + en = round(getenergy()) + dirname = "/sls/x10sa/config/commissioning/Data/GapsFE_0p3/" + combined = np.column_stack((gap_data, bpm_data)) + filename = dirname + "gap" + str(en)+"_"+str(g0*100)[0:3]+ ".txt" + with open(filename, "w") as f: + np.savetxt(f, combined, delimiter=",", fmt="%5f") + maxy = max(bpm_data) indmax = np.argmax(bpm_data) - gm = gap_data[indmax] + gmax = gap_data[indmax] - gcen, xm = fit_plot(gap_data, bpm_data, model="voigt") + gcen, xm = fit_plot(gap_data, bpm_data, model="voigt", silent=silent, iplot=iplot) if gomax: gm = xm @@ -354,6 +404,8 @@ def gscan(centre=0, gomax=0, detune=0,sett=1): gm = gcen print("gap off by ", g0 - gm, " mm") + + print(f"gcen = {gcen}, gmax = {xm} or {gmax}") if detune: gm = gm * 0.996 print("moving to detuned gap value, slightly (0.15 %) below max") @@ -366,4 +418,4 @@ def gscan(centre=0, gomax=0, detune=0,sett=1): else: print("Fit too far off, try using option gomax=1") - return + return gm, xm diff --git a/pxii_bec/macros/check.py b/pxii_bec/macros/check.py index b37f88d..300c619 100755 --- a/pxii_bec/macros/check.py +++ b/pxii_bec/macros/check.py @@ -454,6 +454,9 @@ def filter_results(results, statuses=None): def run_check(show_all=False, scilog=False): + """Check the status of beamline motors (must exist as devices in BEC). + For a full list of checked devices, use run_check(show_all=True). + Results will be logged in scilog if scilog=True""" results = check2() diff --git a/pxii_bec/macros/daily.py b/pxii_bec/macros/daily.py index e5eb88b..d4d81c2 100644 --- a/pxii_bec/macros/daily.py +++ b/pxii_bec/macros/daily.py @@ -1,4 +1,4 @@ -""" Files needed for the daily setup routine for local contacts """ +"""Files needed for the daily setup routine for local contacts""" import time from dataclasses import dataclass @@ -19,6 +19,7 @@ class DailySetupContext: messages: list progress_state: dict + def daily_setup( energy=12400, *, @@ -42,6 +43,8 @@ def daily_setup( "Save new positions to BEC": save_positions, } + results = {} + ctx = get_daily_setup_context(selected) for task, enabled in selected.items(): @@ -52,29 +55,34 @@ def daily_setup( try: if set_energy: - run_daily_energy(energy,ctx) + results["Beamline energy"] = run_daily_energy(energy, ctx) if move_beam: - run_daily_movebeam(ctx) + results["Move beam"] = run_daily_movebeam(ctx) if align_beamstop: - run_daily_beamstop(ctx) + results["Align beamstop"] = run_daily_beamstop(ctx) if measure_beampos: - run_daily_beampos(ctx) + results["Measure beam position"] = run_daily_beampos(ctx) if align_collimator: - run_daily_collimator(ctx) + results["Align collimator"] = run_daily_collimator(ctx) if measure_flux: - run_daily_flux(ctx) + results["Flux"] = run_daily_flux(ctx) if save_positions: run_save_positions(ctx) + log_daily_setup_to_scilog(bec,results) + return(results) + finally: - print("done") - # bl.planner.move_to(BeamlineState.SAMPLE_ALIGNMENT) + bl.planner.move_to(BeamlineState.ROBOT_SAMPLE_EXCHANGE) + +def sanity_checks(): + pass def get_daily_setup_context(tasks=None): """Get widgets and state used by daily setup tasks.""" @@ -89,8 +97,8 @@ def get_daily_setup_context(tasks=None): "Measure beam position", "Align collimator", "Measure flux", - "Save new positions to BEC" - ] + "Save new positions to BEC", + ] return DailySetupContext( plot1=plot1, @@ -100,16 +108,11 @@ def get_daily_setup_context(tasks=None): log=log, progress=progress, messages=[], - progress_state={ - task: "todo" - for task in tasks - }, + progress_state={task: "todo" for task in tasks}, ) -def run_daily_energy( - energy, - ctx, - ): + +def run_daily_energy(energy, ctx): """Set and optimise beamline energy.""" task = "Set energy" @@ -117,18 +120,27 @@ def run_daily_energy( clear_daily_plots() set_progress(ctx.progress, ctx.progress_state, task, "running") - daily_energy(energy, plot_widget=ctx.plot1) + en = daily_energy(energy, plot_widget=ctx.plot1) + + result = { + "energy": en + } update_log( - ctx.log, - ctx.messages, - f"Beamline energy is {get_current_energy():.5g} eV", - ) + ctx.log, + ctx.messages, + format_energy_for_gui(result), + ) set_progress(ctx.progress, ctx.progress_state, task, "done") + return result + + +def format_energy_for_gui(result): + return f"Beamline energy {result['energy']:.0f} eV\n" + def run_daily_movebeam(ctx): - """Move beam to the scintillator crosshair""" task = "Move beam" @@ -136,61 +148,24 @@ def run_daily_movebeam(ctx): clear_daily_plots() set_progress(ctx.progress, ctx.progress_state, task, "running") - move_result = daily_movebeam() - if move_result["success"]: - update_log( - ctx.log, - ctx.messages, - f"Beam position relative to crosshair: " - f"x = {move_result["BeamX"]:.2g} microns, " - f"y = {move_result["BeamY"]:.2g} microns." - ) + result = daily_movebeam() + + update_log( + ctx.log, + ctx.messages, + format_movebeam_for_gui(result), + ) + + set_progress(ctx.progress, ctx.progress_state, task, "done") + return result + +def format_movebeam_for_gui(result): + if result["success"]: + return (f"Beam position relative to crosshair:\n" + f"Beam_X: {result["BeamX"]:.2g} microns, " + f"Beam_Y: {result["BeamY"]:.2g} microns.\n") else: - update_log( - ctx.log, - ctx.messages, - "Moving beam to the crosshair failed" - ) - - set_progress(ctx.progress, ctx.progress_state, task, "done") - -def run_daily_beampos(ctx): - """Measure the beam position at the scintillator at Aare zoom levels""" - - task = "Measure beam position" - set_progress(ctx.progress, ctx.progress_state, task, "running") - - beampos_result = daily_beampos() - - - update_log( - ctx.log, - ctx.messages, - format_beam_positions(beampos_result), - ) - -def run_daily_collimator(ctx): - """Align the collimator and save positions""" - - task = "Align collimator" - set_progress(ctx.progress, ctx.progress_state, task, "running") - - coll_result = daily_coll() - - update_log( - ctx.log, - ctx.messages, - ( - f"I1 intensity with collimator out: {coll_result['intensity_coll_out']:.2e}. " - f"Starting intensity with collimator in: {coll_result['start_intensity_coll_in']:.2e}. " - f"Intensity with collimator in after scans: {coll_result['final_intensity_coll_in']:.2e}. " - f"Collimator X: {coll_result['x_position']:.3f}, " - f"Collimator Y: {coll_result['y_position']:.3f}" - ), - ) - - set_progress(ctx.progress, ctx.progress_state, task, "done") - + return f"Moving beam to crosshaor failed" def run_daily_beamstop(ctx): @@ -201,41 +176,121 @@ def run_daily_beamstop(ctx): # clear_daily_plots() set_progress(ctx.progress, ctx.progress_state, task, "running") - bs_result = daily_beamstop() - # bs_result = {'x_position':20, 'y_position':3} + result = daily_beamstop() update_log( - ctx.log, - ctx.messages, - ( - "Beamstop centred: " - f"X={bs_result['x_position']:.4g}, " - f"Y={bs_result['y_position']:.4g}" - ), - ) + ctx.log, + ctx.messages, + format_beamstop_for_gui(result), + ) # save_current_position(dev.bs_x, "in") # save_current_position(dev.bs_y, "in") set_progress(ctx.progress, ctx.progress_state, task, "done") + return result -def run_daily_flux(ctx): - """Measure the beam intensity using BCU BPM""" +def format_beamstop_for_gui(result): + return ( + f"BS_X: {result['bs_x_pos']:.3g} mm, " + f"BS_Y: {result['bs_y_pos']:.3g} mm\n" + ) - task = "Measure flux" +def run_daily_beampos(ctx): + """Measure the beam position at the scintillator at Aare zoom levels""" + + task = "Measure beam position" set_progress(ctx.progress, ctx.progress_state, task, "running") - flux_result = bpm2flux() + beampos_result = daily_beampos() update_log( ctx.log, ctx.messages, - (f"Intensity at current trasmission: {flux_result[0]:.2e}. " - f"Intensity at 100% transmission: {flux_result[1]:.2e}.") + format_beam_positions(beampos_result), + ) + + set_progress(ctx.progress, ctx.progress_state, task, "done") + + return beampos_result + +def format_beam_positions(pos_result): + """Format camera beam positions for display.""" + + lines = [f"{'Zoom':<8} {'X / px':>10} {'Y / px':>10}", "-" * 30] + + for zoom, pos in pos_result.items(): + lines.append(f"{zoom:<8} {pos['x']:>10.1f} {pos['y']:>10.1f}") + + return "\n".join(lines) + + +def run_daily_collimator(ctx): + """Align the collimator and save positions""" + + task = "Align collimator" + set_progress(ctx.progress, ctx.progress_state, task, "running") + + result = daily_coll() + + update_log( + ctx.log, + ctx.messages, + format_collimator_for_gui(result), + ) + + set_progress(ctx.progress, ctx.progress_state, task, "done") + return result + +def format_collimator_for_gui(result): + """Format collimator result for the Daily Setup GUI.""" + + return ( + f"\nI1 intensity with collimator out: " + f"{result['intensity_coll_out']:.2e}\n" + f"Starting intensity with collimator in: " + f"{result['start_intensity_coll_in']:.2e}\n" + f"Intensity with collimator in after scans: " + f"{result['final_intensity_coll_in']:.2e}\n" + f"Scan Width X: {result['coll_x_width']:.3f} mm, " + f"Scan Width Y: {result['coll_y_width']:.3f} mm\n" + f"Coll_X: {result['coll_x_pos']:.3f} mm, " + f"Coll_Y: {result['coll_y_pos']:.3f} mm\n" ) +def run_daily_flux(ctx): + """Measure the beam intensity using BCU BPM.""" + + task = "Measure flux" + set_progress(ctx.progress, ctx.progress_state, task, "running") + + flux = bpm2flux() + + result = { + "current_flux": flux[0], + "full_flux": flux[1], + } + + update_log( + ctx.log, + ctx.messages, + format_flux_for_gui(result), + ) + + set_progress(ctx.progress, ctx.progress_state, task, "done") + return result + +def format_flux_for_gui(result): + return ( + f"Intensity at current transmission: " + f"{result['current_flux']:.2e} ph/s\n" + f"Intensity at 100% transmission: " + f"{result['full_flux']:.2e} ph/s" + ) + + def select_daily_setup_gui(): """Return widgets belonging to the Daily Setup GUI.""" @@ -246,60 +301,38 @@ def select_daily_setup_gui(): gui = bec.gui.new(window_name) # Row 1 - log = gui.new( - widget="TextBox", - object_name="Info", - ) + log = gui.new(widget="TextBox", object_name="Info") progress = gui.new( - widget="TextBox", - object_name="Progress", - relative_to="Info", - where="right", + widget="TextBox", object_name="Progress", relative_to="Info", where="right" ) # Row 2 - start a new full-width row - plot1 = gui.new( - widget="Waveform", - object_name="Beamstop_X", - where="bottom", - ) + plot1 = gui.new(widget="Waveform", object_name="Plot_1", where="bottom") plot2 = gui.new( - widget="Waveform", - object_name="Beamstop_Y", - relative_to="Beamstop_X", - where="right", + widget="Waveform", object_name="Plot_2", relative_to="Plot_1", where="right" ) # Row 3 - start another full-width row - plot3 = gui.new( - widget="Waveform", - object_name="Collimator_X", - where="bottom", - ) + plot3 = gui.new(widget="Waveform", object_name="Plot_3", where="bottom") plot4 = gui.new( - widget="Waveform", - object_name="Collimator_Y", - relative_to="Collimator_X", - where="right", + widget="Waveform", object_name="Plot_4", relative_to="Plot_3", where="right" ) - gui.set_layout_ratios( - horizontal=[1, 1], - vertical=[1, 1, 1], - ) + gui.set_layout_ratios(horizontal=[1, 1], vertical=[1, 1, 1]) else: gui = open_windows[window_name] - plot1 = gui.Beamstop_X - plot2 = gui.Beamstop_Y - plot3 = gui.Collimator_X - plot4 = gui.Collimator_Y + plot1 = gui.Plot_1 + plot2 = gui.Plot_2 + plot3 = gui.Plot_3 + plot4 = gui.Plot_4 log = gui.Info progress = gui.Progress return plot1, plot2, plot3, plot4, log, progress + def clear_daily_plots(): plot1, plot2, plot3, plot4, log, progress = select_daily_setup_gui() plot1.clear_all() @@ -308,52 +341,45 @@ def clear_daily_plots(): plot4.clear_all() - def update_log(log_box, messages, message): - """Add new message to the daily setup log """ + """Add new message to the daily setup log""" messages.append(message) log_box.set_plain_text("\n".join(messages)) + def update_progress(progress_box, progress_state): - """ Sets up the status icons for the progress tracker""" + """Sets up the status icons for the progress tracker""" status = { - "todo": "\u25CB", - "running": "\u25B6", + "todo": "\u25cb", + "running": "\u25b6", "done": "\u2713", - "warning": "\u26A0", + "warning": "\u26a0", "skipped": "–", "failed": "\u2717", } - - text = "\n".join( - f"{status[state]} {label}" - for label, state in progress_state.items() - ) + text = "\n".join(f"{status[state]} {label}" for label, state in progress_state.items()) progress_box.set_plain_text(text) + def set_progress(progress_box, progress_state, step, status): """Change the status of one step and update the display.""" progress_state[step] = status update_progress(progress_box, progress_state) -def plot_daily_setup_scan( - motor_name, - signal_name, - plot="x", - title=None, -): + +def plot_daily_setup_scan(motor_name, signal_name, plot="x", title=None): """Plot live scan data in one of the Daily Setup waveform widgets.""" plot1, plot2, plot3, plot4, log, progress = select_daily_setup_gui() - if plot.lower() == "beamstop_x": + if plot.lower() == "plot_1": wf = plot1 - elif plot.lower() == "beamstop_y": - wf = plot2 - elif plot.lower() == "collimator_x": + elif plot.lower() == "plot_2": + wf = plot2 + elif plot.lower() == "plot_3": wf = plot3 - elif plot.lower() == "collimator_y": + elif plot.lower() == "plot_4": wf = plot4 else: raise ValueError("plot must be 'x' or 'y'") @@ -367,22 +393,23 @@ def plot_daily_setup_scan( wf.x_label = motor_name wf.y_label = signal_name - wf.plot( - device_x=motor_name, - device_y=signal_name, - ) + wf.plot(device_x=motor_name, device_y=signal_name) + def daily_energy(energy, plot_widget=None): - """ Set the beamline to the required energy """ + """Set the beamline to the required energy""" current_energy = get_current_energy() if abs(energy - current_energy) > 1: bl_energy(energy, window_name="DailySetup", plot_widget=plot_widget) else: gap_actual = dev.id_gap.position gap_req = calc_gap(energy) - if abs(gap_actual-gap_req) > 0.05: + if abs(gap_actual - gap_req) > 0.05: umv(dev.id_gap, gap_req) mono_pitch_scan(window_name="DailySetup", plot_widget=plot_widget) + new_energy = get_current_energy() + return new_energy + def set_zoom(zoom): """Set sample camera zoom level.""" @@ -391,7 +418,8 @@ def set_zoom(zoom): zoom = CameraZoom.from_label(zoom) umv(dev.scam_zoom, zoom.position) else: - umv(dev.scam_zoom, zoom) + umv(dev.scam_zoom, zoom) + def daily_beampos(): """Measure beam positions at different zoom levels""" @@ -409,7 +437,7 @@ def daily_beampos(): dev.bcu_shutter.put(1) for zoom in CameraZoom: - print(F"Moving to {zoom.label}") + print(f"Moving to {zoom.label}") umv(dev.scam_zoom, zoom.position) # set autoexposure @@ -417,31 +445,25 @@ def daily_beampos(): time.sleep(0.2) # take readings - x = dev.samcam_x.read()['samcam_x']['value'] - y = dev.samcam_y.read()['samcam_y']['value'] + x = dev.samcam_x.read()["samcam_x"]["value"] + y = dev.samcam_y.read()["samcam_y"]["value"] # append results - results[zoom.label] = {'x': x, 'y': y} + results[zoom.label] = {"x": x, "y": y} print(f" {zoom.label}: x = {x:.4g}, y = {y:.4g}") finally: - dev.bcu_shutter.put(0) + dev.bcu_shutter.put(0) return results + def daily_coll(): """Centre the collimator in X and Y using the I1 diode.""" plot1, plot2, plot3, plot4, log, progress = select_daily_setup_gui() - result = { - "success": False, - "intensity_coll_out": None, - "start_intensity_coll_in": None, - "final_intensity_coll_in": None, - "y_position": None, - "x_position": None, - } + result = {} try: if not bl.planner.is_state(BeamlineState.FLUX_MEASUREMENT): @@ -452,6 +474,8 @@ def daily_coll(): time.sleep(0.2) + get_value(dev.i1) + result["intensity_coll_out"] = get_value(dev.i1) print(f"Starting intensity is {result["intensity_coll_out"]:.3e}") @@ -460,8 +484,7 @@ def daily_coll(): # Centre Y result["start_intensity_coll_in"] = get_value(dev.i1) print( - "Intensity with collimator in before scans: " - f"{result['start_intensity_coll_in']:.3e}" + "Intensity with collimator in before scans: " f"{result['start_intensity_coll_in']:.3e}" ) y_result = find_feature( @@ -476,8 +499,8 @@ def daily_coll(): plot_widget=plot4, ) - result["y_position"] = y_result["centre"] - result["y_width"] = y_result["width"] + result["coll_y_pos"] = y_result["centre"] + result["coll_y_width"] = y_result["width"] # Centre X @@ -493,13 +516,12 @@ def daily_coll(): plot_widget=plot3, ) - result["x_position"] = x_result["centre"] + result["coll_x_pos"] = x_result["centre"] result["final_intensity_coll_in"] = get_value(dev.i1) - result["x_width"] = x_result["width"] + result["coll_x_width"] = x_result["width"] print( - "Intensity with collimator in after scans: " - f"{result['final_intensity_coll_in']:.3e}" + "Intensity with collimator in after scans: " f"{result['final_intensity_coll_in']:.3e}" ) result["success"] = True @@ -509,41 +531,23 @@ def daily_coll(): finally: dev.bcu_shutter.put(0) + def daily_beamstop(): - """Centre the beamstop against the detector - cover, i2""" + """Centre the beamstop against the detector cover, i2""" plot1, plot2, plot3, plot4, log, progress = select_daily_setup_gui() - result = { - # "success": False, - # "x_position": None, - "y_position": None, - "intensity after alignment": None - } + result = {} dev.transm.put(EnergyDefaults.default_trans) try: - # if not bl.planner.is_state(BeamlineState.BEAMSTOP_ALIGNMENT): - # bl.planner.move_to(BeamlineState.BEAMSTOP_ALIGNMENT) - # set_zoom('2x') - # auto_exposure('samcam', max_iter=20) - - # bl.d['bl_pos'].move('out') - # bl.d['det_cov'].move('close') - # dev.bcu_shutter.put(1) - if not bl.planner.is_state(BeamlineState.DET_DIODE): bl.planner.move_to(BeamlineState.DET_DIODE) - # set_zoom('2x') - # auto_exposure('samcam', max_iter=20) - # bl.d['bl_pos'].move('out') - bl.d['det_cov'].move('close') + bl.d["det_cov"].move("close") dev.bcu_shutter.put(1) - time.sleep(0.2) # Centre Y @@ -570,21 +574,21 @@ def daily_beamstop(): 1.2, 30, feature="edge_offset", - offset = Beamstop.x_offset, + offset=Beamstop.x_offset, relative=True, confirm=False, window_name="DailySetup", plot_widget=plot1, ) - result["x_position"] = x_result["centre"] - result["y_position"] = y_result["centre"] + result["bs_x_pos"] = x_result["centre"] + result["bs_y_pos"] = y_result["centre"] result["intensity after alignment"] = read_i2() print( "Intensity after Y scan: " f"{result['intensity after alignment']:.4g}\n" - f"Centred position is {result["x_position"]:.5g}, {result["y_position"]:.5g}" + f"Centred position is {result["bs_x_pos"]:.5g}, {result["bs_y_pos"]:.5g}" ) return result @@ -592,12 +596,12 @@ def daily_beamstop(): finally: dev.bcu_shutter.put(0) + def test_daily_movebeam(meas="scint", iterations=3): vfm_start = get_value(dev.vfm_ydr) hfm_start = get_value(dev.hfm_xd) - dev.transm.put(EnergyDefaults.default_trans) if meas == "scint": @@ -635,10 +639,7 @@ def test_daily_movebeam(meas="scint", iterations=3): vfm_change = diff_y / BeamMove.scint_y_slope new_vfm = current_vfm + vfm_change - print( - f"VFM: {current_vfm:.6f} -> {new_vfm:.6f} " - f"(change {vfm_change:+.6f})" - ) + print(f"VFM: {current_vfm:.6f} -> {new_vfm:.6f} " f"(change {vfm_change:+.6f})") beam_y_before = y vfm_before = current_vfm @@ -664,10 +665,7 @@ def test_daily_movebeam(meas="scint", iterations=3): ) else: - print( - f"Y within tolerance ({diff_y:+.2f} px) " - "- no VFM move" - ) + print(f"Y within tolerance ({diff_y:+.2f} px) " "- no VFM move") # ---------------------------------------------------------- # HFM correction @@ -685,18 +683,12 @@ def test_daily_movebeam(meas="scint", iterations=3): hfm_change = diff_x / BeamMove.scint_x_slope new_hfm = current_hfm + hfm_change - print( - f"HFM: {current_hfm:.6f} -> {new_hfm:.6f} " - f"(change {hfm_change:+.6f})" - ) + print(f"HFM: {current_hfm:.6f} -> {new_hfm:.6f} " f"(change {hfm_change:+.6f})") umv(dev.hfm_xd, new_hfm) else: - print( - f"X within tolerance ({diff_x:+.2f} px) " - "- no HFM move" - ) + print(f"X within tolerance ({diff_x:+.2f} px) " "- no HFM move") # Final check x, y = read_scintXY(CameraZoom.X12_5.position) @@ -715,10 +707,10 @@ def test_daily_movebeam(meas="scint", iterations=3): final_hfm = get_value(dev.hfm_xd) print( - f"VFM: {vfm_start:.6f} -> {final_vfm:.6f}\n" - f"HFM: {hfm_start:.6f} -> {final_hfm:.6f}" + f"VFM: {vfm_start:.6f} -> {final_vfm:.6f}\n" f"HFM: {hfm_start:.6f} -> {final_hfm:.6f}" ) + def daily_movebeam(meas="scint", iterations=3): """ Move the beam onto the sample-camera crosshair using the VFM and HFM. @@ -734,9 +726,7 @@ def daily_movebeam(meas="scint", iterations=3): if meas != "scint": raise ValueError(f"Unknown beam position measurement: {meas}") - result = {"success": None, - "BeamX": None, - "BeamY": None} + result = {"success": None, "BeamX": None, "BeamY": None} # Starting mirror positions vfm_start = get_value(dev.vfm_ydr) @@ -752,8 +742,7 @@ def daily_movebeam(meas="scint", iterations=3): max_move = 0.02 # mm print( - f"Moving beam to scintillator crosshair\n" - f"Target: X={x_target:.1f}, Y={y_target:.1f} px" + f"Moving beam to scintillator crosshair\n" f"Target: X={x_target:.1f}, Y={y_target:.1f} px" ) for i in range(iterations): @@ -792,10 +781,7 @@ def daily_movebeam(meas="scint", iterations=3): print("Beam alignment stopped.") return False - umv( - dev.vfm_ydr, - current_vfm + vfm_change - ) + umv(dev.vfm_ydr, current_vfm + vfm_change) # Remeasure after VFM move since VFM may also affect X x, y = read_scintXY(CameraZoom.X12_5.position) @@ -819,10 +805,7 @@ def daily_movebeam(meas="scint", iterations=3): print("Beam alignment stopped.") return False - umv( - dev.hfm_xd, - current_hfm + hfm_change - ) + umv(dev.hfm_xd, current_hfm + hfm_change) # -------------------------------------------------------------- # Final verification @@ -836,10 +819,7 @@ def daily_movebeam(meas="scint", iterations=3): final_vfm = get_value(dev.vfm_ydr) final_hfm = get_value(dev.hfm_xd) - success = ( - abs(diff_x) <= tolerance - and abs(diff_y) <= tolerance - ) + success = abs(diff_x) <= tolerance and abs(diff_y) <= tolerance print( f"\nFinal beam position: X={x:.2f}, Y={y:.2f} px\n" @@ -851,10 +831,7 @@ def daily_movebeam(meas="scint", iterations=3): if success: print("Beam alignment successful.") else: - print( - f"Beam is not within ±{tolerance:.1f} px after " - f"{iterations} corrections." - ) + print(f"Beam is not within ±{tolerance:.1f} px after " f"{iterations} corrections.") beamx = calc_scam_microns(diff_x, zoom=CameraZoom.X12_5.position) beamy = calc_scam_microns(diff_y, zoom=CameraZoom.X12_5.position) @@ -865,19 +842,161 @@ def daily_movebeam(meas="scint", iterations=3): return result -def format_beam_positions(pos_result): - """Format camera beam positions for display.""" - lines = [ - "Beam position", - "", - f"{'Zoom':<8} {'X / px':>10} {'Y / px':>10}", - "-" * 30, - ] - for zoom, pos in pos_result.items(): - lines.append( - f"{zoom:<8} {pos['x']:>10.1f} {pos['y']:>10.1f}" +# def format_daily_setup_result(result): +# """Create readable text for a daily setup result.""" + +# if result is None: +# return "completed" + +# # Beam position dictionary +# if isinstance(result, dict): +# lines = [] + +# for key, value in result.items(): +# if ( +# isinstance(value, dict) +# and "x" in value +# and "y" in value +# ): +# lines.append( +# f"{key}: X={value['x']:.1f}, Y={value['y']:.1f}" +# ) +# else: +# lines.append(f"{key}: {value}") + +# return "\n".join(lines) + +# return str(result) + +# def build_daily_setup_log(results): +# """Build the text for a daily setup SciLog entry.""" + +# lines = ["PXII Daily Setup", ""] + +# for step, result in results.items(): +# lines.append(step) +# lines.append(format_daily_setup_result(result)) +# lines.append("") + +# return "\n".join(lines) + + +# def test_scilog(): +# test_results = { +# "Set energy": "12.40 keV", +# "Align collimator": { +# "x": 39.042, +# "y": 12.376, +# }, +# "Align beamstop": "completed", +# "Beam position": { +# "1x": {"x": 996.8, "y": 971.5}, +# "2x": {"x": 999.9, "y": 971.3}, +# "3x": {"x": 998.6, "y": 971.2}, +# "5.8x": {"x": 998.4, "y": 972.5}, +# "7.5x": {"x": 999.4, "y": 977.0}, +# "12.5x": {"x": 995.2, "y": 976.0}, +# }, +# "Measure flux": "1.24e12 ph/s", +# } +# return test_results + +def add_energy_to_scilog(msg, result): + msg.add_text("Energy: ", bold=True) + msg.add_text(f"{result['energy']:.0f} eV\n") + + +def add_flux_to_scilog(msg, result): + msg.add_text("Current transmission: ", bold=True) + msg.add_text(f"{result['current_flux']:.2e} ph/s\n") + + msg.add_text("100% transmission: ", bold=True) + msg.add_text(f"{result['full_flux']:.2e} ph/s\n") + +def add_movebeam_to_scilog(msg, result): + msg.add_text("Beam position relative to crosshair: \n", bold=True) + msg.add_text(f"Beam_X: {result['BeamX']:.3f} microns\n") + msg.add_text(f"Beam_Y: {result['BeamY']:.3f} microns\n") + + +def add_beamstop_to_scilog(msg, result): + msg.add_text("Beamstop X: ", bold=True) + msg.add_text(f"{result['bs_x_pos']:.3f} mm\n") + msg.add_text("Beamstop Y: ", bold=True) + msg.add_text(f"{result['bs_y_pos']:.3f} mm\n") + + +def add_collimator_to_scilog(msg, result): + msg.add_text("Collimator X: ", bold=True) + msg.add_text(f"{result['coll_x_pos']:.3f} mm\n") + + msg.add_text("Collimator Y: ", bold=True) + msg.add_text(f"{result['coll_y_pos']:.3f} mm\n") + + msg.add_text("X width: ", bold=True) + msg.add_text(f"{result['coll_x_width']:.3f} mm\n") + + msg.add_text("Y width: ", bold=True) + msg.add_text(f"{result['coll_y_width']:.3f} mm\n") + +def add_beampos_to_scilog(msg, result): + for zoom, pos in result.items(): + msg.add_text(f"{zoom}: ", bold=True) + msg.add_text( + f"X={pos['x']:.1f} px, " + f"Y={pos['y']:.1f} px\n" ) - return "\n".join(lines) \ No newline at end of file +def log_daily_setup_to_scilog(bec, results): + """Send daily setup results to SciLog.""" + scilog_formatters = { + "Beamline energy": add_energy_to_scilog, + "Move beam": add_movebeam_to_scilog, + "Align beamstop": add_beamstop_to_scilog, + "Measure beam position": add_beampos_to_scilog, + "Align collimator": add_collimator_to_scilog, + "Flux": add_flux_to_scilog, + } + msg = bec.messaging.scilog.new() + + msg.add_text("PXII Daily Setup", bold=True) + msg.add_text("\n") + + for step, result in results.items(): + msg.add_text(f"\n{step}\n", bold=True) + + formatter = scilog_formatters.get(step) + + if formatter: + formatter(msg, result) + else: + msg.add_text(str(result)) + + + msg.add_tags(["daily-setup", "pxii"]) + msg.send() + +def preview_daily_setup_scilog(results): + """Preview the daily setup SciLog content without sending.""" + + print("\nPXII Daily Setup\n") + + for step, result in results.items(): + print(step) + + if isinstance(result, dict): + for key, value in result.items(): + if isinstance(value, dict) and "x" in value and "y" in value: + print( + f" {key}: " + f"X={value['x']:.1f}, " + f"Y={value['y']:.1f}" + ) + else: + print(f" {key}: {value}") + else: + print(f" {result}") + + print() \ No newline at end of file diff --git a/pxii_bec/macros/luts/dcm_calibration_20260902.csv b/pxii_bec/macros/luts/dcm_calibration_20260902.csv new file mode 100644 index 0000000..63785e3 --- /dev/null +++ b/pxii_bec/macros/luts/dcm_calibration_20260902.csv @@ -0,0 +1,65 @@ +energy,harmonic,gap,pitch,samcam_x,samcam_y,zoom=800.0 +6000,H3,5.9135,-5.5184,1011,987.4 +6300,H3,6.1926,-5.5135,1006,988.6 +6600,H3,6.4796,-5.5098,1014,991.3 +6900,H3,6.7745,-5.5083,1006,988.3 +7200,H3,7.0913,-5.506,1002,989.1 +7500,H5,4.6331,-5.5042,1004,982.8 +7800,H5,4.783,-5.502,1009,982.2 +8100,H5,4.9292,-5.5005,1011,981.7 +8400,H5,5.0802,-5.498,1019,978 +8700,H5,5.2312,-5.4978,1011,979.4 +9000,H5,5.3823,-5.4967,1011,979.2 +9300,H5,5.5381,-5.4952,1013,977.1 +9600,H5,5.697,-5.4944,1015,973.8 +9900,H5,5.8558,-5.4934,1015,972.4 +10200,H7,4.529,-5.4935,1010,968.3 +10500,H7,4.6331,-5.4921,1010,970 +10800,H7,4.7365,-5.4911,1010,969.1 +11100,H7,4.8437,-5.4913,1006,969.5 +11400,H7,4.9509,-5.4889,1019,968.7 +11700,H7,5.0581,-5.4889,1012,967.4 +12000,H7,5.1654,-5.489,1015,965.4 +12300,H7,5.2726,-5.489,1011,968.2 +12600,H7,5.3847,-5.488,1008,965.8 +12900,H7,5.495,-5.4882,1005,967.8 +13200,H9,4.5498,-5.4873,1013,964.4 +13500,H9,4.6331,-5.4873,1010,965.8 +13800,H9,4.7121,-5.4864,1014,963.7 +14100,H9,4.7949,-5.4864,1008,963.5 +14400,H9,4.8826,-5.4864,1008,964.7 +14700,H9,4.9605,-5.4853,1013,963.3 +15000,H9,5.0433,-5.4852,1011,963.9 +15300,H9,5.1261,-5.4844,1013,964.9 +15600,H9,5.2089,-5.4844,1012,964.2 +15900,H9,5.2949,-5.4836,1012,965.6 +16200,H11,4.565,-5.4838,1006,962.4 +16500,H11,4.6331,-5.483,1012,964 +16800,H11,4.6955,-5.483,1009,963 +17100,H11,4.7631,-5.4821,1014,963.6 +17400,H11,4.8308,-5.4819,1010,961.8 +17700,H11,4.8984,-5.4822,1007,962 +18000,H11,4.9661,-5.4824,1003,960.8 +18300,H11,5.0337,-5.4811,1010,961.9 +18600,H11,5.1014,-5.4811,1010,962 +18900,H13,4.5186,-5.481,1006,960.6 +19200,H13,4.5804,-5.4804,1007,960.3 +19500,H13,4.6282,-5.4803,1012,960.7 +19800,H13,4.6857,-5.48,1013,959.8 +20100,H13,4.7407,-5.4803,1013,960 +20400,H13,4.7993,-5.4802,1012,958.4 +20700,H13,4.856,-5.4801,1013,958.4 +21000,H13,4.9129,-5.48,1012,956.8 +21300,H13,4.9746,-5.4798,1013,953.9 +21600,H13,5.0313,-5.4795,1015,949.9 +21900,H15,4.5338,-5.4796,1010,943.4 +22200,H15,4.5812,-5.4795,1009,940 +22500,H15,4.6331,-5.4773,1026,933.5 +22800,H15,4.6764,-5.4796,1010,943 +23100,H15,4.7355,-5.4795,1000,934.7 +23400,H15,4.6169,-5.5042,990.5,936.9 +23700,H15,4.8339,-5.4789,1001,933.7 +24000,H15,4.7202,-5.4796,996.7,936.3 +24300,H15,4.7823,-5.4789,996.7,936.3 +24600,H15,4.809,-5.479,996.7,936.3 +24900,H17,4.5417,-5.4789,999,944.1 diff --git a/pxii_bec/macros/luts/dcm_calibration_20260903.csv b/pxii_bec/macros/luts/dcm_calibration_20260903.csv new file mode 100644 index 0000000..0c4e913 --- /dev/null +++ b/pxii_bec/macros/luts/dcm_calibration_20260903.csv @@ -0,0 +1,2 @@ +energy,harmonic,gap,pitch,samcam_x,samcam_y,zoom=800.0 +25000,H17,4.5812,-5.4766,956.3,919.7 diff --git a/pxii_bec/macros/luts/dcm_calibration_failures_20260902.csv b/pxii_bec/macros/luts/dcm_calibration_failures_20260902.csv new file mode 100644 index 0000000..5396b71 --- /dev/null +++ b/pxii_bec/macros/luts/dcm_calibration_failures_20260902.csv @@ -0,0 +1,7 @@ +energy,scan,reason +23400,mono_pitch,Peak FWHM spans only 0.00 scan steps (minimum 1.5); centre uncertainty is large (0.000267) +24900,gap,An alarm has occurred. Severity: MAJOR. +ValueError. + An error occurred during 'set' on device 'id_gap'. + +ValueError: 4.4999 outside of user-specified limits diff --git a/pxii_bec/macros/luts/dcm_calibration_failures_20260903.csv b/pxii_bec/macros/luts/dcm_calibration_failures_20260903.csv new file mode 100644 index 0000000..f2ad276 --- /dev/null +++ b/pxii_bec/macros/luts/dcm_calibration_failures_20260903.csv @@ -0,0 +1,3 @@ +energy,scan,reason +25400,gap,User abort. +25400,mono_pitch_exception,User abort. diff --git a/pxii_bec/macros/pxii_parameters.py b/pxii_bec/macros/pxii_parameters.py index 0b35ea5..5555b01 100755 --- a/pxii_bec/macros/pxii_parameters.py +++ b/pxii_bec/macros/pxii_parameters.py @@ -201,7 +201,7 @@ class BPM_Y_Calibration: # @dataclass(frozen=True) class Beamstop: - x_offset = -0.65 + x_offset = -0.55 class CameraZoom(Enum): @@ -246,7 +246,7 @@ class BeamMove: scint_target_y = 969 scint_x_slope = -19450 scint_y_slope = -37800 - scint_tolerance = 10 + scint_tolerance = 15