Skip to content

Commit

Permalink
Remove get_processing_result()
Browse files Browse the repository at this point in the history
Remove composite results signal
  • Loading branch information
rtuck99 committed Oct 15, 2024
1 parent 41e12b9 commit 82b684b
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 112 deletions.
4 changes: 2 additions & 2 deletions src/dodal/devices/zocalo/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@
NoZocaloSubscription,
XrcResult,
ZocaloResults,
get_processing_result,
get_full_processing_results,
)

__all__ = [
"ZocaloResults",
"XrcResult",
"ZocaloTrigger",
"get_processing_result",
"get_full_processing_results",
"ZOCALO_READING_PLAN_NAME",
"NoResultsFromZocalo",
"NoZocaloSubscription",
Expand Down
113 changes: 40 additions & 73 deletions src/dodal/devices/zocalo/zocalo_results.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import asyncio
from collections import OrderedDict
from collections.abc import Generator, Sequence
from enum import Enum
from queue import Empty, Queue
Expand All @@ -9,7 +8,7 @@
import numpy as np
import workflows.recipe
import workflows.transport
from bluesky.protocols import Descriptor, Triggerable
from bluesky.protocols import Triggerable
from bluesky.utils import Msg
from deepdiff import DeepDiff
from numpy.typing import NDArray
Expand Down Expand Up @@ -131,15 +130,24 @@ def __init__(
self.transport: CommonTransport | None = None
self.use_cpu_and_gpu = use_cpu_and_gpu

self.results, self._results_setter = soft_signal_r_and_setter(
list[XrcResult], name="results"
)
self.centres_of_mass, self._com_setter = soft_signal_r_and_setter(
NDArray[np.uint64], name="centres_of_mass"
)
self.bbox_sizes, self._bbox_setter = soft_signal_r_and_setter(
NDArray[np.uint64], "bbox_sizes", self.name
)
self.max_voxel, self._max_voxel_setter = soft_signal_r_and_setter(
NDArray[np.uint64], int, name="max_voxel"
)
self.max_count, self._max_count_setter = soft_signal_r_and_setter(
NDArray[np.uint64], name="max_count"
)
self.n_voxels, self._n_voxels_setter = soft_signal_r_and_setter(
NDArray[np.uint64], name="n_voxels"
)
self.total_count, self._total_count_setter = soft_signal_r_and_setter(
NDArray[np.uint64], name="total_count"
)
self.ispyb_dcid, self._ispyb_dcid_setter = soft_signal_r_and_setter(
int, name="ispyb_dcid"
)
Expand All @@ -148,7 +156,10 @@ def __init__(
)
self.add_readables(
[
self.results,
self.max_voxel,
self.max_count,
self.n_voxels,
self.total_count,
self.centres_of_mass,
self.bbox_sizes,
self.ispyb_dcid,
Expand All @@ -159,11 +170,14 @@ def __init__(
super().__init__(name)

async def _put_results(self, results: Sequence[XrcResult], recipe_parameters):
self._results_setter(list(results))
centres_of_mass = np.array([r["centre_of_mass"] for r in results])
bbox_sizes = np.array([bbox_size(r) for r in results])
self._com_setter(centres_of_mass)
self._bbox_setter(bbox_sizes)
self._max_voxel_setter([r["max_voxel"] for r in results])
self._max_count_setter([r["max_count"] for r in results])
self._n_voxels_setter([r["n_voxels"] for r in results])
self._total_count_setter([r["total_count"] for r in results])
self._ispyb_dcid_setter(recipe_parameters["dcid"])
self._ispyb_dcgid_setter(recipe_parameters["dcgid"])

Expand Down Expand Up @@ -284,48 +298,6 @@ async def trigger(self):
finally:
self._kickoff_run = False

async def describe(self) -> dict[str, Descriptor]:
zocalo_array_type: Descriptor = {
"source": f"zocalo_service:{self.zocalo_environment}",
"dtype": "array",
"shape": [-1, 3],
}
zocalo_int_type: Descriptor = {
"source": f"zocalo_service:{self.zocalo_environment}",
"dtype": "integer",
"shape": [0],
}
return OrderedDict(
[
(
self._name + "-results",
{
"source": f"zocalo_service:{self.zocalo_environment}",
"dtype": "array",
"shape": [
-1,
], # TODO describe properly - see https://github.com/DiamondLightSource/dodal/issues/253
},
),
(
self._name + "-centres_of_mass",
zocalo_array_type,
),
(
self._name + "-bbox_sizes",
zocalo_array_type,
),
(
self._name + "-ispyb_dcid",
zocalo_int_type,
),
(
self._name + "-ispyb_dcgid",
zocalo_int_type,
),
],
)

def _subscribe_to_results(self):
self.transport = _get_zocalo_connection(self.zocalo_environment)

Expand Down Expand Up @@ -362,28 +334,6 @@ def _receive_result(
)


def get_processing_result(
zocalo: ZocaloResults,
) -> Generator[Any, Any, tuple[np.ndarray, np.ndarray] | tuple[None, None]]:
"""A minimal plan which will extract the top ranked xray centre and crystal bounding
box size from the zocalo results. Returns (None, None) if no crystals were found."""

LOGGER.info("Getting zocalo processing results.")
centres_of_mass = yield from bps.rd(zocalo.centres_of_mass, default_value=[]) # type: ignore
LOGGER.debug(f"Centres of mass: {centres_of_mass}")
centre_of_mass = (
None
if len(centres_of_mass) == 0 # type: ignore
else centres_of_mass[0] - np.array([0.5, 0.5, 0.5]) # type: ignore
)
LOGGER.debug(f"Adjusted top centring result: {centre_of_mass}")
bbox_sizes = yield from bps.rd(zocalo.bbox_sizes, default_value=[]) # type: ignore
LOGGER.debug(f"Bounding box sizes: {centres_of_mass}")
bbox_size = None if len(bbox_sizes) == 0 else bbox_sizes[0] # type: ignore
LOGGER.debug(f"Top bbox size: {bbox_size}")
return centre_of_mass, bbox_size


def _corrected_xrc_result(uncorrected: XrcResult) -> XrcResult:
corrected = XrcResult(**uncorrected)
corrected["centre_of_mass"] = [
Expand All @@ -398,5 +348,22 @@ def get_full_processing_results(
"""A plan that will return the raw zocalo results, ranked in descending order according to the sort key.
Returns empty list in the event no results found."""
LOGGER.info("Retrieving raw zocalo processing results")
raw_results = yield from bps.rd(zocalo.results, default_value=[]) # type: ignore
return [_corrected_xrc_result(r) for r in raw_results] # type: ignore
com = yield from bps.rd(zocalo.centres_of_mass, default_value=[]) # type: ignore
max_voxel = yield from bps.rd(zocalo.max_voxel, default_value=[]) # type: ignore
max_count = yield from bps.rd(zocalo.max_count, default_value=[]) # type: ignore
n_voxels = yield from bps.rd(zocalo.n_voxels, default_value=[]) # type: ignore
total_count = yield from bps.rd(zocalo.total_count, default_value=[]) # type: ignore
bounding_box = yield from bps.rd(zocalo.bounding_box, default_value=[]) # type: ignore
return [
XrcResult(
centre_of_mass=com,
max_voxel=mv,
max_count=mc,
n_voxels=n,
total_count=tc,
bounding_box=bb,
)
for com, mv, mc, n, tc, bb in zip(
com, max_voxel, max_count, n_voxels, total_count, bounding_box, strict=True
)
]
39 changes: 2 additions & 37 deletions tests/devices/unit_tests/test_zocalo_results.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
ZocaloResults,
ZocaloSource,
get_full_processing_results,
get_processing_result,
)

TEST_RESULTS: list[XrcResult] = [
Expand Down Expand Up @@ -124,32 +123,12 @@ async def test_put_result_read_results(
zocalo_device = await mocked_zocalo_device([], run_setup=True)
await zocalo_device._put_results(TEST_RESULTS, test_recipe_parameters)
reading = await zocalo_device.read()
results: list[XrcResult] = reading["zocalo-results"]["value"]
centres: list[XrcResult] = reading["zocalo-centres_of_mass"]["value"]
bboxes: list[XrcResult] = reading["zocalo-bbox_sizes"]["value"]
assert results == TEST_RESULTS
assert np.all(centres == np.array([[1, 2, 3], [2, 3, 4], [4, 5, 6]]))
assert np.all(bboxes[0] == [2, 2, 1])


async def test_rd_top_results(
mocked_zocalo_device,
RE,
):
zocalo_device = await mocked_zocalo_device([], run_setup=True)
await zocalo_device._put_results(TEST_RESULTS, test_recipe_parameters)

def test_plan():
bbox_size = yield from bps.rd(zocalo_device.bbox_sizes)
assert len(bbox_size[0]) == 3 # type: ignore
assert np.all(bbox_size[0] == np.array([2, 2, 1])) # type: ignore
centres_of_mass = yield from bps.rd(zocalo_device.centres_of_mass)
assert len(centres_of_mass[0]) == 3 # type: ignore
assert np.all(centres_of_mass[0] == np.array([1, 2, 3])) # type: ignore

RE(test_plan())


async def test_trigger_and_wait_puts_results(
mocked_zocalo_device,
RE,
Expand All @@ -167,22 +146,6 @@ def plan():
zocalo_device._put_results.assert_called()


async def test_extraction_plan(mocked_zocalo_device, RE) -> None:
zocalo_device: ZocaloResults = await mocked_zocalo_device(
TEST_RESULTS, run_setup=False
)

def plan():
yield from bps.open_run()
yield from bps.trigger_and_read([zocalo_device], name=ZOCALO_READING_PLAN_NAME)
com, bbox = yield from get_processing_result(zocalo_device)
assert np.all(com == np.array([0.5, 1.5, 2.5]))
assert np.all(bbox == np.array([2, 2, 1]))
yield from bps.close_run()

RE(plan())


async def test_get_full_processing_results(mocked_zocalo_device, RE) -> None:
zocalo_device: ZocaloResults = await mocked_zocalo_device(
TEST_RESULTS, run_setup=False
Expand All @@ -200,6 +163,8 @@ def plan():
[[1, 2, 3], [3, 4, 4]],
[[1, 2, 3], [3, 4, 4]],
]
for prop in ["max_voxel", "max_count", "n_voxels", "total_count"]:
assert [r[prop] for r in full_results] == [r[prop] for r in TEST_RESULTS] # type: ignore

RE(plan())

Expand Down

0 comments on commit 82b684b

Please sign in to comment.