Skip to content
This repository has been archived by the owner on Sep 2, 2024. It is now read-only.

Commit

Permalink
(#1017) Read barcode and put in ispyb on robot load
Browse files Browse the repository at this point in the history
  • Loading branch information
DominicOram committed Apr 4, 2024
1 parent d4d1608 commit 7f5caf3
Show file tree
Hide file tree
Showing 7 changed files with 88 additions and 5 deletions.
4 changes: 4 additions & 0 deletions src/hyperion/experiment_plans/robot_load_then_centre_plan.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,10 @@ def robot_load():

yield from bps.wait("robot_load")

yield from bps.create(name=CONST.PLAN.ROBOT_LOAD)
yield from bps.read(composite.robot.barcode)
yield from bps.save()

yield from wait_for_smargon_not_disabled(composite.smargon)

yield from robot_load()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

from typing import TYPE_CHECKING, Dict, Optional

from event_model.documents import EventDescriptor

from hyperion.external_interaction.callbacks.common.ispyb_mapping import (
get_proposal_and_session_from_visit_string,
get_visit_string_from_path,
Expand All @@ -17,7 +19,7 @@
from hyperion.parameters.constants import CONST

if TYPE_CHECKING:
from event_model.documents import EventDescriptor, RunStart, RunStop
from event_model.documents import Event, EventDescriptor, RunStart, RunStop


class RobotLoadISPyBCallback(PlanReactiveCallback):
Expand All @@ -30,7 +32,7 @@ def __init__(self) -> None:
self.expeye = ExpeyeInteraction()

def activity_gated_start(self, doc: RunStart):
ISPYB_LOGGER.debug("ISPyB robot load handler received start document.")
ISPYB_LOGGER.debug("ISPyB robot load callback received start document.")
if doc.get("subplan_name") == CONST.PLAN.ROBOT_LOAD:
self.run_uid = doc.get("uid")
assert isinstance(metadata := doc.get("metadata"), Dict)
Expand All @@ -47,12 +49,26 @@ def activity_gated_start(self, doc: RunStart):
)
return super().activity_gated_start(doc)

def activity_gated_descriptor(self, doc: EventDescriptor) -> EventDescriptor | None:
self.descriptors[doc["uid"]] = doc

def activity_gated_event(self, doc: Event) -> Event | None:
event_descriptor = self.descriptors.get(doc["descriptor"])
if event_descriptor and event_descriptor.get("name") == CONST.PLAN.ROBOT_LOAD:
assert (
self.action_id is not None
), "ISPyB Robot load callback event called unexpectedly"
barcode = doc["data"]["robot-barcode"]
self.expeye.update_barcode(self.action_id, barcode)

return super().activity_gated_event(doc)

def activity_gated_stop(self, doc: RunStop) -> RunStop | None:
ISPYB_LOGGER.debug("ISPyB robot load handler received stop document.")
ISPYB_LOGGER.debug("ISPyB robot load callback received stop document.")
if doc.get("run_start") == self.run_uid:
assert (
self.action_id is not None
), "ISPyB Robot load handler stop called unexpectedly"
), "ISPyB Robot load callback stop called unexpectedly"
exit_status = (
doc.get("exit_status") or "Exit status not available in stop document!"
)
Expand Down
6 changes: 6 additions & 0 deletions src/hyperion/external_interaction/ispyb/exp_eye_store.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,12 @@ def start_load(
response = self._send_and_get_response(url, data, post)
return response["robotActionId"]

def update_barcode(self, action_id: RobotActionID, barcode: str):
url = self.base_url + self.UPDATE_ROBOT_ACTION.format(action_id=action_id)

data = {"sampleBarcode": barcode}
self._send_and_get_response(url, data, patch)

def end_load(self, action_id: RobotActionID, status: str, reason: str):
url = self.base_url + self.UPDATE_ROBOT_ACTION.format(action_id=action_id)

Expand Down
6 changes: 5 additions & 1 deletion tests/system_tests/external_interaction/test_exp_eye_dev.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,11 @@ def test_start_and_end_robot_load():

robot_action_id = expeye.start_load("cm37235", 2, 5289780, 40, 3)

sleep(1)
sleep(0.5)

expeye.update_barcode(robot_action_id, "test_barcode")

sleep(0.5)

expeye.end_load(robot_action_id, "fail", "Oh no!")

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,9 @@ def test_when_prepare_for_robot_load_called_then_moves_as_expected(
@patch(
"hyperion.external_interaction.callbacks.robot_load.ispyb_callback.ExpeyeInteraction.end_load"
)
@patch(
"hyperion.external_interaction.callbacks.robot_load.ispyb_callback.ExpeyeInteraction.update_barcode"
)
@patch(
"hyperion.external_interaction.callbacks.robot_load.ispyb_callback.ExpeyeInteraction.start_load"
)
Expand All @@ -319,6 +322,7 @@ def test_when_prepare_for_robot_load_called_then_moves_as_expected(
def test_given_ispyb_callback_attached_when_robot_load_then_centre_plan_called_then_ispyb_deposited(
mock_centring_plan: MagicMock,
start_load: MagicMock,
update_barcode: MagicMock,
end_load: MagicMock,
robot_load_composite: RobotLoadThenCentreComposite,
robot_load_then_centre_params: RobotLoadThenCentreInternalParameters,
Expand All @@ -332,4 +336,5 @@ def test_given_ispyb_callback_attached_when_robot_load_then_centre_plan_called_t
RE(robot_load_then_centre(robot_load_composite, robot_load_then_centre_params))

start_load.assert_called_once_with("cm31105", 4, "12345", 40, 3)
update_barcode.assert_called_once_with(action_id, "BARCODE")
end_load.assert_called_once_with(action_id, "success", "")
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import bluesky.preprocessors as bpp
import pytest
from bluesky.run_engine import RunEngine
from dodal.devices.robot import BartRobot

from hyperion.external_interaction.callbacks.robot_load.ispyb_callback import (
RobotLoadISPyBCallback,
Expand Down Expand Up @@ -90,3 +91,35 @@ def test_given_end_called_but_no_start_then_exception_raised(end_load):
with pytest.raises(AssertionError):
callback.activity_gated_stop({"run_uid": None}) # type: ignore
end_load.assert_not_called()


@patch(
"hyperion.external_interaction.callbacks.robot_load.ispyb_callback.ExpeyeInteraction.end_load"
)
@patch(
"hyperion.external_interaction.callbacks.robot_load.ispyb_callback.ExpeyeInteraction.start_load"
)
@patch(
"hyperion.external_interaction.callbacks.robot_load.ispyb_callback.ExpeyeInteraction.update_barcode"
)
def test_given_plan_reads_barcode_then_data_put_in_ispyb(
update_barcode: MagicMock,
start_load: MagicMock,
end_load: MagicMock,
robot: BartRobot,
):
RE = RunEngine()
RE.subscribe(RobotLoadISPyBCallback())
start_load.return_value = ACTION_ID

@bpp.run_decorator(md=metadata)
def my_plan():
yield from bps.create(name=CONST.PLAN.ROBOT_LOAD)
yield from bps.read(robot.barcode)
yield from bps.save()

RE(my_plan())

start_load.assert_called_once_with("cm31105", 4, SAMPLE_ID, SAMPLE_PUCK, SAMPLE_PIN)
update_barcode.assert_called_once_with(ACTION_ID, "BARCODE")
end_load.assert_called_once_with(ACTION_ID, "success", "")
Original file line number Diff line number Diff line change
Expand Up @@ -118,3 +118,18 @@ def test_given_server_does_not_respond_when_end_load_called_then_error(mock_patc
expeye_interactor = ExpeyeInteraction()
with pytest.raises(ISPyBDepositionNotMade):
expeye_interactor.end_load(1, "", "")


@patch("hyperion.external_interaction.ispyb.exp_eye_store.patch")
def test_when_update_barcode_called_with_success_then_correct_expected_url_posted_to_with_expected_data(
mock_patch,
):
expeye_interactor = ExpeyeInteraction()
expeye_interactor.update_barcode(3, "test")

mock_patch.assert_called_once()
assert mock_patch.call_args.args[0] == "http://blah/core/robot-actions/3"
expected_data = {
"sampleBarcode": "test",
}
assert mock_patch.call_args.kwargs["json"] == expected_data

0 comments on commit 7f5caf3

Please sign in to comment.