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

add i18 beamline definition - WITH device_factory #722

Closed
wants to merge 94 commits into from
Closed
Show file tree
Hide file tree
Changes from 92 commits
Commits
Show all changes
94 commits
Select commit Hold shift + click to select a range
0baece2
add i18 beamline definition
stan-dot Aug 1, 2024
c902167
add metadata to dcm crystals
stan-dot Aug 1, 2024
4fb6a76
adapt the tests
stan-dot Aug 1, 2024
7311a8e
udpate fixtures
stan-dot Aug 2, 2024
9c52087
move devices from i18-bluesky
stan-dot Aug 2, 2024
d902185
fix some pv values
stan-dot Aug 5, 2024
d774413
move away from ophyd devices
stan-dot Aug 5, 2024
ed4f4c8
add a kb mirror device@
stan-dot Aug 19, 2024
52d6ffe
test lookup table
stan-dot Aug 21, 2024
42f1618
readjust the value param in the set method
stan-dot Aug 21, 2024
ba01d19
trying to add the sim extra for ophyd-async
stan-dot Aug 30, 2024
80ac2e8
adapt to the ophyd-async update
stan-dot Sep 12, 2024
2aa1255
remove the wrong panda import
stan-dot Sep 13, 2024
378b978
fix epics imports
stan-dot Sep 13, 2024
d2a5c14
fix motor
stan-dot Sep 13, 2024
a01e7f5
add a set method
stan-dot Sep 23, 2024
e97bbae
add set wrap asyncstatus
stan-dot Sep 23, 2024
1792482
remove the Movable interface
stan-dot Sep 23, 2024
1502f89
table error still
stan-dot Sep 30, 2024
5b760eb
devices cleared up
stan-dot Sep 30, 2024
a712008
add testing to the i18 devices
stan-dot Oct 2, 2024
b0583a8
respond to feedback
stan-dot Oct 7, 2024
52f7b71
add testing for the crystal metadata
stan-dot Oct 7, 2024
ccd69e5
ruff fix
stan-dot Oct 7, 2024
0f53ba6
respond to feedback
stan-dot Oct 15, 2024
68c0a7a
cancel the skip_device comment
stan-dot Oct 16, 2024
a8a020b
cancel the crystal metadata
stan-dot Oct 16, 2024
314edda
fix imports again
stan-dot Oct 16, 2024
9d522ca
fix dcm i18 test
stan-dot Oct 29, 2024
9376dd1
fix lint
stan-dot Nov 11, 2024
67b43cd
fix import
stan-dot Nov 11, 2024
f5f0618
add test to increase covereage
stan-dot Nov 11, 2024
b808dd1
update the imports
stan-dot Nov 22, 2024
9f2369e
respond to feedback
stan-dot Nov 25, 2024
6526c61
delete test for sim detector (old)
stan-dot Nov 26, 2024
01de971
delete sim detector
stan-dot Nov 26, 2024
70df1eb
add name to diode
stan-dot Nov 26, 2024
78fdc27
restore the thor labs stage and cancel the xpress3 not working one
stan-dot Nov 26, 2024
5224b96
make all connect
stan-dot Nov 26, 2024
61007bd
fix the tests imports
stan-dot Jan 14, 2025
e8c8bcd
Add device_factory
DiamondJoseph Jan 24, 2025
e039885
remove unknown values and simulated device
DiamondJoseph Jan 24, 2025
d94415f
i18 slits centre spelling
DiamondJoseph Jan 24, 2025
5972984
Skip devices that require device classes
DiamondJoseph Jan 24, 2025
ebb5175
Remove unused devices
DiamondJoseph Jan 24, 2025
1068b44
Restore i18 dcm
DiamondJoseph Jan 24, 2025
9201e5b
add i18 beamline definition
stan-dot Aug 1, 2024
b916855
add metadata to dcm crystals
stan-dot Aug 1, 2024
216728c
adapt the tests
stan-dot Aug 1, 2024
1ba4df5
udpate fixtures
stan-dot Aug 2, 2024
cdaaf25
move devices from i18-bluesky
stan-dot Aug 2, 2024
7d2ddd3
fix some pv values
stan-dot Aug 5, 2024
c19a147
move away from ophyd devices
stan-dot Aug 5, 2024
9faa28e
add a kb mirror device@
stan-dot Aug 19, 2024
eb13245
test lookup table
stan-dot Aug 21, 2024
02a94dd
readjust the value param in the set method
stan-dot Aug 21, 2024
fd7adc2
adapt to the ophyd-async update
stan-dot Sep 12, 2024
6616168
remove the wrong panda import
stan-dot Sep 13, 2024
2dccb09
fix epics imports
stan-dot Sep 13, 2024
f9bf3e5
fix motor
stan-dot Sep 13, 2024
3f4cbf2
add a set method
stan-dot Sep 23, 2024
18515b6
add set wrap asyncstatus
stan-dot Sep 23, 2024
f1e03f9
remove the Movable interface
stan-dot Sep 23, 2024
87c9c73
table error still
stan-dot Sep 30, 2024
b79b76d
devices cleared up
stan-dot Sep 30, 2024
11b08e3
add testing to the i18 devices
stan-dot Oct 2, 2024
f743462
respond to feedback
stan-dot Oct 7, 2024
e753e40
add testing for the crystal metadata
stan-dot Oct 7, 2024
17fa5d3
ruff fix
stan-dot Oct 7, 2024
7c651cc
respond to feedback
stan-dot Oct 15, 2024
e3a2e0e
cancel the skip_device comment
stan-dot Oct 16, 2024
3b3fc28
cancel the crystal metadata
stan-dot Oct 16, 2024
5536626
fix imports again
stan-dot Oct 16, 2024
568828d
fix dcm i18 test
stan-dot Oct 29, 2024
8e42ad9
fix lint
stan-dot Nov 11, 2024
8e17e2f
fix import
stan-dot Nov 11, 2024
c239359
add test to increase covereage
stan-dot Nov 11, 2024
1e7f4a2
update the imports
stan-dot Nov 22, 2024
5fe2ca2
respond to feedback
stan-dot Nov 25, 2024
fe7ff5e
delete test for sim detector (old)
stan-dot Nov 26, 2024
a3f8b1a
delete sim detector
stan-dot Nov 26, 2024
b5fef2d
add name to diode
stan-dot Nov 26, 2024
05f2f50
restore the thor labs stage and cancel the xpress3 not working one
stan-dot Nov 26, 2024
5b8fec4
make all connect
stan-dot Nov 26, 2024
3f2a7c3
fix the tests imports
stan-dot Jan 14, 2025
7d66522
respond to feedback
stan-dot Jan 24, 2025
cfc9f78
fix lint
stan-dot Jan 27, 2025
5a87cee
merged
stan-dot Jan 27, 2025
f111987
apply some feedback
stan-dot Jan 27, 2025
5fbf51e
Update src/dodal/beamlines/i22.py
stan-dot Jan 27, 2025
10b54a7
add issue link to vfm error
stan-dot Jan 27, 2025
8171e96
add the tests for i18
stan-dot Jan 27, 2025
de2d3c6
adjust the dcm for i18 to have no metadata
stan-dot Jan 28, 2025
5f4220e
fix the tests
stan-dot Jan 28, 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
140 changes: 140 additions & 0 deletions src/dodal/beamlines/i18.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
from pathlib import Path

from ophyd_async.fastcs.panda import HDFPanda

from dodal.common.beamlines.beamline_utils import (
device_factory,
get_path_provider,
set_path_provider,
)
from dodal.common.beamlines.beamline_utils import set_beamline as set_utils_beamline
from dodal.common.crystal_metadata import CrystalMetadata
from dodal.common.visit import (
LocalDirectoryServiceClient,
StaticVisitPathProvider,
)
from dodal.devices.i18.diode import Diode
from dodal.devices.i18.KBMirror import KBMirror
from dodal.devices.i18.table import Table
from dodal.devices.i18.thor_labs_stage import ThorLabsStage
from dodal.devices.i22.dcm import DoubleCrystalMonochromator
from dodal.devices.slits import Slits
from dodal.devices.synchrotron import Synchrotron
from dodal.devices.tetramm import TetrammDetector
from dodal.devices.undulator import Undulator
from dodal.log import set_beamline as set_log_beamline
from dodal.utils import BeamlinePrefix, get_beamline_name

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


# Currently we must hard-code the visit, determining the visit at runtime requires
# infrastructure that is still WIP.
# Communication with GDA is also WIP so for now we determine an arbitrary scan number
# locally and write the commissioning directory. The scan number is not guaranteed to
# be unique and the data is at risk - this configuration is for testing only.
set_path_provider(
StaticVisitPathProvider(
BL,
Path("/dls/i18/data/2024/cm37264-2/bluesky"),
client=LocalDirectoryServiceClient(),
)
)


@device_factory()
def synchrotron() -> Synchrotron:
return Synchrotron()


@device_factory()
def undulator() -> Undulator:
return Undulator(f"{PREFIX.insertion_prefix}-MO-SERVC-01:")


@device_factory()
def dcm() -> DoubleCrystalMonochromator:
crystal_1_metadata = CrystalMetadata(
usage="Bragg",
type="silicon",
reflection=(1, 1, 1),
d_spacing=(3.13475, "nm"),
)

crystal_2_metadata = CrystalMetadata(
usage="Bragg",
type="silicon",
reflection=(1, 1, 1),
d_spacing=(3.13475, "nm"),
)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these crystals correct or copied from i22?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

correct I think

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can double check

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I sent an email about this


return DoubleCrystalMonochromator(
prefix=f"{PREFIX.beamline_prefix}-MO-DCM-01:",
temperature_prefix=f"{PREFIX.beamline_prefix}-DI-DCM-01:",
crystal_1_metadata=crystal_1_metadata,
crystal_2_metadata=crystal_2_metadata,
)


@device_factory()
def slits_1() -> Slits:
return Slits(
f"{PREFIX.beamline_prefix}-AL-SLITS-01:",
x_centre="X:CENTER",
y_centre="Y:CENTER",
)


# PandA IOC needs to be updated to support PVI
@device_factory(skip=True)
def panda1() -> HDFPanda:
return HDFPanda(
f"{PREFIX.beamline_prefix}-MO-PANDA-01:",
path_provider=get_path_provider(),
)


@device_factory()
def i0() -> TetrammDetector:
return TetrammDetector(
f"{PREFIX.beamline_prefix}-DI-XBPM-02:",
path_provider=get_path_provider(),
type="Cividec Diamond XBPM",
)


@device_factory()
def it() -> TetrammDetector:
return TetrammDetector(
f"{PREFIX.beamline_prefix}-DI-XBPM-01:",
path_provider=get_path_provider(),
)


@device_factory(skip=True)
# VFM uses different IOC than HFM https://github.com/DiamondLightSource/dodal/issues/1009
def vfm() -> KBMirror:
return KBMirror(f"{PREFIX.beamline_prefix}-OP-VFM-01:")


@device_factory()
def hfm() -> KBMirror:
return KBMirror(f"{PREFIX.beamline_prefix}-OP-HFM-01:")


@device_factory()
def d7diode() -> Diode:
return Diode(f"{PREFIX.beamline_prefix}-DI-PHDGN-07:")


@device_factory()
def main_table() -> Table:
return Table(f"{PREFIX.beamline_prefix}-MO-TABLE-01:")


@device_factory()
def thor_labs_stage() -> ThorLabsStage:
return ThorLabsStage(f"{PREFIX.beamline_prefix}-MO-TABLE-02:")
31 changes: 31 additions & 0 deletions src/dodal/devices/i18/KBMirror.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
from bluesky.protocols import Movable
from ophyd_async.core import AsyncStatus, StandardReadable
from ophyd_async.epics.core import epics_signal_rw
from pydantic import BaseModel


class XYPosition(BaseModel):
x: float
y: float


class KBMirror(StandardReadable, Movable):
def __init__(
self,
prefix: str,
name: str = "",
):
self._prefix = prefix
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
self._prefix = prefix

nit: not used anywhere

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd like to have it for reference for checking the object status though

with self.add_children_as_readables():
self.x = epics_signal_rw(float, prefix + "X")
self.y = epics_signal_rw(float, prefix + "Y")
self.bend1 = epics_signal_rw(float, prefix + "BEND1")
self.bend2 = epics_signal_rw(float, prefix + "BEND2")
self.curve = epics_signal_rw(float, prefix + "CURVE")
self.ellip = epics_signal_rw(float, prefix + "ELLIP")
super().__init__(name=name)

@AsyncStatus.wrap
async def set(self, value: XYPosition):
self.x.set(value.x)
self.y.set(value.y)
17 changes: 17 additions & 0 deletions src/dodal/devices/i18/diode.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from ophyd_async.core import (
StandardReadable,
)
from ophyd_async.epics.core import epics_signal_r


class Diode(StandardReadable):
def __init__(
self,
prefix: str,
name: str = "",
):
self._prefix = prefix
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
self._prefix = prefix

nit

with self.add_children_as_readables():
self.signal = epics_signal_r(float, prefix + "B:DIODE:I")

super().__init__(name=name)
32 changes: 32 additions & 0 deletions src/dodal/devices/i18/table.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
from ophyd_async.core import (
AsyncStatus,
StandardReadable,
)
from ophyd_async.epics.motor import Motor
from pydantic import BaseModel


class TablePosition(BaseModel):
x: float
y: float
z: float | None = None
theta: float | None = None
stan-dot marked this conversation as resolved.
Show resolved Hide resolved


class Table(StandardReadable):
def __init__(self, prefix: str, name: str = "") -> None:
with self.add_children_as_readables():
self.x = Motor(prefix + "X")
self.y = Motor(prefix + "Y")
self.z = Motor(prefix + "Z")
self.theta = Motor(prefix + "THETA")
super().__init__(name=name)

@AsyncStatus.wrap
async def set(self, value: TablePosition):
self.x.set(value.x)
self.y.set(value.y)
if value.z:
self.z.set(value.z)
if value.theta:
self.theta.set(value.theta)
24 changes: 24 additions & 0 deletions src/dodal/devices/i18/thor_labs_stage.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
from ophyd_async.core import (
AsyncStatus,
StandardReadable,
)
from ophyd_async.epics.motor import Motor
from pydantic import BaseModel


class XYPosition(BaseModel):
x: float
y: float


class ThorLabsStage(StandardReadable):
def __init__(self, prefix: str, name: str = "") -> None:
with self.add_children_as_readables():
self.x = Motor(prefix + "X")
self.y = Motor(prefix + "Y")
super().__init__(name=name)

@AsyncStatus.wrap
async def set(self, value: XYPosition):
self.x.set(value.x)
self.y.set(value.y)
66 changes: 66 additions & 0 deletions tests/devices/i18/test_kb_mirror.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
from unittest.mock import ANY

import pytest
from ophyd_async.core import DeviceCollector
from ophyd_async.testing import set_mock_value

from dodal.devices.i18.KBMirror import KBMirror, XYPosition


@pytest.fixture
async def kbmirror() -> KBMirror:
"""Fixture to set up a mock KBMirror device using DeviceCollector."""
async with DeviceCollector(mock=True):
kbmirror = KBMirror(prefix="MIRROR:")
return kbmirror


async def test_setting_xy_position_kbmirror(kbmirror: KBMirror):
"""
Test setting x and y positions on the KBMirror using the ophyd_async mock tools.
"""
# Mock the initial values of the x and y signals
set_mock_value(kbmirror.x, 0.0)
set_mock_value(kbmirror.y, 0.0)

# Create a position object
position = XYPosition(x=1.23, y=4.56)

# Call set to update the position
await kbmirror.set(position)

reading = await kbmirror.read()
expected_reading = {
"kbmirror-y": {
"value": 4.56,
"timestamp": ANY,
"alarm_severity": 0,
},
"kbmirror-bend1": {
"value": 0.0,
"timestamp": ANY,
"alarm_severity": 0,
},
"kbmirror-ellip": {
"value": 0.0,
"timestamp": ANY,
"alarm_severity": 0,
},
"kbmirror-x": {
"value": 1.23,
"timestamp": ANY,
"alarm_severity": 0,
},
"kbmirror-bend2": {
"value": 0.0,
"timestamp": ANY,
"alarm_severity": 0,
},
"kbmirror-curve": {
"value": 0.0,
"timestamp": ANY,
"alarm_severity": 0,
},
}

assert reading == expected_reading
51 changes: 51 additions & 0 deletions tests/devices/i18/test_table.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
from unittest.mock import ANY

import pytest
from ophyd_async.core import DeviceCollector
from ophyd_async.testing import set_mock_value

from dodal.devices.i18.table import Table, TablePosition


@pytest.fixture
async def table() -> Table:
"""Fixture to set up a mock Table device using DeviceCollector."""
async with DeviceCollector(mock=True):
table = Table(prefix="MIRROR:")
return table


async def test_setting_xy_position_table(table: Table):
"""
Test setting x and y positions on the Table using the ophyd_async mock tools.
"""
set_mock_value(table.x.user_readback, 1.23)
set_mock_value(table.y.user_readback, 4.56)

# Create a position object
position = TablePosition(x=1.23, y=4.56, z=0.0, theta=0.0)

# Call set to update the position
await table.set(position)

reading = await table.read()
expected_reading = {
"table-y": {
"value": 4.56,
"timestamp": ANY,
"alarm_severity": 0,
},
"table-x": {
"value": 1.23,
"timestamp": ANY,
"alarm_severity": 0,
},
"table-theta": {
"alarm_severity": 0,
"timestamp": ANY,
"value": 0.0,
},
"table-z": {"alarm_severity": 0, "timestamp": ANY, "value": 0.0},
}

assert reading == expected_reading
17 changes: 17 additions & 0 deletions tests/devices/unit_tests/i18/test_thor_labs_stage.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import pytest
from ophyd_async.core import DeviceCollector

from dodal.devices.i18.thor_labs_stage import ThorLabsStage, XYPosition


@pytest.fixture
async def fake_thor_labs_stage():
async with DeviceCollector(mock=True):
fake_thor_labs_stage = ThorLabsStage("", "thor_labs_stage")

return fake_thor_labs_stage


async def test_setting(fake_thor_labs_stage: ThorLabsStage):
pos = XYPosition(x=5, y=5)
await fake_thor_labs_stage.set(pos)
Loading
Loading