[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:
parent
076115f7f5
commit
8dcea2a8c3
@ -180,47 +180,11 @@ class PickingParameters(object):
|
||||
|
||||
|
||||
class PickingResults(dict):
|
||||
|
||||
def init_for_picking(self):
|
||||
"""
|
||||
Initialize intermediary values of PickingResults used during pick calculation.
|
||||
:return:
|
||||
:rtype:
|
||||
Store picking results
|
||||
"""
|
||||
# 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):
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user