start of beamtime p21741

This commit is contained in:
2024-05-07 11:29:52 +02:00
parent f9d036bb9e
commit a65e9070eb
8 changed files with 644 additions and 28 deletions

View File

@ -0,0 +1,19 @@
from slic.core.acquisition import SFAcquisition
from .channels import detectors_with_config, detectors
from .channels import bs_channels_jf_direct_beam, bs_channels_pbps_snapshot
from .channels import pvs_cristallina, pvs_bernina, bs_channels_DCM_Bernina
instrument = "cristallina"
pgroup = "p21569"
acqui_bill = SFAcquisition(
instrument,
pgroup,
default_channels=bs_channels_pbps_snapshot,
default_pvs=pvs_cristallina,
default_detectors=detectors,
rate_multiplicator=1,
)

319
exp_temp/kb_focusing.py Normal file
View File

@ -0,0 +1,319 @@
from cam_server import PipelineClient
from cam_server.utils import get_host_port_from_stream_address
from bsread import source, SUB
from epics import PV
import numpy as np
import time
import datetime
from pathlib import Path
import json
from loguru import logger
wait_time_benders = 1.0 # can probably be reduced as we wait for the move to finish
wait_time_aperture = 0.5 # can probably be reduced as we wait for the move to finish
def get_position_from_pipeline(pip_instance_id, data_field_name, n_pulses=1):
pipeline_client = PipelineClient()
stream_address = pipeline_client.get_instance_stream(pip_instance_id)
stream_host, stream_port = get_host_port_from_stream_address(stream_address)
with source(host=stream_host, port=stream_port, mode=SUB) as input_stream:
sum_pos = 0
for i in np.arange(n_pulses):
input_stream.connect()
message = input_stream.receive()
pos = message.data.data[data_field_name].value
sum_pos = sum_pos + pos
mean_pos = sum_pos / n_pulses
return mean_pos
def evaluate_bender_scan():
""" Evaluation of data is in /sf/cristallina/applications/optic_tools/KBs
"""
pass
def kbV_focusing_acquire(
bender_us=[1.0, 1.2, 1.49, 1.54, 1.59],
bender_ds=[1.1, 1.3, 1.5, 1.6, 1.79, 1.84],
bender_us_start=1.1,
bender_ds_start=1.33,
aperture=[-0.3, 0, 0.3],
aperture_width=0.15,
aperture_height=1.2,
n_pulses=1,
):
""" Vertical KB mirror focusing acquisition with default parameters.
"""
return kb_focusing_acquire(
direction="vertical",
bender_us=bender_us,
bender_ds=bender_ds,
bender_us_start=bender_us_start,
bender_ds_start=bender_ds_start,
aperture=aperture,
aperture_size=aperture_width,
aperture_size_pendicular=aperture_height,
n_pulses=n_pulses,
)
def kbH_focusing_acquire(
bender_us=[1.55, 1.6, 1.7],
bender_ds=[1.7, 1.8, 1.9],
bender_us_start=1.2, # should be 0.3 below the maximum focus
bender_ds_start=1.5, # should be 0.3 below the maximum focus
aperture=[0.18, 0.48, 0.78],
aperture_height=0.15,
aperture_width=1.8,
n_pulses=1,
):
""" Horizontal KB mirror focusing acquisition with default parameters.
"""
return kb_focusing_acquire(
direction="horizontal",
bender_us=bender_us,
bender_ds=bender_ds,
bender_us_start=bender_us_start,
bender_ds_start=bender_ds_start,
aperture=aperture,
aperture_size=aperture_height,
aperture_size_pendicular=aperture_width,
n_pulses=n_pulses,
)
def kb_focusing_acquire(
direction="vertical",
bender_us=[1.49, 1.54, 1.59],
bender_ds=[1.79, 1.84, 1.89],
bender_us_start=1.29,
bender_ds_start=1.59,
aperture=[-0.3, 0, 0.3],
aperture_size=0.15,
aperture_size_pendicular=1.2,
n_pulses=1,
):
""" KB mirror focusing acquisition routine for Cristallina.
TODO: - split this up into separate routines
- Make inner loop a generator, yielding: bender_us_rb, bender_ds_rb, beam_positions
Input into live analysis.
"""
# Benders
if bender_us_start >= np.min(bender_us) - 0.3:
bender_us_start = max(0, np.min(bender_us) - 0.3)
if bender_ds_start >= np.min(bender_ds) - 0.3:
bender_ds_start = max(0, np.min(bender_ds) - 0.3)
bender_us = np.sort(bender_us)
bender_ds = np.sort(bender_ds)
KBV_NAME = "SAROP31-OKBV153"
KBH_NAME = "SAROP31-OKBH154"
if direction == "vertical":
kb_name = KBV_NAME
elif direction == "horizontal":
kb_name = KBH_NAME
BU = PV(kb_name + ":BU.VAL")
BD = PV(kb_name + ":BD.VAL")
# TODO: is the separation necessary?
BU_RB = PV(kb_name + ":BU.VAL")
BD_RB = PV(kb_name + ":BD.VAL")
# Aperture
aperture = np.sort(aperture)
APU_NAME = "SAROP31-OAPU149"
if direction == "vertical":
APU_CENTER = PV(APU_NAME + ":MOTOR_Y.VAL")
APU_CENTER_RB = PV(APU_NAME + ":MOTOR_Y.RBV")
APU_SIZE = PV(APU_NAME + ":MOTOR_H.VAL")
APU_SIZE_RB = PV(APU_NAME + ":MOTOR_H.RBV")
APU_SIZE_PERPENDICULAR = PV(APU_NAME + ":MOTOR_W.VAL")
APU_SIZE_PERPENDICULAR_RB = PV(APU_NAME + ":MOTOR_W.RBV")
APU_CENTER_PERPENDICULAR = PV(APU_NAME + ":MOTOR_X.VAL")
APU_CENTER_PERPENDICULAR_RB = PV(APU_NAME + ":MOTOR_X.RBV")
# Camera field name
data_field_name = "y_fit_mean"
elif direction == "horizontal":
APU_CENTER = PV(APU_NAME + ":MOTOR_X.VAL")
APU_SIZE = PV(APU_NAME + ":MOTOR_W.VAL")
APU_CENTER_RB = PV(APU_NAME + ":MOTOR_X.RBV")
APU_SIZE_RB = PV(APU_NAME + ":MOTOR_W.RBV")
APU_SIZE_PERPENDICULAR = PV(APU_NAME + ":MOTOR_H.VAL")
APU_SIZE_PERPENDICULAR_RB = PV(APU_NAME + ":MOTOR_H.RBV")
APU_CENTER_PERPENDICULAR = PV(APU_NAME + ":MOTOR_Y.VAL")
APU_CENTER_PERPENDICULAR_RB = PV(APU_NAME + ":MOTOR_Y.RBV")
# Camera field name
data_field_name = "x_fit_mean"
# Camera
CAMERA_NAME = "SARES30-CAMS156-XE"
pip_instance_id = CAMERA_NAME + "_sp"
### Acquisition start
apu_center_ref = APU_CENTER_RB.get()
apu_size_ref = APU_SIZE_RB.get()
apu_size_perp_ref = APU_SIZE_PERPENDICULAR.get()
apu_center_perp_ref = APU_CENTER_PERPENDICULAR.get()
logger.info("BU/BD sent to start")
BU.put(bender_us_start, wait=False)
BD.put(bender_ds_start, wait=False)
APU_SIZE.put(aperture_size, wait=False)
APU_SIZE_PERPENDICULAR.put(aperture_size_pendicular, wait=False)
APU_CENTER.put(aperture[0], wait=False)
BU.put(bender_us_start, wait=True)
BD.put(bender_ds_start, wait=True)
time.sleep(wait_time_benders)
logger.info(f"BU to start: {bender_us_start:6.3f}")
logger.info(f"BD to start: {bender_ds_start:6.3f}")
bender_us_rb = []
bender_ds_rb = []
beam_positions = []
bender_scan_data = {}
datestr, timestr = generate_date_and_time_str()
for bu in bender_us:
logger.info("")
BU.put(bu, wait=False)
for bd in bender_ds:
BU.put(bu, wait=False)
BD.put(bd, wait=False)
BU.put(bu, wait=True)
BD.put(bd, wait=True)
time.sleep(wait_time_benders)
logger.info(f" BU / BD positions = {bu:6.3f} / {bd:6.3f}")
bender_us_rb.append(BU_RB.get())
bender_ds_rb.append(BD_RB.get())
beam_pos = []
for apu in aperture:
APU_CENTER.put(apu, wait=True)
time.sleep(wait_time_aperture)
beam_pos_apu = get_position_from_pipeline(pip_instance_id, data_field_name, n_pulses=n_pulses)
logger.info(f" Aperture position = {apu:6.3f}; Beam position = {beam_pos_apu:6.3f}")
beam_pos.append(beam_pos_apu)
time.sleep(wait_time_aperture)
APU_CENTER.put(aperture[0], wait=False)
beam_positions.append(beam_pos)
BD.put(bender_ds_start, wait=True)
logger.info("")
logger.info(f"BD to start: {bender_ds_start:6.3f}")
time.sleep(wait_time_benders)
# save intermediate data
bender_scan_data["bender_us"] = bender_us_rb
bender_scan_data["bender_ds"] = bender_ds_rb
bender_scan_data["beam_positions"] = beam_positions
fpath = save_focusing_data(bender_scan_data, direction=direction, timestr=timestr, datestr=datestr)
out_fpath = convert_focusing_to_bender_data(fpath)
logger.info(f"BU to start: {bender_us_start:6.3f}")
APU_SIZE.put(apu_size_ref, wait=False)
APU_CENTER.put(apu_center_ref, wait=False)
APU_SIZE_PERPENDICULAR.put(apu_size_perp_ref, wait=False)
APU_CENTER_PERPENDICULAR.put(apu_center_perp_ref, wait=False)
BU.put(bender_us_start, wait=False)
BD.put(bender_ds_start, wait=False)
logger.info(f"Data saved to: {out_fpath}")
logger.info("Done")
return bender_scan_data
def generate_date_and_time_str():
t = datetime.datetime.now()
datestr = t.date().isoformat()
timestr = t.isoformat(timespec='minutes')
return datestr, timestr
def save_focusing_data(bender_scan_data, direction="unknown", timestr=None, datestr=None, beamline_directory="/sf/cristallina/applications/beamline/snapshots/KBs/"):
""" Saves bender focusing data to json for analysis in beamline directory.
"""
bender_scan_data["comment"] = "Cristallina bender focusing data"
if timestr is None:
datestr, timestr = generate_date_and_time_str()
directory = Path(beamline_directory) / datestr
directory.mkdir(parents=True, exist_ok=True)
fpath = directory / f"C_{timestr}_{direction}.json"
with open(fpath, "w") as f:
json.dump(bender_scan_data, f)
return fpath
def convert_focusing_to_bender_data(focusing_json_file):
""" Converts focusing data to text array for further processing.
"""
fpath = Path(focusing_json_file)
with open(fpath, "r") as f:
focusing_data = json.loads(f.read())
nrows = len(focusing_data['bender_us'])
arr = np.empty((nrows, 5))
arr[:, 0] = focusing_data['bender_us']
arr[:, 1] = focusing_data['bender_ds']
arr[:, 2:] = focusing_data['beam_positions']
Diff1 = arr[:,2] - arr[:,3]
Diff2 = arr[:,4] - arr[:,3]
# extend array with difference columns
arr = np.c_[arr, Diff1]
arr = np.c_[arr, Diff2]
out_fpath = fpath.with_suffix(".dat")
np.savetxt(out_fpath, arr)
return out_fpath

View File

@ -0,0 +1,13 @@
import requests
import numpy as np
from loguru import logger
def start_sequence(n: int = 100, pulse_phase: float = np.pi/8):
parameters = {"n":n, "pulse_phase":pulse_phase}
url = "http://oscillations.psi.ch:8000/pulse"
r = requests.get(url, params=parameters)
d = r.json()
return d['pids']