dls-dodal 1.46.0__py3-none-any.whl → 1.48.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. {dls_dodal-1.46.0.dist-info → dls_dodal-1.48.0.dist-info}/METADATA +2 -2
  2. {dls_dodal-1.46.0.dist-info → dls_dodal-1.48.0.dist-info}/RECORD +74 -63
  3. {dls_dodal-1.46.0.dist-info → dls_dodal-1.48.0.dist-info}/WHEEL +1 -1
  4. dodal/_version.py +2 -2
  5. dodal/beamlines/__init__.py +0 -1
  6. dodal/beamlines/aithre.py +6 -0
  7. dodal/beamlines/b01_1.py +1 -1
  8. dodal/beamlines/b07.py +2 -6
  9. dodal/beamlines/b07_1.py +1 -3
  10. dodal/beamlines/i03.py +33 -21
  11. dodal/beamlines/i04.py +65 -26
  12. dodal/beamlines/i09.py +1 -3
  13. dodal/beamlines/i09_1.py +1 -3
  14. dodal/beamlines/i18.py +1 -1
  15. dodal/beamlines/i19_1.py +9 -6
  16. dodal/beamlines/i23.py +17 -1
  17. dodal/beamlines/i24.py +5 -5
  18. dodal/beamlines/p38.py +1 -1
  19. dodal/beamlines/p60.py +2 -6
  20. dodal/beamlines/p99.py +48 -4
  21. dodal/common/beamlines/beamline_parameters.py +3 -30
  22. dodal/common/data_util.py +4 -0
  23. dodal/devices/aithre_lasershaping/goniometer.py +36 -2
  24. dodal/devices/aithre_lasershaping/laser_robot.py +27 -0
  25. dodal/devices/aperturescatterguard.py +47 -47
  26. dodal/devices/current_amplifiers/struck_scaler_counter.py +1 -1
  27. dodal/devices/diamond_filter.py +5 -17
  28. dodal/devices/eiger.py +1 -1
  29. dodal/devices/electron_analyser/__init__.py +18 -0
  30. dodal/devices/electron_analyser/abstract/__init__.py +22 -0
  31. dodal/devices/electron_analyser/abstract/base_detector.py +223 -0
  32. dodal/devices/electron_analyser/abstract/base_driver_io.py +230 -0
  33. dodal/devices/electron_analyser/{abstract_region.py → abstract/base_region.py} +3 -9
  34. dodal/devices/electron_analyser/specs/__init__.py +10 -0
  35. dodal/devices/electron_analyser/specs/detector.py +13 -0
  36. dodal/devices/electron_analyser/specs/driver_io.py +89 -0
  37. dodal/devices/electron_analyser/{specs_region.py → specs/region.py} +1 -1
  38. dodal/devices/electron_analyser/types.py +6 -0
  39. dodal/devices/electron_analyser/util.py +13 -0
  40. dodal/devices/electron_analyser/vgscienta/__init__.py +11 -0
  41. dodal/devices/electron_analyser/vgscienta/detector.py +22 -0
  42. dodal/devices/electron_analyser/vgscienta/driver_io.py +67 -0
  43. dodal/devices/electron_analyser/{vgscienta_region.py → vgscienta/region.py} +1 -2
  44. dodal/devices/fast_grid_scan.py +7 -9
  45. dodal/devices/i03/__init__.py +3 -0
  46. dodal/devices/i04/__init__.py +3 -0
  47. dodal/devices/i04/constants.py +9 -0
  48. dodal/devices/i04/murko_results.py +192 -0
  49. dodal/devices/i10/diagnostics.py +9 -61
  50. dodal/devices/i18/diode.py +37 -4
  51. dodal/devices/i24/focus_mirrors.py +9 -13
  52. dodal/devices/i24/pilatus_metadata.py +9 -9
  53. dodal/devices/i24/pmac.py +19 -14
  54. dodal/devices/{i03 → mx_phase1}/beamstop.py +26 -15
  55. dodal/devices/oav/oav_calculations.py +2 -2
  56. dodal/devices/oav/oav_detector.py +80 -32
  57. dodal/devices/oav/oav_parameters.py +46 -16
  58. dodal/devices/oav/oav_to_redis_forwarder.py +2 -2
  59. dodal/devices/oav/utils.py +2 -2
  60. dodal/devices/p99/andor2_point.py +41 -0
  61. dodal/devices/positioner.py +49 -0
  62. dodal/devices/robot.py +20 -1
  63. dodal/devices/smargon.py +43 -4
  64. dodal/devices/tetramm.py +5 -2
  65. dodal/devices/util/adjuster_plans.py +1 -1
  66. dodal/devices/zebra/zebra.py +8 -0
  67. dodal/devices/zebra/zebra_constants_mapping.py +1 -1
  68. dodal/devices/zocalo/__init__.py +0 -3
  69. dodal/devices/zocalo/zocalo_results.py +6 -32
  70. dodal/log.py +14 -14
  71. dodal/plans/configure_arm_trigger_and_disarm_detector.py +167 -0
  72. dodal/common/signal_utils.py +0 -88
  73. dodal/devices/electron_analyser/abstract_analyser_io.py +0 -47
  74. dodal/devices/electron_analyser/specs_analyser_io.py +0 -19
  75. dodal/devices/electron_analyser/vgscienta_analyser_io.py +0 -26
  76. dodal/devices/logging_ophyd_device.py +0 -17
  77. dodal/plan_stubs/electron_analyser/__init__.py +0 -0
  78. dodal/plan_stubs/electron_analyser/configure_controller.py +0 -80
  79. {dls_dodal-1.46.0.dist-info → dls_dodal-1.48.0.dist-info}/entry_points.txt +0 -0
  80. {dls_dodal-1.46.0.dist-info → dls_dodal-1.48.0.dist-info}/licenses/LICENSE +0 -0
  81. {dls_dodal-1.46.0.dist-info → dls_dodal-1.48.0.dist-info}/top_level.txt +0 -0
dodal/beamlines/i04.py CHANGED
@@ -1,7 +1,8 @@
1
- import os
2
-
3
1
  from dodal.common.beamlines.beamline_parameters import get_beamline_parameters
4
- from dodal.common.beamlines.beamline_utils import device_factory, device_instantiation
2
+ from dodal.common.beamlines.beamline_utils import (
3
+ device_factory,
4
+ device_instantiation,
5
+ )
5
6
  from dodal.common.beamlines.beamline_utils import set_beamline as set_utils_beamline
6
7
  from dodal.devices.aperturescatterguard import (
7
8
  AperturePosition,
@@ -17,12 +18,16 @@ from dodal.devices.eiger import EigerDetector
17
18
  from dodal.devices.fast_grid_scan import ZebraFastGridScan
18
19
  from dodal.devices.flux import Flux
19
20
  from dodal.devices.i03.dcm import DCM
21
+ from dodal.devices.i04.constants import RedisConstants
22
+ from dodal.devices.i04.murko_results import MurkoResultsDevice
20
23
  from dodal.devices.i04.transfocator import Transfocator
21
24
  from dodal.devices.ipin import IPin
22
25
  from dodal.devices.motors import XYZPositioner
23
- from dodal.devices.oav.oav_detector import OAV
26
+ from dodal.devices.mx_phase1.beamstop import Beamstop
27
+ from dodal.devices.oav.oav_detector import OAVBeamCentrePV
24
28
  from dodal.devices.oav.oav_parameters import OAVConfig
25
29
  from dodal.devices.oav.oav_to_redis_forwarder import OAVToRedisForwarder
30
+ from dodal.devices.oav.pin_image_recognition import PinTipDetection
26
31
  from dodal.devices.robot import BartRobot
27
32
  from dodal.devices.s4_slit_gaps import S4SlitGaps
28
33
  from dodal.devices.smargon import Smargon
@@ -37,6 +42,7 @@ from dodal.devices.zebra.zebra_constants_mapping import (
37
42
  ZebraTTLOutputs,
38
43
  )
39
44
  from dodal.devices.zebra.zebra_controlled_shutter import ZebraShutter
45
+ from dodal.devices.zocalo import ZocaloResults
40
46
  from dodal.log import set_beamline as set_log_beamline
41
47
  from dodal.utils import BeamlinePrefix, get_beamline_name
42
48
 
@@ -46,11 +52,8 @@ ZOOM_PARAMS_FILE = (
46
52
  DISPLAY_CONFIG = "/dls_sw/i04/software/gda_versions/var/display.configuration"
47
53
  DAQ_CONFIGURATION_PATH = "/dls_sw/i04/software/daq_configuration"
48
54
 
49
- REDIS_HOST = "i04-valkey-murko.diamond.ac.uk"
50
- REDIS_PASSWORD = os.environ.get("VALKEY_PASSWORD", "test_redis_password")
51
- MURKO_REDIS_DB = 7
52
55
 
53
- BL = get_beamline_name("s04")
56
+ BL = get_beamline_name("i04")
54
57
  set_log_beamline(BL)
55
58
  set_utils_beamline(BL)
56
59
 
@@ -107,13 +110,13 @@ def ipin() -> IPin:
107
110
 
108
111
 
109
112
  @device_factory()
110
- def beamstop() -> XYZPositioner:
113
+ def beamstop() -> Beamstop:
111
114
  """Get the i04 beamstop device, instantiate it if it hasn't already been.
112
115
  If this is called when already instantiated in i04, it will return the existing object.
113
116
  """
114
- return XYZPositioner(
117
+ return Beamstop(
115
118
  f"{PREFIX.beamline_prefix}-MO-BS-01:",
116
- "beamstop",
119
+ beamline_parameters=get_beamline_parameters(),
117
120
  )
118
121
 
119
122
 
@@ -294,18 +297,25 @@ def zebra() -> Zebra:
294
297
 
295
298
 
296
299
  @device_factory(skip=BL == "s04")
297
- def oav(
298
- wait_for_connection: bool = True,
299
- fake_with_ophyd_sim: bool = False,
300
- params: OAVConfig | None = None,
301
- ) -> OAV:
300
+ def oav(params: OAVConfig | None = None) -> OAVBeamCentrePV:
301
+ """Get the i04 OAV device, instantiate it if it hasn't already been.
302
+ If this is called when already instantiated in i04, it will return the existing object.
303
+ """
304
+ return OAVBeamCentrePV(
305
+ prefix=f"{PREFIX.beamline_prefix}-DI-OAV-01:",
306
+ config=params or OAVConfig(ZOOM_PARAMS_FILE),
307
+ )
308
+
309
+
310
+ @device_factory(skip=BL == "s04")
311
+ def oav_full_screen(params: OAVConfig | None = None) -> OAVBeamCentrePV:
302
312
  """Get the i04 OAV device, instantiate it if it hasn't already been.
303
313
  If this is called when already instantiated in i04, it will return the existing object.
304
314
  """
305
- return OAV(
315
+ return OAVBeamCentrePV(
306
316
  prefix=f"{PREFIX.beamline_prefix}-DI-OAV-01:",
307
- name="oav",
308
- config=params or OAVConfig(ZOOM_PARAMS_FILE, DISPLAY_CONFIG),
317
+ config=params or OAVConfig(ZOOM_PARAMS_FILE),
318
+ overlay_channel=3,
309
319
  )
310
320
 
311
321
 
@@ -350,19 +360,48 @@ def oav_to_redis_forwarder() -> OAVToRedisForwarder:
350
360
  return OAVToRedisForwarder(
351
361
  f"{PREFIX.beamline_prefix}-DI-OAV-01:",
352
362
  name="oav_to_redis_forwarder",
353
- redis_host=REDIS_HOST,
354
- redis_password=REDIS_PASSWORD,
355
- redis_db=7,
363
+ redis_host=RedisConstants.REDIS_HOST,
364
+ redis_password=RedisConstants.REDIS_PASSWORD,
365
+ redis_db=RedisConstants.MURKO_REDIS_DB,
366
+ )
367
+
368
+
369
+ @device_factory()
370
+ def murko_results() -> MurkoResultsDevice:
371
+ """Get the i04 OAV to redis forwarder, instantiate it if it hasn't already been.
372
+ If this is called when already instantiated in i04, it will return the existing object.
373
+ """
374
+ return MurkoResultsDevice(
375
+ name="murko_results",
376
+ redis_host=RedisConstants.REDIS_HOST,
377
+ redis_password=RedisConstants.REDIS_PASSWORD,
378
+ redis_db=RedisConstants.MURKO_REDIS_DB,
356
379
  )
357
380
 
358
381
 
359
382
  @device_factory()
360
383
  def diamond_filter() -> DiamondFilter[I04Filters]:
361
384
  """Get the i04 diamond filter device, instantiate it if it hasn't already been.
362
- If this is called when already instantiated in i03, it will return the existing object.
385
+ If this is called when already instantiated in i04, it will return the existing object.
363
386
  """
364
387
  return DiamondFilter[I04Filters](
365
- prefix=f"{PREFIX.beamline_prefix}-MO-FLTR-01:",
366
- name="diamond_filter",
367
- data_type=I04Filters,
388
+ f"{PREFIX.beamline_prefix}-MO-FLTR-01:Y", I04Filters
389
+ )
390
+
391
+
392
+ @device_factory()
393
+ def zocalo() -> ZocaloResults:
394
+ """Get the i04 ZocaloResults device, instantiate it if it hasn't already been.
395
+ If this is called when already instantiated in i04, it will return the existing object.
396
+ """
397
+ return ZocaloResults(channel="xrc.i04")
398
+
399
+
400
+ @device_factory()
401
+ def pin_tip_detection() -> PinTipDetection:
402
+ """Get the i04 pin tip detection device, instantiate it if it hasn't already been.
403
+ If this is called when already instantiated in i04, it will return the existing object.
404
+ """
405
+ return PinTipDetection(
406
+ f"{PREFIX.beamline_prefix}-DI-OAV-01:",
368
407
  )
dodal/beamlines/i09.py CHANGED
@@ -2,9 +2,7 @@ from dodal.common.beamlines.beamline_utils import (
2
2
  device_factory,
3
3
  )
4
4
  from dodal.common.beamlines.beamline_utils import set_beamline as set_utils_beamline
5
- from dodal.devices.electron_analyser.vgscienta_analyser_io import (
6
- VGScientaAnalyserDriverIO,
7
- )
5
+ from dodal.devices.electron_analyser.vgscienta import VGScientaAnalyserDriverIO
8
6
  from dodal.devices.synchrotron import Synchrotron
9
7
  from dodal.log import set_beamline as set_log_beamline
10
8
  from dodal.utils import BeamlinePrefix, get_beamline_name
dodal/beamlines/i09_1.py CHANGED
@@ -2,9 +2,7 @@ from dodal.common.beamlines.beamline_utils import (
2
2
  device_factory,
3
3
  )
4
4
  from dodal.common.beamlines.beamline_utils import set_beamline as set_utils_beamline
5
- from dodal.devices.electron_analyser.specs_analyser_io import (
6
- SpecsAnalyserDriverIO,
7
- )
5
+ from dodal.devices.electron_analyser.specs import SpecsAnalyserDriverIO
8
6
  from dodal.devices.synchrotron import Synchrotron
9
7
  from dodal.log import set_beamline as set_log_beamline
10
8
  from dodal.utils import BeamlinePrefix, get_beamline_name
dodal/beamlines/i18.py CHANGED
@@ -113,7 +113,7 @@ def hfm() -> KBMirror:
113
113
 
114
114
 
115
115
  @device_factory()
116
- def d7diode() -> Diode:
116
+ def d7_diode() -> Diode:
117
117
  return Diode(f"{PREFIX.beamline_prefix}-DI-PHDGN-07:")
118
118
 
119
119
 
dodal/beamlines/i19_1.py CHANGED
@@ -6,9 +6,12 @@ from dodal.common.beamlines.beamline_utils import (
6
6
  )
7
7
  from dodal.devices.i19.beamstop import BeamStop
8
8
  from dodal.devices.i19.blueapi_device import HutchState
9
- from dodal.devices.i19.shutter import AccessControlledShutter
10
- from dodal.devices.oav.oav_detector import OAV
11
- from dodal.devices.oav.oav_parameters import OAVConfig
9
+ from dodal.devices.i19.shutter import (
10
+ AccessControlledShutter,
11
+ HutchState,
12
+ )
13
+ from dodal.devices.oav.oav_detector import OAVBeamCentreFile
14
+ from dodal.devices.oav.oav_parameters import OAVConfigBeamCentre
12
15
  from dodal.devices.synchrotron import Synchrotron
13
16
  from dodal.devices.zebra.zebra import Zebra
14
17
  from dodal.devices.zebra.zebra_constants_mapping import (
@@ -48,10 +51,10 @@ def beamstop() -> BeamStop:
48
51
 
49
52
 
50
53
  @device_factory()
51
- def oav() -> OAV:
52
- return OAV(
54
+ def oav() -> OAVBeamCentreFile:
55
+ return OAVBeamCentreFile(
53
56
  prefix=f"{PREFIX.beamline_prefix}-EA-OAV-01:",
54
- config=OAVConfig(ZOOM_PARAMS_FILE, DISPLAY_CONFIG),
57
+ config=OAVConfigBeamCentre(ZOOM_PARAMS_FILE, DISPLAY_CONFIG),
55
58
  )
56
59
 
57
60
 
dodal/beamlines/i23.py CHANGED
@@ -1,5 +1,6 @@
1
1
  from pathlib import Path
2
2
 
3
+ from ophyd_async.core import StrictEnum
3
4
  from ophyd_async.epics.adpilatus import PilatusDetector
4
5
 
5
6
  from dodal.common.beamlines.beamline_utils import (
@@ -12,6 +13,7 @@ from dodal.common.beamlines.device_helpers import HDF5_SUFFIX
12
13
  from dodal.common.visit import LocalDirectoryServiceClient, StaticVisitPathProvider
13
14
  from dodal.devices.motors import SixAxisGonio
14
15
  from dodal.devices.oav.pin_image_recognition import PinTipDetection
16
+ from dodal.devices.positioner import Positioner1D
15
17
  from dodal.devices.zebra.zebra import Zebra
16
18
  from dodal.devices.zebra.zebra_constants_mapping import (
17
19
  ZebraMapping,
@@ -39,10 +41,15 @@ PREFIX = BeamlinePrefix(BL)
39
41
  I23_ZEBRA_MAPPING = ZebraMapping(
40
42
  outputs=ZebraTTLOutputs(TTL_DETECTOR=1, TTL_SHUTTER=4),
41
43
  sources=ZebraSources(),
42
- AND_GATE_FOR_AUTO_SHUTTER=2,
43
44
  )
44
45
 
45
46
 
47
+ class I23DetectorPositions(StrictEnum):
48
+ IN = "In"
49
+ OUT = "Out"
50
+ SAMPLE_CHANGE = "sample change"
51
+
52
+
46
53
  def _is_i23_machine():
47
54
  """
48
55
  Devices using PVA can only connect from i23 machines, due to the absence of
@@ -93,3 +100,12 @@ def pilatus() -> PilatusDetector:
93
100
  drv_suffix="cam1:",
94
101
  fileio_suffix=HDF5_SUFFIX,
95
102
  )
103
+
104
+
105
+ @device_factory()
106
+ def detector_motion() -> Positioner1D[I23DetectorPositions]:
107
+ """Get the i23 detector"""
108
+ return Positioner1D[I23DetectorPositions](
109
+ f"{PREFIX.beamline_prefix}-EA-DET-01:Z",
110
+ datatype=I23DetectorPositions,
111
+ )
dodal/beamlines/i24.py CHANGED
@@ -15,8 +15,8 @@ from dodal.devices.i24.i24_detector_motion import DetectorMotion
15
15
  from dodal.devices.i24.pilatus_metadata import PilatusMetadata
16
16
  from dodal.devices.i24.pmac import PMAC
17
17
  from dodal.devices.i24.vgonio import VerticalGoniometer
18
- from dodal.devices.oav.oav_detector import OAV
19
- from dodal.devices.oav.oav_parameters import OAVConfig
18
+ from dodal.devices.oav.oav_detector import OAVBeamCentreFile
19
+ from dodal.devices.oav.oav_parameters import OAVConfigBeamCentre
20
20
  from dodal.devices.zebra.zebra import Zebra
21
21
  from dodal.devices.zebra.zebra_constants_mapping import (
22
22
  ZebraMapping,
@@ -150,11 +150,11 @@ def pmac() -> PMAC:
150
150
 
151
151
 
152
152
  @device_factory(skip=BL == "s24")
153
- def oav() -> OAV:
154
- return OAV(
153
+ def oav() -> OAVBeamCentreFile:
154
+ return OAVBeamCentreFile(
155
155
  prefix=f"{PREFIX.beamline_prefix}-DI-OAV-01:",
156
156
  name="oav",
157
- config=OAVConfig(ZOOM_PARAMS_FILE, DISPLAY_CONFIG),
157
+ config=OAVConfigBeamCentre(ZOOM_PARAMS_FILE, DISPLAY_CONFIG),
158
158
  )
159
159
 
160
160
 
dodal/beamlines/p38.py CHANGED
@@ -40,7 +40,7 @@ set_utils_beamline(BL)
40
40
  set_path_provider(
41
41
  StaticVisitPathProvider(
42
42
  BL,
43
- Path("/dls/p38/data/2024/cm37282-2/bluesky"),
43
+ Path("/dls/p38/data/2025/cm40650-2/bluesky"),
44
44
  client=LocalDirectoryServiceClient(),
45
45
  )
46
46
  )
dodal/beamlines/p60.py CHANGED
@@ -2,9 +2,7 @@ from dodal.common.beamlines.beamline_utils import (
2
2
  device_factory,
3
3
  )
4
4
  from dodal.common.beamlines.beamline_utils import set_beamline as set_utils_beamline
5
- from dodal.devices.electron_analyser.vgscienta_analyser_io import (
6
- VGScientaAnalyserDriverIO,
7
- )
5
+ from dodal.devices.electron_analyser.vgscienta import VGScientaAnalyserDriverIO
8
6
  from dodal.log import set_beamline as set_log_beamline
9
7
  from dodal.utils import BeamlinePrefix, get_beamline_name
10
8
 
@@ -16,6 +14,4 @@ set_utils_beamline(BL)
16
14
 
17
15
  @device_factory()
18
16
  def analyser_driver() -> VGScientaAnalyserDriverIO:
19
- return VGScientaAnalyserDriverIO(
20
- name="analyser_driver", prefix=f"{PREFIX.beamline_prefix}-EA-DET-01:CAM:"
21
- )
17
+ return VGScientaAnalyserDriverIO(prefix=f"{PREFIX.beamline_prefix}-EA-DET-01:CAM:")
dodal/beamlines/p99.py CHANGED
@@ -1,7 +1,22 @@
1
- from dodal.common.beamlines.beamline_utils import device_factory, set_beamline
1
+ from pathlib import Path
2
+
3
+ from ophyd_async.epics.adandor import Andor2Detector
4
+
5
+ from dodal.common.beamlines.beamline_utils import (
6
+ device_factory,
7
+ get_path_provider,
8
+ set_beamline,
9
+ set_path_provider,
10
+ )
11
+ from dodal.common.beamlines.device_helpers import CAM_SUFFIX, HDF5_SUFFIX
12
+ from dodal.common.visit import (
13
+ LocalDirectoryServiceClient,
14
+ StaticVisitPathProvider,
15
+ )
2
16
  from dodal.devices.attenuator.filter import FilterMotor
3
17
  from dodal.devices.attenuator.filter_selections import P99FilterSelections
4
18
  from dodal.devices.motors import XYZPositioner
19
+ from dodal.devices.p99.andor2_point import Andor2Point
5
20
  from dodal.devices.p99.sample_stage import SampleAngleStage
6
21
  from dodal.log import set_beamline as set_log_beamline
7
22
  from dodal.utils import BeamlinePrefix, get_beamline_name
@@ -19,9 +34,7 @@ def angle_stage() -> SampleAngleStage:
19
34
 
20
35
  @device_factory()
21
36
  def filter() -> FilterMotor:
22
- return FilterMotor(
23
- f"{PREFIX.beamline_prefix}-MO-STAGE-02:MP:SELECT", P99FilterSelections
24
- )
37
+ return FilterMotor(f"{PREFIX.beamline_prefix}-MO-STAGE-02:MP:", P99FilterSelections)
25
38
 
26
39
 
27
40
  @device_factory()
@@ -32,3 +45,34 @@ def sample_stage() -> XYZPositioner:
32
45
  @device_factory()
33
46
  def lab_stage() -> XYZPositioner:
34
47
  return XYZPositioner(f"{PREFIX.beamline_prefix}-MO-STAGE-02:LAB:")
48
+
49
+
50
+ set_path_provider(
51
+ StaticVisitPathProvider(
52
+ BL,
53
+ Path("/dls/p99/data/2024/cm37284-2/processing/writenData"),
54
+ client=LocalDirectoryServiceClient(), # RemoteDirectoryServiceClient("http://p99-control:8088/api"),
55
+ )
56
+ )
57
+
58
+
59
+ @device_factory()
60
+ def andor2_det() -> Andor2Detector:
61
+ """Andor model:DU897_BV."""
62
+ return Andor2Detector(
63
+ prefix=f"{PREFIX.beamline_prefix}-EA-DET-03:",
64
+ path_provider=get_path_provider(),
65
+ drv_suffix=CAM_SUFFIX,
66
+ fileio_suffix=HDF5_SUFFIX,
67
+ )
68
+
69
+
70
+ @device_factory()
71
+ def andor2_point() -> Andor2Point:
72
+ """Using the andor2 as if it is a massive point detector, read the meanValue and total after
73
+ a picture is taken."""
74
+ return Andor2Point(
75
+ prefix=f"{PREFIX.beamline_prefix}-EA-DET-03:",
76
+ drv_suffix=CAM_SUFFIX,
77
+ read_uncached={"mean": "STAT:MeanValue_RBV", "total": "STAT:Total_RBV"},
78
+ )
@@ -1,3 +1,4 @@
1
+ import ast
1
2
  from typing import Any, cast
2
3
 
3
4
  from dodal.log import LOGGER
@@ -8,7 +9,6 @@ BEAMLINE_PARAMETER_KEYWORDS = ["FB", "FULL", "deadtime"]
8
9
  BEAMLINE_PARAMETER_PATHS = {
9
10
  "i03": "/dls_sw/i03/software/daq_configuration/domain/beamlineParameters",
10
11
  "i04": "/dls_sw/i04/software/gda_versions/gda_9_34/workspace_git/gda-mx.git/configurations/i04-config/scripts/beamlineParameters",
11
- "s03": "tests/test_data/test_beamline_parameters.txt",
12
12
  }
13
13
 
14
14
 
@@ -58,41 +58,14 @@ class GDABeamlineParameters:
58
58
 
59
59
  @classmethod
60
60
  def parse_value(cls, value: str):
61
- if value[0] == "[":
62
- return cls.parse_list(value[1:].strip())
63
- else:
64
- return cls.parse_list_element(value)
65
-
66
- @classmethod
67
- def parse_list_element(cls, value: str):
68
- if value == "Yes":
69
- return True
70
- elif value == "No":
71
- return False
72
- else:
73
- return float(value)
74
-
75
- @classmethod
76
- def parse_list(cls, value: str):
77
- list_output = []
78
- remaining = value.strip()
79
- i = 0
80
- while (i := remaining.find(",")) != -1:
81
- list_output.append(cls.parse_list_element(remaining[:i]))
82
- remaining = remaining[i + 1 :].lstrip()
83
- if (i := remaining.find("]")) != -1:
84
- list_output.append(cls.parse_list_element(remaining[:i]))
85
- remaining = remaining[i + 1 :].lstrip()
86
- else:
87
- raise ValueError("Missing closing ']' in list expression")
88
- return list_output
61
+ return ast.literal_eval(value.replace("Yes", "True").replace("No", "False"))
89
62
 
90
63
 
91
64
  def get_beamline_parameters(beamline_param_path: str | None = None):
92
65
  """Loads the beamline parameters from the specified path, or according to the
93
66
  environment variable if none is given"""
94
67
  if not beamline_param_path:
95
- beamline_name = get_beamline_name("s03")
68
+ beamline_name = get_beamline_name("i03")
96
69
  beamline_param_path = BEAMLINE_PARAMETER_PATHS.get(beamline_name)
97
70
  if beamline_param_path is None:
98
71
  raise KeyError(
dodal/common/data_util.py CHANGED
@@ -1,3 +1,4 @@
1
+ import os
1
2
  from typing import TypeVar
2
3
 
3
4
  from pydantic import BaseModel
@@ -9,6 +10,9 @@ def load_json_file_to_class(
9
10
  t: type[TBaseModel],
10
11
  file: str,
11
12
  ) -> TBaseModel:
13
+ if not os.path.isfile(file):
14
+ raise FileNotFoundError(f"Cannot find file {file}")
15
+
12
16
  with open(file) as f:
13
17
  json_obj = f.read()
14
18
  cls = t.model_validate_json(json_obj)
@@ -1,9 +1,21 @@
1
- from ophyd_async.core import StandardReadable
1
+ import asyncio
2
+ import math
3
+
4
+ from ophyd_async.core import StandardReadable, derived_signal_rw
2
5
  from ophyd_async.epics.motor import Motor
3
6
 
4
7
 
5
8
  class Goniometer(StandardReadable):
6
- """Goniometer and the stages it sits on"""
9
+ """The Aithre lab goniometer and the XYZ stage it sits on.
10
+
11
+ `x`, `y` and `z` control the axes of the positioner at the base, while `sampy` and
12
+ `sampz` control the positioner of the sample. `omega` is the rotation about the
13
+ x-axis (along the length of the sample holder).
14
+
15
+ The `vertical_position` signal refers to the height of the sample from the point of
16
+ view of the OAV and setting this value moves the sample vertically in the OAV plane
17
+ regardless of the current rotation.
18
+ """
7
19
 
8
20
  def __init__(self, prefix: str, name: str = "") -> None:
9
21
  self.x = Motor(prefix + "X")
@@ -12,4 +24,26 @@ class Goniometer(StandardReadable):
12
24
  self.sampy = Motor(prefix + "SAMPY")
13
25
  self.sampz = Motor(prefix + "SAMPZ")
14
26
  self.omega = Motor(prefix + "OMEGA")
27
+ self.vertical_position = derived_signal_rw(
28
+ self._get,
29
+ self._set,
30
+ sampy=self.sampy,
31
+ sampz=self.sampz,
32
+ omega=self.omega,
33
+ )
15
34
  super().__init__(name)
35
+
36
+ def _get(self, sampz: float, sampy: float, omega: float) -> float:
37
+ z_component = sampz * math.cos(math.radians(omega))
38
+ y_component = sampy * math.sin(math.radians(omega))
39
+ return z_component + y_component
40
+
41
+ async def _set(self, value: float) -> None:
42
+ omega = await self.omega.user_readback.get_value()
43
+ z_component = value * math.cos(math.radians(omega))
44
+ y_component = value * math.sin(math.radians(omega))
45
+ await asyncio.gather(
46
+ self.sampy.set(y_component),
47
+ self.sampz.set(z_component),
48
+ self.omega.set(omega),
49
+ )
@@ -0,0 +1,27 @@
1
+ from ophyd_async.core import StrictEnum
2
+ from ophyd_async.epics.core import epics_signal_rw
3
+
4
+ from dodal.devices.robot import BartRobot
5
+
6
+
7
+ class ForceBit(StrictEnum):
8
+ ON = "On"
9
+ NO = "No"
10
+ OFF = "Off"
11
+
12
+
13
+ class LidHeatEnable(StrictEnum):
14
+ ENABLED = "Enabled"
15
+ DISABLED = "Disabled"
16
+
17
+
18
+ class LaserRobot(BartRobot):
19
+ def __init__(self, name: str, prefix: str) -> None:
20
+ self.dewar_lid_heater = epics_signal_rw(
21
+ LidHeatEnable, prefix + "DW_1_ENABLED", prefix + "DW_1_CTRL"
22
+ )
23
+ self.cryojet_retract = epics_signal_rw(ForceBit, prefix + "OP_24_FORCE_OPTION")
24
+ self.set_beamline_safe = epics_signal_rw(
25
+ ForceBit, prefix + "IP_16_FORCE_OPTION"
26
+ )
27
+ super().__init__(name=name, prefix=prefix)