Merge branch 'develop' into feature/additional_channel_display
This commit is contained in:
commit
975bd64266
108
PyLoT.py
108
PyLoT.py
@ -274,6 +274,10 @@ class MainWindow(QMainWindow):
|
|||||||
print_icon.addPixmap(QPixmap(':/icons/printer.png'))
|
print_icon.addPixmap(QPixmap(':/icons/printer.png'))
|
||||||
self.filter_icon = QIcon()
|
self.filter_icon = QIcon()
|
||||||
self.filter_icon.addPixmap(QPixmap(':/icons/filter.png'))
|
self.filter_icon.addPixmap(QPixmap(':/icons/filter.png'))
|
||||||
|
self.filter_icon_p = QIcon()
|
||||||
|
self.filter_icon_p.addPixmap(QPixmap(':/icons/filter_p.png'))
|
||||||
|
self.filter_icon_s = QIcon()
|
||||||
|
self.filter_icon_s.addPixmap(QPixmap(':/icons/filter_s.png'))
|
||||||
z_icon = QIcon()
|
z_icon = QIcon()
|
||||||
z_icon.addPixmap(QPixmap(':/icons/key_Z.png'))
|
z_icon.addPixmap(QPixmap(':/icons/key_Z.png'))
|
||||||
n_icon = QIcon()
|
n_icon = QIcon()
|
||||||
@ -368,15 +372,23 @@ class MainWindow(QMainWindow):
|
|||||||
self.setParameter,
|
self.setParameter,
|
||||||
None, paraIcon,
|
None, paraIcon,
|
||||||
"Modify Parameter")
|
"Modify Parameter")
|
||||||
self.filterAction = self.createAction(self, "&Filter ...",
|
self.filterActionP = createAction(parent=self, text='Apply P Filter',
|
||||||
self.filterWaveformData,
|
slot=self.filterP,
|
||||||
"Ctrl+F", self.filter_icon,
|
icon=self.filter_icon_p,
|
||||||
"""Toggle un-/filtered waveforms
|
tip='Toggle filtered/original'
|
||||||
to be displayed, according to the
|
' waveforms',
|
||||||
desired seismic phase.""", True)
|
checkable=True,
|
||||||
|
shortcut='P')
|
||||||
|
self.filterActionS = createAction(parent=self, text='Apply S Filter',
|
||||||
|
slot=self.filterS,
|
||||||
|
icon=self.filter_icon_s,
|
||||||
|
tip='Toggle filtered/original'
|
||||||
|
' waveforms',
|
||||||
|
checkable=True,
|
||||||
|
shortcut='S')
|
||||||
filterEditAction = self.createAction(self, "&Filter parameter ...",
|
filterEditAction = self.createAction(self, "&Filter parameter ...",
|
||||||
self.adjustFilterOptions,
|
self.adjustFilterOptions,
|
||||||
"Alt+F", self.filter_icon,
|
"Ctrl+F", self.filter_icon,
|
||||||
"""Adjust filter parameters.""")
|
"""Adjust filter parameters.""")
|
||||||
self.inventoryAction = self.createAction(self, "Select &Inventory ...",
|
self.inventoryAction = self.createAction(self, "Select &Inventory ...",
|
||||||
self.get_new_metadata,
|
self.get_new_metadata,
|
||||||
@ -502,8 +514,8 @@ class MainWindow(QMainWindow):
|
|||||||
self.updateFileMenu()
|
self.updateFileMenu()
|
||||||
|
|
||||||
self.editMenu = self.menuBar().addMenu('&Edit')
|
self.editMenu = self.menuBar().addMenu('&Edit')
|
||||||
editActions = (self.filterAction, filterEditAction, None,
|
editActions = (self.filterActionP, self.filterActionS, filterEditAction, None,
|
||||||
self.selectPAction, self.selectSAction, None,
|
#self.selectPAction, self.selectSAction, None,
|
||||||
self.inventoryAction, self.initMapAction, None,
|
self.inventoryAction, self.initMapAction, None,
|
||||||
prefsEventAction)
|
prefsEventAction)
|
||||||
#printAction) #TODO: print event?
|
#printAction) #TODO: print event?
|
||||||
@ -1415,7 +1427,8 @@ class MainWindow(QMainWindow):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
def getStime(self):
|
def getStime(self):
|
||||||
return self._stime
|
if self.get_data():
|
||||||
|
return full_range(self.get_data().getWFData())[0]
|
||||||
|
|
||||||
def addActions(self, target, actions):
|
def addActions(self, target, actions):
|
||||||
for action in actions:
|
for action in actions:
|
||||||
@ -1589,18 +1602,9 @@ class MainWindow(QMainWindow):
|
|||||||
# else:
|
# else:
|
||||||
# ans = False
|
# ans = False
|
||||||
self.fnames = self.getWFFnames_from_eventbox()
|
self.fnames = self.getWFFnames_from_eventbox()
|
||||||
self.data.setWFData(self.fnames)
|
self.data.setWFData(self.fnames,
|
||||||
wfdat = self.data.getWFData() # all available streams
|
checkRotated=True,
|
||||||
# remove possible underscores in station names
|
metadata=self.metadata)
|
||||||
wfdat = remove_underscores(wfdat)
|
|
||||||
# check for gaps and doubled channels
|
|
||||||
check4gaps(wfdat)
|
|
||||||
check4doubled(wfdat)
|
|
||||||
# check for stations with rotated components
|
|
||||||
wfdat = check4rotated(wfdat, self.metadata, verbosity=0)
|
|
||||||
# trim station components to same start value
|
|
||||||
trim_station_components(wfdat, trim_start=True, trim_end=False)
|
|
||||||
self._stime = full_range(self.get_data().getWFData())[0]
|
|
||||||
|
|
||||||
def connectWFplotEvents(self):
|
def connectWFplotEvents(self):
|
||||||
'''
|
'''
|
||||||
@ -1759,18 +1763,19 @@ class MainWindow(QMainWindow):
|
|||||||
self.disableSaveEventAction()
|
self.disableSaveEventAction()
|
||||||
self.draw()
|
self.draw()
|
||||||
|
|
||||||
def plotWaveformDataThread(self):
|
def plotWaveformDataThread(self, filter=True):
|
||||||
'''
|
'''
|
||||||
Open a modal thread to plot current waveform data.
|
Open a modal thread to plot current waveform data.
|
||||||
'''
|
'''
|
||||||
self.clearWaveformDataPlot()
|
self.clearWaveformDataPlot()
|
||||||
self.wfp_thread = Thread(self, self.plotWaveformData,
|
self.wfp_thread = Thread(self, self.plotWaveformData,
|
||||||
|
arg=filter,
|
||||||
progressText='Plotting waveform data...',
|
progressText='Plotting waveform data...',
|
||||||
pb_widget=self.mainProgressBarWidget)
|
pb_widget=self.mainProgressBarWidget)
|
||||||
self.wfp_thread.finished.connect(self.finishWaveformDataPlot)
|
self.wfp_thread.finished.connect(self.finishWaveformDataPlot)
|
||||||
self.wfp_thread.start()
|
self.wfp_thread.start()
|
||||||
|
|
||||||
def plotWaveformData(self):
|
def plotWaveformData(self, filter=True):
|
||||||
'''
|
'''
|
||||||
Plot waveform data to current plotWidget.
|
Plot waveform data to current plotWidget.
|
||||||
'''
|
'''
|
||||||
@ -1782,8 +1787,10 @@ class MainWindow(QMainWindow):
|
|||||||
comp = self.getComponent()
|
comp = self.getComponent()
|
||||||
title = 'section: {0} components'.format(zne_text[comp])
|
title = 'section: {0} components'.format(zne_text[comp])
|
||||||
wfst = self.get_data().getWFData()
|
wfst = self.get_data().getWFData()
|
||||||
if self.filterAction.isChecked():
|
if self.filterActionP.isChecked() and filter:
|
||||||
self.filterWaveformData(plot=False)
|
self.filterWaveformData(plot=False, phase='P')
|
||||||
|
elif self.filterActionS.isChecked() and filter:
|
||||||
|
self.filterWaveformData(plot=False, phase='S')
|
||||||
# wfst = self.get_data().getWFData().select(component=comp)
|
# wfst = self.get_data().getWFData().select(component=comp)
|
||||||
# wfst += self.get_data().getWFData().select(component=alter_comp)
|
# wfst += self.get_data().getWFData().select(component=alter_comp)
|
||||||
plotWidget = self.getPlotWidget()
|
plotWidget = self.getPlotWidget()
|
||||||
@ -1823,19 +1830,48 @@ class MainWindow(QMainWindow):
|
|||||||
def pushFilterWF(self, param_args):
|
def pushFilterWF(self, param_args):
|
||||||
self.get_data().filterWFData(param_args)
|
self.get_data().filterWFData(param_args)
|
||||||
|
|
||||||
def filterWaveformData(self, plot=True):
|
def filterP(self):
|
||||||
|
self.filterActionS.setChecked(False)
|
||||||
|
if self.filterActionP.isChecked():
|
||||||
|
self.filterWaveformData(phase='P')
|
||||||
|
else:
|
||||||
|
self.resetWFData()
|
||||||
|
|
||||||
|
def filterS(self):
|
||||||
|
self.filterActionP.setChecked(False)
|
||||||
|
if self.filterActionS.isChecked():
|
||||||
|
self.filterWaveformData(phase='S')
|
||||||
|
else:
|
||||||
|
self.resetWFData()
|
||||||
|
|
||||||
|
def resetWFData(self):
|
||||||
|
self.get_data().resetWFData()
|
||||||
|
self.plotWaveformDataThread()
|
||||||
|
|
||||||
|
def filterWaveformData(self, plot=True, phase=None):
|
||||||
|
if not self.get_current_event():
|
||||||
|
return
|
||||||
|
|
||||||
if self.get_data():
|
if self.get_data():
|
||||||
if self.getFilterOptions() and self.filterAction.isChecked():
|
if not phase:
|
||||||
kwargs = self.getFilterOptions()[self.getSeismicPhase()].parseFilterOptions()
|
if self.filterActionP.isChecked():
|
||||||
|
phase = 'P'
|
||||||
|
elif self.filterActionS.isChecked():
|
||||||
|
phase = 'S'
|
||||||
|
if self.getFilterOptions():
|
||||||
|
if (phase == 'P' and self.filterActionP.isChecked()) or (phase == 'S' and self.filterActionS.isChecked()):
|
||||||
|
kwargs = self.getFilterOptions()[phase].parseFilterOptions()
|
||||||
self.pushFilterWF(kwargs)
|
self.pushFilterWF(kwargs)
|
||||||
elif self.filterAction.isChecked():
|
else:
|
||||||
|
self.get_data().resetWFData()
|
||||||
|
elif self.filterActionP.isChecked() or self.filterActionS.isChecked():
|
||||||
self.adjustFilterOptions()
|
self.adjustFilterOptions()
|
||||||
else:
|
else:
|
||||||
self.get_data().resetWFData()
|
self.get_data().resetWFData()
|
||||||
if plot:
|
if plot:
|
||||||
self.plotWaveformDataThread()
|
self.plotWaveformDataThread(filter=False)
|
||||||
self.drawPicks()
|
#self.drawPicks()
|
||||||
self.draw()
|
#self.draw()
|
||||||
|
|
||||||
def adjustFilterOptions(self):
|
def adjustFilterOptions(self):
|
||||||
fstring = "Filter Options"
|
fstring = "Filter Options"
|
||||||
@ -1844,7 +1880,7 @@ class MainWindow(QMainWindow):
|
|||||||
if self.filterDlg.exec_():
|
if self.filterDlg.exec_():
|
||||||
filteroptions = self.filterDlg.getFilterOptions()
|
filteroptions = self.filterDlg.getFilterOptions()
|
||||||
self.setFilterOptions(filteroptions)
|
self.setFilterOptions(filteroptions)
|
||||||
if self.filterAction.isChecked():
|
if self.filterActionP.isChecked() or self.filterActionS.isChecked():
|
||||||
kwargs = self.getFilterOptions()[self.getSeismicPhase()].parseFilterOptions()
|
kwargs = self.getFilterOptions()[self.getSeismicPhase()].parseFilterOptions()
|
||||||
self.pushFilterWF(kwargs)
|
self.pushFilterWF(kwargs)
|
||||||
self.plotWaveformDataThread()
|
self.plotWaveformDataThread()
|
||||||
@ -1925,7 +1961,7 @@ class MainWindow(QMainWindow):
|
|||||||
# '[{0}: {1} Hz]'.format(
|
# '[{0}: {1} Hz]'.format(
|
||||||
# self.getFilterOptions().getFilterType(),
|
# self.getFilterOptions().getFilterType(),
|
||||||
# self.getFilterOptions().getFreq()))
|
# self.getFilterOptions().getFreq()))
|
||||||
# if self.filterAction.isChecked():
|
# if self.filterActionP.isChecked() or self.filterActionS.isChecked():
|
||||||
# self.filterWaveformData()
|
# self.filterWaveformData()
|
||||||
|
|
||||||
def getSeismicPhase(self):
|
def getSeismicPhase(self):
|
||||||
@ -2018,7 +2054,7 @@ class MainWindow(QMainWindow):
|
|||||||
autopicks=self.getPicksOnStation(station, 'auto'),
|
autopicks=self.getPicksOnStation(station, 'auto'),
|
||||||
metadata=self.metadata, event=event,
|
metadata=self.metadata, event=event,
|
||||||
filteroptions=self.filteroptions)
|
filteroptions=self.filteroptions)
|
||||||
if self.filterAction.isChecked():
|
if self.filterActionP.isChecked() or self.filterActionS.isChecked():
|
||||||
pickDlg.currentPhase = self.getSeismicPhase()
|
pickDlg.currentPhase = self.getSeismicPhase()
|
||||||
pickDlg.filterWFData()
|
pickDlg.filterWFData()
|
||||||
pickDlg.nextStation.setChecked(nextStation)
|
pickDlg.nextStation.setChecked(nextStation)
|
||||||
|
@ -1 +1 @@
|
|||||||
0ebc-dirty
|
f483-dirty
|
||||||
|
@ -12,7 +12,8 @@ from pylot.core.io.phases import readPILOTEvent, picks_from_picksdict, \
|
|||||||
picksdict_from_pilot, merge_picks
|
picksdict_from_pilot, merge_picks
|
||||||
from pylot.core.util.errors import FormatError, OverwriteError
|
from pylot.core.util.errors import FormatError, OverwriteError
|
||||||
from pylot.core.util.event import Event
|
from pylot.core.util.event import Event
|
||||||
from pylot.core.util.utils import fnConstructor, full_range
|
from pylot.core.util.utils import fnConstructor, full_range, remove_underscores, check4gaps, check4doubled, \
|
||||||
|
check4rotated, trim_station_components
|
||||||
import pylot.core.loc.velest as velest
|
import pylot.core.loc.velest as velest
|
||||||
|
|
||||||
|
|
||||||
@ -367,7 +368,7 @@ class Data(object):
|
|||||||
data.filter(**kwargs)
|
data.filter(**kwargs)
|
||||||
self.dirty = True
|
self.dirty = True
|
||||||
|
|
||||||
def setWFData(self, fnames):
|
def setWFData(self, fnames, checkRotated=False, metadata=None):
|
||||||
"""
|
"""
|
||||||
Clear current waveform data and set given waveform data
|
Clear current waveform data and set given waveform data
|
||||||
:param fnames: waveform data names to append
|
:param fnames: waveform data names to append
|
||||||
@ -379,10 +380,26 @@ class Data(object):
|
|||||||
self.appendWFData(fnames)
|
self.appendWFData(fnames)
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
# various pre-processing steps:
|
||||||
|
# remove possible underscores in station names
|
||||||
|
self.wfdata = remove_underscores(self.wfdata)
|
||||||
|
# check for gaps and doubled channels
|
||||||
|
check4gaps(self.wfdata)
|
||||||
|
check4doubled(self.wfdata)
|
||||||
|
# check for stations with rotated components
|
||||||
|
if checkRotated and metadata is not None:
|
||||||
|
self.wfdata = check4rotated(self.wfdata, metadata, verbosity=0)
|
||||||
|
# trim station components to same start value
|
||||||
|
trim_station_components(self.wfdata, trim_start=True, trim_end=False)
|
||||||
|
|
||||||
|
# make a copy of original data
|
||||||
self.wforiginal = self.getWFData().copy()
|
self.wforiginal = self.getWFData().copy()
|
||||||
self.dirty = False
|
self.dirty = False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def appendWFData(self, fnames):
|
def appendWFData(self, fnames):
|
||||||
"""
|
"""
|
||||||
Read waveform data from fnames and append it to current wf data
|
Read waveform data from fnames and append it to current wf data
|
||||||
|
@ -16,7 +16,8 @@ from pylot.core.io.inputs import PylotParameter
|
|||||||
from pylot.core.io.location import create_event, \
|
from pylot.core.io.location import create_event, \
|
||||||
create_magnitude
|
create_magnitude
|
||||||
from pylot.core.pick.utils import select_for_phase
|
from pylot.core.pick.utils import select_for_phase
|
||||||
from pylot.core.util.utils import getOwner, full_range, four_digits
|
from pylot.core.util.utils import getOwner, full_range, four_digits, transformFilteroptions2String, \
|
||||||
|
transformFilterString4Export, backtransformFilterString
|
||||||
|
|
||||||
|
|
||||||
def add_amplitudes(event, amplitudes):
|
def add_amplitudes(event, amplitudes):
|
||||||
@ -235,6 +236,10 @@ def picksdict_from_picks(evt):
|
|||||||
network = pick.waveform_id.network_code
|
network = pick.waveform_id.network_code
|
||||||
mpp = pick.time
|
mpp = pick.time
|
||||||
spe = pick.time_errors.uncertainty
|
spe = pick.time_errors.uncertainty
|
||||||
|
if pick.filter_id:
|
||||||
|
filter_id = backtransformFilterString(str(pick.filter_id.id))
|
||||||
|
else:
|
||||||
|
filter_id = None
|
||||||
try:
|
try:
|
||||||
picker = str(pick.method_id)
|
picker = str(pick.method_id)
|
||||||
if picker.startswith('smi:local/'):
|
if picker.startswith('smi:local/'):
|
||||||
@ -261,6 +266,7 @@ def picksdict_from_picks(evt):
|
|||||||
phase['channel'] = channel
|
phase['channel'] = channel
|
||||||
phase['network'] = network
|
phase['network'] = network
|
||||||
phase['picker'] = picker
|
phase['picker'] = picker
|
||||||
|
phase['filter_id'] = filter_id if filter_id is not None else ''
|
||||||
|
|
||||||
onsets[pick.phase_hint] = phase.copy()
|
onsets[pick.phase_hint] = phase.copy()
|
||||||
picksdict[picker][station] = onsets.copy()
|
picksdict[picker][station] = onsets.copy()
|
||||||
@ -312,6 +318,13 @@ def picks_from_picksdict(picks, creation_info=None):
|
|||||||
pick.waveform_id = ope.WaveformStreamID(station_code=station,
|
pick.waveform_id = ope.WaveformStreamID(station_code=station,
|
||||||
channel_code=ccode,
|
channel_code=ccode,
|
||||||
network_code=ncode)
|
network_code=ncode)
|
||||||
|
try:
|
||||||
|
filter_id = phase['filteroptions']
|
||||||
|
filter_id = transformFilterString4Export(filter_id)
|
||||||
|
except KeyError as e:
|
||||||
|
warnings.warn(e.message, RuntimeWarning)
|
||||||
|
filter_id = ''
|
||||||
|
pick.filter_id = filter_id
|
||||||
try:
|
try:
|
||||||
polarity = phase['fm']
|
polarity = phase['fm']
|
||||||
if polarity == 'U' or '+':
|
if polarity == 'U' or '+':
|
||||||
@ -328,7 +341,6 @@ def picks_from_picksdict(picks, creation_info=None):
|
|||||||
picks_list.append(pick)
|
picks_list.append(pick)
|
||||||
return picks_list
|
return picks_list
|
||||||
|
|
||||||
|
|
||||||
def reassess_pilot_db(root_dir, db_dir, out_dir=None, fn_param=None, verbosity=0):
|
def reassess_pilot_db(root_dir, db_dir, out_dir=None, fn_param=None, verbosity=0):
|
||||||
import glob
|
import glob
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ class Thread(QThread):
|
|||||||
if self.redirect_stdout:
|
if self.redirect_stdout:
|
||||||
sys.stdout = self
|
sys.stdout = self
|
||||||
try:
|
try:
|
||||||
if self.arg:
|
if self.arg is not None:
|
||||||
self.data = self.func(self.arg)
|
self.data = self.func(self.arg)
|
||||||
else:
|
else:
|
||||||
self.data = self.func()
|
self.data = self.func()
|
||||||
|
@ -391,6 +391,38 @@ def full_range(stream):
|
|||||||
return min_start, max_end
|
return min_start, max_end
|
||||||
|
|
||||||
|
|
||||||
|
def transformFilteroptions2String(filtopts):
|
||||||
|
st = ''
|
||||||
|
if not filtopts:
|
||||||
|
return st
|
||||||
|
if 'type' in filtopts.keys():
|
||||||
|
st += '{}'.format(filtopts['type'])
|
||||||
|
if 'freq' in filtopts.keys():
|
||||||
|
st += ' | freq: {}'.format(filtopts['freq'])
|
||||||
|
elif 'freqmin' in filtopts.keys() and 'freqmax' in filtopts.keys():
|
||||||
|
st += ' | freqmin: {} | freqmax: {}'.format(filtopts['freqmin'], filtopts['freqmax'])
|
||||||
|
for key, value in filtopts.items():
|
||||||
|
if key in ['type', 'freq', 'freqmin', 'freqmax']:
|
||||||
|
continue
|
||||||
|
st += ' | {}: {}'.format(key, value)
|
||||||
|
return st
|
||||||
|
|
||||||
|
|
||||||
|
def transformFilterString4Export(st):
|
||||||
|
st = st.replace('|', '//')
|
||||||
|
st = st.replace(':', '/')
|
||||||
|
st = st.replace(' ', '')
|
||||||
|
return st
|
||||||
|
|
||||||
|
|
||||||
|
def backtransformFilterString(st):
|
||||||
|
st = st.split('smi:local/')
|
||||||
|
st = st[1] if len(st) > 1 else st[0]
|
||||||
|
st = st.replace('//', ' | ')
|
||||||
|
st = st.replace('/', ': ')
|
||||||
|
return st
|
||||||
|
|
||||||
|
|
||||||
def getHash(time):
|
def getHash(time):
|
||||||
"""
|
"""
|
||||||
takes a time object and returns the corresponding SHA1 hash of the formatted date string
|
takes a time object and returns the corresponding SHA1 hash of the formatted date string
|
||||||
@ -1137,6 +1169,8 @@ def identifyPhase(phase):
|
|||||||
# common phase suffix for P and S
|
# common phase suffix for P and S
|
||||||
common_P = ['P', 'p', 'R']
|
common_P = ['P', 'p', 'R']
|
||||||
common_S = ['S', 's']
|
common_S = ['S', 's']
|
||||||
|
if phase is None:
|
||||||
|
return False
|
||||||
if phase[-1] in common_P:
|
if phase[-1] in common_P:
|
||||||
return 'P'
|
return 'P'
|
||||||
if phase[-1] in common_S:
|
if phase[-1] in common_S:
|
||||||
|
@ -17,8 +17,6 @@ import time
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
from matplotlib.figure import Figure
|
from matplotlib.figure import Figure
|
||||||
from pylot.core.util.utils import find_horizontals, identifyPhase, loopIdentifyPhase, trim_station_components, \
|
|
||||||
identifyPhaseID, check4rotated, real_Bool, pick_color
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from matplotlib.backends.backend_qt4agg import FigureCanvas
|
from matplotlib.backends.backend_qt4agg import FigureCanvas
|
||||||
@ -49,7 +47,9 @@ from pylot.core.util.defaults import OUTPUTFORMATS, FILTERDEFAULTS, \
|
|||||||
SetChannelComponents
|
SetChannelComponents
|
||||||
from pylot.core.util.utils import prepTimeAxis, full_range, scaleWFData, \
|
from pylot.core.util.utils import prepTimeAxis, full_range, scaleWFData, \
|
||||||
demeanTrace, isSorted, findComboBoxIndex, clims, pick_linestyle_plt, pick_color_plt, \
|
demeanTrace, isSorted, findComboBoxIndex, clims, pick_linestyle_plt, pick_color_plt, \
|
||||||
check4rotated, check4doubled, check4gaps, remove_underscores
|
check4rotated, check4doubled, check4gaps, remove_underscores, find_horizontals, identifyPhase, \
|
||||||
|
loopIdentifyPhase, trim_station_components, transformFilteroptions2String, \
|
||||||
|
identifyPhaseID, real_Bool, pick_color
|
||||||
from autoPyLoT import autoPyLoT
|
from autoPyLoT import autoPyLoT
|
||||||
from pylot.core.util.thread import Thread
|
from pylot.core.util.thread import Thread
|
||||||
|
|
||||||
@ -375,8 +375,8 @@ class ComparisonWidget(QWidget):
|
|||||||
ax = axes_dict[phase]['exp']
|
ax = axes_dict[phase]['exp']
|
||||||
xlims = ax.get_xlim()
|
xlims = ax.get_xlim()
|
||||||
ylims = ax.get_ylim()
|
ylims = ax.get_ylim()
|
||||||
ax.fill_between([xlims[0], 0], ylims[0], ylims[1], color=(0.9, 1.0, 0.9, 0.5), label='earlier than manual')
|
#ax.fill_between([xlims[0], 0], ylims[0], ylims[1], color=(0.9, 1.0, 0.9, 0.5), label='earlier than manual')
|
||||||
ax.fill_between([0, xlims[1]], ylims[0], ylims[1], color=(1.0, 0.9, 0.9, 0.5), label='later than manual')
|
#ax.fill_between([0, xlims[1]], ylims[0], ylims[1], color=(1.0, 0.9, 0.9, 0.5), label='later than manual')
|
||||||
legend = ax.legend()
|
legend = ax.legend()
|
||||||
legend.draggable()
|
legend.draggable()
|
||||||
|
|
||||||
@ -1152,9 +1152,11 @@ class PickDlg(QDialog):
|
|||||||
self.components = 'ZNE'
|
self.components = 'ZNE'
|
||||||
self.currentPhase = None
|
self.currentPhase = None
|
||||||
self.phaseText = []
|
self.phaseText = []
|
||||||
|
self.phaseLines = []
|
||||||
self.arrivals = []
|
self.arrivals = []
|
||||||
self.arrivalsText = []
|
self.arrivalsText = []
|
||||||
self.cidpick = []
|
self.cidpick = []
|
||||||
|
self.cidpress = None
|
||||||
settings = QSettings()
|
settings = QSettings()
|
||||||
pylot_user = getpass.getuser()
|
pylot_user = getpass.getuser()
|
||||||
self._user = settings.value('user/Login', pylot_user)
|
self._user = settings.value('user/Login', pylot_user)
|
||||||
@ -1242,6 +1244,7 @@ class PickDlg(QDialog):
|
|||||||
|
|
||||||
# init pick delete (with right click)
|
# init pick delete (with right click)
|
||||||
self.connect_pick_delete()
|
self.connect_pick_delete()
|
||||||
|
self.connect_mouse_motion()
|
||||||
self.setWindowTitle('Pickwindow on station: {}'.format(self.getStation()))
|
self.setWindowTitle('Pickwindow on station: {}'.format(self.getStation()))
|
||||||
self.setWindowState(QtCore.Qt.WindowMaximized)
|
self.setWindowState(QtCore.Qt.WindowMaximized)
|
||||||
|
|
||||||
@ -1270,6 +1273,8 @@ class PickDlg(QDialog):
|
|||||||
home_icon.addPixmap(QPixmap(':/icons/zoom_0.png'))
|
home_icon.addPixmap(QPixmap(':/icons/zoom_0.png'))
|
||||||
del_icon = QIcon()
|
del_icon = QIcon()
|
||||||
del_icon.addPixmap(QPixmap(':/icons/delete.png'))
|
del_icon.addPixmap(QPixmap(':/icons/delete.png'))
|
||||||
|
sync_icon = QIcon()
|
||||||
|
sync_icon.addPixmap(QPixmap(':/icons/sync.png'))
|
||||||
|
|
||||||
# create actions
|
# create actions
|
||||||
self.filterActionP = createAction(parent=self, text='Apply P Filter',
|
self.filterActionP = createAction(parent=self, text='Apply P Filter',
|
||||||
@ -1278,14 +1283,14 @@ class PickDlg(QDialog):
|
|||||||
tip='Toggle filtered/original'
|
tip='Toggle filtered/original'
|
||||||
' waveforms',
|
' waveforms',
|
||||||
checkable=True,
|
checkable=True,
|
||||||
shortcut='Ctrl+F')
|
shortcut='P')
|
||||||
self.filterActionS = createAction(parent=self, text='Apply S Filter',
|
self.filterActionS = createAction(parent=self, text='Apply S Filter',
|
||||||
slot=self.filterS,
|
slot=self.filterS,
|
||||||
icon=filter_icon_s,
|
icon=filter_icon_s,
|
||||||
tip='Toggle filtered/original'
|
tip='Toggle filtered/original'
|
||||||
' waveforms',
|
' waveforms',
|
||||||
checkable=True,
|
checkable=True,
|
||||||
shortcut='Shift+F')
|
shortcut='S')
|
||||||
self.autoFilterAction = createAction(parent=self, text='Automatic Filtering',
|
self.autoFilterAction = createAction(parent=self, text='Automatic Filtering',
|
||||||
slot=self.toggleAutoFilter,
|
slot=self.toggleAutoFilter,
|
||||||
icon=key_a_icon,
|
icon=key_a_icon,
|
||||||
@ -1302,6 +1307,10 @@ class PickDlg(QDialog):
|
|||||||
self.resetPicksAction = createAction(parent=self, text='Delete Picks',
|
self.resetPicksAction = createAction(parent=self, text='Delete Picks',
|
||||||
slot=self.delPicks, icon=del_icon,
|
slot=self.delPicks, icon=del_icon,
|
||||||
tip='Delete current picks.')
|
tip='Delete current picks.')
|
||||||
|
self.renamePhaseAction = createAction(parent=self, text='Rename Phase',
|
||||||
|
slot=self.initRenamePhase, icon=sync_icon,
|
||||||
|
tip='Rename a Phase.', checkable=True,
|
||||||
|
shortcut='R')
|
||||||
|
|
||||||
self.addPickPhases(menuBar)
|
self.addPickPhases(menuBar)
|
||||||
|
|
||||||
@ -1330,6 +1339,8 @@ class PickDlg(QDialog):
|
|||||||
self.reject_button = QPushButton('&Reject')
|
self.reject_button = QPushButton('&Reject')
|
||||||
self.disable_ar_buttons()
|
self.disable_ar_buttons()
|
||||||
|
|
||||||
|
self.statusbar = QtGui.QStatusBar(self)
|
||||||
|
|
||||||
# add hotkeys
|
# add hotkeys
|
||||||
self._shortcut_space = QtGui.QShortcut(QtGui.QKeySequence(' '), self)
|
self._shortcut_space = QtGui.QShortcut(QtGui.QKeySequence(' '), self)
|
||||||
self._shortcut_space.activated.connect(self.accept_button.clicked)
|
self._shortcut_space.activated.connect(self.accept_button.clicked)
|
||||||
@ -1352,6 +1363,7 @@ class PickDlg(QDialog):
|
|||||||
_dialtoolbar.addAction(self.resetZoomAction)
|
_dialtoolbar.addAction(self.resetZoomAction)
|
||||||
_dialtoolbar.addSeparator()
|
_dialtoolbar.addSeparator()
|
||||||
_dialtoolbar.addAction(self.resetPicksAction)
|
_dialtoolbar.addAction(self.resetPicksAction)
|
||||||
|
_dialtoolbar.addAction(self.renamePhaseAction)
|
||||||
_dialtoolbar.addSeparator()
|
_dialtoolbar.addSeparator()
|
||||||
if self._embedded:
|
if self._embedded:
|
||||||
manu_label = QLabel('Manual Onsets:')
|
manu_label = QLabel('Manual Onsets:')
|
||||||
@ -1375,9 +1387,12 @@ class PickDlg(QDialog):
|
|||||||
# layout the innermost widget
|
# layout the innermost widget
|
||||||
_innerlayout = QVBoxLayout()
|
_innerlayout = QVBoxLayout()
|
||||||
_innerinnerlayout = QtGui.QHBoxLayout()
|
_innerinnerlayout = QtGui.QHBoxLayout()
|
||||||
|
_lowerlayout = QHBoxLayout()
|
||||||
_innerinnerlayout.addWidget(self.multicompfig)
|
_innerinnerlayout.addWidget(self.multicompfig)
|
||||||
_innerinnerlayout.addWidget(self.phaseplot)
|
_innerinnerlayout.addWidget(self.phaseplot)
|
||||||
_innerlayout.addLayout(_innerinnerlayout)
|
_innerlayout.addLayout(_innerinnerlayout)
|
||||||
|
_innerlayout.addLayout(_lowerlayout)
|
||||||
|
_lowerlayout.addWidget(self.statusbar)
|
||||||
|
|
||||||
# add button box to the dialog
|
# add button box to the dialog
|
||||||
_buttonbox = QDialogButtonBox(QDialogButtonBox.Ok |
|
_buttonbox = QDialogButtonBox(QDialogButtonBox.Ok |
|
||||||
@ -1385,13 +1400,17 @@ class PickDlg(QDialog):
|
|||||||
|
|
||||||
# merge widgets and layouts to establish the dialog
|
# merge widgets and layouts to establish the dialog
|
||||||
if not self._embedded:
|
if not self._embedded:
|
||||||
_innerlayout.addWidget(_buttonbox)
|
_lowerlayout.addWidget(_buttonbox)
|
||||||
_outerlayout.addWidget(menuBar)
|
_outerlayout.addWidget(menuBar)
|
||||||
_outerlayout.addWidget(_dialtoolbar)
|
_outerlayout.addWidget(_dialtoolbar)
|
||||||
_outerlayout.addLayout(_innerlayout)
|
_outerlayout.addLayout(_innerlayout)
|
||||||
_outerlayout.setStretch(0, 0)
|
_outerlayout.setStretch(0, 0)
|
||||||
_outerlayout.setStretch(1, 0)
|
_outerlayout.setStretch(1, 0)
|
||||||
_outerlayout.setStretch(2, 1)
|
_outerlayout.setStretch(2, 1)
|
||||||
|
_lowerlayout.setStretch(0, 5)
|
||||||
|
_lowerlayout.setStretch(1, 1)
|
||||||
|
_innerlayout.setStretch(0, 1)
|
||||||
|
_innerlayout.setStretch(1, 0)
|
||||||
|
|
||||||
# connect widget element signals with slots (methods to the dialog
|
# connect widget element signals with slots (methods to the dialog
|
||||||
# object
|
# object
|
||||||
@ -1555,7 +1574,7 @@ class PickDlg(QDialog):
|
|||||||
|
|
||||||
filterOptionsAction = createAction(parent=self, text="&Filter parameter ...",
|
filterOptionsAction = createAction(parent=self, text="&Filter parameter ...",
|
||||||
slot=self.filterOptions,
|
slot=self.filterOptions,
|
||||||
shortcut='Alt+F',
|
shortcut='Ctrl+F',
|
||||||
icon=self.orig_parent.filter_icon)
|
icon=self.orig_parent.filter_icon)
|
||||||
filterMenu = menuBar.addMenu('Filter')
|
filterMenu = menuBar.addMenu('Filter')
|
||||||
filterMenu.addAction(self.filterActionP)
|
filterMenu.addAction(self.filterActionP)
|
||||||
@ -1675,8 +1694,15 @@ class PickDlg(QDialog):
|
|||||||
self.deactivatePicking()
|
self.deactivatePicking()
|
||||||
|
|
||||||
def activatePicking(self):
|
def activatePicking(self):
|
||||||
|
self.leave_rename_phase()
|
||||||
|
self.renamePhaseAction.setEnabled(False)
|
||||||
phase = self.currentPhase
|
phase = self.currentPhase
|
||||||
color = pick_color_plt('manual', self.getPhaseID(phase))
|
phaseID = self.getPhaseID(phase)
|
||||||
|
if not phaseID:
|
||||||
|
self.warn_unknown_phase(phase)
|
||||||
|
self.leave_picking_mode()
|
||||||
|
return
|
||||||
|
color = pick_color_plt('manual', phaseID)
|
||||||
self.multicompfig.set_frame_color(color)
|
self.multicompfig.set_frame_color(color)
|
||||||
self.multicompfig.set_frame_linewidth(1.5)
|
self.multicompfig.set_frame_linewidth(1.5)
|
||||||
if self.zoomAction.isChecked():
|
if self.zoomAction.isChecked():
|
||||||
@ -1700,6 +1726,7 @@ class PickDlg(QDialog):
|
|||||||
|
|
||||||
self.disconnectPressEvent()
|
self.disconnectPressEvent()
|
||||||
self.multicompfig.connectEvents()
|
self.multicompfig.connectEvents()
|
||||||
|
self.renamePhaseAction.setEnabled(True)
|
||||||
self.connect_pick_delete()
|
self.connect_pick_delete()
|
||||||
self.draw()
|
self.draw()
|
||||||
|
|
||||||
@ -1799,6 +1826,17 @@ class PickDlg(QDialog):
|
|||||||
self.resetPicks()
|
self.resetPicks()
|
||||||
self.refreshPlot()
|
self.refreshPlot()
|
||||||
|
|
||||||
|
def initRenamePhase(self):
|
||||||
|
if self.renamePhaseAction.isChecked():
|
||||||
|
self.multicompfig.disconnectEvents()
|
||||||
|
self.multicompfig.set_frame_color('orange')
|
||||||
|
self.draw()
|
||||||
|
self.statusbar.showMessage('Click on a phase you want to rename.')
|
||||||
|
else:
|
||||||
|
self.multicompfig.set_frame_color()
|
||||||
|
self.multicompfig.connectEvents()
|
||||||
|
self.draw()
|
||||||
|
|
||||||
def setIniPick(self, gui_event):
|
def setIniPick(self, gui_event):
|
||||||
self.multicompfig.set_frame_color('green')
|
self.multicompfig.set_frame_color('green')
|
||||||
trace_number = round(gui_event.ydata)
|
trace_number = round(gui_event.ydata)
|
||||||
@ -2006,41 +2044,30 @@ class PickDlg(QDialog):
|
|||||||
# save pick times for actual phase
|
# save pick times for actual phase
|
||||||
phasepicks = dict(epp=epp, lpp=lpp, mpp=mpp, spe=spe,
|
phasepicks = dict(epp=epp, lpp=lpp, mpp=mpp, spe=spe,
|
||||||
picker='manual', channel=channel,
|
picker='manual', channel=channel,
|
||||||
network=wfdata[0].stats.network)
|
network=wfdata[0].stats.network,
|
||||||
|
filteroptions=transformFilteroptions2String(filteroptions))
|
||||||
|
|
||||||
try:
|
saved = self.savePick(phase, phasepicks)
|
||||||
oldphasepick = self.picks[phase]
|
if saved:
|
||||||
except KeyError:
|
self.setDirty(True)
|
||||||
self.picks[phase] = phasepicks
|
|
||||||
else:
|
|
||||||
self.picks[phase] = phasepicks
|
|
||||||
oepp = oldphasepick['epp']
|
|
||||||
ompp = oldphasepick['mpp']
|
|
||||||
olpp = oldphasepick['lpp']
|
|
||||||
msg = """Warning old phase information for phase {phase} has been
|
|
||||||
altered.\n
|
|
||||||
New phase times:\n
|
|
||||||
earliest possible pick: {epp}\n
|
|
||||||
most probable pick: {mpp}\n
|
|
||||||
latest possible pick: {lpp}\n
|
|
||||||
\n
|
|
||||||
Old phase times (overwritten):\n
|
|
||||||
earliest possible pick: {oepp}\n
|
|
||||||
most probable pick: {ompp}\n
|
|
||||||
latest possible pick: {olpp}\n""".format(phase=phase,
|
|
||||||
epp=epp,
|
|
||||||
mpp=pick,
|
|
||||||
lpp=lpp,
|
|
||||||
oepp=oepp,
|
|
||||||
ompp=ompp,
|
|
||||||
olpp=olpp)
|
|
||||||
|
|
||||||
self.disconnectPressEvent()
|
self.disconnectPressEvent()
|
||||||
self.enable_ar_buttons()
|
self.enable_ar_buttons()
|
||||||
self.zoomAction.setEnabled(True)
|
self.zoomAction.setEnabled(True)
|
||||||
#self.pick_block = self.togglePickBlocker()
|
#self.pick_block = self.togglPickBlocker()
|
||||||
self.leave_picking_mode()
|
self.leave_picking_mode()
|
||||||
self.setDirty(True)
|
|
||||||
|
def savePick(self, phase, phasepicks):
|
||||||
|
if not self.getPhaseID(phase):
|
||||||
|
self.warn_unknown_phase(phase)
|
||||||
|
return
|
||||||
|
|
||||||
|
self.picks[phase] = phasepicks
|
||||||
|
return True
|
||||||
|
|
||||||
|
def warn_unknown_phase(self, phase=None):
|
||||||
|
QtGui.QMessageBox.warning(self, 'Unknown phase ID',
|
||||||
|
'Could not identify phase ID: {}.'.format(phase))
|
||||||
|
|
||||||
def disconnectPressEvent(self):
|
def disconnectPressEvent(self):
|
||||||
self.multicompfig.mpl_disconnect(self.cidpress)
|
self.multicompfig.mpl_disconnect(self.cidpress)
|
||||||
@ -2050,6 +2077,7 @@ class PickDlg(QDialog):
|
|||||||
self.removePhaseText()
|
self.removePhaseText()
|
||||||
self.drawPicks(picktype='manual')
|
self.drawPicks(picktype='manual')
|
||||||
self.drawPicks(picktype='auto')
|
self.drawPicks(picktype='auto')
|
||||||
|
self.draw()
|
||||||
|
|
||||||
def drawPicks(self, phase=None, picktype='manual', textOnly=False, picks=None):
|
def drawPicks(self, phase=None, picktype='manual', textOnly=False, picks=None):
|
||||||
# plotting picks
|
# plotting picks
|
||||||
@ -2091,18 +2119,19 @@ class PickDlg(QDialog):
|
|||||||
color = pick_color_plt(picktype, phaseID, quality)
|
color = pick_color_plt(picktype, phaseID, quality)
|
||||||
if not textOnly:
|
if not textOnly:
|
||||||
linestyle_mpp, width_mpp = pick_linestyle_plt(picktype, 'mpp')
|
linestyle_mpp, width_mpp = pick_linestyle_plt(picktype, 'mpp')
|
||||||
ax.plot([mpp, mpp], ylims, color=color, linestyle=linestyle_mpp, linewidth=width_mpp,
|
vl = ax.axvline(mpp, ylims[0], ylims[1], color=color, linestyle=linestyle_mpp, linewidth=width_mpp,
|
||||||
label='{}-Pick (quality: {})'.format(phase, quality), picker=5)
|
label='{}-Pick (quality: {})'.format(phase, quality), picker=5)
|
||||||
|
self.phaseLines.append(vl)
|
||||||
if spe:
|
if spe:
|
||||||
ax.fill_between([mpp-spe, mpp+spe], ylims[0], ylims[1],
|
ax.fill_between([mpp-spe, mpp+spe], ylims[0], ylims[1],
|
||||||
alpha=.25, color=color, label='{}-SPE'.format(phase))
|
alpha=.25, color=color, label='{}-SPE'.format(phase))
|
||||||
if picks['epp']:
|
if picks['epp']:
|
||||||
linestyle_epp, width_epp = pick_linestyle_plt(picktype, 'epp')
|
linestyle_epp, width_epp = pick_linestyle_plt(picktype, 'epp')
|
||||||
ax.plot([epp, epp], ylims, color=color, linestyle=linestyle_epp,
|
ax.axvline(epp, ylims[0], ylims[1], color=color, linestyle=linestyle_epp,
|
||||||
linewidth=width_epp, label='{}-EPP'.format(phase))
|
linewidth=width_epp, label='{}-EPP'.format(phase))
|
||||||
if picks['lpp']:
|
if picks['lpp']:
|
||||||
linestyle_lpp, width_lpp = pick_linestyle_plt(picktype, 'lpp')
|
linestyle_lpp, width_lpp = pick_linestyle_plt(picktype, 'lpp')
|
||||||
ax.plot([lpp, lpp], ylims, color=color, linestyle=linestyle_lpp,
|
ax.axvline(lpp, ylims[0], ylims[1], color=color, linestyle=linestyle_lpp,
|
||||||
linewidth=width_lpp, label='{}-LPP'.format(phase))
|
linewidth=width_lpp, label='{}-LPP'.format(phase))
|
||||||
# else:
|
# else:
|
||||||
# ax.plot([mpp, mpp], ylims, color=color, linestyle=linestyle_mpp, linewidth=width_mpp,
|
# ax.plot([mpp, mpp], ylims, color=color, linestyle=linestyle_mpp, linewidth=width_mpp,
|
||||||
@ -2115,8 +2144,9 @@ class PickDlg(QDialog):
|
|||||||
if not textOnly:
|
if not textOnly:
|
||||||
ax.plot(mpp, ylims[1], color=color, marker='v')
|
ax.plot(mpp, ylims[1], color=color, marker='v')
|
||||||
ax.plot(mpp, ylims[0], color=color, marker='^')
|
ax.plot(mpp, ylims[0], color=color, marker='^')
|
||||||
ax.vlines(mpp, ylims[0], ylims[1], color=color, linestyle=linestyle_mpp, linewidth=width_mpp,
|
vl = ax.axvline(mpp, ylims[0], ylims[1], color=color, linestyle=linestyle_mpp, linewidth=width_mpp,
|
||||||
picker=5, label='{}-Autopick (quality: {})'.format(phase, quality))
|
picker=5, label='{}-Autopick (quality: {})'.format(phase, quality))
|
||||||
|
self.phaseLines.append(vl)
|
||||||
# append phase text (if textOnly: draw with current ylims)
|
# append phase text (if textOnly: draw with current ylims)
|
||||||
self.phaseText.append(ax.text(mpp, ylims[1], phase, color=color))
|
self.phaseText.append(ax.text(mpp, ylims[1], phase, color=color))
|
||||||
else:
|
else:
|
||||||
@ -2124,24 +2154,121 @@ class PickDlg(QDialog):
|
|||||||
|
|
||||||
ax.legend(loc=1)
|
ax.legend(loc=1)
|
||||||
|
|
||||||
|
def connect_mouse_motion(self):
|
||||||
|
self.cidmotion = self.multicompfig.mpl_connect(
|
||||||
|
'motion_notify_event', self.on_motion)
|
||||||
|
|
||||||
def connect_pick_delete(self):
|
def connect_pick_delete(self):
|
||||||
self.cidpick = self.multicompfig.mpl_connect('pick_event', self.onpick_delete)
|
self.cidpick = self.multicompfig.mpl_connect('pick_event', self.onpick)
|
||||||
|
self.cidpick = self.multicompfig.mpl_connect('motion_notify_event', self.on_hover_info)
|
||||||
|
|
||||||
def disconnect_pick_delete(self):
|
def disconnect_pick_delete(self):
|
||||||
if hasattr(self, 'cidpick'):
|
if hasattr(self, 'cidpick'):
|
||||||
self.multicompfig.mpl_disconnect(self.cidpick)
|
self.multicompfig.mpl_disconnect(self.cidpick)
|
||||||
|
|
||||||
|
def on_motion(self, event):
|
||||||
|
x = event.xdata
|
||||||
|
if x is not None:
|
||||||
|
time_code = 'T = {}, t = {} [s]'.format(self.stime+x, x)
|
||||||
|
user_help = ' - Left-Click to Drag | Right-Click to Pan-Zoom |' \
|
||||||
|
' Mousewheel to Zoom | Middle-Click to Delete Pick'
|
||||||
|
self.statusbar.showMessage(time_code + user_help)
|
||||||
|
|
||||||
|
def onpick(self, event):
|
||||||
|
if event.mouseevent.button == 1:
|
||||||
|
self.onpick_info(event)
|
||||||
|
elif event.mouseevent.button == 2:
|
||||||
|
self.onpick_delete(event)
|
||||||
|
|
||||||
|
def on_hover_info(self, event):
|
||||||
|
if not any([phase.contains(event)[0] for phase in self.phaseLines]):
|
||||||
|
return
|
||||||
|
x = event.xdata
|
||||||
|
if not x:
|
||||||
|
return
|
||||||
|
allpicks, pick_rel, phase, picktype = self.identify_selected_picks(x)
|
||||||
|
pick = allpicks[picktype][phase]
|
||||||
|
message = '{} {}-pick'.format(picktype, phase)
|
||||||
|
if 'mpp' in pick:
|
||||||
|
message += ', MPP: {}'.format(pick['mpp'])
|
||||||
|
if 'spe' in pick:
|
||||||
|
message += ', SPE: {} [s]'.format(pick['spe'])
|
||||||
|
if 'filteroptions' in pick:
|
||||||
|
message += ', FILTER: {}'.format(pick['filteroptions'])
|
||||||
|
x = event.x
|
||||||
|
y = event.y
|
||||||
|
y = self.size().height() - y
|
||||||
|
pt = self.mapToGlobal(QtCore.QPoint(x, y))
|
||||||
|
QtGui.QToolTip.showText(pt, message)
|
||||||
|
|
||||||
|
def onpick_info(self, event):
|
||||||
|
if not event.mouseevent.button == 1:
|
||||||
|
return
|
||||||
|
x = event.mouseevent.xdata
|
||||||
|
allpicks, pick_rel, phase, picktype = self.identify_selected_picks(x)
|
||||||
|
pick = allpicks[picktype][phase]
|
||||||
|
message = '{} {}-pick'.format(picktype, phase)
|
||||||
|
if 'mpp' in pick:
|
||||||
|
message += ', MPP: {}'.format(pick['mpp'])
|
||||||
|
if 'spe' in pick:
|
||||||
|
message += ', SPE: {}'.format(pick['spe'])
|
||||||
|
if 'filteroptions' in pick:
|
||||||
|
message += ', FILTER: {}'.format(pick['filteroptions'])
|
||||||
|
|
||||||
|
if self.renamePhaseAction.isChecked():
|
||||||
|
self.renamePhase(picktype, phase)
|
||||||
|
|
||||||
|
self.statusbar.showMessage(message, 10e3)
|
||||||
|
|
||||||
def onpick_delete(self, event):
|
def onpick_delete(self, event):
|
||||||
if not event.mouseevent.button == 3:
|
if not event.mouseevent.button == 2:
|
||||||
return
|
return
|
||||||
x = event.mouseevent.xdata
|
x = event.mouseevent.xdata
|
||||||
self.remove_pick_by_x(x)
|
self.remove_pick_by_x(x)
|
||||||
self.refreshPlot()
|
self.refreshPlot()
|
||||||
|
|
||||||
|
def renamePhase(self, picktype, phase):
|
||||||
|
allpicks = {'manual': self.picks,
|
||||||
|
'auto': self.autopicks}
|
||||||
|
picks = allpicks[picktype]
|
||||||
|
dialog = QtGui.QInputDialog(parent=self)
|
||||||
|
new_phase, executed = dialog.getText(self, 'Rename phase', 'Rename phase {} to:'.format(phase))
|
||||||
|
if executed:
|
||||||
|
try:
|
||||||
|
self.renamePhaseInDict(picks, phase, new_phase)
|
||||||
|
except KeyError as e:
|
||||||
|
QtGui.QMessageBox.warning(self, 'Could not rename phase',
|
||||||
|
'Could not rename phase {} to {}: {}'.format(phase, new_phase, e))
|
||||||
|
self.leave_rename_phase()
|
||||||
|
self.refreshPlot()
|
||||||
|
|
||||||
|
def renamePhaseInDict(self, picks, phase_old, phase_new):
|
||||||
|
if phase_new in picks:
|
||||||
|
raise KeyError('New phase ID already assigned.')
|
||||||
|
picks_new = picks[phase_old].copy()
|
||||||
|
saved = self.savePick(phase_new, picks_new)
|
||||||
|
if saved:
|
||||||
|
picks.pop(phase_old)
|
||||||
|
self.setDirty(True)
|
||||||
|
|
||||||
|
def leave_rename_phase(self):
|
||||||
|
self.renamePhaseAction.setChecked(False)
|
||||||
|
self.multicompfig.set_frame_color()
|
||||||
|
self.multicompfig.connectEvents()
|
||||||
|
|
||||||
def remove_pick_by_x(self, x):
|
def remove_pick_by_x(self, x):
|
||||||
if not self.picks and not self.autopicks:
|
if not self.picks and not self.autopicks:
|
||||||
return
|
return
|
||||||
# init empty list and get station starttime
|
allpicks, pick_rel, phase, picktype = self.identify_selected_picks(x)
|
||||||
|
# delete the value from corresponding dictionary
|
||||||
|
allpicks[picktype].pop(phase)
|
||||||
|
# information output
|
||||||
|
msg = 'Deleted {} pick for phase {}, at timestamp {} (relative time: {} s)'
|
||||||
|
print(msg.format(picktype, phase, self.getStartTime()+pick_rel, pick_rel))
|
||||||
|
self.setDirty(True)
|
||||||
|
|
||||||
|
def identify_selected_picks(self, x):
|
||||||
|
# init empty list and get stat5ion starttime
|
||||||
X = []
|
X = []
|
||||||
starttime = self.getStartTime()
|
starttime = self.getStartTime()
|
||||||
# init dictionaries to iterate through and iterate over them
|
# init dictionaries to iterate through and iterate over them
|
||||||
@ -2159,12 +2286,9 @@ class PickDlg(QDialog):
|
|||||||
index, value = min(enumerate([val[0] for val in X]), key=lambda y: abs(y[1] - x))
|
index, value = min(enumerate([val[0] for val in X]), key=lambda y: abs(y[1] - x))
|
||||||
# unpack the found value
|
# unpack the found value
|
||||||
pick_rel, phase, picktype = X[index]
|
pick_rel, phase, picktype = X[index]
|
||||||
# delete the value from corresponding dictionary
|
return allpicks, pick_rel, phase, picktype
|
||||||
allpicks[picktype].pop(phase)
|
|
||||||
# information output
|
|
||||||
msg = 'Deleted {} pick for phase {}, at timestamp {} (relative time: {} s)'
|
|
||||||
print(msg.format(picktype, phase, starttime+pick_rel, pick_rel))
|
|
||||||
self.setDirty(True)
|
|
||||||
|
|
||||||
def drawPhaseText(self):
|
def drawPhaseText(self):
|
||||||
self.drawPicks(picktype='manual', textOnly=True)
|
self.drawPicks(picktype='manual', textOnly=True)
|
||||||
@ -2219,11 +2343,8 @@ class PickDlg(QDialog):
|
|||||||
data.detrend('linear')
|
data.detrend('linear')
|
||||||
data.taper(0.02, type='cosine')
|
data.taper(0.02, type='cosine')
|
||||||
data.filter(**filtoptions)
|
data.filter(**filtoptions)
|
||||||
title += ' | {} filtered |'.format(filtoptions['type'])
|
filtops_str = transformFilteroptions2String(filtoptions)
|
||||||
for key, value in filtoptions.items():
|
title += ' | Filteroptions: {}'.format(filtops_str)
|
||||||
if key == 'type':
|
|
||||||
continue
|
|
||||||
title += ' {}: {} |'.format(key, value)
|
|
||||||
self.multicompfig.plotWFData(wfdata=data, title=title,
|
self.multicompfig.plotWFData(wfdata=data, title=title,
|
||||||
zoomx=self.getXLims(),
|
zoomx=self.getXLims(),
|
||||||
zoomy=self.getYLims(),
|
zoomy=self.getYLims(),
|
||||||
@ -2258,10 +2379,17 @@ class PickDlg(QDialog):
|
|||||||
if self.autoFilterAction.isChecked():
|
if self.autoFilterAction.isChecked():
|
||||||
self.filterActionP.setChecked(False)
|
self.filterActionP.setChecked(False)
|
||||||
self.filterActionS.setChecked(False)
|
self.filterActionS.setChecked(False)
|
||||||
data = self.getWFData().copy()
|
# data = self.getWFData().copy()
|
||||||
title = self.getStation()
|
# title = self.getStation()
|
||||||
filter = self.filterActionP.isChecked or self.filterActionS.isChecked()
|
filter = False
|
||||||
self.plotWFData(filter=filter)
|
phase = None
|
||||||
|
if self.filterActionP.isChecked():
|
||||||
|
phase = 'P'
|
||||||
|
filter = True
|
||||||
|
if self.filterActionS.isChecked():
|
||||||
|
phase = 'S'
|
||||||
|
filter = True
|
||||||
|
self.plotWFData(phase=phase, filter=filter)
|
||||||
|
|
||||||
def resetZoom(self):
|
def resetZoom(self):
|
||||||
ax = self.multicompfig.axes[0]
|
ax = self.multicompfig.axes[0]
|
||||||
@ -2866,7 +2994,7 @@ class TuneAutopicker(QWidget):
|
|||||||
|
|
||||||
y_top = 0.9 * ax.get_ylim()[1]
|
y_top = 0.9 * ax.get_ylim()[1]
|
||||||
y_bot = 0.9 * ax.get_ylim()[0]
|
y_bot = 0.9 * ax.get_ylim()[0]
|
||||||
self._manual_pick_plots.append(ax.vlines(mpp, y_bot, y_top,
|
self._manual_pick_plots.append(ax.axvline(mpp, y_bot, y_top,
|
||||||
color=color, linewidth=2,
|
color=color, linewidth=2,
|
||||||
label='manual {} Onset (quality: {})'.format(phase, quality)))
|
label='manual {} Onset (quality: {})'.format(phase, quality)))
|
||||||
self._manual_pick_plots.append(ax.plot([mpp - 0.5, mpp + 0.5],
|
self._manual_pick_plots.append(ax.plot([mpp - 0.5, mpp + 0.5],
|
||||||
|
Loading…
Reference in New Issue
Block a user