Skip to content

Commit

Permalink
Merge branch 'main' into 574_make_common_logging
Browse files Browse the repository at this point in the history
  • Loading branch information
olliesilvester authored Oct 16, 2024
2 parents 1bd4583 + 2957b1e commit 026e3ce
Show file tree
Hide file tree
Showing 10 changed files with 241 additions and 55 deletions.
8 changes: 8 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,14 @@ repos:
types: [python]
require_serial: true

- id: import-contracts
name: Ensure import directionality
pass_filenames: false
language: system
entry: lint-imports
types: [python]
require_serial: false

# Type checking
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.4.1
Expand Down
6 changes: 6 additions & 0 deletions hyperion_other/workflows/code.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@ jobs:
- name: Run ruff
run: ruff check .

- name: Install import linter
run: pip install import-linter

- name: Run import linter
run: lint-imports

tests:
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.repository
runs-on: ubuntu-latest
Expand Down
35 changes: 25 additions & 10 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ description = "Bluesky tools for MX Beamlines at DLS"
dependencies = [
#
# If a constraint is not set here or if the dependency is pinned to a hash
# it will be auto-pinned to the latest release version by the pre-release workflow
# it will be auto-pinned to the latest release version by the pre-release workflow
#
"annotated_types",
"caproto",
Expand All @@ -25,7 +25,7 @@ dependencies = [
"matplotlib",
"nexgen",
"numpy",
"opencv-python", # Needed for I24 ssx moveonclick. To be changed to headless once this is moved to separate ui.
"opencv-python", # Needed for I24 ssx moveonclick. To be changed to headless once this is moved to separate ui.
"opentelemetry-distro",
"opentelemetry-exporter-otlp",
"pydantic",
Expand All @@ -39,13 +39,13 @@ dependencies = [
#
# These dependencies may be issued as pre-release versions and should have a pin constraint
# as by default pip-install will not upgrade to a pre-release.
#
#
"blueapi >= 0.5.0",
"daq-config-server >= 0.1.1",
"ophyd == 1.9.0",
"ophyd-async >= 0.3a5",
"bluesky >= 1.13.0a4",
"dls-dodal @ git+https://github.com/DiamondLightSource/dodal.git",
"dls-dodal @ git+https://github.com/DiamondLightSource/dodal.git@main",
]


Expand All @@ -62,6 +62,7 @@ dev = [
# "copier",
"diff-cover",
"GitPython",
"import-linter",
"ipython",
"mypy",
"myst-parser",
Expand Down Expand Up @@ -122,8 +123,6 @@ addopts = """
# https://iscinumpy.gitlab.io/post/bound-version-constraints/#watch-for-warnings
filterwarnings = [
"error",
# Ignore incorrect errors from bluesky (remove when https://github.com/bluesky/bluesky/issues/1797 is released)
"ignore:((.|\n)*)was never iterated.*:RuntimeWarning",
# Ignore deprecation warning from sqlalchemy
"ignore::sqlalchemy.exc.MovedIn20Warning",
# Ignore deprecation warning from setuptools_dso (remove when https://github.com/epics-base/setuptools_dso/issues/36 is released)
Expand All @@ -134,10 +133,6 @@ filterwarnings = [
"ignore:(.*)unclosed file(.*)name='(.*)dodal.log'(.*):ResourceWarning",
"ignore:(.*)unclosed <socket(.*):ResourceWarning",
"ignore:(.*)unclosed event loop(.*):ResourceWarning",
# Ignore pydantic 2 issues from blueapi, see https://github.com/DiamondLightSource/blueapi/issues/622
"ignore::DeprecationWarning:blueapi",
# Ignore deprecation warning from python-workflows https://github.com/DiamondLightSource/python-workflows/issues/180
"ignore:.*pkg_resources.*:DeprecationWarning",
]
# Doctest python code in docs, python code in src docstrings, test functions in tests
testpaths = "docs src tests/unit_tests"
Expand Down Expand Up @@ -198,3 +193,23 @@ lint.extend-ignore = [

[tool.mypy]
plugins = ["pydantic.mypy"]

[tool.importlinter]
root_package = "mx_bluesky"

[[tool.importlinter.contracts]]
name = "Common does not import from apps"
type = "forbidden"
source_modules = "mx_bluesky.common"
forbidden_modules = ["mx_bluesky.beamlines", "mx_bluesky.hyperion"]

[[tool.importlinter.contracts]]
name = "Beamlines do not import from each other"
type = "independence"
modules = "mx_bluesky.beamlines.*"

[[tool.importlinter.contracts]]
name = "Beamlines do not import from hyperion"
type = "forbidden"
source_modules = "mx_bluesky.beamlines.*"
forbidden_modules = "mx_bluesky.hyperion"
34 changes: 31 additions & 3 deletions src/mx_bluesky/beamlines/i04/thawing_plan.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
from collections.abc import Callable

import bluesky.plan_stubs as bps
import bluesky.preprocessors as bpp
from bluesky.preprocessors import run_decorator, subs_decorator
from dls_bluesky_core.core import MsgGenerator
from dodal.beamlines.i04 import MURKO_REDIS_DB, REDIS_HOST, REDIS_PASSWORD
from dodal.common import inject
from dodal.devices.oav.oav_detector import OAV
from dodal.devices.oav.oav_to_redis_forwarder import OAVToRedisForwarder
from dodal.devices.oav.oav_to_redis_forwarder import OAVToRedisForwarder, Source
from dodal.devices.robot import BartRobot
from dodal.devices.smargon import Smargon
from dodal.devices.thawer import Thawer, ThawerStates
Expand All @@ -24,10 +26,16 @@ def thaw_and_stream_to_redis(
) -> MsgGenerator:
zoom_percentage = yield from bps.rd(oav.zoom_controller.percentage) # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
sample_id = yield from bps.rd(robot.sample_id)
zoom_level_before_thawing = yield from bps.rd(oav.zoom_controller.level) # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809

yield from bps.abs_set(oav.zoom_controller.level, "1.0x", wait=True) # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
yield from bps.abs_set(oav_to_redis_forwarder.sample_id, sample_id)

def switch_forwarder_to_ROI() -> MsgGenerator:
yield from bps.complete(oav_to_redis_forwarder)
yield from bps.mv(oav_to_redis_forwarder.selected_source, Source.ROI) # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
yield from bps.kickoff(oav_to_redis_forwarder, wait=True)

@subs_decorator(MurkoCallback(REDIS_HOST, REDIS_PASSWORD, MURKO_REDIS_DB))
@run_decorator(
md={
Expand All @@ -40,20 +48,36 @@ def thaw_and_stream_to_redis(
}
)
def _thaw_and_stream_to_redis():
yield from bps.mv(
oav_to_redis_forwarder.sample_id, # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
sample_id,
oav_to_redis_forwarder.selected_source, # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
Source.FULL_SCREEN, # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
)

yield from bps.kickoff(oav_to_redis_forwarder, wait=True)
yield from bps.monitor(smargon.omega.user_readback, name="smargon")
yield from bps.monitor(oav_to_redis_forwarder.uuid, name="oav")
yield from thaw(time_to_thaw, rotation, thawer, smargon)
yield from thaw(
time_to_thaw, rotation, thawer, smargon, switch_forwarder_to_ROI
)
yield from bps.complete(oav_to_redis_forwarder)

yield from _thaw_and_stream_to_redis()
def cleanup():
yield from bps.mv(oav.zoom_controller.level, zoom_level_before_thawing) # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809

yield from bpp.contingency_wrapper(
_thaw_and_stream_to_redis(),
final_plan=cleanup,
)


def thaw(
time_to_thaw: float,
rotation: float = 360,
thawer: Thawer = inject("thawer"),
smargon: Smargon = inject("smargon"),
plan_between_rotations: Callable[[], MsgGenerator] | None = None,
) -> MsgGenerator:
"""Rotates the sample and thaws it at the same time.
Expand All @@ -64,6 +88,8 @@ def thaw(
thawer (Thawer, optional): The thawing device. Defaults to inject("thawer").
smargon (Smargon, optional): The smargon used to rotate.
Defaults to inject("smargon")
plan_between_rotations (MsgGenerator, optional): A plan to run between rotations
of the smargon. Defaults to no plan.
"""
inital_velocity = yield from bps.rd(smargon.omega.velocity)
new_velocity = abs(rotation / time_to_thaw) * 2.0
Expand All @@ -72,6 +98,8 @@ def do_thaw():
yield from bps.abs_set(smargon.omega.velocity, new_velocity, wait=True)
yield from bps.abs_set(thawer.control, ThawerStates.ON, wait=True)
yield from bps.rel_set(smargon.omega, rotation, wait=True)
if plan_between_rotations:
yield from plan_between_rotations()
yield from bps.rel_set(smargon.omega, -rotation, wait=True)

def cleanup():
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from bluesky.run_engine import RunEngine
from dodal.beamlines import i24
from dodal.devices.i24.pmac import PMAC
from dodal.devices.oav.oav_detector import OAV
from dodal.devices.oav.oav_async import OAV

from mx_bluesky.beamlines.i24.serial.fixed_target import (
i24ssx_Chip_Manager_py3v1 as manager,
Expand All @@ -28,7 +28,9 @@ def _get_beam_centre(oav: OAV):
Args:
oav (OAV): the OAV device.
"""
return oav.parameters.beam_centre_i, oav.parameters.beam_centre_j
beam_x = yield from bps.rd(oav.beam_centre_i)
beam_y = yield from bps.rd(oav.beam_centre_j)
return beam_x, beam_y


def _calculate_zoom_calibrator(oav: OAV):
Expand All @@ -39,13 +41,15 @@ def _calculate_zoom_calibrator(oav: OAV):


def _move_on_mouse_click_plan(
oav: OAV, pmac: PMAC, beam_centre: Sequence[int], clicked_position: Sequence[int]
oav: OAV,
pmac: PMAC,
clicked_position: Sequence[int],
):
"""A plan that calculates the zoom calibrator and moves to the clicked \
position coordinates.
"""
zoomcalibrator = yield from _calculate_zoom_calibrator(oav)
beamX, beamY = beam_centre
beamX, beamY = yield from _get_beam_centre(oav)
x, y = clicked_position
xmove = -1 * (beamX - x) * zoomcalibrator
ymove = -1 * (beamY - y) * zoomcalibrator
Expand All @@ -62,14 +66,13 @@ def onMouse(event, x, y, flags, param):
RE = param[0]
pmac = param[1]
oav = param[2]
beamX, beamY = _get_beam_centre(oav)
logger.info(f"Clicked X and Y {x} {y}")
RE(_move_on_mouse_click_plan(oav, pmac, (beamX, beamY), (x, y)))
RE(_move_on_mouse_click_plan(oav, pmac, (x, y)))


def update_ui(oav, frame):
def update_ui(oav, frame, RE):
# Get beam x and y values
beamX, beamY = _get_beam_centre(oav)
beamX, beamY = RE(_get_beam_centre(oav)).plan_result

# Overlay text and beam centre
cv.ellipse(
Expand Down Expand Up @@ -164,7 +167,7 @@ def start_viewer(oav: OAV, pmac: PMAC, RE: RunEngine, oav1: str = OAV1_CAM):
while success:
success, frame = cap.read()

update_ui(oav, frame)
update_ui(oav, frame, RE)

k = cv.waitKey(1)
if k == 113: # Q
Expand Down Expand Up @@ -212,7 +215,7 @@ def start_viewer(oav: OAV, pmac: PMAC, RE: RunEngine, oav1: str = OAV1_CAM):


if __name__ == "__main__":
RE = RunEngine()
RE = RunEngine(call_returns_result=True)
# Get devices out of dodal
oav: OAV = i24.oav()
pmac: PMAC = i24.pmac()
Expand Down
Empty file.
9 changes: 9 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,15 @@ def oav(test_config_files):
parameters.micronsPerXPixel = 2.87
parameters.micronsPerYPixel = 2.87
oav = i03.oav(fake_with_ophyd_sim=True, params=parameters)

oav.zoom_controller.zrst.set("1.0x")
oav.zoom_controller.onst.set("2.0x")

oav.parameters.micronsPerXPixel = 1.58
oav.parameters.micronsPerYPixel = 1.58
oav.parameters.beam_centre_i = 517
oav.parameters.beam_centre_j = 350

oav.snapshot.trigger = MagicMock(return_value=NullStatus())
oav.zoom_controller.zrst.set("1.0x")
oav.zoom_controller.onst.set("2.0x")
Expand Down
Loading

0 comments on commit 026e3ce

Please sign in to comment.