task: implementation of picking (work in progress)
This commit is contained in:
parent
e35d6b9371
commit
b243be8075
25
QtPyLoT.py
25
QtPyLoT.py
@ -150,10 +150,6 @@ class MainWindow(QMainWindow):
|
|||||||
"Ctrl+W", QIcon(":/wfIcon.png"),
|
"Ctrl+W", QIcon(":/wfIcon.png"),
|
||||||
"""Open waveform data (event will
|
"""Open waveform data (event will
|
||||||
be closed).""")
|
be closed).""")
|
||||||
selectStation = self.createAction(self, "Select station",
|
|
||||||
self.pickOnStation, "Alt+P", pickIcon,
|
|
||||||
"Select a station from overview "
|
|
||||||
"plot for picking")
|
|
||||||
prefsEventAction = self.createAction(self, "Preferences",
|
prefsEventAction = self.createAction(self, "Preferences",
|
||||||
self.PyLoTprefs,
|
self.PyLoTprefs,
|
||||||
QKeySequence.Preferences,
|
QKeySequence.Preferences,
|
||||||
@ -214,10 +210,10 @@ class MainWindow(QMainWindow):
|
|||||||
phaseToolBar.setObjectName("PhaseTools")
|
phaseToolBar.setObjectName("PhaseTools")
|
||||||
self.addActions(phaseToolBar, phaseToolActions)
|
self.addActions(phaseToolBar, phaseToolActions)
|
||||||
|
|
||||||
pickToolBar = self.addToolBar("PickTools")
|
# pickToolBar = self.addToolBar("PickTools")
|
||||||
pickToolActions = (selectStation, )
|
# pickToolActions = (selectStation, )
|
||||||
pickToolBar.setObjectName("PickTools")
|
# pickToolBar.setObjectName("PickTools")
|
||||||
self.addActions(pickToolBar, pickToolActions)
|
# self.addActions(pickToolBar, pickToolActions)
|
||||||
|
|
||||||
self.eventLabel = QLabel()
|
self.eventLabel = QLabel()
|
||||||
self.eventLabel.setFrameStyle(QFrame.StyledPanel | QFrame.Sunken)
|
self.eventLabel.setFrameStyle(QFrame.StyledPanel | QFrame.Sunken)
|
||||||
@ -346,9 +342,9 @@ class MainWindow(QMainWindow):
|
|||||||
def getPlotWidget(self):
|
def getPlotWidget(self):
|
||||||
return self.DataPlot
|
return self.DataPlot
|
||||||
|
|
||||||
def getWFID(self, event):
|
def getWFID(self, gui_event):
|
||||||
|
|
||||||
ycoord = event.ydata
|
ycoord = gui_event.ydata
|
||||||
|
|
||||||
statID = int(round(ycoord))
|
statID = int(round(ycoord))
|
||||||
|
|
||||||
@ -380,6 +376,9 @@ class MainWindow(QMainWindow):
|
|||||||
title = 'overview: {0} components'.format(zne_text[comp])
|
title = 'overview: {0} components'.format(zne_text[comp])
|
||||||
wfst = self.getData().getWFData().select(component=comp)
|
wfst = self.getData().getWFData().select(component=comp)
|
||||||
self.getPlotWidget().plotWFData(wfdata=wfst, title=title)
|
self.getPlotWidget().plotWFData(wfdata=wfst, title=title)
|
||||||
|
pos = self.getPlotWidget().getPlotDict().keys()
|
||||||
|
labels = [int(act) for act in pos]
|
||||||
|
self.getPlotWidget().setYTickLabels(pos, labels)
|
||||||
|
|
||||||
def filterWaveformData(self):
|
def filterWaveformData(self):
|
||||||
if self.getData():
|
if self.getData():
|
||||||
@ -454,7 +453,7 @@ class MainWindow(QMainWindow):
|
|||||||
return self.seismicPhase
|
return self.seismicPhase
|
||||||
|
|
||||||
def getStationName(self, wfID):
|
def getStationName(self, wfID):
|
||||||
return self.getPlotWidget().getPlotDict()[wfID]
|
return self.getPlotWidget().getPlotDict()[wfID][0]
|
||||||
|
|
||||||
def alterPhase(self):
|
def alterPhase(self):
|
||||||
pass
|
pass
|
||||||
@ -464,9 +463,9 @@ class MainWindow(QMainWindow):
|
|||||||
self.updateStatus('Seismic phase changed to '
|
self.updateStatus('Seismic phase changed to '
|
||||||
'{0}'.format(self.getSeismicPhase()))
|
'{0}'.format(self.getSeismicPhase()))
|
||||||
|
|
||||||
def pickOnStation(self, event):
|
def pickOnStation(self, gui_event):
|
||||||
|
|
||||||
wfID = self.getWFID(event)
|
wfID = self.getWFID(gui_event)
|
||||||
|
|
||||||
station = self.getStationName(wfID)
|
station = self.getStationName(wfID)
|
||||||
print 'picking on station {0}'.format(station)
|
print 'picking on station {0}'.format(station)
|
||||||
|
@ -15,33 +15,16 @@ matplotlib.rcParams['backend.qt4'] = 'PySide'
|
|||||||
from matplotlib.figure import Figure
|
from matplotlib.figure import Figure
|
||||||
from matplotlib.backends.backend_qt4agg import FigureCanvas
|
from matplotlib.backends.backend_qt4agg import FigureCanvas
|
||||||
from matplotlib.widgets import MultiCursor
|
from matplotlib.widgets import MultiCursor
|
||||||
from PySide.QtGui import (QAction,
|
from PySide.QtGui import QAction, QApplication,QComboBox, QDateTimeEdit,\
|
||||||
QApplication,
|
QDialog, QDialogButtonBox, QDoubleSpinBox, QGroupBox, QGridLayout,\
|
||||||
QComboBox,
|
QIcon, QKeySequence, QLabel, QLineEdit, QMessageBox, QPixmap, QSpinBox,\
|
||||||
QDateTimeEdit,
|
QTabWidget, QToolBar, QVBoxLayout, QWidget
|
||||||
QDialog,
|
from PySide.QtCore import QSettings, Qt, QUrl, Signal, Slot
|
||||||
QDialogButtonBox,
|
|
||||||
QDoubleSpinBox,
|
|
||||||
QGroupBox,
|
|
||||||
QGridLayout,
|
|
||||||
QHBoxLayout,
|
|
||||||
QIcon,
|
|
||||||
QKeySequence,
|
|
||||||
QLabel,
|
|
||||||
QLineEdit,
|
|
||||||
QMessageBox,
|
|
||||||
QSpinBox,
|
|
||||||
QTabWidget,
|
|
||||||
QToolBar,
|
|
||||||
QVBoxLayout,
|
|
||||||
QWidget)
|
|
||||||
from PySide.QtCore import (QSettings,
|
|
||||||
Qt,
|
|
||||||
QUrl,
|
|
||||||
Signal,
|
|
||||||
Slot)
|
|
||||||
from PySide.QtWebKit import QWebView
|
from PySide.QtWebKit import QWebView
|
||||||
|
from obspy import Stream, UTCDateTime
|
||||||
|
from obspy.core.event import Pick
|
||||||
from pylot.core.read import FilterOptions
|
from pylot.core.read import FilterOptions
|
||||||
|
from pylot.core.pick.utils import getSNR
|
||||||
from pylot.core.util.defaults import OUTPUTFORMATS
|
from pylot.core.util.defaults import OUTPUTFORMATS
|
||||||
from pylot.core.util import prepTimeAxis, getGlobalTimes
|
from pylot.core.util import prepTimeAxis, getGlobalTimes
|
||||||
|
|
||||||
@ -91,39 +74,58 @@ class MPLWidget(FigureCanvas):
|
|||||||
def setPlotDict(self, key, value):
|
def setPlotDict(self, key, value):
|
||||||
self.plotdict[key] = value
|
self.plotdict[key] = value
|
||||||
|
|
||||||
|
def clearPlotDict(self):
|
||||||
|
self.plotdict = dict()
|
||||||
|
|
||||||
def getParent(self):
|
def getParent(self):
|
||||||
return self._parent
|
return self._parent
|
||||||
|
|
||||||
def setParent(self, parent):
|
def setParent(self, parent):
|
||||||
self._parent = parent
|
self._parent = parent
|
||||||
|
|
||||||
def plotWFData(self, wfdata, title = None):
|
def plotWFData(self, wfdata, title=None, zoomx=None, zoomy=None):
|
||||||
self.axes.lines = []
|
self.axes.cla()
|
||||||
|
self.clearPlotDict()
|
||||||
wfstart = getGlobalTimes(wfdata)[0]
|
wfstart = getGlobalTimes(wfdata)[0]
|
||||||
for n, trace in enumerate(wfdata):
|
for n, trace in enumerate(wfdata):
|
||||||
|
channel = trace.stats.channel
|
||||||
station = trace.stats.station
|
station = trace.stats.station
|
||||||
print('plotting station: %s' % station)
|
msg = 'plotting %s channel of station %s' % (channel, station)
|
||||||
|
print(msg)
|
||||||
stime = trace.stats.starttime - wfstart
|
stime = trace.stats.starttime - wfstart
|
||||||
time_ax = prepTimeAxis(stime, trace)
|
time_ax = prepTimeAxis(stime, trace)
|
||||||
trace.detrend()
|
trace.detrend()
|
||||||
trace.detrend('demean')
|
trace.detrend('demean')
|
||||||
trace.normalize(trace.data.max() * 2)
|
trace.normalize(trace.data.max() * 2)
|
||||||
self.axes.plot(time_ax, trace.data + n, 'k')
|
self.axes.plot(time_ax, trace.data + n, 'k')
|
||||||
self.axes.hold(True)
|
|
||||||
xlabel = 'seconds since {0}'.format(wfstart)
|
xlabel = 'seconds since {0}'.format(wfstart)
|
||||||
ylabel = ''
|
ylabel = ''
|
||||||
self.updateWidget(xlabel, ylabel, title)
|
self.updateWidget(xlabel, ylabel, title)
|
||||||
self.setPlotDict(n, station)
|
self.setPlotDict(n, (station, channel))
|
||||||
self.axes.autoscale(tight=True)
|
self.axes.autoscale(tight=True)
|
||||||
|
if zoomx:
|
||||||
|
self.axes.set_xlim(zoomx)
|
||||||
|
if zoomy:
|
||||||
|
self.axes.set_ylim(zoomy)
|
||||||
|
self.draw()
|
||||||
|
|
||||||
|
def setYTickLabels(self, pos, labels):
|
||||||
|
self.axes.set_yticks(pos)
|
||||||
|
self.axes.set_yticklabels(labels)
|
||||||
|
self.draw()
|
||||||
|
|
||||||
def updateXLabel(self, text):
|
def updateXLabel(self, text):
|
||||||
self.axes.set_xlabel(text)
|
self.axes.set_xlabel(text)
|
||||||
|
self.draw()
|
||||||
|
|
||||||
|
|
||||||
def updateYLabel(self, text):
|
def updateYLabel(self, text):
|
||||||
self.axes.set_ylabel(text)
|
self.axes.set_ylabel(text)
|
||||||
|
self.draw()
|
||||||
|
|
||||||
def updateTitle(self, text):
|
def updateTitle(self, text):
|
||||||
self.axes.set_title(text)
|
self.axes.set_title(text)
|
||||||
|
self.draw()
|
||||||
|
|
||||||
def updateWidget(self, xlabel, ylabel, title):
|
def updateWidget(self, xlabel, ylabel, title):
|
||||||
self.updateXLabel(xlabel)
|
self.updateXLabel(xlabel)
|
||||||
@ -237,6 +239,7 @@ class PickDlg(QDialog):
|
|||||||
self.station = station
|
self.station = station
|
||||||
self.rotate = rotate
|
self.rotate = rotate
|
||||||
self.components = 'ZNE'
|
self.components = 'ZNE'
|
||||||
|
self.picks = {}
|
||||||
|
|
||||||
# set attribute holding data
|
# set attribute holding data
|
||||||
if data is None:
|
if data is None:
|
||||||
@ -260,6 +263,12 @@ class PickDlg(QDialog):
|
|||||||
self.getPlotWidget().plotWFData(wfdata=self.getWFData(),
|
self.getPlotWidget().plotWFData(wfdata=self.getWFData(),
|
||||||
title=self.getStation())
|
title=self.getStation())
|
||||||
|
|
||||||
|
# set plot labels
|
||||||
|
self.setPlotLabels()
|
||||||
|
|
||||||
|
# connect button press event to an action
|
||||||
|
self.cid = self.getPlotWidget().mpl_connect('button_press_event', self.setPick)
|
||||||
|
|
||||||
def setupUi(self):
|
def setupUi(self):
|
||||||
|
|
||||||
# create icons
|
# create icons
|
||||||
@ -284,19 +293,22 @@ class PickDlg(QDialog):
|
|||||||
_dialtoolbar.addAction(self.filterAction)
|
_dialtoolbar.addAction(self.filterAction)
|
||||||
_dialtoolbar.addWidget(self.selectPhase)
|
_dialtoolbar.addWidget(self.selectPhase)
|
||||||
|
|
||||||
_innerlayout = QHBoxLayout()
|
_innerlayout = QVBoxLayout()
|
||||||
|
|
||||||
_toolslayout = QVBoxLayout()
|
|
||||||
_toolslabel = QLabel('Place for Tools')
|
|
||||||
_toolslayout.addWidget(_toolslabel)
|
|
||||||
|
|
||||||
_innerlayout.addLayout(_toolslayout)
|
|
||||||
_innerlayout.addWidget(self.multicompfig)
|
_innerlayout.addWidget(self.multicompfig)
|
||||||
|
_buttonbox = QDialogButtonBox(QDialogButtonBox.Apply |
|
||||||
|
QDialogButtonBox.Ok |
|
||||||
|
QDialogButtonBox.Cancel)
|
||||||
|
|
||||||
|
_innerlayout.addWidget(_buttonbox)
|
||||||
|
|
||||||
_outerlayout.addWidget(_dialtoolbar)
|
_outerlayout.addWidget(_dialtoolbar)
|
||||||
_outerlayout.addLayout(_innerlayout)
|
_outerlayout.addLayout(_innerlayout)
|
||||||
self.setLayout(_outerlayout)
|
self.setLayout(_outerlayout)
|
||||||
|
|
||||||
|
def reconnect(self, event_name, slot):
|
||||||
|
self.getPlotWidget().mpl_disconnect(self.cid)
|
||||||
|
self.cid = self.getPlotWidget().mpl_connect(event_name, slot)
|
||||||
|
|
||||||
def getComponents(self):
|
def getComponents(self):
|
||||||
return self.components
|
return self.components
|
||||||
@ -307,14 +319,118 @@ class PickDlg(QDialog):
|
|||||||
def getPlotWidget(self):
|
def getPlotWidget(self):
|
||||||
return self.multicompfig
|
return self.multicompfig
|
||||||
|
|
||||||
|
def getChannelID(self, key):
|
||||||
|
return self.getPlotWidget().getPlotDict()[int(key)][1]
|
||||||
|
|
||||||
def getWFData(self):
|
def getWFData(self):
|
||||||
return self.data
|
return self.data
|
||||||
|
|
||||||
|
def selectWFData(self, channel):
|
||||||
|
component = channel[-1].upper()
|
||||||
|
wfdata = Stream()
|
||||||
|
def selectTrace(trace, components):
|
||||||
|
if trace.stats.channel[-1].upper() in components:
|
||||||
|
return trace
|
||||||
|
|
||||||
|
if component == 'E' or component == 'N':
|
||||||
|
for trace in self.getWFData():
|
||||||
|
trace = selectTrace(trace, 'NE')
|
||||||
|
if trace:
|
||||||
|
wfdata.append(trace)
|
||||||
|
elif component == 'Z':
|
||||||
|
wfdata = self.getWFData().select(component=component)
|
||||||
|
return wfdata
|
||||||
|
|
||||||
|
def getPicks(self):
|
||||||
|
return self.picks
|
||||||
|
|
||||||
|
def setPick(self, gui_event):
|
||||||
|
channel = self.getChannelID(round(gui_event.ydata))
|
||||||
|
wfdata = self.selectWFData(channel)
|
||||||
|
|
||||||
|
ini_pick = gui_event.xdata
|
||||||
|
|
||||||
|
# calculate the resolution window width from SNR
|
||||||
|
# SNR >= 3 -> 2 sec HRW
|
||||||
|
# 3 > SNR >= 2 -> 5 sec MRW
|
||||||
|
# 2 > SNR >= 1.5 -> 10 sec LRW
|
||||||
|
# 1.5 > SNR -> 15 sec VLRW
|
||||||
|
|
||||||
|
res_wins = {
|
||||||
|
'HRW' : 2.,
|
||||||
|
'MRW' : 5.,
|
||||||
|
'LRW' : 10.,
|
||||||
|
'VLRW' : 15.
|
||||||
|
}
|
||||||
|
|
||||||
|
result = getSNR(wfdata, (5,.5,1), ini_pick)
|
||||||
|
|
||||||
|
snr = result[0]
|
||||||
|
noiselevel = result[2] * 1.5
|
||||||
|
|
||||||
|
if snr < 1.5:
|
||||||
|
x_res = res_wins['VLRW']
|
||||||
|
elif snr < 2.:
|
||||||
|
x_res = res_wins['LRW']
|
||||||
|
elif snr < 3.:
|
||||||
|
x_res = res_wins['MRW']
|
||||||
|
else:
|
||||||
|
x_res = res_wins['HRW']
|
||||||
|
x_res /= 2
|
||||||
|
|
||||||
|
zoomx = [ini_pick - x_res, ini_pick + x_res]
|
||||||
|
zoomy = [noiselevel * 1.5, -noiselevel * 1.5]
|
||||||
|
self.getPlotWidget().plotWFData(wfdata=wfdata,
|
||||||
|
title=self.getStation() +
|
||||||
|
' picking mode',
|
||||||
|
zoomx=zoomx,
|
||||||
|
zoomy=zoomy)
|
||||||
|
|
||||||
|
self.getPlotWidget().axes.plot()
|
||||||
|
|
||||||
|
# reset labels
|
||||||
|
self.setPlotLabels()
|
||||||
|
|
||||||
|
self.reconnect('button_press_event', self.plotPick)
|
||||||
|
|
||||||
|
def plotPick(self, gui_event):
|
||||||
|
pick = gui_event.xdata
|
||||||
|
ax = self.getPlotWidget().axes
|
||||||
|
|
||||||
|
ylims = ax.get_ylim()
|
||||||
|
|
||||||
|
ax.plot([pick, pick], ylims, 'r--')
|
||||||
|
self.getPlotWidget().draw()
|
||||||
|
|
||||||
def filterWFData(self):
|
def filterWFData(self):
|
||||||
data = self.getWFData().copy().filter(type='bandpass', freqmin=.5, freqmax=15.)
|
data = self.getWFData().copy().filter(type='bandpass', freqmin=.5, freqmax=15.)
|
||||||
title = self.getStation() + ' (filtered)'
|
title = self.getStation() + ' (filtered)'
|
||||||
self.getPlotWidget().plotWFData(wfdata=data, title=title)
|
self.getPlotWidget().plotWFData(wfdata=data, title=title)
|
||||||
|
self.setPlotLabels()
|
||||||
|
|
||||||
|
def setPlotLabels(self):
|
||||||
|
|
||||||
|
# get channel labels
|
||||||
|
pos = self.getPlotWidget().getPlotDict().keys()
|
||||||
|
labels = [self.getPlotWidget().getPlotDict()[key][1] for key in pos]
|
||||||
|
|
||||||
|
# set channel labels
|
||||||
|
self.getPlotWidget().setYTickLabels(pos, labels)
|
||||||
|
|
||||||
|
def apply(self):
|
||||||
|
if self.getPicks():
|
||||||
|
for phase, time in self.getPicks().iteritems():
|
||||||
|
ope_pick = Pick()
|
||||||
|
ope_pick.time = time
|
||||||
|
ope_pick.phase_hint = phase
|
||||||
|
print ope_pick
|
||||||
|
|
||||||
|
def reject(self):
|
||||||
|
QDialog.reject(self)
|
||||||
|
|
||||||
|
def accept(self):
|
||||||
|
self.apply()
|
||||||
|
QDialog.accept(self)
|
||||||
|
|
||||||
class PropertiesDlg(QDialog):
|
class PropertiesDlg(QDialog):
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user