1# http://pyrocko.org - GPLv3 

2# 

3# The Pyrocko Developers, 21st Century 

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

5from __future__ import absolute_import 

6 

7import os 

8import sys 

9from optparse import OptionParser, OptionGroup 

10from collections import OrderedDict 

11 

12from .report_main import GreensFunctionTest as gftest 

13from .report_main import FilterFrequencyError as gft_ffe 

14from .report_main import FomostoReportError 

15 

16spstr = '\n' + ' '*20 

17subcmds_desc = OrderedDict([ 

18 ('single', 'create pdf of a single store'), 

19 ('double', 'create pdf of two stores'), 

20 ('sstandard', 'create a single store pdf with standard setup'), 

21 ('dstandard', 'create a double store pdf with standard setup'), 

22 ('slow', 'create a single store pdf, filtering the' + 

23 spstr + 'traces with a low frequency'), 

24 ('dlow', 'create a double store pdf, filtering the' + 

25 spstr + 'traces with a low frequency'), 

26 ('shigh', 'create a single store pdf, filtering the' + 

27 spstr + 'traces with a low frequency'), 

28 ('dhigh', 'create a single store pdf, filtering the' + 

29 spstr + 'traces with a low frequency'), 

30 ('slowband', 'create a single store pdf with a low' + 

31 spstr + 'frequency band filter'), 

32 ('dlowband', 'create a double store pdf with a low' + 

33 spstr + 'frequency band filter'), 

34 ('shighband', 'create a single store pdf with a high' + 

35 spstr + 'frequency band filter'), 

36 ('dhighband', 'create a double store pdf with a high' + 

37 spstr + 'frequency band filter'), 

38 ('snone', 'create a single store pdf with unfiltered' 

39 ' traces'), 

40 ('dnone', 'create a double store pdf with unfiltered' 

41 ' traces')]) 

42 

43subcmds_uses = { 

44 'single': 'single <input config file> [options]', 

45 'double': 'double <input config file> [options]', 

46 'sstandard': 'sstandard <store dir> [options]', 

47 'dstandard': 'dstandard <store dir1> <store dir2>' 

48 ' <sensor distance minimum>' 

49 ' <sensor distance maximum> [options]', 

50 'slow': 'slow <store dir> [options]', 

51 'dlow': 'dlow <store dir1> <store dir2>' 

52 ' <sensor distance minimum>' 

53 ' <sensor distance maximum> [options]', 

54 'slowband': 'slowband <store dir> [options]', 

55 'dlowband': 'dlowband <store dir1> <store dir2>' 

56 ' <sensor distance minimum>' 

57 ' <sensor distance maximum> [options]', 

58 'shighband': 'shighband <store dir> [options]', 

59 'dhighband': 'dhighband <store dir1> <store dir2>' 

60 ' <sensor distance minimum>' 

61 ' <sensor distance maximum> [options]', 

62 'shigh': 'shigh <store dir> [options]', 

63 'dhigh': 'dhigh <store dir1> <store dir2>' 

64 ' <sensor distance minimum>' 

65 ' <sensor distance maximum> [options]', 

66 'snone': 'snone <store dir> [options]', 

67 'dnone': 'dnone <store dir1> <store dir2>' 

68 ' <sensor distance minimum>' 

69 ' <sensor distance maximum> [options]'} 

70 

71 

72def dict_to_string(dic): 

73 st = 4 

74 st2 = 20 

75 s = '' 

76 for k, v in dic.items(): 

77 s += '\n{0}{1}{2}{3}'.format(' '*st, k, ' '*(st2 - st - len(k)), v) 

78 return s 

79 

80 

81def add_common_options(parser): 

82 parser.add_option('--show_defaults', '-d', action='store_false', 

83 help='Show the default values of command options.' 

84 ' Must be typed before help option.') 

85 parser.add_option('--plot_velocity', '-v', action='store_true', 

86 help='Plot the velocity traces also.', default=False) 

87 parser.add_option('--output-format', 

88 help='The format of the report: pdf or html', 

89 choices=['pdf', 'html'], default='pdf') 

90 parser.add_option('--pdf_dir', '-p', 

91 help='The directory where the pdf/html will be saved to.' 

92 ' Default is the HOME directory.', 

93 default=None) 

94 parser.add_option('--output', '-o', 

95 help='The full path and name to save the' 

96 ' resulting configuration file.', 

97 default=None) 

98 parser.add_option('--report_only', '-r', dest='plot_everything', 

99 action='store_false', default=True, 

100 help='Do not plot the trace graphs') 

101 

102 

103def add_sensor_options(parser): 

104 grp = OptionGroup(parser, 'Seismic sensor distance options') 

105 grp.add_option('--distance_min', '-n', type=float, default=None, 

106 help="The minimum distance to place sensors. Value of" 

107 " 'None' will use store minimum.") 

108 grp.add_option('--distance_max', '-x', type=float, default=None, 

109 help="The maximum distance to place sensors. Value of" 

110 " 'None' will use store maximum.") 

111 grp.add_option('--sensor_count', '-c', type=int, default=50, 

112 help="The number of sensors to use.") 

113 parser.add_option_group(grp) 

114 

115 

116def add_source_options(parser): 

117 grp = OptionGroup(parser, 'Seismic source options') 

118 grp.add_option('--depth', 

119 dest='source_depth', 

120 type=float, 

121 help="The depth of the source. Value of 'None' will place" 

122 " source at middle depth of allowed values.", 

123 default=None) 

124 parser.add_option_group(grp) 

125 

126 

127def add_filter_options(parser): 

128 grp = OptionGroup(parser, 'Trace frequency filter options') 

129 grp.add_option('--lowpass', 

130 dest='lowpass_frequency', 

131 type=float, 

132 help='The value of the lowpass filter applied to traces.', 

133 default=None) 

134 grp.add_option('--lowpass_rel', 

135 dest='rel_lowpass_frequency', 

136 type=float, 

137 help='''The percentage of the store's sampling rate''' 

138 ' to be used as the lowpass filter.', 

139 default=None) 

140 grp.add_option('--highpass', 

141 dest='highpass_frequency', 

142 type=float, 

143 help='The value of the highpass filter applied to traces.', 

144 default=None) 

145 grp.add_option('--highpass_rel', 

146 dest='rel_highpass_frequency', 

147 type=float, 

148 help='''The percentage of the store's samping rate''' 

149 ' to be used as the lowpass filter.', 

150 default=None) 

151 parser.add_option_group(grp) 

152 

153 

154def add_double_options(parser): 

155 grp = OptionGroup(parser, 'Double store plotting options') 

156 grp.add_option('--together', '-t', dest='together', 

157 action='store_true', default=True, 

158 help='Plot both stores on same axes.') 

159 grp.add_option('--separate', '-s', dest='together', 

160 action='store_false', 

161 help='Plot stores next to each other.') 

162 parser.add_option_group(grp) 

163 

164 

165def cl_parse(command, args, setup=None): 

166 usage = '{0} {1}'.format(program_name, subcmds_uses[command]) 

167 desc = ' '.join(subcmds_desc[command].split()) 

168 parser = OptionParser(usage=usage, description=desc) 

169 add_common_options(parser) 

170 if setup: 

171 setup(parser) 

172 

173 if args and args[0] in ('-d', '--show_defaults'): 

174 for opt in parser.option_list: 

175 if opt.default == ('NO', 'DEFAULT'): 

176 continue 

177 opt.help += (' ' if opt.help else '') + '[default: %default]' 

178 for grp in parser.option_groups: 

179 for opt in grp.option_list: 

180 if opt.default == ('NO', 'DEFAULT'): 

181 continue 

182 opt.help += (' ' if opt.help else '') + '[default: %default]' 

183 opts, args = parser.parse_args(args) 

184 opts = vars(opts) 

185 if 'show_defaults' in opts: 

186 del opts['show_defaults'] 

187 return parser, opts, args 

188 

189 

190def verify_arguements(command, allowed, args): 

191 if len(args) != allowed: 

192 raise TypeError('{0}() takes {1} arguements ({2} given)'.format( 

193 command, allowed, len(args))) 

194 

195 dir1 = args.pop(0) 

196 if not os.path.exists(dir1): 

197 raise OSError('Path does not exist: {0}'.format(dir1)) 

198 

199 if allowed == 1: 

200 return dir1 

201 

202 dir2 = args.pop(0) 

203 if not os.path.exists(dir2): 

204 raise OSError('Path does not exist: {0}'.format(dir1)) 

205 

206 if args: 

207 sen_min = float(args.pop(0)) 

208 sen_max = float(args.pop(0)) 

209 return dir1, dir2, sen_min, sen_max 

210 else: 

211 return dir1, dir2 

212 

213 

214def verify_options(command, **opts): 

215 lpf = None 

216 hpf = None 

217 rlpf = None 

218 rhpf = None 

219 

220 tstr = 'lowpass_frequency' 

221 if tstr in opts: 

222 lpf = opts[tstr] 

223 tstr = 'highpass_frequency' 

224 if tstr in opts: 

225 hpf = opts[tstr] 

226 tstr = 'rel_lowpass_frequency' 

227 if tstr in opts: 

228 rlpf = opts[tstr] 

229 tstr = 'rel_highpass_frequency' 

230 if tstr in opts: 

231 rhpf = opts[tstr] 

232 

233 if lpf and rlpf: 

234 raise gft_ffe('lowpass') 

235 if hpf and rhpf: 

236 raise gft_ffe('highpass') 

237 

238 

239def command_single(command, args): 

240 def setup(parser): 

241 parser.set_defaults(plot_velocity=None) 

242 parser.set_defaults(plot_everything=None) 

243 

244 parser, opts, args = cl_parse(command, args, setup) 

245 filename = verify_arguements('single', 1, args) 

246 out_filename = opts.pop('output') 

247 gft = gftest.createDocumentFromFile(filename, **opts) 

248 if out_filename is not None: 

249 return gft, out_filename 

250 

251 

252def command_sstandard(command, args): 

253 def setup(parser): 

254 add_source_options(parser) 

255 add_sensor_options(parser) 

256 

257 parser, opts, args = cl_parse(command, args, setup) 

258 st_dir = verify_arguements('sstandard', 1, args) 

259 out_filename = opts.pop('output') 

260 gft = gftest.runStandardCheck(st_dir, **opts) 

261 if out_filename is not None: 

262 return gft, out_filename 

263 

264 

265def command_slow(command, args): 

266 def setup(parser): 

267 add_source_options(parser) 

268 add_sensor_options(parser) 

269 add_filter_options(parser) 

270 parser.remove_option('--highpass') 

271 parser.remove_option('--highpass_rel') 

272 parser.set_defaults(rel_lowpass_frequency=0.25) 

273 

274 parser, opts, args = cl_parse(command, args, setup=setup) 

275 if opts['lowpass_frequency'] is not None: 

276 opts['rel_lowpass_frequency'] = None 

277 st_dir = verify_arguements('slow', 1, args) 

278 out_filename = opts.pop('output') 

279 gft = gftest.runStandardCheck(st_dir, **opts) 

280 if out_filename is not None: 

281 return gft, out_filename 

282 

283 

284def command_shigh(command, args): 

285 def setup(parser): 

286 add_source_options(parser) 

287 add_sensor_options(parser) 

288 add_filter_options(parser) 

289 parser.remove_option('--lowpass') 

290 parser.remove_option('--lowpass_rel') 

291 parser.set_defaults(rel_highpass_frequency=0.25) 

292 

293 parser, opts, args = cl_parse(command, args, setup=setup) 

294 if opts['highpass_frequency'] is not None: 

295 opts['rel_highpass_frequency'] = None 

296 st_dir = verify_arguements('shigh', 1, args) 

297 out_filename = opts.pop('output') 

298 gft = gftest.runStandardCheck(st_dir, **opts) 

299 if out_filename is not None: 

300 return gft, out_filename 

301 

302 

303def command_slowband(command, args): 

304 def setup(parser): 

305 add_source_options(parser) 

306 add_sensor_options(parser) 

307 add_filter_options(parser) 

308 parser.set_defaults(lowpass_frequency=0.0018) 

309 parser.set_defaults(highpass_frequency=0.004) 

310 

311 parser, opts, args = cl_parse(command, args, setup=setup) 

312 st_dir = verify_arguements('slowband', 1, args) 

313 verify_options('slowband', **opts) 

314 out_filename = opts.pop('output') 

315 gft = gftest.runStandardCheck(st_dir, **opts) 

316 if out_filename is not None: 

317 return gft, out_filename 

318 

319 

320def command_shighband(command, args): 

321 def setup(parser): 

322 add_source_options(parser) 

323 add_sensor_options(parser) 

324 add_filter_options(parser) 

325 parser.set_defaults(rel_lowpass_frequency=0.125) 

326 parser.set_defaults(rel_highpass_frequency=0.25) 

327 

328 parser, opts, args = cl_parse(command, args, setup=setup) 

329 st_dir = verify_arguements('shighband', 1, args) 

330 verify_options('shighband', **opts) 

331 out_filename = opts.pop('output') 

332 gft = gftest.runStandardCheck(st_dir, **opts) 

333 if out_filename is not None: 

334 return gft, out_filename 

335 

336 

337def command_snone(command, args): 

338 def setup(parser): 

339 add_source_options(parser) 

340 add_sensor_options(parser) 

341 

342 parser, opts, args = cl_parse(command, args, setup=setup) 

343 st_dir = verify_arguements('snone', 1, args) 

344 opts['rel_lowpass_frequency'] = None 

345 opts['rel_highpass_frequency'] = None 

346 out_filename = opts.pop('output') 

347 gft = gftest.runStandardCheck(st_dir, **opts) 

348 if out_filename is not None: 

349 return gft, out_filename 

350 

351 

352def command_double(command, args): 

353 def setup(parser): 

354 add_double_options(parser) 

355 parser.set_defaults(plot_velocity=None) 

356 parser.set_defaults(plot_everything=None) 

357 

358 parser, opts, args = cl_parse(command, args, setup=setup) 

359 filename = verify_arguements('double', 1, args) 

360 verify_options('double', **opts) 

361 out_filename = opts.pop('output') 

362 gfts = gftest.createDocumentFromFile(filename, 2, **opts) 

363 if out_filename is not None: 

364 return gfts, out_filename 

365 

366 

367def command_dstandard(command, args): 

368 def setup(parser): 

369 add_source_options(parser) 

370 add_double_options(parser) 

371 

372 parser, opts, args = cl_parse(command, args, setup=setup) 

373 dir1, dir2, smin, smax = verify_arguements('dstandard', 4, args) 

374 out_filename = opts.pop('output') 

375 gfts = gftest.runComparissonStandardCheck(dir1, dir2, smin, smax, **opts) 

376 if out_filename is not None: 

377 return gfts, out_filename 

378 

379 

380def command_dlow(command, args): 

381 def setup(parser): 

382 add_source_options(parser) 

383 add_double_options(parser) 

384 add_filter_options(parser) 

385 parser.remove_option('--highpass') 

386 parser.remove_option('--highpass_rel') 

387 parser.set_defaults(rel_lowpass_frequency=0.25) 

388 

389 parser, opts, args = cl_parse(command, args, setup=setup) 

390 if opts['lowpass_frequency'] is not None: 

391 opts['rel_lowpass_frequency'] = None 

392 dir1, dir2, smin, smax = verify_arguements('dlow', 4, args) 

393 opts['rel_highpass_frequency'] = None 

394 out_filename = opts.pop('output') 

395 gfts = gftest.runComparissonStandardCheck(dir1, dir2, smin, smax, **opts) 

396 if out_filename is not None: 

397 return gfts, out_filename 

398 

399 

400def command_dhigh(command, args): 

401 def setup(parser): 

402 add_source_options(parser) 

403 add_double_options(parser) 

404 add_filter_options(parser) 

405 parser.remove_option('--lowpass') 

406 parser.remove_option('--lowpass_rel') 

407 parser.set_defaults(rel_highpass_frequency=0.25) 

408 

409 parser, opts, args = cl_parse(command, args, setup=setup) 

410 if opts['highpass_frequency'] is not None: 

411 opts['rel_highpass_frequency'] = None 

412 dir1, dir2, smin, smax = verify_arguements('dhigh', 4, args) 

413 opts['rel_lowpass_frequency'] = None 

414 out_filename = opts.pop('output') 

415 gfts = gftest.runComparissonStandardCheck(dir1, dir2, smin, smax, **opts) 

416 if out_filename is not None: 

417 return gfts, out_filename 

418 

419 

420def command_dlowband(command, args): 

421 def setup(parser): 

422 add_source_options(parser) 

423 add_double_options(parser) 

424 add_filter_options(parser) 

425 parser.set_defaults(lowpass_frequency=0.0018) 

426 parser.set_defaults(highpass_frequency=0.004) 

427 

428 parser, opts, args = cl_parse(command, args, setup=setup) 

429 dir1, dir2, smin, smax = verify_arguements('dlowband', 4, args) 

430 verify_options('dlowband', **opts) 

431 out_filename = opts.pop('output') 

432 gfts = gftest.runComparissonStandardCheck(dir1, dir2, smin, smax, **opts) 

433 if out_filename is not None: 

434 return gfts, out_filename 

435 

436 

437def command_dhighband(command, args): 

438 def setup(parser): 

439 add_source_options(parser) 

440 add_double_options(parser) 

441 add_filter_options(parser) 

442 parser.set_defaults(rel_lowpass_frequency=0.125) 

443 parser.set_defaults(rel_highpass_frequency=0.25) 

444 

445 parser, opts, args = cl_parse(command, args, setup=setup) 

446 dir1, dir2, smin, smax = verify_arguements('dhighband', 4, args) 

447 verify_options('dhighband', **opts) 

448 out_filename = opts.pop('output') 

449 gfts = gftest.runComparissonStandardCheck(dir1, dir2, smin, smax, **opts) 

450 if out_filename is not None: 

451 return gfts, out_filename 

452 

453 

454def command_dnone(command, args): 

455 def setup(parser): 

456 add_source_options(parser) 

457 add_double_options(parser) 

458 

459 parser, opts, args = cl_parse(command, args, setup=setup) 

460 dir1, dir2, smin, smax = verify_arguements('dnone', 4, args) 

461 opts['rel_lowpass_frequency'] = None 

462 opts['rel_highpass_frequency'] = None 

463 out_filename = opts.pop('output') 

464 gfts = gftest.runComparissonStandardCheck(dir1, dir2, smin, smax, **opts) 

465 if out_filename is not None: 

466 return gfts, out_filename 

467 

468 

469program_name = 'fomosto report' 

470usage = 'Create a pdf of displacment and velocity traces, max. amplitude of' \ 

471 ' traces and' \ 

472 ' displacment spectra for Green\'s Function stores.\n\n' \ 

473 'Usage: {0} <subcommand> <arguments> ... [options]\n\nSubcommands:\n' \ 

474 '{1}\n\nTo get further help and a list of available options for any' \ 

475 ' subcommand run:\n\n{2}{0} <subcommand> --help\n\n'. \ 

476 format(program_name, dict_to_string(subcmds_desc), ' '*4) 

477 

478 

479def run_program(args): 

480 if len(args) < 1: 

481 sys.exit(usage) 

482 

483 command = args.pop(0) 

484 if command in ('--help', '-h', 'help'): 

485 sys.exit(usage) 

486 

487 if command in ('--multiple', '-m'): 

488 glbs = globals() 

489 cmds = [] 

490 while args and args[0] in subcmds_desc: 

491 cmds.append(args.pop(0)) 

492 for command in cmds: 

493 glbs['command_' + command](args) 

494 sys.exit() 

495 

496 if command not in subcmds_desc: 

497 sys.exit('{0}: error: no such subcommand: {1}'. 

498 format(program_name, command)) 

499 

500 if len(args) == 0 or (len(args) == 1 and 

501 args[0] in ('-d', '--show_defaults')): 

502 args.append('--help') 

503 

504 try: 

505 lst = globals()['command_' + command](command, args) 

506 if lst is not None: 

507 gfts = lst[0] 

508 with open(lst[-1], 'w') as f: 

509 if isinstance(gfts, gftest): 

510 f.write(gfts.dump()) 

511 else: 

512 for i in lst[0]: 

513 f.write(i.dump()) 

514 

515 except FomostoReportError as e: 

516 sys.exit(str(e)) 

517 

518 

519if __name__ == '__main__': 

520 run_program(sys.argv)