Coverage for /usr/local/lib/python3.11/dist-packages/pyrocko/apps/colosseo.py: 0%

159 statements  

« prev     ^ index     » next       coverage.py v6.5.0, created at 2024-03-07 11:54 +0000

1# https://pyrocko.org - GPLv3 

2# 

3# The Pyrocko Developers, 21st Century 

4# ---|P------/S----------~Lg---------- 

5 

6''' 

7Colosseo - earthquake scenario generator. 

8''' 

9 

10import sys 

11import logging 

12import os.path as op 

13from optparse import OptionParser 

14 

15from pyrocko import util, scenario, guts, gf 

16from pyrocko import __version__ 

17 

18 

19logger = logging.getLogger('pyrocko.apps.colosseo') 

20km = 1000. 

21 

22 

23def d2u(d): 

24 return dict((k.replace('-', '_'), v) for (k, v) in d.items()) 

25 

26 

27description = '''This is Colosseo, an earthquake scenario generator. 

28 

29Create seismic waveforms, InSAR and GNSS offsets for a simulated earthquake 

30scenario. 

31 

32Colosseo is part of Pyrocko. Version %s. 

33''' % __version__ 

34 

35subcommand_descriptions = { 

36 'init': 'initialize a new, blank scenario', 

37 'fill': 'fill the scenario with modelled data', 

38 'snuffle': 'open Snuffler to inspect the waveform data', 

39 'map': 'map the scenario arena' 

40} 

41 

42subcommand_usages = { 

43 'init': 'init <scenario_dir>', 

44 'fill': 'fill <scenario_dir>', 

45 'snuffle': 'snuffle <scenario_dir>', 

46 'map': '<scenario_dir>', 

47} 

48 

49subcommands = subcommand_descriptions.keys() 

50 

51program_name = 'colosseo' 

52 

53usage_tdata = d2u(subcommand_descriptions) 

54usage_tdata['program_name'] = program_name 

55usage_tdata['description'] = description 

56 

57usage = '''%(program_name)s <subcommand> [options] [--] <arguments> ... 

58 

59%(description)s 

60 

61Subcommands: 

62 

63 init %(init)s 

64 fill %(fill)s 

65 snuffle %(snuffle)s 

66 map %(map)s 

67 

68To get further help and a list of available options for any subcommand run: 

69 

70 %(program_name)s <subcommand> --help 

71 

72''' % usage_tdata 

73 

74 

75def die(message, err='', prelude=''): 

76 if prelude: 

77 prelude = prelude + '\n' 

78 

79 if err: 

80 err = '\n' + err 

81 

82 sys.exit('%s%s failed: %s%s' % (prelude, program_name, message, err)) 

83 

84 

85def none_or_float(x): 

86 if x == 'none': 

87 return None 

88 else: 

89 return float(x) 

90 

91 

92def add_common_options(parser): 

93 parser.add_option( 

94 '--loglevel', 

95 action='store', 

96 dest='loglevel', 

97 type='choice', 

98 choices=('critical', 'error', 'warning', 'info', 'debug'), 

99 default='info', 

100 help='set logger level to ' 

101 '"critical", "error", "warning", "info", or "debug". ' 

102 'Default is "%default".') 

103 

104 

105def process_common_options(options): 

106 util.setup_logging(program_name, options.loglevel) 

107 

108 

109def cl_parse(command, args, setup=None, details=None): 

110 usage = subcommand_usages[command] 

111 descr = subcommand_descriptions[command] 

112 

113 if isinstance(usage, str): 

114 usage = [usage] 

115 

116 susage = '%s %s' % (program_name, usage[0]) 

117 for s in usage[1:]: 

118 susage += '\n%s%s %s' % (' '*7, program_name, s) 

119 

120 description = descr[0].upper() + descr[1:] + '.' 

121 

122 if details: 

123 description = description + ' %s' % details 

124 

125 parser = OptionParser(usage=susage, description=description) 

126 

127 if setup: 

128 setup(parser) 

129 

130 add_common_options(parser) 

131 (options, args) = parser.parse_args(args) 

132 process_common_options(options) 

133 return parser, options, args 

134 

135 

136def get_scenario_yml(path): 

137 fn = op.join(path, 'scenario.yml') 

138 if op.exists(fn): 

139 return fn 

140 return False 

141 

142 

143def command_init(args): 

144 

145 def setup(parser): 

146 parser.add_option( 

147 '--force', dest='force', action='store_true', 

148 help='overwrite existing files') 

149 parser.add_option( 

150 '--location', dest='location', metavar='LAT,LON', 

151 help='set scenario center location [deg]') 

152 parser.add_option( 

153 '--radius', dest='radius', metavar='RADIUS', type=float, 

154 help='set scenario center location [km]') 

155 

156 parser, options, args = cl_parse('init', args, setup=setup) 

157 

158 if len(args) != 1: 

159 parser.print_help() 

160 sys.exit(1) 

161 

162 if options.location: 

163 try: 

164 lat, lon = map(float, options.location.split(',')) 

165 except Exception: 

166 die('expected --location=LAT,LON') 

167 else: 

168 lat = lon = None 

169 

170 if options.radius is not None: 

171 radius = options.radius * km 

172 else: 

173 radius = None 

174 

175 project_dir = args[0] 

176 try: 

177 scenario.ScenarioGenerator.initialize( 

178 project_dir, lat, lon, radius, force=options.force) 

179 

180 gf_stores_path = op.join(project_dir, 'gf_stores') 

181 util.ensuredir(gf_stores_path) 

182 

183 except scenario.CannotCreatePath as e: 

184 die(str(e) + ' Use --force to override.') 

185 

186 except scenario.ScenarioError as e: 

187 die(str(e)) 

188 

189 

190def command_fill(args): 

191 

192 def setup(parser): 

193 parser.add_option( 

194 '--force', dest='force', action='store_true', 

195 help='overwrite existing files') 

196 

197 parser, options, args = cl_parse('fill', args, setup=setup) 

198 

199 if len(args) == 0: 

200 args.append('.') 

201 

202 fn = get_scenario_yml(args[0]) 

203 

204 if not fn: 

205 parser.print_help() 

206 sys.exit(1) 

207 

208 project_dir = args[0] 

209 

210 gf_stores_path = op.join(project_dir, 'gf_stores') 

211 

212 try: 

213 engine = get_engine([gf_stores_path]) 

214 

215 sc = guts.load(filename=fn) 

216 sc.init_modelling(engine) 

217 sc.ensure_gfstores(interactive=True) 

218 sc.prepare_data(path=project_dir, overwrite=options.force) 

219 sc.ensure_data(path=project_dir) 

220 sc.make_map(op.join(project_dir, 'map.pdf')) 

221 

222 except scenario.CannotCreatePath as e: 

223 die(str(e) + ' Use --force to override.') 

224 

225 except scenario.ScenarioError as e: 

226 die(str(e)) 

227 

228 

229def command_map(args): 

230 parser, options, args = cl_parse('map', args) 

231 

232 if len(args) == 0: 

233 args.append('.') 

234 

235 fn = get_scenario_yml(args[0]) 

236 

237 if not fn: 

238 parser.print_help() 

239 sys.exit(1) 

240 

241 project_dir = args[0] 

242 

243 gf_stores_path = op.join(project_dir, 'gf_stores') 

244 engine = get_engine([gf_stores_path]) 

245 

246 try: 

247 sc = guts.load(filename=fn) 

248 sc.init_modelling(engine) 

249 sc.make_map(op.join(project_dir, 'map.pdf')) 

250 

251 except scenario.ScenarioError as e: 

252 die(str(e)) 

253 

254 

255def command_snuffle(args): 

256 from pyrocko.gui.snuffler import snuffler 

257 parser, options, args = cl_parse('map', args) 

258 

259 if len(args) == 0: 

260 args.append('.') 

261 

262 fn = get_scenario_yml(args[0]) 

263 

264 if not fn: 

265 parser.print_help() 

266 sys.exit(1) 

267 

268 project_dir = args[0] 

269 gf_stores_path = op.join(project_dir, 'gf_stores') 

270 

271 engine = get_engine([gf_stores_path]) 

272 sc = guts.load(filename=fn) 

273 sc.init_modelling(engine) 

274 

275 return snuffler.snuffle( 

276 sc.get_pile(), 

277 stations=sc.get_stations(), 

278 events=sc.get_events()) 

279 

280 

281def main(args=None): 

282 ''' 

283 CLI entry point for Pyrocko's ``colosseo`` app. 

284 ''' 

285 if args is None: 

286 args = sys.argv[1:] 

287 

288 if len(args) < 1: 

289 sys.exit('Usage: %s' % usage) 

290 

291 command = args.pop(0) 

292 

293 if command in subcommands: 

294 globals()['command_' + command](args) 

295 

296 elif command in ('--help', '-h', 'help'): 

297 if command == 'help' and args: 

298 acommand = args[0] 

299 if acommand in subcommands: 

300 globals()['command_' + acommand](['--help']) 

301 

302 sys.exit('Usage: %s' % usage) 

303 

304 else: 

305 sys.exit('%s: error: no such subcommand: %s' % (program_name, command)) 

306 

307 

308def get_engine(gf_store_superdirs): 

309 engine = gf.LocalEngine( 

310 store_superdirs=gf_store_superdirs, use_config=True) 

311 

312 logger.info( 

313 'Directories to be searched for GF stores:\n%s' 

314 % '\n'.join(' ' + s for s in engine.store_superdirs)) 

315 

316 return engine 

317 

318 

319if __name__ == '__main__': 

320 main()