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