Skip to content
Draft
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
35 changes: 35 additions & 0 deletions docs/developer/hyperion/hyperion-blueapi.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
Hyperion on BlueAPI
===================

This document describes the migration of Hyperion from a monolithic service that contains its own application server
and is only partially dependent on BlueAPI,
to a standard BlueAPI application deployment.

Architecture
------------

Hyperion on BlueAPI consists of two components:

* hyperion-blueapi: This is intended to ultimately be a standard blueapi installation, consisting of a beamline
module and a dodal plan module. In the interim, deployment may vary from the standard method until such time as
monolithic operation can be desupported. ``hyperion-blueapi`` exposes a minimal set of bluesky plans for UDC data
collection.

* hyperion-supervisor: This will be a separate service that is responsible for fetching instructions from
Agamemnon, decoding them and sending corresponding requests to ``hyperion-blueapi`` for execution. The supervisor
also monitors the state of ``hyperion-blueapi``, manages the Hyperion baton and provides endpoints for status
monitoring.

Deployment
----------

``hyperion-blueapi`` is automatically available in a standard Hyperion deployment.

Launching
---------

``hyperion-blueapi`` can be launched in using the ``run_hyperion.sh`` script, using the ``--blueapi`` option:

::

./run_hyperion.sh --beamline=i03 --dev --blueapi
26 changes: 19 additions & 7 deletions run_hyperion.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ START=1
IN_DEV=false
MODE=gda

CONFIG_DIR=`dirname $0`/src/mx_bluesky/hyperion
BLUEAPI_CONFIG=$CONFIG_DIR/blueapi_config.yaml

for option in "$@"; do
case $option in
-b=*|--beamline=*)
Expand All @@ -22,10 +25,14 @@ for option in "$@"; do
;;
--dev)
IN_DEV=true
BLUEAPI_CONFIG=$CONFIG_DIR/blueapi_dev_config.yaml
;;
--udc)
MODE=udc
;;
--blueapi)
MODE=blueapi
;;
--help|--info|--h)
source .venv/bin/activate
echo "`basename $0` [options]"
Expand All @@ -38,10 +45,9 @@ Options:
--stop Used to stop a currently running instance of Hyperion. Will override any other operations
options.
--no-start Used to specify that the script should be run without starting the server.
--skip-startup-connection
Do not connect to devices at startup
--dev Enable dev mode to run from a local workspace on a development machine.
--udc Start hyperion in UDC mode instead of taking commands from GDA
--blueapi Start hyperion in blueapi mode instead of taking commands from GDA
--help This help

By default this script will start an Hyperion server unless the --no-start flag is specified.
Expand All @@ -59,6 +65,7 @@ kill_active_apps () {
echo "Killing active instances of hyperion and hyperion-callbacks..."
pkill -e -f "python.*hyperion"
pkill -e -f "SCREEN.*hyperion"
blueapi controller stop 2>/dev/null
echo "done."
}

Expand Down Expand Up @@ -120,8 +127,6 @@ if [[ $START == 1 ]]; then

source .venv/bin/activate

#Add future arguments here

declare -A h_and_cb_args=( ["IN_DEV"]="$IN_DEV" )
declare -A h_and_cb_arg_strings=( ["IN_DEV"]="--dev" )

Expand All @@ -136,16 +141,23 @@ if [[ $START == 1 ]]; then
done

unset PYEPICS_LIBCA
echo "Starting hyperion with hyperion $h_commands, start_log is $start_log_path"
hyperion `echo $h_commands;`>$start_log_path 2>&1 &
if [ $MODE = "blueapi" ]; then
echo "Starting hyperion in blueapi mode, start log is $start_log_path"
blueapi --config $BLUEAPI_CONFIG serve > $start_log_path 2>&1 &
HEALTHCHECK_ENDPOINT="healthz"
else
echo "Starting hyperion with hyperion $h_commands, start_log is $start_log_path"
hyperion `echo $h_commands;`>$start_log_path 2>&1 &
HEALTHCHECK_ENDPOINT="status"
fi
echo "Starting hyperion-callbacks with hyperion-callbacks $cb_commands, start_log is $callback_start_log_path"
hyperion-callbacks `echo $cb_commands;`>$callback_start_log_path 2>&1 &
echo "$(date) Waiting for Hyperion to start"

for i in {1..30}
do
echo "$(date)"
curl --head -X GET http://localhost:5005/status >/dev/null
curl --head -X GET http://localhost:5005/$HEALTHCHECK_ENDPOINT >/dev/null
ret_value=$?
if [ $ret_value -ne 0 ]; then
sleep 1
Expand Down
19 changes: 19 additions & 0 deletions src/mx_bluesky/hyperion/blueapi_config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
env:
sources:
- kind: dodal
module: dodal.beamlines.i03
- kind: planFunctions
module: mx_bluesky.hyperion.experiment_plans.load_centre_collect_full_plan
events:
broadcast_status_events: false
api:
url: http://localhost:5005
cors:
allow_credentials: True
origins:
- "*"
logging:
graylog:
url: "tcp://graylog-log-target.diamond.ac.uk:12232"
enabled: true

17 changes: 17 additions & 0 deletions src/mx_bluesky/hyperion/blueapi_dev_config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
env:
sources:
- kind: dodal
module: dodal.beamlines.i03
mock: true
- kind: planFunctions
module: mx_bluesky.hyperion.blueapi_plans
events:
broadcast_status_events: false
api:
url: http://localhost:5005
cors:
allow_credentials: True
origins:
- "*"
logging:
level: DEBUG
77 changes: 77 additions & 0 deletions src/mx_bluesky/hyperion/blueapi_plans/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
"""
This module contains the bluesky plan entry points for use with hyperion-blueapi.
The json schema and documentation therein generated by the blueapi /plans endpoint
from this file constitutes the hyperion-blueapi interface to the hyperion supervisor
process.
"""

from bluesky.utils import MsgGenerator
from dodal.common import inject
from dodal.devices.aperturescatterguard import ApertureScatterguard
from dodal.devices.motors import XYZStage
from dodal.devices.robot import BartRobot
from dodal.devices.smargon import Smargon

from mx_bluesky.common.device_setup_plans.robot_load_unload import (
robot_unload as _robot_unload,
)
from mx_bluesky.common.experiment_plans.inner_plans.udc_default_state import (
UDCDefaultDevices,
)
from mx_bluesky.common.experiment_plans.inner_plans.udc_default_state import (
move_to_udc_default_state as _move_to_udc_default_state,
)
from mx_bluesky.hyperion.experiment_plans.load_centre_collect_full_plan import (
LoadCentreCollectComposite,
)
from mx_bluesky.hyperion.experiment_plans.load_centre_collect_full_plan import (
load_centre_collect_full as _load_centre_collect_full,
)
from mx_bluesky.hyperion.parameters.load_centre_collect import LoadCentreCollect

__all__ = [
"LoadCentreCollectComposite",
"LoadCentreCollect",
"UDCDefaultDevices",
"load_centre_collect",
"move_to_udc_default_state",
"robot_unload",
]


def load_centre_collect(
parameters: LoadCentreCollect, composite: LoadCentreCollectComposite = inject()
) -> MsgGenerator:
"""
Attempt a complete data collection experiment, consisting of the following:
* Load the sample if necessary
* Move to the specified goniometer start angles
* Perform optical centring, then X-ray centring
* If X-ray centring finds one or more diffracting centres then for each centre
that satisfies the chosen selection function,
move to that centre and do a collection with the specified parameters.
"""
yield from _load_centre_collect_full(composite, parameters)


def robot_unload(
visit: str,
robot: BartRobot = inject("robot"),
smargon: Smargon = inject("smargon"),
aperture_scatterguard: ApertureScatterguard = inject("aperture_scatterguard"),
lower_gonio: XYZStage = inject("lower_gonio"),
) -> MsgGenerator:
"""
Unload the currently mounted pin into the location that it was loaded from.
This is to be invoked as the final step upon successful completion of the UDC queue.
"""
yield from _robot_unload(robot, smargon, aperture_scatterguard, lower_gonio, visit)


def move_to_udc_default_state(
composite: UDCDefaultDevices = inject(),
) -> MsgGenerator:
"""
Move beamline hardware to known positions prior to UDC start.
"""
yield from _move_to_udc_default_state(composite)
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "move_to_udc_default_state",
"params": {},
"instrument_session": "cm12345-1"
}
7 changes: 7 additions & 0 deletions tests/test_data/hyperion_blueapi/robot_unload.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"name": "robot_unload",
"params": {
"visit": "cm12345-1"
},
"instrument_session": "cm12345-1"
}
56 changes: 56 additions & 0 deletions tests/test_data/hyperion_blueapi/test_load_centre_collect.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
{
"name": "load_centre_collect",
"params": {
"parameters": {
"parameter_model_version": "5.0.0",
"beamline": "BL03S",
"det_dist_to_beam_converter_path": "tests/test_data/test_lookup_table.txt",
"insertion_prefix": "SR03S",
"visit": "cm31105-4",
"detector_distance_mm": 255,
"sample_id": 12345,
"sample_puck": 40,
"sample_pin": 3,
"robot_load_then_centre": {
"storage_directory": "{tmp_data}/123458/xraycentring",
"file_name": "robot_load_centring_file",
"comment": "Robot load and centre",
"exposure_time_s": 0.004,
"use_roi_mode": false,
"demand_energy_ev": 11100,
"run_number": 0,
"panda_runup_distance_mm": 0.17,
"box_size_um": 20
},
"multi_rotation_scan": {
"comment": "Rotation",
"storage_directory": "{tmp_data}/123458/",
"file_name": "file_name",
"exposure_time_s": 0.004,
"selected_aperture": "SMALL_APERTURE",
"transmission_frac": 1.0,
"demand_energy_ev": 11100,
"rotation_increment_deg": 0.1,
"shutter_opening_time_s": 0.6,
"snapshot_omegas_deg": [
0,
90,
180,
270
],
"run_number": 1,
"rotation_scans": [
{
"rotation_axis": "omega",
"rotation_direction": "Negative",
"scan_width_deg": 180.0,
"omega_start_deg": 0,
"phi_start_deg": 0.47,
"chi_start_deg": 23.85
}
]
}
}
},
"instrument_session": "cm12345-1"
}
Loading