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
14from ..common import dq, ldq
16logger = logging.getLogger('psq.cli.template')
18headline = 'Print configuration snippets.'
20path_prefix = '''
21# All file paths given below are treated relative to the location of this
22# configuration file. Here we may give a common prefix. For example, if the
23# configuration file is in the sub-directory 'PROJECT/config/', set it to '..'
24# so that all paths are relative to 'PROJECT/'.
25path_prefix: '.'
26'''.strip()
29def _template_online_dataset(**kwargs):
30 lqargs = []
31 for k in ['network', 'station', 'channel']:
32 if k in kwargs:
33 v = kwargs.pop(k)
34 lqargs.append(" %s: '%s'" % (k, v))
36 kwargs['qargs'] = '\n' + '\n'.join(lqargs) if lqargs else '{}'
37 return '''
38--- !squirrel.Dataset
40{path_prefix}
42# Data sources to be added (LocalData, FDSNSource, CatalogSource, ...)
43sources:
44- !squirrel.FDSNSource
46 # URL or alias of FDSN site.
47 site: {site}
49 # Uncomment to let metadata expire in 10 days:
50 #expires: 10d
52 # Waveforms can be optionally shared with other FDSN client configurations,
53 # so that data is not downloaded multiple times. The downside may be that in
54 # some cases more data than expected is available (if data was previously
55 # downloaded for a different application).
56 #shared_waveforms: true
58 # FDSN query arguments to make metadata queries.
59 # See http://www.fdsn.org/webservices/fdsnws-station-1.1.pdf
60 # Time span arguments should not be added here, because they are handled
61 # automatically by Squirrel.
62 query_args: {qargs}
63'''.format(path_prefix=path_prefix, **kwargs).strip()
66templates = {
67 'local.dataset': {
68 'description':
69 'A typical collection of local files.',
70 'yaml': '''
71--- !squirrel.Dataset
73{path_prefix}
75# Data sources to be added (LocalData, FDSNSource, CatalogSource, ...)
76sources:
77- !squirrel.LocalData # This data source is for local files.
79 # These paths are scanned for waveforms, stations, events.
80 paths:
81 - 'catalogs/events.txt'
82 - 'meta/stations.xml'
83 - 'data/waveforms'
85 # Select file format or 'detect' for autodetection.
86 format: 'detect'
87'''.format(path_prefix=path_prefix).strip()},
89 'geofon.dataset': {
90 'description':
91 'Everything available through GEOFON.',
92 'yaml': _template_online_dataset(
93 site='geofon',
94 ),
95 },
97 'iris-seis.dataset': {
98 'description':
99 'High- and low-gain seismometer channels from IRIS.',
100 'yaml': _template_online_dataset(
101 site='iris',
102 channel='?H?,?L?',
103 ),
104 },
106 'iris-seis-bb.dataset': {
107 'description':
108 'Broad-band high-gain seismometer channels from IRIS.',
109 'yaml': _template_online_dataset(
110 site='iris',
111 channel='VH?,LH?,BH?,HH?',
112 ),
113 },
115 'bgr-gr-lh.dataset': {
116 'description': 'LH channels for network GR from BGR.',
117 'yaml': _template_online_dataset(
118 site='bgr',
119 network='GR',
120 channel='LH?',
121 ),
122 },
124 'gcmt-m7.dataset': {
125 'description': 'Global-CMT events with Mw >= 7.0.',
126 'yaml': '''
127--- !squirrel.Dataset
129{path_prefix}
131# Data sources to be added (LocalData, FDSNSource, CatalogSource, ...)
132sources:
133- !squirrel.CatalogSource
134 catalog: gcmt
135 query_args:
136 magmin: '7.0'
137'''.format(path_prefix=path_prefix).strip()
138 },
139}
141names = sorted(templates.keys())
143template_listing = '\n'.join(
144 '%-30s %s' % (
145 '%s:' % name,
146 templates[name]['description']) for name in templates)
149def make_subparser(subparsers):
150 return subparsers.add_parser(
151 'template',
152 help=headline,
153 description=headline + '''
155Available SNIPPETs
157{}
158'''.format('\n'.join(' ' + line for line in template_listing.splitlines())))
161def setup(parser):
162 parser.add_argument(
163 'name',
164 choices=names,
165 nargs='?',
166 metavar='SNIPPET',
167 help='Name of template snippet to print.')
169 format_default = 'commented'
170 format_choices = ['commented', 'normal', 'brief']
172 parser.add_argument(
173 '--format', '-f',
174 choices=format_choices,
175 default=format_default,
176 metavar='FMT',
177 help='Set verbosity level of output YAML. Choices: %s. '
178 'Default: %s.' % (ldq(format_choices), dq(format_default)))
180 parser.add_argument(
181 '--write', '-w',
182 action='store_true',
183 help='Write to file.')
186def decomment(s):
187 out = []
188 for line in s.splitlines():
189 line = re.sub(r'#.+', '', line)
190 if line.strip():
191 out.append(line)
193 return '\n'.join(out)
196def brief(s):
197 return dump(load_string(s))
200def run(parser, args):
202 if not args.name:
203 print(template_listing)
205 else:
206 func = {
207 'brief': brief,
208 'commented': lambda s: s,
209 'normal': decomment}[args.format]
211 s = func(templates[args.name]['yaml'])
213 if args.write:
214 path = args.name + '.yaml'
215 try:
216 with open(path, 'x') as f:
217 f.write(s)
218 f.write('\n')
220 logger.info('File written: %s' % path)
222 except FileExistsError:
223 raise ToolError('File exists: %s' % path)
224 else:
225 print(s)