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

View File

@ -64,7 +64,7 @@ from pylot.core.io.data import Data
from pylot.core.io.inputs import FilterOptions, PylotParameter from pylot.core.io.inputs import FilterOptions, PylotParameter
from autoPyLoT import autoPyLoT from autoPyLoT import autoPyLoT
from pylot.core.pick.compare import Comparison 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 from pylot.core.io.phases import picksdict_from_picks
import pylot.core.loc.nll as nll import pylot.core.loc.nll as nll
from pylot.core.util.defaults import FILTERDEFAULTS, SetChannelComponents 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.dataprocessing import read_metadata, restitute_data
from pylot.core.util.utils import fnConstructor, getLogin, \ from pylot.core.util.utils import fnConstructor, getLogin, \
full_range, readFilterInformation, trim_station_components, check4gaps, make_pen, pick_color_plt, \ 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.util.event import Event
from pylot.core.io.location import create_creation_info, create_event from pylot.core.io.location import create_creation_info, create_event
from pylot.core.util.widgets import FilterOptionsDialog, NewEventDlg, \ from pylot.core.util.widgets import FilterOptionsDialog, NewEventDlg, \
WaveformWidget, WaveformWidgetPG, PropertiesDlg, HelpForm, createAction, PickDlg, \ 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.map_projection import map_projection
from pylot.core.util.structure import DATASTRUCTURE from pylot.core.util.structure import DATASTRUCTURE
from pylot.core.util.thread import Thread, Worker from pylot.core.util.thread import Thread, Worker
@ -865,7 +865,7 @@ class MainWindow(QMainWindow):
return fnames return fnames
def getPhaseID(self, phase): def getPhaseID(self, phase):
return identifyPhase(loopIdentifyPhase(phase)) return identifyPhaseID(phase)
def get_current_event(self, eventbox=None): def get_current_event(self, eventbox=None):
''' '''
@ -1025,6 +1025,11 @@ class MainWindow(QMainWindow):
:param: select_events, can be 'all', 'ref' :param: select_events, can be 'all', 'ref'
:type: str :type: str
''' '''
# if pick widget is open, refresh tooltips as well
if hasattr(self, 'apw'):
self.apw.refresh_tooltips()
if not eventBox: if not eventBox:
eventBox = self.eventBox eventBox = self.eventBox
index = eventBox.currentIndex() index = eventBox.currentIndex()
@ -1048,12 +1053,23 @@ class MainWindow(QMainWindow):
for id, event in enumerate(self.project.eventlist): for id, event in enumerate(self.project.eventlist):
event_path = event.path event_path = event.path
event_npicks = 0 phaseErrors = {'P': self._inputs['timeerrorsP'],
event_nautopicks = 0 'S': self._inputs['timeerrorsS']}
if event.pylot_picks:
event_npicks = len(event.pylot_picks) ma_props = {'manual': event.pylot_picks,
if event.pylot_autopicks: 'auto': event.pylot_autopicks}
event_nautopicks = len(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_ref = event.isRefEvent()
event_test = event.isTestEvent() event_test = event.isTestEvent()
@ -1064,9 +1080,9 @@ class MainWindow(QMainWindow):
# a=event_nautopicks) # a=event_nautopicks)
item_path = QtGui.QStandardItem('{path:{plen}}'.format(path=event_path, plen=plmax)) 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_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_nap.setIcon(self.autopicksicon_small)
item_ref = QtGui.QStandardItem() # str(event_ref)) item_ref = QtGui.QStandardItem() # str(event_ref))
item_test = QtGui.QStandardItem() # str(event_test)) item_test = QtGui.QStandardItem() # str(event_test))
@ -1215,9 +1231,13 @@ class MainWindow(QMainWindow):
def comparePicks(self): def comparePicks(self):
if self.check4Comparison(): if self.check4Comparison():
co = Comparison(auto=self.getPicks('auto'), manu=self.getPicks()) autopicks = excludeQualityClasses(self.getPicks('auto'), [4],
compare_dlg = ComparisonDialog(co, self) self._inputs['timeerrorsP'], self._inputs['timeerrorsS'])
compare_dlg.exec_() 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): def getPlotWidget(self):
return self.dataPlot return self.dataPlot
@ -1813,16 +1833,8 @@ class MainWindow(QMainWindow):
self.listWidget.addItem(text) self.listWidget.addItem(text)
self.listWidget.scrollToBottom() self.listWidget.scrollToBottom()
def tune_autopicker(self): def init_fig_dict(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.fig_dict = {} self.fig_dict = {}
self.canvas_dict = {}
self.fig_keys = [ self.fig_keys = [
'mainFig', 'mainFig',
'aicFig', 'aicFig',
@ -1834,12 +1846,45 @@ class MainWindow(QMainWindow):
'el_S1pick', 'el_S1pick',
'el_S2pick', 'el_S2pick',
'refSpick', 'refSpick',
'aicARHfig', 'aicARHfig'
] ]
for key in self.fig_keys: for key in self.fig_keys:
fig = Figure() fig = Figure()
self.fig_dict[key] = fig 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: #if not self.tap:
# init TuneAutopicker object # init TuneAutopicker object
self.tap = TuneAutopicker(self) self.tap = TuneAutopicker(self)
@ -1858,8 +1903,7 @@ class MainWindow(QMainWindow):
''' '''
Create and fill TuneAutopicker tabs with figure canvas. Create and fill TuneAutopicker tabs with figure canvas.
''' '''
for key in self.fig_keys: self.init_canvas_dict()
self.canvas_dict[key] = FigureCanvas(self.fig_dict[key])
self.tap.fill_tabs(picked=True) self.tap.fill_tabs(picked=True)
def autoPick(self): def autoPick(self):
@ -1868,36 +1912,79 @@ class MainWindow(QMainWindow):
QMessageBox.warning(self, "PyLoT Warning", QMessageBox.warning(self, "PyLoT Warning",
"No autoPyLoT output declared!") "No autoPyLoT output declared!")
return 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.listWidget = QListWidget()
self.setDirty(True) self.setDirty(True)
self.logDockWidget = QDockWidget("AutoPickLog", self) self.apw = AutoPickWidget(self, self.pickoptions)
self.logDockWidget.setObjectName("LogDockWidget") self.apw.insert_log_widget(self.listWidget)
self.logDockWidget.setAllowedAreas( self.apw.refresh_tooltips()
Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea)
self.logDockWidget.setWidget(self.listWidget) # self.logDockWidget = QDockWidget("AutoPickLog", self)
self.addDockWidget(Qt.LeftDockWidgetArea, self.logDockWidget) # 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.addListItem('Loading default values from PyLoT-input file %s'
# % self.infile) # % 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, args = {'parameter': self._inputs,
'station': 'all', 'station': 'all',
'fnames': 'None', 'fnames': 'None',
'eventid': self.get_current_event_path(), 'eventid': eventPaths,
'iplot': 0, 'iplot': 0,
'fig_dict': None, 'fig_dict': None,
'fig_dict_wadatijack': self.fig_dict_wadatijack,
'locflag': 0} 'locflag': 0}
# init pick thread
self.mp_thread = QtCore.QThreadPool() self.mp_thread = QtCore.QThreadPool()
self.mp_worker = Worker(autoPyLoT, args, redirect_stdout=True) self.mp_worker = Worker(autoPyLoT, args, redirect_stdout=True)
self.mp_thread.start(self.mp_worker)
self.addListItem(str(self._inputs)) self.addListItem(str(self._inputs))
self.mp_worker.signals.message.connect(self.addListItem) self.mp_worker.signals.message.connect(self.addListItem)
self.mp_worker.signals.result.connect(self.finalizeAutoPick) self.mp_worker.signals.result.connect(self.finalizeAutoPick)
self.mp_thread.start(self.mp_worker)
def autoPickProject(self): def autoPickProject(self):
if not self.apd_local: if not self.apd_local:
self.apd_local = AutoPickDlg(self, sge=False) self.apd_local = AutoPickDlg(self, sge=False)
@ -1909,12 +1996,63 @@ class MainWindow(QMainWindow):
self.apd_sge.show() self.apd_sge.show()
def finalizeAutoPick(self, result): def finalizeAutoPick(self, result):
self.apw.enable(True)
if result: if result:
event = self.get_current_event() self.init_canvas_dict_wadatijack()
event.addAutopicks(result) 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.drawPicks(picktype='auto')
self.draw() 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'): def addPicks(self, station, picks, type='manual'):
stat_picks = self.getPicksOnStation(station, type) stat_picks = self.getPicksOnStation(station, type)
if not stat_picks: if not stat_picks:
@ -1994,16 +2132,17 @@ class MainWindow(QMainWindow):
stime = self.getStime() stime = self.getStime()
for phase in stat_picks: for phase in stat_picks:
if phase == 'SPt': continue # wadati SP time
picks = stat_picks[phase] picks = stat_picks[phase]
if type(stat_picks[phase]) is not dict and type(stat_picks[phase]) is not AttribDict: if type(stat_picks[phase]) is not dict and type(stat_picks[phase]) is not AttribDict:
return return
# get quality classes # get quality classes
if self.getPhaseID(phase) == 'P': if self.getPhaseID(phase) == 'P':
quality = getQualityfromUncertainty(picks['spe'], self._inputs['timeerrorsP']) quality = getQualityFromUncertainty(picks['spe'], self._inputs['timeerrorsP'])
phaseID = 'P' phaseID = 'P'
elif self.getPhaseID(phase) == 'S': elif self.getPhaseID(phase) == 'S':
quality = getQualityfromUncertainty(picks['spe'], self._inputs['timeerrorsS']) quality = getQualityFromUncertainty(picks['spe'], self._inputs['timeerrorsS'])
phaseID = 'S' phaseID = 'S'
mpp = picks['mpp'] - stime mpp = picks['mpp'] - stime
@ -2326,12 +2465,22 @@ class MainWindow(QMainWindow):
# iterate through eventlist and generate items for table rows # iterate through eventlist and generate items for table rows
self.project._table = [] self.project._table = []
for index, event in enumerate(eventlist): for index, event in enumerate(eventlist):
event_npicks = 0 phaseErrors = {'P': self._inputs['timeerrorsP'],
event_nautopicks = 0 'S': self._inputs['timeerrorsS']}
if event.pylot_picks:
event_npicks = len(event.pylot_picks) ma_props = {'manual': event.pylot_picks,
if event.pylot_autopicks: 'auto': event.pylot_autopicks}
event_nautopicks = len(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 # init table items for current row
item_delete = QtGui.QTableWidgetItem() item_delete = QtGui.QTableWidgetItem()
@ -2342,9 +2491,9 @@ class MainWindow(QMainWindow):
item_lon = QtGui.QTableWidgetItem() item_lon = QtGui.QTableWidgetItem()
item_depth = QtGui.QTableWidgetItem() item_depth = QtGui.QTableWidgetItem()
item_mag = 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_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_nap.setIcon(self.autopicksicon_small)
item_ref = QtGui.QTableWidgetItem() item_ref = QtGui.QTableWidgetItem()
item_test = QtGui.QTableWidgetItem() item_test = QtGui.QTableWidgetItem()

View File

@ -78,12 +78,17 @@ def autoPyLoT(input_dict=None, parameter=None, inputfile=None, fnames=None, even
inputfile = real_None(inputfile) inputfile = real_None(inputfile)
eventid = real_None(eventid) eventid = real_None(eventid)
fig_dict = None
fig_dict_wadatijack = None
locflag = 1 locflag = 1
if input_dict and isinstance(input_dict, dict): if input_dict and isinstance(input_dict, dict):
if 'parameter' in input_dict: if 'parameter' in input_dict:
parameter = input_dict['parameter'] parameter = input_dict['parameter']
if 'fig_dict' in input_dict: if 'fig_dict' in input_dict:
fig_dict = input_dict['fig_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: if 'station' in input_dict:
station = input_dict['station'] station = input_dict['station']
if 'fnames' in input_dict: 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] evID = os.path.split(eventid)[-1]
locflag = 2 locflag = 2
else: else:
# started in tune mode # started in tune or interactive mode
datapath = os.path.join(parameter['rootpath'], datapath = os.path.join(parameter['rootpath'],
parameter['datapath']) parameter['datapath'])
events = [] events = []
events.append(os.path.join(datapath, for eventID in eventid:
parameter['database'], events.append(os.path.join(datapath,
eventid)) parameter['database'],
eventID))
if not events: if not events:
print('autoPyLoT: No events given. Return!') 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, '/') eventpath = eventpath.replace(SEPARATOR, '/')
events[index] = eventpath events[index] = eventpath
allpicks = {}
glocflag = locflag glocflag = locflag
for eventpath in events: for eventpath in events:
evID = os.path.split(eventpath)[-1] evID = os.path.split(eventpath)[-1]
@ -260,14 +267,12 @@ def autoPyLoT(input_dict=None, parameter=None, inputfile=None, fnames=None, even
print(wfdat) print(wfdat)
########################################################## ##########################################################
# !automated picking starts here! # !automated picking starts here!
if input_dict: fdwj = None
if 'fig_dict' in input_dict: if fig_dict_wadatijack:
fig_dict = input_dict['fig_dict'] fdwj = fig_dict_wadatijack[evID]
picks = autopickevent(wfdat, parameter, iplot=iplot, fig_dict=fig_dict, picks = autopickevent(wfdat, parameter, iplot=iplot, fig_dict=fig_dict,
ncores=ncores, metadata=metadata, origin=data.get_evt_data().origins) fig_dict_wadatijack=fdwj,
else: ncores=ncores, metadata=metadata, origin=data.get_evt_data().origins)
picks = autopickevent(wfdat, parameter, iplot=iplot,
ncores=ncores, metadata=metadata, origin=data.get_evt_data().origins)
########################################################## ##########################################################
# locating # locating
if locflag > 0: if locflag > 0:
@ -383,7 +388,8 @@ def autoPyLoT(input_dict=None, parameter=None, inputfile=None, fnames=None, even
iplot) iplot)
# update pick with moment property values (w0, fc, Mo) # update pick with moment property values (w0, fc, Mo)
for stats, props in moment_mag.moment_props.items(): 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() evt = moment_mag.updated_event()
net_mw = moment_mag.net_magnitude() net_mw = moment_mag.net_magnitude()
print("Network moment magnitude: %4.1f" % net_mw.mag) 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'), parameter.get('sstop'),
WAscaling, True, iplot) WAscaling, True, iplot)
for stats, amplitude in local_mag.amplitudes.items(): 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("Local station magnitudes scaled with:")
print("log(Ao) + %f * log(r) + %f * r + %f" % (WAscaling[0], print("log(Ao) + %f * log(r) + %f * r + %f" % (WAscaling[0],
WAscaling[1], WAscaling[1],
@ -452,13 +459,16 @@ def autoPyLoT(input_dict=None, parameter=None, inputfile=None, fnames=None, even
if locflag == 0: if locflag == 0:
print("autoPyLoT was running in non-location mode!") print("autoPyLoT was running in non-location mode!")
# save picks for current event ID to dictionary with ALL picks
allpicks[evID] = picks
endsp = '''####################################\n endsp = '''####################################\n
************************************\n ************************************\n
*********autoPyLoT terminates*******\n *********autoPyLoT terminates*******\n
The Python picking and Location Tool\n The Python picking and Location Tool\n
************************************'''.format(version=_getVersionString()) ************************************'''.format(version=_getVersionString())
print(endsp) print(endsp)
return picks return allpicks
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -879,6 +879,9 @@ def getQualitiesfromxml(xmlnames, ErrorsP, ErrorsS, plotflag=1):
Ludger Küperkoch, BESTEC GmbH, 07/2017 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 # read all onset weights
Pw0 = [] Pw0 = []
Pw1 = [] Pw1 = []
@ -902,14 +905,15 @@ def getQualitiesfromxml(xmlnames, ErrorsP, ErrorsS, plotflag=1):
mstation = Pick.waveform_id.station_code mstation = Pick.waveform_id.station_code
mstation_ext = mstation + '_' mstation_ext = mstation + '_'
for mpick in arrivals_copy: 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 \ if ((mpick.waveform_id.station_code == mstation) or \
(mpick.waveform_id.station_code == mstation_ext)) and \ (mpick.waveform_id.station_code == mstation_ext)) and \
((mpick.method_id).split('/')[1] == 'auto') and \ ((mpick.method_id).split('/')[1] == 'auto') and \
(mpick.time_errors['uncertainty'] <= ErrorsP[3]): (mpick.time_errors['uncertainty'] <= ErrorsP[3]):
del mpick del mpick
break break
elif mpick.phase_hint[0] == 'S': elif phase == 'S':
if ((mpick.waveform_id.station_code == mstation) or \ if ((mpick.waveform_id.station_code == mstation) or \
(mpick.waveform_id.station_code == mstation_ext)) and \ (mpick.waveform_id.station_code == mstation_ext)) and \
((mpick.method_id).split('/')[1] == 'auto') 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)) print("Found manual as well as automatic picks, prefered the {} manual ones!".format(lendiff))
for Pick in arrivals_copy: for Pick in arrivals_copy:
if Pick.phase_hint[0] == 'P': phase = identifyPhase(loopIdentifyPhase(Pick.phase_hint))
if Pick.time_errors.uncertainty <= ErrorsP[0]: if phase == 'P':
Pqual = getQualityFromUncertainty(Pick.time_errors.uncertainty, ErrorsP)
if Pqual == 0:
Pw0.append(Pick.time_errors.uncertainty) Pw0.append(Pick.time_errors.uncertainty)
elif (Pick.time_errors.uncertainty > ErrorsP[0]) and \ elif Pqual == 1:
(Pick.time_errors.uncertainty <= ErrorsP[1]):
Pw1.append(Pick.time_errors.uncertainty) Pw1.append(Pick.time_errors.uncertainty)
elif (Pick.time_errors.uncertainty > ErrorsP[1]) and \ elif Pqual == 2:
(Pick.time_errors.uncertainty <= ErrorsP[2]):
Pw2.append(Pick.time_errors.uncertainty) Pw2.append(Pick.time_errors.uncertainty)
elif (Pick.time_errors.uncertainty > ErrorsP[2]) and \ elif Pqual == 3:
(Pick.time_errors.uncertainty <= ErrorsP[3]):
Pw3.append(Pick.time_errors.uncertainty) Pw3.append(Pick.time_errors.uncertainty)
elif Pick.time_errors.uncertainty > ErrorsP[3]: elif Pqual == 4:
Pw4.append(Pick.time_errors.uncertainty) Pw4.append(Pick.time_errors.uncertainty)
else: elif phase == 'S':
pass Squal = getQualityFromUncertainty(Pick.time_errors.uncertainty, ErrorsS)
elif Pick.phase_hint[0] == 'S': if Squal == 0:
if Pick.time_errors.uncertainty <= ErrorsS[0]:
Sw0.append(Pick.time_errors.uncertainty) Sw0.append(Pick.time_errors.uncertainty)
elif (Pick.time_errors.uncertainty > ErrorsS[0]) and \ elif Squal == 1:
(Pick.time_errors.uncertainty <= ErrorsS[1]):
Sw1.append(Pick.time_errors.uncertainty) Sw1.append(Pick.time_errors.uncertainty)
elif (Pick.time_errors.uncertainty > ErrorsS[1]) and \ elif Squal == 2:
(Pick.time_errors.uncertainty <= ErrorsS[2]):
Sw2.append(Pick.time_errors.uncertainty) Sw2.append(Pick.time_errors.uncertainty)
elif (Pick.time_errors.uncertainty > ErrorsS[2]) and \ elif Squal == 3:
(Pick.time_errors.uncertainty <= ErrorsS[3]):
Sw3.append(Pick.time_errors.uncertainty) Sw3.append(Pick.time_errors.uncertainty)
elif Pick.time_errors.uncertainty > ErrorsS[3]: elif Squal == 4:
Sw4.append(Pick.time_errors.uncertainty) Sw4.append(Pick.time_errors.uncertainty)
else:
pass
else: else:
print("Phase hint not defined for picking!") print("Phase hint not defined for picking!")
pass pass
@ -965,45 +962,45 @@ def getQualitiesfromxml(xmlnames, ErrorsP, ErrorsS, plotflag=1):
# get percentage of weights # get percentage of weights
numPweights = np.sum([len(Pw0), len(Pw1), len(Pw2), len(Pw3), len(Pw4)]) 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)]) numSweights = np.sum([len(Sw0), len(Sw1), len(Sw2), len(Sw3), len(Sw4)])
try: if len(Pw0) > 0:
P0perc = 100 / numPweights * len(Pw0) P0perc = 100 / numPweights * len(Pw0)
except: else:
P0perc = 0 P0perc = 0
try: if len(Pw1) > 0:
P1perc = 100 / numPweights * len(Pw1) P1perc = 100 / numPweights * len(Pw1)
except: else:
P1perc = 0 P1perc = 0
try: if len(Pw2) > 0:
P2perc = 100 / numPweights * len(Pw2) P2perc = 100 / numPweights * len(Pw2)
except: else:
P2perc = 0 P2perc = 0
try: if len(Pw3) > 0:
P3perc = 100 / numPweights * len(Pw3) P3perc = 100 / numPweights * len(Pw3)
except: else:
P3perc = 0 P3perc = 0
try: if len(Pw4) > 0:
P4perc = 100 / numPweights * len(Pw4) P4perc = 100 / numPweights * len(Pw4)
except: else:
P4perc = 0 P4perc = 0
try: if len(Sw0) > 0:
S0perc = 100 / numSweights * len(Sw0) S0perc = 100 / numSweights * len(Sw0)
except: else:
S0perc = 0 S0perc = 0
try: if len(Sw1) > 0:
S1perc = 100 / numSweights * len(Sw1) S1perc = 100 / numSweights * len(Sw1)
except: else:
S1perc = 0 S1perc = 0
try: if len(Sw2) > 0:
S2perc = 100 / numSweights * len(Sw2) S2perc = 100 / numSweights * len(Sw2)
except: else:
S2perc = 0 S2perc = 0
try: if len(Sw3) > 0:
S3perc = 100 / numSweights * len(Sw3) S3perc = 100 / numSweights * len(Sw3)
except: else:
S3perc = 0 S3perc = 0
try: if len(Sw4) > 0:
S4perc = 100 / numSweights * len(Sw4) S4perc = 100 / numSweights * len(Sw4)
except: else:
S4perc = 0 S4perc = 0
weights = ('0', '1', '2', '3', '4') weights = ('0', '1', '2', '3', '4')

View File

@ -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.picker import AICPicker, PragPicker
from pylot.core.pick.utils import checksignallength, checkZ4S, earllatepicker, \ from pylot.core.pick.utils import checksignallength, checkZ4S, earllatepicker, \
getSNR, fmpicker, checkPonsets, wadaticheck getSNR, fmpicker, checkPonsets, wadaticheck
from pylot.core.util.utils import getPatternLine, gen_Pool, identifyPhase, loopIdentifyPhase, \ from pylot.core.util.utils import getPatternLine, gen_Pool,\
real_Bool real_Bool, identifyPhaseID
from obspy.taup import TauPyModel 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 = [] stations = []
all_onsets = {} all_onsets = {}
input_tuples = [] input_tuples = []
@ -76,14 +76,15 @@ def autopickevent(data, param, iplot=0, fig_dict=None, ncores=0, metadata=None,
pick.pop('station') pick.pop('station')
all_onsets[station] = pick all_onsets[station] = pick
all_onsets = checkPonsets(all_onsets, mdttolerance, iplot) #return all_onsets
return all_onsets
# quality control # quality control
# median check and jackknife on P-onset times # 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) # 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): def call_autopickstation(input_tuple):
@ -255,7 +256,7 @@ def autopickstation(wfstream, pickparam, verbose=False,
phases = {'P': [], phases = {'P': [],
'S': []} 'S': []}
for arr in arrivals: 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 # 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]) 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 # calculate "real" onset times
if lpickP is not None and lpickP == mpickP: if lpickP is not None and lpickP == mpickP:
lpickP += timeerrorsP[0] lpickP += zdat[0].stats.delta
if epickP is not None and epickP == mpickP: 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: if mpickP is not None and epickP is not None and lpickP is not None:
lpickP = zdat[0].stats.starttime + lpickP lpickP = zdat[0].stats.starttime + lpickP
epickP = zdat[0].stats.starttime + epickP epickP = zdat[0].stats.starttime + epickP
@ -998,27 +999,27 @@ def autopickstation(wfstream, pickparam, verbose=False,
epickP = zdat[0].stats.starttime - timeerrorsP[3] epickP = zdat[0].stats.starttime - timeerrorsP[3]
mpickP = zdat[0].stats.starttime 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: if lpickS is not None and lpickS == mpickS:
lpickS += timeerrorsS[0] lpickS += hdat.stats.delta
if epickS is not None and epickS == mpickS: 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: if mpickS is not None and epickS is not None and lpickS is not None:
lpickS = edat[0].stats.starttime + lpickS lpickS = hdat.stats.starttime + lpickS
epickS = edat[0].stats.starttime + epickS epickS = hdat.stats.starttime + epickS
mpickS = edat[0].stats.starttime + mpickS mpickS = hdat.stats.starttime + mpickS
else: else:
# dummy values (start of seismic trace) in order to derive # dummy values (start of seismic trace) in order to derive
# theoretical onset times for iteratve picking # theoretical onset times for iteratve picking
if edat: lpickS = hdat.stats.starttime + timeerrorsS[3]
lpickS = edat[0].stats.starttime + timeerrorsS[3] epickS = hdat.stats.starttime - timeerrorsS[3]
epickS = edat[0].stats.starttime - timeerrorsS[3] mpickS = hdat.stats.starttime
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
# create dictionary # create dictionary
# for P phase # 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, snrdb=SNRPdB, weight=Pweight, fm=FM, w0=None, fc=None, Mo=None,
Mw=None, picker=picker, marked=Pmarker) Mw=None, picker=picker, marked=Pmarker)
# add S phase # add S phase
try: ccode = hdat.stats.channel
ccode = edat[0].stats.channel ncode = hdat.stats.network
ncode = edat[0].stats.network
except:
ccode = ndat[0].stats.channel
ncode = ndat[0].stats.network
spick = dict(channel=ccode, network=ncode, lpp=lpickS, epp=epickS, mpp=mpickS, spe=Serror, snr=SNRS, 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) snrdb=SNRSdB, weight=Sweight, fm=None, picker=picker, Ao=Ao)
# merge picks into returning dictionary # merge picks into returning dictionary

View File

@ -566,7 +566,7 @@ def select_for_phase(st, phase):
return sel_st 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 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 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 ii = 0
ibad = 0 ibad = 0
for key in pickdic: for key in pickdic:
if pickdic[key].has_key('SPt'): if 'SPt' in pickdic[key]:
wddiff = abs(pickdic[key]['SPt'] - wdfit[ii]) wddiff = abs(pickdic[key]['SPt'] - wdfit[ii])
ii += 1 ii += 1
# check, if deviation is larger than adjusted # check, if deviation is larger than adjusted
@ -664,21 +664,28 @@ def wadaticheck(pickdic, dttolerance, iplot):
# plot results # plot results
if iplot > 0: if iplot > 0:
plt.figure() # iplot) if fig_dict:
f1, = plt.plot(Ppicks, SPtimes, 'ro') fig = fig_dict['wadati']
if wfitflag == 0: plt_flag = 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')
else: 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]') ax.set_ylabel('S-P Times [s]')
plt.xlabel('P Times [s]') ax.set_xlabel('P Times [s]')
if plt_flag:
fig.show()
return checkedonsets return checkedonsets
@ -796,7 +803,7 @@ def checksignallength(X, pick, TSNR, minsiglength, nfac, minpercent, iplot=0, fi
return returnflag 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 Function to check statistics of P-onset times: Control deviation from
median (maximum adjusted deviation = dttolerance) and apply pseudo- median (maximum adjusted deviation = dttolerance) and apply pseudo-
@ -818,17 +825,19 @@ def checkPonsets(pickdic, dttolerance, iplot):
# search for good quality P picks # search for good quality P picks
Ppicks = [] Ppicks = []
stations = [] stations = []
for key in pickdic: for station in pickdic:
if pickdic[key]['P']['weight'] < 4: if pickdic[station]['P']['weight'] < 4:
# add P onsets to list # add P onsets to list
UTCPpick = UTCDateTime(pickdic[key]['P']['mpp']) UTCPpick = UTCDateTime(pickdic[station]['P']['mpp'])
Ppicks.append(UTCPpick.timestamp) Ppicks.append(UTCPpick.timestamp)
stations.append(key) stations.append(station)
# apply jackknife bootstrapping on variance of P onsets # apply jackknife bootstrapping on variance of P onsets
print("###############################################") print("###############################################")
print("checkPonsets: Apply jackknife bootstrapping on P-onset times ...") print("checkPonsets: Apply jackknife bootstrapping on P-onset times ...")
[xjack, PHI_pseudo, PHI_sub] = jackknife(Ppicks, 'VAR', 1) [xjack, PHI_pseudo, PHI_sub] = jackknife(Ppicks, 'VAR', 1)
if not xjack:
return
# get pseudo variances smaller than average variances # get pseudo variances smaller than average variances
# (times safety factor), these picks passed jackknife test # (times safety factor), these picks passed jackknife test
ij = np.where(PHI_pseudo <= 5 * xjack) ij = np.where(PHI_pseudo <= 5 * xjack)
@ -872,21 +881,30 @@ def checkPonsets(pickdic, dttolerance, iplot):
checkedonsets = pickdic checkedonsets = pickdic
if iplot > 0: if iplot > 0:
p1, = plt.plot(np.arange(0, len(Ppicks)), Ppicks, 'ro', markersize=14) if fig_dict:
if len(badstations) < 1 and len(badjkstations) < 1: fig = fig_dict['jackknife']
p2, = plt.plot(np.arange(0, len(Ppicks)), Ppicks, 'go', markersize=14) plt_flag = 0
else: else:
p2, = plt.plot(igood, np.array(Ppicks)[igood], 'go', markersize=14) fig = plt.figure()
p3, = plt.plot([0, len(Ppicks) - 1], [pmedian, pmedian], 'g', plt_flag = 1
linewidth=2) ax = fig.add_subplot(111)
for i in range(0, len(Ppicks)):
plt.text(i, Ppicks[i] + 0.01, '{0}'.format(stations[i]))
plt.xlabel('Number of P Picks') ax.plot(np.arange(0, len(Ppicks)), Ppicks, 'ro', markersize=14)
plt.ylabel('Onset Time [s] from 1.1.1970') if len(badstations) < 1 and len(badjkstations) < 1:
plt.legend([p1, p2, p3], ['Skipped P Picks', 'Good P Picks', 'Median'], ax.plot(np.arange(0, len(Ppicks)), Ppicks, 'go', markersize=14, label='Skipped P Picks')
loc='best') else:
plt.title('Jackknifing and Median Tests on P Onsets') 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 return checkedonsets
@ -922,6 +940,7 @@ def jackknife(X, phi, h):
print("Choose another size for subgroups!") print("Choose another size for subgroups!")
return PHI_jack, PHI_pseudo, PHI_sub return PHI_jack, PHI_pseudo, PHI_sub
else: else:
g = int(len(X) / h)
# estimator of undisturbed spot check # estimator of undisturbed spot check
if phi == 'MEA': if phi == 'MEA':
phi_sc = np.mean(X) phi_sc = np.mean(X)
@ -1100,7 +1119,7 @@ def checkZ4S(X, pick, zfac, checkwin, iplot, fig=None):
return returnflag return returnflag
def getQualityfromUncertainty(uncertainty, Errors): def getQualityFromUncertainty(uncertainty, Errors):
'''Script to transform uncertainty into quality classes 0-4 '''Script to transform uncertainty into quality classes 0-4
regarding adjusted time errors Errors. regarding adjusted time errors Errors.
''' '''

View File

@ -74,6 +74,37 @@ def gen_Pool(ncores=0):
return pool 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): def clims(lim1, lim2):
""" """
takes two pairs of limits and returns one pair of common limts takes two pairs of limits and returns one pair of common limts
@ -897,6 +928,15 @@ def identifyPhase(phase):
return False 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__": if __name__ == "__main__":

View File

@ -12,6 +12,7 @@ import multiprocessing
import os import os
import subprocess import subprocess
import sys import sys
import time
import numpy as np import numpy as np
@ -22,7 +23,7 @@ except:
from matplotlib.figure import Figure 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, \
check4rotated identifyPhaseID
try: try:
from matplotlib.backends.backend_qt4agg import FigureCanvas 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.data import Data
from pylot.core.io.inputs import FilterOptions, PylotParameter from pylot.core.io.inputs import FilterOptions, PylotParameter
from pylot.core.pick.utils import getSNR, earllatepicker, getnoisewin, \ from pylot.core.pick.utils import getSNR, earllatepicker, getnoisewin, \
getResolutionWindow, getQualityfromUncertainty getResolutionWindow, getQualityFromUncertainty
from pylot.core.pick.compare import Comparison from pylot.core.pick.compare import Comparison
from pylot.core.util.defaults import OUTPUTFORMATS, FILTERDEFAULTS, \ from pylot.core.util.defaults import OUTPUTFORMATS, FILTERDEFAULTS, \
SetChannelComponents SetChannelComponents
@ -119,7 +120,7 @@ def createAction(parent, text, slot=None, shortcut=None, icon=None,
return action return action
class ComparisonDialog(QDialog): class ComparisonWidget(QWidget):
def __init__(self, c, parent=None): def __init__(self, c, parent=None):
self._data = c self._data = c
self._stats = c.stations self._stats = c.stations
@ -129,8 +130,9 @@ class ComparisonDialog(QDialog):
histCheckBox=None) histCheckBox=None)
self._phases = 'PS' self._phases = 'PS'
self._plotprops = dict(station=list(self.stations)[0], phase=list(self.phases)[0]) 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.setupUI()
self.resize(1280, 720)
self.plotcomparison() self.plotcomparison()
def setupUI(self): def setupUI(self):
@ -162,17 +164,12 @@ class ComparisonDialog(QDialog):
_toolbar.addWidget(_phases_combobox) _toolbar.addWidget(_phases_combobox)
_toolbar.addWidget(_hist_checkbox) _toolbar.addWidget(_hist_checkbox)
_buttonbox = QDialogButtonBox(QDialogButtonBox.Close)
_innerlayout.addWidget(self.canvas) _innerlayout.addWidget(self.canvas)
_innerlayout.addWidget(_buttonbox)
_outerlayout.addWidget(_toolbar) _outerlayout.addWidget(_toolbar)
_outerlayout.addLayout(_innerlayout) _outerlayout.addLayout(_innerlayout)
_buttonbox.rejected.connect(self.reject) # finally layout the entire widget
# finally layout the entire dialog
self.setLayout(_outerlayout) self.setLayout(_outerlayout)
@property @property
@ -271,6 +268,10 @@ class ComparisonDialog(QDialog):
# _axes.cla() # _axes.cla()
station = self.plotprops['station'] station = self.plotprops['station']
phase = self.plotprops['phase'] 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] pdf = self.data.comparison[station][phase]
x, y, std, exp = pdf.axis, pdf.data, pdf.standard_deviation(), \ x, y, std, exp = pdf.axis, pdf.data, pdf.standard_deviation(), \
pdf.expectation() pdf.expectation()
@ -1286,7 +1287,7 @@ class PickDlg(QDialog):
self.currentPhase = str(self.s_button.text()) self.currentPhase = str(self.s_button.text())
def getPhaseID(self, phase): def getPhaseID(self, phase):
return identifyPhase(loopIdentifyPhase(phase)) return identifyPhaseID(phase)
def set_button_color(self, button, color=None): def set_button_color(self, button, color=None):
if type(color) == QtGui.QColor: if type(color) == QtGui.QColor:
@ -1700,7 +1701,7 @@ class PickDlg(QDialog):
else: else:
ylims = self.getPlotWidget().getYLims() ylims = self.getPlotWidget().getYLims()
if self.getPicks(picktype): 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 if (type(self.getPicks(picktype)[phase]) is dict
or type(self.getPicks(picktype)[phase]) is AttribDict): or type(self.getPicks(picktype)[phase]) is AttribDict):
picks = self.getPicks(picktype)[phase] picks = self.getPicks(picktype)[phase]
@ -1715,10 +1716,10 @@ class PickDlg(QDialog):
# get quality classes # get quality classes
if self.getPhaseID(phase) == 'P': if self.getPhaseID(phase) == 'P':
quality = getQualityfromUncertainty(picks['spe'], self.parameter['timeerrorsP']) quality = getQualityFromUncertainty(picks['spe'], self.parameter['timeerrorsP'])
phaseID = 'P' phaseID = 'P'
elif self.getPhaseID(phase) == 'S': elif self.getPhaseID(phase) == 'S':
quality = getQualityfromUncertainty(picks['spe'], self.parameter['timeerrorsS']) quality = getQualityFromUncertainty(picks['spe'], self.parameter['timeerrorsS'])
phaseID = 'S' phaseID = 'S'
mpp = picks['mpp'] - self.getStartTime() mpp = picks['mpp'] - self.getStartTime()
@ -2011,6 +2012,167 @@ class PhasePlotWidget(FigureCanvas):
super(PhasePlotWidget, self).__init__(self.fig) 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): class TuneAutopicker(QWidget):
update = QtCore.Signal(str) update = QtCore.Signal(str)
''' '''
@ -2343,7 +2505,7 @@ class TuneAutopicker(QWidget):
args = {'parameter': self.parameter, args = {'parameter': self.parameter,
'station': station, 'station': station,
'fnames': 'None', 'fnames': 'None',
'eventid': self.get_current_event_fp(), 'eventid': [self.get_current_event_fp()],
'iplot': 2, 'iplot': 2,
'fig_dict': self.fig_dict, 'fig_dict': self.fig_dict,
'locflag': 0, 'locflag': 0,
@ -2369,7 +2531,7 @@ class TuneAutopicker(QWidget):
info = self.ap_thread._executedErrorInfo info = self.ap_thread._executedErrorInfo
self._warn(msg, info) self._warn(msg, info)
return 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: if not self.pylot_picks:
self._warn('No picks found. See terminal output.') self._warn('No picks found. See terminal output.')
return return