1# http://pyrocko.org - GPLv3 

2# 

3# The Pyrocko Developers, 21st Century 

4# ---|P------/S----------~Lg---------- 

5 

6from __future__ import absolute_import, print_function 

7 

8import re 

9import logging 

10 

11from pyrocko.guts import load_string, dump 

12 

13from pyrocko.squirrel.error import ToolError 

14 

15logger = logging.getLogger('psq.cli.template') 

16 

17headline = 'Print configuration snippets.' 

18 

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() 

26 

27 

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)) 

34 

35 kwargs['qargs'] = '\n' + '\n'.join(lqargs) if lqargs else '{}' 

36 return ''' 

37--- !squirrel.Dataset 

38 

39{path_prefix} 

40 

41# Data sources to be added (LocalData, FDSNSource, CatalogSource, ...) 

42sources: 

43- !squirrel.FDSNSource 

44 

45 # URL or alias of FDSN site. 

46 site: {site} 

47 

48 # Uncomment to let metadata expire in 10 days: 

49 #expires: 10d 

50 

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 

56 

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() 

63 

64 

65templates = { 

66 'local.dataset': { 

67 'description': 

68 'A typical collection of local files.', 

69 'yaml': ''' 

70--- !squirrel.Dataset 

71 

72{path_prefix} 

73 

74# Data sources to be added (LocalData, FDSNSource, CatalogSource, ...) 

75sources: 

76- !squirrel.LocalData # This data source is for local files. 

77 

78 # These paths are scanned for waveforms, stations, events. 

79 paths: 

80 - 'catalogs/events.txt' 

81 - 'meta/stations.xml' 

82 - 'data/waveforms' 

83 

84 # Select file format or 'detect' for autodetection. 

85 format: 'detect' 

86'''.format(path_prefix=path_prefix).strip()}, 

87 

88 'geofon.dataset': { 

89 'description': 

90 'Everything available through GEOFON.', 

91 'yaml': _template_online_dataset( 

92 site='geofon', 

93 ), 

94 }, 

95 

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 }, 

104 

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 }, 

113 

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} 

123 

124names = sorted(templates.keys()) 

125 

126template_listing = '\n'.join( 

127 '%-30s %s' % ( 

128 '%s:' % name, 

129 templates[name]['description']) for name in templates) 

130 

131 

132def make_subparser(subparsers): 

133 return subparsers.add_parser( 

134 'template', 

135 help=headline, 

136 description=headline + ''' 

137 

138Available configuration SNIPPETs: 

139 

140{} 

141'''.format(template_listing).strip()) 

142 

143 

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.') 

151 

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.') 

159 

160 parser.add_argument( 

161 '--write', '-w', 

162 action='store_true', 

163 help='Write to file.') 

164 

165 

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) 

172 

173 return '\n'.join(out) 

174 

175 

176def brief(s): 

177 return dump(load_string(s)) 

178 

179 

180def run(parser, args): 

181 

182 if not args.name: 

183 print(template_listing) 

184 

185 else: 

186 func = { 

187 'brief': brief, 

188 'commented': lambda s: s, 

189 'normal': decomment}[args.format] 

190 

191 s = func(templates[args.name]['yaml']) 

192 

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') 

199 

200 logger.info('File written: %s' % path) 

201 

202 except FileExistsError: 

203 raise ToolError('File exists: %s' % path) 

204 else: 

205 print(s)