call_sync (calling external code)

API reference: call_sync

All interaction with the “outside world” should be via bluesky messages, and not directly called from within a plan. For example, the following is bad:

import bluesky.plan_stubs as bps
from genie_python import genie as g

def bad_plan():
    yield from bps.open_run()
    g.cset("foo", 123)  # This is bad - must not do this
    yield from bps.close_run()

Danger

External I/O - including most genie_python or inst functions - should never be done directly in a plan, as it will break:

  • Rewindability (for example, the ability to interrupt a scan and then later seamlessly continue it)

  • Simulation (the cset above would be executed during a simulation)

  • Error handling (including ctrl-c handling)

  • Ability to emit documents

  • Ability to use bluesky signals

In the above case, a good plan, which uses bluesky messages in a better way using a bluesky-native Block object, would be:

import bluesky.plan_stubs as bps
from ophyd_async.plan_stubs import ensure_connected
from ibex_bluesky_core.devices.block import block_rw

foo = block_rw(float, "foo")

def good_plan():
    yield from ensure_connected(foo)
    yield from bps.open_run()
    yield from bps.mv(foo, 123)
    yield from bps.close_run()

However, if the functionality you want to use is not yet natively available in bluesky, a fallback option for synchronous functions is available using the call_sync plan stub:

import bluesky.plan_stubs as bps
from ibex_bluesky_core.plan_stubs import call_sync
from genie_python import genie as g

def good_plan():
    yield from bps.open_run()
    
    # Note use of g.some_function, rather than g.some_function() - i.e. a function reference
    # We can also access the returned value from the call.
    return_value = yield from call_sync(g.some_function, 123, keyword_argument=456)
    yield from bps.close_run()

It is strongly recommended that any functions run in this way are “fast” (i.e. less than a few seconds). In particular, avoid doing arbitrarily-long waits - for example, waiting for detector data or sample environment. For these long-running tasks, seek to implement at least the long-running parts using native bluesky mechanisms.