1# http://pyrocko.org - GPLv3 

2# 

3# The Pyrocko Developers, 21st Century 

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

5 

6import os 

7import sys 

8from optparse import OptionParser, OptionGroup 

9from collections import OrderedDict 

10 

11from .report_main import GreensFunctionTest as gftest 

12from .report_main import FilterFrequencyError as gft_ffe 

13from .report_main import FomostoReportError 

14 

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

16subcmds_desc = OrderedDict([ 

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

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

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

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

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

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

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

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

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

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

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

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

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

30 spstr + 'frequency band filter'), 

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

32 spstr + 'frequency band filter'), 

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

34 spstr + 'frequency band filter'), 

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

36 spstr + 'frequency band filter'), 

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

38 ' traces'), 

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

40 ' traces')]) 

41 

42subcmds_uses = { 

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

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

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

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

47 ' <sensor distance minimum>' 

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

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

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

51 ' <sensor distance minimum>' 

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

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

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

55 ' <sensor distance minimum>' 

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

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

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

59 ' <sensor distance minimum>' 

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

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

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

63 ' <sensor distance minimum>' 

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

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

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

67 ' <sensor distance minimum>' 

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

69 

70 

71def dict_to_string(dic): 

72 st = 4 

73 st2 = 20 

74 s = '' 

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

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

77 return s 

78 

79 

80def add_common_options(parser): 

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

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

83 ' Must be typed before help option.') 

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

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

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

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

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

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

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

91 ' Default is the HOME directory.', 

92 default=None) 

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

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

95 ' resulting configuration file.', 

96 default=None) 

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

98 action='store_false', default=True, 

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

100 

101 

102def add_sensor_options(parser): 

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

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

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

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

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

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

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

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

111 help='The number of sensors to use.') 

112 parser.add_option_group(grp) 

113 

114 

115def add_source_options(parser): 

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

117 grp.add_option('--depth', 

118 dest='source_depth', 

119 type=float, 

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

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

122 default=None) 

123 parser.add_option_group(grp) 

124 

125 

126def add_filter_options(parser): 

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

128 grp.add_option('--lowpass', 

129 dest='lowpass_frequency', 

130 type=float, 

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

132 default=None) 

133 grp.add_option('--lowpass_rel', 

134 dest='rel_lowpass_frequency', 

135 type=float, 

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

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

138 default=None) 

139 grp.add_option('--highpass', 

140 dest='highpass_frequency', 

141 type=float, 

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

143 default=None) 

144 grp.add_option('--highpass_rel', 

145 dest='rel_highpass_frequency', 

146 type=float, 

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

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

149 default=None) 

150 parser.add_option_group(grp) 

151 

152 

153def add_double_options(parser): 

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

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

156 action='store_true', default=True, 

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

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

159 action='store_false', 

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

161 parser.add_option_group(grp) 

162 

163 

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

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

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

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

168 add_common_options(parser) 

169 if setup: 

170 setup(parser) 

171 

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

173 for opt in parser.option_list: 

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

175 continue 

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

177 for grp in parser.option_groups: 

178 for opt in grp.option_list: 

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

180 continue 

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

182 opts, args = parser.parse_args(args) 

183 opts = vars(opts) 

184 if 'show_defaults' in opts: 

185 del opts['show_defaults'] 

186 return parser, opts, args 

187 

188 

189def verify_arguements(command, allowed, args): 

190 if len(args) != allowed: 

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

192 command, allowed, len(args))) 

193 

194 dir1 = args.pop(0) 

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

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

197 

198 if allowed == 1: 

199 return dir1 

200 

201 dir2 = args.pop(0) 

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

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

204 

205 if args: 

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

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

208 return dir1, dir2, sen_min, sen_max 

209 else: 

210 return dir1, dir2 

211 

212 

213def verify_options(command, **opts): 

214 lpf = None 

215 hpf = None 

216 rlpf = None 

217 rhpf = None 

218 

219 tstr = 'lowpass_frequency' 

220 if tstr in opts: 

221 lpf = opts[tstr] 

222 tstr = 'highpass_frequency' 

223 if tstr in opts: 

224 hpf = opts[tstr] 

225 tstr = 'rel_lowpass_frequency' 

226 if tstr in opts: 

227 rlpf = opts[tstr] 

228 tstr = 'rel_highpass_frequency' 

229 if tstr in opts: 

230 rhpf = opts[tstr] 

231 

232 if lpf and rlpf: 

233 raise gft_ffe('lowpass') 

234 if hpf and rhpf: 

235 raise gft_ffe('highpass') 

236 

237 

238def command_single(command, args): 

239 def setup(parser): 

240 parser.set_defaults(plot_velocity=None) 

241 parser.set_defaults(plot_everything=None) 

242 

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

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

245 out_filename = opts.pop('output') 

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

247 if out_filename is not None: 

248 return gft, out_filename 

249 

250 

251def command_sstandard(command, args): 

252 def setup(parser): 

253 add_source_options(parser) 

254 add_sensor_options(parser) 

255 

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

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

258 out_filename = opts.pop('output') 

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

260 if out_filename is not None: 

261 return gft, out_filename 

262 

263 

264def command_slow(command, args): 

265 def setup(parser): 

266 add_source_options(parser) 

267 add_sensor_options(parser) 

268 add_filter_options(parser) 

269 parser.remove_option('--highpass') 

270 parser.remove_option('--highpass_rel') 

271 parser.set_defaults(rel_lowpass_frequency=0.25) 

272 

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

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

275 opts['rel_lowpass_frequency'] = None 

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

277 out_filename = opts.pop('output') 

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

279 if out_filename is not None: 

280 return gft, out_filename 

281 

282 

283def command_shigh(command, args): 

284 def setup(parser): 

285 add_source_options(parser) 

286 add_sensor_options(parser) 

287 add_filter_options(parser) 

288 parser.remove_option('--lowpass') 

289 parser.remove_option('--lowpass_rel') 

290 parser.set_defaults(rel_highpass_frequency=0.25) 

291 

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

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

294 opts['rel_highpass_frequency'] = None 

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

296 out_filename = opts.pop('output') 

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

298 if out_filename is not None: 

299 return gft, out_filename 

300 

301 

302def command_slowband(command, args): 

303 def setup(parser): 

304 add_source_options(parser) 

305 add_sensor_options(parser) 

306 add_filter_options(parser) 

307 parser.set_defaults(lowpass_frequency=0.0018) 

308 parser.set_defaults(highpass_frequency=0.004) 

309 

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

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

312 verify_options('slowband', **opts) 

313 out_filename = opts.pop('output') 

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

315 if out_filename is not None: 

316 return gft, out_filename 

317 

318 

319def command_shighband(command, args): 

320 def setup(parser): 

321 add_source_options(parser) 

322 add_sensor_options(parser) 

323 add_filter_options(parser) 

324 parser.set_defaults(rel_lowpass_frequency=0.125) 

325 parser.set_defaults(rel_highpass_frequency=0.25) 

326 

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

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

329 verify_options('shighband', **opts) 

330 out_filename = opts.pop('output') 

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

332 if out_filename is not None: 

333 return gft, out_filename 

334 

335 

336def command_snone(command, args): 

337 def setup(parser): 

338 add_source_options(parser) 

339 add_sensor_options(parser) 

340 

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

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

343 opts['rel_lowpass_frequency'] = None 

344 opts['rel_highpass_frequency'] = None 

345 out_filename = opts.pop('output') 

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

347 if out_filename is not None: 

348 return gft, out_filename 

349 

350 

351def command_double(command, args): 

352 def setup(parser): 

353 add_double_options(parser) 

354 parser.set_defaults(plot_velocity=None) 

355 parser.set_defaults(plot_everything=None) 

356 

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

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

359 verify_options('double', **opts) 

360 out_filename = opts.pop('output') 

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

362 if out_filename is not None: 

363 return gfts, out_filename 

364 

365 

366def command_dstandard(command, args): 

367 def setup(parser): 

368 add_source_options(parser) 

369 add_double_options(parser) 

370 

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

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

373 out_filename = opts.pop('output') 

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

375 if out_filename is not None: 

376 return gfts, out_filename 

377 

378 

379def command_dlow(command, args): 

380 def setup(parser): 

381 add_source_options(parser) 

382 add_double_options(parser) 

383 add_filter_options(parser) 

384 parser.remove_option('--highpass') 

385 parser.remove_option('--highpass_rel') 

386 parser.set_defaults(rel_lowpass_frequency=0.25) 

387 

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

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

390 opts['rel_lowpass_frequency'] = None 

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

392 opts['rel_highpass_frequency'] = None 

393 out_filename = opts.pop('output') 

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

395 if out_filename is not None: 

396 return gfts, out_filename 

397 

398 

399def command_dhigh(command, args): 

400 def setup(parser): 

401 add_source_options(parser) 

402 add_double_options(parser) 

403 add_filter_options(parser) 

404 parser.remove_option('--lowpass') 

405 parser.remove_option('--lowpass_rel') 

406 parser.set_defaults(rel_highpass_frequency=0.25) 

407 

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

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

410 opts['rel_highpass_frequency'] = None 

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

412 opts['rel_lowpass_frequency'] = None 

413 out_filename = opts.pop('output') 

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

415 if out_filename is not None: 

416 return gfts, out_filename 

417 

418 

419def command_dlowband(command, args): 

420 def setup(parser): 

421 add_source_options(parser) 

422 add_double_options(parser) 

423 add_filter_options(parser) 

424 parser.set_defaults(lowpass_frequency=0.0018) 

425 parser.set_defaults(highpass_frequency=0.004) 

426 

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

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

429 verify_options('dlowband', **opts) 

430 out_filename = opts.pop('output') 

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

432 if out_filename is not None: 

433 return gfts, out_filename 

434 

435 

436def command_dhighband(command, args): 

437 def setup(parser): 

438 add_source_options(parser) 

439 add_double_options(parser) 

440 add_filter_options(parser) 

441 parser.set_defaults(rel_lowpass_frequency=0.125) 

442 parser.set_defaults(rel_highpass_frequency=0.25) 

443 

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

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

446 verify_options('dhighband', **opts) 

447 out_filename = opts.pop('output') 

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

449 if out_filename is not None: 

450 return gfts, out_filename 

451 

452 

453def command_dnone(command, args): 

454 def setup(parser): 

455 add_source_options(parser) 

456 add_double_options(parser) 

457 

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

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

460 opts['rel_lowpass_frequency'] = None 

461 opts['rel_highpass_frequency'] = None 

462 out_filename = opts.pop('output') 

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

464 if out_filename is not None: 

465 return gfts, out_filename 

466 

467 

468program_name = 'fomosto report' 

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

470 ' traces and' \ 

471 " displacment spectra for Green's Function stores.\n\n" \ 

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

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

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

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

476 

477 

478def run_program(args): 

479 if len(args) < 1: 

480 sys.exit(usage) 

481 

482 command = args.pop(0) 

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

484 sys.exit(usage) 

485 

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

487 glbs = globals() 

488 cmds = [] 

489 while args and args[0] in subcmds_desc: 

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

491 for command in cmds: 

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

493 sys.exit() 

494 

495 if command not in subcmds_desc: 

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

497 format(program_name, command)) 

498 

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

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

501 args.append('--help') 

502 

503 try: 

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

505 if lst is not None: 

506 gfts = lst[0] 

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

508 if isinstance(gfts, gftest): 

509 f.write(gfts.dump()) 

510 else: 

511 for i in lst[0]: 

512 f.write(i.dump()) 

513 

514 except FomostoReportError as e: 

515 sys.exit(str(e)) 

516 

517 

518if __name__ == '__main__': 

519 run_program(sys.argv)