Merge branch 'develop' into darius

This commit is contained in:
Darius Arnold 2017-08-26 01:42:18 +02:00
commit 1dab754811
7 changed files with 563 additions and 189 deletions

@ -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
@ -74,12 +74,12 @@ 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, check4rotated
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, \
WaveformWidget, WaveformWidgetPG, PropertiesDlg, HelpForm, createAction, PickDlg, \
getDataType, ComparisonDialog, TuneAutopicker, PylotParaBox, AutoPickDlg
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
@ -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):
'''
@ -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()
@ -1048,12 +1053,23 @@ 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 not type(pick) in [dict, AttribDict]:
continue
if getQualityFromUncertainty(has_spe(pick), phaseErrors[self.getPhaseID(phasename)]) < 4:
ma_count[ma] += 1
event_ref = event.isRefEvent()
event_test = event.isTestEvent()
@ -1064,9 +1080,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))
@ -1215,9 +1231,13 @@ class MainWindow(QMainWindow):
def comparePicks(self):
if self.check4Comparison():
co = Comparison(auto=self.getPicks('auto'), manu=self.getPicks())
compare_dlg = ComparisonDialog(co, self)
compare_dlg.exec_()
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 = ComparisonWidget(co, self)
compare_dlg.show()
def getPlotWidget(self):
return self.dataPlot
@ -1813,16 +1833,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',
@ -1834,12 +1846,45 @@ class MainWindow(QMainWindow):
'el_S1pick',
'el_S2pick',
'refSpick',
'aicARHfig',
'aicARHfig'
]
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 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
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)
@ -1858,8 +1903,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):
@ -1868,36 +1912,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),
('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)]
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.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': 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)
@ -1909,12 +1996,63 @@ 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 = 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()
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)
if not stat_picks:
@ -1994,16 +2132,17 @@ 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
# 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
@ -2326,12 +2465,22 @@ 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 not type(pick) in [dict, AttribDict]:
continue
if getQualityFromUncertainty(has_spe(pick), phaseErrors[self.getPhaseID(phasename)]) < 4:
ma_count[ma] += 1
# init table items for current row
item_delete = QtGui.QTableWidgetItem()
@ -2342,9 +2491,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()

@ -78,12 +78,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:
@ -179,13 +184,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!')
@ -196,6 +202,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]
@ -260,14 +267,12 @@ 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)
fdwj = None
if fig_dict_wadatijack:
fdwj = fig_dict_wadatijack[evID]
picks = autopickevent(wfdat, parameter, iplot=iplot, fig_dict=fig_dict,
fig_dict_wadatijack=fdwj,
ncores=ncores, metadata=metadata, origin=data.get_evt_data().origins)
##########################################################
# locating
if locflag > 0:
@ -383,7 +388,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)
@ -394,7 +400,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],
@ -452,13 +459,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__":

@ -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 = getQualityFromUncertainty(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 = getQualityFromUncertainty(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')

@ -18,13 +18,13 @@ 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
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 = []
@ -76,14 +76,15 @@ def autopickevent(data, param, iplot=0, fig_dict=None, ncores=0, metadata=None,
pick.pop('station')
all_onsets[station] = pick
all_onsets = checkPonsets(all_onsets, mdttolerance, iplot)
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_wadatijack)
#return jk_checked_onsets
# check S-P times (Wadati)
return wadaticheck(jk_checked_onsets, wdttolerance, iplot)
wadationsets = wadaticheck(jk_checked_onsets, wdttolerance, 1, fig_dict_wadatijack)
return wadationsets
def call_autopickstation(input_tuple):
@ -255,7 +256,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])
@ -984,9 +985,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
@ -998,27 +999,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
@ -1028,12 +1029,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

@ -566,7 +566,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
@ -620,7 +620,7 @@ def wadaticheck(pickdic, dttolerance, iplot):
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
@ -664,21 +664,28 @@ def wadaticheck(pickdic, dttolerance, iplot):
# 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
@ -796,7 +803,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-
@ -818,17 +825,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)
@ -872,21 +881,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
@ -922,6 +940,7 @@ def jackknife(X, phi, h):
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)
@ -1100,7 +1119,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.
'''

@ -74,6 +74,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
@ -897,6 +928,15 @@ def identifyPhase(phase):
return False
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__":

@ -12,6 +12,7 @@ import multiprocessing
import os
import subprocess
import sys
import time
import numpy as np
@ -22,7 +23,7 @@ except:
from matplotlib.figure import Figure
from pylot.core.util.utils import find_horizontals, identifyPhase, loopIdentifyPhase, trim_station_components, \
check4rotated
identifyPhaseID
try:
from matplotlib.backends.backend_qt4agg import FigureCanvas
@ -45,7 +46,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
@ -119,7 +120,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 +130,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 +164,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
@ -271,6 +268,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()
@ -1286,7 +1287,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:
@ -1700,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]
@ -1715,10 +1716,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()
@ -2011,6 +2012,167 @@ class PhasePlotWidget(FigureCanvas):
super(PhasePlotWidget, self).__init__(self.fig)
class CanvasWidget(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 AutoPickWidget(QWidget):
start = Signal()
'''
'''
def __init__(self, parent, pickoptions):
QtGui.QWidget.__init__(self, parent, 1)
self.pickoptions = pickoptions
self.setupUi()
self.connect_buttons()
self.reinitEvents2plot()
self.setWindowTitle('Autopick events interactively')
# 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.eventbox = QtGui.QComboBox()
self.button_clear = QtGui.QPushButton('Clear')
self.main_layout.insertWidget(1, self.main_splitter)
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)
self.button_clear.clicked.connect(self.reinitEvents2plot)
def init_checkboxes(self):
self.rb_layout = QtGui.QHBoxLayout()
self.rb_dict = {}
self.start_button = QtGui.QPushButton('Start')
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.rb_layout.addWidget(self.start_button)
self.rb_layout.addWidget(QtGui.QWidget())
self.rb_layout.setStretch(len(self.pickoptions)+1, 1)
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.insertWidget(1, 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 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:
eventlist = func()
if not type(eventlist) == list:
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'
if not tooltip:
tooltip = 'No events for this selection'
self.rb_dict[key].setToolTip(tooltip)
def start_picker(self):
self.refresh_plot_tabs()
self.start.emit()
def enable(self, bool):
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):
update = QtCore.Signal(str)
'''
@ -2343,7 +2505,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,
@ -2369,7 +2531,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