diff --git a/README.md b/README.md index 6de9e779..ffdaa5c5 100644 --- a/README.md +++ b/README.md @@ -46,6 +46,18 @@ $ conda activate haven $ pip install -e ".[dev]" ``` +## Usage + +The easiest way to start **haven** is to use IPython's magic run command. + +``` +$ ipython +In [1]: %run -m haven.ipython_startup +``` + +This will load some common tools, and print some useful information +about how to use Haven. + ## Running Tests To run tests, run diff --git a/pyproject.toml b/pyproject.toml index fbbdaaf7..ec88d552 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "haven-spc" -version = "2024.8.0" +version = "2024.8.1" authors = [ { name="Mark Wolfman", email="wolfman@anl.gov" }, ] diff --git a/src/haven/ipython_startup.py b/src/haven/ipython_startup.py new file mode 100644 index 00000000..3811ed9e --- /dev/null +++ b/src/haven/ipython_startup.py @@ -0,0 +1,81 @@ +import logging +import time +import asyncio + +import databroker # noqa: F401 +import matplotlib.pyplot as plt # noqa: F401 +from bluesky.run_engine import RunEngine, call_in_bluesky_event_loop # noqa: F401 +from bluesky import suspenders # noqa: F401 +from bluesky import plan_stubs as bps # noqa: F401 +from bluesky.plan_stubs import mv, mvr, rd # noqa: F401 +from bluesky import plans as bp # noqa: F401 +from bluesky.callbacks.best_effort import BestEffortCallback # noqa: F401 +from bluesky.simulators import summarize_plan # noqa: F401 +from rich import print +from rich.console import Console +from rich.panel import Panel +from rich.theme import Theme + +import haven # noqa: F401 + +logging.basicConfig(level=logging.WARNING) + +# Make sure asyncio and the bluesky run engine share an event loop +loop = asyncio.new_event_loop() +asyncio.set_event_loop(loop) +RE = haven.run_engine(loop=loop) +# Add metadata to the run engine +RE.preprocessors.append(haven.preprocessors.inject_haven_md_wrapper) + +# Import some ophyd-async stuff +# NB: This has to be after the run engine setup +# or else ipython gets stuck and vanilla ophyd +# devices get stuck +from ophyd_async.core import DeviceCollector # noqa: F401 + +# Allow best effort callback to update properly +plt.ion() + +# Prepare the haven instrument +config = haven.load_config() +t0 = time.monotonic() +print(f"Initializing [repr.number]{config['beamline']['name']}[/]…", flush=True) +call_in_bluesky_event_loop(haven.load_instrument()) +print(f"Finished initalization in {time.monotonic() - t0:.2f} seconds.", flush=True) + +# Save references to some commonly used things in the global namespace +registry = haven.registry +ion_chambers = haven.registry.findall("ion_chambers", allow_none=True) + +# Print helpful information to the console +custom_theme = Theme({ + "code": "white on grey27", +}) +console = Console(theme=custom_theme) +motd = ( + "[bold]Devices[/bold] are available by name through the [italic]registry[/italic].\n" + " ┗━ [code]m = registry['sim_motor_2'][/]\n" + "\n" + "[bold]Bluesky plans and plan-stubs[/bold] are available as " + "[italic]bp[/] and [italic]bps[/] respectively.\n" + " ┗━ [code]plan = bps.mv(m, 2)[/]\n" + "\n" + "The [bold]RunEngine[/bold] is available as [italic]RE[/italic].\n" + " ┗━ [code]RE(bps.mv(m, 2))[/code]\n" + "\n" + "The run engine is also registered as the transform [italic]<[/].\n" + " ┣━ [code]