1# http://pyrocko.org - GPLv3
2#
3# The Pyrocko Developers, 21st Century
4# ---|P------/S----------~Lg----------
6from __future__ import absolute_import, print_function
8import re
9import logging
11from pyrocko.guts import load_string, dump
13from pyrocko.squirrel.error import ToolError
15logger = logging.getLogger('psq.cli.template')
17headline = 'Print configuration snippets.'
19path_prefix = '''
20# All file paths given below are treated relative to the location of this
21# configuration file. Here we may give a common prefix. For example, if the
22# configuration file is in the sub-directory 'PROJECT/config/', set it to '..'
23# so that all paths are relative to 'PROJECT/'.
24path_prefix: '.'
25'''.strip()
28def _template_online_dataset(**kwargs):
29 lqargs = []
30 for k in ['network', 'station', 'channel']:
31 if k in kwargs:
32 v = kwargs.pop(k)
33 lqargs.append(" %s: '%s'" % (k, v))
35 kwargs['qargs'] = '\n' + '\n'.join(lqargs) if lqargs else '{}'
36 return '''
37--- !squirrel.Dataset
39{path_prefix}
41# Data sources to be added (LocalData, FDSNSource, CatalogSource, ...)
42sources:
43- !squirrel.FDSNSource
45 # URL or alias of FDSN site.
46 site: {site}
48 # FDSN query arguments to make metadata queries.
49 # See http://www.fdsn.org/webservices/fdsnws-station-1.1.pdf
50 # Time span arguments should not be added here, because they are handled
51 # automatically by Squirrel.
52 query_args: {qargs}
53'''.format(path_prefix=path_prefix, **kwargs).strip()
56templates = {
57 'local.dataset': {
58 'description':
59 'A typical collection of local files.',
60 'yaml': '''
61--- !squirrel.Dataset
63{path_prefix}
65# Data sources to be added (LocalData, FDSNSource, CatalogSource, ...)
66sources:
67- !squirrel.LocalData # This data source is for local files.
69 # These paths are scanned for waveforms, stations, events.
70 paths:
71 - 'catalogs/events.txt'
72 - 'meta/stations.xml'
73 - 'data/waveforms'
75 # Select file format or 'detect' for autodetection.
76 format: 'detect'
77'''.format(path_prefix=path_prefix).strip()},
79 'geofon.dataset': {
80 'description':
81 'Everything available through GEOFON.',
82 'yaml': _template_online_dataset(
83 site='geofon',
84 ),
85 },
87 'iris-seis.dataset': {
88 'description':
89 'All high- and low-gain seismometer channels at IRIS.',
90 'yaml': _template_online_dataset(
91 site='iris',
92 channel='?H?,?L?',
93 ),
94 },
96 'iris-seis-bb.dataset': {
97 'description':
98 'All broad-band high-gain seismometer channels at IRIS.',
99 'yaml': _template_online_dataset(
100 site='iris',
101 channel='VH?,LH?,BH?,HH?',
102 ),
103 },
105 'bgr-gr-lh.dataset': {
106 'description': 'All LH channels for network GR from BGR.',
107 'yaml': _template_online_dataset(
108 site='bgr',
109 network='GR',
110 channel='LH?',
111 ),
112 },
113}
115names = sorted(templates.keys())
117template_listing = '\n'.join(
118 '%-30s %s' % (
119 '%s:' % name,
120 templates[name]['description']) for name in templates)
123def make_subparser(subparsers):
124 return subparsers.add_parser(
125 'template',
126 help=headline,
127 description=headline + '''
129Available configuration SNIPPETs:
131{}
132'''.format(template_listing).strip())
135def setup(parser):
136 parser.add_argument(
137 'name',
138 choices=names,
139 nargs='?',
140 metavar='SNIPPET',
141 help='Name of template snippet to print.')
143 parser.add_argument(
144 '--format', '-f',
145 choices=['commented', 'normal', 'brief'],
146 default='commented',
147 metavar='FMT',
148 help='Set verbosity level of output YAML. Choices: %(choices)s. '
149 'Default: %(default)s.')
151 parser.add_argument(
152 '--write', '-w',
153 action='store_true',
154 help='Write to file.')
157def decomment(s):
158 out = []
159 for line in s.splitlines():
160 line = re.sub(r'#.+', '', line)
161 if line.strip():
162 out.append(line)
164 return '\n'.join(out)
167def brief(s):
168 return dump(load_string(s))
171def run(parser, args):
173 if not args.name:
174 print(template_listing)
176 else:
177 func = {
178 'brief': brief,
179 'commented': lambda s: s,
180 'normal': decomment}[args.format]
182 s = func(templates[args.name]['yaml'])
184 if args.write:
185 path = args.name + '.yaml'
186 try:
187 with open(path, 'x') as f:
188 f.write(s)
189 f.write('\n')
191 logger.info('File written: %s' % path)
193 except FileExistsError:
194 raise ToolError('File exists: %s' % path)
195 else:
196 print(s)