Skip to content

Commit

Permalink
add plans used on ndxargus and rikenfe
Browse files Browse the repository at this point in the history
  • Loading branch information
rerpha committed Feb 20, 2025
1 parent 45e06d2 commit a9e3c9b
Show file tree
Hide file tree
Showing 2 changed files with 176 additions and 108 deletions.
76 changes: 40 additions & 36 deletions src/ibex_bluesky_core/plans/muons/dae_magnet_scan.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,71 +15,75 @@
from ibex_bluesky_core.devices.simpledae import SimpleDae
from ibex_bluesky_core.devices.simpledae.controllers import (
RunPerPointController,
PeriodPerPointController,
)
from ibex_bluesky_core.devices.simpledae.reducers import (
GoodFramesNormalizer,
)
from ibex_bluesky_core.devices.simpledae.waiters import GoodFramesWaiter
from ibex_bluesky_core.devices.simpledae.reducers import PeriodGoodFramesNormalizer
from ibex_bluesky_core.devices.simpledae.waiters import GoodFramesWaiter, PeriodGoodFramesWaiter
from ibex_bluesky_core.plans import set_num_periods
from ibex_bluesky_core.run_engine import get_run_engine

Check failure on line 23 in src/ibex_bluesky_core/plans/muons/dae_magnet_scan.py

View workflow job for this annotation

GitHub Actions / call-linter-workflow / ruff

Ruff (F401)

src/ibex_bluesky_core/plans/muons/dae_magnet_scan.py:23:42: F401 `ibex_bluesky_core.run_engine.get_run_engine` imported but unused

NUM_POINTS: int = 3

MAGNET_SETTLE_TIME = 3
MAGNET_BLOCK_NAME = "p3"
MAGNET_TOLERANCE = 0.1
from ibex_bluesky_core.callbacks.fitting.fitting_utils import Gaussian

Check failure on line 25 in src/ibex_bluesky_core/plans/muons/dae_magnet_scan.py

View workflow job for this annotation

GitHub Actions / call-linter-workflow / ruff

Ruff (I001)

src/ibex_bluesky_core/plans/muons/dae_magnet_scan.py:3:1: I001 Import block is un-sorted or un-formatted


def dae_magnet_plan() -> Generator[Msg, None, None]:
def dae_magnet_plan(

Check failure on line 28 in src/ibex_bluesky_core/plans/muons/dae_magnet_scan.py

View workflow job for this annotation

GitHub Actions / call-linter-workflow / ruff

Ruff (PLR0913)

src/ibex_bluesky_core/plans/muons/dae_magnet_scan.py:28:5: PLR0913 Too many arguments in function definition (9 > 6)

Check failure on line 28 in src/ibex_bluesky_core/plans/muons/dae_magnet_scan.py

View workflow job for this annotation

GitHub Actions / call-linter-workflow / ruff

Ruff (PLR0917)

src/ibex_bluesky_core/plans/muons/dae_magnet_scan.py:28:5: PLR0917 Too many positional arguments (9/6)
block,

Check failure on line 29 in src/ibex_bluesky_core/plans/muons/dae_magnet_scan.py

View workflow job for this annotation

GitHub Actions / call-linter-workflow / ruff

Ruff (ANN001)

src/ibex_bluesky_core/plans/muons/dae_magnet_scan.py:29:5: ANN001 Missing type annotation for function argument `block`
start,

Check failure on line 30 in src/ibex_bluesky_core/plans/muons/dae_magnet_scan.py

View workflow job for this annotation

GitHub Actions / call-linter-workflow / ruff

Ruff (ANN001)

src/ibex_bluesky_core/plans/muons/dae_magnet_scan.py:30:5: ANN001 Missing type annotation for function argument `start`
stop,

Check failure on line 31 in src/ibex_bluesky_core/plans/muons/dae_magnet_scan.py

View workflow job for this annotation

GitHub Actions / call-linter-workflow / ruff

Ruff (ANN001)

src/ibex_bluesky_core/plans/muons/dae_magnet_scan.py:31:5: ANN001 Missing type annotation for function argument `stop`
num,
periods=True,
frames=500,
save_run=True,
magnet_tolerance=0.01,
magnet_settle_time=1,
) -> Generator[Msg, None, None]:
"""Scan a DAE against a magnet."""

def check_within_tolerance(setpoint: float, actual: float) -> bool:
return setpoint - MAGNET_TOLERANCE <= actual <= setpoint + MAGNET_TOLERANCE
return setpoint - magnet_tolerance <= actual <= setpoint + magnet_tolerance

magnet = block_rw_rbv(
float,
MAGNET_BLOCK_NAME,
block,
write_config=BlockWriteConfig(
settle_time_s=MAGNET_SETTLE_TIME, set_success_func=check_within_tolerance
settle_time_s=magnet_settle_time, set_success_func=check_within_tolerance
),
)

prefix = get_pv_prefix()
controller_chronus = RunPerPointController(save_run=True)
waiter_chronus = GoodFramesWaiter(500)
reducer_chronus = GoodFramesNormalizer(
prefix=prefix,
detector_spectra=[i for i in range(1, 32 + 1)],
)

dae_chronus = SimpleDae(
if periods:
controller = PeriodPerPointController(save_run=save_run)
waiter = PeriodGoodFramesWaiter(frames)
else:
controller = RunPerPointController(save_run=save_run)
waiter = GoodFramesWaiter(frames)

reducer = PeriodGoodFramesNormalizer(prefix, detector_spectra=[i for i in range(1, 32 + 1)])

dae = SimpleDae(
prefix=prefix,
controller=controller_chronus,
waiter=waiter_chronus,
reducer=reducer_chronus,
controller=controller,
waiter=waiter,
reducer=reducer,
)

# yield from set_num_periods(dae_chronus, 100)
yield from ensure_connected(magnet, dae, force_reconnect=True)

yield from ensure_connected(magnet, dae_chronus, force_reconnect=True)
if periods:
yield from set_num_periods(dae, num)
else:
yield from set_num_periods(dae, 1)

icc = ISISCallbacks(
y=reducer_chronus.intensity.name,
y=reducer.intensity.name,
x=magnet.name,
yerr=reducer_chronus.intensity_stddev.name,
yerr=reducer.intensity_stddev.name,
fit=Gaussian().fit(),
)

@icc
def _inner() -> Generator[Msg, None, None]:
yield from bp.scan([dae_chronus], magnet, 0, 10, num=NUM_POINTS)
yield from bp.scan([dae], magnet, start, stop, num=num)

yield from _inner()
print(icc.live_fit.result.fit_report())


if __name__ == "__main__" and not os.environ.get("FROM_IBEX") == "True":
matplotlib.use("qtagg")
plt.ion()
RE = get_run_engine()
RE(dae_magnet_plan())
input("Plan complete, press return to close plot and exit")
208 changes: 136 additions & 72 deletions src/ibex_bluesky_core/plans/muons/two_dae_scan.py
Original file line number Diff line number Diff line change
@@ -1,130 +1,194 @@
"""Muon scan that uses two DAEs to scan a magnet."""

import os
from collections.abc import Generator

import bluesky.plans as bp
import matplotlib
import matplotlib.pyplot as plt
from bluesky.callbacks import LiveFitPlot, LiveTable
from bluesky.preprocessors import subs_decorator
from bluesky.utils import Msg
from ibex_bluesky_core.callbacks import LiveFitLogger
from ophyd_async.plan_stubs import ensure_connected

from ibex_bluesky_core.callbacks.fitting import LiveFit
from ibex_bluesky_core.callbacks.fitting.fitting_utils import Linear
from ibex_bluesky_core.callbacks.fitting.fitting_utils import Gaussian
from ibex_bluesky_core.callbacks.plotting import LivePlot
from ibex_bluesky_core.devices.block import block_rw_rbv
from ibex_bluesky_core.devices.block import block_rw_rbv, BlockWriteConfig
from ibex_bluesky_core.devices.simpledae import SimpleDae
from ibex_bluesky_core.devices.simpledae.controllers import (
RunPerPointController,
)
from ibex_bluesky_core.devices.simpledae.reducers import (
GoodFramesNormalizer,
PeriodGoodFramesNormalizer,
)
from ibex_bluesky_core.devices.simpledae.waiters import GoodFramesWaiter
from ibex_bluesky_core.plan_stubs import call_qt_aware
from ibex_bluesky_core.run_engine import get_run_engine

NUM_POINTS: int = 3


def two_dae_scan() -> Generator[Msg, None, None]:
"""Scan a block using two DAEs."""
magnet = block_rw_rbv(float, "p3")
from ibex_bluesky_core.callbacks.file_logger import HumanReadableFileCallback


def two_dae_scan(
magnet_1_block,
start_1,
stop_1,
magnet_2_block,
start_2,
stop_2,
num,
frames=500,
save_run=True,
magnet_tolerance=0.01,
magnet_settle_time=1,
dae_1_prefix="IN:ARGUS:",
dae_2_prefix="IN:CHRONUS:",
spectra_total_1=96,
spectra_total_2=32,
) -> Generator[Msg, None, None]:
"""Scan a block using two DAEs and two magnets."""

def check_within_tolerance(setpoint: float, actual: float) -> bool:
return setpoint - magnet_tolerance <= actual <= setpoint + magnet_tolerance

magnet_1 = block_rw_rbv(
float,
magnet_1_block,
write_config=BlockWriteConfig(
settle_time_s=magnet_settle_time, set_success_func=check_within_tolerance
),
)

emu_prefix = "IN:EMU:"
controller_emu = RunPerPointController(save_run=True)
waiter_emu = GoodFramesWaiter(500)
reducer_emu = GoodFramesNormalizer(
prefix=emu_prefix,
detector_spectra=[i for i in range(1, 100)],
magnet_2 = block_rw_rbv(
float,
magnet_2_block,
write_config=BlockWriteConfig(
settle_time_s=magnet_settle_time, set_success_func=check_within_tolerance
),
)

dae_emu = SimpleDae(
prefix=emu_prefix,
controller=controller_emu,
waiter=waiter_emu,
reducer=reducer_emu,
name="emu_dae",
controller_1 = RunPerPointController(save_run=save_run)
waiter_1 = GoodFramesWaiter(frames)
reducer_1 = PeriodGoodFramesNormalizer(
prefix=dae_1_prefix,
detector_spectra=[i for i in range(1, spectra_total_1 + 1)],
)

musr_prefix = "IN:MUSR:"
dae_1 = SimpleDae(
prefix=dae_1_prefix,
controller=controller_1,
waiter=waiter_1,
reducer=reducer_1,
name="dae_1",
)

controller_musr = RunPerPointController(save_run=True)
waiter_musr = GoodFramesWaiter(500)
reducer_musr = GoodFramesNormalizer(
prefix=musr_prefix,
detector_spectra=[i for i in range(1, 96)],
controller_2 = RunPerPointController(save_run=save_run)
waiter_2 = GoodFramesWaiter(frames)
reducer_2 = PeriodGoodFramesNormalizer(
prefix=dae_2_prefix,
detector_spectra=[i for i in range(1, spectra_total_2 + 1)],
)

dae_musr = SimpleDae(
prefix=musr_prefix,
controller=controller_musr,
waiter=waiter_musr,
reducer=reducer_musr,
name="musr_dae",
dae_2 = SimpleDae(
prefix=dae_2_prefix,
controller=controller_2,
waiter=waiter_2,
reducer=reducer_2,
name="dae_2",
)

_, ax = yield from call_qt_aware(plt.subplots)

lf = LiveFit(
Linear.fit(),
y=reducer_emu.intensity.name,
x=magnet.name,
yerr=reducer_emu.intensity_stddev.name,
lf_1 = LiveFit(
Gaussian().fit(),
y=reducer_1.intensity.name,
x=magnet_1.name,
yerr=reducer_1.intensity_stddev.name,
)
lf_2 = LiveFit(
Gaussian().fit(),
y=reducer_2.intensity.name,
x=magnet_1.name,
yerr=reducer_2.intensity_stddev.name,
)

yield from ensure_connected(magnet, dae_emu, dae_musr, force_reconnect=True)
yield from ensure_connected(magnet_1, magnet_2, dae_1, dae_2, force_reconnect=True)

@subs_decorator(
[
LiveFitPlot(livefit=lf, ax=ax),
LiveFitPlot(livefit=lf_1, ax=ax),
LiveFitPlot(livefit=lf_2, ax=ax),
LivePlot(
y=reducer_emu.intensity.name,
x=magnet.name,
y=reducer_1.intensity.name,
x=magnet_1.name,
marker="x",
linestyle="none",
ax=ax,
yerr=reducer_emu.intensity_stddev.name,
yerr=reducer_1.intensity_stddev.name,
),
LivePlot(
y=reducer_musr.intensity.name,
x=magnet.name,
y=reducer_2.intensity.name,
x=magnet_1.name,
marker="x",
linestyle="none",
ax=ax,
yerr=reducer_musr.intensity_stddev.name,
yerr=reducer_2.intensity_stddev.name,
),
LiveTable(
[
magnet.name,
controller_emu.run_number.name,
reducer_emu.intensity.name,
reducer_emu.intensity_stddev.name,
reducer_emu.det_counts.name,
reducer_emu.det_counts_stddev.name,
dae_emu.good_frames.name,
controller_musr.run_number.name,
reducer_musr.intensity.name,
reducer_musr.intensity_stddev.name,
reducer_musr.det_counts.name,
reducer_musr.det_counts_stddev.name,
dae_musr.good_frames.name,
magnet_1.name,
magnet_2.name,
controller_1.run_number.name,
reducer_1.intensity.name,
reducer_1.intensity_stddev.name,
reducer_1.det_counts.name,
reducer_1.det_counts_stddev.name,
dae_1.good_frames.name,
controller_2.run_number.name,
reducer_2.intensity.name,
reducer_2.intensity_stddev.name,
reducer_2.det_counts.name,
reducer_2.det_counts_stddev.name,
dae_2.good_frames.name,
]
),
HumanReadableFileCallback(
fields=[
magnet_1.name,
magnet_2.name,
controller_1.run_number.name,
reducer_1.intensity.name,
reducer_1.intensity_stddev.name,
reducer_1.det_counts.name,
reducer_1.det_counts_stddev.name,
dae_1.good_frames.name,
controller_2.run_number.name,
reducer_2.intensity.name,
reducer_2.intensity_stddev.name,
reducer_2.det_counts.name,
reducer_2.det_counts_stddev.name,
dae_2.good_frames.name,
]
),
LiveFitLogger(
lf_1,
x=magnet_1.name,
y=reducer_1.intensity.name,
yerr=reducer_1.intensity_stddev.name,
postfix="lf_1",
),
LiveFitLogger(
lf_2,
x=magnet_1.name,
y=reducer_2.intensity.name,
yerr=reducer_2.intensity_stddev.name,
postfix="lf_2",
),
]
)
def _inner() -> Generator[Msg, None, None]:
yield from bp.scan([dae_musr, dae_emu], magnet, 0, 10, num=NUM_POINTS)
print(lf.result.fit_report())
yield from bp.scan(
[dae_2, dae_1], magnet_1, start_1, stop_1, magnet_2, start_2, stop_2, num=num
)
print(lf_1.result.fit_report())
print(lf_2.result.fit_report())

yield from _inner()


if __name__ == "__main__" and not os.environ.get("FROM_IBEX") == "True":
matplotlib.use("qtagg")
plt.ion()
RE = get_run_engine()
RE(two_dae_scan())
input("Plan complete, press return to close plot and exit")

0 comments on commit a9e3c9b

Please sign in to comment.