From a5097e1da61d8bd4f30227219e90cd6520748c6c Mon Sep 17 00:00:00 2001 From: marcel Date: Mon, 21 Aug 2017 17:19:08 +0200 Subject: [PATCH] [add] updates to jackknife from GUI (WIP, experimental) --- QtPyLoT.py | 38 +++++++++++++++++--------- pylot/core/pick/autopick.py | 7 ++--- pylot/core/pick/utils.py | 53 ++++++++++++++++++++++--------------- pylot/core/util/widgets.py | 11 ++++++++ 4 files changed, 72 insertions(+), 37 deletions(-) diff --git a/QtPyLoT.py b/QtPyLoT.py index e4e54691..f3265172 100755 --- a/QtPyLoT.py +++ b/QtPyLoT.py @@ -79,7 +79,7 @@ from pylot.core.util.event import Event from pylot.core.io.location import create_creation_info, create_event from pylot.core.util.widgets import FilterOptionsDialog, NewEventDlg, \ WaveformWidget, WaveformWidgetPG, PropertiesDlg, HelpForm, createAction, PickDlg, \ - getDataType, ComparisonWidget, TuneAutopicker, PylotParaBox, AutoPickDlg + getDataType, ComparisonWidget, TuneAutopicker, PylotParaBox, AutoPickDlg, JackknifeWidget from pylot.core.util.map_projection import map_projection from pylot.core.util.structure import DATASTRUCTURE from pylot.core.util.thread import Thread, Worker @@ -1815,16 +1815,8 @@ class MainWindow(QMainWindow): self.listWidget.addItem(text) self.listWidget.scrollToBottom() - def tune_autopicker(self): - ''' - Initiates TuneAutopicker widget use to interactively - tune parameters for autopicking algorithm. - ''' - # figures and canvas have to be iniated from the main GUI - # thread to prevent handling of QPixmap objects outside of - # the main thread + def init_fig_dict(self): self.fig_dict = {} - self.canvas_dict = {} self.fig_keys = [ 'mainFig', 'aicFig', @@ -1837,11 +1829,27 @@ class MainWindow(QMainWindow): 'el_S2pick', 'refSpick', 'aicARHfig', + 'jackknife', + 'wadati' ] for key in self.fig_keys: fig = Figure() self.fig_dict[key] = fig + def init_canvas_dict(self): + self.canvas_dict = {} + for key in self.fig_keys: + self.canvas_dict[key] = FigureCanvas(self.fig_dict[key]) + + def tune_autopicker(self): + ''' + Initiates TuneAutopicker widget use to interactively + tune parameters for autopicking algorithm. + ''' + # figures and canvas have to be iniated from the main GUI + # thread to prevent handling of QPixmap objects outside of + # the main thread + self.init_fig_dict() #if not self.tap: # init TuneAutopicker object self.tap = TuneAutopicker(self) @@ -1860,8 +1868,7 @@ class MainWindow(QMainWindow): ''' Create and fill TuneAutopicker tabs with figure canvas. ''' - for key in self.fig_keys: - self.canvas_dict[key] = FigureCanvas(self.fig_dict[key]) + self.init_canvas_dict() self.tap.fill_tabs(picked=True) def autoPick(self): @@ -1883,12 +1890,14 @@ class MainWindow(QMainWindow): # self.addListItem('Loading default values from PyLoT-input file %s' # % self.infile) + self.init_fig_dict() + args = {'parameter': self._inputs, 'station': 'all', 'fnames': 'None', 'eventid': self.get_current_event_path(), 'iplot': 0, - 'fig_dict': None, + 'fig_dict': self.fig_dict, 'locflag': 0} self.mp_thread = QtCore.QThreadPool() @@ -1916,6 +1925,9 @@ class MainWindow(QMainWindow): event.addAutopicks(result) self.drawPicks(picktype='auto') self.draw() + self.init_canvas_dict() + jkw = JackknifeWidget(self, self.canvas_dict['jackknife']) + jkw.show() def addPicks(self, station, picks, type='manual'): stat_picks = self.getPicksOnStation(station, type) diff --git a/pylot/core/pick/autopick.py b/pylot/core/pick/autopick.py index 7bea990e..7ce4a21a 100644 --- a/pylot/core/pick/autopick.py +++ b/pylot/core/pick/autopick.py @@ -76,13 +76,14 @@ def autopickevent(data, param, iplot=0, fig_dict=None, ncores=0, metadata=None, pick.pop('station') all_onsets[station] = pick - return all_onsets + #return all_onsets # quality control # median check and jackknife on P-onset times - jk_checked_onsets = checkPonsets(all_onsets, mdttolerance, iplot) + jk_checked_onsets = checkPonsets(all_onsets, mdttolerance, 1, fig_dict) + return jk_checked_onsets # check S-P times (Wadati) - return wadaticheck(jk_checked_onsets, wdttolerance, iplot) + return wadaticheck(jk_checked_onsets, wdttolerance, iplot, fig_dict) def call_autopickstation(input_tuple): diff --git a/pylot/core/pick/utils.py b/pylot/core/pick/utils.py index cc7b80ce..913f1f8c 100644 --- a/pylot/core/pick/utils.py +++ b/pylot/core/pick/utils.py @@ -564,7 +564,7 @@ def select_for_phase(st, phase): return sel_st -def wadaticheck(pickdic, dttolerance, iplot): +def wadaticheck(pickdic, dttolerance, iplot=0, fig_dict=None): ''' Function to calculate Wadati-diagram from given P and S onsets in order to detect S pick outliers. If a certain S-P time deviates by dttolerance @@ -794,7 +794,7 @@ def checksignallength(X, pick, TSNR, minsiglength, nfac, minpercent, iplot=0, fi return returnflag -def checkPonsets(pickdic, dttolerance, iplot): +def checkPonsets(pickdic, dttolerance, iplot=0, fig_dict=None): ''' Function to check statistics of P-onset times: Control deviation from median (maximum adjusted deviation = dttolerance) and apply pseudo- @@ -816,17 +816,19 @@ def checkPonsets(pickdic, dttolerance, iplot): # search for good quality P picks Ppicks = [] stations = [] - for key in pickdic: - if pickdic[key]['P']['weight'] < 4: + for station in pickdic: + if pickdic[station]['P']['weight'] < 4: # add P onsets to list - UTCPpick = UTCDateTime(pickdic[key]['P']['mpp']) + UTCPpick = UTCDateTime(pickdic[station]['P']['mpp']) Ppicks.append(UTCPpick.timestamp) - stations.append(key) + stations.append(station) # apply jackknife bootstrapping on variance of P onsets print("###############################################") print("checkPonsets: Apply jackknife bootstrapping on P-onset times ...") [xjack, PHI_pseudo, PHI_sub] = jackknife(Ppicks, 'VAR', 1) + if not xjack: + return # get pseudo variances smaller than average variances # (times safety factor), these picks passed jackknife test ij = np.where(PHI_pseudo <= 5 * xjack) @@ -870,21 +872,30 @@ def checkPonsets(pickdic, dttolerance, iplot): checkedonsets = pickdic if iplot > 0: - p1, = plt.plot(np.arange(0, len(Ppicks)), Ppicks, 'ro', markersize=14) - if len(badstations) < 1 and len(badjkstations) < 1: - p2, = plt.plot(np.arange(0, len(Ppicks)), Ppicks, 'go', markersize=14) + if fig_dict: + fig = fig_dict['jackknife'] + plt_flag = 0 else: - p2, = plt.plot(igood, np.array(Ppicks)[igood], 'go', markersize=14) - p3, = plt.plot([0, len(Ppicks) - 1], [pmedian, pmedian], 'g', - linewidth=2) - for i in range(0, len(Ppicks)): - plt.text(i, Ppicks[i] + 0.01, '{0}'.format(stations[i])) + fig = plt.figure() + plt_flag = 1 + ax = fig.add_subplot(111) - plt.xlabel('Number of P Picks') - plt.ylabel('Onset Time [s] from 1.1.1970') - plt.legend([p1, p2, p3], ['Skipped P Picks', 'Good P Picks', 'Median'], - loc='best') - plt.title('Jackknifing and Median Tests on P Onsets') + ax.plot(np.arange(0, len(Ppicks)), Ppicks, 'ro', markersize=14) + if len(badstations) < 1 and len(badjkstations) < 1: + ax.plot(np.arange(0, len(Ppicks)), Ppicks, 'go', markersize=14, label='Skipped P Picks') + else: + ax.plot(igood, np.array(Ppicks)[igood], 'go', markersize=14, label='Good P Picks') + ax.plot([0, len(Ppicks) - 1], [pmedian, pmedian], 'g', + linewidth=2, label='Median') + for i in range(0, len(Ppicks)): + ax.text(i, Ppicks[i] + 0.01, '{0}'.format(stations[i])) + + ax.set_xlabel('Number of P Picks') + ax.set_ylabel('Onset Time [s] from 1.1.1970') + ax.legend() + ax.set_title('Jackknifing and Median Tests on P Onsets') + if plt_flag: + fig.show() return checkedonsets @@ -913,13 +924,13 @@ def jackknife(X, phi, h): PHI_sub = None # determine number of subgroups - g = len(X) / h - if type(g) is not int: + if len(X) % h: print("jackknife: Cannot divide quantity X in equal sized subgroups!") print("Choose another size for subgroups!") return PHI_jack, PHI_pseudo, PHI_sub else: + g = int(len(X) / h) # estimator of undisturbed spot check if phi == 'MEA': phi_sc = np.mean(X) diff --git a/pylot/core/util/widgets.py b/pylot/core/util/widgets.py index 1a32fa12..ae71fe32 100644 --- a/pylot/core/util/widgets.py +++ b/pylot/core/util/widgets.py @@ -2011,6 +2011,17 @@ class PhasePlotWidget(FigureCanvas): super(PhasePlotWidget, self).__init__(self.fig) +class JackknifeWidget(QWidget): + ''' + ''' + + def __init__(self, parent, canvas): + QtGui.QWidget.__init__(self, parent, 1) + self.main_layout = QtGui.QVBoxLayout() + self.setLayout(self.main_layout) + self.main_layout.addWidget(canvas) + + class TuneAutopicker(QWidget): update = QtCore.Signal(str) '''