Resolved conflicts fmtomoUtils
This commit is contained in:
commit
ddb1ad4a15
73
QtPyLoT.py
73
QtPyLoT.py
@ -43,8 +43,10 @@ from obspy import UTCDateTime
|
||||
from pylot.core.read.data import Data
|
||||
from pylot.core.read.inputs import FilterOptions, AutoPickParameter
|
||||
from pylot.core.pick.autopick import autopickevent
|
||||
from pylot.core.read.io import picks_from_evt
|
||||
from pylot.core.loc.nll import locate as locateNll
|
||||
from pylot.core.util.defaults import FILTERDEFAULTS
|
||||
from pylot.core.util.defaults import FILTERDEFAULTS, COMPNAME_MAP,\
|
||||
AUTOMATIC_DEFAULTS
|
||||
from pylot.core.util.errors import FormatError, DatastructureError, \
|
||||
OverwriteError
|
||||
from pylot.core.util.connection import checkurl
|
||||
@ -110,8 +112,10 @@ class MainWindow(QMainWindow):
|
||||
# load and display waveform data
|
||||
self.dirty = False
|
||||
self.loadData()
|
||||
self.loadWaveformData()
|
||||
if self.loadWaveformData():
|
||||
self.updateFilterOptions()
|
||||
else:
|
||||
sys.exit(0)
|
||||
|
||||
def setupUi(self):
|
||||
|
||||
@ -354,7 +358,10 @@ class MainWindow(QMainWindow):
|
||||
settings = QSettings()
|
||||
return settings.value("data/dataRoot")
|
||||
|
||||
def loadData(self, fname=None):
|
||||
def loadAutoPicks(self):
|
||||
self.loadData(type='auto')
|
||||
|
||||
def loadData(self, fname=None, type='manual'):
|
||||
if not self.okToContinue():
|
||||
return
|
||||
if fname is None:
|
||||
@ -368,10 +375,10 @@ class MainWindow(QMainWindow):
|
||||
filter=filt)
|
||||
fname = fname[0]
|
||||
else:
|
||||
fname = unicode(action.data().toString())
|
||||
fname = str(action.data().toString())
|
||||
self.setFileName(fname)
|
||||
self.data += Data(self, evtdata=self.getFileName())
|
||||
self.updatePicks()
|
||||
self.updatePicks(type=type)
|
||||
self.drawPicks()
|
||||
|
||||
def getLastEvent(self):
|
||||
@ -403,6 +410,8 @@ class MainWindow(QMainWindow):
|
||||
|
||||
else:
|
||||
raise DatastructureError('not specified')
|
||||
if not self.fnames:
|
||||
return None
|
||||
return self.fnames
|
||||
except DatastructureError as e:
|
||||
print(e)
|
||||
@ -431,13 +440,14 @@ class MainWindow(QMainWindow):
|
||||
print('warning: {0}'.format(e))
|
||||
directory = os.path.join(self.getRoot(), self.getEventFileName())
|
||||
file_filter = "QuakeML file (*.xml);;VELEST observation file format (*.cnv);;NonLinLoc observation file (*.obs)"
|
||||
fname = QFileDialog.getSaveFileName(self, 'Save event data ...',
|
||||
fname, selected_filter = QFileDialog.getSaveFileName(self, 'Save event data ...',
|
||||
directory, file_filter)
|
||||
|
||||
fbasename, exform = os.path.splitext(fname[0])
|
||||
fbasename, exform = os.path.splitext(fname)
|
||||
|
||||
if not exform and selected_filter:
|
||||
exform = selected_filter.split('*')[1][:-1]
|
||||
|
||||
if not exform:
|
||||
exform = file_filter[0].split('*')[1][:-1]
|
||||
return fbasename, exform
|
||||
|
||||
settings = QSettings()
|
||||
@ -455,7 +465,7 @@ class MainWindow(QMainWindow):
|
||||
ret = msgBox.exec_()
|
||||
if ret == QMessageBox.Save:
|
||||
self.getData().resetPicks()
|
||||
self.saveData()
|
||||
return self.saveData()
|
||||
elif ret == QMessageBox.Cancel:
|
||||
return False
|
||||
try:
|
||||
@ -524,17 +534,23 @@ class MainWindow(QMainWindow):
|
||||
def loadWaveformData(self):
|
||||
if self.fnames and self.okToContinue():
|
||||
self.setDirty(True)
|
||||
self.data.setWFData(self.fnames)
|
||||
ans = self.data.setWFData(self.fnames)
|
||||
elif self.fnames is None and self.okToContinue():
|
||||
self.data.setWFData(self.getWFFnames())
|
||||
ans = self.data.setWFData(self.getWFFnames())
|
||||
if ans:
|
||||
self.plotWaveformData()
|
||||
return ans
|
||||
else:
|
||||
return ans
|
||||
|
||||
def plotWaveformData(self):
|
||||
zne_text = {'Z': 'vertical', 'N': 'north-south', 'E': 'east-west'}
|
||||
comp = self.getComponent()
|
||||
title = 'section: {0} components'.format(zne_text[comp])
|
||||
alter_comp = COMPNAME_MAP[comp]
|
||||
wfst = self.getData().getWFData().select(component=comp)
|
||||
self.getPlotWidget().plotWFData(wfdata=wfst, title=title)
|
||||
wfst += self.getData().getWFData().select(component=alter_comp)
|
||||
self.getPlotWidget().plotWFData(wfdata=wfst, title=title, mapping=False)
|
||||
self.draw()
|
||||
plotDict = self.getPlotWidget().getPlotDict()
|
||||
pos = plotDict.keys()
|
||||
@ -569,6 +585,7 @@ class MainWindow(QMainWindow):
|
||||
else:
|
||||
self.getData().resetWFData()
|
||||
self.plotWaveformData()
|
||||
self.drawPicks()
|
||||
|
||||
def adjustFilterOptions(self):
|
||||
fstring = "Filter Options ({0})".format(self.getSeismicPhase())
|
||||
@ -673,8 +690,7 @@ class MainWindow(QMainWindow):
|
||||
self.logDockWidget.setWidget(self.listWidget)
|
||||
self.addDockWidget(Qt.LeftDockWidgetArea, self.logDockWidget)
|
||||
self.addListItem('loading default values for local data ...')
|
||||
home = os.path.expanduser("~")
|
||||
autopick_parameter = AutoPickParameter('%s/.pylot/autoPyLoT_local.in' % home)
|
||||
autopick_parameter = AutoPickParameter(AUTOMATIC_DEFAULTS)
|
||||
self.addListItem(str(autopick_parameter))
|
||||
|
||||
# Create the worker thread and run it
|
||||
@ -718,29 +734,12 @@ class MainWindow(QMainWindow):
|
||||
self.getPicks(type=type)[station] = stat_picks
|
||||
return rval
|
||||
|
||||
def updatePicks(self):
|
||||
evt = self.getData().getEvtData()
|
||||
picks = {}
|
||||
for pick in evt.picks:
|
||||
phase = {}
|
||||
station = pick.waveform_id.station_code
|
||||
try:
|
||||
onsets = picks[station]
|
||||
except KeyError as e:
|
||||
print(e)
|
||||
onsets = {}
|
||||
mpp = pick.time
|
||||
lpp = mpp + pick.time_errors.upper_uncertainty
|
||||
epp = mpp - pick.time_errors.lower_uncertainty
|
||||
spe = pick.time_errors.uncertainty
|
||||
phase['mpp'] = mpp
|
||||
phase['epp'] = epp
|
||||
phase['lpp'] = lpp
|
||||
phase['spe'] = spe
|
||||
|
||||
onsets[pick.phase_hint] = phase.copy()
|
||||
picks[station] = onsets.copy()
|
||||
def updatePicks(self, type='manual'):
|
||||
picks = picks_from_evt(evt=self.getData().getEvtData())
|
||||
if type == 'manual':
|
||||
self.picks.update(picks)
|
||||
elif type == 'auto':
|
||||
self.autopicks.update(picks)
|
||||
|
||||
def drawPicks(self, station=None, picktype='manual'):
|
||||
# if picks to draw not specified, draw all picks available
|
||||
|
21
autoPyLoT.py
21
autoPyLoT.py
@ -1,6 +1,7 @@
|
||||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from __future__ import print_function
|
||||
import os
|
||||
import argparse
|
||||
import glob
|
||||
@ -94,7 +95,6 @@ def autoPyLoT(inputfile):
|
||||
print("!!No source parameter estimation possible!!")
|
||||
print(" !!! ")
|
||||
|
||||
|
||||
# multiple event processing
|
||||
# read each event in database
|
||||
datapath = datastructure.expandDataPath()
|
||||
@ -202,10 +202,15 @@ def autoPyLoT(inputfile):
|
||||
if hasattr(finalpicks, 'getpicdic'):
|
||||
if finalpicks.getpicdic() is not None:
|
||||
writephases(finalpicks.getpicdic(), 'HYPO71', hypo71file)
|
||||
data.applyEVTData(finalpicks.getpicdic())
|
||||
else:
|
||||
writephases(picks, 'HYPO71', hypo71file)
|
||||
data.applyEVTData(picks)
|
||||
else:
|
||||
writephases(picks, 'HYPO71', hypo71file)
|
||||
data.applyEVTData(picks)
|
||||
fnqml = '%s/autoPyLoT' % event
|
||||
data.exportEvent(fnqml)
|
||||
|
||||
endsplash = '''------------------------------------------\n'
|
||||
-----Finished event %s!-----\n'
|
||||
@ -218,8 +223,8 @@ def autoPyLoT(inputfile):
|
||||
# single event processing
|
||||
else:
|
||||
data.setWFData(glob.glob(os.path.join(datapath, parameter.getParam('eventID'), '*')))
|
||||
print("Working on event "), parameter.getParam('eventID')
|
||||
print data
|
||||
print("Working on event {0}".format(parameter.getParam('eventID')))
|
||||
print(data)
|
||||
|
||||
wfdat = data.getWFData() # all available streams
|
||||
##########################################################
|
||||
@ -318,10 +323,15 @@ def autoPyLoT(inputfile):
|
||||
if hasattr(finalpicks, 'getpicdic'):
|
||||
if finalpicks.getpicdic() is not None:
|
||||
writephases(finalpicks.getpicdic(), 'HYPO71', hypo71file)
|
||||
data.applyEVTData(finalpicks.getpicdic())
|
||||
else:
|
||||
writephases(picks, 'HYPO71', hypo71file)
|
||||
data.applyEVTData(picks)
|
||||
else:
|
||||
writephases(picks, 'HYPO71', hypo71file)
|
||||
data.applyEVTData(picks)
|
||||
fnqml = '%s/%s/autoPyLoT' % (datapath, parameter.getParam('eventID'))
|
||||
data.exportEvent(fnqml)
|
||||
|
||||
endsplash = '''------------------------------------------\n'
|
||||
-----Finished event %s!-----\n'
|
||||
@ -338,7 +348,9 @@ def autoPyLoT(inputfile):
|
||||
************************************'''.format(version=_getVersionString())
|
||||
print(endsp)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
from pylot.core.util.defaults import AUTOMATIC_DEFAULTS
|
||||
# parse arguments
|
||||
parser = argparse.ArgumentParser(
|
||||
description='''autoPyLoT automatically picks phase onset times using higher order statistics,
|
||||
@ -348,8 +360,7 @@ if __name__ == "__main__":
|
||||
action='store',
|
||||
help='''full path to the file containing the input
|
||||
parameters for autoPyLoT''',
|
||||
default=os.path.join(os.path.expanduser('~'), '.pylot',
|
||||
'autoPyLoT.in')
|
||||
default=AUTOMATIC_DEFAULTS
|
||||
)
|
||||
parser.add_argument('-v', '-V', '--version', action='version',
|
||||
version='autoPyLoT ' + __version__,
|
||||
|
@ -1,2 +1,2 @@
|
||||
P
|
||||
S bandpass 4 0.5 5.0
|
||||
P bandpass 4 2.0 20.0
|
||||
S bandpass 4 2.0 15.0
|
@ -1,5 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
# encoding: utf-8
|
||||
from __future__ import print_function
|
||||
|
||||
"""
|
||||
makePyLoT -- build and install PyLoT
|
||||
|
||||
@ -123,7 +125,7 @@ USAGE
|
||||
except KeyboardInterrupt:
|
||||
cleanUp(verbose)
|
||||
return 0
|
||||
except Exception, e:
|
||||
except Exception as e:
|
||||
if DEBUG or TESTRUN:
|
||||
raise e
|
||||
indent = len(program_name) * " "
|
||||
@ -139,7 +141,7 @@ def buildPyLoT(verbosity=None):
|
||||
"\n"
|
||||
" Current working directory: {1}\n"
|
||||
).format(system, os.getcwd())
|
||||
print msg
|
||||
print(msg)
|
||||
if system.startswith(('win', 'microsoft')):
|
||||
raise CLIError(
|
||||
"building on Windows system not tested yet; implementation pending")
|
||||
|
@ -1 +1 @@
|
||||
a31e-dirty
|
||||
1508-dirty
|
||||
|
@ -4,6 +4,7 @@ import numpy as np
|
||||
from pylot.core.active import seismicshot
|
||||
from pylot.core.active.surveyUtils import cleanUp
|
||||
|
||||
|
||||
class Survey(object):
|
||||
def __init__(self, path, sourcefile, receiverfile, useDefaultParas=False):
|
||||
'''
|
||||
@ -70,7 +71,8 @@ class Survey(object):
|
||||
Removes traces that do not exist in the dataset for any reason.
|
||||
'''
|
||||
filename = 'updateShots.out'
|
||||
count = 0; countTraces = 0
|
||||
count = 0;
|
||||
countTraces = 0
|
||||
for shot in self.data.values():
|
||||
del_traceIDs = shot.updateTraceList()
|
||||
if len(del_traceIDs) > 0:
|
||||
@ -135,7 +137,10 @@ class Survey(object):
|
||||
|
||||
def plotDiffs(self):
|
||||
import matplotlib.pyplot as plt
|
||||
diffs = []; dists = []; mpicks = []; picks = []
|
||||
diffs = [];
|
||||
dists = [];
|
||||
mpicks = [];
|
||||
picks = []
|
||||
diffsDic = self.getDiffsFromManual()
|
||||
for shot in self.data.values():
|
||||
for traceID in shot.getTraceIDlist():
|
||||
@ -181,10 +186,12 @@ class Survey(object):
|
||||
'''
|
||||
from datetime import datetime
|
||||
starttime = datetime.now()
|
||||
count = 0; tpicksum = starttime - starttime
|
||||
count = 0;
|
||||
tpicksum = starttime - starttime
|
||||
|
||||
for shot in self.data.values():
|
||||
tstartpick = datetime.now(); count += 1
|
||||
tstartpick = datetime.now();
|
||||
count += 1
|
||||
for traceID in shot.getTraceIDlist():
|
||||
distance = shot.getDistance(traceID) # receive distance
|
||||
|
||||
@ -211,7 +218,8 @@ class Survey(object):
|
||||
if shot.getSNR(traceID)[0] > 1:
|
||||
shot.setEarllatepick(traceID)
|
||||
|
||||
tpicksum += (datetime.now() - tstartpick); tpick = tpicksum/count
|
||||
tpicksum += (datetime.now() - tstartpick);
|
||||
tpick = tpicksum / count
|
||||
tremain = (tpick * (len(self.getShotDict()) - count))
|
||||
tend = datetime.now() + tremain
|
||||
progress = float(count) / float(len(self.getShotDict())) * 100
|
||||
@ -339,7 +347,9 @@ class Survey(object):
|
||||
|
||||
count = 0
|
||||
fmtomo_factor = 1000 # transforming [m/s] -> [km/s]
|
||||
LatAll = []; LonAll = []; DepthAll = []
|
||||
LatAll = [];
|
||||
LonAll = [];
|
||||
DepthAll = []
|
||||
srcfile = open(directory + '/' + sourcefile, 'w')
|
||||
srcfile.writelines('%10s\n' % len(self.data)) # number of sources
|
||||
for shotnumber in self.getShotlist():
|
||||
@ -347,7 +357,9 @@ class Survey(object):
|
||||
ttfilename = str(shotnumber) + ttFileExtension
|
||||
(x, y, z) = shot.getSrcLoc() # getSrcLoc returns (x, y, z)
|
||||
srcfile.writelines('%10s %10s %10s\n' % (getAngle(y), getAngle(x), (-1) * z)) # lat, lon, depth
|
||||
LatAll.append(getAngle(y)); LonAll.append(getAngle(x)); DepthAll.append((-1)*z)
|
||||
LatAll.append(getAngle(y));
|
||||
LonAll.append(getAngle(x));
|
||||
DepthAll.append((-1) * z)
|
||||
srcfile.writelines('%10s\n' % 1) #
|
||||
srcfile.writelines('%10s %10s %10s\n' % (1, 1, ttfilename))
|
||||
ttfile = open(directory + '/' + ttfilename, 'w')
|
||||
@ -360,7 +372,9 @@ class Survey(object):
|
||||
delta = shot.getSymmetricPickError(traceID) * fmtomo_factor
|
||||
(x, y, z) = shot.getRecLoc(traceID)
|
||||
ttfile.writelines('%20s %20s %20s %10s %10s\n' % (getAngle(y), getAngle(x), (-1) * z, pick, delta))
|
||||
LatAll.append(getAngle(y)); LonAll.append(getAngle(x)); DepthAll.append((-1)*z)
|
||||
LatAll.append(getAngle(y));
|
||||
LonAll.append(getAngle(x));
|
||||
DepthAll.append((-1) * z)
|
||||
count += 1
|
||||
ttfile.close()
|
||||
srcfile.close()
|
||||
|
@ -2,6 +2,7 @@
|
||||
import sys
|
||||
import numpy as np
|
||||
|
||||
|
||||
def vgrids2VTK(inputfile='vgrids.in', outputfile='vgrids.vtk', absOrRel='abs', inputfileref='vgridsref.in'):
|
||||
'''
|
||||
Generate a vtk-file readable by e.g. paraview from FMTOMO output vgrids.in
|
||||
@ -19,7 +20,9 @@ def vgrids2VTK(inputfile = 'vgrids.in', outputfile = 'vgrids.vtk', absOrRel = 'a
|
||||
|
||||
nPoints = nR * nTheta * nPhi
|
||||
|
||||
nX = nPhi; nY = nTheta; nZ = nR
|
||||
nX = nPhi;
|
||||
nY = nTheta;
|
||||
nZ = nR
|
||||
|
||||
sZ = sR - R
|
||||
sX = _getDistance(sPhi)
|
||||
@ -42,9 +45,13 @@ def vgrids2VTK(inputfile = 'vgrids.in', outputfile = 'vgrids.vtk', absOrRel = 'a
|
||||
|
||||
outfile.writelines('POINT_DATA %15d\n' % (nPoints))
|
||||
if absOrRel == 'abs':
|
||||
<<<<<<< HEAD
|
||||
outfile.writelines('SCALARS velocity float %d\n' %(1))
|
||||
if absOrRel == 'relDepth':
|
||||
outfile.writelines('SCALARS velocity2depthMean float %d\n' %(1))
|
||||
=======
|
||||
outfile.writelines('SCALARS velocity float %d\n' % (1))
|
||||
>>>>>>> 37f9292c39246b327d3630995ca2521725c6cdd7
|
||||
elif absOrRel == 'rel':
|
||||
outfile.writelines('SCALARS velChangePercent float %d\n' % (1))
|
||||
outfile.writelines('LOOKUP_TABLE default\n')
|
||||
@ -55,6 +62,7 @@ def vgrids2VTK(inputfile = 'vgrids.in', outputfile = 'vgrids.vtk', absOrRel = 'a
|
||||
if absOrRel == 'abs':
|
||||
print("Writing velocity values to VTK file...")
|
||||
for velocity in vel:
|
||||
<<<<<<< HEAD
|
||||
outfile.writelines('%10f\n' %velocity)
|
||||
elif absOrRel == 'relDepth':
|
||||
print("Writing velocity values to VTK file relative to mean of each depth...")
|
||||
@ -69,6 +77,9 @@ def vgrids2VTK(inputfile = 'vgrids.in', outputfile = 'vgrids.vtk', absOrRel = 'a
|
||||
for vel in veldepth:
|
||||
outfile.writelines('%10f\n' %(vel - velmean))
|
||||
veldepth = []
|
||||
=======
|
||||
outfile.writelines('%10f\n' % velocity)
|
||||
>>>>>>> 37f9292c39246b327d3630995ca2521725c6cdd7
|
||||
elif absOrRel == 'rel':
|
||||
nref, dref, sref, velref = _readVgrid(inputfileref)
|
||||
nR_ref, nTheta_ref, nPhi_ref = nref
|
||||
@ -96,6 +107,7 @@ def vgrids2VTK(inputfile = 'vgrids.in', outputfile = 'vgrids.vtk', absOrRel = 'a
|
||||
print("Wrote velocity grid for %d points to file: %s" % (nPoints, outputfile))
|
||||
return
|
||||
|
||||
|
||||
def rays2VTK(fnin, fdirout='./vtk_files/', nthPoint=50):
|
||||
'''
|
||||
Writes VTK file(s) for FMTOMO rays from rays.dat
|
||||
@ -127,7 +139,8 @@ def rays2VTK(fnin, fdirout = './vtk_files/', nthPoint = 50):
|
||||
for index in range(nRayPoints):
|
||||
if index % nthPoint is 0 or index == (nRayPoints - 1):
|
||||
rad, lat, lon = infile.readline().split()
|
||||
rays[shotnumber][raynumber].append([_getDistance(np.rad2deg(float(lon))), _getDistance(np.rad2deg(float(lat))), float(rad) - R])
|
||||
rays[shotnumber][raynumber].append(
|
||||
[_getDistance(np.rad2deg(float(lon))), _getDistance(np.rad2deg(float(lat))), float(rad) - R])
|
||||
else:
|
||||
dummy = infile.readline()
|
||||
|
||||
@ -169,6 +182,7 @@ def rays2VTK(fnin, fdirout = './vtk_files/', nthPoint = 50):
|
||||
count += 1
|
||||
outfile.writelines('\n')
|
||||
|
||||
|
||||
def _readVgrid(filename):
|
||||
def readNumberOfPoints(filename):
|
||||
fin = open(filename, 'r')
|
||||
@ -209,7 +223,8 @@ def _readVgrid(filename):
|
||||
'''
|
||||
Reads in velocity from vgrids file and returns a list containing all values in the same order
|
||||
'''
|
||||
vel = []; count = 0
|
||||
vel = [];
|
||||
count = 0
|
||||
fin = open(filename, 'r')
|
||||
vglines = fin.readlines()
|
||||
|
||||
@ -235,6 +250,7 @@ def _readVgrid(filename):
|
||||
start = (sR, sTheta, sPhi)
|
||||
return number, delta, start, vel
|
||||
|
||||
|
||||
def _generateGrids(number, delta, start):
|
||||
nR, nTheta, nPhi = number
|
||||
dR, dTheta, dPhi = delta
|
||||
@ -250,6 +266,7 @@ def _generateGrids(number, delta, start):
|
||||
|
||||
return (thetaGrid, phiGrid, rGrid)
|
||||
|
||||
|
||||
def addCheckerboard(spacing=10., pertubation=0.1, inputfile='vgrids.in',
|
||||
outputfile='vgrids_cb.in', ampmethod='linear', rect=(None, None)):
|
||||
'''
|
||||
@ -261,6 +278,7 @@ def addCheckerboard(spacing = 10., pertubation = 0.1, inputfile = 'vgrids.in',
|
||||
:param: pertubation, pertubation (default: 0.1 = 10%)
|
||||
type: float
|
||||
'''
|
||||
|
||||
def correctSpacing(spacing, delta, disttype=None):
|
||||
if spacing > delta:
|
||||
spacing_corr = round(spacing / delta) * delta
|
||||
@ -315,7 +333,8 @@ def addCheckerboard(spacing = 10., pertubation = 0.1, inputfile = 'vgrids.in',
|
||||
|
||||
count = 0
|
||||
evenOdd = 1
|
||||
even = 0; odd = 0
|
||||
even = 0;
|
||||
odd = 0
|
||||
|
||||
# In the following loop it is checked whether the positive distance from the border of the model
|
||||
# for a point on the grid divided by the spacing is even or odd and then pertubated.
|
||||
@ -361,6 +380,7 @@ def addCheckerboard(spacing = 10., pertubation = 0.1, inputfile = 'vgrids.in',
|
||||
'Outputfile: %s.' % (inputfile, spacing, pertubation * 100, outputfile))
|
||||
outfile.close()
|
||||
|
||||
|
||||
def addBox(x=(None, None), y=(None, None), z=(None, None),
|
||||
boxvelocity=1.0, inputfile='vgrids.in',
|
||||
outputfile='vgrids_box.in'):
|
||||
@ -440,10 +460,12 @@ def addBox(x = (None, None), y = (None, None), z = (None, None),
|
||||
'Outputfile: %s.' % (inputfile, outputfile))
|
||||
outfile.close()
|
||||
|
||||
|
||||
def _update_progress(progress):
|
||||
sys.stdout.write("%d%% done \r" % (progress))
|
||||
sys.stdout.flush()
|
||||
|
||||
|
||||
def _getAngle(distance):
|
||||
'''
|
||||
Function returns the angle on a Sphere of the radius R = 6371 [km] for a distance [km].
|
||||
@ -453,9 +475,9 @@ def _getAngle(distance):
|
||||
angle = distance * 180. / (PI * R)
|
||||
return angle
|
||||
|
||||
|
||||
def _getDistance(angle):
|
||||
PI = np.pi
|
||||
R = 6371.
|
||||
distance = angle / 180 * (PI * R)
|
||||
return distance
|
||||
|
||||
|
@ -3,6 +3,7 @@ import sys
|
||||
import numpy as np
|
||||
from scipy.interpolate import griddata
|
||||
|
||||
|
||||
class SeisArray(object):
|
||||
'''
|
||||
Can be used to interpolate missing values of a receiver grid, if only support points were measured.
|
||||
@ -15,6 +16,7 @@ class SeisArray(object):
|
||||
Supports vtk output for sources and receivers.
|
||||
Note: Source and Receiver files for FMTOMO will be generated by the Survey object (because traveltimes will be added directly).
|
||||
'''
|
||||
|
||||
def __init__(self, recfile):
|
||||
self.recfile = recfile
|
||||
self._receiverlines = {}
|
||||
@ -151,7 +153,8 @@ class SeisArray(object):
|
||||
Returns the mean distance between two traceID's depending on the number of geophones in between
|
||||
'''
|
||||
num_spaces = abs(self._getGeophoneNumber(traceID1) - self._getGeophoneNumber(traceID2))
|
||||
mean_distance = abs(self._getReceiverValue(traceID1, coordinate) - self._getReceiverValue(traceID2, coordinate))/num_spaces
|
||||
mean_distance = abs(
|
||||
self._getReceiverValue(traceID1, coordinate) - self._getReceiverValue(traceID2, coordinate)) / num_spaces
|
||||
return mean_distance
|
||||
|
||||
def interpolateValues(self, coordinate):
|
||||
@ -214,7 +217,8 @@ class SeisArray(object):
|
||||
|
||||
for traceID in self.getReceiverCoordinates().keys():
|
||||
if type(self.getReceiverCoordinates()[traceID]) is not tuple:
|
||||
z = griddata((measured_x, measured_y), measured_z, (self._getXreceiver(traceID), self._getYreceiver(traceID)), method = method)
|
||||
z = griddata((measured_x, measured_y), measured_z,
|
||||
(self._getXreceiver(traceID), self._getYreceiver(traceID)), method=method)
|
||||
self._setZvalue(traceID, float(z))
|
||||
|
||||
def _getAngle(self, distance):
|
||||
@ -239,7 +243,9 @@ class SeisArray(object):
|
||||
'''
|
||||
Returns a list of all measured receivers known to SeisArray.
|
||||
'''
|
||||
x = []; y = []; z = []
|
||||
x = [];
|
||||
y = [];
|
||||
z = []
|
||||
for traceID in self.getMeasuredReceivers().keys():
|
||||
x.append(self.getMeasuredReceivers()[traceID][0])
|
||||
y.append(self.getMeasuredReceivers()[traceID][1])
|
||||
@ -250,7 +256,9 @@ class SeisArray(object):
|
||||
'''
|
||||
Returns a list of all measured topography points known to the SeisArray.
|
||||
'''
|
||||
x = []; y = []; z = []
|
||||
x = [];
|
||||
y = [];
|
||||
z = []
|
||||
for pointID in self.getMeasuredTopo().keys():
|
||||
x.append(self.getMeasuredTopo()[pointID][0])
|
||||
y.append(self.getMeasuredTopo()[pointID][1])
|
||||
@ -261,7 +269,9 @@ class SeisArray(object):
|
||||
'''
|
||||
Returns a list of all measured source locations known to SeisArray.
|
||||
'''
|
||||
x = []; y = []; z = []
|
||||
x = [];
|
||||
y = [];
|
||||
z = []
|
||||
for pointID in self.getSourceLocations().keys():
|
||||
x.append(self.getSourceLocations()[pointID][0])
|
||||
y.append(self.getSourceLocations()[pointID][1])
|
||||
@ -285,7 +295,9 @@ class SeisArray(object):
|
||||
'''
|
||||
Returns a list of all receivers (measured and interpolated).
|
||||
'''
|
||||
x = []; y =[]; z = []
|
||||
x = [];
|
||||
y = [];
|
||||
z = []
|
||||
for traceID in self.getReceiverCoordinates().keys():
|
||||
x.append(self.getReceiverCoordinates()[traceID][0])
|
||||
y.append(self.getReceiverCoordinates()[traceID][1])
|
||||
@ -364,7 +376,8 @@ class SeisArray(object):
|
||||
thetaGrid = np.linspace(thetaS - deltaTheta, thetaN + deltaTheta, num=nTheta + 2) # +2 cushion nodes
|
||||
phiGrid = np.linspace(phiW - deltaPhi, phiE + deltaPhi, num=nPhi + 2) # +2 cushion nodes
|
||||
|
||||
nTotal = len(thetaGrid) * len(phiGrid); count = 0
|
||||
nTotal = len(thetaGrid) * len(phiGrid);
|
||||
count = 0
|
||||
for theta in thetaGrid:
|
||||
for phi in phiGrid:
|
||||
xval = self._getDistance(phi)
|
||||
@ -457,7 +470,6 @@ class SeisArray(object):
|
||||
|
||||
outfile.close()
|
||||
|
||||
|
||||
def generateInterfaces(self, nTheta, nPhi, depthmax, cushionfactor=0.1,
|
||||
outfilename='interfaces.in', method='linear',
|
||||
returnInterfaces=False):
|
||||
@ -641,7 +653,10 @@ class SeisArray(object):
|
||||
return nlayers
|
||||
|
||||
def readMygrid(filename):
|
||||
ztop = []; zbot = []; vtop = []; vbot = []
|
||||
ztop = [];
|
||||
zbot = [];
|
||||
vtop = [];
|
||||
vbot = []
|
||||
infile = open(filename, 'r')
|
||||
nlayers = readMygridNlayers(filename)
|
||||
|
||||
@ -696,7 +711,8 @@ class SeisArray(object):
|
||||
outfile.writelines('%10s %10s \n' % (1, 1))
|
||||
outfile.writelines('%10s %10s %10s\n' % (nR + 2, nTheta + 2, nPhi + 2))
|
||||
outfile.writelines('%10s %10s %10s\n' % (deltaR, np.deg2rad(deltaTheta), np.deg2rad(deltaPhi)))
|
||||
outfile.writelines('%10s %10s %10s\n' %(rbot - deltaR, np.deg2rad(thetaS - deltaTheta), np.deg2rad(phiW - deltaPhi)))
|
||||
outfile.writelines(
|
||||
'%10s %10s %10s\n' % (rbot - deltaR, np.deg2rad(thetaS - deltaTheta), np.deg2rad(phiW - deltaPhi)))
|
||||
|
||||
surface = self.interpolateTopography(nTheta, nPhi, thetaSN, phiWE, method=method)
|
||||
|
||||
@ -726,14 +742,18 @@ class SeisArray(object):
|
||||
else:
|
||||
for index in range(nlayers):
|
||||
if (ztop[index]) >= depth > (zbot[index]):
|
||||
vel = (depth - ztop[index]) / (zbot[index] - ztop[index]) * (vbot[index] - vtop[index]) + vtop[index]
|
||||
vel = (depth - ztop[index]) / (zbot[index] - ztop[index]) * (
|
||||
vbot[index] - vtop[index]) + vtop[index]
|
||||
break
|
||||
if not (ztop[index]) >= depth > (zbot[index]):
|
||||
print('ERROR in grid inputfile, could not find velocity for a z-value of %s in the inputfile'%(depth-topo))
|
||||
print(
|
||||
'ERROR in grid inputfile, could not find velocity for a z-value of %s in the inputfile' % (
|
||||
depth - topo))
|
||||
return
|
||||
count += 1
|
||||
if vel < 0:
|
||||
print('ERROR, vel <0; z, topo, zbot, vbot, vtop:', depth, topo, zbot[index], vbot[index], vtop[index])
|
||||
print(
|
||||
'ERROR, vel <0; z, topo, zbot, vbot, vtop:', depth, topo, zbot[index], vbot[index], vtop[index])
|
||||
outfile.writelines('%10s %10s\n' % (vel, decm))
|
||||
|
||||
progress = float(count) / float(nTotal) * 100
|
||||
@ -786,11 +806,11 @@ class SeisArray(object):
|
||||
plt.legend()
|
||||
if annotations == True:
|
||||
for traceID in self.getReceiverCoordinates().keys():
|
||||
ax.annotate((' ' + str(traceID)), xy = (self._getXreceiver(traceID), self._getYreceiver(traceID)), fontsize = 'x-small', color = 'k')
|
||||
ax.annotate((' ' + str(traceID)), xy=(self._getXreceiver(traceID), self._getYreceiver(traceID)),
|
||||
fontsize='x-small', color='k')
|
||||
for shotnumber in self.getSourceLocations().keys():
|
||||
ax.annotate((' ' + str(shotnumber)), xy = (self._getXshot(shotnumber), self._getYshot(shotnumber)), fontsize = 'x-small', color = 'b')
|
||||
|
||||
|
||||
ax.annotate((' ' + str(shotnumber)), xy=(self._getXshot(shotnumber), self._getYshot(shotnumber)),
|
||||
fontsize='x-small', color='b')
|
||||
|
||||
def plotArray3D(self, ax=None):
|
||||
import matplotlib.pyplot as plt
|
||||
@ -815,12 +835,13 @@ class SeisArray(object):
|
||||
ax.plot(xmr, ymr, zmr, 'ro', label='measured receivers')
|
||||
if len(xsc) > 0:
|
||||
ax.plot(xsc, ysc, zsc, 'b*', label='shot locations')
|
||||
ax.set_xlabel('X [m]'); ax.set_ylabel('Y [m]'); ax.set_zlabel('Z [m]')
|
||||
ax.set_xlabel('X [m]');
|
||||
ax.set_ylabel('Y [m]');
|
||||
ax.set_zlabel('Z [m]')
|
||||
ax.legend()
|
||||
|
||||
return ax
|
||||
|
||||
|
||||
def plotSurface3D(self, ax=None, step=0.5, method='linear', exag=False):
|
||||
from matplotlib import cm
|
||||
import matplotlib.pyplot as plt
|
||||
@ -853,7 +874,9 @@ class SeisArray(object):
|
||||
ax.set_zlim(-(max(x) - min(x) / 2), (max(x) - min(x) / 2))
|
||||
ax.set_aspect('equal')
|
||||
|
||||
ax.set_xlabel('X [m]'); ax.set_ylabel('Y [m]'); ax.set_zlabel('Z [m]')
|
||||
ax.set_xlabel('X [m]');
|
||||
ax.set_ylabel('Y [m]');
|
||||
ax.set_zlabel('Z [m]')
|
||||
ax.legend()
|
||||
|
||||
return ax
|
||||
@ -1005,7 +1028,6 @@ class SeisArray(object):
|
||||
print("Wrote %d sources to file: %s" % (nPoints, filename))
|
||||
return
|
||||
|
||||
|
||||
def saveSeisArray(self, filename='seisArray.pickle'):
|
||||
import cPickle
|
||||
outfile = open(filename, 'wb')
|
||||
|
@ -6,17 +6,20 @@ import numpy as np
|
||||
from obspy.core import read
|
||||
from obspy import Stream
|
||||
from obspy import Trace
|
||||
from pylot.core.pick.CharFuns import HOScf
|
||||
from pylot.core.pick.CharFuns import AICcf
|
||||
from pylot.core.pick.charfuns import HOScf
|
||||
from pylot.core.pick.charfuns import AICcf
|
||||
from pylot.core.pick.utils import getSNR
|
||||
from pylot.core.pick.utils import earllatepicker
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
plt.interactive('True')
|
||||
|
||||
|
||||
class SeismicShot(object):
|
||||
'''
|
||||
SuperClass for a seismic shot object.
|
||||
'''
|
||||
|
||||
def __init__(self, obsfile):
|
||||
'''
|
||||
Initialize seismic shot object giving an inputfile.
|
||||
@ -368,7 +371,8 @@ class SeismicShot(object):
|
||||
# threshold = folm * max(hoscflist[leftb : rightb]) # combination of local maximum and threshold
|
||||
|
||||
### TEST TEST
|
||||
threshold = folm * (max(hoscflist[leftb : rightb]) - min(hoscflist[leftb : rightb])) + min(hoscflist[leftb : rightb]) # combination of local maximum and threshold
|
||||
threshold = folm * (max(hoscflist[leftb: rightb]) - min(hoscflist[leftb: rightb])) + min(
|
||||
hoscflist[leftb: rightb]) # combination of local maximum and threshold
|
||||
### TEST TEST
|
||||
|
||||
m = leftb
|
||||
@ -446,7 +450,8 @@ class SeismicShot(object):
|
||||
return float(x), float(y), float(z)
|
||||
# return float(self.getSingleStream(traceID)[0].stats.seg2['SOURCE_LOCATION'])
|
||||
|
||||
def getTraceIDs4Dist(self, distance = 0, distancebin = (0, 0)): ########## nur fuer 2D benutzt, 'distance bins' ##########
|
||||
def getTraceIDs4Dist(self, distance=0,
|
||||
distancebin=(0, 0)): ########## nur fuer 2D benutzt, 'distance bins' ##########
|
||||
'''
|
||||
Returns the traceID(s) for a certain distance between source and receiver.
|
||||
Used for 2D Tomography. TO BE IMPROVED.
|
||||
@ -517,7 +522,6 @@ class SeismicShot(object):
|
||||
else:
|
||||
self.setManualPickFlag(traceID, 1)
|
||||
|
||||
|
||||
def setPick(self, traceID, pick): ########## siehe Kommentar ##########
|
||||
if not traceID in self.picks.keys():
|
||||
self.picks[traceID] = {}
|
||||
@ -587,7 +591,6 @@ class SeismicShot(object):
|
||||
|
||||
return distancearray
|
||||
|
||||
|
||||
def plot2dttc(self, ax=None): ########## 2D ##########
|
||||
'''
|
||||
Function to plot the traveltime curve for automated picks of a shot. 2d only! ATM: X DIRECTION!!
|
||||
@ -605,7 +608,8 @@ class SeismicShot(object):
|
||||
|
||||
# shotnumbers = [shotnumbers for (shotnumbers, shotnames) in sorted(zip(shotnumbers, shotnames))]
|
||||
plotarray = sorted(zip(self.getDistArray4ttcPlot(), picks))
|
||||
x = []; y = []
|
||||
x = [];
|
||||
y = []
|
||||
for point in plotarray:
|
||||
x.append(point[0])
|
||||
y.append(point[1])
|
||||
@ -632,7 +636,8 @@ class SeismicShot(object):
|
||||
ax = fig.add_subplot(111)
|
||||
|
||||
plotarray = sorted(zip(self.getDistArray4ttcPlot(), manualpicktimesarray))
|
||||
x = []; y = []
|
||||
x = [];
|
||||
y = []
|
||||
for point in plotarray:
|
||||
x.append(point[0])
|
||||
y.append(point[1])
|
||||
@ -669,7 +674,8 @@ class SeismicShot(object):
|
||||
|
||||
ax.plot([0, tnoise], [noiselevel, noiselevel], 'm', linewidth=lw, label='noise level')
|
||||
ax.plot([tnoise, pick], [noiselevel, noiselevel], 'g:', linewidth=lw, label='gap')
|
||||
ax.plot([tnoise + tgap, pick + tsignal], [noiselevel * snr, noiselevel * snr], 'b', linewidth = lw, label = 'signal level')
|
||||
ax.plot([tnoise + tgap, pick + tsignal], [noiselevel * snr, noiselevel * snr], 'b', linewidth=lw,
|
||||
label='signal level')
|
||||
ax.legend()
|
||||
ax.text(0.05, 0.9, 'SNR: %s' % snr, transform=ax.transAxes)
|
||||
|
||||
@ -868,9 +874,12 @@ class SeismicShot(object):
|
||||
from matplotlib import cm
|
||||
cmap = cm.jet
|
||||
|
||||
x = []; xcut = []
|
||||
y = []; ycut = []
|
||||
z = []; zcut = []
|
||||
x = [];
|
||||
xcut = []
|
||||
y = [];
|
||||
ycut = []
|
||||
z = [];
|
||||
zcut = []
|
||||
|
||||
for traceID in self.picks.keys():
|
||||
if self.getPickFlag(traceID) != 0:
|
||||
@ -895,7 +904,8 @@ class SeismicShot(object):
|
||||
ax = plt.axes()
|
||||
|
||||
count = 0
|
||||
ax.imshow(zgrid, extent = [min(x), max(x), min(y), max(y)], vmin = tmin, vmax = tmax, cmap = cmap, origin = 'lower', alpha = 0.85)
|
||||
ax.imshow(zgrid, extent=[min(x), max(x), min(y), max(y)], vmin=tmin, vmax=tmax, cmap=cmap, origin='lower',
|
||||
alpha=0.85)
|
||||
ax.text(0.5, 0.95, 'shot: %s' % self.getShotnumber(), transform=ax.transAxes
|
||||
, horizontalalignment='center')
|
||||
sc = ax.scatter(x, y, c=z, s=30, label='picked shots', vmin=tmin, vmax=tmax, cmap=cmap, linewidths=1.5)
|
||||
@ -928,5 +938,3 @@ class SeismicShot(object):
|
||||
fontsize='x-small', color='r')
|
||||
|
||||
plt.show()
|
||||
|
||||
|
||||
|
@ -2,8 +2,10 @@
|
||||
import matplotlib.pyplot as plt
|
||||
import math
|
||||
import numpy as np
|
||||
|
||||
plt.interactive(True)
|
||||
|
||||
|
||||
class regions(object):
|
||||
'''
|
||||
A class used for manual inspection and processing of all picks for the user.
|
||||
@ -179,7 +181,8 @@ class regions(object):
|
||||
self.drawLastPolyLine()
|
||||
x = self._polyx
|
||||
y = self._polyy
|
||||
self._polyx = []; self._polyy = []
|
||||
self._polyx = [];
|
||||
self._polyy = []
|
||||
|
||||
key = self.getKey()
|
||||
self.markPolygon(x, y, key=key)
|
||||
@ -279,8 +282,10 @@ class regions(object):
|
||||
angle = 0
|
||||
epsilon = 1e-07
|
||||
for index in range(len(x)):
|
||||
xval1 = x[index - 1]; yval1 = y[index - 1]
|
||||
xval2 = x[index]; yval2 = y[index]
|
||||
xval1 = x[index - 1];
|
||||
yval1 = y[index - 1]
|
||||
xval2 = x[index];
|
||||
yval2 = y[index]
|
||||
angle += getangle([xval1 - pickX, yval1 - pickY], [xval2 - pickX, yval2 - pickY])
|
||||
if 360 - epsilon <= angle <= 360 + epsilon: ### IMPROVE THAT??
|
||||
return True
|
||||
@ -289,9 +294,12 @@ class regions(object):
|
||||
self.printOutput('No polygon defined.')
|
||||
return
|
||||
|
||||
shots_found = {}; numtraces = 0
|
||||
x0 = min(x); x1 = max(x)
|
||||
y0 = min(y); y1 = max(y)
|
||||
shots_found = {};
|
||||
numtraces = 0
|
||||
x0 = min(x);
|
||||
x1 = max(x)
|
||||
y0 = min(y);
|
||||
y1 = max(y)
|
||||
|
||||
shots, numtracesrect = self.findTracesInShotDict((x0, x1), (y0, y1), highlight=False)
|
||||
for shotnumber in shots.keys():
|
||||
@ -315,9 +323,12 @@ class regions(object):
|
||||
'''
|
||||
Returns traces corresponding to a certain area in the plot with all picks over the distances.
|
||||
'''
|
||||
shots_found = {}; numtraces = 0
|
||||
if picks == 'normal': pickflag = 0
|
||||
elif picks == 'includeCutOut': pickflag = None
|
||||
shots_found = {};
|
||||
numtraces = 0
|
||||
if picks == 'normal':
|
||||
pickflag = 0
|
||||
elif picks == 'includeCutOut':
|
||||
pickflag = None
|
||||
|
||||
for line in self._allpicks:
|
||||
dist, pick, shotnumber, traceID, flag = line
|
||||
@ -344,9 +355,11 @@ class regions(object):
|
||||
if shot.getPickFlag(traceID) is 0:
|
||||
return
|
||||
|
||||
self.ax.scatter(shot.getDistance(traceID), shot.getPick(traceID), s = 50, marker = 'o', facecolors = 'none', edgecolors = 'm', alpha = 1)
|
||||
self.ax.scatter(shot.getDistance(traceID), shot.getPick(traceID), s=50, marker='o', facecolors='none',
|
||||
edgecolors='m', alpha=1)
|
||||
if annotations == True:
|
||||
self.ax.annotate(s='s%s|t%s' % (shot.getShotnumber(), traceID), xy=(shot.getDistance(traceID), shot.getPick(traceID)), fontsize='xx-small')
|
||||
self.ax.annotate(s='s%s|t%s' % (shot.getShotnumber(), traceID),
|
||||
xy=(shot.getDistance(traceID), shot.getPick(traceID)), fontsize='xx-small')
|
||||
|
||||
def highlightAllActiveRegions(self):
|
||||
'''
|
||||
@ -382,7 +395,8 @@ class regions(object):
|
||||
for traceID in self.shots_found[key]['shots'][shotnumber]:
|
||||
count += 1
|
||||
if count > maxfigures:
|
||||
print 'Maximum number of figures (%s) reached. %sth figure was not opened.' %(maxfigures, count)
|
||||
print 'Maximum number of figures (%s) reached. %sth figure was not opened.' % (
|
||||
maxfigures, count)
|
||||
break
|
||||
shot.plot_traces(traceID)
|
||||
else:
|
||||
@ -420,7 +434,6 @@ class regions(object):
|
||||
self.markPolygon(self.shots_found[key]['xvalues'],
|
||||
self.shots_found[key]['yvalues'], key=key)
|
||||
|
||||
|
||||
def markRectangle(self, (x0, x1), (y0, y1), key=None, color='grey', alpha=0.1, linewidth=1):
|
||||
'''
|
||||
Mark a rectangular region on the axes.
|
||||
|
@ -1,6 +1,13 @@
|
||||
import numpy as np
|
||||
from __future__ import print_function
|
||||
|
||||
|
||||
def readParameters(parfile, parameter):
|
||||
"""
|
||||
|
||||
:param parfile:
|
||||
:param parameter:
|
||||
:return:
|
||||
"""
|
||||
from ConfigParser import ConfigParser
|
||||
parameterConfig = ConfigParser()
|
||||
parameterConfig.read('parfile')
|
||||
@ -9,14 +16,29 @@ def readParameters(parfile, parameter):
|
||||
|
||||
return value
|
||||
|
||||
|
||||
def setArtificialPick(shot_dict, traceID, pick):
|
||||
"""
|
||||
|
||||
:param shot_dict:
|
||||
:param traceID:
|
||||
:param pick:
|
||||
:return:
|
||||
"""
|
||||
for shot in shot_dict.values():
|
||||
shot.setPick(traceID, pick)
|
||||
shot.setPickwindow(traceID, shot.getCut())
|
||||
|
||||
|
||||
def fitSNR4dist(shot_dict, shiftdist=30, shiftSNR=100):
|
||||
"""
|
||||
|
||||
:param shot_dict:
|
||||
:param shiftdist:
|
||||
:param shiftSNR:
|
||||
:return:
|
||||
"""
|
||||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
dists = []
|
||||
picks = []
|
||||
snrs = []
|
||||
@ -41,6 +63,14 @@ def fitSNR4dist(shot_dict, shiftdist = 30, shiftSNR = 100):
|
||||
|
||||
|
||||
def plotFittedSNR(dists, snrthresholds, snrs, snrBestFit):
|
||||
"""
|
||||
|
||||
:param dists:
|
||||
:param snrthresholds:
|
||||
:param snrs:
|
||||
:param snrBestFit:
|
||||
:return:
|
||||
"""
|
||||
import matplotlib.pyplot as plt
|
||||
plt.interactive(True)
|
||||
fig = plt.figure()
|
||||
@ -54,7 +84,22 @@ def plotFittedSNR(dists, snrthresholds, snrs, snrBestFit):
|
||||
plt.ylabel('SNR')
|
||||
plt.legend()
|
||||
|
||||
|
||||
def setDynamicFittedSNR(shot_dict, shiftdist=30, shiftSNR=100, p1=0.004, p2=-0.0007):
|
||||
"""
|
||||
|
||||
:param shot_dict:
|
||||
:type shot_dict: dict
|
||||
:param shiftdist:
|
||||
:type shiftdist: int
|
||||
:param shiftSNR:
|
||||
:type shiftSNR: int
|
||||
:param p1:
|
||||
:type p1: float
|
||||
:param p2:
|
||||
:type p2: float
|
||||
:return:
|
||||
"""
|
||||
import numpy as np
|
||||
minSNR = 2.5
|
||||
# fit_fn = fitSNR4dist(shot_dict)
|
||||
@ -69,14 +114,21 @@ def setDynamicFittedSNR(shot_dict, shiftdist = 30, shiftSNR = 100, p1 = 0.004, p
|
||||
shot.setSNRthreshold(traceID, minSNR)
|
||||
else:
|
||||
shot.setSNRthreshold(traceID, snrthreshold)
|
||||
print "setDynamicFittedSNR: Finished setting of fitted SNR-threshold"
|
||||
print("setDynamicFittedSNR: Finished setting of fitted SNR-threshold")
|
||||
|
||||
|
||||
def setConstantSNR(shot_dict, snrthreshold=2.5):
|
||||
import numpy as np
|
||||
"""
|
||||
|
||||
:param shot_dict:
|
||||
:param snrthreshold:
|
||||
:return:
|
||||
"""
|
||||
for shot in shot_dict.values():
|
||||
for traceID in shot.getTraceIDlist():
|
||||
shot.setSNRthreshold(traceID, snrthreshold)
|
||||
print "setConstantSNR: Finished setting of SNR threshold to a constant value of %s"%snrthreshold
|
||||
print("setConstantSNR: Finished setting of SNR threshold to a constant value of %s" % snrthreshold)
|
||||
|
||||
|
||||
def findTracesInRanges(shot_dict, distancebin, pickbin):
|
||||
'''
|
||||
@ -103,11 +155,17 @@ def findTracesInRanges(shot_dict, distancebin, pickbin):
|
||||
|
||||
return shots_found
|
||||
|
||||
def cleanUp(survey):
|
||||
|
||||
def cleanUp(survey):
|
||||
"""
|
||||
|
||||
:param survey:
|
||||
:return:
|
||||
"""
|
||||
for shot in survey.data.values():
|
||||
shot.traces4plot = {}
|
||||
|
||||
|
||||
# def plotScatterStats(survey, key, ax = None):
|
||||
# import matplotlib.pyplot as plt
|
||||
# x = []; y = []; value = []
|
||||
@ -131,14 +189,19 @@ def cleanUp(survey):
|
||||
# cbar.set_label(key)
|
||||
|
||||
def plotScatterStats4Shots(survey, key):
|
||||
'''
|
||||
"""
|
||||
Statistics, scatter plot.
|
||||
key can be 'mean SNR', 'median SNR', 'mean SPE', 'median SPE', or 'picked traces'
|
||||
'''
|
||||
:param survey:
|
||||
:param key:
|
||||
:return:
|
||||
"""
|
||||
import matplotlib.pyplot as plt
|
||||
import numpy as np
|
||||
statsShot = {}
|
||||
x = []; y = []; value = []
|
||||
x = []
|
||||
y = []
|
||||
value = []
|
||||
for shot in survey.data.values():
|
||||
for traceID in shot.getTraceIDlist():
|
||||
if not shot in statsShot.keys():
|
||||
@ -182,15 +245,21 @@ def plotScatterStats4Shots(survey, key):
|
||||
ax.annotate(' %s' % shot.getShotnumber(), xy=(shot.getSrcLoc()[0], shot.getSrcLoc()[1]),
|
||||
fontsize='x-small', color='k')
|
||||
|
||||
|
||||
def plotScatterStats4Receivers(survey, key):
|
||||
'''
|
||||
"""
|
||||
Statistics, scatter plot.
|
||||
key can be 'mean SNR', 'median SNR', 'mean SPE', 'median SPE', or 'picked traces'
|
||||
'''
|
||||
:param survey:
|
||||
:param key:
|
||||
:return:
|
||||
"""
|
||||
import matplotlib.pyplot as plt
|
||||
import numpy as np
|
||||
statsRec = {}
|
||||
x = []; y = []; value = []
|
||||
x = []
|
||||
y = []
|
||||
value = []
|
||||
for shot in survey.data.values():
|
||||
for traceID in shot.getTraceIDlist():
|
||||
if not traceID in statsRec.keys():
|
||||
@ -205,7 +274,6 @@ def plotScatterStats4Receivers(survey, key):
|
||||
statsRec[traceID]['picked traces'] += 1
|
||||
statsRec[traceID]['SPE'].append(shot.getSymmetricPickError(traceID))
|
||||
|
||||
|
||||
for traceID in statsRec.keys():
|
||||
statsRec[traceID]['mean SNR'] = np.mean(statsRec[traceID]['SNR'])
|
||||
statsRec[traceID]['median SNR'] = np.median(statsRec[traceID]['SNR'])
|
||||
|
@ -5,9 +5,7 @@ from obspy.core import read
|
||||
from obspy.signal.trigger import coincidenceTrigger
|
||||
|
||||
|
||||
|
||||
class CoincidenceTimes(object):
|
||||
|
||||
def __init__(self, st, comp='Z', coinum=4, sta=1., lta=10., on=5., off=1.):
|
||||
_type = 'recstalta'
|
||||
self.coinclist = self.createCoincTriggerlist(data=st, trigcomp=comp,
|
||||
|
@ -6,11 +6,15 @@ import numpy as np
|
||||
|
||||
def crosscorrsingle(wf1, wf2, taumax):
|
||||
'''
|
||||
|
||||
:param Wx:
|
||||
:param Wy:
|
||||
:param taumax:
|
||||
:return:
|
||||
Calculates the crosscorrelation between two waveforms with a defined maximum timedifference.
|
||||
:param wf1: first waveformdata
|
||||
:type wf1: list
|
||||
:param wf2: second waveformdata
|
||||
:type wf2: list
|
||||
:param taumax: maximum time difference between waveforms
|
||||
:type taumax: positive integer
|
||||
:return: returns the crosscorrelation funktion 'c' and the lagvector 'l'
|
||||
:rtype: c and l are lists
|
||||
'''
|
||||
N = len(wf1)
|
||||
c = np.zeros(2 * taumax - 1)
|
||||
@ -83,10 +87,13 @@ def wfscrosscorr(weights, wfs, taumax):
|
||||
|
||||
SWB 26.01.2010 as arranged with Thomas Meier and Monika Bischoff
|
||||
|
||||
:param weights:
|
||||
:param wfs:
|
||||
:param taumax:
|
||||
:return:
|
||||
:param weights: weighting factors for the single components
|
||||
:type weights: tuple
|
||||
:param wfs: tuple of `~numpy.array` object containing waveform data
|
||||
:type wfs: tuple
|
||||
:param taumax: maximum time difference
|
||||
:type taumax: positive integer
|
||||
:return: returns cross correlation function normalized by the waveform energy
|
||||
'''
|
||||
|
||||
ccnorm = 0.
|
||||
|
@ -15,6 +15,7 @@ from scipy.optimize import curve_fit
|
||||
from scipy import integrate, signal
|
||||
from pylot.core.read.data import Data
|
||||
|
||||
|
||||
class Magnitude(object):
|
||||
'''
|
||||
Superclass for calculating Wood-Anderson peak-to-peak
|
||||
@ -72,7 +73,6 @@ class Magnitude(object):
|
||||
self.calcsourcespec()
|
||||
self.run_calcMoMw()
|
||||
|
||||
|
||||
def getwfstream(self):
|
||||
return self.wfstream
|
||||
|
||||
@ -154,6 +154,7 @@ class Magnitude(object):
|
||||
def run_calcMoMw(self):
|
||||
self.pickdic = None
|
||||
|
||||
|
||||
class WApp(Magnitude):
|
||||
'''
|
||||
Method to derive peak-to-peak amplitude as seen on a Wood-Anderson-
|
||||
@ -261,6 +262,7 @@ class M0Mw(Magnitude):
|
||||
picks[key]['P']['Mw'] = Mw
|
||||
self.picdic = picks
|
||||
|
||||
|
||||
def calcMoMw(wfstream, w0, rho, vp, delta, inv):
|
||||
'''
|
||||
Subfunction of run_calcMoMw to calculate individual
|
||||
@ -302,7 +304,6 @@ def calcMoMw(wfstream, w0, rho, vp, delta, inv):
|
||||
return Mo, Mw
|
||||
|
||||
|
||||
|
||||
def calcsourcespec(wfstream, onset, inventory, vp, delta, azimuth, incidence, Qp, iplot):
|
||||
'''
|
||||
Subfunction to calculate the source spectrum and to derive from that the plateau
|
||||
@ -639,10 +640,3 @@ def fitSourceModel(f, S, fc0, iplot):
|
||||
plt.close()
|
||||
|
||||
return w0, fc
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -1,25 +1,31 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from obspy.signal.trigger import recSTALTA, triggerOnset
|
||||
from obspy.signal.trigger import recursive_sta_lta, trigger_onset
|
||||
|
||||
|
||||
def createSingleTriggerlist(st, station='ZV01', trigcomp='Z', stalta=(1, 10),
|
||||
trigonoff=(6, 1)):
|
||||
'''
|
||||
uses a single-station trigger to create a triggerlist for this station
|
||||
:param st:
|
||||
:param station:
|
||||
:param trigcomp:
|
||||
:param stalta:
|
||||
:param trigonoff:
|
||||
:return:
|
||||
:param st: obspy stream
|
||||
:type st:
|
||||
:param station: station name to get triggers for (optional, default = ZV01)
|
||||
:type station: str
|
||||
:param trigcomp: (optional, default = Z)
|
||||
:type trigcomp: str
|
||||
:param stalta: (optional, default = (1,10))
|
||||
:type stalta: tuple
|
||||
:param trigonoff: (optional, default = (6,1))
|
||||
:type trigonoff: tuple
|
||||
:return: list of triggtimes
|
||||
:rtype: list
|
||||
'''
|
||||
tr = st.copy().select(component=trigcomp, station=station)[0]
|
||||
df = tr.stats.sampling_rate
|
||||
|
||||
cft = recSTALTA(tr.data, int(stalta[0] * df), int(stalta[1] * df))
|
||||
triggers = triggerOnset(cft, trigonoff[0], trigonoff[1])
|
||||
cft = recursive_sta_lta(tr.data, int(stalta[0] * df), int(stalta[1] * df))
|
||||
triggers = trigger_onset(cft, trigonoff[0], trigonoff[1])
|
||||
trigg = []
|
||||
for time in triggers:
|
||||
trigg.append(tr.stats.starttime + time[0] / df)
|
||||
@ -32,7 +38,7 @@ def createSubCoincTriggerlist(trig, station='ZV01'):
|
||||
coincidence trigger and are seen at the demanded station
|
||||
:param trig: list containing triggers from coincidence trigger
|
||||
:type trig: list
|
||||
:param station: station name to get triggers for
|
||||
:param station: station name to get triggers for (optional, default = ZV01)
|
||||
:type station: str
|
||||
:return: list of triggertimes
|
||||
:rtype: list
|
||||
|
@ -3,13 +3,13 @@
|
||||
|
||||
import subprocess
|
||||
import os
|
||||
from obspy.core.event import readEvents
|
||||
from pylot.core.pick.utils import writephases
|
||||
from pylot.core.util.utils import getPatternLine
|
||||
from pylot.core.util.version import get_git_version as _getVersionString
|
||||
|
||||
__version__ = _getVersionString()
|
||||
|
||||
|
||||
def picksExport(picks, locrt, phasefile):
|
||||
'''
|
||||
Take <picks> dictionary and exports picking data to a NLLOC-obs
|
||||
@ -27,6 +27,7 @@ def picksExport(picks, locrt, phasefile):
|
||||
# write phases to NLLoc-phase file
|
||||
writephases(picks, locrt, phasefile)
|
||||
|
||||
|
||||
def modifyInputFile(ctrfn, root, nllocoutn, phasefn, tttn):
|
||||
'''
|
||||
:param ctrfn: name of NLLoc-control file
|
||||
@ -64,6 +65,7 @@ def modifyInputFile(ctrfn, root, nllocoutn, phasefn, tttn):
|
||||
nllfile.write(filedata)
|
||||
nllfile.close()
|
||||
|
||||
|
||||
def locate(call, fnin):
|
||||
'''
|
||||
Takes paths to NLLoc executable <call> and input parameter file <fnin>
|
||||
@ -79,8 +81,10 @@ def locate(call, fnin):
|
||||
# locate the event
|
||||
subprocess.call([call, fnin])
|
||||
|
||||
|
||||
def readLocation(fn):
|
||||
pass
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
pass
|
||||
|
@ -11,15 +11,17 @@ function conglomerate utils.
|
||||
|
||||
import matplotlib.pyplot as plt
|
||||
import numpy as np
|
||||
from scipy import integrate
|
||||
from pylot.core.pick.Picker import AICPicker, PragPicker
|
||||
from pylot.core.pick.CharFuns import HOScf, AICcf, ARZcf, ARHcf, AR3Ccf
|
||||
from pylot.core.read.inputs import AutoPickParameter
|
||||
from pylot.core.pick.picker import AICPicker, PragPicker
|
||||
from pylot.core.pick.charfuns import CharacteristicFunction
|
||||
from pylot.core.pick.charfuns import HOScf, AICcf, ARZcf, ARHcf, AR3Ccf
|
||||
from pylot.core.pick.utils import checksignallength, checkZ4S, earllatepicker, \
|
||||
getSNR, fmpicker, checkPonsets, wadaticheck
|
||||
from pylot.core.util.utils import getPatternLine
|
||||
from pylot.core.read.data import Data
|
||||
from pylot.core.analysis.magnitude import WApp
|
||||
|
||||
|
||||
def autopickevent(data, param):
|
||||
stations = []
|
||||
all_onsets = {}
|
||||
@ -46,14 +48,18 @@ def autopickevent(data, param):
|
||||
# check S-P times (Wadati)
|
||||
return wadaticheck(jk_checked_onsets, wdttolerance, iplot)
|
||||
|
||||
|
||||
def autopickstation(wfstream, pickparam, verbose=False):
|
||||
"""
|
||||
:param: wfstream
|
||||
:type: `~obspy.core.stream.Stream`
|
||||
:param wfstream: `~obspy.core.stream.Stream` containing waveform
|
||||
:type wfstream: obspy.core.stream.Stream
|
||||
|
||||
:param: pickparam
|
||||
:type: container of picking parameters from input file,
|
||||
:param pickparam: container of picking parameters from input file,
|
||||
usually autoPyLoT.in
|
||||
:type pickparam: AutoPickParameter
|
||||
:param verbose:
|
||||
:type verbose: bool
|
||||
|
||||
"""
|
||||
|
||||
# declaring pickparam variables (only for convenience)
|
||||
@ -138,6 +144,7 @@ def autopickstation(wfstream, pickparam, verbose=False):
|
||||
Sflag = 0
|
||||
Pmarker = []
|
||||
Ao = None # Wood-Anderson peak-to-peak amplitude
|
||||
picker = 'autoPyLoT' # name of the picking programm
|
||||
|
||||
# split components
|
||||
zdat = wfstream.select(component="Z")
|
||||
@ -175,6 +182,7 @@ def autopickstation(wfstream, pickparam, verbose=False):
|
||||
pstart = 0
|
||||
pstop = len(zdat[0].data) * zdat[0].stats.delta
|
||||
cuttimes = [pstart, pstop]
|
||||
cf1 = None
|
||||
if algoP == 'HOS':
|
||||
# calculate HOS-CF using subclass HOScf of class
|
||||
# CharacteristicFunction
|
||||
@ -188,6 +196,10 @@ def autopickstation(wfstream, pickparam, verbose=False):
|
||||
# calculate AIC-HOS-CF using subclass AICcf of class
|
||||
# CharacteristicFunction
|
||||
# class needs stream object => build it
|
||||
assert isinstance(cf1, CharacteristicFunction), 'cf2 is not set ' \
|
||||
'correctly: maybe the algorithm name ({algoP}) is ' \
|
||||
'corrupted'.format(
|
||||
algoP=algoP)
|
||||
tr_aic = tr_filt.copy()
|
||||
tr_aic.data = cf1.getCF()
|
||||
z_copy[0].data = tr_aic.data
|
||||
@ -249,8 +261,7 @@ def autopickstation(wfstream, pickparam, verbose=False):
|
||||
##############################################################
|
||||
# go on with processing if AIC onset passes quality control
|
||||
if (aicpick.getSlope() >= minAICPslope and
|
||||
aicpick.getSNR() >= minAICPSNR and
|
||||
Pflag == 1):
|
||||
aicpick.getSNR() >= minAICPSNR and Pflag == 1):
|
||||
aicPflag = 1
|
||||
msg = 'AIC P-pick passes quality control: Slope: {0} counts/s, ' \
|
||||
'SNR: {1}\nGo on with refined picking ...\n' \
|
||||
@ -270,6 +281,7 @@ def autopickstation(wfstream, pickparam, verbose=False):
|
||||
cuttimes2 = [round(max([aicpick.getpick() - Precalcwin, 0])),
|
||||
round(min([len(zdat[0].data) * zdat[0].stats.delta,
|
||||
aicpick.getpick() + Precalcwin]))]
|
||||
cf2 = None
|
||||
if algoP == 'HOS':
|
||||
# calculate HOS-CF using subclass HOScf of class
|
||||
# CharacteristicFunction
|
||||
@ -282,14 +294,18 @@ def autopickstation(wfstream, pickparam, verbose=False):
|
||||
addnoise) # instance of ARZcf
|
||||
##############################################################
|
||||
# get refined onset time from CF2 using class Picker
|
||||
assert isinstance(cf2, CharacteristicFunction), 'cf2 is not set ' \
|
||||
'correctly: maybe the algorithm name ({algoP}) is ' \
|
||||
'corrupted'.format(
|
||||
algoP=algoP)
|
||||
refPpick = PragPicker(cf2, tsnrz, pickwinP, iplot, ausP, tsmoothP,
|
||||
aicpick.getpick())
|
||||
mpickP = refPpick.getpick()
|
||||
#############################################################
|
||||
if mpickP is not None:
|
||||
# quality assessment
|
||||
# get earliest and latest possible pick and symmetrized uncertainty
|
||||
[lpickP, epickP, Perror] = earllatepicker(z_copy, nfacP, tsnrz,
|
||||
# get earliest/latest possible pick and symmetrized uncertainty
|
||||
[epickP, lpickP, Perror] = earllatepicker(z_copy, nfacP, tsnrz,
|
||||
mpickP, iplot)
|
||||
|
||||
# get SNR
|
||||
@ -473,13 +489,14 @@ def autopickstation(wfstream, pickparam, verbose=False):
|
||||
#############################################################
|
||||
if mpickS is not None:
|
||||
# quality assessment
|
||||
# get earliest and latest possible pick and symmetrized uncertainty
|
||||
# get earliest/latest possible pick and symmetrized uncertainty
|
||||
h_copy[0].data = trH1_filt.data
|
||||
[lpickS1, epickS1, Serror1] = earllatepicker(h_copy, nfacS,
|
||||
[epickS1, lpickS1, Serror1] = earllatepicker(h_copy, nfacS,
|
||||
tsnrh,
|
||||
mpickS, iplot)
|
||||
|
||||
h_copy[0].data = trH2_filt.data
|
||||
[lpickS2, epickS2, Serror2] = earllatepicker(h_copy, nfacS,
|
||||
[epickS2, lpickS2, Serror2] = earllatepicker(h_copy, nfacS,
|
||||
tsnrh,
|
||||
mpickS, iplot)
|
||||
if epickS1 is not None and epickS2 is not None:
|
||||
@ -488,28 +505,30 @@ def autopickstation(wfstream, pickparam, verbose=False):
|
||||
epick = [epickS1, epickS2]
|
||||
lpick = [lpickS1, lpickS2]
|
||||
pickerr = [Serror1, Serror2]
|
||||
if epickS1 == None and epickS2 is not None:
|
||||
if epickS1 is None and epickS2 is not None:
|
||||
ipick = 1
|
||||
elif epickS1 is not None and epickS2 == None:
|
||||
elif epickS1 is not None and epickS2 is None:
|
||||
ipick = 0
|
||||
elif epickS1 is not None and epickS2 is not None:
|
||||
ipick = np.argmin([epickS1, epickS2])
|
||||
elif algoS == 'AR3':
|
||||
[lpickS3, epickS3, Serror3] = earllatepicker(h_copy, nfacS,
|
||||
[epickS3, lpickS3, Serror3] = earllatepicker(h_copy,
|
||||
nfacS,
|
||||
tsnrh,
|
||||
mpickS, iplot)
|
||||
mpickS,
|
||||
iplot)
|
||||
# get earliest pick of all three picks
|
||||
epick = [epickS1, epickS2, epickS3]
|
||||
lpick = [lpickS1, lpickS2, lpickS3]
|
||||
pickerr = [Serror1, Serror2, Serror3]
|
||||
if epickS1 == None and epickS2 is not None \
|
||||
if epickS1 is None and epickS2 is not None \
|
||||
and epickS3 is not None:
|
||||
ipick = np.argmin([epickS2, epickS3])
|
||||
elif epickS1 is not None and epickS2 == None \
|
||||
elif epickS1 is not None and epickS2 is None \
|
||||
and epickS3 is not None:
|
||||
ipick = np.argmin([epickS2, epickS3])
|
||||
elif epickS1 is not None and epickS2 is not None \
|
||||
and epickS3 == None:
|
||||
and epickS3 is None:
|
||||
ipick = np.argmin([epickS1, epickS2])
|
||||
elif epickS1 is not None and epickS2 is not None \
|
||||
and epickS3 is not None:
|
||||
@ -538,7 +557,7 @@ def autopickstation(wfstream, pickparam, verbose=False):
|
||||
'SNR[dB]: {2}\n'
|
||||
'################################################'
|
||||
''.format(Sweight, SNRS, SNRSdB))
|
||||
##################################################################
|
||||
################################################################
|
||||
# get Wood-Anderson peak-to-peak amplitude
|
||||
# initialize Data object
|
||||
data = Data()
|
||||
@ -555,7 +574,7 @@ def autopickstation(wfstream, pickparam, verbose=False):
|
||||
else:
|
||||
# use larger window for getting peak-to-peak amplitude
|
||||
# as the S pick is quite unsure
|
||||
wapp = WApp(cordat, mpickP, mpickP + sstop + \
|
||||
wapp = WApp(cordat, mpickP, mpickP + sstop +
|
||||
(0.5 * (mpickP + sstop)), iplot)
|
||||
|
||||
Ao = wapp.getwapp()
|
||||
@ -585,7 +604,8 @@ def autopickstation(wfstream, pickparam, verbose=False):
|
||||
# calculate WA-peak-to-peak amplitude
|
||||
# using subclass WApp of superclass Magnitude
|
||||
wapp = WApp(cordat, mpickP, mpickP + sstop + (0.5 * (mpickP
|
||||
+ sstop)), iplot)
|
||||
+ sstop)),
|
||||
iplot)
|
||||
Ao = wapp.getwapp()
|
||||
|
||||
else:
|
||||
@ -754,46 +774,46 @@ def autopickstation(wfstream, pickparam, verbose=False):
|
||||
plt.close()
|
||||
##########################################################################
|
||||
# calculate "real" onset times
|
||||
if mpickP is not None and epickP is not None and mpickP is not None:
|
||||
if lpickP is not None and lpickP == mpickP:
|
||||
lpickP += timeerrorsP[0]
|
||||
if epickP is not None and epickP == mpickP:
|
||||
epickP -= timeerrorsP[0]
|
||||
if mpickP is not None and epickP is not None and lpickP is not None:
|
||||
lpickP = zdat[0].stats.starttime + lpickP
|
||||
epickP = zdat[0].stats.starttime + epickP
|
||||
mpickP = zdat[0].stats.starttime + mpickP
|
||||
else:
|
||||
# dummy values (start of seismic trace) in order to derive
|
||||
# theoretical onset times for iteratve picking
|
||||
lpickP = zdat[0].stats.starttime
|
||||
epickP = zdat[0].stats.starttime
|
||||
lpickP = zdat[0].stats.starttime + timeerrorsP[3]
|
||||
epickP = zdat[0].stats.starttime - timeerrorsP[3]
|
||||
mpickP = zdat[0].stats.starttime
|
||||
|
||||
if mpickS is not None and epickS is not None and mpickS is not None:
|
||||
if lpickS is not None and lpickS == mpickS:
|
||||
lpickS += timeerrorsS[0]
|
||||
if epickS is not None and epickS == mpickS:
|
||||
epickS -= timeerrorsS[0]
|
||||
if mpickS is not None and epickS is not None and lpickS is not None:
|
||||
lpickS = edat[0].stats.starttime + lpickS
|
||||
epickS = edat[0].stats.starttime + epickS
|
||||
mpickS = edat[0].stats.starttime + mpickS
|
||||
else:
|
||||
# dummy values (start of seismic trace) in order to derive
|
||||
# theoretical onset times for iteratve picking
|
||||
lpickS = edat[0].stats.starttime
|
||||
epickS = edat[0].stats.starttime
|
||||
lpickS = edat[0].stats.starttime + timeerrorsS[3]
|
||||
epickS = edat[0].stats.starttime - timeerrorsS[3]
|
||||
mpickS = edat[0].stats.starttime
|
||||
|
||||
# create dictionary
|
||||
# for P phase
|
||||
phase = 'P'
|
||||
phasepick = {'lpp': lpickP, 'epp': epickP, 'mpp': mpickP, 'spe': Perror,
|
||||
'snr': SNRP, 'snrdb': SNRPdB, 'weight': Pweight, 'fm': FM,
|
||||
'w0': None, 'fc': None, 'Mo': None, 'Mw': None}
|
||||
picks = {phase: phasepick}
|
||||
# add P marker
|
||||
picks[phase]['marked'] = Pmarker
|
||||
ppick = dict(lpp=lpickP, epp=epickP, mpp=mpickP, spe=Perror, snr=SNRP,
|
||||
snrdb=SNRPdB, weight=Pweight, fm=FM, w0=None, fc=None, Mo=None,
|
||||
Mw=None, picker=picker, marked=Pmarker)
|
||||
# add S phase
|
||||
phase = 'S'
|
||||
phasepick = {'lpp': lpickS, 'epp': epickS, 'mpp': mpickS, 'spe': Serror,
|
||||
'snr': SNRS, 'snrdb': SNRSdB, 'weight': Sweight, 'fm': None}
|
||||
picks[phase] = phasepick
|
||||
# add Wood-Anderson amplitude
|
||||
picks[phase]['Ao'] = Ao
|
||||
|
||||
|
||||
spick = dict(lpp=lpickS, epp=epickS, mpp=mpickS, spe=Serror, snr=SNRS,
|
||||
snrdb=SNRSdB, weight=Sweight, fm=None, picker=picker, Ao=Ao)
|
||||
# merge picks into returning dictionary
|
||||
picks = dict(P=ppick, S=spick)
|
||||
return picks
|
||||
|
||||
|
||||
@ -844,22 +864,31 @@ def iteratepicker(wf, NLLocfile, picks, badpicks, pickparameter):
|
||||
Precalcwin_old = pickparameter.getParam('Precalcwin')
|
||||
noisefactor_old = pickparameter.getParam('noisefactor')
|
||||
zfac_old = pickparameter.getParam('zfac')
|
||||
pickparameter.setParam(pstart=max([0, badpicks[i][1] - wf2pick[0].stats.starttime \
|
||||
pickparameter.setParam(
|
||||
pstart=max([0, badpicks[i][1] - wf2pick[0].stats.starttime \
|
||||
- pickparameter.getParam('tlta')]))
|
||||
pickparameter.setParam(pstop=pickparameter.getParam('pstart') + \
|
||||
(3 * pickparameter.getParam('tlta')))
|
||||
pickparameter.setParam(sstop=pickparameter.getParam('sstop') / 2)
|
||||
pickparameter.setParam(pickwinP=pickparameter.getParam('pickwinP') / 2)
|
||||
pickparameter.setParam(Precalcwin=pickparameter.getParam('Precalcwin') / 2)
|
||||
pickparameter.setParam(
|
||||
Precalcwin=pickparameter.getParam('Precalcwin') / 2)
|
||||
pickparameter.setParam(noisefactor=1.0)
|
||||
pickparameter.setParam(zfac=1.0)
|
||||
print("iteratepicker: The following picking parameters have been modified for iterative picking:")
|
||||
print("pstart: %fs => %fs" % (pstart_old, pickparameter.getParam('pstart')))
|
||||
print("pstop: %fs => %fs" % (pstop_old, pickparameter.getParam('pstop')))
|
||||
print("sstop: %fs => %fs" % (sstop_old, pickparameter.getParam('sstop')))
|
||||
print("pickwinP: %fs => %fs" % (pickwinP_old, pickparameter.getParam('pickwinP')))
|
||||
print("Precalcwin: %fs => %fs" % (Precalcwin_old, pickparameter.getParam('Precalcwin')))
|
||||
print("noisefactor: %f => %f" % (noisefactor_old, pickparameter.getParam('noisefactor')))
|
||||
print(
|
||||
"iteratepicker: The following picking parameters have been modified for iterative picking:")
|
||||
print(
|
||||
"pstart: %fs => %fs" % (pstart_old, pickparameter.getParam('pstart')))
|
||||
print(
|
||||
"pstop: %fs => %fs" % (pstop_old, pickparameter.getParam('pstop')))
|
||||
print(
|
||||
"sstop: %fs => %fs" % (sstop_old, pickparameter.getParam('sstop')))
|
||||
print("pickwinP: %fs => %fs" % (
|
||||
pickwinP_old, pickparameter.getParam('pickwinP')))
|
||||
print("Precalcwin: %fs => %fs" % (
|
||||
Precalcwin_old, pickparameter.getParam('Precalcwin')))
|
||||
print("noisefactor: %f => %f" % (
|
||||
noisefactor_old, pickparameter.getParam('noisefactor')))
|
||||
print("zfac: %f => %f" % (zfac_old, pickparameter.getParam('zfac')))
|
||||
|
||||
# repick station
|
||||
@ -879,10 +908,3 @@ def iteratepicker(wf, NLLocfile, picks, badpicks, pickparameter):
|
||||
pickparameter.setParam(zfac=zfac_old)
|
||||
|
||||
return picks
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -21,10 +21,12 @@ import matplotlib.pyplot as plt
|
||||
import numpy as np
|
||||
from obspy.core import Stream
|
||||
|
||||
|
||||
class CharacteristicFunction(object):
|
||||
'''
|
||||
SuperClass for different types of characteristic functions.
|
||||
'''
|
||||
|
||||
def __init__(self, data, cut, t2=None, order=None, t1=None, fnoise=None, stealthMode=False):
|
||||
'''
|
||||
Initialize data type object with information from the original
|
||||
@ -247,6 +249,7 @@ class AICcf(CharacteristicFunction):
|
||||
self.cf = cf - np.mean(cf)
|
||||
self.xcf = x
|
||||
|
||||
|
||||
class HOScf(CharacteristicFunction):
|
||||
'''
|
||||
Function to calculate skewness (statistics of order 3) or kurtosis
|
||||
@ -302,7 +305,6 @@ class HOScf(CharacteristicFunction):
|
||||
|
||||
|
||||
class ARZcf(CharacteristicFunction):
|
||||
|
||||
def calcCF(self, data):
|
||||
|
||||
print 'Calculating AR-prediction error from single trace ...'
|
||||
@ -426,7 +428,6 @@ class ARZcf(CharacteristicFunction):
|
||||
|
||||
|
||||
class ARHcf(CharacteristicFunction):
|
||||
|
||||
def calcCF(self, data):
|
||||
|
||||
print 'Calculating AR-prediction error from both horizontal traces ...'
|
||||
@ -464,7 +465,8 @@ class ARHcf(CharacteristicFunction):
|
||||
self.arPredH(xnp, self.arpara, i + 1, lpred)
|
||||
# prediction error = CF
|
||||
cf[i + lpred] = np.sqrt(np.sum(np.power(self.xpred[0][i:i + lpred] - xnp[0][i:i + lpred], 2) \
|
||||
+ np.power(self.xpred[1][i:i + lpred] - xnp[1][i:i + lpred], 2)) / (2 * lpred))
|
||||
+ np.power(self.xpred[1][i:i + lpred] - xnp[1][i:i + lpred], 2)) / (
|
||||
2 * lpred))
|
||||
nn = np.isnan(cf)
|
||||
if len(nn) > 1:
|
||||
cf[nn] = 0
|
||||
@ -561,8 +563,8 @@ class ARHcf(CharacteristicFunction):
|
||||
z = np.array([z1.tolist(), z2.tolist()])
|
||||
self.xpred = z
|
||||
|
||||
class AR3Ccf(CharacteristicFunction):
|
||||
|
||||
class AR3Ccf(CharacteristicFunction):
|
||||
def calcCF(self, data):
|
||||
|
||||
print 'Calculating AR-prediction error from all 3 components ...'
|
||||
@ -605,7 +607,8 @@ class AR3Ccf(CharacteristicFunction):
|
||||
# prediction error = CF
|
||||
cf[i + lpred] = np.sqrt(np.sum(np.power(self.xpred[0][i:i + lpred] - xnp[0][i:i + lpred], 2) \
|
||||
+ np.power(self.xpred[1][i:i + lpred] - xnp[1][i:i + lpred], 2) \
|
||||
+ np.power(self.xpred[2][i:i + lpred] - xnp[2][i:i + lpred], 2)) / (3 * lpred))
|
||||
+ np.power(self.xpred[2][i:i + lpred] - xnp[2][i:i + lpred], 2)) / (
|
||||
3 * lpred))
|
||||
nn = np.isnan(cf)
|
||||
if len(nn) > 1:
|
||||
cf[nn] = 0
|
259
pylot/core/pick/compare.py
Normal file
259
pylot/core/pick/compare.py
Normal file
@ -0,0 +1,259 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import copy
|
||||
|
||||
import numpy as np
|
||||
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
from obspy import read_events
|
||||
|
||||
from pylot.core.read.io import picks_from_evt
|
||||
from pylot.core.util.pdf import ProbabilityDensityFunction
|
||||
from pylot.core.util.version import get_git_version as _getVersionString
|
||||
|
||||
__version__ = _getVersionString()
|
||||
__author__ = 'sebastianw'
|
||||
|
||||
|
||||
class Comparison(object):
|
||||
"""
|
||||
A Comparison object contains information on the evaluated picks' probability
|
||||
density function and compares these in terms of building the difference of
|
||||
compared pick sets. The results can be displayed as histograms showing its
|
||||
properties.
|
||||
"""
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
names = list()
|
||||
self._pdfs = dict()
|
||||
for name, fn in kwargs.items():
|
||||
self._pdfs[name] = PDFDictionary.from_quakeml(fn)
|
||||
names.append(name)
|
||||
if len(names) > 2:
|
||||
raise ValueError('Comparison is only defined for two '
|
||||
'arguments!')
|
||||
self._names = names
|
||||
self._compare = self.compare_picksets()
|
||||
|
||||
def __nonzero__(self):
|
||||
if not len(self.names) == 2 or not self._pdfs:
|
||||
return False
|
||||
return True
|
||||
|
||||
def get(self, name):
|
||||
return self._pdfs[name]
|
||||
|
||||
@property
|
||||
def names(self):
|
||||
return self._names
|
||||
|
||||
@names.setter
|
||||
def names(self, names):
|
||||
assert isinstance(names, list) and len(names) == 2, 'variable "names"' \
|
||||
' is either not a' \
|
||||
' list or its ' \
|
||||
'length is not 2:' \
|
||||
'names : {names}'.format(
|
||||
names=names)
|
||||
self._names = names
|
||||
|
||||
@property
|
||||
def comparison(self):
|
||||
return self._compare
|
||||
|
||||
@property
|
||||
def stations(self):
|
||||
return self.comparison.keys()
|
||||
|
||||
@property
|
||||
def nstations(self):
|
||||
return len(self.stations)
|
||||
|
||||
def compare_picksets(self, type='exp'):
|
||||
"""
|
||||
Compare two picksets A and B and return a dictionary compiling the results.
|
||||
Comparison is carried out with the help of pdf representation of the picks
|
||||
and a probabilistic approach to the time difference of two onset
|
||||
measurements.
|
||||
:param a: filename for pickset A
|
||||
:type a: str
|
||||
:param b: filename for pickset B
|
||||
:type b: str
|
||||
:return: dictionary containing the resulting comparison pdfs for all picks
|
||||
:rtype: dict
|
||||
"""
|
||||
compare_pdfs = dict()
|
||||
|
||||
pdf_a = self.get(self.names[0]).pdf_data(type)
|
||||
pdf_b = self.get(self.names[1]).pdf_data(type)
|
||||
|
||||
for station, phases in pdf_a.items():
|
||||
if station in pdf_b.keys():
|
||||
compare_pdf = dict()
|
||||
for phase in phases:
|
||||
if phase in pdf_b[station].keys():
|
||||
compare_pdf[phase] = phases[phase] - pdf_b[station][
|
||||
phase]
|
||||
if compare_pdf is not None:
|
||||
compare_pdfs[station] = compare_pdf
|
||||
|
||||
return compare_pdfs
|
||||
|
||||
def plot(self):
|
||||
nstations = self.nstations
|
||||
stations = self.stations
|
||||
istations = range(nstations)
|
||||
fig, axarr = plt.subplots(nstations, 2, sharex='col', sharey='row')
|
||||
|
||||
for n in istations:
|
||||
station = stations[n]
|
||||
compare_pdf = self.comparison[station]
|
||||
for l, phase in enumerate(compare_pdf.keys()):
|
||||
axarr[n, l].plot(compare_pdf[phase].axis,
|
||||
compare_pdf[phase].data)
|
||||
if n is 0:
|
||||
axarr[n, l].set_title(phase)
|
||||
if l is 0:
|
||||
axann = axarr[n, l].annotate(station, xy=(.05, .5),
|
||||
xycoords='axes fraction')
|
||||
bbox_props = dict(boxstyle='round', facecolor='lightgrey',
|
||||
alpha=.7)
|
||||
axann.set_bbox(bbox_props)
|
||||
if n == int(np.median(istations)) and l is 0:
|
||||
label = 'probability density (qualitative)'
|
||||
axarr[n, l].set_ylabel(label)
|
||||
plt.setp([a.get_xticklabels() for a in axarr[0, :]], visible=False)
|
||||
plt.setp([a.get_yticklabels() for a in axarr[:, 1]], visible=False)
|
||||
plt.setp([a.get_yticklabels() for a in axarr[:, 0]], visible=False)
|
||||
|
||||
plt.show()
|
||||
|
||||
def get_expectation_array(self, phase):
|
||||
pdf_dict = self.comparison
|
||||
exp_array = list()
|
||||
for station, phases in pdf_dict.items():
|
||||
try:
|
||||
exp_array.append(phases[phase].expectation())
|
||||
except KeyError as e:
|
||||
print('{err_msg}; station = {station}, phase = {phase}'.format(
|
||||
err_msg=str(e), station=station, phase=phase))
|
||||
continue
|
||||
return exp_array
|
||||
|
||||
def get_std_array(self, phase):
|
||||
pdf_dict = self.comparison
|
||||
std_array = list()
|
||||
for station, phases in pdf_dict.items():
|
||||
try:
|
||||
std_array.append(phases[phase].standard_deviation())
|
||||
except KeyError as e:
|
||||
print('{err_msg}; station = {station}, phase = {phase}'.format(
|
||||
err_msg=str(e), station=station, phase=phase))
|
||||
continue
|
||||
return std_array
|
||||
|
||||
def hist_expectation(self, phases='all', bins=20, normed=False):
|
||||
phases.strip()
|
||||
if phases.find('all') is 0:
|
||||
phases = 'ps'
|
||||
phases = phases.upper()
|
||||
nsp = len(phases)
|
||||
fig, axarray = plt.subplots(1, nsp, sharey=True)
|
||||
for n, phase in enumerate(phases):
|
||||
ax = axarray[n]
|
||||
data = self.get_expectation_array(phase)
|
||||
xlims = [min(data), max(data)]
|
||||
ax.hist(data, range=xlims, bins=bins, normed=normed)
|
||||
title_str = 'phase: {0}, samples: {1}'.format(phase, len(data))
|
||||
ax.set_title(title_str)
|
||||
ax.set_xlabel('expectation [s]')
|
||||
if n is 0:
|
||||
ax.set_ylabel('abundance [-]')
|
||||
plt.setp([a.get_yticklabels() for a in axarray[1:]], visible=False)
|
||||
plt.show()
|
||||
|
||||
def hist_standard_deviation(self, phases='all', bins=20, normed=False):
|
||||
phases.strip()
|
||||
if phases.find('all') == 0:
|
||||
phases = 'ps'
|
||||
phases = phases.upper()
|
||||
nsp = len(phases)
|
||||
fig, axarray = plt.subplots(1, nsp, sharey=True)
|
||||
for n, phase in enumerate(phases):
|
||||
ax = axarray[n]
|
||||
data = self.get_std_array(phase)
|
||||
xlims = [min(data), max(data)]
|
||||
ax.hist(data, range=xlims, bins=bins, normed=normed)
|
||||
title_str = 'phase: {0}, samples: {1}'.format(phase, len(data))
|
||||
ax.set_title(title_str)
|
||||
ax.set_xlabel('standard deviation [s]')
|
||||
if n is 0:
|
||||
ax.set_ylabel('abundance [-]')
|
||||
plt.setp([a.get_yticklabels() for a in axarray[1:]], visible=False)
|
||||
plt.show()
|
||||
|
||||
def hist(self, type='std'):
|
||||
pass
|
||||
|
||||
|
||||
class PDFDictionary(object):
|
||||
"""
|
||||
A PDFDictionary is a dictionary like object containing structured data on
|
||||
the probability density function of seismic phase onsets.
|
||||
"""
|
||||
|
||||
def __init__(self, data):
|
||||
self._pickdata = data
|
||||
|
||||
def __nonzero__(self):
|
||||
if len(self.pick_data) < 1:
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
@property
|
||||
def pick_data(self):
|
||||
return self._pickdata
|
||||
|
||||
@pick_data.setter
|
||||
def pick_data(self, data):
|
||||
self._pickdata = data
|
||||
|
||||
@classmethod
|
||||
def from_quakeml(self, fn):
|
||||
cat = read_events(fn)
|
||||
if len(cat) > 1:
|
||||
raise NotImplementedError('reading more than one event at the same '
|
||||
'time is not implemented yet! Sorry!')
|
||||
return PDFDictionary(picks_from_evt(cat[0]))
|
||||
|
||||
def pdf_data(self, type='exp'):
|
||||
"""
|
||||
Returns probabiliy density function dictionary containing the
|
||||
representation of the actual pick_data.
|
||||
:param type: type of the returned
|
||||
`~pylot.core.util.pdf.ProbabilityDensityFunction` object
|
||||
:type type: str
|
||||
:return: a dictionary containing the picks represented as pdfs
|
||||
"""
|
||||
|
||||
pdf_picks = copy.deepcopy(self.pick_data)
|
||||
|
||||
for station, phases in pdf_picks.items():
|
||||
for phase, values in phases.items():
|
||||
phases[phase] = ProbabilityDensityFunction.from_pick(
|
||||
values['epp'],
|
||||
values['mpp'],
|
||||
values['lpp'],
|
||||
type=type)
|
||||
|
||||
return pdf_picks
|
||||
|
||||
|
||||
#comp_obj = Comparison(manual='/home/sebastianp/Data/Insheim/e0019.048.13.xml',
|
||||
# auto='/data/Geothermie/Insheim/EVENT_DATA/LOCAL/RefDB/e0019.048.13/autoPyLoT.xml')
|
||||
#comp_obj.plot()
|
||||
#comp_obj.hist_expectation()
|
||||
#comp_obj.hist_standard_deviation()
|
@ -22,10 +22,11 @@ calculated after Diehl & Kissling (2009).
|
||||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
from pylot.core.pick.utils import getnoisewin, getsignalwin
|
||||
from pylot.core.pick.CharFuns import CharacteristicFunction
|
||||
from pylot.core.pick.charfuns import CharacteristicFunction
|
||||
import warnings
|
||||
|
||||
class AutoPicking(object):
|
||||
|
||||
class AutoPicker(object):
|
||||
'''
|
||||
Superclass of different, automated picking algorithms applied on a CF determined
|
||||
using AIC, HOS, or AR prediction.
|
||||
@ -87,7 +88,6 @@ class AutoPicking(object):
|
||||
Tsmooth=self.getTsmooth(),
|
||||
Pick1=self.getpick1())
|
||||
|
||||
|
||||
def getTSNR(self):
|
||||
return self.TSNR
|
||||
|
||||
@ -137,7 +137,7 @@ class AutoPicking(object):
|
||||
self.Pick = None
|
||||
|
||||
|
||||
class AICPicker(AutoPicking):
|
||||
class AICPicker(AutoPicker):
|
||||
'''
|
||||
Method to derive the onset time of an arriving phase based on CF
|
||||
derived from AIC. In order to get an impression of the quality of this inital pick,
|
||||
@ -273,7 +273,8 @@ class AICPicker(AutoPicking):
|
||||
p13, = plt.plot(self.Tcf[isignal], self.Data[0].data[isignal], 'r')
|
||||
p14, = plt.plot(self.Tcf[islope], dataslope, 'g--')
|
||||
p15, = plt.plot(self.Tcf[islope], datafit, 'g', linewidth=2)
|
||||
plt.legend([p11, p12, p13, p14, p15], ['Data', 'Noise Window', 'Signal Window', 'Slope Window', 'Slope'],
|
||||
plt.legend([p11, p12, p13, p14, p15],
|
||||
['Data', 'Noise Window', 'Signal Window', 'Slope Window', 'Slope'],
|
||||
loc='best')
|
||||
plt.title('Station %s, SNR=%7.2f, Slope= %12.2f counts/s' % (self.Data[0].stats.station,
|
||||
self.SNR, self.slope))
|
||||
@ -289,7 +290,7 @@ class AICPicker(AutoPicking):
|
||||
print('AICPicker: Could not find minimum, picking window too short?')
|
||||
|
||||
|
||||
class PragPicker(AutoPicking):
|
||||
class PragPicker(AutoPicker):
|
||||
'''
|
||||
Method of pragmatic picking exploiting information given by CF.
|
||||
'''
|
@ -70,7 +70,8 @@ def earllatepicker(X, nfac, TSNR, Pick1, iplot=None, stealthMode = False):
|
||||
|
||||
# get earliest possible pick
|
||||
|
||||
EPick = np.nan; count = 0
|
||||
EPick = np.nan;
|
||||
count = 0
|
||||
pis = isignal
|
||||
|
||||
# if EPick stays NaN the signal window size will be doubled
|
||||
@ -94,7 +95,6 @@ def earllatepicker(X, nfac, TSNR, Pick1, iplot=None, stealthMode = False):
|
||||
T0 = np.mean(np.diff(zc)) * X[0].stats.delta # this is half wave length!
|
||||
EPick = Pick1 - T0 # half wavelength as suggested by Diehl et al.
|
||||
|
||||
|
||||
# get symmetric pick error as mean from earliest and latest possible pick
|
||||
# by weighting latest possible pick two times earliest possible pick
|
||||
diffti_tl = LPick - Pick1
|
||||
@ -133,117 +133,6 @@ def earllatepicker(X, nfac, TSNR, Pick1, iplot=None, stealthMode = False):
|
||||
return EPick, LPick, PickError
|
||||
|
||||
|
||||
def gauss_parameter(te, tm, tl, eta):
|
||||
'''
|
||||
takes three onset times and returns the parameters sig1, sig2, a1 and a2
|
||||
to represent the pick as a probability density funtion (PDF) with two
|
||||
Gauss branches
|
||||
:param te:
|
||||
:param tm:
|
||||
:param tl:
|
||||
:param eta:
|
||||
:return:
|
||||
'''
|
||||
|
||||
sig1 = (tm - te) / np.sqrt(2 * np.log(1 / eta))
|
||||
sig2 = (tl - tm) / np.sqrt(2 * np.log(1 / eta))
|
||||
|
||||
a1 = 2 / (1 + sig2 / sig1)
|
||||
a2 = 2 / (1 + sig1 / sig2)
|
||||
|
||||
return sig1, sig2, a1, a2
|
||||
|
||||
|
||||
def exp_parameter(te, tm, tl, eta):
|
||||
'''
|
||||
takes three onset times te, tm and tl and returns the parameters sig1,
|
||||
sig2 and a to represent the pick as a probability density function (PDF)
|
||||
with two exponential decay branches
|
||||
:param te:
|
||||
:param tm:
|
||||
:param tl:
|
||||
:param eta:
|
||||
:return:
|
||||
'''
|
||||
|
||||
sig1 = np.log(eta) / (te - tm)
|
||||
sig2 = np.log(eta) / (tm - tl)
|
||||
a = 1 / (1 / sig1 + 1 / sig2)
|
||||
|
||||
return sig1, sig2, a
|
||||
|
||||
|
||||
def gauss_branches(x, mu, sig1, sig2, a1, a2):
|
||||
'''
|
||||
function gauss_branches takes an axes x, a center value mu, two sigma
|
||||
values sig1 and sig2 and two scaling factors a1 and a2 and return a
|
||||
list containing the values of a probability density function (PDF)
|
||||
consisting of gauss branches
|
||||
:param x:
|
||||
:type x:
|
||||
:param mu:
|
||||
:type mu:
|
||||
:param sig1:
|
||||
:type sig1:
|
||||
:param sig2:
|
||||
:type sig2:
|
||||
:param a1:
|
||||
:type a1:
|
||||
:param a2:
|
||||
:returns fun_vals: list with function values along axes x
|
||||
'''
|
||||
fun_vals = []
|
||||
for k in x:
|
||||
if k < mu:
|
||||
fun_vals.append(a1 * 1 / (np.sqrt(2 * np.pi) * sig1) * np.exp(-((k - mu) / sig1)**2 / 2 ))
|
||||
else:
|
||||
fun_vals.append(a2 * 1 / (np.sqrt(2 * np.pi) * sig2) * np.exp(-((k - mu) / sig2)**2 / 2))
|
||||
return fun_vals
|
||||
|
||||
|
||||
def exp_branches(x, mu, sig1, sig2, a):
|
||||
'''
|
||||
function exp_branches takes an axes x, a center value mu, two sigma
|
||||
values sig1 and sig2 and a scaling factor a and return a
|
||||
list containing the values of a probability density function (PDF)
|
||||
consisting of exponential decay branches
|
||||
:param x:
|
||||
:param mu:
|
||||
:param sig1:
|
||||
:param sig2:
|
||||
:param a:
|
||||
:returns fun_vals: list with function values along axes x:
|
||||
'''
|
||||
fun_vals = []
|
||||
for k in x:
|
||||
if k < mu:
|
||||
fun_vals.append(a * np.exp(sig1 * (k - mu)))
|
||||
else:
|
||||
fun_vals.append(a * np.exp(-sig2 * (k - mu)))
|
||||
return fun_vals
|
||||
|
||||
|
||||
def pick_pdf(t, te, tm, tl, type='gauss', eta=0.01):
|
||||
'''
|
||||
|
||||
:param t:
|
||||
:param te:
|
||||
:param tm:
|
||||
:param tl:
|
||||
:param type:
|
||||
:param eta:
|
||||
:param args:
|
||||
:return:
|
||||
'''
|
||||
|
||||
parameter = dict(gauss=gauss_parameter, exp=exp_parameter)
|
||||
branches = dict(gauss=gauss_branches, exp=exp_branches)
|
||||
|
||||
params = parameter[type](te, tm, tl, eta)
|
||||
|
||||
return branches[type](t, tm, *params)
|
||||
|
||||
|
||||
def fmpicker(Xraw, Xfilt, pickwin, Pick, iplot=None):
|
||||
'''
|
||||
Function to derive first motion (polarity) of given phase onset Pick.
|
||||
@ -432,7 +321,7 @@ def crossings_nonzero_all(data):
|
||||
return ((pos[:-1] & npos[1:]) | (npos[:-1] & pos[1:])).nonzero()[0]
|
||||
|
||||
|
||||
def getSNR(X, TSNR, t1):
|
||||
def getSNR(X, TSNR, t1, tracenum=0):
|
||||
'''
|
||||
Function to calculate SNR of certain part of seismogram relative to
|
||||
given time (onset) out of given noise and signal windows. A safety gap
|
||||
@ -451,9 +340,11 @@ def getSNR(X, TSNR, t1):
|
||||
|
||||
assert isinstance(X, Stream), "%s is not a stream object" % str(X)
|
||||
|
||||
x = X[0].data
|
||||
t = np.arange(0, X[0].stats.npts / X[0].stats.sampling_rate,
|
||||
X[0].stats.delta)
|
||||
x = X[tracenum].data
|
||||
npts = X[tracenum].stats.npts
|
||||
sr = X[tracenum].stats.sampling_rate
|
||||
dt = X[tracenum].stats.delta
|
||||
t = np.arange(0, npts / sr, dt)
|
||||
|
||||
# get noise window
|
||||
inoise = getnoisewin(t, t1, TSNR[0], TSNR[1])
|
||||
@ -471,8 +362,12 @@ def getSNR(X, TSNR, t1):
|
||||
x = x - np.mean(x[inoise])
|
||||
|
||||
# calculate ratios
|
||||
noiselevel = np.sqrt(np.mean(np.square(x[inoise])))
|
||||
signallevel = np.sqrt(np.mean(np.square(x[isignal])))
|
||||
# noiselevel = np.sqrt(np.mean(np.square(x[inoise])))
|
||||
# signallevel = np.sqrt(np.mean(np.square(x[isignal])))
|
||||
|
||||
noiselevel = np.abs(x[inoise]).max()
|
||||
signallevel = np.abs(x[isignal]).max()
|
||||
|
||||
SNR = signallevel / noiselevel
|
||||
SNRdB = 10 * np.log10(SNR)
|
||||
|
||||
@ -604,7 +499,6 @@ def wadaticheck(pickdic, dttolerance, iplot):
|
||||
Spicks.append(UTCSpick.timestamp)
|
||||
SPtimes.append(spt)
|
||||
|
||||
|
||||
if len(SPtimes) >= 3:
|
||||
# calculate slope
|
||||
p1 = np.polyfit(Ppicks, SPtimes, 1)
|
||||
@ -986,7 +880,6 @@ def checkZ4S(X, pick, zfac, checkwin, iplot):
|
||||
if len(ndat) == 0: # check for other components
|
||||
ndat = X.select(component="1")
|
||||
|
||||
|
||||
z = zdat[0].data
|
||||
tz = np.arange(0, zdat[0].stats.npts / zdat[0].stats.sampling_rate,
|
||||
zdat[0].stats.delta)
|
||||
@ -1065,7 +958,6 @@ def writephases(arrivals, fformat, filename):
|
||||
:type: string
|
||||
'''
|
||||
|
||||
|
||||
if fformat == 'NLLoc':
|
||||
print ("Writing phases to %s for NLLoc" % filename)
|
||||
fid = open("%s" % filename, 'w')
|
||||
@ -1203,4 +1095,5 @@ def writephases(arrivals, fformat, filename):
|
||||
|
||||
if __name__ == '__main__':
|
||||
import doctest
|
||||
|
||||
doctest.testmod()
|
||||
|
@ -3,9 +3,10 @@
|
||||
|
||||
import os
|
||||
import glob
|
||||
from obspy.xseed import Parser
|
||||
import warnings
|
||||
from obspy.io.xseed import Parser
|
||||
from obspy.core import read, Stream, UTCDateTime
|
||||
from obspy import readEvents, read_inventory
|
||||
from obspy import read_events, read_inventory
|
||||
from obspy.core.event import Event, ResourceIdentifier, Pick, WaveformStreamID
|
||||
|
||||
from pylot.core.read.io import readPILOTEvent
|
||||
@ -37,9 +38,10 @@ class Data(object):
|
||||
if isinstance(evtdata, Event):
|
||||
self.evtdata = evtdata
|
||||
elif isinstance(evtdata, dict):
|
||||
cat = readPILOTEvent(**evtdata)
|
||||
evt = readPILOTEvent(**evtdata)
|
||||
self.evtdata = evt
|
||||
elif evtdata:
|
||||
cat = readEvents(evtdata)
|
||||
cat = read_events(evtdata)
|
||||
self.evtdata = cat[0]
|
||||
else: # create an empty Event object
|
||||
self.setNew()
|
||||
@ -79,7 +81,6 @@ class Data(object):
|
||||
picks_str += str(pick) + '\n'
|
||||
return picks_str
|
||||
|
||||
|
||||
def getParent(self):
|
||||
"""
|
||||
|
||||
@ -186,8 +187,11 @@ class Data(object):
|
||||
self.wforiginal = None
|
||||
if fnames is not None:
|
||||
self.appendWFData(fnames)
|
||||
else:
|
||||
return False
|
||||
self.wforiginal = self.getWFData().copy()
|
||||
self.dirty = False
|
||||
return True
|
||||
|
||||
def appendWFData(self, fnames):
|
||||
"""
|
||||
@ -413,16 +417,24 @@ class Data(object):
|
||||
for station, onsets in picks.items():
|
||||
print('Reading picks on station %s' % station)
|
||||
for label, phase in onsets.items():
|
||||
if not isinstance(phase, dict):
|
||||
continue
|
||||
onset = phase['mpp']
|
||||
epp = phase['epp']
|
||||
lpp = phase['lpp']
|
||||
error = phase['spe']
|
||||
try:
|
||||
picker = phase['picker']
|
||||
except KeyError as e:
|
||||
warnings.warn(str(e), Warning)
|
||||
picker = 'Unknown'
|
||||
pick = Pick()
|
||||
pick.time = onset
|
||||
pick.time_errors.lower_uncertainty = onset - epp
|
||||
pick.time_errors.upper_uncertainty = lpp - onset
|
||||
pick.time_errors.uncertainty = error
|
||||
pick.phase_hint = label
|
||||
pick.method_id = ResourceIdentifier(id=picker)
|
||||
pick.waveform_id = WaveformStreamID(station_code=station)
|
||||
self.getEvtData().picks.append(pick)
|
||||
try:
|
||||
@ -432,11 +444,13 @@ class Data(object):
|
||||
if firstonset is None or firstonset > onset:
|
||||
firstonset = onset
|
||||
|
||||
if 'smi:local' in self.getID():
|
||||
if 'smi:local' in self.getID() and firstonset:
|
||||
fonset_str = firstonset.strftime('%Y_%m_%d_%H_%M_%S')
|
||||
ID = ResourceIdentifier('event/' + fonset_str)
|
||||
ID.convertIDToQuakeMLURI(authority_id=authority_id)
|
||||
self.getEvtData().resource_id = ID
|
||||
else:
|
||||
print('No picks to apply!')
|
||||
|
||||
def applyArrivals(arrivals):
|
||||
"""
|
||||
|
@ -1,6 +1,8 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from pylot.core.util.errors import ParameterError
|
||||
|
||||
|
||||
class AutoPickParameter(object):
|
||||
'''
|
||||
@ -57,7 +59,7 @@ class AutoPickParameter(object):
|
||||
for line in lines:
|
||||
parspl = line.split('\t')[:2]
|
||||
parFileCont[parspl[0].strip()] = parspl[1]
|
||||
except Exception as e:
|
||||
except IndexError as e:
|
||||
self._printParameterError(e)
|
||||
inputFile.seek(0)
|
||||
lines = inputFile.readlines()
|
||||
@ -136,11 +138,13 @@ class AutoPickParameter(object):
|
||||
return self.__getitem__(param)
|
||||
except KeyError as e:
|
||||
self._printParameterError(e)
|
||||
raise ParameterError(e)
|
||||
except TypeError:
|
||||
try:
|
||||
return self.__getitem__(args)
|
||||
except KeyError as e:
|
||||
self._printParameterError(e)
|
||||
raise ParameterError(e)
|
||||
|
||||
def setParam(self, **kwargs):
|
||||
for param, value in kwargs.items():
|
||||
@ -190,6 +194,7 @@ class FilterOptions(object):
|
||||
``'highpass'``
|
||||
Butterworth-Highpass
|
||||
'''
|
||||
|
||||
def __init__(self, filtertype='bandpass', freq=[2., 5.], order=3,
|
||||
**kwargs):
|
||||
self._order = order
|
||||
|
@ -10,6 +10,7 @@ from obspy.core import UTCDateTime
|
||||
from pylot.core.util.utils import getOwner, createPick, createArrival, \
|
||||
createEvent, createOrigin, createMagnitude
|
||||
|
||||
|
||||
def readPILOTEvent(phasfn=None, locfn=None, authority_id=None, **kwargs):
|
||||
"""
|
||||
readPILOTEvent - function
|
||||
@ -134,4 +135,57 @@ def readPILOTEvent(phasfn=None, locfn=None, authority_id=None, **kwargs):
|
||||
raise AttributeError('{0} - Matlab LOC files {1} and {2} contains \
|
||||
insufficient data!'.format(e, phasfn, locfn))
|
||||
|
||||
def picks_from_obs(fn):
|
||||
picks = dict()
|
||||
station_name = str()
|
||||
for line in open(fn, 'r'):
|
||||
if line.startswith('#'):
|
||||
continue
|
||||
else:
|
||||
phase_line = line.split()
|
||||
if not station_name == phase_line[0]:
|
||||
phase = dict()
|
||||
station_name = phase_line[0]
|
||||
phase_name = phase_line[4].upper()
|
||||
pick = UTCDateTime(phase_line[6] + phase_line[7] + phase_line[8])
|
||||
phase[phase_name] = dict(mpp=pick, fm=phase_line[5])
|
||||
picks[station_name] = phase
|
||||
return picks
|
||||
|
||||
|
||||
def picks_from_evt(evt):
|
||||
'''
|
||||
Takes an Event object and return the pick dictionary commonly used within
|
||||
PyLoT
|
||||
:param evt: Event object contain all available information
|
||||
:type evt: `~obspy.core.event.Event`
|
||||
:return: pick dictionary
|
||||
'''
|
||||
picks = {}
|
||||
for pick in evt.picks:
|
||||
phase = {}
|
||||
station = pick.waveform_id.station_code
|
||||
try:
|
||||
onsets = picks[station]
|
||||
except KeyError as e:
|
||||
print(e)
|
||||
onsets = {}
|
||||
mpp = pick.time
|
||||
lpp = mpp + pick.time_errors.upper_uncertainty
|
||||
epp = mpp - pick.time_errors.lower_uncertainty
|
||||
spe = pick.time_errors.uncertainty
|
||||
phase['mpp'] = mpp
|
||||
phase['epp'] = epp
|
||||
phase['lpp'] = lpp
|
||||
phase['spe'] = spe
|
||||
try:
|
||||
picker = str(pick.method_id)
|
||||
if picker.startswith('smi:local/'):
|
||||
picker = picker.split('smi:local/')[1]
|
||||
phase['picker'] = picker
|
||||
except IndexError:
|
||||
pass
|
||||
|
||||
onsets[pick.phase_hint] = phase.copy()
|
||||
picks[station] = onsets.copy()
|
||||
return picks
|
||||
|
@ -7,7 +7,7 @@ from pylot.core.pick.utils import getnoisewin
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('--t', type=~numpy.array, help='numpy array of time stamps')
|
||||
parser.add_argument('--t', type=numpy.array, help='numpy array of time stamps')
|
||||
parser.add_argument('--t1', type=float, help='time from which relativ to it noise window is extracted')
|
||||
parser.add_argument('--tnoise', type=float, help='length of time window [s] for noise part extraction')
|
||||
parser.add_argument('--tgap', type=float, help='safety gap between signal (t1=onset) and noise')
|
@ -14,11 +14,12 @@ import argparse
|
||||
import obspy
|
||||
from pylot.core.pick.utils import earllatepicker
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('--X', type=~obspy.core.stream.Stream, help='time series (seismogram) read with obspy module read')
|
||||
parser.add_argument('--nfac', type=int, help='(noise factor), nfac times noise level to calculate latest possible pick')
|
||||
parser.add_argument('--X', type=~obspy.core.stream.Stream,
|
||||
help='time series (seismogram) read with obspy module read')
|
||||
parser.add_argument('--nfac', type=int,
|
||||
help='(noise factor), nfac times noise level to calculate latest possible pick')
|
||||
parser.add_argument('--TSNR', type=tuple, help='length of time windows around pick used to determine SNR \
|
||||
[s] (Tnoise, Tgap, Tsignal)')
|
||||
parser.add_argument('--Pick1', type=float, help='Onset time of most likely pick')
|
@ -13,11 +13,12 @@ from pylot.core.pick.utils import fmpicker
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('--Xraw', type=~obspy.core.stream.Stream, help='unfiltered time series (seismogram) read with obspy module read')
|
||||
parser.add_argument('--Xfilt', type=~obspy.core.stream.Stream, help='filtered time series (seismogram) read with obspy module read')
|
||||
parser.add_argument('--Xraw', type=obspy.core.stream.Stream,
|
||||
help='unfiltered time series (seismogram) read with obspy module read')
|
||||
parser.add_argument('--Xfilt', type=obspy.core.stream.Stream,
|
||||
help='filtered time series (seismogram) read with obspy module read')
|
||||
parser.add_argument('--pickwin', type=float, help='length of pick window [s] for first motion determination')
|
||||
parser.add_argument('--Pick', type=float, help='Onset time of most likely pick')
|
||||
parser.add_argument('--iplot', type=int, help='if set, figure no. iplot occurs')
|
||||
args = parser.parse_args()
|
||||
fmpicker(args.Xraw, args.Xfilt, args.pickwin, args.Pick, args.iplot)
|
||||
|
@ -7,7 +7,7 @@ from pylot.core.pick.utils import getsignalwin
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('--t', type=~numpy.array, help='numpy array of time stamps')
|
||||
parser.add_argument('--t', type=numpy.array, help='numpy array of time stamps')
|
||||
parser.add_argument('--t1', type=float, help='time from which relativ to it signal window is extracted')
|
||||
parser.add_argument('--tsignal', type=float, help='length of time window [s] for signal part extraction')
|
||||
args = parser.parse_args()
|
@ -14,7 +14,7 @@ from pylot.core.pick.utils import getSNR
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('--data', '-d', type=~obspy.core.stream.Stream,
|
||||
parser.add_argument('--data', '-d', type=obspy.core.stream.Stream,
|
||||
help='time series (seismogram) read with obspy module '
|
||||
'read',
|
||||
dest='data')
|
@ -9,8 +9,8 @@
|
||||
from obspy.core import read
|
||||
import matplotlib.pyplot as plt
|
||||
import numpy as np
|
||||
from pylot.core.pick.CharFuns import CharacteristicFunction
|
||||
from pylot.core.pick.Picker import AutoPicking
|
||||
from pylot.core.pick.charfuns import CharacteristicFunction
|
||||
from pylot.core.pick.picker import AutoPicker
|
||||
from pylot.core.pick.utils import *
|
||||
import glob
|
||||
import argparse
|
@ -11,6 +11,7 @@ from pylot.core.loc import nll
|
||||
from pylot.core.loc import hsat
|
||||
from pylot.core.loc import velest
|
||||
|
||||
|
||||
def readFilterInformation(fname):
|
||||
def convert2FreqRange(*args):
|
||||
if len(args) > 1:
|
||||
@ -18,6 +19,7 @@ def readFilterInformation(fname):
|
||||
elif len(args) == 1:
|
||||
return float(args[0])
|
||||
return None
|
||||
|
||||
filter_file = open(fname, 'r')
|
||||
filter_information = dict()
|
||||
for filter_line in filter_file.readlines():
|
||||
@ -41,8 +43,19 @@ FILTERDEFAULTS = readFilterInformation(os.path.join(os.path.expanduser('~'),
|
||||
'.pylot',
|
||||
'filter.in'))
|
||||
|
||||
AUTOMATIC_DEFAULTS = os.path.join(os.path.expanduser('~'),
|
||||
'.pylot',
|
||||
'autoPyLoT.in')
|
||||
|
||||
OUTPUTFORMATS = {'.xml': 'QUAKEML',
|
||||
'.cnv': 'CNV',
|
||||
'.obs': 'NLLOC_OBS'}
|
||||
|
||||
LOCTOOLS = dict(nll=nll, hsat=hsat, velest=velest)
|
||||
|
||||
COMPPOSITION_MAP = dict(Z=2, N=1, E=0)
|
||||
COMPPOSITION_MAP['1'] = 1
|
||||
COMPPOSITION_MAP['2'] = 0
|
||||
COMPPOSITION_MAP['3'] = 2
|
||||
|
||||
COMPNAME_MAP = dict(Z='3', N='1', E='2')
|
||||
|
@ -20,3 +20,7 @@ class DatastructureError(Exception):
|
||||
|
||||
class OverwriteError(IOError):
|
||||
pass
|
||||
|
||||
|
||||
class ParameterError(Exception):
|
||||
pass
|
||||
|
395
pylot/core/util/pdf.py
Normal file
395
pylot/core/util/pdf.py
Normal file
@ -0,0 +1,395 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import warnings
|
||||
import numpy as np
|
||||
from obspy import UTCDateTime
|
||||
from pylot.core.util.utils import find_nearest
|
||||
from pylot.core.util.version import get_git_version as _getVersionString
|
||||
|
||||
__version__ = _getVersionString()
|
||||
__author__ = 'sebastianw'
|
||||
|
||||
def create_axis(x0, incr, npts):
|
||||
ax = np.zeros(npts)
|
||||
for i in range(npts):
|
||||
ax[i] = x0 + incr * i
|
||||
return ax
|
||||
|
||||
def gauss_parameter(te, tm, tl, eta):
|
||||
'''
|
||||
takes three onset times and returns the parameters sig1, sig2, a1 and a2
|
||||
to represent the pick as a probability density funtion (PDF) with two
|
||||
Gauss branches
|
||||
:param te:
|
||||
:param tm:
|
||||
:param tl:
|
||||
:param eta:
|
||||
:return:
|
||||
'''
|
||||
|
||||
sig1 = (tm - te) / np.sqrt(2 * np.log(1 / eta))
|
||||
sig2 = (tl - tm) / np.sqrt(2 * np.log(1 / eta))
|
||||
|
||||
a1 = 2 / (1 + sig2 / sig1)
|
||||
a2 = 2 / (1 + sig1 / sig2)
|
||||
|
||||
return sig1, sig2, a1, a2
|
||||
|
||||
|
||||
def exp_parameter(te, tm, tl, eta):
|
||||
'''
|
||||
takes three onset times te, tm and tl and returns the parameters sig1,
|
||||
sig2 and a to represent the pick as a probability density function (PDF)
|
||||
with two exponential decay branches
|
||||
:param te:
|
||||
:param tm:
|
||||
:param tl:
|
||||
:param eta:
|
||||
:return:
|
||||
'''
|
||||
|
||||
sig1 = np.log(eta) / (te - tm)
|
||||
sig2 = np.log(eta) / (tm - tl)
|
||||
a = 1 / (1 / sig1 + 1 / sig2)
|
||||
|
||||
return sig1, sig2, a
|
||||
|
||||
|
||||
def gauss_branches(x, mu, sig1, sig2, a1, a2):
|
||||
'''
|
||||
function gauss_branches takes an axes x, a center value mu, two sigma
|
||||
values sig1 and sig2 and two scaling factors a1 and a2 and return a
|
||||
list containing the values of a probability density function (PDF)
|
||||
consisting of gauss branches
|
||||
:param x:
|
||||
:type x:
|
||||
:param mu:
|
||||
:type mu:
|
||||
:param sig1:
|
||||
:type sig1:
|
||||
:param sig2:
|
||||
:type sig2:
|
||||
:param a1:
|
||||
:type a1:
|
||||
:param a2:
|
||||
:returns fun_vals: list with function values along axes x
|
||||
'''
|
||||
fun_vals = []
|
||||
for k in x:
|
||||
if k < mu:
|
||||
fun_vals.append(a1 * 1 / (np.sqrt(2 * np.pi) * sig1) * np.exp(-((k - mu) / sig1) ** 2 / 2))
|
||||
else:
|
||||
fun_vals.append(a2 * 1 / (np.sqrt(2 * np.pi) * sig2) * np.exp(-((k - mu) / sig2) ** 2 / 2))
|
||||
return np.array(fun_vals)
|
||||
|
||||
|
||||
def exp_branches(x, mu, sig1, sig2, a):
|
||||
'''
|
||||
function exp_branches takes an axes x, a center value mu, two sigma
|
||||
values sig1 and sig2 and a scaling factor a and return a
|
||||
list containing the values of a probability density function (PDF)
|
||||
consisting of exponential decay branches
|
||||
:param x:
|
||||
:param mu:
|
||||
:param sig1:
|
||||
:param sig2:
|
||||
:param a:
|
||||
:returns fun_vals: list with function values along axes x:
|
||||
'''
|
||||
fun_vals = []
|
||||
for k in x:
|
||||
if k < mu:
|
||||
fun_vals.append(a * np.exp(sig1 * (k - mu)))
|
||||
else:
|
||||
fun_vals.append(a * np.exp(-sig2 * (k - mu)))
|
||||
return np.array(fun_vals)
|
||||
|
||||
# define container dictionaries for different types of pdfs
|
||||
parameter = dict(gauss=gauss_parameter, exp=exp_parameter)
|
||||
branches = dict(gauss=gauss_branches, exp=exp_branches)
|
||||
|
||||
|
||||
class ProbabilityDensityFunction(object):
|
||||
'''
|
||||
A probability density function toolkit.
|
||||
'''
|
||||
|
||||
version = __version__
|
||||
|
||||
def __init__(self, x0, incr, npts, pdf):
|
||||
self.x0 = x0
|
||||
self.incr = incr
|
||||
self.npts = npts
|
||||
self.axis = create_axis(x0, incr, npts)
|
||||
self.data = pdf
|
||||
|
||||
def __add__(self, other):
|
||||
assert isinstance(other, ProbabilityDensityFunction), \
|
||||
'both operands must be of type ProbabilityDensityFunction'
|
||||
|
||||
x0, incr, npts, pdf_self, pdf_other = self.rearrange(other)
|
||||
pdf = np.convolve(pdf_self, pdf_other, 'full') * incr
|
||||
|
||||
# shift axis values for correct plotting
|
||||
npts = pdf.size
|
||||
x0 *= 2
|
||||
return ProbabilityDensityFunction(x0, incr, npts, pdf)
|
||||
|
||||
def __sub__(self, other):
|
||||
assert isinstance(other, ProbabilityDensityFunction), \
|
||||
'both operands must be of type ProbabilityDensityFunction'
|
||||
|
||||
x0, incr, npts, pdf_self, pdf_other = self.rearrange(other)
|
||||
|
||||
pdf = np.correlate(pdf_self, pdf_other, 'same') * incr
|
||||
|
||||
# shift axis values for correct plotting
|
||||
midpoint = npts / 2
|
||||
x0 = -incr * midpoint
|
||||
|
||||
return ProbabilityDensityFunction(x0, incr, npts, pdf)
|
||||
|
||||
def __nonzero__(self):
|
||||
prec = self.precision(self.incr)
|
||||
gtzero = np.all(self.data >= 0)
|
||||
probone = bool(np.round(self.prob_gt_val(self.axis[0]), prec) == 1.)
|
||||
return bool(gtzero and probone)
|
||||
|
||||
def __str__(self):
|
||||
return str(self.data)
|
||||
|
||||
@staticmethod
|
||||
def precision(incr):
|
||||
prec = int(np.ceil(np.abs(np.log10(incr)))) - 2
|
||||
return prec if prec >= 0 else 0
|
||||
|
||||
@property
|
||||
def data(self):
|
||||
return self._pdf
|
||||
|
||||
@data.setter
|
||||
def data(self, pdf):
|
||||
self._pdf = np.array(pdf)
|
||||
|
||||
@property
|
||||
def axis(self):
|
||||
return self._x
|
||||
|
||||
@axis.setter
|
||||
def axis(self, x):
|
||||
self._x = np.array(x)
|
||||
|
||||
@classmethod
|
||||
def from_pick(self, lbound, barycentre, rbound, incr=0.001, decfact=0.01,
|
||||
type='gauss'):
|
||||
'''
|
||||
Initialize a new ProbabilityDensityFunction object.
|
||||
Takes incr, lbound, barycentre and rbound to derive x0 and the number
|
||||
of points npts for the axis vector.
|
||||
Maximum density
|
||||
is given at the barycentre and on the boundaries the function has
|
||||
declined to decfact times the maximum value. Integration of the
|
||||
function over a particular interval gives the probability for the
|
||||
variable value to be in that interval.
|
||||
'''
|
||||
|
||||
# derive adequate window of definition
|
||||
margin = 2. * np.max([barycentre - lbound, rbound - barycentre])
|
||||
|
||||
# find midpoint accounting also for `~obspy.UTCDateTime` object usage
|
||||
try:
|
||||
midpoint = (rbound + lbound) / 2
|
||||
except TypeError:
|
||||
try:
|
||||
midpoint = (rbound + float(lbound)) / 2
|
||||
except TypeError:
|
||||
midpoint = float(rbound + float(lbound)) / 2
|
||||
|
||||
# find x0 on a grid point and sufficient npts
|
||||
was_datetime = None
|
||||
if isinstance(barycentre, UTCDateTime):
|
||||
barycentre = float(barycentre)
|
||||
was_datetime = True
|
||||
n = int(np.ceil((barycentre - midpoint) / incr))
|
||||
m = int(np.ceil((margin / incr)))
|
||||
midpoint = barycentre - n * incr
|
||||
margin = m * incr
|
||||
x0 = midpoint - margin
|
||||
npts = 2 * m
|
||||
|
||||
if was_datetime:
|
||||
barycentre = UTCDateTime(barycentre)
|
||||
|
||||
# calculate parameter for pdf representing function
|
||||
params = parameter[type](lbound, barycentre, rbound, decfact)
|
||||
|
||||
# calculate pdf values
|
||||
try:
|
||||
pdf = branches[type](create_axis(x0, incr, npts), barycentre, *params)
|
||||
except TypeError as e:
|
||||
print('Warning:\n' + e.message + '\n' + 'trying timestamp instead')
|
||||
assert isinstance(barycentre, UTCDateTime), 'object not capable of' \
|
||||
' timestamp representation'
|
||||
pdf = branches[type](create_axis(x0, incr, npts),
|
||||
barycentre.timestamp, *params)
|
||||
|
||||
# return the object
|
||||
return ProbabilityDensityFunction(x0, incr, npts, pdf)
|
||||
|
||||
def broadcast(self, pdf, si, ei, data):
|
||||
try:
|
||||
pdf[si:ei] = data
|
||||
except ValueError as e:
|
||||
warnings.warn(str(e), Warning)
|
||||
return self.broadcast(pdf, si, ei, data[:-1])
|
||||
return pdf
|
||||
|
||||
def expectation(self):
|
||||
'''
|
||||
returns the expectation value of the actual pdf object
|
||||
|
||||
..formula::
|
||||
mu_{\Delta t} = \int\limits_{-\infty}^\infty x \cdot f(x)dx
|
||||
|
||||
:return float: rval
|
||||
'''
|
||||
|
||||
rval = 0
|
||||
for n, x in enumerate(self.axis):
|
||||
rval += x * self.data[n]
|
||||
return rval * self.incr
|
||||
|
||||
def standard_deviation(self):
|
||||
mu = self.expectation()
|
||||
rval = 0
|
||||
for n, x in enumerate(self.axis):
|
||||
rval += (x - mu) ** 2 * self.data[n]
|
||||
return rval * self.incr
|
||||
|
||||
def prob_lt_val(self, value):
|
||||
if value <= self.axis[0] or value > self.axis[-1]:
|
||||
raise ValueError('value out of bounds: {0}'.format(value))
|
||||
return self.prob_limits((self.axis[0], value))
|
||||
|
||||
def prob_gt_val(self, value):
|
||||
if value < self.axis[0] or value >= self.axis[-1]:
|
||||
raise ValueError('value out of bounds: {0}'.format(value))
|
||||
return self.prob_limits((value, self.axis[-1]))
|
||||
|
||||
def prob_limits(self, limits):
|
||||
lim_ind = np.logical_and(limits[0] <= self.axis, self.axis <= limits[1])
|
||||
data = self.data[lim_ind]
|
||||
min_est, max_est = 0., 0.
|
||||
for n in range(len(data) - 1):
|
||||
min_est += min(data[n], data[n + 1])
|
||||
max_est += max(data[n], data[n + 1])
|
||||
return (min_est + max_est) / 2. * self.incr
|
||||
|
||||
def prob_val(self, value):
|
||||
if not (self.axis[0] <= value <= self.axis[-1]):
|
||||
Warning('{0} not on axis'.format(value))
|
||||
return None
|
||||
return self.data[find_nearest(self.axis, value)] * self.incr
|
||||
|
||||
def plot(self, label=None):
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
plt.plot(self.axis, self.data)
|
||||
plt.xlabel('x')
|
||||
plt.ylabel('f(x)')
|
||||
plt.autoscale(axis='x', tight=True)
|
||||
if self:
|
||||
title_str = 'Probability density function '
|
||||
if label:
|
||||
title_str += label
|
||||
title_str.strip()
|
||||
else:
|
||||
title_str = 'Function not suitable as probability density function'
|
||||
plt.title(title_str)
|
||||
plt.show()
|
||||
|
||||
def commonlimits(self, incr, other, max_npts=1e5):
|
||||
'''
|
||||
Takes an increment incr and two left and two right limits and returns
|
||||
the left most limit and the minimum number of points needed to cover
|
||||
the whole given interval.
|
||||
:param incr:
|
||||
:param l1:
|
||||
:param l2:
|
||||
:param r1:
|
||||
:param r2:
|
||||
:param max_npts:
|
||||
:return:
|
||||
|
||||
'''
|
||||
# >>> manu = ProbabilityDensityFunction.from_pick(0.01, 0.3, 0.5, 0.54)
|
||||
# >>> auto = ProbabilityDensityFunction.from_pick(0.01, 0.3, 0.34, 0.54)
|
||||
# >>> manu.commonlimits(0.01, auto)
|
||||
# (
|
||||
|
||||
l1 = self.x0
|
||||
r1 = l1 + self.incr * self.npts
|
||||
l2 = other.x0
|
||||
r2 = l2 + other.incr * other.npts
|
||||
|
||||
if l1 < l2:
|
||||
x0 = l1
|
||||
else:
|
||||
x0 = l2
|
||||
|
||||
# calculate index for rounding
|
||||
ri = self.precision(incr)
|
||||
|
||||
if r1 < r2:
|
||||
npts = int(round(r2 - x0, ri) // incr)
|
||||
else:
|
||||
npts = int(round(r1 - x0, ri) // incr)
|
||||
|
||||
if npts > max_npts:
|
||||
raise ValueError('Maximum number of points exceeded:\n'
|
||||
'max_npts - %d\n'
|
||||
'npts - %d\n' % (max_npts, npts))
|
||||
|
||||
npts = np.max([npts, self.npts, other.npts])
|
||||
|
||||
if npts < self.npts or npts < other.npts:
|
||||
raise ValueError('new npts is to small')
|
||||
|
||||
return x0, npts
|
||||
|
||||
|
||||
def rearrange(self, other):
|
||||
'''
|
||||
Method rearrange takes another Probability Density Function and returns
|
||||
a new axis with mid-point 0 and covering positive and negative range
|
||||
of axis values, either containing the maximum value of both axis or
|
||||
the sum of the maxima
|
||||
:param other:
|
||||
:return:
|
||||
'''
|
||||
|
||||
assert isinstance(other, ProbabilityDensityFunction), \
|
||||
'both operands must be of type ProbabilityDensityFunction'
|
||||
|
||||
if not self.incr == other.incr:
|
||||
raise NotImplementedError('Upsampling of the lower sampled PDF not implemented yet!')
|
||||
else:
|
||||
incr = self.incr
|
||||
|
||||
x0, npts = self.commonlimits(incr, other)
|
||||
|
||||
pdf_self = np.zeros(npts)
|
||||
pdf_other = np.zeros(npts)
|
||||
|
||||
x = create_axis(x0, incr, npts)
|
||||
|
||||
sstart = find_nearest(x, self.x0)
|
||||
s_end = sstart + self.data.size
|
||||
ostart = find_nearest(x, other.x0)
|
||||
o_end = ostart + other.data.size
|
||||
|
||||
pdf_self = self.broadcast(pdf_self, sstart, s_end, self.data)
|
||||
pdf_other = self.broadcast(pdf_other, ostart, o_end, other.data)
|
||||
|
||||
return x0, incr, npts, pdf_self, pdf_other
|
@ -2,6 +2,7 @@
|
||||
import sys
|
||||
from PySide.QtCore import QThread, Signal
|
||||
|
||||
|
||||
class AutoPickThread(QThread):
|
||||
message = Signal(str)
|
||||
finished = Signal()
|
||||
@ -28,6 +29,5 @@ class AutoPickThread(QThread):
|
||||
sys.stdout = sys.__stdout__
|
||||
self.finished.emit()
|
||||
|
||||
|
||||
def write(self, text):
|
||||
self.message.emit(text)
|
||||
|
@ -10,6 +10,7 @@ import numpy as np
|
||||
from obspy.core import UTCDateTime
|
||||
import obspy.core.event as ope
|
||||
|
||||
|
||||
def createAmplitude(pickID, amp, unit, category, cinfo):
|
||||
'''
|
||||
|
||||
@ -28,6 +29,7 @@ def createAmplitude(pickID, amp, unit, category, cinfo):
|
||||
amplitude.pick_id = pickID
|
||||
return amplitude
|
||||
|
||||
|
||||
def createArrival(pickresID, cinfo, phase, azimuth=None, dist=None):
|
||||
'''
|
||||
createArrival - function to create an Obspy Arrival
|
||||
@ -56,6 +58,7 @@ def createArrival(pickresID, cinfo, phase, azimuth=None, dist=None):
|
||||
arrival.distance = dist
|
||||
return arrival
|
||||
|
||||
|
||||
def createCreationInfo(agency_id=None, creation_time=None, author=None):
|
||||
'''
|
||||
|
||||
@ -71,6 +74,7 @@ def createCreationInfo(agency_id=None, creation_time=None, author=None):
|
||||
return ope.CreationInfo(agency_id=agency_id, author=author,
|
||||
creation_time=creation_time)
|
||||
|
||||
|
||||
def createEvent(origintime, cinfo, originloc=None, etype=None, resID=None,
|
||||
authority_id=None):
|
||||
'''
|
||||
@ -115,6 +119,7 @@ def createEvent(origintime, cinfo, originloc=None, etype=None, resID=None,
|
||||
event.origins = [o]
|
||||
return event
|
||||
|
||||
|
||||
def createMagnitude(originID, cinfo):
|
||||
'''
|
||||
createMagnitude - function to create an ObsPy Magnitude object
|
||||
@ -129,6 +134,7 @@ def createMagnitude(originID, cinfo):
|
||||
magnitude.origin_id = originID
|
||||
return magnitude
|
||||
|
||||
|
||||
def createOrigin(origintime, cinfo, latitude, longitude, depth):
|
||||
'''
|
||||
createOrigin - function to create an ObsPy Origin
|
||||
@ -158,6 +164,7 @@ def createOrigin(origintime, cinfo, latitude, longitude, depth):
|
||||
origin.depth = depth
|
||||
return origin
|
||||
|
||||
|
||||
def createPick(origintime, picknum, picktime, eventnum, cinfo, phase, station,
|
||||
wfseedstr, authority_id):
|
||||
'''
|
||||
@ -196,6 +203,7 @@ def createPick(origintime, picknum, picktime, eventnum, cinfo, phase, station,
|
||||
pick.waveform_id = ope.ResourceIdentifier(id=wfseedstr, prefix='file:/')
|
||||
return pick
|
||||
|
||||
|
||||
def createResourceID(timetohash, restype, authority_id=None, hrstr=None):
|
||||
'''
|
||||
|
||||
@ -220,6 +228,7 @@ def createResourceID(timetohash, restype, authority_id=None, hrstr=None):
|
||||
resID.convertIDToQuakeMLURI(authority_id=authority_id)
|
||||
return resID
|
||||
|
||||
|
||||
def demeanTrace(trace, window):
|
||||
"""
|
||||
returns the DATA where each trace is demean by the average value within
|
||||
@ -234,6 +243,7 @@ def demeanTrace(trace, window):
|
||||
trace.data -= trace.data[window].mean()
|
||||
return trace
|
||||
|
||||
|
||||
def findComboBoxIndex(combo_box, val):
|
||||
"""
|
||||
Function findComboBoxIndex takes a QComboBox object and a string and
|
||||
@ -246,6 +256,18 @@ def findComboBoxIndex(combo_box, val):
|
||||
"""
|
||||
return combo_box.findText(val) if combo_box.findText(val) is not -1 else 0
|
||||
|
||||
|
||||
def find_nearest(array, value):
|
||||
'''
|
||||
Function find_nearest takes an array and a value and returns the
|
||||
index of the nearest value found in the array.
|
||||
:param array:
|
||||
:param value:
|
||||
:return:
|
||||
'''
|
||||
return (np.abs(array - value)).argmin()
|
||||
|
||||
|
||||
def fnConstructor(s):
|
||||
'''
|
||||
|
||||
@ -267,6 +289,7 @@ def fnConstructor(s):
|
||||
fn = '_' + fn
|
||||
return fn
|
||||
|
||||
|
||||
def getGlobalTimes(stream):
|
||||
'''
|
||||
|
||||
@ -283,6 +306,7 @@ def getGlobalTimes(stream):
|
||||
max_end = trace.stats.endtime
|
||||
return min_start, max_end
|
||||
|
||||
|
||||
def getHash(time):
|
||||
'''
|
||||
:param time: time object for which a hash should be calculated
|
||||
@ -293,6 +317,7 @@ def getHash(time):
|
||||
hg.update(time.strftime('%Y-%m-%d %H:%M:%S.%f'))
|
||||
return hg.hexdigest()
|
||||
|
||||
|
||||
def getLogin():
|
||||
'''
|
||||
|
||||
@ -300,6 +325,7 @@ def getLogin():
|
||||
'''
|
||||
return pwd.getpwuid(os.getuid())[0]
|
||||
|
||||
|
||||
def getOwner(fn):
|
||||
'''
|
||||
|
||||
@ -309,6 +335,7 @@ def getOwner(fn):
|
||||
'''
|
||||
return pwd.getpwuid(os.stat(fn).st_uid).pw_name
|
||||
|
||||
|
||||
def getPatternLine(fn, pattern):
|
||||
"""
|
||||
Takes a file name and a pattern string to search for in the file and
|
||||
@ -333,6 +360,7 @@ def getPatternLine(fn, pattern):
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def isSorted(iterable):
|
||||
'''
|
||||
|
||||
@ -342,6 +370,7 @@ def isSorted(iterable):
|
||||
'''
|
||||
return sorted(iterable) == iterable
|
||||
|
||||
|
||||
def prepTimeAxis(stime, trace):
|
||||
'''
|
||||
|
||||
@ -368,6 +397,7 @@ def prepTimeAxis(stime, trace):
|
||||
'delta: {2}'.format(nsamp, len(time_ax), tincr))
|
||||
return time_ax
|
||||
|
||||
|
||||
def scaleWFData(data, factor=None, components='all'):
|
||||
"""
|
||||
produce scaled waveforms from given waveform data and a scaling factor,
|
||||
@ -399,6 +429,7 @@ def scaleWFData(data, factor=None, components='all'):
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def runProgram(cmd, parameter=None):
|
||||
"""
|
||||
run an external program specified by cmd with parameters input returning the
|
||||
@ -419,6 +450,8 @@ def runProgram(cmd, parameter=None):
|
||||
output = subprocess.check_output('{} | tee /dev/stderr'.format(cmd),
|
||||
shell=True)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import doctest
|
||||
|
||||
doctest.testmod()
|
||||
|
@ -31,12 +31,15 @@
|
||||
#
|
||||
# include RELEASE-VERSION
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
__all__ = "get_git_version"
|
||||
|
||||
# NO IMPORTS FROM PYLOT IN THIS FILE! (file gets used at installation time)
|
||||
import os
|
||||
import inspect
|
||||
from subprocess import Popen, PIPE
|
||||
|
||||
# NO IMPORTS FROM PYLOT IN THIS FILE! (file gets used at installation time)
|
||||
|
||||
script_dir = os.path.abspath(os.path.dirname(inspect.getfile(
|
||||
@ -108,4 +111,4 @@ def get_git_version(abbrev=4):
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
print get_git_version()
|
||||
print(get_git_version())
|
||||
|
@ -5,10 +5,12 @@ Created on Wed Mar 19 11:27:35 2014
|
||||
@author: sebastianw
|
||||
"""
|
||||
|
||||
import warnings
|
||||
import datetime
|
||||
import numpy as np
|
||||
|
||||
from matplotlib.figure import Figure
|
||||
|
||||
try:
|
||||
from matplotlib.backends.backend_qt4agg import FigureCanvas
|
||||
except ImportError:
|
||||
@ -25,7 +27,8 @@ from obspy import Stream, UTCDateTime
|
||||
from pylot.core.read.inputs import FilterOptions
|
||||
from pylot.core.pick.utils import getSNR, earllatepicker, getnoisewin, \
|
||||
getResolutionWindow
|
||||
from pylot.core.util.defaults import OUTPUTFORMATS, FILTERDEFAULTS, LOCTOOLS
|
||||
from pylot.core.util.defaults import OUTPUTFORMATS, FILTERDEFAULTS, LOCTOOLS, \
|
||||
COMPPOSITION_MAP
|
||||
from pylot.core.util.utils import prepTimeAxis, getGlobalTimes, scaleWFData, \
|
||||
demeanTrace, isSorted, findComboBoxIndex
|
||||
|
||||
@ -63,7 +66,7 @@ class MPLWidget(FigureCanvas):
|
||||
# clear axes each time plot is called
|
||||
self.axes.hold(True)
|
||||
# initialize super class
|
||||
FigureCanvas.__init__(self, self.figure)
|
||||
super(MPLWidget, self).__init__(self.figure)
|
||||
# add an cursor for station selection
|
||||
self.multiCursor = MultiCursor(self.figure.canvas, (self.axes,),
|
||||
horizOn=True,
|
||||
@ -87,13 +90,19 @@ class MPLWidget(FigureCanvas):
|
||||
self._parent = parent
|
||||
|
||||
def plotWFData(self, wfdata, title=None, zoomx=None, zoomy=None,
|
||||
noiselevel=None, scaleddata=False):
|
||||
noiselevel=None, scaleddata=False, mapping=True):
|
||||
self.getAxes().cla()
|
||||
self.clearPlotDict()
|
||||
wfstart, wfend = getGlobalTimes(wfdata)
|
||||
nmax = 0
|
||||
for n, trace in enumerate(wfdata):
|
||||
channel = trace.stats.channel
|
||||
station = trace.stats.station
|
||||
if mapping:
|
||||
comp = channel[-1]
|
||||
n = COMPPOSITION_MAP[comp]
|
||||
if n > nmax:
|
||||
nmax = n
|
||||
msg = 'plotting %s channel of station %s' % (channel, station)
|
||||
print(msg)
|
||||
stime = trace.stats.starttime - wfstart
|
||||
@ -110,7 +119,7 @@ class MPLWidget(FigureCanvas):
|
||||
ylabel = ''
|
||||
self.updateWidget(xlabel, ylabel, title)
|
||||
self.setXLims([0, wfend - wfstart])
|
||||
self.setYLims([-0.5, n + 0.5])
|
||||
self.setYLims([-0.5, nmax + 0.5])
|
||||
if zoomx is not None:
|
||||
self.setXLims(zoomx)
|
||||
if zoomy is not None:
|
||||
@ -160,6 +169,7 @@ class MPLWidget(FigureCanvas):
|
||||
xycoords='axes fraction')
|
||||
axann.set_bbox(dict(facecolor='lightgrey', alpha=.6))
|
||||
|
||||
|
||||
class PickDlg(QDialog):
|
||||
def __init__(self, parent=None, data=None, station=None, picks=None,
|
||||
rotate=False):
|
||||
@ -169,11 +179,14 @@ class PickDlg(QDialog):
|
||||
self.station = station
|
||||
self.rotate = rotate
|
||||
self.components = 'ZNE'
|
||||
settings = QSettings()
|
||||
self._user = settings.value('user/Login', 'anonymous')
|
||||
if picks:
|
||||
self.picks = picks
|
||||
else:
|
||||
self.picks = {}
|
||||
self.filteroptions = FILTERDEFAULTS
|
||||
self.pick_block = False
|
||||
|
||||
# initialize panning attributes
|
||||
self.press = None
|
||||
@ -247,8 +260,7 @@ class PickDlg(QDialog):
|
||||
slot=self.filterWFData,
|
||||
icon=filter_icon,
|
||||
tip='Toggle filtered/original'
|
||||
' waveforms',
|
||||
checkable=True)
|
||||
' waveforms')
|
||||
self.zoomAction = createAction(parent=self, text='Zoom',
|
||||
slot=self.zoom, icon=zoom_icon,
|
||||
tip='Zoom into waveform',
|
||||
@ -337,6 +349,10 @@ class PickDlg(QDialog):
|
||||
return widget.mpl_connect('button_release_event', slot)
|
||||
|
||||
def verifyPhaseSelection(self):
|
||||
if self.pick_block:
|
||||
self.pick_block = self.togglePickBlocker()
|
||||
warnings.warn('Changed selection before phase was set!',
|
||||
UserWarning)
|
||||
phase = self.selectPhase.currentText()
|
||||
self.updateCurrentLimits()
|
||||
if phase:
|
||||
@ -348,6 +364,7 @@ class PickDlg(QDialog):
|
||||
self.disconnectPressEvent()
|
||||
self.cidpress = self.connectPressEvent(self.setIniPick)
|
||||
self.filterWFData()
|
||||
self.pick_block = self.togglePickBlocker()
|
||||
else:
|
||||
self.disconnectPressEvent()
|
||||
self.cidpress = self.connectPressEvent(self.panPress)
|
||||
@ -383,6 +400,9 @@ class PickDlg(QDialog):
|
||||
traceIDs.append(traceID)
|
||||
return traceIDs
|
||||
|
||||
def getUser(self):
|
||||
return self._user
|
||||
|
||||
def getFilterOptions(self, phase):
|
||||
options = self.filteroptions[phase]
|
||||
return FilterOptions(**options)
|
||||
@ -422,6 +442,11 @@ class PickDlg(QDialog):
|
||||
trace = selectTrace(trace, 'NE')
|
||||
if trace:
|
||||
wfdata.append(trace)
|
||||
elif component == '1' or component == '2':
|
||||
for trace in self.getWFData():
|
||||
trace = selectTrace(trace, '12')
|
||||
if trace:
|
||||
wfdata.append(trace)
|
||||
elif component == 'Z':
|
||||
wfdata = self.getWFData().select(component=component)
|
||||
return wfdata
|
||||
@ -470,8 +495,22 @@ class PickDlg(QDialog):
|
||||
noise_win = settings.value('picking/noise_win_P', 5.)
|
||||
gap_win = settings.value('picking/gap_win_P', .2)
|
||||
signal_win = settings.value('picking/signal_win_P', 3.)
|
||||
itrace = int(trace_number)
|
||||
|
||||
result = getSNR(wfdata, (noise_win, gap_win, signal_win), ini_pick)
|
||||
while itrace > len(wfdata) - 1:
|
||||
itrace -= 1
|
||||
|
||||
# copy data for plotting
|
||||
data = self.getWFData().copy()
|
||||
|
||||
# filter data and trace on which is picked prior to determination of SNR
|
||||
phase = self.selectPhase.currentText()
|
||||
filteroptions = self.getFilterOptions(phase).parseFilterOptions()
|
||||
if filteroptions:
|
||||
data.filter(**filteroptions)
|
||||
wfdata.filter(**filteroptions)
|
||||
|
||||
result = getSNR(wfdata, (noise_win, gap_win, signal_win), ini_pick, itrace)
|
||||
|
||||
snr = result[0]
|
||||
noiselevel = result[2] * nfac
|
||||
@ -479,8 +518,7 @@ class PickDlg(QDialog):
|
||||
x_res = getResolutionWindow(snr)
|
||||
|
||||
# remove mean noise level from waveforms
|
||||
wfdata = self.getWFData().copy()
|
||||
for trace in wfdata:
|
||||
for trace in data:
|
||||
t = prepTimeAxis(trace.stats.starttime - self.getStartTime(), trace)
|
||||
inoise = getnoisewin(t, ini_pick, noise_win, gap_win)
|
||||
trace = demeanTrace(trace=trace, window=inoise)
|
||||
@ -488,7 +526,7 @@ class PickDlg(QDialog):
|
||||
self.setXLims([ini_pick - x_res, ini_pick + x_res])
|
||||
self.setYLims(np.array([-noiselevel * 2.5, noiselevel * 2.5]) +
|
||||
trace_number)
|
||||
self.getPlotWidget().plotWFData(wfdata=wfdata,
|
||||
self.getPlotWidget().plotWFData(wfdata=data,
|
||||
title=self.getStation() +
|
||||
' picking mode',
|
||||
zoomx=self.getXLims(),
|
||||
@ -502,29 +540,39 @@ class PickDlg(QDialog):
|
||||
|
||||
settings = QSettings()
|
||||
|
||||
nfac = settings.value('picking/nfac_P', 1.5)
|
||||
noise_win = settings.value('picking/noise_win_P', 5.)
|
||||
gap_win = settings.value('picking/gap_win_P', .2)
|
||||
signal_win = settings.value('picking/signal_win_P', 3.)
|
||||
nfac = settings.value('picking/nfac_S', 1.5)
|
||||
noise_win = settings.value('picking/noise_win_S', 5.)
|
||||
gap_win = settings.value('picking/gap_win_S', .2)
|
||||
signal_win = settings.value('picking/signal_win_S', 3.)
|
||||
|
||||
# copy data for plotting
|
||||
data = self.getWFData().copy()
|
||||
|
||||
# filter data and trace on which is picked prior to determination of SNR
|
||||
phase = self.selectPhase.currentText()
|
||||
filteroptions = self.getFilterOptions(phase).parseFilterOptions()
|
||||
if filteroptions:
|
||||
data.filter(**filteroptions)
|
||||
wfdata.filter(**filteroptions)
|
||||
|
||||
# determine SNR and noiselevel
|
||||
result = getSNR(wfdata, (noise_win, gap_win, signal_win), ini_pick)
|
||||
|
||||
snr = result[0]
|
||||
noiselevel = result[2] * nfac
|
||||
|
||||
data = self.getWFData().copy()
|
||||
|
||||
phase = self.selectPhase.currentText()
|
||||
filteroptions = self.getFilterOptions(phase).parseFilterOptions()
|
||||
data.filter(**filteroptions)
|
||||
|
||||
# prepare plotting of data
|
||||
for trace in data:
|
||||
t = prepTimeAxis(trace.stats.starttime - self.getStartTime(), trace)
|
||||
inoise = getnoisewin(t, ini_pick, noise_win, gap_win)
|
||||
trace = demeanTrace(trace, inoise)
|
||||
|
||||
# account for non-oriented horizontal waveforms
|
||||
try:
|
||||
horiz_comp = ('n', 'e')
|
||||
|
||||
data = scaleWFData(data, noiselevel * 2.5, horiz_comp)
|
||||
except IndexError as e:
|
||||
print('warning: {0}'.format(e))
|
||||
horiz_comp = ('1', '2')
|
||||
data = scaleWFData(data, noiselevel * 2.5, horiz_comp)
|
||||
|
||||
x_res = getResolutionWindow(snr)
|
||||
@ -554,21 +602,28 @@ class PickDlg(QDialog):
|
||||
pick = gui_event.xdata # get pick time relative to the traces timeaxis not to the global
|
||||
channel = self.getChannelID(round(gui_event.ydata))
|
||||
|
||||
wfdata = self.getWFData().copy().select(channel=channel)
|
||||
stime = self.getStartTime()
|
||||
# get earliest and latest possible pick and symmetric pick error
|
||||
[epp, lpp, spe] = earllatepicker(wfdata, 1.5, (5., .5, 2.), pick)
|
||||
|
||||
# get name of phase actually picked
|
||||
phase = self.selectPhase.currentText()
|
||||
|
||||
# get filter parameter for the phase to be picked
|
||||
filteroptions = self.getFilterOptions(phase).parseFilterOptions()
|
||||
|
||||
# copy and filter data for earliest and latest possible picks
|
||||
wfdata = self.getWFData().copy().select(channel=channel)
|
||||
wfdata.filter(**filteroptions)
|
||||
|
||||
# get earliest and latest possible pick and symmetric pick error
|
||||
[epp, lpp, spe] = earllatepicker(wfdata, 1.5, (5., .5, 2.), pick)
|
||||
|
||||
# return absolute time values for phases
|
||||
stime = self.getStartTime()
|
||||
epp = stime + epp
|
||||
mpp = stime + pick
|
||||
lpp = stime + lpp
|
||||
|
||||
# save pick times for actual phase
|
||||
phasepicks = {'epp': epp, 'lpp': lpp, 'mpp': mpp, 'spe': spe}
|
||||
phasepicks = dict(epp=epp, lpp=lpp, mpp=mpp, spe=spe,
|
||||
picker=self.getUser())
|
||||
|
||||
try:
|
||||
oldphasepick = self.picks[phase]
|
||||
@ -601,6 +656,7 @@ class PickDlg(QDialog):
|
||||
self.drawPicks()
|
||||
self.disconnectPressEvent()
|
||||
self.zoomAction.setEnabled(True)
|
||||
self.pick_block = self.togglePickBlocker()
|
||||
self.selectPhase.setCurrentIndex(-1)
|
||||
self.setPlotLabels()
|
||||
|
||||
@ -660,7 +716,12 @@ class PickDlg(QDialog):
|
||||
|
||||
ax.figure.canvas.draw()
|
||||
|
||||
def togglePickBlocker(self):
|
||||
return not self.pick_block
|
||||
|
||||
def filterWFData(self):
|
||||
if self.pick_block:
|
||||
return
|
||||
self.updateCurrentLimits()
|
||||
data = self.getWFData().copy()
|
||||
old_title = self.getPlotWidget().getAxes().get_title()
|
||||
@ -675,13 +736,15 @@ class PickDlg(QDialog):
|
||||
filtoptions = filtoptions.parseFilterOptions()
|
||||
if filtoptions is not None:
|
||||
data.filter(**filtoptions)
|
||||
if old_title.endswith(')'):
|
||||
title = old_title[:-1] + ', filtered)'
|
||||
else:
|
||||
if not old_title.endswith(')'):
|
||||
title = old_title + ' (filtered)'
|
||||
elif not old_title.endswith(' (filtered)') and not old_title.endswith(', filtered)'):
|
||||
title = old_title[:-1] + ', filtered)'
|
||||
else:
|
||||
if old_title.endswith(' (filtered)'):
|
||||
title = old_title.replace(' (filtered)', '')
|
||||
elif old_title.endswith(', filtered)'):
|
||||
title = old_title.replace(', filtered)', ')')
|
||||
if title is None:
|
||||
title = old_title
|
||||
self.getPlotWidget().plotWFData(wfdata=data, title=title,
|
||||
@ -702,7 +765,6 @@ class PickDlg(QDialog):
|
||||
self.drawPicks()
|
||||
self.draw()
|
||||
|
||||
|
||||
def setPlotLabels(self):
|
||||
|
||||
# get channel labels
|
||||
@ -715,7 +777,9 @@ class PickDlg(QDialog):
|
||||
self.getPlotWidget().setYLims(self.getYLims())
|
||||
|
||||
def zoom(self):
|
||||
if self.zoomAction.isChecked():
|
||||
if self.zoomAction.isChecked() and self.pick_block:
|
||||
self.zoomAction.setChecked(False)
|
||||
elif self.zoomAction.isChecked():
|
||||
self.disconnectPressEvent()
|
||||
self.disconnectMotionEvent()
|
||||
self.disconnectReleaseEvent()
|
||||
@ -995,7 +1059,6 @@ class LocalisationTab(PropTab):
|
||||
return values
|
||||
|
||||
|
||||
|
||||
class NewEventDlg(QDialog):
|
||||
def __init__(self, parent=None, titleString="Create a new event"):
|
||||
"""
|
||||
@ -1236,6 +1299,8 @@ class HelpForm(QDialog):
|
||||
def updatePageTitle(self):
|
||||
self.pageLabel.setText(self.webBrowser.documentTitle())
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import doctest
|
||||
|
||||
doctest.testmod()
|
||||
|
@ -9,8 +9,8 @@
|
||||
from obspy.core import read
|
||||
import matplotlib.pyplot as plt
|
||||
import numpy as np
|
||||
from pylot.core.pick.CharFuns import *
|
||||
from pylot.core.pick.Picker import *
|
||||
from pylot.core.pick.charfuns import *
|
||||
from pylot.core.pick.picker import *
|
||||
import glob
|
||||
import argparse
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user