Coverage for src/pytribeam/constants.py: 100%

86 statements  

« prev     ^ index     » next       coverage.py v7.6.1, created at 2026-09-09 18:27 +0000

1#!/usr/bin/python3 

2"""Package-wide constants and unit conversion factors. 

3 

4This module centralizes shared constants used throughout `pytribeam`, including 

5software version identifiers, logging dataset names and dtypes, beam and detector 

6tolerances, laser and FIB defaults, stage limits, mapping defaults, and test 

7configuration values. 

8 

9It also defines the unit conversion factors used by the package. Most modules 

10should import conversion factors from `Conversions` rather than hard-coding 

11numeric scale factors. 

12 

13## Typical usage 

14 

15```python 

16from pytribeam.constants import Constants, Conversions 

17 

18width_m = width_um * Conversions.UM_TO_M 

19current_a = current_pa * Conversions.PA_TO_A 

20 

21if dwell_ratio > Constants.beam_dwell_tol_ratio: 

22 ... 

23``` 

24 

25## Main objects 

26 

27- `Constants`: package-wide configuration constants, default values, hardware 

28 limits, logging dataset definitions, and test configuration values. 

29- `Conversions`: scalar conversion factors for length, time, voltage, current, 

30 and angle units. 

31 

32## Unit conventions 

33 

34The package uses explicit field names to indicate user-facing units, for example 

35`x_mm`, `width_um`, `current_pa`, `dwell_us`, and `rotation_deg`. Values passed 

36to microscope APIs are converted internally as needed using `Conversions`. 

37 

38Common conversion factors include: 

39 

40| Conversion | Factor | 

41| --- | ---: | 

42| micrometers to meters | `Conversions.UM_TO_M` | 

43| millimeters to meters | `Conversions.MM_TO_M` | 

44| microseconds to seconds | `Conversions.US_TO_S` | 

45| kilovolts to volts | `Conversions.KV_TO_V` | 

46| picoamperes to amperes | `Conversions.PA_TO_A` | 

47| degrees to radians | `Conversions.DEG_TO_RAD` | 

48 

49> **Warning** 

50> 

51> Constants in this module are used across the package. Update them carefully and 

52> verify downstream behavior, especially for values related to hardware limits, 

53> pattern generation, stage motion, and file/log formats. 

54 

55<hr style="height: 12px; background-color: #333; border: none;"> 

56""" 

57 

58__all__ = [ 

59 "Constants", 

60 "Conversions", 

61] 

62 

63# Default python modules 

64import math 

65from typing import NamedTuple 

66 

67import numpy as np 

68import h5py 

69 

70# import pytribeam.utilities as ut 

71import pytribeam.types as tbt 

72 

73 

74class Constants(NamedTuple): 

75 """ 

76 A NamedTuple containing various constants used throughout the software. 

77 

78 ## Attributes 

79 

80 - `module_short_name` (`str`): Short name of the module. 

81 - `autoscript_version` (`str`): Version of the AutoScript software. 

82 - `laser_api_version` (`str`): Version of the Laser API. 

83 - `yml_schema_version` (`str`): Maximum supported version of the YAML schema. 

84 - `logfile_extension` (`str`): Extension for log files. 

85 - `settings_dataset_name` (`str`): Name of the dataset for experiment settings. 

86 - `pre_position_dataset_name` (`str`): Name of the dataset for position before an event. 

87 - `post_position_dataset_name` (`str`): Name of the dataset for position after an event. 

88 - `pre_lasing_dataset_name` (`str`): Name of the dataset for laser power before an event. 

89 - `post_lasing_dataset_name` (`str`): Name of the dataset for laser power after an event. 

90 - `specimen_current_dataset_name` (`str`): Name of the dataset for specimen current. 

91 - `settings_dtype` (`np.dtype`): Data type for settings dataset. 

92 - `position_dtype` (`np.dtype`): Data type for position dataset. 

93 - `laser_power_dtype` (`np.dtype`): Data type for laser power dataset. 

94 - `specimen_current_dtype` (`np.dtype`): Data type for specimen current dataset. 

95 - `beam_types` (`list of str`): Types of beams (electron/ion). 

96 - `voltage_tol_ratio` (`float`): Tolerance ratio for voltage. 

97 - `current_tol_ratio` (`float`): Tolerance ratio for current. 

98 - `beam_dwell_tol_ratio` (`float`): Tolerance ratio for beam dwell time. 

99 - `default_color_depth` (`tbt.ColorDepth`): Default color depth. 

100 - `scan_resolution_limit` (`tbt.Limit`): Limit for scan resolution. 

101 - `contrast_brightness_tolerance` (`float`): Tolerance for contrast and brightness. 

102 - `image_scan_rotation_for_laser_deg` (`float`): Image scan rotation for laser in degrees. 

103 - `laser_objective_limit_mm` (`tbt.Limit`): Limit for laser objective in millimeters. 

104 - `laser_objective_retracted_mm` (`float`): Safe retracted position for laser objective in millimeters. 

105 - `laser_objective_tolerance_mm` (`float`): Tolerance for laser objective in millimeters. 

106 - `laser_beam_shift_tolerance_um` (`float`): Tolerance for laser beam shift in micrometers. 

107 - `laser_energy_tol_uj` (`float`): Tolerance for laser energy in microjoules. 

108 - `laser_delay_s` (`float`): Delay for measuring power and setting pulse divider/energy in seconds. 

109 - `default_fib_rectangle_pattern` (`tbt.FIBRectanglePattern`): Default FIB rectangle pattern. 

110 - `stream_pattern_scale` (`int`): Scale for stream pattern. 

111 - `stream_pattern_y_shift` (`int`): Y-axis shift for stream pattern. 

112 - `stream_pattern_base_dwell_us` (`float`): Base dwell time for stream pattern in microseconds. 

113 - `stage_move_delay_s` (`float`): Delay for stage movement in seconds. 

114 - `stage_move_attempts` (`int`): Number of attempts for stage movement. 

115 - `default_stage_tolerance` (`tbt.StageTolerance`): Default stage tolerance. 

116 - `slice_thickness_limit_um` (`tbt.Limit`): Limit for slice thickness in micrometers. 

117 - `pre_tilt_limit_deg_generic` (`tbt.Limit`): Generic limit for pre-tilt in degrees. 

118 - `pre_tilt_limit_deg_non_Z_sectioning` (`tbt.Limit`): Limit for pre-tilt in non-Z sectioning in degrees. 

119 - `home_position` (`tbt.StagePositionUser`): Home position of the stage. 

120 - `rotation_axis_limit_deg` (`tbt.Limit`): Limit for rotation axis in degrees. 

121 - `detector_collisions` (`list of list of tbt.DetectorType`): List of detector collisions. 

122 - `min_map_time_s` (`int`): Minimum mapping time in seconds. 

123 - `specimen_current_hfw_mm` (`float`): Specimen current high field width in millimeters. 

124 - `specimen_current_delay_s` (`float`): Delay for specimen current in seconds. 

125 - `test_hardware_movement` (`bool`): Flag for testing hardware movement. 

126 - `offline_machines` (`list of str`): List of offline machines. 

127 - `microscope_machines` (`list of str`): List of microscope machines. 

128 - `default_column_count` (`int`): Default number of columns for printing large lists of values. 

129 - `default_column_width` (`int`): Default width of columns in characters. 

130 """ 

131 

132 # Software versions 

133 module_short_name = "pyTriBeam" 

134 autoscript_version = "4.8.1" 

135 laser_api_version = "2.2.1" 

136 yml_schema_version = "1.0" # max supported version #TODO convert to float 

137 

138 # Log file constants 

139 logfile_extension = ".h5" 

140 settings_dataset_name = "Experiment Settings" 

141 pre_position_dataset_name = "Position Before" 

142 post_position_dataset_name = "Position After" 

143 pre_lasing_dataset_name = "Laser Power Before" 

144 post_lasing_dataset_name = "Laser Power After" 

145 specimen_current_dataset_name = "Specimen Current" 

146 settings_dtype = np.dtype( 

147 [ 

148 ("Slice", "<u4"), 

149 ("Step", "<u4"), 

150 ("Config File", h5py.special_dtype(vlen=str)), 

151 ("Timestamp", h5py.special_dtype(vlen=str)), 

152 ("UNIX time", "<u8"), 

153 ] 

154 ) 

155 position_dtype = np.dtype( 

156 [ 

157 ("Slice", "<u4"), 

158 ("X", "<f8"), 

159 ("Y", "<f8"), 

160 ("Z", "<f8"), 

161 ("T", "<f8"), 

162 ("R", "<f8"), 

163 ("Timestamp", h5py.special_dtype(vlen=str)), 

164 ("UNIX time", "<u8"), 

165 ] 

166 ) 

167 laser_power_dtype = np.dtype( 

168 [ 

169 ("Slice", "<u4"), 

170 ("Power", "<f8"), 

171 ("Timestamp", h5py.special_dtype(vlen=str)), 

172 ("UNIX time", "<u8"), 

173 ] 

174 ) 

175 specimen_current_dtype = np.dtype( 

176 [ 

177 ("Slice", "<u4"), 

178 ("Current", "<f8"), 

179 ("Timestamp", h5py.special_dtype(vlen=str)), 

180 ("UNIX time", "<u8"), 

181 ] 

182 ) 

183 

184 # Beam (electron/ion) constants 

185 beam_types = [ 

186 "electron", 

187 "ion", 

188 ] 

189 voltage_tol_ratio = 0.05 

190 current_tol_ratio = 0.05 

191 beam_dwell_tol_ratio = 0.001 

192 default_color_depth = tbt.ColorDepth.BITS_8 

193 scan_resolution_limit = tbt.Limit(min=12, max=65535) # max of 2^16 - 1 

194 

195 # Detector constants 

196 contrast_brightness_tolerance = 1.0e-4 # range is 0 to 1 

197 

198 # Laser constants 

199 image_scan_rotation_for_laser_deg = 180.0 # requirement by TFS for laser milling 

200 laser_objective_limit_mm = tbt.Limit(min=2.0, max=29.0) 

201 laser_objective_retracted_mm = 2.5 # safe retracted position 

202 laser_objective_tolerance_mm = 0.005 

203 laser_beam_shift_tolerance_um = 0.5 

204 laser_energy_tol_uj = 0.05 

205 laser_delay_s = 3.0 # for measuring power and settings pulse divider/energy 

206 

207 # FIB constants 

208 default_fib_rectangle_pattern = tbt.FIBRectanglePattern( 

209 center_um=tbt.Point( 

210 x=0.0, 

211 y=0.0, 

212 ), 

213 width_um=10.0, 

214 height_um=5.0, 

215 depth_um=0.1, 

216 scan_direction=tbt.FIBPatternScanDirection.TOP_TO_BOTTOM, 

217 scan_type=tbt.FIBPatternScanType.RASTER, 

218 ) 

219 stream_pattern_scale = ( 

220 2**12 

221 ) # upscales fib image to this value / width for higher density of points 

222 stream_pattern_y_shift = int( 

223 2**16 / 6 

224 ) # for correct centering of stream patterns, with scan control available only at 16 bit depth, must account for 3:2 aspect ratio for image length:width and cut off half the discrepancy on both top and bottom. Full equation: 2^16(1-(2/3)) / 2 

225 stream_pattern_base_dwell_us = 0.025 # can be 25 or 100 ns, defaults to 25ns 

226 

227 # Stage constants 

228 stage_move_delay_s = 0.5 

229 stage_move_attempts = ( 

230 2 # generally higher accuracy on movement with 2 attempts for non-piezo stages 

231 ) 

232 default_stage_tolerance = tbt.StageTolerance( 

233 translational_um=0.5, 

234 angular_deg=0.02, 

235 ) 

236 slice_thickness_limit_um = tbt.Limit(min=0.0, max=30.0) # TODO revert to 0.5 micron 

237 pre_tilt_limit_deg_generic = tbt.Limit(min=-60.0, max=60.0) 

238 pre_tilt_limit_deg_non_Z_sectioning = tbt.Limit(min=0.0, max=0.0) 

239 home_position = tbt.StagePositionUser( 

240 x_mm=0.0, y_mm=0.0, z_mm=0.0, r_deg=0.0, t_deg=0.0 

241 ) 

242 rotation_axis_limit_deg = tbt.Limit( 

243 min=-180.0, max=180.0 

244 ) # used as right-open internal: 180.0 is not valid and should be converted to -180.0 

245 detector_collisions = [ 

246 [tbt.DetectorType.CBS, tbt.DetectorType.EDS], 

247 [tbt.DetectorType.CBS, tbt.DetectorType.EBSD], 

248 ] 

249 

250 # Mapping (EBSD/EDS) constants 

251 min_map_time_s = 30 

252 specimen_current_hfw_mm = 1.0e-3 

253 specimen_current_delay_s = 2.0 

254 

255 # Test suite constants 

256 test_hardware_movement = True 

257 offline_machines = [ 

258 "S1099177", 

259 "S1125518", 

260 "daasplus2130w11", 

261 "daasplus2131w11", 

262 "daasplus2132w11", 

263 "daasplus2134w11", 

264 ] 

265 microscope_machines = ["HPN125v-MPC", "HPN276-MPC"] 

266 

267 # error message display constants 

268 default_column_count = 3 # for printing large lists of values 

269 default_column_width = 20 # characters 

270 

271 

272class Conversions(NamedTuple): 

273 """ 

274 A NamedTuple containing various conversion constants for length, time, voltage, current, and angle. 

275 

276 ## Attributes 

277 

278 - `MM_TO_M` (`float`): Conversion factor from millimeters to meters. 

279 - `UM_TO_M` (`float`): Conversion factor from micrometers to meters. 

280 - `M_TO_MM` (`float`): Conversion factor from meters to millimeters. 

281 - `M_TO_UM` (`float`): Conversion factor from meters to micrometers. 

282 - `UM_TO_MM` (`float`): Conversion factor from micrometers to millimeters. 

283 - `MM_TO_UM` (`float`): Conversion factor from millimeters to micrometers. 

284 - `US_TO_S` (`float`): Conversion factor from microseconds to seconds. 

285 - `S_TO_US` (`float`): Conversion factor from seconds to microseconds. 

286 - `S_TO_NS` (`float`): Conversion factor from seconds to nanoseconds. 

287 - `NS_TO_S` (`float`): Conversion factor from nanoseconds to seconds. 

288 - `US_TO_NS` (`float`): Conversion factor from microseconds to nanoseconds. 

289 - `NS_TO_US` (`float`): Conversion factor from nanoseconds to microseconds. 

290 - `KV_TO_V` (`float`): Conversion factor from kilovolts to volts. 

291 - `V_TO_KV` (`float`): Conversion factor from volts to kilovolts. 

292 - `UA_TO_A` (`float`): Conversion factor from microamperes to amperes. 

293 - `NA_TO_A` (`float`): Conversion factor from nanoamperes to amperes. 

294 - `PA_TO_A` (`float`): Conversion factor from picoamperes to amperes. 

295 - `A_TO_UA` (`float`): Conversion factor from amperes to microamperes. 

296 - `A_TO_NA` (`float`): Conversion factor from amperes to nanoamperes. 

297 - `A_TO_PA` (`float`): Conversion factor from amperes to picoamperes. 

298 - `PA_TO_NA` (`float`): Conversion factor from picoamperes to nanoamperes. 

299 - `PA_TO_UA` (`float`): Conversion factor from picoamperes to microamperes. 

300 - `NA_TO_UA` (`float`): Conversion factor from nanoamperes to microamperes. 

301 - `NA_TO_PA` (`float`): Conversion factor from nanoamperes to picoamperes. 

302 - `UA_TO_NA` (`float`): Conversion factor from microamperes to nanoamperes. 

303 - `UA_TO_PA` (`float`): Conversion factor from microamperes to picoamperes. 

304 - `DEG_TO_RAD` (`float`): Conversion factor from degrees to radians. 

305 - `RAD_TO_DEG` (`float`): Conversion factor from radians to degrees. 

306 """ 

307 

308 # length 

309 MM_TO_M = 1.0e-3 

310 UM_TO_M = MM_TO_M / 1000.0 

311 M_TO_MM = 1.0 / MM_TO_M 

312 M_TO_UM = 1.0 / UM_TO_M 

313 UM_TO_MM = UM_TO_M * M_TO_MM 

314 MM_TO_UM = 1.0 / UM_TO_MM 

315 

316 # time 

317 US_TO_S = 1.0e-6 

318 S_TO_US = 1.0 / US_TO_S 

319 S_TO_NS = S_TO_US * 1000.0 

320 NS_TO_S = 1.0 / S_TO_NS 

321 US_TO_NS = US_TO_S * S_TO_NS 

322 NS_TO_US = 1.0 / US_TO_NS 

323 

324 # voltage 

325 KV_TO_V = 1.0e3 

326 V_TO_KV = 1.0 / KV_TO_V 

327 

328 # current 

329 UA_TO_A = 1.0e-6 

330 NA_TO_A = UA_TO_A / 1000.0 

331 PA_TO_A = NA_TO_A / 1000.0 

332 A_TO_UA = 1.0 / UA_TO_A 

333 A_TO_NA = 1.0 / NA_TO_A 

334 A_TO_PA = 1.0 / PA_TO_A 

335 PA_TO_NA = PA_TO_A * A_TO_NA 

336 PA_TO_UA = PA_TO_A * A_TO_UA 

337 NA_TO_UA = NA_TO_A * A_TO_UA 

338 NA_TO_PA = 1.0 / PA_TO_NA 

339 UA_TO_NA = 1.0 / NA_TO_UA 

340 UA_TO_PA = 1.0 / PA_TO_UA 

341 

342 # angle 

343 DEG_TO_RAD = math.pi / 180.0 # convert degrees to radians 

344 RAD_TO_DEG = 180.0 / math.pi