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 .. import common 

15 

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

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 # FDSN query arguments to make metadata queries. 

48 # See http://www.fdsn.org/webservices/fdsnws-station-1.1.pdf 

49 # Time span arguments should not be added here, because they are handled 

50 # automatically by Squirrel. 

51 query_args: {qargs} 

52'''.format(path_prefix=path_prefix, **kwargs).strip() 

53 

54 

55templates = { 

56 'local.dataset.yaml': { 

57 'description': 

58 'A typical collection of local files.', 

59 'yaml': ''' 

60--- !squirrel.Dataset 

61 

62{path_prefix} 

63 

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

65sources: 

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

67 

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

69 paths: 

70 - 'catalogs/events.txt' 

71 - 'meta/stations.xml' 

72 - 'data/waveforms' 

73 

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

75 format: 'detect' 

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

77 

78 'geofon.dataset.yaml': { 

79 'description': 

80 'Everything available through GEOFON.', 

81 'yaml': _template_online_dataset( 

82 site='geofon', 

83 ), 

84 }, 

85 

86 'iris-seis.dataset.yaml': { 

87 'description': 

88 'All high- and low-gain seismometer channels at IRIS.', 

89 'yaml': _template_online_dataset( 

90 site='iris', 

91 channel='?H?,?L?', 

92 ), 

93 }, 

94 

95 'iris-seis-bb.dataset.yaml': { 

96 'description': 

97 'All broad-band high-gain seismometer channels at IRIS.', 

98 'yaml': _template_online_dataset( 

99 site='iris', 

100 channel='VH?,LH?,BH?,HH?', 

101 ), 

102 }, 

103 

104 'bgr-gr-bfo.dataset.yaml': { 

105 'description': 'Station GR.BFO from BGR.', 

106 'yaml': _template_online_dataset( 

107 site='bgr', 

108 network='GR', 

109 station='BFO', 

110 ), 

111 }, 

112} 

113 

114names = sorted(templates.keys()) 

115 

116template_listing = '\n'.join( 

117 '%-30s %s' % ( 

118 '%s:' % name, 

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

120 

121 

122def setup_subcommand(subparsers): 

123 return common.add_parser( 

124 subparsers, 'template', 

125 help='Print configuration snippets.', 

126 description=''' 

127Available configuration SNIPPETs: 

128 

129{} 

130'''.format(template_listing).strip()) 

131 

132 

133def setup(parser): 

134 parser.add_argument( 

135 'name', 

136 choices=names, 

137 nargs='?', 

138 metavar='SNIPPET', 

139 help='Name of template snippet to print.') 

140 

141 parser.add_argument( 

142 '--format', '-f', 

143 choices=['commented', 'normal', 'brief'], 

144 default='commented', 

145 metavar='FMT', 

146 help='Set verbosity level of output YAML. Choices: %(choices)s. ' 

147 'Default: %(default)s.') 

148 

149 parser.add_argument( 

150 '--write', '-w', 

151 action='store_true', 

152 help='Write to file.') 

153 

154 

155def decomment(s): 

156 out = [] 

157 for line in s.splitlines(): 

158 line = re.sub(r'#.+', '', line) 

159 if line.strip(): 

160 out.append(line) 

161 

162 return '\n'.join(out) 

163 

164 

165def brief(s): 

166 return dump(load_string(s)) 

167 

168 

169def call(parser, args): 

170 

171 if not args.name: 

172 print(template_listing) 

173 

174 else: 

175 func = { 

176 'brief': brief, 

177 'commented': lambda s: s, 

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

179 

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

181 

182 if args.write: 

183 try: 

184 with open(args.name, 'x') as f: 

185 f.write(s) 

186 f.write('\n') 

187 

188 logger.info('File written: %s' % args.name) 

189 

190 except FileExistsError: 

191 raise ToolError('File exists: %s' % args.name) 

192 else: 

193 print(s)