Coverage for src\pytribeam\log.py: 98%

97 statements  

« prev     ^ index     » next       coverage.py v7.5.1, created at 2025-03-04 17:41 -0800

1#!/usr/bin/python3 

2 

3# Default python modules 

4# from functools import singledispatch 

5import os 

6from pathlib import Path 

7import warnings 

8import math 

9from typing import NamedTuple, List, Tuple 

10from functools import singledispatch 

11import time 

12import datetime 

13 

14# Autoscript included modules 

15import numpy as np 

16from matplotlib import pyplot as plt 

17import h5py 

18import pandas as pd 

19 

20# 3rd party module 

21 

22# Local scripts 

23from pytribeam.constants import Constants 

24import pytribeam.types as tbt 

25 

26 

27def create_file(path: Path) -> bool: 

28 if not path.is_file(): 

29 log = h5py.File(path, "w") 

30 log.close() 

31 if path.is_file(): 

32 print(f'Logfile created at "{path}".') 

33 if path.is_file(): 

34 return True 

35 raise ValueError(f'Unable to create log file at location "{path}".') 

36 

37 

38def current_time() -> tbt.TimeStamp: 

39 now = datetime.datetime.now() 

40 human_readable = now.strftime("%m/%d/%Y %H:%M:%S") 

41 unix_time = int(now.timestamp()) 

42 time = tbt.TimeStamp(human_readable=human_readable, unix=unix_time) 

43 return time 

44 

45 

46def yml_from_log( 

47 log_path_h5: Path, 

48 output_path_yml: Path, 

49 row: int, 

50 config_field: str = "Config File", 

51) -> bool: 

52 # TODO enforce file formats on inputs 

53 with h5py.File(log_path_h5, "r") as file: 

54 data = np.array(file[Constants.settings_dataset_name][:]) 

55 settings = data[row][Constants.settings_dtype.names.index(config_field)].decode( 

56 "utf-8" 

57 ) 

58 

59 with open(output_path_yml, "w") as file: 

60 file.write(settings) 

61 

62 return True 

63 

64 

65def experiment_settings( 

66 slice_number: int, 

67 step_number: int, 

68 log_filepath: Path, 

69 yml_path: Path, 

70) -> bool: 

71 dataset_name = Constants.settings_dataset_name 

72 settings_dtype = Constants.settings_dtype 

73 time = current_time() 

74 

75 with open(yml_path, "r") as yml_file: 

76 yml_lines = yml_file.readlines() 

77 

78 yml_data = " ".join([line for line in yml_lines]) 

79 

80 if not log_filepath.exists(): 

81 log_filepath.touch() 

82 

83 with h5py.File(log_filepath, "r+") as log: 

84 if not dataset_name in log: 

85 settings = log.create_dataset( 

86 dataset_name, 

87 (0,), 

88 settings_dtype, 

89 maxshape=(None,), 

90 ) 

91 dataset = log[dataset_name] 

92 settings_data = np.array( 

93 [ 

94 ( 

95 slice_number, 

96 step_number, 

97 yml_data, 

98 time.human_readable, 

99 time.unix, 

100 ) 

101 ], 

102 settings_dtype, 

103 ) 

104 # add one row to table 

105 dataset.resize(dataset.shape[0] + 1, axis=0) 

106 dataset[-1:] = settings_data 

107 

108 return True 

109 

110 

111def position( 

112 step_number: int, 

113 step_name: str, 

114 slice_number: int, 

115 log_filepath: Path, 

116 dataset_name: str, 

117 current_position: tbt.StagePositionUser, 

118) -> bool: 

119 print("\tLogging current position...") 

120 dataset_location = f"{step_number:02d}_{step_name}/{dataset_name}" 

121 time = current_time() 

122 

123 with h5py.File(log_filepath, "r+") as file: 

124 if not dataset_location in file: 

125 position = file.create_dataset( 

126 dataset_location, 

127 (0,), 

128 Constants.position_dtype, 

129 maxshape=(None,), 

130 ) 

131 position.attrs["X Units"] = np.string_("[mm]") 

132 position.attrs["Y Units"] = np.string_("[mm]") 

133 position.attrs["Z Units"] = np.string_("[mm]") 

134 position.attrs["T Units"] = np.string_("[degrees]") 

135 position.attrs["R Units"] = np.string_("[degrees]") 

136 

137 dataset = file[dataset_location] 

138 position_data = np.array( 

139 [ 

140 ( 

141 slice_number, 

142 round(current_position.x_mm, 6), 

143 round(current_position.y_mm, 6), 

144 round(current_position.z_mm, 6), 

145 round(current_position.t_deg, 6), 

146 round(current_position.r_deg, 6), 

147 time.human_readable, 

148 time.unix, 

149 ) 

150 ], 

151 Constants.position_dtype, 

152 ) 

153 # add one row to table 

154 dataset.resize(dataset.shape[0] + 1, axis=0) 

155 dataset[-1:] = position_data 

156 

157 return True 

158 

159 

160def laser_power( 

161 step_number: int, 

162 step_name: str, 

163 slice_number: int, 

164 log_filepath: Path, 

165 dataset_name: str, 

166 power_w: float, 

167) -> bool: 

168 print("\tLogging laser power...") 

169 dataset_location = f"{step_number:02d}_{step_name}/{dataset_name}" 

170 time = current_time() 

171 

172 with h5py.File(log_filepath, "r+") as file: 

173 if not dataset_location in file: 

174 laser_power = file.create_dataset( 

175 dataset_location, 

176 (0,), 

177 Constants.laser_power_dtype, 

178 maxshape=(None,), 

179 ) 

180 laser_power.attrs["Units"] = np.string_("[W]") 

181 

182 dataset = file[dataset_location] 

183 laser_power_data = np.array( 

184 [ 

185 ( 

186 slice_number, 

187 round(power_w, 6), 

188 time.human_readable, 

189 time.unix, 

190 ) 

191 ], 

192 Constants.laser_power_dtype, 

193 ) 

194 # add one row to table 

195 dataset.resize(dataset.shape[0] + 1, axis=0) 

196 dataset[-1:] = laser_power_data 

197 

198 

199def specimen_current( 

200 step_number: int, 

201 step_name: str, 

202 slice_number: int, 

203 log_filepath: Path, 

204 dataset_name: str, 

205 specimen_current_na: float, 

206) -> bool: 

207 print("\tLogging sample current...") 

208 dataset_location = f"{step_number:02d}_{step_name}/{dataset_name}" 

209 time = current_time() 

210 

211 with h5py.File(log_filepath, "r+") as file: 

212 if not dataset_location in file: 

213 specimen_current = file.create_dataset( 

214 dataset_location, 

215 (0,), 

216 Constants.specimen_current_dtype, 

217 maxshape=(None,), 

218 ) 

219 specimen_current.attrs["Units"] = np.string_("[nA]") 

220 

221 dataset = file[dataset_location] 

222 specimen_current_data = np.array( 

223 [ 

224 ( 

225 slice_number, 

226 round(specimen_current_na, 6), 

227 time.human_readable, 

228 time.unix, 

229 ) 

230 ], 

231 Constants.specimen_current_dtype, 

232 ) 

233 # add one row to table 

234 dataset.resize(dataset.shape[0] + 1, axis=0) 

235 dataset[-1:] = specimen_current_data 

236 print("\tLogging sample current complete...") 

237 

238 

239if __name__ == "__main__": 

240 pass