[add] for global seismology CF pick windows will now be calculated

relative to estimated tt from TauPy, metadata and source location (in XML
file) needed
[TO DO]: automatic export of XML (esp. source loc) before autopicking
This commit is contained in:
2017-08-07 11:21:20 +02:00
parent 60ebaa6528
commit 17a93cf62f
7 changed files with 169 additions and 87 deletions

View File

@@ -87,12 +87,14 @@ defaults = {'rootpath': {'type': str,
'namestring': ('Quality factor', 'Qp1', 'Qp2')},
'pstart': {'type': float,
'tooltip': 'start time [s] for calculating CF for P-picking',
'tooltip': 'start time [s] for calculating CF for P-picking (if TauPy:'
' seconds relative to estimated onset)',
'value': 15.0,
'namestring': 'P start'},
'pstop': {'type': float,
'tooltip': 'end time [s] for calculating CF for P-picking',
'tooltip': 'end time [s] for calculating CF for P-picking (if TauPy:'
' seconds relative to estimated onset)',
'value': 60.0,
'namestring': 'P stop'},
@@ -381,12 +383,12 @@ defaults = {'rootpath': {'type': str,
'use_taup': {'type': bool,
'tooltip': 'use estimated traveltimes from TauPy for calculating windows for CF',
'value': True,
'namestring': 'Use Taupy'},
'namestring': 'Use TauPy'},
'taup_model': {'type': str,
'tooltip': 'define TauPy model for traveltime estimation',
'value': 'iasp91',
'namestring': 'Taupy model'}
'namestring': 'TauPy model'}
}
settings_main = {

View File

@@ -18,10 +18,13 @@ from pylot.core.pick.charfuns import HOScf, AICcf, ARZcf, ARHcf, AR3Ccf
from pylot.core.pick.picker import AICPicker, PragPicker
from pylot.core.pick.utils import checksignallength, checkZ4S, earllatepicker, \
getSNR, fmpicker, checkPonsets, wadaticheck
from pylot.core.util.utils import getPatternLine, gen_Pool
from pylot.core.util.utils import getPatternLine, gen_Pool, identifyPhase, loopIdentifyPhase, \
full_range
from obspy.taup import TauPyModel
def autopickevent(data, param, iplot=0, fig_dict=None, ncores=0):
def autopickevent(data, param, iplot=0, fig_dict=None, ncores=0, metadata=None, origin=None):
stations = []
all_onsets = {}
input_tuples = []
@@ -42,9 +45,11 @@ def autopickevent(data, param, iplot=0, fig_dict=None, ncores=0):
topick = data.select(station=station)
if not iplot:
input_tuples.append((topick, param, apverbose))
input_tuples.append((topick, param, apverbose, metadata, origin))
if iplot > 0:
all_onsets[station] = autopickstation(topick, param, verbose=apverbose, iplot=iplot, fig_dict=fig_dict)
all_onsets[station] = autopickstation(topick, param, verbose=apverbose,
iplot=iplot, fig_dict=fig_dict,
metadata=metadata, origin=origin)
if iplot > 0:
print('iPlot Flag active: NO MULTIPROCESSING possible.')
@@ -69,12 +74,13 @@ def autopickevent(data, param, iplot=0, fig_dict=None, ncores=0):
def call_autopickstation(input_tuple):
wfstream, pickparam, verbose = input_tuple
wfstream, pickparam, verbose, metadata, origin = input_tuple
# multiprocessing not possible with interactive plotting
return autopickstation(wfstream, pickparam, verbose, iplot=0)
return autopickstation(wfstream, pickparam, verbose, iplot=0, metadata=metadata, origin=origin)
def autopickstation(wfstream, pickparam, verbose=False, iplot=0, fig_dict=None):
def autopickstation(wfstream, pickparam, verbose=False,
iplot=0, fig_dict=None, metadata=None, origin=None):
"""
:param wfstream: `~obspy.core.stream.Stream` containing waveform
:type wfstream: obspy.core.stream.Stream
@@ -117,6 +123,8 @@ def autopickstation(wfstream, pickparam, verbose=False, iplot=0, fig_dict=None):
algoS = pickparam.get('algoS')
sstart = pickparam.get('sstart')
sstop = pickparam.get('sstop')
use_taup = pickparam.get('use_taup')
taup_model = pickparam.get('taup_model')
bph1 = pickparam.get('bph1')
bph2 = pickparam.get('bph2')
tsnrh = pickparam.get('tsnrh')
@@ -182,6 +190,8 @@ def autopickstation(wfstream, pickparam, verbose=False, iplot=0, fig_dict=None):
if len(ndat) == 0: # check for other components
ndat = wfstream.select(component="1")
wfstart, wfend = full_range(wfstream)
if algoP == 'HOS' or algoP == 'ARZ' and zdat is not None:
msg = '##################################################\nautopickstation:' \
' Working on P onset of station {station}\nFiltering vertical ' \
@@ -197,7 +207,47 @@ def autopickstation(wfstream, pickparam, verbose=False, iplot=0, fig_dict=None):
z_copy[0].data = tr_filt.data
##############################################################
# check length of waveform and compare with cut times
Lc = pstop - pstart
# for global seismology: use tau-p method for estimating travel times (needs source and station coords.)
# if not given: sets Lc to infinity to use full stream
if use_taup:
Lc = np.inf
print('autopickstation: use_taup flag active.')
if not metadata[1]:
print('Warning: Could not use TauPy to estimate onsets as there are no metadata given.')
else:
if origin:
source_origin = origin[0]
station_id = wfstream[0].get_id()
parser = metadata[1]
station_coords = parser.get_coordinates(station_id)
model = TauPyModel(taup_model)
arrivals = model.get_travel_times_geo(
source_origin.depth,
source_origin.latitude,
source_origin.longitude,
station_coords['latitude'],
station_coords['longitude']
)
phases = {'P': [],
'S': []}
for arr in arrivals:
phases[identifyPhase(loopIdentifyPhase(arr.phase.name))].append(arr)
# get first P and S onsets from arrivals list
arrP, estFirstP = min([(arr, arr.time) for arr in phases['P']], key = lambda t: t[1])
arrS, estFirstS = min([(arr, arr.time) for arr in phases['S']], key = lambda t: t[1])
print('autopick: estimated first arrivals for P: {}, S:{} using TauPy'.format(estFirstP, estFirstS))
# modifiy pstart and pstop relative to estimated first P arrival (relative to station time axis)
pstart += (source_origin.time + estFirstP) - wfstart
pstop += (source_origin.time + estFirstP) - wfstart
Lc = pstop - pstart
else:
print('No source origins given!')
else:
Lc = pstop - pstart
Lwf = zdat[0].stats.endtime - zdat[0].stats.starttime
Ldiff = Lwf - Lc
if Ldiff < 0:
@@ -238,6 +288,12 @@ def autopickstation(wfstream, pickparam, verbose=False, iplot=0, fig_dict=None):
else:
fig = None
aicpick = AICPicker(aiccf, tsnrz, pickwinP, iplot, None, tsmoothP, fig=fig)
# add pstart and pstop to aic plot
if fig.axes:
for ax in fig.axes:
ax.vlines(pstart, ax.get_ylim()[0], ax.get_ylim()[1], color='c', linestyles='dashed', label='P start')
ax.vlines(pstop, ax.get_ylim()[0], ax.get_ylim()[1], color='c', linestyles='dashed', label='P stop')
ax.legend()
##############################################################
if aicpick.getpick() is not None:
# check signal length to detect spuriously picked noise peaks

View File

@@ -9,7 +9,7 @@ Created on Wed Feb 26 12:31:25 2014
import os
import platform
from pylot.core.io.inputs import PylotParameter
from pylot.core.util.utils import readDefaultFilterInformation
from pylot.core.loc import hypo71
from pylot.core.loc import hypodd
from pylot.core.loc import hyposat
@@ -17,23 +17,6 @@ from pylot.core.loc import nll
from pylot.core.loc import velest
def readDefaultFilterInformation(fname):
pparam = PylotParameter(fname)
return readFilterInformation(pparam)
def readFilterInformation(pylot_parameter):
p_filter = {'filtertype': pylot_parameter['filter_type'][0],
'freq': [pylot_parameter['minfreq'][0], pylot_parameter['maxfreq'][0]],
'order': int(pylot_parameter['filter_order'][0])}
s_filter = {'filtertype': pylot_parameter['filter_type'][1],
'freq': [pylot_parameter['minfreq'][1], pylot_parameter['maxfreq'][1]],
'order': int(pylot_parameter['filter_order'][1])}
filter_information = {'P': p_filter,
'S': s_filter}
return filter_information
# determine system dependent path separator
system_name = platform.system()
if system_name in ["Linux", "Darwin"]:

View File

@@ -10,8 +10,8 @@ import subprocess
import numpy as np
from obspy import UTCDateTime, read
from pylot.core.io.inputs import PylotParameter
from scipy.interpolate import splrep, splev
from scipy.interpolate import splrep, splev
def _pickle_method(m):
if m.im_self is None:
@@ -20,6 +20,23 @@ def _pickle_method(m):
return getattr, (m.im_self, m.im_func.func_name)
def readDefaultFilterInformation(fname):
pparam = PylotParameter(fname)
return readFilterInformation(pparam)
def readFilterInformation(pylot_parameter):
p_filter = {'filtertype': pylot_parameter['filter_type'][0],
'freq': [pylot_parameter['minfreq'][0], pylot_parameter['maxfreq'][0]],
'order': int(pylot_parameter['filter_order'][0])}
s_filter = {'filtertype': pylot_parameter['filter_type'][1],
'freq': [pylot_parameter['minfreq'][1], pylot_parameter['maxfreq'][1]],
'order': int(pylot_parameter['filter_order'][1])}
filter_information = {'P': p_filter,
'S': s_filter}
return filter_information
def fit_curve(x, y):
return splev, splrep(x, y)
@@ -551,6 +568,51 @@ def which(program, infile=None):
return None
def loopIdentifyPhase(phase):
'''
Loop through phase string and try to recognize its type (P or S wave).
Global variable ALTSUFFIX gives alternative suffix for phases if they do not end with P, p or S, s.
If ALTSUFFIX is not given, the function will cut the last letter of the phase string until string ends
with P or S.
:param phase: phase name (str)
:return:
'''
from pylot.core.util.defaults import ALTSUFFIX
phase_copy = phase
while not identifyPhase(phase_copy):
identified = False
for alt_suf in ALTSUFFIX:
if phase_copy.endswith(alt_suf):
phase_copy = phase_copy.split(alt_suf)[0]
identified = True
if not identified:
phase_copy = phase_copy[:-1]
if len(phase_copy) < 1:
print('Warning: Could not identify phase {}!'.format(phase))
return
return phase_copy
def identifyPhase(phase):
'''
Returns capital P or S if phase string is identified by last letter. Else returns False.
:param phase: phase name (str)
:return: 'P', 'S' or False
'''
# common phase suffix for P and S
common_P = ['P', 'p']
common_S = ['S', 's']
if phase[-1] in common_P:
return 'P'
if phase[-1] in common_S:
return 'S'
else:
return False
if __name__ == "__main__":
import doctest

View File

@@ -21,7 +21,7 @@ except:
pg = None
from matplotlib.figure import Figure
from pylot.core.util.utils import find_horizontals
from pylot.core.util.utils import find_horizontals, identifyPhase, loopIdentifyPhase
try:
from matplotlib.backends.backend_qt4agg import FigureCanvas
@@ -46,7 +46,7 @@ from pylot.core.io.inputs import FilterOptions, PylotParameter
from pylot.core.pick.utils import getSNR, earllatepicker, getnoisewin, \
getResolutionWindow
from pylot.core.pick.compare import Comparison
from pylot.core.util.defaults import OUTPUTFORMATS, FILTERDEFAULTS, ALTSUFFIX, \
from pylot.core.util.defaults import OUTPUTFORMATS, FILTERDEFAULTS, \
SetChannelComponents
from pylot.core.util.utils import prepTimeAxis, full_range, scaleWFData, \
demeanTrace, isSorted, findComboBoxIndex, clims
@@ -118,34 +118,6 @@ def createAction(parent, text, slot=None, shortcut=None, icon=None,
return action
def loopIdentifyPhase(phase):
phase_copy = phase
while not identifyPhase(phase_copy):
identified = False
for alt_suf in ALTSUFFIX:
if phase_copy.endswith(alt_suf):
phase_copy = phase_copy.split(alt_suf)[0]
identified = True
if not identified:
phase_copy = phase_copy[:-1]
if len(phase_copy) < 1:
print('Warning: Could not identify phase {}!'.format(phase))
return
return phase_copy
def identifyPhase(phase):
# common phase suffix for P and S
common_P = ['P', 'p']
common_S = ['S', 's']
if phase[-1] in common_P:
return 'P'
if phase[-1] in common_S:
return 'S'
else:
return False
class ComparisonDialog(QDialog):
def __init__(self, c, parent=None):
self._data = c