[change] PickingResults now only stores actual results, PickingContainer stores intermediary values

PickingResults now stores only the actual results of picking, which are returned from the autopickstation function. 
To store intermediary results during picking, the new class PickingContainer is used.
This commit is contained in:
Darius Arnold 2018-08-03 10:59:10 +02:00
parent 076115f7f5
commit 8dcea2a8c3
2 changed files with 125 additions and 209 deletions

View File

@ -180,47 +180,11 @@ class PickingParameters(object):
class PickingResults(dict):
"""
Store picking results
"""
def init_for_picking(self):
"""
Initialize intermediary values of PickingResults used during pick calculation.
:return:
:rtype:
"""
# initialize output
self.Pweight = 4 # weight for P onset
self.Sweight = 4 # weight for S onset
self.FM = 'N' # first motion (polarity)
self.SNRP = None # signal-to-noise ratio of P onset
self.SNRPdB = None # signal-to-noise ratio of P onset [dB]
self.SNRS = None # signal-to-noise ratio of S onset
self.SNRSdB = None # signal-to-noise ratio of S onset [dB]
self.mpickP = None # most likely P onset
self.lpickP = None # latest possible P onset
self.epickP = None # earliest possible P onset
self.mpickS = None # most likely S onset
self.lpickS = None # latest possible S onset
self.epickS = None # earliest possible S onset
self.Perror = None # symmetrized picking error P onset
self.Serror = None # symmetrized picking error S onset
self.Pmarker = []
self.Ao = None # Wood-Anderson peak-to-peak amplitude
self.picker = 'auto' # type of picks
# these get added during the construction of the p pick results dictionary
self.w0 = None
self.fc = None
self.Mw = None
self.Mo = None
# flags for plotting
self.p_aic_plot_flag = 0
self.aicSflag = 0
self.Pflag = 0
self.Sflag = 0
def init_default_values(self):
def __init__(self):
"""
Inits default values of picking results. Called to generate a clean
PickingResults instance with sensible defaults.
@ -234,87 +198,25 @@ class PickingResults(dict):
# TODO What are those?
self.w0 = None
self.fc = None
self.Ao = None # Wood-Anderson peak-to-peak amplitude
# Station information
self.network = None
self.channel = None
# pick information
self.picker = 'auto'
self.picker = 'auto' # type of pick
self.marked = []
# pick results
self.epp = None
self.mpp = None
self.lpp = None
self.fm = 'N'
self.snr = None
self.snrdb = None
self.spe = None
self.weight = 4
def make_clean_results(self, pick, channel, network):
"""
Create a new PickingResults instance that only contains relevant results.
No intermediate pick information is saved in the new PickingResults.
:param pick: decides P or S pick results are collected
:type pick: str
:param channel: channel on which the pick was calculated
:type channel: str
:param network: Network id of station
:type network: str
:return:
:rtype: PickingResults
"""
if pick.upper() == 'P':
p = PickingResults()
p.init_default_values()
# Magnitude parameters
p.Mo = self.Mo
p.Mw = self.Mw
# TODO What are those?
p.w0 = self.w0
p.fc = self.fc
# Station information
p.network = network
p.channel = channel
# pick information
p.picker = self.picker
p.marked = self.Pmarker
# pick results
p.epp = self.epickP
p.mpp = self.mpickP
p.lpp = self.lpickP
p.fm = self.FM
p.snr = self.SNRP
p.snrdb = self.SNRPdB
p.spe = self.Perror
p.weight = self.Pweight
return p
if pick.upper() == 'S':
s = PickingResults()
s.init_default_values()
# Station information
s.network = network
s.channel = channel
# Pick results
s.lpp = self.lpickS
s.mpp = self.mpickS
s.epp = self.epickS
s.spe = self.Serror
s.snr = self.SNRS
s.snrdb = self.SNRSdB
s.weight = self.Sweight
s.fm = None
s.picker = self.picker
s.Ao = self.Ao
return s
self.epp = None # earliest possible pick
self.mpp = None # most likely onset
self.lpp = None # latest possible pick
self.fm = 'N' # first motion polarity, can be set to 'U' (Up) or 'D' (Down)
self.snr = None # signal-to-noise ratio of onset
self.snrdb = None # signal-to-noise ratio of onset [dB]
self.spe = None # symmetrized picking error
self.weight = 4 # weight of onset
def __setattr__(self, key, value):
self[key] = value
@ -323,6 +225,19 @@ class PickingResults(dict):
return self[key]
class PickingContainer:
"""
Keeps intermediary results and values during picking
"""
def __init__(self):
# flags for plotting
self.p_aic_plot_flag = 0
self.aicSflag = 0
self.Pflag = 0
self.Sflag = 0
class MissingTraceException(ValueError):
"""
Used to indicate missing traces in a obspy.core.stream.Stream object
@ -369,14 +284,15 @@ class AutopickStation(object):
# initialize picking results
self.p_results = PickingResults()
self.p_results.init_for_picking()
self.s_results = PickingResults()
self.s_results.init_for_picking()
# intialize containers that keep intermediary values between picking P- and S phase and plotting
self.p_data = PickingContainer()
self.s_data = PickingContainer()
# extract additional information
pickparams = self.extract_pickparams(pickparam)
self.p_params, self.s_params, self.first_motion_params, self.signal_length_params = pickparams
self.results = PickingResults()
# TODO get channelorder from the pylot preferences
self.channelorder = {'Z': 3, 'N': 1, 'E': 2}
self.station_name = wfstream[0].stats.station
@ -597,7 +513,7 @@ class AutopickStation(object):
except PickingFailedException as pfe:
print(pfe)
if self.horizontal_traces_exist() and self.p_results.Pweight is not None and self.p_results.Pweight < 4:
if self.horizontal_traces_exist() and self.p_results.weight is not None and self.p_results.weight < 4:
try:
self.pick_s_phase()
except MissingTraceException as mte:
@ -612,24 +528,23 @@ class AutopickStation(object):
def finish_picking(self):
# calculate "real" onset times, save them in PickingResults
if self.p_results.lpickP is not None and self.p_results.lpickP == self.p_results.mpickP:
self.p_results.lpickP += self.ztrace.stats.delta
if self.p_results.epickP is not None and self.p_results.epickP == self.p_results.mpickP:
self.p_results.epickP -= self.ztrace.stats.delta
if self.p_results.mpickP is not None and self.p_results.epickP is not None and self.p_results.lpickP is not None:
self.p_results.lpickP = self.ztrace.stats.starttime + self.p_results.lpickP
self.p_results.epickP = self.ztrace.stats.starttime + self.p_results.epickP
self.p_results.mpickP = self.ztrace.stats.starttime + self.p_results.mpickP
if self.p_results.lpp is not None and self.p_results.lpp == self.p_results.mpp:
self.p_results.lpp += self.ztrace.stats.delta
if self.p_results.epp is not None and self.p_results.epp == self.p_results.mpp:
self.p_results.epp -= self.ztrace.stats.delta
if self.p_results.mpp is not None and self.p_results.epp is not None and self.p_results.lpp is not None:
self.p_results.lpp = self.ztrace.stats.starttime + self.p_results.lpp
self.p_results.epp = self.ztrace.stats.starttime + self.p_results.epp
self.p_results.mpp = self.ztrace.stats.starttime + self.p_results.mpp
else:
# dummy values (start of seismic trace) in order to derive
# theoretical onset times for iterative picking
self.p_results.lpickP = self.ztrace.stats.starttime + self.p_params.timeerrorsP[3]
self.p_results.epickP = self.ztrace.stats.starttime - self.p_params.timeerrorsP[3]
self.p_results.mpickP = self.ztrace.stats.starttime
self.p_results = self.p_results.make_clean_results('P', self.ztrace.stats.channel, self.ztrace.stats.network)
# add picking results to PickingResults instance
self.p_results.lpp = self.ztrace.stats.starttime + self.p_params.timeerrorsP[3]
self.p_results.epp = self.ztrace.stats.starttime - self.p_params.timeerrorsP[3]
self.p_results.mpp = self.ztrace.stats.starttime
self.p_results.channel = self.ztrace.stats.channel
self.p_results.network = self.ztrace.stats.network
#
# S results
#
@ -641,22 +556,24 @@ class AutopickStation(object):
elif self.ntrace:
hdat = self.ntrace
if self.s_results.lpickS is not None and self.s_results.lpickS == self.s_results.mpickS:
self.s_results.lpickS += hdat.stats.delta
if self.s_results.epickS is not None and self.s_results.epickS == self.s_results.mpickS:
self.s_results.epickS -= hdat.stats.delta
if self.s_results.mpickS is not None and self.s_results.epickS is not None and self.s_results.lpickS is not None:
self.s_results.lpickS = hdat.stats.starttime + self.s_results.lpickS
self.s_results.epickS = hdat.stats.starttime + self.s_results.epickS
self.s_results.mpickS = hdat.stats.starttime + self.s_results.mpickS
if self.s_results.lpp is not None and self.s_results.lpp == self.s_results.mpp:
self.s_results.lpp += hdat.stats.delta
if self.s_results.epp is not None and self.s_results.epp == self.s_results.mpp:
self.s_results.epp -= hdat.stats.delta
if self.s_results.mpp is not None and self.s_results.epp is not None and self.s_results.lpp is not None:
self.s_results.lpp = hdat.stats.starttime + self.s_results.lpp
self.s_results.epp = hdat.stats.starttime + self.s_results.epp
self.s_results.mpp = hdat.stats.starttime + self.s_results.mpp
else:
# dummy values (start of seismic trace) in order to derive
# theoretical onset times for iteratve picking
self.s_results.lpickS = hdat.stats.starttime + self.s_params.timeerrorsS[3]
self.s_results.epickS = hdat.stats.starttime - self.s_params.timeerrorsS[3]
self.s_results.mpickS = hdat.stats.starttime
self.s_results.lpp = hdat.stats.starttime + self.s_params.timeerrorsS[3]
self.s_results.epp = hdat.stats.starttime - self.s_params.timeerrorsS[3]
self.s_results.mpp = hdat.stats.starttime
self.s_results = self.s_results.make_clean_results('S', self.etrace.stats.channel, self.etrace.stats.network)
self.s_results.channel = self.etrace.stats.channel
self.s_results.network = self.etrace.stats.network
self.s_results.fm = None # override default value 'N'
def plot_pick_results(self):
if self.iplot > 0:
@ -674,12 +591,12 @@ class AutopickStation(object):
tdata = np.linspace(start=0, stop=self.ztrace.stats.npts*self.ztrace.stats.delta, num=self.ztrace.stats.npts)
# plot tapered trace filtered with bpz2 filter settings
ax1.plot(tdata, self.tr_filt_z_bpz2.data/max(self.tr_filt_z_bpz2.data), color=linecolor, linewidth=0.7, label='Data')
if self.p_results.Pweight < 4:
if self.p_results.weight < 4:
# plot CF of initial onset (HOScf or ARZcf)
ax1.plot(self.cf1.getTimeArray(), self.cf1.getCF()/max(self.cf1.getCF()), 'b', label='CF1')
if self.p_results.p_aic_plot_flag == 1:
aicpick = self.p_results.aicpick
refPpick = self.p_results.refPpick
if self.p_data.p_aic_plot_flag == 1:
aicpick = self.p_data.aicpick
refPpick = self.p_data.refPpick
# plot CF of precise pick (HOScf or ARZcf)
ax1.plot(self.cf2.getTimeArray(), self.cf2.getCF() / max(self.cf2.getCF()), 'm', label='CF2')
# plot inital P pick
@ -691,36 +608,36 @@ class AutopickStation(object):
ax1.plot([refPpick.getpick() - 0.5, refPpick.getpick() + 0.5], [1.3, 1.3], 'r', linewidth=2)
ax1.plot([refPpick.getpick() - 0.5, refPpick.getpick() + 0.5], [-1.3, -1.3], 'r', linewidth=2)
# plot latest possible P pick
ax1.plot([self.p_results.lpickP, self.p_results.lpickP], [-1.1, 1.1], 'r--', label='lpp')
ax1.plot([self.p_results.lpp, self.p_results.lpp], [-1.1, 1.1], 'r--', label='lpp')
# plot earliest possible P pick
ax1.plot([self.p_results.epickP, self.p_results.epickP], [-1.1, 1.1], 'r--', label='epp')
ax1.plot([self.p_results.epp, self.p_results.epp], [-1.1, 1.1], 'r--', label='epp')
# add title to plot
title = '{station}, {channel}, P weight={pweight:d}, SNR={snr:7.2}, SNR[dB]={snrdb:7.2}, Polarity: {polarity}'
ax1.set_title(title.format(station=self.ztrace.stats.station,
channel=self.ztrace.stats.channel,
pweight=self.p_results.Pweight,
snr=self.p_results.SNRP,
snrdb=self.p_results.SNRPdB,
polarity=self.p_results.FM))
pweight=self.p_results.weight,
snr=self.p_results.snr,
snrdb=self.p_results.snrdb,
polarity=self.p_results.fm))
else:
title = '{channel}, P weight={pweight}, SNR=None, SNR[dB]=None'
ax1.set_title(title.format(channel=self.ztrace.stats.channel, pweight=self.p_results.Pweight))
ax1.set_title(title.format(channel=self.ztrace.stats.channel, pweight=self.p_results.weight))
ax1.legend(loc=1)
ax1.set_yticks([])
ax1.set_ylim([-1.5, 1.5])
ax1.set_ylabel('Normalized Counts')
if self.horizontal_traces_exist() and self.s_results.Sflag == 1:
if self.horizontal_traces_exist() and self.s_data.Sflag == 1:
# plot E trace
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)
# plot filtered and tapered waveform
ax2.plot(th1data, self.etrace.data / max(self.etrace.data), color=linecolor, linewidth=0.7, label='Data')
if self.p_results.Pweight < 4:
if self.p_results.weight < 4:
# plot initial CF (ARHcf or AR3Ccf)
ax2.plot(self.arhcf1.getTimeArray(), self.arhcf1.getCF() / max(self.arhcf1.getCF()), 'b', label='CF1')
if self.s_results.aicSflag == 1 and self.s_results.Sweight <= 4:
if self.s_data.aicSflag == 1 and self.s_results.weight <= 4:
aicarhpick = self.aicarhpick
refSpick = self.refSpick
# plot second cf, used for determing precise onset (ARHcf or AR3Ccf)
@ -733,16 +650,16 @@ class AutopickStation(object):
ax2.plot([refSpick.getpick(), refSpick.getpick()], [-1.3, 1.3], 'g', linewidth=2, label='Final S Pick')
ax2.plot([refSpick.getpick() - 0.5, refSpick.getpick() + 0.5], [1.3, 1.3], 'g', linewidth=2)
ax2.plot([refSpick.getpick() - 0.5, refSpick.getpick() + 0.5], [-1.3, -1.3], 'g', linewidth=2)
ax2.plot([self.s_results.lpickS, self.s_results.lpickS], [-1.1, 1.1], 'g--', label='lpp')
ax2.plot([self.s_results.epickS, self.s_results.epickS], [-1.1, 1.1], 'g--', label='epp')
ax2.plot([self.s_results.lpp, self.s_results.lpp], [-1.1, 1.1], 'g--', label='lpp')
ax2.plot([self.s_results.epp, self.s_results.epp], [-1.1, 1.1], 'g--', label='epp')
title = '{channel}, S weight={sweight}, SNR={snr:7.2}, SNR[dB]={snrdb:7.2}'
ax2.set_title(title.format(channel=self.etrace.stats.channel,
sweight=self.s_results.Sweight,
snr=self.s_results.SNRS,
snrdb=self.s_results.SNRSdB))
sweight=self.s_results.weight,
snr=self.s_results.snr,
snrdb=self.s_results.snrdb))
else:
title = '{channel}, S weight={sweight}, SNR=None, SNR[dB]=None'
ax2.set_title(title.format(channel=self.etrace.stats.channel, sweight=self.s_results.Sweight))
ax2.set_title(title.format(channel=self.etrace.stats.channel, sweight=self.s_results.weight))
ax2.legend(loc=1)
ax2.set_yticks([])
ax2.set_ylim([-1.5, 1.5])
@ -753,9 +670,9 @@ class AutopickStation(object):
th2data= np.linspace(0, self.ntrace.stats.npts*self.ntrace.stats.delta, self.ntrace.stats.npts)
# plot trace
ax3.plot(th2data, self.ntrace.data / max(self.ntrace.data), color=linecolor, linewidth=0.7, label='Data')
if self.p_results.Pweight < 4:
if self.p_results.weight < 4:
p22, = ax3.plot(self.arhcf1.getTimeArray(), self.arhcf1.getCF() / max(self.arhcf1.getCF()), 'b', label='CF1')
if self.s_results.aicSflag == 1:
if self.s_data.aicSflag == 1:
aicarhpick = self.aicarhpick
refSpick = self.refSpick
ax3.plot(self.arhcf2.getTimeArray(), self.arhcf2.getCF() / max(self.arhcf2.getCF()), 'm', label='CF2')
@ -766,8 +683,8 @@ class AutopickStation(object):
label='Final S Pick')
ax3.plot([refSpick.getpick() - 0.5, refSpick.getpick() + 0.5], [1.3, 1.3], 'g', linewidth=2)
ax3.plot([refSpick.getpick() - 0.5, refSpick.getpick() + 0.5], [-1.3, -1.3], 'g', linewidth=2)
ax3.plot([self.s_results.lpickS, self.s_results.lpickS], [-1.1, 1.1], 'g--', label='lpp')
ax3.plot([self.s_results.epickS, self.s_results.epickS], [-1.1, 1.1], 'g--', label='epp')
ax3.plot([self.s_results.lpp, self.s_results.lpp], [-1.1, 1.1], 'g--', label='lpp')
ax3.plot([self.s_results.epp, self.s_results.epp], [-1.1, 1.1], 'g--', label='epp')
ax3.legend(loc=1)
ax3.set_yticks([])
ax3.set_ylim([-1.5, 1.5])
@ -823,8 +740,8 @@ class AutopickStation(object):
self.signal_length_params.noisefactor, self.signal_length_params.minpercent,
self.iplot, self.current_figure, self.current_linecolor)
if Pflag == 0:
self.p_results.Pmarker = 'shortsignallength'
self.p_results.Pweight = 9
self.p_results.marked = 'shortsignallength'
self.p_results.weight = 9
return 0
if self.nstream == self.estream:
@ -837,8 +754,8 @@ class AutopickStation(object):
Pflag = checkZ4S(zne, aicpick.getpick(), self.s_params.zfac, self.p_params.tsnrz[2], self.iplot,
self.current_figure, self.current_linecolor)
if Pflag == 0:
self.p_results.Pmarker = 'SinsteadP'
self.p_results.Pweight = 9
self.p_results.marked = 'SinsteadP'
self.p_results.weight = 9
return 0
return 1
@ -885,7 +802,7 @@ class AutopickStation(object):
aicpick = AICPicker(aiccf, self.p_params.tsnrz, self.p_params.pickwinP, self.iplot,
Tsmooth=self.p_params.aictsmooth, fig=self.current_figure, linecolor=self.current_linecolor)
# save aicpick for plotting later
self.p_results.aicpick = aicpick
self.p_data.aicpick = aicpick
# add pstart and pstop to aic plot
if self.current_figure:
# TODO remove plotting from picking, make own plot function
@ -908,7 +825,7 @@ class AutopickStation(object):
error_msg = 'AIC P onset SNR to small: got {}, min {}'.format(aicpick.getSNR(), self.p_params.minAICPSNR)
raise PickingFailedException(error_msg)
self.p_results.p_aic_plot_flag = 1
self.p_data.p_aic_plot_flag = 1
msg = 'AIC P-pick passes quality control: Slope: {0} counts/s, SNR: {1}\nGo on with refined picking ...\n' \
'autopickstation: re-filtering vertical trace...'.format(aicpick.getSlope(), aicpick.getSNR())
self.vprint(msg)
@ -931,37 +848,38 @@ class AutopickStation(object):
refPpick = PragPicker(self.cf2, self.p_params.tsnrz, self.p_params.pickwinP, self.iplot, self.p_params.ausP,
self.p_params.tsmoothP, aicpick.getpick(), self.current_figure, self.current_linecolor)
# save PragPicker result for plotting
self.p_results.refPpick = refPpick
self.p_results.mpickP = refPpick.getpick()
if self.p_results.mpickP is None:
self.p_data.refPpick = refPpick
self.p_results.mpp = refPpick.getpick()
if self.p_results.mpp is None:
msg = 'Bad initial (AIC) P-pick, skipping this onset!\n AIC-SNR={}, AIC-Slope={}counts/s\n' \
'(min. AIC-SNR={}, min. AIC-Slope={}counts/s)'
msg.format(aicpick.getSNR(), aicpick.getSlope(), self.p_params.minAICPSNR, self.p_params.minAICPslope)
self.vprint(msg)
self.s_results.Sflag = 0
self.s_data.Sflag = 0
raise PickingFailedException(msg)
# quality assessment, get earliest/latest pick and symmetrized uncertainty
#todo quality assessment in own function
self.set_current_figure('el_Ppick')
elpicker_results = earllatepicker(z_copy, self.p_params.nfacP, self.p_params.tsnrz, self.p_results.mpickP,
elpicker_results = earllatepicker(z_copy, self.p_params.nfacP, self.p_params.tsnrz, self.p_results.mpp,
self.iplot, fig=self.current_figure, linecolor=self.current_linecolor)
self.p_results.epickP, self.p_results.lpickP, self.p_results.Perror = elpicker_results
snr_results = getSNR(z_copy, self.p_params.tsnrz, self.p_results.mpickP)
self.p_results.SNRP, self.p_results.SNRPdB, self.p_results.Pnoiselevel = snr_results
self.p_results.epp, self.p_results.lpp, self.p_results.spe = elpicker_results
snr_results = getSNR(z_copy, self.p_params.tsnrz, self.p_results.mpp)
self.p_results.snr, self.p_results.snrdb, _ = snr_results
# weight P-onset using symmetric error
self.p_results.Pweight = get_quality_class(self.p_results.Perror, self.p_params.timeerrorsP)
if self.p_results.Pweight <= self.first_motion_params.minfmweight and self.p_results.SNRP >= self.first_motion_params.minFMSNR:
self.p_results.weight = get_quality_class(self.p_results.spe, self.p_params.timeerrorsP)
if self.p_results.weight <= self.first_motion_params.minfmweight and self.p_results.snr >= self.first_motion_params.minFMSNR:
# if SNR is low enough, try to determine first motion of onset
self.set_current_figure('fm_picker')
self.p_results.FM = fmpicker(self.zstream, z_copy, self.first_motion_params.fmpickwin,
self.p_results.mpickP, self.iplot, self.current_figure, self.current_linecolor)
self.p_results.fm = fmpicker(self.zstream, z_copy, self.first_motion_params.fmpickwin,
self.p_results.mpp, self.iplot, self.current_figure, self.current_linecolor)
msg = "autopickstation: P-weight: {}, SNR: {}, SNR[dB]: {}, Polarity: {}"
msg = msg.format(self.p_results.Pweight, self.p_results.SNRP, self.p_results.SNRPdB, self.p_results.FM)
msg = msg.format(self.p_results.weight, self.p_results.snr, self.p_results.snrdb, self.p_results.fm)
print(msg)
msg = 'autopickstation: Refined P-Pick: {} s | P-Error: {} s'
msg = msg.format(self.p_results.mpickP, self.p_results.Perror)
msg = msg.format(self.p_results.mpp, self.p_results.spe)
print(msg)
self.s_results.Sflag = 1
self.s_data.Sflag = 1
def _calculate_cuttimes(self, type, iteration):
"""
@ -978,16 +896,16 @@ class AutopickStation(object):
if iteration == 1:
return [self.p_params.pstart, self.p_params.pstop]
if iteration == 2:
starttime2 = round(max(self.p_results.aicpick.getpick() - self.p_params.Precalcwin, 0))
starttime2 = round(max(self.p_data.aicpick.getpick() - self.p_params.Precalcwin, 0))
endtime2 = round(
min(len(self.ztrace.data) * self.ztrace.stats.delta, self.p_results.aicpick.getpick() + self.p_params.Precalcwin))
min(len(self.ztrace.data) * self.ztrace.stats.delta, self.p_data.aicpick.getpick() + self.p_params.Precalcwin))
return [starttime2, endtime2]
elif type.upper() == 'S':
if iteration == 1:
# Calculate start times for preliminary S onset
start = round(max(self.p_results.mpickP + self.s_params.sstart, 0)) # limit start time to >0 seconds
start = round(max(self.p_results.mpp + self.s_params.sstart, 0)) # limit start time to >0 seconds
stop = round(min([
self.p_results.mpickP + self.s_params.sstop,
self.p_results.mpp + self.s_params.sstop,
self.etrace.stats.endtime - self.etrace.stats.starttime,
self.ntrace.stats.endtime - self.ntrace.stats.starttime
]))
@ -1059,7 +977,7 @@ class AutopickStation(object):
if self.aicarhpick.getpick() is None:
error_msg = 'Invalid AIC S pick!'
raise PickingFailedException(error_msg)
self.s_results.aicSflag = 1
self.s_data.aicSflag = 1
msg = 'AIC S-pick passes quality control: Slope: {0} counts/s, ' \
'SNR: {1}\nGo on with refined picking ...\n' \
'autopickstation: re-filtering horizontal traces ' \
@ -1105,7 +1023,7 @@ class AutopickStation(object):
if self.iplot:
self.set_current_figure('el_S1pick')
epickS1, lpickS1, Serror1 = earllatepicker(h_copy, self.s_params.nfacS, self.s_params.tsnrh,
self.s_results.mpickS, self.iplot, fig=self.current_figure,
self.s_results.mpp, self.iplot, fig=self.current_figure,
linecolor=self.current_linecolor)
h_copy[0].data = self.nstream_bph2.data
@ -1115,7 +1033,7 @@ class AutopickStation(object):
# why is it set to empty here? DA
linecolor = ''
epickS2, lpickS2, Serror2 = earllatepicker(h_copy, self.s_params.nfacS, self.s_params.tsnrh,
self.s_results.mpickS, self.iplot, fig=self.current_figure,
self.s_results.mpp, self.iplot, fig=self.current_figure,
linecolor=self.current_linecolor)
if epickS1 is not None and epickS2 is not None:
@ -1127,7 +1045,7 @@ class AutopickStation(object):
ipick = np.argmin(epick)
if self.s_params.algoS == 'AR3':
epickS3, lpickS3, Serror3 = earllatepicker(h_copy, self.s_params.nfacS, self.s_params.tsnrh,
self.s_results.mpickS, self.iplot)
self.s_results.mpp, self.iplot)
# get earliest of all three picks
epick = [epickS1, epickS2, epickS3]
lpick = [lpickS1, lpickS2, lpickS3]
@ -1137,24 +1055,23 @@ class AutopickStation(object):
ipick = np.argmin(epick)
else:
ipick = np.argmin([epickS1, epickS2])
self.s_results.epickS = epick[ipick]
self.s_results.lpickS = lpick[ipick]
self.s_results.Serror = pickerr[ipick]
self.s_results.epp = epick[ipick]
self.s_results.lpp = lpick[ipick]
self.s_results.spe = pickerr[ipick]
msg = 'autopickstation: Refined S-Pick: {} s | S-Error: {} s'.format(self.s_results.mpickS,
self.s_results.Serror)
msg = 'autopickstation: Refined S-Pick: {} s | S-Error: {} s'.format(self.s_results.mpp,
self.s_results.spe)
print(msg)
# get SNR
self.s_results.SNRS, self.s_results.SNRSdB, self.s_results.Snoiselevel = getSNR(h_copy, self.s_params.tsnrh,
self.s_results.mpickS)
self.s_results.snr, self.s_results.snrdb, _ = getSNR(h_copy, self.s_params.tsnrh, self.s_results.mpp)
self.s_results.Sweight = get_quality_class(self.s_results.Serror, self.s_params.timeerrorsS)
self.s_results.weight = get_quality_class(self.s_results.spe, self.s_params.timeerrorsS)
print('autopickstation: S-weight: {0}, SNR: {1}, '
'SNR[dB]: {2}\n'
'##################################################'
''.format(self.s_results.Sweight, self.s_results.SNRS, self.s_results.SNRSdB))
''.format(self.s_results.weight, self.s_results.snr, self.s_results.snrdb))
def pick_s_phase(self):
@ -1185,9 +1102,9 @@ class AutopickStation(object):
self.s_params.tsmoothS, aicarhpick.getpick(), self.current_figure, self.current_linecolor)
# save refSpick for later plotitng
self.refSpick = refSpick
self.s_results.mpickS = refSpick.getpick()
self.s_results.mpp = refSpick.getpick()
if self.s_results.mpickS is not None:
if self.s_results.mpp is not None:
self._pick_s_quality_assessment(self.h_copy)
def set_current_figure(self, figkey):

View File

@ -178,15 +178,14 @@ class TestAutopickStation(unittest.TestCase):
"""Picking on a stream without horizontal traces should still pick the P phase on the vertical component"""
wfstream = self.gra1.copy()
wfstream = wfstream.select(channel='*Z')
expected = {'P': {'picker': 'auto', 'snrdb': 15.405649120980094, 'network': u'GR', 'weight': 0, 'Mo': None, 'marked': [], 'lpp': UTCDateTime(2016, 1, 24, 10, 41, 32, 690000), 'Mw': None, 'fc': None, 'snr': 34.718816470730317, 'epp': UTCDateTime(2016, 1, 24, 10, 41, 28, 890000), 'mpp': UTCDateTime(2016, 1, 24, 10, 41, 31, 690000), 'w0': None, 'spe': 0.9333333333333323, 'fm': 'D', 'channel': u'LHZ'}, 'S': {'picker': 'auto', 'Sweight': 4, 'w0': None, 'epickP': None, 'epickS': None, 'FM': 'N', 'p_aic_plot_flag': 0, 'Serror': None, 'aicSflag': 0, 'Perror': None, 'lpickS': None, 'Mo': None, 'lpickP': None, 'Mw': None, 'fc': None, 'SNRSdB': None, 'Pweight': 4, 'Pflag': 0, 'Pmarker': [], 'mpickP': None, 'Ao': None, 'mpickS': None, 'SNRP': None, 'SNRS': None, 'Sflag': 1, 'SNRPdB': None}, 'station': u'GRA1'}
expected = {'P': {'picker': 'auto', 'snrdb': 15.405649120980094, 'network': u'GR', 'weight': 0, 'Ao': None, 'Mo': None, 'marked': [], 'lpp': UTCDateTime(2016, 1, 24, 10, 41, 32, 690000), 'Mw': None, 'fc': None, 'snr': 34.718816470730317, 'epp': UTCDateTime(2016, 1, 24, 10, 41, 28, 890000), 'mpp': UTCDateTime(2016, 1, 24, 10, 41, 31, 690000), 'w0': None, 'spe': 0.9333333333333323, 'fm': 'D', 'channel': u'LHZ'}, 'S': {'picker': 'auto', 'snrdb': None, 'network': None, 'weight': 4, 'Mo': None, 'Ao': None, 'lpp': None, 'Mw': None, 'fc': None, 'snr': None, 'marked': [], 'mpp': None, 'w0': None, 'spe': None, 'epp': None, 'fm': 'N', 'channel': None}, 'station': u'GRA1'}
with HidePrints():
result = autopickstation(wfstream=wfstream, pickparam=self.pickparam_taupy_disabled, metadata=(None, None))
print(result['S'])
self.assertEqual(expected, result)
def test_autopickstation_a106_taupy_enabled(self):
"""This station has invalid values recorded on both N and E component, but a pick can still be found on Z"""
expected = {'P': {'picker': 'auto', 'snrdb': 12.862128789922826, 'network': u'Z3', 'weight': 0, 'Mo': None, 'marked': [], 'lpp': UTCDateTime(2016, 1, 24, 10, 41, 34), 'Mw': None, 'fc': None, 'snr': 19.329155459132608, 'epp': UTCDateTime(2016, 1, 24, 10, 41, 30), 'mpp': UTCDateTime(2016, 1, 24, 10, 41, 33), 'w0': None, 'spe': 1.6666666666666667, 'fm': None, 'channel': u'LHZ'}, 'S': {'picker': 'auto', 'snrdb': None, 'network': u'Z3', 'weight': 4, 'Ao': None, 'Mo': None, 'marked': [], 'lpp': UTCDateTime(2016, 1, 24, 10, 28, 56), 'Mw': None, 'fc': None, 'snr': None, 'epp': UTCDateTime(2016, 1, 24, 10, 28, 24), 'mpp': UTCDateTime(2016, 1, 24, 10, 28, 40), 'w0': None, 'spe': None, 'fm': None, 'channel': u'LHE'}, 'station': u'A106A'}
expected = {'P': {'picker': 'auto', 'snrdb': 12.862128789922826, 'network': u'Z3', 'weight': 0, 'Ao': None, 'Mo': None, 'marked': [], 'lpp': UTCDateTime(2016, 1, 24, 10, 41, 34), 'Mw': None, 'fc': None, 'snr': 19.329155459132608, 'epp': UTCDateTime(2016, 1, 24, 10, 41, 30), 'mpp': UTCDateTime(2016, 1, 24, 10, 41, 33), 'w0': None, 'spe': 1.6666666666666667, 'fm': None, 'channel': u'LHZ'}, 'S': {'picker': 'auto', 'snrdb': None, 'network': u'Z3', 'weight': 4, 'Ao': None, 'Mo': None, 'marked': [], 'lpp': UTCDateTime(2016, 1, 24, 10, 28, 56), 'Mw': None, 'fc': None, 'snr': None, 'epp': UTCDateTime(2016, 1, 24, 10, 28, 24), 'mpp': UTCDateTime(2016, 1, 24, 10, 28, 40), 'w0': None, 'spe': None, 'fm': None, 'channel': u'LHE'}, 'station': u'A106A'}
with HidePrints():
result = autopickstation(wfstream=self.a106, pickparam=self.pickparam_taupy_enabled, metadata=self.metadata, origin=self.origin)
self.assertEqual(expected, result)