mx-bluesky 1.2.0__py3-none-any.whl → 1.4.1__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 (105) hide show
  1. mx_bluesky/__init__.py +8 -3
  2. mx_bluesky/__main__.py +12 -7
  3. mx_bluesky/_version.py +2 -2
  4. mx_bluesky/beamlines/i04/callbacks/murko_callback.py +14 -4
  5. mx_bluesky/beamlines/i04/redis_to_murko_forwarder.py +178 -0
  6. mx_bluesky/beamlines/i04/thawing_plan.py +49 -11
  7. mx_bluesky/beamlines/i24/serial/__init__.py +3 -0
  8. mx_bluesky/beamlines/i24/serial/dcid.py +143 -171
  9. mx_bluesky/beamlines/i24/serial/extruder/EX-gui-edm/DiamondExtruder-I24-py3v1.edl +1 -1
  10. mx_bluesky/beamlines/i24/serial/extruder/i24ssx_Extruder_Collect_py3v2.py +121 -110
  11. mx_bluesky/beamlines/i24/serial/fixed_target/FT-gui-edm/DiamondChipI24-py3v1.edl +3 -6
  12. mx_bluesky/beamlines/i24/serial/fixed_target/ft_utils.py +0 -1
  13. mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_Chip_Collect_py3v1.py +164 -169
  14. mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_Chip_Manager_py3v1.py +149 -225
  15. mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_Chip_StartUp_py3v1.py +7 -216
  16. mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_moveonclick.py +18 -17
  17. mx_bluesky/beamlines/i24/serial/log.py +58 -49
  18. mx_bluesky/beamlines/i24/serial/parameters/__init__.py +4 -0
  19. mx_bluesky/beamlines/i24/serial/parameters/constants.py +6 -1
  20. mx_bluesky/beamlines/i24/serial/parameters/experiment_parameters.py +42 -15
  21. mx_bluesky/beamlines/i24/serial/parameters/fixed_target/cs/cs_maker.json +3 -3
  22. mx_bluesky/beamlines/i24/serial/run_extruder.sh +30 -5
  23. mx_bluesky/beamlines/i24/serial/run_fixed_target.sh +30 -5
  24. mx_bluesky/beamlines/i24/serial/run_serial.py +24 -8
  25. mx_bluesky/beamlines/i24/serial/setup_beamline/ca.py +0 -2
  26. mx_bluesky/beamlines/i24/serial/setup_beamline/pv.py +2 -0
  27. mx_bluesky/beamlines/i24/serial/setup_beamline/setup_beamline.py +104 -82
  28. mx_bluesky/beamlines/i24/serial/setup_beamline/setup_detector.py +9 -20
  29. mx_bluesky/beamlines/i24/serial/setup_beamline/setup_zebra_plans.py +26 -28
  30. mx_bluesky/beamlines/i24/serial/write_nexus.py +74 -72
  31. mx_bluesky/common/__init__.py +0 -0
  32. mx_bluesky/common/device_setup_plans/read_hardware_for_setup.py +14 -0
  33. mx_bluesky/common/external_interaction/config_server.py +46 -0
  34. mx_bluesky/common/parameters/components.py +258 -0
  35. mx_bluesky/common/parameters/constants.py +143 -0
  36. mx_bluesky/common/parameters/gridscan.py +94 -0
  37. mx_bluesky/common/parameters/robot_load.py +16 -0
  38. mx_bluesky/common/plans/__init__.py +1 -0
  39. mx_bluesky/common/plans/do_fgs.py +121 -0
  40. mx_bluesky/common/utils/log.py +118 -0
  41. mx_bluesky/{hyperion → common/utils}/tracing.py +2 -2
  42. mx_bluesky/hyperion/__main__.py +13 -10
  43. mx_bluesky/hyperion/device_setup_plans/dcm_pitch_roll_mirror_adjuster.py +47 -52
  44. mx_bluesky/hyperion/device_setup_plans/read_hardware_for_setup.py +6 -12
  45. mx_bluesky/hyperion/device_setup_plans/setup_oav.py +6 -12
  46. mx_bluesky/hyperion/device_setup_plans/setup_panda.py +5 -6
  47. mx_bluesky/hyperion/device_setup_plans/setup_zebra.py +49 -18
  48. mx_bluesky/hyperion/device_setup_plans/smargon.py +9 -9
  49. mx_bluesky/hyperion/device_setup_plans/utils.py +2 -2
  50. mx_bluesky/hyperion/device_setup_plans/xbpm_feedback.py +4 -4
  51. mx_bluesky/hyperion/exceptions.py +13 -1
  52. mx_bluesky/hyperion/experiment_plans/__init__.py +4 -0
  53. mx_bluesky/hyperion/experiment_plans/change_aperture_then_move_plan.py +83 -0
  54. mx_bluesky/hyperion/experiment_plans/common/xrc_result.py +47 -0
  55. mx_bluesky/hyperion/experiment_plans/experiment_registry.py +9 -9
  56. mx_bluesky/hyperion/experiment_plans/flyscan_xray_centre_plan.py +147 -169
  57. mx_bluesky/hyperion/experiment_plans/grid_detect_then_xray_centre_plan.py +48 -22
  58. mx_bluesky/hyperion/experiment_plans/load_centre_collect_full_plan.py +75 -9
  59. mx_bluesky/hyperion/experiment_plans/oav_grid_detection_plan.py +21 -20
  60. mx_bluesky/hyperion/experiment_plans/oav_snapshot_plan.py +9 -6
  61. mx_bluesky/hyperion/experiment_plans/optimise_attenuation_plan.py +2 -2
  62. mx_bluesky/hyperion/experiment_plans/pin_centre_then_xray_centre_plan.py +40 -21
  63. mx_bluesky/hyperion/experiment_plans/pin_tip_centring_plan.py +22 -22
  64. mx_bluesky/hyperion/experiment_plans/robot_load_and_change_energy.py +43 -39
  65. mx_bluesky/hyperion/experiment_plans/robot_load_then_centre_plan.py +69 -18
  66. mx_bluesky/hyperion/experiment_plans/rotation_scan_plan.py +17 -7
  67. mx_bluesky/hyperion/experiment_plans/set_energy_plan.py +13 -13
  68. mx_bluesky/hyperion/external_interaction/callbacks/__init__.py +0 -4
  69. mx_bluesky/hyperion/external_interaction/callbacks/__main__.py +5 -2
  70. mx_bluesky/hyperion/external_interaction/callbacks/common/abstract_event.py +66 -0
  71. mx_bluesky/hyperion/external_interaction/callbacks/common/callback_util.py +5 -0
  72. mx_bluesky/hyperion/external_interaction/callbacks/common/ispyb_mapping.py +1 -1
  73. mx_bluesky/hyperion/external_interaction/callbacks/grid_detection_callback.py +30 -25
  74. mx_bluesky/hyperion/external_interaction/callbacks/ispyb_callback_base.py +29 -12
  75. mx_bluesky/hyperion/external_interaction/callbacks/log_uid_tag_callback.py +1 -1
  76. mx_bluesky/hyperion/external_interaction/callbacks/robot_load/ispyb_callback.py +19 -11
  77. mx_bluesky/hyperion/external_interaction/callbacks/rotation/ispyb_callback.py +7 -4
  78. mx_bluesky/hyperion/external_interaction/callbacks/rotation/nexus_callback.py +5 -3
  79. mx_bluesky/hyperion/external_interaction/callbacks/sample_handling/__init__.py +0 -0
  80. mx_bluesky/hyperion/external_interaction/callbacks/sample_handling/sample_handling_callback.py +84 -0
  81. mx_bluesky/hyperion/external_interaction/callbacks/xray_centre/ispyb_callback.py +38 -27
  82. mx_bluesky/hyperion/external_interaction/callbacks/xray_centre/nexus_callback.py +5 -4
  83. mx_bluesky/hyperion/external_interaction/config_server.py +11 -28
  84. mx_bluesky/hyperion/external_interaction/exceptions.py +0 -9
  85. mx_bluesky/hyperion/external_interaction/ispyb/exp_eye_store.py +65 -15
  86. mx_bluesky/hyperion/external_interaction/ispyb/ispyb_store.py +1 -1
  87. mx_bluesky/hyperion/external_interaction/nexus/nexus_utils.py +2 -2
  88. mx_bluesky/hyperion/external_interaction/nexus/write_nexus.py +1 -1
  89. mx_bluesky/hyperion/log.py +0 -84
  90. mx_bluesky/hyperion/parameters/components.py +4 -251
  91. mx_bluesky/hyperion/parameters/constants.py +22 -119
  92. mx_bluesky/hyperion/parameters/gridscan.py +35 -74
  93. mx_bluesky/hyperion/parameters/load_centre_collect.py +16 -11
  94. mx_bluesky/hyperion/parameters/rotation.py +23 -10
  95. mx_bluesky/hyperion/utils/utils.py +17 -0
  96. mx_bluesky/hyperion/utils/validation.py +5 -6
  97. {mx_bluesky-1.2.0.dist-info → mx_bluesky-1.4.1.dist-info}/METADATA +36 -33
  98. {mx_bluesky-1.2.0.dist-info → mx_bluesky-1.4.1.dist-info}/RECORD +102 -89
  99. {mx_bluesky-1.2.0.dist-info → mx_bluesky-1.4.1.dist-info}/WHEEL +1 -1
  100. mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_Chip_Mapping_py3v1.py +0 -161
  101. mx_bluesky/example.py +0 -19
  102. mx_bluesky/hyperion/parameters/robot_load.py +0 -16
  103. {mx_bluesky-1.2.0.dist-info → mx_bluesky-1.4.1.dist-info}/LICENSE +0 -0
  104. {mx_bluesky-1.2.0.dist-info → mx_bluesky-1.4.1.dist-info}/entry_points.txt +0 -0
  105. {mx_bluesky-1.2.0.dist-info → mx_bluesky-1.4.1.dist-info}/top_level.txt +0 -0
@@ -2,9 +2,7 @@
2
2
  Fixed target data collection
3
3
  """
4
4
 
5
- import logging
6
5
  import shutil
7
- import time
8
6
  from datetime import datetime
9
7
  from pathlib import Path
10
8
  from time import sleep
@@ -12,19 +10,25 @@ from time import sleep
12
10
  import bluesky.plan_stubs as bps
13
11
  import bluesky.preprocessors as bpp
14
12
  import numpy as np
15
- from blueapi.core import MsgGenerator
13
+ from bluesky.utils import MsgGenerator
16
14
  from dodal.common import inject
15
+ from dodal.devices.attenuator import ReadOnlyAttenuator
17
16
  from dodal.devices.hutch_shutter import HutchShutter, ShutterDemand
18
17
  from dodal.devices.i24.aperture import Aperture
18
+ from dodal.devices.i24.beam_center import DetectorBeamCenter
19
19
  from dodal.devices.i24.beamstop import Beamstop
20
20
  from dodal.devices.i24.dcm import DCM
21
21
  from dodal.devices.i24.dual_backlight import DualBacklight
22
+ from dodal.devices.i24.focus_mirrors import FocusMirrorsMode
22
23
  from dodal.devices.i24.i24_detector_motion import DetectorMotion
23
24
  from dodal.devices.i24.pmac import PMAC
24
25
  from dodal.devices.zebra import Zebra
25
26
 
26
- from mx_bluesky.beamlines.i24.serial import log
27
- from mx_bluesky.beamlines.i24.serial.dcid import DCID
27
+ from mx_bluesky.beamlines.i24.serial.dcid import (
28
+ DCID,
29
+ get_pilatus_filename_template_from_device,
30
+ read_beam_info_from_hardware,
31
+ )
28
32
  from mx_bluesky.beamlines.i24.serial.fixed_target.ft_utils import (
29
33
  ChipType,
30
34
  MappingType,
@@ -33,10 +37,10 @@ from mx_bluesky.beamlines.i24.serial.fixed_target.ft_utils import (
33
37
  from mx_bluesky.beamlines.i24.serial.fixed_target.i24ssx_Chip_Manager_py3v1 import (
34
38
  write_parameter_file,
35
39
  )
40
+ from mx_bluesky.beamlines.i24.serial.log import SSX_LOGGER, log_on_entry
36
41
  from mx_bluesky.beamlines.i24.serial.parameters import (
37
42
  ChipDescription,
38
43
  FixedTargetParameters,
39
- SSXType,
40
44
  )
41
45
  from mx_bluesky.beamlines.i24.serial.parameters.constants import (
42
46
  LITEMAP_PATH,
@@ -56,15 +60,9 @@ from mx_bluesky.beamlines.i24.serial.setup_beamline.setup_zebra_plans import (
56
60
  )
57
61
  from mx_bluesky.beamlines.i24.serial.write_nexus import call_nexgen
58
62
 
59
- ABORTED = False
60
-
61
- logger = logging.getLogger("I24ssx.fixed_target")
62
-
63
-
64
- def setup_logging():
65
- # Log should now change name daily
66
- logfile = time.strftime("i24fixedtarget_%d%B%y.log").lower()
67
- log.config(logfile)
63
+ # Move this in common place as part of
64
+ # https://github.com/DiamondLightSource/mx-bluesky/pull/603
65
+ PMAC_MOVE_TIME = 0.008 # Move time between positions on chip ~ 7-8 ms
68
66
 
69
67
 
70
68
  def calculate_collection_timeout(parameters: FixedTargetParameters) -> float:
@@ -85,7 +83,7 @@ def calculate_collection_timeout(parameters: FixedTargetParameters) -> float:
85
83
  Returns:
86
84
  The estimated collection time, in s.
87
85
  """
88
- buffer = 30
86
+ buffer = PMAC_MOVE_TIME * parameters.total_num_images + 600
89
87
  pump_setting = parameters.pump_repeat
90
88
  collection_time = parameters.total_num_images * parameters.exposure_time_s
91
89
  if pump_setting in [
@@ -105,7 +103,7 @@ def calculate_collection_timeout(parameters: FixedTargetParameters) -> float:
105
103
  )
106
104
  if pump_setting == PumpProbeSetting.Medium1:
107
105
  # Long delay between pump and probe, with fast shutter opening and closing.
108
- timeout = timeout + SHUTTER_OPEN_TIME
106
+ timeout = timeout + SHUTTER_OPEN_TIME * parameters.total_num_images
109
107
  return timeout
110
108
 
111
109
 
@@ -131,7 +129,7 @@ def write_userlog(
131
129
  # Write a record of what was collected to the processing directory
132
130
  userlog_path = Path(parameters.visit) / f"processing/{parameters.directory}"
133
131
  userlog_fid = f"{filename}_parameters.txt"
134
- logger.debug(f"Write a user log in {userlog_path}")
132
+ SSX_LOGGER.debug(f"Write a user log in {userlog_path}")
135
133
 
136
134
  userlog_path.mkdir(parents=True, exist_ok=True)
137
135
 
@@ -154,7 +152,7 @@ def write_userlog(
154
152
  f.write(text)
155
153
 
156
154
 
157
- @log.log_on_entry
155
+ @log_on_entry
158
156
  def get_chip_prog_values(
159
157
  parameters: FixedTargetParameters,
160
158
  ):
@@ -179,7 +177,7 @@ def get_chip_prog_values(
179
177
  else:
180
178
  raise ValueError(f"Unknown pump_repeat, pump_repeat = {parameters.pump_repeat}")
181
179
 
182
- logger.info(
180
+ SSX_LOGGER.info(
183
181
  f"Pump repeat is {str(parameters.pump_repeat)}, PVAR set to {pump_repeat_pvar}"
184
182
  )
185
183
 
@@ -188,7 +186,7 @@ def get_chip_prog_values(
188
186
  else:
189
187
  pump_in_probe = 0
190
188
 
191
- logger.info(f"pump_in_probe set to {pump_in_probe}")
189
+ SSX_LOGGER.info(f"pump_in_probe set to {pump_in_probe}")
192
190
 
193
191
  chip_dict: dict[str, list] = {
194
192
  "X_NUM_STEPS": [11, parameters.chip.x_num_steps],
@@ -226,7 +224,7 @@ def get_chip_prog_values(
226
224
  return chip_dict
227
225
 
228
226
 
229
- @log.log_on_entry
227
+ @log_on_entry
230
228
  def load_motion_program_data(
231
229
  pmac: PMAC,
232
230
  motion_program_dict: dict[str, list],
@@ -234,26 +232,24 @@ def load_motion_program_data(
234
232
  pump_repeat: int,
235
233
  checker_pattern: bool,
236
234
  ):
237
- logger.info("Loading motion program data for chip.")
238
- logger.info(f"Pump_repeat is {PumpProbeSetting(pump_repeat)}")
235
+ SSX_LOGGER.info("Loading motion program data for chip.")
236
+ SSX_LOGGER.info(f"Pump_repeat is {PumpProbeSetting(pump_repeat)}")
239
237
  if pump_repeat == PumpProbeSetting.NoPP:
240
238
  if map_type == MappingType.NoMap:
241
239
  prefix = 11
242
- logger.info(f"Map type is None, setting program prefix to {prefix}")
240
+ SSX_LOGGER.info(f"Map type is None, setting program prefix to {prefix}")
243
241
  elif map_type == MappingType.Lite:
244
242
  prefix = 12
245
- elif map_type == MappingType.Full:
246
- prefix = 13
247
243
  else:
248
- logger.warning(f"Unknown Map Type, map_type = {map_type}")
244
+ SSX_LOGGER.warning(f"Unknown Map Type, map_type = {map_type}")
249
245
  return
250
246
  elif pump_repeat in [pp.value for pp in PumpProbeSetting if pp != 0]:
251
247
  # Pump setting chosen
252
248
  prefix = 14
253
- logger.info(f"Setting program prefix to {prefix}")
249
+ SSX_LOGGER.info(f"Setting program prefix to {prefix}")
254
250
  yield from bps.abs_set(pmac.pmac_string, "P1439=0", wait=True)
255
251
  if checker_pattern:
256
- logger.info("Checker pattern setting enabled.")
252
+ SSX_LOGGER.info("Checker pattern setting enabled.")
257
253
  yield from bps.abs_set(pmac.pmac_string, "P1439=1", wait=True)
258
254
  if pump_repeat == PumpProbeSetting.Medium1:
259
255
  # Medium1 has time delays (Fast shutter opening time in ms)
@@ -261,23 +257,23 @@ def load_motion_program_data(
261
257
  else:
262
258
  yield from bps.abs_set(pmac.pmac_string, "P1441=0", wait=True)
263
259
  else:
264
- logger.warning(f"Unknown Pump repeat, pump_repeat = {pump_repeat}")
260
+ SSX_LOGGER.warning(f"Unknown Pump repeat, pump_repeat = {pump_repeat}")
265
261
  return
266
262
 
267
- logger.info("Set PMAC_STRING pv.")
263
+ SSX_LOGGER.info("Set PMAC_STRING pv.")
268
264
  for key in sorted(motion_program_dict.keys()):
269
265
  v = motion_program_dict[key]
270
266
  pvar_base = prefix * 100
271
267
  pvar = pvar_base + v[0]
272
268
  value = str(v[1])
273
269
  s = f"P{pvar}={value}"
274
- logger.info(f"{key} \t {s}")
270
+ SSX_LOGGER.info(f"{key} \t {s}")
275
271
  yield from bps.abs_set(pmac.pmac_string, s, wait=True)
276
272
  yield from bps.sleep(0.02)
277
273
  yield from bps.sleep(0.2)
278
274
 
279
275
 
280
- @log.log_on_entry
276
+ @log_on_entry
281
277
  def get_prog_num(
282
278
  chip_type: ChipType, map_type: MappingType, pump_repeat: PumpProbeSetting
283
279
  ) -> int:
@@ -290,60 +286,52 @@ def get_prog_num(
290
286
  - Oxford chips with full mapping should return 13. Currently disabled, will \
291
287
  raise an error.
292
288
  """
293
- logger.info("Get Program Number for the motion program.")
294
- logger.info(f"Pump_repeat: {str(pump_repeat)} \t Chip Type: {str(chip_type)}")
289
+ SSX_LOGGER.info("Get Program Number for the motion program.")
290
+ SSX_LOGGER.info(f"Pump_repeat: {str(pump_repeat)} \t Chip Type: {str(chip_type)}")
295
291
  if pump_repeat != PumpProbeSetting.NoPP:
296
- logger.info("Assuming Map type = Mapping Lite.")
297
- logger.info("Program number: 14")
292
+ SSX_LOGGER.info("Assuming Map type = Mapping Lite.")
293
+ SSX_LOGGER.info("Program number: 14")
298
294
  return 14
299
295
 
300
296
  if chip_type not in [ChipType.Oxford, ChipType.OxfordInner]:
301
- logger.info("Program number: 11")
297
+ SSX_LOGGER.info("Program number: 11")
302
298
  return 11
303
299
 
304
300
  if map_type == MappingType.NoMap:
305
- logger.info(f"Map type: {str(map_type)}")
306
- logger.info("Program number: 11")
301
+ SSX_LOGGER.info(f"Map type: {str(map_type)}")
302
+ SSX_LOGGER.info("Program number: 11")
307
303
  return 11
308
304
  if map_type == MappingType.Lite:
309
- logger.info(f"Map type: {str(map_type)}")
310
- logger.info("Program number: 12")
305
+ SSX_LOGGER.info(f"Map type: {str(map_type)}")
306
+ SSX_LOGGER.info("Program number: 12")
311
307
  return 12
312
- if map_type == MappingType.Full:
313
- # TODO See https://github.com/DiamondLightSource/mx-bluesky/issues/515
314
- logger.info(f"Map type: {str(map_type)}")
315
- logger.info("Program number: 13")
316
- # TODO once reinstated return 13
317
- msg = "Full mapping is broken and currently disabled."
318
- logger.error(msg)
319
- raise ValueError(msg)
320
308
 
321
309
 
322
- @log.log_on_entry
310
+ @log_on_entry
323
311
  def datasetsizei24(
324
312
  n_exposures: int,
325
313
  chip_params: ChipDescription,
326
314
  map_type: MappingType,
327
315
  ) -> int:
328
316
  # Calculates how many images will be collected based on map type and N repeats
329
- logger.info("Calculate total number of images expected in data collection.")
317
+ SSX_LOGGER.info("Calculate total number of images expected in data collection.")
330
318
 
331
319
  if map_type == MappingType.NoMap:
332
320
  if chip_params.chip_type == ChipType.Custom:
333
321
  total_numb_imgs = chip_params.x_num_steps * chip_params.y_num_steps
334
- logger.info(
322
+ SSX_LOGGER.info(
335
323
  f"Map type: None \tCustom chip \tNumber of images {total_numb_imgs}"
336
324
  )
337
325
  else:
338
326
  chip_format = chip_params.chip_format[:4]
339
327
  total_numb_imgs = int(np.prod(chip_format))
340
- logger.info(
328
+ SSX_LOGGER.info(
341
329
  f"""Map type: None \tOxford chip {chip_params.chip_type} \t \
342
330
  Number of images {total_numb_imgs}"""
343
331
  )
344
332
 
345
333
  elif map_type == MappingType.Lite:
346
- logger.info(f"Using Mapping Lite on chip type {chip_params.chip_type}")
334
+ SSX_LOGGER.info(f"Using Mapping Lite on chip type {chip_params.chip_type}")
347
335
  chip_format = chip_params.chip_format[2:4]
348
336
  block_count = 0
349
337
  with open(LITEMAP_PATH / "currentchip.map") as f:
@@ -352,29 +340,21 @@ def datasetsizei24(
352
340
  if entry[2] == "1":
353
341
  block_count += 1
354
342
 
355
- logger.info(f"Block count={block_count}")
356
- logger.info(f"Chip format={chip_format}")
343
+ SSX_LOGGER.info(f"Block count={block_count}")
344
+ SSX_LOGGER.info(f"Chip format={chip_format}")
357
345
 
358
- logger.info(f"Number of exposures={n_exposures}")
346
+ SSX_LOGGER.info(f"Number of exposures={n_exposures}")
359
347
 
360
348
  total_numb_imgs = int(np.prod(chip_format) * block_count * n_exposures)
361
- logger.info(f"Calculated number of images: {total_numb_imgs}")
362
-
363
- elif map_type == MappingType.Full:
364
- logger.error("Not Set Up For Full Mapping")
365
- raise ValueError("The beamline is currently not set for Full Mapping.")
366
-
367
- else:
368
- logger.warning(f"Unknown Map Type, map_type = {str(map_type)}")
369
- raise ValueError("Unknown map type")
349
+ SSX_LOGGER.info(f"Calculated number of images: {total_numb_imgs}")
370
350
 
371
- logger.info("Set PV to calculated number of images.")
351
+ SSX_LOGGER.info("Set PV to calculated number of images.")
372
352
  caput(pv.me14e_gp10, int(total_numb_imgs))
373
353
 
374
354
  return int(total_numb_imgs)
375
355
 
376
356
 
377
- @log.log_on_entry
357
+ @log_on_entry
378
358
  def start_i24(
379
359
  zebra: Zebra,
380
360
  aperture: Aperture,
@@ -383,6 +363,9 @@ def start_i24(
383
363
  detector_stage: DetectorMotion,
384
364
  shutter: HutchShutter,
385
365
  parameters: FixedTargetParameters,
366
+ dcm: DCM,
367
+ mirrors: FocusMirrorsMode,
368
+ beam_center_device: DetectorBeamCenter,
386
369
  dcid: DCID,
387
370
  ):
388
371
  """Set up for I24 fixed target data collection, trigger the detector and open \
@@ -390,11 +373,14 @@ def start_i24(
390
373
  Returns the start_time.
391
374
  """
392
375
 
393
- logger.info("Start I24 data collection.")
376
+ beam_settings = yield from read_beam_info_from_hardware(
377
+ dcm, mirrors, beam_center_device, parameters.detector_name
378
+ )
379
+ SSX_LOGGER.info("Start I24 data collection.")
394
380
  start_time = datetime.now()
395
- logger.info(f"Collection start time {start_time.ctime()}")
381
+ SSX_LOGGER.info(f"Collection start time {start_time.ctime()}")
396
382
 
397
- logger.debug("Set up beamline")
383
+ SSX_LOGGER.debug("Set up beamline")
398
384
  yield from sup.setup_beamline_for_collection_plan(
399
385
  aperture, backlight, beamstop, wait=True
400
386
  )
@@ -403,27 +389,27 @@ def start_i24(
403
389
  detector_stage, parameters.detector_distance_mm
404
390
  )
405
391
 
406
- logger.debug("Set up beamline DONE")
392
+ SSX_LOGGER.debug("Set up beamline DONE")
407
393
 
408
394
  filepath = parameters.collection_directory.as_posix()
409
395
  filename = parameters.filename
410
396
 
411
- logger.debug("Acquire Region")
397
+ SSX_LOGGER.debug("Acquire Region")
412
398
 
413
399
  num_gates = parameters.total_num_images // parameters.num_exposures
414
400
 
415
- logger.info(f"Total number of images: {parameters.total_num_images}")
416
- logger.info(f"Number of exposures: {parameters.num_exposures}")
417
- logger.info(f"Number of gates (=Total images/N exposures): {num_gates:.4f}")
401
+ SSX_LOGGER.info(f"Total number of images: {parameters.total_num_images}")
402
+ SSX_LOGGER.info(f"Number of exposures: {parameters.num_exposures}")
403
+ SSX_LOGGER.info(f"Number of gates (=Total images/N exposures): {num_gates:.4f}")
418
404
 
419
405
  if parameters.detector_name == "pilatus":
420
- logger.info("Using Pilatus detector")
421
- logger.info(f"Fastchip Pilatus setup: filepath {filepath}")
422
- logger.info(f"Fastchip Pilatus setup: filename {filename}")
423
- logger.info(
406
+ SSX_LOGGER.info("Using Pilatus detector")
407
+ SSX_LOGGER.info(f"Fastchip Pilatus setup: filepath {filepath}")
408
+ SSX_LOGGER.info(f"Fastchip Pilatus setup: filename {filename}")
409
+ SSX_LOGGER.info(
424
410
  f"Fastchip Pilatus setup: number of images {parameters.total_num_images}"
425
411
  )
426
- logger.info(
412
+ SSX_LOGGER.info(
427
413
  f"Fastchip Pilatus setup: exposure time {parameters.exposure_time_s}"
428
414
  )
429
415
 
@@ -438,21 +424,24 @@ def start_i24(
438
424
  )
439
425
 
440
426
  # DCID process depends on detector PVs being set up already
441
- logger.debug("Start DCID process")
427
+ SSX_LOGGER.debug("Start DCID process")
428
+ filetemplate = yield from get_pilatus_filename_template_from_device()
442
429
  dcid.generate_dcid(
443
- visit=parameters.visit.name,
430
+ beam_settings=beam_settings,
444
431
  image_dir=filepath,
445
- start_time=start_time,
432
+ file_template=filetemplate,
446
433
  num_images=parameters.total_num_images,
447
- exposure_time=parameters.exposure_time_s,
448
434
  shots_per_position=parameters.num_exposures,
449
- pump_exposure_time=parameters.laser_dwell_s,
450
- pump_delay=parameters.laser_delay_s or 0,
451
- pump_status=parameters.pump_repeat.value,
435
+ start_time=start_time,
436
+ pump_probe=bool(parameters.pump_repeat),
452
437
  )
453
438
 
454
- logger.debug("Arm Pilatus. Arm Zebra.")
455
- shutter_time_offset = SHUTTER_OPEN_TIME if PumpProbeSetting.Medium1 else 0.0
439
+ SSX_LOGGER.debug("Arm Pilatus. Arm Zebra.")
440
+ shutter_time_offset = (
441
+ SHUTTER_OPEN_TIME
442
+ if parameters.pump_repeat is PumpProbeSetting.Medium1
443
+ else 0.0
444
+ )
456
445
  yield from setup_zebra_for_fastchip_plan(
457
446
  zebra,
458
447
  parameters.detector_name,
@@ -472,33 +461,17 @@ def start_i24(
472
461
  sleep(1.5)
473
462
 
474
463
  elif parameters.detector_name == "eiger":
475
- logger.info("Using Eiger detector")
464
+ SSX_LOGGER.info("Using Eiger detector")
476
465
 
477
- logger.warning(
478
- """TEMPORARY HACK!
479
- Running a Single image pilatus data collection to create directory."""
480
- )
481
- num_imgs = 1
482
- sup.pilatus(
483
- "quickshot-internaltrig",
484
- [filepath, filename, num_imgs, parameters.exposure_time_s],
485
- )
486
- logger.debug("Sleep 2s waiting for pilatus to arm")
487
- sleep(2)
488
- sleep(0.5)
489
- caput(pv.pilat_acquire, "0") # Disarm pilatus
490
- sleep(0.5)
491
- caput(pv.pilat_acquire, "1") # Arm pilatus
492
- logger.debug("Pilatus data collection DONE")
493
- sup.pilatus("return to normal", None)
494
- logger.info("Pilatus back to normal. Single image pilatus data collection DONE")
466
+ SSX_LOGGER.debug(f"Creating the directory for the collection in {filepath}.")
467
+ Path(filepath).mkdir(parents=True, exist_ok=True)
495
468
 
496
- logger.info(f"Triggered Eiger setup: filepath {filepath}")
497
- logger.info(f"Triggered Eiger setup: filename {filename}")
498
- logger.info(
469
+ SSX_LOGGER.info(f"Triggered Eiger setup: filepath {filepath}")
470
+ SSX_LOGGER.info(f"Triggered Eiger setup: filename {filename}")
471
+ SSX_LOGGER.info(
499
472
  f"Triggered Eiger setup: number of images {parameters.total_num_images}"
500
473
  )
501
- logger.info(
474
+ SSX_LOGGER.info(
502
475
  f"Triggered Eiger setup: exposure time {parameters.exposure_time_s}"
503
476
  )
504
477
 
@@ -513,21 +486,24 @@ def start_i24(
513
486
  )
514
487
 
515
488
  # DCID process depends on detector PVs being set up already
516
- logger.debug("Start DCID process")
489
+ SSX_LOGGER.debug("Start DCID process")
490
+ filetemplate = f"{parameters.filename}.nxs"
517
491
  dcid.generate_dcid(
518
- visit=parameters.visit.name,
492
+ beam_settings=beam_settings,
519
493
  image_dir=filepath,
520
- start_time=start_time,
494
+ file_template=filetemplate,
521
495
  num_images=parameters.total_num_images,
522
- exposure_time=parameters.exposure_time_s,
523
496
  shots_per_position=parameters.num_exposures,
524
- pump_exposure_time=parameters.laser_dwell_s,
525
- pump_delay=parameters.laser_delay_s or 0,
526
- pump_status=parameters.pump_repeat.value,
497
+ start_time=start_time,
498
+ pump_probe=bool(parameters.pump_repeat),
527
499
  )
528
500
 
529
- logger.debug("Arm Zebra.")
530
- shutter_time_offset = SHUTTER_OPEN_TIME if PumpProbeSetting.Medium1 else 0.0
501
+ SSX_LOGGER.debug("Arm Zebra.")
502
+ shutter_time_offset = (
503
+ SHUTTER_OPEN_TIME
504
+ if parameters.pump_repeat is PumpProbeSetting.Medium1
505
+ else 0.0
506
+ )
531
507
  yield from setup_zebra_for_fastchip_plan(
532
508
  zebra,
533
509
  parameters.detector_name,
@@ -547,7 +523,7 @@ def start_i24(
547
523
 
548
524
  else:
549
525
  msg = f"Unknown Detector Type, det_type = {parameters.detector_name}"
550
- logger.error(msg)
526
+ SSX_LOGGER.error(msg)
551
527
  raise ValueError(msg)
552
528
 
553
529
  # Open the hutch shutter
@@ -556,7 +532,7 @@ def start_i24(
556
532
  return start_time
557
533
 
558
534
 
559
- @log.log_on_entry
535
+ @log_on_entry
560
536
  def finish_i24(
561
537
  zebra: Zebra,
562
538
  pmac: PMAC,
@@ -564,20 +540,22 @@ def finish_i24(
564
540
  dcm: DCM,
565
541
  parameters: FixedTargetParameters,
566
542
  ):
567
- logger.info(f"Finish I24 data collection with {parameters.detector_name} detector.")
543
+ SSX_LOGGER.info(
544
+ f"Finish I24 data collection with {parameters.detector_name} detector."
545
+ )
568
546
 
569
547
  complete_filename: str
570
548
  transmission = float(caget(pv.pilat_filtertrasm))
571
549
  wavelength = yield from bps.rd(dcm.wavelength_in_a)
572
550
 
573
551
  if parameters.detector_name == "pilatus":
574
- logger.debug("Finish I24 Pilatus")
552
+ SSX_LOGGER.debug("Finish I24 Pilatus")
575
553
  complete_filename = f"{parameters.filename}_{caget(pv.pilat_filenum)}"
576
554
  yield from reset_zebra_when_collection_done_plan(zebra)
577
555
  sup.pilatus("return-to-normal", None)
578
556
  sleep(0.2)
579
557
  elif parameters.detector_name == "eiger":
580
- logger.debug("Finish I24 Eiger")
558
+ SSX_LOGGER.debug("Finish I24 Eiger")
581
559
  yield from reset_zebra_when_collection_done_plan(zebra)
582
560
  sup.eiger("return-to-normal", None)
583
561
  complete_filename = cagetstring(pv.eiger_ODfilenameRBV) # type: ignore
@@ -585,9 +563,9 @@ def finish_i24(
585
563
  raise ValueError(f"{parameters.detector_name=} unrecognised")
586
564
 
587
565
  # Detector independent moves
588
- logger.info("Move chip back to home position by setting PMAC_STRING pv.")
566
+ SSX_LOGGER.info("Move chip back to home position by setting PMAC_STRING pv.")
589
567
  yield from bps.trigger(pmac.to_xyz_zero)
590
- logger.info("Closing shutter")
568
+ SSX_LOGGER.info("Closing shutter")
591
569
  yield from bps.abs_set(shutter, ShutterDemand.CLOSE, wait=True)
592
570
 
593
571
  # Write a record of what was collected to the processing directory
@@ -599,14 +577,14 @@ def run_aborted_plan(pmac: PMAC, dcid: DCID):
599
577
  either by pressing the Abort button or because of a timeout, and to reset the \
600
578
  P variable.
601
579
  """
602
- logger.warning("Data Collection Aborted")
580
+ SSX_LOGGER.warning("Data Collection Aborted")
603
581
  yield from bps.trigger(pmac.abort_program, wait=True)
604
582
 
605
583
  end_time = datetime.now()
606
584
  dcid.collection_complete(end_time, aborted=True)
607
585
 
608
586
 
609
- @log.log_on_entry
587
+ @log_on_entry
610
588
  def main_fixed_target_plan(
611
589
  zebra: Zebra,
612
590
  pmac: PMAC,
@@ -616,20 +594,26 @@ def main_fixed_target_plan(
616
594
  detector_stage: DetectorMotion,
617
595
  shutter: HutchShutter,
618
596
  dcm: DCM,
597
+ mirrors: FocusMirrorsMode,
598
+ beam_center_device: DetectorBeamCenter,
619
599
  parameters: FixedTargetParameters,
620
600
  dcid: DCID,
621
601
  ) -> MsgGenerator:
622
- logger.info("Running a chip collection on I24")
602
+ SSX_LOGGER.info("Running a chip collection on I24")
603
+
604
+ yield from sup.set_detector_beam_center_plan(
605
+ beam_center_device, parameters.detector_name
606
+ )
623
607
 
624
- logger.info("Getting Program Dictionary")
608
+ SSX_LOGGER.info("Getting Program Dictionary")
625
609
 
626
610
  # If alignment type is Oxford inner it is still an Oxford type chip
627
611
  if parameters.chip.chip_type == ChipType.OxfordInner:
628
- logger.debug("Change chip type Oxford Inner to Oxford.")
612
+ SSX_LOGGER.debug("Change chip type Oxford Inner to Oxford.")
629
613
  parameters.chip.chip_type = ChipType.Oxford
630
614
 
631
615
  chip_prog_dict = get_chip_prog_values(parameters)
632
- logger.info("Loading Motion Program Data")
616
+ SSX_LOGGER.info("Loading Motion Program Data")
633
617
  yield from load_motion_program_data(
634
618
  pmac,
635
619
  chip_prog_dict,
@@ -643,29 +627,38 @@ def main_fixed_target_plan(
643
627
  )
644
628
 
645
629
  start_time = yield from start_i24(
646
- zebra, aperture, backlight, beamstop, detector_stage, shutter, parameters, dcid
630
+ zebra,
631
+ aperture,
632
+ backlight,
633
+ beamstop,
634
+ detector_stage,
635
+ shutter,
636
+ parameters,
637
+ dcm,
638
+ mirrors,
639
+ beam_center_device,
640
+ dcid,
647
641
  )
648
642
 
649
- logger.info("Moving to Start")
643
+ SSX_LOGGER.info("Moving to Start")
650
644
  yield from bps.trigger(pmac.to_xyz_zero)
651
645
  sleep(2.0)
652
646
 
653
647
  # Now ready for data collection. Open fast shutter (zebra gate)
654
- logger.info("Opening fast shutter.")
648
+ SSX_LOGGER.info("Opening fast shutter.")
655
649
  yield from open_fast_shutter(zebra)
656
650
 
657
651
  # Kick off the StartOfCollect script
658
- logger.debug("Notify DCID of the start of the collection.")
652
+ SSX_LOGGER.debug("Notify DCID of the start of the collection.")
659
653
  dcid.notify_start()
660
654
 
661
- wavelength = yield from bps.rd(dcm.wavelength_in_a)
662
655
  if parameters.detector_name == "eiger":
663
- logger.debug("Start nexus writing service.")
656
+ wavelength = yield from bps.rd(dcm.wavelength_in_a)
657
+ beam_x = yield from bps.rd(beam_center_device.beam_x)
658
+ beam_y = yield from bps.rd(beam_center_device.beam_y)
659
+ SSX_LOGGER.debug("Start nexus writing service.")
664
660
  call_nexgen(
665
- chip_prog_dict,
666
- start_time,
667
- parameters,
668
- wavelength,
661
+ chip_prog_dict, parameters, wavelength, (beam_x, beam_y), start_time
669
662
  )
670
663
 
671
664
  yield from kickoff_and_complete_collection(pmac, parameters)
@@ -678,7 +671,7 @@ def kickoff_and_complete_collection(pmac: PMAC, parameters: FixedTargetParameter
678
671
  yield from bps.abs_set(pmac.program_number, prog_num, group="setup_pmac")
679
672
  # Calculate approx collection time
680
673
  total_collection_time = calculate_collection_timeout(parameters)
681
- logger.info(f"Estimated collection time: {total_collection_time}s.")
674
+ SSX_LOGGER.info(f"Estimated collection time: {total_collection_time}s.")
682
675
  yield from bps.abs_set(
683
676
  pmac.collection_time, total_collection_time, group="setup_pmac"
684
677
  )
@@ -686,20 +679,20 @@ def kickoff_and_complete_collection(pmac: PMAC, parameters: FixedTargetParameter
686
679
 
687
680
  @bpp.run_decorator(md={"subplan_name": "run_ft_collection"})
688
681
  def run_collection():
689
- logger.info(f"Kick off PMAC with program number {prog_num}.")
682
+ SSX_LOGGER.info(f"Kick off PMAC with program number {prog_num}.")
690
683
  yield from bps.kickoff(pmac.run_program, wait=True)
691
684
  yield from bps.complete(pmac.run_program, wait=True)
692
- logger.info("Collection completed without errors.")
685
+ SSX_LOGGER.info("Collection completed without errors.")
693
686
 
694
687
  yield from run_collection()
695
688
 
696
689
 
697
- @log.log_on_entry
690
+ @log_on_entry
698
691
  def collection_complete_plan(
699
692
  dcid: DCID, collection_directory: Path, map_type: MappingType
700
693
  ) -> MsgGenerator:
701
694
  end_time = datetime.now()
702
- logger.debug(f"Collection end time {end_time}")
695
+ SSX_LOGGER.debug(f"Collection end time {end_time}")
703
696
  dcid.collection_complete(end_time, aborted=False)
704
697
 
705
698
  # Copy parameter file and eventual chip map to collection directory
@@ -707,7 +700,7 @@ def collection_complete_plan(
707
700
  yield from bps.null()
708
701
 
709
702
 
710
- @log.log_on_entry
703
+ @log_on_entry
711
704
  def tidy_up_after_collection_plan(
712
705
  zebra: Zebra,
713
706
  pmac: PMAC,
@@ -719,27 +712,29 @@ def tidy_up_after_collection_plan(
719
712
  """A plan to be run to tidy things up at the end af a fixed target collection, \
720
713
  both successful or aborted.
721
714
  """
722
- logger.info("Closing fast shutter")
715
+ SSX_LOGGER.info("Closing fast shutter")
723
716
  yield from close_fast_shutter(zebra)
724
717
  sleep(2.0)
725
718
 
726
719
  # This probably should go in main then
727
720
  if parameters.detector_name == "pilatus":
728
- logger.debug("Pilatus Acquire STOP")
721
+ SSX_LOGGER.debug("Pilatus Acquire STOP")
729
722
  caput(pv.pilat_acquire, 0)
730
723
  elif parameters.detector_name == "eiger":
731
- logger.debug("Eiger Acquire STOP")
724
+ SSX_LOGGER.debug("Eiger Acquire STOP")
732
725
  caput(pv.eiger_acquire, 0)
733
726
  caput(pv.eiger_ODcapture, "Done")
734
727
  sleep(0.5)
735
728
 
736
729
  yield from finish_i24(zebra, pmac, shutter, dcm, parameters)
737
730
 
738
- logger.debug("Notify DCID of end of collection.")
731
+ SSX_LOGGER.debug("Notify DCID of end of collection.")
739
732
  dcid.notify_end()
740
733
 
741
- logger.debug("Quick summary of settings")
742
- logger.debug(f"Chip name = {parameters.filename} sub_dir = {parameters.directory}")
734
+ SSX_LOGGER.debug("Quick summary of settings")
735
+ SSX_LOGGER.debug(
736
+ f"Chip name = {parameters.filename} sub_dir = {parameters.directory}"
737
+ )
743
738
 
744
739
 
745
740
  def run_fixed_target_plan(
@@ -751,13 +746,13 @@ def run_fixed_target_plan(
751
746
  detector_stage: DetectorMotion = inject("detector_motion"),
752
747
  shutter: HutchShutter = inject("shutter"),
753
748
  dcm: DCM = inject("dcm"),
749
+ mirrors: FocusMirrorsMode = inject("focus_mirrors"),
750
+ attenuator: ReadOnlyAttenuator = inject("attenuator"),
754
751
  ) -> MsgGenerator:
755
- setup_logging()
756
-
757
752
  # in the first instance, write params here
758
- yield from write_parameter_file(detector_stage)
753
+ yield from write_parameter_file(detector_stage, attenuator)
759
754
 
760
- logger.info("Getting parameters from file.")
755
+ SSX_LOGGER.info("Getting parameters from file.")
761
756
  parameters = FixedTargetParameters.from_file(PARAM_FILE_PATH_FT / PARAM_FILE_NAME)
762
757
 
763
758
  log_msg = f"""
@@ -776,14 +771,12 @@ def run_fixed_target_plan(
776
771
  pumpdelay = {parameters.laser_delay_s}
777
772
  prepumpexptime = {parameters.pre_pump_exposure_s}
778
773
  """
779
- logger.info(log_msg)
774
+ SSX_LOGGER.info(log_msg)
775
+
776
+ beam_center_device = sup.get_beam_center_device(parameters.detector_name)
780
777
 
781
778
  # DCID instance - do not create yet
782
- dcid = DCID(
783
- emit_errors=False,
784
- ssx_type=SSXType.FIXED,
785
- detector=parameters.detector_name,
786
- )
779
+ dcid = DCID(emit_errors=False, expt_params=parameters)
787
780
 
788
781
  yield from bpp.contingency_wrapper(
789
782
  main_fixed_target_plan(
@@ -795,6 +788,8 @@ def run_fixed_target_plan(
795
788
  detector_stage,
796
789
  shutter,
797
790
  dcm,
791
+ mirrors,
792
+ beam_center_device,
798
793
  parameters,
799
794
  dcid,
800
795
  ),