Coverage for physped/core/lattice_selection.py: 0%

76 statements  

« prev     ^ index     » next       coverage.py v7.6.12, created at 2025-04-01 09:28 +0000

1"""This module contains functions to select a single point or a range of 

2values in the configuration file. 

3 

4The only purpose is to let the user make a selection along the discretization 

5lattice. 

6""" 

7 

8import logging 

9 

10import numpy as np 

11from omegaconf import DictConfig, OmegaConf 

12 

13from physped.core.digitizers import digitize_coordinates_to_lattice 

14from physped.utils.functions import periodic_angular_conditions 

15 

16log = logging.getLogger(__name__) 

17 

18 

19# ! The functions below are used to select a single point in the config file 

20 

21 

22def validate_value_within_lattice( 

23 selected_value: float, bins: dict, dimension: str 

24) -> None: 

25 """Check if the selected value is outside the lattice. 

26 

27 Args: 

28 selected_value: The selected value in one of the dimensions. 

29 bins: The bins of the lattice in all the dimensions. 

30 dimension: The dimension of the given value. 

31 

32 Raises: 

33 ValueError: If the selected value is outside the lattice. 

34 """ 

35 left_bound = bins[dimension][0] 

36 right_bound = bins[dimension][-1] 

37 outside_lattice = (selected_value < left_bound) or ( 

38 selected_value > right_bound 

39 ) 

40 if outside_lattice: 

41 raise ValueError( 

42 f"Selected {dimension} value ({selected_value}) is outside the " 

43 f"lattice. Please select a value within the range " 

44 f"[{left_bound},{right_bound}]." 

45 ) 

46 

47 

48def validate_point_within_lattice( 

49 selected_point: DictConfig, grid_bins: dict 

50) -> None: 

51 """Validate the selection. 

52 

53 Args: 

54 selected_point: The selected point. 

55 grid_bins: The bins of the lattice in all the dimensions. 

56 """ 

57 for dimension, value in selected_point.items(): 

58 validate_value_within_lattice(value, grid_bins, dimension) 

59 log.info("The selected point is located within the grid.") 

60 

61 

62def get_boundaries_that_enclose_the_selected_bin( 

63 bin_index: int, bins: np.ndarray 

64) -> dict: 

65 left_bound = bins[bin_index] 

66 right_bound = bins[bin_index + 1] 

67 return [left_bound, right_bound] 

68 

69 

70def evaluate_selection_point(config: DictConfig) -> DictConfig: 

71 selection = config.params.selection 

72 selected_point = selection.point 

73 grid_bins = config.params.grid.bins 

74 

75 selected_point.theta_periodic = periodic_angular_conditions( 

76 selected_point.theta, grid_bins["theta"] 

77 ) 

78 validate_point_within_lattice(selected_point, grid_bins) 

79 selected_point.x_index = digitize_coordinates_to_lattice( 

80 selected_point.x, grid_bins["x"] 

81 ) 

82 selected_point.y_index = digitize_coordinates_to_lattice( 

83 selected_point.y, grid_bins["y"] 

84 ) 

85 selected_point.r_index = digitize_coordinates_to_lattice( 

86 selected_point.r, grid_bins["r"] 

87 ) 

88 selected_point.theta_index = digitize_coordinates_to_lattice( 

89 selected_point.theta_periodic, grid_bins["theta"] 

90 ) 

91 selected_point.k_index = digitize_coordinates_to_lattice( 

92 selected_point.k, grid_bins["k"] 

93 ) 

94 return config 

95 

96 

97# ! The functions below are used to select a range of values in the config file 

98 

99 

100def is_selected_range_within_grid( 

101 selected_range: OmegaConf, grid_bins: dict 

102) -> None: 

103 for dimension in ["x", "y", "r", "theta", "k"]: 

104 for value in selected_range[dimension]: 

105 validate_value_within_lattice(value, grid_bins, dimension) 

106 log.info("The selected range is located within the grid.") 

107 

108 

109def is_range_decreasing(selected_range: OmegaConf): 

110 """ 

111 Check if the range is increasing. 

112 

113 Raises: 

114 ValueError: If the range is decreasing 

115 

116 Args: 

117 selected_range (OmegaConf): The selection. 

118 """ 

119 range_decreasing = selected_range[0] > selected_range[1] 

120 if range_decreasing: 

121 raise ValueError( 

122 "The selected range is invalid. The range must be increasing." 

123 ) 

124 

125 

126def is_selected_range_valid(selected_range: OmegaConf) -> None: 

127 """ 

128 Validate the selection. 

129 

130 Args: 

131 selection: The selection. 

132 """ 

133 for dimension in ["x", "y", "r", "theta", "k"]: 

134 is_range_decreasing(selected_range[dimension]) 

135 log.info("The selected range is valid.") 

136 

137 

138def get_boundaries_that_enclose_the_selected_range( 

139 selected_range: OmegaConf, bins: dict 

140) -> dict: 

141 left_bound = bins[selected_range[0]] 

142 right_bound = bins[selected_range[1] + 1] 

143 return [float(left_bound), float(right_bound)] 

144 

145 

146def evaluate_selection_range(config: DictConfig) -> DictConfig: 

147 selected_range = config.params.selection.range 

148 grid_bins = config.params.grid.bins 

149 selected_range.theta_periodic = periodic_angular_conditions( 

150 selected_range.theta, grid_bins["theta"] 

151 ).tolist() 

152 

153 is_selected_range_valid(selected_range) 

154 is_selected_range_within_grid(selected_range, grid_bins) 

155 selected_range.x_indices = digitize_coordinates_to_lattice( 

156 selected_range.x, grid_bins["x"] 

157 ).tolist() 

158 selected_range.y_indices = digitize_coordinates_to_lattice( 

159 selected_range.y, grid_bins["y"] 

160 ).tolist() 

161 selected_range.r_indices = digitize_coordinates_to_lattice( 

162 selected_range.r, grid_bins["r"] 

163 ).tolist() 

164 selected_range.theta_indices = digitize_coordinates_to_lattice( 

165 selected_range.theta_periodic, grid_bins["theta"] 

166 ).tolist() 

167 selected_range.k_indices = digitize_coordinates_to_lattice( 

168 selected_range.k, grid_bins["k"] 

169 ).tolist() 

170 

171 selected_range.x_bounds = get_boundaries_that_enclose_the_selected_range( 

172 selected_range.x_indices, grid_bins["x"] 

173 ) 

174 selected_range.y_bounds = get_boundaries_that_enclose_the_selected_range( 

175 selected_range.y_indices, grid_bins["y"] 

176 ) 

177 selected_range.r_bounds = get_boundaries_that_enclose_the_selected_range( 

178 selected_range.r_indices, grid_bins["r"] 

179 ) 

180 selected_range.theta_bounds = ( 

181 get_boundaries_that_enclose_the_selected_range( 

182 selected_range.theta_indices, grid_bins["theta"] 

183 ) 

184 ) 

185 selected_range.k_bounds = get_boundaries_that_enclose_the_selected_range( 

186 selected_range.k_indices, grid_bins["k"] 

187 ) 

188 

189 log.debug("x bins: %s", [np.round(x, 2) for x in grid_bins["x"]]) 

190 log.debug( 

191 "range: %s ---> %s ---> %s", 

192 selected_range.x, 

193 selected_range.x_indices, 

194 [np.round(x, 2) for x in selected_range.x_bounds], 

195 ) 

196 log.debug("y bins: %s", [np.round(x, 2) for x in grid_bins["y"]]) 

197 log.debug( 

198 "range: %s ---> %s ---> %s", 

199 selected_range.y, 

200 selected_range.y_indices, 

201 [np.round(x, 2) for x in selected_range.y_bounds], 

202 ) 

203 log.debug("r bins: %s", [np.round(x, 2) for x in grid_bins["r"]]) 

204 log.debug( 

205 "range: %s ---> %s ---> %s", 

206 selected_range.r, 

207 selected_range.r_indices, 

208 [np.round(x, 2) for x in selected_range.r_bounds], 

209 ) 

210 log.debug("theta bins: %s", [np.round(x, 2) for x in grid_bins["theta"]]) 

211 log.debug( 

212 "range: %s ---> %s ---> %s", 

213 selected_range.theta, 

214 selected_range.theta_indices, 

215 [np.round(x, 2) for x in selected_range.theta_bounds], 

216 ) 

217 log.debug("k bins: %s", [np.round(x, 2) for x in grid_bins["k"]]) 

218 log.debug( 

219 "range: %s ---> %s ---> %s", 

220 selected_range.k, 

221 selected_range.k_indices, 

222 [np.round(x, 2) for x in selected_range.k_bounds], 

223 ) 

224 return config