[change] Enable picking on traces with only one vertical component

Only the P pick will be calculated
This commit is contained in:
Darius Arnold 2018-07-30 12:03:33 +02:00
parent 09721c7bb9
commit da2b1ed133

View File

@ -20,6 +20,7 @@ from pylot.core.util.utils import getPatternLine, gen_Pool,\
real_Bool, identifyPhaseID, real_None, correct_iplot real_Bool, identifyPhaseID, real_None, correct_iplot
from obspy.taup import TauPyModel from obspy.taup import TauPyModel
from obspy import Trace
def autopickevent(data, param, iplot=0, fig_dict=None, fig_dict_wadatijack=None, ncores=0, metadata=None, origin=None): def autopickevent(data, param, iplot=0, fig_dict=None, fig_dict_wadatijack=None, ncores=0, metadata=None, origin=None):
@ -301,7 +302,6 @@ class PickingResults(dict):
# Station information # Station information
s.network = network s.network = network
s.channel = channel s.channel = channel
# Pick results # Pick results
s.lpp = self.lpickS s.lpp = self.lpickS
s.mpp = self.mpickS s.mpp = self.mpickS
@ -385,34 +385,25 @@ class AutopickStation(object):
# save streams and traces # save streams and traces
self.zstream, self.nstream, self.estream = self.get_components_from_waveformstream() self.zstream, self.nstream, self.estream = self.get_components_from_waveformstream()
if len(self.zstream) == 0: self.ztrace, self.ntrace, self.etrace = self.get_traces_from_streams()
msg = 'No Z-component found for station {}. STOP'.format(self.wfstream[0].stats.station)
raise MissingTraceException(msg)
if len(self.nstream) == len(self.estream) == 0:
#TODO correct handling of missing both horizontal traces
msg = 'No horizontal traces found for station {}. STOP'.format(self.wfstream[0].stats.station)
raise MissingTraceException(msg)
self.ztrace = self.zstream[0]
try:
self.ntrace = self.nstream[0]
except IndexError:
# if N trace is misisng, copy E trace
self.nstream = self.estream
self.ntrace = self.nstream[0]
try:
# if E trace is missing, copy N trace
self.etrace = self.estream[0]
except IndexError:
self.estream = self.nstream
self.etrace = self.estream[0]
# default values used in old autopickstation function #TODO way for user to set those # default values used in old autopickstation function
# #TODO way for user to set those
self.detrend_type = 'demean' self.detrend_type = 'demean'
self.filter_type = 'bandpass' self.filter_type = 'bandpass'
self.zerophase = False self.zerophase = False
self.taper_max_percentage = 0.05 self.taper_max_percentage = 0.05
self.taper_type = 'hann' self.taper_type = 'hann'
def horizontal_traces_exist(self):
"""
Return true when at least one horizontal traces exists
:rtype: bool
"""
if len(self.nstream) == len(self.estream) == 0:
return False
return True
def vprint(self, s): def vprint(self, s):
"""Only print statement if verbose picking is set to true.""" """Only print statement if verbose picking is set to true."""
if self.verbose: if self.verbose:
@ -455,7 +446,8 @@ class AutopickStation(object):
:param waveformstream: Stream containing all three components for one station either by ZNE or 123 channel code :param waveformstream: Stream containing all three components for one station either by ZNE or 123 channel code
(mixture of both options is handled as well) (mixture of both options is handled as well)
:type waveformstream: obspy.core.stream.Stream :type waveformstream: obspy.core.stream.Stream
:return: Tuple containing (z waveform, n waveform, e waveform) selected by the given channels :return: Tuple containing (z waveform, n waveform, e waveform) selected by the given channels. If no waveform
could be found for a given channel, an empty obspy Stream will be returned for that channel
:rtype: (obspy.core.stream.Stream, obspy.core.stream.Stream, obspy.core.stream.Stream) :rtype: (obspy.core.stream.Stream, obspy.core.stream.Stream, obspy.core.stream.Stream)
""" """
waveform_data = {} waveform_data = {}
@ -465,6 +457,36 @@ class AutopickStation(object):
waveform_data[key] = self.wfstream.select(component=str(self.channelorder[key])) # use 123 as second option waveform_data[key] = self.wfstream.select(component=str(self.channelorder[key])) # use 123 as second option
return waveform_data['Z'], waveform_data['N'], waveform_data['E'] return waveform_data['Z'], waveform_data['N'], waveform_data['E']
def get_traces_from_streams(self):
"""
Extract Trace from Stream. If a component has data, an empty trace will be returned
:return: Tuple of obspy.Trace instances in order ZNE
:rtype: (obspy.Trace)
"""
if len(self.zstream) == 0:
msg = 'No Z-component found for station {}. STOP'.format(self.wfstream[0].stats.station)
raise MissingTraceException(msg)
if not self.horizontal_traces_exist():
# Both horizontal traces missing, only P pick can be determined
msg = 'No horizontal traces found for station {}'.format(self.wfstream[0].stats.station)
self.vprint(msg)
return self.zstream[0], Trace(), Trace()
ztrace = self.zstream[0]
try:
ntrace = self.nstream[0]
except IndexError:
# if N trace is missing, copy E trace
self.nstream = self.estream
ntrace = self.nstream[0]
try:
# if E trace is missing, copy N trace
etrace = self.estream[0]
except IndexError:
self.estream = self.nstream
etrace = self.estream[0]
return ztrace, ntrace, etrace
def prepare_wfstream(self, wfstream, freqmin=None, freqmax=None): def prepare_wfstream(self, wfstream, freqmin=None, freqmax=None):
""" """
Prepare a waveformstream for picking by applying detrending, filtering and tapering. Creates a copy of the Prepare a waveformstream for picking by applying detrending, filtering and tapering. Creates a copy of the
@ -571,7 +593,7 @@ class AutopickStation(object):
except PickingFailedException as pfe: except PickingFailedException as pfe:
print(pfe) print(pfe)
if self.p_results.Pweight is not None and self.p_results.Pweight < 4: if self.horizontal_traces_exist() and self.p_results.Pweight is not None and self.p_results.Pweight < 4:
try: try:
self.pick_s_phase() self.pick_s_phase()
except MissingTraceException as mte: except MissingTraceException as mte:
@ -607,13 +629,14 @@ class AutopickStation(object):
# #
# S results # S results
# #
if not self.horizontal_traces_exist():
# no horizontal components means there is no S pick to be finished
return
if self.etrace: if self.etrace:
hdat = self.etrace hdat = self.etrace
elif self.ntrace: elif self.ntrace:
hdat = self.ntrace hdat = self.ntrace
# TODO picks are calculated with stats from E trace if it exists, otherwise stats from N trace is used.
# What if the stats are different?
if self.s_results.lpickS is not None and self.s_results.lpickS == self.s_results.mpickS: if self.s_results.lpickS is not None and self.s_results.lpickS == self.s_results.mpickS:
self.s_results.lpickS += hdat.stats.delta self.s_results.lpickS += hdat.stats.delta
if self.s_results.epickS is not None and self.s_results.epickS == self.s_results.mpickS: if self.s_results.epickS is not None and self.s_results.epickS == self.s_results.mpickS:
@ -684,7 +707,7 @@ class AutopickStation(object):
ax1.set_ylim([-1.5, 1.5]) ax1.set_ylim([-1.5, 1.5])
ax1.set_ylabel('Normalized Counts') ax1.set_ylabel('Normalized Counts')
if self.s_results.Sflag == 1: if self.horizontal_traces_exist() and self.s_results.Sflag == 1:
# plot E trace # plot E trace
ax2 = fig.add_subplot(3, 1, 2, sharex=ax1) ax2 = fig.add_subplot(3, 1, 2, sharex=ax1)
th1data = np.linspace(0, self.etrace.stats.npts*self.etrace.stats.delta, self.etrace.stats.npts) th1data = np.linspace(0, self.etrace.stats.npts*self.etrace.stats.delta, self.etrace.stats.npts)
@ -1012,7 +1035,6 @@ class AutopickStation(object):
if aicarhpick.getpick() is None: if aicarhpick.getpick() is None:
error_msg = 'Invalid AIC S pick!' error_msg = 'Invalid AIC S pick!'
raise PickingFailedException(error_msg) raise PickingFailedException(error_msg)
#if slope >= self.s_params.minAICSslope and aicarhpick.getSNR() >= self.s_params.minAICSSNR and aicarhpick.getpick() is not None:
self.s_results.aicSflag = 1 self.s_results.aicSflag = 1
msg = 'AIC S-pick passes quality control: Slope: {0} counts/s, ' \ msg = 'AIC S-pick passes quality control: Slope: {0} counts/s, ' \
'SNR: {1}\nGo on with refined picking ...\n' \ 'SNR: {1}\nGo on with refined picking ...\n' \