mx-bluesky 0.0.2__py3-none-any.whl → 1.1.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 (150) hide show
  1. mx_bluesky/__main__.py +1 -2
  2. mx_bluesky/_version.py +14 -2
  3. mx_bluesky/beamlines/i04/__init__.py +3 -0
  4. mx_bluesky/beamlines/i04/callbacks/murko_callback.py +45 -0
  5. mx_bluesky/beamlines/i04/thawing_plan.py +85 -0
  6. mx_bluesky/beamlines/i24/serial/__init__.py +49 -0
  7. mx_bluesky/beamlines/i24/serial/blueapi_config.yaml +12 -0
  8. mx_bluesky/{I24 → beamlines/i24}/serial/dcid.py +53 -41
  9. mx_bluesky/{I24 → beamlines/i24}/serial/extruder/EX-gui-edm/DetStage.edl +3 -4
  10. mx_bluesky/{I24 → beamlines/i24}/serial/extruder/EX-gui-edm/DiamondExtruder-I24-py3v1.edl +28 -32
  11. mx_bluesky/{I24 → beamlines/i24}/serial/extruder/EX-gui-edm/microdrop_alignment.edl +0 -1
  12. mx_bluesky/beamlines/i24/serial/extruder/i24ssx_Extruder_Collect_py3v2.py +516 -0
  13. mx_bluesky/{I24 → beamlines/i24}/serial/fixed_target/FT-gui-edm/CustomChip_py3v1.edl +3 -4
  14. mx_bluesky/{I24 → beamlines/i24}/serial/fixed_target/FT-gui-edm/DetStage.edl +3 -4
  15. mx_bluesky/{I24 → beamlines/i24}/serial/fixed_target/FT-gui-edm/DiamondChipI24-py3v1.edl +273 -223
  16. mx_bluesky/{I24 → beamlines/i24}/serial/fixed_target/FT-gui-edm/ME14E-GeneralPurpose.edl +0 -1
  17. mx_bluesky/{I24 → beamlines/i24}/serial/fixed_target/FT-gui-edm/MappingLite-oxford_py3v1.edl +12 -13
  18. mx_bluesky/{I24 → beamlines/i24}/serial/fixed_target/FT-gui-edm/PMAC_Command.edl +0 -1
  19. mx_bluesky/{I24 → beamlines/i24}/serial/fixed_target/FT-gui-edm/Shutter_Control.edl +0 -1
  20. mx_bluesky/{I24 → beamlines/i24}/serial/fixed_target/FT-gui-edm/microdrop_alignment.edl +0 -1
  21. mx_bluesky/{I24 → beamlines/i24}/serial/fixed_target/FT-gui-edm/nudgechip.edl +0 -1
  22. mx_bluesky/{I24 → beamlines/i24}/serial/fixed_target/FT-gui-edm/pumpprobe-py3v1.edl +273 -143
  23. mx_bluesky/beamlines/i24/serial/fixed_target/FT-gui-edm/short1-laser.png +0 -0
  24. mx_bluesky/beamlines/i24/serial/fixed_target/FT-gui-edm/short2-laser.png +0 -0
  25. mx_bluesky/{I24 → beamlines/i24}/serial/fixed_target/ft_utils.py +24 -1
  26. mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_Chip_Collect_py3v1.py +808 -0
  27. mx_bluesky/{I24 → beamlines/i24}/serial/fixed_target/i24ssx_Chip_Manager_py3v1.py +377 -416
  28. mx_bluesky/{I24 → beamlines/i24}/serial/fixed_target/i24ssx_Chip_Mapping_py3v1.py +34 -40
  29. mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_Chip_StartUp_py3v1.py +328 -0
  30. mx_bluesky/{I24 → beamlines/i24}/serial/fixed_target/i24ssx_moveonclick.py +66 -48
  31. mx_bluesky/{I24 → beamlines/i24}/serial/log.py +66 -19
  32. mx_bluesky/beamlines/i24/serial/parameters/__init__.py +15 -0
  33. mx_bluesky/beamlines/i24/serial/parameters/constants.py +47 -0
  34. mx_bluesky/beamlines/i24/serial/parameters/experiment_parameters.py +103 -0
  35. mx_bluesky/beamlines/i24/serial/parameters/fixed_target/cs/cs_maker.json +9 -0
  36. mx_bluesky/{I24 → beamlines/i24}/serial/parameters/fixed_target/cs/motor_direction.txt +1 -1
  37. mx_bluesky/{I24 → beamlines/i24}/serial/parameters/fixed_target/pvar_files/minichip-oxford.pvar +1 -1
  38. mx_bluesky/beamlines/i24/serial/parameters/utils.py +42 -0
  39. mx_bluesky/beamlines/i24/serial/run_extruder.sh +19 -0
  40. mx_bluesky/beamlines/i24/serial/run_fixed_target.sh +22 -0
  41. mx_bluesky/beamlines/i24/serial/run_serial.py +36 -0
  42. mx_bluesky/{I24 → beamlines/i24}/serial/set_visit_directory.sh +6 -1
  43. mx_bluesky/{I24 → beamlines/i24}/serial/setup_beamline/pv.py +1 -62
  44. mx_bluesky/{I24 → beamlines/i24}/serial/setup_beamline/pv_abstract.py +6 -7
  45. mx_bluesky/{I24 → beamlines/i24}/serial/setup_beamline/setup_beamline.py +90 -269
  46. mx_bluesky/{I24 → beamlines/i24}/serial/setup_beamline/setup_detector.py +47 -40
  47. mx_bluesky/beamlines/i24/serial/setup_beamline/setup_zebra_plans.py +459 -0
  48. mx_bluesky/beamlines/i24/serial/start_blueapi.sh +28 -0
  49. mx_bluesky/beamlines/i24/serial/write_nexus.py +105 -0
  50. mx_bluesky/example.py +4 -4
  51. mx_bluesky/hyperion/__init__.py +1 -0
  52. mx_bluesky/hyperion/__main__.py +374 -0
  53. mx_bluesky/hyperion/device_setup_plans/__init__.py +0 -0
  54. mx_bluesky/hyperion/device_setup_plans/dcm_pitch_roll_mirror_adjuster.py +134 -0
  55. mx_bluesky/hyperion/device_setup_plans/manipulate_sample.py +110 -0
  56. mx_bluesky/hyperion/device_setup_plans/position_detector.py +16 -0
  57. mx_bluesky/hyperion/device_setup_plans/read_hardware_for_setup.py +60 -0
  58. mx_bluesky/hyperion/device_setup_plans/setup_oav.py +87 -0
  59. mx_bluesky/hyperion/device_setup_plans/setup_panda.py +210 -0
  60. mx_bluesky/hyperion/device_setup_plans/setup_zebra.py +214 -0
  61. mx_bluesky/hyperion/device_setup_plans/smargon.py +25 -0
  62. mx_bluesky/hyperion/device_setup_plans/utils.py +44 -0
  63. mx_bluesky/hyperion/device_setup_plans/xbpm_feedback.py +93 -0
  64. mx_bluesky/hyperion/exceptions.py +47 -0
  65. mx_bluesky/hyperion/experiment_plans/__init__.py +30 -0
  66. mx_bluesky/hyperion/experiment_plans/experiment_registry.py +84 -0
  67. mx_bluesky/hyperion/experiment_plans/flyscan_xray_centre_plan.py +528 -0
  68. mx_bluesky/hyperion/experiment_plans/grid_detect_then_xray_centre_plan.py +209 -0
  69. mx_bluesky/hyperion/experiment_plans/oav_grid_detection_plan.py +173 -0
  70. mx_bluesky/hyperion/experiment_plans/oav_snapshot_plan.py +81 -0
  71. mx_bluesky/hyperion/experiment_plans/optimise_attenuation_plan.py +463 -0
  72. mx_bluesky/hyperion/experiment_plans/pin_centre_then_xray_centre_plan.py +119 -0
  73. mx_bluesky/hyperion/experiment_plans/pin_tip_centring_plan.py +164 -0
  74. mx_bluesky/hyperion/experiment_plans/robot_load_then_centre_plan.py +322 -0
  75. mx_bluesky/hyperion/experiment_plans/rotation_scan_plan.py +436 -0
  76. mx_bluesky/hyperion/experiment_plans/set_energy_plan.py +68 -0
  77. mx_bluesky/hyperion/external_interaction/__init__.py +9 -0
  78. mx_bluesky/hyperion/external_interaction/callbacks/__init__.py +10 -0
  79. mx_bluesky/hyperion/external_interaction/callbacks/__main__.py +148 -0
  80. mx_bluesky/hyperion/external_interaction/callbacks/aperture_change_callback.py +22 -0
  81. mx_bluesky/hyperion/external_interaction/callbacks/common/__init__.py +0 -0
  82. mx_bluesky/hyperion/external_interaction/callbacks/common/callback_util.py +46 -0
  83. mx_bluesky/hyperion/external_interaction/callbacks/common/ispyb_mapping.py +70 -0
  84. mx_bluesky/hyperion/external_interaction/callbacks/grid_detection_callback.py +88 -0
  85. mx_bluesky/hyperion/external_interaction/callbacks/ispyb_callback_base.py +203 -0
  86. mx_bluesky/hyperion/external_interaction/callbacks/log_uid_tag_callback.py +20 -0
  87. mx_bluesky/hyperion/external_interaction/callbacks/logging_callback.py +29 -0
  88. mx_bluesky/hyperion/external_interaction/callbacks/plan_reactive_callback.py +101 -0
  89. mx_bluesky/hyperion/external_interaction/callbacks/robot_load/ispyb_callback.py +88 -0
  90. mx_bluesky/hyperion/external_interaction/callbacks/rotation/__init__.py +0 -0
  91. mx_bluesky/hyperion/external_interaction/callbacks/rotation/ispyb_callback.py +174 -0
  92. mx_bluesky/hyperion/external_interaction/callbacks/rotation/ispyb_mapping.py +17 -0
  93. mx_bluesky/hyperion/external_interaction/callbacks/rotation/nexus_callback.py +102 -0
  94. mx_bluesky/hyperion/external_interaction/callbacks/xray_centre/__init__.py +0 -0
  95. mx_bluesky/hyperion/external_interaction/callbacks/xray_centre/ispyb_callback.py +269 -0
  96. mx_bluesky/hyperion/external_interaction/callbacks/xray_centre/ispyb_mapping.py +53 -0
  97. mx_bluesky/hyperion/external_interaction/callbacks/xray_centre/nexus_callback.py +95 -0
  98. mx_bluesky/hyperion/external_interaction/callbacks/zocalo_callback.py +92 -0
  99. mx_bluesky/hyperion/external_interaction/config_server.py +35 -0
  100. mx_bluesky/hyperion/external_interaction/exceptions.py +13 -0
  101. mx_bluesky/hyperion/external_interaction/ispyb/__init__.py +0 -0
  102. mx_bluesky/hyperion/external_interaction/ispyb/data_model.py +95 -0
  103. mx_bluesky/hyperion/external_interaction/ispyb/exp_eye_store.py +125 -0
  104. mx_bluesky/hyperion/external_interaction/ispyb/ispyb_store.py +276 -0
  105. mx_bluesky/hyperion/external_interaction/ispyb/ispyb_utils.py +29 -0
  106. mx_bluesky/hyperion/external_interaction/nexus/__init__.py +0 -0
  107. mx_bluesky/hyperion/external_interaction/nexus/nexus_utils.py +148 -0
  108. mx_bluesky/hyperion/external_interaction/nexus/write_nexus.py +114 -0
  109. mx_bluesky/hyperion/log.py +99 -0
  110. mx_bluesky/hyperion/parameters/__init__.py +2 -0
  111. mx_bluesky/hyperion/parameters/cli.py +68 -0
  112. mx_bluesky/hyperion/parameters/components.py +253 -0
  113. mx_bluesky/hyperion/parameters/constants.py +158 -0
  114. mx_bluesky/hyperion/parameters/gridscan.py +216 -0
  115. mx_bluesky/hyperion/parameters/rotation.py +160 -0
  116. mx_bluesky/hyperion/resources/panda/panda-gridscan.yaml +964 -0
  117. mx_bluesky/hyperion/tracing.py +28 -0
  118. mx_bluesky/hyperion/utils/context.py +84 -0
  119. mx_bluesky/hyperion/utils/utils.py +25 -0
  120. mx_bluesky/hyperion/utils/validation.py +196 -0
  121. mx_bluesky/jupyter_example.ipynb +3 -2
  122. {mx_bluesky-0.0.2.dist-info → mx_bluesky-1.1.0.dist-info}/METADATA +53 -32
  123. mx_bluesky-1.1.0.dist-info/RECORD +136 -0
  124. {mx_bluesky-0.0.2.dist-info → mx_bluesky-1.1.0.dist-info}/WHEEL +1 -1
  125. mx_bluesky-1.1.0.dist-info/entry_points.txt +8 -0
  126. mx_bluesky/I24/serial/extruder/i24ssx_Extruder_Collect_py3v2.py +0 -476
  127. mx_bluesky/I24/serial/fixed_target/FT-gui-edm/ME14E-motors.edl +0 -1874
  128. mx_bluesky/I24/serial/fixed_target/i24ssx_Chip_Collect_py3v1.py +0 -706
  129. mx_bluesky/I24/serial/fixed_target/i24ssx_Chip_StartUp_py3v1.py +0 -463
  130. mx_bluesky/I24/serial/parameters/__init__.py +0 -5
  131. mx_bluesky/I24/serial/parameters/constants.py +0 -39
  132. mx_bluesky/I24/serial/parameters/fixed_target/cs/cs_maker.json +0 -9
  133. mx_bluesky/I24/serial/parameters/fixed_target/cs/fiducial_1.txt +0 -4
  134. mx_bluesky/I24/serial/parameters/fixed_target/cs/fiducial_2.txt +0 -4
  135. mx_bluesky/I24/serial/parameters/fixed_target/litemaps/currentchip.map +0 -81
  136. mx_bluesky/I24/serial/parameters/fixed_target/parameters.txt +0 -13
  137. mx_bluesky/I24/serial/run_serial.py +0 -52
  138. mx_bluesky/I24/serial/write_nexus.py +0 -113
  139. mx_bluesky-0.0.2.dist-info/RECORD +0 -58
  140. mx_bluesky-0.0.2.dist-info/entry_points.txt +0 -4
  141. /mx_bluesky/{I24 → beamlines}/__init__.py +0 -0
  142. /mx_bluesky/{I24/serial → beamlines/i24}/__init__.py +0 -0
  143. /mx_bluesky/{I24 → beamlines/i24}/serial/extruder/__init__.py +0 -0
  144. /mx_bluesky/{I24 → beamlines/i24}/serial/fixed_target/__init__.py +0 -0
  145. /mx_bluesky/{I24 → beamlines/i24}/serial/parameters/fixed_target/pvar_files/oxford.pvar +0 -0
  146. /mx_bluesky/{I24 → beamlines/i24}/serial/run_ssx.sh +0 -0
  147. /mx_bluesky/{I24 → beamlines/i24}/serial/setup_beamline/__init__.py +0 -0
  148. /mx_bluesky/{I24 → beamlines/i24}/serial/setup_beamline/ca.py +0 -0
  149. {mx_bluesky-0.0.2.dist-info → mx_bluesky-1.1.0.dist-info}/LICENSE +0 -0
  150. {mx_bluesky-0.0.2.dist-info → mx_bluesky-1.1.0.dist-info}/top_level.txt +0 -0
@@ -3,23 +3,24 @@ Chip mapping utilities for fixed target
3
3
 
4
4
  This version changed to python3 March2020 by RLO
5
5
  """
6
+
6
7
  import logging
7
8
  import time
8
9
 
9
10
  import numpy as np
10
11
  from matplotlib import pyplot as plt
11
12
 
12
- from mx_bluesky.I24.serial import log
13
- from mx_bluesky.I24.serial.fixed_target.ft_utils import ChipType
14
- from mx_bluesky.I24.serial.fixed_target.i24ssx_Chip_StartUp_py3v1 import (
13
+ from mx_bluesky.beamlines.i24.serial import log
14
+ from mx_bluesky.beamlines.i24.serial.fixed_target.ft_utils import ChipType
15
+ from mx_bluesky.beamlines.i24.serial.fixed_target.i24ssx_Chip_StartUp_py3v1 import (
15
16
  check_files,
16
- get_format,
17
17
  get_shot_order,
18
18
  get_xy,
19
- scrape_parameter_file,
19
+ read_parameter_file,
20
20
  write_file,
21
21
  )
22
- from mx_bluesky.I24.serial.parameters.constants import PARAM_FILE_PATH_FT
22
+ from mx_bluesky.beamlines.i24.serial.parameters import get_chip_format
23
+ from mx_bluesky.beamlines.i24.serial.parameters.constants import PARAM_FILE_PATH_FT
23
24
 
24
25
  logger = logging.getLogger("I24ssx.chip_mapping")
25
26
 
@@ -34,7 +35,7 @@ def setup_logging():
34
35
  def read_file_make_dict(fid, chip_type, switch=False):
35
36
  a_dict = {}
36
37
  b_dict = {}
37
- with open(fid, "r") as f:
38
+ with open(fid) as f:
38
39
  for line in f.readlines():
39
40
  if line.startswith("#"):
40
41
  continue
@@ -78,36 +79,36 @@ def plot_file(fid, chip_type):
78
79
  ax1.set_xlim(-1, 26)
79
80
  ax1.set_ylim(-1, 26)
80
81
  ax1.invert_yaxis()
81
- check_files(["%s.png" % chip_type])
82
- plt.savefig("%s.png" % fid[:-5], dpi=200, bbox_inches="tight", pad_inches=0.05)
82
+ check_files("i24", [f"{chip_type}.png"])
83
+ plt.savefig(f"{fid[:-5]}.png", dpi=200, bbox_inches="tight", pad_inches=0.05)
83
84
  return 1
84
85
 
85
86
 
86
87
  @log.log_on_entry
87
88
  def convert_chip_to_hex(fid, chip_type):
88
89
  chip_dict = read_file_make_dict(fid, chip_type, True)
89
- chip_format = get_format(chip_type)
90
- check_files(["%s.full" % chip_type])
91
- with open("%s.full" % fid[:-5], "w") as g:
90
+ chip_format = get_chip_format(ChipType(chip_type))
91
+ check_files("i24", [f"{chip_type}.full"])
92
+ with open(f"{fid[:-5]}.full", "w") as g:
92
93
  # Normal
93
94
  if chip_type in [ChipType.Oxford, ChipType.OxfordInner]:
94
95
  shot_order_list = get_shot_order(chip_type)
95
96
  logger.info("Shot Order List: \n")
96
- logger.info("%s" % shot_order_list[:14])
97
- logger.info("%s" % shot_order_list[-14:])
97
+ logger.info(f"{shot_order_list[:14]}")
98
+ logger.info(f"{shot_order_list[-14:]}")
98
99
  for i, k in enumerate(shot_order_list):
99
100
  if i % 20 == 0:
100
101
  logger.info("\n")
101
102
  else:
102
- logger.info("%s" % k)
103
+ logger.info(f"{k}")
103
104
  sorted_pres_list = []
104
105
  for addr in shot_order_list:
105
106
  sorted_pres_list.append(chip_dict[addr])
106
107
 
107
- windows_per_block = chip_format[2]
108
- number_of_lines = len(sorted_pres_list) / windows_per_block
108
+ windows_per_block = chip_format.x_num_steps
109
+ number_of_lines = int(len(sorted_pres_list) / windows_per_block)
109
110
  hex_length = windows_per_block / 4
110
- pad = 7 - hex_length
111
+ pad = int(7 - hex_length)
111
112
  for i in range(number_of_lines):
112
113
  sublist = sorted_pres_list[
113
114
  i * windows_per_block : (i * windows_per_block) + windows_per_block
@@ -116,24 +117,24 @@ def convert_chip_to_hex(fid, chip_type):
116
117
  right_list = sublist
117
118
  else:
118
119
  right_list = sublist[::-1]
119
- hex_string = ("{0:0>%sX}" % hex_length).format(
120
+ hex_string = (f"{{0:0>{hex_length}X}}").format(
120
121
  int("".join(str(x) for x in right_list), 2)
121
122
  )
122
- hex_string = hex_string + pad * "0"
123
+ hex_string = hex_string + (pad * "0")
123
124
  pvar = 5001 + i
124
- line = "P%s=$%s" % (pvar, hex_string)
125
+ line = f"P{pvar}=${hex_string}"
125
126
  g.write(line + "\n")
126
127
  logger.info("hex string: %s" % (hex_string + 4 * "0"))
127
- logger.info("line number= %s" % i)
128
+ logger.info(f"line number= {i}")
128
129
  logger.info(
129
- "right_list: \n%s\n" % ("".join(str(x) for x in right_list))
130
+ "right_list: \n{}\n".format("".join(str(x) for x in right_list))
130
131
  )
131
- logger.info("PVAR: %s" % line)
132
+ logger.info(f"PVAR: {line}")
132
133
  if (i + 1) % windows_per_block == 0:
133
134
  logger.info(
134
135
  "\n %s" % (40 * (" %i" % ((i / windows_per_block) + 2)))
135
136
  )
136
- logger.info("hex_length: %s" % hex_length)
137
+ logger.info(f"hex_length: {hex_length}")
137
138
  else:
138
139
  logger.warning("Chip type unknown, no conversion done.")
139
140
  return 0
@@ -141,24 +142,17 @@ def convert_chip_to_hex(fid, chip_type):
141
142
 
142
143
  def main():
143
144
  setup_logging()
144
- (
145
- chip_name,
146
- visit,
147
- sub_dir,
148
- n_exposures,
149
- chip_type,
150
- map_type,
151
- ) = scrape_parameter_file()
152
-
153
- check_files([".spec"])
145
+ params = read_parameter_file()
146
+
147
+ check_files("i24", [".spec"])
154
148
  write_file(suffix=".spec", order="shot")
155
149
 
156
- logger.info("PARAMETER PATH = %s" % PARAM_FILE_PATH_FT)
157
- fid = PARAM_FILE_PATH_FT / f"{chip_name}.spec"
158
- logger.info("FID = %s" % fid)
150
+ logger.info(f"PARAMETER PATH = {PARAM_FILE_PATH_FT}")
151
+ fid = PARAM_FILE_PATH_FT / f"{params.filename}.spec"
152
+ logger.info(f"FID = {fid}")
159
153
 
160
- plot_file(fid, chip_type)
161
- convert_chip_to_hex(fid, chip_type)
154
+ plot_file(fid, params.chip.chip_type.value)
155
+ convert_chip_to_hex(fid, params.chip.chip_type.value)
162
156
 
163
157
 
164
158
  if __name__ == "__main__":
@@ -0,0 +1,328 @@
1
+ """
2
+ Startup utilities for chip
3
+ """
4
+
5
+ import logging
6
+ import os
7
+ import string
8
+ import time
9
+ from pathlib import Path
10
+
11
+ import numpy as np
12
+
13
+ from mx_bluesky.beamlines.i24.serial import log
14
+ from mx_bluesky.beamlines.i24.serial.fixed_target.ft_utils import ChipType
15
+ from mx_bluesky.beamlines.i24.serial.parameters import (
16
+ FixedTargetParameters,
17
+ get_chip_format,
18
+ )
19
+ from mx_bluesky.beamlines.i24.serial.parameters.constants import (
20
+ HEADER_FILES_PATH,
21
+ PARAM_FILE_NAME,
22
+ PARAM_FILE_PATH_FT,
23
+ )
24
+
25
+ logger = logging.getLogger("I24ssx.chip_startup")
26
+
27
+
28
+ def setup_logging():
29
+ # Log should now change name daily.
30
+ logfile = time.strftime("i24fixedtarget_%d%B%y.log").lower()
31
+ log.config(logfile)
32
+
33
+
34
+ def read_parameter_file(
35
+ param_path: Path | str = PARAM_FILE_PATH_FT,
36
+ ) -> FixedTargetParameters:
37
+ if not isinstance(param_path, Path):
38
+ param_path = Path(param_path)
39
+ params_file = param_path / PARAM_FILE_NAME
40
+ params = FixedTargetParameters.from_file(params_file)
41
+ return params
42
+
43
+
44
+ @log.log_on_entry
45
+ def fiducials(chip_type: int):
46
+ fiducial_list: list | None = None
47
+ if chip_type in [ChipType.Oxford, ChipType.OxfordInner, ChipType.Minichip]:
48
+ fiducial_list = []
49
+ elif chip_type == ChipType.Custom:
50
+ # No fiducial for custom
51
+ logger.warning("No fiducials for custom chip")
52
+ else:
53
+ logger.warning(f"Unknown chip_type, {chip_type}, in fiducials")
54
+ return fiducial_list
55
+
56
+
57
+ def get_xy(addr: str, chip_type: ChipType):
58
+ entry = addr.split("_")[-2:]
59
+ R, C = entry[0][0], entry[0][1]
60
+ r2, c2 = entry[1][0], entry[1][1]
61
+ blockR = string.ascii_uppercase.index(R)
62
+ blockC = int(C) - 1
63
+ lowercase_list = list(string.ascii_lowercase + string.ascii_uppercase + "0")
64
+ windowR = lowercase_list.index(r2)
65
+ windowC = lowercase_list.index(c2)
66
+
67
+ chip_params = get_chip_format(chip_type)
68
+
69
+ x = (
70
+ (blockC * chip_params.b2b_horz)
71
+ + (blockC * (chip_params.x_num_steps - 1) * chip_params.x_step_size)
72
+ + (windowC * chip_params.x_step_size)
73
+ )
74
+ y = (
75
+ (blockR * chip_params.b2b_vert)
76
+ + (blockR * (chip_params.y_num_steps - 1) * chip_params.y_step_size)
77
+ + (windowR * chip_params.y_step_size)
78
+ )
79
+ return x, y
80
+
81
+
82
+ def pathli(l_in=None, way="typewriter", reverse=False):
83
+ if l_in is None:
84
+ l_in = []
85
+ if reverse is True:
86
+ li = list(reversed(l_in))
87
+ else:
88
+ li = list(l_in)
89
+ long_list = []
90
+ if li:
91
+ if way == "typewriter":
92
+ for i in range(len(li) ** 2):
93
+ long_list.append(li[i % len(li)])
94
+ elif way == "snake":
95
+ lr = list(reversed(li))
96
+ for rep in range(len(li)):
97
+ if rep % 2 == 0:
98
+ long_list += li
99
+ else:
100
+ long_list += lr
101
+ elif way == "snake53":
102
+ lr = list(reversed(li))
103
+ for rep in range(53):
104
+ if rep % 2 == 0:
105
+ long_list += li
106
+ else:
107
+ long_list += lr
108
+ elif way == "expand":
109
+ for entry in li:
110
+ for _ in range(len(li)):
111
+ long_list.append(entry)
112
+ elif way == "expand28":
113
+ for entry in li:
114
+ for _ in range(28):
115
+ long_list.append(entry)
116
+ elif way == "expand25":
117
+ for entry in li:
118
+ for _ in range(25):
119
+ long_list.append(entry)
120
+ else:
121
+ logger.warning(f"No known path, way = {way}")
122
+ else:
123
+ logger.warning("No list written")
124
+ return long_list
125
+
126
+
127
+ def zippum(list_1_args, list_2_args):
128
+ list_1, type_1, reverse_1 = list_1_args
129
+ list_2, type_2, reverse_2 = list_2_args
130
+ A_path = pathli(list_1, type_1, reverse_1)
131
+ B_path = pathli(list_2, type_2, reverse_2)
132
+ zipped_list = []
133
+ for a, b in zip(A_path, B_path, strict=False):
134
+ zipped_list.append(a + b)
135
+ return zipped_list
136
+
137
+
138
+ def get_alphanumeric(chip_type: ChipType):
139
+ cell_format = get_chip_format(chip_type)
140
+ blk_num = cell_format.x_blocks
141
+ wnd_num = cell_format.x_num_steps
142
+ uppercase_list = list(string.ascii_uppercase)[:blk_num]
143
+ lowercase_list = list(string.ascii_lowercase + string.ascii_uppercase + "0")[
144
+ :wnd_num
145
+ ]
146
+ number_list = [str(x) for x in range(1, blk_num + 1)]
147
+
148
+ block_list = zippum([uppercase_list, "expand", 0], [number_list, "typewriter", 0])
149
+ window_list = zippum(
150
+ [lowercase_list, "expand", 0], [lowercase_list, "typewriter", 0]
151
+ )
152
+
153
+ alphanumeric_list = []
154
+ for block in block_list:
155
+ for window in window_list:
156
+ alphanumeric_list.append(block + "_" + window)
157
+ logger.info(f"Length of alphanumeric list = {len(alphanumeric_list)}")
158
+ return alphanumeric_list
159
+
160
+
161
+ @log.log_on_entry
162
+ def get_shot_order(chip_type: ChipType):
163
+ cell_format = get_chip_format(chip_type)
164
+ blk_num = cell_format.x_blocks
165
+ wnd_num = cell_format.x_num_steps
166
+ uppercase_list = list(string.ascii_uppercase)[:blk_num]
167
+ number_list = [str(x) for x in range(1, blk_num + 1)]
168
+ lowercase_list = list(string.ascii_lowercase + string.ascii_uppercase + "0")[
169
+ :wnd_num
170
+ ]
171
+
172
+ block_list = zippum([uppercase_list, "snake", 0], [number_list, "expand", 0])
173
+ window_dn = zippum([lowercase_list, "expand", 0], [lowercase_list, "snake", 0])
174
+ window_up = zippum([lowercase_list, "expand", 1], [lowercase_list, "snake", 0])
175
+
176
+ switch = 0
177
+ count = 0
178
+ collect_list = []
179
+ for block in block_list:
180
+ if switch == 0:
181
+ for window in window_dn:
182
+ collect_list.append(block + "_" + window)
183
+ count += 1
184
+ if count == blk_num:
185
+ count = 0
186
+ switch = 1
187
+ else:
188
+ for window in window_up:
189
+ collect_list.append(block + "_" + window)
190
+ count += 1
191
+ if count == blk_num:
192
+ count = 0
193
+ switch = 0
194
+
195
+ logger.info(f"Length of collect list = {len(collect_list)}")
196
+ return collect_list
197
+
198
+
199
+ @log.log_on_entry
200
+ def write_file(
201
+ location: str = "i24",
202
+ suffix: str = ".addr",
203
+ order: str = "alphanumeric",
204
+ param_file_path: Path = PARAM_FILE_PATH_FT,
205
+ save_path: Path = HEADER_FILES_PATH,
206
+ ):
207
+ if location == "i24":
208
+ params = read_parameter_file(param_file_path)
209
+ else:
210
+ msg = f"Unknown location, {location}"
211
+ logger.error(msg)
212
+ raise ValueError(msg)
213
+ chip_file_path = save_path / f"chips/{params.directory}/{params.filename}{suffix}"
214
+
215
+ fiducial_list = fiducials(params.chip.chip_type.value)
216
+
217
+ if order == "alphanumeric":
218
+ addr_list = get_alphanumeric(params.chip.chip_type)
219
+ elif order == "shot":
220
+ addr_list = get_shot_order(params.chip.chip_type)
221
+ else:
222
+ raise ValueError(f"{order=} unrecognised")
223
+
224
+ with open(chip_file_path, "a") as g:
225
+ for addr in addr_list:
226
+ xtal_name = "_".join([params.filename, addr])
227
+ (x, y) = get_xy(xtal_name, params.chip.chip_type)
228
+ if addr in fiducial_list:
229
+ pres = "0"
230
+ else:
231
+ if "rand" in suffix:
232
+ pres = str(np.random.randint(2))
233
+ else:
234
+ pres = "-1"
235
+ line = "\t".join([xtal_name, str(x), str(y), "0.0", pres]) + "\n"
236
+ g.write(line)
237
+
238
+ logger.info(f"Write {chip_file_path} completed")
239
+
240
+
241
+ @log.log_on_entry
242
+ def check_files(
243
+ location: str,
244
+ suffix_list: list[str],
245
+ param_file_path: Path | str = PARAM_FILE_PATH_FT,
246
+ save_path: Path = HEADER_FILES_PATH,
247
+ ):
248
+ if location == "i24":
249
+ params = read_parameter_file(param_file_path)
250
+ else:
251
+ msg = f"Unknown location, {location}"
252
+ logger.error(msg)
253
+ raise ValueError(msg)
254
+ chip_file_path = save_path / f"chips/{params.directory}/{params.filename}"
255
+
256
+ try:
257
+ os.stat(chip_file_path)
258
+ except Exception:
259
+ os.makedirs(chip_file_path)
260
+ for suffix in suffix_list:
261
+ full_fid = chip_file_path.with_suffix(suffix)
262
+ if full_fid.is_file():
263
+ time_str = time.strftime("%Y%m%d_%H%M%S_")
264
+ timestamp_fid = ( # noqa: F841
265
+ full_fid.parent / f"{time_str}_{params.filename}{full_fid.suffix}"
266
+ )
267
+ # FIXME hack / fix. Actually move the file
268
+ logger.info(f"File {full_fid} Already Exists")
269
+ logger.debug("Check files done")
270
+ return 1
271
+
272
+
273
+ @log.log_on_entry
274
+ def write_headers(
275
+ location: str,
276
+ suffix_list: list[str],
277
+ param_file_path: Path = PARAM_FILE_PATH_FT,
278
+ save_path: Path = HEADER_FILES_PATH,
279
+ ):
280
+ if location == "i24":
281
+ params = read_parameter_file(param_file_path)
282
+ chip_file_path = save_path / f"chips/{params.directory}/{params.filename}"
283
+
284
+ for suffix in suffix_list:
285
+ full_fid = chip_file_path.with_suffix(suffix)
286
+ with open(full_fid, "w") as g:
287
+ g.write(
288
+ "#23456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\n#\n"
289
+ )
290
+ g.write(f"#&i24\tchip_name = {params.filename}\n")
291
+ g.write(f"#&i24\tvisit = {params.visit}\n")
292
+ g.write(f"#&i24\tsub_dir = {params.directory}\n")
293
+ g.write(f"#&i24\tn_exposures = {params.num_exposures}\n")
294
+ g.write(f"#&i24\tchip_type = {params.chip.chip_type.value}\n")
295
+ g.write(f"#&i24\tmap_type = {params.map_type.value}\n")
296
+ g.write(f"#&i24\tpump_repeat = {params.pump_repeat.value}\n")
297
+ g.write(f"#&i24\tpumpexptime = {params.laser_dwell_s}\n")
298
+ g.write(f"#&i24\texptime = {params.laser_delay_s}\n")
299
+ g.write(f"#&i24\tdcdetdist = {params.detector_distance_mm}\n")
300
+ g.write(f"#&i24\tprepumpexptime = {params.pre_pump_exposure_s}\n")
301
+ g.write(f"#&i24\tdet_Type = {params.detector_name}\n")
302
+ g.write("#\n")
303
+ g.write(
304
+ "#XtalAddr XCoord YCoord ZCoord Present Shot Spare04 Spare03 Spare02 Spare01\n"
305
+ )
306
+ else:
307
+ msg = f"Unknown location, {location}"
308
+ logger.error(msg)
309
+ raise ValueError(msg)
310
+ logger.debug("Write headers done")
311
+
312
+
313
+ def run():
314
+ logger.debug("Run Startup")
315
+ check_files("i24", [".addr", ".shot"])
316
+ logger.info("Checked Files")
317
+ write_headers("i24", [".addr", ".shot"])
318
+ logger.info("Written Headers")
319
+ logger.info("Writing to Files has been disabled. Headers Only")
320
+ # Makes a file with random crystal positions
321
+ check_files("i24", ["rando.spec"])
322
+ write_headers("i24", ["rando.spec"])
323
+ logger.debug("StartUp Done")
324
+
325
+
326
+ if __name__ == "__main__":
327
+ setup_logging()
328
+ run()
@@ -2,21 +2,25 @@
2
2
  Move on click gui for fixed targets at I24
3
3
  Robin Owen 12 Jan 2021
4
4
  """
5
+
5
6
  import logging
7
+ from collections.abc import Sequence
6
8
 
9
+ import bluesky.plan_stubs as bps
7
10
  import cv2 as cv
11
+ from bluesky.run_engine import RunEngine
8
12
  from dodal.beamlines import i24
13
+ from dodal.devices.i24.pmac import PMAC
9
14
  from dodal.devices.oav.oav_detector import OAV
10
15
 
11
- from mx_bluesky.I24.serial.fixed_target import i24ssx_Chip_Manager_py3v1 as manager
12
- from mx_bluesky.I24.serial.parameters.constants import OAV1_CAM
16
+ from mx_bluesky.beamlines.i24.serial.fixed_target import (
17
+ i24ssx_Chip_Manager_py3v1 as manager,
18
+ )
19
+ from mx_bluesky.beamlines.i24.serial.fixed_target.ft_utils import Fiducials
20
+ from mx_bluesky.beamlines.i24.serial.parameters.constants import OAV1_CAM
13
21
 
14
22
  logger = logging.getLogger("I24ssx.moveonclick")
15
23
 
16
- # Set scale.
17
- # TODO See https://github.com/DiamondLightSource/mx_bluesky/issues/44
18
- zoomcalibrator = 6 # 8 seems to work well for zoom 2
19
-
20
24
 
21
25
  def _get_beam_centre(oav: OAV):
22
26
  """Extract the beam centre x/y positions from the display.configuration file.
@@ -27,40 +31,50 @@ def _get_beam_centre(oav: OAV):
27
31
  return oav.parameters.beam_centre_i, oav.parameters.beam_centre_j
28
32
 
29
33
 
30
- # TODO In the future, this should be done automatically in the OAV device
31
- # See https://github.com/DiamondLightSource/dodal/issues/224
32
- def get_beam_centre():
33
- # Get I24 oav device from dodal
34
- oav = i24.oav()
34
+ def _calculate_zoom_calibrator(oav: OAV):
35
+ """Set the scale for the zoom calibrator for the pmac moves."""
36
+ currentzoom = yield from bps.rd(oav.zoom_controller.percentage)
37
+ zoomcalibrator = 1.547 - (0.03 * currentzoom) + (0.0001634 * currentzoom**2)
38
+ return zoomcalibrator
35
39
 
36
- beamX, beamY = _get_beam_centre(oav)
37
- return beamX, beamY
40
+
41
+ def _move_on_mouse_click_plan(
42
+ oav: OAV, pmac: PMAC, beam_centre: Sequence[int], clicked_position: Sequence[int]
43
+ ):
44
+ """A plan that calculates the zoom calibrator and moves to the clicked \
45
+ position coordinates.
46
+ """
47
+ zoomcalibrator = yield from _calculate_zoom_calibrator(oav)
48
+ beamX, beamY = beam_centre
49
+ x, y = clicked_position
50
+ xmove = -1 * (beamX - x) * zoomcalibrator
51
+ ymove = -1 * (beamY - y) * zoomcalibrator
52
+ logger.info(f"Moving X and Y {xmove} {ymove}")
53
+ xmovepmacstring = "#1J:" + str(xmove)
54
+ ymovepmacstring = "#2J:" + str(ymove)
55
+ yield from bps.abs_set(pmac.pmac_string, xmovepmacstring, wait=True)
56
+ yield from bps.abs_set(pmac.pmac_string, ymovepmacstring, wait=True)
38
57
 
39
58
 
40
59
  # Register clicks and move chip stages
41
60
  def onMouse(event, x, y, flags, param):
42
- pmac = param
43
- beamX, beamY = get_beam_centre()
44
61
  if event == cv.EVENT_LBUTTONUP:
45
- logger.info("Clicked X and Y %s %s" % (x, y))
46
- xmove = -1 * (beamX - x) * zoomcalibrator
47
- ymove = -1 * (beamY - y) * zoomcalibrator
48
- logger.info("Moving X and Y %s %s" % (xmove, ymove))
49
- xmovepmacstring = "#1J:" + str(xmove)
50
- ymovepmacstring = "#2J:" + str(ymove)
51
- pmac.pmac_string.set(xmovepmacstring)
52
- pmac.pmac_string.set(ymovepmacstring)
62
+ RE = param[0]
63
+ pmac = param[1]
64
+ oav = param[2]
65
+ beamX, beamY = _get_beam_centre(oav)
66
+ logger.info(f"Clicked X and Y {x} {y}")
67
+ RE(_move_on_mouse_click_plan(oav, pmac, (beamX, beamY), (x, y)))
53
68
 
54
69
 
55
- def update_ui(frame):
70
+ def update_ui(oav, frame):
56
71
  # Get beam x and y values
57
- beamX, beamY = get_beam_centre()
72
+ beamX, beamY = _get_beam_centre(oav)
58
73
 
59
74
  # Overlay text and beam centre
60
75
  cv.ellipse(
61
76
  frame, (beamX, beamY), (12, 8), 0.0, 0.0, 360, (0, 255, 255), thickness=2
62
77
  )
63
- # putText(frame,'text',bottomLeftCornerOfText, font, fontScale, fontColor, thickness, lineType)
64
78
  cv.putText(
65
79
  frame,
66
80
  "Key bindings",
@@ -134,15 +148,13 @@ def update_ui(frame):
134
148
  cv.imshow("OAV1view", frame)
135
149
 
136
150
 
137
- def start_viewer(oav1: str = OAV1_CAM):
138
- # Get PMAC device
139
- pmac = i24.pmac()
151
+ def start_viewer(oav: OAV, pmac: PMAC, RE: RunEngine, oav1: str = OAV1_CAM):
140
152
  # Create a video caputure from OAV1
141
153
  cap = cv.VideoCapture(oav1)
142
154
 
143
155
  # Create window named OAV1view and set onmouse to this
144
156
  cv.namedWindow("OAV1view")
145
- cv.setMouseCallback("OAV1view", onMouse, param=pmac) # type: ignore
157
+ cv.setMouseCallback("OAV1view", onMouse, param=[RE, pmac, oav]) # type: ignore
146
158
 
147
159
  logger.info("Showing camera feed. Press escape to close")
148
160
  # Read captured video and store them in success and frame
@@ -152,42 +164,44 @@ def start_viewer(oav1: str = OAV1_CAM):
152
164
  while success:
153
165
  success, frame = cap.read()
154
166
 
155
- update_ui(frame)
167
+ update_ui(oav, frame)
156
168
 
157
169
  k = cv.waitKey(1)
158
170
  if k == 113: # Q
159
- manager.moveto("zero")
171
+ RE(manager.moveto(Fiducials.zero, pmac))
160
172
  if k == 119: # W
161
- manager.moveto("f1")
173
+ RE(manager.moveto(Fiducials.fid1, pmac))
162
174
  if k == 101: # E
163
- manager.moveto("f2")
175
+ RE(manager.moveto(Fiducials.fid2, pmac))
164
176
  if k == 97: # A
165
- pmac.pmac_string.set(r"\#1hmz\#2hmz\#3hmz")
177
+ RE(bps.trigger(pmac.home, wait=True))
166
178
  print("Current position set as origin")
167
179
  if k == 115: # S
168
- manager.fiducial(1)
180
+ RE(manager.fiducial(1))
169
181
  if k == 100: # D
170
- manager.fiducial(2)
182
+ RE(manager.fiducial(2))
171
183
  if k == 99: # C
172
- manager.cs_maker()
184
+ RE(manager.cs_maker(pmac))
173
185
  if k == 98: # B
174
- manager.block_check() # doesn't work well for blockcheck as image doesn't update
186
+ RE(
187
+ manager.block_check()
188
+ ) # doesn't work well for blockcheck as image doesn't update
175
189
  if k == 104: # H
176
- pmac.pmac_string.set("#2J:-10")
190
+ RE(bps.abs_set(pmac.pmac_string, "#2J:-10", wait=True))
177
191
  if k == 110: # N
178
- pmac.pmac_string.set("#2J:10")
192
+ RE(bps.abs_set(pmac.pmac_string, "#2J:10", wait=True))
179
193
  if k == 109: # M
180
- pmac.pmac_string.set("#1J:-10")
194
+ RE(bps.abs_set(pmac.pmac_string, "#1J:-10", wait=True))
181
195
  if k == 98: # B
182
- pmac.pmac_string.set("#1J:10")
196
+ RE(bps.abs_set(pmac.pmac_string, "#1J:10", wait=True))
183
197
  if k == 105: # I
184
- pmac.pmac_string.set("#3J:-150")
198
+ RE(bps.abs_set(pmac.pmac_string, "#3J:-150", wait=True))
185
199
  if k == 111: # O
186
- pmac.pmac_string.set("#3J:150")
200
+ RE(bps.abs_set(pmac.pmac_string, "#3J:150", wait=True))
187
201
  if k == 117: # U
188
- pmac.pmac_string.set("#3J:-1000")
202
+ RE(bps.abs_set(pmac.pmac_string, "#3J:-1000", wait=True))
189
203
  if k == 112: # P
190
- pmac.pmac_string.set("#3J:1000")
204
+ RE(bps.abs_set(pmac.pmac_string, "#3J:1000", wait=True))
191
205
  if k == 0x1B: # esc
192
206
  cv.destroyWindow("OAV1view")
193
207
  print("Pressed escape. Closing window")
@@ -198,4 +212,8 @@ def start_viewer(oav1: str = OAV1_CAM):
198
212
 
199
213
 
200
214
  if __name__ == "__main__":
201
- start_viewer()
215
+ RE = RunEngine()
216
+ # Get devices out of dodal
217
+ oav: OAV = i24.oav()
218
+ pmac: PMAC = i24.pmac()
219
+ start_viewer(oav, pmac, RE)