Coverage for python/bellhop/constants.py: 100%

98 statements  

« prev     ^ index     » next       coverage.py v7.11.0, created at 2025-10-22 12:04 +0000

1from dataclasses import dataclass, field 

2from enum import Enum 

3 

4 

5 

6class _File_Ext: 

7 """Strings to define file extensions. 

8 

9 Using this class avoids typos in the source. 

10 It is also used to loop through files to delete them 

11 when needed before/after Bellhop execution. 

12 """ 

13 

14 arr = ".arr" 

15 ati = ".ati" 

16 bty = ".bty" 

17 log = ".log" 

18 sbp = ".sbp" 

19 shd = ".shd" 

20 prt = ".prt" 

21 ray = ".ray" 

22 env = ".env" 

23 ssp = ".ssp" 

24 brc = ".brc" 

25 trc = ".trc" 

26 

27 

28class _Strings(str, Enum): 

29 """String definitions to avoid hard-coding magic strings in the source code 

30 

31 This helps prevent typos and permits autocomplete (if your editor is smart enough). 

32 """ 

33 

34 exe = "bellhop.exe" 

35 

36 default = "default" 

37 none = "none" 

38 

39 # interpolation 

40 linear = "linear" 

41 spline = "spline" 

42 pchip = "pchip" 

43 nlinear = "nlinear" 

44 quadrilateral = "quadrilateral" 

45 hexahedral = "hexahedral" 

46 

47 # ati/bty interpolation 

48 curvilinear = "curvilinear" 

49 

50 # boundaries 

51 vacuum = "vacuum" 

52 acousto_elastic = "acousto-elastic" 

53 rigid = "rigid" 

54 

55 # bathymetry 

56 from_file = "from-file" 

57 flat = "flat" 

58 

59 # sources 

60 line = "line" 

61 point = "point" 

62 

63 # beam 

64 hat_cartesian = "hat-cartesian", 

65 hat_ray = "hat-ray", 

66 gaussian_cartesian = "gaussian-cartesian", 

67 gaussian_ray = "gaussian-ray", 

68 omnidirectional = "omnidirectional" 

69 single_beam = "single beam" 

70 

71 # grid 

72 rectilinear = "rectilinear" 

73 irregular = "irregular" 

74 

75 # volume attenuation 

76 thorp = "thorp" 

77 francois_garrison = "francois-garrison" 

78 biological = "biological" 

79 

80 # attenuation units 

81 nepers_per_meter = "nepers per meter" 

82 frequency_dependent = "frequency dependent" 

83 db_per_meter = "dB per meter" 

84 db_per_wavelength = "dB per wavelength" 

85 quality_factor = "quality factor" 

86 loss_parameter = "loss parameter" 

87 

88 # tasks 

89 rays = "rays" 

90 eigenrays = "eigenrays" 

91 arrivals = "arrivals" 

92 coherent = "coherent" 

93 incoherent = "incoherent" 

94 semicoherent = "semicoherent" 

95 amplitude = "amplitude" 

96 amplitude_b = "amplitude-binary" 

97 

98 

99class _Maps: 

100 """Mappings from Bellhop single-char input file options to readable Python options 

101 

102 These are also defined with reverse mappings in the form: 

103 

104 >>> _Maps.soundspeed_interp["S"] 

105 "spline" 

106 

107 >>> _Maps.soundspeed_interp_rev["spline"] 

108 "S" 

109 

110 """ 

111 

112 soundspeed_interp = { 

113 "S": _Strings.spline, 

114 "C": _Strings.linear, 

115 "Q": _Strings.quadrilateral, # TODO: add test 

116 "P": _Strings.pchip, 

117 "H": _Strings.hexahedral, # TODO: add test 

118 "N": _Strings.nlinear, 

119 " ": _Strings.default, 

120 } 

121 depth_interp = { 

122 "L": _Strings.linear, 

123 "C": _Strings.curvilinear, 

124 } 

125 surface_interp = { 

126 "L": _Strings.linear, 

127 "C": _Strings.curvilinear, 

128 } 

129 bottom_boundary_condition = { 

130 "V": _Strings.vacuum, 

131 "A": _Strings.acousto_elastic, 

132 "R": _Strings.rigid, 

133 "F": _Strings.from_file, 

134 " ": _Strings.default, 

135 } 

136 surface_boundary_condition = { 

137 "V": _Strings.vacuum, 

138 "A": _Strings.acousto_elastic, 

139 "R": _Strings.rigid, 

140 "F": _Strings.from_file, 

141 " ": _Strings.default, 

142 } 

143 attenuation_units = { 

144 "N": _Strings.nepers_per_meter, 

145 "F": _Strings.frequency_dependent, 

146 "M": _Strings.db_per_meter, 

147 "W": _Strings.db_per_wavelength, 

148 "Q": _Strings.quality_factor, 

149 "L": _Strings.loss_parameter, 

150 " ": _Strings.default, 

151 } 

152 volume_attenuation = { 

153 "T": _Strings.thorp, 

154 "F": _Strings.francois_garrison, 

155 "B": _Strings.biological, 

156 " ": _Strings.none, 

157 } 

158 _bathymetry = { 

159 "_": _Strings.flat, 

160 "~": _Strings.from_file, 

161 "*": _Strings.from_file, 

162 " ": _Strings.default, 

163 } 

164 _altimetry = { 

165 "_": _Strings.flat, 

166 "~": _Strings.from_file, 

167 "*": _Strings.from_file, 

168 " ": _Strings.default, 

169 } 

170 source_type = { 

171 "R": _Strings.point, 

172 "X": _Strings.line, 

173 " ": _Strings.default, 

174 } 

175 _sbp_file = { 

176 "*": _Strings.from_file, 

177 "O": _Strings.omnidirectional, 

178 " ": _Strings.default, 

179 } 

180 grid_type = { 

181 "R": _Strings.rectilinear, 

182 "I": _Strings.irregular, 

183 " ": _Strings.default, 

184 } 

185 beam_type = { 

186 "G": _Strings.hat_cartesian, 

187 "^": _Strings.hat_cartesian, 

188 "g": _Strings.hat_ray, 

189 "B": _Strings.gaussian_cartesian, 

190 "b": _Strings.gaussian_ray, 

191 " ": _Strings.default, 

192 } 

193 _single_beam = { 

194 "I": _Strings.single_beam, 

195 " ": _Strings.default, 

196 } 

197 task = { 

198 "R": _Strings.rays, 

199 "E": _Strings.eigenrays, 

200 "A": _Strings.amplitude, 

201 "a": _Strings.amplitude_b, 

202 "C": _Strings.coherent, 

203 "I": _Strings.incoherent, 

204 "S": _Strings.semicoherent, 

205 } 

206 mode = { 

207 "C": _Strings.coherent, 

208 "I": _Strings.incoherent, 

209 "S": _Strings.semicoherent, 

210 } 

211 

212 # reverse maps 

213 soundspeed_interp_rev = {v: k for k, v in soundspeed_interp.items()} 

214 depth_interp_rev = {v: k for k, v in depth_interp.items()} 

215 surface_interp_rev = {v: k for k, v in surface_interp.items()} 

216 bottom_boundary_condition_rev = {v: k for k, v in bottom_boundary_condition.items()} 

217 surface_boundary_condition_rev = {v: k for k, v in surface_boundary_condition.items()} 

218 attenuation_units_rev = {v: k for k, v in attenuation_units.items()} 

219 volume_attenuation_rev = {v: k for k, v in volume_attenuation.items()} 

220 _bathymetry_rev = {v: k for k, v in _bathymetry.items()} 

221 _altimetry_rev = {v: k for k, v in _altimetry.items()} 

222 source_type_rev = {v: k for k, v in source_type.items()} 

223 grid_type_rev = {v: k for k, v in grid_type.items()} 

224 beam_type_rev = {v: k for k, v in beam_type.items()} 

225 _single_beam_rev = {v: k for k, v in _single_beam.items()} 

226 task_rev = {v: k for k, v in task.items()} 

227 mode_rev = {v: k for k, v in mode.items()} 

228 

229 

230@dataclass(frozen=True) 

231class Defaults: 

232 """Dataclass of hard-coded defaults used throughout the Bellhop interface.""" 

233 model_name: str = field(default="bellhop", metadata={"desc": "Name of the class instance for the model"}) 

234 exe: str = field(default="bellhop.exe", metadata={"desc": "Executable name"}) 

235 beam_angle_halfspace: float = field(default=90.0, metadata={"units": "deg"}) 

236 beam_angle_fullspace: float = field(default=180.0, metadata={"units": "deg"}) 

237 env_comment_pad: int = field(default=50, metadata={"desc": "Number of characters used before the comment in the constructed .env files."}) 

238 interference_mode: str = field(default=_Strings.coherent, metadata={"desc": "Mode of interference when calculating transmission loss"}) 

239 

240