2015-06-19 09:08:28 +02:00
|
|
|
#!/usr/bin/python
|
2015-04-22 12:46:24 +02:00
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
|
2016-03-30 08:14:58 +02:00
|
|
|
from __future__ import print_function
|
2016-05-01 21:10:30 +02:00
|
|
|
|
2015-04-22 12:46:24 +02:00
|
|
|
import argparse
|
2015-05-20 09:38:25 +02:00
|
|
|
import glob
|
2016-08-25 13:31:51 +02:00
|
|
|
import os
|
2016-05-01 21:10:30 +02:00
|
|
|
|
2016-09-28 11:03:53 +02:00
|
|
|
from obspy import read_events
|
2016-05-01 21:10:30 +02:00
|
|
|
|
2017-02-28 15:02:39 +01:00
|
|
|
import pylot.core.loc.hyposat as hyposat
|
|
|
|
import pylot.core.loc.hypo71 as hypo71
|
2017-03-02 09:19:42 +01:00
|
|
|
import pylot.core.loc.velest as velest
|
2017-03-02 11:10:28 +01:00
|
|
|
import pylot.core.loc.hypodd as hypodd
|
2017-03-14 10:33:56 +01:00
|
|
|
import pylot.core.loc.focmec as focmec
|
2016-09-28 11:03:53 +02:00
|
|
|
import pylot.core.loc.nll as nll
|
|
|
|
from pylot.core.analysis.magnitude import MomentMagnitude, RichterMagnitude
|
2016-05-01 21:10:30 +02:00
|
|
|
from pylot.core.io.data import Data
|
|
|
|
from pylot.core.io.inputs import AutoPickParameter
|
|
|
|
from pylot.core.pick.autopick import autopickevent, iteratepicker
|
2016-09-28 14:56:01 +02:00
|
|
|
from pylot.core.util.dataprocessing import restitute_data, read_metadata, \
|
|
|
|
remove_underscores
|
2016-05-01 21:10:30 +02:00
|
|
|
from pylot.core.util.structure import DATASTRUCTURE
|
2015-10-19 05:32:10 +02:00
|
|
|
from pylot.core.util.version import get_git_version as _getVersionString
|
2015-07-02 09:27:11 +02:00
|
|
|
|
2015-04-22 12:46:24 +02:00
|
|
|
__version__ = _getVersionString()
|
|
|
|
|
|
|
|
|
2015-05-20 09:43:32 +02:00
|
|
|
def autoPyLoT(inputfile):
|
2015-10-28 09:13:13 +01:00
|
|
|
"""
|
2015-04-29 06:29:08 +02:00
|
|
|
Determine phase onsets automatically utilizing the automatic picking
|
2015-06-19 09:08:28 +02:00
|
|
|
algorithms by Kueperkoch et al. 2010/2012.
|
2015-04-29 06:29:08 +02:00
|
|
|
|
|
|
|
:param inputfile: path to the input file containing all parameter
|
|
|
|
information for automatic picking (for formatting details, see.
|
2016-05-01 21:10:30 +02:00
|
|
|
`~pylot.core.io.inputs.AutoPickParameter`
|
2015-04-29 06:29:08 +02:00
|
|
|
:type inputfile: str
|
|
|
|
:return:
|
|
|
|
|
|
|
|
.. rubric:: Example
|
|
|
|
|
2015-10-28 09:13:13 +01:00
|
|
|
"""
|
2015-11-04 13:11:48 +01:00
|
|
|
splash = '''************************************\n
|
|
|
|
*********autoPyLoT starting*********\n
|
|
|
|
The Python picking and Location Tool\n
|
|
|
|
Version {version} 2015\n
|
|
|
|
\n
|
|
|
|
Authors:\n
|
|
|
|
S. Wehling-Benatelli (Ruhr-Universität Bochum)\n
|
|
|
|
L. Küperkoch (BESTEC GmbH, Landau i. d. Pfalz)\n
|
|
|
|
K. Olbert (Christian-Albrechts Universität zu Kiel)\n
|
|
|
|
***********************************'''.format(version=_getVersionString())
|
|
|
|
print(splash)
|
2015-05-20 09:38:25 +02:00
|
|
|
|
|
|
|
# reading parameter file
|
2015-04-22 12:46:24 +02:00
|
|
|
parameter = AutoPickParameter(inputfile)
|
2015-04-29 06:29:08 +02:00
|
|
|
|
2015-04-22 12:46:24 +02:00
|
|
|
data = Data()
|
|
|
|
|
2016-09-28 11:03:53 +02:00
|
|
|
evt = None
|
2015-05-20 09:38:25 +02:00
|
|
|
# getting information on data structure
|
|
|
|
|
2015-04-29 06:29:08 +02:00
|
|
|
if parameter.hasParam('datastructure'):
|
2016-05-03 08:46:13 +02:00
|
|
|
datastructure = DATASTRUCTURE[parameter.get('datastructure')]()
|
|
|
|
dsfields = {'root': parameter.get('rootpath'),
|
|
|
|
'dpath': parameter.get('datapath'),
|
|
|
|
'dbase': parameter.get('database')}
|
2015-04-29 07:57:52 +02:00
|
|
|
|
2015-05-20 09:59:06 +02:00
|
|
|
exf = ['root', 'dpath', 'dbase']
|
|
|
|
|
|
|
|
if parameter.hasParam('eventID'):
|
2016-05-03 08:46:13 +02:00
|
|
|
dsfields['eventID'] = parameter.get('eventID')
|
2015-05-20 09:59:06 +02:00
|
|
|
exf.append('eventID')
|
2015-04-22 12:46:24 +02:00
|
|
|
|
2015-06-01 16:28:27 +02:00
|
|
|
datastructure.modifyFields(**dsfields)
|
2015-05-20 09:59:06 +02:00
|
|
|
datastructure.setExpandFields(exf)
|
2015-04-22 12:46:24 +02:00
|
|
|
|
2015-10-28 09:13:13 +01:00
|
|
|
# check if default location routine NLLoc is available
|
|
|
|
if parameter.hasParam('nllocbin'):
|
|
|
|
locflag = 1
|
|
|
|
# get NLLoc-root path
|
2016-05-03 08:46:13 +02:00
|
|
|
nllocroot = parameter.get('nllocroot')
|
2015-10-28 09:13:13 +01:00
|
|
|
# get path to NLLoc executable
|
2016-05-03 08:46:13 +02:00
|
|
|
nllocbin = parameter.get('nllocbin')
|
2015-10-28 09:13:13 +01:00
|
|
|
nlloccall = '%s/NLLoc' % nllocbin
|
2015-11-04 13:11:48 +01:00
|
|
|
# get name of phase file
|
2016-05-03 08:46:13 +02:00
|
|
|
phasef = parameter.get('phasefile')
|
2015-10-28 09:13:13 +01:00
|
|
|
phasefile = '%s/obs/%s' % (nllocroot, phasef)
|
|
|
|
# get name of NLLoc-control file
|
2016-05-03 08:46:13 +02:00
|
|
|
ctrf = parameter.get('ctrfile')
|
2015-11-18 10:27:42 +01:00
|
|
|
ctrfile = '%s/run/%s' % (nllocroot, ctrf)
|
|
|
|
# pattern of NLLoc ttimes from location grid
|
2016-05-03 08:46:13 +02:00
|
|
|
ttpat = parameter.get('ttpatter')
|
2015-11-18 10:27:42 +01:00
|
|
|
# pattern of NLLoc-output file
|
2016-05-03 08:46:13 +02:00
|
|
|
nllocoutpatter = parameter.get('outpatter')
|
2016-03-30 08:14:58 +02:00
|
|
|
maxnumit = 3 # maximum number of iterations for re-picking
|
2015-10-28 09:13:13 +01:00
|
|
|
else:
|
|
|
|
locflag = 0
|
2015-12-01 15:39:28 +01:00
|
|
|
print(" !!! ")
|
|
|
|
print("!!No location routine available, autoPyLoT is running in non-location mode!!")
|
|
|
|
print("!!No source parameter estimation possible!!")
|
|
|
|
print(" !!! ")
|
2015-10-27 10:00:16 +01:00
|
|
|
|
2015-05-20 09:38:25 +02:00
|
|
|
datapath = datastructure.expandDataPath()
|
2015-05-20 09:59:06 +02:00
|
|
|
if not parameter.hasParam('eventID'):
|
2016-09-28 11:03:53 +02:00
|
|
|
# multiple event processing
|
|
|
|
# read each event in database
|
|
|
|
events = [events for events in glob.glob(os.path.join(datapath, '*')) if os.path.isdir(events)]
|
2015-05-20 09:59:06 +02:00
|
|
|
else:
|
2016-09-28 11:03:53 +02:00
|
|
|
# single event processing
|
|
|
|
events = glob.glob(os.path.join(datapath, parameter.get('eventID')))
|
|
|
|
for event in events:
|
|
|
|
data.setWFData(glob.glob(os.path.join(datapath, event, '*')))
|
|
|
|
evID = os.path.split(event)[-1]
|
|
|
|
print('Working on event %s' % event)
|
2016-03-30 08:14:58 +02:00
|
|
|
print(data)
|
2015-10-28 09:13:13 +01:00
|
|
|
wfdat = data.getWFData() # all available streams
|
2016-09-28 14:56:01 +02:00
|
|
|
wfdat = remove_underscores(wfdat)
|
2016-09-28 11:03:53 +02:00
|
|
|
metadata = read_metadata(parameter.get('invdir'))
|
|
|
|
corr_dat, rest_flag = restitute_data(wfdat.copy(), *metadata)
|
2015-06-01 16:28:27 +02:00
|
|
|
##########################################################
|
2015-07-10 09:22:58 +02:00
|
|
|
# !automated picking starts here!
|
|
|
|
picks = autopickevent(wfdat, parameter)
|
2015-10-27 15:26:25 +01:00
|
|
|
##########################################################
|
2015-10-28 09:13:13 +01:00
|
|
|
# locating
|
|
|
|
if locflag == 1:
|
|
|
|
# write phases to NLLoc-phase file
|
2017-02-28 15:02:39 +01:00
|
|
|
nll.export(picks, phasefile, parameter)
|
2015-10-28 09:13:13 +01:00
|
|
|
|
2015-11-04 16:52:39 +01:00
|
|
|
# For locating the event the NLLoc-control file has to be modified!
|
2016-09-28 11:03:53 +02:00
|
|
|
nllocout = '%s_%s' % (evID, nllocoutpatter)
|
2015-11-18 10:27:42 +01:00
|
|
|
# create comment line for NLLoc-control file
|
2016-09-28 11:03:53 +02:00
|
|
|
nll.modify_inputs(ctrf, nllocroot, nllocout, phasef,
|
|
|
|
ttpat)
|
2015-10-28 09:13:13 +01:00
|
|
|
|
|
|
|
# locate the event
|
2017-03-15 14:17:02 +01:00
|
|
|
nll.locate(ctrfile, inputfile)
|
2016-09-28 11:03:53 +02:00
|
|
|
|
2015-11-18 10:27:42 +01:00
|
|
|
# !iterative picking if traces remained unpicked or occupied with bad picks!
|
2015-11-12 17:21:04 +01:00
|
|
|
# get theoretical onset times for picks with weights >= 4
|
2015-11-20 15:49:34 +01:00
|
|
|
# in order to reprocess them using smaller time windows around theoretical onset
|
|
|
|
# get stations with bad onsets
|
|
|
|
badpicks = []
|
|
|
|
for key in picks:
|
2016-03-30 08:14:58 +02:00
|
|
|
if picks[key]['P']['weight'] >= 4 or picks[key]['S']['weight'] >= 4:
|
|
|
|
badpicks.append([key, picks[key]['P']['mpp']])
|
2015-11-20 15:49:34 +01:00
|
|
|
|
2016-09-28 11:03:53 +02:00
|
|
|
# TODO keep code DRY (Don't Repeat Yourself) the following part is written twice
|
|
|
|
# suggestion: delete block and modify the later similar block to work properly
|
|
|
|
|
2015-11-20 15:49:34 +01:00
|
|
|
if len(badpicks) == 0:
|
2016-03-30 08:14:58 +02:00
|
|
|
print("autoPyLoT: No bad onsets found, thus no iterative picking necessary!")
|
2015-12-01 15:39:28 +01:00
|
|
|
# get NLLoc-location file
|
|
|
|
locsearch = '%s/loc/%s.????????.??????.grid?.loc.hyp' % (nllocroot, nllocout)
|
|
|
|
if len(glob.glob(locsearch)) > 0:
|
2016-09-28 11:03:53 +02:00
|
|
|
# get latest NLLoc-location file if several are available
|
2016-03-30 08:14:58 +02:00
|
|
|
nllocfile = max(glob.glob(locsearch), key=os.path.getctime)
|
2016-09-28 14:56:01 +02:00
|
|
|
evt = read_events(nllocfile)[0]
|
2015-12-01 15:39:28 +01:00
|
|
|
# calculating seismic moment Mo and moment magnitude Mw
|
2016-09-28 11:03:53 +02:00
|
|
|
moment_mag = MomentMagnitude(corr_dat, evt, parameter.get('vp'),
|
2016-09-28 14:56:01 +02:00
|
|
|
parameter.get('Qp'),
|
2016-10-28 14:54:55 +02:00
|
|
|
parameter.get('rho'), True, \
|
|
|
|
parameter.get('iplot'))
|
2016-09-29 11:55:08 +02:00
|
|
|
# update pick with moment property values (w0, fc, Mo)
|
|
|
|
for station, props in moment_mag.moment_props.items():
|
|
|
|
picks[station]['P'].update(props)
|
|
|
|
evt = moment_mag.updated_event()
|
2016-09-28 14:56:01 +02:00
|
|
|
local_mag = RichterMagnitude(corr_dat, evt,
|
2016-10-28 14:54:55 +02:00
|
|
|
parameter.get('sstop'), True,\
|
|
|
|
parameter.get('iplot'))
|
2016-09-28 14:56:01 +02:00
|
|
|
for station, amplitude in local_mag.amplitudes.items():
|
2016-09-29 11:55:08 +02:00
|
|
|
picks[station]['S']['Ao'] = amplitude.generic_amplitude
|
|
|
|
evt = local_mag.updated_event()
|
2015-12-01 15:39:28 +01:00
|
|
|
else:
|
|
|
|
print("autoPyLoT: No NLLoc-location file available!")
|
|
|
|
print("No source parameter estimation possible!")
|
2015-11-20 15:49:34 +01:00
|
|
|
else:
|
|
|
|
# get theoretical P-onset times from NLLoc-location file
|
|
|
|
locsearch = '%s/loc/%s.????????.??????.grid?.loc.hyp' % (nllocroot, nllocout)
|
2015-11-23 16:38:52 +01:00
|
|
|
if len(glob.glob(locsearch)) > 0:
|
|
|
|
# get latest file if several are available
|
2016-03-30 08:14:58 +02:00
|
|
|
nllocfile = max(glob.glob(locsearch), key=os.path.getctime)
|
2015-11-23 16:38:52 +01:00
|
|
|
nlloccounter = 0
|
2016-03-30 08:14:58 +02:00
|
|
|
while len(badpicks) > 0 and nlloccounter <= maxnumit:
|
2015-11-23 16:38:52 +01:00
|
|
|
nlloccounter += 1
|
|
|
|
if nlloccounter > maxnumit:
|
|
|
|
print("autoPyLoT: Number of maximum iterations reached, stop iterative picking!")
|
|
|
|
break
|
|
|
|
print("autoPyLoT: Starting with iteration No. %d ..." % nlloccounter)
|
|
|
|
picks = iteratepicker(wfdat, nllocfile, picks, badpicks, parameter)
|
|
|
|
# write phases to NLLoc-phase file
|
2017-02-28 15:02:39 +01:00
|
|
|
nll.export(picks, phasefile, parameter)
|
2015-12-03 14:55:07 +01:00
|
|
|
# remove actual NLLoc-location file to keep only the last
|
|
|
|
os.remove(nllocfile)
|
2015-11-23 16:38:52 +01:00
|
|
|
# locate the event
|
2017-03-15 14:17:02 +01:00
|
|
|
nll.locate(ctrfile, inputfile)
|
2015-11-23 16:38:52 +01:00
|
|
|
print("autoPyLoT: Iteration No. %d finished." % nlloccounter)
|
2015-12-01 15:39:28 +01:00
|
|
|
# get updated NLLoc-location file
|
2016-03-30 08:14:58 +02:00
|
|
|
nllocfile = max(glob.glob(locsearch), key=os.path.getctime)
|
2015-12-01 15:39:28 +01:00
|
|
|
# check for bad picks
|
2015-11-23 16:38:52 +01:00
|
|
|
badpicks = []
|
|
|
|
for key in picks:
|
2016-03-30 08:14:58 +02:00
|
|
|
if picks[key]['P']['weight'] >= 4 or picks[key]['S']['weight'] >= 4:
|
|
|
|
badpicks.append([key, picks[key]['P']['mpp']])
|
2015-11-23 16:38:52 +01:00
|
|
|
print("autoPyLoT: After iteration No. %d: %d bad onsets found ..." % (nlloccounter, \
|
2016-03-30 08:14:58 +02:00
|
|
|
len(badpicks)))
|
2015-11-23 16:38:52 +01:00
|
|
|
if len(badpicks) == 0:
|
|
|
|
print("autoPyLoT: No more bad onsets found, stop iterative picking!")
|
2015-12-01 15:39:28 +01:00
|
|
|
nlloccounter = maxnumit
|
2016-09-28 14:56:01 +02:00
|
|
|
evt = read_events(nllocfile)[0]
|
2015-12-01 15:39:28 +01:00
|
|
|
# calculating seismic moment Mo and moment magnitude Mw
|
2016-09-28 11:03:53 +02:00
|
|
|
moment_mag = MomentMagnitude(corr_dat, evt, parameter.get('vp'),
|
2016-09-28 14:56:01 +02:00
|
|
|
parameter.get('Qp'),
|
2016-10-28 14:54:55 +02:00
|
|
|
parameter.get('rho'), True, \
|
|
|
|
parameter.get('iplot'))
|
2016-09-29 11:55:08 +02:00
|
|
|
# update pick with moment property values (w0, fc, Mo)
|
|
|
|
for station, props in moment_mag.moment_props.items():
|
|
|
|
picks[station]['P'].update(props)
|
|
|
|
evt = moment_mag.updated_event()
|
2016-09-28 14:56:01 +02:00
|
|
|
local_mag = RichterMagnitude(corr_dat, evt,
|
2016-10-28 14:54:55 +02:00
|
|
|
parameter.get('sstop'), True, \
|
|
|
|
parameter.get('iplot'))
|
2016-09-28 14:56:01 +02:00
|
|
|
for station, amplitude in local_mag.amplitudes.items():
|
2016-09-29 11:55:08 +02:00
|
|
|
picks[station]['S']['Ao'] = amplitude.generic_amplitude
|
|
|
|
evt = local_mag.updated_event()
|
|
|
|
net_mw = moment_mag.net_magnitude()
|
|
|
|
print("Network moment magnitude: %4.1f" % net_mw.mag)
|
2015-11-20 15:49:34 +01:00
|
|
|
else:
|
|
|
|
print("autoPyLoT: No NLLoc-location file available! Stop iteration!")
|
2015-10-27 15:26:25 +01:00
|
|
|
##########################################################
|
2017-03-14 10:33:56 +01:00
|
|
|
# write phase files for various location
|
|
|
|
# and fault mechanism calculation routines
|
2015-11-04 16:52:39 +01:00
|
|
|
# HYPO71
|
2017-02-28 15:02:39 +01:00
|
|
|
hypo71file = '%s/autoPyLoT_HYPO71_phases' % event
|
|
|
|
hypo71.export(picks, hypo71file, parameter)
|
|
|
|
# HYPOSAT
|
|
|
|
hyposatfile = '%s/autoPyLoT_HYPOSAT_phases' % event
|
|
|
|
hyposat.export(picks, hyposatfile, parameter)
|
2017-03-02 09:19:42 +01:00
|
|
|
# VELEST
|
|
|
|
velestfile = '%s/autoPyLoT_VELEST_phases.cnv' % event
|
|
|
|
velest.export(picks, velestfile, parameter, evt)
|
2017-03-02 11:10:28 +01:00
|
|
|
# hypoDD
|
|
|
|
hypoddfile = '%s/autoPyLoT_hypoDD_phases.pha' % event
|
|
|
|
hypodd.export(picks, hypoddfile, parameter, evt)
|
2017-03-16 11:27:48 +01:00
|
|
|
# FOCMEC
|
|
|
|
focmecfile = '%s/autoPyLoT_FOCMEC.in' % event
|
2017-03-14 10:33:56 +01:00
|
|
|
focmec.export(picks, focmecfile, parameter, evt)
|
2017-02-28 15:02:39 +01:00
|
|
|
# ObsPy event object
|
2016-09-28 11:03:53 +02:00
|
|
|
data.applyEVTData(picks)
|
|
|
|
if evt is not None:
|
|
|
|
data.applyEVTData(evt, 'event')
|
|
|
|
fnqml = '%s/autoPyLoT' % event
|
2016-04-11 13:59:32 +02:00
|
|
|
data.exportEvent(fnqml)
|
2016-03-30 08:14:58 +02:00
|
|
|
|
2015-11-12 17:21:04 +01:00
|
|
|
endsplash = '''------------------------------------------\n'
|
2016-03-30 08:14:58 +02:00
|
|
|
-----Finished event %s!-----\n'
|
2015-11-12 17:21:04 +01:00
|
|
|
------------------------------------------'''.format \
|
2016-09-28 11:03:53 +02:00
|
|
|
(version=_getVersionString()) % evID
|
2015-11-12 17:21:04 +01:00
|
|
|
print(endsplash)
|
|
|
|
if locflag == 0:
|
|
|
|
print("autoPyLoT was running in non-location mode!")
|
2016-03-30 08:14:58 +02:00
|
|
|
|
2015-11-12 17:21:04 +01:00
|
|
|
endsp = '''####################################\n
|
|
|
|
************************************\n
|
|
|
|
*********autoPyLoT terminates*******\n
|
|
|
|
The Python picking and Location Tool\n
|
|
|
|
************************************'''.format(version=_getVersionString())
|
|
|
|
print(endsp)
|
2015-04-29 07:57:52 +02:00
|
|
|
|
2016-03-30 08:14:58 +02:00
|
|
|
|
2015-04-22 12:46:24 +02:00
|
|
|
if __name__ == "__main__":
|
2016-04-11 13:59:32 +02:00
|
|
|
from pylot.core.util.defaults import AUTOMATIC_DEFAULTS
|
2015-04-22 12:46:24 +02:00
|
|
|
# parse arguments
|
|
|
|
parser = argparse.ArgumentParser(
|
2015-07-10 09:22:58 +02:00
|
|
|
description='''autoPyLoT automatically picks phase onset times using higher order statistics,
|
2015-05-29 16:26:31 +02:00
|
|
|
autoregressive prediction and AIC''')
|
2015-04-22 12:46:24 +02:00
|
|
|
|
|
|
|
parser.add_argument('-i', '-I', '--inputfile', type=str,
|
|
|
|
action='store',
|
|
|
|
help='''full path to the file containing the input
|
|
|
|
parameters for autoPyLoT''',
|
2016-04-11 13:59:32 +02:00
|
|
|
default=AUTOMATIC_DEFAULTS
|
2015-04-22 12:46:24 +02:00
|
|
|
)
|
|
|
|
parser.add_argument('-v', '-V', '--version', action='version',
|
|
|
|
version='autoPyLoT ' + __version__,
|
|
|
|
help='show version information and exit')
|
|
|
|
|
|
|
|
cla = parser.parse_args()
|
|
|
|
|
2015-05-20 10:01:19 +02:00
|
|
|
autoPyLoT(str(cla.inputfile))
|