Skip to content

Commit

Permalink
DiamondLightSource/hyperion#1192 call emit from planreactivecallback
Browse files Browse the repository at this point in the history
  • Loading branch information
dperl-dls committed Feb 28, 2024
1 parent d68b932 commit e1a2b51
Show file tree
Hide file tree
Showing 7 changed files with 23 additions and 27 deletions.
4 changes: 2 additions & 2 deletions src/hyperion/experiment_plans/flyscan_xray_centre_plan.py
Original file line number Diff line number Diff line change
Expand Up @@ -340,9 +340,9 @@ def flyscan_xray_centre(
@bpp.run_decorator( # attach experiment metadata to the start document
md={
"subplan_name": GRIDSCAN_OUTER_PLAN,
"trigger_zocalo_on": GRIDSCAN_MAIN_PLAN,
"hyperion_internal_parameters": parameters.json(),
"activate_callbacks": [
"ZocaloCallback",
"GridscanISPyBCallback",
"GridscanNexusFileCallback",
],
Expand Down Expand Up @@ -376,7 +376,7 @@ def run_gridscan_and_move_and_tidy(fgs_composite, params):
)

parameters = GridscanInternalParameters(**external_parameters.from_file())
subscriptions = XrayCentreCallbackCollection.setup()
subscriptions = XrayCentreCallbackCollection()

context = setup_context(wait_for_connection=True)
composite = create_devices(context)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -270,9 +270,9 @@ def panda_flyscan_xray_centre(
@bpp.run_decorator( # attach experiment metadata to the start document
md={
"subplan_name": GRIDSCAN_OUTER_PLAN,
"trigger_zocalo_on": GRIDSCAN_MAIN_PLAN,
"hyperion_internal_parameters": parameters.json(),
"activate_callbacks": [
"ZocaloCallback",
"GridscanISPyBCallback",
"GridscanNexusFileCallback",
],
Expand Down
2 changes: 1 addition & 1 deletion src/hyperion/experiment_plans/rotation_scan_plan.py
Original file line number Diff line number Diff line change
Expand Up @@ -266,9 +266,9 @@ def rotation_scan(composite: RotationScanComposite, parameters: Any) -> MsgGener
@bpp.run_decorator( # attach experiment metadata to the start document
md={
"subplan_name": ROTATION_OUTER_PLAN,
"trigger_zocalo_on": ROTATION_PLAN_MAIN,
"hyperion_internal_parameters": parameters.json(),
"activate_callbacks": [
"ZocaloCallback",
"RotationISPyBCallback",
"RotationNexusFileCallback",
],
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from __future__ import annotations

from abc import ABC, abstractmethod
from abc import ABC
from dataclasses import fields
from typing import Any, Generator

Expand All @@ -14,19 +14,12 @@ class AbstractPlanCallbackCollection(ABC):
@subs_decorator(list(callback_collection)) to subscribe them to your plan in order.
"""

@classmethod
@abstractmethod
def setup(cls) -> AbstractPlanCallbackCollection: ...

def __iter__(self) -> Generator[CallbackBase, Any, None]:
for field in fields(self): # type: ignore # subclasses must be dataclass
yield getattr(self, field.name)


class NullPlanCallbackCollection(AbstractPlanCallbackCollection):
@classmethod
def setup(cls):
return cls()

def __iter__(self):
yield from ()
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ def __init__(
for self.ispyb_ids."""
ISPYB_LOGGER.debug("Initialising ISPyB callback")
super().__init__(log=ISPYB_LOGGER, emit=emit)
self.emit_cb = emit # to avoid GC; base class only holds a WeakRef
self.params: GridscanInternalParameters | RotationInternalParameters | None = (
None
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class will be activated, and on recieving the stop document for the
self.activity_uid = 0
self.log = log

def _run_activity_gated(self, func, doc, override=False):
def _run_activity_gated(self, name: str, func, doc, override=False):
# Runs `func` if self.active is True or overide is true. Override can be used
# to run the function even after setting self.active to False, i.e. in the last
# handler of a run.
Expand All @@ -46,7 +46,7 @@ def _run_activity_gated(self, func, doc, override=False):
if not running_gated_function:
return doc
try:
return func(doc)
return self.emit(name, func(doc))
except Exception as e:
self.log.exception(e)
raise
Expand All @@ -60,21 +60,25 @@ def start(self, doc: RunStart) -> RunStart | None:
f"{'' if activate else 'not'} activating {type(self).__name__}"
)
self.activity_uid = doc.get("uid")
return self._run_activity_gated(self.activity_gated_start, doc)
return self._run_activity_gated("start", self.activity_gated_start, doc)

def descriptor(self, doc: EventDescriptor) -> EventDescriptor | None:
return self._run_activity_gated(self.activity_gated_descriptor, doc)
return self._run_activity_gated(
"descriptor", self.activity_gated_descriptor, doc
)

def event(self, doc: Event) -> Event:
return self._run_activity_gated(self.activity_gated_event, doc)
def event(self, doc: Event) -> Event | None:
return self._run_activity_gated("event", self.activity_gated_event, doc)

def stop(self, doc: RunStop) -> RunStop | None:
do_stop = self.active
if doc.get("run_start") == self.activity_uid:
self.active = False
self.activity_uid = 0
return (
self._run_activity_gated(self.activity_gated_stop, doc, override=True)
self._run_activity_gated(
"stop", self.activity_gated_stop, doc, override=True
)
if do_stop
else doc
)
Expand All @@ -85,7 +89,7 @@ def activity_gated_start(self, doc: RunStart) -> RunStart | None:
def activity_gated_descriptor(self, doc: EventDescriptor) -> EventDescriptor | None:
return doc

def activity_gated_event(self, doc: Event) -> Event:
def activity_gated_event(self, doc: Event) -> Event | None:
return doc

def activity_gated_stop(self, doc: RunStop) -> RunStop | None:
Expand Down
12 changes: 5 additions & 7 deletions src/hyperion/external_interaction/callbacks/zocalo_callback.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,19 @@

from typing import TYPE_CHECKING, Optional

from bluesky.callbacks import CallbackBase
from dodal.devices.zocalo import (
ZocaloTrigger,
)

from hyperion.external_interaction.callbacks.plan_reactive_callback import (
PlanReactiveCallback,
)
from hyperion.external_interaction.exceptions import ISPyBDepositionNotMade
from hyperion.log import ISPYB_LOGGER

if TYPE_CHECKING:
from event_model.documents import RunStart, RunStop


class ZocaloCallback(PlanReactiveCallback):
class ZocaloCallback(CallbackBase):
"""Callback class to handle the triggering of Zocalo processing.
Sends zocalo a run_start signal on receiving a start document for the specified
sub-plan, and sends a run_end signal on receiving a stop document for the same plan.
Expand All @@ -35,10 +33,10 @@ def _reset_state(self):
def __init__(
self,
):
super().__init__(ISPYB_LOGGER)
super().__init__()
self._reset_state()

def activity_gated_start(self, doc: RunStart):
def start(self, doc: RunStart):
ISPYB_LOGGER.info("Zocalo handler received start document.")
if triggering_plan := doc.get("trigger_zocalo_on"):
self.triggering_plan = triggering_plan
Expand All @@ -56,7 +54,7 @@ def activity_gated_start(self, doc: RunStart):
f"No ISPyB IDs received by the start of {self.triggering_plan=}"
)

def activity_gated_stop(self, doc: RunStop):
def stop(self, doc: RunStop):
if doc.get("run_start") == self.run_uid:
ISPYB_LOGGER.info(
f"Zocalo handler received stop document, for run {doc.get('run_start')}."
Expand Down

0 comments on commit e1a2b51

Please sign in to comment.