Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
4ed70ec
Implement concrete analyser classes for beamlines to remove generics
oliwenmandiamond Jan 16, 2026
e10fd04
Merge branch 'main' into Implement_concrete_analyser_classes_for_beam…
oliwenmandiamond Jan 16, 2026
7b8b811
Add i09_1 specs model
oliwenmandiamond Jan 19, 2026
fd65ea6
Add device args
oliwenmandiamond Jan 19, 2026
b1bbbfb
Merge branch 'main' into Implement_concrete_analyser_classes_for_beam…
oliwenmandiamond Jan 19, 2026
bb03340
Merge branch 'main' into Implement_concrete_analyser_classes_for_beam…
oliwenmandiamond Jan 22, 2026
6a9465d
Fix lint
oliwenmandiamond Jan 22, 2026
146163c
Reorder DeviceManager placement for P60
oliwenmandiamond Jan 22, 2026
0c08873
Merge branch 'main' into Implement_concrete_analyser_classes_for_beam…
oliwenmandiamond Jan 23, 2026
04a0371
Removed VGScienta and Specs Detector. Moved this
oliwenmandiamond Jan 26, 2026
e31edfe
Fix tests
oliwenmandiamond Jan 27, 2026
ecc4d7b
Merge branch 'main' into Implement_concrete_analyser_classes_for_beam…
oliwenmandiamond Jan 27, 2026
c5063d0
Add doc string to EW4000
oliwenmandiamond Jan 27, 2026
66ce50b
Add missing classes from __init__
oliwenmandiamond Jan 27, 2026
76405c2
Merge branch 'Implement_concrete_analyser_classes_for_beamlines' of s…
oliwenmandiamond Jan 27, 2026
ec6d817
Add psu_mode_suffix option to driver to fix i09 and p60 connection fail
oliwenmandiamond Jan 27, 2026
60804b9
Renamed sequence functions
oliwenmandiamond Jan 27, 2026
d95a95f
Merge branch 'main' into Implement_concrete_analyser_classes_for_beam…
oliwenmandiamond Jan 28, 2026
1264e9a
Add comment linking bluesky issue
oliwenmandiamond Jan 28, 2026
dac774f
Merge branch 'main' into Implement_concrete_analyser_classes_for_beam…
oliwenmandiamond Jan 30, 2026
7db944a
Update outdated doc string
oliwenmandiamond Jan 30, 2026
46e7b3d
Merge branch 'main' into Implement_concrete_analyser_classes_for_beam…
oliwenmandiamond Feb 4, 2026
9e1108e
Merge into main
oliwenmandiamond Feb 4, 2026
5d2bde2
Merge branch 'main' into Implement_concrete_analyser_classes_for_beam…
oliwenmandiamond Feb 10, 2026
e470d24
Rename driver to drv
oliwenmandiamond Feb 10, 2026
8cab29c
Merge branch 'main' into Implement_concrete_analyser_classes_for_beam…
oliwenmandiamond Feb 10, 2026
a72ec1c
Merge branch 'main' into Implement_concrete_analyser_classes_for_beam…
oliwenmandiamond Feb 11, 2026
714195b
Merge branch 'Implement_concrete_analyser_classes_for_beamlines' of s…
oliwenmandiamond Feb 11, 2026
78cfb7f
Merge branch 'main' into Implement_concrete_analyser_classes_for_beam…
oliwenmandiamond Feb 12, 2026
2d85839
Merge branch 'main' into Implement_concrete_analyser_classes_for_beam…
oliwenmandiamond Feb 13, 2026
cb912ea
Merge branch 'Implement_concrete_analyser_classes_for_beamlines' of s…
oliwenmandiamond Feb 13, 2026
95aae82
Update the device names
oliwenmandiamond Feb 13, 2026
360419c
Fix tests
oliwenmandiamond Feb 13, 2026
b358266
Remove temp drv variable from analyser
oliwenmandiamond Feb 13, 2026
0a54935
Merge branch 'analyser_works_with_blueapi' into Implement_concrete_an…
oliwenmandiamond Feb 17, 2026
ef6b7d3
Fix tests
oliwenmandiamond Feb 17, 2026
92aab6b
Merge branch 'analyser_works_with_blueapi' into Implement_concrete_an…
oliwenmandiamond Feb 17, 2026
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
13 changes: 3 additions & 10 deletions src/dodal/beamlines/b07.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,11 @@
from dodal.common.beamlines.beamline_utils import set_beamline as set_utils_beamline
from dodal.device_manager import DeviceManager
from dodal.devices.beamlines.b07 import (
B07BSpecs150,
B07SampleManipulator52B,
Grating,
LensMode,
)
from dodal.devices.beamlines.b07_shared import PsuMode
from dodal.devices.electron_analyser.base import EnergySource
from dodal.devices.electron_analyser.specs import SpecsDetector
from dodal.devices.motors import XYZPolarStage
from dodal.devices.pgm import PlaneGratingMonochromator
from dodal.log import set_beamline as set_log_beamline
Expand Down Expand Up @@ -39,13 +37,8 @@ def energy_source(pgm: PlaneGratingMonochromator) -> EnergySource:
# CAM:IMAGE will fail to connect outside the beamline network,
# see https://github.com/DiamondLightSource/dodal/issues/1852
@devices.factory()
def analyser(energy_source: EnergySource) -> SpecsDetector[LensMode, PsuMode]:
return SpecsDetector[LensMode, PsuMode](
prefix=f"{B_PREFIX.beamline_prefix}-EA-DET-01:CAM:",
lens_mode_type=LensMode,
psu_mode_type=PsuMode,
energy_source=energy_source,
)
def analyser(energy_source: EnergySource) -> B07BSpecs150:
return B07BSpecs150(f"{B_PREFIX.beamline_prefix}-EA-DET-01:CAM:", energy_source)


@devices.factory()
Expand Down
10 changes: 3 additions & 7 deletions src/dodal/beamlines/b07_1.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,11 @@
from dodal.common.beamlines.beamline_utils import set_beamline as set_utils_beamline
from dodal.device_manager import DeviceManager
from dodal.devices.beamlines.b07_1 import (
B07CSpecs150,
ChannelCutMonochromator,
Grating,
LensMode,
)
from dodal.devices.beamlines.b07_shared import PsuMode
from dodal.devices.electron_analyser.base import EnergySource
from dodal.devices.electron_analyser.specs import SpecsDetector
from dodal.devices.motors import XYZPolarAzimuthStage
from dodal.devices.pgm import PlaneGratingMonochromator
from dodal.log import set_beamline as set_log_beamline
Expand Down Expand Up @@ -44,11 +42,9 @@ def energy_source(pgm: PlaneGratingMonochromator) -> EnergySource:
# CAM:IMAGE will fail to connect outside the beamline network,
# see https://github.com/DiamondLightSource/dodal/issues/1852
@devices.factory()
def analyser(energy_source: EnergySource) -> SpecsDetector[LensMode, PsuMode]:
return SpecsDetector[LensMode, PsuMode](
def analyser(energy_source: EnergySource) -> B07CSpecs150:
return B07CSpecs150(
prefix=f"{C_PREFIX.beamline_prefix}-EA-DET-01:CAM:",
lens_mode_type=LensMode,
psu_mode_type=PsuMode,
energy_source=energy_source,
)

Expand Down
20 changes: 8 additions & 12 deletions src/dodal/beamlines/i09.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,9 @@
from dodal.beamlines.i09_2_shared import devices as i09_2_shared_devices
from dodal.common.beamlines.beamline_utils import set_beamline as set_utils_beamline
from dodal.device_manager import DeviceManager
from dodal.devices.beamlines.i09.enums import LensMode, PassEnergy, PsuMode
from dodal.devices.beamlines.i09 import I09VGScientaEW4000
from dodal.devices.common_dcm import DoubleCrystalMonochromatorWithDSpacing
from dodal.devices.electron_analyser.base import DualEnergySource
from dodal.devices.electron_analyser.vgscienta import VGScientaDetector
from dodal.devices.fast_shutter import DualFastShutter, GenericFastShutter
from dodal.devices.motors import XYZPolarAzimuthStage
from dodal.devices.pgm import PlaneGratingMonochromator
Expand Down Expand Up @@ -80,18 +79,15 @@ def dual_fast_shutter(
# see https://github.com/DiamondLightSource/dodal/issues/1852
@devices.factory()
def ew4000(
dual_fast_shutter: DualFastShutter,
dual_energy_source: DualEnergySource,
dual_fast_shutter: DualFastShutter,
source_selector: SourceSelector,
) -> VGScientaDetector[LensMode, PsuMode, PassEnergy]:
return VGScientaDetector[LensMode, PsuMode, PassEnergy](
prefix=f"{I_PREFIX.beamline_prefix}-EA-DET-01:CAM:",
lens_mode_type=LensMode,
psu_mode_type=PsuMode,
pass_energy_type=PassEnergy,
energy_source=dual_energy_source,
shutter=dual_fast_shutter,
source_selector=source_selector,
) -> I09VGScientaEW4000:
return I09VGScientaEW4000(
f"{I_PREFIX.beamline_prefix}-EA-DET-01:CAM:",
dual_energy_source,
dual_fast_shutter,
source_selector,
)


Expand Down
12 changes: 4 additions & 8 deletions src/dodal/beamlines/i09_1.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
from dodal.beamlines.i09_1_shared import devices as i09_1_shared_devices
from dodal.common.beamlines.beamline_utils import set_beamline as set_utils_beamline
from dodal.device_manager import DeviceManager
from dodal.devices.beamlines.i09_1 import LensMode, PsuMode
from dodal.devices.beamlines.i09_1 import I091SpecsPhoibos225
from dodal.devices.common_dcm import DoubleCrystalMonochromatorWithDSpacing
from dodal.devices.electron_analyser.base import EnergySource
from dodal.devices.electron_analyser.specs import SpecsDetector
from dodal.devices.motors import XYZPolarAzimuthTiltStage
from dodal.devices.synchrotron import Synchrotron
from dodal.devices.temperture_controller import Lakeshore336
Expand Down Expand Up @@ -33,12 +32,9 @@ def energy_source(dcm: DoubleCrystalMonochromatorWithDSpacing) -> EnergySource:
# CAM:IMAGE will fail to connect outside the beamline network,
# see https://github.com/DiamondLightSource/dodal/issues/1852
@devices.factory()
def analyser(energy_source: EnergySource) -> SpecsDetector[LensMode, PsuMode]:
return SpecsDetector[LensMode, PsuMode](
prefix=f"{PREFIX.beamline_prefix}-EA-DET-02:CAM:",
lens_mode_type=LensMode,
psu_mode_type=PsuMode,
energy_source=energy_source,
def analyser(energy_source: EnergySource) -> I091SpecsPhoibos225:
return I091SpecsPhoibos225(
f"{PREFIX.beamline_prefix}-EA-DET-02:CAM:", energy_source
)


Expand Down
23 changes: 7 additions & 16 deletions src/dodal/beamlines/p60.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,9 @@
from dodal.devices.beamlines.p60 import (
LabXraySource,
LabXraySourceReadable,
LensMode,
PassEnergy,
PsuMode,
P60VGScientaR4000,
)
from dodal.devices.electron_analyser.base import DualEnergySource
from dodal.devices.electron_analyser.vgscienta import VGScientaDetector
from dodal.devices.selectable_source import SourceSelector
from dodal.log import set_beamline as set_log_beamline
from dodal.utils import BeamlinePrefix, get_beamline_name
Expand All @@ -18,13 +15,13 @@
be on the beamline network to access them so a remote `dodal connect p60` will fail.
"""

devices = DeviceManager()

BL = get_beamline_name("p60")
PREFIX = BeamlinePrefix(BL)
set_log_beamline(BL)
set_utils_beamline(BL)

devices = DeviceManager()


@devices.factory()
def source_selector() -> SourceSelector:
Expand All @@ -42,7 +39,7 @@ def mg_kalpha_source() -> LabXraySourceReadable:


@devices.factory()
def energy_source(
def dual_energy_source(
al_kalpha_source: LabXraySourceReadable,
mg_kalpha_source: LabXraySourceReadable,
source_selector: SourceSelector,
Expand All @@ -57,13 +54,7 @@ def energy_source(
# Connect will work again after this work completed
# https://jira.diamond.ac.uk/browse/P60-13
@devices.factory()
def r4000(
energy_source: DualEnergySource,
) -> VGScientaDetector[LensMode, PsuMode, PassEnergy]:
return VGScientaDetector[LensMode, PsuMode, PassEnergy](
prefix=f"{PREFIX.beamline_prefix}-EA-DET-01:CAM:",
lens_mode_type=LensMode,
psu_mode_type=PsuMode,
pass_energy_type=PassEnergy,
energy_source=energy_source,
def r4000(dual_energy_source: DualEnergySource) -> P60VGScientaR4000:
return P60VGScientaR4000(
f"{PREFIX.beamline_prefix}-EA-DET-01:CAM:", dual_energy_source
)
18 changes: 17 additions & 1 deletion src/dodal/devices/beamlines/b07/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,20 @@
from .analyser import (
B07BElectronAnalyserController,
B07BSpecs150,
B07BSpecsAnalyserDriverIO,
B07BSpecsRegion,
B07BSpecsSequence,
)
from .b07_motors import B07SampleManipulator52B
from .enums import Grating, LensMode

__all__ = ["B07SampleManipulator52B", "Grating", "LensMode"]
__all__ = [
"B07BElectronAnalyserController",
"B07BSpecsAnalyserDriverIO",
"B07BSpecsRegion",
"B07BSpecsSequence",
"B07BSpecs150",
"B07SampleManipulator52B",
"Grating",
"LensMode",
]
42 changes: 42 additions & 0 deletions src/dodal/devices/beamlines/b07/analyser.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
from dodal.devices.beamlines.b07.enums import LensMode
from dodal.devices.beamlines.b07_shared.enums import PsuMode
from dodal.devices.electron_analyser.base.base_controller import (
ElectronAnalyserController,
)
from dodal.devices.electron_analyser.base.base_detector import ElectronAnalyserDetector
from dodal.devices.electron_analyser.base.energy_sources import EnergySource
from dodal.devices.electron_analyser.specs import (
SpecsAnalyserDriverIO,
SpecsRegion,
SpecsSequence,
)
from dodal.devices.fast_shutter import FastShutter

B07BSpecsRegion = SpecsRegion[LensMode, PsuMode]
B07BSpecsSequence = SpecsSequence[LensMode, PsuMode]


class B07BSpecsAnalyserDriverIO(SpecsAnalyserDriverIO):
def __init__(self, prefix: str, name: str = ""):
super().__init__(prefix, LensMode, PsuMode, name)


B07BElectronAnalyserController = ElectronAnalyserController[
B07BSpecsAnalyserDriverIO, B07BSpecsRegion
]


class B07BSpecs150(
ElectronAnalyserDetector[B07BSpecsAnalyserDriverIO, B07BSpecsRegion]
):
def __init__(
self,
prefix: str,
energy_source: EnergySource,
shutter: FastShutter | None = None,
name: str = "",
):
controller = B07BElectronAnalyserController(
B07BSpecsAnalyserDriverIO(prefix), energy_source, shutter
)
super().__init__(controller, name)
16 changes: 14 additions & 2 deletions src/dodal/devices/beamlines/b07_1/__init__.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,22 @@
from dodal.devices.beamlines.b07_1.ccmc import (
from .analyser import (
B07CElectronAnalyserController,
B07CSpecs150,
B07CSpecsAnalyserDriverIO,
B07CSpecsRegion,
B07CSpecsSequence,
)
from .ccmc import (
ChannelCutMonochromator,
ChannelCutMonochromatorPositions,
)
from dodal.devices.beamlines.b07_1.enums import Grating, LensMode
from .enums import Grating, LensMode

__all__ = [
"B07CElectronAnalyserController",
"B07CSpecsAnalyserDriverIO",
"B07CSpecsRegion",
"B07CSpecsSequence",
"B07CSpecs150",
"Grating",
"LensMode",
"ChannelCutMonochromator",
Expand Down
42 changes: 42 additions & 0 deletions src/dodal/devices/beamlines/b07_1/analyser.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
from dodal.devices.beamlines.b07_1.enums import LensMode
from dodal.devices.beamlines.b07_shared.enums import PsuMode
from dodal.devices.electron_analyser.base.base_controller import (
ElectronAnalyserController,
)
from dodal.devices.electron_analyser.base.base_detector import ElectronAnalyserDetector
from dodal.devices.electron_analyser.base.energy_sources import EnergySource
from dodal.devices.electron_analyser.specs import (
SpecsAnalyserDriverIO,
SpecsRegion,
SpecsSequence,
)
from dodal.devices.fast_shutter import FastShutter

B07CSpecsRegion = SpecsRegion[LensMode, PsuMode]
B07CSpecsSequence = SpecsSequence[LensMode, PsuMode]


class B07CSpecsAnalyserDriverIO(SpecsAnalyserDriverIO):
def __init__(self, prefix: str, name: str = ""):
super().__init__(prefix, LensMode, PsuMode, name)


B07CElectronAnalyserController = ElectronAnalyserController[
B07CSpecsAnalyserDriverIO, B07CSpecsRegion
]


class B07CSpecs150(
ElectronAnalyserDetector[B07CSpecsAnalyserDriverIO, B07CSpecsRegion]
):
def __init__(
self,
prefix: str,
energy_source: EnergySource,
shutter: FastShutter | None = None,
name: str = "",
):
controller = B07CElectronAnalyserController(
B07CSpecsAnalyserDriverIO(prefix), energy_source, shutter
)
super().__init__(controller, name)
21 changes: 19 additions & 2 deletions src/dodal/devices/beamlines/i09/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,20 @@
from dodal.devices.beamlines.i09.enums import Grating, LensMode, PassEnergy, PsuMode
from .analyser import (
I09ElectronAnalyserController,
I09VGScientaAnalyserDriverIO,
I09VGScientaEW4000,
I09VGScientaRegion,
I09VGScientaSequence,
)
from .enums import Grating, LensMode, PassEnergy, PsuMode

__all__ = ["Grating", "LensMode", "PsuMode", "PassEnergy"]
__all__ = [
"I09ElectronAnalyserController",
"I09VGScientaAnalyserDriverIO",
"I09VGScientaEW4000",
"I09VGScientaRegion",
"I09VGScientaSequence",
"Grating",
"LensMode",
"PsuMode",
"PassEnergy",
]
60 changes: 60 additions & 0 deletions src/dodal/devices/beamlines/i09/analyser.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
from dodal.devices.beamlines.i09.enums import LensMode, PassEnergy, PsuMode
from dodal.devices.electron_analyser.base import DualEnergySource
from dodal.devices.electron_analyser.base.base_controller import (
ElectronAnalyserController,
)
from dodal.devices.electron_analyser.base.base_detector import ElectronAnalyserDetector
from dodal.devices.electron_analyser.vgscienta import (
VGScientaAnalyserDriverIO,
VGScientaRegion,
VGScientaSequence,
)
from dodal.devices.electron_analyser.vgscienta.vgscienta_driver_io import (
VGScientaAnalyserDriverIO,
)
from dodal.devices.electron_analyser.vgscienta.vgscienta_region import (
VGScientaRegion,
VGScientaSequence,
)
from dodal.devices.fast_shutter import DualFastShutter
from dodal.devices.selectable_source import SourceSelector

I09VGScientaRegion = VGScientaRegion[LensMode, PassEnergy]
I09VGScientaSequence = VGScientaSequence[LensMode, PsuMode, PassEnergy]


class I09VGScientaAnalyserDriverIO(
VGScientaAnalyserDriverIO[LensMode, PsuMode, PassEnergy]
):
def __init__(self, prefix: str, name: str = ""):
super().__init__(prefix, LensMode, PsuMode, PassEnergy, "ELEMENT_SET", name)


I09ElectronAnalyserController = ElectronAnalyserController[
I09VGScientaAnalyserDriverIO, I09VGScientaRegion
]


class I09VGScientaEW4000(
ElectronAnalyserDetector[I09VGScientaAnalyserDriverIO, I09VGScientaRegion]
):
"""Implementation of VGScienta Electron Analyser. This model is unique for i09
beamline because it has access to multiple energy sources and shutters. The selected
source is deterimined by the source_selector device.
"""

def __init__(
self,
prefix: str,
dual_energy_source: DualEnergySource,
dual_fast_shutter: DualFastShutter,
source_selector: SourceSelector,
name: str = "",
):
controller = I09ElectronAnalyserController(
I09VGScientaAnalyserDriverIO(prefix),
dual_energy_source,
dual_fast_shutter,
source_selector,
)
super().__init__(controller, name)
Loading