Compare commits

...

31 Commits

Author SHA1 Message Date
Darius Arnold
cfe59cc264 Merge remote-tracking branch 'origin/develop' into darius 2017-09-07 17:03:18 +02:00
Darius Arnold
11fb9bfa52 Merge remote-tracking branch 'origin/develop' into darius 2017-09-07 13:00:47 +02:00
Darius Arnold
f06d11ab07 Merge remote-tracking branch 'origin/develop' into darius 2017-08-31 22:49:44 +02:00
Darius Arnold
591743240c Merge branch 'develop' into darius 2017-08-31 10:57:23 +02:00
Darius Arnold
f65b5efe41 [bugfix] for #240, tune autopicker not showing plots for some stations
this is probably just a workaround. Why was the program trying to access picks that were removed from the pick-dictionary?
2017-08-27 17:51:04 +02:00
Darius Arnold
bb54f2843e [experimental] enable tight layout option on tune autopicker
Seems to work if autopicker is called from the GUI. No further testing done
2017-08-27 16:52:21 +02:00
Darius Arnold
8293d63d28 [change] show more stations in stationbox of tune autopicker dialog 2017-08-27 16:34:00 +02:00
Darius Arnold
85e1e45552 [change] wadaticheck and jackknife print excluded stations 2017-08-26 19:41:26 +02:00
Darius Arnold
66d091197a [minor] change axis label for comparison dialog 2017-08-26 19:30:46 +02:00
Darius Arnold
6de5ebfe52 [minor] only show a single point in legends of wadati-/jacknife-plot 2017-08-26 19:20:43 +02:00
Darius Arnold
2b7ff9fd3a [change] include safetygap in check for other maxima in front of first one
And some changes to improve readability/understandability
2017-08-26 19:19:55 +02:00
Darius Arnold
01dc489569 [bugfix] avoid indexing an empty array when there are no NaNs at start of CF 2017-08-26 17:26:35 +02:00
Darius Arnold
efd2621db9 [add] jackknife safety factor no longer hardcoded, GUI parameter added 2017-08-26 17:22:28 +02:00
Darius Arnold
fde3f251fb [bugfix] Earllate-Picker would use wrong timearray for plotting
signal-timearray gets doubled if not enough zero crossings are found to calculate valid signal period. Plotting would then use the old "single" timearray.
2017-08-26 12:14:44 +02:00
Darius Arnold
2db6fde709 [add] check second maximum of HOS/AR-CF
Use the second maximum if it is larger than first maximum * minfactor. This helps when two onsets are close together (eg. S and SKS at 90°) and the second onset is stronger.
2017-08-26 02:12:31 +02:00
Darius Arnold
cd83c99034 [bugfix] wdfit2 referenced before set if wadaticheck had < 3 good picks 2017-08-26 01:55:16 +02:00
Darius Arnold
c760ea394c [add] remove picks with weight > 3 from pickdictionary after autopicking 2017-08-26 01:53:38 +02:00
Darius Arnold
1afc6bdcf1 readd imports of check4rotated that got lost during merge 2017-08-26 01:49:18 +02:00
Darius Arnold
63293c6f93 gitignore file update 2017-08-26 01:43:21 +02:00
Darius Arnold
1dab754811 Merge branch 'develop' into darius 2017-08-26 01:42:18 +02:00
Darius Arnold
17da0b9ddb [bugfix] check4rotated unable to access metadata in TuneAutopicker 2017-08-26 01:10:17 +02:00
Darius Arnold
2a2c4d7a37 [change] replace NaN's in HOScf by first NaN value instead of zero 2017-08-24 15:42:12 +02:00
Darius Arnold
9dfb4f37a5 [change] calculate slope from two or more samples 2017-08-21 13:20:05 +02:00
Darius Arnold
c454640619 [bugfix] handle to short zero crossings window 2017-08-21 13:19:22 +02:00
Darius Arnold
6223c4b5e1 [change] more readable indexing during slope determination 2017-08-21 13:18:31 +02:00
Darius Arnold
2e094fb0b5 [bugfix] catch empty index array during slope determination 2017-08-21 13:17:33 +02:00
Darius Arnold
f6ae77d4d2 [add] tune autopicker displays picked onset time and error in seconds 2017-08-21 13:16:22 +02:00
Darius Arnold
08ce54e890 [add] enabled jackknife function fpr P onsets 2017-08-21 13:15:38 +02:00
Darius Arnold
f2a6228e83 [bugfix] error in if check during load of eventliste.csv file 2017-08-21 13:14:10 +02:00
Darius Arnold
3e3b00b304 [add] function to rotate back traces if metadata is available 2017-08-21 13:13:03 +02:00
Darius Arnold
f1b64bb314 [add] possible models displayed in taupy tooltip 2017-08-21 13:09:54 +02:00
7 changed files with 129 additions and 21 deletions

4
.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
\.idea/
*.pyc

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, removePicksAbove
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,7 +74,8 @@ 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, remove_underscores, check4doubled, identifyPhaseID, excludeQualityClasses, has_spe, check4rotated pick_linestyle_plt, remove_underscores, check4doubled, identifyPhaseID, excludeQualityClasses, has_spe, \
check4rotated
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, \
@ -2051,6 +2052,7 @@ class MainWindow(QMainWindow):
def finalizeAutoPick(self, result): def finalizeAutoPick(self, result):
self.apw.enable(True) self.apw.enable(True)
if result: if result:
result = removePicksAbove(result, 3)
self.init_canvas_dict_wadatijack() self.init_canvas_dict_wadatijack()
for eventID in result.keys(): for eventID in result.keys():
event = self.get_event_from_id(eventID) event = self.get_event_from_id(eventID)
@ -2956,7 +2958,7 @@ class Project(object):
print(e, datetime, filename) print(e, datetime, filename)
continue continue
for event in self.eventlist: for event in self.eventlist:
if eventID in str(event.resource_id) or event.origins: if eventID in str(event.resource_id) or eventID in event.origins:
if event.origins: if event.origins:
origin = event.origins[0] # should have only one origin origin = event.origins[0] # should have only one origin
if origin.time == datetime: if origin.time == datetime:

View File

@ -273,6 +273,26 @@ defaults = {'rootpath': {'type': str,
'value': 1.5, 'value': 1.5,
'namestring': 'Noise factor S'}, 'namestring': 'Noise factor S'},
'checkwindowP': {'type': float,
'tooltip': 'time window before HOS/AR-maximum to check for smaller maxima [s]',
'value': 10.0,
'namestring': 'Check Window P'},
'minfactorP': {'type': float,
'tooltip': 'Second maximum must be at least minfactor * first maximum [-]',
'value': 0.7,
'namestring': 'Minimum Factor P'},
'checkwindowS': {'type': float,
'tooltip': 'time window before AR-maximum to check for smaller maxima [s]',
'value': 10.0,
'namestring': 'Check Window S'},
'minfactorS': {'type': float,
'tooltip': 'Second maximum must be at least minfactor * first maximum [-]',
'value': 0.7,
'namestring': 'Minimum Factor S'},
'minfmweight': {'type': int, 'minfmweight': {'type': int,
'tooltip': 'minimum required P weight for first-motion determination', 'tooltip': 'minimum required P weight for first-motion determination',
'value': 1, 'value': 1,
@ -455,7 +475,9 @@ settings_special_pick = {
'aictsmooth', 'aictsmooth',
'tsmoothP', 'tsmoothP',
'ausP', 'ausP',
'nfacP'], 'nfacP',
'checkwindowP',
'minfactorP'],
'h': [ 'h': [
'algoS', 'algoS',
'tdet1h', 'tdet1h',
@ -469,7 +491,9 @@ settings_special_pick = {
'aictsmoothS', 'aictsmoothS',
'tsmoothS', 'tsmoothS',
'ausS', 'ausS',
'nfacS'], 'nfacS',
'checkwindowS',
'minfactorS'],
'fm': [ 'fm': [
'minfmweight', 'minfmweight',
'minFMSNR', 'minFMSNR',

View File

@ -177,6 +177,10 @@ def autopickstation(wfstream, pickparam, verbose=False,
# parameter to check for spuriously picked S onset # parameter to check for spuriously picked S onset
zfac = pickparam.get('zfac') zfac = pickparam.get('zfac')
# path to inventory-, dataless- or resp-files # path to inventory-, dataless- or resp-files
checkwindowP = pickparam.get('checkwindowP')
minfactorP = pickparam.get('minfactorP')
checkwindowS = pickparam.get('checkwindowS')
minfactorS = pickparam.get('minfactorS')
# initialize output # initialize output
Pweight = 4 # weight for P onset Pweight = 4 # weight for P onset
@ -324,7 +328,8 @@ def autopickstation(wfstream, pickparam, verbose=False,
fig = fig_dict[key] fig = fig_dict[key]
else: else:
fig = None fig = None
aicpick = AICPicker(aiccf, tsnrz, pickwinP, iplot, None, aictsmoothP, fig=fig) aicpick = AICPicker(aiccf, tsnrz, pickwinP, checkwindow=checkwindowP, minfactor=minfactorP,
iplot=iplot, Tsmooth=tsmoothP, fig=fig)
# add pstart and pstop to aic plot # add pstart and pstop to aic plot
if fig: if fig:
for ax in fig.axes: for ax in fig.axes:
@ -444,8 +449,8 @@ def autopickstation(wfstream, pickparam, verbose=False,
fig = fig_dict['refPpick'] fig = fig_dict['refPpick']
else: else:
fig = None fig = None
refPpick = PragPicker(cf2, tsnrz, pickwinP, iplot, ausP, tsmoothP, refPpick = PragPicker(cf2, tsnrz, pickwinP, iplot=iplot, aus=ausP, Tsmooth=tsmoothP,
aicpick.getpick(), fig) Pick1 = aicpick.getpick(), fig=fig)
mpickP = refPpick.getpick() mpickP = refPpick.getpick()
############################################################# #############################################################
if mpickP is not None: if mpickP is not None:
@ -626,8 +631,9 @@ def autopickstation(wfstream, pickparam, verbose=False,
fig = fig_dict['aicARHfig'] fig = fig_dict['aicARHfig']
else: else:
fig = None fig = None
aicarhpick = AICPicker(haiccf, tsnrh, pickwinS, iplot, None, aicarhpick = AICPicker(haiccf, tsnrh, pickwinS, checkwindow=checkwindowS,
aictsmoothS, fig=fig) minfactor=minfactorS, iplot=iplot, Tsmooth=aictsmoothS,
fig=fig)
############################################################### ###############################################################
# go on with processing if AIC onset passes quality control # go on with processing if AIC onset passes quality control
slope = aicarhpick.getSlope() slope = aicarhpick.getSlope()
@ -688,8 +694,8 @@ def autopickstation(wfstream, pickparam, verbose=False,
fig = fig_dict['refSpick'] fig = fig_dict['refSpick']
else: else:
fig = None fig = None
refSpick = PragPicker(arhcf2, tsnrh, pickwinS, iplot, ausS, refSpick = PragPicker(arhcf2, tsnrh, pickwinS, iplot=iplot, aus=ausS,
tsmoothS, aicarhpick.getpick(), fig) Tsmooth=tsmoothS, Pick1=aicarhpick.getpick(), fig=fig)
mpickS = refSpick.getpick() mpickS = refSpick.getpick()
############################################################# #############################################################
if mpickS is not None: if mpickS is not None:

View File

@ -24,7 +24,7 @@ import warnings
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
import numpy as np import numpy as np
from pylot.core.pick.charfuns import CharacteristicFunction from pylot.core.pick.charfuns import CharacteristicFunction
from pylot.core.pick.utils import getnoisewin, getsignalwin from pylot.core.pick.utils import getnoisewin, getsignalwin, get_maximum_index
class AutoPicker(object): class AutoPicker(object):
@ -35,7 +35,7 @@ class AutoPicker(object):
warnings.simplefilter('ignore') warnings.simplefilter('ignore')
def __init__(self, cf, TSNR, PickWindow, iplot=0, aus=None, Tsmooth=None, Pick1=None, fig=None): def __init__(self, cf, TSNR, PickWindow, checkwindow=None, minfactor=None, iplot=0, aus=None, Tsmooth=None, Pick1=None, fig=None):
''' '''
:param: cf, characteristic function, on which the picking algorithm is applied :param: cf, characteristic function, on which the picking algorithm is applied
:type: `~pylot.core.pick.CharFuns.CharacteristicFunction` object :type: `~pylot.core.pick.CharFuns.CharacteristicFunction` object
@ -74,6 +74,8 @@ class AutoPicker(object):
self.setTsmooth(Tsmooth) self.setTsmooth(Tsmooth)
self.setpick1(Pick1) self.setpick1(Pick1)
self.fig = fig self.fig = fig
self.setCheckWindow(checkwindow)
self.minfactor = minfactor
self.calcPick() self.calcPick()
def __str__(self): def __str__(self):
@ -89,6 +91,10 @@ class AutoPicker(object):
aus=self.getaus(), aus=self.getaus(),
Tsmooth=self.getTsmooth(), Tsmooth=self.getTsmooth(),
Pick1=self.getpick1()) Pick1=self.getpick1())
def setCheckWindow(self, checkwindow):
'''convert checkwindow to samples'''
if checkwindow:
self.checkwindow = int(checkwindow / self.Data[0].stats.delta)
def getTSNR(self): def getTSNR(self):
return self.TSNR return self.TSNR
@ -187,8 +193,9 @@ class AICPicker(AutoPicker):
offset = abs(min(aic) - min(aicsmooth)) offset = abs(min(aic) - min(aicsmooth))
aicsmooth = aicsmooth - offset aicsmooth = aicsmooth - offset
# get maximum of HOS/AR-CF as startimg point for searching # get maximum of HOS/AR-CF as startimg point for searching
# minimum in AIC function # minimum in AIC function
icfmax = np.argmax(self.Data[0].data) icfmax = get_maximum_index(self.Data[0].data, self.checkwindow, self.minfactor,
int(self.TSNR[1]/self.Data[0].stats.delta))
# find minimum in AIC-CF front of maximum of HOS/AR-CF # find minimum in AIC-CF front of maximum of HOS/AR-CF
lpickwindow = int(round(self.PickWindow / self.dt)) lpickwindow = int(round(self.PickWindow / self.dt))

View File

@ -13,6 +13,7 @@ import warnings
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
import numpy as np import numpy as np
from obspy.core import Stream, UTCDateTime from obspy.core import Stream, UTCDateTime
from scipy.signal import argrelextrema
def earllatepicker(X, nfac, TSNR, Pick1, iplot=0, verbosity=1, fig=None): def earllatepicker(X, nfac, TSNR, Pick1, iplot=0, verbosity=1, fig=None):
@ -616,6 +617,7 @@ def wadaticheck(pickdic, dttolerance, iplot=0, fig_dict=None):
checkedPpicks = [] checkedPpicks = []
checkedSpicks = [] checkedSpicks = []
checkedSPtimes = [] checkedSPtimes = []
badstations = []
# calculate deviations from Wadati regression # calculate deviations from Wadati regression
ii = 0 ii = 0
ibad = 0 ibad = 0
@ -629,6 +631,7 @@ def wadaticheck(pickdic, dttolerance, iplot=0, fig_dict=None):
# (not used anymore) # (not used anymore)
marker = 'badWadatiCheck' marker = 'badWadatiCheck'
pickdic[key]['S']['weight'] = 9 pickdic[key]['S']['weight'] = 9
badstations.append(key)
ibad += 1 ibad += 1
else: else:
marker = 'goodWadatiCheck' marker = 'goodWadatiCheck'
@ -640,6 +643,8 @@ def wadaticheck(pickdic, dttolerance, iplot=0, fig_dict=None):
checkedSPtimes.append(checkedSPtime) checkedSPtimes.append(checkedSPtime)
pickdic[key]['S']['marked'] = marker pickdic[key]['S']['marked'] = marker
print("wadaticheck: the following stations failed the check:")
print(badstations)
if len(checkedPpicks) >= 3: if len(checkedPpicks) >= 3:
# calculate new slope # calculate new slope
@ -862,6 +867,7 @@ def checkPonsets(pickdic, dttolerance, jackfactor=5, iplot=0, fig_dict=None):
print("checkPonsets: %d pick(s) deviate too much from median!" % len(ibad)) print("checkPonsets: %d pick(s) deviate too much from median!" % len(ibad))
print("checkPonsets: Skipped %d P pick(s) out of %d" % (len(badstations) \ print("checkPonsets: Skipped %d P pick(s) out of %d" % (len(badstations) \
+ len(badjkstations), len(stations))) + len(badjkstations), len(stations)))
print(badstations)
goodmarker = 'goodPonsetcheck' goodmarker = 'goodPonsetcheck'
badmarker = 'badPonsetcheck' badmarker = 'badPonsetcheck'
@ -935,8 +941,9 @@ def jackknife(X, phi, h):
PHI_sub = None PHI_sub = None
# determine number of subgroups # determine number of subgroups
g = int(len(X) / h)
if len(X) % h: if (len(X) / h) % 1 != 0:
print("jackknife: Cannot divide quantity X in equal sized subgroups!") print("jackknife: Cannot divide quantity X in equal sized subgroups!")
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
@ -953,7 +960,7 @@ def jackknife(X, phi, h):
# estimators of subgroups # estimators of subgroups
PHI_pseudo = [] PHI_pseudo = []
PHI_sub = [] PHI_sub = []
for i in range(0, g - 1): for i in range(0, g):
# subgroup i, remove i-th sample # subgroup i, remove i-th sample
xx = X[:] xx = X[:]
del xx[i] del xx[i]
@ -1147,6 +1154,55 @@ def getQualityFromUncertainty(uncertainty, Errors):
return quality return quality
def removePicksAbove(pickDic, minWeight):
'''remove picks from pick dicitonary with a weight > minweight'''
newdic = {}
for event in pickDic.keys():
newdic[event] = {}
for eventKey, eventDic in pickDic.items():
for station, phases in eventDic.items():
if phases['P']['weight'] < minWeight or phases['S']['weight'] < minWeight:
# dont append stations that will be empty to output dict
newdic[eventKey][station] = {}
if len(phases) > 2:
# copy over other values beside P/S information
additional_info = phases.copy()
if 'P' in phases.keys():
additional_info.pop('P')
if 'S' in phases.keys():
additional_info.pop('S')
newdic[eventKey][station].update(additional_info)
for phasename, phaseinfo in phases.items():
if phasename in ('P', 'S') and phaseinfo['weight'] < minWeight:
newdic[eventKey][station].update({phasename: phaseinfo})
return newdic
def get_maximum_index(data, checkwindow, minfactor, safetygap):
'''get maximum of CF as starting point, then check for highest local maximum
in front of it.
return second maximum if its larger than first maximum * minfactor, else
return first maximum.
checkwindow and safetygap are given in samples'''
icfmax1 = np.argmax(data)
imax_local = argrelextrema(data[icfmax1 - checkwindow:icfmax1 - safetygap], np.greater)[0] # indices of local maxima
if imax_local.size > 0:
imax_local = imax_local + icfmax1 - checkwindow
local_maxima = (imax_local, data[imax_local])
largest_local_max = np.where(local_maxima[1] == max(local_maxima[1]))
icfmax2 = local_maxima[0][largest_local_max]
if data[icfmax2] > data[icfmax1] * minfactor:
print("Found valid local maximum in front of first maximum")
return icfmax2[0]
else:
print("First maximum is the largest: {}>{}".format(data[icfmax1],
data[icfmax2]))
return icfmax1
else:
print("No local maxima found in check window")
return icfmax1
if __name__ == '__main__': if __name__ == '__main__':
import doctest import doctest

View File

@ -377,7 +377,7 @@ class ComparisonWidget(QWidget):
axes_dict[phase]['std'].set_xlabel('standard deviation [s]') axes_dict[phase]['std'].set_xlabel('standard deviation [s]')
for ax in axes_dict['P'].values(): for ax in axes_dict['P'].values():
ax.set_ylabel('frequency [-]') ax.set_ylabel('number of picks [-]')
self.canvas.draw() self.canvas.draw()
else: else:
@ -2442,7 +2442,7 @@ class TuneAutopicker(QWidget):
self.setParent(parent) self.setParent(parent)
self.setWindowTitle('PyLoT - Tune Autopicker') self.setWindowTitle('PyLoT - Tune Autopicker')
self.parameter = parent._inputs self.parameter = parent._inputs
self.fig_dict = parent.fig_dict self.set_fig_dict(parent.fig_dict)
self.data = Data() self.data = Data()
self.init_main_layouts() self.init_main_layouts()
self.init_eventlist() self.init_eventlist()
@ -2462,6 +2462,11 @@ class TuneAutopicker(QWidget):
# self.setWindowModality(QtCore.Qt.WindowModality.ApplicationModal) # self.setWindowModality(QtCore.Qt.WindowModality.ApplicationModal)
# self.setWindowFlags(self.windowFlags() | QtCore.Qt.WindowStaysOnTopHint) # self.setWindowFlags(self.windowFlags() | QtCore.Qt.WindowStaysOnTopHint)
def set_fig_dict(self, fig_dict):
for key, value in fig_dict.items():
value._tight = True
self.fig_dict = fig_dict
def init_main_layouts(self): def init_main_layouts(self):
self.main_layout = QtGui.QVBoxLayout() self.main_layout = QtGui.QVBoxLayout()
self.tune_layout = QtGui.QHBoxLayout() self.tune_layout = QtGui.QHBoxLayout()
@ -2480,6 +2485,7 @@ class TuneAutopicker(QWidget):
def init_stationlist(self): def init_stationlist(self):
self.stationBox = QtGui.QComboBox() self.stationBox = QtGui.QComboBox()
self.stationBox.setMaxVisibleItems(42)
self.trace_layout.addWidget(self.stationBox) self.trace_layout.addWidget(self.stationBox)
self.fill_stationbox() self.fill_stationbox()
self.figure_tabs.setCurrentIndex(0) self.figure_tabs.setCurrentIndex(0)
@ -2568,7 +2574,10 @@ class TuneAutopicker(QWidget):
def get_current_event_autopicks(self, station): def get_current_event_autopicks(self, station):
event = self.get_current_event() event = self.get_current_event()
if event.pylot_autopicks: if event.pylot_autopicks:
return event.pylot_autopicks[station] if station in event.pylot_autopicks:
return event.pylot_autopicks[station]
else:
return
def get_current_station(self): def get_current_station(self):
return str(self.stationBox.currentText()).split('.')[-1] return str(self.stationBox.currentText()).split('.')[-1]