From f6225f817606b1a3f9882fd0f7f2ae906398d636 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ludger=20K=C3=BCperkoch?= Date: Mon, 21 Aug 2017 13:20:15 +0200 Subject: [PATCH 01/20] [Bugfix] Strange bug, happened only in multiple-event processing, key error. --- autoPyLoT.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/autoPyLoT.py b/autoPyLoT.py index ce3436ed..a203075d 100755 --- a/autoPyLoT.py +++ b/autoPyLoT.py @@ -380,7 +380,8 @@ def autoPyLoT(input_dict=None, parameter=None, inputfile=None, fnames=None, even iplot) # update pick with moment property values (w0, fc, Mo) for stats, props in moment_mag.moment_props.items(): - picks[stats]['P'].update(props) + if picks.has_key(stats): + picks[stats]['P'].update(props) evt = moment_mag.updated_event() net_mw = moment_mag.net_magnitude() print("Network moment magnitude: %4.1f" % net_mw.mag) @@ -391,7 +392,8 @@ def autoPyLoT(input_dict=None, parameter=None, inputfile=None, fnames=None, even parameter.get('sstop'), WAscaling, True, iplot) for stats, amplitude in local_mag.amplitudes.items(): - picks[stats]['S']['Ao'] = amplitude.generic_amplitude + if picks.has_key(stats): + picks[stats]['S']['Ao'] = amplitude.generic_amplitude print("Local station magnitudes scaled with:") print("log(Ao) + %f * log(r) + %f * r + %f" % (WAscaling[0], WAscaling[1], From bdcb0ba6499065c101f73e1101f8e44e39718b95 Mon Sep 17 00:00:00 2001 From: marcel Date: Mon, 21 Aug 2017 13:38:50 +0200 Subject: [PATCH 02/20] [change] islope calculation with 2 samples --- pylot/core/pick/picker.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pylot/core/pick/picker.py b/pylot/core/pick/picker.py index 87162ecc..2355d4f3 100644 --- a/pylot/core/pick/picker.py +++ b/pylot/core/pick/picker.py @@ -250,7 +250,7 @@ class AICPicker(AutoPicker): return imax = np.argmax(dataslope) iislope = islope[0][0:imax+1] - if len(iislope) <= 2: + if len(iislope) < 2: # calculate slope from initial onset to maximum of AIC function print("AICPicker: Not enough data samples left for slope calculation!") print("Calculating slope from initial onset to maximum of AIC function ...") From b9bdaa391ba982285fc3d0b1ff6b3914fb7139b0 Mon Sep 17 00:00:00 2001 From: marcel Date: Mon, 21 Aug 2017 13:51:54 +0200 Subject: [PATCH 03/20] [change] use timedelta if (epick or lpick)=mpick --- pylot/core/pick/autopick.py | 42 +++++++++++++++++-------------------- 1 file changed, 19 insertions(+), 23 deletions(-) diff --git a/pylot/core/pick/autopick.py b/pylot/core/pick/autopick.py index 56b69a7d..3b281f9c 100644 --- a/pylot/core/pick/autopick.py +++ b/pylot/core/pick/autopick.py @@ -978,9 +978,9 @@ def autopickstation(wfstream, pickparam, verbose=False, ########################################################################## # calculate "real" onset times if lpickP is not None and lpickP == mpickP: - lpickP += timeerrorsP[0] + lpickP += zdat[0].stats.delta if epickP is not None and epickP == mpickP: - epickP -= timeerrorsP[0] + epickP -= zdat[0].stats.delta if mpickP is not None and epickP is not None and lpickP is not None: lpickP = zdat[0].stats.starttime + lpickP epickP = zdat[0].stats.starttime + epickP @@ -992,27 +992,27 @@ def autopickstation(wfstream, pickparam, verbose=False, epickP = zdat[0].stats.starttime - timeerrorsP[3] mpickP = zdat[0].stats.starttime + if edat: + hdat = edat[0] + elif ndat: + hdat = ndat[0] + else: + return + if lpickS is not None and lpickS == mpickS: - lpickS += timeerrorsS[0] + lpickS += hdat.stats.delta if epickS is not None and epickS == mpickS: - epickS -= timeerrorsS[0] + epickS -= hdat.stats.delta if mpickS is not None and epickS is not None and lpickS is not None: - lpickS = edat[0].stats.starttime + lpickS - epickS = edat[0].stats.starttime + epickS - mpickS = edat[0].stats.starttime + mpickS + lpickS = hdat.stats.starttime + lpickS + epickS = hdat.stats.starttime + epickS + mpickS = hdat.stats.starttime + mpickS else: # dummy values (start of seismic trace) in order to derive # theoretical onset times for iteratve picking - if edat: - lpickS = edat[0].stats.starttime + timeerrorsS[3] - epickS = edat[0].stats.starttime - timeerrorsS[3] - mpickS = edat[0].stats.starttime - elif ndat: - lpickS = ndat[0].stats.starttime + timeerrorsS[3] - epickS = ndat[0].stats.starttime - timeerrorsS[3] - mpickS = ndat[0].stats.starttime - else: - return + lpickS = hdat.stats.starttime + timeerrorsS[3] + epickS = hdat.stats.starttime - timeerrorsS[3] + mpickS = hdat.stats.starttime # create dictionary # for P phase @@ -1022,12 +1022,8 @@ def autopickstation(wfstream, pickparam, verbose=False, snrdb=SNRPdB, weight=Pweight, fm=FM, w0=None, fc=None, Mo=None, Mw=None, picker=picker, marked=Pmarker) # add S phase - try: - ccode = edat[0].stats.channel - ncode = edat[0].stats.network - except: - ccode = ndat[0].stats.channel - ncode = ndat[0].stats.network + ccode = hdat.stats.channel + ncode = hdat.stats.network spick = dict(channel=ccode, network=ncode, lpp=lpickS, epp=epickS, mpp=mpickS, spe=Serror, snr=SNRS, snrdb=SNRSdB, weight=Sweight, fm=None, picker=picker, Ao=Ao) # merge picks into returning dictionary From 55a54ae154b94e61d2684f17dd37ea0c8f364e2b Mon Sep 17 00:00:00 2001 From: marcel Date: Mon, 21 Aug 2017 14:50:18 +0200 Subject: [PATCH 04/20] [rename] getQualityFromUncertainty --- QtPyLoT.py | 6 +++--- pylot/core/pick/utils.py | 2 +- pylot/core/util/widgets.py | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/QtPyLoT.py b/QtPyLoT.py index ec2a9325..f647f205 100755 --- a/QtPyLoT.py +++ b/QtPyLoT.py @@ -64,7 +64,7 @@ from pylot.core.io.data import Data from pylot.core.io.inputs import FilterOptions, PylotParameter from autoPyLoT import autoPyLoT from pylot.core.pick.compare import Comparison -from pylot.core.pick.utils import symmetrize_error, getQualityfromUncertainty +from pylot.core.pick.utils import symmetrize_error, getQualityFromUncertainty from pylot.core.io.phases import picksdict_from_picks import pylot.core.loc.nll as nll from pylot.core.util.defaults import FILTERDEFAULTS, SetChannelComponents @@ -1998,10 +1998,10 @@ class MainWindow(QMainWindow): # get quality classes if self.getPhaseID(phase) == 'P': - quality = getQualityfromUncertainty(picks['spe'], self._inputs['timeerrorsP']) + quality = getQualityFromUncertainty(picks['spe'], self._inputs['timeerrorsP']) phaseID = 'P' elif self.getPhaseID(phase) == 'S': - quality = getQualityfromUncertainty(picks['spe'], self._inputs['timeerrorsS']) + quality = getQualityFromUncertainty(picks['spe'], self._inputs['timeerrorsS']) phaseID = 'S' mpp = picks['mpp'] - stime diff --git a/pylot/core/pick/utils.py b/pylot/core/pick/utils.py index 9322f64a..cc7b80ce 100644 --- a/pylot/core/pick/utils.py +++ b/pylot/core/pick/utils.py @@ -1098,7 +1098,7 @@ def checkZ4S(X, pick, zfac, checkwin, iplot, fig=None): return returnflag -def getQualityfromUncertainty(uncertainty, Errors): +def getQualityFromUncertainty(uncertainty, Errors): '''Script to transform uncertainty into quality classes 0-4 regarding adjusted time errors Errors. ''' diff --git a/pylot/core/util/widgets.py b/pylot/core/util/widgets.py index 62a6dd80..cb38443d 100644 --- a/pylot/core/util/widgets.py +++ b/pylot/core/util/widgets.py @@ -44,7 +44,7 @@ from obspy.taup.utils import get_phase_names from pylot.core.io.data import Data from pylot.core.io.inputs import FilterOptions, PylotParameter from pylot.core.pick.utils import getSNR, earllatepicker, getnoisewin, \ - getResolutionWindow, getQualityfromUncertainty + getResolutionWindow, getQualityFromUncertainty from pylot.core.pick.compare import Comparison from pylot.core.util.defaults import OUTPUTFORMATS, FILTERDEFAULTS, \ SetChannelComponents @@ -1714,10 +1714,10 @@ class PickDlg(QDialog): # get quality classes if self.getPhaseID(phase) == 'P': - quality = getQualityfromUncertainty(picks['spe'], self.parameter['timeerrorsP']) + quality = getQualityFromUncertainty(picks['spe'], self.parameter['timeerrorsP']) phaseID = 'P' elif self.getPhaseID(phase) == 'S': - quality = getQualityfromUncertainty(picks['spe'], self.parameter['timeerrorsS']) + quality = getQualityFromUncertainty(picks['spe'], self.parameter['timeerrorsS']) phaseID = 'S' mpp = picks['mpp'] - self.getStartTime() From 2b0aa38b37a6a1cc2cb29f7eb3a30adf144c23e7 Mon Sep 17 00:00:00 2001 From: marcel Date: Mon, 21 Aug 2017 14:59:28 +0200 Subject: [PATCH 05/20] [change] restructure identifyPhase functions --- QtPyLoT.py | 4 ++-- pylot/core/pick/autopick.py | 6 +++--- pylot/core/util/utils.py | 3 +++ pylot/core/util/widgets.py | 5 +++-- 4 files changed, 11 insertions(+), 7 deletions(-) diff --git a/QtPyLoT.py b/QtPyLoT.py index f647f205..0d52073f 100755 --- a/QtPyLoT.py +++ b/QtPyLoT.py @@ -74,7 +74,7 @@ from pylot.core.util.connection import checkurl from pylot.core.util.dataprocessing import read_metadata, restitute_data from pylot.core.util.utils import fnConstructor, getLogin, \ full_range, readFilterInformation, trim_station_components, check4gaps, make_pen, pick_color_plt, \ - pick_linestyle_plt, identifyPhase, loopIdentifyPhase, remove_underscores, check4doubled + pick_linestyle_plt, remove_underscores, check4doubled, identifyPhaseID 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, \ @@ -865,7 +865,7 @@ class MainWindow(QMainWindow): return fnames def getPhaseID(self, phase): - return identifyPhase(loopIdentifyPhase(phase)) + return identifyPhaseID(phase) def get_current_event(self, eventbox=None): ''' diff --git a/pylot/core/pick/autopick.py b/pylot/core/pick/autopick.py index 3b281f9c..7bea990e 100644 --- a/pylot/core/pick/autopick.py +++ b/pylot/core/pick/autopick.py @@ -18,8 +18,8 @@ from pylot.core.pick.charfuns import HOScf, AICcf, ARZcf, ARHcf, AR3Ccf from pylot.core.pick.picker import AICPicker, PragPicker from pylot.core.pick.utils import checksignallength, checkZ4S, earllatepicker, \ getSNR, fmpicker, checkPonsets, wadaticheck -from pylot.core.util.utils import getPatternLine, gen_Pool, identifyPhase, loopIdentifyPhase, \ - real_Bool +from pylot.core.util.utils import getPatternLine, gen_Pool,\ + real_Bool, identifyPhaseID from obspy.taup import TauPyModel @@ -254,7 +254,7 @@ def autopickstation(wfstream, pickparam, verbose=False, phases = {'P': [], 'S': []} for arr in arrivals: - phases[identifyPhase(loopIdentifyPhase(arr.phase.name))].append(arr) + phases[identifyPhaseID(arr.phase.name)].append(arr) # get first P and S onsets from arrivals list arrP, estFirstP = min([(arr, arr.time) for arr in phases['P']], key = lambda t: t[1]) diff --git a/pylot/core/util/utils.py b/pylot/core/util/utils.py index c51f6599..426c966d 100644 --- a/pylot/core/util/utils.py +++ b/pylot/core/util/utils.py @@ -806,6 +806,9 @@ def identifyPhase(phase): return False +def identifyPhaseID(phase): + return identifyPhase(loopIdentifyPhase(phase)) + if __name__ == "__main__": diff --git a/pylot/core/util/widgets.py b/pylot/core/util/widgets.py index cb38443d..08b8e003 100644 --- a/pylot/core/util/widgets.py +++ b/pylot/core/util/widgets.py @@ -21,7 +21,8 @@ except: pg = None from matplotlib.figure import Figure -from pylot.core.util.utils import find_horizontals, identifyPhase, loopIdentifyPhase, trim_station_components +from pylot.core.util.utils import find_horizontals, identifyPhase, loopIdentifyPhase, trim_station_components, \ + identifyPhaseID try: from matplotlib.backends.backend_qt4agg import FigureCanvas @@ -1285,7 +1286,7 @@ class PickDlg(QDialog): self.currentPhase = str(self.s_button.text()) def getPhaseID(self, phase): - return identifyPhase(loopIdentifyPhase(phase)) + return identifyPhaseID(phase) def set_button_color(self, button, color=None): if type(color) == QtGui.QColor: From 50e7b8381222c1884cef03ae58bb6fdabb2c8697 Mon Sep 17 00:00:00 2001 From: marcel Date: Mon, 21 Aug 2017 15:11:07 +0200 Subject: [PATCH 06/20] [new] new function to exclude picks by quality --- QtPyLoT.py | 2 +- pylot/core/util/utils.py | 31 +++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/QtPyLoT.py b/QtPyLoT.py index 0d52073f..031214fd 100755 --- a/QtPyLoT.py +++ b/QtPyLoT.py @@ -74,7 +74,7 @@ from pylot.core.util.connection import checkurl from pylot.core.util.dataprocessing import read_metadata, restitute_data from pylot.core.util.utils import fnConstructor, getLogin, \ full_range, readFilterInformation, trim_station_components, check4gaps, make_pen, pick_color_plt, \ - pick_linestyle_plt, remove_underscores, check4doubled, identifyPhaseID + pick_linestyle_plt, remove_underscores, check4doubled, identifyPhaseID, excludeQualityClasses 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, \ diff --git a/pylot/core/util/utils.py b/pylot/core/util/utils.py index 426c966d..24ad261e 100644 --- a/pylot/core/util/utils.py +++ b/pylot/core/util/utils.py @@ -71,6 +71,37 @@ def gen_Pool(ncores=0): return pool +def excludeQualityClasses(picks, qClasses, timeerrorsP, timeerrorsS): + ''' + takes PyLoT picks dictionary and returns a new dictionary with certain classes excluded. + :param picks: PyLoT picks dictionary + :param qClasses: list (or int) of quality classes (0-4) to exclude + :param timeerrorsP: time errors for classes (0-4) for P + :param timeerrorsS: time errors for classes (0-4) for S + :return: new picks dictionary + ''' + from pylot.core.pick.utils import getQualityFromUncertainty + + if type(qClasses) in [int, float]: + qClasses = [qClasses] + + picksdict_new = {} + + phaseError = {'P': timeerrorsP, + 'S': timeerrorsS} + + for station, phases in picks.items(): + for phase, pick in phases.items(): + pickerror = phaseError[identifyPhaseID(phase)] + quality = getQualityFromUncertainty(pick['spe'], pickerror) + if not quality in qClasses: + if not station in picksdict_new: + picksdict_new[station] = {} + picksdict_new[station][phase] = pick + + return picksdict_new + + def clims(lim1, lim2): """ takes two pairs of limits and returns one pair of common limts From b30ab69ad223d9cb0430436220c1d499d413ee2c Mon Sep 17 00:00:00 2001 From: marcel Date: Mon, 21 Aug 2017 15:33:00 +0200 Subject: [PATCH 07/20] [bugfix] teach comparison to cope without pick --- pylot/core/util/widgets.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pylot/core/util/widgets.py b/pylot/core/util/widgets.py index 08b8e003..87978ea1 100644 --- a/pylot/core/util/widgets.py +++ b/pylot/core/util/widgets.py @@ -271,6 +271,10 @@ class ComparisonDialog(QDialog): # _axes.cla() station = self.plotprops['station'] phase = self.plotprops['phase'] + if not phase in self.data.comparison[station]: + _axes.set_title('No pick found for phase {}.'.format(phase)) + self.canvas.draw() + return pdf = self.data.comparison[station][phase] x, y, std, exp = pdf.axis, pdf.data, pdf.standard_deviation(), \ pdf.expectation() From b185ce72b134f0e430c6f869e7297d55b8f88aec Mon Sep 17 00:00:00 2001 From: marcel Date: Mon, 21 Aug 2017 15:33:19 +0200 Subject: [PATCH 08/20] [add] exclude quality class 4 from comparison --- QtPyLoT.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/QtPyLoT.py b/QtPyLoT.py index 031214fd..d53e4906 100755 --- a/QtPyLoT.py +++ b/QtPyLoT.py @@ -1215,7 +1215,11 @@ class MainWindow(QMainWindow): def comparePicks(self): if self.check4Comparison(): - co = Comparison(auto=self.getPicks('auto'), manu=self.getPicks()) + autopicks = excludeQualityClasses(self.getPicks('auto'), [4], + self._inputs['timeerrorsP'], self._inputs['timeerrorsS']) + manupicks = excludeQualityClasses(self.getPicks('manual'), [4], + self._inputs['timeerrorsP'], self._inputs['timeerrorsS']) + co = Comparison(auto=autopicks, manu=manupicks) compare_dlg = ComparisonDialog(co, self) compare_dlg.exec_() From ed994e987f5aebe91ae5ea2f61dff3a676f9b544 Mon Sep 17 00:00:00 2001 From: marcel Date: Mon, 21 Aug 2017 16:07:57 +0200 Subject: [PATCH 09/20] [change] ComparisonDlg -> ComparisonWidget --- QtPyLoT.py | 6 +++--- pylot/core/util/widgets.py | 12 ++++-------- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/QtPyLoT.py b/QtPyLoT.py index d53e4906..e4e54691 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, ComparisonDialog, TuneAutopicker, PylotParaBox, AutoPickDlg + getDataType, ComparisonWidget, TuneAutopicker, PylotParaBox, AutoPickDlg from pylot.core.util.map_projection import map_projection from pylot.core.util.structure import DATASTRUCTURE from pylot.core.util.thread import Thread, Worker @@ -1220,8 +1220,8 @@ class MainWindow(QMainWindow): manupicks = excludeQualityClasses(self.getPicks('manual'), [4], self._inputs['timeerrorsP'], self._inputs['timeerrorsS']) co = Comparison(auto=autopicks, manu=manupicks) - compare_dlg = ComparisonDialog(co, self) - compare_dlg.exec_() + compare_dlg = ComparisonWidget(co, self) + compare_dlg.show() def getPlotWidget(self): return self.dataPlot diff --git a/pylot/core/util/widgets.py b/pylot/core/util/widgets.py index 87978ea1..1a32fa12 100644 --- a/pylot/core/util/widgets.py +++ b/pylot/core/util/widgets.py @@ -119,7 +119,7 @@ def createAction(parent, text, slot=None, shortcut=None, icon=None, return action -class ComparisonDialog(QDialog): +class ComparisonWidget(QWidget): def __init__(self, c, parent=None): self._data = c self._stats = c.stations @@ -129,8 +129,9 @@ class ComparisonDialog(QDialog): histCheckBox=None) self._phases = 'PS' self._plotprops = dict(station=list(self.stations)[0], phase=list(self.phases)[0]) - super(ComparisonDialog, self).__init__(parent) + super(ComparisonWidget, self).__init__(parent, 1) self.setupUI() + self.resize(1280, 720) self.plotcomparison() def setupUI(self): @@ -162,17 +163,12 @@ class ComparisonDialog(QDialog): _toolbar.addWidget(_phases_combobox) _toolbar.addWidget(_hist_checkbox) - _buttonbox = QDialogButtonBox(QDialogButtonBox.Close) - _innerlayout.addWidget(self.canvas) - _innerlayout.addWidget(_buttonbox) _outerlayout.addWidget(_toolbar) _outerlayout.addLayout(_innerlayout) - _buttonbox.rejected.connect(self.reject) - - # finally layout the entire dialog + # finally layout the entire widget self.setLayout(_outerlayout) @property From 75d206b9b1db701c4802df329e3b1f6694bbaf18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ludger=20K=C3=BCperkoch?= Date: Mon, 21 Aug 2017 16:11:10 +0200 Subject: [PATCH 10/20] Revised function using already existing functions. --- pylot/core/io/phases.py | 85 ++++++++++++++++++++--------------------- 1 file changed, 41 insertions(+), 44 deletions(-) diff --git a/pylot/core/io/phases.py b/pylot/core/io/phases.py index c54c120a..54a42030 100644 --- a/pylot/core/io/phases.py +++ b/pylot/core/io/phases.py @@ -879,6 +879,9 @@ def getQualitiesfromxml(xmlnames, ErrorsP, ErrorsS, plotflag=1): Ludger Küperkoch, BESTEC GmbH, 07/2017 """ + from pylot.core.pick.utils import getQualityfromUncertainty + from pylot.core.util.utils import loopIdentifyPhase, identifyPhase + # read all onset weights Pw0 = [] Pw1 = [] @@ -902,14 +905,15 @@ def getQualitiesfromxml(xmlnames, ErrorsP, ErrorsS, plotflag=1): mstation = Pick.waveform_id.station_code mstation_ext = mstation + '_' for mpick in arrivals_copy: - if mpick.phase_hint[0] == 'P': + phase = identifyPhase(loopIdentifyPhase(Pick.phase_hint))) + if phase == 'P': if ((mpick.waveform_id.station_code == mstation) or \ (mpick.waveform_id.station_code == mstation_ext)) and \ ((mpick.method_id).split('/')[1] == 'auto') and \ (mpick.time_errors['uncertainty'] <= ErrorsP[3]): del mpick break - elif mpick.phase_hint[0] == 'S': + elif phase == 'S': if ((mpick.waveform_id.station_code == mstation) or \ (mpick.waveform_id.station_code == mstation_ext)) and \ ((mpick.method_id).split('/')[1] == 'auto') and \ @@ -921,38 +925,31 @@ def getQualitiesfromxml(xmlnames, ErrorsP, ErrorsS, plotflag=1): print("Found manual as well as automatic picks, prefered the {} manual ones!".format(lendiff)) for Pick in arrivals_copy: - if Pick.phase_hint[0] == 'P': - if Pick.time_errors.uncertainty <= ErrorsP[0]: + phase = identifyPhase(loopIdentifyPhase(Pick.phase_hint))) + if phase == 'P': + Pqual = getQualitiesfromxml(Pick.time_errors.uncertainty, ErrorsP) + if Pqual == 0: Pw0.append(Pick.time_errors.uncertainty) - elif (Pick.time_errors.uncertainty > ErrorsP[0]) and \ - (Pick.time_errors.uncertainty <= ErrorsP[1]): + elif Pqual == 1: Pw1.append(Pick.time_errors.uncertainty) - elif (Pick.time_errors.uncertainty > ErrorsP[1]) and \ - (Pick.time_errors.uncertainty <= ErrorsP[2]): + elif Pqual == 2: Pw2.append(Pick.time_errors.uncertainty) - elif (Pick.time_errors.uncertainty > ErrorsP[2]) and \ - (Pick.time_errors.uncertainty <= ErrorsP[3]): + elif Pqual == 3: Pw3.append(Pick.time_errors.uncertainty) - elif Pick.time_errors.uncertainty > ErrorsP[3]: + elif Pqual == 4 Pw4.append(Pick.time_errors.uncertainty) - else: - pass - elif Pick.phase_hint[0] == 'S': - if Pick.time_errors.uncertainty <= ErrorsS[0]: + elif phase == 'S': + Squal = getQualitiesfromxml(Pick.time_errors.uncertainty, ErrorsS) + if Squal == 0: Sw0.append(Pick.time_errors.uncertainty) - elif (Pick.time_errors.uncertainty > ErrorsS[0]) and \ - (Pick.time_errors.uncertainty <= ErrorsS[1]): + elif Squal == 1: Sw1.append(Pick.time_errors.uncertainty) - elif (Pick.time_errors.uncertainty > ErrorsS[1]) and \ - (Pick.time_errors.uncertainty <= ErrorsS[2]): + elif Squal == 2: Sw2.append(Pick.time_errors.uncertainty) - elif (Pick.time_errors.uncertainty > ErrorsS[2]) and \ - (Pick.time_errors.uncertainty <= ErrorsS[3]): + elif Squal == 3: Sw3.append(Pick.time_errors.uncertainty) - elif Pick.time_errors.uncertainty > ErrorsS[3]: + elif Squal == 4 Sw4.append(Pick.time_errors.uncertainty) - else: - pass else: print("Phase hint not defined for picking!") pass @@ -965,45 +962,45 @@ def getQualitiesfromxml(xmlnames, ErrorsP, ErrorsS, plotflag=1): # get percentage of weights numPweights = np.sum([len(Pw0), len(Pw1), len(Pw2), len(Pw3), len(Pw4)]) numSweights = np.sum([len(Sw0), len(Sw1), len(Sw2), len(Sw3), len(Sw4)]) - try: + if len(Pw0) > 0: P0perc = 100 / numPweights * len(Pw0) - except: + else: P0perc = 0 - try: + if len(Pw1) > 0: P1perc = 100 / numPweights * len(Pw1) - except: + else: P1perc = 0 - try: + if len(Pw2) > 0: P2perc = 100 / numPweights * len(Pw2) - except: + else: P2perc = 0 - try: + if len(Pw3) > 0: P3perc = 100 / numPweights * len(Pw3) - except: + else: P3perc = 0 - try: + if len(Pw4) > 0: P4perc = 100 / numPweights * len(Pw4) - except: + else: P4perc = 0 - try: + if len(Sw0) > 0: S0perc = 100 / numSweights * len(Sw0) - except: + else: S0perc = 0 - try: + if len(Sw1) > 0: S1perc = 100 / numSweights * len(Sw1) - except: + else: S1perc = 0 - try: + if len(Sw2) > 0: S2perc = 100 / numSweights * len(Sw2) - except: + else: S2perc = 0 - try: + if len(Sw3) > 0: S3perc = 100 / numSweights * len(Sw3) - except: + else: S3perc = 0 - try: + if len(Sw4) > 0: S4perc = 100 / numSweights * len(Sw4) - except: + else: S4perc = 0 weights = ('0', '1', '2', '3', '4') From 672202474948ece1f04c7ebc442f59e3ab5392f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ludger=20K=C3=BCperkoch?= Date: Mon, 21 Aug 2017 16:16:09 +0200 Subject: [PATCH 11/20] Take renaming of existing function into account. --- pylot/core/io/phases.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pylot/core/io/phases.py b/pylot/core/io/phases.py index 54a42030..2355be13 100644 --- a/pylot/core/io/phases.py +++ b/pylot/core/io/phases.py @@ -879,7 +879,7 @@ def getQualitiesfromxml(xmlnames, ErrorsP, ErrorsS, plotflag=1): Ludger Küperkoch, BESTEC GmbH, 07/2017 """ - from pylot.core.pick.utils import getQualityfromUncertainty + from pylot.core.pick.utils import getQualityFromUncertainty from pylot.core.util.utils import loopIdentifyPhase, identifyPhase # read all onset weights @@ -927,7 +927,7 @@ def getQualitiesfromxml(xmlnames, ErrorsP, ErrorsS, plotflag=1): for Pick in arrivals_copy: phase = identifyPhase(loopIdentifyPhase(Pick.phase_hint))) if phase == 'P': - Pqual = getQualitiesfromxml(Pick.time_errors.uncertainty, ErrorsP) + Pqual = getQualityFromUncertainty(Pick.time_errors.uncertainty, ErrorsP) if Pqual == 0: Pw0.append(Pick.time_errors.uncertainty) elif Pqual == 1: @@ -939,7 +939,7 @@ def getQualitiesfromxml(xmlnames, ErrorsP, ErrorsS, plotflag=1): elif Pqual == 4 Pw4.append(Pick.time_errors.uncertainty) elif phase == 'S': - Squal = getQualitiesfromxml(Pick.time_errors.uncertainty, ErrorsS) + Squal = getQualityFromUncertainty(Pick.time_errors.uncertainty, ErrorsS) if Squal == 0: Sw0.append(Pick.time_errors.uncertainty) elif Squal == 1: From a5097e1da61d8bd4f30227219e90cd6520748c6c Mon Sep 17 00:00:00 2001 From: marcel Date: Mon, 21 Aug 2017 17:19:08 +0200 Subject: [PATCH 12/20] [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) ''' From f7cada6d09c95bd9a61ee5f91521bd1a58a5b326 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ludger=20K=C3=BCperkoch?= Date: Tue, 22 Aug 2017 10:34:58 +0200 Subject: [PATCH 13/20] [Bugfix] Some typo. --- pylot/core/io/phases.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pylot/core/io/phases.py b/pylot/core/io/phases.py index 2355be13..fd89df4c 100644 --- a/pylot/core/io/phases.py +++ b/pylot/core/io/phases.py @@ -879,8 +879,8 @@ def getQualitiesfromxml(xmlnames, ErrorsP, ErrorsS, plotflag=1): Ludger Küperkoch, BESTEC GmbH, 07/2017 """ - from pylot.core.pick.utils import getQualityFromUncertainty - from pylot.core.util.utils import loopIdentifyPhase, identifyPhase + from pylot.core.pick.utils import getQualityFromUncertainty + from pylot.core.util.utils import loopIdentifyPhase, identifyPhase # read all onset weights Pw0 = [] @@ -905,7 +905,7 @@ def getQualitiesfromxml(xmlnames, ErrorsP, ErrorsS, plotflag=1): mstation = Pick.waveform_id.station_code mstation_ext = mstation + '_' for mpick in arrivals_copy: - phase = identifyPhase(loopIdentifyPhase(Pick.phase_hint))) + phase = identifyPhase(loopIdentifyPhase(Pick.phase_hint)) if phase == 'P': if ((mpick.waveform_id.station_code == mstation) or \ (mpick.waveform_id.station_code == mstation_ext)) and \ @@ -925,7 +925,7 @@ def getQualitiesfromxml(xmlnames, ErrorsP, ErrorsS, plotflag=1): print("Found manual as well as automatic picks, prefered the {} manual ones!".format(lendiff)) for Pick in arrivals_copy: - phase = identifyPhase(loopIdentifyPhase(Pick.phase_hint))) + phase = identifyPhase(loopIdentifyPhase(Pick.phase_hint)) if phase == 'P': Pqual = getQualityFromUncertainty(Pick.time_errors.uncertainty, ErrorsP) if Pqual == 0: @@ -936,7 +936,7 @@ def getQualitiesfromxml(xmlnames, ErrorsP, ErrorsS, plotflag=1): Pw2.append(Pick.time_errors.uncertainty) elif Pqual == 3: Pw3.append(Pick.time_errors.uncertainty) - elif Pqual == 4 + elif Pqual == 4: Pw4.append(Pick.time_errors.uncertainty) elif phase == 'S': Squal = getQualityFromUncertainty(Pick.time_errors.uncertainty, ErrorsS) @@ -948,7 +948,7 @@ def getQualitiesfromxml(xmlnames, ErrorsP, ErrorsS, plotflag=1): Sw2.append(Pick.time_errors.uncertainty) elif Squal == 3: Sw3.append(Pick.time_errors.uncertainty) - elif Squal == 4 + elif Squal == 4: Sw4.append(Pick.time_errors.uncertainty) else: print("Phase hint not defined for picking!") From 0f2660e20b25a30d8ccbbdf51c2f977a4cedf6f1 Mon Sep 17 00:00:00 2001 From: marcel Date: Tue, 22 Aug 2017 11:53:19 +0200 Subject: [PATCH 14/20] [change] number of picks regards pick quality --- QtPyLoT.py | 51 ++++++++++++++++++++++++++-------------- pylot/core/util/utils.py | 6 +++++ 2 files changed, 40 insertions(+), 17 deletions(-) diff --git a/QtPyLoT.py b/QtPyLoT.py index f3265172..6cb9e4eb 100755 --- a/QtPyLoT.py +++ b/QtPyLoT.py @@ -74,7 +74,7 @@ from pylot.core.util.connection import checkurl from pylot.core.util.dataprocessing import read_metadata, restitute_data from pylot.core.util.utils import fnConstructor, getLogin, \ full_range, readFilterInformation, trim_station_components, check4gaps, make_pen, pick_color_plt, \ - pick_linestyle_plt, remove_underscores, check4doubled, identifyPhaseID, excludeQualityClasses + pick_linestyle_plt, remove_underscores, check4doubled, identifyPhaseID, excludeQualityClasses, has_spe 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, \ @@ -1048,12 +1048,21 @@ class MainWindow(QMainWindow): for id, event in enumerate(self.project.eventlist): event_path = event.path - event_npicks = 0 - event_nautopicks = 0 - if event.pylot_picks: - event_npicks = len(event.pylot_picks) - if event.pylot_autopicks: - event_nautopicks = len(event.pylot_autopicks) + phaseErrors = {'P': self._inputs['timeerrorsP'], + 'S': self._inputs['timeerrorsS']} + + ma_props = {'manual': event.pylot_picks, + 'auto': event.pylot_autopicks} + ma_count = {'manual': 0, + 'auto': 0} + + for ma in ma_props.keys(): + if ma_props[ma]: + for picks in ma_props[ma].values(): + for phasename, pick in picks.items(): + if getQualityFromUncertainty(has_spe(pick), phaseErrors[self.getPhaseID(phasename)]) < 4: + ma_count[ma] += 1 + event_ref = event.isRefEvent() event_test = event.isTestEvent() @@ -1064,9 +1073,9 @@ class MainWindow(QMainWindow): # a=event_nautopicks) item_path = QtGui.QStandardItem('{path:{plen}}'.format(path=event_path, plen=plmax)) - item_nmp = QtGui.QStandardItem(str(event_npicks)) + item_nmp = QtGui.QStandardItem(str(ma_count['manual'])) item_nmp.setIcon(self.manupicksicon_small) - item_nap = QtGui.QStandardItem(str(event_nautopicks)) + item_nap = QtGui.QStandardItem(str(ma_count['auto'])) item_nap.setIcon(self.autopicksicon_small) item_ref = QtGui.QStandardItem() # str(event_ref)) item_test = QtGui.QStandardItem() # str(event_test)) @@ -2340,12 +2349,20 @@ class MainWindow(QMainWindow): # iterate through eventlist and generate items for table rows self.project._table = [] for index, event in enumerate(eventlist): - event_npicks = 0 - event_nautopicks = 0 - if event.pylot_picks: - event_npicks = len(event.pylot_picks) - if event.pylot_autopicks: - event_nautopicks = len(event.pylot_autopicks) + phaseErrors = {'P': self._inputs['timeerrorsP'], + 'S': self._inputs['timeerrorsS']} + + ma_props = {'manual': event.pylot_picks, + 'auto': event.pylot_autopicks} + ma_count = {'manual': 0, + 'auto': 0} + + for ma in ma_props.keys(): + if ma_props[ma]: + for picks in ma_props[ma].values(): + for phasename, pick in picks.items(): + if getQualityFromUncertainty(has_spe(pick), phaseErrors[self.getPhaseID(phasename)]) < 4: + ma_count[ma] += 1 # init table items for current row item_delete = QtGui.QTableWidgetItem() @@ -2356,9 +2373,9 @@ class MainWindow(QMainWindow): item_lon = QtGui.QTableWidgetItem() item_depth = QtGui.QTableWidgetItem() item_mag = QtGui.QTableWidgetItem() - item_nmp = QtGui.QTableWidgetItem(str(event_npicks)) + item_nmp = QtGui.QTableWidgetItem(str(ma_count['manual'])) item_nmp.setIcon(self.manupicksicon_small) - item_nap = QtGui.QTableWidgetItem(str(event_nautopicks)) + item_nap = QtGui.QTableWidgetItem(str(ma_count['auto'])) item_nap.setIcon(self.autopicksicon_small) item_ref = QtGui.QTableWidgetItem() item_test = QtGui.QTableWidgetItem() diff --git a/pylot/core/util/utils.py b/pylot/core/util/utils.py index 24ad261e..8112d9f1 100644 --- a/pylot/core/util/utils.py +++ b/pylot/core/util/utils.py @@ -841,6 +841,12 @@ def identifyPhaseID(phase): return identifyPhase(loopIdentifyPhase(phase)) +def has_spe(pick): + if not 'spe' in pick.keys(): + return None + else: + return pick['spe'] + if __name__ == "__main__": import doctest From d818e6aef9c7f676f87751f2866f006160f89d5a Mon Sep 17 00:00:00 2001 From: marcel Date: Tue, 22 Aug 2017 13:21:06 +0200 Subject: [PATCH 15/20] [new] widget for picking interactive inside GUI --- pylot/core/util/widgets.py | 70 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/pylot/core/util/widgets.py b/pylot/core/util/widgets.py index ae71fe32..836269e0 100644 --- a/pylot/core/util/widgets.py +++ b/pylot/core/util/widgets.py @@ -2022,6 +2022,76 @@ class JackknifeWidget(QWidget): self.main_layout.addWidget(canvas) +class AutoPickWidget(QWidget): + ''' + ''' + + def __init__(self, parent): + QtGui.QWidget.__init__(self, parent, 1) + self.setupUi() + self.connect_buttons() + # set initial size + self.resize(1280, 720) + + def setupUi(self): + # init main layout + self.main_layout = QtGui.QVBoxLayout() + self.setLayout(self.main_layout) + # init main splitter + self.main_splitter = QtGui.QSplitter() + self.main_splitter.setChildrenCollapsible(False) + + self.init_checkboxes() + self.init_log_layout() + self.init_plot_layout() + + self.main_layout.insertWidget(1, self.main_splitter) + + self.main_layout.setStretch(0, 0) + self.main_layout.setStretch(1, 1) + + def connect_buttons(self): + self.start_button.clicked.connect(self.start_picker) + + def init_checkboxes(self): + self.cb_layout = QtGui.QHBoxLayout() + + cb_keys = ['current event', + 'reference set', + 'test set', + 'all'] + self.cb_dict = {} + + self.start_button = QtGui.QPushButton('Start') + + for index, key in enumerate(cb_keys): + cb = QCheckBox(key) + self.cb_dict[key] = cb + self.cb_layout.insertWidget(index, cb) + self.cb_layout.setStretch(index, 0) + + self.cb_layout.addWidget(self.start_button) + + self.cb_layout.addWidget(QtGui.QWidget()) + self.cb_layout.setStretch(len(cb_keys)+1, 1) + + self.main_layout.insertLayout(0, self.cb_layout) + + def init_plot_layout(self): + self.gb_plots = QtGui.QGroupBox('Plots') + self.gb_plots.setMinimumSize(100, 100) + self.main_splitter.insertWidget(1, self.gb_plots) + self.plot_layout = QtGui.QVBoxLayout() + + def init_log_layout(self): + self.gb_log = QtGui.QGroupBox('Log') + self.gb_log.setMinimumSize(100, 100) + self.main_splitter.insertWidget(0, self.gb_log) + + def start_picker(self): + pass + + class TuneAutopicker(QWidget): update = QtCore.Signal(str) ''' From c6c13f85bc823eeeb766fb47c14d652f6d014b9b Mon Sep 17 00:00:00 2001 From: marcel Date: Tue, 22 Aug 2017 16:43:09 +0200 Subject: [PATCH 16/20] [new] first working version of jackknife plots for multiple events (WIP) --- QtPyLoT.py | 150 +++++++++++++++++++++++++++++++----- autoPyLoT.py | 31 ++++---- pylot/core/pick/autopick.py | 6 +- pylot/core/util/widgets.py | 69 ++++++++++++----- 4 files changed, 199 insertions(+), 57 deletions(-) diff --git a/QtPyLoT.py b/QtPyLoT.py index 6cb9e4eb..3f5814fc 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, JackknifeWidget + getDataType, ComparisonWidget, TuneAutopicker, PylotParaBox, AutoPickDlg, JackknifeWidget, AutoPickWidget from pylot.core.util.map_projection import map_projection from pylot.core.util.structure import DATASTRUCTURE from pylot.core.util.thread import Thread, Worker @@ -1025,6 +1025,11 @@ class MainWindow(QMainWindow): :param: select_events, can be 'all', 'ref' :type: str ''' + + # if pick widget is open, refresh tooltips as well + if hasattr(self, 'apw'): + self.apw.refresh_tooltips() + if not eventBox: eventBox = self.eventBox index = eventBox.currentIndex() @@ -1837,9 +1842,7 @@ class MainWindow(QMainWindow): 'el_S1pick', 'el_S2pick', 'refSpick', - 'aicARHfig', - 'jackknife', - 'wadati' + 'aicARHfig' ] for key in self.fig_keys: fig = Figure() @@ -1850,6 +1853,25 @@ class MainWindow(QMainWindow): for key in self.fig_keys: self.canvas_dict[key] = FigureCanvas(self.fig_dict[key]) + def init_fig_dict_wadatijack(self, eventIDs): + self.fig_dict_wadatijack = {} + self.fig_keys_wadatijack = [ + 'jackknife', + 'wadati' + ] + for eventID in eventIDs: + self.fig_dict_wadatijack[eventID] = {} + for key in self.fig_keys_wadatijack: + fig = Figure() + self.fig_dict_wadatijack[eventID][key] = fig + + def init_canvas_dict_wadatijack(self): + self.canvas_dict_wadatijack = {} + for eventID in self.fig_dict_wadatijack.keys(): + self.canvas_dict_wadatijack[eventID] = {} + for key in self.fig_keys_wadatijack: + self.canvas_dict_wadatijack[eventID][key] = FigureCanvas(self.fig_dict_wadatijack[eventID][key]) + def tune_autopicker(self): ''' Initiates TuneAutopicker widget use to interactively @@ -1886,38 +1908,79 @@ class MainWindow(QMainWindow): QMessageBox.warning(self, "PyLoT Warning", "No autoPyLoT output declared!") return - event = self.get_current_event() - self.saveData(event, event.path, outformats=['.xml']) + + self.pickoptions =[('current event', self.get_current_event), + ('reference set events', self.get_ref_events), + ('test set events', self.get_test_events), + ('all (picked) events', self.get_manu_picked_events), + ('all events', self.get_all_events)] + self.listWidget = QListWidget() self.setDirty(True) - self.logDockWidget = QDockWidget("AutoPickLog", self) - self.logDockWidget.setObjectName("LogDockWidget") - self.logDockWidget.setAllowedAreas( - Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea) - self.logDockWidget.setWidget(self.listWidget) - self.addDockWidget(Qt.LeftDockWidgetArea, self.logDockWidget) + self.apw = AutoPickWidget(self, self.pickoptions) + self.apw.insert_log_widget(self.listWidget) + self.apw.refresh_tooltips() + + # self.logDockWidget = QDockWidget("AutoPickLog", self) + # self.logDockWidget.setObjectName("LogDockWidget") + # self.logDockWidget.setAllowedAreas( + # Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea) + # self.logDockWidget.setWidget(self.listWidget) + # self.addDockWidget(Qt.LeftDockWidgetArea, self.logDockWidget) # self.addListItem('Loading default values from PyLoT-input file %s' # % self.infile) - self.init_fig_dict() + self.apw.start.connect(self.start_autopick) + self.apw.show() + def start_autopick(self): + for key, func in self.pickoptions: + if self.apw.rb_dict[key].isChecked(): + # if radio button is checked break for loop and use func + break + + events = func() + if not type(events) == list: + events = [events] + eventPaths = self.get_event_paths(events) + eventIDs = self.get_event_ids(events) + + self.init_fig_dict_wadatijack(eventIDs) + + if not eventPaths: + self.addListItem("No events found for '{}'".format(key)) + return + else: + self.addListItem("Picking the following events ({}):".format(key)) + for eventID in eventPaths: + self.addListItem(str(eventID)) + + self.apw.enable(False) + + # export current picks etc. + self.exportAllEvents(['.xml']) + + # define arguments for picker args = {'parameter': self._inputs, 'station': 'all', 'fnames': 'None', - 'eventid': self.get_current_event_path(), + 'eventid': eventPaths, 'iplot': 0, - 'fig_dict': self.fig_dict, + 'fig_dict': None, + 'fig_dict_wadatijack': self.fig_dict_wadatijack, 'locflag': 0} + # init pick thread self.mp_thread = QtCore.QThreadPool() self.mp_worker = Worker(autoPyLoT, args, redirect_stdout=True) - self.mp_thread.start(self.mp_worker) self.addListItem(str(self._inputs)) self.mp_worker.signals.message.connect(self.addListItem) self.mp_worker.signals.result.connect(self.finalizeAutoPick) + self.mp_thread.start(self.mp_worker) + def autoPickProject(self): if not self.apd_local: self.apd_local = AutoPickDlg(self, sge=False) @@ -1929,14 +1992,59 @@ class MainWindow(QMainWindow): self.apd_sge.show() def finalizeAutoPick(self, result): + self.apw.enable(True) if result: - event = self.get_current_event() - event.addAutopicks(result) + self.init_canvas_dict_wadatijack() + for eventID in result.keys(): + event = self.get_event_from_id(eventID) + if not event: + continue + event.addAutopicks(result[eventID]) + jkw = JackknifeWidget(self, self.canvas_dict_wadatijack[eventID]['jackknife']) + self.apw.insert_plot_widget(jkw, 'Jackknife', eventID) self.drawPicks(picktype='auto') self.draw() - self.init_canvas_dict() - jkw = JackknifeWidget(self, self.canvas_dict['jackknife']) - jkw.show() + + def get_event_from_id(self, eventID): + for event in self.project.eventlist: + if event.pylot_id == eventID: + return event + + def get_event_paths(self, eventlist): + eventPaths = [] + for event in eventlist: + eventPaths.append(event.path) + return eventPaths + + def get_event_ids(self, eventlist): + eventIDs = [] + for event in eventlist: + eventIDs.append(event.pylot_id) + return eventIDs + + def get_all_events(self): + return self.project.eventlist + + def get_ref_events(self): + events = [] + for event in self.project.eventlist: + if event.isRefEvent(): + events.append(event) + return events + + def get_test_events(self): + events = [] + for event in self.project.eventlist: + if event.isTestEvent(): + events.append(event) + return events + + def get_manu_picked_events(self): + events = [] + for event in self.project.eventlist: + if len(event.pylot_picks) > 0: + events.append(event) + return events def addPicks(self, station, picks, type='manual'): stat_picks = self.getPicksOnStation(station, type) diff --git a/autoPyLoT.py b/autoPyLoT.py index a203075d..d55129d6 100755 --- a/autoPyLoT.py +++ b/autoPyLoT.py @@ -77,12 +77,17 @@ def autoPyLoT(input_dict=None, parameter=None, inputfile=None, fnames=None, even inputfile = real_None(inputfile) eventid = real_None(eventid) + fig_dict = None + fig_dict_wadatijack = None + locflag = 1 if input_dict and isinstance(input_dict, dict): if 'parameter' in input_dict: parameter = input_dict['parameter'] if 'fig_dict' in input_dict: fig_dict = input_dict['fig_dict'] + if 'fig_dict_wadatijack' in input_dict: + fig_dict_wadatijack = input_dict['fig_dict_wadatijack'] if 'station' in input_dict: station = input_dict['station'] if 'fnames' in input_dict: @@ -178,13 +183,14 @@ def autoPyLoT(input_dict=None, parameter=None, inputfile=None, fnames=None, even evID = os.path.split(eventid)[-1] locflag = 2 else: - # started in tune mode + # started in tune or interactive mode datapath = os.path.join(parameter['rootpath'], parameter['datapath']) events = [] - events.append(os.path.join(datapath, - parameter['database'], - eventid)) + for eventID in eventid: + events.append(os.path.join(datapath, + parameter['database'], + eventID)) if not events: print('autoPyLoT: No events given. Return!') @@ -195,6 +201,7 @@ def autoPyLoT(input_dict=None, parameter=None, inputfile=None, fnames=None, even eventpath = eventpath.replace(SEPARATOR, '/') events[index] = eventpath + allpicks = {} glocflag = locflag for eventpath in events: evID = os.path.split(eventpath)[-1] @@ -257,14 +264,9 @@ def autoPyLoT(input_dict=None, parameter=None, inputfile=None, fnames=None, even print(wfdat) ########################################################## # !automated picking starts here! - if input_dict: - if 'fig_dict' in input_dict: - fig_dict = input_dict['fig_dict'] - picks = autopickevent(wfdat, parameter, iplot=iplot, fig_dict=fig_dict, - ncores=ncores, metadata=metadata, origin=data.get_evt_data().origins) - else: - picks = autopickevent(wfdat, parameter, iplot=iplot, - ncores=ncores, metadata=metadata, origin=data.get_evt_data().origins) + picks = autopickevent(wfdat, parameter, iplot=iplot, fig_dict=fig_dict, + fig_dict_wadatijack=fig_dict_wadatijack[evID], + ncores=ncores, metadata=metadata, origin=data.get_evt_data().origins) ########################################################## # locating if locflag > 0: @@ -451,13 +453,16 @@ def autoPyLoT(input_dict=None, parameter=None, inputfile=None, fnames=None, even if locflag == 0: print("autoPyLoT was running in non-location mode!") + # save picks for current event ID to dictionary with ALL picks + allpicks[evID] = picks + endsp = '''####################################\n ************************************\n *********autoPyLoT terminates*******\n The Python picking and Location Tool\n ************************************'''.format(version=_getVersionString()) print(endsp) - return picks + return allpicks if __name__ == "__main__": diff --git a/pylot/core/pick/autopick.py b/pylot/core/pick/autopick.py index 7ce4a21a..d348e284 100644 --- a/pylot/core/pick/autopick.py +++ b/pylot/core/pick/autopick.py @@ -24,7 +24,7 @@ from pylot.core.util.utils import getPatternLine, gen_Pool,\ from obspy.taup import TauPyModel -def autopickevent(data, param, iplot=0, fig_dict=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): stations = [] all_onsets = {} input_tuples = [] @@ -80,10 +80,10 @@ def autopickevent(data, param, iplot=0, fig_dict=None, ncores=0, metadata=None, # quality control # median check and jackknife on P-onset times - jk_checked_onsets = checkPonsets(all_onsets, mdttolerance, 1, fig_dict) + jk_checked_onsets = checkPonsets(all_onsets, mdttolerance, 1, fig_dict_wadatijack) return jk_checked_onsets # check S-P times (Wadati) - return wadaticheck(jk_checked_onsets, wdttolerance, iplot, fig_dict) + return wadaticheck(jk_checked_onsets, wdttolerance, iplot, fig_dict_wadatijack) def call_autopickstation(input_tuple): diff --git a/pylot/core/util/widgets.py b/pylot/core/util/widgets.py index 836269e0..a91216f3 100644 --- a/pylot/core/util/widgets.py +++ b/pylot/core/util/widgets.py @@ -2016,18 +2016,20 @@ class JackknifeWidget(QWidget): ''' def __init__(self, parent, canvas): - QtGui.QWidget.__init__(self, parent, 1) + QtGui.QWidget.__init__(self, parent)#, 1) self.main_layout = QtGui.QVBoxLayout() self.setLayout(self.main_layout) self.main_layout.addWidget(canvas) class AutoPickWidget(QWidget): + start = Signal() ''' ''' - def __init__(self, parent): + def __init__(self, parent, pickoptions): QtGui.QWidget.__init__(self, parent, 1) + self.pickoptions = pickoptions self.setupUi() self.connect_buttons() # set initial size @@ -2054,42 +2056,69 @@ class AutoPickWidget(QWidget): self.start_button.clicked.connect(self.start_picker) def init_checkboxes(self): - self.cb_layout = QtGui.QHBoxLayout() + self.rb_layout = QtGui.QHBoxLayout() - cb_keys = ['current event', - 'reference set', - 'test set', - 'all'] - self.cb_dict = {} + self.rb_dict = {} self.start_button = QtGui.QPushButton('Start') - for index, key in enumerate(cb_keys): - cb = QCheckBox(key) - self.cb_dict[key] = cb - self.cb_layout.insertWidget(index, cb) - self.cb_layout.setStretch(index, 0) + for index, (key, func) in enumerate(self.pickoptions): + rb = QtGui.QRadioButton(key) + if index == 0: + rb.setChecked(True) + self.rb_dict[key] = rb + self.rb_layout.insertWidget(index, rb) + self.rb_layout.setStretch(index, 0) - self.cb_layout.addWidget(self.start_button) + self.rb_layout.addWidget(self.start_button) - self.cb_layout.addWidget(QtGui.QWidget()) - self.cb_layout.setStretch(len(cb_keys)+1, 1) + self.rb_layout.addWidget(QtGui.QWidget()) + self.rb_layout.setStretch(len(self.pickoptions)+1, 1) - self.main_layout.insertLayout(0, self.cb_layout) + self.main_layout.insertLayout(0, self.rb_layout) def init_plot_layout(self): + self.tab_plots = QtGui.QTabWidget() self.gb_plots = QtGui.QGroupBox('Plots') self.gb_plots.setMinimumSize(100, 100) self.main_splitter.insertWidget(1, self.gb_plots) self.plot_layout = QtGui.QVBoxLayout() + self.plot_layout.addWidget(self.tab_plots) + self.gb_plots.setLayout(self.plot_layout) def init_log_layout(self): self.gb_log = QtGui.QGroupBox('Log') self.gb_log.setMinimumSize(100, 100) self.main_splitter.insertWidget(0, self.gb_log) + def insert_log_widget(self, widget): + vl = QtGui.QVBoxLayout() + vl.addWidget(widget) + self.gb_log.setLayout(vl) + + def insert_plot_widget(self, widget, key, eventID): + self.tab_plots.addTab(widget, str(key+eventID)) + + def refresh_tooltips(self): + for key, func in self.pickoptions: + eventlist = func() + if not type(eventlist) == list: + eventlist = [eventlist] + tooltip='' + for index, event in enumerate(eventlist): + tooltip += '{}'.format(event.pylot_id) + if not index + 1 == len(eventlist): + tooltip += '\n' + self.rb_dict[key].setToolTip(tooltip) + def start_picker(self): - pass + self.tab_plots.clear() + self.start.emit() + + def enable(self, bool): + for rb in self.rb_dict.values(): + rb.setEnabled(bool) + self.start_button.setEnabled(bool) class TuneAutopicker(QWidget): @@ -2422,7 +2451,7 @@ class TuneAutopicker(QWidget): args = {'parameter': self.parameter, 'station': station, 'fnames': 'None', - 'eventid': self.get_current_event_fp(), + 'eventid': [self.get_current_event_fp()], 'iplot': 2, 'fig_dict': self.fig_dict, 'locflag': 0, @@ -2448,7 +2477,7 @@ class TuneAutopicker(QWidget): info = self.ap_thread._executedErrorInfo self._warn(msg, info) return - self.pylot_picks = self.ap_thread.data + self.pylot_picks = self.ap_thread.data[self.get_current_event_name()] if not self.pylot_picks: self._warn('No picks found. See terminal output.') return From 9a5196c33ff0ab5cf5492eb4ea536ac8f7cb4d2f Mon Sep 17 00:00:00 2001 From: Marcel Date: Wed, 23 Aug 2017 09:20:59 +0200 Subject: [PATCH 17/20] [minor] cosmetics --- pylot/core/util/widgets.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pylot/core/util/widgets.py b/pylot/core/util/widgets.py index a91216f3..d863fe77 100644 --- a/pylot/core/util/widgets.py +++ b/pylot/core/util/widgets.py @@ -2051,6 +2051,8 @@ class AutoPickWidget(QWidget): self.main_layout.setStretch(0, 0) self.main_layout.setStretch(1, 1) + self.main_splitter.setStretchFactor(0, 1) + self.main_splitter.setStretchFactor(1, 2) def connect_buttons(self): self.start_button.clicked.connect(self.start_picker) @@ -2109,6 +2111,8 @@ class AutoPickWidget(QWidget): tooltip += '{}'.format(event.pylot_id) if not index + 1 == len(eventlist): tooltip += '\n' + if not tooltip: + tooltip = 'No events for this selection' self.rb_dict[key].setToolTip(tooltip) def start_picker(self): From 0e650dfb75e5f32dc97bfe548e604559551eacf6 Mon Sep 17 00:00:00 2001 From: Marcel Date: Wed, 23 Aug 2017 10:25:46 +0200 Subject: [PATCH 18/20] [update] working version of autopickwidget --- QtPyLoT.py | 7 ++--- pylot/core/util/widgets.py | 52 +++++++++++++++++++++++++++++++++++--- 2 files changed, 52 insertions(+), 7 deletions(-) diff --git a/QtPyLoT.py b/QtPyLoT.py index 3f5814fc..193b8ad9 100755 --- a/QtPyLoT.py +++ b/QtPyLoT.py @@ -1910,8 +1910,8 @@ class MainWindow(QMainWindow): return self.pickoptions =[('current event', self.get_current_event), - ('reference set events', self.get_ref_events), - ('test set events', self.get_test_events), + ('tune events', self.get_ref_events), + ('test events', self.get_test_events), ('all (picked) events', self.get_manu_picked_events), ('all events', self.get_all_events)] @@ -2001,7 +2001,8 @@ class MainWindow(QMainWindow): continue event.addAutopicks(result[eventID]) jkw = JackknifeWidget(self, self.canvas_dict_wadatijack[eventID]['jackknife']) - self.apw.insert_plot_widget(jkw, 'Jackknife', eventID) + self.apw.add_plot_widget(jkw, 'Jackknife', eventID) + self.apw.update_plots() self.drawPicks(picktype='auto') self.draw() diff --git a/pylot/core/util/widgets.py b/pylot/core/util/widgets.py index d863fe77..027d2aa3 100644 --- a/pylot/core/util/widgets.py +++ b/pylot/core/util/widgets.py @@ -12,6 +12,7 @@ import multiprocessing import os import subprocess import sys +import time import numpy as np @@ -2032,6 +2033,8 @@ class AutoPickWidget(QWidget): self.pickoptions = pickoptions self.setupUi() self.connect_buttons() + self.reinitEvents2plot() + self.setWindowTitle('Autopick events interactively') # set initial size self.resize(1280, 720) @@ -2047,6 +2050,9 @@ class AutoPickWidget(QWidget): self.init_log_layout() self.init_plot_layout() + self.eventbox = QtGui.QComboBox() + self.button_clear = QtGui.QPushButton('Clear') + self.main_layout.insertWidget(1, self.main_splitter) self.main_layout.setStretch(0, 0) @@ -2056,6 +2062,7 @@ class AutoPickWidget(QWidget): def connect_buttons(self): self.start_button.clicked.connect(self.start_picker) + self.button_clear.clicked.connect(self.reinitEvents2plot) def init_checkboxes(self): self.rb_layout = QtGui.QHBoxLayout() @@ -2080,12 +2087,13 @@ class AutoPickWidget(QWidget): self.main_layout.insertLayout(0, self.rb_layout) def init_plot_layout(self): + # init tab widget self.tab_plots = QtGui.QTabWidget() self.gb_plots = QtGui.QGroupBox('Plots') self.gb_plots.setMinimumSize(100, 100) self.main_splitter.insertWidget(1, self.gb_plots) self.plot_layout = QtGui.QVBoxLayout() - self.plot_layout.addWidget(self.tab_plots) + self.plot_layout.insertWidget(1, self.tab_plots) self.gb_plots.setLayout(self.plot_layout) def init_log_layout(self): @@ -2098,8 +2106,44 @@ class AutoPickWidget(QWidget): vl.addWidget(widget) self.gb_log.setLayout(vl) - def insert_plot_widget(self, widget, key, eventID): - self.tab_plots.addTab(widget, str(key+eventID)) + def add_plot_widget(self, widget, key, eventID): + eventID += ' [picked: {}]'.format(time.strftime('%X %x %z')) + if not eventID in self.events2plot.keys(): + self.events2plot[eventID] = {} + self.events2plot[eventID][key] = widget + + def generate_combobox(self): + self.eventbox.clear() + for eventID, widgets in self.events2plot.items(): + self.eventbox.addItem(str(eventID), widgets) + self.eventbox.currentIndexChanged.connect(self.draw_plots) + self.draw_plots() + + def draw_plots(self, index=0): + self.refresh_plot_tabs() + widgets = self.eventbox.itemData(index) + if not widgets: + return + for key, widget in widgets.items(): + self.tab_plots.addTab(widget, str(key)) + + def update_plots(self): + self.refresh_plot_tabs() + if len(self.events2plot) > 0: + self.eventbox_layout = QtGui.QHBoxLayout() + self.generate_combobox() + self.eventbox_layout.addWidget(self.eventbox) + self.eventbox_layout.addWidget(self.button_clear) + self.eventbox_layout.setStretch(0, 1) + self.plot_layout.insertLayout(0, self.eventbox_layout) + + def reinitEvents2plot(self): + self.events2plot = {} + self.eventbox.clear() + self.refresh_plot_tabs() + + def refresh_plot_tabs(self): + self.tab_plots.clear() def refresh_tooltips(self): for key, func in self.pickoptions: @@ -2116,7 +2160,7 @@ class AutoPickWidget(QWidget): self.rb_dict[key].setToolTip(tooltip) def start_picker(self): - self.tab_plots.clear() + self.refresh_plot_tabs() self.start.emit() def enable(self, bool): From 47a79c766032947eade0da4d77c2906a3023a4d7 Mon Sep 17 00:00:00 2001 From: Marcel Date: Wed, 23 Aug 2017 11:51:59 +0200 Subject: [PATCH 19/20] [add] wadaticheck added to widget (problem: picking weights showing wadati/jk check will be lost on saving/loading XML) --- QtPyLoT.py | 11 +++++++++-- pylot/core/pick/autopick.py | 5 +++-- pylot/core/pick/utils.py | 35 +++++++++++++++++++++-------------- pylot/core/util/widgets.py | 8 ++++++-- 4 files changed, 39 insertions(+), 20 deletions(-) diff --git a/QtPyLoT.py b/QtPyLoT.py index 193b8ad9..0d596133 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, JackknifeWidget, AutoPickWidget + getDataType, ComparisonWidget, TuneAutopicker, PylotParaBox, AutoPickDlg, CanvasWidget, AutoPickWidget from pylot.core.util.map_projection import map_projection from pylot.core.util.structure import DATASTRUCTURE from pylot.core.util.thread import Thread, Worker @@ -1065,6 +1065,8 @@ class MainWindow(QMainWindow): if ma_props[ma]: for picks in ma_props[ma].values(): for phasename, pick in picks.items(): + if not type(pick) in [dict, AttribDict]: + continue if getQualityFromUncertainty(has_spe(pick), phaseErrors[self.getPhaseID(phasename)]) < 4: ma_count[ma] += 1 @@ -2000,8 +2002,10 @@ class MainWindow(QMainWindow): if not event: continue event.addAutopicks(result[eventID]) - jkw = JackknifeWidget(self, self.canvas_dict_wadatijack[eventID]['jackknife']) + jkw = CanvasWidget(self, self.canvas_dict_wadatijack[eventID]['jackknife']) + wdw = CanvasWidget(self, self.canvas_dict_wadatijack[eventID]['wadati']) self.apw.add_plot_widget(jkw, 'Jackknife', eventID) + self.apw.add_plot_widget(wdw, 'Wadati', eventID) self.apw.update_plots() self.drawPicks(picktype='auto') self.draw() @@ -2126,6 +2130,7 @@ class MainWindow(QMainWindow): stime = self.getStime() for phase in stat_picks: + if phase == 'SPt': continue # wadati SP time picks = stat_picks[phase] if type(stat_picks[phase]) is not dict and type(stat_picks[phase]) is not AttribDict: return @@ -2470,6 +2475,8 @@ class MainWindow(QMainWindow): if ma_props[ma]: for picks in ma_props[ma].values(): for phasename, pick in picks.items(): + if not type(pick) in [dict, AttribDict]: + continue if getQualityFromUncertainty(has_spe(pick), phaseErrors[self.getPhaseID(phasename)]) < 4: ma_count[ma] += 1 diff --git a/pylot/core/pick/autopick.py b/pylot/core/pick/autopick.py index d348e284..c5ec5d78 100644 --- a/pylot/core/pick/autopick.py +++ b/pylot/core/pick/autopick.py @@ -81,9 +81,10 @@ def autopickevent(data, param, iplot=0, fig_dict=None, fig_dict_wadatijack=None, # quality control # median check and jackknife on P-onset times jk_checked_onsets = checkPonsets(all_onsets, mdttolerance, 1, fig_dict_wadatijack) - return jk_checked_onsets + #return jk_checked_onsets # check S-P times (Wadati) - return wadaticheck(jk_checked_onsets, wdttolerance, iplot, fig_dict_wadatijack) + wadationsets = wadaticheck(jk_checked_onsets, wdttolerance, 1, fig_dict_wadatijack) + return wadationsets def call_autopickstation(input_tuple): diff --git a/pylot/core/pick/utils.py b/pylot/core/pick/utils.py index 913f1f8c..f7cb76cf 100644 --- a/pylot/core/pick/utils.py +++ b/pylot/core/pick/utils.py @@ -618,7 +618,7 @@ def wadaticheck(pickdic, dttolerance, iplot=0, fig_dict=None): ii = 0 ibad = 0 for key in pickdic: - if pickdic[key].has_key('SPt'): + if 'SPt' in pickdic[key]: wddiff = abs(pickdic[key]['SPt'] - wdfit[ii]) ii += 1 # check, if deviation is larger than adjusted @@ -662,21 +662,28 @@ def wadaticheck(pickdic, dttolerance, iplot=0, fig_dict=None): # plot results if iplot > 0: - plt.figure() # iplot) - f1, = plt.plot(Ppicks, SPtimes, 'ro') - if wfitflag == 0: - f2, = plt.plot(Ppicks, wdfit, 'k') - f3, = plt.plot(checkedPpicks, checkedSPtimes, 'ko') - f4, = plt.plot(checkedPpicks, wdfit2, 'g') - plt.title('Wadati-Diagram, %d S-P Times, Vp/Vs(raw)=%5.2f,' \ - 'Vp/Vs(checked)=%5.2f' % (len(SPtimes), vpvsr, cvpvsr)) - plt.legend([f1, f2, f3, f4], ['Skipped S-Picks', 'Wadati 1', - 'Reliable S-Picks', 'Wadati 2'], loc='best') + if fig_dict: + fig = fig_dict['wadati'] + plt_flag = 0 else: - plt.title('Wadati-Diagram, %d S-P Times' % len(SPtimes)) + fig = plt.figure() + plt_flag = 1 + ax = fig.add_subplot(111) + ax.plot(Ppicks, SPtimes, 'ro', label='Skipped S-Picks') + if wfitflag == 0: + ax.plot(Ppicks, wdfit, 'k', label='Wadati 1') + ax.plot(checkedPpicks, checkedSPtimes, 'ko', label='Reliable S-Picks') + ax.plot(checkedPpicks, wdfit2, 'g', label='Wadati 2') + ax.set_title('Wadati-Diagram, %d S-P Times, Vp/Vs(raw)=%5.2f,' \ + 'Vp/Vs(checked)=%5.2f' % (len(SPtimes), vpvsr, cvpvsr)) + ax.legend() + else: + ax.set_title('Wadati-Diagram, %d S-P Times' % len(SPtimes)) - plt.ylabel('S-P Times [s]') - plt.xlabel('P Times [s]') + ax.set_ylabel('S-P Times [s]') + ax.set_xlabel('P Times [s]') + if plt_flag: + fig.show() return checkedonsets diff --git a/pylot/core/util/widgets.py b/pylot/core/util/widgets.py index 027d2aa3..47d97057 100644 --- a/pylot/core/util/widgets.py +++ b/pylot/core/util/widgets.py @@ -1701,7 +1701,7 @@ class PickDlg(QDialog): else: ylims = self.getPlotWidget().getYLims() if self.getPicks(picktype): - if phase is not None: + if phase is not None and not phase == 'SPt': if (type(self.getPicks(picktype)[phase]) is dict or type(self.getPicks(picktype)[phase]) is AttribDict): picks = self.getPicks(picktype)[phase] @@ -2012,7 +2012,7 @@ class PhasePlotWidget(FigureCanvas): super(PhasePlotWidget, self).__init__(self.fig) -class JackknifeWidget(QWidget): +class CanvasWidget(QWidget): ''' ''' @@ -2152,6 +2152,8 @@ class AutoPickWidget(QWidget): eventlist = [eventlist] tooltip='' for index, event in enumerate(eventlist): + if not event: + continue tooltip += '{}'.format(event.pylot_id) if not index + 1 == len(eventlist): tooltip += '\n' @@ -2167,6 +2169,8 @@ class AutoPickWidget(QWidget): for rb in self.rb_dict.values(): rb.setEnabled(bool) self.start_button.setEnabled(bool) + self.eventbox.setEnabled(bool) + self.button_clear.setEnabled(bool) class TuneAutopicker(QWidget): From 2ce609a19c75e709d3732e42ec4bbc7738895853 Mon Sep 17 00:00:00 2001 From: Marcel Date: Wed, 23 Aug 2017 14:46:30 +0200 Subject: [PATCH 20/20] [bugfix] tuneAutopicker not working cause of wadatijack --- autoPyLoT.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/autoPyLoT.py b/autoPyLoT.py index d55129d6..88e09c8b 100755 --- a/autoPyLoT.py +++ b/autoPyLoT.py @@ -264,8 +264,11 @@ def autoPyLoT(input_dict=None, parameter=None, inputfile=None, fnames=None, even print(wfdat) ########################################################## # !automated picking starts here! + fdwj = None + if fig_dict_wadatijack: + fdwj = fig_dict_wadatijack[evID] picks = autopickevent(wfdat, parameter, iplot=iplot, fig_dict=fig_dict, - fig_dict_wadatijack=fig_dict_wadatijack[evID], + fig_dict_wadatijack=fdwj, ncores=ncores, metadata=metadata, origin=data.get_evt_data().origins) ########################################################## # locating