Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions queue-server/startup_bl531/00_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,23 @@


from bluesky.callbacks.best_effort import BestEffortCallback
from bluesky.callbacks.tiled_writer import TiledWriter
from tiled.server import SimpleTiledServer
from tiled.client import from_uri
#load the api key from env var
import os
api_key = os.getenv("TILED_SINGLE_USER_API_KEY")
if not api_key:
raise ValueError("TILED_SINGLE_USER_API_KEY environment variable is not set.")

# Initialize the Tiled server and client
tiled_client = from_uri("http://127.0.0.1:8000", api_key=api_key)
tw = TiledWriter(tiled_client)
RE.subscribe(tw)

bec = BestEffortCallback()

bec.disable_plots()

# Send all metadata/data captured to the BestEffortCallback.
RE.subscribe(bec)
36 changes: 21 additions & 15 deletions queue-server/startup_bl531/01_devices.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from ophyd import Component, Device, EpicsSignal, EpicsSignalRO
from ophyd import Component, Device, EpicsSignal, EpicsSignalRO, EpicsMotor
#This method of grouping devices should be used for the final production
""" class M101(Device):
m101_pitch_mm = Component(EpicsSignalRO, 'm101_pitch_mm')
Expand All @@ -9,20 +9,26 @@

#Temporary: Manually add each device as a signal

m101_pitch = EpicsSignal("bl531_esp300:m101_pitch_mm", name="m101_pitch")
m101_bend = EpicsSignal("bl531_esp300:m101_bend_um", name="m101_bend")
# m101_pitch = EpicsSignal("bl531_esp300:m101_pitch_mm", name="m101_pitch")
# m101_bend = EpicsSignal("bl531_esp300:m101_bend_um", name="m101_bend")

dcm_angle = EpicsSignal("bl531_xps1:mono_angle_deg", name="dcm_angle")
dcm_height = EpicsSignal("bl531_xps1:mono_height_mm", name="dcm_height")
# dcm_angle = EpicsSignal("bl531_xps1:mono_angle_deg", name="dcm_angle")
# dcm_height = EpicsSignal("bl531_xps1:mono_height_mm", name="dcm_height")

beamstop_horiz = EpicsSignal("bl531_xps2:beamstop_x_mm", name="beamstop_horizon")
beamstop_vert = EpicsSignal("bl531_xps2:beamstop_y_mm", name="beamstop_vert")
beamstop_diode = EpicsSignal("bl201-beamstop:current", name="beamstop_diode")

endstation_slit_inboard = EpicsSignal("DMC02:E", name="endstation_slit_inboard")
endstation_slit_outboard = EpicsSignal("DMC02:F", name="endstation_slit_outboard")
endstation_slit_top = EpicsSignal("DMC02:G", name="endstation_slit_top")
endstation_slit_bottom = EpicsSignal("DMC02:H", name="endstation_slit_bottom")
harm_slit_inboard = EpicsSignal("DMC01:A", name="harm_slit_inboard")
harm_slit_outboard = EpicsSignal("DMC01:B", name="harm_slit_outboard")
harm_slit_top = EpicsSignal("DMC01:C", name="harm_slit_top")
harm_slit_bottom = EpicsSignal("DMC01:D", name="harm_slit_bottom")
beamstop_horiz = EpicsMotor("bl531_xps2:beamstop_x_mm", name="beamstop_horizon")
beamstop_vert = EpicsMotor("bl531_xps2:beamstop_y_mm", name="beamstop_vert")

sampleholder_x = EpicsMotor("bl531_xps2:sample_x_mm", name="sampleholder_x")
sampleholder_y = EpicsMotor("bl531_xps2:sample_y_mm", name="sampleholder_y")


# endstation_slit_inboard = EpicsSignal("DMC02:E", name="endstation_slit_inboard")
# endstation_slit_outboard = EpicsSignal("DMC02:F", name="endstation_slit_outboard")
# endstation_slit_top = EpicsSignal("DMC02:G", name="endstation_slit_top")
# endstation_slit_bottom = EpicsSignal("DMC02:H", name="endstation_slit_bottom")
# harm_slit_inboard = EpicsSignal("DMC01:A", name="harm_slit_inboard")
# harm_slit_outboard = EpicsSignal("DMC01:B", name="harm_slit_outboard")
# harm_slit_top = EpicsSignal("DMC01:C", name="harm_slit_top")
# harm_slit_bottom = EpicsSignal("DMC01:D", name="harm_slit_bottom")
35 changes: 35 additions & 0 deletions queue-server/startup_bl531/02_detectors.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# # Connect to Pilatus detector
#Leave this commented out for now, there's some issue with the detector and we don't want this affecting anything
# import ophyd
# import os
# import numpy as np
# from ophyd import ADComponent
# from ophyd import ImagePlugin
# from ophyd import PilatusDetector
# from ophyd import SingleTrigger
# from ophyd.areadetector.filestore_mixins import FileStoreHDF5IterativeWrite
# from ophyd.areadetector.plugins import HDF5Plugin_V34
# from ophyd import EpicsSignalRO

# # File path configuration
# PILATUS_FILES_ROOT = "/mnt/data531"
# BLUESKY_FILES_ROOT = "/mnt/data531"
# TEST_IMAGE_DIR = "test/pilatus/%Y/%m/%d/"

# # Custom HDF5 plugin with file store integration
# class MyHDF5Plugin(FileStoreHDF5IterativeWrite, HDF5Plugin_V34):
# pass

# # Custom Pilatus detector class
# class MyPilatusDetector(SingleTrigger, PilatusDetector):
# """Pilatus detector with HDF5 file writing capability"""
# image = ADComponent(ImagePlugin, "image1:")
# hdf1 = ADComponent(
# MyHDF5Plugin,
# "HDF1:",
# write_path_template=os.path.join(PILATUS_FILES_ROOT, TEST_IMAGE_DIR),
# read_path_template=os.path.join(BLUESKY_FILES_ROOT, TEST_IMAGE_DIR),
# )

# # Create detector instance
# det = MyPilatusDetector("13PIL1:", name="det")
81 changes: 81 additions & 0 deletions queue-server/startup_bl531/15_plans.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,87 @@
x2x_scan as _x2x_scan,
)

# 2D grid scan for spectroscopy
@parameter_annotation_decorator({
"description": "Scan over a 2d grid to perform spectroscopy",
"parameters": {
"detectors": {
"description": "Required. List of detectors",
"annotation": "typing.List[str]",
"convert_device_names": True,

},
"motor1": {
"description": "Required. First inidividual motor that is moved between the start and stop positions.",
"annotation": "typing.Any",
"convert_device_names": True,

},
"motor1_start": {
"description": "Required. The start position for motor #1, uses the default units of the motor",
"default": 0.0,
"min": 0,
"max": 20,
"step": 0.1,

},
"motor1_stop": {
"description": "Required. The stop position for motor #1, uses the default units of the motor",
"default": 20.0,
"min": 0,
"max": 20,
"step": 0.1,

},
"motor1_num": {
"description": "Required. The number of points that motor #1 will stop at between the start and stop.",
"default": 10,
"min": 0,
"max": 30,
"step": 1,

},
"motor2": {
"description": "Required. Second inidividual motor that is moved between the start and stop positions.",
"annotation": "typing.Any",
"convert_device_names": True,

},
"motor2_start": {
"description": "Required. The start position for motor #2, uses the default units of the motor",
"default": 0.0,
"min": 0,
"max": 20,
"step": 0.1,

},
"motor2_stop": {
"description": "Required. The stop position for motor #2, uses the default units of the motor",
"default": 20.0,
"min": 0,
"max": 20,
"step": 0.1,

},
"motor2_num": {
"description": "Required. The number of points that motor #2 will stop at between the start and stop.",
"default": 10,
"min": 0,
"max": 30,
"step": 1,

},
"snake_axes": {
"description": "Optional boolean. Should the motors follow a snake pattern when moving through the selected locations? Default=True",
"annotation": "bool",
"default": True,
},
}
})
def grid_scan(detectors, motor1, motor2, motor1_start:float=0.0, motor2_start:float=0.0, motor1_stop:float=20.0, motor2_stop:float=20.0, motor1_num:int=10, motor2_num:int=10, snake_axes:bool=True, *, md:dict=None):

yield from _grid_scan(detectors, motor1, motor1_start, motor1_stop, motor1_num, motor2, motor2_start, motor2_stop, motor2_num, snake_axes, md=md)

# 1D scan for endstation x, z or filters
@parameter_annotation_decorator({
"description": "Scan over one multi-motor trajectory.",
Expand Down
Loading