coppied files from Ludgers Laptop

This commit is contained in:
2017-04-06 13:16:28 +02:00
parent f5c06cd6b7
commit c90b061de9
56 changed files with 64030 additions and 244 deletions

View File

@@ -1 +1 @@
0.1a
f5c0-dirty

0
pylot/__init__.py Executable file → Normal file
View File

0
pylot/core/__init__.py Executable file → Normal file
View File

View File

@@ -6,19 +6,16 @@ Created autumn/winter 2015.
:author: Ludger Küperkoch / MAGS2 EP3 working group
"""
import os
import matplotlib.pyplot as plt
import numpy as np
import obspy.core.event as ope
from obspy.geodetics import degrees2kilometers
from scipy import integrate, signal
from scipy.optimize import curve_fit
from pylot.core.pick.utils import getsignalwin, crossings_nonzero_all, \
select_for_phase
from pylot.core.util.utils import common_range, fit_curve
def richter_magnitude_scaling(delta):
relation = np.loadtxt(os.path.join(os.path.expanduser('~'),
'.pylot', 'richter_scaling.data'))
@@ -200,8 +197,8 @@ class RichterMagnitude(Magnitude):
iwin = getsignalwin(th, t0 - stime, self.calc_win)
wapp = np.max(sqH[iwin])
if self.verbose:
print("Determined Wood-Anderson peak-to-peak amplitude: {0} "
"mm".format(wapp))
print("Determined Wood-Anderson peak-to-peak amplitude for station {0}: {1} "
"mm".format(st[0].stats.station, wapp))
# check for plot flag (for debugging only)
if self.plot_flag > 1:
@@ -317,8 +314,8 @@ class MomentMagnitude(Magnitude):
continue
pick = a.pick_id.get_referred_object()
station = pick.waveform_id.station_code
wf = select_for_phase(self.stream.select(
station=station), a.phase)
scopy = self.stream.copy()
wf = scopy.select(station=station)
if not wf:
continue
onset = pick.time
@@ -326,15 +323,16 @@ class MomentMagnitude(Magnitude):
azimuth = a.azimuth
incidence = a.takeoff_angle
w0, fc = calcsourcespec(wf, onset, self.p_velocity, distance,
azimuth,
incidence, self.p_attenuation,
azimuth, incidence, self.p_attenuation,
self.plot_flag, self.verbose)
if w0 is None or fc is None:
if self.verbose:
print("WARNING: insufficient frequency information")
continue
wf = select_for_phase(wf, "P")
m0, mw = calcMoMw(wf, w0, self.rock_density, self.p_velocity,
WF = select_for_phase(self.stream.select(
station=station), a.phase)
WF = select_for_phase(WF, "P")
m0, mw = calcMoMw(WF, w0, self.rock_density, self.p_velocity,
distance, self.verbose)
self.moment_props = (station, dict(w0=w0, fc=fc, Mo=m0))
magnitude = ope.StationMagnitude(mag=mw)
@@ -426,7 +424,7 @@ def calcsourcespec(wfstream, onset, vp, delta, azimuth, incidence,
:type: integer
'''
if verbosity:
print ("Calculating source spectrum ....")
print ("Calculating source spectrum for station %s ...." % wfstream[0].stats.station)
# get Q value
Q, A = qp
@@ -453,18 +451,21 @@ def calcsourcespec(wfstream, onset, vp, delta, azimuth, incidence,
LQT = wfstream.rotate('ZNE->LQT', azimuth, incidence)
ldat = LQT.select(component="L")
if len(ldat) == 0:
# if horizontal channels are 2 and 3
# if horizontal channels are 1 and 2
# no azimuth information is available and thus no
# rotation is possible!
if verbosity:
print("calcsourcespec: Azimuth information is missing, "
"no rotation of components possible!")
ldat = LQT.select(component="Z")
# instead, use component 3
ldat = LQT.select(component="3")
if len(ldat) == 0:
# maybe component z available
ldat = LQT.select(component="Z")
# integrate to displacement
# unrotated vertical component (for comparison)
inttrz = signal.detrend(integrate.cumtrapz(zdat[0].data, None, dt))
# rotated component Z => L
Ldat = signal.detrend(integrate.cumtrapz(ldat[0].data, None, dt))
@@ -527,22 +528,24 @@ def calcsourcespec(wfstream, onset, vp, delta, azimuth, incidence,
# use of implicit scipy otimization function
fit = synthsourcespec(F, w0in, Fcin)
[optspecfit, _] = curve_fit(synthsourcespec, F, YYcor, [w0in, Fcin])
w01 = optspecfit[0]
fc1 = optspecfit[1]
w0 = optspecfit[0]
fc = optspecfit[1]
#w01 = optspecfit[0]
#fc1 = optspecfit[1]
if verbosity:
print ("calcsourcespec: Determined w0-value: %e m/Hz, \n"
"Determined corner frequency: %f Hz" % (w01, fc1))
"calcsourcespec: Determined corner frequency: %f Hz" % (w0, fc))
# use of conventional fitting
[w02, fc2] = fitSourceModel(F, YYcor, Fcin, iplot, verbosity)
# [w02, fc2] = fitSourceModel(F, YYcor, Fcin, iplot, verbosity)
# get w0 and fc as median of both
# source spectrum fits
w0 = np.median([w01, w02])
fc = np.median([fc1, fc2])
if verbosity:
print("calcsourcespec: Using w0-value = %e m/Hz and fc = %f Hz" % (
w0, fc))
#w0 = np.median([w01, w02])
#fc = np.median([fc1, fc2])
#if verbosity:
# print("calcsourcespec: Using w0-value = %e m/Hz and fc = %f Hz" % (
# w0, fc))
if iplot > 1:
f1 = plt.figure()
@@ -627,18 +630,35 @@ def fitSourceModel(f, S, fc0, iplot, verbosity=False):
fc = []
stdfc = []
STD = []
# get window around initial corner frequency for trials
fcstopl = fc0 - max(1, len(f) / 10)
il = np.argmin(abs(f - fcstopl))
fcstopl = f[il]
fcstopr = fc0 + min(len(f), len(f) / 10)
ir = np.argmin(abs(f - fcstopr))
fcstopr = f[ir]
iF = np.where((f >= fcstopl) & (f <= fcstopr))
# left side of initial corner frequency
fcstopl = max(f[0], fc0 - max(1, fc0 / 2))
il = np.where(f <= fcstopl)
il = il[0][np.size(il) - 1]
# right side of initial corner frequency
fcstopr = min(fc0 + (fc0 / 2), f[len(f) - 1])
ir = np.where(f >= fcstopr)
# check, if fcstopr is available
if np.size(ir) == 0:
fcstopr = fc0
ir = len(f) - 1
else:
ir = ir[0][0]
# vary corner frequency around initial point
for i in range(il, ir):
print("fitSourceModel: Varying corner frequency "
"around initial corner frequency ...")
# check difference of il and ir in order to
# keep calculation time acceptable
idiff = ir - il
if idiff > 10000:
increment = 100
elif idiff <= 20:
increment = 1
else:
increment = 10
for i in range(il, ir, increment):
FC = f[i]
indexdc = np.where((f > 0) & (f <= FC))
dc = np.mean(S[indexdc])

View File

@@ -6,13 +6,11 @@ import os
from obspy import read_events
from obspy.core import read, Stream, UTCDateTime
from obspy.core.event import Event
from pylot.core.io.phases import readPILOTEvent, picks_from_picksdict, \
picksdict_from_pilot, merge_picks
from pylot.core.util.errors import FormatError, OverwriteError
from pylot.core.util.utils import fnConstructor, full_range
class Data(object):
"""
Data container with attributes wfdata holding ~obspy.core.stream.
@@ -298,10 +296,20 @@ class Data(object):
"""
#firstonset = find_firstonset(picks)
if self.get_evt_data().picks:
raise OverwriteError('Actual picks would be overwritten!')
else:
picks = picks_from_picksdict(picks)
# check for automatic picks
print("Writing phases to ObsPy-quakeml file")
for key in picks:
if picks[key]['P']['picker'] == 'auto':
print("Existing picks will be overwritten!")
picks = picks_from_picksdict(picks)
break
else:
if self.get_evt_data().picks:
raise OverwriteError('Existing picks would be overwritten!')
break
else:
picks = picks_from_picksdict(picks)
break
self.get_evt_data().picks = picks
# if 'smi:local' in self.getID() and firstonset:
# fonset_str = firstonset.strftime('%Y_%m_%d_%H_%M_%S')

View File

@@ -14,7 +14,6 @@ from pylot.core.io.location import create_arrival, create_event, \
from pylot.core.pick.utils import select_for_phase
from pylot.core.util.utils import getOwner, full_range, four_digits
def add_amplitudes(event, amplitudes):
amplitude_list = []
for pick in event.picks:
@@ -233,6 +232,8 @@ def picks_from_picksdict(picks, creation_info=None):
if not isinstance(phase, dict):
continue
onset = phase['mpp']
ccode = phase['channel']
ncode = phase['network']
pick = ope.Pick()
if creation_info:
pick.creation_info = creation_info
@@ -253,7 +254,9 @@ def picks_from_picksdict(picks, creation_info=None):
picker = 'Unknown'
pick.phase_hint = label
pick.method_id = ope.ResourceIdentifier(id=picker)
pick.waveform_id = ope.WaveformStreamID(station_code=station)
pick.waveform_id = ope.WaveformStreamID(station_code=station,
channel_code=ccode,
network_code=ncode)
try:
polarity = phase['fm']
if polarity == 'U' or '+':
@@ -384,7 +387,7 @@ def reassess_pilot_event(root_dir, db_dir, event_id, out_dir=None, fn_param=None
#evt.write(fnout_prefix + 'cnv', format='VELEST')
def writephases(arrivals, fformat, filename):
def writephases(arrivals, fformat, filename, parameter, eventinfo=None):
"""
Function of methods to write phases to the following standard file
formats used for locating earthquakes:
@@ -402,17 +405,25 @@ def writephases(arrivals, fformat, filename):
HYPOINVERSE, and hypoDD
:param: filename, full path and name of phase file
:type: string
"""
:type: string
:param: parameter, all input information
:type: object
:param: eventinfo, optional, needed for VELEST-cnv file
and FOCMEC- and HASH-input files
:type: `obspy.core.event.Event` object
"""
if fformat == 'NLLoc':
print ("Writing phases to %s for NLLoc" % filename)
fid = open("%s" % filename, 'w')
# write header
fid.write('# EQEVENT: Label: EQ001 Loc: X 0.00 Y 0.00 Z 10.00 OT 0.00 \n')
fid.write('# EQEVENT: %s Label: EQ%s Loc: X 0.00 Y 0.00 Z 10.00 OT 0.00 \n' %
(parameter.get('database'), parameter.get('eventID')))
for key in arrivals:
# P onsets
if arrivals[key]['P']:
if arrivals[key].has_key('P'):
try:
fm = arrivals[key]['P']['fm']
except KeyError as e:
@@ -477,9 +488,13 @@ def writephases(arrivals, fformat, filename):
print ("Writing phases to %s for HYPO71" % filename)
fid = open("%s" % filename, 'w')
# write header
fid.write(' EQ001\n')
fid.write(' %s\n' %
parameter.get('eventID'))
for key in arrivals:
if arrivals[key]['P']['weight'] < 4:
stat = key
if len(stat) > 4: # HYPO71 handles only 4-string station IDs
stat = stat[1:5]
Ponset = arrivals[key]['P']['mpp']
Sonset = arrivals[key]['S']['mpp']
pweight = arrivals[key]['P']['weight']
@@ -517,7 +532,7 @@ def writephases(arrivals, fformat, filename):
sstr = 'I'
elif sweight >= 2:
sstr = 'E'
fid.write('%s%sP%s%d %02d%02d%02d%02d%02d%5.2f %s%sS %d %s\n' % (key,
fid.write('%-4s%sP%s%d %02d%02d%02d%02d%02d%5.2f %s%sS %d %s\n' % (stat,
pstr,
fm,
pweight,
@@ -532,7 +547,7 @@ def writephases(arrivals, fformat, filename):
sweight,
Ao))
else:
fid.write('%s%sP%s%d %02d%02d%02d%02d%02d%5.2f %s\n' % (key,
fid.write('%-4s%sP%s%d %02d%02d%02d%02d%02d%5.2f %s\n' % (stat,
pstr,
fm,
pweight,
@@ -546,6 +561,258 @@ def writephases(arrivals, fformat, filename):
fid.close()
elif fformat == 'HYPOSAT':
print ("Writing phases to %s for HYPOSAT" % filename)
fid = open("%s" % filename, 'w')
# write header
fid.write('%s, event %s \n' % (parameter.get('database'), parameter.get('eventID')))
errP = parameter.get('timeerrorsP')
errS = parameter.get('timeerrorsS')
for key in arrivals:
# P onsets
if arrivals[key].has_key('P'):
if arrivals[key]['P']['weight'] < 4:
Ponset = arrivals[key]['P']['mpp']
pyear = Ponset.year
pmonth = Ponset.month
pday = Ponset.day
phh = Ponset.hour
pmm = Ponset.minute
pss = Ponset.second
pms = Ponset.microsecond
Pss = pss + pms / 1000000.0
# use symmetrized picking error as std
# (read the HYPOSAT manual)
pstd = arrivals[key]['P']['spe']
fid.write('%-5s P1 %4.0f %02d %02d %02d %02d %05.02f %5.3f -999. 0.00 -999. 0.00\n'
% (key, pyear, pmonth, pday, phh, pmm, Pss, pstd))
# S onsets
if arrivals[key].has_key('S') and arrivals[key]['S']:
if arrivals[key]['S']['weight'] < 4:
Sonset = arrivals[key]['S']['mpp']
syear = Sonset.year
smonth = Sonset.month
sday = Sonset.day
shh = Sonset.hour
smm = Sonset.minute
sss = Sonset.second
sms = Sonset.microsecond
Sss = sss + sms / 1000000.0
sstd = arrivals[key]['S']['spe']
fid.write('%-5s S1 %4.0f %02d %02d %02d %02d %05.02f %5.3f -999. 0.00 -999. 0.00\n'
% (key, syear, smonth, sday, shh, smm, Sss, sstd))
fid.close()
elif fformat == 'VELEST':
print ("Writing phases to %s for VELEST" % filename)
fid = open("%s" % filename, 'w')
# get informations needed in cnv-file
# check, whether latitude is N or S and longitude is E or W
eventsource = eventinfo.origins[0]
if eventsource['latitude'] < 0:
cns = 'S'
else:
cns = 'N'
if eventsource['longitude'] < 0:
cew = 'W'
else:
cew = 'E'
# get last two integers of origin year
stime = eventsource['time']
if stime.year - 2000 >= 0:
syear = stime.year - 2000
else:
syear = stime.year - 1900
ifx = 0 # default value, see VELEST manual, pp. 22-23
# write header
fid.write('%s%02d%02d %02d%02d %05.2f %7.4f%c %8.4f%c %7.2f %6.2f %02.0f 0.0 0.03 1.0 1.0\n' % (
syear, stime.month, stime.day, stime.hour, stime.minute, stime.second, eventsource['latitude'],
cns, eventsource['longitude'], cew, eventsource['depth'],eventinfo.magnitudes[0]['mag'], ifx))
n = 0
for key in arrivals:
# P onsets
if arrivals[key].has_key('P'):
if arrivals[key]['P']['weight'] < 4:
n += 1
stat = key
if len(stat) > 4: # VELEST handles only 4-string station IDs
stat = stat[1:5]
Ponset = arrivals[key]['P']['mpp']
Pweight = arrivals[key]['P']['weight']
Prt = Ponset - stime # onset time relative to source time
if n % 6 is not 0:
fid.write('%-4sP%d%6.2f' % (stat, Pweight, Prt))
else:
fid.write('%-4sP%d%6.2f\n' % (stat, Pweight, Prt))
# S onsets
if arrivals[key].has_key('S'):
if arrivals[key]['S']['weight'] < 4:
n += 1
stat = key
if len(stat) > 4: # VELEST handles only 4-string station IDs
stat = stat[1:5]
Sonset = arrivals[key]['S']['mpp']
Sweight = arrivals[key]['S']['weight']
Srt = Ponset - stime # onset time relative to source time
if n % 6 is not 0:
fid.write('%-4sS%d%6.2f' % (stat, Sweight, Srt))
else:
fid.write('%-4sS%d%6.2f\n' % (stat, Sweight, Srt))
fid.close()
elif fformat == 'hypoDD':
print ("Writing phases to %s for hypoDD" % filename)
fid = open("%s" % filename, 'w')
# get event information needed for hypoDD-phase file
eventsource = eventinfo.origins[0]
stime = eventsource['time']
event = parameter.get('eventID')
hddID = event.split('.')[0][1:5]
# write header
fid.write('# %d %d %d %d %d %5.2f %7.4f +%6.4f %7.4f %4.2f 0.1 0.5 %4.2f %s\n' % (
stime.year, stime.month, stime.day, stime.hour, stime.minute, stime.second,
eventsource['latitude'], eventsource['longitude'], eventsource['depth'] / 1000,
eventinfo.magnitudes[0]['mag'], eventsource['quality']['standard_error'], hddID))
for key in arrivals:
if arrivals[key].has_key('P'):
# P onsets
if arrivals[key]['P']['weight'] < 4:
Ponset = arrivals[key]['P']['mpp']
Prt = Ponset - stime # onset time relative to source time
fid.write('%s %6.3f 1 P\n' % (key, Prt))
# S onsets
if arrivals[key]['S']['weight'] < 4:
Sonset = arrivals[key]['S']['mpp']
Srt = Sonset - stime # onset time relative to source time
fid.write('%-5s %6.3f 1 S\n' % (key, Srt))
fid.close()
elif fformat == 'FOCMEC':
print ("Writing phases to %s for FOCMEC" % filename)
fid = open("%s" % filename, 'w')
# get event information needed for FOCMEC-input file
eventsource = eventinfo.origins[0]
stime = eventsource['time']
# write header line including event information
fid.write('%s %d%02d%02d%02d%02d%02.0f %7.4f %6.4f %3.1f %3.1f\n' % (parameter.get('eventID'),
stime.year, stime.month, stime.day, stime.hour, stime.minute, stime.second,
eventsource['latitude'], eventsource['longitude'], eventsource['depth'] / 1000,
eventinfo.magnitudes[0]['mag']))
picks = eventinfo.picks
for key in arrivals:
if arrivals[key].has_key('P'):
if arrivals[key]['P']['weight'] < 4 and arrivals[key]['P']['fm'] is not None:
stat = key
for i in range(len(picks)):
station = picks[i].waveform_id.station_code
if station == stat:
# get resource ID
resid_picks = picks[i].get('resource_id')
# find same ID in eventinfo
# there it is the pick_id!!
for j in range(len(eventinfo.origins[0].arrivals)):
resid_eventinfo = eventinfo.origins[0].arrivals[j].get('pick_id')
if resid_eventinfo == resid_picks and eventinfo.origins[0].arrivals[j].phase == 'P':
if len(stat) > 4: # FOCMEC handles only 4-string station IDs
stat = stat[1:5]
az = eventinfo.origins[0].arrivals[j].get('azimuth')
inz = eventinfo.origins[0].arrivals[j].get('takeoff_angle')
fid.write('%-4s %6.2f %6.2f%s \n' % (stat,
az,
inz,
arrivals[key]['P']['fm']))
break
fid.close()
elif fformat == 'HASH':
# two different input files for
# HASH-driver 1 and 2 (see HASH manual!)
filename1 = filename + 'drv1' + '.phase'
filename2 = filename + 'drv2' + '.phase'
print ("Writing phases to %s for HASH for HASH-driver 1" % filename1)
fid1 = open("%s" % filename1, 'w')
print ("Writing phases to %s for HASH for HASH-driver 2" % filename2)
fid2 = open("%s" % filename2, 'w')
# get event information needed for HASH-input file
eventsource = eventinfo.origins[0]
event = parameter.get('eventID')
hashID = event.split('.')[0][1:5]
latdeg = eventsource['latitude']
latmin = eventsource['latitude'] * 60 / 10000
londeg = eventsource['longitude']
lonmin = eventsource['longitude'] * 60 / 10000
erh = 1 / 2 * (eventsource.origin_uncertainty['min_horizontal_uncertainty'] +
eventsource.origin_uncertainty['max_horizontal_uncertainty']) / 1000
erz = eventsource.depth_errors['uncertainty']
stime = eventsource['time']
if stime.year - 2000 >= 0:
syear = stime.year - 2000
else:
syear = stime.year - 1900
picks = eventinfo.picks
# write header line including event information
# for HASH-driver 1
fid1.write('%s%02d%02d%02d%02d%5.2f%2dN%5.2f%3dE%5.2f%6.3f%4.2f%5.2f%5.2f%s\n' % (syear,
stime.month, stime.day, stime.hour, stime.minute, stime.second,
latdeg, latmin, londeg, lonmin, eventsource['depth'],
eventinfo.magnitudes[0]['mag'], erh, erz,
hashID))
# write header line including event information
# for HASH-driver 2
fid2.write('%d%02d%02d%02d%02d%5.2f%dN%5.2f%3dE%6.2f%5.2f %d %5.2f %5.2f %4.2f %s \n' % (syear, stime.month, stime.day,
stime.hour, stime.minute, stime.second,
latdeg,latmin,londeg, lonmin,
eventsource['depth'],
eventsource['quality']['used_phase_count'],
erh, erz, eventinfo.magnitudes[0]['mag'],
hashID))
# write phase lines
for key in arrivals:
if arrivals[key].has_key('P'):
if arrivals[key]['P']['weight'] < 4 and arrivals[key]['P']['fm'] is not None:
stat = key
ccode = arrivals[key]['P']['channel']
ncode = arrivals[key]['P']['network']
if arrivals[key]['P']['weight'] < 2:
Pqual='I'
else:
Pqual='E'
for i in range(len(picks)):
station = picks[i].waveform_id.station_code
if station == stat:
# get resource ID
resid_picks = picks[i].get('resource_id')
# find same ID in eventinfo
# there it is the pick_id!!
for j in range(len(eventinfo.origins[0].arrivals)):
resid_eventinfo = eventinfo.origins[0].arrivals[j].get('pick_id')
if resid_eventinfo == resid_picks and eventinfo.origins[0].arrivals[j].phase == 'P':
if len(stat) > 4: # HASH handles only 4-string station IDs
stat = stat[1:5]
az = eventinfo.origins[0].arrivals[j].get('azimuth')
inz = eventinfo.origins[0].arrivals[j].get('takeoff_angle')
dist = eventinfo.origins[0].arrivals[j].get('distance')
# write phase line for HASH-driver 1
fid1.write('%-4s%sP%s%d 0 %3.1f %03d %03d 2 1 %s\n' % (stat, Pqual, arrivals[key]['P']['fm'], arrivals[key]['P']['weight'],
dist, inz, az, ccode))
# write phase line for HASH-driver 2
fid2.write('%-4s %s %s %s %s \n' % (
stat,
ncode,
ccode,
Pqual,
arrivals[key]['P']['fm']))
break
fid1.write(' %s' % hashID)
fid1.close()
fid2.close()
def merge_picks(event, picks):
"""

View File

@@ -1,21 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from pylot.core.io.phases import writephases
from pylot.core.util.version import get_git_version as _getVersionString
__version__ = _getVersionString()
def export(picks, fnout):
'''
Take <picks> dictionary and exports picking data to a NLLOC-obs
<phasefile> without creating an ObsPy event object.
:param picks: picking data dictionary
:type picks: dict
:param fnout: complete path to the exporting obs file
:type fnout: str
'''
# write phases to NLLoc-phase file
writephases(picks, 'HYPO71', fnout)

View File

@@ -14,7 +14,7 @@ __version__ = _getVersionString()
class NLLocError(EnvironmentError):
pass
def export(picks, fnout):
def export(picks, fnout, parameter):
'''
Take <picks> dictionary and exports picking data to a NLLOC-obs
<phasefile> without creating an ObsPy event object.
@@ -24,9 +24,12 @@ def export(picks, fnout):
:param fnout: complete path to the exporting obs file
:type fnout: str
:param: parameter, all input information
:type: object
'''
# write phases to NLLoc-phase file
writephases(picks, 'NLLoc', fnout)
writephases(picks, 'NLLoc', fnout, parameter)
def modify_inputs(ctrfn, root, nllocoutn, phasefn, tttn):
@@ -67,14 +70,17 @@ def modify_inputs(ctrfn, root, nllocoutn, phasefn, tttn):
nllfile.close()
def locate(fnin):
def locate(fnin, infile=None):
"""
takes an external program name
:param fnin:
:return:
"""
exe_path = which('NLLoc')
if infile is None:
exe_path = which('NLLoc')
else:
exe_path = which('NLLoc', infile)
if exe_path is None:
raise NLLocError('NonLinLoc executable not found; check your '
'environment variables')

View File

@@ -1,2 +1,27 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from pylot.core.io.phases import writephases
from pylot.core.util.version import get_git_version as _getVersionString
__version__ = _getVersionString()
def export(picks, fnout, parameter, eventinfo):
'''
Take <picks> dictionary and exports picking data to a VELEST-cnv
<phasefile> without creating an ObsPy event object.
:param picks: picking data dictionary
:type picks: dict
:param fnout: complete path to the exporting obs file
:type fnout: str
:param: parameter, all input information
:type: object
:param: eventinfo, source time needed for VELEST-cnv format
:type: list object
'''
# write phases to VELEST-phase file
writephases(picks, 'VELEST', fnout, parameter, eventinfo)

20
pylot/core/pick/autopick.py Executable file → Normal file
View File

@@ -143,7 +143,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
picker = 'auto' # type of picks
# split components
zdat = wfstream.select(component="Z")
@@ -157,7 +157,7 @@ def autopickstation(wfstream, pickparam, verbose=False):
ndat = wfstream.select(component="1")
if algoP == 'HOS' or algoP == 'ARZ' and zdat is not None:
msg = '##########################################\nautopickstation:' \
msg = '##################################################\nautopickstation:' \
' Working on P onset of station {station}\nFiltering vertical ' \
'trace ...\n{data}'.format(station=zdat[0].stats.station,
data=str(zdat))
@@ -552,7 +552,7 @@ def autopickstation(wfstream, pickparam, verbose=False):
print('autopickstation: S-weight: {0}, SNR: {1}, '
'SNR[dB]: {2}\n'
'################################################'
'##################################################'
''.format(Sweight, SNRS, SNRSdB))
################################################################
# get Wood-Anderson peak-to-peak amplitude
@@ -566,7 +566,7 @@ def autopickstation(wfstream, pickparam, verbose=False):
'AIC-SNR={0}, AIC-Slope={1}counts/s\n' \
'(min. AIC-SNR={2}, ' \
'min. AIC-Slope={3}counts/s)\n' \
'################################################' \
'##################################################' \
''.format(aicarhpick.getSNR(),
aicarhpick.getSlope(),
minAICSSNR,
@@ -778,11 +778,15 @@ def autopickstation(wfstream, pickparam, verbose=False):
# create dictionary
# for P phase
ppick = dict(lpp=lpickP, epp=epickP, mpp=mpickP, spe=Perror, snr=SNRP,
ccode = zdat[0].stats.channel
ncode = zdat[0].stats.network
ppick = dict(channel=ccode, network=ncode, 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
spick = dict(lpp=lpickS, epp=epickS, mpp=mpickS, spe=Serror, snr=SNRS,
ccode = edat[0].stats.channel
ncode = edat[0].stats.network
spick = dict(channel=ccode, network=ncode, 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)
@@ -804,7 +808,7 @@ def iteratepicker(wf, NLLocfile, picks, badpicks, pickparameter):
:param pickparameter: picking parameters from autoPyLoT-input file
'''
msg = '#######################################################\n' \
msg = '##################################################\n' \
'autoPyLoT: Found {0} bad onsets at station(s) {1}, ' \
'starting re-picking them ...'.format(len(badpicks), badpicks)
print(msg)
@@ -823,7 +827,7 @@ def iteratepicker(wf, NLLocfile, picks, badpicks, pickparameter):
badpicks[i][1] = picks[badpicks[i][0]]['P']['mpp'] - float(res)
# get corresponding waveform stream
msg = '#######################################################\n' \
msg = '##################################################\n' \
'iteratepicker: Re-picking station {0}'.format(badpicks[i][0])
print(msg)
wf2pick = wf.select(station=badpicks[i][0])

View File

@@ -7,7 +7,6 @@ import os
import numpy as np
import glob
import matplotlib.pyplot as plt
from obspy import read_events
from pylot.core.io.phases import picksdict_from_picks
@@ -289,7 +288,6 @@ class PDFDictionary(object):
values['mpp'],
values['lpp'],
type=type)
return pdf_picks
def plot(self, stations=None):
@@ -493,4 +491,4 @@ if __name__ == "__main__":
main()
pr.disable()
# after your program ends
pr.print_stats(sort="calls")
pr.print_stats(sort="calls")

View File

@@ -1,12 +1,11 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# -*- coding: utf-8 -*-
"""
Created Mar/Apr 2015
Collection of helpful functions for manual and automatic picking.
:author: Ludger Kueperkoch / MAGS2 EP3 working group
:author: Ludger Kueperkoch, BESTEC GmbH
"""
import warnings

0
pylot/core/util/__init__.py Executable file → Normal file
View File

View File

@@ -180,8 +180,10 @@ def read_metadata(path_to_inventory):
invtype = key_for_set_value(inv)
if invtype is None:
raise IOError("Neither dataless-SEED file, inventory-xml file nor "
"RESP-file found!")
print("Neither dataless-SEED file, inventory-xml file nor "
"RESP-file found!")
print("!!WRONG CALCULATION OF SOURCE PARAMETERS!!")
robj = None,
elif invtype == 'dless': # prevent multiple read of large dlsv
print("Reading metadata information from dataless-SEED file ...")
if len(inv[invtype]) == 1:
@@ -250,13 +252,23 @@ def restitute_data(data, invtype, inobj, unit='VEL', force=False):
else:
finv = invlist[0]
inventory = read_inventory(finv, format='STATIONXML')
elif invtype == None:
print("No restitution possible, as there are no station-meta data available!")
break
else:
data.remove(tr)
continue
# apply restitution to data
print("Correcting instrument at station %s, channel %s" \
% (tr.stats.station, tr.stats.channel))
try:
if invtype in ['resp', 'dless']:
tr.simulate(**kwargs)
try:
tr.simulate(**kwargs)
except ValueError as e:
vmsg = '{0}'.format(e)
print(vmsg)
else:
tr.attach_response(inventory)
tr.remove_response(output=unit,

View File

@@ -8,7 +8,9 @@ Created on Wed Feb 26 12:31:25 2014
import os
from pylot.core.loc import nll
from pylot.core.loc import hsat
from pylot.core.loc import hyposat
from pylot.core.loc import hypo71
from pylot.core.loc import hypodd
from pylot.core.loc import velest
@@ -43,10 +45,6 @@ FILTERDEFAULTS = readFilterInformation(os.path.join(os.path.expanduser('~'),
'.pylot',
'filter.in'))
AUTOMATIC_DEFAULTS = os.path.join(os.path.expanduser('~'),
'.pylot',
'autoPyLoT.in')
TIMEERROR_DEFAULTS = os.path.join(os.path.expanduser('~'),
'.pylot',
'PILOT_TimeErrors.in')
@@ -55,7 +53,7 @@ OUTPUTFORMATS = {'.xml': 'QUAKEML',
'.cnv': 'CNV',
'.obs': 'NLLOC_OBS'}
LOCTOOLS = dict(nll=nll, hsat=hsat, velest=velest)
LOCTOOLS = dict(nll=nll, hyposat=hyposat, velest=velest, hypo71=hypo71, hypodd=hypodd)
COMPPOSITION_MAP = dict(Z=2, N=1, E=0)
COMPPOSITION_MAP['1'] = 1

View File

@@ -51,8 +51,11 @@ def exp_parameter(te, tm, tl, eta):
sig1 = np.log(eta) / (te - tm)
sig2 = np.log(eta) / (tm - tl)
if np.isinf(sig1) == True:
sig1 = np.log(eta) / (tm - tl)
if np.isinf(sig2) == True:
sig2 = np.log(eta) / (te - tm)
a = 1 / (1 / sig1 + 1 / sig2)
return tm, sig1, sig2, a
@@ -237,7 +240,7 @@ class ProbabilityDensityFunction(object):
@classmethod
def from_pick(self, lbound, barycentre, rbound, incr=0.001, decfact=0.01,
type='gauss'):
type='exp'):
'''
Initialize a new ProbabilityDensityFunction object.
Takes incr, lbound, barycentre and rbound to derive x0 and the number
@@ -304,10 +307,14 @@ class ProbabilityDensityFunction(object):
:return float: rval
'''
rval = 0
for x in self.axis:
rval += x * self.data(x)
return rval * self.incr
#rval = 0
#for x in self.axis:
# rval += x * self.data(x)
rval = self.mu
# Not sure about this! That might not be the barycentre.
# However, for std calculation (next function)
# self.mu is also used!! (LK, 02/2017)
return rval
def standard_deviation(self):
mu = self.mu

View File

@@ -7,17 +7,18 @@ class AutoPickThread(QThread):
message = Signal(str)
finished = Signal()
def __init__(self, parent, func, data, param):
def __init__(self, parent, func, infile, fnames, savepath):
super(AutoPickThread, self).__init__()
self.setParent(parent)
self.func = func
self.data = data
self.param = param
self.infile = infile
self.fnames = fnames
self.savepath = savepath
def run(self):
sys.stdout = self
picks = self.func(self.data, self.param)
picks = self.func(self.infile, self.fnames, self.savepath)
print("Autopicking finished!\n")

View File

@@ -477,7 +477,7 @@ def runProgram(cmd, parameter=None):
subprocess.check_output('{} | tee /dev/stderr'.format(cmd), shell=True)
def which(program):
def which(program, infile=None):
"""
takes a program name and returns the full path to the executable or None
modified after: http://stackoverflow.com/questions/377017/test-if-executable-exists-in-python
@@ -490,7 +490,12 @@ def which(program):
for key in settings.allKeys():
if 'binPath' in key:
os.environ['PATH'] += ':{0}'.format(settings.value(key))
bpath = os.path.join(os.path.expanduser('~'), '.pylot', 'autoPyLoT.in')
if infile is None:
# use default parameter-file name
bpath = os.path.join(os.path.expanduser('~'), '.pylot', 'pylot.in')
else:
bpath = os.path.join(os.path.expanduser('~'), '.pylot', infile)
if os.path.exists(bpath):
nllocpath = ":" + AutoPickParameter(bpath).get('nllocbin')
os.environ['PATH'] += nllocpath

0
pylot/core/util/version.py Executable file → Normal file
View File

View File

@@ -5,12 +5,15 @@ Created on Wed Mar 19 11:27:35 2014
@author: sebastianw
"""
import os
import getpass
import warnings
import copy
import datetime
import numpy as np
from matplotlib.figure import Figure
from pylot.core.util.utils import find_horizontals
try:
from matplotlib.backends.backend_qt4agg import FigureCanvas
@@ -26,7 +29,7 @@ from PySide.QtGui import QAction, QApplication, QCheckBox, QComboBox, \
from PySide.QtCore import QSettings, Qt, QUrl, Signal, Slot
from PySide.QtWebKit import QWebView
from obspy import Stream, UTCDateTime
from pylot.core.io.inputs import FilterOptions
from pylot.core.io.inputs import FilterOptions, AutoPickParameter
from pylot.core.pick.utils import getSNR, earllatepicker, getnoisewin, \
getResolutionWindow
from pylot.core.pick.compare import Comparison
@@ -49,7 +52,12 @@ def getDataType(parent):
def plot_pdf(_axes, x, y, annotation, bbox_props, xlabel=None, ylabel=None,
title=None):
_axes.plot(x, y)
# try method or data
try:
_axes.plot(x, y()) # y provided as method
except:
_axes.plot(x, y) # y provided as data
if title:
_axes.set_title(title)
if xlabel:
@@ -235,23 +243,23 @@ class ComparisonDialog(QDialog):
x, y, std, exp = pdf.axis, pdf.data, pdf.standard_deviation(), \
pdf.expectation()
annotation = "{phase} difference on {station}\n" \
"expectation: {exp}\n" \
"std: {std}".format(station=station, phase=phase,
std=std, exp=exp)
annotation = "%s difference on %s\n" \
"expectation: %7.4f s\n" \
"std: %7.4f s" % (phase, station,
exp, std)
bbox_props = dict(boxstyle='round', facecolor='lightgrey', alpha=.7)
plot_pdf(_axes, x, y, annotation, bbox_props, 'time difference [s]',
'propability density [-]', phase)
'propability density [-]', phase)
pdf_a = copy.deepcopy(self.data.get('auto')[station][phase])
pdf_m = copy.deepcopy(self.data.get('manu')[station][phase])
xauto, yauto, stdauto, expauto, alim = pdf_a.axis, pdf_a.data, \
xauto, yauto, stdauto, expauto, alim = pdf_a.axis, pdf_a.data(), \
pdf_a.standard_deviation(), \
pdf_a.expectation(), \
pdf_a.limits()
xmanu, ymanu, stdmanu, expmanu, mlim = pdf_m.axis, pdf_m.data, \
xmanu, ymanu, stdmanu, expmanu, mlim = pdf_m.axis, pdf_m.data(), \
pdf_m.standard_deviation(), \
pdf_m.expectation(), \
pdf_m.limits()
@@ -259,21 +267,19 @@ class ComparisonDialog(QDialog):
lims = clims(alim, mlim)
# relative x axis
x0 = lims[0]
xmanu -= x0
xmanu -= x0
xauto -= x0
lims = [lim - x0 for lim in lims]
x0 = UTCDateTime(x0)
# set annotation text
mannotation = "probability density for manual pick\n" \
"expectation: {exp}\n" \
"std: {std}".format(std=stdmanu,
exp=expmanu-x0.timestamp)
mannotation = "probability density of manual pick\n" \
"expectation: %7.4f s\n" \
"std: %7.4f s" % (expmanu-x0.timestamp, stdmanu)
aannotation = "probability density for automatic pick\n" \
"expectation: {exp}\n" \
"std: {std}".format(std=stdauto,
exp=expauto-x0.timestamp)
aannotation = "probability density of automatic pick\n" \
"expectation: %7.4f s\n" \
"std: %7.4f s" % (expauto-x0.timestamp, stdauto)
_ax1 = plot_pdf(_ax1, xmanu, ymanu, mannotation,
bbox_props=bbox_props, xlabel='seconds since '
@@ -504,15 +510,17 @@ class WaveformWidget(FigureCanvas):
class PickDlg(QDialog):
def __init__(self, parent=None, data=None, station=None, picks=None,
rotate=False):
rotate=False, infile=None):
super(PickDlg, self).__init__(parent)
# initialize attributes
self.infile = infile
self.station = station
self.rotate = rotate
self.components = 'ZNE'
settings = QSettings()
self._user = settings.value('user/Login', 'anonymous')
pylot_user = getpass.getuser()
self._user = settings.value('user/Login', pylot_user)
if picks:
self.picks = picks
else:
@@ -704,6 +712,9 @@ class PickDlg(QDialog):
self.cidrelease = self.connectReleaseEvent(self.panRelease)
self.cidscroll = self.connectScrollEvent(self.scrollZoom)
def getinfile(self):
return self.infile
def getStartTime(self):
return self.stime
@@ -806,6 +817,7 @@ class PickDlg(QDialog):
self.disconnectMotionEvent()
self.cidpress = self.connectPressEvent(self.setPick)
print(self.selectPhase.currentText())
if self.selectPhase.currentText().upper().startswith('P'):
self.setIniPickP(gui_event, wfdata, trace_number)
elif self.selectPhase.currentText().upper().startswith('S'):
@@ -819,14 +831,14 @@ class PickDlg(QDialog):
def setIniPickP(self, gui_event, wfdata, trace_number):
parameter = AutoPickParameter(self.getinfile())
ini_pick = gui_event.xdata
settings = QSettings()
nfac = settings.value('picking/nfac_P', 1.3)
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 = parameter.get('nfacP')
twins = parameter.get('tsnrz')
noise_win = twins[0]
gap_win = twins[1]
signal_win = twins[2]
itrace = int(trace_number)
while itrace > len(wfdata) - 1:
@@ -868,14 +880,14 @@ class PickDlg(QDialog):
def setIniPickS(self, gui_event, wfdata):
parameter = AutoPickParameter(self.getinfile())
ini_pick = gui_event.xdata
settings = QSettings()
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.)
nfac = parameter.get('nfacS')
twins = parameter.get('tsnrh')
noise_win = twins[0]
gap_win = twins[1]
signal_win = twins[2]
# copy data for plotting
data = self.getWFData().copy()
@@ -922,6 +934,8 @@ class PickDlg(QDialog):
def setPick(self, gui_event):
parameter = AutoPickParameter(self.getinfile())
# get axes limits
self.updateCurrentLimits()
@@ -941,7 +955,14 @@ class PickDlg(QDialog):
wfdata.filter(**filteroptions)
# get earliest and latest possible pick and symmetric pick error
[epp, lpp, spe] = earllatepicker(wfdata, 1.5, (5., .5, 2.), pick)
if wfdata[0].stats.channel[2] == 'Z' or wfdata[0].stats.channel[2] == '3':
nfac = parameter.get('nfacP')
TSNR = parameter.get('tsnrz')
else:
nfac = parameter.get('nfacS')
TSNR = parameter.get('tsnrh')
[epp, lpp, spe] = earllatepicker(wfdata, nfac, (TSNR[0], TSNR[1], TSNR[2]), pick)
# return absolute time values for phases
stime = self.getStartTime()
@@ -951,7 +972,8 @@ class PickDlg(QDialog):
# save pick times for actual phase
phasepicks = dict(epp=epp, lpp=lpp, mpp=mpp, spe=spe,
picker=self.getUser())
picker='manual', channel=channel,
network=wfdata[0].stats.network)
try:
oldphasepick = self.picks[phase]
@@ -1171,13 +1193,15 @@ class PickDlg(QDialog):
class PropertiesDlg(QDialog):
def __init__(self, parent=None):
def __init__(self, parent=None, infile=None):
super(PropertiesDlg, self).__init__(parent)
self.infile = infile
appName = QApplication.applicationName()
self.setWindowTitle("{0} Properties".format(appName))
self.tabWidget = QTabWidget()
self.tabWidget.addTab(InputsTab(self), "Inputs")
self.tabWidget.addTab(OutputsTab(self), "Outputs")
@@ -1186,7 +1210,8 @@ class PropertiesDlg(QDialog):
self.tabWidget.addTab(LocalisationTab(self), "Loc Tools")
self.buttonBox = QDialogButtonBox(QDialogButtonBox.Ok |
QDialogButtonBox.Apply |
QDialogButtonBox.Close)
QDialogButtonBox.Close |
QDialogButtonBox.RestoreDefaults)
layout = QVBoxLayout()
layout.addWidget(self.tabWidget)
@@ -1195,8 +1220,11 @@ class PropertiesDlg(QDialog):
self.buttonBox.accepted.connect(self.accept)
self.buttonBox.rejected.connect(self.reject)
self.buttonBox.button(QDialogButtonBox.Apply).clicked.connect(
self.apply)
self.buttonBox.button(QDialogButtonBox.Apply).clicked.connect(self.apply)
self.buttonBox.button(QDialogButtonBox.RestoreDefaults).clicked.connect(self.restore)
def getinfile(self):
return self.infile
def accept(self, *args, **kwargs):
self.apply()
@@ -1209,6 +1237,14 @@ class PropertiesDlg(QDialog):
if values is not None:
self.setValues(values)
def restore(self):
for widint in range(self.tabWidget.count()):
curwid = self.tabWidget.widget(widint)
values = curwid.resetValues(self.getinfile())
if values is not None:
self.setValues(values)
@staticmethod
def setValues(tabValues):
settings = QSettings()
@@ -1224,16 +1260,19 @@ class PropTab(QWidget):
def getValues(self):
return None
def resetValues(self, infile=None):
return None
class InputsTab(PropTab):
def __init__(self, parent):
def __init__(self, parent, infile=None):
super(InputsTab, self).__init__(parent)
settings = QSettings()
pylot_user = getpass.getuser()
fulluser = settings.value("user/FullName")
login = settings.value("user/Login")
fullNameLabel = QLabel("Full name for user '{0}': ".format(login))
fullNameLabel = QLabel("Full name for user '{0}': ".format(pylot_user))
# get the full name of the actual user
self.fullNameEdit = QLineEdit()
@@ -1276,9 +1315,24 @@ class InputsTab(PropTab):
"data/Structure": self.structureSelect.currentText()}
return values
def resetValues(self, infile):
para = AutoPickParameter(infile)
datstruct = para.get('datastructure')
if datstruct == 'SeisComp':
index = 0
else:
index = 2
datapath = para.get('datapath')
rootpath = para.get('rootpath')
database = para.get('database')
path = os.path.join(os.path.expanduser('~'), rootpath, datapath, database)
values = {"data/dataRoot": self.dataDirEdit.setText("%s" % path),
"user/FullName": self.fullNameEdit.text(),
"data/Structure": self.structureSelect.setCurrentIndex(index)}
return values
class OutputsTab(PropTab):
def __init__(self, parent=None):
def __init__(self, parent=None, infile=None):
super(OutputsTab, self).__init__(parent)
settings = QSettings()
@@ -1302,6 +1356,9 @@ class OutputsTab(PropTab):
values = {"output/Format": self.eventOutputComboBox.currentText()}
return values
def resetValues(self, infile):
values = {"output/Format": self.eventOutputComboBox.setCurrentIndex(1)}
return values
class PhasesTab(PropTab):
def __init__(self, parent=None):
@@ -1318,7 +1375,7 @@ class GraphicsTab(PropTab):
class LocalisationTab(PropTab):
def __init__(self, parent=None):
def __init__(self, parent=None, infile=None):
super(LocalisationTab, self).__init__(parent)
settings = QSettings()
@@ -1388,6 +1445,13 @@ class LocalisationTab(PropTab):
"loc/tool": loctool}
return values
def resetValues(self, infile):
para = AutoPickParameter(infile)
nllocroot = para.get('nllocroot')
nllocbin = para.get('nllocbin')
loctool = self.locToolComboBox.setCurrentIndex(3)
values = {"nll/rootPath": self.rootedit.setText("%s" % nllocroot),
"nll/binPath": self.binedit.setText("%s" % nllocbin)}
class NewEventDlg(QDialog):
def __init__(self, parent=None, titleString="Create a new event"):

0
pylot/testing/testHelpForm.py Executable file → Normal file
View File

0
pylot/testing/testPickDlg.py Executable file → Normal file
View File

0
pylot/testing/testPropDlg.py Executable file → Normal file
View File

0
pylot/testing/testUIcomponents.py Executable file → Normal file
View File

0
pylot/testing/test_autopick.py Executable file → Normal file
View File