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

Make the prepare planstub modular in fly_and_collect #339

Merged
merged 5 commits into from
May 24, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
129 changes: 68 additions & 61 deletions src/ophyd_async/plan_stubs/fly.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import List
from typing import Any, Callable, Concatenate, List, ParamSpec

import bluesky.plan_stubs as bps
from bluesky.utils import short_uid
Expand All @@ -9,22 +9,87 @@
from ophyd_async.panda._table import SeqTable, SeqTableRow, seq_table_from_rows
from ophyd_async.panda._trigger import SeqTableInfo

P = ParamSpec("P")


def prepare_static_seq_table_flyer_and_detectors_with_same_trigger(
flyer: HardwareTriggeredFlyable[SeqTableInfo],
detectors: List[StandardDetector],
number_of_frames: int,
exposure: float,
deadtime: float,
shutter_time: float,
repeats: int = 1,
period: float = 0.0,
):
"""Prepare a hardware triggered flyable and one or more detectors.

Prepare a hardware triggered flyable and one or more detectors with the
same trigger. This method constructs TriggerInfo and a static sequence
table from required parameters. The table is required to prepare the flyer,
and the TriggerInfo is required to prepare the detector(s).

This prepares all supplied detectors with the same trigger.

"""
trigger_info = TriggerInfo(
num=number_of_frames * repeats,
trigger=DetectorTrigger.constant_gate,
deadtime=deadtime,
livetime=exposure,
)

trigger_time = number_of_frames * (exposure + deadtime)
pre_delay = max(period - 2 * shutter_time - trigger_time, 0)

table: SeqTable = seq_table_from_rows(
# Wait for pre-delay then open shutter
SeqTableRow(
time1=in_micros(pre_delay),
time2=in_micros(shutter_time),
outa2=True,
),
# Keeping shutter open, do N triggers
SeqTableRow(
repeats=number_of_frames,
time1=in_micros(exposure),
outa1=True,
outb1=True,
time2=in_micros(deadtime),
outa2=True,
),
# Add the shutter close
SeqTableRow(time2=in_micros(shutter_time)),
)

table_info = SeqTableInfo(table, repeats)

for det in detectors:
yield from bps.prepare(det, trigger_info, wait=False, group="prep")
yield from bps.prepare(flyer, table_info, wait=False, group="prep")
yield from bps.wait(group="prep")


def time_resolved_fly_and_collect_with_static_seq_table(
stream_name: str,
detectors: List[StandardDetector],
flyer: HardwareTriggeredFlyable[SeqTableInfo],
number_of_frames: int,
exposure: int,
exposure: float,
shutter_time: float,
repeats: int = 1,
period: float = 0.0,
prepare_flyer_and_detectors: Callable[
Concatenate[HardwareTriggeredFlyable[SeqTableInfo], List[StandardDetector], P],
Any,
] = prepare_static_seq_table_flyer_and_detectors_with_same_trigger,
):
"""Run a scan wth a flyer and multiple detectors.

The standard basic flow for a flyscan:

- Set up the flyer with a static sequence table and detectors with a trigger
(A default plan stub is provided for this but a custom one can be used instead.)
- Declare the stream and kickoff the scan
- Collect while completing

Expand All @@ -37,7 +102,7 @@ def time_resolved_fly_and_collect_with_static_seq_table(

# Set up scan and prepare trigger
deadtime = max(det.controller.get_deadtime(exposure) for det in detectors)
yield from prepare_static_seq_table_flyer_and_detectors_with_same_trigger(
yield from prepare_flyer_and_detectors(
flyer,
detectors,
number_of_frames=number_of_frames,
Expand Down Expand Up @@ -73,61 +138,3 @@ def time_resolved_fly_and_collect_with_static_seq_table(
name=stream_name,
)
yield from bps.wait(group=group)


def prepare_static_seq_table_flyer_and_detectors_with_same_trigger(
flyer: HardwareTriggeredFlyable[SeqTableInfo],
detectors: List[StandardDetector],
number_of_frames: int,
exposure: float,
deadtime: float,
shutter_time: float,
repeats: int = 1,
period: float = 0.0,
):
"""Prepare a hardware triggered flyable and one or more detectors.

Prepare a hardware triggered flyable and one or more detectors with the
same trigger. This method constructs TriggerInfo and a static sequence
table from required parameters. The table is required to prepare the flyer,
and the TriggerInfo is required to prepare the detector(s).

This prepares all supplied detectors with the same trigger.

"""
trigger_info = TriggerInfo(
num=number_of_frames * repeats,
trigger=DetectorTrigger.constant_gate,
deadtime=deadtime,
livetime=exposure,
)

trigger_time = number_of_frames * (exposure + deadtime)
pre_delay = max(period - 2 * shutter_time - trigger_time, 0)

table: SeqTable = seq_table_from_rows(
# Wait for pre-delay then open shutter
SeqTableRow(
time1=in_micros(pre_delay),
time2=in_micros(shutter_time),
outa2=True,
),
# Keeping shutter open, do N triggers
SeqTableRow(
repeats=number_of_frames,
time1=in_micros(exposure),
outa1=True,
outb1=True,
time2=in_micros(deadtime),
outa2=True,
),
# Add the shutter close
SeqTableRow(time2=in_micros(shutter_time)),
)

table_info = SeqTableInfo(table, repeats)

for det in detectors:
yield from bps.prepare(det, trigger_info, wait=False, group="prep")
yield from bps.prepare(flyer, table_info, wait=False, group="prep")
yield from bps.wait(group="prep")
Loading