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 2023-10-04 09:52 +0000
« prev ^ index » next coverage.py v6.5.0, created at 2023-10-04 09:52 +0000
1# https://pyrocko.org - GPLv3
2#
3# The Pyrocko Developers, 21st Century
4# ---|P------/S----------~Lg----------
6'''
7Colosseo - earthquake scenario generator.
8'''
10import sys
11import logging
12import os.path as op
13from optparse import OptionParser
15from pyrocko import util, scenario, guts, gf
16from pyrocko import __version__
19logger = logging.getLogger('pyrocko.apps.colosseo')
20km = 1000.
23def d2u(d):
24 return dict((k.replace('-', '_'), v) for (k, v) in d.items())
27description = '''This is Colosseo, an earthquake scenario generator.
29Create seismic waveforms, InSAR and GNSS offsets for a simulated earthquake
30scenario.
32Colosseo is part of Pyrocko. Version %s.
33''' % __version__
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}
42subcommand_usages = {
43 'init': 'init <scenario_dir>',
44 'fill': 'fill <scenario_dir>',
45 'snuffle': 'snuffle <scenario_dir>',
46 'map': '<scenario_dir>',
47}
49subcommands = subcommand_descriptions.keys()
51program_name = 'colosseo'
53usage_tdata = d2u(subcommand_descriptions)
54usage_tdata['program_name'] = program_name
55usage_tdata['description'] = description
57usage = '''%(program_name)s <subcommand> [options] [--] <arguments> ...
59%(description)s
61Subcommands:
63 init %(init)s
64 fill %(fill)s
65 snuffle %(snuffle)s
66 map %(map)s
68To get further help and a list of available options for any subcommand run:
70 %(program_name)s <subcommand> --help
72''' % usage_tdata
75def die(message, err='', prelude=''):
76 if prelude:
77 prelude = prelude + '\n'
79 if err:
80 err = '\n' + err
82 sys.exit('%s%s failed: %s%s' % (prelude, program_name, message, err))
85def none_or_float(x):
86 if x == 'none':
87 return None
88 else:
89 return float(x)
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".')
105def process_common_options(options):
106 util.setup_logging(program_name, options.loglevel)
109def cl_parse(command, args, setup=None, details=None):
110 usage = subcommand_usages[command]
111 descr = subcommand_descriptions[command]
113 if isinstance(usage, str):
114 usage = [usage]
116 susage = '%s %s' % (program_name, usage[0])
117 for s in usage[1:]:
118 susage += '\n%s%s %s' % (' '*7, program_name, s)
120 description = descr[0].upper() + descr[1:] + '.'
122 if details:
123 description = description + ' %s' % details
125 parser = OptionParser(usage=susage, description=description)
127 if setup:
128 setup(parser)
130 add_common_options(parser)
131 (options, args) = parser.parse_args(args)
132 process_common_options(options)
133 return parser, options, args
136def get_scenario_yml(path):
137 fn = op.join(path, 'scenario.yml')
138 if op.exists(fn):
139 return fn
140 return False
143def command_init(args):
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]')
156 parser, options, args = cl_parse('init', args, setup=setup)
158 if len(args) != 1:
159 parser.print_help()
160 sys.exit(1)
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
170 if options.radius is not None:
171 radius = options.radius * km
172 else:
173 radius = None
175 project_dir = args[0]
176 try:
177 scenario.ScenarioGenerator.initialize(
178 project_dir, lat, lon, radius, force=options.force)
180 gf_stores_path = op.join(project_dir, 'gf_stores')
181 util.ensuredir(gf_stores_path)
183 except scenario.CannotCreatePath as e:
184 die(str(e) + ' Use --force to override.')
186 except scenario.ScenarioError as e:
187 die(str(e))
190def command_fill(args):
192 def setup(parser):
193 parser.add_option(
194 '--force', dest='force', action='store_true',
195 help='overwrite existing files')
197 parser, options, args = cl_parse('fill', args, setup=setup)
199 if len(args) == 0:
200 args.append('.')
202 fn = get_scenario_yml(args[0])
204 if not fn:
205 parser.print_help()
206 sys.exit(1)
208 project_dir = args[0]
210 gf_stores_path = op.join(project_dir, 'gf_stores')
212 try:
213 engine = get_engine([gf_stores_path])
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'))
222 except scenario.CannotCreatePath as e:
223 die(str(e) + ' Use --force to override.')
225 except scenario.ScenarioError as e:
226 die(str(e))
229def command_map(args):
230 parser, options, args = cl_parse('map', args)
232 if len(args) == 0:
233 args.append('.')
235 fn = get_scenario_yml(args[0])
237 if not fn:
238 parser.print_help()
239 sys.exit(1)
241 project_dir = args[0]
243 gf_stores_path = op.join(project_dir, 'gf_stores')
244 engine = get_engine([gf_stores_path])
246 try:
247 sc = guts.load(filename=fn)
248 sc.init_modelling(engine)
249 sc.make_map(op.join(project_dir, 'map.pdf'))
251 except scenario.ScenarioError as e:
252 die(str(e))
255def command_snuffle(args):
256 from pyrocko.gui.snuffler import snuffler
257 parser, options, args = cl_parse('map', args)
259 if len(args) == 0:
260 args.append('.')
262 fn = get_scenario_yml(args[0])
264 if not fn:
265 parser.print_help()
266 sys.exit(1)
268 project_dir = args[0]
269 gf_stores_path = op.join(project_dir, 'gf_stores')
271 engine = get_engine([gf_stores_path])
272 sc = guts.load(filename=fn)
273 sc.init_modelling(engine)
275 return snuffler.snuffle(
276 sc.get_pile(),
277 stations=sc.get_stations(),
278 events=sc.get_events())
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:]
288 if len(args) < 1:
289 sys.exit('Usage: %s' % usage)
291 command = args.pop(0)
293 if command in subcommands:
294 globals()['command_' + command](args)
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'])
302 sys.exit('Usage: %s' % usage)
304 else:
305 sys.exit('%s: error: no such subcommand: %s' % (program_name, command))
308def get_engine(gf_store_superdirs):
309 engine = gf.LocalEngine(
310 store_superdirs=gf_store_superdirs, use_config=True)
312 logger.info(
313 'Directories to be searched for GF stores:\n%s'
314 % '\n'.join(' ' + s for s in engine.store_superdirs))
316 return engine
319if __name__ == '__main__':
320 main()