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 # Uncomment to let metadata expire in 10 days:
49 #expires: 10d
51 # Waveforms can be optionally shared with other FDSN client configurations,
52 # so that data is not downloaded multiple times. The downside may be that in
53 # some cases more data than expected is available (if data was previously
54 # downloaded for a different application).
55 #shared_waveforms: true
57 # FDSN query arguments to make metadata queries.
58 # See http://www.fdsn.org/webservices/fdsnws-station-1.1.pdf
59 # Time span arguments should not be added here, because they are handled
60 # automatically by Squirrel.
61 query_args: {qargs}
62'''.format(path_prefix=path_prefix, **kwargs).strip()
65templates = {
66 'local.dataset': {
67 'description':
68 'A typical collection of local files.',
69 'yaml': '''
70--- !squirrel.Dataset
72{path_prefix}
74# Data sources to be added (LocalData, FDSNSource, CatalogSource, ...)
75sources:
76- !squirrel.LocalData # This data source is for local files.
78 # These paths are scanned for waveforms, stations, events.
79 paths:
80 - 'catalogs/events.txt'
81 - 'meta/stations.xml'
82 - 'data/waveforms'
84 # Select file format or 'detect' for autodetection.
85 format: 'detect'
86'''.format(path_prefix=path_prefix).strip()},
88 'geofon.dataset': {
89 'description':
90 'Everything available through GEOFON.',
91 'yaml': _template_online_dataset(
92 site='geofon',
93 ),
94 },
96 'iris-seis.dataset': {
97 'description':
98 'All high- and low-gain seismometer channels at IRIS.',
99 'yaml': _template_online_dataset(
100 site='iris',
101 channel='?H?,?L?',
102 ),
103 },
105 'iris-seis-bb.dataset': {
106 'description':
107 'All broad-band high-gain seismometer channels at IRIS.',
108 'yaml': _template_online_dataset(
109 site='iris',
110 channel='VH?,LH?,BH?,HH?',
111 ),
112 },
114 'bgr-gr-lh.dataset': {
115 'description': 'All LH channels for network GR from BGR.',
116 'yaml': _template_online_dataset(
117 site='bgr',
118 network='GR',
119 channel='LH?',
120 ),
121 },
122}
124names = sorted(templates.keys())
126template_listing = '\n'.join(
127 '%-30s %s' % (
128 '%s:' % name,
129 templates[name]['description']) for name in templates)
132def make_subparser(subparsers):
133 return subparsers.add_parser(
134 'template',
135 help=headline,
136 description=headline + '''
138Available configuration SNIPPETs:
140{}
141'''.format(template_listing).strip())
144def setup(parser):
145 parser.add_argument(
146 'name',
147 choices=names,
148 nargs='?',
149 metavar='SNIPPET',
150 help='Name of template snippet to print.')
152 parser.add_argument(
153 '--format', '-f',
154 choices=['commented', 'normal', 'brief'],
155 default='commented',
156 metavar='FMT',
157 help='Set verbosity level of output YAML. Choices: %(choices)s. '
158 'Default: %(default)s.')
160 parser.add_argument(
161 '--write', '-w',
162 action='store_true',
163 help='Write to file.')
166def decomment(s):
167 out = []
168 for line in s.splitlines():
169 line = re.sub(r'#.+', '', line)
170 if line.strip():
171 out.append(line)
173 return '\n'.join(out)
176def brief(s):
177 return dump(load_string(s))
180def run(parser, args):
182 if not args.name:
183 print(template_listing)
185 else:
186 func = {
187 'brief': brief,
188 'commented': lambda s: s,
189 'normal': decomment}[args.format]
191 s = func(templates[args.name]['yaml'])
193 if args.write:
194 path = args.name + '.yaml'
195 try:
196 with open(path, 'x') as f:
197 f.write(s)
198 f.write('\n')
200 logger.info('File written: %s' % path)
202 except FileExistsError:
203 raise ToolError('File exists: %s' % path)
204 else:
205 print(s)