From 0fb6e5d4df7a671790df1063ddac980ed8dfa66d Mon Sep 17 00:00:00 2001 From: Marcel Paffrath Date: Thu, 1 Jun 2017 15:25:43 +0200 Subject: [PATCH] [bugfix] pickDlg takes into account timeshift of trace.starttime for different components [add] initial pick displayed in pickDlg --- QtPyLoT.py | 22 ++++++---- pylot/RELEASE-VERSION | 2 +- pylot/core/io/phases.py | 2 +- pylot/core/pick/utils.py | 23 +++++++--- pylot/core/util/dataprocessing.py | 3 +- pylot/core/util/widgets.py | 71 ++++++++++++++++++++----------- 6 files changed, 83 insertions(+), 40 deletions(-) diff --git a/QtPyLoT.py b/QtPyLoT.py index 84a906a4..7935eafb 100755 --- a/QtPyLoT.py +++ b/QtPyLoT.py @@ -1616,18 +1616,24 @@ class MainWindow(QMainWindow): colors = phase_col[phase[0].upper()] mpp = picks['mpp'] - stime - epp = picks['epp'] - stime - lpp = picks['lpp'] - stime + if picks['epp'] and picks['lpp']: + epp = picks['epp'] - stime + lpp = picks['lpp'] - stime spe = picks['spe'] - if not spe: + + if not spe and epp and lpp: spe = symmetrize_error(mpp - epp, lpp - mpp) if picktype == 'manual': - ax.fill_between([epp, lpp], ylims[0], ylims[1], - alpha=.25, color=colors[0]) - ax.plot([mpp - spe, mpp - spe], ylims, colors[1], - [mpp, mpp], ylims, colors[2], - [mpp + spe, mpp + spe], ylims, colors[1]) + if picks['epp'] and picks['lpp']: + ax.fill_between([epp, lpp], ylims[0], ylims[1], + alpha=.25, color=colors[0], label='EPP, LPP') + if spe: + ax.plot([mpp - spe, mpp - spe], ylims, colors[1], label='{}-SPE'.format(phase)) + ax.plot([mpp + spe, mpp + spe], ylims, colors[1]) + ax.plot([mpp, mpp], ylims, colors[2], label='{}-Pick'.format(phase)) + else: + ax.plot([mpp, mpp], ylims, colors[6], label='{}-Pick (NO PICKERROR)'.format(phase)) elif picktype == 'auto': ax.plot(mpp, ylims[1], colors[3], mpp, ylims[0], colors[4]) diff --git a/pylot/RELEASE-VERSION b/pylot/RELEASE-VERSION index 31221127..92ef72a4 100644 --- a/pylot/RELEASE-VERSION +++ b/pylot/RELEASE-VERSION @@ -1 +1 @@ -eaa4-dirty +0430-dirty diff --git a/pylot/core/io/phases.py b/pylot/core/io/phases.py index 78b3c6c0..54f30695 100644 --- a/pylot/core/io/phases.py +++ b/pylot/core/io/phases.py @@ -358,7 +358,7 @@ def reassess_pilot_event(root_dir, db_dir, event_id, out_dir=None, fn_param=None default.get('tsnrz' if phase == 'P' else 'tsnrh'), Pick1=rel_pick, iplot=None, - stealth_mode=True) + verbosity=0) if epp is None or lpp is None: continue epp = stime + epp diff --git a/pylot/core/pick/utils.py b/pylot/core/pick/utils.py index 071acedb..9031dd46 100644 --- a/pylot/core/pick/utils.py +++ b/pylot/core/pick/utils.py @@ -14,7 +14,7 @@ import numpy as np from obspy.core import Stream, UTCDateTime -def earllatepicker(X, nfac, TSNR, Pick1, iplot=None, stealth_mode=False, fig=None): +def earllatepicker(X, nfac, TSNR, Pick1, iplot=None, verbosity=1, fig=None): ''' Function to derive earliest and latest possible pick after Diehl & Kissling (2009) as reasonable uncertainties. Latest possible pick is based on noise level, @@ -40,10 +40,16 @@ def earllatepicker(X, nfac, TSNR, Pick1, iplot=None, stealth_mode=False, fig=Non assert isinstance(X, Stream), "%s is not a stream object" % str(X) + if verbosity == 2: + print('earllatepicker:') + print('nfac:', nfac) + print('Init pick:', Pick1) + print('TSNR (T_noise, T_gap, T_signal):', TSNR) + LPick = None EPick = None PickError = None - if stealth_mode is False: + if verbosity: print('earllatepicker: Get earliest and latest possible pick' ' relative to most likely pick ...') @@ -57,11 +63,18 @@ def earllatepicker(X, nfac, TSNR, Pick1, iplot=None, stealth_mode=False, fig=Non x = x - np.mean(x[inoise]) # calculate noise level nlevel = np.sqrt(np.mean(np.square(x[inoise]))) * nfac + if verbosity == 2: + print('x:', x) + print('t:', t) + print('x_inoise:', x[inoise]) + print('x_isignal:', x[isignal]) + print('nlevel:', nlevel) + # get time where signal exceeds nlevel ilup, = np.where(x[isignal] > nlevel) ildown, = np.where(x[isignal] < -nlevel) if not ilup.size and not ildown.size: - if stealth_mode is False: + if verbosity: print ("earllatepicker: Signal lower than noise level!\n" "Skip this trace!") return LPick, EPick, PickError @@ -78,7 +91,7 @@ def earllatepicker(X, nfac, TSNR, Pick1, iplot=None, stealth_mode=False, fig=Non # if EPick stays NaN the signal window size will be doubled while np.isnan(EPick): if count > 0: - if stealth_mode is False: + if verbosity: print("\nearllatepicker: Doubled signal window size %s time(s) " "because of NaN for earliest pick." % count) isigDoubleWinStart = pis[-1] + 1 @@ -87,7 +100,7 @@ def earllatepicker(X, nfac, TSNR, Pick1, iplot=None, stealth_mode=False, fig=Non if (isigDoubleWinStart + len(pis)) < X[0].data.size: pis = np.concatenate((pis, isignalDoubleWin)) else: - if stealth_mode is False: + if verbosity: print("Could not double signal window. Index out of bounds.") break count += 1 diff --git a/pylot/core/util/dataprocessing.py b/pylot/core/util/dataprocessing.py index 82a09caf..dc8536ed 100644 --- a/pylot/core/util/dataprocessing.py +++ b/pylot/core/util/dataprocessing.py @@ -169,7 +169,8 @@ def read_metadata(path_to_inventory): dlfile = list() invfile = list() respfile = list() - inv = dict(dless=dlfile, xml=invfile, resp=respfile) + # possible file extensions specified here: + inv = dict(dless=dlfile, xml=invfile, resp=respfile, dseed=dlfile) if os.path.isfile(path_to_inventory): ext = os.path.splitext(path_to_inventory)[1].split('.')[1] inv[ext] += [path_to_inventory] diff --git a/pylot/core/util/widgets.py b/pylot/core/util/widgets.py index 05d0bf95..fee3d411 100644 --- a/pylot/core/util/widgets.py +++ b/pylot/core/util/widgets.py @@ -431,7 +431,7 @@ class WaveformWidget(FigureCanvas): def plotWFData(self, wfdata, title=None, zoomx=None, zoomy=None, noiselevel=None, scaleddata=False, mapping=True, - component='*', nth_sample=1): + component='*', nth_sample=1, iniPick=None): self.getAxes().cla() self.clearPlotDict() wfstart, wfend = full_range(wfdata) @@ -477,6 +477,11 @@ class WaveformWidget(FigureCanvas): for level in noiselevel: self.getAxes().plot([time_ax[0], time_ax[-1]], [level, level], '--k') + if iniPick: + ax = self.getAxes() + ax.vlines(iniPick, ax.get_ylim()[0], ax.get_ylim()[1], + colors='green', linestyles='dashed', + linewidth=2) self.setPlotDict(n, (station, channel, network)) xlabel = 'seconds since {0}'.format(wfstart) ylabel = '' @@ -954,7 +959,7 @@ class PickDlg(QDialog): parameter = self.parameter ini_pick = gui_event.xdata - + nfac = parameter.get('nfacP') twins = parameter.get('tsnrz') noise_win = twins[0] @@ -965,6 +970,9 @@ class PickDlg(QDialog): while itrace > len(wfdata) - 1: itrace -= 1 + stime = self.getStartTime() + stime_diff = wfdata[itrace].stats.starttime-stime + # copy data for plotting data = self.getWFData().copy() @@ -975,7 +983,7 @@ class PickDlg(QDialog): data.filter(**filteroptions) wfdata.filter(**filteroptions) - result = getSNR(wfdata, (noise_win, gap_win, signal_win), ini_pick, itrace) + result = getSNR(wfdata, (noise_win, gap_win, signal_win), ini_pick-stime_diff, itrace) snr = result[0] noiselevel = result[2] @@ -988,8 +996,8 @@ class PickDlg(QDialog): # remove mean noise level from waveforms for trace in data: - t = prepTimeAxis(trace.stats.starttime - self.getStartTime(), trace) - inoise = getnoisewin(t, ini_pick, noise_win, gap_win) + t = prepTimeAxis(trace.stats.starttime - stime, trace) + inoise = getnoisewin(t, ini_pick-stime_diff, noise_win, gap_win) trace = demeanTrace(trace=trace, window=inoise) self.setXLims([ini_pick - x_res, ini_pick + x_res]) @@ -1001,7 +1009,8 @@ class PickDlg(QDialog): zoomx=self.getXLims(), zoomy=self.getYLims(), noiselevel=(trace_number + noiselevel, - trace_number - noiselevel)) + trace_number - noiselevel), + iniPick=ini_pick) def setIniPickS(self, gui_event, wfdata): @@ -1014,6 +1023,9 @@ class PickDlg(QDialog): gap_win = twins[1] signal_win = twins[2] + stime = self.getStartTime() + stime_diff = wfdata[0].stats.starttime-stime + # copy data for plotting data = self.getWFData().copy() @@ -1025,7 +1037,7 @@ class PickDlg(QDialog): wfdata.filter(**filteroptions) # determine SNR and noiselevel - result = getSNR(wfdata, (noise_win, gap_win, signal_win), ini_pick) + result = getSNR(wfdata, (noise_win, gap_win, signal_win), ini_pick-stime_diff) snr = result[0] noiselevel = result[2] @@ -1036,8 +1048,8 @@ class PickDlg(QDialog): # prepare plotting of data for trace in data: - t = prepTimeAxis(trace.stats.starttime - self.getStartTime(), trace) - inoise = getnoisewin(t, ini_pick, noise_win, gap_win) + t = prepTimeAxis(trace.stats.starttime - stime, trace) + inoise = getnoisewin(t, ini_pick-stime_diff, noise_win, gap_win) trace = demeanTrace(trace, inoise) # scale waveform for plotting @@ -1060,7 +1072,8 @@ class PickDlg(QDialog): zoomx=self.getXLims(), zoomy=self.getYLims(), noiselevel=noiselevels, - scaleddata=True) + scaleddata=True, + iniPick=ini_pick) def setPick(self, gui_event): @@ -1091,14 +1104,18 @@ class PickDlg(QDialog): else: nfac = parameter.get('nfacS') TSNR = parameter.get('tsnrh') - - [epp, lpp, spe] = earllatepicker(wfdata, nfac, (TSNR[0], TSNR[1], TSNR[2]), pick) - + # return absolute time values for phases stime = self.getStartTime() - epp = stime + epp + stime_diff = wfdata[0].stats.starttime-stime + + [epp, lpp, spe] = earllatepicker(wfdata, nfac, (TSNR[0], TSNR[1], TSNR[2]), pick-stime_diff, verbosity=2) + mpp = stime + pick - lpp = stime + lpp + if epp: + epp = stime + epp + stime_diff + if lpp: + lpp = stime + lpp + stime_diff # save pick times for actual phase phasepicks = dict(epp=epp, lpp=lpp, mpp=mpp, spe=spe, @@ -1147,8 +1164,8 @@ class PickDlg(QDialog): ax = self.getPlotWidget().axes ylims = self.getGlobalLimits('y') phase_col = { - 'P': ('c', 'c--', 'b-', 'bv', 'b^', 'b'), - 'S': ('m', 'm--', 'r-', 'rv', 'r^', 'r') + 'P': ('c', 'c--', 'b-', 'bv', 'b^', 'b', 'c:'), + 'S': ('m', 'm--', 'r-', 'rv', 'r^', 'r', 'm:') } if self.getPicks(picktype): if phase is not None and type(self.getPicks(picktype)[phase]) is dict: @@ -1164,23 +1181,29 @@ class PickDlg(QDialog): return mpp = picks['mpp'] - self.getStartTime() - epp = picks['epp'] - self.getStartTime() - lpp = picks['lpp'] - self.getStartTime() + if picks['epp'] and picks['lpp']: + epp = picks['epp'] - self.getStartTime() + lpp = picks['lpp'] - self.getStartTime() spe = picks['spe'] if picktype == 'manual': - ax.fill_between([epp, lpp], ylims[0], ylims[1], - alpha=.25, color=colors[0]) + if picks['epp'] and picks['lpp']: + ax.fill_between([epp, lpp], ylims[0], ylims[1], + alpha=.25, color=colors[0], label='EPP, LPP') if spe: - ax.plot([mpp - spe, mpp - spe], ylims, colors[1], - [mpp, mpp], ylims, colors[2], - [mpp + spe, mpp + spe], ylims, colors[1]) + ax.plot([mpp - spe, mpp - spe], ylims, colors[1], label='{}-SPE'.format(phase)) + ax.plot([mpp + spe, mpp + spe], ylims, colors[1]) + ax.plot([mpp, mpp], ylims, colors[2], label='{}-Pick'.format(phase)) + else: + ax.plot([mpp, mpp], ylims, colors[6], label='{}-Pick (NO PICKERROR)'.format(phase)) + elif picktype == 'auto': ax.plot(mpp, ylims[1], colors[3], mpp, ylims[0], colors[4]) ax.vlines(mpp, ylims[0], ylims[1], colors[5], linestyles='dotted') else: raise TypeError('Unknown picktype {0}'.format(picktype)) + ax.legend() def panPress(self, gui_event):