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 

14from ..common import dq, ldq 

15 

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

17 

18headline = 'Print configuration snippets.' 

19 

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

27 

28 

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

35 

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

37 return ''' 

38--- !squirrel.Dataset 

39 

40{path_prefix} 

41 

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

43sources: 

44- !squirrel.FDSNSource 

45 

46 # URL or alias of FDSN site. 

47 site: {site} 

48 

49 # Uncomment to let metadata expire in 10 days: 

50 #expires: 10d 

51 

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 

57 

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

64 

65 

66templates = { 

67 'local.dataset': { 

68 'description': 

69 'A typical collection of local files.', 

70 'yaml': ''' 

71--- !squirrel.Dataset 

72 

73{path_prefix} 

74 

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

76sources: 

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

78 

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

80 paths: 

81 - 'catalogs/events.txt' 

82 - 'meta/stations.xml' 

83 - 'data/waveforms' 

84 

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

86 format: 'detect' 

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

88 

89 'geofon.dataset': { 

90 'description': 

91 'Everything available through GEOFON.', 

92 'yaml': _template_online_dataset( 

93 site='geofon', 

94 ), 

95 }, 

96 

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

105 

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

114 

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

123 

124 'gcmt-m7.dataset': { 

125 'description': 'Global-CMT events with Mw >= 7.0.', 

126 'yaml': ''' 

127--- !squirrel.Dataset 

128 

129{path_prefix} 

130 

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} 

140 

141names = sorted(templates.keys()) 

142 

143template_listing = '\n'.join( 

144 '%-30s %s' % ( 

145 '%s:' % name, 

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

147 

148 

149def make_subparser(subparsers): 

150 return subparsers.add_parser( 

151 'template', 

152 help=headline, 

153 description=headline + ''' 

154 

155Available SNIPPETs 

156 

157{} 

158'''.format('\n'.join(' ' + line for line in template_listing.splitlines()))) 

159 

160 

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

168 

169 format_default = 'commented' 

170 format_choices = ['commented', 'normal', 'brief'] 

171 

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

179 

180 parser.add_argument( 

181 '--write', '-w', 

182 action='store_true', 

183 help='Write to file.') 

184 

185 

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) 

192 

193 return '\n'.join(out) 

194 

195 

196def brief(s): 

197 return dump(load_string(s)) 

198 

199 

200def run(parser, args): 

201 

202 if not args.name: 

203 print(template_listing) 

204 

205 else: 

206 func = { 

207 'brief': brief, 

208 'commented': lambda s: s, 

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

210 

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

212 

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

219 

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

221 

222 except FileExistsError: 

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

224 else: 

225 print(s)