Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
88 commits
Select commit Hold shift + click to select a range
ca1038e
Add do manual acquisition plan
olliesilvester Aug 11, 2025
bb2d127
Add option to override path provider
olliesilvester Aug 13, 2025
b392a26
remove todos
olliesilvester Aug 13, 2025
972ed36
Review response
olliesilvester Aug 21, 2025
940da42
Merge branch 'main' into 1200_add_basic_jf_plans
olliesilvester Aug 29, 2025
5386324
Merge remote-tracking branch 'origin/main' into 1200_add_basic_jf_plans
olliesilvester Aug 29, 2025
b92a863
Merge branch '1200_add_basic_jf_plans' of github.com:DiamondLightSour…
olliesilvester Aug 29, 2025
de5479f
remove accidentally added file
olliesilvester Aug 29, 2025
8f28c71
Remove print from test
olliesilvester Aug 29, 2025
f67cb7f
Remove frames per trigger for external acquisitions
olliesilvester Sep 1, 2025
cb8447e
Add do internal acquisition plan
olliesilvester Aug 29, 2025
aff58b0
Add initial plan
olliesilvester Sep 1, 2025
4bf34af
Add tests and fixes
olliesilvester Sep 1, 2025
a8ee429
Monitor signals during tests
olliesilvester Sep 2, 2025
61b6e38
Add full do darks plan
olliesilvester Sep 2, 2025
6cfab71
Add tests and docstring
olliesilvester Sep 2, 2025
f832c1d
WIP add rotation scan plan
olliesilvester Sep 3, 2025
fdfc32f
Fixes and add test
olliesilvester Sep 4, 2025
27b6416
Merge branch 'main' into 1200_add_jf_internal_acquisition
olliesilvester Sep 17, 2025
dc680a5
Refactor external acquisiton plan into reusable plan utils
olliesilvester Sep 22, 2025
9eea8d3
Improve tests
olliesilvester Sep 22, 2025
5291289
pin dodal
olliesilvester Sep 22, 2025
56cb214
update dodal pin
olliesilvester Sep 22, 2025
594046c
update path provider of the writer in override plan
olliesilvester Sep 22, 2025
090a429
Add stop JF in contingency wrapper for fly plan
olliesilvester Sep 22, 2025
15416c0
Fix race condition in test
olliesilvester Sep 22, 2025
824be80
Fix override_file_path
olliesilvester Sep 24, 2025
020d5fe
dodal pin
olliesilvester Sep 24, 2025
496f404
Merge branch 'main' into 1200_add_jf_internal_acquisition
olliesilvester Sep 24, 2025
92874c7
Fix test
olliesilvester Sep 25, 2025
0c4a7ef
Merge remote-tracking branch 'origin/main' into 1200_add_jf_internal_…
olliesilvester Sep 25, 2025
53dffe2
unpin dodal
olliesilvester Sep 25, 2025
7ea94c9
Maybe fix test again
olliesilvester Sep 25, 2025
3701394
Add non-zero sleep to test
olliesilvester Sep 25, 2025
e828621
Revert changes to vscode workspace settings
olliesilvester Sep 25, 2025
0bcf536
Wait for JF to unstage
DominicOram Sep 25, 2025
809811a
Merge branch '1200_add_jf_internal_acquisition' of github.com:Diamond…
olliesilvester Sep 25, 2025
af4f9a7
Merge remote-tracking branch 'origin/main' into 1200_add_jf_do_darks
olliesilvester Sep 26, 2025
dbef0cf
Update plan for comissioning jungfrau device
Sep 26, 2025
5f8a352
Improve docstring to explain pedestal mode
olliesilvester Sep 26, 2025
5d7624d
Add another comment
olliesilvester Sep 26, 2025
408cb98
Merge branch '1200_add_jf_do_darks' into 1200_add_jf_rotation_plan
olliesilvester Sep 26, 2025
d4bf17d
Implement revised jungfrau rotation scans
olliesilvester Sep 26, 2025
a4b289f
Make zebra and shutter setup plans more generic
olliesilvester Sep 30, 2025
55a1f3a
Improve docstring
olliesilvester Oct 1, 2025
37ffe91
Add another docstring
olliesilvester Oct 1, 2025
3e752e6
Merge remote-tracking branch 'origin/1314_make_zebra_shutter_setup_pl…
olliesilvester Oct 1, 2025
dabdcfe
Make setup and tidy up zebra rotation plans common
olliesilvester Oct 1, 2025
01b5419
Merge branch '1314_make_zebra_shutter_setup_plans_more_generic' into …
olliesilvester Oct 1, 2025
23fab94
Do all setup in parallel, add plan to do multi rotations by transmission
olliesilvester Oct 1, 2025
01b063d
Make metadata writer less weird
olliesilvester Oct 1, 2025
4711e36
More tidy up and test stubs
olliesilvester Oct 1, 2025
43590d1
Add test that pedestal mode is turned off on exception
olliesilvester Oct 2, 2025
69bfe2f
Create fixture for enum attenuator
olliesilvester Oct 2, 2025
27a3076
rename exception
olliesilvester Oct 2, 2025
49de8b8
relentless testing
olliesilvester Oct 2, 2025
4c58ff4
Add metadata writer test
olliesilvester Oct 2, 2025
038a8c8
Add run decorator onto plan
olliesilvester Oct 2, 2025
48c48db
Merge remote-tracking branch 'origin/1200_add_jf_do_darks' into 1200_…
olliesilvester Oct 2, 2025
90721b2
Add extra patch to test
olliesilvester Oct 3, 2025
2cafc60
remove wait as a parameter
olliesilvester Oct 3, 2025
385cd68
Let ophyd async revert pedestal mode on disarm instead of the plan
olliesilvester Oct 3, 2025
1b609ea
Add contingency wrapper
olliesilvester Oct 3, 2025
c6f5e14
Add more tests
olliesilvester Oct 6, 2025
5f1420d
Merge remote-tracking branch 'origin/1200_add_jf_do_darks' into 1200_…
olliesilvester Oct 6, 2025
fe6d846
make gain mode a parameter of fly_jungfrau plan
olliesilvester Oct 6, 2025
1c2ab2b
Merge branch 'main' of github.com:DiamondLightSource/mx-bluesky into …
olliesilvester Oct 20, 2025
50afbe9
Remove beam xy from metadata writer
olliesilvester Oct 20, 2025
a9886ef
Put gain mode into fly_jungfrau
olliesilvester Oct 20, 2025
971b2b3
Merge remote-tracking branch 'origin/main' into 1200_add_jf_rotation_…
olliesilvester Oct 21, 2025
d715aad
Merge remote-tracking branch 'origin/main' into 1200_add_jf_rotation_…
olliesilvester Oct 21, 2025
cfae73b
remove flux from metadata
olliesilvester Oct 21, 2025
63a4304
Fix namings
olliesilvester Oct 21, 2025
76b5df2
Review response
olliesilvester Oct 22, 2025
70a2112
Merge remote-tracking branch 'origin/main' into 1200_add_jf_rotation_…
olliesilvester Dec 8, 2025
cf47c5b
Fixes from merge
olliesilvester Dec 8, 2025
0fa19d2
Fix some tests
olliesilvester Dec 8, 2025
15829f4
Use common read hardware plan inside fly jungfrau plan
olliesilvester Dec 8, 2025
ca71fc4
Refactor and fix broken tests
olliesilvester Dec 9, 2025
d9cf5ab
Merge remote-tracking branch 'origin/main' into 1200_add_jf_rotation_…
Dec 11, 2025
021623f
Rework parameters to be numtracker-friendly
olliesilvester Dec 16, 2025
767efd1
ispyb callback optionally gets visit from runengine metadata
olliesilvester Dec 17, 2025
dc74094
Fix tests
olliesilvester Dec 17, 2025
38e77aa
Reset RE fixture's metadata after each test
olliesilvester Dec 17, 2025
bb0cd83
Use BlueAPI-like pathprovider in JF tests
olliesilvester Dec 17, 2025
dbef9d1
Merge branch '1200_add_jf_rotation_plan' of github.com:DiamondLightSo…
olliesilvester Dec 17, 2025
797b3d9
Get metadata writer and experiment params working with numtracker
olliesilvester Dec 18, 2025
bdf5756
Merge branch 'main' into 1200_add_jf_rotation_plan
olliesilvester Dec 18, 2025
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
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ dependencies = [
"ophyd >= 1.10.5",
"ophyd-async >= 0.14.0",
"bluesky >= 1.14.6",
"dls-dodal @ git+https://github.com/DiamondLightSource/dodal.git@62960e0e587bf86943ce1b581848fa131ef884d5",
"dls-dodal @ git+https://github.com/DiamondLightSource/dodal.git@50e72219dd379dd05e1fb1173397852407832f75",
]


Expand Down
13 changes: 13 additions & 0 deletions src/mx_bluesky/beamlines/i24/jungfrau_commissioning/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from mx_bluesky.beamlines.i24.jungfrau_commissioning.experiment_plans.do_darks import (
do_non_pedestal_darks,
do_pedestal_darks,
)
from mx_bluesky.beamlines.i24.jungfrau_commissioning.experiment_plans.rotation_scan_plan import (
single_rotation_plan,
)

__all__ = [
"do_pedestal_darks",
"do_non_pedestal_darks",
"single_rotation_plan",
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import json

from bluesky.callbacks import CallbackBase
from dodal.devices.i24.commissioning_jungfrau import JungfrauCommissioningWriter

from mx_bluesky.beamlines.i24.parameters.constants import PlanNameConstants
from mx_bluesky.common.parameters.rotation import SingleRotationScan
from mx_bluesky.common.utils.log import LOGGER

READING_DUMP_FILENAME = "collection_info.json"


class JsonMetadataWriter(CallbackBase):
"""Callback class to handle the creation of metadata json files for commissioning.

To use, subscribe the Bluesky RunEngine to an instance of this class.
E.g.:
metadata_writer_callback = JsonMetadataWriter(parameters)
RE.subscribe(metadata_writer_callback)
Or decorate a plan using bluesky.preprocessors.subs_decorator.

See: https://blueskyproject.io/bluesky/callbacks.html#ways-to-invoke-callbacks

"""

def __init__(self, jf_writer: JungfrauCommissioningWriter):
self.jf_writer = jf_writer # For path information
self.wavelength_in_a = None
self.energy_in_kev = None
self.detector_distance_mm = None
self.descriptors: dict[str, dict] = {}
self.transmission: float | None = None
self.parameters: SingleRotationScan | None = None

super().__init__()

def start(self, doc: dict): # type: ignore
if doc.get("subplan_name") == PlanNameConstants.ROTATION_MAIN:
json_params = doc.get("rotation_scan_params")
assert json_params is not None
LOGGER.info(
f"Metadata writer recieved start document with experiment parameters {json_params}"
)
self.parameters = SingleRotationScan(**json.loads(json_params))
self.run_start_uid = doc.get("uid")

def descriptor(self, doc: dict): # type: ignore
self.descriptors[doc["uid"]] = doc

def event(self, doc: dict): # type: ignore
event_descriptor = self.descriptors[doc["descriptor"]]

if event_descriptor.get("name") == PlanNameConstants.ROTATION_DEVICE_READ:
assert self.parameters is not None
data = doc.get("data")
assert data is not None
self.wavelength_in_a = data.get("dcm-wavelength_in_a")
self.energy_in_kev = data.get("dcm-energy_in_keV")
self.detector_distance_mm = data.get("detector_motion-z")

LOGGER.info(
f"Metadata writer received parameters, energy_in_kev: {self.energy_in_kev}, wavelength: {self.wavelength_in_a}, det_distance_mm: {self.detector_distance_mm}"
)

def stop(self, doc: dict): # type: ignore
assert self.parameters is not None
if (
self.run_start_uid is not None
and doc.get("run_start") == self.run_start_uid
):
with open(self.jf_writer.final_path / READING_DUMP_FILENAME, "w") as f:
f.write(
json.dumps(
{
"wavelength_in_a": self.wavelength_in_a,
"energy_kev": self.energy_in_kev,
"angular_increment_deg": self.parameters.rotation_increment_deg,
"detector_distance_mm": self.detector_distance_mm,
}
)
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
from __future__ import annotations

import pydantic
from dodal.devices.attenuator.attenuator import EnumFilterAttenuator
from dodal.devices.hutch_shutter import HutchShutter
from dodal.devices.i24.aperture import Aperture
from dodal.devices.i24.beamstop import Beamstop
from dodal.devices.i24.commissioning_jungfrau import CommissioningJungfrau
from dodal.devices.i24.dcm import DCM
from dodal.devices.i24.dual_backlight import DualBacklight
from dodal.devices.i24.vgonio import VerticalGoniometer
from dodal.devices.motors import YZStage
from dodal.devices.synchrotron import Synchrotron
from dodal.devices.xbpm_feedback import XBPMFeedback
from dodal.devices.zebra.zebra import Zebra
from dodal.devices.zebra.zebra_controlled_shutter import ZebraShutter


@pydantic.dataclasses.dataclass(config={"arbitrary_types_allowed": True})
class RotationScanComposite:
"""All devices which are directly or indirectly required by this plan"""

aperture: Aperture
attenuator: EnumFilterAttenuator
jungfrau: CommissioningJungfrau
gonio: VerticalGoniometer
synchrotron: Synchrotron
sample_shutter: ZebraShutter
zebra: Zebra
xbpm_feedback: XBPMFeedback
hutch_shutter: HutchShutter
beamstop: Beamstop
det_stage: YZStage
backlight: DualBacklight
dcm: DCM
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@

from mx_bluesky.beamlines.i24.jungfrau_commissioning.plan_stubs.plan_utils import (
fly_jungfrau,
override_file_path,
)
from mx_bluesky.common.utils.log import LOGGER

Expand All @@ -25,8 +24,8 @@ def do_pedestal_darks(
exp_time_s: float = 0.001,
pedestal_frames: PositiveInt = 20,
pedestal_loops: PositiveInt = 200,
filename: str = "pedestal_darks",
jungfrau: CommissioningJungfrau = inject("jungfrau"),
path_of_output_file: str | None = None,
) -> MsgGenerator:
"""Acquire darks in pedestal mode, using dynamic gain mode. This calibrates the offsets
for the jungfrau, and must be performed before acquiring real data in dynamic gain mode.
Expand All @@ -46,18 +45,19 @@ def do_pedestal_darks(
exp_time_s: Length of detector exposure for each frame.
pedestal_frames: Number of frames acquired per pedestal loop.
pedestal_loops: Number of times to acquire a set of pedestal_frames
filename: Name of output file
jungfrau: Jungfrau device
path_of_output_file: Absolute path of the detector file output, including file name. If None, then use the PathProvider
set during Jungfrau device instantiation
"""

@bpp.set_run_key_decorator(PEDESTAL_DARKS_RUN)
@bpp.run_decorator(md={"subplan_name": PEDESTAL_DARKS_RUN})
@bpp.run_decorator(
md={
"subplan_name": PEDESTAL_DARKS_RUN,
"detector_file_template": filename,
}
)
@bpp.stage_decorator([jungfrau])
def _do_decorated_plan():
if path_of_output_file:
override_file_path(jungfrau, path_of_output_file)

trigger_info = create_jungfrau_pedestal_triggering_info(
exp_time_s, pedestal_frames, pedestal_loops
)
Expand All @@ -67,12 +67,11 @@ def _do_decorated_plan():
yield from bps.mv(
jungfrau.drv.acquisition_type,
AcquisitionType.PEDESTAL,
jungfrau.drv.gain_mode,
GainMode.DYNAMIC,
)
yield from fly_jungfrau(
jungfrau,
trigger_info,
GainMode.DYNAMIC,
wait=True,
log_on_percentage_prefix="Jungfrau pedestal dynamic gain mode darks triggers received",
)
Expand All @@ -84,8 +83,8 @@ def do_non_pedestal_darks(
gain_mode: GainMode,
exp_time_s: float = 0.001,
total_triggers: PositiveInt = 1000,
filename: str = "darks",
jungfrau: CommissioningJungfrau = inject("jungfrau"),
path_of_output_file: str | None = None,
) -> MsgGenerator:
"""Internally take a set of images at a given gain mode.

Expand All @@ -96,26 +95,26 @@ def do_non_pedestal_darks(
exp_time_s: Length of detector exposure for each trigger.
total_triggers: Total triggers for the dark scan.
jungfrau: Jungfrau device
path_of_output_file: Absolute path of the detector file output, including file name. If None, then use the PathProvider
set during Jungfrau device instantiation
filename: Name of output file
"""

@bpp.set_run_key_decorator(STANDARD_DARKS_RUN)
@bpp.run_decorator(md={"subplan_name": STANDARD_DARKS_RUN})
@bpp.run_decorator(
md={
"subplan_name": STANDARD_DARKS_RUN,
"detector_file_template": filename,
}
)
@bpp.stage_decorator([jungfrau])
def _do_decorated_plan():
if path_of_output_file:
override_file_path(jungfrau, path_of_output_file)

trigger_info = create_jungfrau_internal_triggering_info(
total_triggers, exp_time_s
)

yield from bps.mv(jungfrau.drv.gain_mode, gain_mode)

yield from fly_jungfrau(
jungfrau,
trigger_info,
gain_mode,
wait=True,
log_on_percentage_prefix=f"Jungfrau {gain_mode} gain mode darks triggers received",
)
Expand Down
Loading
Loading