1# http://pyrocko.org - GPLv3 

2# 

3# The Pyrocko Developers, 21st Century 

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

5 

6import re 

7import logging 

8 

9from pyrocko.guts import load_string, dump 

10 

11from pyrocko.squirrel.error import ToolError 

12from ..common import dq, ldq 

13 

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

15 

16headline = 'Print configuration snippets.' 

17 

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

25 

26 

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

33 

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

35 return ''' 

36--- !squirrel.Dataset 

37 

38{path_prefix} 

39 

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

41sources: 

42- !squirrel.FDSNSource 

43 

44 # URL or alias of FDSN site. 

45 site: {site} 

46 

47 # Uncomment to let metadata expire in 10 days: 

48 #expires: 10d 

49 

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 

55 

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

62 

63 

64templates = { 

65 'local.dataset': { 

66 'description': 

67 'A typical collection of local files.', 

68 'yaml': ''' 

69--- !squirrel.Dataset 

70 

71{path_prefix} 

72 

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

74sources: 

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

76 

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

78 paths: 

79 - 'catalogs/events.txt' 

80 - 'meta/stations.xml' 

81 - 'data/waveforms' 

82 

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

84 format: 'detect' 

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

86 

87 'geofon.dataset': { 

88 'description': 

89 'Everything available through GEOFON.', 

90 'yaml': _template_online_dataset( 

91 site='geofon', 

92 ), 

93 }, 

94 

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

103 

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

112 

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

121 

122 'gcmt-m7.dataset': { 

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

124 'yaml': ''' 

125--- !squirrel.Dataset 

126 

127{path_prefix} 

128 

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} 

138 

139names = sorted(templates.keys()) 

140 

141template_listing = '\n'.join( 

142 '%-30s %s' % ( 

143 '%s:' % name, 

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

145 

146 

147def make_subparser(subparsers): 

148 return subparsers.add_parser( 

149 'template', 

150 help=headline, 

151 description=headline + ''' 

152 

153Available SNIPPETs 

154 

155{} 

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

157 

158 

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

166 

167 format_default = 'commented' 

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

169 

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

177 

178 parser.add_argument( 

179 '--write', '-w', 

180 action='store_true', 

181 help='Write to file.') 

182 

183 

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) 

190 

191 return '\n'.join(out) 

192 

193 

194def brief(s): 

195 return dump(load_string(s)) 

196 

197 

198def run(parser, args): 

199 

200 if not args.name: 

201 print(template_listing) 

202 

203 else: 

204 func = { 

205 'brief': brief, 

206 'commented': lambda s: s, 

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

208 

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

210 

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

217 

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

219 

220 except FileExistsError: 

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

222 else: 

223 print(s)