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 autoPyLoT import autoPyLoT
from pylot.core.pick.compare import Comparison
from pylot.core.pick.utils import symmetrize_error, getQualityFromUncertainty
from pylot.core.pick.utils import symmetrize_error, getQualityFromUncertainty, removePicksAbove
from pylot.core.io.phases import picksdict_from_picks
import pylot.core.loc.nll as nll
from pylot.core.util.defaults import FILTERDEFAULTS, SetChannelComponents
@ -74,7 +74,8 @@ from pylot.core.util.connection import checkurl
from pylot.core.util.dataprocessing import read_metadata, restitute_data
from pylot.core.util.utils import fnConstructor, getLogin, \
full_range, readFilterInformation, trim_station_components, check4gaps, make_pen, pick_color_plt, \
pick_linestyle_plt, 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.io.location import create_creation_info, create_event
from pylot.core.util.widgets import FilterOptionsDialog, NewEventDlg, \
@ -2051,6 +2052,7 @@ class MainWindow(QMainWindow):
def finalizeAutoPick(self, result):
self.apw.enable(True)
if result:
result = removePicksAbove(result, 3)
self.init_canvas_dict_wadatijack()
for eventID in result.keys():
event = self.get_event_from_id(eventID)
@ -2956,7 +2958,7 @@ class Project(object):
print(e, datetime, filename)
continue
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:
origin = event.origins[0] # should have only one origin
if origin.time == datetime:

View File

@ -273,6 +273,26 @@ defaults = {'rootpath': {'type': str,
'value': 1.5,
'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,
'tooltip': 'minimum required P weight for first-motion determination',
'value': 1,
@ -455,7 +475,9 @@ settings_special_pick = {
'aictsmooth',
'tsmoothP',
'ausP',
'nfacP'],
'nfacP',
'checkwindowP',
'minfactorP'],
'h': [
'algoS',
'tdet1h',
@ -469,7 +491,9 @@ settings_special_pick = {
'aictsmoothS',
'tsmoothS',
'ausS',
'nfacS'],
'nfacS',
'checkwindowS',
'minfactorS'],
'fm': [
'minfmweight',
'minFMSNR',

View File

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

View File

@ -24,7 +24,7 @@ import warnings
import matplotlib.pyplot as plt
import numpy as np
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):
@ -35,7 +35,7 @@ class AutoPicker(object):
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
:type: `~pylot.core.pick.CharFuns.CharacteristicFunction` object
@ -74,6 +74,8 @@ class AutoPicker(object):
self.setTsmooth(Tsmooth)
self.setpick1(Pick1)
self.fig = fig
self.setCheckWindow(checkwindow)
self.minfactor = minfactor
self.calcPick()
def __str__(self):
@ -89,6 +91,10 @@ class AutoPicker(object):
aus=self.getaus(),
Tsmooth=self.getTsmooth(),
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):
return self.TSNR
@ -187,8 +193,9 @@ class AICPicker(AutoPicker):
offset = abs(min(aic) - min(aicsmooth))
aicsmooth = aicsmooth - offset
# get maximum of HOS/AR-CF as startimg point for searching
# minimum in AIC function
icfmax = np.argmax(self.Data[0].data)
# minimum in AIC function
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
lpickwindow = int(round(self.PickWindow / self.dt))

View File

@ -13,6 +13,7 @@ import warnings
import matplotlib.pyplot as plt
import numpy as np
from obspy.core import Stream, UTCDateTime
from scipy.signal import argrelextrema
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 = []
checkedSpicks = []
checkedSPtimes = []
badstations = []
# calculate deviations from Wadati regression
ii = 0
ibad = 0
@ -629,6 +631,7 @@ def wadaticheck(pickdic, dttolerance, iplot=0, fig_dict=None):
# (not used anymore)
marker = 'badWadatiCheck'
pickdic[key]['S']['weight'] = 9
badstations.append(key)
ibad += 1
else:
marker = 'goodWadatiCheck'
@ -640,6 +643,8 @@ def wadaticheck(pickdic, dttolerance, iplot=0, fig_dict=None):
checkedSPtimes.append(checkedSPtime)
pickdic[key]['S']['marked'] = marker
print("wadaticheck: the following stations failed the check:")
print(badstations)
if len(checkedPpicks) >= 3:
# 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: Skipped %d P pick(s) out of %d" % (len(badstations) \
+ len(badjkstations), len(stations)))
print(badstations)
goodmarker = 'goodPonsetcheck'
badmarker = 'badPonsetcheck'
@ -935,8 +941,9 @@ def jackknife(X, phi, h):
PHI_sub = None
# 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("Choose another size for subgroups!")
return PHI_jack, PHI_pseudo, PHI_sub
@ -953,7 +960,7 @@ def jackknife(X, phi, h):
# estimators of subgroups
PHI_pseudo = []
PHI_sub = []
for i in range(0, g - 1):
for i in range(0, g):
# subgroup i, remove i-th sample
xx = X[:]
del xx[i]
@ -1147,6 +1154,55 @@ def getQualityFromUncertainty(uncertainty, Errors):
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__':
import doctest

View File

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