Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v2: Motor and AreaDetector devices do not set their event loops as the bluesky event loop, meaning some bluesky plan stubs fail. #1102

Open
rosesyrett opened this issue Feb 3, 2023 · 1 comment
Assignees

Comments

@rosesyrett
Copy link
Contributor

Overview of the issue

When trying to run a bluesky plan with ophyd-epics-devices motors and area detectors, I came across a bug where trying to read a PV from either of these devices would result in a RuntimeError:

RuntimeError: Task <Task pending name='Task-65' coro=<RunEngine._run() running at /dls/science/users/ton99817/projects/p45/venv/lib/python3.9/site-packages/bluesky/run_engine.py:1583> cb=[_chain_future.<locals>._call_set_state() at /dls_sw/apps/python/anaconda/4.6.14/64/envs/python3.9/lib/python3.9/asyncio/futures.py:391]> got Future <Future pending> attached to a different loop

After some investigation by @coretl it was discovered that this is because upon collecting these devices, their event loops are set to be the current user event loop, not the bluesky event loop. This means some bluesky plan stubs (like read) don't work, because they check the ._valid property of the devices and ensure they are running on the bluesky event loop. It was subsequently fixed by directly handling and setting the event loop to be the bluesky event loop in the script.

Steps to recreate

from ophyd.v2.core import DeviceCollector
from ophyd_epics_devices.areadetector import MyHDFFlyerSim
from ophyd_epics_devices.motor import Motor
import bluesky.preprocessors as bpp
import bluesky.plan_stubs as bps
from bluesky import RunEngine

RE = RunEngine()

with DeviceCollector():
    rot_motor = Motor("BL46P-MO-MAP-01:STAGE:A")
    x_motor = Motor("BL46P-MO-MAP-01:STAGE:X")
    camera = MyHDFFlyerSim("BL46P-EA-DET-01:", drv_prefix="DET:")


@bpp.run_decorator()
@bpp.stage_decorator([camera])
def collect_sample_projections(start_angle: float, stop_angle: float, num_projections: int):

    yield from bps.abs_set(camera.hdf.file_path, "/dls/science/users/ton99817/projects")
    yield from bps.abs_set(camera.hdf.file_name, "p45test.h5")

    exposure_time = yield from bps.rd(camera.drv.acquire_time)

RE(collect_sample_projections(0.0, 0.0, 10))

In this case, I was running the script above inside "dls/science/users/ton99817/projects/p45", with this snippet of code saved at "dls/science/users/ton99817/projects/p45/src/p45/bluesky/plan.py". Running this script with the minimal dependencies required (bluesky, ophyd and aioca, with ophyd installed from the github repo) produced the following output:

Run aborted
Traceback (most recent call last):
  File "/dls/science/users/ton99817/projects/p45/venv/lib/python3.9/site-packages/bluesky/run_engine.py", line 1523, in _run
    msg = self._plan_stack[-1].send(resp)
  File "/dls/science/users/ton99817/projects/p45/venv/lib/python3.9/site-packages/bluesky/utils/__init__.py", line 1147, in dec_inner
    return (yield from plan)
  File "/dls/science/users/ton99817/projects/p45/venv/lib/python3.9/site-packages/bluesky/preprocessors.py", line 333, in run_wrapper
    yield from contingency_wrapper(plan, except_plan=except_plan, else_plan=close_run)
  File "/dls/science/users/ton99817/projects/p45/venv/lib/python3.9/site-packages/bluesky/preprocessors.py", line 575, in contingency_wrapper
    ret = yield from plan
  File "/dls/science/users/ton99817/projects/p45/venv/lib/python3.9/site-packages/bluesky/utils/__init__.py", line 1147, in dec_inner
    return (yield from plan)
  File "/dls/science/users/ton99817/projects/p45/venv/lib/python3.9/site-packages/bluesky/preprocessors.py", line 965, in stage_wrapper
    return (yield from finalize_wrapper(inner(), unstage_devices()))
  File "/dls/science/users/ton99817/projects/p45/venv/lib/python3.9/site-packages/bluesky/preprocessors.py", line 511, in finalize_wrapper
    ret = yield from plan
  File "/dls/science/users/ton99817/projects/p45/venv/lib/python3.9/site-packages/bluesky/preprocessors.py", line 963, in inner
    return (yield from plan)
  File "/dls/science/users/ton99817/projects/p45/src/p45/bluesky/plan.py", line 39, in collect_sample_projections
    exposure_time = yield from bps.rd(camera.drv.acquire_time)
  File "/dls/science/users/ton99817/projects/p45/venv/lib/python3.9/site-packages/bluesky/plan_stubs.py", line 371, in rd
    ret = yield from read(obj)
  File "/dls/science/users/ton99817/projects/p45/venv/lib/python3.9/site-packages/bluesky/plan_stubs.py", line 96, in read
    return (yield Msg('read', obj))
  File "/dls/science/users/ton99817/projects/p45/venv/lib/python3.9/site-packages/bluesky/run_engine.py", line 1583, in _run
    new_response = await coro(msg)
  File "/dls/science/users/ton99817/projects/p45/venv/lib/python3.9/site-packages/bluesky/run_engine.py", line 1835, in _read
    ret = await maybe_await(obj.read(*msg.args, **msg.kwargs))
  File "/dls/science/users/ton99817/projects/p45/venv/lib/python3.9/site-packages/bluesky/utils/__init__.py", line 1779, in maybe_await
    return await ret
  File "/dls/science/users/ton99817/projects/p45/venv/lib/python3.9/site-packages/ophyd/v2/epics.py", line 90, in read
    await self._valid.wait()
  File "/dls_sw/apps/python/anaconda/4.6.14/64/envs/python3.9/lib/python3.9/asyncio/locks.py", line 226, in wait
    await fut
RuntimeError: Task <Task pending name='Task-65' coro=<RunEngine._run() running at /dls/science/users/ton99817/projects/p45/venv/lib/python3.9/site-packages/bluesky/run_engine.py:1583> cb=[_chain_future.<locals>._call_set_state() at /dls_sw/apps/python/anaconda/4.6.14/64/envs/python3.9/lib/python3.9/asyncio/futures.py:391]> got Future <Future pending> attached to a different loop
Traceback (most recent call last):
  File "/dls/science/users/ton99817/projects/p45/src/p45/bluesky/plan.py", line 78, in <module>
    RE(
  File "/dls/science/users/ton99817/projects/p45/venv/lib/python3.9/site-packages/bluesky/run_engine.py", line 893, in __call__
    plan_return = self._resume_task(init_func=_build_task)
  File "/dls/science/users/ton99817/projects/p45/venv/lib/python3.9/site-packages/bluesky/run_engine.py", line 1032, in _resume_task
    raise exc
  File "/dls/science/users/ton99817/projects/p45/venv/lib/python3.9/site-packages/bluesky/run_engine.py", line 1663, in _run
    raise err
  File "/dls/science/users/ton99817/projects/p45/venv/lib/python3.9/site-packages/bluesky/run_engine.py", line 1523, in _run
    msg = self._plan_stack[-1].send(resp)
  File "/dls/science/users/ton99817/projects/p45/venv/lib/python3.9/site-packages/bluesky/utils/__init__.py", line 1147, in dec_inner
    return (yield from plan)
  File "/dls/science/users/ton99817/projects/p45/venv/lib/python3.9/site-packages/bluesky/preprocessors.py", line 333, in run_wrapper
    yield from contingency_wrapper(plan, except_plan=except_plan, else_plan=close_run)
  File "/dls/science/users/ton99817/projects/p45/venv/lib/python3.9/site-packages/bluesky/preprocessors.py", line 575, in contingency_wrapper
    ret = yield from plan
  File "/dls/science/users/ton99817/projects/p45/venv/lib/python3.9/site-packages/bluesky/utils/__init__.py", line 1147, in dec_inner
    return (yield from plan)
  File "/dls/science/users/ton99817/projects/p45/venv/lib/python3.9/site-packages/bluesky/preprocessors.py", line 965, in stage_wrapper
    return (yield from finalize_wrapper(inner(), unstage_devices()))
  File "/dls/science/users/ton99817/projects/p45/venv/lib/python3.9/site-packages/bluesky/preprocessors.py", line 511, in finalize_wrapper
    ret = yield from plan
  File "/dls/science/users/ton99817/projects/p45/venv/lib/python3.9/site-packages/bluesky/preprocessors.py", line 963, in inner
    return (yield from plan)
  File "/dls/science/users/ton99817/projects/p45/src/p45/bluesky/plan.py", line 39, in collect_sample_projections
    exposure_time = yield from bps.rd(camera.drv.acquire_time)
  File "/dls/science/users/ton99817/projects/p45/venv/lib/python3.9/site-packages/bluesky/plan_stubs.py", line 371, in rd
    ret = yield from read(obj)
  File "/dls/science/users/ton99817/projects/p45/venv/lib/python3.9/site-packages/bluesky/plan_stubs.py", line 96, in read
    return (yield Msg('read', obj))
  File "/dls/science/users/ton99817/projects/p45/venv/lib/python3.9/site-packages/bluesky/run_engine.py", line 1583, in _run
    new_response = await coro(msg)
  File "/dls/science/users/ton99817/projects/p45/venv/lib/python3.9/site-packages/bluesky/run_engine.py", line 1835, in _read
    ret = await maybe_await(obj.read(*msg.args, **msg.kwargs))
  File "/dls/science/users/ton99817/projects/p45/venv/lib/python3.9/site-packages/bluesky/utils/__init__.py", line 1779, in maybe_await
    return await ret
  File "/dls/science/users/ton99817/projects/p45/venv/lib/python3.9/site-packages/ophyd/v2/epics.py", line 90, in read
    await self._valid.wait()
  File "/dls_sw/apps/python/anaconda/4.6.14/64/envs/python3.9/lib/python3.9/asyncio/locks.py", line 226, in wait
    await fut
RuntimeError: Task <Task pending name='Task-65' coro=<RunEngine._run() running at /dls/science/users/ton99817/projects/p45/venv/lib/python3.9/site-packages/bluesky/run_engine.py:1583> cb=[_chain_future.<locals>._call_set_state() at /dls_sw/apps/python/anaconda/4.6.14/64/envs/python3.9/lib/python3.9/asyncio/futures.py:391]> got Future <Future pending> attached to a different loop

To rectify the issue, the bluesky plan file can be changed to:

from ophyd.v2.core import DeviceCollector
from ophyd_epics_devices.areadetector import MyHDFFlyerSim
from ophyd_epics_devices.motor import Motor
import bluesky.preprocessors as bpp
import bluesky.plan_stubs as bps
from bluesky import RunEngine

RE = RunEngine()

import asyncio
from bluesky.run_engine import _bluesky_event_loop

asyncio.set_event_loop(_bluesky_event_loop)

with DeviceCollector():
    rot_motor = Motor("BL46P-MO-MAP-01:STAGE:A")
    x_motor = Motor("BL46P-MO-MAP-01:STAGE:X")
    camera = MyHDFFlyerSim("BL46P-EA-DET-01:", drv_prefix="DET:")


@bpp.run_decorator()
@bpp.stage_decorator([camera])
def collect_sample_projections(start_angle: float, stop_angle: float, num_projections: int):

    yield from bps.abs_set(camera.hdf.file_path, "/dls/science/users/ton99817/projects")
    yield from bps.abs_set(camera.hdf.file_name, "p45test.h5")

    exposure_time = yield from bps.rd(camera.drv.acquire_time)
@coretl
Copy link
Collaborator

coretl commented Feb 21, 2023

Decided that this can be put into DeviceCollector, and it should have a set_event_loop arg to turn on and off

@coretl coretl changed the title Motor and AreaDetector devices do not set their event loops as the bluesky event loop, meaning some bluesky plan stubs fail. v2: Motor and AreaDetector devices do not set their event loops as the bluesky event loop, meaning some bluesky plan stubs fail. Mar 15, 2023
@coretl coretl transferred this issue from bluesky/ophyd-epics-devices Mar 15, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants