release version 0.2
release notes: ============== Features: - centralize all functionalities of PyLoT and control them from within the main GUI - handling multiple events inside GUI with project files (save and load work progress) - GUI based adjustments of pick parameters and I/O - interactive tuning of parameters from within the GUI - call automatic picking algorithm from within the GUI - comparison of automatic with manual picks for multiple events using clear differentiation of manual picks into 'tune' and 'test-set' (beta) - manual picking of different (user defined) phase types - phase onset estimation with ObsPy TauPy - interactive zoom/scale functionalities in all plots (mousewheel, pan, pan-zoom) - array map to visualize stations and control onsets (beta feature, switch to manual picks not implemented) Platform support: - python 3 support - Windows support Performance: - multiprocessing for automatic picking and restitution of multiple stations - use pyqtgraph library for better performance on main waveform plot Visualization: - pick uncertainty (quality classes) visualization with gradients - pick color unification for all plots - new icons and stylesheets Known Issues:
1177
QtPyLoT.py
82
README.md
@ -1,6 +1,6 @@
|
|||||||
# PyLoT
|
# PyLoT
|
||||||
|
|
||||||
version: 0.1a
|
version: 0.2
|
||||||
|
|
||||||
The Python picking and Localisation Tool
|
The Python picking and Localisation Tool
|
||||||
|
|
||||||
@ -14,79 +14,97 @@ to redevelop the software package in Python. The great work of the ObsPy
|
|||||||
group allows easy handling of a bunch of seismic data and PyLoT will
|
group allows easy handling of a bunch of seismic data and PyLoT will
|
||||||
benefit a lot compared to the former MatLab version.
|
benefit a lot compared to the former MatLab version.
|
||||||
|
|
||||||
The development of PyLoT is part of the joint research project MAGS2.
|
The development of PyLoT is part of the joint research project MAGS2 and AlpArray.
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
At the moment there is no automatic installation procedure available for PyLoT.
|
At the moment there is no automatic installation procedure available for PyLoT.
|
||||||
Best way to install is to clone the repository and add the path to your Python path.
|
Best way to install is to clone the repository and add the path to your Python path.
|
||||||
|
|
||||||
####prerequisites:
|
#### Prerequisites:
|
||||||
|
|
||||||
In order to run PyLoT you need to install:
|
In order to run PyLoT you need to install:
|
||||||
|
|
||||||
- python
|
- python 2 or 3
|
||||||
- scipy
|
- scipy
|
||||||
- numpy
|
- numpy
|
||||||
- matplotlib
|
- matplotlib
|
||||||
- obspy
|
- obspy
|
||||||
- pyside
|
- pyside
|
||||||
|
|
||||||
####some handwork
|
#### Some handwork:
|
||||||
|
|
||||||
PyLoT needs a properties folder on your system to work. It should be situated in your home directory:
|
PyLoT needs a properties folder on your system to work. It should be situated in your home directory
|
||||||
|
(on Windows usually C:/Users/*username*):
|
||||||
|
|
||||||
mkdir ~/.pylot
|
mkdir ~/.pylot
|
||||||
|
|
||||||
In the next step you have to copy some files to this directory:
|
In the next step you have to copy some files to this directory:
|
||||||
|
|
||||||
cp path-to-pylot/inputs/pylot.in ~/.pylot/
|
*for local distance seismicity*
|
||||||
|
|
||||||
for local distance seismicity
|
cp path-to-pylot/inputs/pylot_local.in ~/.pylot/pylot.in
|
||||||
|
|
||||||
cp path-to-pylot/inputs/autoPyLoT_local.in ~/.pylot/autoPyLoT.in
|
*for regional distance seismicity*
|
||||||
|
|
||||||
for regional distance seismicity
|
cp path-to-pylot/inputs/pylot_regional.in ~/.pylot/pylot.in
|
||||||
|
|
||||||
cp path-to-pylot/inputs/autoPyLoT_regional.in ~/.pylot/autoPyLoT.in
|
*for global distance seismicity*
|
||||||
|
|
||||||
and some extra information on filtering, error estimates (just needed for reading old PILOT data) and the Richter magnitude scaling relation
|
cp path-to-pylot/inputs/pylot_global.in ~/.pylot/pylot.in
|
||||||
|
|
||||||
cp path-to-pylot/inputs/filter.in path-to-pylot/inputs/PILOT_TimeErrors.in path-to-pylot/inputs/richter_scaling.data ~/.pylot/
|
and some extra information on error estimates (just needed for reading old PILOT data) and the Richter magnitude scaling relation
|
||||||
|
|
||||||
|
cp path-to-pylot/inputs/PILOT_TimeErrors.in path-to-pylot/inputs/richter_scaling.data ~/.pylot/
|
||||||
|
|
||||||
You may need to do some modifications to these files. Especially folder names should be reviewed.
|
You may need to do some modifications to these files. Especially folder names should be reviewed.
|
||||||
|
|
||||||
PyLoT has been tested on Mac OSX (10.11) and Debian Linux 8.
|
PyLoT has been tested on Mac OSX (10.11), Debian Linux 8 and on Windows 10.
|
||||||
|
|
||||||
|
|
||||||
##release notes:
|
## Release notes
|
||||||
==============
|
|
||||||
|
|
||||||
#### Features
|
#### Features:
|
||||||
|
|
||||||
- consistent manual phase picking through predefined SNR dependant zoom level
|
- centralize all functionalities of PyLoT and control them from within the main GUI
|
||||||
- uniform uncertainty estimation from waveform's properties for automatic and manual picks
|
- handling multiple events inside GUI with project files (save and load work progress)
|
||||||
- pdf representation and comparison of picks taking the uncertainty intrinsically into account
|
- GUI based adjustments of pick parameters and I/O
|
||||||
- Richter and moment magnitude estimation
|
- interactive tuning of parameters from within the GUI
|
||||||
- location determination with external installation of [NonLinLoc](http://alomax.free.fr/nlloc/index.html)
|
- call automatic picking algorithm from within the GUI
|
||||||
|
- comparison of automatic with manual picks for multiple events using clear differentiation of manual picks into 'tune' and 'test-set' (beta)
|
||||||
|
- manual picking of different (user defined) phase types
|
||||||
|
- phase onset estimation with ObsPy TauPy
|
||||||
|
- interactive zoom/scale functionalities in all plots (mousewheel, pan, pan-zoom)
|
||||||
|
- array map to visualize stations and control onsets (beta feature, switch to manual picks not implemented)
|
||||||
|
|
||||||
#### Known issues
|
##### Platform support:
|
||||||
|
- Python 3 support
|
||||||
|
- Windows support
|
||||||
|
|
||||||
- Magnitude estimation from manual PyLoT takes some time (instrument correction)
|
##### Performance:
|
||||||
|
- multiprocessing for automatic picking and restitution of multiple stations
|
||||||
|
- use pyqtgraph library for better performance on main waveform plot
|
||||||
|
|
||||||
We hope to solve these with the next release.
|
##### Visualization:
|
||||||
|
- pick uncertainty (quality classes) visualization with gradients
|
||||||
|
- pick color unification for all plots
|
||||||
|
- new icons and stylesheets
|
||||||
|
|
||||||
####staff:
|
#### Known Issues:
|
||||||
======
|
- some Qt related errors might occur at runtime
|
||||||
|
- filter toggle not working in pickDlg
|
||||||
|
- PyLoT data structure requires at least three parent directories for waveform data directory
|
||||||
|
|
||||||
original author(s): L. Kueperkoch, S. Wehling-Benatelli, M. Bischoff (PILOT)
|
## Staff
|
||||||
|
|
||||||
developer(s): S. Wehling-Benatelli, L. Kueperkoch, K. Olbert, M. Bischoff,
|
Original author(s): L. Kueperkoch, S. Wehling-Benatelli, M. Bischoff (PILOT)
|
||||||
C. Wollin, M. Rische, M. Paffrath
|
|
||||||
|
|
||||||
others: A. Bruestle, T. Meier, W. Friederich
|
Developer(s): S. Wehling-Benatelli, L. Kueperkoch, M. Paffrath, K. Olbert,
|
||||||
|
M. Bischoff, C. Wollin, M. Rische
|
||||||
|
|
||||||
|
Others: A. Bruestle, T. Meier, W. Friederich
|
||||||
|
|
||||||
|
|
||||||
[ObsPy]: http://github.com/obspy/obspy/wiki
|
[ObsPy]: http://github.com/obspy/obspy/wiki
|
||||||
|
|
||||||
October 2016
|
September 2017
|
||||||
|
379
autoPyLoT.py
@ -4,61 +4,125 @@
|
|||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
|
import datetime
|
||||||
import glob
|
import glob
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from obspy import read_events
|
import pylot.core.loc.focmec as focmec
|
||||||
|
import pylot.core.loc.hash as hash
|
||||||
import pylot.core.loc.hsat as hsat
|
import pylot.core.loc.hypo71 as hypo71
|
||||||
|
import pylot.core.loc.hypodd as hypodd
|
||||||
|
import pylot.core.loc.hyposat as hyposat
|
||||||
import pylot.core.loc.nll as nll
|
import pylot.core.loc.nll as nll
|
||||||
from pylot.core.analysis.magnitude import MomentMagnitude, RichterMagnitude
|
import pylot.core.loc.velest as velest
|
||||||
|
from obspy import read_events
|
||||||
|
from obspy.core.event import ResourceIdentifier
|
||||||
|
# from PySide.QtGui import QWidget, QInputDialog
|
||||||
|
from pylot.core.analysis.magnitude import MomentMagnitude, LocalMagnitude
|
||||||
from pylot.core.io.data import Data
|
from pylot.core.io.data import Data
|
||||||
from pylot.core.io.inputs import AutoPickParameter
|
from pylot.core.io.inputs import PylotParameter
|
||||||
from pylot.core.pick.autopick import autopickevent, iteratepicker
|
from pylot.core.pick.autopick import autopickevent, iteratepicker
|
||||||
from pylot.core.util.dataprocessing import restitute_data, read_metadata, \
|
from pylot.core.util.dataprocessing import restitute_data, read_metadata
|
||||||
remove_underscores
|
from pylot.core.util.defaults import SEPARATOR
|
||||||
|
from pylot.core.util.event import Event
|
||||||
from pylot.core.util.structure import DATASTRUCTURE
|
from pylot.core.util.structure import DATASTRUCTURE
|
||||||
|
from pylot.core.util.utils import real_None, remove_underscores, trim_station_components, check4gaps, check4doubled, \
|
||||||
|
check4rotated
|
||||||
from pylot.core.util.version import get_git_version as _getVersionString
|
from pylot.core.util.version import get_git_version as _getVersionString
|
||||||
|
|
||||||
__version__ = _getVersionString()
|
__version__ = _getVersionString()
|
||||||
|
|
||||||
|
|
||||||
def autoPyLoT(inputfile):
|
def autoPyLoT(input_dict=None, parameter=None, inputfile=None, fnames=None, eventid=None, savepath=None,
|
||||||
|
savexml=True, station='all', iplot=0, ncores=0):
|
||||||
"""
|
"""
|
||||||
Determine phase onsets automatically utilizing the automatic picking
|
Determine phase onsets automatically utilizing the automatic picking
|
||||||
algorithms by Kueperkoch et al. 2010/2012.
|
algorithms by Kueperkoch et al. 2010/2012.
|
||||||
|
|
||||||
:param inputfile: path to the input file containing all parameter
|
:param inputfile: path to the input file containing all parameter
|
||||||
information for automatic picking (for formatting details, see.
|
information for automatic picking (for formatting details, see.
|
||||||
`~pylot.core.io.inputs.AutoPickParameter`
|
`~pylot.core.io.inputs.PylotParameter`
|
||||||
:type inputfile: str
|
:type inputfile: str
|
||||||
:return:
|
:return:
|
||||||
|
|
||||||
.. rubric:: Example
|
.. rubric:: Example
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
if ncores == 1:
|
||||||
|
sp_info = 'autoPyLoT is running serial on 1 cores.'
|
||||||
|
else:
|
||||||
|
if ncores == 0:
|
||||||
|
ncores_readable = 'all available'
|
||||||
|
else:
|
||||||
|
ncores_readable = ncores
|
||||||
|
sp_info = 'autoPyLoT is running in parallel on {} cores.'.format(ncores_readable)
|
||||||
|
|
||||||
splash = '''************************************\n
|
splash = '''************************************\n
|
||||||
*********autoPyLoT starting*********\n
|
*********autoPyLoT starting*********\n
|
||||||
The Python picking and Location Tool\n
|
The Python picking and Location Tool\n
|
||||||
Version {version} 2015\n
|
Version {version} 2017\n
|
||||||
\n
|
\n
|
||||||
Authors:\n
|
Authors:\n
|
||||||
S. Wehling-Benatelli (Ruhr-Universität Bochum)\n
|
L. Kueperkoch (BESTEC GmbH, Landau i. d. Pfalz)\n
|
||||||
L. Küperkoch (BESTEC GmbH, Landau i. d. Pfalz)\n
|
M. Paffrath (Ruhr-Universitaet Bochum)\n
|
||||||
K. Olbert (Christian-Albrechts Universität zu Kiel)\n
|
S. Wehling-Benatelli (Ruhr-Universitaet Bochum)\n
|
||||||
***********************************'''.format(version=_getVersionString())
|
|
||||||
|
{sp}
|
||||||
|
***********************************'''.format(version=_getVersionString(),
|
||||||
|
sp=sp_info)
|
||||||
print(splash)
|
print(splash)
|
||||||
|
|
||||||
# reading parameter file
|
|
||||||
|
|
||||||
parameter = AutoPickParameter(inputfile)
|
parameter = real_None(parameter)
|
||||||
|
inputfile = real_None(inputfile)
|
||||||
|
eventid = real_None(eventid)
|
||||||
|
|
||||||
data = Data()
|
fig_dict = None
|
||||||
|
fig_dict_wadatijack = None
|
||||||
|
|
||||||
|
locflag = 1
|
||||||
|
if input_dict and isinstance(input_dict, dict):
|
||||||
|
if 'parameter' in input_dict:
|
||||||
|
parameter = input_dict['parameter']
|
||||||
|
if 'fig_dict' in input_dict:
|
||||||
|
fig_dict = input_dict['fig_dict']
|
||||||
|
if 'fig_dict_wadatijack' in input_dict:
|
||||||
|
fig_dict_wadatijack = input_dict['fig_dict_wadatijack']
|
||||||
|
if 'station' in input_dict:
|
||||||
|
station = input_dict['station']
|
||||||
|
if 'fnames' in input_dict:
|
||||||
|
fnames = input_dict['fnames']
|
||||||
|
if 'eventid' in input_dict:
|
||||||
|
eventid = input_dict['eventid']
|
||||||
|
if 'iplot' in input_dict:
|
||||||
|
iplot = input_dict['iplot']
|
||||||
|
if 'locflag' in input_dict:
|
||||||
|
locflag = input_dict['locflag']
|
||||||
|
if 'savexml' in input_dict:
|
||||||
|
savexml = input_dict['savexml']
|
||||||
|
|
||||||
|
if not parameter:
|
||||||
|
if inputfile:
|
||||||
|
parameter = PylotParameter(inputfile)
|
||||||
|
#iplot = parameter['iplot']
|
||||||
|
else:
|
||||||
|
infile = os.path.join(os.path.expanduser('~'), '.pylot', 'pylot.in')
|
||||||
|
print('Using default input file {}'.format(infile))
|
||||||
|
parameter = PylotParameter(infile)
|
||||||
|
else:
|
||||||
|
if not type(parameter) == PylotParameter:
|
||||||
|
print('Wrong input type for parameter: {}'.format(type(parameter)))
|
||||||
|
return
|
||||||
|
if inputfile:
|
||||||
|
print('Parameters set and input file given. Choose either of both.')
|
||||||
|
return
|
||||||
|
|
||||||
evt = None
|
evt = None
|
||||||
# getting information on data structure
|
|
||||||
|
|
||||||
|
# reading parameter file
|
||||||
if parameter.hasParam('datastructure'):
|
if parameter.hasParam('datastructure'):
|
||||||
|
# getting information on data structure
|
||||||
datastructure = DATASTRUCTURE[parameter.get('datastructure')]()
|
datastructure = DATASTRUCTURE[parameter.get('datastructure')]()
|
||||||
dsfields = {'root': parameter.get('rootpath'),
|
dsfields = {'root': parameter.get('rootpath'),
|
||||||
'dpath': parameter.get('datapath'),
|
'dpath': parameter.get('datapath'),
|
||||||
@ -66,16 +130,15 @@ def autoPyLoT(inputfile):
|
|||||||
|
|
||||||
exf = ['root', 'dpath', 'dbase']
|
exf = ['root', 'dpath', 'dbase']
|
||||||
|
|
||||||
if parameter.hasParam('eventID'):
|
if parameter['eventID'] is not '*' and fnames == 'None':
|
||||||
dsfields['eventID'] = parameter.get('eventID')
|
dsfields['eventID'] = parameter['eventID']
|
||||||
exf.append('eventID')
|
exf.append('eventID')
|
||||||
|
|
||||||
datastructure.modifyFields(**dsfields)
|
datastructure.modifyFields(**dsfields)
|
||||||
datastructure.setExpandFields(exf)
|
datastructure.setExpandFields(exf)
|
||||||
|
|
||||||
# check if default location routine NLLoc is available
|
# check if default location routine NLLoc is available
|
||||||
if parameter.hasParam('nllocbin'):
|
if real_None(parameter['nllocbin']) and locflag:
|
||||||
locflag = 1
|
|
||||||
# get NLLoc-root path
|
# get NLLoc-root path
|
||||||
nllocroot = parameter.get('nllocroot')
|
nllocroot = parameter.get('nllocroot')
|
||||||
# get path to NLLoc executable
|
# get path to NLLoc executable
|
||||||
@ -99,31 +162,122 @@ def autoPyLoT(inputfile):
|
|||||||
print("!!No source parameter estimation possible!!")
|
print("!!No source parameter estimation possible!!")
|
||||||
print(" !!! ")
|
print(" !!! ")
|
||||||
|
|
||||||
|
if not input_dict:
|
||||||
|
# started in production mode
|
||||||
datapath = datastructure.expandDataPath()
|
datapath = datastructure.expandDataPath()
|
||||||
if not parameter.hasParam('eventID'):
|
if fnames == 'None' and parameter['eventID'] is '*':
|
||||||
# multiple event processing
|
# multiple event processing
|
||||||
# read each event in database
|
# read each event in database
|
||||||
events = [events for events in glob.glob(os.path.join(datapath, '*')) if os.path.isdir(events)]
|
events = [events for events in glob.glob(os.path.join(datapath, '*')) if os.path.isdir(events)]
|
||||||
else:
|
elif fnames == 'None' and parameter['eventID'] is not '*' and not type(parameter['eventID']) == list:
|
||||||
# single event processing
|
# single event processing
|
||||||
events = glob.glob(os.path.join(datapath, parameter.get('eventID')))
|
events = glob.glob(os.path.join(datapath, parameter['eventID']))
|
||||||
for event in events:
|
elif fnames == 'None' and type(parameter['eventID']) == list:
|
||||||
data.setWFData(glob.glob(os.path.join(datapath, event, '*')))
|
# multiple event processing
|
||||||
evID = os.path.split(event)[-1]
|
events = []
|
||||||
print('Working on event %s' % event)
|
for eventID in parameter['eventID']:
|
||||||
print(data)
|
events.append(os.path.join(datapath, eventID))
|
||||||
|
else:
|
||||||
|
# autoPyLoT was initialized from GUI
|
||||||
|
events = []
|
||||||
|
events.append(eventid)
|
||||||
|
evID = os.path.split(eventid)[-1]
|
||||||
|
locflag = 2
|
||||||
|
else:
|
||||||
|
# started in tune or interactive mode
|
||||||
|
datapath = os.path.join(parameter['rootpath'],
|
||||||
|
parameter['datapath'])
|
||||||
|
events = []
|
||||||
|
for eventID in eventid:
|
||||||
|
events.append(os.path.join(datapath,
|
||||||
|
parameter['database'],
|
||||||
|
eventID))
|
||||||
|
|
||||||
|
if not events:
|
||||||
|
print('autoPyLoT: No events given. Return!')
|
||||||
|
return
|
||||||
|
|
||||||
|
# transform system path separator to '/'
|
||||||
|
for index, eventpath in enumerate(events):
|
||||||
|
eventpath = eventpath.replace(SEPARATOR, '/')
|
||||||
|
events[index] = eventpath
|
||||||
|
|
||||||
|
allpicks = {}
|
||||||
|
glocflag = locflag
|
||||||
|
for eventpath in events:
|
||||||
|
evID = os.path.split(eventpath)[-1]
|
||||||
|
fext = '.xml'
|
||||||
|
filename = os.path.join(eventpath, 'PyLoT_' + evID + fext)
|
||||||
|
try:
|
||||||
|
data = Data(evtdata=filename)
|
||||||
|
data.get_evt_data().path = eventpath
|
||||||
|
print('Reading event data from filename {}...'.format(filename))
|
||||||
|
except Exception as e:
|
||||||
|
print('Could not read event from file {}: {}'.format(filename, e))
|
||||||
|
data = Data()
|
||||||
|
pylot_event = Event(eventpath) # event should be path to event directory
|
||||||
|
data.setEvtData(pylot_event)
|
||||||
|
if fnames == 'None':
|
||||||
|
data.setWFData(glob.glob(os.path.join(datapath, eventpath, '*')))
|
||||||
|
# the following is necessary because within
|
||||||
|
# multiple event processing no event ID is provided
|
||||||
|
# in autopylot.in
|
||||||
|
try:
|
||||||
|
parameter.get('eventID')
|
||||||
|
except:
|
||||||
|
now = datetime.datetime.now()
|
||||||
|
eventID = '%d%02d%02d%02d%02d' % (now.year,
|
||||||
|
now.month,
|
||||||
|
now.day,
|
||||||
|
now.hour,
|
||||||
|
now.minute)
|
||||||
|
parameter.setParam(eventID=eventID)
|
||||||
|
else:
|
||||||
|
data.setWFData(fnames)
|
||||||
|
|
||||||
|
eventpath = events[0]
|
||||||
|
# now = datetime.datetime.now()
|
||||||
|
# evID = '%d%02d%02d%02d%02d' % (now.year,
|
||||||
|
# now.month,
|
||||||
|
# now.day,
|
||||||
|
# now.hour,
|
||||||
|
# now.minute)
|
||||||
|
parameter.setParam(eventID=eventid)
|
||||||
wfdat = data.getWFData() # all available streams
|
wfdat = data.getWFData() # all available streams
|
||||||
|
if not station == 'all':
|
||||||
|
wfdat = wfdat.select(station=station)
|
||||||
|
if not wfdat:
|
||||||
|
print('Could not find station {}. STOP!'.format(station))
|
||||||
|
return
|
||||||
wfdat = remove_underscores(wfdat)
|
wfdat = remove_underscores(wfdat)
|
||||||
|
# trim components for each station to avoid problems with different trace starttimes for one station
|
||||||
|
wfdat = check4gaps(wfdat)
|
||||||
|
wfdat = check4doubled(wfdat)
|
||||||
|
wfdat = trim_station_components(wfdat, trim_start=True, trim_end=False)
|
||||||
metadata = read_metadata(parameter.get('invdir'))
|
metadata = read_metadata(parameter.get('invdir'))
|
||||||
corr_dat, rest_flag = restitute_data(wfdat.copy(), *metadata)
|
# rotate stations to ZNE
|
||||||
|
wfdat = check4rotated(wfdat, metadata)
|
||||||
|
corr_dat = None
|
||||||
|
if locflag:
|
||||||
|
print("Restitute data ...")
|
||||||
|
corr_dat = restitute_data(wfdat.copy(), *metadata, ncores=ncores)
|
||||||
|
if not corr_dat and locflag:
|
||||||
|
locflag = 2
|
||||||
|
print('Working on event %s. Stations: %s' % (eventpath, station))
|
||||||
|
print(wfdat)
|
||||||
##########################################################
|
##########################################################
|
||||||
# !automated picking starts here!
|
# !automated picking starts here!
|
||||||
picks = autopickevent(wfdat, parameter)
|
fdwj = None
|
||||||
|
if fig_dict_wadatijack:
|
||||||
|
fdwj = fig_dict_wadatijack[evID]
|
||||||
|
picks = autopickevent(wfdat, parameter, iplot=iplot, fig_dict=fig_dict,
|
||||||
|
fig_dict_wadatijack=fdwj,
|
||||||
|
ncores=ncores, metadata=metadata, origin=data.get_evt_data().origins)
|
||||||
##########################################################
|
##########################################################
|
||||||
# locating
|
# locating
|
||||||
if locflag == 1:
|
if locflag > 0:
|
||||||
# write phases to NLLoc-phase file
|
# write phases to NLLoc-phase file
|
||||||
nll.export(picks, phasefile)
|
nll.export(picks, phasefile, parameter)
|
||||||
|
|
||||||
# For locating the event the NLLoc-control file has to be modified!
|
# For locating the event the NLLoc-control file has to be modified!
|
||||||
nllocout = '%s_%s' % (evID, nllocoutpatter)
|
nllocout = '%s_%s' % (evID, nllocoutpatter)
|
||||||
@ -132,7 +286,7 @@ def autoPyLoT(inputfile):
|
|||||||
ttpat)
|
ttpat)
|
||||||
|
|
||||||
# locate the event
|
# locate the event
|
||||||
nll.locate(ctrfile)
|
nll.locate(ctrfile, inputfile)
|
||||||
|
|
||||||
# !iterative picking if traces remained unpicked or occupied with bad picks!
|
# !iterative picking if traces remained unpicked or occupied with bad picks!
|
||||||
# get theoretical onset times for picks with weights >= 4
|
# get theoretical onset times for picks with weights >= 4
|
||||||
@ -154,22 +308,38 @@ def autoPyLoT(inputfile):
|
|||||||
# get latest NLLoc-location file if several are available
|
# get latest NLLoc-location file if several are available
|
||||||
nllocfile = max(glob.glob(locsearch), key=os.path.getctime)
|
nllocfile = max(glob.glob(locsearch), key=os.path.getctime)
|
||||||
evt = read_events(nllocfile)[0]
|
evt = read_events(nllocfile)[0]
|
||||||
# calculating seismic moment Mo and moment magnitude Mw
|
# calculate seismic moment Mo and moment magnitude Mw
|
||||||
moment_mag = MomentMagnitude(corr_dat, evt, parameter.get('vp'),
|
moment_mag = MomentMagnitude(corr_dat, evt, parameter.get('vp'),
|
||||||
parameter.get('Qp'),
|
parameter.get('Qp'),
|
||||||
parameter.get('rho'), True, 0)
|
parameter.get('rho'), True,
|
||||||
|
iplot)
|
||||||
# update pick with moment property values (w0, fc, Mo)
|
# update pick with moment property values (w0, fc, Mo)
|
||||||
for station, props in moment_mag.moment_props.items():
|
for stats, props in moment_mag.moment_props.items():
|
||||||
picks[station]['P'].update(props)
|
picks[stats]['P'].update(props)
|
||||||
evt = moment_mag.updated_event()
|
evt = moment_mag.updated_event()
|
||||||
local_mag = RichterMagnitude(corr_dat, evt,
|
net_mw = moment_mag.net_magnitude()
|
||||||
parameter.get('sstop'), True, 0)
|
print("Network moment magnitude: %4.1f" % net_mw.mag)
|
||||||
for station, amplitude in local_mag.amplitudes.items():
|
# calculate local (Richter) magntiude
|
||||||
picks[station]['S']['Ao'] = amplitude.generic_amplitude
|
WAscaling = parameter.get('WAscaling')
|
||||||
evt = local_mag.updated_event()
|
magscaling = parameter.get('magscaling')
|
||||||
|
local_mag = LocalMagnitude(corr_dat, evt,
|
||||||
|
parameter.get('sstop'),
|
||||||
|
WAscaling, True, iplot)
|
||||||
|
for stats, amplitude in local_mag.amplitudes.items():
|
||||||
|
picks[stats]['S']['Ao'] = amplitude.generic_amplitude
|
||||||
|
print("Local station magnitudes scaled with:")
|
||||||
|
print("log(Ao) + %f * log(r) + %f * r + %f" % (WAscaling[0],
|
||||||
|
WAscaling[1],
|
||||||
|
WAscaling[2]))
|
||||||
|
evt = local_mag.updated_event(magscaling)
|
||||||
|
net_ml = local_mag.net_magnitude(magscaling)
|
||||||
|
print("Network local magnitude: %4.1f" % net_ml.mag)
|
||||||
|
print("Network local magnitude scaled with:")
|
||||||
|
print("%f * Ml + %f" % (magscaling[0], magscaling[1]))
|
||||||
else:
|
else:
|
||||||
print("autoPyLoT: No NLLoc-location file available!")
|
print("autoPyLoT: No NLLoc-location file available!")
|
||||||
print("No source parameter estimation possible!")
|
print("No source parameter estimation possible!")
|
||||||
|
locflag = 9
|
||||||
else:
|
else:
|
||||||
# get theoretical P-onset times from NLLoc-location file
|
# get theoretical P-onset times from NLLoc-location file
|
||||||
locsearch = '%s/loc/%s.????????.??????.grid?.loc.hyp' % (nllocroot, nllocout)
|
locsearch = '%s/loc/%s.????????.??????.grid?.loc.hyp' % (nllocroot, nllocout)
|
||||||
@ -183,13 +353,19 @@ def autoPyLoT(inputfile):
|
|||||||
print("autoPyLoT: Number of maximum iterations reached, stop iterative picking!")
|
print("autoPyLoT: Number of maximum iterations reached, stop iterative picking!")
|
||||||
break
|
break
|
||||||
print("autoPyLoT: Starting with iteration No. %d ..." % nlloccounter)
|
print("autoPyLoT: Starting with iteration No. %d ..." % nlloccounter)
|
||||||
|
if input_dict:
|
||||||
|
if 'fig_dict' in input_dict:
|
||||||
|
fig_dict = input_dict['fig_dict']
|
||||||
|
picks = iteratepicker(wfdat, nllocfile, picks, badpicks, parameter,
|
||||||
|
fig_dict=fig_dict)
|
||||||
|
else:
|
||||||
picks = iteratepicker(wfdat, nllocfile, picks, badpicks, parameter)
|
picks = iteratepicker(wfdat, nllocfile, picks, badpicks, parameter)
|
||||||
# write phases to NLLoc-phase file
|
# write phases to NLLoc-phase file
|
||||||
nll.export(picks, phasefile)
|
nll.export(picks, phasefile, parameter)
|
||||||
# remove actual NLLoc-location file to keep only the last
|
# remove actual NLLoc-location file to keep only the last
|
||||||
os.remove(nllocfile)
|
os.remove(nllocfile)
|
||||||
# locate the event
|
# locate the event
|
||||||
nll.locate(ctrfile)
|
nll.locate(ctrfile, inputfile)
|
||||||
print("autoPyLoT: Iteration No. %d finished." % nlloccounter)
|
print("autoPyLoT: Iteration No. %d finished." % nlloccounter)
|
||||||
# get updated NLLoc-location file
|
# get updated NLLoc-location file
|
||||||
nllocfile = max(glob.glob(locsearch), key=os.path.getctime)
|
nllocfile = max(glob.glob(locsearch), key=os.path.getctime)
|
||||||
@ -198,73 +374,132 @@ def autoPyLoT(inputfile):
|
|||||||
for key in picks:
|
for key in picks:
|
||||||
if picks[key]['P']['weight'] >= 4 or picks[key]['S']['weight'] >= 4:
|
if picks[key]['P']['weight'] >= 4 or picks[key]['S']['weight'] >= 4:
|
||||||
badpicks.append([key, picks[key]['P']['mpp']])
|
badpicks.append([key, picks[key]['P']['mpp']])
|
||||||
print("autoPyLoT: After iteration No. %d: %d bad onsets found ..." % (nlloccounter, \
|
print("autoPyLoT: After iteration No. %d: %d bad onsets found ..." % (nlloccounter,
|
||||||
len(badpicks)))
|
len(badpicks)))
|
||||||
if len(badpicks) == 0:
|
if len(badpicks) == 0:
|
||||||
print("autoPyLoT: No more bad onsets found, stop iterative picking!")
|
print("autoPyLoT: No more bad onsets found, stop iterative picking!")
|
||||||
nlloccounter = maxnumit
|
nlloccounter = maxnumit
|
||||||
evt = read_events(nllocfile)[0]
|
evt = read_events(nllocfile)[0]
|
||||||
# calculating seismic moment Mo and moment magnitude Mw
|
if locflag < 2:
|
||||||
|
# calculate seismic moment Mo and moment magnitude Mw
|
||||||
moment_mag = MomentMagnitude(corr_dat, evt, parameter.get('vp'),
|
moment_mag = MomentMagnitude(corr_dat, evt, parameter.get('vp'),
|
||||||
parameter.get('Qp'),
|
parameter.get('Qp'),
|
||||||
parameter.get('rho'), True, 0)
|
parameter.get('rho'), True,
|
||||||
|
iplot)
|
||||||
# update pick with moment property values (w0, fc, Mo)
|
# update pick with moment property values (w0, fc, Mo)
|
||||||
for station, props in moment_mag.moment_props.items():
|
for stats, props in moment_mag.moment_props.items():
|
||||||
picks[station]['P'].update(props)
|
if picks.has_key(stats):
|
||||||
|
picks[stats]['P'].update(props)
|
||||||
evt = moment_mag.updated_event()
|
evt = moment_mag.updated_event()
|
||||||
local_mag = RichterMagnitude(corr_dat, evt,
|
|
||||||
parameter.get('sstop'), True, 0)
|
|
||||||
for station, amplitude in local_mag.amplitudes.items():
|
|
||||||
picks[station]['S']['Ao'] = amplitude.generic_amplitude
|
|
||||||
evt = local_mag.updated_event()
|
|
||||||
net_mw = moment_mag.net_magnitude()
|
net_mw = moment_mag.net_magnitude()
|
||||||
print("Network moment magnitude: %4.1f" % net_mw.mag)
|
print("Network moment magnitude: %4.1f" % net_mw.mag)
|
||||||
|
# calculate local (Richter) magntiude
|
||||||
|
WAscaling = parameter.get('WAscaling')
|
||||||
|
magscaling = parameter.get('magscaling')
|
||||||
|
local_mag = LocalMagnitude(corr_dat, evt,
|
||||||
|
parameter.get('sstop'),
|
||||||
|
WAscaling, True, iplot)
|
||||||
|
for stats, amplitude in local_mag.amplitudes.items():
|
||||||
|
if picks.has_key(stats):
|
||||||
|
picks[stats]['S']['Ao'] = amplitude.generic_amplitude
|
||||||
|
print("Local station magnitudes scaled with:")
|
||||||
|
print("log(Ao) + %f * log(r) + %f * r + %f" % (WAscaling[0],
|
||||||
|
WAscaling[1],
|
||||||
|
WAscaling[2]))
|
||||||
|
evt = local_mag.updated_event(magscaling)
|
||||||
|
net_ml = local_mag.net_magnitude(magscaling)
|
||||||
|
print("Network local magnitude: %4.1f" % net_ml.mag)
|
||||||
|
print("Network local magnitude scaled with:")
|
||||||
|
print("%f * Ml + %f" % (magscaling[0], magscaling[1]))
|
||||||
else:
|
else:
|
||||||
print("autoPyLoT: No NLLoc-location file available! Stop iteration!")
|
print("autoPyLoT: No NLLoc-location file available! Stop iteration!")
|
||||||
|
locflag = 9
|
||||||
##########################################################
|
##########################################################
|
||||||
# write phase files for various location routines
|
# write phase files for various location
|
||||||
# HYPO71
|
# and fault mechanism calculation routines
|
||||||
hypo71file = '%s/autoPyLoT_HYPO71.pha' % event
|
# ObsPy event object
|
||||||
hsat.export(picks, hypo71file)
|
|
||||||
data.applyEVTData(picks)
|
|
||||||
if evt is not None:
|
if evt is not None:
|
||||||
|
event_id = eventpath.split('/')[-1]
|
||||||
|
evt.resource_id = ResourceIdentifier('smi:local/' + event_id)
|
||||||
data.applyEVTData(evt, 'event')
|
data.applyEVTData(evt, 'event')
|
||||||
fnqml = '%s/autoPyLoT' % event
|
data.applyEVTData(picks)
|
||||||
data.exportEvent(fnqml)
|
if savexml:
|
||||||
|
if savepath == 'None' or savepath == None:
|
||||||
|
saveEvtPath = eventpath
|
||||||
|
else:
|
||||||
|
saveEvtPath = savepath
|
||||||
|
fnqml = '%s/PyLoT_%s' % (saveEvtPath, evID)
|
||||||
|
data.exportEvent(fnqml, fnext='.xml', fcheck=['auto', 'magnitude', 'origin'])
|
||||||
|
if locflag == 1:
|
||||||
|
# HYPO71
|
||||||
|
hypo71file = '%s/PyLoT_%s_HYPO71_phases' % (eventpath, evID)
|
||||||
|
hypo71.export(picks, hypo71file, parameter)
|
||||||
|
# HYPOSAT
|
||||||
|
hyposatfile = '%s/PyLoT_%s_HYPOSAT_phases' % (eventpath, evID)
|
||||||
|
hyposat.export(picks, hyposatfile, parameter)
|
||||||
|
# VELEST
|
||||||
|
velestfile = '%s/PyLoT_%s_VELEST_phases.cnv' % (eventpath, evID)
|
||||||
|
velest.export(picks, velestfile, evt, parameter)
|
||||||
|
# hypoDD
|
||||||
|
hypoddfile = '%s/PyLoT_%s_hypoDD_phases.pha' % (eventpath, evID)
|
||||||
|
hypodd.export(picks, hypoddfile, parameter, evt)
|
||||||
|
# FOCMEC
|
||||||
|
focmecfile = '%s/PyLoT_%s_FOCMEC.in' % (eventpath, evID)
|
||||||
|
focmec.export(picks, focmecfile, parameter, evt)
|
||||||
|
# HASH
|
||||||
|
hashfile = '%s/PyLoT_%s_HASH' % (eventpath, evID)
|
||||||
|
hash.export(picks, hashfile, parameter, evt)
|
||||||
|
|
||||||
endsplash = '''------------------------------------------\n'
|
endsplash = '''------------------------------------------\n'
|
||||||
-----Finished event %s!-----\n'
|
-----Finished event %s!-----\n'
|
||||||
------------------------------------------'''.format \
|
------------------------------------------'''.format \
|
||||||
(version=_getVersionString()) % evID
|
(version=_getVersionString()) % evID
|
||||||
print(endsplash)
|
print(endsplash)
|
||||||
|
locflag = glocflag
|
||||||
if locflag == 0:
|
if locflag == 0:
|
||||||
print("autoPyLoT was running in non-location mode!")
|
print("autoPyLoT was running in non-location mode!")
|
||||||
|
|
||||||
|
# save picks for current event ID to dictionary with ALL picks
|
||||||
|
allpicks[evID] = picks
|
||||||
|
|
||||||
endsp = '''####################################\n
|
endsp = '''####################################\n
|
||||||
************************************\n
|
************************************\n
|
||||||
*********autoPyLoT terminates*******\n
|
*********autoPyLoT terminates*******\n
|
||||||
The Python picking and Location Tool\n
|
The Python picking and Location Tool\n
|
||||||
************************************'''.format(version=_getVersionString())
|
************************************'''.format(version=_getVersionString())
|
||||||
print(endsp)
|
print(endsp)
|
||||||
|
return allpicks
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
from pylot.core.util.defaults import AUTOMATIC_DEFAULTS
|
|
||||||
# parse arguments
|
# parse arguments
|
||||||
parser = argparse.ArgumentParser(
|
parser = argparse.ArgumentParser(
|
||||||
description='''autoPyLoT automatically picks phase onset times using higher order statistics,
|
description='''autoPyLoT automatically picks phase onset times using higher order statistics,
|
||||||
autoregressive prediction and AIC''')
|
autoregressive prediction and AIC followed by locating the seismic events using
|
||||||
|
NLLoc''')
|
||||||
|
|
||||||
parser.add_argument('-i', '-I', '--inputfile', type=str,
|
parser.add_argument('-i', '-I', '--inputfile', type=str,
|
||||||
action='store',
|
action='store',
|
||||||
help='''full path to the file containing the input
|
help='''full path to the file containing the input
|
||||||
parameters for autoPyLoT''',
|
parameters for autoPyLoT''')
|
||||||
default=AUTOMATIC_DEFAULTS
|
parser.add_argument('-p', '-P', '--iplot', type=int,
|
||||||
)
|
action='store',
|
||||||
parser.add_argument('-v', '-V', '--version', action='version',
|
help='''optional, logical variable for plotting: 0=none, 1=partial, 2=all''')
|
||||||
version='autoPyLoT ' + __version__,
|
parser.add_argument('-f', '-F', '--fnames', type=str,
|
||||||
help='show version information and exit')
|
action='store',
|
||||||
|
help='''optional, list of data file names''')
|
||||||
|
parser.add_argument('-e', '--eventid', type=str,
|
||||||
|
action='store',
|
||||||
|
help='''optional, event path incl. event ID''')
|
||||||
|
parser.add_argument('-s', '-S', '--spath', type=str,
|
||||||
|
action='store',
|
||||||
|
help='''optional, save path for autoPyLoT output''')
|
||||||
|
parser.add_argument('-c', '-C', '--ncores', type=int,
|
||||||
|
action='store', default=0,
|
||||||
|
help='''optional, number of CPU cores used for parallel processing (default: all available(=0))''')
|
||||||
|
|
||||||
cla = parser.parse_args()
|
cla = parser.parse_args()
|
||||||
|
|
||||||
autoPyLoT(str(cla.inputfile))
|
picks = autoPyLoT(inputfile=str(cla.inputfile), fnames=str(cla.fnames),
|
||||||
|
eventid=str(cla.eventid), savepath=str(cla.spath),
|
||||||
|
ncores=cla.ncores, iplot=int(cla.iplot))
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
<html><head><title>PyLoT - the Python picking and Localisation Tool</title></head>
|
<html>
|
||||||
|
<head><title>PyLoT - the Python picking and Localisation Tool</title></head>
|
||||||
<body>
|
<body>
|
||||||
<p><b>PyLoT</b> is a program which is capable of picking seismic phases,
|
<p><b>PyLoT</b> is a program which is capable of picking seismic phases,
|
||||||
exporting these as numerous standard phase format and localize the corresponding
|
exporting these as numerous standard phase format and localize the corresponding
|
||||||
@ -14,4 +15,5 @@ seismic event with external software as, e.g.:</p>
|
|||||||
<p>Bug reports are very much appreciated and can also be delivered on our
|
<p>Bug reports are very much appreciated and can also be delivered on our
|
||||||
<a href="https://ariadne.geophysik.rub.de/trac/PyLoT">PyLoT TracPage</a> after
|
<a href="https://ariadne.geophysik.rub.de/trac/PyLoT">PyLoT TracPage</a> after
|
||||||
successful registration.</p>
|
successful registration.</p>
|
||||||
</body></html>
|
</body>
|
||||||
|
</html>
|
||||||
|
31
icons.qrc
@ -2,10 +2,37 @@
|
|||||||
<qresource>
|
<qresource>
|
||||||
<file>icons/pylot.ico</file>
|
<file>icons/pylot.ico</file>
|
||||||
<file>icons/pylot.png</file>
|
<file>icons/pylot.png</file>
|
||||||
<file>icons/locate.png</file>
|
<file>icons/back.png</file>
|
||||||
|
<file>icons/home.png</file>
|
||||||
|
<file>icons/newfile.png</file>
|
||||||
|
<file>icons/open.png</file>
|
||||||
|
<file>icons/openproject.png</file>
|
||||||
|
<file>icons/add.png</file>
|
||||||
|
<file>icons/save.png</file>
|
||||||
|
<file>icons/saveas.png</file>
|
||||||
|
<file>icons/saveproject.png</file>
|
||||||
|
<file>icons/saveprojectas.png</file>
|
||||||
|
<file>icons/manupicksicon_small.png</file>
|
||||||
|
<file>icons/autopicksicon_small.png</file>
|
||||||
|
<file>icons/tune.png</file>
|
||||||
|
<file>icons/autopylot_button.png</file>
|
||||||
|
<file>icons/pick.png</file>
|
||||||
|
<file>icons/waveform.png</file>
|
||||||
|
<file>icons/openpick.png</file>
|
||||||
|
<file>icons/openpicks.png</file>
|
||||||
|
<file>icons/openpick.png</file>
|
||||||
|
<file>icons/openpicks.png</file>
|
||||||
|
<file>icons/savepicks.png</file>
|
||||||
|
<file>icons/preferences.png</file>
|
||||||
|
<file>icons/parameter.png</file>
|
||||||
|
<file>icons/inventory.png</file>
|
||||||
|
<file>icons/map.png</file>
|
||||||
|
<file>icons/openloc.png</file>
|
||||||
|
<file>icons/compare_button.png</file>
|
||||||
|
<file>icons/locate_button.png</file>
|
||||||
|
<file>icons/Matlab_PILOT_icon.png</file>
|
||||||
<file>icons/printer.png</file>
|
<file>icons/printer.png</file>
|
||||||
<file>icons/delete.png</file>
|
<file>icons/delete.png</file>
|
||||||
<file>icons/compare.png</file>
|
|
||||||
<file>icons/key_E.png</file>
|
<file>icons/key_E.png</file>
|
||||||
<file>icons/key_N.png</file>
|
<file>icons/key_N.png</file>
|
||||||
<file>icons/key_P.png</file>
|
<file>icons/key_P.png</file>
|
||||||
|
BIN
icons/Matlab_PILOT_icon.png
Normal file
After Width: | Height: | Size: 50 KiB |
BIN
icons/add.png
Normal file
After Width: | Height: | Size: 44 KiB |
BIN
icons/autopicksicon_small.png
Normal file
After Width: | Height: | Size: 26 KiB |
BIN
icons/autopicsicon.png
Normal file
After Width: | Height: | Size: 7.1 KiB |
BIN
icons/autopylot_button.png
Normal file
After Width: | Height: | Size: 30 KiB |
BIN
icons/back.png
Normal file
After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 3.0 KiB |
BIN
icons/compare_button.png
Normal file
After Width: | Height: | Size: 18 KiB |
0
icons/delete.png
Executable file → Normal file
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 5.0 KiB |
BIN
icons/home.png
Normal file
After Width: | Height: | Size: 23 KiB |
BIN
icons/inventory.png
Normal file
After Width: | Height: | Size: 24 KiB |
BIN
icons/key_E.png
Executable file → Normal file
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 37 KiB |
BIN
icons/key_N.png
Executable file → Normal file
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 44 KiB |
BIN
icons/key_P.png
Executable file → Normal file
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 43 KiB |
BIN
icons/key_Q.png
Executable file → Normal file
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 59 KiB |
BIN
icons/key_R.png
Executable file → Normal file
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 47 KiB |
BIN
icons/key_S.png
Executable file → Normal file
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 55 KiB |
BIN
icons/key_T.png
Executable file → Normal file
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 36 KiB |
BIN
icons/key_U.png
Executable file → Normal file
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 44 KiB |
BIN
icons/key_V.png
Executable file → Normal file
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 48 KiB |
BIN
icons/key_W.png
Executable file → Normal file
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 54 KiB |
BIN
icons/key_Z.png
Executable file → Normal file
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 45 KiB |
BIN
icons/locate.png
Before Width: | Height: | Size: 7.1 KiB |
BIN
icons/locate_button.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
icons/manupicksicon_small.png
Normal file
After Width: | Height: | Size: 22 KiB |
BIN
icons/manupicsicon.png
Normal file
After Width: | Height: | Size: 7.5 KiB |
BIN
icons/map.png
Normal file
After Width: | Height: | Size: 56 KiB |
BIN
icons/newfile.png
Normal file
After Width: | Height: | Size: 19 KiB |
BIN
icons/open.png
Normal file
After Width: | Height: | Size: 37 KiB |
BIN
icons/openfile.png
Normal file
After Width: | Height: | Size: 50 KiB |
BIN
icons/openloc.png
Normal file
After Width: | Height: | Size: 57 KiB |
BIN
icons/openpick.png
Normal file
After Width: | Height: | Size: 50 KiB |
BIN
icons/openpicks.png
Normal file
After Width: | Height: | Size: 52 KiB |
BIN
icons/openproject.png
Normal file
After Width: | Height: | Size: 58 KiB |
BIN
icons/parameter.png
Normal file
After Width: | Height: | Size: 38 KiB |
BIN
icons/pick.png
Normal file
After Width: | Height: | Size: 23 KiB |
BIN
icons/preferences.png
Normal file
After Width: | Height: | Size: 38 KiB |
BIN
icons/pylot.png
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 39 KiB |
BIN
icons/save.png
Normal file
After Width: | Height: | Size: 19 KiB |
BIN
icons/saveas.png
Normal file
After Width: | Height: | Size: 25 KiB |
BIN
icons/savepicks.png
Normal file
After Width: | Height: | Size: 28 KiB |
BIN
icons/saveproject.png
Normal file
After Width: | Height: | Size: 35 KiB |
BIN
icons/saveprojectas.png
Normal file
After Width: | Height: | Size: 41 KiB |
0
icons/sync.png
Executable file → Normal file
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 4.2 KiB |
BIN
icons/tune.png
Normal file
After Width: | Height: | Size: 37 KiB |
BIN
icons/waveform.png
Normal file
After Width: | Height: | Size: 16 KiB |
0
icons/zoom_0.png
Executable file → Normal file
Before Width: | Height: | Size: 6.9 KiB After Width: | Height: | Size: 6.9 KiB |
0
icons/zoom_in.png
Executable file → Normal file
Before Width: | Height: | Size: 7.0 KiB After Width: | Height: | Size: 7.0 KiB |
0
icons/zoom_out.png
Executable file → Normal file
Before Width: | Height: | Size: 6.9 KiB After Width: | Height: | Size: 6.9 KiB |
21
icons_rc.py
104841
icons_rc_2.py
Normal file
104841
icons_rc_3.py
Normal file
@ -1,100 +0,0 @@
|
|||||||
%This is a parameter input file for autoPyLoT.
|
|
||||||
%All main and special settings regarding data handling
|
|
||||||
%and picking are to be set here!
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
||||||
|
|
||||||
#main settings#
|
|
||||||
/DATA/Insheim #rootpath# %project path
|
|
||||||
EVENT_DATA/LOCAL #datapath# %data path
|
|
||||||
2013.02_Insheim #database# %name of data base
|
|
||||||
e0019.048.13 #eventID# %certain evnt ID for processing
|
|
||||||
True #apverbose#
|
|
||||||
PILOT #datastructure# %choose data structure
|
|
||||||
0 #iplot# %flag for plotting: 0 none, 1, partly, >1 everything
|
|
||||||
AUTOPHASES_AIC_HOS4_ARH #phasefile# %name of autoPILOT output phase file
|
|
||||||
AUTOLOC_AIC_HOS4_ARH #locfile# %name of autoPILOT output location file
|
|
||||||
AUTOFOCMEC_AIC_HOS4_ARH.in #focmecin# %name of focmec input file containing polarities
|
|
||||||
HYPOSAT #locrt# %location routine used ("HYPOINVERSE" or "HYPOSAT")
|
|
||||||
6 #pmin# %minimum required P picks for location
|
|
||||||
4 #p0min# %minimum required P picks for location if at least
|
|
||||||
%3 excellent P picks are found
|
|
||||||
2 #smin# %minimum required S picks for location
|
|
||||||
/home/ludger/bin/run_HYPOSAT4autoPILOT.csh #cshellp# %path and name of c-shell script to run location routine
|
|
||||||
7.6 8.5 #blon# %longitude bounding for location map
|
|
||||||
49 49.4 #blat# %lattitude bounding for location map
|
|
||||||
#parameters for moment magnitude estimation#
|
|
||||||
5000 #vp# %average P-wave velocity
|
|
||||||
2800 #vs# %average S-wave velocity
|
|
||||||
2200 #rho# %rock density [kg/m^3]
|
|
||||||
300 #Qp# %quality factor for P waves
|
|
||||||
100 #Qs# %quality factor for S waves
|
|
||||||
#common settings picker#
|
|
||||||
15 #pstart# %start time [s] for calculating CF for P-picking
|
|
||||||
40 #pstop# %end time [s] for calculating CF for P-picking
|
|
||||||
-1.0 #sstart# %start time [s] after or before(-) P-onset for calculating CF for S-picking
|
|
||||||
7 #sstop# %end time [s] after P-onset for calculating CF for S-picking
|
|
||||||
2 20 #bpz1# %lower/upper corner freq. of first band pass filter Z-comp. [Hz]
|
|
||||||
2 30 #bpz2# %lower/upper corner freq. of second band pass filter Z-comp. [Hz]
|
|
||||||
2 15 #bph1# %lower/upper corner freq. of first band pass filter H-comp. [Hz]
|
|
||||||
2 20 #bph2# %lower/upper corner freq. of second band pass filter z-comp. [Hz]
|
|
||||||
#special settings for calculating CF#
|
|
||||||
%!!Be careful when editing the following!!
|
|
||||||
#Z-component#
|
|
||||||
HOS #algoP# %choose algorithm for P-onset determination (HOS, ARZ, or AR3)
|
|
||||||
7 #tlta# %for HOS-/AR-AIC-picker, length of LTA window [s]
|
|
||||||
4 #hosorder# %for HOS-picker, order of Higher Order Statistics
|
|
||||||
2 #Parorder# %for AR-picker, order of AR process of Z-component
|
|
||||||
1.2 #tdet1z# %for AR-picker, length of AR determination window [s] for Z-component, 1st pick
|
|
||||||
0.4 #tpred1z# %for AR-picker, length of AR prediction window [s] for Z-component, 1st pick
|
|
||||||
0.6 #tdet2z# %for AR-picker, length of AR determination window [s] for Z-component, 2nd pick
|
|
||||||
0.2 #tpred2z# %for AR-picker, length of AR prediction window [s] for Z-component, 2nd pick
|
|
||||||
0.001 #addnoise# %add noise to seismogram for stable AR prediction
|
|
||||||
3 0.1 0.5 0.1 #tsnrz# %for HOS/AR, window lengths for SNR-and slope estimation [tnoise,tsafetey,tsignal,tslope] [s]
|
|
||||||
3 #pickwinP# %for initial AIC pick, length of P-pick window [s]
|
|
||||||
8 #Precalcwin# %for HOS/AR, window length [s] for recalculation of CF (relative to 1st pick)
|
|
||||||
0 #peps4aic# %for HOS/AR, artificial uplift of samples of AIC-function (P)
|
|
||||||
0.2 #aictsmooth# %for HOS/AR, take average of samples for smoothing of AIC-function [s]
|
|
||||||
0.1 #tsmoothP# %for HOS/AR, take average of samples for smoothing CF [s]
|
|
||||||
0.001 #ausP# %for HOS/AR, artificial uplift of samples (aus) of CF (P)
|
|
||||||
1.3 #nfacP# %for HOS/AR, noise factor for noise level determination (P)
|
|
||||||
#H-components#
|
|
||||||
ARH #algoS# %choose algorithm for S-onset determination (ARH or AR3)
|
|
||||||
0.8 #tdet1h# %for HOS/AR, length of AR-determination window [s], H-components, 1st pick
|
|
||||||
0.4 #tpred1h# %for HOS/AR, length of AR-prediction window [s], H-components, 1st pick
|
|
||||||
0.6 #tdet2h# %for HOS/AR, length of AR-determinaton window [s], H-components, 2nd pick
|
|
||||||
0.3 #tpred2h# %for HOS/AR, length of AR-prediction window [s], H-components, 2nd pick
|
|
||||||
4 #Sarorder# %for AR-picker, order of AR process of H-components
|
|
||||||
6 #Srecalcwin# %for AR-picker, window length [s] for recalculation of CF (2nd pick) (H)
|
|
||||||
3 #pickwinS# %for initial AIC pick, length of S-pick window [s]
|
|
||||||
2 0.2 1.5 0.5 #tsnrh# %for ARH/AR3, window lengths for SNR-and slope estimation [tnoise,tsafetey,tsignal,tslope] [s]
|
|
||||||
0.05 #aictsmoothS# %for AIC-picker, take average of samples for smoothing of AIC-function [s]
|
|
||||||
0.02 #tsmoothS# %for AR-picker, take average of samples for smoothing CF [s] (S)
|
|
||||||
0.2 #pepsS# %for AR-picker, artificial uplift of samples of CF (S)
|
|
||||||
0.4 #ausS# %for HOS/AR, artificial uplift of samples (aus) of CF (S)
|
|
||||||
1.5 #nfacS# %for AR-picker, noise factor for noise level determination (S)
|
|
||||||
%first-motion picker%
|
|
||||||
1 #minfmweight# %minimum required p weight for first-motion determination
|
|
||||||
2 #minFMSNR# %miniumum required SNR for first-motion determination
|
|
||||||
0.2 #fmpickwin# %pick window around P onset for calculating zero crossings
|
|
||||||
%quality assessment%
|
|
||||||
#inital AIC onset#
|
|
||||||
0.01 0.02 0.04 0.08 #timeerrorsP# %discrete time errors [s] corresponding to picking weights [0 1 2 3] for P
|
|
||||||
0.04 0.08 0.16 0.32 #timeerrorsS# %discrete time errors [s] corresponding to picking weights [0 1 2 3] for S
|
|
||||||
80 #minAICPslope# %below this slope [counts/s] the initial P pick is rejected
|
|
||||||
1.2 #minAICPSNR# %below this SNR the initial P pick is rejected
|
|
||||||
50 #minAICSslope# %below this slope [counts/s] the initial S pick is rejected
|
|
||||||
1.5 #minAICSSNR# %below this SNR the initial S pick is rejected
|
|
||||||
#check duration of signal using envelope function#
|
|
||||||
1.5 #prepickwin# %pre-signal window length [s] for noise level estimation
|
|
||||||
0.7 #minsiglength# %minimum required length of signal [s]
|
|
||||||
0.2 #sgap# %safety gap between noise and signal window [s]
|
|
||||||
2 #noisefactor# %noiselevel*noisefactor=threshold
|
|
||||||
60 #minpercent# %per cent of samples required higher than threshold
|
|
||||||
#check for spuriously picked S-onsets#
|
|
||||||
3.0 #zfac# %P-amplitude must exceed zfac times RMS-S amplitude
|
|
||||||
#jackknife-processing for P-picks#
|
|
||||||
3 #thresholdweight#%minimum required weight of picks
|
|
||||||
3 #dttolerance# %maximum allowed deviation of P picks from median [s]
|
|
||||||
4 #minstats# %minimum number of stations with reliable P picks
|
|
||||||
3 #Sdttolerance# %maximum allowed deviation from Wadati-diagram
|
|
||||||
|
|
@ -1,99 +0,0 @@
|
|||||||
%This is a parameter input file for autoPyLoT.
|
|
||||||
%All main and special settings regarding data handling
|
|
||||||
%and picking are to be set here!
|
|
||||||
%Parameters are optimized for local data sets!
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
||||||
#main settings#
|
|
||||||
/DATA/Insheim #rootpath# %project path
|
|
||||||
EVENT_DATA/LOCAL #datapath# %data path
|
|
||||||
2016.08_Insheim #database# %name of data base
|
|
||||||
e0007.224.16 #eventID# %event ID for single event processing
|
|
||||||
/DATA/Insheim/STAT_INFO #invdir# %full path to inventory or dataless-seed file
|
|
||||||
PILOT #datastructure#%choose data structure
|
|
||||||
0 #iplot# %flag for plotting: 0 none, 1 partly, >1 everything
|
|
||||||
True #apverbose# %choose 'True' or 'False' for terminal output
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
||||||
#NLLoc settings#
|
|
||||||
/home/ludger/NLLOC #nllocbin# %path to NLLoc executable
|
|
||||||
/home/ludger/NLLOC/Insheim #nllocroot# %root of NLLoc-processing directory
|
|
||||||
AUTOPHASES.obs #phasefile# %name of autoPyLoT-output phase file for NLLoc
|
|
||||||
%(in nllocroot/obs)
|
|
||||||
Insheim_min1d032016_auto.in #ctrfile# %name of autoPyLoT-output control file for NLLoc
|
|
||||||
%(in nllocroot/run)
|
|
||||||
ttime #ttpatter# %pattern of NLLoc ttimes from grid
|
|
||||||
%(in nllocroot/times)
|
|
||||||
AUTOLOC_nlloc #outpatter# %pattern of NLLoc-output file
|
|
||||||
%(returns 'eventID_outpatter')
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
||||||
#parameters for seismic moment estimation#
|
|
||||||
3530 #vp# %average P-wave velocity
|
|
||||||
2500 #rho# %average rock density [kg/m^3]
|
|
||||||
300 0.8 #Qp# %quality factor for P waves ([Qp, ap], Qp*f^a)
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
||||||
AUTOFOCMEC_AIC_HOS4_ARH.in #focmecin# %name of focmec input file containing derived polarities
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
||||||
#common settings picker#
|
|
||||||
15.0 #pstart# %start time [s] for calculating CF for P-picking
|
|
||||||
60.0 #pstop# %end time [s] for calculating CF for P-picking
|
|
||||||
-1.0 #sstart# %start time [s] relative to P-onset for calculating CF for S-picking
|
|
||||||
10.0 #sstop# %end time [s] after P-onset for calculating CF for S-picking
|
|
||||||
2 20 #bpz1# %lower/upper corner freq. of first band pass filter Z-comp. [Hz]
|
|
||||||
2 30 #bpz2# %lower/upper corner freq. of second band pass filter Z-comp. [Hz]
|
|
||||||
2 15 #bph1# %lower/upper corner freq. of first band pass filter H-comp. [Hz]
|
|
||||||
2 20 #bph2# %lower/upper corner freq. of second band pass filter z-comp. [Hz]
|
|
||||||
#special settings for calculating CF#
|
|
||||||
%!!Edit the following only if you know what you are doing!!%
|
|
||||||
#Z-component#
|
|
||||||
HOS #algoP# %choose algorithm for P-onset determination (HOS, ARZ, or AR3)
|
|
||||||
7.0 #tlta# %for HOS-/AR-AIC-picker, length of LTA window [s]
|
|
||||||
4 #hosorder# %for HOS-picker, order of Higher Order Statistics
|
|
||||||
2 #Parorder# %for AR-picker, order of AR process of Z-component
|
|
||||||
1.2 #tdet1z# %for AR-picker, length of AR determination window [s] for Z-component, 1st pick
|
|
||||||
0.4 #tpred1z# %for AR-picker, length of AR prediction window [s] for Z-component, 1st pick
|
|
||||||
0.6 #tdet2z# %for AR-picker, length of AR determination window [s] for Z-component, 2nd pick
|
|
||||||
0.2 #tpred2z# %for AR-picker, length of AR prediction window [s] for Z-component, 2nd pick
|
|
||||||
0.001 #addnoise# %add noise to seismogram for stable AR prediction
|
|
||||||
3 0.1 0.5 0.5 #tsnrz# %for HOS/AR, window lengths for SNR-and slope estimation [tnoise,tsafetey,tsignal,tslope] [s]
|
|
||||||
3.0 #pickwinP# %for initial AIC pick, length of P-pick window [s]
|
|
||||||
6.0 #Precalcwin# %for HOS/AR, window length [s] for recalculation of CF (relative to 1st pick)
|
|
||||||
0.2 #aictsmooth# %for HOS/AR, take average of samples for smoothing of AIC-function [s]
|
|
||||||
0.1 #tsmoothP# %for HOS/AR, take average of samples for smoothing CF [s]
|
|
||||||
0.001 #ausP# %for HOS/AR, artificial uplift of samples (aus) of CF (P)
|
|
||||||
1.3 #nfacP# %for HOS/AR, noise factor for noise level determination (P)
|
|
||||||
#H-components#
|
|
||||||
ARH #algoS# %choose algorithm for S-onset determination (ARH or AR3)
|
|
||||||
0.8 #tdet1h# %for HOS/AR, length of AR-determination window [s], H-components, 1st pick
|
|
||||||
0.4 #tpred1h# %for HOS/AR, length of AR-prediction window [s], H-components, 1st pick
|
|
||||||
0.6 #tdet2h# %for HOS/AR, length of AR-determinaton window [s], H-components, 2nd pick
|
|
||||||
0.3 #tpred2h# %for HOS/AR, length of AR-prediction window [s], H-components, 2nd pick
|
|
||||||
4 #Sarorder# %for AR-picker, order of AR process of H-components
|
|
||||||
5.0 #Srecalcwin# %for AR-picker, window length [s] for recalculation of CF (2nd pick) (H)
|
|
||||||
3.0 #pickwinS# %for initial AIC pick, length of S-pick window [s]
|
|
||||||
2 0.2 1.5 0.5 #tsnrh# %for ARH/AR3, window lengths for SNR-and slope estimation [tnoise,tsafetey,tsignal,tslope] [s]
|
|
||||||
0.5 #aictsmoothS# %for AIC-picker, take average of samples for smoothing of AIC-function [s]
|
|
||||||
0.7 #tsmoothS# %for AR-picker, take average of samples for smoothing CF [s] (S)
|
|
||||||
0.9 #ausS# %for HOS/AR, artificial uplift of samples (aus) of CF (S)
|
|
||||||
1.5 #nfacS# %for AR-picker, noise factor for noise level determination (S)
|
|
||||||
%first-motion picker%
|
|
||||||
1 #minfmweight# %minimum required P weight for first-motion determination
|
|
||||||
2 #minFMSNR# %miniumum required SNR for first-motion determination
|
|
||||||
0.2 #fmpickwin# %pick window around P onset for calculating zero crossings
|
|
||||||
%quality assessment%
|
|
||||||
#inital AIC onset#
|
|
||||||
0.01 0.02 0.04 0.08 #timeerrorsP# %discrete time errors [s] corresponding to picking weights [0 1 2 3] for P
|
|
||||||
0.04 0.08 0.16 0.32 #timeerrorsS# %discrete time errors [s] corresponding to picking weights [0 1 2 3] for S
|
|
||||||
4 #minAICPslope# %below this slope [counts/s] the initial P pick is rejected
|
|
||||||
1.2 #minAICPSNR# %below this SNR the initial P pick is rejected
|
|
||||||
2 #minAICSslope# %below this slope [counts/s] the initial S pick is rejected
|
|
||||||
1.5 #minAICSSNR# %below this SNR the initial S pick is rejected
|
|
||||||
#check duration of signal using envelope function#
|
|
||||||
3 #minsiglength# %minimum required length of signal [s]
|
|
||||||
1.0 #noisefactor# %noiselevel*noisefactor=threshold
|
|
||||||
40 #minpercent# %required percentage of samples higher than threshold
|
|
||||||
#check for spuriously picked S-onsets#
|
|
||||||
2.0 #zfac# %P-amplitude must exceed at least zfac times RMS-S amplitude
|
|
||||||
#check statistics of P onsets#
|
|
||||||
2.5 #mdttolerance# %maximum allowed deviation of P picks from median [s]
|
|
||||||
#wadati check#
|
|
||||||
1.0 #wdttolerance# %maximum allowed deviation from Wadati-diagram
|
|
||||||
|
|
@ -1,100 +0,0 @@
|
|||||||
%This is a parameter input file for autoPyLoT.
|
|
||||||
%All main and special settings regarding data handling
|
|
||||||
%and picking are to be set here!
|
|
||||||
%Parameters are optimized for regional data sets!
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
||||||
|
|
||||||
#main settings#
|
|
||||||
/DATA/Egelados #rootpath# %project path
|
|
||||||
EVENT_DATA/LOCAL #datapath# %data path
|
|
||||||
2006.01_Nisyros #database# %name of data base
|
|
||||||
e1412.008.06 #eventID# %event ID for single event processing
|
|
||||||
/DATA/Egelados/STAT_INFO #invdir# %full path to inventory or dataless-seed file
|
|
||||||
PILOT #datastructure# %choose data structure
|
|
||||||
0 #iplot# %flag for plotting: 0 none, 1, partly, >1 everything
|
|
||||||
True #apverbose# %choose 'True' or 'False' for terminal output
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
||||||
#NLLoc settings#
|
|
||||||
/home/ludger/NLLOC #nllocbin# %path to NLLoc executable
|
|
||||||
/home/ludger/NLLOC/Insheim #nllocroot# %root of NLLoc-processing directory
|
|
||||||
AUTOPHASES.obs #phasefile# %name of autoPyLoT-output phase file for NLLoc
|
|
||||||
%(in nllocroot/obs)
|
|
||||||
Insheim_min1d2015_auto.in #ctrfile# %name of autoPyLoT-output control file for NLLoc
|
|
||||||
%(in nllocroot/run)
|
|
||||||
ttime #ttpatter# %pattern of NLLoc ttimes from grid
|
|
||||||
%(in nllocroot/times)
|
|
||||||
AUTOLOC_nlloc #outpatter# %pattern of NLLoc-output file
|
|
||||||
%(returns 'eventID_outpatter')
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
||||||
#parameters for seismic moment estimation#
|
|
||||||
3530 #vp# %average P-wave velocity
|
|
||||||
2700 #rho# %average rock density [kg/m^3]
|
|
||||||
1000f**0.8 #Qp# %quality factor for P waves (Qp*f^a)
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
||||||
AUTOFOCMEC_AIC_HOS4_ARH.in #focmecin# %name of focmec input file containing derived polarities
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
||||||
#common settings picker#
|
|
||||||
20 #pstart# %start time [s] for calculating CF for P-picking
|
|
||||||
100 #pstop# %end time [s] for calculating CF for P-picking
|
|
||||||
1.0 #sstart# %start time [s] after or before(-) P-onset for calculating CF for S-picking
|
|
||||||
100 #sstop# %end time [s] after P-onset for calculating CF for S-picking
|
|
||||||
3 10 #bpz1# %lower/upper corner freq. of first band pass filter Z-comp. [Hz]
|
|
||||||
3 12 #bpz2# %lower/upper corner freq. of second band pass filter Z-comp. [Hz]
|
|
||||||
3 8 #bph1# %lower/upper corner freq. of first band pass filter H-comp. [Hz]
|
|
||||||
3 6 #bph2# %lower/upper corner freq. of second band pass filter H-comp. [Hz]
|
|
||||||
#special settings for calculating CF#
|
|
||||||
%!!Be careful when editing the following!!
|
|
||||||
#Z-component#
|
|
||||||
HOS #algoP# %choose algorithm for P-onset determination (HOS, ARZ, or AR3)
|
|
||||||
7 #tlta# %for HOS-/AR-AIC-picker, length of LTA window [s]
|
|
||||||
4 #hosorder# %for HOS-picker, order of Higher Order Statistics
|
|
||||||
2 #Parorder# %for AR-picker, order of AR process of Z-component
|
|
||||||
1.2 #tdet1z# %for AR-picker, length of AR determination window [s] for Z-component, 1st pick
|
|
||||||
0.4 #tpred1z# %for AR-picker, length of AR prediction window [s] for Z-component, 1st pick
|
|
||||||
0.6 #tdet2z# %for AR-picker, length of AR determination window [s] for Z-component, 2nd pick
|
|
||||||
0.2 #tpred2z# %for AR-picker, length of AR prediction window [s] for Z-component, 2nd pick
|
|
||||||
0.001 #addnoise# %add noise to seismogram for stable AR prediction
|
|
||||||
5 0.2 3.0 1.5 #tsnrz# %for HOS/AR, window lengths for SNR-and slope estimation [tnoise,tsafetey,tsignal,tslope] [s]
|
|
||||||
3 #pickwinP# %for initial AIC and refined pick, length of P-pick window [s]
|
|
||||||
8 #Precalcwin# %for HOS/AR, window length [s] for recalculation of CF (relative to 1st pick)
|
|
||||||
1.0 #aictsmooth# %for HOS/AR, take average of samples for smoothing of AIC-function [s]
|
|
||||||
0.3 #tsmoothP# %for HOS/AR, take average of samples for smoothing CF [s]
|
|
||||||
0.3 #ausP# %for HOS/AR, artificial uplift of samples (aus) of CF (P)
|
|
||||||
1.3 #nfacP# %for HOS/AR, noise factor for noise level determination (P)
|
|
||||||
#H-components#
|
|
||||||
ARH #algoS# %choose algorithm for S-onset determination (ARH or AR3)
|
|
||||||
0.8 #tdet1h# %for HOS/AR, length of AR-determination window [s], H-components, 1st pick
|
|
||||||
0.4 #tpred1h# %for HOS/AR, length of AR-prediction window [s], H-components, 1st pick
|
|
||||||
0.6 #tdet2h# %for HOS/AR, length of AR-determinaton window [s], H-components, 2nd pick
|
|
||||||
0.3 #tpred2h# %for HOS/AR, length of AR-prediction window [s], H-components, 2nd pick
|
|
||||||
4 #Sarorder# %for AR-picker, order of AR process of H-components
|
|
||||||
10 #Srecalcwin# %for AR-picker, window length [s] for recalculation of CF (2nd pick) (H)
|
|
||||||
25 #pickwinS# %for initial AIC and refined pick, length of S-pick window [s]
|
|
||||||
5 0.2 3.0 3.0 #tsnrh# %for ARH/AR3, window lengths for SNR-and slope estimation [tnoise,tsafetey,tsignal,tslope] [s]
|
|
||||||
3.5 #aictsmoothS# %for AIC-picker, take average of samples for smoothing of AIC-function [s]
|
|
||||||
1.0 #tsmoothS# %for AR-picker, take average of samples for smoothing CF [s] (S)
|
|
||||||
0.2 #ausS# %for HOS/AR, artificial uplift of samples (aus) of CF (S)
|
|
||||||
1.5 #nfacS# %for AR-picker, noise factor for noise level determination (S)
|
|
||||||
%first-motion picker%
|
|
||||||
1 #minfmweight# %minimum required p weight for first-motion determination
|
|
||||||
2 #minFMSNR# %miniumum required SNR for first-motion determination
|
|
||||||
6.0 #fmpickwin# %pick window around P onset for calculating zero crossings
|
|
||||||
%quality assessment%
|
|
||||||
#inital AIC onset#
|
|
||||||
0.04 0.08 0.16 0.32 #timeerrorsP# %discrete time errors [s] corresponding to picking weights [0 1 2 3] for P
|
|
||||||
0.04 0.08 0.16 0.32 #timeerrorsS# %discrete time errors [s] corresponding to picking weights [0 1 2 3] for S
|
|
||||||
3 #minAICPslope# %below this slope [counts/s] the initial P pick is rejected
|
|
||||||
1.2 #minAICPSNR# %below this SNR the initial P pick is rejected
|
|
||||||
5 #minAICSslope# %below this slope [counts/s] the initial S pick is rejected
|
|
||||||
2.5 #minAICSSNR# %below this SNR the initial S pick is rejected
|
|
||||||
#check duration of signal using envelope function#
|
|
||||||
30 #minsiglength# %minimum required length of signal [s]
|
|
||||||
2.5 #noisefactor# %noiselevel*noisefactor=threshold
|
|
||||||
60 #minpercent# %required percentage of samples higher than threshold
|
|
||||||
#check for spuriously picked S-onsets#
|
|
||||||
0.5 #zfac# %P-amplitude must exceed at least zfac times RMS-S amplitude
|
|
||||||
#check statistics of P onsets#
|
|
||||||
45 #mdttolerance# %maximum allowed deviation of P picks from median [s]
|
|
||||||
#wadati check#
|
|
||||||
3.0 #wdttolerance# %maximum allowed deviation from Wadati-diagram
|
|
||||||
|
|
@ -1,2 +0,0 @@
|
|||||||
P bandpass 4 2.0 20.0
|
|
||||||
S bandpass 4 2.0 15.0
|
|
@ -1,98 +0,0 @@
|
|||||||
%This is a example parameter input file for PyLoT.
|
|
||||||
%All main and special settings regarding data handling
|
|
||||||
%and picking are to be set here!
|
|
||||||
%Parameters shown here are optimized for local data sets!
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
||||||
#main settings#
|
|
||||||
/data/Geothermie/Insheim #rootpath# %project path
|
|
||||||
EVENT_DATA/LOCAL #datapath# %data path
|
|
||||||
2013.02_Insheim #database# %name of data base
|
|
||||||
e0019.048.13 #eventID# %event ID for single event processing
|
|
||||||
/data/Geothermie/Insheim/STAT_INFO #invdir# %full path to inventory or dataless-seed file
|
|
||||||
PILOT #datastructure# %choose data structure
|
|
||||||
0 #iplot# %flag for plotting: 0 none, 1 partly, >1 everything
|
|
||||||
True #apverbose# %choose 'True' or 'False' for terminal output
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
||||||
#NLLoc settings#
|
|
||||||
/progs/bin #nllocbin# %path to NLLoc executable
|
|
||||||
/data/Geothermie/Insheim/LOCALISATION/NLLoc #nllocroot# %root of NLLoc-processing directory
|
|
||||||
AUTOPHASES.obs #phasefile# %name of autoPyLoT-output phase file for NLLoc
|
|
||||||
%(in nllocroot/obs)
|
|
||||||
Insheim_min1d2015.in #ctrfile# %name of PyLoT-output control file for NLLoc
|
|
||||||
%(in nllocroot/run)
|
|
||||||
ttime #ttpatter# %pattern of NLLoc ttimes from grid
|
|
||||||
%(in nllocroot/times)
|
|
||||||
AUTOLOC_nlloc #outpatter# %pattern of NLLoc-output file
|
|
||||||
%(returns 'eventID_outpatter')
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
||||||
#parameters for seismic moment estimation#
|
|
||||||
3530 #vp# %average P-wave velocity
|
|
||||||
2500 #rho# %average rock density [kg/m^3]
|
|
||||||
300 0.8 #Qp# %quality factor for P waves (Qp*f^a); list(Qp, a)
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
||||||
AUTOFOCMEC_AIC_HOS4_ARH.in #focmecin# %name of focmec input file containing derived polarities
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
||||||
#common settings picker#
|
|
||||||
15.0 #pstart# %start time [s] for calculating CF for P-picking
|
|
||||||
60.0 #pstop# %end time [s] for calculating CF for P-picking
|
|
||||||
-1.0 #sstart# %start time [s] relative to P-onset for calculating CF for S-picking
|
|
||||||
10.0 #sstop# %end time [s] after P-onset for calculating CF for S-picking
|
|
||||||
2 20 #bpz1# %lower/upper corner freq. of first band pass filter Z-comp. [Hz]
|
|
||||||
2 30 #bpz2# %lower/upper corner freq. of second band pass filter Z-comp. [Hz]
|
|
||||||
2 15 #bph1# %lower/upper corner freq. of first band pass filter H-comp. [Hz]
|
|
||||||
2 20 #bph2# %lower/upper corner freq. of second band pass filter z-comp. [Hz]
|
|
||||||
#special settings for calculating CF#
|
|
||||||
%!!Edit the following only if you know what you are doing!!%
|
|
||||||
#Z-component#
|
|
||||||
HOS #algoP# %choose algorithm for P-onset determination (HOS, ARZ, or AR3)
|
|
||||||
7.0 #tlta# %for HOS-/AR-AIC-picker, length of LTA window [s]
|
|
||||||
4 #hosorder# %for HOS-picker, order of Higher Order Statistics
|
|
||||||
2 #Parorder# %for AR-picker, order of AR process of Z-component
|
|
||||||
1.2 #tdet1z# %for AR-picker, length of AR determination window [s] for Z-component, 1st pick
|
|
||||||
0.4 #tpred1z# %for AR-picker, length of AR prediction window [s] for Z-component, 1st pick
|
|
||||||
0.6 #tdet2z# %for AR-picker, length of AR determination window [s] for Z-component, 2nd pick
|
|
||||||
0.2 #tpred2z# %for AR-picker, length of AR prediction window [s] for Z-component, 2nd pick
|
|
||||||
0.001 #addnoise# %add noise to seismogram for stable AR prediction
|
|
||||||
3 0.1 0.5 0.5 #tsnrz# %for HOS/AR, window lengths for SNR-and slope estimation [tnoise,tsafetey,tsignal,tslope] [s]
|
|
||||||
3.0 #pickwinP# %for initial AIC pick, length of P-pick window [s]
|
|
||||||
6.0 #Precalcwin# %for HOS/AR, window length [s] for recalculation of CF (relative to 1st pick)
|
|
||||||
0.2 #aictsmooth# %for HOS/AR, take average of samples for smoothing of AIC-function [s]
|
|
||||||
0.1 #tsmoothP# %for HOS/AR, take average of samples for smoothing CF [s]
|
|
||||||
0.001 #ausP# %for HOS/AR, artificial uplift of samples (aus) of CF (P)
|
|
||||||
1.3 #nfacP# %for HOS/AR, noise factor for noise level determination (P)
|
|
||||||
#H-components#
|
|
||||||
ARH #algoS# %choose algorithm for S-onset determination (ARH or AR3)
|
|
||||||
0.8 #tdet1h# %for HOS/AR, length of AR-determination window [s], H-components, 1st pick
|
|
||||||
0.4 #tpred1h# %for HOS/AR, length of AR-prediction window [s], H-components, 1st pick
|
|
||||||
0.6 #tdet2h# %for HOS/AR, length of AR-determinaton window [s], H-components, 2nd pick
|
|
||||||
0.3 #tpred2h# %for HOS/AR, length of AR-prediction window [s], H-components, 2nd pick
|
|
||||||
4 #Sarorder# %for AR-picker, order of AR process of H-components
|
|
||||||
5.0 #Srecalcwin# %for AR-picker, window length [s] for recalculation of CF (2nd pick) (H)
|
|
||||||
3.0 #pickwinS# %for initial AIC pick, length of S-pick window [s]
|
|
||||||
2 0.2 1.5 0.5 #tsnrh# %for ARH/AR3, window lengths for SNR-and slope estimation [tnoise,tsafetey,tsignal,tslope] [s]
|
|
||||||
0.5 #aictsmoothS# %for AIC-picker, take average of samples for smoothing of AIC-function [s]
|
|
||||||
0.7 #tsmoothS# %for AR-picker, take average of samples for smoothing CF [s] (S)
|
|
||||||
0.9 #ausS# %for HOS/AR, artificial uplift of samples (aus) of CF (S)
|
|
||||||
1.5 #nfacS# %for AR-picker, noise factor for noise level determination (S)
|
|
||||||
%first-motion picker%
|
|
||||||
1 #minfmweight# %minimum required P weight for first-motion determination
|
|
||||||
2 #minFMSNR# %miniumum required SNR for first-motion determination
|
|
||||||
0.2 #fmpickwin# %pick window around P onset for calculating zero crossings
|
|
||||||
%quality assessment%
|
|
||||||
#inital AIC onset#
|
|
||||||
0.01 0.02 0.04 0.08 #timeerrorsP# %discrete time errors [s] corresponding to picking weights [0 1 2 3] for P
|
|
||||||
0.04 0.08 0.16 0.32 #timeerrorsS# %discrete time errors [s] corresponding to picking weights [0 1 2 3] for S
|
|
||||||
4 #minAICPslope# %below this slope [counts/s] the initial P pick is rejected
|
|
||||||
1.2 #minAICPSNR# %below this SNR the initial P pick is rejected
|
|
||||||
2 #minAICSslope# %below this slope [counts/s] the initial S pick is rejected
|
|
||||||
1.5 #minAICSSNR# %below this SNR the initial S pick is rejected
|
|
||||||
#check duration of signal using envelope function#
|
|
||||||
3 #minsiglength# %minimum required length of signal [s]
|
|
||||||
1.0 #noisefactor# %noiselevel*noisefactor=threshold
|
|
||||||
40 #minpercent# %required percentage of samples higher than threshold
|
|
||||||
#check for spuriously picked S-onsets#
|
|
||||||
2.0 #zfac# %P-amplitude must exceed at least zfac times RMS-S amplitude
|
|
||||||
#check statistics of P onsets#
|
|
||||||
2.5 #mdttolerance# %maximum allowed deviation of P picks from median [s]
|
|
||||||
#wadati check#
|
|
||||||
1.0 #wdttolerance# %maximum allowed deviation from Wadati-diagram
|
|
100
inputs/pylot_global.in
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
%This is a parameter input file for PyLoT/autoPyLoT.
|
||||||
|
%All main and special settings regarding data handling
|
||||||
|
%and picking are to be set here!
|
||||||
|
%Parameters are optimized for %extent data sets!
|
||||||
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
#main settings#
|
||||||
|
#rootpath# %project path
|
||||||
|
#datapath# %data path
|
||||||
|
#database# %name of data base
|
||||||
|
#eventID# %event ID for single event processing (* for all events found in database)
|
||||||
|
#invdir# %full path to inventory or dataless-seed file
|
||||||
|
PILOT #datastructure# %choose data structure
|
||||||
|
True #apverbose# %choose 'True' or 'False' for terminal output
|
||||||
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
#NLLoc settings#
|
||||||
|
None #nllocbin# %path to NLLoc executable
|
||||||
|
None #nllocroot# %root of NLLoc-processing directory
|
||||||
|
None #phasefile# %name of autoPyLoT-output phase file for NLLoc
|
||||||
|
None #ctrfile# %name of autoPyLoT-output control file for NLLoc
|
||||||
|
ttime #ttpatter# %pattern of NLLoc ttimes from grid
|
||||||
|
AUTOLOC_nlloc #outpatter# %pattern of NLLoc-output file
|
||||||
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
#parameters for seismic moment estimation#
|
||||||
|
3530.0 #vp# %average P-wave velocity
|
||||||
|
2500.0 #rho# %average rock density [kg/m^3]
|
||||||
|
300.0 0.8 #Qp# %quality factor for P waves (Qp*f^a); list(Qp, a)
|
||||||
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
#settings local magnitude#
|
||||||
|
1.0 1.0 1.0 #WAscaling# %Scaling relation (log(Ao)+Alog(r)+Br+C) of Wood-Anderson amplitude Ao [nm] If zeros are set, original Richter magnitude is calculated!
|
||||||
|
1.0 1.0 #magscaling# %Scaling relation for derived local magnitude [a*Ml+b]. If zeros are set, no scaling of network magnitude is applied!
|
||||||
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
#filter settings#
|
||||||
|
0.01 0.01 #minfreq# %Lower filter frequency [P, S]
|
||||||
|
0.3 0.3 #maxfreq# %Upper filter frequency [P, S]
|
||||||
|
3 3 #filter_order# %filter order [P, S]
|
||||||
|
bandpass bandpass #filter_type# %filter type (bandpass, bandstop, lowpass, highpass) [P, S]
|
||||||
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
#common settings picker#
|
||||||
|
global #extent# %extent of array ("local", "regional" or "global")
|
||||||
|
-150.0 #pstart# %start time [s] for calculating CF for P-picking (if TauPy: seconds relative to estimated onset)
|
||||||
|
600.0 #pstop# %end time [s] for calculating CF for P-picking (if TauPy: seconds relative to estimated onset)
|
||||||
|
200.0 #sstart# %start time [s] relative to P-onset for calculating CF for S-picking
|
||||||
|
1150.0 #sstop# %end time [s] after P-onset for calculating CF for S-picking
|
||||||
|
True #use_taup# %use estimated traveltimes from TauPy for calculating windows for CF
|
||||||
|
iasp91 #taup_model# %define TauPy model for traveltime estimation. Possible values: 1066a, 1066b, ak135, ak135f, herrin, iasp91, jb, prem, pwdk, sp6
|
||||||
|
0.05 0.5 #bpz1# %lower/upper corner freq. of first band pass filter Z-comp. [Hz]
|
||||||
|
0.001 0.5 #bpz2# %lower/upper corner freq. of second band pass filter Z-comp. [Hz]
|
||||||
|
0.05 0.5 #bph1# %lower/upper corner freq. of first band pass filter H-comp. [Hz]
|
||||||
|
0.001 0.5 #bph2# %lower/upper corner freq. of second band pass filter z-comp. [Hz]
|
||||||
|
#special settings for calculating CF#
|
||||||
|
%!!Edit the following only if you know what you are doing!!%
|
||||||
|
#Z-component#
|
||||||
|
HOS #algoP# %choose algorithm for P-onset determination (HOS, ARZ, or AR3)
|
||||||
|
150.0 #tlta# %for HOS-/AR-AIC-picker, length of LTA window [s]
|
||||||
|
4 #hosorder# %for HOS-picker, order of Higher Order Statistics
|
||||||
|
2 #Parorder# %for AR-picker, order of AR process of Z-component
|
||||||
|
16.0 #tdet1z# %for AR-picker, length of AR determination window [s] for Z-component, 1st pick
|
||||||
|
10.0 #tpred1z# %for AR-picker, length of AR prediction window [s] for Z-component, 1st pick
|
||||||
|
12.0 #tdet2z# %for AR-picker, length of AR determination window [s] for Z-component, 2nd pick
|
||||||
|
6.0 #tpred2z# %for AR-picker, length of AR prediction window [s] for Z-component, 2nd pick
|
||||||
|
0.001 #addnoise# %add noise to seismogram for stable AR prediction
|
||||||
|
60.0 10.0 40.0 10.0 #tsnrz# %for HOS/AR, window lengths for SNR-and slope estimation [tnoise, tsafetey, tsignal, tslope] [s]
|
||||||
|
150.0 #pickwinP# %for initial AIC pick, length of P-pick window [s]
|
||||||
|
35.0 #Precalcwin# %for HOS/AR, window length [s] for recalculation of CF (relative to 1st pick)
|
||||||
|
6.0 #aictsmooth# %for HOS/AR, take average of samples for smoothing of AIC-function [s]
|
||||||
|
4.0 #tsmoothP# %for HOS/AR, take average of samples for smoothing CF [s]
|
||||||
|
0.001 #ausP# %for HOS/AR, artificial uplift of samples (aus) of CF (P)
|
||||||
|
1.1 #nfacP# %for HOS/AR, noise factor for noise level determination (P)
|
||||||
|
#H-components#
|
||||||
|
ARH #algoS# %choose algorithm for S-onset determination (ARH or AR3)
|
||||||
|
12.0 #tdet1h# %for HOS/AR, length of AR-determination window [s], H-components, 1st pick
|
||||||
|
6.0 #tpred1h# %for HOS/AR, length of AR-prediction window [s], H-components, 1st pick
|
||||||
|
8.0 #tdet2h# %for HOS/AR, length of AR-determinaton window [s], H-components, 2nd pick
|
||||||
|
4.0 #tpred2h# %for HOS/AR, length of AR-prediction window [s], H-components, 2nd pick
|
||||||
|
4 #Sarorder# %for AR-picker, order of AR process of H-components
|
||||||
|
30.0 #Srecalcwin# %for AR-picker, window length [s] for recalculation of CF (2nd pick) (H)
|
||||||
|
195.0 #pickwinS# %for initial AIC pick, length of S-pick window [s]
|
||||||
|
100.0 10.0 45.0 10.0 #tsnrh# %for ARH/AR3, window lengths for SNR-and slope estimation [tnoise, tsafetey, tsignal, tslope] [s]
|
||||||
|
22.0 #aictsmoothS# %for AIC-picker, take average of samples for smoothing of AIC-function [s]
|
||||||
|
10.0 #tsmoothS# %for AR-picker, take average of samples for smoothing CF [s] (S)
|
||||||
|
0.001 #ausS# %for HOS/AR, artificial uplift of samples (aus) of CF (S)
|
||||||
|
1.2 #nfacS# %for AR-picker, noise factor for noise level determination (S)
|
||||||
|
#first-motion picker#
|
||||||
|
1 #minfmweight# %minimum required P weight for first-motion determination
|
||||||
|
3.0 #minFMSNR# %miniumum required SNR for first-motion determination
|
||||||
|
10.0 #fmpickwin# %pick window around P onset for calculating zero crossings
|
||||||
|
#quality assessment#
|
||||||
|
1.0 2.0 4.0 8.0 #timeerrorsP# %discrete time errors [s] corresponding to picking weights [0 1 2 3] for P
|
||||||
|
4.0 8.0 16.0 32.0 #timeerrorsS# %discrete time errors [s] corresponding to picking weights [0 1 2 3] for S
|
||||||
|
0.5 #minAICPslope# %below this slope [counts/s] the initial P pick is rejected
|
||||||
|
1.1 #minAICPSNR# %below this SNR the initial P pick is rejected
|
||||||
|
1.0 #minAICSslope# %below this slope [counts/s] the initial S pick is rejected
|
||||||
|
1.3 #minAICSSNR# %below this SNR the initial S pick is rejected
|
||||||
|
5.0 #minsiglength# %length of signal part for which amplitudes must exceed noiselevel [s]
|
||||||
|
1.0 #noisefactor# %noiselevel*noisefactor=threshold
|
||||||
|
10.0 #minpercent# %required percentage of amplitudes exceeding threshold
|
||||||
|
1.2 #zfac# %P-amplitude must exceed at least zfac times RMS-S amplitude
|
||||||
|
25.0 #mdttolerance# %maximum allowed deviation of P picks from median [s]
|
||||||
|
50.0 #wdttolerance# %maximum allowed deviation from Wadati-diagram
|
||||||
|
5.0 #jackfactor# %pick is removed if the variance of the subgroup with the pick removed is larger than the mean variance of all subgroups times safety factor
|
100
inputs/pylot_local.in
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
%This is a parameter input file for PyLoT/autoPyLoT.
|
||||||
|
%All main and special settings regarding data handling
|
||||||
|
%and picking are to be set here!
|
||||||
|
%Parameters are optimized for %extent data sets!
|
||||||
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
#main settings#
|
||||||
|
#rootpath# %project path
|
||||||
|
#datapath# %data path
|
||||||
|
#database# %name of data base
|
||||||
|
#eventID# %event ID for single event processing (* for all events found in database)
|
||||||
|
#invdir# %full path to inventory or dataless-seed file
|
||||||
|
PILOT #datastructure# %choose data structure
|
||||||
|
True #apverbose# %choose 'True' or 'False' for terminal output
|
||||||
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
#NLLoc settings#
|
||||||
|
None #nllocbin# %path to NLLoc executable
|
||||||
|
None #nllocroot# %root of NLLoc-processing directory
|
||||||
|
None #phasefile# %name of autoPyLoT-output phase file for NLLoc
|
||||||
|
None #ctrfile# %name of autoPyLoT-output control file for NLLoc
|
||||||
|
ttime #ttpatter# %pattern of NLLoc ttimes from grid
|
||||||
|
AUTOLOC_nlloc #outpatter# %pattern of NLLoc-output file
|
||||||
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
#parameters for seismic moment estimation#
|
||||||
|
3530.0 #vp# %average P-wave velocity
|
||||||
|
2500.0 #rho# %average rock density [kg/m^3]
|
||||||
|
300.0 0.8 #Qp# %quality factor for P waves (Qp*f^a); list(Qp, a)
|
||||||
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
#settings local magnitude#
|
||||||
|
1.11 0.0009 -2.0 #WAscaling# %Scaling relation (log(Ao)+Alog(r)+Br+C) of Wood-Anderson amplitude Ao [nm] If zeros are set, original Richter magnitude is calculated!
|
||||||
|
1.0382 -0.447 #magscaling# %Scaling relation for derived local magnitude [a*Ml+b]. If zeros are set, no scaling of network magnitude is applied!
|
||||||
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
#filter settings#
|
||||||
|
1.0 1.0 #minfreq# %Lower filter frequency [P, S]
|
||||||
|
10.0 10.0 #maxfreq# %Upper filter frequency [P, S]
|
||||||
|
2 2 #filter_order# %filter order [P, S]
|
||||||
|
bandpass bandpass #filter_type# %filter type (bandpass, bandstop, lowpass, highpass) [P, S]
|
||||||
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
#common settings picker#
|
||||||
|
local #extent# %extent of array ("local", "regional" or "global")
|
||||||
|
15.0 #pstart# %start time [s] for calculating CF for P-picking
|
||||||
|
60.0 #pstop# %end time [s] for calculating CF for P-picking
|
||||||
|
-1.0 #sstart# %start time [s] relative to P-onset for calculating CF for S-picking
|
||||||
|
10.0 #sstop# %end time [s] after P-onset for calculating CF for S-picking
|
||||||
|
True #use_taup# %use estimated traveltimes from TauPy for calculating windows for CF
|
||||||
|
iasp91 #taup_model# %define TauPy model for traveltime estimation
|
||||||
|
2.0 10.0 #bpz1# %lower/upper corner freq. of first band pass filter Z-comp. [Hz]
|
||||||
|
2.0 12.0 #bpz2# %lower/upper corner freq. of second band pass filter Z-comp. [Hz]
|
||||||
|
2.0 8.0 #bph1# %lower/upper corner freq. of first band pass filter H-comp. [Hz]
|
||||||
|
2.0 10.0 #bph2# %lower/upper corner freq. of second band pass filter z-comp. [Hz]
|
||||||
|
#special settings for calculating CF#
|
||||||
|
%!!Edit the following only if you know what you are doing!!%
|
||||||
|
#Z-component#
|
||||||
|
HOS #algoP# %choose algorithm for P-onset determination (HOS, ARZ, or AR3)
|
||||||
|
7.0 #tlta# %for HOS-/AR-AIC-picker, length of LTA window [s]
|
||||||
|
4 #hosorder# %for HOS-picker, order of Higher Order Statistics
|
||||||
|
2 #Parorder# %for AR-picker, order of AR process of Z-component
|
||||||
|
1.2 #tdet1z# %for AR-picker, length of AR determination window [s] for Z-component, 1st pick
|
||||||
|
0.4 #tpred1z# %for AR-picker, length of AR prediction window [s] for Z-component, 1st pick
|
||||||
|
0.6 #tdet2z# %for AR-picker, length of AR determination window [s] for Z-component, 2nd pick
|
||||||
|
0.2 #tpred2z# %for AR-picker, length of AR prediction window [s] for Z-component, 2nd pick
|
||||||
|
0.001 #addnoise# %add noise to seismogram for stable AR prediction
|
||||||
|
3.0 0.1 0.5 1.0 #tsnrz# %for HOS/AR, window lengths for SNR-and slope estimation [tnoise, tsafetey, tsignal, tslope] [s]
|
||||||
|
3.0 #pickwinP# %for initial AIC pick, length of P-pick window [s]
|
||||||
|
6.0 #Precalcwin# %for HOS/AR, window length [s] for recalculation of CF (relative to 1st pick)
|
||||||
|
0.2 #aictsmooth# %for HOS/AR, take average of samples for smoothing of AIC-function [s]
|
||||||
|
0.1 #tsmoothP# %for HOS/AR, take average of samples for smoothing CF [s]
|
||||||
|
0.001 #ausP# %for HOS/AR, artificial uplift of samples (aus) of CF (P)
|
||||||
|
1.3 #nfacP# %for HOS/AR, noise factor for noise level determination (P)
|
||||||
|
#H-components#
|
||||||
|
ARH #algoS# %choose algorithm for S-onset determination (ARH or AR3)
|
||||||
|
0.8 #tdet1h# %for HOS/AR, length of AR-determination window [s], H-components, 1st pick
|
||||||
|
0.4 #tpred1h# %for HOS/AR, length of AR-prediction window [s], H-components, 1st pick
|
||||||
|
0.6 #tdet2h# %for HOS/AR, length of AR-determinaton window [s], H-components, 2nd pick
|
||||||
|
0.3 #tpred2h# %for HOS/AR, length of AR-prediction window [s], H-components, 2nd pick
|
||||||
|
4 #Sarorder# %for AR-picker, order of AR process of H-components
|
||||||
|
5.0 #Srecalcwin# %for AR-picker, window length [s] for recalculation of CF (2nd pick) (H)
|
||||||
|
4.0 #pickwinS# %for initial AIC pick, length of S-pick window [s]
|
||||||
|
2.0 0.3 1.5 1.0 #tsnrh# %for ARH/AR3, window lengths for SNR-and slope estimation [tnoise, tsafetey, tsignal, tslope] [s]
|
||||||
|
1.0 #aictsmoothS# %for AIC-picker, take average of samples for smoothing of AIC-function [s]
|
||||||
|
0.7 #tsmoothS# %for AR-picker, take average of samples for smoothing CF [s] (S)
|
||||||
|
0.9 #ausS# %for HOS/AR, artificial uplift of samples (aus) of CF (S)
|
||||||
|
1.5 #nfacS# %for AR-picker, noise factor for noise level determination (S)
|
||||||
|
#first-motion picker#
|
||||||
|
1 #minfmweight# %minimum required P weight for first-motion determination
|
||||||
|
2.0 #minFMSNR# %miniumum required SNR for first-motion determination
|
||||||
|
0.2 #fmpickwin# %pick window around P onset for calculating zero crossings
|
||||||
|
#quality assessment#
|
||||||
|
0.02 0.04 0.08 0.16 #timeerrorsP# %discrete time errors [s] corresponding to picking weights [0 1 2 3] for P
|
||||||
|
0.04 0.08 0.16 0.32 #timeerrorsS# %discrete time errors [s] corresponding to picking weights [0 1 2 3] for S
|
||||||
|
0.8 #minAICPslope# %below this slope [counts/s] the initial P pick is rejected
|
||||||
|
1.1 #minAICPSNR# %below this SNR the initial P pick is rejected
|
||||||
|
1.0 #minAICSslope# %below this slope [counts/s] the initial S pick is rejected
|
||||||
|
1.5 #minAICSSNR# %below this SNR the initial S pick is rejected
|
||||||
|
1.0 #minsiglength# %length of signal part for which amplitudes must exceed noiselevel [s]
|
||||||
|
1.0 #noisefactor# %noiselevel*noisefactor=threshold
|
||||||
|
10.0 #minpercent# %required percentage of amplitudes exceeding threshold
|
||||||
|
1.5 #zfac# %P-amplitude must exceed at least zfac times RMS-S amplitude
|
||||||
|
6.0 #mdttolerance# %maximum allowed deviation of P picks from median [s]
|
||||||
|
1.0 #wdttolerance# %maximum allowed deviation from Wadati-diagram
|
||||||
|
5.0 #jackfactor# %pick is removed if the variance of the subgroup with the pick removed is larger than the mean variance of all subgroups times safety factor
|
100
inputs/pylot_regional.in
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
%This is a parameter input file for PyLoT/autoPyLoT.
|
||||||
|
%All main and special settings regarding data handling
|
||||||
|
%and picking are to be set here!
|
||||||
|
%Parameters are optimized for %extent data sets!
|
||||||
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
#main settings#
|
||||||
|
#rootpath# %project path
|
||||||
|
#datapath# %data path
|
||||||
|
#database# %name of data base
|
||||||
|
#eventID# %event ID for single event processing (* for all events found in database)
|
||||||
|
#invdir# %full path to inventory or dataless-seed file
|
||||||
|
PILOT #datastructure# %choose data structure
|
||||||
|
True #apverbose# %choose 'True' or 'False' for terminal output
|
||||||
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
#NLLoc settings#
|
||||||
|
None #nllocbin# %path to NLLoc executable
|
||||||
|
None #nllocroot# %root of NLLoc-processing directory
|
||||||
|
None #phasefile# %name of autoPyLoT-output phase file for NLLoc
|
||||||
|
None #ctrfile# %name of autoPyLoT-output control file for NLLoc
|
||||||
|
ttime #ttpatter# %pattern of NLLoc ttimes from grid
|
||||||
|
AUTOLOC_nlloc #outpatter# %pattern of NLLoc-output file
|
||||||
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
#parameters for seismic moment estimation#
|
||||||
|
3530.0 #vp# %average P-wave velocity
|
||||||
|
2500.0 #rho# %average rock density [kg/m^3]
|
||||||
|
300.0 0.8 #Qp# %quality factor for P waves (Qp*f^a); list(Qp, a)
|
||||||
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
#settings local magnitude#
|
||||||
|
1.11 0.0009 -2.0 #WAscaling# %Scaling relation (log(Ao)+Alog(r)+Br+C) of Wood-Anderson amplitude Ao [nm] If zeros are set, original Richter magnitude is calculated!
|
||||||
|
1.0382 -0.447 #magscaling# %Scaling relation for derived local magnitude [a*Ml+b]. If zeros are set, no scaling of network magnitude is applied!
|
||||||
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
#filter settings#
|
||||||
|
1.0 1.0 #minfreq# %Lower filter frequency [P, S]
|
||||||
|
10.0 10.0 #maxfreq# %Upper filter frequency [P, S]
|
||||||
|
2 2 #filter_order# %filter order [P, S]
|
||||||
|
bandpass bandpass #filter_type# %filter type (bandpass, bandstop, lowpass, highpass) [P, S]
|
||||||
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
#common settings picker#
|
||||||
|
local #extent# %extent of array ("local", "regional" or "global")
|
||||||
|
15.0 #pstart# %start time [s] for calculating CF for P-picking
|
||||||
|
60.0 #pstop# %end time [s] for calculating CF for P-picking
|
||||||
|
-1.0 #sstart# %start time [s] relative to P-onset for calculating CF for S-picking
|
||||||
|
10.0 #sstop# %end time [s] after P-onset for calculating CF for S-picking
|
||||||
|
True #use_taup# %use estimated traveltimes from TauPy for calculating windows for CF
|
||||||
|
iasp91 #taup_model# %define TauPy model for traveltime estimation
|
||||||
|
2.0 10.0 #bpz1# %lower/upper corner freq. of first band pass filter Z-comp. [Hz]
|
||||||
|
2.0 12.0 #bpz2# %lower/upper corner freq. of second band pass filter Z-comp. [Hz]
|
||||||
|
2.0 8.0 #bph1# %lower/upper corner freq. of first band pass filter H-comp. [Hz]
|
||||||
|
2.0 10.0 #bph2# %lower/upper corner freq. of second band pass filter z-comp. [Hz]
|
||||||
|
#special settings for calculating CF#
|
||||||
|
%!!Edit the following only if you know what you are doing!!%
|
||||||
|
#Z-component#
|
||||||
|
HOS #algoP# %choose algorithm for P-onset determination (HOS, ARZ, or AR3)
|
||||||
|
7.0 #tlta# %for HOS-/AR-AIC-picker, length of LTA window [s]
|
||||||
|
4 #hosorder# %for HOS-picker, order of Higher Order Statistics
|
||||||
|
2 #Parorder# %for AR-picker, order of AR process of Z-component
|
||||||
|
1.2 #tdet1z# %for AR-picker, length of AR determination window [s] for Z-component, 1st pick
|
||||||
|
0.4 #tpred1z# %for AR-picker, length of AR prediction window [s] for Z-component, 1st pick
|
||||||
|
0.6 #tdet2z# %for AR-picker, length of AR determination window [s] for Z-component, 2nd pick
|
||||||
|
0.2 #tpred2z# %for AR-picker, length of AR prediction window [s] for Z-component, 2nd pick
|
||||||
|
0.001 #addnoise# %add noise to seismogram for stable AR prediction
|
||||||
|
3.0 0.1 0.5 1.0 #tsnrz# %for HOS/AR, window lengths for SNR-and slope estimation [tnoise, tsafetey, tsignal, tslope] [s]
|
||||||
|
3.0 #pickwinP# %for initial AIC pick, length of P-pick window [s]
|
||||||
|
6.0 #Precalcwin# %for HOS/AR, window length [s] for recalculation of CF (relative to 1st pick)
|
||||||
|
0.2 #aictsmooth# %for HOS/AR, take average of samples for smoothing of AIC-function [s]
|
||||||
|
0.1 #tsmoothP# %for HOS/AR, take average of samples for smoothing CF [s]
|
||||||
|
0.001 #ausP# %for HOS/AR, artificial uplift of samples (aus) of CF (P)
|
||||||
|
1.3 #nfacP# %for HOS/AR, noise factor for noise level determination (P)
|
||||||
|
#H-components#
|
||||||
|
ARH #algoS# %choose algorithm for S-onset determination (ARH or AR3)
|
||||||
|
0.8 #tdet1h# %for HOS/AR, length of AR-determination window [s], H-components, 1st pick
|
||||||
|
0.4 #tpred1h# %for HOS/AR, length of AR-prediction window [s], H-components, 1st pick
|
||||||
|
0.6 #tdet2h# %for HOS/AR, length of AR-determinaton window [s], H-components, 2nd pick
|
||||||
|
0.3 #tpred2h# %for HOS/AR, length of AR-prediction window [s], H-components, 2nd pick
|
||||||
|
4 #Sarorder# %for AR-picker, order of AR process of H-components
|
||||||
|
5.0 #Srecalcwin# %for AR-picker, window length [s] for recalculation of CF (2nd pick) (H)
|
||||||
|
4.0 #pickwinS# %for initial AIC pick, length of S-pick window [s]
|
||||||
|
2.0 0.3 1.5 1.0 #tsnrh# %for ARH/AR3, window lengths for SNR-and slope estimation [tnoise, tsafetey, tsignal, tslope] [s]
|
||||||
|
1.0 #aictsmoothS# %for AIC-picker, take average of samples for smoothing of AIC-function [s]
|
||||||
|
0.7 #tsmoothS# %for AR-picker, take average of samples for smoothing CF [s] (S)
|
||||||
|
0.9 #ausS# %for HOS/AR, artificial uplift of samples (aus) of CF (S)
|
||||||
|
1.5 #nfacS# %for AR-picker, noise factor for noise level determination (S)
|
||||||
|
#first-motion picker#
|
||||||
|
1 #minfmweight# %minimum required P weight for first-motion determination
|
||||||
|
2.0 #minFMSNR# %miniumum required SNR for first-motion determination
|
||||||
|
0.2 #fmpickwin# %pick window around P onset for calculating zero crossings
|
||||||
|
#quality assessment#
|
||||||
|
0.02 0.04 0.08 0.16 #timeerrorsP# %discrete time errors [s] corresponding to picking weights [0 1 2 3] for P
|
||||||
|
0.04 0.08 0.16 0.32 #timeerrorsS# %discrete time errors [s] corresponding to picking weights [0 1 2 3] for S
|
||||||
|
0.8 #minAICPslope# %below this slope [counts/s] the initial P pick is rejected
|
||||||
|
1.1 #minAICPSNR# %below this SNR the initial P pick is rejected
|
||||||
|
1.0 #minAICSslope# %below this slope [counts/s] the initial S pick is rejected
|
||||||
|
1.5 #minAICSSNR# %below this SNR the initial S pick is rejected
|
||||||
|
1.0 #minsiglength# %length of signal part for which amplitudes must exceed noiselevel [s]
|
||||||
|
1.0 #noisefactor# %noiselevel*noisefactor=threshold
|
||||||
|
10.0 #minpercent# %required percentage of amplitudes exceeding threshold
|
||||||
|
1.5 #zfac# %P-amplitude must exceed at least zfac times RMS-S amplitude
|
||||||
|
6.0 #mdttolerance# %maximum allowed deviation of P picks from median [s]
|
||||||
|
1.0 #wdttolerance# %maximum allowed deviation from Wadati-diagram
|
||||||
|
5.0 #jackfactor# %pick is removed if the variance of the subgroup with the pick removed is larger than the mean variance of all subgroups times safety factor
|
19
makePyLoT.py
@ -158,24 +158,29 @@ def buildPyLoT(verbosity=None):
|
|||||||
|
|
||||||
|
|
||||||
def installPyLoT(verbosity=None):
|
def installPyLoT(verbosity=None):
|
||||||
files_to_copy = {'autoPyLoT_local.in':['~', '.pylot'],
|
files_to_copy = {'pylot_local.in': ['~', '.pylot'],
|
||||||
'autoPyLoT_regional.in':['~', '.pylot'],
|
'pylot_regional.in': ['~', '.pylot'],
|
||||||
'filter.in':['~', '.pylot']}
|
'pylot_global.in': ['~', '.pylot']}
|
||||||
if verbosity > 0:
|
if verbosity > 0:
|
||||||
print('starting installation of PyLoT ...')
|
print('starting installation of PyLoT ...')
|
||||||
if verbosity > 1:
|
if verbosity > 1:
|
||||||
print('copying input files into destination folder ...')
|
print('copying input files into destination folder ...')
|
||||||
ans = input('please specify scope of interest '
|
ans = input('please specify scope of interest '
|
||||||
'([0]=local, 1=regional) :') or 0
|
'([0]=local, 1=regional, 2=global) :') or 0
|
||||||
if not isinstance(ans, int):
|
if not isinstance(ans, int):
|
||||||
ans = int(ans)
|
ans = int(ans)
|
||||||
ans = 'local' if ans is 0 else 'regional'
|
if ans == 0:
|
||||||
|
ans = 'local'
|
||||||
|
elif ans == 1:
|
||||||
|
ans = 'regional'
|
||||||
|
elif ans == 2:
|
||||||
|
ans = 'global'
|
||||||
link_dest = []
|
link_dest = []
|
||||||
for file, destination in files_to_copy.items():
|
for file, destination in files_to_copy.items():
|
||||||
link_file = ans in file
|
link_file = ans in file
|
||||||
if link_file:
|
if link_file:
|
||||||
link_dest = copy.deepcopy(destination)
|
link_dest = copy.deepcopy(destination)
|
||||||
link_dest.append('autoPyLoT.in')
|
link_dest.append('pylot.in')
|
||||||
link_dest = os.path.join(*link_dest)
|
link_dest = os.path.join(*link_dest)
|
||||||
destination.append(file)
|
destination.append(file)
|
||||||
destination = os.path.join(*destination)
|
destination = os.path.join(*destination)
|
||||||
@ -191,8 +196,6 @@ def installPyLoT(verbosity=None):
|
|||||||
os.symlink(destination, link_dest)
|
os.symlink(destination, link_dest)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def cleanUp(verbosity=None):
|
def cleanUp(verbosity=None):
|
||||||
if verbosity >= 1:
|
if verbosity >= 1:
|
||||||
print('cleaning up build files...')
|
print('cleaning up build files...')
|
||||||
|
BIN
pylot/PyLoT.ico
Before Width: | Height: | Size: 2.2 KiB |
@ -1 +0,0 @@
|
|||||||
0.1a
|
|
0
pylot/__init__.py
Executable file → Normal file
0
pylot/core/__init__.py
Executable file → Normal file
@ -2,28 +2,33 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
"""
|
"""
|
||||||
Created autumn/winter 2015.
|
Created autumn/winter 2015.
|
||||||
|
Revised/extended summer 2017.
|
||||||
|
|
||||||
:author: Ludger Küperkoch / MAGS2 EP3 working group
|
:author: Ludger Küperkoch / MAGS2 EP3 working group
|
||||||
"""
|
"""
|
||||||
import os
|
|
||||||
|
|
||||||
import matplotlib.pyplot as plt
|
import matplotlib.pyplot as plt
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import obspy.core.event as ope
|
import obspy.core.event as ope
|
||||||
from obspy.geodetics import degrees2kilometers
|
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, \
|
from pylot.core.pick.utils import getsignalwin, crossings_nonzero_all, \
|
||||||
select_for_phase
|
select_for_phase
|
||||||
from pylot.core.util.utils import common_range, fit_curve
|
from pylot.core.util.utils import common_range, fit_curve
|
||||||
|
from scipy import integrate, signal
|
||||||
|
from scipy.optimize import curve_fit
|
||||||
|
|
||||||
|
|
||||||
def richter_magnitude_scaling(delta):
|
def richter_magnitude_scaling(delta):
|
||||||
relation = np.loadtxt(os.path.join(os.path.expanduser('~'),
|
distance = np.array([0, 10, 20, 25, 30, 35, 40, 45, 50, 60, 70, 75, 85, 90, 100, 110,
|
||||||
'.pylot', 'richter_scaling.data'))
|
120, 130, 140, 150, 160, 170, 180, 190, 200, 210, 230, 240, 250,
|
||||||
|
260, 270, 280, 290, 300, 310, 320, 330, 340, 350, 360, 370, 380,
|
||||||
|
390, 400, 430, 470, 510, 560, 600, 700, 800, 900, 1000])
|
||||||
|
richter_scaling = np.array([1.4, 1.5, 1.7, 1.9, 2.1, 2.3, 2.4, 2.5, 2.6, 2.8, 2.8, 2.9,
|
||||||
|
2.9, 3.0, 3.1, 3.1, 3.2, 3.2, 3.3, 3.3, 3.4, 3.4, 3.5, 3.5,
|
||||||
|
3.6, 3.7, 3.7, 3.8, 3.8, 3.9, 3.9, 4.0, 4.0, 4.1, 4.2, 4.2,
|
||||||
|
4.2, 4.2, 4.3, 4.3, 4.3, 4.4, 4.4, 4.5, 4.6, 4.7, 4.8, 4.9,
|
||||||
|
5.1, 5.2, 5.4, 5.5, 5.7])
|
||||||
# prepare spline interpolation to calculate return value
|
# prepare spline interpolation to calculate return value
|
||||||
func, params = fit_curve(relation[:, 0], relation[:, 1])
|
func, params = fit_curve(distance, richter_scaling)
|
||||||
return func(delta, params)
|
return func(delta, params)
|
||||||
|
|
||||||
|
|
||||||
@ -34,10 +39,10 @@ class Magnitude(object):
|
|||||||
|
|
||||||
def __init__(self, stream, event, verbosity=False, iplot=0):
|
def __init__(self, stream, event, verbosity=False, iplot=0):
|
||||||
self._type = "M"
|
self._type = "M"
|
||||||
|
self._stream = stream
|
||||||
self._plot_flag = iplot
|
self._plot_flag = iplot
|
||||||
self._verbosity = verbosity
|
self._verbosity = verbosity
|
||||||
self._event = event
|
self._event = event
|
||||||
self._stream = stream
|
|
||||||
self._magnitudes = dict()
|
self._magnitudes = dict()
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
@ -111,17 +116,24 @@ class Magnitude(object):
|
|||||||
def calc(self):
|
def calc(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def updated_event(self):
|
def updated_event(self, magscaling=None):
|
||||||
self.event.magnitudes.append(self.net_magnitude())
|
self.event.magnitudes.append(self.net_magnitude(magscaling))
|
||||||
return self.event
|
return self.event
|
||||||
|
|
||||||
def net_magnitude(self):
|
def net_magnitude(self, magscaling=None):
|
||||||
if self:
|
if self:
|
||||||
# TODO if an average Magnitude instead of the median is calculated
|
if magscaling is not None and str(magscaling) is not '[0.0, 0.0]':
|
||||||
# StationMagnitudeContributions should be added to the returned
|
# scaling necessary
|
||||||
# Magnitude object
|
print("Scaling network magnitude ...")
|
||||||
# mag_error => weights (magnitude error estimate from peak_to_peak, calcsourcespec?)
|
mag = ope.Magnitude(
|
||||||
# weights => StationMagnitdeContribution
|
mag=np.median([M.mag for M in self.magnitudes.values()]) * \
|
||||||
|
magscaling[0] + magscaling[1],
|
||||||
|
magnitude_type=self.type,
|
||||||
|
origin_id=self.origin_id,
|
||||||
|
station_count=len(self.magnitudes),
|
||||||
|
azimuthal_gap=self.origin_id.get_referred_object().quality.azimuthal_gap)
|
||||||
|
else:
|
||||||
|
# no saling necessary
|
||||||
mag = ope.Magnitude(
|
mag = ope.Magnitude(
|
||||||
mag=np.median([M.mag for M in self.magnitudes.values()]),
|
mag=np.median([M.mag for M in self.magnitudes.values()]),
|
||||||
magnitude_type=self.type,
|
magnitude_type=self.type,
|
||||||
@ -132,7 +144,7 @@ class Magnitude(object):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
class RichterMagnitude(Magnitude):
|
class LocalMagnitude(Magnitude):
|
||||||
"""
|
"""
|
||||||
Method to derive peak-to-peak amplitude as seen on a Wood-Anderson-
|
Method to derive peak-to-peak amplitude as seen on a Wood-Anderson-
|
||||||
seismograph. Has to be derived from instrument corrected traces!
|
seismograph. Has to be derived from instrument corrected traces!
|
||||||
@ -149,10 +161,11 @@ class RichterMagnitude(Magnitude):
|
|||||||
|
|
||||||
_amplitudes = dict()
|
_amplitudes = dict()
|
||||||
|
|
||||||
def __init__(self, stream, event, calc_win, verbosity=False, iplot=0):
|
def __init__(self, stream, event, calc_win, wascaling, verbosity=False, iplot=0):
|
||||||
super(RichterMagnitude, self).__init__(stream, event, verbosity, iplot)
|
super(LocalMagnitude, self).__init__(stream, event, verbosity, iplot)
|
||||||
|
|
||||||
self._calc_win = calc_win
|
self._calc_win = calc_win
|
||||||
|
self._wascaling = wascaling
|
||||||
self._type = 'ML'
|
self._type = 'ML'
|
||||||
self.calc()
|
self.calc()
|
||||||
|
|
||||||
@ -164,6 +177,10 @@ class RichterMagnitude(Magnitude):
|
|||||||
def calc_win(self, value):
|
def calc_win(self, value):
|
||||||
self._calc_win = value
|
self._calc_win = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def wascaling(self):
|
||||||
|
return self._wascaling
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def amplitudes(self):
|
def amplitudes(self):
|
||||||
return self._amplitudes
|
return self._amplitudes
|
||||||
@ -175,6 +192,14 @@ class RichterMagnitude(Magnitude):
|
|||||||
|
|
||||||
def peak_to_peak(self, st, t0):
|
def peak_to_peak(self, st, t0):
|
||||||
|
|
||||||
|
try:
|
||||||
|
iplot = int(self.plot_flag)
|
||||||
|
except:
|
||||||
|
if self.plot_flag == True or self.plot_flag == 'True':
|
||||||
|
iplot = 2
|
||||||
|
else:
|
||||||
|
iplot = 0
|
||||||
|
|
||||||
# simulate Wood-Anderson response
|
# simulate Wood-Anderson response
|
||||||
st.simulate(paz_remove=None, paz_simulate=self._paz)
|
st.simulate(paz_remove=None, paz_simulate=self._paz)
|
||||||
|
|
||||||
@ -198,28 +223,29 @@ class RichterMagnitude(Magnitude):
|
|||||||
th = np.arange(0, len(sqH) * dt, dt)
|
th = np.arange(0, len(sqH) * dt, dt)
|
||||||
# get maximum peak within pick window
|
# get maximum peak within pick window
|
||||||
iwin = getsignalwin(th, t0 - stime, self.calc_win)
|
iwin = getsignalwin(th, t0 - stime, self.calc_win)
|
||||||
|
ii = min([iwin[len(iwin) - 1], len(th)])
|
||||||
|
iwin = iwin[0:ii]
|
||||||
wapp = np.max(sqH[iwin])
|
wapp = np.max(sqH[iwin])
|
||||||
if self.verbose:
|
if self.verbose:
|
||||||
print("Determined Wood-Anderson peak-to-peak amplitude: {0} "
|
print("Determined Wood-Anderson peak-to-peak amplitude for station {0}: {1} "
|
||||||
"mm".format(wapp))
|
"mm".format(st[0].stats.station, wapp))
|
||||||
|
|
||||||
# check for plot flag (for debugging only)
|
# check for plot flag (for debugging only)
|
||||||
if self.plot_flag > 1:
|
fig = None
|
||||||
|
if iplot > 1:
|
||||||
st.plot()
|
st.plot()
|
||||||
f = plt.figure(2)
|
fig = plt.figure()
|
||||||
plt.plot(th, sqH)
|
ax = fig.add_subplot(111)
|
||||||
plt.plot(th[iwin], sqH[iwin], 'g')
|
ax.plot(th, sqH)
|
||||||
plt.plot([t0, t0], [0, max(sqH)], 'r', linewidth=2)
|
ax.plot(th[iwin], sqH[iwin], 'g')
|
||||||
plt.title(
|
ax.plot([t0, t0], [0, max(sqH)], 'r', linewidth=2)
|
||||||
|
ax.title(
|
||||||
'Station %s, RMS Horizontal Traces, WA-peak-to-peak=%4.1f mm' \
|
'Station %s, RMS Horizontal Traces, WA-peak-to-peak=%4.1f mm' \
|
||||||
% (st[0].stats.station, wapp))
|
% (st[0].stats.station, wapp))
|
||||||
plt.xlabel('Time [s]')
|
ax.set_xlabel('Time [s]')
|
||||||
plt.ylabel('Displacement [mm]')
|
ax.set_ylabel('Displacement [mm]')
|
||||||
plt.show()
|
|
||||||
raw_input()
|
|
||||||
plt.close(f)
|
|
||||||
|
|
||||||
return wapp
|
return wapp, fig
|
||||||
|
|
||||||
def calc(self):
|
def calc(self):
|
||||||
for a in self.arrivals:
|
for a in self.arrivals:
|
||||||
@ -237,7 +263,7 @@ class RichterMagnitude(Magnitude):
|
|||||||
continue
|
continue
|
||||||
delta = degrees2kilometers(a.distance)
|
delta = degrees2kilometers(a.distance)
|
||||||
onset = pick.time
|
onset = pick.time
|
||||||
a0 = self.peak_to_peak(wf, onset)
|
a0, self.p2p_fig = self.peak_to_peak(wf, onset)
|
||||||
amplitude = ope.Amplitude(generic_amplitude=a0 * 1e-3)
|
amplitude = ope.Amplitude(generic_amplitude=a0 * 1e-3)
|
||||||
amplitude.unit = 'm'
|
amplitude.unit = 'm'
|
||||||
amplitude.category = 'point'
|
amplitude.category = 'point'
|
||||||
@ -248,10 +274,18 @@ class RichterMagnitude(Magnitude):
|
|||||||
self.event.amplitudes.append(amplitude)
|
self.event.amplitudes.append(amplitude)
|
||||||
self.amplitudes = (station, amplitude)
|
self.amplitudes = (station, amplitude)
|
||||||
# using standard Gutenberg-Richter relation
|
# using standard Gutenberg-Richter relation
|
||||||
# TODO make the ML calculation more flexible by allowing
|
# or scale WA amplitude with given scaling relation
|
||||||
# use of custom relation functions
|
if str(self.wascaling) == '[0.0, 0.0, 0.0]':
|
||||||
magnitude = ope.StationMagnitude(
|
print("Calculating original Richter magnitude ...")
|
||||||
mag=np.log10(a0) + richter_magnitude_scaling(delta))
|
magnitude = ope.StationMagnitude(mag=np.log10(a0) \
|
||||||
|
+ richter_magnitude_scaling(delta))
|
||||||
|
else:
|
||||||
|
print("Calculating scaled local magnitude ...")
|
||||||
|
a0 = a0 * 1e03 # mm to nm (see Havskov & Ottemöller, 2010)
|
||||||
|
magnitude = ope.StationMagnitude(mag=np.log10(a0) \
|
||||||
|
+ self.wascaling[0] * np.log10(delta) + self.wascaling[1]
|
||||||
|
* delta + self.wascaling[
|
||||||
|
2])
|
||||||
magnitude.origin_id = self.origin_id
|
magnitude.origin_id = self.origin_id
|
||||||
magnitude.waveform_id = pick.waveform_id
|
magnitude.waveform_id = pick.waveform_id
|
||||||
magnitude.amplitude_id = amplitude.resource_id
|
magnitude.amplitude_id = amplitude.resource_id
|
||||||
@ -317,8 +351,8 @@ class MomentMagnitude(Magnitude):
|
|||||||
continue
|
continue
|
||||||
pick = a.pick_id.get_referred_object()
|
pick = a.pick_id.get_referred_object()
|
||||||
station = pick.waveform_id.station_code
|
station = pick.waveform_id.station_code
|
||||||
wf = select_for_phase(self.stream.select(
|
scopy = self.stream.copy()
|
||||||
station=station), a.phase)
|
wf = scopy.select(station=station)
|
||||||
if not wf:
|
if not wf:
|
||||||
continue
|
continue
|
||||||
onset = pick.time
|
onset = pick.time
|
||||||
@ -326,15 +360,16 @@ class MomentMagnitude(Magnitude):
|
|||||||
azimuth = a.azimuth
|
azimuth = a.azimuth
|
||||||
incidence = a.takeoff_angle
|
incidence = a.takeoff_angle
|
||||||
w0, fc = calcsourcespec(wf, onset, self.p_velocity, distance,
|
w0, fc = calcsourcespec(wf, onset, self.p_velocity, distance,
|
||||||
azimuth,
|
azimuth, incidence, self.p_attenuation,
|
||||||
incidence, self.p_attenuation,
|
|
||||||
self.plot_flag, self.verbose)
|
self.plot_flag, self.verbose)
|
||||||
if w0 is None or fc is None:
|
if w0 is None or fc is None:
|
||||||
if self.verbose:
|
if self.verbose:
|
||||||
print("WARNING: insufficient frequency information")
|
print("WARNING: insufficient frequency information")
|
||||||
continue
|
continue
|
||||||
wf = select_for_phase(wf, "P")
|
WF = select_for_phase(self.stream.select(
|
||||||
m0, mw = calcMoMw(wf, w0, self.rock_density, self.p_velocity,
|
station=station), a.phase)
|
||||||
|
WF = select_for_phase(WF, "P")
|
||||||
|
m0, mw = calcMoMw(WF, w0, self.rock_density, self.p_velocity,
|
||||||
distance, self.verbose)
|
distance, self.verbose)
|
||||||
self.moment_props = (station, dict(w0=w0, fc=fc, Mo=m0))
|
self.moment_props = (station, dict(w0=w0, fc=fc, Mo=m0))
|
||||||
magnitude = ope.StationMagnitude(mag=mw)
|
magnitude = ope.StationMagnitude(mag=mw)
|
||||||
@ -426,7 +461,15 @@ def calcsourcespec(wfstream, onset, vp, delta, azimuth, incidence,
|
|||||||
:type: integer
|
:type: integer
|
||||||
'''
|
'''
|
||||||
if verbosity:
|
if verbosity:
|
||||||
print ("Calculating source spectrum ....")
|
print("Calculating source spectrum for station %s ...." % wfstream[0].stats.station)
|
||||||
|
|
||||||
|
try:
|
||||||
|
iplot = int(iplot)
|
||||||
|
except:
|
||||||
|
if iplot == True or iplot == 'True':
|
||||||
|
iplot = 2
|
||||||
|
else:
|
||||||
|
iplot = 0
|
||||||
|
|
||||||
# get Q value
|
# get Q value
|
||||||
Q, A = qp
|
Q, A = qp
|
||||||
@ -453,18 +496,21 @@ def calcsourcespec(wfstream, onset, vp, delta, azimuth, incidence,
|
|||||||
LQT = wfstream.rotate('ZNE->LQT', azimuth, incidence)
|
LQT = wfstream.rotate('ZNE->LQT', azimuth, incidence)
|
||||||
ldat = LQT.select(component="L")
|
ldat = LQT.select(component="L")
|
||||||
if len(ldat) == 0:
|
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
|
# no azimuth information is available and thus no
|
||||||
# rotation is possible!
|
# rotation is possible!
|
||||||
if verbosity:
|
if verbosity:
|
||||||
print("calcsourcespec: Azimuth information is missing, "
|
print("calcsourcespec: Azimuth information is missing, "
|
||||||
"no rotation of components possible!")
|
"no rotation of components possible!")
|
||||||
|
# instead, use component 3
|
||||||
|
ldat = LQT.select(component="3")
|
||||||
|
if len(ldat) == 0:
|
||||||
|
# maybe component z available
|
||||||
ldat = LQT.select(component="Z")
|
ldat = LQT.select(component="Z")
|
||||||
|
|
||||||
# integrate to displacement
|
# integrate to displacement
|
||||||
# unrotated vertical component (for comparison)
|
# unrotated vertical component (for comparison)
|
||||||
inttrz = signal.detrend(integrate.cumtrapz(zdat[0].data, None, dt))
|
inttrz = signal.detrend(integrate.cumtrapz(zdat[0].data, None, dt))
|
||||||
|
|
||||||
# rotated component Z => L
|
# rotated component Z => L
|
||||||
Ldat = signal.detrend(integrate.cumtrapz(ldat[0].data, None, dt))
|
Ldat = signal.detrend(integrate.cumtrapz(ldat[0].data, None, dt))
|
||||||
|
|
||||||
@ -527,22 +573,24 @@ def calcsourcespec(wfstream, onset, vp, delta, azimuth, incidence,
|
|||||||
# use of implicit scipy otimization function
|
# use of implicit scipy otimization function
|
||||||
fit = synthsourcespec(F, w0in, Fcin)
|
fit = synthsourcespec(F, w0in, Fcin)
|
||||||
[optspecfit, _] = curve_fit(synthsourcespec, F, YYcor, [w0in, Fcin])
|
[optspecfit, _] = curve_fit(synthsourcespec, F, YYcor, [w0in, Fcin])
|
||||||
w01 = optspecfit[0]
|
w0 = optspecfit[0]
|
||||||
fc1 = optspecfit[1]
|
fc = optspecfit[1]
|
||||||
|
# w01 = optspecfit[0]
|
||||||
|
# fc1 = optspecfit[1]
|
||||||
if verbosity:
|
if verbosity:
|
||||||
print("calcsourcespec: Determined w0-value: %e m/Hz, \n"
|
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
|
# 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
|
# get w0 and fc as median of both
|
||||||
# source spectrum fits
|
# source spectrum fits
|
||||||
w0 = np.median([w01, w02])
|
# w0 = np.median([w01, w02])
|
||||||
fc = np.median([fc1, fc2])
|
# fc = np.median([fc1, fc2])
|
||||||
if verbosity:
|
# if verbosity:
|
||||||
print("calcsourcespec: Using w0-value = %e m/Hz and fc = %f Hz" % (
|
# print("calcsourcespec: Using w0-value = %e m/Hz and fc = %f Hz" % (
|
||||||
w0, fc))
|
# w0, fc))
|
||||||
|
|
||||||
if iplot > 1:
|
if iplot > 1:
|
||||||
f1 = plt.figure()
|
f1 = plt.figure()
|
||||||
@ -569,18 +617,15 @@ def calcsourcespec(wfstream, onset, vp, delta, azimuth, incidence,
|
|||||||
p3, = plt.loglog(F, YYcor, 'r')
|
p3, = plt.loglog(F, YYcor, 'r')
|
||||||
p4, = plt.loglog(F, fit, 'g')
|
p4, = plt.loglog(F, fit, 'g')
|
||||||
plt.loglog([fc, fc], [w0 / 100, w0], 'g')
|
plt.loglog([fc, fc], [w0 / 100, w0], 'g')
|
||||||
plt.legend([p1, p2, p3, p4], ['Raw Spectrum', \
|
plt.legend([p1, p2, p3, p4], ['Raw Spectrum',
|
||||||
'Used Raw Spectrum', \
|
'Used Raw Spectrum',
|
||||||
'Q-Corrected Spectrum', \
|
'Q-Corrected Spectrum',
|
||||||
'Fit to Spectrum'])
|
'Fit to Spectrum'])
|
||||||
plt.title('Source Spectrum from P Pulse, w0=%e m/Hz, fc=%6.2f Hz' \
|
plt.title('Source Spectrum from P Pulse, w0=%e m/Hz, fc=%6.2f Hz' \
|
||||||
% (w0, fc))
|
% (w0, fc))
|
||||||
plt.xlabel('Frequency [Hz]')
|
plt.xlabel('Frequency [Hz]')
|
||||||
plt.ylabel('Amplitude [m/Hz]')
|
plt.ylabel('Amplitude [m/Hz]')
|
||||||
plt.grid()
|
plt.grid()
|
||||||
plt.show()
|
|
||||||
raw_input()
|
|
||||||
plt.close(f1)
|
|
||||||
|
|
||||||
return w0, fc
|
return w0, fc
|
||||||
|
|
||||||
@ -622,23 +667,48 @@ def fitSourceModel(f, S, fc0, iplot, verbosity=False):
|
|||||||
:type: float
|
:type: float
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
try:
|
||||||
|
iplot = int(iplot)
|
||||||
|
except:
|
||||||
|
if iplot == True or iplot == 'True':
|
||||||
|
iplot = 2
|
||||||
|
else:
|
||||||
|
iplot = 0
|
||||||
|
|
||||||
w0 = []
|
w0 = []
|
||||||
stdw0 = []
|
stdw0 = []
|
||||||
fc = []
|
fc = []
|
||||||
stdfc = []
|
stdfc = []
|
||||||
STD = []
|
STD = []
|
||||||
|
|
||||||
# get window around initial corner frequency for trials
|
# get window around initial corner frequency for trials
|
||||||
fcstopl = fc0 - max(1, len(f) / 10)
|
# left side of initial corner frequency
|
||||||
il = np.argmin(abs(f - fcstopl))
|
fcstopl = max(f[0], fc0 - max(1, fc0 / 2))
|
||||||
fcstopl = f[il]
|
il = np.where(f <= fcstopl)
|
||||||
fcstopr = fc0 + min(len(f), len(f) / 10)
|
il = il[0][np.size(il) - 1]
|
||||||
ir = np.argmin(abs(f - fcstopr))
|
# right side of initial corner frequency
|
||||||
fcstopr = f[ir]
|
fcstopr = min(fc0 + (fc0 / 2), f[len(f) - 1])
|
||||||
iF = np.where((f >= fcstopl) & (f <= fcstopr))
|
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
|
# 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]
|
FC = f[i]
|
||||||
indexdc = np.where((f > 0) & (f <= FC))
|
indexdc = np.where((f > 0) & (f <= FC))
|
||||||
dc = np.mean(S[indexdc])
|
dc = np.mean(S[indexdc])
|
||||||
@ -665,7 +735,7 @@ def fitSourceModel(f, S, fc0, iplot, verbosity=False):
|
|||||||
"fitSourceModel: best fc: {0} Hz, best w0: {1} m/Hz".format(fc, w0))
|
"fitSourceModel: best fc: {0} Hz, best w0: {1} m/Hz".format(fc, w0))
|
||||||
|
|
||||||
if iplot > 1:
|
if iplot > 1:
|
||||||
plt.figure(iplot)
|
plt.figure() # iplot)
|
||||||
plt.loglog(f, S, 'k')
|
plt.loglog(f, S, 'k')
|
||||||
plt.loglog([f[0], fc], [w0, w0], 'g')
|
plt.loglog([f[0], fc], [w0, w0], 'g')
|
||||||
plt.loglog([fc, fc], [w0 / 100, w0], 'g')
|
plt.loglog([fc, fc], [w0 / 100, w0], 'g')
|
||||||
@ -674,7 +744,7 @@ def fitSourceModel(f, S, fc0, iplot, verbosity=False):
|
|||||||
plt.xlabel('Frequency [Hz]')
|
plt.xlabel('Frequency [Hz]')
|
||||||
plt.ylabel('Amplitude [m/Hz]')
|
plt.ylabel('Amplitude [m/Hz]')
|
||||||
plt.grid()
|
plt.grid()
|
||||||
plt.figure(iplot + 1)
|
plt.figure() # iplot + 1)
|
||||||
plt.subplot(311)
|
plt.subplot(311)
|
||||||
plt.plot(f[il:ir], STD, '*')
|
plt.plot(f[il:ir], STD, '*')
|
||||||
plt.title('Common Standard Deviations')
|
plt.title('Common Standard Deviations')
|
||||||
@ -687,8 +757,5 @@ def fitSourceModel(f, S, fc0, iplot, verbosity=False):
|
|||||||
plt.plot(f[il:ir], stdfc, '*')
|
plt.plot(f[il:ir], stdfc, '*')
|
||||||
plt.title('Standard Deviations of Corner Frequencies')
|
plt.title('Standard Deviations of Corner Frequencies')
|
||||||
plt.xlabel('Corner Frequencies [Hz]')
|
plt.xlabel('Corner Frequencies [Hz]')
|
||||||
plt.show()
|
|
||||||
raw_input()
|
|
||||||
plt.close()
|
|
||||||
|
|
||||||
return w0, fc
|
return w0, fc
|
||||||
|
@ -3,14 +3,17 @@
|
|||||||
|
|
||||||
import copy
|
import copy
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from obspy import read_events
|
from obspy import read_events
|
||||||
from obspy.core import read, Stream, UTCDateTime
|
from obspy.core import read, Stream, UTCDateTime
|
||||||
from obspy.core.event import Event
|
from obspy.core.event import Event as ObsPyEvent
|
||||||
|
from obspy.io.sac import SacIOError
|
||||||
from pylot.core.io.phases import readPILOTEvent, picks_from_picksdict, \
|
from pylot.core.io.phases import readPILOTEvent, picks_from_picksdict, \
|
||||||
picksdict_from_pilot, merge_picks
|
picksdict_from_pilot, merge_picks
|
||||||
from pylot.core.util.errors import FormatError, OverwriteError
|
from pylot.core.util.errors import FormatError, OverwriteError
|
||||||
|
from pylot.core.util.event import Event
|
||||||
from pylot.core.util.utils import fnConstructor, full_range
|
from pylot.core.util.utils import fnConstructor, full_range
|
||||||
|
import pylot.core.loc.velest as velest
|
||||||
|
|
||||||
|
|
||||||
class Data(object):
|
class Data(object):
|
||||||
@ -34,12 +37,12 @@ class Data(object):
|
|||||||
self.comp = 'Z'
|
self.comp = 'Z'
|
||||||
self.wfdata = Stream()
|
self.wfdata = Stream()
|
||||||
self._new = False
|
self._new = False
|
||||||
if isinstance(evtdata, Event):
|
if isinstance(evtdata, ObsPyEvent) or isinstance(evtdata, Event):
|
||||||
pass
|
pass
|
||||||
elif isinstance(evtdata, dict):
|
elif isinstance(evtdata, dict):
|
||||||
evt = readPILOTEvent(**evtdata)
|
evt = readPILOTEvent(**evtdata)
|
||||||
evtdata = evt
|
evtdata = evt
|
||||||
elif isinstance(evtdata, basestring):
|
elif isinstance(evtdata, str):
|
||||||
try:
|
try:
|
||||||
cat = read_events(evtdata)
|
cat = read_events(evtdata)
|
||||||
if len(cat) is not 1:
|
if len(cat) is not 1:
|
||||||
@ -50,7 +53,7 @@ class Data(object):
|
|||||||
if 'Unknown format for file' in e.message:
|
if 'Unknown format for file' in e.message:
|
||||||
if 'PHASES' in evtdata:
|
if 'PHASES' in evtdata:
|
||||||
picks = picksdict_from_pilot(evtdata)
|
picks = picksdict_from_pilot(evtdata)
|
||||||
evtdata = Event()
|
evtdata = ObsPyEvent()
|
||||||
evtdata.picks = picks_from_picksdict(picks)
|
evtdata.picks = picks_from_picksdict(picks)
|
||||||
elif 'LOC' in evtdata:
|
elif 'LOC' in evtdata:
|
||||||
raise NotImplementedError('PILOT location information '
|
raise NotImplementedError('PILOT location information '
|
||||||
@ -62,7 +65,7 @@ class Data(object):
|
|||||||
raise e
|
raise e
|
||||||
else: # create an empty Event object
|
else: # create an empty Event object
|
||||||
self.setNew()
|
self.setNew()
|
||||||
evtdata = Event()
|
evtdata = ObsPyEvent()
|
||||||
evtdata.picks = []
|
evtdata.picks = []
|
||||||
self.evtdata = evtdata
|
self.evtdata = evtdata
|
||||||
self.wforiginal = None
|
self.wforiginal = None
|
||||||
@ -74,6 +77,8 @@ class Data(object):
|
|||||||
|
|
||||||
def __add__(self, other):
|
def __add__(self, other):
|
||||||
assert isinstance(other, Data), "operands must be of same type 'Data'"
|
assert isinstance(other, Data), "operands must be of same type 'Data'"
|
||||||
|
rs_id = self.get_evt_data().get('resource_id')
|
||||||
|
rs_id_other = other.get_evt_data().get('resource_id')
|
||||||
if other.isNew() and not self.isNew():
|
if other.isNew() and not self.isNew():
|
||||||
picks_to_add = other.get_evt_data().picks
|
picks_to_add = other.get_evt_data().picks
|
||||||
old_picks = self.get_evt_data().picks
|
old_picks = self.get_evt_data().picks
|
||||||
@ -85,7 +90,7 @@ class Data(object):
|
|||||||
self.evtdata = new.get_evt_data()
|
self.evtdata = new.get_evt_data()
|
||||||
elif self.isNew() and other.isNew():
|
elif self.isNew() and other.isNew():
|
||||||
pass
|
pass
|
||||||
elif self.get_evt_data().get('id') == other.get_evt_data().get('id'):
|
elif rs_id == rs_id_other:
|
||||||
other.setNew()
|
other.setNew()
|
||||||
return self + other
|
return self + other
|
||||||
else:
|
else:
|
||||||
@ -145,16 +150,57 @@ class Data(object):
|
|||||||
# handle forbidden filenames especially on windows systems
|
# handle forbidden filenames especially on windows systems
|
||||||
return fnConstructor(str(ID))
|
return fnConstructor(str(ID))
|
||||||
|
|
||||||
def exportEvent(self, fnout, fnext='.xml'):
|
def checkEvent(self, event, fcheck, forceOverwrite=False):
|
||||||
|
if 'origin' in fcheck:
|
||||||
|
self.replaceOrigin(event, forceOverwrite)
|
||||||
|
if 'magnitude' in fcheck:
|
||||||
|
self.replaceMagnitude(event, forceOverwrite)
|
||||||
|
if 'auto' in fcheck:
|
||||||
|
self.replacePicks(event, 'auto')
|
||||||
|
if 'manual' in fcheck:
|
||||||
|
self.replacePicks(event, 'manual')
|
||||||
|
|
||||||
|
def replaceOrigin(self, event, forceOverwrite=False):
|
||||||
|
if self.get_evt_data().origins or forceOverwrite:
|
||||||
|
if event.origins:
|
||||||
|
print("Found origin, replace it by new origin.")
|
||||||
|
event.origins = self.get_evt_data().origins
|
||||||
|
|
||||||
|
def replaceMagnitude(self, event, forceOverwrite=False):
|
||||||
|
if self.get_evt_data().magnitudes or forceOverwrite:
|
||||||
|
if event.magnitudes:
|
||||||
|
print("Found magnitude, replace it by new magnitude")
|
||||||
|
event.magnitudes = self.get_evt_data().magnitudes
|
||||||
|
|
||||||
|
def replacePicks(self, event, picktype):
|
||||||
|
checkflag = 0
|
||||||
|
picks = event.picks
|
||||||
|
# remove existing picks
|
||||||
|
for j, pick in reversed(list(enumerate(picks))):
|
||||||
|
if picktype in str(pick.method_id.id):
|
||||||
|
picks.pop(j)
|
||||||
|
checkflag = 1
|
||||||
|
if checkflag:
|
||||||
|
print("Found %s pick(s), remove them and append new picks to catalog." % picktype)
|
||||||
|
|
||||||
|
# append new picks
|
||||||
|
for pick in self.get_evt_data().picks:
|
||||||
|
if picktype in str(pick.method_id.id):
|
||||||
|
picks.append(pick)
|
||||||
|
|
||||||
|
def exportEvent(self, fnout, fnext='.xml', fcheck='auto', upperErrors=None):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
:param fnout: basename of file
|
||||||
:param fnout:
|
:param fnext: file extension
|
||||||
:param fnext:
|
:param fcheck: check and delete existing information
|
||||||
:raise KeyError:
|
can be a str or a list of strings of ['manual', 'auto', 'origin', 'magnitude']
|
||||||
"""
|
"""
|
||||||
from pylot.core.util.defaults import OUTPUTFORMATS
|
from pylot.core.util.defaults import OUTPUTFORMATS
|
||||||
|
|
||||||
|
if not type(fcheck) == list:
|
||||||
|
fcheck = [fcheck]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
evtformat = OUTPUTFORMATS[fnext]
|
evtformat = OUTPUTFORMATS[fnext]
|
||||||
except KeyError as e:
|
except KeyError as e:
|
||||||
@ -162,9 +208,96 @@ class Data(object):
|
|||||||
'supported'.format(e, fnext)
|
'supported'.format(e, fnext)
|
||||||
raise FormatError(errmsg)
|
raise FormatError(errmsg)
|
||||||
|
|
||||||
# try exporting event via ObsPy
|
# check for already existing xml-file
|
||||||
try:
|
if fnext == '.xml':
|
||||||
|
if os.path.isfile(fnout + fnext):
|
||||||
|
print("xml-file already exists! Check content ...")
|
||||||
|
cat = read_events(fnout + fnext)
|
||||||
|
if len(cat) > 1:
|
||||||
|
raise IOError('Ambigious event information in file {}'.format(fnout + fnext))
|
||||||
|
if len(cat) < 1:
|
||||||
|
raise IOError('No event information in file {}'.format(fnout + fnext))
|
||||||
|
event = cat[0]
|
||||||
|
if not event.resource_id == self.get_evt_data().resource_id:
|
||||||
|
raise IOError("Missmatching event resource id's: {} and {}".format(event.resource_id,
|
||||||
|
self.get_evt_data().resource_id))
|
||||||
|
self.checkEvent(event, fcheck)
|
||||||
|
self.setEvtData(event)
|
||||||
self.get_evt_data().write(fnout + fnext, format=evtformat)
|
self.get_evt_data().write(fnout + fnext, format=evtformat)
|
||||||
|
# try exporting event
|
||||||
|
else:
|
||||||
|
evtdata_org = self.get_evt_data()
|
||||||
|
picks = evtdata_org.picks
|
||||||
|
eventpath = evtdata_org.path
|
||||||
|
picks_copy = copy.deepcopy(picks)
|
||||||
|
evtdata_copy = Event(eventpath)
|
||||||
|
evtdata_copy.picks = picks_copy
|
||||||
|
|
||||||
|
# check for stations picked automatically as well as manually
|
||||||
|
# Prefer manual picks!
|
||||||
|
for i in range(len(picks)):
|
||||||
|
if picks[i].method_id == 'manual':
|
||||||
|
mstation = picks[i].waveform_id.station_code
|
||||||
|
mstation_ext = mstation + '_'
|
||||||
|
for k in range(len(picks_copy)):
|
||||||
|
if ((picks_copy[k].waveform_id.station_code == mstation) or
|
||||||
|
(picks_copy[k].waveform_id.station_code == mstation_ext)) and \
|
||||||
|
(picks_copy[k].method_id == 'auto'):
|
||||||
|
del picks_copy[k]
|
||||||
|
break
|
||||||
|
lendiff = len(picks) - len(picks_copy)
|
||||||
|
if lendiff is not 0:
|
||||||
|
print("Manual as well as automatic picks available. Prefered the {} manual ones!".format(lendiff))
|
||||||
|
|
||||||
|
if upperErrors:
|
||||||
|
# check for pick uncertainties exceeding adjusted upper errors
|
||||||
|
# Picks with larger uncertainties will not be saved in output file!
|
||||||
|
for j in range(len(picks)):
|
||||||
|
for i in range(len(picks_copy)):
|
||||||
|
if picks_copy[i].phase_hint[0] == 'P':
|
||||||
|
if (picks_copy[i].time_errors['upper_uncertainty'] >= upperErrors[0]) or \
|
||||||
|
(picks_copy[i].time_errors['uncertainty'] == None):
|
||||||
|
print("Uncertainty exceeds or equal adjusted upper time error!")
|
||||||
|
print("Adjusted uncertainty: {}".format(upperErrors[0]))
|
||||||
|
print("Pick uncertainty: {}".format(picks_copy[i].time_errors['uncertainty']))
|
||||||
|
print("{1} P-Pick of station {0} will not be saved in outputfile".format(
|
||||||
|
picks_copy[i].waveform_id.station_code,
|
||||||
|
picks_copy[i].method_id))
|
||||||
|
print("#")
|
||||||
|
del picks_copy[i]
|
||||||
|
break
|
||||||
|
if picks_copy[i].phase_hint[0] == 'S':
|
||||||
|
if (picks_copy[i].time_errors['upper_uncertainty'] >= upperErrors[1]) or \
|
||||||
|
(picks_copy[i].time_errors['uncertainty'] == None):
|
||||||
|
print("Uncertainty exceeds or equal adjusted upper time error!")
|
||||||
|
print("Adjusted uncertainty: {}".format(upperErrors[1]))
|
||||||
|
print("Pick uncertainty: {}".format(picks_copy[i].time_errors['uncertainty']))
|
||||||
|
print("{1} S-Pick of station {0} will not be saved in outputfile".format(
|
||||||
|
picks_copy[i].waveform_id.station_code,
|
||||||
|
picks_copy[i].method_id))
|
||||||
|
print("#")
|
||||||
|
del picks_copy[i]
|
||||||
|
break
|
||||||
|
|
||||||
|
if fnext == '.obs':
|
||||||
|
try:
|
||||||
|
evtdata_copy.write(fnout + fnext, format=evtformat)
|
||||||
|
# write header afterwards
|
||||||
|
evid = str(evtdata_org.resource_id).split('/')[1]
|
||||||
|
header = '# EQEVENT: Label: EQ%s Loc: X 0.00 Y 0.00 Z 10.00 OT 0.00 \n' % evid
|
||||||
|
nllocfile = open(fnout + fnext)
|
||||||
|
l = nllocfile.readlines()
|
||||||
|
nllocfile.close()
|
||||||
|
l.insert(0, header)
|
||||||
|
nllocfile = open(fnout + fnext, 'w')
|
||||||
|
nllocfile.write("".join(l))
|
||||||
|
nllocfile.close()
|
||||||
|
except KeyError as e:
|
||||||
|
raise KeyError('''{0} export format
|
||||||
|
not implemented: {1}'''.format(evtformat, e))
|
||||||
|
if fnext == '.cnv':
|
||||||
|
try:
|
||||||
|
velest.export(picks_copy, fnout + fnext, eventinfo=self.get_evt_data())
|
||||||
except KeyError as e:
|
except KeyError as e:
|
||||||
raise KeyError('''{0} export format
|
raise KeyError('''{0} export format
|
||||||
not implemented: {1}'''.format(evtformat, e))
|
not implemented: {1}'''.format(evtformat, e))
|
||||||
@ -232,6 +365,8 @@ class Data(object):
|
|||||||
self.wfdata += read(fname, format='GSE2')
|
self.wfdata += read(fname, format='GSE2')
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
warnmsg += '{0}\n{1}\n'.format(fname, e)
|
warnmsg += '{0}\n{1}\n'.format(fname, e)
|
||||||
|
except SacIOError as se:
|
||||||
|
warnmsg += '{0}\n{1}\n'.format(fname, se)
|
||||||
if warnmsg:
|
if warnmsg:
|
||||||
warnmsg = 'WARNING: unable to read\n' + warnmsg
|
warnmsg = 'WARNING: unable to read\n' + warnmsg
|
||||||
print(warnmsg)
|
print(warnmsg)
|
||||||
@ -278,12 +413,12 @@ class Data(object):
|
|||||||
def setEvtData(self, event):
|
def setEvtData(self, event):
|
||||||
self.evtdata = event
|
self.evtdata = event
|
||||||
|
|
||||||
def applyEVTData(self, data, type='pick', authority_id='rub'):
|
def applyEVTData(self, data, typ='pick', authority_id='rub'):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
:param data:
|
:param data:
|
||||||
:param type:
|
:param typ:
|
||||||
:param authority_id:
|
:param authority_id:
|
||||||
:raise OverwriteError:
|
:raise OverwriteError:
|
||||||
"""
|
"""
|
||||||
@ -296,12 +431,20 @@ class Data(object):
|
|||||||
:raise OverwriteError: raises an OverwriteError if the picks list is
|
:raise OverwriteError: raises an OverwriteError if the picks list is
|
||||||
not empty. The GUI will then ask for a decision.
|
not empty. The GUI will then ask for a decision.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# firstonset = find_firstonset(picks)
|
# firstonset = find_firstonset(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:
|
if self.get_evt_data().picks:
|
||||||
raise OverwriteError('Actual picks would be overwritten!')
|
raise OverwriteError('Existing picks would be overwritten!')
|
||||||
else:
|
else:
|
||||||
picks = picks_from_picksdict(picks)
|
picks = picks_from_picksdict(picks)
|
||||||
|
break
|
||||||
self.get_evt_data().picks = picks
|
self.get_evt_data().picks = picks
|
||||||
# if 'smi:local' in self.getID() and firstonset:
|
# if 'smi:local' in self.getID() and firstonset:
|
||||||
# fonset_str = firstonset.strftime('%Y_%m_%d_%H_%M_%S')
|
# fonset_str = firstonset.strftime('%Y_%m_%d_%H_%M_%S')
|
||||||
@ -309,26 +452,32 @@ class Data(object):
|
|||||||
# ID.convertIDToQuakeMLURI(authority_id=authority_id)
|
# ID.convertIDToQuakeMLURI(authority_id=authority_id)
|
||||||
# self.get_evt_data().resource_id = ID
|
# self.get_evt_data().resource_id = ID
|
||||||
|
|
||||||
|
|
||||||
def applyEvent(event):
|
def applyEvent(event):
|
||||||
"""
|
"""
|
||||||
takes an `obspy.core.event.Event` object and applies all new
|
takes an `obspy.core.event.Event` object and applies all new
|
||||||
information on the event to the actual data
|
information on the event to the actual data
|
||||||
:param event:
|
:param event:
|
||||||
"""
|
"""
|
||||||
if not self.isNew():
|
if self.isNew():
|
||||||
self.setEvtData(event)
|
self.setEvtData(event)
|
||||||
else:
|
else:
|
||||||
# prevent overwriting original pick information
|
# prevent overwriting original pick information
|
||||||
picks = copy.deepcopy(self.get_evt_data().picks)
|
event_old = self.get_evt_data()
|
||||||
|
if not event_old.resource_id == event.resource_id:
|
||||||
|
print("WARNING: Missmatch in event resource id's: {} and {}".format(
|
||||||
|
event_old.resource_id,
|
||||||
|
event.resource_id))
|
||||||
|
else:
|
||||||
|
picks = copy.deepcopy(event_old.picks)
|
||||||
event = merge_picks(event, picks)
|
event = merge_picks(event, picks)
|
||||||
# apply event information from location
|
# apply event information from location
|
||||||
self.get_evt_data().update(event)
|
event_old.update(event)
|
||||||
|
|
||||||
applydata = {'pick': applyPicks,
|
applydata = {'pick': applyPicks,
|
||||||
'event': applyEvent}
|
'event': applyEvent}
|
||||||
|
|
||||||
applydata[type](data)
|
applydata[typ](data)
|
||||||
|
self._new = False
|
||||||
|
|
||||||
|
|
||||||
class GenericDataStructure(object):
|
class GenericDataStructure(object):
|
||||||
|
491
pylot/core/io/default_parameters.py
Normal file
@ -0,0 +1,491 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
defaults = {'rootpath': {'type': str,
|
||||||
|
'tooltip': 'project path',
|
||||||
|
'value': '',
|
||||||
|
'namestring': 'Root path'},
|
||||||
|
|
||||||
|
'datapath': {'type': str,
|
||||||
|
'tooltip': 'data path',
|
||||||
|
'value': '',
|
||||||
|
'namestring': 'Data path'},
|
||||||
|
|
||||||
|
'database': {'type': str,
|
||||||
|
'tooltip': 'name of data base',
|
||||||
|
'value': '',
|
||||||
|
'namestring': 'Database path'},
|
||||||
|
|
||||||
|
'eventID': {'type': str,
|
||||||
|
'tooltip': 'event ID for single event processing (* for all events found in database)',
|
||||||
|
'value': '',
|
||||||
|
'namestring': 'Event ID'},
|
||||||
|
|
||||||
|
'extent': {'type': str,
|
||||||
|
'tooltip': 'extent of array ("local", "regional" or "global")',
|
||||||
|
'value': 'local',
|
||||||
|
'namestring': 'Array extent'},
|
||||||
|
|
||||||
|
'invdir': {'type': str,
|
||||||
|
'tooltip': 'full path to inventory or dataless-seed file',
|
||||||
|
'value': '',
|
||||||
|
'namestring': 'Inversion dir'},
|
||||||
|
|
||||||
|
'datastructure': {'type': str,
|
||||||
|
'tooltip': 'choose data structure',
|
||||||
|
'value': 'PILOT',
|
||||||
|
'namestring': 'Datastructure'},
|
||||||
|
|
||||||
|
'apverbose': {'type': bool,
|
||||||
|
'tooltip': "choose 'True' or 'False' for terminal output",
|
||||||
|
'value': True,
|
||||||
|
'namestring': 'App. verbosity'},
|
||||||
|
|
||||||
|
'nllocbin': {'type': str,
|
||||||
|
'tooltip': 'path to NLLoc executable',
|
||||||
|
'value': '',
|
||||||
|
'namestring': 'NLLoc bin path'},
|
||||||
|
|
||||||
|
'nllocroot': {'type': str,
|
||||||
|
'tooltip': 'root of NLLoc-processing directory',
|
||||||
|
'value': '',
|
||||||
|
'namestring': 'NLLoc root path'},
|
||||||
|
|
||||||
|
'phasefile': {'type': str,
|
||||||
|
'tooltip': 'name of autoPyLoT-output phase file for NLLoc',
|
||||||
|
'value': 'AUTOPHASES.obs',
|
||||||
|
'namestring': 'Phase filename'},
|
||||||
|
|
||||||
|
'ctrfile': {'type': str,
|
||||||
|
'tooltip': 'name of autoPyLoT-output control file for NLLoc',
|
||||||
|
'value': 'Insheim_min1d2015_auto.in',
|
||||||
|
'namestring': 'Control filename'},
|
||||||
|
|
||||||
|
'ttpatter': {'type': str,
|
||||||
|
'tooltip': 'pattern of NLLoc ttimes from grid',
|
||||||
|
'value': 'ttime',
|
||||||
|
'namestring': 'Traveltime pattern'},
|
||||||
|
|
||||||
|
'outpatter': {'type': str,
|
||||||
|
'tooltip': 'pattern of NLLoc-output file',
|
||||||
|
'value': 'AUTOLOC_nlloc',
|
||||||
|
'namestring': 'NLLoc output pattern'},
|
||||||
|
|
||||||
|
'vp': {'type': float,
|
||||||
|
'tooltip': 'average P-wave velocity',
|
||||||
|
'value': 3530.,
|
||||||
|
'namestring': 'P-velocity'},
|
||||||
|
|
||||||
|
'rho': {'type': float,
|
||||||
|
'tooltip': 'average rock density [kg/m^3]',
|
||||||
|
'value': 2500.,
|
||||||
|
'namestring': 'Density'},
|
||||||
|
|
||||||
|
'Qp': {'type': (float, float),
|
||||||
|
'tooltip': 'quality factor for P waves (Qp*f^a); list(Qp, a)',
|
||||||
|
'value': (300., 0.8),
|
||||||
|
'namestring': ('Quality factor', 'Qp1', 'Qp2')},
|
||||||
|
|
||||||
|
'pstart': {'type': float,
|
||||||
|
'tooltip': 'start time [s] for calculating CF for P-picking (if TauPy:'
|
||||||
|
' seconds relative to estimated onset)',
|
||||||
|
'value': 15.0,
|
||||||
|
'namestring': 'P start'},
|
||||||
|
|
||||||
|
'pstop': {'type': float,
|
||||||
|
'tooltip': 'end time [s] for calculating CF for P-picking (if TauPy:'
|
||||||
|
' seconds relative to estimated onset)',
|
||||||
|
'value': 60.0,
|
||||||
|
'namestring': 'P stop'},
|
||||||
|
|
||||||
|
'sstart': {'type': float,
|
||||||
|
'tooltip': 'start time [s] relative to P-onset for calculating CF for S-picking',
|
||||||
|
'value': -1.0,
|
||||||
|
'namestring': 'S start'},
|
||||||
|
|
||||||
|
'sstop': {'type': float,
|
||||||
|
'tooltip': 'end time [s] after P-onset for calculating CF for S-picking',
|
||||||
|
'value': 10.0,
|
||||||
|
'namestring': 'S stop'},
|
||||||
|
|
||||||
|
'bpz1': {'type': (float, float),
|
||||||
|
'tooltip': 'lower/upper corner freq. of first band pass filter Z-comp. [Hz]',
|
||||||
|
'value': (2, 20),
|
||||||
|
'namestring': ('Z-bandpass 1', 'Lower', 'Upper')},
|
||||||
|
|
||||||
|
'bpz2': {'type': (float, float),
|
||||||
|
'tooltip': 'lower/upper corner freq. of second band pass filter Z-comp. [Hz]',
|
||||||
|
'value': (2, 30),
|
||||||
|
'namestring': ('Z-bandpass 2', 'Lower', 'Upper')},
|
||||||
|
|
||||||
|
'bph1': {'type': (float, float),
|
||||||
|
'tooltip': 'lower/upper corner freq. of first band pass filter H-comp. [Hz]',
|
||||||
|
'value': (2, 15),
|
||||||
|
'namestring': ('H-bandpass 1', 'Lower', 'Upper')},
|
||||||
|
|
||||||
|
'bph2': {'type': (float, float),
|
||||||
|
'tooltip': 'lower/upper corner freq. of second band pass filter z-comp. [Hz]',
|
||||||
|
'value': (2, 20),
|
||||||
|
'namestring': ('H-bandpass 2', 'Lower', 'Upper')},
|
||||||
|
|
||||||
|
'algoP': {'type': str,
|
||||||
|
'tooltip': 'choose algorithm for P-onset determination (HOS, ARZ, or AR3)',
|
||||||
|
'value': 'HOS',
|
||||||
|
'namestring': 'P algorithm'},
|
||||||
|
|
||||||
|
'tlta': {'type': float,
|
||||||
|
'tooltip': 'for HOS-/AR-AIC-picker, length of LTA window [s]',
|
||||||
|
'value': 7.0,
|
||||||
|
'namestring': 'LTA window'},
|
||||||
|
|
||||||
|
'hosorder': {'type': int,
|
||||||
|
'tooltip': 'for HOS-picker, order of Higher Order Statistics',
|
||||||
|
'value': 4,
|
||||||
|
'namestring': 'HOS order'},
|
||||||
|
|
||||||
|
'Parorder': {'type': int,
|
||||||
|
'tooltip': 'for AR-picker, order of AR process of Z-component',
|
||||||
|
'value': 2,
|
||||||
|
'namestring': 'AR order P'},
|
||||||
|
|
||||||
|
'tdet1z': {'type': float,
|
||||||
|
'tooltip': 'for AR-picker, length of AR determination window [s] for Z-component, 1st pick',
|
||||||
|
'value': 1.2,
|
||||||
|
'namestring': 'AR det. window Z 1'},
|
||||||
|
|
||||||
|
'tpred1z': {'type': float,
|
||||||
|
'tooltip': 'for AR-picker, length of AR prediction window [s] for Z-component, 1st pick',
|
||||||
|
'value': 0.4,
|
||||||
|
'namestring': 'AR pred. window Z 1'},
|
||||||
|
|
||||||
|
'tdet2z': {'type': float,
|
||||||
|
'tooltip': 'for AR-picker, length of AR determination window [s] for Z-component, 2nd pick',
|
||||||
|
'value': 0.6,
|
||||||
|
'namestring': 'AR det. window Z 2'},
|
||||||
|
|
||||||
|
'tpred2z': {'type': float,
|
||||||
|
'tooltip': 'for AR-picker, length of AR prediction window [s] for Z-component, 2nd pick',
|
||||||
|
'value': 0.2,
|
||||||
|
'namestring': 'AR pred. window Z 2'},
|
||||||
|
|
||||||
|
'addnoise': {'type': float,
|
||||||
|
'tooltip': 'add noise to seismogram for stable AR prediction',
|
||||||
|
'value': 0.001,
|
||||||
|
'namestring': 'Add noise'},
|
||||||
|
|
||||||
|
'tsnrz': {'type': (float, float, float, float),
|
||||||
|
'tooltip': 'for HOS/AR, window lengths for SNR-and slope estimation [tnoise, tsafetey, tsignal, tslope] [s]',
|
||||||
|
'value': (3, 0.1, 0.5, 1.0),
|
||||||
|
'namestring': ('SNR windows P', 'Noise', 'Safety', 'Signal', 'Slope')},
|
||||||
|
|
||||||
|
'pickwinP': {'type': float,
|
||||||
|
'tooltip': 'for initial AIC pick, length of P-pick window [s]',
|
||||||
|
'value': 3.0,
|
||||||
|
'namestring': 'AIC window P'},
|
||||||
|
|
||||||
|
'Precalcwin': {'type': float,
|
||||||
|
'tooltip': 'for HOS/AR, window length [s] for recalculation of CF (relative to 1st pick)',
|
||||||
|
'value': 6.0,
|
||||||
|
'namestring': 'Recal. window P'},
|
||||||
|
|
||||||
|
'aictsmooth': {'type': float,
|
||||||
|
'tooltip': 'for HOS/AR, take average of samples for smoothing of AIC-function [s]',
|
||||||
|
'value': 0.2,
|
||||||
|
'namestring': 'AIC smooth P'},
|
||||||
|
|
||||||
|
'tsmoothP': {'type': float,
|
||||||
|
'tooltip': 'for HOS/AR, take average of samples for smoothing CF [s]',
|
||||||
|
'value': 0.1,
|
||||||
|
'namestring': 'CF smooth P'},
|
||||||
|
|
||||||
|
'ausP': {'type': float,
|
||||||
|
'tooltip': 'for HOS/AR, artificial uplift of samples (aus) of CF (P)',
|
||||||
|
'value': 0.001,
|
||||||
|
'namestring': 'Artificial uplift P'},
|
||||||
|
|
||||||
|
'nfacP': {'type': float,
|
||||||
|
'tooltip': 'for HOS/AR, noise factor for noise level determination (P)',
|
||||||
|
'value': 1.3,
|
||||||
|
'namestring': 'Noise factor P'},
|
||||||
|
|
||||||
|
'algoS': {'type': str,
|
||||||
|
'tooltip': 'choose algorithm for S-onset determination (ARH or AR3)',
|
||||||
|
'value': 'ARH',
|
||||||
|
'namestring': 'S algorithm'},
|
||||||
|
|
||||||
|
'tdet1h': {'type': float,
|
||||||
|
'tooltip': 'for HOS/AR, length of AR-determination window [s], H-components, 1st pick',
|
||||||
|
'value': 0.8,
|
||||||
|
'namestring': 'AR det. window H 1'},
|
||||||
|
|
||||||
|
'tpred1h': {'type': float,
|
||||||
|
'tooltip': 'for HOS/AR, length of AR-prediction window [s], H-components, 1st pick',
|
||||||
|
'value': 0.4,
|
||||||
|
'namestring': 'AR pred. window H 1'},
|
||||||
|
|
||||||
|
'tdet2h': {'type': float,
|
||||||
|
'tooltip': 'for HOS/AR, length of AR-determinaton window [s], H-components, 2nd pick',
|
||||||
|
'value': 0.6,
|
||||||
|
'namestring': 'AR det. window H 2'},
|
||||||
|
|
||||||
|
'tpred2h': {'type': float,
|
||||||
|
'tooltip': 'for HOS/AR, length of AR-prediction window [s], H-components, 2nd pick',
|
||||||
|
'value': 0.3,
|
||||||
|
'namestring': 'AR pred. window H 2'},
|
||||||
|
|
||||||
|
'Sarorder': {'type': int,
|
||||||
|
'tooltip': 'for AR-picker, order of AR process of H-components',
|
||||||
|
'value': 4,
|
||||||
|
'namestring': 'AR order S'},
|
||||||
|
|
||||||
|
'Srecalcwin': {'type': float,
|
||||||
|
'tooltip': 'for AR-picker, window length [s] for recalculation of CF (2nd pick) (H)',
|
||||||
|
'value': 5.0,
|
||||||
|
'namestring': 'Recal. window S'},
|
||||||
|
|
||||||
|
'pickwinS': {'type': float,
|
||||||
|
'tooltip': 'for initial AIC pick, length of S-pick window [s]',
|
||||||
|
'value': 3.0,
|
||||||
|
'namestring': 'AIC window S'},
|
||||||
|
|
||||||
|
'tsnrh': {'type': (float, float, float, float),
|
||||||
|
'tooltip': 'for ARH/AR3, window lengths for SNR-and slope estimation [tnoise, tsafetey, tsignal, tslope] [s]',
|
||||||
|
'value': (2, 0.2, 1.5, 0.5),
|
||||||
|
'namestring': ('SNR windows S', 'Noise', 'Safety', 'Signal', 'Slope')},
|
||||||
|
|
||||||
|
'aictsmoothS': {'type': float,
|
||||||
|
'tooltip': 'for AIC-picker, take average of samples for smoothing of AIC-function [s]',
|
||||||
|
'value': 0.5,
|
||||||
|
'namestring': 'AIC smooth S'},
|
||||||
|
|
||||||
|
'tsmoothS': {'type': float,
|
||||||
|
'tooltip': 'for AR-picker, take average of samples for smoothing CF [s] (S)',
|
||||||
|
'value': 0.7,
|
||||||
|
'namestring': 'CF smooth S'},
|
||||||
|
|
||||||
|
'ausS': {'type': float,
|
||||||
|
'tooltip': 'for HOS/AR, artificial uplift of samples (aus) of CF (S)',
|
||||||
|
'value': 0.9,
|
||||||
|
'namestring': 'Artificial uplift S'},
|
||||||
|
|
||||||
|
'nfacS': {'type': float,
|
||||||
|
'tooltip': 'for AR-picker, noise factor for noise level determination (S)',
|
||||||
|
'value': 1.5,
|
||||||
|
'namestring': 'Noise factor S'},
|
||||||
|
|
||||||
|
'minfmweight': {'type': int,
|
||||||
|
'tooltip': 'minimum required P weight for first-motion determination',
|
||||||
|
'value': 1,
|
||||||
|
'namestring': 'Min. P weight'},
|
||||||
|
|
||||||
|
'minFMSNR': {'type': float,
|
||||||
|
'tooltip': 'miniumum required SNR for first-motion determination',
|
||||||
|
'value': 2.,
|
||||||
|
'namestring': 'Min SNR'},
|
||||||
|
|
||||||
|
'fmpickwin': {'type': float,
|
||||||
|
'tooltip': 'pick window around P onset for calculating zero crossings',
|
||||||
|
'value': 0.2,
|
||||||
|
'namestring': 'Zero crossings window'},
|
||||||
|
|
||||||
|
'timeerrorsP': {'type': (float, float, float, float),
|
||||||
|
'tooltip': 'discrete time errors [s] corresponding to picking weights [0 1 2 3] for P',
|
||||||
|
'value': (0.01, 0.02, 0.04, 0.08),
|
||||||
|
'namestring': ('Time errors P', '0', '1', '2', '3')},
|
||||||
|
|
||||||
|
'timeerrorsS': {'type': (float, float, float, float),
|
||||||
|
'tooltip': 'discrete time errors [s] corresponding to picking weights [0 1 2 3] for S',
|
||||||
|
'value': (0.04, 0.08, 0.16, 0.32),
|
||||||
|
'namestring': ('Time errors S', '0', '1', '2', '3')},
|
||||||
|
|
||||||
|
'minAICPslope': {'type': float,
|
||||||
|
'tooltip': 'below this slope [counts/s] the initial P pick is rejected',
|
||||||
|
'value': 0.8,
|
||||||
|
'namestring': 'Min. slope P'},
|
||||||
|
|
||||||
|
'minAICPSNR': {'type': float,
|
||||||
|
'tooltip': 'below this SNR the initial P pick is rejected',
|
||||||
|
'value': 1.1,
|
||||||
|
'namestring': 'Min. SNR P'},
|
||||||
|
|
||||||
|
'minAICSslope': {'type': float,
|
||||||
|
'tooltip': 'below this slope [counts/s] the initial S pick is rejected',
|
||||||
|
'value': 1.,
|
||||||
|
'namestring': 'Min. slope S'},
|
||||||
|
|
||||||
|
'minAICSSNR': {'type': float,
|
||||||
|
'tooltip': 'below this SNR the initial S pick is rejected',
|
||||||
|
'value': 1.5,
|
||||||
|
'namestring': 'Min. SNR S'},
|
||||||
|
|
||||||
|
'minsiglength': {'type': float,
|
||||||
|
'tooltip': 'length of signal part for which amplitudes must exceed noiselevel [s]',
|
||||||
|
'value': 1.,
|
||||||
|
'namestring': 'Min. signal length'},
|
||||||
|
|
||||||
|
'noisefactor': {'type': float,
|
||||||
|
'tooltip': 'noiselevel*noisefactor=threshold',
|
||||||
|
'value': 1.0,
|
||||||
|
'namestring': 'Noise factor'},
|
||||||
|
|
||||||
|
'minpercent': {'type': float,
|
||||||
|
'tooltip': 'required percentage of amplitudes exceeding threshold',
|
||||||
|
'value': 10.,
|
||||||
|
'namestring': 'Min amplitude [%]'},
|
||||||
|
|
||||||
|
'zfac': {'type': float,
|
||||||
|
'tooltip': 'P-amplitude must exceed at least zfac times RMS-S amplitude',
|
||||||
|
'value': 1.5,
|
||||||
|
'namestring': 'Z factor'},
|
||||||
|
|
||||||
|
'mdttolerance': {'type': float,
|
||||||
|
'tooltip': 'maximum allowed deviation of P picks from median [s]',
|
||||||
|
'value': 6.0,
|
||||||
|
'namestring': 'Median tolerance'},
|
||||||
|
|
||||||
|
'wdttolerance': {'type': float,
|
||||||
|
'tooltip': 'maximum allowed deviation from Wadati-diagram',
|
||||||
|
'value': 1.0,
|
||||||
|
'namestring': 'Wadati tolerance'},
|
||||||
|
|
||||||
|
'jackfactor': {'type': float,
|
||||||
|
'tooltip': 'pick is removed if the variance of the subgroup with the pick removed is larger than the mean variance of all subgroups times safety factor',
|
||||||
|
'value': 5.0,
|
||||||
|
'namestring': 'Jackknife safety factor'},
|
||||||
|
|
||||||
|
'WAscaling': {'type': (float, float, float),
|
||||||
|
'tooltip': 'Scaling relation (log(Ao)+Alog(r)+Br+C) of Wood-Anderson amplitude Ao [nm] \
|
||||||
|
If zeros are set, original Richter magnitude is calculated!',
|
||||||
|
'value': (0., 0., 0.),
|
||||||
|
'namestring': ('Wood-Anderson scaling', '', '', '')},
|
||||||
|
|
||||||
|
'magscaling': {'type': (float, float),
|
||||||
|
'tooltip': 'Scaling relation for derived local magnitude [a*Ml+b]. \
|
||||||
|
If zeros are set, no scaling of network magnitude is applied!',
|
||||||
|
'value': (0., 0.),
|
||||||
|
'namestring': ('Local mag. scaling', '', '')},
|
||||||
|
|
||||||
|
'minfreq': {'type': (float, float),
|
||||||
|
'tooltip': 'Lower filter frequency [P, S]',
|
||||||
|
'value': (1.0, 1.0),
|
||||||
|
'namestring': ('Lower freq.', 'P', 'S')},
|
||||||
|
|
||||||
|
'maxfreq': {'type': (float, float),
|
||||||
|
'tooltip': 'Upper filter frequency [P, S]',
|
||||||
|
'value': (10.0, 10.0),
|
||||||
|
'namestring': ('Upper freq.', 'P', 'S')},
|
||||||
|
|
||||||
|
'filter_order': {'type': (int, int),
|
||||||
|
'tooltip': 'filter order [P, S]',
|
||||||
|
'value': (2, 2),
|
||||||
|
'namestring': ('Order', 'P', 'S')},
|
||||||
|
|
||||||
|
'filter_type': {'type': (str, str),
|
||||||
|
'tooltip': 'filter type (bandpass, bandstop, lowpass, highpass) [P, S]',
|
||||||
|
'value': ('bandpass', 'bandpass'),
|
||||||
|
'namestring': ('Type', 'P', 'S')},
|
||||||
|
|
||||||
|
'use_taup': {'type': bool,
|
||||||
|
'tooltip': 'use estimated traveltimes from TauPy for calculating windows for CF',
|
||||||
|
'value': True,
|
||||||
|
'namestring': 'Use TauPy'},
|
||||||
|
|
||||||
|
'taup_model': {'type': str,
|
||||||
|
'tooltip': 'define TauPy model for traveltime estimation. Possible values: 1066a, 1066b, ak135, ak135f, herrin, iasp91, jb, prem, pwdk, sp6',
|
||||||
|
'value': 'iasp91',
|
||||||
|
'namestring': 'TauPy model'}
|
||||||
|
}
|
||||||
|
|
||||||
|
settings_main = {
|
||||||
|
'dirs': [
|
||||||
|
'rootpath',
|
||||||
|
'datapath',
|
||||||
|
'database',
|
||||||
|
'eventID',
|
||||||
|
'invdir',
|
||||||
|
'datastructure',
|
||||||
|
'apverbose'],
|
||||||
|
'nlloc': [
|
||||||
|
'nllocbin',
|
||||||
|
'nllocroot',
|
||||||
|
'phasefile',
|
||||||
|
'ctrfile',
|
||||||
|
'ttpatter',
|
||||||
|
'outpatter'],
|
||||||
|
'smoment': [
|
||||||
|
'vp',
|
||||||
|
'rho',
|
||||||
|
'Qp'],
|
||||||
|
'localmag': [
|
||||||
|
'WAscaling',
|
||||||
|
'magscaling'],
|
||||||
|
'filter': [
|
||||||
|
'minfreq',
|
||||||
|
'maxfreq',
|
||||||
|
'filter_order',
|
||||||
|
'filter_type'],
|
||||||
|
'pick': [
|
||||||
|
'extent',
|
||||||
|
'pstart',
|
||||||
|
'pstop',
|
||||||
|
'sstart',
|
||||||
|
'sstop',
|
||||||
|
'use_taup',
|
||||||
|
'taup_model',
|
||||||
|
'bpz1',
|
||||||
|
'bpz2',
|
||||||
|
'bph1',
|
||||||
|
'bph2']
|
||||||
|
}
|
||||||
|
|
||||||
|
settings_special_pick = {
|
||||||
|
'z': [
|
||||||
|
'algoP',
|
||||||
|
'tlta',
|
||||||
|
'hosorder',
|
||||||
|
'Parorder',
|
||||||
|
'tdet1z',
|
||||||
|
'tpred1z',
|
||||||
|
'tdet2z',
|
||||||
|
'tpred2z',
|
||||||
|
'addnoise',
|
||||||
|
'tsnrz',
|
||||||
|
'pickwinP',
|
||||||
|
'Precalcwin',
|
||||||
|
'aictsmooth',
|
||||||
|
'tsmoothP',
|
||||||
|
'ausP',
|
||||||
|
'nfacP'],
|
||||||
|
'h': [
|
||||||
|
'algoS',
|
||||||
|
'tdet1h',
|
||||||
|
'tpred1h',
|
||||||
|
'tdet2h',
|
||||||
|
'tpred2h',
|
||||||
|
'Sarorder',
|
||||||
|
'Srecalcwin',
|
||||||
|
'pickwinS',
|
||||||
|
'tsnrh',
|
||||||
|
'aictsmoothS',
|
||||||
|
'tsmoothS',
|
||||||
|
'ausS',
|
||||||
|
'nfacS'],
|
||||||
|
'fm': [
|
||||||
|
'minfmweight',
|
||||||
|
'minFMSNR',
|
||||||
|
'fmpickwin'],
|
||||||
|
'quality': [
|
||||||
|
'timeerrorsP',
|
||||||
|
'timeerrorsS',
|
||||||
|
'minAICPslope',
|
||||||
|
'minAICPSNR',
|
||||||
|
'minAICSslope',
|
||||||
|
'minAICSSNR',
|
||||||
|
'minsiglength',
|
||||||
|
'noisefactor',
|
||||||
|
'minpercent',
|
||||||
|
'zfac',
|
||||||
|
'mdttolerance',
|
||||||
|
'wdttolerance',
|
||||||
|
'jackfactor'],
|
||||||
|
}
|
@ -1,12 +1,13 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from pylot.core.io import default_parameters
|
||||||
from pylot.core.util.errors import ParameterError
|
from pylot.core.util.errors import ParameterError
|
||||||
|
|
||||||
|
|
||||||
class AutoPickParameter(object):
|
class PylotParameter(object):
|
||||||
'''
|
'''
|
||||||
AutoPickParameters is a parameter type object capable to read and/or write
|
PylotParameter is a parameter type object capable to read and/or write
|
||||||
parameter ASCII.
|
parameter ASCII.
|
||||||
|
|
||||||
:param fn str: Filename of the input file
|
:param fn str: Filename of the input file
|
||||||
@ -44,48 +45,15 @@ class AutoPickParameter(object):
|
|||||||
contain all parameters.
|
contain all parameters.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
self.__init_default_paras()
|
||||||
|
self.__init_subsettings()
|
||||||
self.__filename = fnin
|
self.__filename = fnin
|
||||||
parFileCont = {}
|
self._verbosity = verbosity
|
||||||
|
self._parFileCont = {}
|
||||||
# io from parsed arguments alternatively
|
# io from parsed arguments alternatively
|
||||||
for key, val in kwargs.items():
|
for key, val in kwargs.items():
|
||||||
parFileCont[key] = val
|
self._parFileCont[key] = val
|
||||||
|
self.from_file()
|
||||||
if self.__filename is not None:
|
|
||||||
inputFile = open(self.__filename, 'r')
|
|
||||||
else:
|
|
||||||
return
|
|
||||||
try:
|
|
||||||
lines = inputFile.readlines()
|
|
||||||
for line in lines:
|
|
||||||
parspl = line.split('\t')[:2]
|
|
||||||
parFileCont[parspl[0].strip()] = parspl[1]
|
|
||||||
except IndexError as e:
|
|
||||||
if verbosity > 0:
|
|
||||||
self._printParameterError(e)
|
|
||||||
inputFile.seek(0)
|
|
||||||
lines = inputFile.readlines()
|
|
||||||
for line in lines:
|
|
||||||
if not line.startswith(('#', '%', '\n', ' ')):
|
|
||||||
parspl = line.split('#')[:2]
|
|
||||||
parFileCont[parspl[1].strip()] = parspl[0].strip()
|
|
||||||
for key, value in parFileCont.items():
|
|
||||||
try:
|
|
||||||
val = int(value)
|
|
||||||
except:
|
|
||||||
try:
|
|
||||||
val = float(value)
|
|
||||||
except:
|
|
||||||
if len(value.split(' ')) > 1:
|
|
||||||
vallist = value.strip().split(' ')
|
|
||||||
val = []
|
|
||||||
for val0 in vallist:
|
|
||||||
val0 = float(val0)
|
|
||||||
val.append(val0)
|
|
||||||
else:
|
|
||||||
val = str(value.strip())
|
|
||||||
parFileCont[key] = val
|
|
||||||
self.__parameter = parFileCont
|
|
||||||
|
|
||||||
if fnout:
|
if fnout:
|
||||||
self.export2File(fnout)
|
self.export2File(fnout)
|
||||||
|
|
||||||
@ -100,16 +68,28 @@ class AutoPickParameter(object):
|
|||||||
string += 'Empty parameter dictionary.'
|
string += 'Empty parameter dictionary.'
|
||||||
return string
|
return string
|
||||||
|
|
||||||
|
# Set default values of parameter names
|
||||||
|
def __init_default_paras(self):
|
||||||
|
parameters = default_parameters.defaults
|
||||||
|
self.__defaults = parameters
|
||||||
|
|
||||||
|
def __init_subsettings(self):
|
||||||
|
self._settings_main = default_parameters.settings_main
|
||||||
|
self._settings_special_pick = default_parameters.settings_special_pick
|
||||||
|
|
||||||
# String representation of the object
|
# String representation of the object
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "AutoPickParameter('%s')" % self.__filename
|
return "PylotParameter('%s')" % self.__filename
|
||||||
|
|
||||||
# Boolean test
|
# Boolean test
|
||||||
def __nonzero__(self):
|
def __nonzero__(self):
|
||||||
return self.__parameter
|
return bool(self.__parameter)
|
||||||
|
|
||||||
def __getitem__(self, key):
|
def __getitem__(self, key):
|
||||||
|
try:
|
||||||
return self.__parameter[key]
|
return self.__parameter[key]
|
||||||
|
except:
|
||||||
|
return None
|
||||||
|
|
||||||
def __setitem__(self, key, value):
|
def __setitem__(self, key, value):
|
||||||
self.__parameter[key] = value
|
self.__parameter[key] = value
|
||||||
@ -128,7 +108,7 @@ class AutoPickParameter(object):
|
|||||||
yield key, value
|
yield key, value
|
||||||
|
|
||||||
def hasParam(self, parameter):
|
def hasParam(self, parameter):
|
||||||
if self.__parameter.has_key(parameter):
|
if parameter in self.__parameter.keys():
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@ -147,21 +127,165 @@ class AutoPickParameter(object):
|
|||||||
self._printParameterError(e)
|
self._printParameterError(e)
|
||||||
raise ParameterError(e)
|
raise ParameterError(e)
|
||||||
|
|
||||||
def setParam(self, **kwargs):
|
def get_defaults(self):
|
||||||
for param, value in kwargs.items():
|
return self.__defaults
|
||||||
|
|
||||||
|
def get_main_para_names(self):
|
||||||
|
return self._settings_main
|
||||||
|
|
||||||
|
def get_special_para_names(self):
|
||||||
|
return self._settings_special_pick
|
||||||
|
|
||||||
|
def get_all_para_names(self):
|
||||||
|
all_names = []
|
||||||
|
all_names += self.get_main_para_names()['dirs']
|
||||||
|
all_names += self.get_main_para_names()['nlloc']
|
||||||
|
all_names += self.get_main_para_names()['smoment']
|
||||||
|
all_names += self.get_main_para_names()['localmag']
|
||||||
|
all_names += self.get_main_para_names()['pick']
|
||||||
|
all_names += self.get_main_para_names()['filter']
|
||||||
|
all_names += self.get_special_para_names()['z']
|
||||||
|
all_names += self.get_special_para_names()['h']
|
||||||
|
all_names += self.get_special_para_names()['fm']
|
||||||
|
all_names += self.get_special_para_names()['quality']
|
||||||
|
return all_names
|
||||||
|
|
||||||
|
def checkValue(self, param, value):
|
||||||
|
is_type = type(value)
|
||||||
|
expect_type = self.get_defaults()[param]['type']
|
||||||
|
if not is_type == expect_type and not is_type == tuple:
|
||||||
|
message = 'Type check failed for param: {}, is type: {}, expected type:{}'
|
||||||
|
message = message.format(param, is_type, expect_type)
|
||||||
|
print(Warning(message))
|
||||||
|
|
||||||
|
def setParamKV(self, param, value):
|
||||||
self.__setitem__(param, value)
|
self.__setitem__(param, value)
|
||||||
# print(self)
|
|
||||||
|
def setParam(self, **kwargs):
|
||||||
|
for key in kwargs:
|
||||||
|
self.__setitem__(key, kwargs[key])
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _printParameterError(errmsg):
|
def _printParameterError(errmsg):
|
||||||
print('ParameterError:\n non-existent parameter %s' % errmsg)
|
print('ParameterError:\n non-existent parameter %s' % errmsg)
|
||||||
|
|
||||||
|
def reset_defaults(self):
|
||||||
|
defaults = self.get_defaults()
|
||||||
|
for param in defaults:
|
||||||
|
self.setParamKV(param, defaults[param]['value'])
|
||||||
|
|
||||||
|
def from_file(self, fnin=None):
|
||||||
|
if not fnin:
|
||||||
|
if self.__filename is not None:
|
||||||
|
fnin = self.__filename
|
||||||
|
else:
|
||||||
|
return
|
||||||
|
|
||||||
|
if isinstance(fnin, (list, tuple)):
|
||||||
|
fnin = fnin[0]
|
||||||
|
|
||||||
|
inputFile = open(fnin, 'r')
|
||||||
|
try:
|
||||||
|
lines = inputFile.readlines()
|
||||||
|
for line in lines:
|
||||||
|
parspl = line.split('\t')[:2]
|
||||||
|
self._parFileCont[parspl[0].strip()] = parspl[1]
|
||||||
|
except IndexError as e:
|
||||||
|
if self._verbosity > 0:
|
||||||
|
self._printParameterError(e)
|
||||||
|
inputFile.seek(0)
|
||||||
|
lines = inputFile.readlines()
|
||||||
|
for line in lines:
|
||||||
|
if not line.startswith(('#', '%', '\n', ' ')):
|
||||||
|
parspl = line.split('#')[:2]
|
||||||
|
self._parFileCont[parspl[1].strip()] = parspl[0].strip()
|
||||||
|
for key, value in self._parFileCont.items():
|
||||||
|
try:
|
||||||
|
val = int(value)
|
||||||
|
except:
|
||||||
|
try:
|
||||||
|
val = float(value)
|
||||||
|
except:
|
||||||
|
if len(value.split(' ')) > 1:
|
||||||
|
vallist = value.strip().split(' ')
|
||||||
|
val = []
|
||||||
|
for val0 in vallist:
|
||||||
|
try:
|
||||||
|
val0 = float(val0)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
val.append(val0)
|
||||||
|
else:
|
||||||
|
val = str(value.strip())
|
||||||
|
self._parFileCont[key] = val
|
||||||
|
self.__parameter = self._parFileCont
|
||||||
|
|
||||||
def export2File(self, fnout):
|
def export2File(self, fnout):
|
||||||
fid_out = open(fnout, 'w')
|
fid_out = open(fnout, 'w')
|
||||||
lines = []
|
lines = []
|
||||||
for key, value in self.iteritems():
|
# for key, value in self.iteritems():
|
||||||
lines.append('{key}\t{value}'.format(key=key, value=value))
|
# lines.append('{key}\t{value}\n'.format(key=key, value=value))
|
||||||
fid_out.writelines(lines)
|
# fid_out.writelines(lines)
|
||||||
|
header = ('%This is a parameter input file for PyLoT/autoPyLoT.\n' +
|
||||||
|
'%All main and special settings regarding data handling\n' +
|
||||||
|
'%and picking are to be set here!\n' +
|
||||||
|
'%Parameters are optimized for %{} data sets!\n'.format(self.get_main_para_names()['pick'][0]))
|
||||||
|
separator = '%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n'
|
||||||
|
|
||||||
|
fid_out.write(header)
|
||||||
|
self.write_section(fid_out, self.get_main_para_names()['dirs'],
|
||||||
|
'main settings', separator)
|
||||||
|
self.write_section(fid_out, self.get_main_para_names()['nlloc'],
|
||||||
|
'NLLoc settings', separator)
|
||||||
|
self.write_section(fid_out, self.get_main_para_names()['smoment'],
|
||||||
|
'parameters for seismic moment estimation', separator)
|
||||||
|
self.write_section(fid_out, self.get_main_para_names()['localmag'],
|
||||||
|
'settings local magnitude', separator)
|
||||||
|
self.write_section(fid_out, self.get_main_para_names()['filter'],
|
||||||
|
'filter settings', separator)
|
||||||
|
self.write_section(fid_out, self.get_main_para_names()['pick'],
|
||||||
|
'common settings picker', separator)
|
||||||
|
fid_out.write(('#special settings for calculating CF#\n' +
|
||||||
|
'%!!Edit the following only if you know what you are doing!!%\n'))
|
||||||
|
self.write_section(fid_out, self.get_special_para_names()['z'],
|
||||||
|
'Z-component', None)
|
||||||
|
self.write_section(fid_out, self.get_special_para_names()['h'],
|
||||||
|
'H-components', None)
|
||||||
|
self.write_section(fid_out, self.get_special_para_names()['fm'],
|
||||||
|
'first-motion picker', None)
|
||||||
|
self.write_section(fid_out, self.get_special_para_names()['quality'],
|
||||||
|
'quality assessment', None)
|
||||||
|
|
||||||
|
def write_section(self, fid, names, title, separator):
|
||||||
|
if separator:
|
||||||
|
fid.write(separator)
|
||||||
|
fid.write('#{}#\n'.format(title))
|
||||||
|
l_val = 50
|
||||||
|
l_name = 15
|
||||||
|
l_ttip = 100
|
||||||
|
for name in names:
|
||||||
|
value = self[name]
|
||||||
|
if type(value) == list or type(value) == tuple:
|
||||||
|
value_tmp = ''
|
||||||
|
for vl in value:
|
||||||
|
value_tmp += '{} '.format(vl)
|
||||||
|
value = value_tmp
|
||||||
|
tooltip = self.get_defaults()[name]['tooltip']
|
||||||
|
if not len(str(value)) > l_val:
|
||||||
|
value = '{:<{}} '.format(str(value), l_val)
|
||||||
|
else:
|
||||||
|
value = '{} '.format(str(value))
|
||||||
|
name += '#'
|
||||||
|
if not len(name) > l_name:
|
||||||
|
name = '#{:<{}} '.format(name, l_name)
|
||||||
|
else:
|
||||||
|
name = '#{} '.format(name)
|
||||||
|
if not len(tooltip) > l_ttip:
|
||||||
|
ttip = '%{:<{}}\n'.format(tooltip, l_ttip)
|
||||||
|
else:
|
||||||
|
ttip = '%{}\n'.format(tooltip)
|
||||||
|
line = value + name + ttip
|
||||||
|
fid.write(line)
|
||||||
|
|
||||||
|
|
||||||
class FilterOptions(object):
|
class FilterOptions(object):
|
||||||
@ -218,12 +342,13 @@ class FilterOptions(object):
|
|||||||
def parseFilterOptions(self):
|
def parseFilterOptions(self):
|
||||||
if self:
|
if self:
|
||||||
robject = {'type': self.getFilterType(), 'corners': self.getOrder()}
|
robject = {'type': self.getFilterType(), 'corners': self.getOrder()}
|
||||||
if len(self.getFreq()) > 1:
|
if not self.getFilterType() in ['highpass', 'lowpass']:
|
||||||
robject['freqmin'] = self.getFreq()[0]
|
robject['freqmin'] = self.getFreq()[0]
|
||||||
robject['freqmax'] = self.getFreq()[1]
|
robject['freqmax'] = self.getFreq()[1]
|
||||||
else:
|
elif self.getFilterType() == 'highpass':
|
||||||
robject['freq'] = self.getFreq() if type(self.getFreq()) is \
|
robject['freq'] = self.getFreq()[0]
|
||||||
float else self.getFreq()[0]
|
elif self.getFilterType() == 'lowpass':
|
||||||
|
robject['freq'] = self.getFreq()[1]
|
||||||
return robject
|
return robject
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@ -2,15 +2,19 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
import glob
|
import glob
|
||||||
import obspy.core.event as ope
|
|
||||||
import os
|
import os
|
||||||
import scipy.io as sio
|
|
||||||
import warnings
|
import warnings
|
||||||
from obspy.core import UTCDateTime
|
|
||||||
|
|
||||||
from pylot.core.io.inputs import AutoPickParameter
|
import matplotlib.pyplot as plt
|
||||||
from pylot.core.io.location import create_arrival, create_event, \
|
import numpy as np
|
||||||
create_magnitude, create_origin, create_pick
|
import obspy.core.event as ope
|
||||||
|
import scipy.io as sio
|
||||||
|
from obspy.core import UTCDateTime
|
||||||
|
from obspy.core.event import read_events
|
||||||
|
from obspy.core.util import AttribDict
|
||||||
|
from pylot.core.io.inputs import PylotParameter
|
||||||
|
from pylot.core.io.location import create_event, \
|
||||||
|
create_magnitude
|
||||||
from pylot.core.pick.utils import select_for_phase
|
from pylot.core.pick.utils import select_for_phase
|
||||||
from pylot.core.util.utils import getOwner, full_range, four_digits
|
from pylot.core.util.utils import getOwner, full_range, four_digits
|
||||||
|
|
||||||
@ -33,6 +37,7 @@ def add_amplitudes(event, amplitudes):
|
|||||||
event.amplitudes = amplitude_list
|
event.amplitudes = amplitude_list
|
||||||
return event
|
return event
|
||||||
|
|
||||||
|
|
||||||
def readPILOTEvent(phasfn=None, locfn=None, authority_id='RUB', **kwargs):
|
def readPILOTEvent(phasfn=None, locfn=None, authority_id='RUB', **kwargs):
|
||||||
"""
|
"""
|
||||||
readPILOTEvent - function
|
readPILOTEvent - function
|
||||||
@ -117,7 +122,7 @@ def picksdict_from_pilot(fn):
|
|||||||
picks = dict()
|
picks = dict()
|
||||||
phases_pilot = sio.loadmat(fn)
|
phases_pilot = sio.loadmat(fn)
|
||||||
stations = stations_from_pilot(phases_pilot['stat'])
|
stations = stations_from_pilot(phases_pilot['stat'])
|
||||||
params = AutoPickParameter(TIMEERROR_DEFAULTS)
|
params = PylotParameter(TIMEERROR_DEFAULTS)
|
||||||
timeerrors = dict(P=params.get('timeerrorsP'),
|
timeerrors = dict(P=params.get('timeerrorsP'),
|
||||||
S=params.get('timeerrorsS'))
|
S=params.get('timeerrorsS'))
|
||||||
for n, station in enumerate(stations):
|
for n, station in enumerate(stations):
|
||||||
@ -189,24 +194,35 @@ def picksdict_from_picks(evt):
|
|||||||
PyLoT
|
PyLoT
|
||||||
:param evt: Event object contain all available information
|
:param evt: Event object contain all available information
|
||||||
:type evt: `~obspy.core.event.Event`
|
:type evt: `~obspy.core.event.Event`
|
||||||
:return: pick dictionary
|
:return: pick dictionary (auto and manual)
|
||||||
"""
|
"""
|
||||||
picks = {}
|
picksdict = {
|
||||||
|
'manual': {},
|
||||||
|
'auto': {}
|
||||||
|
}
|
||||||
for pick in evt.picks:
|
for pick in evt.picks:
|
||||||
phase = {}
|
phase = {}
|
||||||
station = pick.waveform_id.station_code
|
station = pick.waveform_id.station_code
|
||||||
|
channel = pick.waveform_id.channel_code
|
||||||
|
network = pick.waveform_id.network_code
|
||||||
|
mpp = pick.time
|
||||||
|
spe = pick.time_errors.uncertainty
|
||||||
try:
|
try:
|
||||||
onsets = picks[station]
|
picker = str(pick.method_id)
|
||||||
|
if picker.startswith('smi:local/'):
|
||||||
|
picker = picker.split('smi:local/')[1]
|
||||||
|
except IndexError:
|
||||||
|
picker = 'manual' # MP MP TODO maybe improve statement
|
||||||
|
try:
|
||||||
|
onsets = picksdict[picker][station]
|
||||||
except KeyError as e:
|
except KeyError as e:
|
||||||
# print(e)
|
# print(e)
|
||||||
onsets = {}
|
onsets = {}
|
||||||
mpp = pick.time
|
|
||||||
spe = pick.time_errors.uncertainty
|
|
||||||
try:
|
try:
|
||||||
lpp = mpp + pick.time_errors.upper_uncertainty
|
lpp = mpp + pick.time_errors.upper_uncertainty
|
||||||
epp = mpp - pick.time_errors.lower_uncertainty
|
epp = mpp - pick.time_errors.lower_uncertainty
|
||||||
except TypeError as e:
|
except TypeError as e:
|
||||||
msg = e.message + ',\n falling back to symmetric uncertainties'
|
msg = e + ',\n falling back to symmetric uncertainties'
|
||||||
warnings.warn(msg)
|
warnings.warn(msg)
|
||||||
lpp = mpp + spe
|
lpp = mpp + spe
|
||||||
epp = mpp - spe
|
epp = mpp - spe
|
||||||
@ -214,25 +230,27 @@ def picksdict_from_picks(evt):
|
|||||||
phase['epp'] = epp
|
phase['epp'] = epp
|
||||||
phase['lpp'] = lpp
|
phase['lpp'] = lpp
|
||||||
phase['spe'] = spe
|
phase['spe'] = spe
|
||||||
try:
|
phase['channel'] = channel
|
||||||
picker = str(pick.method_id)
|
phase['network'] = network
|
||||||
if picker.startswith('smi:local/'):
|
|
||||||
picker = picker.split('smi:local/')[1]
|
|
||||||
phase['picker'] = picker
|
phase['picker'] = picker
|
||||||
except IndexError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
onsets[pick.phase_hint] = phase.copy()
|
onsets[pick.phase_hint] = phase.copy()
|
||||||
picks[station] = onsets.copy()
|
picksdict[picker][station] = onsets.copy()
|
||||||
return picks
|
return picksdict
|
||||||
|
|
||||||
|
|
||||||
def picks_from_picksdict(picks, creation_info=None):
|
def picks_from_picksdict(picks, creation_info=None):
|
||||||
picks_list = list()
|
picks_list = list()
|
||||||
for station, onsets in picks.items():
|
for station, onsets in picks.items():
|
||||||
for label, phase in onsets.items():
|
for label, phase in onsets.items():
|
||||||
if not isinstance(phase, dict):
|
if not isinstance(phase, dict) and not isinstance(phase, AttribDict):
|
||||||
continue
|
continue
|
||||||
onset = phase['mpp']
|
onset = phase['mpp']
|
||||||
|
try:
|
||||||
|
ccode = phase['channel']
|
||||||
|
ncode = phase['network']
|
||||||
|
except:
|
||||||
|
continue
|
||||||
pick = ope.Pick()
|
pick = ope.Pick()
|
||||||
if creation_info:
|
if creation_info:
|
||||||
pick.creation_info = creation_info
|
pick.creation_info = creation_info
|
||||||
@ -244,8 +262,8 @@ def picks_from_picksdict(picks, creation_info=None):
|
|||||||
lpp = phase['lpp']
|
lpp = phase['lpp']
|
||||||
pick.time_errors.lower_uncertainty = onset - epp
|
pick.time_errors.lower_uncertainty = onset - epp
|
||||||
pick.time_errors.upper_uncertainty = lpp - onset
|
pick.time_errors.upper_uncertainty = lpp - onset
|
||||||
except KeyError as e:
|
except (KeyError, TypeError) as e:
|
||||||
warnings.warn(e.message, RuntimeWarning)
|
warnings.warn(str(e), RuntimeWarning)
|
||||||
try:
|
try:
|
||||||
picker = phase['picker']
|
picker = phase['picker']
|
||||||
except KeyError as e:
|
except KeyError as e:
|
||||||
@ -253,7 +271,9 @@ def picks_from_picksdict(picks, creation_info=None):
|
|||||||
picker = 'Unknown'
|
picker = 'Unknown'
|
||||||
pick.phase_hint = label
|
pick.phase_hint = label
|
||||||
pick.method_id = ope.ResourceIdentifier(id=picker)
|
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:
|
try:
|
||||||
polarity = phase['fm']
|
polarity = phase['fm']
|
||||||
if polarity == 'U' or '+':
|
if polarity == 'U' or '+':
|
||||||
@ -263,7 +283,7 @@ def picks_from_picksdict(picks, creation_info=None):
|
|||||||
else:
|
else:
|
||||||
pick.polarity = 'undecidable'
|
pick.polarity = 'undecidable'
|
||||||
except KeyError as e:
|
except KeyError as e:
|
||||||
if 'fm' in e.message: # no polarity information found for this phase
|
if 'fm' in str(e): # no polarity information found for this phase
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
raise e
|
raise e
|
||||||
@ -283,18 +303,16 @@ def reassess_pilot_db(root_dir, db_dir, out_dir=None, fn_param=None, verbosity=0
|
|||||||
reassess_pilot_event(root_dir, db_dir, evt, out_dir, fn_param, verbosity)
|
reassess_pilot_event(root_dir, db_dir, evt, out_dir, fn_param, verbosity)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def reassess_pilot_event(root_dir, db_dir, event_id, out_dir=None, fn_param=None, verbosity=0):
|
def reassess_pilot_event(root_dir, db_dir, event_id, out_dir=None, fn_param=None, verbosity=0):
|
||||||
from obspy import read
|
from obspy import read
|
||||||
|
|
||||||
from pylot.core.io.inputs import AutoPickParameter
|
from pylot.core.io.inputs import PylotParameter
|
||||||
from pylot.core.pick.utils import earllatepicker
|
from pylot.core.pick.utils import earllatepicker
|
||||||
|
|
||||||
if fn_param is None:
|
if fn_param is None:
|
||||||
import pylot.core.util.defaults as defaults
|
|
||||||
fn_param = defaults.AUTOMATIC_DEFAULTS
|
fn_param = defaults.AUTOMATIC_DEFAULTS
|
||||||
|
|
||||||
default = AutoPickParameter(fn_param, verbosity)
|
default = PylotParameter(fn_param, verbosity)
|
||||||
|
|
||||||
search_base = os.path.join(root_dir, db_dir, event_id)
|
search_base = os.path.join(root_dir, db_dir, event_id)
|
||||||
phases_file = glob.glob(os.path.join(search_base, 'PHASES.mat'))
|
phases_file = glob.glob(os.path.join(search_base, 'PHASES.mat'))
|
||||||
@ -325,7 +343,8 @@ def reassess_pilot_event(root_dir, db_dir, event_id, out_dir=None, fn_param=None
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
if 'No file matching file pattern:' in e.message:
|
if 'No file matching file pattern:' in e.message:
|
||||||
if verbosity > 0:
|
if verbosity > 0:
|
||||||
warnings.warn('no waveform data found for station {station}'.format(station=station), RuntimeWarning)
|
warnings.warn('no waveform data found for station {station}'.format(station=station),
|
||||||
|
RuntimeWarning)
|
||||||
datacheck.append(fn_pattern + ' (no data)\n')
|
datacheck.append(fn_pattern + ' (no data)\n')
|
||||||
continue
|
continue
|
||||||
else:
|
else:
|
||||||
@ -349,8 +368,8 @@ def reassess_pilot_event(root_dir, db_dir, event_id, out_dir=None, fn_param=None
|
|||||||
default.get('nfac{0}'.format(phase)),
|
default.get('nfac{0}'.format(phase)),
|
||||||
default.get('tsnrz' if phase == 'P' else 'tsnrh'),
|
default.get('tsnrz' if phase == 'P' else 'tsnrh'),
|
||||||
Pick1=rel_pick,
|
Pick1=rel_pick,
|
||||||
iplot=None,
|
iplot=0,
|
||||||
stealth_mode=True)
|
verbosity=0)
|
||||||
if epp is None or lpp is None:
|
if epp is None or lpp is None:
|
||||||
continue
|
continue
|
||||||
epp = stime + epp
|
epp = stime + epp
|
||||||
@ -374,17 +393,17 @@ def reassess_pilot_event(root_dir, db_dir, event_id, out_dir=None, fn_param=None
|
|||||||
evt.picks = picks_from_picksdict(picks_dict)
|
evt.picks = picks_from_picksdict(picks_dict)
|
||||||
# write phase information to file
|
# write phase information to file
|
||||||
if not out_dir:
|
if not out_dir:
|
||||||
fnout_prefix = os.path.join(root_dir, db_dir, event_id, '{0}.'.format(event_id))
|
fnout_prefix = os.path.join(root_dir, db_dir, event_id, 'PyLoT_{0}.'.format(event_id))
|
||||||
else:
|
else:
|
||||||
out_dir = os.path.join(out_dir, db_dir)
|
out_dir = os.path.join(out_dir, db_dir)
|
||||||
if not os.path.isdir(out_dir):
|
if not os.path.isdir(out_dir):
|
||||||
os.makedirs(out_dir)
|
os.makedirs(out_dir)
|
||||||
fnout_prefix = os.path.join(out_dir, '{0}.'.format(event_id))
|
fnout_prefix = os.path.join(out_dir, 'PyLoT_{0}.'.format(event_id))
|
||||||
evt.write(fnout_prefix + 'xml', format='QUAKEML')
|
evt.write(fnout_prefix + 'xml', format='QUAKEML')
|
||||||
# evt.write(fnout_prefix + 'cnv', format='VELEST')
|
# evt.write(fnout_prefix + 'cnv', format='VELEST')
|
||||||
|
|
||||||
|
|
||||||
def writephases(arrivals, fformat, filename):
|
def writephases(arrivals, fformat, filename, parameter=None, eventinfo=None):
|
||||||
"""
|
"""
|
||||||
Function of methods to write phases to the following standard file
|
Function of methods to write phases to the following standard file
|
||||||
formats used for locating earthquakes:
|
formats used for locating earthquakes:
|
||||||
@ -403,16 +422,24 @@ def writephases(arrivals, fformat, filename):
|
|||||||
|
|
||||||
:param: filename, full path and name of phase file
|
: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':
|
if fformat == 'NLLoc':
|
||||||
print("Writing phases to %s for NLLoc" % filename)
|
print("Writing phases to %s for NLLoc" % filename)
|
||||||
fid = open("%s" % filename, 'w')
|
fid = open("%s" % filename, 'w')
|
||||||
# write header
|
# 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:
|
for key in arrivals:
|
||||||
# P onsets
|
# P onsets
|
||||||
if arrivals[key]['P']:
|
if arrivals[key].has_key('P'):
|
||||||
try:
|
try:
|
||||||
fm = arrivals[key]['P']['fm']
|
fm = arrivals[key]['P']['fm']
|
||||||
except KeyError as e:
|
except KeyError as e:
|
||||||
@ -477,9 +504,13 @@ def writephases(arrivals, fformat, filename):
|
|||||||
print("Writing phases to %s for HYPO71" % filename)
|
print("Writing phases to %s for HYPO71" % filename)
|
||||||
fid = open("%s" % filename, 'w')
|
fid = open("%s" % filename, 'w')
|
||||||
# write header
|
# write header
|
||||||
fid.write(' EQ001\n')
|
fid.write(' %s\n' %
|
||||||
|
parameter.get('eventID'))
|
||||||
for key in arrivals:
|
for key in arrivals:
|
||||||
if arrivals[key]['P']['weight'] < 4:
|
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']
|
Ponset = arrivals[key]['P']['mpp']
|
||||||
Sonset = arrivals[key]['S']['mpp']
|
Sonset = arrivals[key]['S']['mpp']
|
||||||
pweight = arrivals[key]['P']['weight']
|
pweight = arrivals[key]['P']['weight']
|
||||||
@ -517,7 +548,7 @@ def writephases(arrivals, fformat, filename):
|
|||||||
sstr = 'I'
|
sstr = 'I'
|
||||||
elif sweight >= 2:
|
elif sweight >= 2:
|
||||||
sstr = 'E'
|
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,
|
pstr,
|
||||||
fm,
|
fm,
|
||||||
pweight,
|
pweight,
|
||||||
@ -532,7 +563,7 @@ def writephases(arrivals, fformat, filename):
|
|||||||
sweight,
|
sweight,
|
||||||
Ao))
|
Ao))
|
||||||
else:
|
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,
|
pstr,
|
||||||
fm,
|
fm,
|
||||||
pweight,
|
pweight,
|
||||||
@ -546,6 +577,271 @@ def writephases(arrivals, fformat, filename):
|
|||||||
|
|
||||||
fid.close()
|
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')))
|
||||||
|
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
|
||||||
|
try:
|
||||||
|
eventsource = eventinfo.origins[0]
|
||||||
|
except:
|
||||||
|
print("No source origin calculated yet, thus no cnv-file creation possible!")
|
||||||
|
return
|
||||||
|
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):
|
def merge_picks(event, picks):
|
||||||
"""
|
"""
|
||||||
@ -563,8 +859,158 @@ def merge_picks(event, picks):
|
|||||||
err = pick.time_errors
|
err = pick.time_errors
|
||||||
phase = pick.phase_hint
|
phase = pick.phase_hint
|
||||||
station = pick.waveform_id.station_code
|
station = pick.waveform_id.station_code
|
||||||
|
network = pick.waveform_id.network_code
|
||||||
|
method = pick.method_id
|
||||||
for p in event.picks:
|
for p in event.picks:
|
||||||
if p.waveform_id.station_code == station and p.phase_hint == phase:
|
if p.waveform_id.station_code == station\
|
||||||
p.time, p.time_errors = time, err
|
and p.waveform_id.network_code == network\
|
||||||
del time, err, phase, station
|
and p.phase_hint == phase\
|
||||||
|
and (str(p.method_id) in str(method)
|
||||||
|
or str(method) in str(p.method_id)):
|
||||||
|
p.time, p.time_errors, p.waveform_id.network_code, p.method_id = time, err, network, method
|
||||||
|
del time, err, phase, station, network, method
|
||||||
return event
|
return event
|
||||||
|
|
||||||
|
|
||||||
|
def getQualitiesfromxml(xmlnames, ErrorsP, ErrorsS, plotflag=1):
|
||||||
|
"""
|
||||||
|
Script to get onset uncertainties from Quakeml.xml files created by PyLoT.
|
||||||
|
Uncertainties are tranformed into quality classes and visualized via histogram if desired.
|
||||||
|
Ludger Küperkoch, BESTEC GmbH, 07/2017
|
||||||
|
"""
|
||||||
|
|
||||||
|
from pylot.core.pick.utils import getQualityFromUncertainty
|
||||||
|
from pylot.core.util.utils import loopIdentifyPhase, identifyPhase
|
||||||
|
|
||||||
|
# read all onset weights
|
||||||
|
Pw0 = []
|
||||||
|
Pw1 = []
|
||||||
|
Pw2 = []
|
||||||
|
Pw3 = []
|
||||||
|
Pw4 = []
|
||||||
|
Sw0 = []
|
||||||
|
Sw1 = []
|
||||||
|
Sw2 = []
|
||||||
|
Sw3 = []
|
||||||
|
Sw4 = []
|
||||||
|
for names in xmlnames:
|
||||||
|
print("Getting onset weights from {}".format(names))
|
||||||
|
cat = read_events(names)
|
||||||
|
cat_copy = cat.copy()
|
||||||
|
arrivals = cat.events[0].picks
|
||||||
|
arrivals_copy = cat_copy.events[0].picks
|
||||||
|
# Prefere manual picks if qualities are sufficient!
|
||||||
|
for Pick in arrivals:
|
||||||
|
if (Pick.method_id.id).split('/')[1] == 'manual':
|
||||||
|
mstation = Pick.waveform_id.station_code
|
||||||
|
mstation_ext = mstation + '_'
|
||||||
|
for mpick in arrivals_copy:
|
||||||
|
phase = identifyPhase(loopIdentifyPhase(Pick.phase_hint))
|
||||||
|
if phase == 'P':
|
||||||
|
if ((mpick.waveform_id.station_code == mstation) or
|
||||||
|
(mpick.waveform_id.station_code == mstation_ext)) and \
|
||||||
|
((mpick.method_id).split('/')[1] == 'auto') and \
|
||||||
|
(mpick.time_errors['uncertainty'] <= ErrorsP[3]):
|
||||||
|
del mpick
|
||||||
|
break
|
||||||
|
elif phase == 'S':
|
||||||
|
if ((mpick.waveform_id.station_code == mstation) or
|
||||||
|
(mpick.waveform_id.station_code == mstation_ext)) and \
|
||||||
|
((mpick.method_id).split('/')[1] == 'auto') and \
|
||||||
|
(mpick.time_errors['uncertainty'] <= ErrorsS[3]):
|
||||||
|
del mpick
|
||||||
|
break
|
||||||
|
lendiff = len(arrivals) - len(arrivals_copy)
|
||||||
|
if lendiff is not 0:
|
||||||
|
print("Found manual as well as automatic picks, prefered the {} manual ones!".format(lendiff))
|
||||||
|
|
||||||
|
for Pick in arrivals_copy:
|
||||||
|
phase = identifyPhase(loopIdentifyPhase(Pick.phase_hint))
|
||||||
|
if phase == 'P':
|
||||||
|
Pqual = getQualityFromUncertainty(Pick.time_errors.uncertainty, ErrorsP)
|
||||||
|
if Pqual == 0:
|
||||||
|
Pw0.append(Pick.time_errors.uncertainty)
|
||||||
|
elif Pqual == 1:
|
||||||
|
Pw1.append(Pick.time_errors.uncertainty)
|
||||||
|
elif Pqual == 2:
|
||||||
|
Pw2.append(Pick.time_errors.uncertainty)
|
||||||
|
elif Pqual == 3:
|
||||||
|
Pw3.append(Pick.time_errors.uncertainty)
|
||||||
|
elif Pqual == 4:
|
||||||
|
Pw4.append(Pick.time_errors.uncertainty)
|
||||||
|
elif phase == 'S':
|
||||||
|
Squal = getQualityFromUncertainty(Pick.time_errors.uncertainty, ErrorsS)
|
||||||
|
if Squal == 0:
|
||||||
|
Sw0.append(Pick.time_errors.uncertainty)
|
||||||
|
elif Squal == 1:
|
||||||
|
Sw1.append(Pick.time_errors.uncertainty)
|
||||||
|
elif Squal == 2:
|
||||||
|
Sw2.append(Pick.time_errors.uncertainty)
|
||||||
|
elif Squal == 3:
|
||||||
|
Sw3.append(Pick.time_errors.uncertainty)
|
||||||
|
elif Squal == 4:
|
||||||
|
Sw4.append(Pick.time_errors.uncertainty)
|
||||||
|
else:
|
||||||
|
print("Phase hint not defined for picking!")
|
||||||
|
pass
|
||||||
|
|
||||||
|
if plotflag == 0:
|
||||||
|
Punc = [Pw0, Pw1, Pw2, Pw3, Pw4]
|
||||||
|
Sunc = [Sw0, Sw1, Sw2, Sw3, Sw4]
|
||||||
|
return Punc, Sunc
|
||||||
|
else:
|
||||||
|
# get percentage of weights
|
||||||
|
numPweights = np.sum([len(Pw0), len(Pw1), len(Pw2), len(Pw3), len(Pw4)])
|
||||||
|
numSweights = np.sum([len(Sw0), len(Sw1), len(Sw2), len(Sw3), len(Sw4)])
|
||||||
|
if len(Pw0) > 0:
|
||||||
|
P0perc = 100 / numPweights * len(Pw0)
|
||||||
|
else:
|
||||||
|
P0perc = 0
|
||||||
|
if len(Pw1) > 0:
|
||||||
|
P1perc = 100 / numPweights * len(Pw1)
|
||||||
|
else:
|
||||||
|
P1perc = 0
|
||||||
|
if len(Pw2) > 0:
|
||||||
|
P2perc = 100 / numPweights * len(Pw2)
|
||||||
|
else:
|
||||||
|
P2perc = 0
|
||||||
|
if len(Pw3) > 0:
|
||||||
|
P3perc = 100 / numPweights * len(Pw3)
|
||||||
|
else:
|
||||||
|
P3perc = 0
|
||||||
|
if len(Pw4) > 0:
|
||||||
|
P4perc = 100 / numPweights * len(Pw4)
|
||||||
|
else:
|
||||||
|
P4perc = 0
|
||||||
|
if len(Sw0) > 0:
|
||||||
|
S0perc = 100 / numSweights * len(Sw0)
|
||||||
|
else:
|
||||||
|
S0perc = 0
|
||||||
|
if len(Sw1) > 0:
|
||||||
|
S1perc = 100 / numSweights * len(Sw1)
|
||||||
|
else:
|
||||||
|
S1perc = 0
|
||||||
|
if len(Sw2) > 0:
|
||||||
|
S2perc = 100 / numSweights * len(Sw2)
|
||||||
|
else:
|
||||||
|
S2perc = 0
|
||||||
|
if len(Sw3) > 0:
|
||||||
|
S3perc = 100 / numSweights * len(Sw3)
|
||||||
|
else:
|
||||||
|
S3perc = 0
|
||||||
|
if len(Sw4) > 0:
|
||||||
|
S4perc = 100 / numSweights * len(Sw4)
|
||||||
|
else:
|
||||||
|
S4perc = 0
|
||||||
|
|
||||||
|
weights = ('0', '1', '2', '3', '4')
|
||||||
|
y_pos = np.arange(len(weights))
|
||||||
|
width = 0.34
|
||||||
|
plt.bar(y_pos - width, [P0perc, P1perc, P2perc, P3perc, P4perc], width, color='black')
|
||||||
|
plt.bar(y_pos, [S0perc, S1perc, S2perc, S3perc, S4perc], width, color='red')
|
||||||
|
plt.ylabel('%')
|
||||||
|
plt.xticks(y_pos, weights)
|
||||||
|
plt.xlim([-0.5, 4.5])
|
||||||
|
plt.xlabel('Qualities')
|
||||||
|
plt.title('{0} P-Qualities, {1} S-Qualities'.format(numPweights, numSweights))
|
||||||
|
plt.show()
|
||||||
|
28
pylot/core/loc/focmec.py
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#!/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 focmec
|
||||||
|
<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 information needed for focmec format
|
||||||
|
:type: list object
|
||||||
|
'''
|
||||||
|
# write phases to FOCMEC-phase file
|
||||||
|
writephases(picks, 'FOCMEC', fnout, parameter, eventinfo)
|
28
pylot/core/loc/hash.py
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#!/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 HASH
|
||||||
|
<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 information needed for HASH format
|
||||||
|
:type: list object
|
||||||
|
'''
|
||||||
|
# write phases to HASH-phase file
|
||||||
|
writephases(picks, 'HASH', fnout, parameter, eventinfo)
|
@ -6,9 +6,10 @@ from pylot.core.util.version import get_git_version as _getVersionString
|
|||||||
|
|
||||||
__version__ = _getVersionString()
|
__version__ = _getVersionString()
|
||||||
|
|
||||||
def export(picks, fnout):
|
|
||||||
|
def export(picks, fnout, parameter):
|
||||||
'''
|
'''
|
||||||
Take <picks> dictionary and exports picking data to a NLLOC-obs
|
Take <picks> dictionary and exports picking data to a HYPO71
|
||||||
<phasefile> without creating an ObsPy event object.
|
<phasefile> without creating an ObsPy event object.
|
||||||
|
|
||||||
:param picks: picking data dictionary
|
:param picks: picking data dictionary
|
||||||
@ -16,6 +17,9 @@ def export(picks, fnout):
|
|||||||
|
|
||||||
:param fnout: complete path to the exporting obs file
|
:param fnout: complete path to the exporting obs file
|
||||||
:type fnout: str
|
:type fnout: str
|
||||||
|
|
||||||
|
:param: parameter, all input information
|
||||||
|
:type: object
|
||||||
'''
|
'''
|
||||||
# write phases to NLLoc-phase file
|
# write phases to HYPO71-phase file
|
||||||
writephases(picks, 'HYPO71', fnout)
|
writephases(picks, 'HYPO71', fnout, parameter)
|
28
pylot/core/loc/hypodd.py
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#!/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 hypoDD
|
||||||
|
<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 information needed for hypoDD format
|
||||||
|
:type: list object
|
||||||
|
'''
|
||||||
|
# write phases to hypoDD-phase file
|
||||||
|
writephases(picks, 'hypoDD', fnout, parameter, eventinfo)
|
25
pylot/core/loc/hyposat.py
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
#!/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):
|
||||||
|
'''
|
||||||
|
Take <picks> dictionary and exports picking data to a HYPOSAT
|
||||||
|
<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
|
||||||
|
'''
|
||||||
|
# write phases to HYPOSAT-phase file
|
||||||
|
writephases(picks, 'HYPOSAT', fnout, parameter)
|
@ -1,9 +1,10 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
import subprocess
|
|
||||||
import os
|
|
||||||
import glob
|
import glob
|
||||||
|
import os
|
||||||
|
import subprocess
|
||||||
|
|
||||||
from obspy import read_events
|
from obspy import read_events
|
||||||
from pylot.core.io.phases import writephases
|
from pylot.core.io.phases import writephases
|
||||||
from pylot.core.util.utils import getPatternLine, runProgram, which
|
from pylot.core.util.utils import getPatternLine, runProgram, which
|
||||||
@ -11,10 +12,12 @@ from pylot.core.util.version import get_git_version as _getVersionString
|
|||||||
|
|
||||||
__version__ = _getVersionString()
|
__version__ = _getVersionString()
|
||||||
|
|
||||||
|
|
||||||
class NLLocError(EnvironmentError):
|
class NLLocError(EnvironmentError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def export(picks, fnout):
|
|
||||||
|
def export(picks, fnout, parameter):
|
||||||
'''
|
'''
|
||||||
Take <picks> dictionary and exports picking data to a NLLOC-obs
|
Take <picks> dictionary and exports picking data to a NLLOC-obs
|
||||||
<phasefile> without creating an ObsPy event object.
|
<phasefile> without creating an ObsPy event object.
|
||||||
@ -24,9 +27,12 @@ def export(picks, fnout):
|
|||||||
|
|
||||||
:param fnout: complete path to the exporting obs file
|
:param fnout: complete path to the exporting obs file
|
||||||
:type fnout: str
|
:type fnout: str
|
||||||
|
|
||||||
|
:param: parameter, all input information
|
||||||
|
:type: object
|
||||||
'''
|
'''
|
||||||
# write phases to NLLoc-phase file
|
# write phases to NLLoc-phase file
|
||||||
writephases(picks, 'NLLoc', fnout)
|
writephases(picks, 'NLLoc', fnout, parameter)
|
||||||
|
|
||||||
|
|
||||||
def modify_inputs(ctrfn, root, nllocoutn, phasefn, tttn):
|
def modify_inputs(ctrfn, root, nllocoutn, phasefn, tttn):
|
||||||
@ -67,14 +73,17 @@ def modify_inputs(ctrfn, root, nllocoutn, phasefn, tttn):
|
|||||||
nllfile.close()
|
nllfile.close()
|
||||||
|
|
||||||
|
|
||||||
def locate(fnin):
|
def locate(fnin, infile=None):
|
||||||
"""
|
"""
|
||||||
takes an external program name
|
takes an external program name
|
||||||
:param fnin:
|
:param fnin:
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
if infile is None:
|
||||||
exe_path = which('NLLoc')
|
exe_path = which('NLLoc')
|
||||||
|
else:
|
||||||
|
exe_path = which('NLLoc', infile)
|
||||||
if exe_path is None:
|
if exe_path is None:
|
||||||
raise NLLocError('NonLinLoc executable not found; check your '
|
raise NLLocError('NonLinLoc executable not found; check your '
|
||||||
'environment variables')
|
'environment variables')
|
||||||
|
@ -1,2 +1,28 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- 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, eventinfo, parameter=None):
|
||||||
|
'''
|
||||||
|
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: eventinfo, source time needed for VELEST-cnv format
|
||||||
|
:type: list object
|
||||||
|
|
||||||
|
:param: parameter, all input information
|
||||||
|
:type: object
|
||||||
|
'''
|
||||||
|
# write phases to VELEST-phase file
|
||||||
|
writephases(picks, 'VELEST', fnout, parameter, eventinfo)
|
||||||
|
605
pylot/core/pick/autopick.py
Executable file → Normal file
@ -11,25 +11,37 @@ function conglomerate utils.
|
|||||||
|
|
||||||
import matplotlib.pyplot as plt
|
import matplotlib.pyplot as plt
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from pylot.core.io.inputs import AutoPickParameter
|
from pylot.core.io.data import Data
|
||||||
from pylot.core.pick.picker import AICPicker, PragPicker
|
from pylot.core.io.inputs import PylotParameter
|
||||||
from pylot.core.pick.charfuns import CharacteristicFunction
|
from pylot.core.pick.charfuns import CharacteristicFunction
|
||||||
from pylot.core.pick.charfuns import HOScf, AICcf, ARZcf, ARHcf, AR3Ccf
|
from pylot.core.pick.charfuns import HOScf, AICcf, ARZcf, ARHcf, AR3Ccf
|
||||||
|
from pylot.core.pick.picker import AICPicker, PragPicker
|
||||||
from pylot.core.pick.utils import checksignallength, checkZ4S, earllatepicker, \
|
from pylot.core.pick.utils import checksignallength, checkZ4S, earllatepicker, \
|
||||||
getSNR, fmpicker, checkPonsets, wadaticheck
|
getSNR, fmpicker, checkPonsets, wadaticheck
|
||||||
from pylot.core.util.utils import getPatternLine
|
from pylot.core.util.utils import getPatternLine, gen_Pool,\
|
||||||
from pylot.core.io.data import Data
|
real_Bool, identifyPhaseID
|
||||||
|
|
||||||
|
from obspy.taup import TauPyModel
|
||||||
|
|
||||||
|
|
||||||
def autopickevent(data, param):
|
def autopickevent(data, param, iplot=0, fig_dict=None, fig_dict_wadatijack=None, ncores=0, metadata=None, origin=None):
|
||||||
stations = []
|
stations = []
|
||||||
all_onsets = {}
|
all_onsets = {}
|
||||||
|
input_tuples = []
|
||||||
|
try:
|
||||||
|
iplot = int(iplot)
|
||||||
|
except:
|
||||||
|
if iplot == True or iplot == 'True':
|
||||||
|
iplot = 2
|
||||||
|
else:
|
||||||
|
iplot = 0
|
||||||
|
|
||||||
|
|
||||||
# get some parameters for quality control from
|
# get some parameters for quality control from
|
||||||
# parameter input file (usually autoPyLoT.in).
|
# parameter input file (usually pylot.in).
|
||||||
wdttolerance = param.get('wdttolerance')
|
wdttolerance = param.get('wdttolerance')
|
||||||
mdttolerance = param.get('mdttolerance')
|
mdttolerance = param.get('mdttolerance')
|
||||||
iplot = param.get('iplot')
|
jackfactor = param.get('jackfactor')
|
||||||
apverbose = param.get('apverbose')
|
apverbose = param.get('apverbose')
|
||||||
for n in range(len(data)):
|
for n in range(len(data)):
|
||||||
station = data[n].stats.station
|
station = data[n].stats.station
|
||||||
@ -40,34 +52,80 @@ def autopickevent(data, param):
|
|||||||
|
|
||||||
for station in stations:
|
for station in stations:
|
||||||
topick = data.select(station=station)
|
topick = data.select(station=station)
|
||||||
all_onsets[station] = autopickstation(topick, param, verbose=apverbose)
|
|
||||||
|
if iplot == None or iplot == 'None' or iplot == 0:
|
||||||
|
input_tuples.append((topick, param, apverbose, metadata, origin))
|
||||||
|
if iplot > 0:
|
||||||
|
all_onsets[station] = autopickstation(topick, param, verbose=apverbose,
|
||||||
|
iplot=iplot, fig_dict=fig_dict,
|
||||||
|
metadata=metadata, origin=origin)
|
||||||
|
|
||||||
|
if iplot > 0:
|
||||||
|
print('iPlot Flag active: NO MULTIPROCESSING possible.')
|
||||||
|
return all_onsets
|
||||||
|
|
||||||
|
# rename str for ncores in case ncores == 0 (use all cores)
|
||||||
|
ncores_str = ncores if ncores != 0 else 'all available'
|
||||||
|
|
||||||
|
print('Autopickstation: Distribute autopicking for {} '
|
||||||
|
'stations on {} cores.'.format(len(input_tuples), ncores_str))
|
||||||
|
|
||||||
|
pool = gen_Pool(ncores)
|
||||||
|
result = pool.map(call_autopickstation, input_tuples)
|
||||||
|
pool.close()
|
||||||
|
|
||||||
|
for pick in result:
|
||||||
|
if pick:
|
||||||
|
station = pick['station']
|
||||||
|
pick.pop('station')
|
||||||
|
all_onsets[station] = pick
|
||||||
|
|
||||||
|
#return all_onsets
|
||||||
|
|
||||||
# quality control
|
# quality control
|
||||||
# median check and jackknife on P-onset times
|
# median check and jackknife on P-onset times
|
||||||
jk_checked_onsets = checkPonsets(all_onsets, mdttolerance, iplot)
|
jk_checked_onsets = checkPonsets(all_onsets, mdttolerance, jackfactor, 1, fig_dict_wadatijack)
|
||||||
|
#return jk_checked_onsets
|
||||||
# check S-P times (Wadati)
|
# check S-P times (Wadati)
|
||||||
return wadaticheck(jk_checked_onsets, wdttolerance, iplot)
|
wadationsets = wadaticheck(jk_checked_onsets, wdttolerance, 1, fig_dict_wadatijack)
|
||||||
|
return wadationsets
|
||||||
|
|
||||||
|
|
||||||
def autopickstation(wfstream, pickparam, verbose=False):
|
def call_autopickstation(input_tuple):
|
||||||
|
wfstream, pickparam, verbose, metadata, origin = input_tuple
|
||||||
|
# multiprocessing not possible with interactive plotting
|
||||||
|
return autopickstation(wfstream, pickparam, verbose, iplot=0, metadata=metadata, origin=origin)
|
||||||
|
|
||||||
|
|
||||||
|
def get_source_coords(parser, station_id):
|
||||||
|
station_coords = None
|
||||||
|
try:
|
||||||
|
station_coords = parser.get_coordinates(station_id)
|
||||||
|
except Exception as e:
|
||||||
|
print('Could not get source coordinates for station {}: {}'.format(station_id, e))
|
||||||
|
return station_coords
|
||||||
|
|
||||||
|
|
||||||
|
def autopickstation(wfstream, pickparam, verbose=False,
|
||||||
|
iplot=0, fig_dict=None, metadata=None, origin=None):
|
||||||
"""
|
"""
|
||||||
:param wfstream: `~obspy.core.stream.Stream` containing waveform
|
:param wfstream: `~obspy.core.stream.Stream` containing waveform
|
||||||
:type wfstream: obspy.core.stream.Stream
|
:type wfstream: obspy.core.stream.Stream
|
||||||
|
|
||||||
:param pickparam: container of picking parameters from input file,
|
:param pickparam: container of picking parameters from input file,
|
||||||
usually autoPyLoT.in
|
usually pylot.in
|
||||||
:type pickparam: AutoPickParameter
|
:type pickparam: PylotParameter
|
||||||
:param verbose:
|
:param verbose:
|
||||||
:type verbose: bool
|
:type verbose: bool
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# declaring pickparam variables (only for convenience)
|
# declaring pickparam variables (only for convenience)
|
||||||
# read your autoPyLoT.in for details!
|
# read your pylot.in for details!
|
||||||
|
plt_flag = 0
|
||||||
|
|
||||||
# special parameters for P picking
|
# special parameters for P picking
|
||||||
algoP = pickparam.get('algoP')
|
algoP = pickparam.get('algoP')
|
||||||
iplot = pickparam.get('iplot')
|
|
||||||
pstart = pickparam.get('pstart')
|
pstart = pickparam.get('pstart')
|
||||||
pstop = pickparam.get('pstop')
|
pstop = pickparam.get('pstop')
|
||||||
thosmw = pickparam.get('tlta')
|
thosmw = pickparam.get('tlta')
|
||||||
@ -76,6 +134,7 @@ def autopickstation(wfstream, pickparam, verbose=False):
|
|||||||
bpz1 = pickparam.get('bpz1')
|
bpz1 = pickparam.get('bpz1')
|
||||||
bpz2 = pickparam.get('bpz2')
|
bpz2 = pickparam.get('bpz2')
|
||||||
pickwinP = pickparam.get('pickwinP')
|
pickwinP = pickparam.get('pickwinP')
|
||||||
|
aictsmoothP = pickparam.get('aictsmooth')
|
||||||
tsmoothP = pickparam.get('tsmoothP')
|
tsmoothP = pickparam.get('tsmoothP')
|
||||||
ausP = pickparam.get('ausP')
|
ausP = pickparam.get('ausP')
|
||||||
nfacP = pickparam.get('nfacP')
|
nfacP = pickparam.get('nfacP')
|
||||||
@ -91,6 +150,8 @@ def autopickstation(wfstream, pickparam, verbose=False):
|
|||||||
algoS = pickparam.get('algoS')
|
algoS = pickparam.get('algoS')
|
||||||
sstart = pickparam.get('sstart')
|
sstart = pickparam.get('sstart')
|
||||||
sstop = pickparam.get('sstop')
|
sstop = pickparam.get('sstop')
|
||||||
|
use_taup = real_Bool(pickparam.get('use_taup'))
|
||||||
|
taup_model = pickparam.get('taup_model')
|
||||||
bph1 = pickparam.get('bph1')
|
bph1 = pickparam.get('bph1')
|
||||||
bph2 = pickparam.get('bph2')
|
bph2 = pickparam.get('bph2')
|
||||||
tsnrh = pickparam.get('tsnrh')
|
tsnrh = pickparam.get('tsnrh')
|
||||||
@ -143,7 +204,7 @@ def autopickstation(wfstream, pickparam, verbose=False):
|
|||||||
Sflag = 0
|
Sflag = 0
|
||||||
Pmarker = []
|
Pmarker = []
|
||||||
Ao = None # Wood-Anderson peak-to-peak amplitude
|
Ao = None # Wood-Anderson peak-to-peak amplitude
|
||||||
picker = 'autoPyLoT' # name of the picking programm
|
picker = 'auto' # type of picks
|
||||||
|
|
||||||
# split components
|
# split components
|
||||||
zdat = wfstream.select(component="Z")
|
zdat = wfstream.select(component="Z")
|
||||||
@ -156,25 +217,82 @@ def autopickstation(wfstream, pickparam, verbose=False):
|
|||||||
if len(ndat) == 0: # check for other components
|
if len(ndat) == 0: # check for other components
|
||||||
ndat = wfstream.select(component="1")
|
ndat = wfstream.select(component="1")
|
||||||
|
|
||||||
|
if not zdat:
|
||||||
|
print('No z-component found for station {}. STOP'.format(wfstream[0].stats.station))
|
||||||
|
return
|
||||||
|
|
||||||
if algoP == 'HOS' or algoP == 'ARZ' and zdat is not None:
|
if algoP == 'HOS' or algoP == 'ARZ' and zdat is not None:
|
||||||
msg = '##########################################\nautopickstation:' \
|
msg = '##################################################\nautopickstation:' \
|
||||||
' Working on P onset of station {station}\nFiltering vertical ' \
|
' Working on P onset of station {station}\nFiltering vertical ' \
|
||||||
'trace ...\n{data}'.format(station=zdat[0].stats.station,
|
'trace ...\n{data}'.format(station=wfstream[0].stats.station,
|
||||||
data=str(zdat))
|
data=str(zdat))
|
||||||
if verbose: print(msg)
|
if verbose: print(msg)
|
||||||
z_copy = zdat.copy()
|
z_copy = zdat.copy()
|
||||||
# filter and taper data
|
|
||||||
tr_filt = zdat[0].copy()
|
tr_filt = zdat[0].copy()
|
||||||
|
#remove constant offset from data to avoid unwanted filter response
|
||||||
|
tr_filt.detrend(type='demean')
|
||||||
|
# filter and taper data
|
||||||
tr_filt.filter('bandpass', freqmin=bpz1[0], freqmax=bpz1[1],
|
tr_filt.filter('bandpass', freqmin=bpz1[0], freqmax=bpz1[1],
|
||||||
zerophase=False)
|
zerophase=False)
|
||||||
tr_filt.taper(max_percentage=0.05, type='hann')
|
tr_filt.taper(max_percentage=0.05, type='hann')
|
||||||
z_copy[0].data = tr_filt.data
|
z_copy[0].data = tr_filt.data
|
||||||
##############################################################
|
##############################################################
|
||||||
# check length of waveform and compare with cut times
|
# check length of waveform and compare with cut times
|
||||||
|
|
||||||
|
# for global seismology: use tau-p method for estimating travel times (needs source and station coords.)
|
||||||
|
# if not given: sets Lc to infinity to use full stream
|
||||||
|
if use_taup == True:
|
||||||
|
Lc = np.inf
|
||||||
|
print('autopickstation: use_taup flag active.')
|
||||||
|
if not metadata[1]:
|
||||||
|
print('Warning: Could not use TauPy to estimate onsets as there are no metadata given.')
|
||||||
|
else:
|
||||||
|
station_id = wfstream[0].get_id()
|
||||||
|
parser = metadata[1]
|
||||||
|
station_coords = get_source_coords(parser, station_id)
|
||||||
|
if station_coords and origin:
|
||||||
|
source_origin = origin[0]
|
||||||
|
model = TauPyModel(taup_model)
|
||||||
|
arrivals = model.get_travel_times_geo(
|
||||||
|
source_origin.depth,
|
||||||
|
source_origin.latitude,
|
||||||
|
source_origin.longitude,
|
||||||
|
station_coords['latitude'],
|
||||||
|
station_coords['longitude']
|
||||||
|
)
|
||||||
|
phases = {'P': [],
|
||||||
|
'S': []}
|
||||||
|
for arr in arrivals:
|
||||||
|
phases[identifyPhaseID(arr.phase.name)].append(arr)
|
||||||
|
|
||||||
|
# get first P and S onsets from arrivals list
|
||||||
|
arrP, estFirstP = min([(arr, arr.time) for arr in phases['P']], key = lambda t: t[1])
|
||||||
|
arrS, estFirstS = min([(arr, arr.time) for arr in phases['S']], key = lambda t: t[1])
|
||||||
|
print('autopick: estimated first arrivals for P: {} s, S:{} s after event'
|
||||||
|
' origin time using TauPy'.format(estFirstP, estFirstS))
|
||||||
|
|
||||||
|
# modifiy pstart and pstop relative to estimated first P arrival (relative to station time axis)
|
||||||
|
pstart += (source_origin.time + estFirstP) - zdat[0].stats.starttime
|
||||||
|
pstop += (source_origin.time + estFirstP) - zdat[0].stats.starttime
|
||||||
|
print('autopick: CF calculation times respectively:'
|
||||||
|
' pstart: {} s, pstop: {} s'.format(pstart, pstop))
|
||||||
|
elif not origin:
|
||||||
|
print('No source origins given!')
|
||||||
|
|
||||||
|
# make sure pstart and pstop are inside zdat[0]
|
||||||
|
pstart = max(pstart, 0)
|
||||||
|
pstop = min(pstop, len(zdat[0])*zdat[0].stats.delta)
|
||||||
|
|
||||||
|
if not use_taup == True or origin:
|
||||||
Lc = pstop - pstart
|
Lc = pstop - pstart
|
||||||
|
|
||||||
Lwf = zdat[0].stats.endtime - zdat[0].stats.starttime
|
Lwf = zdat[0].stats.endtime - zdat[0].stats.starttime
|
||||||
Ldiff = Lwf - Lc
|
if not Lwf > 0:
|
||||||
if Ldiff < 0:
|
print('autopickstation: empty trace! Return!')
|
||||||
|
return
|
||||||
|
|
||||||
|
Ldiff = Lwf - abs(Lc)
|
||||||
|
if Ldiff < 0 or pstop <= pstart:
|
||||||
msg = 'autopickstation: Cutting times are too large for actual ' \
|
msg = 'autopickstation: Cutting times are too large for actual ' \
|
||||||
'waveform!\nUsing entire waveform instead!'
|
'waveform!\nUsing entire waveform instead!'
|
||||||
if verbose: print(msg)
|
if verbose: print(msg)
|
||||||
@ -206,7 +324,20 @@ def autopickstation(wfstream, pickparam, verbose=False):
|
|||||||
##############################################################
|
##############################################################
|
||||||
# get prelimenary onset time from AIC-HOS-CF using subclass AICPicker
|
# get prelimenary onset time from AIC-HOS-CF using subclass AICPicker
|
||||||
# of class AutoPicking
|
# of class AutoPicking
|
||||||
aicpick = AICPicker(aiccf, tsnrz, pickwinP, iplot, None, tsmoothP)
|
key = 'aicFig'
|
||||||
|
if fig_dict:
|
||||||
|
fig = fig_dict[key]
|
||||||
|
linecolor = fig_dict['plot_style']['linecolor']['rgba_mpl']
|
||||||
|
else:
|
||||||
|
fig = None
|
||||||
|
linecolor = 'k'
|
||||||
|
aicpick = AICPicker(aiccf, tsnrz, pickwinP, iplot, None, aictsmoothP, fig=fig, linecolor=linecolor)
|
||||||
|
# add pstart and pstop to aic plot
|
||||||
|
if fig:
|
||||||
|
for ax in fig.axes:
|
||||||
|
ax.vlines(pstart, ax.get_ylim()[0], ax.get_ylim()[1], color='c', linestyles='dashed', label='P start')
|
||||||
|
ax.vlines(pstop, ax.get_ylim()[0], ax.get_ylim()[1], color='c', linestyles='dashed', label='P stop')
|
||||||
|
ax.legend(loc=1)
|
||||||
##############################################################
|
##############################################################
|
||||||
if aicpick.getpick() is not None:
|
if aicpick.getpick() is not None:
|
||||||
# check signal length to detect spuriously picked noise peaks
|
# check signal length to detect spuriously picked noise peaks
|
||||||
@ -220,13 +351,24 @@ def autopickstation(wfstream, pickparam, verbose=False):
|
|||||||
'Decreasing minsiglengh from {0} to ' \
|
'Decreasing minsiglengh from {0} to ' \
|
||||||
'{1}'.format(minsiglength, minsiglength / 2)
|
'{1}'.format(minsiglength, minsiglength / 2)
|
||||||
if verbose: print(msg)
|
if verbose: print(msg)
|
||||||
|
key = 'slength'
|
||||||
|
if fig_dict:
|
||||||
|
fig = fig_dict[key]
|
||||||
|
linecolor = fig_dict['plot_style']['linecolor']['rgba_mpl']
|
||||||
|
else:
|
||||||
|
fig = None
|
||||||
|
linecolor = 'k'
|
||||||
Pflag = checksignallength(zne, aicpick.getpick(), tsnrz,
|
Pflag = checksignallength(zne, aicpick.getpick(), tsnrz,
|
||||||
minsiglength / 2,
|
minsiglength / 2,
|
||||||
nfacsl, minpercent, iplot)
|
nfacsl, minpercent, iplot,
|
||||||
|
fig, linecolor)
|
||||||
else:
|
else:
|
||||||
# filter and taper horizontal traces
|
# filter and taper horizontal traces
|
||||||
trH1_filt = edat.copy()
|
trH1_filt = edat.copy()
|
||||||
trH2_filt = ndat.copy()
|
trH2_filt = ndat.copy()
|
||||||
|
# remove constant offset from data to avoid unwanted filter response
|
||||||
|
trH1_filt.detrend(type='demean')
|
||||||
|
trH2_filt.detrend(type='demean')
|
||||||
trH1_filt.filter('bandpass', freqmin=bph1[0],
|
trH1_filt.filter('bandpass', freqmin=bph1[0],
|
||||||
freqmax=bph1[1],
|
freqmax=bph1[1],
|
||||||
zerophase=False)
|
zerophase=False)
|
||||||
@ -237,9 +379,16 @@ def autopickstation(wfstream, pickparam, verbose=False):
|
|||||||
trH2_filt.taper(max_percentage=0.05, type='hann')
|
trH2_filt.taper(max_percentage=0.05, type='hann')
|
||||||
zne += trH1_filt
|
zne += trH1_filt
|
||||||
zne += trH2_filt
|
zne += trH2_filt
|
||||||
|
if fig_dict:
|
||||||
|
fig = fig_dict['slength']
|
||||||
|
linecolor = fig_dict['plot_style']['linecolor']['rgba_mpl']
|
||||||
|
else:
|
||||||
|
fig = None
|
||||||
|
linecolor = 'k'
|
||||||
Pflag = checksignallength(zne, aicpick.getpick(), tsnrz,
|
Pflag = checksignallength(zne, aicpick.getpick(), tsnrz,
|
||||||
minsiglength,
|
minsiglength,
|
||||||
nfacsl, minpercent, iplot)
|
nfacsl, minpercent, iplot,
|
||||||
|
fig, linecolor)
|
||||||
|
|
||||||
if Pflag == 1:
|
if Pflag == 1:
|
||||||
# check for spuriously picked S onset
|
# check for spuriously picked S onset
|
||||||
@ -249,8 +398,15 @@ def autopickstation(wfstream, pickparam, verbose=False):
|
|||||||
'Skipping control function checkZ4S.'
|
'Skipping control function checkZ4S.'
|
||||||
if verbose: print(msg)
|
if verbose: print(msg)
|
||||||
else:
|
else:
|
||||||
|
if iplot > 1:
|
||||||
|
if fig_dict:
|
||||||
|
fig = fig_dict['checkZ4s']
|
||||||
|
linecolor = fig_dict['plot_style']['linecolor']['rgba_mpl']
|
||||||
|
else:
|
||||||
|
fig = None
|
||||||
|
linecolor = 'k'
|
||||||
Pflag = checkZ4S(zne, aicpick.getpick(), zfac,
|
Pflag = checkZ4S(zne, aicpick.getpick(), zfac,
|
||||||
tsnrz[3], iplot)
|
tsnrz[2], iplot, fig, linecolor)
|
||||||
if Pflag == 0:
|
if Pflag == 0:
|
||||||
Pmarker = 'SinsteadP'
|
Pmarker = 'SinsteadP'
|
||||||
Pweight = 9
|
Pweight = 9
|
||||||
@ -259,7 +415,10 @@ def autopickstation(wfstream, pickparam, verbose=False):
|
|||||||
Pweight = 9
|
Pweight = 9
|
||||||
##############################################################
|
##############################################################
|
||||||
# go on with processing if AIC onset passes quality control
|
# go on with processing if AIC onset passes quality control
|
||||||
if (aicpick.getSlope() >= minAICPslope and
|
slope = aicpick.getSlope()
|
||||||
|
if not slope:
|
||||||
|
slope = 0
|
||||||
|
if (slope >= minAICPslope and
|
||||||
aicpick.getSNR() >= minAICPSNR and Pflag == 1):
|
aicpick.getSNR() >= minAICPSNR and Pflag == 1):
|
||||||
aicPflag = 1
|
aicPflag = 1
|
||||||
msg = 'AIC P-pick passes quality control: Slope: {0} counts/s, ' \
|
msg = 'AIC P-pick passes quality control: Slope: {0} counts/s, ' \
|
||||||
@ -270,6 +429,7 @@ def autopickstation(wfstream, pickparam, verbose=False):
|
|||||||
# re-filter waveform with larger bandpass
|
# re-filter waveform with larger bandpass
|
||||||
z_copy = zdat.copy()
|
z_copy = zdat.copy()
|
||||||
tr_filt = zdat[0].copy()
|
tr_filt = zdat[0].copy()
|
||||||
|
tr_filt.detrend(type='demean')
|
||||||
tr_filt.filter('bandpass', freqmin=bpz2[0], freqmax=bpz2[1],
|
tr_filt.filter('bandpass', freqmin=bpz2[0], freqmax=bpz2[1],
|
||||||
zerophase=False)
|
zerophase=False)
|
||||||
tr_filt.taper(max_percentage=0.05, type='hann')
|
tr_filt.taper(max_percentage=0.05, type='hann')
|
||||||
@ -297,20 +457,40 @@ def autopickstation(wfstream, pickparam, verbose=False):
|
|||||||
'correctly: maybe the algorithm name ({algoP}) is ' \
|
'correctly: maybe the algorithm name ({algoP}) is ' \
|
||||||
'corrupted'.format(
|
'corrupted'.format(
|
||||||
algoP=algoP)
|
algoP=algoP)
|
||||||
|
if fig_dict:
|
||||||
|
fig = fig_dict['refPpick']
|
||||||
|
linecolor = fig_dict['plot_style']['linecolor']['rgba_mpl']
|
||||||
|
else:
|
||||||
|
fig = None
|
||||||
|
linecolor = 'k'
|
||||||
refPpick = PragPicker(cf2, tsnrz, pickwinP, iplot, ausP, tsmoothP,
|
refPpick = PragPicker(cf2, tsnrz, pickwinP, iplot, ausP, tsmoothP,
|
||||||
aicpick.getpick())
|
aicpick.getpick(), fig, linecolor)
|
||||||
mpickP = refPpick.getpick()
|
mpickP = refPpick.getpick()
|
||||||
#############################################################
|
#############################################################
|
||||||
if mpickP is not None:
|
if mpickP is not None:
|
||||||
# quality assessment
|
# quality assessment
|
||||||
# get earliest/latest possible pick and symmetrized uncertainty
|
# get earliest/latest possible pick and symmetrized uncertainty
|
||||||
[epickP, lpickP, Perror] = earllatepicker(z_copy, nfacP, tsnrz,
|
if iplot:
|
||||||
|
if fig_dict:
|
||||||
|
fig = fig_dict['el_Ppick']
|
||||||
|
linecolor = fig_dict['plot_style']['linecolor']['rgba_mpl']
|
||||||
|
else:
|
||||||
|
fig = None
|
||||||
|
linecolor = 'k'
|
||||||
|
epickP, lpickP, Perror = earllatepicker(z_copy, nfacP, tsnrz,
|
||||||
|
mpickP, iplot, fig=fig,
|
||||||
|
linecolor=linecolor)
|
||||||
|
else:
|
||||||
|
epickP, lpickP, Perror = earllatepicker(z_copy, nfacP, tsnrz,
|
||||||
mpickP, iplot)
|
mpickP, iplot)
|
||||||
|
|
||||||
# get SNR
|
# get SNR
|
||||||
[SNRP, SNRPdB, Pnoiselevel] = getSNR(z_copy, tsnrz, mpickP)
|
[SNRP, SNRPdB, Pnoiselevel] = getSNR(z_copy, tsnrz, mpickP)
|
||||||
|
|
||||||
# weight P-onset using symmetric error
|
# weight P-onset using symmetric error
|
||||||
|
if Perror == None:
|
||||||
|
Pweight = 4
|
||||||
|
else:
|
||||||
if Perror <= timeerrorsP[0]:
|
if Perror <= timeerrorsP[0]:
|
||||||
Pweight = 0
|
Pweight = 0
|
||||||
elif timeerrorsP[0] < Perror <= timeerrorsP[1]:
|
elif timeerrorsP[0] < Perror <= timeerrorsP[1]:
|
||||||
@ -326,6 +506,14 @@ def autopickstation(wfstream, pickparam, verbose=False):
|
|||||||
# get first motion of P onset
|
# get first motion of P onset
|
||||||
# certain quality required
|
# certain quality required
|
||||||
if Pweight <= minfmweight and SNRP >= minFMSNR:
|
if Pweight <= minfmweight and SNRP >= minFMSNR:
|
||||||
|
if iplot:
|
||||||
|
if fig_dict:
|
||||||
|
fig = fig_dict['fm_picker']
|
||||||
|
linecolor = fig_dict['plot_style']['linecolor']['rgba_mpl']
|
||||||
|
else:
|
||||||
|
fig = None
|
||||||
|
FM = fmpicker(zdat, z_copy, fmpickwin, mpickP, iplot, fig, linecolor)
|
||||||
|
else:
|
||||||
FM = fmpicker(zdat, z_copy, fmpickwin, mpickP, iplot)
|
FM = fmpicker(zdat, z_copy, fmpickwin, mpickP, iplot)
|
||||||
else:
|
else:
|
||||||
FM = 'N'
|
FM = 'N'
|
||||||
@ -336,6 +524,8 @@ def autopickstation(wfstream, pickparam, verbose=False):
|
|||||||
SNRPdB,
|
SNRPdB,
|
||||||
FM)
|
FM)
|
||||||
print(msg)
|
print(msg)
|
||||||
|
msg = 'autopickstation: Refined P-Pick: {} s | P-Error: {} s'.format(mpickP, Perror)
|
||||||
|
print(msg)
|
||||||
Sflag = 1
|
Sflag = 1
|
||||||
|
|
||||||
else:
|
else:
|
||||||
@ -353,16 +543,46 @@ def autopickstation(wfstream, pickparam, verbose=False):
|
|||||||
print('autopickstation: No vertical component data available!, '
|
print('autopickstation: No vertical component data available!, '
|
||||||
'Skipping station!')
|
'Skipping station!')
|
||||||
|
|
||||||
if edat is not None and ndat is not None and len(edat) > 0 and len(
|
if ((len(edat) > 0 and len(ndat) == 0) or (
|
||||||
ndat) > 0 and Pweight < 4:
|
len(ndat) > 0 and len(edat) == 0)) and Pweight < 4:
|
||||||
|
msg = 'Go on picking S onset ...\n' \
|
||||||
|
'##################################################\n' \
|
||||||
|
'Only one horizontal component available!\n' \
|
||||||
|
'ARH prediction requires at least 2 components!\n' \
|
||||||
|
'Copying existing horizontal component ...'
|
||||||
|
if verbose: print(msg)
|
||||||
|
|
||||||
|
# check which component is missing
|
||||||
|
if len(edat) == 0:
|
||||||
|
edat = ndat
|
||||||
|
else:
|
||||||
|
ndat = edat
|
||||||
|
|
||||||
|
pickSonset = (edat is not None and ndat is not None and len(edat) > 0 and len(
|
||||||
|
ndat) > 0 and Pweight < 4)
|
||||||
|
|
||||||
|
if pickSonset:
|
||||||
|
# determine time window for calculating CF after P onset
|
||||||
|
cuttimesh = [
|
||||||
|
round(max([mpickP + sstart, 0])), # MP MP relative time axis
|
||||||
|
round(min([
|
||||||
|
mpickP + sstop,
|
||||||
|
edat[0].stats.endtime-edat[0].stats.starttime,
|
||||||
|
ndat[0].stats.endtime-ndat[0].stats.starttime
|
||||||
|
]))
|
||||||
|
]
|
||||||
|
|
||||||
|
if not cuttimesh[1] >= cuttimesh[0]:
|
||||||
|
print('Cut window for horizontal phases too small! Will not pick S onsets.')
|
||||||
|
pickSonset = False
|
||||||
|
|
||||||
|
if pickSonset:
|
||||||
msg = 'Go on picking S onset ...\n' \
|
msg = 'Go on picking S onset ...\n' \
|
||||||
'##################################################\n' \
|
'##################################################\n' \
|
||||||
'Working on S onset of station {0}\nFiltering horizontal ' \
|
'Working on S onset of station {0}\nFiltering horizontal ' \
|
||||||
'traces ...'.format(edat[0].stats.station)
|
'traces ...'.format(edat[0].stats.station)
|
||||||
if verbose: print(msg)
|
if verbose: print(msg)
|
||||||
# determine time window for calculating CF after P onset
|
|
||||||
cuttimesh = [round(max([mpickP + sstart, 0])),
|
|
||||||
round(min([mpickP + sstop, Lwf]))]
|
|
||||||
|
|
||||||
if algoS == 'ARH':
|
if algoS == 'ARH':
|
||||||
# re-create stream object including both horizontal components
|
# re-create stream object including both horizontal components
|
||||||
@ -372,6 +592,8 @@ def autopickstation(wfstream, pickparam, verbose=False):
|
|||||||
# filter and taper data
|
# filter and taper data
|
||||||
trH1_filt = hdat[0].copy()
|
trH1_filt = hdat[0].copy()
|
||||||
trH2_filt = hdat[1].copy()
|
trH2_filt = hdat[1].copy()
|
||||||
|
trH1_filt.detrend(type='demean')
|
||||||
|
trH2_filt.detrend(type='demean')
|
||||||
trH1_filt.filter('bandpass', freqmin=bph1[0], freqmax=bph1[1],
|
trH1_filt.filter('bandpass', freqmin=bph1[0], freqmax=bph1[1],
|
||||||
zerophase=False)
|
zerophase=False)
|
||||||
trH2_filt.filter('bandpass', freqmin=bph1[0], freqmax=bph1[1],
|
trH2_filt.filter('bandpass', freqmin=bph1[0], freqmax=bph1[1],
|
||||||
@ -390,6 +612,9 @@ def autopickstation(wfstream, pickparam, verbose=False):
|
|||||||
trH1_filt = hdat[0].copy()
|
trH1_filt = hdat[0].copy()
|
||||||
trH2_filt = hdat[1].copy()
|
trH2_filt = hdat[1].copy()
|
||||||
trH3_filt = hdat[2].copy()
|
trH3_filt = hdat[2].copy()
|
||||||
|
trH1_filt.detrend(type='demean')
|
||||||
|
trH2_filt.detrend(type='demean')
|
||||||
|
trH3_filt.detrend(type='demean')
|
||||||
trH1_filt.filter('bandpass', freqmin=bph1[0], freqmax=bph1[1],
|
trH1_filt.filter('bandpass', freqmin=bph1[0], freqmax=bph1[1],
|
||||||
zerophase=False)
|
zerophase=False)
|
||||||
trH2_filt.filter('bandpass', freqmin=bph1[0], freqmax=bph1[1],
|
trH2_filt.filter('bandpass', freqmin=bph1[0], freqmax=bph1[1],
|
||||||
@ -425,11 +650,20 @@ def autopickstation(wfstream, pickparam, verbose=False):
|
|||||||
##############################################################
|
##############################################################
|
||||||
# get prelimenary onset time from AIC-HOS-CF using subclass AICPicker
|
# get prelimenary onset time from AIC-HOS-CF using subclass AICPicker
|
||||||
# of class AutoPicking
|
# of class AutoPicking
|
||||||
|
if fig_dict:
|
||||||
|
fig = fig_dict['aicARHfig']
|
||||||
|
linecolor = fig_dict['plot_style']['linecolor']['rgba_mpl']
|
||||||
|
else:
|
||||||
|
fig = None
|
||||||
|
linecolor = 'k'
|
||||||
aicarhpick = AICPicker(haiccf, tsnrh, pickwinS, iplot, None,
|
aicarhpick = AICPicker(haiccf, tsnrh, pickwinS, iplot, None,
|
||||||
aictsmoothS)
|
aictsmoothS, fig=fig, linecolor=linecolor)
|
||||||
###############################################################
|
###############################################################
|
||||||
# go on with processing if AIC onset passes quality control
|
# go on with processing if AIC onset passes quality control
|
||||||
if (aicarhpick.getSlope() >= minAICSslope and
|
slope = aicarhpick.getSlope()
|
||||||
|
if not slope:
|
||||||
|
slope = 0
|
||||||
|
if (slope >= minAICSslope and
|
||||||
aicarhpick.getSNR() >= minAICSSNR and
|
aicarhpick.getSNR() >= minAICSSNR and
|
||||||
aicarhpick.getpick() is not None):
|
aicarhpick.getpick() is not None):
|
||||||
aicSflag = 1
|
aicSflag = 1
|
||||||
@ -448,6 +682,8 @@ def autopickstation(wfstream, pickparam, verbose=False):
|
|||||||
if algoS == 'ARH':
|
if algoS == 'ARH':
|
||||||
trH1_filt = hdat[0].copy()
|
trH1_filt = hdat[0].copy()
|
||||||
trH2_filt = hdat[1].copy()
|
trH2_filt = hdat[1].copy()
|
||||||
|
trH1_filt.detrend(type='demean')
|
||||||
|
trH2_filt.detrend(type='demean')
|
||||||
trH1_filt.filter('bandpass', freqmin=bph2[0], freqmax=bph2[1],
|
trH1_filt.filter('bandpass', freqmin=bph2[0], freqmax=bph2[1],
|
||||||
zerophase=False)
|
zerophase=False)
|
||||||
trH2_filt.filter('bandpass', freqmin=bph2[0], freqmax=bph2[1],
|
trH2_filt.filter('bandpass', freqmin=bph2[0], freqmax=bph2[1],
|
||||||
@ -463,6 +699,9 @@ def autopickstation(wfstream, pickparam, verbose=False):
|
|||||||
trH1_filt = hdat[0].copy()
|
trH1_filt = hdat[0].copy()
|
||||||
trH2_filt = hdat[1].copy()
|
trH2_filt = hdat[1].copy()
|
||||||
trH3_filt = hdat[2].copy()
|
trH3_filt = hdat[2].copy()
|
||||||
|
trH1_filt.detrend(type='demean')
|
||||||
|
trH2_filt.detrend(type='demean')
|
||||||
|
trH3_filt.detrend(type='demean')
|
||||||
trH1_filt.filter('bandpass', freqmin=bph2[0], freqmax=bph2[1],
|
trH1_filt.filter('bandpass', freqmin=bph2[0], freqmax=bph2[1],
|
||||||
zerophase=False)
|
zerophase=False)
|
||||||
trH2_filt.filter('bandpass', freqmin=bph2[0], freqmax=bph2[1],
|
trH2_filt.filter('bandpass', freqmin=bph2[0], freqmax=bph2[1],
|
||||||
@ -480,20 +719,52 @@ def autopickstation(wfstream, pickparam, verbose=False):
|
|||||||
addnoise) # instance of ARHcf
|
addnoise) # instance of ARHcf
|
||||||
|
|
||||||
# get refined onset time from CF2 using class Picker
|
# get refined onset time from CF2 using class Picker
|
||||||
|
if fig_dict:
|
||||||
|
fig = fig_dict['refSpick']
|
||||||
|
linecolor = fig_dict['plot_style']['linecolor']['rgba_mpl']
|
||||||
|
else:
|
||||||
|
fig = None
|
||||||
|
linecolor = 'k'
|
||||||
refSpick = PragPicker(arhcf2, tsnrh, pickwinS, iplot, ausS,
|
refSpick = PragPicker(arhcf2, tsnrh, pickwinS, iplot, ausS,
|
||||||
tsmoothS, aicarhpick.getpick())
|
tsmoothS, aicarhpick.getpick(), fig, linecolor)
|
||||||
mpickS = refSpick.getpick()
|
mpickS = refSpick.getpick()
|
||||||
#############################################################
|
#############################################################
|
||||||
if mpickS is not None:
|
if mpickS is not None:
|
||||||
# quality assessment
|
# quality assessment
|
||||||
# get earliest/latest possible pick and symmetrized uncertainty
|
# get earliest/latest possible pick and symmetrized uncertainty
|
||||||
h_copy[0].data = trH1_filt.data
|
h_copy[0].data = trH1_filt.data
|
||||||
[epickS1, lpickS1, Serror1] = earllatepicker(h_copy, nfacS,
|
if iplot:
|
||||||
|
if fig_dict:
|
||||||
|
fig = fig_dict['el_S1pick']
|
||||||
|
linecolor = fig_dict['plot_style']['linecolor']['rgba_mpl']
|
||||||
|
else:
|
||||||
|
fig = None
|
||||||
|
linecolor = 'k'
|
||||||
|
epickS1, lpickS1, Serror1 = earllatepicker(h_copy, nfacS,
|
||||||
|
tsnrh,
|
||||||
|
mpickS, iplot,
|
||||||
|
fig=fig,
|
||||||
|
linecolor=linecolor)
|
||||||
|
else:
|
||||||
|
epickS1, lpickS1, Serror1 = earllatepicker(h_copy, nfacS,
|
||||||
tsnrh,
|
tsnrh,
|
||||||
mpickS, iplot)
|
mpickS, iplot)
|
||||||
|
|
||||||
h_copy[0].data = trH2_filt.data
|
h_copy[0].data = trH2_filt.data
|
||||||
[epickS2, lpickS2, Serror2] = earllatepicker(h_copy, nfacS,
|
if iplot:
|
||||||
|
if fig_dict:
|
||||||
|
fig = fig_dict['el_S2pick']
|
||||||
|
linecolor = fig_dict['plot_style']['linecolor']['rgba_mpl']
|
||||||
|
else:
|
||||||
|
fig = None
|
||||||
|
linecolor = ''
|
||||||
|
epickS2, lpickS2, Serror2 = earllatepicker(h_copy, nfacS,
|
||||||
|
tsnrh,
|
||||||
|
mpickS, iplot,
|
||||||
|
fig=fig,
|
||||||
|
linecolor=linecolor)
|
||||||
|
else:
|
||||||
|
epickS2, lpickS2, Serror2 = earllatepicker(h_copy, nfacS,
|
||||||
tsnrh,
|
tsnrh,
|
||||||
mpickS, iplot)
|
mpickS, iplot)
|
||||||
if epickS1 is not None and epickS2 is not None:
|
if epickS1 is not None and epickS2 is not None:
|
||||||
@ -535,6 +806,9 @@ def autopickstation(wfstream, pickparam, verbose=False):
|
|||||||
lpickS = lpick[ipick]
|
lpickS = lpick[ipick]
|
||||||
Serror = pickerr[ipick]
|
Serror = pickerr[ipick]
|
||||||
|
|
||||||
|
msg = 'autopickstation: Refined S-Pick: {} s | S-Error: {} s'.format(mpickS, Serror)
|
||||||
|
print(msg)
|
||||||
|
|
||||||
# get SNR
|
# get SNR
|
||||||
[SNRS, SNRSdB, Snoiselevel] = getSNR(h_copy, tsnrh, mpickS)
|
[SNRS, SNRSdB, Snoiselevel] = getSNR(h_copy, tsnrh, mpickS)
|
||||||
|
|
||||||
@ -552,12 +826,11 @@ def autopickstation(wfstream, pickparam, verbose=False):
|
|||||||
|
|
||||||
print('autopickstation: S-weight: {0}, SNR: {1}, '
|
print('autopickstation: S-weight: {0}, SNR: {1}, '
|
||||||
'SNR[dB]: {2}\n'
|
'SNR[dB]: {2}\n'
|
||||||
'################################################'
|
'##################################################'
|
||||||
''.format(Sweight, SNRS, SNRSdB))
|
''.format(Sweight, SNRS, SNRSdB))
|
||||||
################################################################
|
################################################################
|
||||||
# get Wood-Anderson peak-to-peak amplitude
|
# get Wood-Anderson peak-to-peak amplitude
|
||||||
# initialize Data object
|
# initialize Data object
|
||||||
data = Data()
|
|
||||||
# re-create stream object including both horizontal components
|
# re-create stream object including both horizontal components
|
||||||
hdat = edat.copy()
|
hdat = edat.copy()
|
||||||
hdat += ndat
|
hdat += ndat
|
||||||
@ -566,7 +839,7 @@ def autopickstation(wfstream, pickparam, verbose=False):
|
|||||||
'AIC-SNR={0}, AIC-Slope={1}counts/s\n' \
|
'AIC-SNR={0}, AIC-Slope={1}counts/s\n' \
|
||||||
'(min. AIC-SNR={2}, ' \
|
'(min. AIC-SNR={2}, ' \
|
||||||
'min. AIC-Slope={3}counts/s)\n' \
|
'min. AIC-Slope={3}counts/s)\n' \
|
||||||
'################################################' \
|
'##################################################' \
|
||||||
''.format(aicarhpick.getSNR(),
|
''.format(aicarhpick.getSNR(),
|
||||||
aicarhpick.getSlope(),
|
aicarhpick.getSlope(),
|
||||||
minAICSSNR,
|
minAICSSNR,
|
||||||
@ -576,50 +849,62 @@ def autopickstation(wfstream, pickparam, verbose=False):
|
|||||||
############################################################
|
############################################################
|
||||||
# get Wood-Anderson peak-to-peak amplitude
|
# get Wood-Anderson peak-to-peak amplitude
|
||||||
# initialize Data object
|
# initialize Data object
|
||||||
data = Data()
|
|
||||||
# re-create stream object including both horizontal components
|
# re-create stream object including both horizontal components
|
||||||
hdat = edat.copy()
|
hdat = edat.copy()
|
||||||
hdat += ndat
|
hdat += ndat
|
||||||
|
|
||||||
else:
|
else:
|
||||||
print('autopickstation: No horizontal component data available or ' \
|
print('autopickstation: No horizontal component data available or '
|
||||||
'bad P onset, skipping S picking!')
|
'bad P onset, skipping S picking!')
|
||||||
|
|
||||||
##############################################################
|
##############################################################
|
||||||
|
try:
|
||||||
|
iplot = int(iplot)
|
||||||
|
except:
|
||||||
|
if iplot == True or iplot == 'True':
|
||||||
|
iplot = 2
|
||||||
|
else:
|
||||||
|
iplot = 0
|
||||||
|
|
||||||
if iplot > 0:
|
if iplot > 0:
|
||||||
# plot vertical trace
|
# plot vertical trace
|
||||||
plt.figure()
|
if fig_dict == None or fig_dict == 'None':
|
||||||
plt.subplot(3, 1, 1)
|
fig = plt.figure()
|
||||||
|
plt_flag = 1
|
||||||
|
linecolor = 'k'
|
||||||
|
else:
|
||||||
|
fig = fig_dict['mainFig']
|
||||||
|
linecolor = fig_dict['plot_style']['linecolor']['rgba_mpl']
|
||||||
|
fig._tight = True
|
||||||
|
ax1 = fig.add_subplot(311)
|
||||||
tdata = np.arange(0, zdat[0].stats.npts / tr_filt.stats.sampling_rate,
|
tdata = np.arange(0, zdat[0].stats.npts / tr_filt.stats.sampling_rate,
|
||||||
tr_filt.stats.delta)
|
tr_filt.stats.delta)
|
||||||
# check equal length of arrays, sometimes they are different!?
|
# check equal length of arrays, sometimes they are different!?
|
||||||
wfldiff = len(tr_filt.data) - len(tdata)
|
wfldiff = len(tr_filt.data) - len(tdata)
|
||||||
if wfldiff < 0:
|
if wfldiff < 0:
|
||||||
tdata = tdata[0:len(tdata) - abs(wfldiff)]
|
tdata = tdata[0:len(tdata) - abs(wfldiff)]
|
||||||
p1, = plt.plot(tdata, tr_filt.data / max(tr_filt.data), 'k')
|
ax1.plot(tdata, tr_filt.data / max(tr_filt.data), color=linecolor, linewidth=0.7, label='Data')
|
||||||
if Pweight < 4:
|
if Pweight < 4:
|
||||||
p2, = plt.plot(cf1.getTimeArray(), cf1.getCF() / max(cf1.getCF()),
|
ax1.plot(cf1.getTimeArray(), cf1.getCF() / max(cf1.getCF()),
|
||||||
'b')
|
'b', label='CF1')
|
||||||
if aicPflag == 1:
|
if aicPflag == 1:
|
||||||
p3, = plt.plot(cf2.getTimeArray(),
|
ax1.plot(cf2.getTimeArray(),
|
||||||
cf2.getCF() / max(cf2.getCF()), 'm')
|
cf2.getCF() / max(cf2.getCF()), 'm', label='CF2')
|
||||||
p4, = plt.plot([aicpick.getpick(), aicpick.getpick()], [-1, 1],
|
ax1.plot([aicpick.getpick(), aicpick.getpick()], [-1, 1],
|
||||||
'r')
|
'r', label='Initial P Onset')
|
||||||
plt.plot([aicpick.getpick() - 0.5, aicpick.getpick() + 0.5],
|
ax1.plot([aicpick.getpick() - 0.5, aicpick.getpick() + 0.5],
|
||||||
[1, 1], 'r')
|
[1, 1], 'r')
|
||||||
plt.plot([aicpick.getpick() - 0.5, aicpick.getpick() + 0.5],
|
ax1.plot([aicpick.getpick() - 0.5, aicpick.getpick() + 0.5],
|
||||||
[-1, -1], 'r')
|
[-1, -1], 'r')
|
||||||
p5, = plt.plot([refPpick.getpick(), refPpick.getpick()],
|
ax1.plot([refPpick.getpick(), refPpick.getpick()],
|
||||||
[-1.3, 1.3], 'r', linewidth=2)
|
[-1.3, 1.3], 'r', linewidth=2, label='Final P Pick')
|
||||||
plt.plot([refPpick.getpick() - 0.5, refPpick.getpick() + 0.5],
|
ax1.plot([refPpick.getpick() - 0.5, refPpick.getpick() + 0.5],
|
||||||
[1.3, 1.3], 'r', linewidth=2)
|
[1.3, 1.3], 'r', linewidth=2)
|
||||||
plt.plot([refPpick.getpick() - 0.5, refPpick.getpick() + 0.5],
|
ax1.plot([refPpick.getpick() - 0.5, refPpick.getpick() + 0.5],
|
||||||
[-1.3, -1.3], 'r', linewidth=2)
|
[-1.3, -1.3], 'r', linewidth=2)
|
||||||
plt.plot([lpickP, lpickP], [-1.1, 1.1], 'r--')
|
ax1.plot([lpickP, lpickP], [-1.1, 1.1], 'r--', label='lpp')
|
||||||
plt.plot([epickP, epickP], [-1.1, 1.1], 'r--')
|
ax1.plot([epickP, epickP], [-1.1, 1.1], 'r--', label='epp')
|
||||||
plt.legend([p1, p2, p3, p4, p5],
|
ax1.set_title('%s, %s, P Weight=%d, SNR=%7.2f, SNR[dB]=%7.2f '
|
||||||
['Data', 'CF1', 'CF2', 'Initial P Onset',
|
|
||||||
'Final P Pick'])
|
|
||||||
plt.title('%s, %s, P Weight=%d, SNR=%7.2f, SNR[dB]=%7.2f '
|
|
||||||
'Polarity: %s' % (tr_filt.stats.station,
|
'Polarity: %s' % (tr_filt.stats.station,
|
||||||
tr_filt.stats.channel,
|
tr_filt.stats.channel,
|
||||||
Pweight,
|
Pweight,
|
||||||
@ -627,22 +912,28 @@ def autopickstation(wfstream, pickparam, verbose=False):
|
|||||||
SNRPdB,
|
SNRPdB,
|
||||||
FM))
|
FM))
|
||||||
else:
|
else:
|
||||||
plt.legend([p1, p2], ['Data', 'CF1'])
|
ax1.set_title('%s, P Weight=%d, SNR=None, '
|
||||||
plt.title('%s, P Weight=%d, SNR=None, '
|
|
||||||
'SNRdB=None' % (tr_filt.stats.channel, Pweight))
|
'SNRdB=None' % (tr_filt.stats.channel, Pweight))
|
||||||
else:
|
else:
|
||||||
plt.title('%s, %s, P Weight=%d' % (tr_filt.stats.station,
|
ax1.set_title('%s, %s, P Weight=%d' % (tr_filt.stats.station,
|
||||||
tr_filt.stats.channel,
|
tr_filt.stats.channel,
|
||||||
Pweight))
|
Pweight))
|
||||||
|
ax1.legend(loc=1)
|
||||||
plt.yticks([])
|
ax1.set_yticks([])
|
||||||
plt.ylim([-1.5, 1.5])
|
ax1.set_ylim([-1.5, 1.5])
|
||||||
plt.ylabel('Normalized Counts')
|
ax1.set_ylabel('Normalized Counts')
|
||||||
plt.suptitle(tr_filt.stats.starttime)
|
# fig.suptitle(tr_filt.stats.starttime)
|
||||||
|
try:
|
||||||
|
len(edat[0])
|
||||||
|
except:
|
||||||
|
edat = ndat
|
||||||
|
try:
|
||||||
|
len(ndat[0])
|
||||||
|
except:
|
||||||
|
ndat = edat
|
||||||
if len(edat[0]) > 1 and len(ndat[0]) > 1 and Sflag == 1:
|
if len(edat[0]) > 1 and len(ndat[0]) > 1 and Sflag == 1:
|
||||||
# plot horizontal traces
|
# plot horizontal traces
|
||||||
plt.subplot(3, 1, 2)
|
ax2 = fig.add_subplot(3, 1, 2, sharex=ax1)
|
||||||
th1data = np.arange(0,
|
th1data = np.arange(0,
|
||||||
trH1_filt.stats.npts /
|
trH1_filt.stats.npts /
|
||||||
trH1_filt.stats.sampling_rate,
|
trH1_filt.stats.sampling_rate,
|
||||||
@ -651,50 +942,47 @@ def autopickstation(wfstream, pickparam, verbose=False):
|
|||||||
wfldiff = len(trH1_filt.data) - len(th1data)
|
wfldiff = len(trH1_filt.data) - len(th1data)
|
||||||
if wfldiff < 0:
|
if wfldiff < 0:
|
||||||
th1data = th1data[0:len(th1data) - abs(wfldiff)]
|
th1data = th1data[0:len(th1data) - abs(wfldiff)]
|
||||||
p21, = plt.plot(th1data, trH1_filt.data / max(trH1_filt.data), 'k')
|
ax2.plot(th1data, trH1_filt.data / max(trH1_filt.data), color=linecolor, linewidth=0.7, label='Data')
|
||||||
if Pweight < 4:
|
if Pweight < 4:
|
||||||
p22, = plt.plot(arhcf1.getTimeArray(),
|
ax2.plot(arhcf1.getTimeArray(),
|
||||||
arhcf1.getCF() / max(arhcf1.getCF()), 'b')
|
arhcf1.getCF() / max(arhcf1.getCF()), 'b', label='CF1')
|
||||||
if aicSflag == 1:
|
if aicSflag == 1 and Sweight < 4:
|
||||||
p23, = plt.plot(arhcf2.getTimeArray(),
|
ax2.plot(arhcf2.getTimeArray(),
|
||||||
arhcf2.getCF() / max(arhcf2.getCF()), 'm')
|
arhcf2.getCF() / max(arhcf2.getCF()), 'm', label='CF2')
|
||||||
p24, = plt.plot(
|
ax2.plot(
|
||||||
[aicarhpick.getpick(), aicarhpick.getpick()],
|
[aicarhpick.getpick(), aicarhpick.getpick()],
|
||||||
[-1, 1], 'g')
|
[-1, 1], 'g', label='Initial S Onset')
|
||||||
plt.plot(
|
ax2.plot(
|
||||||
[aicarhpick.getpick() - 0.5,
|
[aicarhpick.getpick() - 0.5,
|
||||||
aicarhpick.getpick() + 0.5],
|
aicarhpick.getpick() + 0.5],
|
||||||
[1, 1], 'g')
|
[1, 1], 'g')
|
||||||
plt.plot(
|
ax2.plot(
|
||||||
[aicarhpick.getpick() - 0.5,
|
[aicarhpick.getpick() - 0.5,
|
||||||
aicarhpick.getpick() + 0.5],
|
aicarhpick.getpick() + 0.5],
|
||||||
[-1, -1], 'g')
|
[-1, -1], 'g')
|
||||||
p25, = plt.plot([refSpick.getpick(), refSpick.getpick()],
|
ax2.plot([refSpick.getpick(), refSpick.getpick()],
|
||||||
[-1.3, 1.3], 'g', linewidth=2)
|
[-1.3, 1.3], 'g', linewidth=2, label='Final S Pick')
|
||||||
plt.plot(
|
ax2.plot(
|
||||||
[refSpick.getpick() - 0.5, refSpick.getpick() + 0.5],
|
[refSpick.getpick() - 0.5, refSpick.getpick() + 0.5],
|
||||||
[1.3, 1.3], 'g', linewidth=2)
|
[1.3, 1.3], 'g', linewidth=2)
|
||||||
plt.plot(
|
ax2.plot(
|
||||||
[refSpick.getpick() - 0.5, refSpick.getpick() + 0.5],
|
[refSpick.getpick() - 0.5, refSpick.getpick() + 0.5],
|
||||||
[-1.3, -1.3], 'g', linewidth=2)
|
[-1.3, -1.3], 'g', linewidth=2)
|
||||||
plt.plot([lpickS, lpickS], [-1.1, 1.1], 'g--')
|
ax2.plot([lpickS, lpickS], [-1.1, 1.1], 'g--', label='lpp')
|
||||||
plt.plot([epickS, epickS], [-1.1, 1.1], 'g--')
|
ax2.plot([epickS, epickS], [-1.1, 1.1], 'g--', label='epp')
|
||||||
plt.legend([p21, p22, p23, p24, p25],
|
ax2.set_title('%s, S Weight=%d, SNR=%7.2f, SNR[dB]=%7.2f' % (
|
||||||
['Data', 'CF1', 'CF2', 'Initial S Onset',
|
|
||||||
'Final S Pick'])
|
|
||||||
plt.title('%s, S Weight=%d, SNR=%7.2f, SNR[dB]=%7.2f' % (
|
|
||||||
trH1_filt.stats.channel,
|
trH1_filt.stats.channel,
|
||||||
Sweight, SNRS, SNRSdB))
|
Sweight, SNRS, SNRSdB))
|
||||||
else:
|
else:
|
||||||
plt.legend([p21, p22], ['Data', 'CF1'])
|
ax2.set_title('%s, S Weight=%d, SNR=None, SNRdB=None' % (
|
||||||
plt.title('%s, S Weight=%d, SNR=None, SNRdB=None' % (
|
|
||||||
trH1_filt.stats.channel, Sweight))
|
trH1_filt.stats.channel, Sweight))
|
||||||
plt.yticks([])
|
ax2.legend(loc=1)
|
||||||
plt.ylim([-1.5, 1.5])
|
ax2.set_yticks([])
|
||||||
plt.ylabel('Normalized Counts')
|
ax2.set_ylim([-1.5, 1.5])
|
||||||
plt.suptitle(trH1_filt.stats.starttime)
|
ax2.set_ylabel('Normalized Counts')
|
||||||
|
# fig.suptitle(trH1_filt.stats.starttime)
|
||||||
|
|
||||||
plt.subplot(3, 1, 3)
|
ax3 = fig.add_subplot(3, 1, 3, sharex=ax1)
|
||||||
th2data = np.arange(0,
|
th2data = np.arange(0,
|
||||||
trH2_filt.stats.npts /
|
trH2_filt.stats.npts /
|
||||||
trH2_filt.stats.sampling_rate,
|
trH2_filt.stats.sampling_rate,
|
||||||
@ -703,53 +991,51 @@ def autopickstation(wfstream, pickparam, verbose=False):
|
|||||||
wfldiff = len(trH2_filt.data) - len(th2data)
|
wfldiff = len(trH2_filt.data) - len(th2data)
|
||||||
if wfldiff < 0:
|
if wfldiff < 0:
|
||||||
th2data = th2data[0:len(th2data) - abs(wfldiff)]
|
th2data = th2data[0:len(th2data) - abs(wfldiff)]
|
||||||
plt.plot(th2data, trH2_filt.data / max(trH2_filt.data), 'k')
|
ax3.plot(th2data, trH2_filt.data / max(trH2_filt.data), color=linecolor, linewidth=0.7, label='Data')
|
||||||
if Pweight < 4:
|
if Pweight < 4:
|
||||||
p22, = plt.plot(arhcf1.getTimeArray(),
|
p22, = ax3.plot(arhcf1.getTimeArray(),
|
||||||
arhcf1.getCF() / max(arhcf1.getCF()), 'b')
|
arhcf1.getCF() / max(arhcf1.getCF()), 'b', label='CF1')
|
||||||
if aicSflag == 1:
|
if aicSflag == 1:
|
||||||
p23, = plt.plot(arhcf2.getTimeArray(),
|
ax3.plot(arhcf2.getTimeArray(),
|
||||||
arhcf2.getCF() / max(arhcf2.getCF()), 'm')
|
arhcf2.getCF() / max(arhcf2.getCF()), 'm', label='CF2')
|
||||||
p24, = plt.plot(
|
ax3.plot(
|
||||||
[aicarhpick.getpick(), aicarhpick.getpick()],
|
[aicarhpick.getpick(), aicarhpick.getpick()],
|
||||||
[-1, 1], 'g')
|
[-1, 1], 'g', label='Initial S Onset')
|
||||||
plt.plot(
|
ax3.plot(
|
||||||
[aicarhpick.getpick() - 0.5,
|
[aicarhpick.getpick() - 0.5,
|
||||||
aicarhpick.getpick() + 0.5],
|
aicarhpick.getpick() + 0.5],
|
||||||
[1, 1], 'g')
|
[1, 1], 'g')
|
||||||
plt.plot(
|
ax3.plot(
|
||||||
[aicarhpick.getpick() - 0.5,
|
[aicarhpick.getpick() - 0.5,
|
||||||
aicarhpick.getpick() + 0.5],
|
aicarhpick.getpick() + 0.5],
|
||||||
[-1, -1], 'g')
|
[-1, -1], 'g')
|
||||||
p25, = plt.plot([refSpick.getpick(), refSpick.getpick()],
|
ax3.plot([refSpick.getpick(), refSpick.getpick()],
|
||||||
[-1.3, 1.3], 'g', linewidth=2)
|
[-1.3, 1.3], 'g', linewidth=2, label='Final S Pick')
|
||||||
plt.plot(
|
ax3.plot(
|
||||||
[refSpick.getpick() - 0.5, refSpick.getpick() + 0.5],
|
[refSpick.getpick() - 0.5, refSpick.getpick() + 0.5],
|
||||||
[1.3, 1.3], 'g', linewidth=2)
|
[1.3, 1.3], 'g', linewidth=2)
|
||||||
plt.plot(
|
ax3.plot(
|
||||||
[refSpick.getpick() - 0.5, refSpick.getpick() + 0.5],
|
[refSpick.getpick() - 0.5, refSpick.getpick() + 0.5],
|
||||||
[-1.3, -1.3], 'g', linewidth=2)
|
[-1.3, -1.3], 'g', linewidth=2)
|
||||||
plt.plot([lpickS, lpickS], [-1.1, 1.1], 'g--')
|
ax3.plot([lpickS, lpickS], [-1.1, 1.1], 'g--', label='lpp')
|
||||||
plt.plot([epickS, epickS], [-1.1, 1.1], 'g--')
|
ax3.plot([epickS, epickS], [-1.1, 1.1], 'g--', label='epp')
|
||||||
plt.legend([p21, p22, p23, p24, p25],
|
ax3.legend(loc=1)
|
||||||
['Data', 'CF1', 'CF2', 'Initial S Onset',
|
ax3.set_yticks([])
|
||||||
'Final S Pick'])
|
ax3.set_ylim([-1.5, 1.5])
|
||||||
else:
|
ax3.set_xlabel('Time [s] after %s' % tr_filt.stats.starttime)
|
||||||
plt.legend([p21, p22], ['Data', 'CF1'])
|
ax3.set_ylabel('Normalized Counts')
|
||||||
plt.yticks([])
|
ax3.set_title(trH2_filt.stats.channel)
|
||||||
plt.ylim([-1.5, 1.5])
|
if plt_flag == 1:
|
||||||
plt.xlabel('Time [s] after %s' % tr_filt.stats.starttime)
|
fig.show()
|
||||||
plt.ylabel('Normalized Counts')
|
try: input()
|
||||||
plt.title(trH2_filt.stats.channel)
|
except SyntaxError: pass
|
||||||
plt.show()
|
plt.close(fig)
|
||||||
raw_input()
|
|
||||||
plt.close()
|
|
||||||
##########################################################################
|
##########################################################################
|
||||||
# calculate "real" onset times
|
# calculate "real" onset times
|
||||||
if lpickP is not None and lpickP == mpickP:
|
if lpickP is not None and lpickP == mpickP:
|
||||||
lpickP += timeerrorsP[0]
|
lpickP += zdat[0].stats.delta
|
||||||
if epickP is not None and epickP == mpickP:
|
if epickP is not None and epickP == mpickP:
|
||||||
epickP -= timeerrorsP[0]
|
epickP -= zdat[0].stats.delta
|
||||||
if mpickP is not None and epickP is not None and lpickP is not None:
|
if mpickP is not None and epickP is not None and lpickP is not None:
|
||||||
lpickP = zdat[0].stats.starttime + lpickP
|
lpickP = zdat[0].stats.starttime + lpickP
|
||||||
epickP = zdat[0].stats.starttime + epickP
|
epickP = zdat[0].stats.starttime + epickP
|
||||||
@ -761,35 +1047,46 @@ def autopickstation(wfstream, pickparam, verbose=False):
|
|||||||
epickP = zdat[0].stats.starttime - timeerrorsP[3]
|
epickP = zdat[0].stats.starttime - timeerrorsP[3]
|
||||||
mpickP = zdat[0].stats.starttime
|
mpickP = zdat[0].stats.starttime
|
||||||
|
|
||||||
|
if edat:
|
||||||
|
hdat = edat[0]
|
||||||
|
elif ndat:
|
||||||
|
hdat = ndat[0]
|
||||||
|
else:
|
||||||
|
return
|
||||||
|
|
||||||
if lpickS is not None and lpickS == mpickS:
|
if lpickS is not None and lpickS == mpickS:
|
||||||
lpickS += timeerrorsS[0]
|
lpickS += hdat.stats.delta
|
||||||
if epickS is not None and epickS == mpickS:
|
if epickS is not None and epickS == mpickS:
|
||||||
epickS -= timeerrorsS[0]
|
epickS -= hdat.stats.delta
|
||||||
if mpickS is not None and epickS is not None and lpickS is not None:
|
if mpickS is not None and epickS is not None and lpickS is not None:
|
||||||
lpickS = edat[0].stats.starttime + lpickS
|
lpickS = hdat.stats.starttime + lpickS
|
||||||
epickS = edat[0].stats.starttime + epickS
|
epickS = hdat.stats.starttime + epickS
|
||||||
mpickS = edat[0].stats.starttime + mpickS
|
mpickS = hdat.stats.starttime + mpickS
|
||||||
else:
|
else:
|
||||||
# dummy values (start of seismic trace) in order to derive
|
# dummy values (start of seismic trace) in order to derive
|
||||||
# theoretical onset times for iteratve picking
|
# theoretical onset times for iteratve picking
|
||||||
lpickS = edat[0].stats.starttime + timeerrorsS[3]
|
lpickS = hdat.stats.starttime + timeerrorsS[3]
|
||||||
epickS = edat[0].stats.starttime - timeerrorsS[3]
|
epickS = hdat.stats.starttime - timeerrorsS[3]
|
||||||
mpickS = edat[0].stats.starttime
|
mpickS = hdat.stats.starttime
|
||||||
|
|
||||||
# create dictionary
|
# create dictionary
|
||||||
# for P phase
|
# 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,
|
snrdb=SNRPdB, weight=Pweight, fm=FM, w0=None, fc=None, Mo=None,
|
||||||
Mw=None, picker=picker, marked=Pmarker)
|
Mw=None, picker=picker, marked=Pmarker)
|
||||||
# add S phase
|
# add S phase
|
||||||
spick = dict(lpp=lpickS, epp=epickS, mpp=mpickS, spe=Serror, snr=SNRS,
|
ccode = hdat.stats.channel
|
||||||
|
ncode = hdat.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)
|
snrdb=SNRSdB, weight=Sweight, fm=None, picker=picker, Ao=Ao)
|
||||||
# merge picks into returning dictionary
|
# merge picks into returning dictionary
|
||||||
picks = dict(P=ppick, S=spick)
|
picks = dict(P=ppick, S=spick, station=zdat[0].stats.station)
|
||||||
return picks
|
return picks
|
||||||
|
|
||||||
|
|
||||||
def iteratepicker(wf, NLLocfile, picks, badpicks, pickparameter):
|
def iteratepicker(wf, NLLocfile, picks, badpicks, pickparameter, fig_dict=None):
|
||||||
'''
|
'''
|
||||||
Repicking of bad onsets. Uses theoretical onset times from NLLoc-location file.
|
Repicking of bad onsets. Uses theoretical onset times from NLLoc-location file.
|
||||||
|
|
||||||
@ -804,7 +1101,7 @@ def iteratepicker(wf, NLLocfile, picks, badpicks, pickparameter):
|
|||||||
:param pickparameter: picking parameters from autoPyLoT-input file
|
:param pickparameter: picking parameters from autoPyLoT-input file
|
||||||
'''
|
'''
|
||||||
|
|
||||||
msg = '#######################################################\n' \
|
msg = '##################################################\n' \
|
||||||
'autoPyLoT: Found {0} bad onsets at station(s) {1}, ' \
|
'autoPyLoT: Found {0} bad onsets at station(s) {1}, ' \
|
||||||
'starting re-picking them ...'.format(len(badpicks), badpicks)
|
'starting re-picking them ...'.format(len(badpicks), badpicks)
|
||||||
print(msg)
|
print(msg)
|
||||||
@ -823,7 +1120,7 @@ def iteratepicker(wf, NLLocfile, picks, badpicks, pickparameter):
|
|||||||
badpicks[i][1] = picks[badpicks[i][0]]['P']['mpp'] - float(res)
|
badpicks[i][1] = picks[badpicks[i][0]]['P']['mpp'] - float(res)
|
||||||
|
|
||||||
# get corresponding waveform stream
|
# get corresponding waveform stream
|
||||||
msg = '#######################################################\n' \
|
msg = '##################################################\n' \
|
||||||
'iteratepicker: Re-picking station {0}'.format(badpicks[i][0])
|
'iteratepicker: Re-picking station {0}'.format(badpicks[i][0])
|
||||||
print(msg)
|
print(msg)
|
||||||
wf2pick = wf.select(station=badpicks[i][0])
|
wf2pick = wf.select(station=badpicks[i][0])
|
||||||
@ -836,17 +1133,21 @@ def iteratepicker(wf, NLLocfile, picks, badpicks, pickparameter):
|
|||||||
Precalcwin_old = pickparameter.get('Precalcwin')
|
Precalcwin_old = pickparameter.get('Precalcwin')
|
||||||
noisefactor_old = pickparameter.get('noisefactor')
|
noisefactor_old = pickparameter.get('noisefactor')
|
||||||
zfac_old = pickparameter.get('zfac')
|
zfac_old = pickparameter.get('zfac')
|
||||||
pickparameter.setParam(
|
twindows = pickparameter.get('tsnrz')
|
||||||
pstart=max([0, badpicks[i][1] - wf2pick[0].stats.starttime \
|
tsafety = twindows[1]
|
||||||
- pickparameter.get('tlta')]))
|
pstart = max([0, badpicks[i][1] - wf2pick[0].stats.starttime - pickparameter.get('tlta')])
|
||||||
|
if abs(float(res)) <= tsafety / 2 or pstart == 0:
|
||||||
|
print("iteratepicker: Small residuum, leave parameters unchanged for this phase!")
|
||||||
|
else:
|
||||||
|
pickparameter.setParam(pstart=pstart)
|
||||||
pickparameter.setParam(pstop=pickparameter.get('pstart') + \
|
pickparameter.setParam(pstop=pickparameter.get('pstart') + \
|
||||||
(3 * pickparameter.get('tlta')))
|
(pickparameter.get('Precalcwin')))
|
||||||
pickparameter.setParam(sstop=pickparameter.get('sstop') / 2)
|
pickparameter.setParam(sstop=pickparameter.get('sstop') / 2)
|
||||||
pickparameter.setParam(pickwinP=pickparameter.get('pickwinP') / 2)
|
pickparameter.setParam(pickwinP=pickparameter.get('pickwinP') / 2)
|
||||||
pickparameter.setParam(
|
pickparameter.setParam(Precalcwin=pickparameter.get('Precalcwin') / 2)
|
||||||
Precalcwin=pickparameter.get('Precalcwin') / 2)
|
|
||||||
pickparameter.setParam(noisefactor=1.0)
|
pickparameter.setParam(noisefactor=1.0)
|
||||||
pickparameter.setParam(zfac=1.0)
|
pickparameter.setParam(zfac=1.0)
|
||||||
|
|
||||||
print(
|
print(
|
||||||
"iteratepicker: The following picking parameters have been modified for iterative picking:")
|
"iteratepicker: The following picking parameters have been modified for iterative picking:")
|
||||||
print(
|
print(
|
||||||
@ -864,7 +1165,7 @@ def iteratepicker(wf, NLLocfile, picks, badpicks, pickparameter):
|
|||||||
print("zfac: %f => %f" % (zfac_old, pickparameter.get('zfac')))
|
print("zfac: %f => %f" % (zfac_old, pickparameter.get('zfac')))
|
||||||
|
|
||||||
# repick station
|
# repick station
|
||||||
newpicks = autopickstation(wf2pick, pickparameter)
|
newpicks = autopickstation(wf2pick, pickparameter, fig_dict=fig_dict)
|
||||||
|
|
||||||
# replace old dictionary with new one
|
# replace old dictionary with new one
|
||||||
picks[badpicks[i][0]] = newpicks
|
picks[badpicks[i][0]] = newpicks
|
||||||
|
@ -17,7 +17,6 @@ autoregressive prediction: application ot local and regional distances, Geophys.
|
|||||||
:author: MAGS2 EP3 working group
|
:author: MAGS2 EP3 working group
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import matplotlib.pyplot as plt
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from obspy.core import Stream
|
from obspy.core import Stream
|
||||||
|
|
||||||
@ -27,7 +26,7 @@ class CharacteristicFunction(object):
|
|||||||
SuperClass for different types of characteristic functions.
|
SuperClass for different types of characteristic functions.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
def __init__(self, data, cut, t2=None, order=None, t1=None, fnoise=None, stealthMode=False):
|
def __init__(self, data, cut, t2=None, order=None, t1=None, fnoise=None):
|
||||||
'''
|
'''
|
||||||
Initialize data type object with information from the original
|
Initialize data type object with information from the original
|
||||||
Seismogram.
|
Seismogram.
|
||||||
@ -64,7 +63,6 @@ class CharacteristicFunction(object):
|
|||||||
self.calcCF(self.getDataArray())
|
self.calcCF(self.getDataArray())
|
||||||
self.arpara = np.array([])
|
self.arpara = np.array([])
|
||||||
self.xpred = np.array([])
|
self.xpred = np.array([])
|
||||||
self._stealthMode = stealthMode
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return '''\n\t{name} object:\n
|
return '''\n\t{name} object:\n
|
||||||
@ -138,9 +136,6 @@ class CharacteristicFunction(object):
|
|||||||
def getXCF(self):
|
def getXCF(self):
|
||||||
return self.xcf
|
return self.xcf
|
||||||
|
|
||||||
def _getStealthMode(self):
|
|
||||||
return self._stealthMode()
|
|
||||||
|
|
||||||
def getDataArray(self, cut=None):
|
def getDataArray(self, cut=None):
|
||||||
'''
|
'''
|
||||||
If cut times are given, time series is cut from cut[0] (start time)
|
If cut times are given, time series is cut from cut[0] (start time)
|
||||||
@ -225,13 +220,11 @@ class AICcf(CharacteristicFunction):
|
|||||||
|
|
||||||
def calcCF(self, data):
|
def calcCF(self, data):
|
||||||
|
|
||||||
# if self._getStealthMode() is False:
|
|
||||||
# print 'Calculating AIC ...'
|
|
||||||
x = self.getDataArray()
|
x = self.getDataArray()
|
||||||
xnp = x[0].data
|
xnp = x[0].data
|
||||||
nn = np.isnan(xnp)
|
ind = np.where(~np.isnan(xnp))[0]
|
||||||
if len(nn) > 1:
|
if ind.size:
|
||||||
xnp[nn] = 0
|
xnp[:ind[0]] = xnp[ind[0]]
|
||||||
datlen = len(xnp)
|
datlen = len(xnp)
|
||||||
k = np.arange(1, datlen)
|
k = np.arange(1, datlen)
|
||||||
cf = np.zeros(datlen)
|
cf = np.zeros(datlen)
|
||||||
@ -265,13 +258,9 @@ class HOScf(CharacteristicFunction):
|
|||||||
if len(nn) > 1:
|
if len(nn) > 1:
|
||||||
xnp[nn] = 0
|
xnp[nn] = 0
|
||||||
if self.getOrder() == 3: # this is skewness
|
if self.getOrder() == 3: # this is skewness
|
||||||
# if self._getStealthMode() is False:
|
|
||||||
# print 'Calculating skewness ...'
|
|
||||||
y = np.power(xnp, 3)
|
y = np.power(xnp, 3)
|
||||||
y1 = np.power(xnp, 2)
|
y1 = np.power(xnp, 2)
|
||||||
elif self.getOrder() == 4: # this is kurtosis
|
elif self.getOrder() == 4: # this is kurtosis
|
||||||
# if self._getStealthMode() is False:
|
|
||||||
# print 'Calculating kurtosis ...'
|
|
||||||
y = np.power(xnp, 4)
|
y = np.power(xnp, 4)
|
||||||
y1 = np.power(xnp, 2)
|
y1 = np.power(xnp, 2)
|
||||||
|
|
||||||
@ -297,9 +286,12 @@ class HOScf(CharacteristicFunction):
|
|||||||
elif self.getOrder() == 4:
|
elif self.getOrder() == 4:
|
||||||
LTA[j] = lta / np.power(lta1, 2)
|
LTA[j] = lta / np.power(lta1, 2)
|
||||||
|
|
||||||
nn = np.isnan(LTA)
|
# remove NaN's with first not-NaN-value,
|
||||||
if len(nn) > 1:
|
# so autopicker doesnt pick discontinuity at start of the trace
|
||||||
LTA[nn] = 0
|
ind = np.where(~np.isnan(LTA))[0]
|
||||||
|
if ind.size:
|
||||||
|
first = ind[0]
|
||||||
|
LTA[:first] = LTA[first]
|
||||||
self.cf = LTA
|
self.cf = LTA
|
||||||
self.xcf = x
|
self.xcf = x
|
||||||
|
|
||||||
@ -307,7 +299,7 @@ class HOScf(CharacteristicFunction):
|
|||||||
class ARZcf(CharacteristicFunction):
|
class ARZcf(CharacteristicFunction):
|
||||||
def calcCF(self, data):
|
def calcCF(self, data):
|
||||||
|
|
||||||
print 'Calculating AR-prediction error from single trace ...'
|
print('Calculating AR-prediction error from single trace ...')
|
||||||
x = self.getDataArray(self.getCut())
|
x = self.getDataArray(self.getCut())
|
||||||
xnp = x[0].data
|
xnp = x[0].data
|
||||||
nn = np.isnan(xnp)
|
nn = np.isnan(xnp)
|
||||||
@ -343,6 +335,7 @@ class ARZcf(CharacteristicFunction):
|
|||||||
cf = tap * cf
|
cf = tap * cf
|
||||||
io = np.where(cf == 0)
|
io = np.where(cf == 0)
|
||||||
ino = np.where(cf > 0)
|
ino = np.where(cf > 0)
|
||||||
|
if np.size(ino):
|
||||||
cf[io] = cf[ino[0][0]]
|
cf[io] = cf[ino[0][0]]
|
||||||
|
|
||||||
self.cf = cf
|
self.cf = cf
|
||||||
@ -430,7 +423,7 @@ class ARZcf(CharacteristicFunction):
|
|||||||
class ARHcf(CharacteristicFunction):
|
class ARHcf(CharacteristicFunction):
|
||||||
def calcCF(self, data):
|
def calcCF(self, data):
|
||||||
|
|
||||||
print 'Calculating AR-prediction error from both horizontal traces ...'
|
print('Calculating AR-prediction error from both horizontal traces ...')
|
||||||
|
|
||||||
xnp = self.getDataArray(self.getCut())
|
xnp = self.getDataArray(self.getCut())
|
||||||
n0 = np.isnan(xnp[0].data)
|
n0 = np.isnan(xnp[0].data)
|
||||||
@ -475,6 +468,7 @@ class ARHcf(CharacteristicFunction):
|
|||||||
cf = tap * cf
|
cf = tap * cf
|
||||||
io = np.where(cf == 0)
|
io = np.where(cf == 0)
|
||||||
ino = np.where(cf > 0)
|
ino = np.where(cf > 0)
|
||||||
|
if np.size(ino):
|
||||||
cf[io] = cf[ino[0][0]]
|
cf[io] = cf[ino[0][0]]
|
||||||
|
|
||||||
self.cf = cf
|
self.cf = cf
|
||||||
@ -567,7 +561,7 @@ class ARHcf(CharacteristicFunction):
|
|||||||
class AR3Ccf(CharacteristicFunction):
|
class AR3Ccf(CharacteristicFunction):
|
||||||
def calcCF(self, data):
|
def calcCF(self, data):
|
||||||
|
|
||||||
print 'Calculating AR-prediction error from all 3 components ...'
|
print('Calculating AR-prediction error from all 3 components ...')
|
||||||
|
|
||||||
xnp = self.getDataArray(self.getCut())
|
xnp = self.getDataArray(self.getCut())
|
||||||
n0 = np.isnan(xnp[0].data)
|
n0 = np.isnan(xnp[0].data)
|
||||||
@ -617,6 +611,7 @@ class AR3Ccf(CharacteristicFunction):
|
|||||||
cf = tap * cf
|
cf = tap * cf
|
||||||
io = np.where(cf == 0)
|
io = np.where(cf == 0)
|
||||||
ino = np.where(cf > 0)
|
ino = np.where(cf > 0)
|
||||||
|
if np.size(ino):
|
||||||
cf[io] = cf[ino[0][0]]
|
cf[io] = cf[ino[0][0]]
|
||||||
|
|
||||||
self.cf = cf
|
self.cf = cf
|
||||||
|
@ -4,12 +4,11 @@
|
|||||||
import copy
|
import copy
|
||||||
import operator
|
import operator
|
||||||
import os
|
import os
|
||||||
import numpy as np
|
|
||||||
import glob
|
|
||||||
import matplotlib.pyplot as plt
|
import matplotlib.pyplot as plt
|
||||||
|
import numpy as np
|
||||||
from obspy import read_events
|
from obspy import read_events
|
||||||
|
from obspy.core import AttribDict
|
||||||
from pylot.core.io.phases import picksdict_from_picks
|
from pylot.core.io.phases import picksdict_from_picks
|
||||||
from pylot.core.util.pdf import ProbabilityDensityFunction
|
from pylot.core.util.pdf import ProbabilityDensityFunction
|
||||||
from pylot.core.util.utils import find_in_list
|
from pylot.core.util.utils import find_in_list
|
||||||
@ -28,16 +27,8 @@ class Comparison(object):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
names = list()
|
|
||||||
self._pdfs = dict()
|
self._pdfs = dict()
|
||||||
for name, fn in kwargs.items():
|
names = self.iter_kwargs(kwargs)
|
||||||
if isinstance(fn, PDFDictionary):
|
|
||||||
self._pdfs[name] = fn
|
|
||||||
elif isinstance(fn, dict):
|
|
||||||
self._pdfs[name] = PDFDictionary(fn)
|
|
||||||
else:
|
|
||||||
self._pdfs[name] = PDFDictionary.from_quakeml(fn)
|
|
||||||
names.append(name)
|
|
||||||
if len(names) > 2:
|
if len(names) > 2:
|
||||||
raise ValueError('Comparison is only defined for two '
|
raise ValueError('Comparison is only defined for two '
|
||||||
'arguments!')
|
'arguments!')
|
||||||
@ -49,6 +40,40 @@ class Comparison(object):
|
|||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def iter_kwargs(self, kwargs):
|
||||||
|
names = list()
|
||||||
|
for name, fn in kwargs.items():
|
||||||
|
if name == 'eventlist':
|
||||||
|
names = self.init_by_eventlist(fn)
|
||||||
|
break
|
||||||
|
if isinstance(fn, PDFDictionary):
|
||||||
|
self._pdfs[name] = fn
|
||||||
|
elif isinstance(fn, dict) or isinstance(fn, AttribDict):
|
||||||
|
self._pdfs[name] = PDFDictionary(fn)
|
||||||
|
else:
|
||||||
|
self._pdfs[name] = PDFDictionary.from_quakeml(fn)
|
||||||
|
names.append(name)
|
||||||
|
return names
|
||||||
|
|
||||||
|
def init_by_eventlist(self, eventlist):
|
||||||
|
# create one dictionary containing all picks for all events (therefore modify station key)
|
||||||
|
global_picksdict = {}
|
||||||
|
for event in eventlist:
|
||||||
|
automanu = {'manu': event.pylot_picks,
|
||||||
|
'auto': event.pylot_autopicks}
|
||||||
|
for method, picksdict in automanu.items():
|
||||||
|
if not method in global_picksdict.keys():
|
||||||
|
global_picksdict[method] = {}
|
||||||
|
for station, picks in picksdict.items():
|
||||||
|
new_picksdict = global_picksdict[method]
|
||||||
|
# new id combining event and station in one dictionary for all events
|
||||||
|
id = '{}_{}'.format(event.pylot_id, station)
|
||||||
|
new_picksdict[id] = picks
|
||||||
|
for method, picksdict in global_picksdict.items():
|
||||||
|
self._pdfs[method] = PDFDictionary(picksdict)
|
||||||
|
names = list(global_picksdict.keys())
|
||||||
|
return names
|
||||||
|
|
||||||
def get(self, name):
|
def get(self, name):
|
||||||
return self._pdfs[name]
|
return self._pdfs[name]
|
||||||
|
|
||||||
@ -93,8 +118,8 @@ class Comparison(object):
|
|||||||
"""
|
"""
|
||||||
compare_pdfs = dict()
|
compare_pdfs = dict()
|
||||||
|
|
||||||
pdf_a = self.get(self.names[0]).generate_pdf_data(type)
|
pdf_a = self.get('auto').generate_pdf_data(type)
|
||||||
pdf_b = self.get(self.names[1]).generate_pdf_data(type)
|
pdf_b = self.get('manu').generate_pdf_data(type)
|
||||||
|
|
||||||
for station, phases in pdf_a.items():
|
for station, phases in pdf_a.items():
|
||||||
if station in pdf_b.keys():
|
if station in pdf_b.keys():
|
||||||
@ -155,7 +180,7 @@ class Comparison(object):
|
|||||||
def get_array(self, phase, method_name):
|
def get_array(self, phase, method_name):
|
||||||
method = operator.methodcaller(method_name)
|
method = operator.methodcaller(method_name)
|
||||||
pdf_list = self.get_all(phase)
|
pdf_list = self.get_all(phase)
|
||||||
rarray = map(method, pdf_list)
|
rarray = list(map(method, pdf_list))
|
||||||
return np.array(rarray)
|
return np.array(rarray)
|
||||||
|
|
||||||
def get_expectation_array(self, phase):
|
def get_expectation_array(self, phase):
|
||||||
@ -253,11 +278,7 @@ class PDFDictionary(object):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_quakeml(self, fn):
|
def from_quakeml(self, fn):
|
||||||
cat = read_events(fn)
|
return PDFDictionary(fn)
|
||||||
if len(cat) > 1:
|
|
||||||
raise NotImplementedError('reading more than one event at the same '
|
|
||||||
'time is not implemented yet! Sorry!')
|
|
||||||
return PDFDictionary(picksdict_from_picks(cat[0]))
|
|
||||||
|
|
||||||
def get_all(self, phase):
|
def get_all(self, phase):
|
||||||
rlist = list()
|
rlist = list()
|
||||||
@ -289,7 +310,6 @@ class PDFDictionary(object):
|
|||||||
values['mpp'],
|
values['mpp'],
|
||||||
values['lpp'],
|
values['lpp'],
|
||||||
type=type)
|
type=type)
|
||||||
|
|
||||||
return pdf_picks
|
return pdf_picks
|
||||||
|
|
||||||
def plot(self, stations=None):
|
def plot(self, stations=None):
|
||||||
@ -354,7 +374,6 @@ class PDFstatistics(object):
|
|||||||
Takes a path as argument.
|
Takes a path as argument.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
def __init__(self, directory):
|
def __init__(self, directory):
|
||||||
"""Initiates some values needed when dealing with pdfs later"""
|
"""Initiates some values needed when dealing with pdfs later"""
|
||||||
self._rootdir = directory
|
self._rootdir = directory
|
||||||
@ -482,7 +501,7 @@ def main():
|
|||||||
Insheim = PDFstatistics(root_dir)
|
Insheim = PDFstatistics(root_dir)
|
||||||
Insheim.curphase = 'p'
|
Insheim.curphase = 'p'
|
||||||
qdlist = Insheim.get('qdf', 0.2)
|
qdlist = Insheim.get('qdf', 0.2)
|
||||||
print qdlist
|
print(qdlist)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
@ -19,12 +19,14 @@ calculated after Diehl & Kissling (2009).
|
|||||||
:author: MAGS2 EP3 working group / Ludger Kueperkoch
|
:author: MAGS2 EP3 working group / Ludger Kueperkoch
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import numpy as np
|
|
||||||
import matplotlib.pyplot as plt
|
|
||||||
from pylot.core.pick.utils import getnoisewin, getsignalwin
|
|
||||||
from pylot.core.pick.charfuns import CharacteristicFunction
|
|
||||||
import warnings
|
import warnings
|
||||||
|
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
import numpy as np
|
||||||
|
from scipy.signal import argrelmax
|
||||||
|
from pylot.core.pick.charfuns import CharacteristicFunction
|
||||||
|
from pylot.core.pick.utils import getnoisewin, getsignalwin
|
||||||
|
|
||||||
|
|
||||||
class AutoPicker(object):
|
class AutoPicker(object):
|
||||||
'''
|
'''
|
||||||
@ -34,7 +36,7 @@ class AutoPicker(object):
|
|||||||
|
|
||||||
warnings.simplefilter('ignore')
|
warnings.simplefilter('ignore')
|
||||||
|
|
||||||
def __init__(self, cf, TSNR, PickWindow, iplot=None, aus=None, Tsmooth=None, Pick1=None):
|
def __init__(self, cf, TSNR, PickWindow, iplot=0, aus=None, Tsmooth=None, Pick1=None, fig=None, linecolor='k'):
|
||||||
'''
|
'''
|
||||||
:param: cf, characteristic function, on which the picking algorithm is applied
|
:param: cf, characteristic function, on which the picking algorithm is applied
|
||||||
:type: `~pylot.core.pick.CharFuns.CharacteristicFunction` object
|
:type: `~pylot.core.pick.CharFuns.CharacteristicFunction` object
|
||||||
@ -61,7 +63,8 @@ class AutoPicker(object):
|
|||||||
'''
|
'''
|
||||||
|
|
||||||
assert isinstance(cf, CharacteristicFunction), "%s is not a CharacteristicFunction object" % str(cf)
|
assert isinstance(cf, CharacteristicFunction), "%s is not a CharacteristicFunction object" % str(cf)
|
||||||
|
self._linecolor = linecolor
|
||||||
|
self._pickcolor_p = 'b'
|
||||||
self.cf = cf.getCF()
|
self.cf = cf.getCF()
|
||||||
self.Tcf = cf.getTimeArray()
|
self.Tcf = cf.getTimeArray()
|
||||||
self.Data = cf.getXCF()
|
self.Data = cf.getXCF()
|
||||||
@ -72,6 +75,7 @@ class AutoPicker(object):
|
|||||||
self.setaus(aus)
|
self.setaus(aus)
|
||||||
self.setTsmooth(Tsmooth)
|
self.setTsmooth(Tsmooth)
|
||||||
self.setpick1(Pick1)
|
self.setpick1(Pick1)
|
||||||
|
self.fig = fig
|
||||||
self.calcPick()
|
self.calcPick()
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
@ -152,6 +156,15 @@ class AICPicker(AutoPicker):
|
|||||||
self.Pick = None
|
self.Pick = None
|
||||||
self.slope = None
|
self.slope = None
|
||||||
self.SNR = None
|
self.SNR = None
|
||||||
|
plt_flag = 0
|
||||||
|
try:
|
||||||
|
iplot = int(self.iplot)
|
||||||
|
except:
|
||||||
|
if self.iplot == True or self.iplot == 'True':
|
||||||
|
iplot = 2
|
||||||
|
else:
|
||||||
|
iplot = 0
|
||||||
|
|
||||||
# find NaN's
|
# find NaN's
|
||||||
nn = np.isnan(self.cf)
|
nn = np.isnan(self.cf)
|
||||||
if len(nn) > 1:
|
if len(nn) > 1:
|
||||||
@ -172,21 +185,14 @@ class AICPicker(AutoPicker):
|
|||||||
aicsmooth[i] = aicsmooth[i - 1] + (aic[i] - aic[ii1]) / ismooth
|
aicsmooth[i] = aicsmooth[i - 1] + (aic[i] - aic[ii1]) / ismooth
|
||||||
else:
|
else:
|
||||||
aicsmooth[i] = np.mean(aic[1: i])
|
aicsmooth[i] = np.mean(aic[1: i])
|
||||||
# remove offset
|
# remove offset in AIC function
|
||||||
offset = abs(min(aic) - min(aicsmooth))
|
offset = abs(min(aic) - min(aicsmooth))
|
||||||
aicsmooth = aicsmooth - offset
|
aicsmooth = aicsmooth - offset
|
||||||
# get maximum of 1st derivative of AIC-CF (more stable!) as starting point
|
# get maximum of HOS/AR-CF as startimg point for searching
|
||||||
diffcf = np.diff(aicsmooth)
|
# minimum in AIC function
|
||||||
# find NaN's
|
icfmax = np.argmax(self.Data[0].data)
|
||||||
nn = np.isnan(diffcf)
|
|
||||||
if len(nn) > 1:
|
|
||||||
diffcf[nn] = 0
|
|
||||||
# taper CF to get rid off side maxima
|
|
||||||
tap = np.hanning(len(diffcf))
|
|
||||||
diffcf = tap * diffcf * max(abs(aicsmooth))
|
|
||||||
icfmax = np.argmax(diffcf)
|
|
||||||
|
|
||||||
# find minimum in AIC-CF front of maximum
|
# find minimum in AIC-CF front of maximum of HOS/AR-CF
|
||||||
lpickwindow = int(round(self.PickWindow / self.dt))
|
lpickwindow = int(round(self.PickWindow / self.dt))
|
||||||
for i in range(icfmax - 1, max([icfmax - lpickwindow, 2]), -1):
|
for i in range(icfmax - 1, max([icfmax - lpickwindow, 2]), -1):
|
||||||
if aicsmooth[i - 1] >= aicsmooth[i]:
|
if aicsmooth[i - 1] >= aicsmooth[i]:
|
||||||
@ -195,6 +201,14 @@ class AICPicker(AutoPicker):
|
|||||||
# if no minimum could be found:
|
# if no minimum could be found:
|
||||||
# search in 1st derivative of AIC-CF
|
# search in 1st derivative of AIC-CF
|
||||||
if self.Pick is None:
|
if self.Pick is None:
|
||||||
|
diffcf = np.diff(aicsmooth)
|
||||||
|
# find NaN's
|
||||||
|
nn = np.isnan(diffcf)
|
||||||
|
if len(nn) > 1:
|
||||||
|
diffcf[nn] = 0
|
||||||
|
# taper CF to get rid off side maxima
|
||||||
|
tap = np.hanning(len(diffcf))
|
||||||
|
diffcf = tap * diffcf * max(abs(aicsmooth))
|
||||||
for i in range(icfmax - 1, max([icfmax - lpickwindow, 2]), -1):
|
for i in range(icfmax - 1, max([icfmax - lpickwindow, 2]), -1):
|
||||||
if diffcf[i - 1] >= diffcf[i]:
|
if diffcf[i - 1] >= diffcf[i]:
|
||||||
self.Pick = self.Tcf[i]
|
self.Pick = self.Tcf[i]
|
||||||
@ -206,89 +220,148 @@ class AICPicker(AutoPicker):
|
|||||||
inoise = getnoisewin(self.Tcf, self.Pick, self.TSNR[0], self.TSNR[1])
|
inoise = getnoisewin(self.Tcf, self.Pick, self.TSNR[0], self.TSNR[1])
|
||||||
# check, if these are counts or m/s, important for slope estimation!
|
# check, if these are counts or m/s, important for slope estimation!
|
||||||
# this is quick and dirty, better solution?
|
# this is quick and dirty, better solution?
|
||||||
if max(self.Data[0].data < 1e-3):
|
if max(self.Data[0].data < 1e-3) and max(self.Data[0].data >= 1e-6):
|
||||||
self.Data[0].data = self.Data[0].data * 1000000
|
self.Data[0].data = self.Data[0].data * 1000000.
|
||||||
|
elif max(self.Data[0].data < 1e-6):
|
||||||
|
self.Data[0].data = self.Data[0].data * 1e13
|
||||||
# get signal window
|
# get signal window
|
||||||
isignal = getsignalwin(self.Tcf, self.Pick, self.TSNR[2])
|
isignal = getsignalwin(self.Tcf, self.Pick, self.TSNR[2])
|
||||||
|
if len(isignal) == 0:
|
||||||
|
return
|
||||||
|
ii = min([isignal[len(isignal) - 1], len(self.Tcf)])
|
||||||
|
isignal = isignal[0:ii]
|
||||||
|
try:
|
||||||
|
self.Data[0].data[isignal]
|
||||||
|
except IndexError as e:
|
||||||
|
msg = "Time series out of bounds! {}".format(e)
|
||||||
|
print(msg)
|
||||||
|
return
|
||||||
# calculate SNR from CF
|
# calculate SNR from CF
|
||||||
self.SNR = max(abs(aic[isignal] - np.mean(aic[isignal]))) / \
|
self.SNR = max(abs(self.Data[0].data[isignal] - np.mean(self.Data[0].data[isignal]))) / \
|
||||||
max(abs(aic[inoise] - np.mean(aic[inoise])))
|
max(abs(self.Data[0].data[inoise] - np.mean(self.Data[0].data[inoise])))
|
||||||
# calculate slope from CF after initial pick
|
# calculate slope from CF after initial pick
|
||||||
# get slope window
|
# get slope window
|
||||||
tslope = self.TSNR[3] # slope determination window
|
tslope = self.TSNR[3] # slope determination window
|
||||||
islope = np.where((self.Tcf <= min([self.Pick + tslope, len(self.Data[0].data)])) \
|
islope = np.where((self.Tcf <= min([self.Pick + tslope, self.Tcf[-1]])) \
|
||||||
& (self.Tcf >= self.Pick))
|
& (self.Tcf >= self.Pick)) # TODO: put this in a seperate function like getsignalwin
|
||||||
# find maximum within slope determination window
|
# find maximum within slope determination window
|
||||||
# 'cause slope should be calculated up to first local minimum only!
|
# 'cause slope should be calculated up to first local minimum only!
|
||||||
imax = np.argmax(self.Data[0].data[islope])
|
try:
|
||||||
if imax == 0:
|
dataslope = self.Data[0].data[islope[0][0:-1]]
|
||||||
print('AICPicker: Maximum for slope determination right at the beginning of the window!')
|
except IndexError:
|
||||||
print('Choose longer slope determination window!')
|
print("Slope Calculation: empty array islope, check signal window")
|
||||||
if self.iplot > 1:
|
|
||||||
p = plt.figure(self.iplot)
|
|
||||||
x = self.Data[0].data
|
|
||||||
p1, = plt.plot(self.Tcf, x / max(x), 'k')
|
|
||||||
p2, = plt.plot(self.Tcf, aicsmooth / max(aicsmooth), 'r')
|
|
||||||
plt.legend([p1, p2], ['(HOS-/AR-) Data', 'Smoothed AIC-CF'])
|
|
||||||
plt.xlabel('Time [s] since %s' % self.Data[0].stats.starttime)
|
|
||||||
plt.yticks([])
|
|
||||||
plt.title(self.Data[0].stats.station)
|
|
||||||
plt.show()
|
|
||||||
raw_input()
|
|
||||||
plt.close(p)
|
|
||||||
return
|
return
|
||||||
islope = islope[0][0:imax]
|
if len(dataslope) < 1:
|
||||||
dataslope = self.Data[0].data[islope]
|
print('No data in slope window found!')
|
||||||
|
return
|
||||||
|
imaxs, = argrelmax(dataslope)
|
||||||
|
if imaxs.size:
|
||||||
|
imax = imaxs[0]
|
||||||
|
else:
|
||||||
|
imax = np.argmax(dataslope)
|
||||||
|
iislope = islope[0][0:imax + 1]
|
||||||
|
if len(iislope) < 2:
|
||||||
|
# calculate slope from initial onset to maximum of AIC function
|
||||||
|
print("AICPicker: Not enough data samples left for slope calculation!")
|
||||||
|
print("Calculating slope from initial onset to maximum of AIC function ...")
|
||||||
|
imax = np.argmax(aicsmooth[islope[0][0:-1]])
|
||||||
|
if imax == 0:
|
||||||
|
print("AICPicker: Maximum for slope determination right at the beginning of the window!")
|
||||||
|
print("Choose longer slope determination window!")
|
||||||
|
if self.iplot > 1:
|
||||||
|
if self.fig == None or self.fig == 'None':
|
||||||
|
fig = plt.figure()
|
||||||
|
plt_flag = 1
|
||||||
|
else:
|
||||||
|
fig = self.fig
|
||||||
|
ax = fig.add_subplot(111)
|
||||||
|
x = self.Data[0].data
|
||||||
|
ax.plot(self.Tcf, x / max(x), color=self._linecolor, linewidth=0.7, label='(HOS-/AR-) Data')
|
||||||
|
ax.plot(self.Tcf, aicsmooth / max(aicsmooth), 'r', label='Smoothed AIC-CF')
|
||||||
|
ax.legend(loc=1)
|
||||||
|
ax.set_xlabel('Time [s] since %s' % self.Data[0].stats.starttime)
|
||||||
|
ax.set_yticks([])
|
||||||
|
ax.set_title(self.Data[0].stats.station)
|
||||||
|
if plt_flag == 1:
|
||||||
|
fig.show()
|
||||||
|
try: input()
|
||||||
|
except SyntaxError: pass
|
||||||
|
plt.close(fig)
|
||||||
|
return
|
||||||
|
iislope = islope[0][0:imax+1]
|
||||||
|
dataslope = self.Data[0].data[iislope]
|
||||||
# calculate slope as polynomal fit of order 1
|
# calculate slope as polynomal fit of order 1
|
||||||
xslope = np.arange(0, len(dataslope), 1)
|
xslope = np.arange(0, len(dataslope), 1)
|
||||||
P = np.polyfit(xslope, dataslope, 1)
|
P = np.polyfit(xslope, dataslope, 1)
|
||||||
datafit = np.polyval(P, xslope)
|
datafit = np.polyval(P, xslope)
|
||||||
if datafit[0] >= datafit[len(datafit) - 1]:
|
if datafit[0] >= datafit[-1]:
|
||||||
print('AICPicker: Negative slope, bad onset skipped!')
|
print('AICPicker: Negative slope, bad onset skipped!')
|
||||||
return
|
return
|
||||||
self.slope = 1 / tslope * (datafit[len(dataslope) - 1] - datafit[0])
|
self.slope = 1 / (len(dataslope) * self.Data[0].stats.delta) * (datafit[-1] - datafit[0])
|
||||||
|
|
||||||
else:
|
else:
|
||||||
self.SNR = None
|
self.SNR = None
|
||||||
self.slope = None
|
self.slope = None
|
||||||
|
|
||||||
if self.iplot > 1:
|
if iplot > 1:
|
||||||
p = plt.figure(self.iplot)
|
if self.fig == None or self.fig == 'None':
|
||||||
x = self.Data[0].data
|
fig = plt.figure() # self.iplot)
|
||||||
p1, = plt.plot(self.Tcf, x / max(x), 'k')
|
plt_flag = 1
|
||||||
p2, = plt.plot(self.Tcf, aicsmooth / max(aicsmooth), 'r')
|
|
||||||
if self.Pick is not None:
|
|
||||||
p3, = plt.plot([self.Pick, self.Pick], [-0.1, 0.5], 'b', linewidth=2)
|
|
||||||
plt.legend([p1, p2, p3], ['(HOS-/AR-) Data', 'Smoothed AIC-CF', 'AIC-Pick'])
|
|
||||||
else:
|
else:
|
||||||
plt.legend([p1, p2], ['(HOS-/AR-) Data', 'Smoothed AIC-CF'])
|
fig = self.fig
|
||||||
plt.xlabel('Time [s] since %s' % self.Data[0].stats.starttime)
|
fig._tight = True
|
||||||
plt.yticks([])
|
ax1 = fig.add_subplot(211)
|
||||||
plt.title(self.Data[0].stats.station)
|
x = self.Data[0].data
|
||||||
|
if len(self.Tcf) > len(self.Data[0].data): # why? LK
|
||||||
|
self.Tcf = self.Tcf[0:len(self.Tcf)-1]
|
||||||
|
ax1.plot(self.Tcf, x / max(x), color=self._linecolor, linewidth=0.7, label='(HOS-/AR-) Data')
|
||||||
|
ax1.plot(self.Tcf, aicsmooth / max(aicsmooth), 'r', label='Smoothed AIC-CF')
|
||||||
|
if self.Pick is not None:
|
||||||
|
ax1.plot([self.Pick, self.Pick], [-0.1, 0.5], 'b', linewidth=2, label='AIC-Pick')
|
||||||
|
ax1.set_xlabel('Time [s] since %s' % self.Data[0].stats.starttime)
|
||||||
|
ax1.set_yticks([])
|
||||||
|
ax1.legend(loc=1)
|
||||||
|
|
||||||
if self.Pick is not None:
|
if self.Pick is not None:
|
||||||
plt.figure(self.iplot + 1)
|
ax2 = fig.add_subplot(2, 1, 2, sharex=ax1)
|
||||||
p11, = plt.plot(self.Tcf, x, 'k')
|
ax2.plot(self.Tcf, x, color=self._linecolor, linewidth=0.7, label='Data')
|
||||||
p12, = plt.plot(self.Tcf[inoise], self.Data[0].data[inoise])
|
ax1.axvspan(self.Tcf[inoise[0]], self.Tcf[inoise[-1]], color='y', alpha=0.2, lw=0, label='Noise Window')
|
||||||
p13, = plt.plot(self.Tcf[isignal], self.Data[0].data[isignal], 'r')
|
ax1.axvspan(self.Tcf[isignal[0]], self.Tcf[isignal[-1]], color='b', alpha=0.2, lw=0,
|
||||||
p14, = plt.plot(self.Tcf[islope], dataslope, 'g--')
|
label='Signal Window')
|
||||||
p15, = plt.plot(self.Tcf[islope], datafit, 'g', linewidth=2)
|
ax1.axvspan(self.Tcf[iislope[0]], self.Tcf[iislope[-1]], color='g', alpha=0.2, lw=0,
|
||||||
plt.legend([p11, p12, p13, p14, p15],
|
label='Slope Window')
|
||||||
['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))
|
|
||||||
plt.xlabel('Time [s] since %s' % self.Data[0].stats.starttime)
|
|
||||||
plt.ylabel('Counts')
|
|
||||||
plt.yticks([])
|
|
||||||
|
|
||||||
plt.show()
|
ax2.axvspan(self.Tcf[inoise[0]], self.Tcf[inoise[-1]], color='y', alpha=0.2, lw=0, label='Noise Window')
|
||||||
raw_input()
|
ax2.axvspan(self.Tcf[isignal[0]], self.Tcf[isignal[-1]], color='b', alpha=0.2, lw=0,
|
||||||
plt.close(p)
|
label='Signal Window')
|
||||||
|
ax2.axvspan(self.Tcf[iislope[0]], self.Tcf[iislope[-1]], color='g', alpha=0.2, lw=0,
|
||||||
|
label='Slope Window')
|
||||||
|
ax2.plot(self.Tcf[iislope], datafit, 'g', linewidth=2, label='Slope')
|
||||||
|
|
||||||
|
ax1.set_title('Station %s, SNR=%7.2f, Slope= %12.2f counts/s' % (self.Data[0].stats.station,
|
||||||
|
self.SNR, self.slope))
|
||||||
|
ax2.set_xlabel('Time [s] since %s' % self.Data[0].stats.starttime)
|
||||||
|
ax2.set_ylabel('Counts')
|
||||||
|
ax2.set_yticks([])
|
||||||
|
ax2.legend(loc=1)
|
||||||
|
if plt_flag == 1:
|
||||||
|
fig.show()
|
||||||
|
try: input()
|
||||||
|
except SyntaxError: pass
|
||||||
|
plt.close(fig)
|
||||||
|
else:
|
||||||
|
ax1.set_title(self.Data[0].stats.station)
|
||||||
|
if plt_flag == 1:
|
||||||
|
fig.show()
|
||||||
|
try: input()
|
||||||
|
except SyntaxError: pass
|
||||||
|
plt.close(fig)
|
||||||
|
|
||||||
if self.Pick == None:
|
if self.Pick == None:
|
||||||
print('AICPicker: Could not find minimum, picking window too short?')
|
print('AICPicker: Could not find minimum, picking window too short?')
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
class PragPicker(AutoPicker):
|
class PragPicker(AutoPicker):
|
||||||
'''
|
'''
|
||||||
@ -297,6 +370,14 @@ class PragPicker(AutoPicker):
|
|||||||
|
|
||||||
def calcPick(self):
|
def calcPick(self):
|
||||||
|
|
||||||
|
try:
|
||||||
|
iplot = int(self.getiplot())
|
||||||
|
except:
|
||||||
|
if self.getiplot() == True or self.getiplot() == 'True':
|
||||||
|
iplot = 2
|
||||||
|
else:
|
||||||
|
iplot = 0
|
||||||
|
|
||||||
if self.getpick1() is not None:
|
if self.getpick1() is not None:
|
||||||
print('PragPicker: Get most likely pick from HOS- or AR-CF using pragmatic picking algorithm ...')
|
print('PragPicker: Get most likely pick from HOS- or AR-CF using pragmatic picking algorithm ...')
|
||||||
|
|
||||||
@ -304,6 +385,7 @@ class PragPicker(AutoPicker):
|
|||||||
self.SNR = None
|
self.SNR = None
|
||||||
self.slope = None
|
self.slope = None
|
||||||
pickflag = 0
|
pickflag = 0
|
||||||
|
plt_flag = 0
|
||||||
# smooth CF
|
# smooth CF
|
||||||
ismooth = int(round(self.Tsmooth / self.dt))
|
ismooth = int(round(self.Tsmooth / self.dt))
|
||||||
cfsmooth = np.zeros(len(self.cf))
|
cfsmooth = np.zeros(len(self.cf))
|
||||||
@ -328,12 +410,19 @@ class PragPicker(AutoPicker):
|
|||||||
ipick1 = np.argmin(abs(self.Tcf - self.getpick1()))
|
ipick1 = np.argmin(abs(self.Tcf - self.getpick1()))
|
||||||
cfpick1 = 2 * self.cf[ipick1]
|
cfpick1 = 2 * self.cf[ipick1]
|
||||||
|
|
||||||
# check trend of CF, i.e. differences of CF and adjust aus regarding this trend
|
# check trend of CF, i.e. differences of CF and adjust aus ("artificial uplift
|
||||||
|
# of picks") regarding this trend
|
||||||
# prominent trend: decrease aus
|
# prominent trend: decrease aus
|
||||||
# flat: use given aus
|
# flat: use given aus
|
||||||
cfdiff = np.diff(cfipick)
|
cfdiff = np.diff(cfipick)
|
||||||
|
if len(cfdiff)<20:
|
||||||
|
print('PragPicker: Very few samples for CF. Check LTA window dimensions!')
|
||||||
i0diff = np.where(cfdiff > 0)
|
i0diff = np.where(cfdiff > 0)
|
||||||
cfdiff = cfdiff[i0diff]
|
cfdiff = cfdiff[i0diff]
|
||||||
|
if len(cfdiff)<1:
|
||||||
|
print('PragPicker: Negative slope for CF. Check LTA window dimensions! STOP')
|
||||||
|
self.Pick = None
|
||||||
|
return
|
||||||
minaus = min(cfdiff * (1 + self.aus))
|
minaus = min(cfdiff * (1 + self.aus))
|
||||||
aus1 = max([minaus, self.aus])
|
aus1 = max([minaus, self.aus])
|
||||||
|
|
||||||
@ -354,6 +443,7 @@ class PragPicker(AutoPicker):
|
|||||||
break
|
break
|
||||||
|
|
||||||
# now we look to the left
|
# now we look to the left
|
||||||
|
if len(self.cf) > ipick1 +1:
|
||||||
for i in range(ipick1, max([ipick1 - lpickwindow + 1, 2]), -1):
|
for i in range(ipick1, max([ipick1 - lpickwindow + 1, 2]), -1):
|
||||||
if self.cf[i + 1] > self.cf[i] and self.cf[i - 1] >= self.cf[i]:
|
if self.cf[i + 1] > self.cf[i] and self.cf[i - 1] >= self.cf[i]:
|
||||||
if cfsmooth[i - 1] * (1 + aus1) >= cfsmooth[i]:
|
if cfsmooth[i - 1] * (1 + aus1) >= cfsmooth[i]:
|
||||||
@ -363,6 +453,10 @@ class PragPicker(AutoPicker):
|
|||||||
flagpick_r = 1
|
flagpick_r = 1
|
||||||
cfpick_l = self.cf[i]
|
cfpick_l = self.cf[i]
|
||||||
break
|
break
|
||||||
|
else:
|
||||||
|
msg ='PragPicker: Initial onset too close to start of CF! \
|
||||||
|
Stop finalizing pick to the left.'
|
||||||
|
print(msg)
|
||||||
|
|
||||||
# now decide which pick: left or right?
|
# now decide which pick: left or right?
|
||||||
if flagpick_l > 0 and flagpick_r > 0 and cfpick_l <= 3 * cfpick_r:
|
if flagpick_l > 0 and flagpick_r > 0 and cfpick_l <= 3 * cfpick_r:
|
||||||
@ -375,25 +469,34 @@ class PragPicker(AutoPicker):
|
|||||||
self.Pick = pick_l
|
self.Pick = pick_l
|
||||||
pickflag = 1
|
pickflag = 1
|
||||||
else:
|
else:
|
||||||
print('PragPicker: Could not find reliable onset!')
|
print("PragPicker: Could not find reliable onset!")
|
||||||
self.Pick = None
|
self.Pick = None
|
||||||
pickflag = 0
|
pickflag = 0
|
||||||
|
|
||||||
if self.getiplot() > 1:
|
if iplot > 1:
|
||||||
p = plt.figure(self.getiplot())
|
if self.fig == None or self.fig == 'None':
|
||||||
p1, = plt.plot(Tcfpick, cfipick, 'k')
|
fig = plt.figure() # self.getiplot())
|
||||||
p2, = plt.plot(Tcfpick, cfsmoothipick, 'r')
|
plt_flag = 1
|
||||||
|
else:
|
||||||
|
fig = self.fig
|
||||||
|
fig._tight = True
|
||||||
|
ax = fig.add_subplot(111)
|
||||||
|
ax.plot(Tcfpick, cfipick, color=self._linecolor, linewidth=0.7, label='CF')
|
||||||
|
ax.plot(Tcfpick, cfsmoothipick, 'r', label='Smoothed CF')
|
||||||
if pickflag > 0:
|
if pickflag > 0:
|
||||||
p3, = plt.plot([self.Pick, self.Pick], [min(cfipick), max(cfipick)], 'b', linewidth=2)
|
ax.plot([self.Pick, self.Pick], [min(cfipick), max(cfipick)], self._pickcolor_p, linewidth=2, label='Pick')
|
||||||
plt.legend([p1, p2, p3], ['CF', 'Smoothed CF', 'Pick'])
|
ax.set_xlabel('Time [s] since %s' % self.Data[0].stats.starttime)
|
||||||
plt.xlabel('Time [s] since %s' % self.Data[0].stats.starttime)
|
ax.set_yticks([])
|
||||||
plt.yticks([])
|
ax.set_title(self.Data[0].stats.station)
|
||||||
plt.title(self.Data[0].stats.station)
|
ax.legend(loc=1)
|
||||||
plt.show()
|
if plt_flag == 1:
|
||||||
raw_input()
|
fig.show()
|
||||||
plt.close(p)
|
try: input()
|
||||||
|
except SyntaxError: pass
|
||||||
|
plt.close(fig)
|
||||||
|
return
|
||||||
|
|
||||||
else:
|
else:
|
||||||
print('PragPicker: No initial onset time given! Check input!')
|
print("PragPicker: No initial onset time given! Check input!")
|
||||||
self.Pick = None
|
self.Pick = None
|
||||||
return
|
return
|
||||||
|
@ -1,12 +1,11 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
"""
|
"""
|
||||||
Created Mar/Apr 2015
|
Created Mar/Apr 2015
|
||||||
Collection of helpful functions for manual and automatic picking.
|
Collection of helpful functions for manual and automatic picking.
|
||||||
|
|
||||||
:author: Ludger Kueperkoch / MAGS2 EP3 working group
|
:author: Ludger Kueperkoch, BESTEC GmbH
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import warnings
|
import warnings
|
||||||
@ -16,7 +15,7 @@ import numpy as np
|
|||||||
from obspy.core import Stream, UTCDateTime
|
from obspy.core import Stream, UTCDateTime
|
||||||
|
|
||||||
|
|
||||||
def earllatepicker(X, nfac, TSNR, Pick1, iplot=None, stealth_mode=False):
|
def earllatepicker(X, nfac, TSNR, Pick1, iplot=0, verbosity=1, fig=None, linecolor='k'):
|
||||||
'''
|
'''
|
||||||
Function to derive earliest and latest possible pick after Diehl & Kissling (2009)
|
Function to derive earliest and latest possible pick after Diehl & Kissling (2009)
|
||||||
as reasonable uncertainties. Latest possible pick is based on noise level,
|
as reasonable uncertainties. Latest possible pick is based on noise level,
|
||||||
@ -42,10 +41,25 @@ def earllatepicker(X, nfac, TSNR, Pick1, iplot=None, stealth_mode=False):
|
|||||||
|
|
||||||
assert isinstance(X, Stream), "%s is not a stream object" % str(X)
|
assert isinstance(X, Stream), "%s is not a stream object" % str(X)
|
||||||
|
|
||||||
|
if verbosity == 2:
|
||||||
|
print('earllatepicker:')
|
||||||
|
print('nfac:', nfac)
|
||||||
|
print('Init pick:', Pick1)
|
||||||
|
print('TSNR (T_noise, T_gap, T_signal):', TSNR)
|
||||||
|
|
||||||
LPick = None
|
LPick = None
|
||||||
EPick = None
|
EPick = None
|
||||||
PickError = None
|
PickError = None
|
||||||
if stealth_mode is False:
|
plt_flag = 0
|
||||||
|
try:
|
||||||
|
iplot = int(iplot)
|
||||||
|
except:
|
||||||
|
if iplot == True or iplot == 'True':
|
||||||
|
iplot = 2
|
||||||
|
else:
|
||||||
|
iplot = 0
|
||||||
|
|
||||||
|
if verbosity:
|
||||||
print('earllatepicker: Get earliest and latest possible pick'
|
print('earllatepicker: Get earliest and latest possible pick'
|
||||||
' relative to most likely pick ...')
|
' relative to most likely pick ...')
|
||||||
|
|
||||||
@ -59,11 +73,18 @@ def earllatepicker(X, nfac, TSNR, Pick1, iplot=None, stealth_mode=False):
|
|||||||
x = x - np.mean(x[inoise])
|
x = x - np.mean(x[inoise])
|
||||||
# calculate noise level
|
# calculate noise level
|
||||||
nlevel = np.sqrt(np.mean(np.square(x[inoise]))) * nfac
|
nlevel = np.sqrt(np.mean(np.square(x[inoise]))) * nfac
|
||||||
|
if verbosity == 2:
|
||||||
|
print('x:', x)
|
||||||
|
print('t:', t)
|
||||||
|
print('x_inoise:', x[inoise])
|
||||||
|
print('x_isignal:', x[isignal])
|
||||||
|
print('nlevel:', nlevel)
|
||||||
|
|
||||||
# get time where signal exceeds nlevel
|
# get time where signal exceeds nlevel
|
||||||
ilup, = np.where(x[isignal] > nlevel)
|
ilup, = np.where(x[isignal] > nlevel)
|
||||||
ildown, = np.where(x[isignal] < -nlevel)
|
ildown, = np.where(x[isignal] < -nlevel)
|
||||||
if not ilup.size and not ildown.size:
|
if not ilup.size and not ildown.size:
|
||||||
if stealth_mode is False:
|
if verbosity:
|
||||||
print("earllatepicker: Signal lower than noise level!\n"
|
print("earllatepicker: Signal lower than noise level!\n"
|
||||||
"Skip this trace!")
|
"Skip this trace!")
|
||||||
return LPick, EPick, PickError
|
return LPick, EPick, PickError
|
||||||
@ -73,14 +94,14 @@ def earllatepicker(X, nfac, TSNR, Pick1, iplot=None, stealth_mode=False):
|
|||||||
|
|
||||||
# get earliest possible pick
|
# get earliest possible pick
|
||||||
|
|
||||||
EPick = np.nan;
|
EPick = np.nan
|
||||||
count = 0
|
count = 0
|
||||||
pis = isignal
|
pis = isignal
|
||||||
|
|
||||||
# if EPick stays NaN the signal window size will be doubled
|
# if EPick stays NaN the signal window size will be doubled
|
||||||
while np.isnan(EPick):
|
while np.isnan(EPick):
|
||||||
if count > 0:
|
if count > 0:
|
||||||
if stealth_mode is False:
|
if verbosity:
|
||||||
print("\nearllatepicker: Doubled signal window size %s time(s) "
|
print("\nearllatepicker: Doubled signal window size %s time(s) "
|
||||||
"because of NaN for earliest pick." % count)
|
"because of NaN for earliest pick." % count)
|
||||||
isigDoubleWinStart = pis[-1] + 1
|
isigDoubleWinStart = pis[-1] + 1
|
||||||
@ -89,7 +110,7 @@ def earllatepicker(X, nfac, TSNR, Pick1, iplot=None, stealth_mode=False):
|
|||||||
if (isigDoubleWinStart + len(pis)) < X[0].data.size:
|
if (isigDoubleWinStart + len(pis)) < X[0].data.size:
|
||||||
pis = np.concatenate((pis, isignalDoubleWin))
|
pis = np.concatenate((pis, isignalDoubleWin))
|
||||||
else:
|
else:
|
||||||
if stealth_mode is False:
|
if verbosity:
|
||||||
print("Could not double signal window. Index out of bounds.")
|
print("Could not double signal window. Index out of bounds.")
|
||||||
break
|
break
|
||||||
count += 1
|
count += 1
|
||||||
@ -106,38 +127,41 @@ def earllatepicker(X, nfac, TSNR, Pick1, iplot=None, stealth_mode=False):
|
|||||||
PickError = symmetrize_error(diffti_te, diffti_tl)
|
PickError = symmetrize_error(diffti_te, diffti_tl)
|
||||||
|
|
||||||
if iplot > 1:
|
if iplot > 1:
|
||||||
p = plt.figure(iplot)
|
if fig == None or fig == 'None':
|
||||||
p1, = plt.plot(t, x, 'k')
|
fig = plt.figure() # iplot)
|
||||||
p2, = plt.plot(t[inoise], x[inoise])
|
plt_flag = 1
|
||||||
p3, = plt.plot(t[isignal], x[isignal], 'r')
|
fig._tight = True
|
||||||
p4, = plt.plot([t[0], t[int(len(t)) - 1]], [nlevel, nlevel], '--k')
|
ax = fig.add_subplot(111)
|
||||||
p5, = plt.plot(t[isignal[zc]], np.zeros(len(zc)), '*g',
|
ax.plot(t, x, color=linecolor, linewidth=0.7, label='Data')
|
||||||
markersize=14)
|
ax.axvspan(t[inoise[0]], t[inoise[-1]], color='y', alpha=0.2, lw=0, label='Noise Window')
|
||||||
plt.legend([p1, p2, p3, p4, p5],
|
ax.axvspan(t[isignal[0]], t[isignal[-1]], color='b', alpha=0.2, lw=0, label='Signal Window')
|
||||||
['Data', 'Noise Window', 'Signal Window', 'Noise Level',
|
ax.plot([t[0], t[int(len(t)) - 1]], [nlevel, nlevel], color=linecolor, linewidth=0.7, linestyle='dashed', label='Noise Level')
|
||||||
'Zero Crossings'],
|
ax.plot(t[pis[zc]], np.zeros(len(zc)), '*g',
|
||||||
loc='best')
|
markersize=14, label='Zero Crossings')
|
||||||
plt.plot([t[0], t[int(len(t)) - 1]], [-nlevel, -nlevel], '--k')
|
ax.plot([t[0], t[int(len(t)) - 1]], [-nlevel, -nlevel], color=linecolor, linewidth=0.7, linestyle='dashed')
|
||||||
plt.plot([Pick1, Pick1], [max(x), -max(x)], 'b', linewidth=2)
|
ax.plot([Pick1, Pick1], [max(x), -max(x)], 'b', linewidth=2, label='mpp')
|
||||||
plt.plot([LPick, LPick], [max(x) / 2, -max(x) / 2], '--k')
|
ax.plot([LPick, LPick], [max(x) / 2, -max(x) / 2], color=linecolor, linewidth=0.7, linestyle='dashed', label='lpp')
|
||||||
plt.plot([EPick, EPick], [max(x) / 2, -max(x) / 2], '--k')
|
ax.plot([EPick, EPick], [max(x) / 2, -max(x) / 2], color=linecolor, linewidth=0.7, linestyle='dashed', label='epp')
|
||||||
plt.plot([Pick1 + PickError, Pick1 + PickError],
|
ax.plot([Pick1 + PickError, Pick1 + PickError],
|
||||||
|
[max(x) / 2, -max(x) / 2], 'r--', label='spe')
|
||||||
|
ax.plot([Pick1 - PickError, Pick1 - PickError],
|
||||||
[max(x) / 2, -max(x) / 2], 'r--')
|
[max(x) / 2, -max(x) / 2], 'r--')
|
||||||
plt.plot([Pick1 - PickError, Pick1 - PickError],
|
ax.set_xlabel('Time [s] since %s' % X[0].stats.starttime)
|
||||||
[max(x) / 2, -max(x) / 2], 'r--')
|
ax.set_yticks([])
|
||||||
plt.xlabel('Time [s] since %s' % X[0].stats.starttime)
|
ax.set_title(
|
||||||
plt.yticks([])
|
|
||||||
plt.title(
|
|
||||||
'Earliest-/Latest Possible/Most Likely Pick & Symmetric Pick Error, %s' %
|
'Earliest-/Latest Possible/Most Likely Pick & Symmetric Pick Error, %s' %
|
||||||
X[0].stats.station)
|
X[0].stats.station)
|
||||||
plt.show()
|
ax.legend(loc=1)
|
||||||
raw_input()
|
if plt_flag == 1:
|
||||||
plt.close(p)
|
fig.show()
|
||||||
|
try: input()
|
||||||
|
except SyntaxError: pass
|
||||||
|
plt.close(fig)
|
||||||
|
|
||||||
return EPick, LPick, PickError
|
return EPick, LPick, PickError
|
||||||
|
|
||||||
|
|
||||||
def fmpicker(Xraw, Xfilt, pickwin, Pick, iplot=None):
|
def fmpicker(Xraw, Xfilt, pickwin, Pick, iplot=0, fig=None, linecolor='k'):
|
||||||
'''
|
'''
|
||||||
Function to derive first motion (polarity) of given phase onset Pick.
|
Function to derive first motion (polarity) of given phase onset Pick.
|
||||||
Calculation is based on zero crossings determined within time window pickwin
|
Calculation is based on zero crossings determined within time window pickwin
|
||||||
@ -159,6 +183,15 @@ def fmpicker(Xraw, Xfilt, pickwin, Pick, iplot=None):
|
|||||||
:type: int
|
:type: int
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
plt_flag = 0
|
||||||
|
try:
|
||||||
|
iplot = int(iplot)
|
||||||
|
except:
|
||||||
|
if iplot == True or iplot == 'True':
|
||||||
|
iplot = 2
|
||||||
|
else:
|
||||||
|
iplot = 0
|
||||||
|
|
||||||
warnings.simplefilter('ignore', np.RankWarning)
|
warnings.simplefilter('ignore', np.RankWarning)
|
||||||
|
|
||||||
assert isinstance(Xraw, Stream), "%s is not a stream object" % str(Xraw)
|
assert isinstance(Xraw, Stream), "%s is not a stream object" % str(Xraw)
|
||||||
@ -173,8 +206,10 @@ def fmpicker(Xraw, Xfilt, pickwin, Pick, iplot=None):
|
|||||||
t = np.arange(0, Xraw[0].stats.npts / Xraw[0].stats.sampling_rate,
|
t = np.arange(0, Xraw[0].stats.npts / Xraw[0].stats.sampling_rate,
|
||||||
Xraw[0].stats.delta)
|
Xraw[0].stats.delta)
|
||||||
# get pick window
|
# get pick window
|
||||||
ipick = np.where(
|
ipick = np.where((t <= min([Pick + pickwin, len(Xraw[0])])) & (t >= Pick))
|
||||||
(t <= min([Pick + pickwin, len(Xraw[0])])) & (t >= Pick))
|
if len(ipick[0]) <= 1:
|
||||||
|
print('fmpicker: Zero crossings window to short!')
|
||||||
|
return
|
||||||
# remove mean
|
# remove mean
|
||||||
xraw[ipick] = xraw[ipick] - np.mean(xraw[ipick])
|
xraw[ipick] = xraw[ipick] - np.mean(xraw[ipick])
|
||||||
xfilt[ipick] = xfilt[ipick] - np.mean(xfilt[ipick])
|
xfilt[ipick] = xfilt[ipick] - np.mean(xfilt[ipick])
|
||||||
@ -197,6 +232,10 @@ def fmpicker(Xraw, Xfilt, pickwin, Pick, iplot=None):
|
|||||||
if len(zc1) == 3:
|
if len(zc1) == 3:
|
||||||
break
|
break
|
||||||
|
|
||||||
|
if len(zc1) < 3:
|
||||||
|
print('fmpicker: Could not determine zero crossings!')
|
||||||
|
return
|
||||||
|
|
||||||
# if time difference betweeen 1st and 2cnd zero crossing
|
# if time difference betweeen 1st and 2cnd zero crossing
|
||||||
# is too short, get time difference between 1st and 3rd
|
# is too short, get time difference between 1st and 3rd
|
||||||
# to derive maximum
|
# to derive maximum
|
||||||
@ -204,7 +243,7 @@ def fmpicker(Xraw, Xfilt, pickwin, Pick, iplot=None):
|
|||||||
li1 = index1[1]
|
li1 = index1[1]
|
||||||
else:
|
else:
|
||||||
li1 = index1[0]
|
li1 = index1[0]
|
||||||
if np.size(xraw[ipick[0][1]:ipick[0][li1]]) == 0:
|
if np.size(xraw[ipick[0][1]:ipick[0][li1]]) == 0 or len(index1) <= 1:
|
||||||
print("fmpicker: Onset on unfiltered trace too emergent for first motion determination!")
|
print("fmpicker: Onset on unfiltered trace too emergent for first motion determination!")
|
||||||
P1 = None
|
P1 = None
|
||||||
else:
|
else:
|
||||||
@ -246,7 +285,7 @@ def fmpicker(Xraw, Xfilt, pickwin, Pick, iplot=None):
|
|||||||
li2 = index2[1]
|
li2 = index2[1]
|
||||||
else:
|
else:
|
||||||
li2 = index2[0]
|
li2 = index2[0]
|
||||||
if np.size(xfilt[ipick[0][1]:ipick[0][li2]]) == 0:
|
if np.size(xfilt[ipick[0][1]:ipick[0][li2]]) == 0 or len(index2) <= 1:
|
||||||
print("fmpicker: Onset on filtered trace too emergent for first motion determination!")
|
print("fmpicker: Onset on filtered trace too emergent for first motion determination!")
|
||||||
P2 = None
|
P2 = None
|
||||||
else:
|
else:
|
||||||
@ -282,39 +321,40 @@ def fmpicker(Xraw, Xfilt, pickwin, Pick, iplot=None):
|
|||||||
print("fmpicker: Found polarity %s" % FM)
|
print("fmpicker: Found polarity %s" % FM)
|
||||||
|
|
||||||
if iplot > 1:
|
if iplot > 1:
|
||||||
plt.figure(iplot)
|
if fig == None or fig == 'None':
|
||||||
plt.subplot(2, 1, 1)
|
fig = plt.figure() # iplot)
|
||||||
plt.plot(t, xraw, 'k')
|
plt_flag = 1
|
||||||
p1, = plt.plot([Pick, Pick], [max(xraw), -max(xraw)], 'b', linewidth=2)
|
fig._tight = True
|
||||||
|
ax1 = fig.add_subplot(211)
|
||||||
|
ax1.plot(t, xraw, color=linecolor, linewidth=0.7)
|
||||||
|
ax1.plot([Pick, Pick], [max(xraw), -max(xraw)], 'b', linewidth=2, label='Pick')
|
||||||
if P1 is not None:
|
if P1 is not None:
|
||||||
p2, = plt.plot(t[islope1], xraw[islope1])
|
ax1.plot(t[islope1], xraw[islope1], label='Slope Window')
|
||||||
p3, = plt.plot(zc1, np.zeros(len(zc1)), '*g', markersize=14)
|
ax1.plot(zc1, np.zeros(len(zc1)), '*g', markersize=14, label='Zero Crossings')
|
||||||
p4, = plt.plot(t[islope1], datafit1, '--g', linewidth=2)
|
ax1.plot(t[islope1], datafit1, '--g', linewidth=2)
|
||||||
plt.legend([p1, p2, p3, p4],
|
ax1.legend(loc=1)
|
||||||
['Pick', 'Slope Window', 'Zero Crossings', 'Slope'],
|
ax1.text(Pick + 0.02, max(xraw) / 2, '%s' % FM, fontsize=14)
|
||||||
loc='best')
|
ax1.set_yticks([])
|
||||||
plt.text(Pick + 0.02, max(xraw) / 2, '%s' % FM, fontsize=14)
|
ax1.set_title('First-Motion Determination, %s, Unfiltered Data' % Xraw[
|
||||||
ax = plt.gca()
|
|
||||||
plt.yticks([])
|
|
||||||
plt.title('First-Motion Determination, %s, Unfiltered Data' % Xraw[
|
|
||||||
0].stats.station)
|
0].stats.station)
|
||||||
|
|
||||||
plt.subplot(2, 1, 2)
|
ax2 = fig.add_subplot(2, 1, 2, sharex=ax1)
|
||||||
plt.title('First-Motion Determination, Filtered Data')
|
ax2.set_title('First-Motion Determination, Filtered Data')
|
||||||
plt.plot(t, xfilt, 'k')
|
ax2.plot(t, xfilt, color=linecolor, linewidth=0.7)
|
||||||
p1, = plt.plot([Pick, Pick], [max(xfilt), -max(xfilt)], 'b',
|
ax2.plot([Pick, Pick], [max(xfilt), -max(xfilt)], 'b',
|
||||||
linewidth=2)
|
linewidth=2)
|
||||||
if P2 is not None:
|
if P2 is not None:
|
||||||
p2, = plt.plot(t[islope2], xfilt[islope2])
|
ax2.plot(t[islope2], xfilt[islope2])
|
||||||
p3, = plt.plot(zc2, np.zeros(len(zc2)), '*g', markersize=14)
|
ax2.plot(zc2, np.zeros(len(zc2)), '*g', markersize=14)
|
||||||
p4, = plt.plot(t[islope2], datafit2, '--g', linewidth=2)
|
ax2.plot(t[islope2], datafit2, '--g', linewidth=2)
|
||||||
plt.text(Pick + 0.02, max(xraw) / 2, '%s' % FM, fontsize=14)
|
ax2.text(Pick + 0.02, max(xraw) / 2, '%s' % FM, fontsize=14)
|
||||||
ax = plt.gca()
|
ax2.set_xlabel('Time [s] since %s' % Xraw[0].stats.starttime)
|
||||||
plt.xlabel('Time [s] since %s' % Xraw[0].stats.starttime)
|
ax2.set_yticks([])
|
||||||
plt.yticks([])
|
if plt_flag == 1:
|
||||||
plt.show()
|
fig.show()
|
||||||
raw_input()
|
try: input()
|
||||||
plt.close(iplot)
|
except SyntaxError: pass
|
||||||
|
plt.close(fig)
|
||||||
|
|
||||||
return FM
|
return FM
|
||||||
|
|
||||||
@ -355,6 +395,10 @@ def getSNR(X, TSNR, t1, tracenum=0):
|
|||||||
|
|
||||||
assert isinstance(X, Stream), "%s is not a stream object" % str(X)
|
assert isinstance(X, Stream), "%s is not a stream object" % str(X)
|
||||||
|
|
||||||
|
SNR = None
|
||||||
|
SNRdB = None
|
||||||
|
noiselevel = None
|
||||||
|
|
||||||
x = X[tracenum].data
|
x = X[tracenum].data
|
||||||
npts = X[tracenum].stats.npts
|
npts = X[tracenum].stats.npts
|
||||||
sr = X[tracenum].stats.sampling_rate
|
sr = X[tracenum].stats.sampling_rate
|
||||||
@ -368,19 +412,20 @@ def getSNR(X, TSNR, t1, tracenum=0):
|
|||||||
isignal = getsignalwin(t, t1, TSNR[2])
|
isignal = getsignalwin(t, t1, TSNR[2])
|
||||||
if np.size(inoise) < 1:
|
if np.size(inoise) < 1:
|
||||||
print("getSNR: Empty array inoise, check noise window!")
|
print("getSNR: Empty array inoise, check noise window!")
|
||||||
return
|
return SNR, SNRdB, noiselevel
|
||||||
elif np.size(isignal) < 1:
|
|
||||||
print ("getSNR: Empty array isignal, check signal window!")
|
|
||||||
return
|
|
||||||
|
|
||||||
# demean over entire waveform
|
# demean over entire waveform
|
||||||
x = x - np.mean(x[inoise])
|
x = x - np.mean(x[inoise])
|
||||||
|
|
||||||
# calculate ratios
|
# calculate ratios
|
||||||
# noiselevel = np.sqrt(np.mean(np.square(x[inoise])))
|
noiselevel = np.sqrt(np.mean(np.square(x[inoise])))
|
||||||
# signallevel = np.sqrt(np.mean(np.square(x[isignal])))
|
# signallevel = np.sqrt(np.mean(np.square(x[isignal])))
|
||||||
|
|
||||||
noiselevel = np.abs(x[inoise]).max()
|
if np.size(isignal) < 1:
|
||||||
|
print("getSNR: Empty array isignal, check signal window!")
|
||||||
|
return SNR, SNRdB, noiselevel
|
||||||
|
|
||||||
|
# noiselevel = np.abs(x[inoise]).max()
|
||||||
signallevel = np.abs(x[isignal]).max()
|
signallevel = np.abs(x[isignal]).max()
|
||||||
|
|
||||||
SNR = signallevel / noiselevel
|
SNR = signallevel / noiselevel
|
||||||
@ -411,6 +456,8 @@ def getnoisewin(t, t1, tnoise, tgap):
|
|||||||
# get noise window
|
# get noise window
|
||||||
inoise, = np.where((t <= max([t1 - tgap, 0])) \
|
inoise, = np.where((t <= max([t1 - tgap, 0])) \
|
||||||
& (t >= max([t1 - tnoise - tgap, 0])))
|
& (t >= max([t1 - tnoise - tgap, 0])))
|
||||||
|
if np.size(inoise) < 1:
|
||||||
|
inoise, = np.where((t >= t[0]) & (t <= t1))
|
||||||
if np.size(inoise) < 1:
|
if np.size(inoise) < 1:
|
||||||
print("getnoisewin: Empty array inoise, check noise window!")
|
print("getnoisewin: Empty array inoise, check noise window!")
|
||||||
|
|
||||||
@ -433,7 +480,7 @@ def getsignalwin(t, t1, tsignal):
|
|||||||
'''
|
'''
|
||||||
|
|
||||||
# get signal window
|
# get signal window
|
||||||
isignal, = np.where((t <= min([t1 + tsignal, len(t)])) \
|
isignal, = np.where((t <= min([t1 + tsignal, t[-1]])) \
|
||||||
& (t >= t1))
|
& (t >= t1))
|
||||||
if np.size(isignal) < 1:
|
if np.size(isignal) < 1:
|
||||||
print("getsignalwin: Empty array isignal, check signal window!")
|
print("getsignalwin: Empty array isignal, check signal window!")
|
||||||
@ -441,7 +488,7 @@ def getsignalwin(t, t1, tsignal):
|
|||||||
return isignal
|
return isignal
|
||||||
|
|
||||||
|
|
||||||
def getResolutionWindow(snr):
|
def getResolutionWindow(snr, extent):
|
||||||
"""
|
"""
|
||||||
Number -> Float
|
Number -> Float
|
||||||
produce the half of the time resolution window width from given SNR
|
produce the half of the time resolution window width from given SNR
|
||||||
@ -452,6 +499,8 @@ def getResolutionWindow(snr):
|
|||||||
1.5 > SNR -> 15 sec VLRW
|
1.5 > SNR -> 15 sec VLRW
|
||||||
see also Diehl et al. 2009
|
see also Diehl et al. 2009
|
||||||
|
|
||||||
|
:parameter: extent, can be 'local', 'regional', 'global'
|
||||||
|
|
||||||
>>> getResolutionWindow(0.5)
|
>>> getResolutionWindow(0.5)
|
||||||
7.5
|
7.5
|
||||||
>>> getResolutionWindow(1.8)
|
>>> getResolutionWindow(1.8)
|
||||||
@ -464,16 +513,23 @@ def getResolutionWindow(snr):
|
|||||||
2.5
|
2.5
|
||||||
"""
|
"""
|
||||||
|
|
||||||
res_wins = {'HRW': 2., 'MRW': 5., 'LRW': 10., 'VLRW': 15.}
|
res_wins = {
|
||||||
|
'regional': {'HRW': 2., 'MRW': 5., 'LRW': 10., 'VLRW': 15.},
|
||||||
|
'local': {'HRW': 2., 'MRW': 5., 'LRW': 10., 'VLRW': 15.},
|
||||||
|
'global': {'HRW': 40., 'MRW': 100., 'LRW': 200., 'VLRW': 300.}
|
||||||
|
}
|
||||||
|
|
||||||
|
if snr:
|
||||||
if snr < 1.5:
|
if snr < 1.5:
|
||||||
time_resolution = res_wins['VLRW']
|
time_resolution = res_wins[extent]['VLRW']
|
||||||
elif snr < 2.:
|
elif snr < 2.:
|
||||||
time_resolution = res_wins['LRW']
|
time_resolution = res_wins[extent]['LRW']
|
||||||
elif snr < 3.:
|
elif snr < 3.:
|
||||||
time_resolution = res_wins['MRW']
|
time_resolution = res_wins[extent]['MRW']
|
||||||
|
elif snr > 3.:
|
||||||
|
time_resolution = res_wins[extent]['HRW']
|
||||||
else:
|
else:
|
||||||
time_resolution = res_wins['HRW']
|
time_resolution = res_wins[extent]['VLRW']
|
||||||
|
|
||||||
return time_resolution / 2
|
return time_resolution / 2
|
||||||
|
|
||||||
@ -490,18 +546,21 @@ def select_for_phase(st, phase):
|
|||||||
:type phase: str
|
:type phase: str
|
||||||
:return:
|
:return:
|
||||||
'''
|
'''
|
||||||
from pylot.core.util.defaults import COMPNAME_MAP
|
from pylot.core.util.defaults import SetChannelComponents
|
||||||
|
|
||||||
sel_st = Stream()
|
sel_st = Stream()
|
||||||
|
compclass = SetChannelComponents()
|
||||||
if phase.upper() == 'P':
|
if phase.upper() == 'P':
|
||||||
comp = 'Z'
|
comp = 'Z'
|
||||||
alter_comp = COMPNAME_MAP[comp]
|
alter_comp = compclass.getCompPosition(comp)
|
||||||
|
alter_comp = str(alter_comp[0])
|
||||||
sel_st += st.select(component=comp)
|
sel_st += st.select(component=comp)
|
||||||
sel_st += st.select(component=alter_comp)
|
sel_st += st.select(component=alter_comp)
|
||||||
elif phase.upper() == 'S':
|
elif phase.upper() == 'S':
|
||||||
comps = 'NE'
|
comps = 'NE'
|
||||||
for comp in comps:
|
for comp in comps:
|
||||||
alter_comp = COMPNAME_MAP[comp]
|
alter_comp = compclass.getCompPosition(comp)
|
||||||
|
alter_comp = str(alter_comp[0])
|
||||||
sel_st += st.select(component=comp)
|
sel_st += st.select(component=comp)
|
||||||
sel_st += st.select(component=alter_comp)
|
sel_st += st.select(component=alter_comp)
|
||||||
else:
|
else:
|
||||||
@ -509,7 +568,7 @@ def select_for_phase(st, phase):
|
|||||||
return sel_st
|
return sel_st
|
||||||
|
|
||||||
|
|
||||||
def wadaticheck(pickdic, dttolerance, iplot):
|
def wadaticheck(pickdic, dttolerance, iplot=0, fig_dict=None):
|
||||||
'''
|
'''
|
||||||
Function to calculate Wadati-diagram from given P and S onsets in order
|
Function to calculate Wadati-diagram from given P and S onsets in order
|
||||||
to detect S pick outliers. If a certain S-P time deviates by dttolerance
|
to detect S pick outliers. If a certain S-P time deviates by dttolerance
|
||||||
@ -532,7 +591,10 @@ def wadaticheck(pickdic, dttolerance, iplot):
|
|||||||
Ppicks = []
|
Ppicks = []
|
||||||
Spicks = []
|
Spicks = []
|
||||||
SPtimes = []
|
SPtimes = []
|
||||||
for key in pickdic:
|
stations = []
|
||||||
|
ibad = 0
|
||||||
|
|
||||||
|
for key in list(pickdic.keys()):
|
||||||
if pickdic[key]['P']['weight'] < 4 and pickdic[key]['S']['weight'] < 4:
|
if pickdic[key]['P']['weight'] < 4 and pickdic[key]['S']['weight'] < 4:
|
||||||
# calculate S-P time
|
# calculate S-P time
|
||||||
spt = pickdic[key]['S']['mpp'] - pickdic[key]['P']['mpp']
|
spt = pickdic[key]['S']['mpp'] - pickdic[key]['P']['mpp']
|
||||||
@ -559,19 +621,23 @@ def wadaticheck(pickdic, dttolerance, iplot):
|
|||||||
checkedPpicks = []
|
checkedPpicks = []
|
||||||
checkedSpicks = []
|
checkedSpicks = []
|
||||||
checkedSPtimes = []
|
checkedSPtimes = []
|
||||||
|
badstations = []
|
||||||
# calculate deviations from Wadati regression
|
# calculate deviations from Wadati regression
|
||||||
ii = 0
|
ii = 0
|
||||||
ibad = 0
|
for key in list(pickdic.keys()):
|
||||||
for key in pickdic:
|
if 'SPt' in pickdic[key]:
|
||||||
if pickdic[key].has_key('SPt'):
|
stations.append(key)
|
||||||
wddiff = abs(pickdic[key]['SPt'] - wdfit[ii])
|
wddiff = abs(pickdic[key]['SPt'] - wdfit[ii])
|
||||||
ii += 1
|
ii += 1
|
||||||
# check, if deviation is larger than adjusted
|
# check, if deviation is larger than adjusted
|
||||||
if wddiff > dttolerance:
|
if wddiff > dttolerance:
|
||||||
# mark onset and downgrade S-weight to 9
|
# remove pick from dictionary
|
||||||
# (not used anymore)
|
pickdic.pop(key)
|
||||||
marker = 'badWadatiCheck'
|
# # mark onset and downgrade S-weight to 9
|
||||||
pickdic[key]['S']['weight'] = 9
|
# # (not used anymore)
|
||||||
|
# marker = 'badWadatiCheck'
|
||||||
|
# pickdic[key]['S']['weight'] = 9
|
||||||
|
badstations.append(key)
|
||||||
ibad += 1
|
ibad += 1
|
||||||
else:
|
else:
|
||||||
marker = 'goodWadatiCheck'
|
marker = 'goodWadatiCheck'
|
||||||
@ -583,6 +649,9 @@ def wadaticheck(pickdic, dttolerance, iplot):
|
|||||||
checkedSPtimes.append(checkedSPtime)
|
checkedSPtimes.append(checkedSPtime)
|
||||||
|
|
||||||
pickdic[key]['S']['marked'] = marker
|
pickdic[key]['S']['marked'] = marker
|
||||||
|
#pickdic[key]['S']['marked'] = marker
|
||||||
|
print("wadaticheck: the following stations failed the check:")
|
||||||
|
print(badstations)
|
||||||
|
|
||||||
if len(checkedPpicks) >= 3:
|
if len(checkedPpicks) >= 3:
|
||||||
# calculate new slope
|
# calculate new slope
|
||||||
@ -595,8 +664,10 @@ def wadaticheck(pickdic, dttolerance, iplot):
|
|||||||
print("wadatacheck: Skipped %d S pick(s)" % ibad)
|
print("wadatacheck: Skipped %d S pick(s)" % ibad)
|
||||||
else:
|
else:
|
||||||
print("###############################################")
|
print("###############################################")
|
||||||
print ("wadatacheck: Not enough checked S-P times available!")
|
print("wadaticheck: Not enough checked S-P times available!")
|
||||||
print("Skip Wadati check!")
|
print("Skip Wadati check!")
|
||||||
|
wfitflag = 1
|
||||||
|
wdfit2 = None
|
||||||
|
|
||||||
checkedonsets = pickdic
|
checkedonsets = pickdic
|
||||||
|
|
||||||
@ -606,30 +677,50 @@ def wadaticheck(pickdic, dttolerance, iplot):
|
|||||||
wfitflag = 1
|
wfitflag = 1
|
||||||
|
|
||||||
# plot results
|
# plot results
|
||||||
if iplot > 1:
|
if iplot > 0:
|
||||||
plt.figure(iplot)
|
if fig_dict:
|
||||||
f1, = plt.plot(Ppicks, SPtimes, 'ro')
|
fig = fig_dict['wadati']
|
||||||
if wfitflag == 0:
|
linecolor = fig_dict['plot_style']['linecolor']['rgba_mpl']
|
||||||
f2, = plt.plot(Ppicks, wdfit, 'k')
|
plt_flag = 0
|
||||||
f3, = plt.plot(checkedPpicks, checkedSPtimes, 'ko')
|
|
||||||
f4, = plt.plot(checkedPpicks, wdfit2, 'g')
|
|
||||||
plt.title('Wadati-Diagram, %d S-P Times, Vp/Vs(raw)=%5.2f,' \
|
|
||||||
'Vp/Vs(checked)=%5.2f' % (len(SPtimes), vpvsr, cvpvsr))
|
|
||||||
plt.legend([f1, f2, f3, f4], ['Skipped S-Picks', 'Wadati 1',
|
|
||||||
'Reliable S-Picks', 'Wadati 2'], loc='best')
|
|
||||||
else:
|
else:
|
||||||
plt.title('Wadati-Diagram, %d S-P Times' % len(SPtimes))
|
fig = plt.figure()
|
||||||
|
linecolor = 'k'
|
||||||
|
plt_flag = 1
|
||||||
|
ax = fig.add_subplot(111)
|
||||||
|
if ibad > 0:
|
||||||
|
ax.plot(Ppicks, SPtimes, 'ro', label='Skipped S-Picks')
|
||||||
|
if wfitflag == 0:
|
||||||
|
ax.plot(Ppicks, wdfit, color=linecolor, linewidth=0.7, label='Wadati 1')
|
||||||
|
ax.plot(Ppicks, wdfit+dttolerance, color='0.9', linewidth=0.5, label='Wadati 1 Tolerance')
|
||||||
|
ax.plot(Ppicks, wdfit-dttolerance, color='0.9', linewidth=0.5)
|
||||||
|
ax.plot(checkedPpicks, wdfit2, 'g', label='Wadati 2')
|
||||||
|
ax.plot(checkedPpicks, checkedSPtimes, color=linecolor,
|
||||||
|
linewidth=0, marker='o', label='Reliable S-Picks')
|
||||||
|
for Ppick, SPtime, station in zip(Ppicks, SPtimes, stations):
|
||||||
|
ax.text(Ppick, SPtime + 0.01, '{0}'.format(station), color='0.25')
|
||||||
|
|
||||||
plt.ylabel('S-P Times [s]')
|
ax.set_title('Wadati-Diagram, %d S-P Times, Vp/Vs(raw)=%5.2f,' \
|
||||||
plt.xlabel('P Times [s]')
|
'Vp/Vs(checked)=%5.2f' % (len(SPtimes), vpvsr, cvpvsr))
|
||||||
plt.show()
|
ax.legend(loc=1, numpoints=1)
|
||||||
raw_input()
|
else:
|
||||||
plt.close(iplot)
|
ax.set_title('Wadati-Diagram, %d S-P Times' % len(SPtimes))
|
||||||
|
|
||||||
|
ax.set_ylabel('S-P Times [s]')
|
||||||
|
ax.set_xlabel('P Times [s]')
|
||||||
|
if plt_flag:
|
||||||
|
fig.show()
|
||||||
|
|
||||||
return checkedonsets
|
return checkedonsets
|
||||||
|
|
||||||
|
|
||||||
def checksignallength(X, pick, TSNR, minsiglength, nfac, minpercent, iplot):
|
def RMS(X):
|
||||||
|
'''
|
||||||
|
Function returns root mean square of a given array X
|
||||||
|
'''
|
||||||
|
return np.sqrt(np.sum(np.power(X, 2)) / len(X))
|
||||||
|
|
||||||
|
|
||||||
|
def checksignallength(X, pick, TSNR, minsiglength, nfac, minpercent, iplot=0, fig=None, linecolor='k'):
|
||||||
'''
|
'''
|
||||||
Function to detect spuriously picked noise peaks.
|
Function to detect spuriously picked noise peaks.
|
||||||
Uses RMS trace of all 3 components (if available) to determine,
|
Uses RMS trace of all 3 components (if available) to determine,
|
||||||
@ -660,6 +751,15 @@ def checksignallength(X, pick, TSNR, minsiglength, nfac, minpercent, iplot):
|
|||||||
: type: int
|
: type: int
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
plt_flag = 0
|
||||||
|
try:
|
||||||
|
iplot = int(iplot)
|
||||||
|
except:
|
||||||
|
if iplot == True or iplot == 'True':
|
||||||
|
iplot = 2
|
||||||
|
else:
|
||||||
|
iplot = 0
|
||||||
|
|
||||||
assert isinstance(X, Stream), "%s is not a stream object" % str(X)
|
assert isinstance(X, Stream), "%s is not a stream object" % str(X)
|
||||||
|
|
||||||
print("Checking signal length ...")
|
print("Checking signal length ...")
|
||||||
@ -675,17 +775,18 @@ def checksignallength(X, pick, TSNR, minsiglength, nfac, minpercent, iplot):
|
|||||||
rms = np.sqrt((np.power(x1, 2) + np.power(x2, 2) + np.power(x3, 2)) / 3)
|
rms = np.sqrt((np.power(x1, 2) + np.power(x2, 2) + np.power(x3, 2)) / 3)
|
||||||
else:
|
else:
|
||||||
x1 = X[0].data
|
x1 = X[0].data
|
||||||
rms = np.sqrt(np.power(2, x1))
|
ilen = len(x1)
|
||||||
|
rms = abs(x1)
|
||||||
|
|
||||||
t = np.arange(0, ilen / X[0].stats.sampling_rate,
|
t = np.arange(0, ilen / X[0].stats.sampling_rate,
|
||||||
X[0].stats.delta)
|
X[0].stats.delta)
|
||||||
|
|
||||||
# get noise window in front of pick plus saftey gap
|
# get noise window in front of pick plus saftey gap
|
||||||
inoise = getnoisewin(t, pick - 0.5, TSNR[0], TSNR[1])
|
inoise = getnoisewin(t, pick, TSNR[0], TSNR[1])
|
||||||
# get signal window
|
# get signal window
|
||||||
isignal = getsignalwin(t, pick, minsiglength)
|
isignal = getsignalwin(t, pick, minsiglength)
|
||||||
# calculate minimum adjusted signal level
|
# calculate minimum adjusted signal level
|
||||||
minsiglevel = max(rms[inoise]) * nfac
|
minsiglevel = np.mean(rms[inoise]) * nfac
|
||||||
# minimum adjusted number of samples over minimum signal level
|
# minimum adjusted number of samples over minimum signal level
|
||||||
minnum = len(isignal) * minpercent / 100
|
minnum = len(isignal) * minpercent / 100
|
||||||
# get number of samples above minimum adjusted signal level
|
# get number of samples above minimum adjusted signal level
|
||||||
@ -700,29 +801,33 @@ def checksignallength(X, pick, TSNR, minsiglength, nfac, minpercent, iplot):
|
|||||||
print("(min. signal length required: %s s)" % minsiglength)
|
print("(min. signal length required: %s s)" % minsiglength)
|
||||||
returnflag = 0
|
returnflag = 0
|
||||||
|
|
||||||
if iplot == 2:
|
if iplot > 1:
|
||||||
plt.figure(iplot)
|
if fig == None or fig == 'None':
|
||||||
p1, = plt.plot(t, rms, 'k')
|
fig = plt.figure() # iplot)
|
||||||
p2, = plt.plot(t[inoise], rms[inoise], 'c')
|
plt_flag = 1
|
||||||
p3, = plt.plot(t[isignal], rms[isignal], 'r')
|
fig._tight = True
|
||||||
p4, = plt.plot([t[isignal[0]], t[isignal[len(isignal) - 1]]],
|
ax = fig.add_subplot(111)
|
||||||
[minsiglevel, minsiglevel], 'g', linewidth=2)
|
ax.plot(t, rms, color=linecolor, linewidth=0.7, label='RMS Data')
|
||||||
p5, = plt.plot([pick, pick], [min(rms), max(rms)], 'b', linewidth=2)
|
ax.axvspan(t[inoise[0]], t[inoise[-1]], color='y', alpha=0.2, lw=0, label='Noise Window')
|
||||||
plt.legend([p1, p2, p3, p4, p5], ['RMS Data', 'RMS Noise Window',
|
ax.axvspan(t[isignal[0]], t[isignal[-1]], color='b', alpha=0.2, lw=0, label='Signal Window')
|
||||||
'RMS Signal Window', 'Minimum Signal Level',
|
ax.plot([t[isignal[0]], t[isignal[len(isignal) - 1]]],
|
||||||
'Onset'], loc='best')
|
[minsiglevel, minsiglevel], 'g', linewidth=2, label='Minimum Signal Level')
|
||||||
plt.xlabel('Time [s] since %s' % X[0].stats.starttime)
|
ax.plot([pick, pick], [min(rms), max(rms)], 'b', linewidth=2, label='Onset')
|
||||||
plt.ylabel('Counts')
|
ax.legend(loc=1)
|
||||||
plt.title('Check for Signal Length, Station %s' % X[0].stats.station)
|
ax.set_xlabel('Time [s] since %s' % X[0].stats.starttime)
|
||||||
plt.yticks([])
|
ax.set_ylabel('Counts')
|
||||||
plt.show()
|
ax.set_title('Check for Signal Length, Station %s' % X[0].stats.station)
|
||||||
raw_input()
|
ax.set_yticks([])
|
||||||
plt.close(iplot)
|
if plt_flag == 1:
|
||||||
|
fig.show()
|
||||||
|
try: input()
|
||||||
|
except SyntaxError: pass
|
||||||
|
plt.close(fig)
|
||||||
|
|
||||||
return returnflag
|
return returnflag
|
||||||
|
|
||||||
|
|
||||||
def checkPonsets(pickdic, dttolerance, iplot):
|
def checkPonsets(pickdic, dttolerance, jackfactor=5, iplot=0, fig_dict=None):
|
||||||
'''
|
'''
|
||||||
Function to check statistics of P-onset times: Control deviation from
|
Function to check statistics of P-onset times: Control deviation from
|
||||||
median (maximum adjusted deviation = dttolerance) and apply pseudo-
|
median (maximum adjusted deviation = dttolerance) and apply pseudo-
|
||||||
@ -744,24 +849,27 @@ def checkPonsets(pickdic, dttolerance, iplot):
|
|||||||
# search for good quality P picks
|
# search for good quality P picks
|
||||||
Ppicks = []
|
Ppicks = []
|
||||||
stations = []
|
stations = []
|
||||||
for key in pickdic:
|
for station in pickdic:
|
||||||
if pickdic[key]['P']['weight'] < 4:
|
if pickdic[station]['P']['weight'] < 4:
|
||||||
# add P onsets to list
|
# add P onsets to list
|
||||||
UTCPpick = UTCDateTime(pickdic[key]['P']['mpp'])
|
UTCPpick = UTCDateTime(pickdic[station]['P']['mpp'])
|
||||||
Ppicks.append(UTCPpick.timestamp)
|
Ppicks.append(UTCPpick.timestamp)
|
||||||
stations.append(key)
|
stations.append(station)
|
||||||
|
|
||||||
# apply jackknife bootstrapping on variance of P onsets
|
# apply jackknife bootstrapping on variance of P onsets
|
||||||
print("###############################################")
|
print("###############################################")
|
||||||
print("checkPonsets: Apply jackknife bootstrapping on P-onset times ...")
|
print("checkPonsets: Apply jackknife bootstrapping on P-onset times ...")
|
||||||
[xjack, PHI_pseudo, PHI_sub] = jackknife(Ppicks, 'VAR', 1)
|
[xjack, PHI_pseudo, PHI_sub] = jackknife(Ppicks, 'VAR', 1)
|
||||||
|
if not xjack:
|
||||||
|
return
|
||||||
# get pseudo variances smaller than average variances
|
# get pseudo variances smaller than average variances
|
||||||
# (times safety factor), these picks passed jackknife test
|
# (times safety factor), these picks passed jackknife test
|
||||||
ij = np.where(PHI_pseudo <= 2 * xjack)
|
ij = np.where(PHI_pseudo <= jackfactor * xjack)
|
||||||
# these picks did not pass jackknife test
|
# these picks did not pass jackknife test
|
||||||
badjk = np.where(PHI_pseudo > 2 * xjack)
|
badjk = np.where(PHI_pseudo > jackfactor * xjack)
|
||||||
badjkstations = np.array(stations)[badjk]
|
badjkstations = np.array(stations)[badjk]
|
||||||
print("checkPonsets: %d pick(s) did not pass jackknife test!" % len(badjkstations))
|
print("checkPonsets: %d pick(s) did not pass jackknife test!" % len(badjkstations))
|
||||||
|
print(badjkstations)
|
||||||
|
|
||||||
# calculate median from these picks
|
# calculate median from these picks
|
||||||
pmedian = np.median(np.array(Ppicks)[ij])
|
pmedian = np.median(np.array(Ppicks)[ij])
|
||||||
@ -774,6 +882,7 @@ def checkPonsets(pickdic, dttolerance, iplot):
|
|||||||
badstations = np.array(stations)[ibad]
|
badstations = np.array(stations)[ibad]
|
||||||
|
|
||||||
print("checkPonsets: %d pick(s) deviate too much from median!" % len(ibad))
|
print("checkPonsets: %d pick(s) deviate too much from median!" % len(ibad))
|
||||||
|
print(badstations)
|
||||||
print("checkPonsets: Skipped %d P pick(s) out of %d" % (len(badstations) \
|
print("checkPonsets: Skipped %d P pick(s) out of %d" % (len(badstations) \
|
||||||
+ len(badjkstations), len(stations)))
|
+ len(badjkstations), len(stations)))
|
||||||
|
|
||||||
@ -784,33 +893,52 @@ def checkPonsets(pickdic, dttolerance, iplot):
|
|||||||
# mark P onset as checked and keep P weight
|
# mark P onset as checked and keep P weight
|
||||||
pickdic[goodstations[i]]['P']['marked'] = goodmarker
|
pickdic[goodstations[i]]['P']['marked'] = goodmarker
|
||||||
for i in range(0, len(badstations)):
|
for i in range(0, len(badstations)):
|
||||||
# mark P onset and downgrade P weight to 9
|
# remove pick from dictionary
|
||||||
# (not used anymore)
|
pickdic.pop(badstations[i])
|
||||||
pickdic[badstations[i]]['P']['marked'] = badmarker
|
|
||||||
pickdic[badstations[i]]['P']['weight'] = 9
|
|
||||||
for i in range(0, len(badjkstations)):
|
for i in range(0, len(badjkstations)):
|
||||||
# mark P onset and downgrade P weight to 9
|
# remove pick from dictionary
|
||||||
# (not used anymore)
|
pickdic.pop(badjkstations[i])
|
||||||
pickdic[badjkstations[i]]['P']['marked'] = badjkmarker
|
# for i in range(0, len(badstations)):
|
||||||
pickdic[badjkstations[i]]['P']['weight'] = 9
|
# # mark P onset and downgrade P weight to 9
|
||||||
|
# # (not used anymore)
|
||||||
|
# pickdic[badstations[i]]['P']['marked'] = badmarker
|
||||||
|
# pickdic[badstations[i]]['P']['weight'] = 9
|
||||||
|
# for i in range(0, len(badjkstations)):
|
||||||
|
# # mark P onset and downgrade P weight to 9
|
||||||
|
# # (not used anymore)
|
||||||
|
# pickdic[badjkstations[i]]['P']['marked'] = badjkmarker
|
||||||
|
# pickdic[badjkstations[i]]['P']['weight'] = 9
|
||||||
|
|
||||||
checkedonsets = pickdic
|
checkedonsets = pickdic
|
||||||
|
|
||||||
if iplot > 1:
|
if iplot > 0:
|
||||||
p1, = plt.plot(np.arange(0, len(Ppicks)), Ppicks, 'r+', markersize=14)
|
if fig_dict:
|
||||||
p2, = plt.plot(igood, np.array(Ppicks)[igood], 'g*', markersize=14)
|
fig = fig_dict['jackknife']
|
||||||
p3, = plt.plot([0, len(Ppicks) - 1], [pmedian, pmedian], 'g',
|
plt_flag = 0
|
||||||
linewidth=2)
|
else:
|
||||||
for i in range(0, len(Ppicks)):
|
fig = plt.figure()
|
||||||
plt.text(i, Ppicks[i] + 0.2, stations[i])
|
plt_flag = 1
|
||||||
|
ax = fig.add_subplot(111)
|
||||||
|
|
||||||
plt.xlabel('Number of P Picks')
|
if len(badstations) > 0:
|
||||||
plt.ylabel('Onset Time [s] from 1.1.1970')
|
ax.plot(ibad, np.array(Ppicks)[ibad], marker ='o', markerfacecolor='orange', markersize=14,
|
||||||
plt.legend([p1, p2, p3], ['Skipped P Picks', 'Good P Picks', 'Median'],
|
linestyle='None', label='Median Skipped P Picks')
|
||||||
loc='best')
|
if len(badjkstations) > 0:
|
||||||
plt.title('Check P Onsets')
|
ax.plot(badjk[0], np.array(Ppicks)[badjk], 'ro', markersize=14, label='Jackknife Skipped P Picks')
|
||||||
plt.show()
|
ax.plot(igood, np.array(Ppicks)[igood], 'go', markersize=14, label='Good P Picks')
|
||||||
raw_input()
|
ax.plot([0, len(Ppicks) - 1], [pmedian, pmedian], 'g', linewidth=2, label='Median')
|
||||||
|
ax.plot([0, len(Ppicks) - 1], [pmedian + dttolerance, pmedian + dttolerance], 'g--', linewidth=1.2,
|
||||||
|
dashes=[25, 25], label='Median Tolerance')
|
||||||
|
ax.plot([0, len(Ppicks) - 1], [pmedian - dttolerance, pmedian - dttolerance], 'g--', linewidth=1.2,
|
||||||
|
dashes=[25, 25])
|
||||||
|
for index, pick in enumerate(Ppicks):
|
||||||
|
ax.text(index, pick + 0.01, '{0}'.format(stations[index]), color='0.25')
|
||||||
|
ax.set_xlabel('Number of P Picks')
|
||||||
|
ax.set_ylabel('Onset Time [s] from 1.1.1970') # MP MP Improve this?
|
||||||
|
ax.legend(loc=1, numpoints=1)
|
||||||
|
ax.set_title('Jackknifing and Median Tests on P Onsets')
|
||||||
|
if plt_flag:
|
||||||
|
fig.show()
|
||||||
|
|
||||||
return checkedonsets
|
return checkedonsets
|
||||||
|
|
||||||
@ -839,13 +967,13 @@ def jackknife(X, phi, h):
|
|||||||
PHI_sub = None
|
PHI_sub = None
|
||||||
|
|
||||||
# determine number of subgroups
|
# determine number of subgroups
|
||||||
g = len(X) / h
|
|
||||||
|
|
||||||
if type(g) is not int:
|
if len(X) % h:
|
||||||
print("jackknife: Cannot divide quantity X in equal sized subgroups!")
|
print("jackknife: Cannot divide quantity X in equal sized subgroups!")
|
||||||
print("Choose another size for subgroups!")
|
print("Choose another size for subgroups!")
|
||||||
return PHI_jack, PHI_pseudo, PHI_sub
|
return PHI_jack, PHI_pseudo, PHI_sub
|
||||||
else:
|
else:
|
||||||
|
g = int(len(X) / h)
|
||||||
# estimator of undisturbed spot check
|
# estimator of undisturbed spot check
|
||||||
if phi == 'MEA':
|
if phi == 'MEA':
|
||||||
phi_sc = np.mean(X)
|
phi_sc = np.mean(X)
|
||||||
@ -879,7 +1007,7 @@ def jackknife(X, phi, h):
|
|||||||
return PHI_jack, PHI_pseudo, PHI_sub
|
return PHI_jack, PHI_pseudo, PHI_sub
|
||||||
|
|
||||||
|
|
||||||
def checkZ4S(X, pick, zfac, checkwin, iplot):
|
def checkZ4S(X, pick, zfac, checkwin, iplot, fig=None, linecolor='k'):
|
||||||
'''
|
'''
|
||||||
Function to compare energy content of vertical trace with
|
Function to compare energy content of vertical trace with
|
||||||
energy content of horizontal traces to detect spuriously
|
energy content of horizontal traces to detect spuriously
|
||||||
@ -909,6 +1037,16 @@ def checkZ4S(X, pick, zfac, checkwin, iplot):
|
|||||||
: type: int
|
: type: int
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
plt_flag = 0
|
||||||
|
try:
|
||||||
|
iplot = int(iplot)
|
||||||
|
except:
|
||||||
|
if iplot == True or iplot == 'True':
|
||||||
|
iplot = 2
|
||||||
|
else:
|
||||||
|
iplot = 0
|
||||||
|
|
||||||
|
|
||||||
assert isinstance(X, Stream), "%s is not a stream object" % str(X)
|
assert isinstance(X, Stream), "%s is not a stream object" % str(X)
|
||||||
|
|
||||||
print("Check for spuriously picked S onset instead of P onset ...")
|
print("Check for spuriously picked S onset instead of P onset ...")
|
||||||
@ -926,63 +1064,122 @@ def checkZ4S(X, pick, zfac, checkwin, iplot):
|
|||||||
if len(ndat) == 0: # check for other components
|
if len(ndat) == 0: # check for other components
|
||||||
ndat = X.select(component="1")
|
ndat = X.select(component="1")
|
||||||
|
|
||||||
z = zdat[0].data
|
# get earliest time of all 3 traces
|
||||||
|
min_t = min(zdat[0].stats.starttime, edat[0].stats.starttime, ndat[0].stats.starttime)
|
||||||
|
|
||||||
|
# generate time arrays for all 3 traces
|
||||||
tz = np.arange(0, zdat[0].stats.npts / zdat[0].stats.sampling_rate,
|
tz = np.arange(0, zdat[0].stats.npts / zdat[0].stats.sampling_rate,
|
||||||
zdat[0].stats.delta)
|
zdat[0].stats.delta)
|
||||||
|
tn = np.arange(0, ndat[0].stats.npts / ndat[0].stats.sampling_rate,
|
||||||
|
ndat[0].stats.delta)
|
||||||
|
te = np.arange(0, edat[0].stats.npts / edat[0].stats.sampling_rate,
|
||||||
|
edat[0].stats.delta)
|
||||||
|
|
||||||
# calculate RMS trace from vertical component
|
zdiff = (zdat[0].stats.starttime - min_t)
|
||||||
absz = np.sqrt(np.power(z, 2))
|
ndiff = (ndat[0].stats.starttime - min_t)
|
||||||
# calculate RMS trace from both horizontal traces
|
ediff = (edat[0].stats.starttime - min_t)
|
||||||
# make sure, both traces have equal lengths
|
|
||||||
lene = len(edat[0].data)
|
|
||||||
lenn = len(ndat[0].data)
|
|
||||||
minlen = min([lene, lenn])
|
|
||||||
absen = np.sqrt(np.power(edat[0].data[0:minlen - 1], 2) \
|
|
||||||
+ np.power(ndat[0].data[0:minlen - 1], 2))
|
|
||||||
|
|
||||||
# get signal window
|
# get signal windows
|
||||||
isignal = getsignalwin(tz, pick, checkwin)
|
isignalz = getsignalwin(tz, pick - zdiff, checkwin)
|
||||||
|
isignaln = getsignalwin(tn, pick - ndiff, checkwin)
|
||||||
|
isignale = getsignalwin(te, pick - ediff, checkwin)
|
||||||
|
|
||||||
# calculate energy levels
|
# calculate RMS of traces
|
||||||
zcodalevel = max(absz[isignal])
|
rmsz = RMS(zdat[0].data[isignalz])
|
||||||
encodalevel = max(absen[isignal])
|
rmsn = RMS(ndat[0].data[isignaln])
|
||||||
|
rmse = RMS(edat[0].data[isignale])
|
||||||
|
|
||||||
# calculate threshold
|
# calculate threshold
|
||||||
minsiglevel = encodalevel * zfac
|
minsiglevel = (rmsn + rmse) / 2 * zfac
|
||||||
|
|
||||||
# vertical P-coda level must exceed horizontal P-coda level
|
# vertical P-coda level must exceed horizontal P-coda level
|
||||||
# zfac times encodalevel
|
# zfac times encodalevel
|
||||||
if zcodalevel < minsiglevel:
|
if rmsz < minsiglevel:
|
||||||
print("checkZ4S: Maybe S onset? Skip this P pick!")
|
print("checkZ4S: Maybe S onset? Skip this P pick!")
|
||||||
else:
|
else:
|
||||||
print("checkZ4S: P onset passes checkZ4S test!")
|
print("checkZ4S: P onset passes checkZ4S test!")
|
||||||
returnflag = 1
|
returnflag = 1
|
||||||
|
|
||||||
if iplot > 1:
|
if iplot > 1:
|
||||||
te = np.arange(0, edat[0].stats.npts / edat[0].stats.sampling_rate,
|
rms_dict = {'Z': rmsz,
|
||||||
edat[0].stats.delta)
|
'N': rmsn,
|
||||||
tn = np.arange(0, ndat[0].stats.npts / ndat[0].stats.sampling_rate,
|
'E': rmse}
|
||||||
ndat[0].stats.delta)
|
|
||||||
plt.plot(tz, z / max(z), 'k')
|
|
||||||
plt.plot(tz[isignal], z[isignal] / max(z), 'r')
|
|
||||||
plt.plot(te, edat[0].data / max(edat[0].data) + 1, 'k')
|
|
||||||
plt.plot(te[isignal], edat[0].data[isignal] / max(edat[0].data) + 1, 'r')
|
|
||||||
plt.plot(tn, ndat[0].data / max(ndat[0].data) + 2, 'k')
|
|
||||||
plt.plot(tn[isignal], ndat[0].data[isignal] / max(ndat[0].data) + 2, 'r')
|
|
||||||
plt.plot([tz[isignal[0]], tz[isignal[len(isignal) - 1]]],
|
|
||||||
[minsiglevel / max(z), minsiglevel / max(z)], 'g',
|
|
||||||
linewidth=2)
|
|
||||||
plt.xlabel('Time [s] since %s' % zdat[0].stats.starttime)
|
|
||||||
plt.ylabel('Normalized Counts')
|
|
||||||
plt.yticks([0, 1, 2], [zdat[0].stats.channel, edat[0].stats.channel,
|
|
||||||
ndat[0].stats.channel])
|
|
||||||
plt.title('CheckZ4S, Station %s' % zdat[0].stats.station)
|
|
||||||
plt.show()
|
|
||||||
raw_input()
|
|
||||||
|
|
||||||
|
traces_dict = {'Z': zdat[0],
|
||||||
|
'N': ndat[0],
|
||||||
|
'E': edat[0]}
|
||||||
|
|
||||||
|
diff_dict = {'Z': zdiff,
|
||||||
|
'N': ndiff,
|
||||||
|
'E': ediff}
|
||||||
|
|
||||||
|
signal_dict = {'Z': isignalz,
|
||||||
|
'N': isignaln,
|
||||||
|
'E': isignale}
|
||||||
|
|
||||||
|
for i, key in enumerate(['Z', 'N', 'E']):
|
||||||
|
rms = rms_dict[key]
|
||||||
|
trace = traces_dict[key]
|
||||||
|
t = np.arange(diff_dict[key], trace.stats.npts / trace.stats.sampling_rate + diff_dict[key],
|
||||||
|
trace.stats.delta)
|
||||||
|
if i == 0:
|
||||||
|
if fig == None or fig == 'None':
|
||||||
|
fig = plt.figure() # self.iplot) ### WHY? MP MP
|
||||||
|
plt_flag = 1
|
||||||
|
ax1 = fig.add_subplot(3, 1, i + 1)
|
||||||
|
ax = ax1
|
||||||
|
ax.set_title('CheckZ4S, Station %s' % zdat[0].stats.station)
|
||||||
|
else:
|
||||||
|
if fig == None or fig == 'None':
|
||||||
|
fig = plt.figure() # self.iplot) ### WHY? MP MP
|
||||||
|
plt_flag = 1
|
||||||
|
ax = fig.add_subplot(3, 1, i + 1, sharex=ax1)
|
||||||
|
fig._tight = True
|
||||||
|
ax.plot(t, abs(trace.data), color='b', label='abs')
|
||||||
|
ax.plot(t, trace.data, color=linecolor, linewidth=0.7)
|
||||||
|
name = str(trace.stats.channel) + ': {}'.format(rms)
|
||||||
|
ax.plot([pick, pick + checkwin], [rms, rms], 'r', label='RMS {}'.format(name))
|
||||||
|
ax.plot([pick, pick], ax.get_ylim(), 'm', label='Pick')
|
||||||
|
ax.set_ylabel('Normalized Counts')
|
||||||
|
ax.axvspan(pick, pick + checkwin, color='c', alpha=0.2,
|
||||||
|
lw=0)
|
||||||
|
ax.legend(loc=1)
|
||||||
|
ax.set_xlabel('Time [s] since %s' % zdat[0].stats.starttime)
|
||||||
|
if plt_flag == 1:
|
||||||
|
fig.show()
|
||||||
|
try: input()
|
||||||
|
except SyntaxError: pass
|
||||||
|
plt.close(fig)
|
||||||
return returnflag
|
return returnflag
|
||||||
|
|
||||||
|
|
||||||
|
def getQualityFromUncertainty(uncertainty, Errors):
|
||||||
|
'''Script to transform uncertainty into quality classes 0-4
|
||||||
|
regarding adjusted time errors Errors.
|
||||||
|
'''
|
||||||
|
|
||||||
|
# set initial quality to 4 (worst) and change only if one condition is hit
|
||||||
|
quality = 4
|
||||||
|
|
||||||
|
if uncertainty == None or uncertainty == 'None':
|
||||||
|
return quality
|
||||||
|
|
||||||
|
if uncertainty <= Errors[0]:
|
||||||
|
quality = 0
|
||||||
|
elif (uncertainty > Errors[0]) and \
|
||||||
|
(uncertainty < Errors[1]):
|
||||||
|
quality = 1
|
||||||
|
elif (uncertainty > Errors[1]) and \
|
||||||
|
(uncertainty < Errors[2]):
|
||||||
|
quality = 2
|
||||||
|
elif (uncertainty > Errors[2]) and \
|
||||||
|
(uncertainty < Errors[3]):
|
||||||
|
quality = 3
|
||||||
|
elif uncertainty > Errors[3]:
|
||||||
|
quality = 4
|
||||||
|
|
||||||
|
return quality
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
import doctest
|
import doctest
|
||||||
|
|
||||||
|
0
pylot/core/util/__init__.py
Executable file → Normal file
@ -1,13 +1,16 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
import urllib2
|
|
||||||
|
|
||||||
|
|
||||||
def checkurl(url='https://ariadne.geophysik.rub.de/trac/PyLoT'):
|
|
||||||
try:
|
try:
|
||||||
urllib2.urlopen(url, timeout=1)
|
from urllib2 import urlopen
|
||||||
|
except:
|
||||||
|
from urllib.request import urlopen
|
||||||
|
|
||||||
|
|
||||||
|
def checkurl(url='https://ariadne.geophysik.ruhr-uni-bochum.de/trac/PyLoT/'):
|
||||||
|
try:
|
||||||
|
urlopen(url, timeout=1)
|
||||||
return True
|
return True
|
||||||
except urllib2.URLError:
|
except:
|
||||||
pass
|
pass
|
||||||
return False
|
return False
|
||||||
|
@ -1,17 +1,15 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
import os
|
|
||||||
import glob
|
import glob
|
||||||
|
import os
|
||||||
import sys
|
import sys
|
||||||
from obspy.io.xseed import Parser
|
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
from obspy import UTCDateTime, read_inventory, read
|
from obspy import UTCDateTime, read_inventory, read
|
||||||
from obspy.io.xseed import Parser
|
from obspy.io.xseed import Parser
|
||||||
from pylot.core.util.utils import key_for_set_value, find_in_list, \
|
from pylot.core.util.utils import key_for_set_value, find_in_list, \
|
||||||
remove_underscores
|
remove_underscores, gen_Pool
|
||||||
|
|
||||||
|
|
||||||
def time_from_header(header):
|
def time_from_header(header):
|
||||||
@ -169,7 +167,8 @@ def read_metadata(path_to_inventory):
|
|||||||
dlfile = list()
|
dlfile = list()
|
||||||
invfile = list()
|
invfile = list()
|
||||||
respfile = list()
|
respfile = list()
|
||||||
inv = dict(dless=dlfile, xml=invfile, resp=respfile)
|
# possible file extensions specified here:
|
||||||
|
inv = dict(dless=dlfile, xml=invfile, resp=respfile, dseed=dlfile[:])
|
||||||
if os.path.isfile(path_to_inventory):
|
if os.path.isfile(path_to_inventory):
|
||||||
ext = os.path.splitext(path_to_inventory)[1].split('.')[1]
|
ext = os.path.splitext(path_to_inventory)[1].split('.')[1]
|
||||||
inv[ext] += [path_to_inventory]
|
inv[ext] += [path_to_inventory]
|
||||||
@ -180,8 +179,10 @@ def read_metadata(path_to_inventory):
|
|||||||
invtype = key_for_set_value(inv)
|
invtype = key_for_set_value(inv)
|
||||||
|
|
||||||
if invtype is None:
|
if invtype is None:
|
||||||
raise IOError("Neither dataless-SEED file, inventory-xml file nor "
|
print("Neither dataless-SEED file, inventory-xml file nor "
|
||||||
"RESP-file found!")
|
"RESP-file found!")
|
||||||
|
print("!!WRONG CALCULATION OF SOURCE PARAMETERS!!")
|
||||||
|
robj = None,
|
||||||
elif invtype == 'dless': # prevent multiple read of large dlsv
|
elif invtype == 'dless': # prevent multiple read of large dlsv
|
||||||
print("Reading metadata information from dataless-SEED file ...")
|
print("Reading metadata information from dataless-SEED file ...")
|
||||||
if len(inv[invtype]) == 1:
|
if len(inv[invtype]) == 1:
|
||||||
@ -195,33 +196,18 @@ def read_metadata(path_to_inventory):
|
|||||||
return invtype, robj
|
return invtype, robj
|
||||||
|
|
||||||
|
|
||||||
def restitute_data(data, invtype, inobj, unit='VEL', force=False):
|
def restitute_trace(input_tuple):
|
||||||
"""
|
tr, invtype, inobj, unit, force = input_tuple
|
||||||
takes a data stream and a path_to_inventory and returns the corrected
|
|
||||||
waveform data stream
|
|
||||||
:param data: seismic data stream
|
|
||||||
:param invtype: type of found metadata
|
|
||||||
:param inobj: either list of metadata files or `obspy.io.xseed.Parser`
|
|
||||||
object
|
|
||||||
:param unit: unit to correct for (default: 'VEL')
|
|
||||||
:param force: force restitution for already corrected traces (default:
|
|
||||||
False)
|
|
||||||
:return: corrected data stream
|
|
||||||
"""
|
|
||||||
|
|
||||||
restflag = list()
|
remove_trace = False
|
||||||
|
|
||||||
data = remove_underscores(data)
|
|
||||||
|
|
||||||
# loop over traces
|
|
||||||
for tr in data:
|
|
||||||
seed_id = tr.get_id()
|
seed_id = tr.get_id()
|
||||||
# check, whether this trace has already been corrected
|
# check, whether this trace has already been corrected
|
||||||
if 'processing' in tr.stats.keys() \
|
if 'processing' in tr.stats.keys() \
|
||||||
and np.any(['remove' in p for p in tr.stats.processing]) \
|
and np.any(['remove' in p for p in tr.stats.processing]) \
|
||||||
and not force:
|
and not force:
|
||||||
print("Trace {0} has already been corrected!".format(seed_id))
|
print("Trace {0} has already been corrected!".format(seed_id))
|
||||||
continue
|
return tr, False
|
||||||
stime = tr.stats.starttime
|
stime = tr.stats.starttime
|
||||||
prefilt = get_prefilt(tr)
|
prefilt = get_prefilt(tr)
|
||||||
if invtype == 'resp':
|
if invtype == 'resp':
|
||||||
@ -250,13 +236,22 @@ def restitute_data(data, invtype, inobj, unit='VEL', force=False):
|
|||||||
else:
|
else:
|
||||||
finv = invlist[0]
|
finv = invlist[0]
|
||||||
inventory = read_inventory(finv, format='STATIONXML')
|
inventory = read_inventory(finv, format='STATIONXML')
|
||||||
|
elif invtype == None:
|
||||||
|
print("No restitution possible, as there are no station-meta data available!")
|
||||||
|
return tr, True
|
||||||
else:
|
else:
|
||||||
data.remove(tr)
|
remove_trace = True
|
||||||
continue
|
|
||||||
# apply restitution to data
|
# apply restitution to data
|
||||||
|
print("Correcting instrument at station %s, channel %s" \
|
||||||
|
% (tr.stats.station, tr.stats.channel))
|
||||||
try:
|
try:
|
||||||
if invtype in ['resp', 'dless']:
|
if invtype in ['resp', 'dless']:
|
||||||
|
try:
|
||||||
tr.simulate(**kwargs)
|
tr.simulate(**kwargs)
|
||||||
|
except ValueError as e:
|
||||||
|
vmsg = '{0}'.format(e)
|
||||||
|
print(vmsg)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
tr.attach_response(inventory)
|
tr.attach_response(inventory)
|
||||||
tr.remove_response(output=unit,
|
tr.remove_response(output=unit,
|
||||||
@ -269,17 +264,52 @@ def restitute_data(data, invtype, inobj, unit='VEL', force=False):
|
|||||||
else:
|
else:
|
||||||
# restitution done to copies of data thus deleting traces
|
# restitution done to copies of data thus deleting traces
|
||||||
# that failed should not be a problem
|
# that failed should not be a problem
|
||||||
|
remove_trace = True
|
||||||
|
|
||||||
|
return tr, remove_trace
|
||||||
|
|
||||||
|
|
||||||
|
def restitute_data(data, invtype, inobj, unit='VEL', force=False, ncores=0):
|
||||||
|
"""
|
||||||
|
takes a data stream and a path_to_inventory and returns the corrected
|
||||||
|
waveform data stream
|
||||||
|
:param data: seismic data stream
|
||||||
|
:param invtype: type of found metadata
|
||||||
|
:param inobj: either list of metadata files or `obspy.io.xseed.Parser`
|
||||||
|
object
|
||||||
|
:param unit: unit to correct for (default: 'VEL')
|
||||||
|
:param force: force restitution for already corrected traces (default:
|
||||||
|
False)
|
||||||
|
:return: corrected data stream
|
||||||
|
"""
|
||||||
|
|
||||||
|
restflag = list()
|
||||||
|
|
||||||
|
data = remove_underscores(data)
|
||||||
|
|
||||||
|
# loop over traces
|
||||||
|
input_tuples = []
|
||||||
|
for tr in data:
|
||||||
|
input_tuples.append((tr, invtype, inobj, unit, force))
|
||||||
data.remove(tr)
|
data.remove(tr)
|
||||||
continue
|
|
||||||
restflag.append(True)
|
pool = gen_Pool(ncores)
|
||||||
|
result = pool.map(restitute_trace, input_tuples)
|
||||||
|
pool.close()
|
||||||
|
|
||||||
|
for tr, remove_trace in result:
|
||||||
|
if not remove_trace:
|
||||||
|
data.traces.append(tr)
|
||||||
|
|
||||||
# check if ALL traces could be restituted, take care of large datasets
|
# check if ALL traces could be restituted, take care of large datasets
|
||||||
# better try restitution for smaller subsets of data (e.g. station by
|
# better try restitution for smaller subsets of data (e.g. station by
|
||||||
# station)
|
# station)
|
||||||
if len(restflag) > 0:
|
|
||||||
restflag = bool(np.all(restflag))
|
# if len(restflag) > 0:
|
||||||
else:
|
# restflag = bool(np.all(restflag))
|
||||||
restflag = False
|
# else:
|
||||||
return data, restflag
|
# restflag = False
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
||||||
def get_prefilt(trace, tlow=(0.5, 0.9), thi=(5., 2.), verbosity=0):
|
def get_prefilt(trace, tlow=(0.5, 0.9), thi=(5., 2.), verbosity=0):
|
||||||
|
@ -7,45 +7,29 @@ Created on Wed Feb 26 12:31:25 2014
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
import platform
|
||||||
|
|
||||||
|
from pylot.core.util.utils import readDefaultFilterInformation
|
||||||
|
from pylot.core.loc import hypo71
|
||||||
|
from pylot.core.loc import hypodd
|
||||||
|
from pylot.core.loc import hyposat
|
||||||
from pylot.core.loc import nll
|
from pylot.core.loc import nll
|
||||||
from pylot.core.loc import hsat
|
|
||||||
from pylot.core.loc import velest
|
from pylot.core.loc import velest
|
||||||
|
|
||||||
|
|
||||||
def readFilterInformation(fname):
|
# determine system dependent path separator
|
||||||
def convert2FreqRange(*args):
|
system_name = platform.system()
|
||||||
if len(args) > 1:
|
if system_name in ["Linux", "Darwin"]:
|
||||||
return [float(arg) for arg in args]
|
SEPARATOR = '/'
|
||||||
elif len(args) == 1:
|
elif system_name == "Windows":
|
||||||
return float(args[0])
|
SEPARATOR = '\\'
|
||||||
return None
|
|
||||||
|
|
||||||
filter_file = open(fname, 'r')
|
# suffix for phase name if not phase identified by last letter (P, p, etc.)
|
||||||
filter_information = dict()
|
ALTSUFFIX = ['diff', 'n', 'g', '1', '2', '3']
|
||||||
for filter_line in filter_file.readlines():
|
|
||||||
filter_line = filter_line.split(' ')
|
|
||||||
for n, pos in enumerate(filter_line):
|
|
||||||
if pos == '\n':
|
|
||||||
filter_line[n] = ''
|
|
||||||
filter_information[filter_line[0]] = {'filtertype': filter_line[1]
|
|
||||||
if filter_line[1]
|
|
||||||
else None,
|
|
||||||
'order': int(filter_line[2])
|
|
||||||
if filter_line[1]
|
|
||||||
else None,
|
|
||||||
'freq': convert2FreqRange(*filter_line[3:])
|
|
||||||
if filter_line[1]
|
|
||||||
else None}
|
|
||||||
return filter_information
|
|
||||||
|
|
||||||
|
FILTERDEFAULTS = readDefaultFilterInformation(os.path.join(os.path.expanduser('~'),
|
||||||
FILTERDEFAULTS = readFilterInformation(os.path.join(os.path.expanduser('~'),
|
|
||||||
'.pylot',
|
'.pylot',
|
||||||
'filter.in'))
|
'pylot.in'))
|
||||||
|
|
||||||
AUTOMATIC_DEFAULTS = os.path.join(os.path.expanduser('~'),
|
|
||||||
'.pylot',
|
|
||||||
'autoPyLoT.in')
|
|
||||||
|
|
||||||
TIMEERROR_DEFAULTS = os.path.join(os.path.expanduser('~'),
|
TIMEERROR_DEFAULTS = os.path.join(os.path.expanduser('~'),
|
||||||
'.pylot',
|
'.pylot',
|
||||||
@ -55,11 +39,57 @@ OUTPUTFORMATS = {'.xml': 'QUAKEML',
|
|||||||
'.cnv': 'CNV',
|
'.cnv': 'CNV',
|
||||||
'.obs': 'NLLOC_OBS'}
|
'.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
|
|
||||||
COMPPOSITION_MAP['2'] = 0
|
|
||||||
COMPPOSITION_MAP['3'] = 2
|
|
||||||
|
|
||||||
COMPNAME_MAP = dict(Z='3', N='1', E='2')
|
class SetChannelComponents(object):
|
||||||
|
def __init__(self):
|
||||||
|
self.setDefaultCompPosition()
|
||||||
|
|
||||||
|
def setDefaultCompPosition(self):
|
||||||
|
# default component order
|
||||||
|
self.compPosition_Map = dict(Z=2, N=1, E=0)
|
||||||
|
self.compName_Map = {'3': 'Z',
|
||||||
|
'1': 'N',
|
||||||
|
'2': 'E'}
|
||||||
|
|
||||||
|
def _getCurrentPosition(self, component):
|
||||||
|
for key, value in self.compName_Map.items():
|
||||||
|
if value == component:
|
||||||
|
return key, value
|
||||||
|
errMsg = 'getCurrentPosition: Could not find former position of component {}.'.format(component)
|
||||||
|
raise ValueError(errMsg)
|
||||||
|
|
||||||
|
def _switch(self, component, component_alter):
|
||||||
|
# Without switching, multiple definitions of the same alter_comp are possible
|
||||||
|
old_alter_comp, _ = self._getCurrentPosition(component)
|
||||||
|
old_comp = self.compName_Map[component_alter]
|
||||||
|
if not old_alter_comp == component_alter and not old_comp == component:
|
||||||
|
self.compName_Map[old_alter_comp] = old_comp
|
||||||
|
print('switch: Automatically switched component {} to {}'.format(old_alter_comp, old_comp))
|
||||||
|
|
||||||
|
def setCompPosition(self, component_alter, component, switch=True):
|
||||||
|
component_alter = str(component_alter)
|
||||||
|
if not component_alter in self.compName_Map.keys():
|
||||||
|
errMsg = 'setCompPosition: Unrecognized alternative component {}. Expecting one of {}.'
|
||||||
|
raise ValueError(errMsg.format(component_alter, self.compName_Map.keys()))
|
||||||
|
if not component in self.compPosition_Map.keys():
|
||||||
|
errMsg = 'setCompPosition: Unrecognized target component {}. Expecting one of {}.'
|
||||||
|
raise ValueError(errMsg.format(component, self.compPosition_Map.keys()))
|
||||||
|
print('setCompPosition: set component {} to {}'.format(component_alter, component))
|
||||||
|
if switch:
|
||||||
|
self._switch(component, component_alter)
|
||||||
|
self.compName_Map[component_alter] = component
|
||||||
|
|
||||||
|
def getCompPosition(self, component):
|
||||||
|
return self._getCurrentPosition(component)[0]
|
||||||
|
|
||||||
|
def getPlotPosition(self, component):
|
||||||
|
component = str(component)
|
||||||
|
if component in self.compPosition_Map.keys():
|
||||||
|
return self.compPosition_Map[component]
|
||||||
|
elif component in self.compName_Map.keys():
|
||||||
|
return self.compPosition_Map[self.compName_Map[component]]
|
||||||
|
else:
|
||||||
|
errMsg = 'getCompPosition: Unrecognized component {}. Expecting one of {} or {}.'
|
||||||
|
raise ValueError(errMsg.format(component, self.compPosition_Map.keys(), self.compName_Map.keys()))
|
||||||
|
@ -25,5 +25,6 @@ class OverwriteError(IOError):
|
|||||||
class ParameterError(Exception):
|
class ParameterError(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class ProcessingError(RuntimeError):
|
class ProcessingError(RuntimeError):
|
||||||
pass
|
pass
|
||||||
|
172
pylot/core/util/event.py
Normal file
@ -0,0 +1,172 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
from obspy import UTCDateTime
|
||||||
|
from obspy.core.event import Event as ObsPyEvent
|
||||||
|
from obspy.core.event import Origin, ResourceIdentifier
|
||||||
|
from pylot.core.io.phases import picks_from_picksdict
|
||||||
|
|
||||||
|
|
||||||
|
class Event(ObsPyEvent):
|
||||||
|
'''
|
||||||
|
Pickable class derived from ~obspy.core.event.Event containing information on a single event.
|
||||||
|
'''
|
||||||
|
|
||||||
|
def __init__(self, path):
|
||||||
|
self.pylot_id = path.split('/')[-1]
|
||||||
|
# initialize super class
|
||||||
|
super(Event, self).__init__(resource_id=ResourceIdentifier('smi:local/' + self.pylot_id))
|
||||||
|
self.path = path
|
||||||
|
self.database = path.split('/')[-2]
|
||||||
|
self.datapath = path.split('/')[-3]
|
||||||
|
self.rootpath = '/' + os.path.join(*path.split('/')[:-3])
|
||||||
|
self.pylot_autopicks = {}
|
||||||
|
self.pylot_picks = {}
|
||||||
|
self.notes = ''
|
||||||
|
self._testEvent = False
|
||||||
|
self._refEvent = False
|
||||||
|
self.get_notes()
|
||||||
|
|
||||||
|
def get_notes_path(self):
|
||||||
|
notesfile = os.path.join(self.path, 'notes.txt')
|
||||||
|
return notesfile
|
||||||
|
|
||||||
|
def get_notes(self):
|
||||||
|
notesfile = self.get_notes_path()
|
||||||
|
if os.path.isfile(notesfile):
|
||||||
|
with open(notesfile) as infile:
|
||||||
|
path = str(infile.readlines()[0].split('\n')[0])
|
||||||
|
text = '[eventInfo: ' + path + ']'
|
||||||
|
self.addNotes(text)
|
||||||
|
try:
|
||||||
|
datetime = UTCDateTime(path.split('/')[-1])
|
||||||
|
origin = Origin(resource_id=self.resource_id, time=datetime, latitude=0, longitude=0, depth=0)
|
||||||
|
self.origins.append(origin)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def addNotes(self, notes):
|
||||||
|
self.notes = str(notes)
|
||||||
|
|
||||||
|
def clearNotes(self):
|
||||||
|
self.notes = None
|
||||||
|
|
||||||
|
def isRefEvent(self):
|
||||||
|
return self._refEvent
|
||||||
|
|
||||||
|
def isTestEvent(self):
|
||||||
|
return self._testEvent
|
||||||
|
|
||||||
|
def setRefEvent(self, bool):
|
||||||
|
self._refEvent = bool
|
||||||
|
if bool: self._testEvent = False
|
||||||
|
|
||||||
|
def setTestEvent(self, bool):
|
||||||
|
self._testEvent = bool
|
||||||
|
if bool: self._refEvent = False
|
||||||
|
|
||||||
|
def clearObsPyPicks(self, picktype):
|
||||||
|
for index, pick in reversed(list(enumerate(self.picks))):
|
||||||
|
if picktype in str(pick.method_id):
|
||||||
|
self.picks.pop(index)
|
||||||
|
|
||||||
|
def addPicks(self, picks):
|
||||||
|
'''
|
||||||
|
add pylot picks and overwrite existing ones
|
||||||
|
'''
|
||||||
|
for station in picks:
|
||||||
|
self.pylot_picks[station] = picks[station]
|
||||||
|
# add ObsPy picks (clear old manual and copy all new manual from pylot)
|
||||||
|
self.clearObsPyPicks('manual')
|
||||||
|
self.picks += picks_from_picksdict(self.pylot_picks)
|
||||||
|
|
||||||
|
def addAutopicks(self, autopicks):
|
||||||
|
for station in autopicks:
|
||||||
|
self.pylot_autopicks[station] = autopicks[station]
|
||||||
|
# add ObsPy picks (clear old auto and copy all new auto from pylot)
|
||||||
|
self.clearObsPyPicks('auto')
|
||||||
|
self.picks += picks_from_picksdict(self.pylot_autopicks)
|
||||||
|
|
||||||
|
def setPick(self, station, pick):
|
||||||
|
if pick:
|
||||||
|
self.pylot_picks[station] = pick
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
self.pylot_picks.pop(station)
|
||||||
|
except Exception as e:
|
||||||
|
print('Could not remove pick {} from station {}: {}'.format(pick, station, e))
|
||||||
|
self.clearObsPyPicks('manual')
|
||||||
|
self.picks += picks_from_picksdict(self.pylot_picks)
|
||||||
|
|
||||||
|
def setPicks(self, picks):
|
||||||
|
'''
|
||||||
|
set pylot picks and delete and overwrite all existing
|
||||||
|
'''
|
||||||
|
self.pylot_picks = picks
|
||||||
|
self.clearObsPyPicks('manual')
|
||||||
|
self.picks += picks_from_picksdict(self.pylot_picks)
|
||||||
|
|
||||||
|
def getPick(self, station):
|
||||||
|
if station in self.pylot_picks.keys():
|
||||||
|
return self.pylot_picks[station]
|
||||||
|
|
||||||
|
def getPicks(self):
|
||||||
|
return self.pylot_picks
|
||||||
|
|
||||||
|
def setAutopick(self, station, pick):
|
||||||
|
if pick:
|
||||||
|
self.pylot_autopicks[station] = pick
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
self.pylot_autopicks.pop(station)
|
||||||
|
except Exception as e:
|
||||||
|
print('Could not remove pick {} from station {}: {}'.format(pick, station, e))
|
||||||
|
self.clearObsPyPicks('auto')
|
||||||
|
self.picks += picks_from_picksdict(self.pylot_autopicks)
|
||||||
|
|
||||||
|
def setAutopicks(self, picks):
|
||||||
|
'''
|
||||||
|
set pylot picks and delete and overwrite all existing
|
||||||
|
'''
|
||||||
|
self.pylot_autopicks = picks
|
||||||
|
self.clearObsPyPicks('auto')
|
||||||
|
self.picks += picks_from_picksdict(self.pylot_autopicks)
|
||||||
|
|
||||||
|
def getAutopick(self, station):
|
||||||
|
if station in self.pylot_autopicks.keys():
|
||||||
|
return self.pylot_autopicks[station]
|
||||||
|
|
||||||
|
def getAutopicks(self):
|
||||||
|
return self.pylot_autopicks
|
||||||
|
|
||||||
|
def save(self, filename):
|
||||||
|
'''
|
||||||
|
Save PyLoT Event to a file.
|
||||||
|
Can be loaded by using event.load(filename).
|
||||||
|
'''
|
||||||
|
try:
|
||||||
|
import cPickle
|
||||||
|
except ImportError:
|
||||||
|
import _pickle as cPickle
|
||||||
|
|
||||||
|
try:
|
||||||
|
outfile = open(filename, 'wb')
|
||||||
|
cPickle.dump(self, outfile, -1)
|
||||||
|
except Exception as e:
|
||||||
|
print('Could not pickle PyLoT event. Reason: {}'.format(e))
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def load(filename):
|
||||||
|
'''
|
||||||
|
Load project from filename.
|
||||||
|
'''
|
||||||
|
try:
|
||||||
|
import cPickle
|
||||||
|
except ImportError:
|
||||||
|
import _pickle as cPickle
|
||||||
|
infile = open(filename, 'rb')
|
||||||
|
event = cPickle.load(infile)
|
||||||
|
print('Loaded %s' % filename)
|
||||||
|
return event
|
376
pylot/core/util/map_projection.py
Normal file
@ -0,0 +1,376 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
import numpy as np
|
||||||
|
import obspy
|
||||||
|
from PySide import QtGui
|
||||||
|
from matplotlib.backends.backend_qt4agg import NavigationToolbar2QT as NavigationToolbar
|
||||||
|
from mpl_toolkits.basemap import Basemap
|
||||||
|
from pylot.core.util.widgets import PickDlg
|
||||||
|
from scipy.interpolate import griddata
|
||||||
|
|
||||||
|
plt.interactive(False)
|
||||||
|
|
||||||
|
|
||||||
|
class map_projection(QtGui.QWidget):
|
||||||
|
def __init__(self, parent, figure=None):
|
||||||
|
'''
|
||||||
|
|
||||||
|
:param: picked, can be False, auto, manual
|
||||||
|
:value: str
|
||||||
|
'''
|
||||||
|
QtGui.QWidget.__init__(self)
|
||||||
|
self._parent = parent
|
||||||
|
self.metadata = parent.metadata
|
||||||
|
self.parser = parent.metadata[1]
|
||||||
|
self.picks = None
|
||||||
|
self.picks_dict = None
|
||||||
|
self.eventLoc = None
|
||||||
|
self.figure = figure
|
||||||
|
self.init_graphics()
|
||||||
|
self.init_stations()
|
||||||
|
self.init_basemap(resolution='l')
|
||||||
|
self.init_map()
|
||||||
|
# self.show()
|
||||||
|
|
||||||
|
def init_map(self):
|
||||||
|
self.init_lat_lon_dimensions()
|
||||||
|
self.init_lat_lon_grid()
|
||||||
|
self.init_x_y_dimensions()
|
||||||
|
self.connectSignals()
|
||||||
|
self.draw_everything()
|
||||||
|
|
||||||
|
def onpick(self, event):
|
||||||
|
ind = event.ind
|
||||||
|
button = event.mouseevent.button
|
||||||
|
if ind == [] or not button == 1:
|
||||||
|
return
|
||||||
|
data = self._parent.get_data().getWFData()
|
||||||
|
for index in ind:
|
||||||
|
station = str(self.station_names[index].split('.')[-1])
|
||||||
|
try:
|
||||||
|
pickDlg = PickDlg(self, parameter=self._parent._inputs,
|
||||||
|
data=data.select(station=station),
|
||||||
|
station=station,
|
||||||
|
picks=self._parent.get_current_event().getPick(station),
|
||||||
|
autopicks=self._parent.get_current_event().getAutopick(station))
|
||||||
|
except Exception as e:
|
||||||
|
message = 'Could not generate Plot for station {st}.\n {er}'.format(st=station, er=e)
|
||||||
|
self._warn(message)
|
||||||
|
print(message, e)
|
||||||
|
return
|
||||||
|
pyl_mw = self._parent
|
||||||
|
try:
|
||||||
|
if pickDlg.exec_():
|
||||||
|
pyl_mw.setDirty(True)
|
||||||
|
pyl_mw.update_status('picks accepted ({0})'.format(station))
|
||||||
|
replot = pyl_mw.get_current_event().setPick(station, pickDlg.getPicks())
|
||||||
|
self._refresh_drawings()
|
||||||
|
if replot:
|
||||||
|
pyl_mw.plotWaveformData()
|
||||||
|
pyl_mw.drawPicks()
|
||||||
|
pyl_mw.draw()
|
||||||
|
else:
|
||||||
|
pyl_mw.drawPicks(station)
|
||||||
|
pyl_mw.draw()
|
||||||
|
else:
|
||||||
|
pyl_mw.update_status('picks discarded ({0})'.format(station))
|
||||||
|
except Exception as e:
|
||||||
|
message = 'Could not save picks for station {st}.\n{er}'.format(st=station, er=e)
|
||||||
|
self._warn(message)
|
||||||
|
print(message, e)
|
||||||
|
|
||||||
|
def connectSignals(self):
|
||||||
|
self.comboBox_phase.currentIndexChanged.connect(self._refresh_drawings)
|
||||||
|
self.zoom_id = self.basemap.ax.figure.canvas.mpl_connect('scroll_event', self.zoom)
|
||||||
|
|
||||||
|
def init_graphics(self):
|
||||||
|
if not self.figure:
|
||||||
|
if not hasattr(self._parent, 'am_figure'):
|
||||||
|
self.figure = plt.figure()
|
||||||
|
self.toolbar = NavigationToolbar(self.figure.canvas, self)
|
||||||
|
else:
|
||||||
|
self.figure = self._parent.am_figure
|
||||||
|
self.toolbar = self._parent.am_toolbar
|
||||||
|
|
||||||
|
self.main_ax = self.figure.add_subplot(111)
|
||||||
|
self.canvas = self.figure.canvas
|
||||||
|
|
||||||
|
self.main_box = QtGui.QVBoxLayout()
|
||||||
|
self.setLayout(self.main_box)
|
||||||
|
|
||||||
|
self.top_row = QtGui.QHBoxLayout()
|
||||||
|
self.main_box.addLayout(self.top_row)
|
||||||
|
|
||||||
|
self.comboBox_phase = QtGui.QComboBox()
|
||||||
|
self.comboBox_phase.insertItem(0, 'P')
|
||||||
|
self.comboBox_phase.insertItem(1, 'S')
|
||||||
|
|
||||||
|
self.comboBox_am = QtGui.QComboBox()
|
||||||
|
self.comboBox_am.insertItem(0, 'auto')
|
||||||
|
self.comboBox_am.insertItem(1, 'manual')
|
||||||
|
|
||||||
|
self.top_row.addWidget(QtGui.QLabel('Select a phase: '))
|
||||||
|
self.top_row.addWidget(self.comboBox_phase)
|
||||||
|
self.top_row.setStretch(1, 1) # set stretch of item 1 to 1
|
||||||
|
|
||||||
|
self.main_box.addWidget(self.canvas)
|
||||||
|
self.main_box.addWidget(self.toolbar)
|
||||||
|
|
||||||
|
def init_stations(self):
|
||||||
|
def get_station_names_lat_lon(parser):
|
||||||
|
station_names = []
|
||||||
|
lat = []
|
||||||
|
lon = []
|
||||||
|
for station in parser.stations:
|
||||||
|
station_name = station[0].station_call_letters
|
||||||
|
network = station[0].network_code
|
||||||
|
if not station_name in station_names:
|
||||||
|
station_names.append(network + '.' + station_name)
|
||||||
|
lat.append(station[0].latitude)
|
||||||
|
lon.append(station[0].longitude)
|
||||||
|
return station_names, lat, lon
|
||||||
|
|
||||||
|
station_names, lat, lon = get_station_names_lat_lon(self.parser)
|
||||||
|
self.station_names = station_names
|
||||||
|
self.lat = lat
|
||||||
|
self.lon = lon
|
||||||
|
|
||||||
|
def init_picks(self):
|
||||||
|
phase = self.comboBox_phase.currentText()
|
||||||
|
|
||||||
|
def get_picks(station_names):
|
||||||
|
picks = []
|
||||||
|
for station in station_names:
|
||||||
|
try:
|
||||||
|
station = station.split('.')[-1]
|
||||||
|
picks.append(self.picks_dict[station][phase]['mpp'])
|
||||||
|
except:
|
||||||
|
picks.append(np.nan)
|
||||||
|
return picks
|
||||||
|
|
||||||
|
def get_picks_rel(picks):
|
||||||
|
picks_rel = []
|
||||||
|
picks_utc = []
|
||||||
|
for pick in picks:
|
||||||
|
if type(pick) is obspy.core.utcdatetime.UTCDateTime:
|
||||||
|
picks_utc.append(pick)
|
||||||
|
minp = min(picks_utc)
|
||||||
|
for pick in picks:
|
||||||
|
if type(pick) is obspy.core.utcdatetime.UTCDateTime:
|
||||||
|
pick -= minp
|
||||||
|
picks_rel.append(pick)
|
||||||
|
return picks_rel
|
||||||
|
|
||||||
|
self.picks = get_picks(self.station_names)
|
||||||
|
self.picks_rel = get_picks_rel(self.picks)
|
||||||
|
|
||||||
|
def init_picks_active(self):
|
||||||
|
def remove_nan_picks(picks):
|
||||||
|
picks_no_nan = []
|
||||||
|
for pick in picks:
|
||||||
|
if not np.isnan(pick):
|
||||||
|
picks_no_nan.append(pick)
|
||||||
|
return picks_no_nan
|
||||||
|
|
||||||
|
self.picks_no_nan = remove_nan_picks(self.picks_rel)
|
||||||
|
|
||||||
|
def init_stations_active(self):
|
||||||
|
def remove_nan_lat_lon(picks, lat, lon):
|
||||||
|
lat_no_nan = []
|
||||||
|
lon_no_nan = []
|
||||||
|
for index, pick in enumerate(picks):
|
||||||
|
if not np.isnan(pick):
|
||||||
|
lat_no_nan.append(lat[index])
|
||||||
|
lon_no_nan.append(lon[index])
|
||||||
|
return lat_no_nan, lon_no_nan
|
||||||
|
|
||||||
|
self.lat_no_nan, self.lon_no_nan = remove_nan_lat_lon(self.picks_rel, self.lat, self.lon)
|
||||||
|
|
||||||
|
def init_lat_lon_dimensions(self):
|
||||||
|
def get_lon_lat_dim(lon, lat):
|
||||||
|
londim = max(lon) - min(lon)
|
||||||
|
latdim = max(lat) - min(lat)
|
||||||
|
return londim, latdim
|
||||||
|
|
||||||
|
self.londim, self.latdim = get_lon_lat_dim(self.lon, self.lat)
|
||||||
|
|
||||||
|
def init_x_y_dimensions(self):
|
||||||
|
def get_x_y_dim(x, y):
|
||||||
|
xdim = max(x) - min(x)
|
||||||
|
ydim = max(y) - min(y)
|
||||||
|
return xdim, ydim
|
||||||
|
|
||||||
|
self.x, self.y = self.basemap(self.lon, self.lat)
|
||||||
|
self.xdim, self.ydim = get_x_y_dim(self.x, self.y)
|
||||||
|
|
||||||
|
def init_basemap(self, resolution='l'):
|
||||||
|
# basemap = Basemap(projection=projection, resolution = resolution, ax=self.main_ax)
|
||||||
|
basemap = Basemap(projection='lcc', resolution=resolution, ax=self.main_ax,
|
||||||
|
width=5e6, height=2e6,
|
||||||
|
lat_0=(min(self.lat) + max(self.lat)) / 2.,
|
||||||
|
lon_0=(min(self.lon) + max(self.lon)) / 2.)
|
||||||
|
|
||||||
|
# basemap.fillcontinents(color=None, lake_color='aqua',zorder=1)
|
||||||
|
basemap.drawmapboundary(zorder=2) # fill_color='darkblue')
|
||||||
|
basemap.shadedrelief(zorder=3)
|
||||||
|
basemap.drawcountries(zorder=4)
|
||||||
|
basemap.drawstates(zorder=5)
|
||||||
|
basemap.drawcoastlines(zorder=6)
|
||||||
|
self.basemap = basemap
|
||||||
|
self.figure.tight_layout()
|
||||||
|
|
||||||
|
def init_lat_lon_grid(self):
|
||||||
|
def get_lat_lon_axis(lat, lon):
|
||||||
|
steplat = (max(lat) - min(lat)) / 250
|
||||||
|
steplon = (max(lon) - min(lon)) / 250
|
||||||
|
|
||||||
|
lataxis = np.arange(min(lat), max(lat), steplat)
|
||||||
|
lonaxis = np.arange(min(lon), max(lon), steplon)
|
||||||
|
return lataxis, lonaxis
|
||||||
|
|
||||||
|
def get_lat_lon_grid(lataxis, lonaxis):
|
||||||
|
longrid, latgrid = np.meshgrid(lonaxis, lataxis)
|
||||||
|
return latgrid, longrid
|
||||||
|
|
||||||
|
self.lataxis, self.lonaxis = get_lat_lon_axis(self.lat, self.lon)
|
||||||
|
self.latgrid, self.longrid = get_lat_lon_grid(self.lataxis, self.lonaxis)
|
||||||
|
|
||||||
|
def init_picksgrid(self):
|
||||||
|
self.picksgrid_no_nan = griddata((self.lat_no_nan, self.lon_no_nan),
|
||||||
|
self.picks_no_nan, (self.latgrid, self.longrid),
|
||||||
|
method='linear') ##################
|
||||||
|
|
||||||
|
def draw_contour_filled(self, nlevel='50'):
|
||||||
|
levels = np.linspace(min(self.picks_no_nan), max(self.picks_no_nan), nlevel)
|
||||||
|
self.contourf = self.basemap.contourf(self.longrid, self.latgrid, self.picksgrid_no_nan,
|
||||||
|
levels, latlon=True, zorder=9, alpha=0.5)
|
||||||
|
|
||||||
|
def scatter_all_stations(self):
|
||||||
|
self.sc = self.basemap.scatter(self.lon, self.lat, s=50, facecolor='none', latlon=True,
|
||||||
|
zorder=10, picker=True, edgecolor='m', label='Not Picked')
|
||||||
|
self.cid = self.canvas.mpl_connect('pick_event', self.onpick)
|
||||||
|
if self.eventLoc:
|
||||||
|
lat, lon = self.eventLoc
|
||||||
|
self.sc_event = self.basemap.scatter(lon, lat, s=100, facecolor='red',
|
||||||
|
latlon=True, zorder=11, label='Event (might be outside map region)')
|
||||||
|
|
||||||
|
def scatter_picked_stations(self):
|
||||||
|
lon = self.lon_no_nan
|
||||||
|
lat = self.lat_no_nan
|
||||||
|
|
||||||
|
# workaround because of an issue with latlon transformation of arrays with len <3
|
||||||
|
if len(lon) <= 2 and len(lat) <= 2:
|
||||||
|
self.sc_picked = self.basemap.scatter(lon[0], lat[0], s=50, facecolor='white',
|
||||||
|
c=self.picks_no_nan[0], latlon=True, zorder=11, label='Picked')
|
||||||
|
if len(lon) == 2 and len(lat) == 2:
|
||||||
|
self.sc_picked = self.basemap.scatter(lon[1], lat[1], s=50, facecolor='white',
|
||||||
|
c=self.picks_no_nan[1], latlon=True, zorder=11)
|
||||||
|
else:
|
||||||
|
self.sc_picked = self.basemap.scatter(lon, lat, s=50, facecolor='white',
|
||||||
|
c=self.picks_no_nan, latlon=True, zorder=11, label='Picked')
|
||||||
|
|
||||||
|
def annotate_ax(self):
|
||||||
|
self.annotations = []
|
||||||
|
for index, name in enumerate(self.station_names):
|
||||||
|
self.annotations.append(self.main_ax.annotate(' %s' % name, xy=(self.x[index], self.y[index]),
|
||||||
|
fontsize='x-small', color='white', zorder=12))
|
||||||
|
self.legend = self.main_ax.legend(loc=1)
|
||||||
|
|
||||||
|
def add_cbar(self, label):
|
||||||
|
cbar = self.main_ax.figure.colorbar(self.sc_picked, fraction=0.025)
|
||||||
|
cbar.set_label(label)
|
||||||
|
return cbar
|
||||||
|
|
||||||
|
def refresh_drawings(self, picks=None):
|
||||||
|
self.picks_dict = picks
|
||||||
|
self._refresh_drawings()
|
||||||
|
|
||||||
|
def _refresh_drawings(self):
|
||||||
|
self.remove_drawings()
|
||||||
|
self.draw_everything()
|
||||||
|
|
||||||
|
def draw_everything(self):
|
||||||
|
if self.picks_dict:
|
||||||
|
self.init_picks()
|
||||||
|
self.init_picks_active()
|
||||||
|
self.init_stations_active()
|
||||||
|
if len(self.picks_no_nan) >= 3:
|
||||||
|
self.init_picksgrid()
|
||||||
|
self.draw_contour_filled()
|
||||||
|
self.scatter_all_stations()
|
||||||
|
if self.picks_dict:
|
||||||
|
self.scatter_picked_stations()
|
||||||
|
self.cbar = self.add_cbar(label='Time relative to first onset [s]')
|
||||||
|
self.comboBox_phase.setEnabled(True)
|
||||||
|
else:
|
||||||
|
self.comboBox_phase.setEnabled(False)
|
||||||
|
self.annotate_ax()
|
||||||
|
self.canvas.draw()
|
||||||
|
|
||||||
|
def remove_drawings(self):
|
||||||
|
if hasattr(self, 'sc_picked'):
|
||||||
|
self.sc_picked.remove()
|
||||||
|
del (self.sc_picked)
|
||||||
|
if hasattr(self, 'sc_event'):
|
||||||
|
self.sc_event.remove()
|
||||||
|
del (self.sc_event)
|
||||||
|
if hasattr(self, 'cbar'):
|
||||||
|
self.cbar.remove()
|
||||||
|
del (self.cbar)
|
||||||
|
if hasattr(self, 'contourf'):
|
||||||
|
self.remove_contourf()
|
||||||
|
del (self.contourf)
|
||||||
|
if hasattr(self, 'cid'):
|
||||||
|
self.canvas.mpl_disconnect(self.cid)
|
||||||
|
del (self.cid)
|
||||||
|
try:
|
||||||
|
self.sc.remove()
|
||||||
|
except Exception as e:
|
||||||
|
print('Warning: could not remove station scatter plot.\nReason: {}'.format(e))
|
||||||
|
try:
|
||||||
|
self.legend.remove()
|
||||||
|
except Exception as e:
|
||||||
|
print('Warning: could not remove legend. Reason: {}'.format(e))
|
||||||
|
self.canvas.draw()
|
||||||
|
|
||||||
|
def remove_contourf(self):
|
||||||
|
for item in self.contourf.collections:
|
||||||
|
item.remove()
|
||||||
|
|
||||||
|
def remove_annotations(self):
|
||||||
|
for annotation in self.annotations:
|
||||||
|
annotation.remove()
|
||||||
|
|
||||||
|
def zoom(self, event):
|
||||||
|
map = self.basemap
|
||||||
|
xlim = map.ax.get_xlim()
|
||||||
|
ylim = map.ax.get_ylim()
|
||||||
|
x, y = event.xdata, event.ydata
|
||||||
|
zoom = {'up': 1. / 2.,
|
||||||
|
'down': 2.}
|
||||||
|
|
||||||
|
if not event.xdata or not event.ydata:
|
||||||
|
return
|
||||||
|
|
||||||
|
if event.button in zoom:
|
||||||
|
factor = zoom[event.button]
|
||||||
|
xdiff = (xlim[1] - xlim[0]) * factor
|
||||||
|
xl = x - 0.5 * xdiff
|
||||||
|
xr = x + 0.5 * xdiff
|
||||||
|
ydiff = (ylim[1] - ylim[0]) * factor
|
||||||
|
yb = y - 0.5 * ydiff
|
||||||
|
yt = y + 0.5 * ydiff
|
||||||
|
|
||||||
|
if xl < map.xmin or yb < map.ymin or xr > map.xmax or yt > map.ymax:
|
||||||
|
xl, xr = map.xmin, map.xmax
|
||||||
|
yb, yt = map.ymin, map.ymax
|
||||||
|
map.ax.set_xlim(xl, xr)
|
||||||
|
map.ax.set_ylim(yb, yt)
|
||||||
|
map.ax.figure.canvas.draw()
|
||||||
|
|
||||||
|
def _warn(self, message):
|
||||||
|
self.qmb = QtGui.QMessageBox(QtGui.QMessageBox.Icon.Warning,
|
||||||
|
'Warning', message)
|
||||||
|
self.qmb.show()
|
@ -2,20 +2,23 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
import warnings
|
import warnings
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from obspy import UTCDateTime
|
from obspy import UTCDateTime
|
||||||
from pylot.core.util.utils import fit_curve, find_nearest, clims
|
from pylot.core.util.utils import fit_curve, clims
|
||||||
from pylot.core.util.version import get_git_version as _getVersionString
|
from pylot.core.util.version import get_git_version as _getVersionString
|
||||||
|
|
||||||
__version__ = _getVersionString()
|
__version__ = _getVersionString()
|
||||||
__author__ = 'sebastianw'
|
__author__ = 'sebastianw'
|
||||||
|
|
||||||
|
|
||||||
def create_axis(x0, incr, npts):
|
def create_axis(x0, incr, npts):
|
||||||
ax = np.zeros(npts)
|
ax = np.zeros(npts)
|
||||||
for i in range(npts):
|
for i in range(npts):
|
||||||
ax[i] = x0 + incr * i
|
ax[i] = x0 + incr * i
|
||||||
return ax
|
return ax
|
||||||
|
|
||||||
|
|
||||||
def gauss_parameter(te, tm, tl, eta):
|
def gauss_parameter(te, tm, tl, eta):
|
||||||
'''
|
'''
|
||||||
takes three onset times and returns the parameters sig1, sig2, a1 and a2
|
takes three onset times and returns the parameters sig1, sig2, a1 and a2
|
||||||
@ -51,12 +54,15 @@ def exp_parameter(te, tm, tl, eta):
|
|||||||
|
|
||||||
sig1 = np.log(eta) / (te - tm)
|
sig1 = np.log(eta) / (te - tm)
|
||||||
sig2 = np.log(eta) / (tm - tl)
|
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)
|
a = 1 / (1 / sig1 + 1 / sig2)
|
||||||
|
|
||||||
return tm, sig1, sig2, a
|
return tm, sig1, sig2, a
|
||||||
|
|
||||||
|
|
||||||
def gauss_branches(k, (mu, sig1, sig2, a1, a2)):
|
def gauss_branches(k, param_tuple):
|
||||||
'''
|
'''
|
||||||
function gauss_branches takes an axes x, a center value mu, two sigma
|
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
|
values sig1 and sig2 and two scaling factors a1 and a2 and return a
|
||||||
@ -76,6 +82,9 @@ def gauss_branches(k, (mu, sig1, sig2, a1, a2)):
|
|||||||
:returns fun_vals: list with function values along axes x
|
:returns fun_vals: list with function values along axes x
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
# python 3 workaround
|
||||||
|
mu, sig1, sig2, a1, a2 = param_tuple
|
||||||
|
|
||||||
def _func(k, mu, sig1, sig2, a1, a2):
|
def _func(k, mu, sig1, sig2, a1, a2):
|
||||||
if k < mu:
|
if k < mu:
|
||||||
rval = a1 * 1 / (np.sqrt(2 * np.pi) * sig1) * np.exp(-((k - mu) / sig1) ** 2 / 2)
|
rval = a1 * 1 / (np.sqrt(2 * np.pi) * sig1) * np.exp(-((k - mu) / sig1) ** 2 / 2)
|
||||||
@ -90,7 +99,7 @@ def gauss_branches(k, (mu, sig1, sig2, a1, a2)):
|
|||||||
return _func(k, mu, sig1, sig2, a1, a2)
|
return _func(k, mu, sig1, sig2, a1, a2)
|
||||||
|
|
||||||
|
|
||||||
def exp_branches(k, (mu, sig1, sig2, a)):
|
def exp_branches(k, param_tuple):
|
||||||
'''
|
'''
|
||||||
function exp_branches takes an axes x, a center value mu, two sigma
|
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
|
values sig1 and sig2 and a scaling factor a and return a
|
||||||
@ -104,6 +113,9 @@ def exp_branches(k, (mu, sig1, sig2, a)):
|
|||||||
:returns fun_vals: list with function values along axes x:
|
:returns fun_vals: list with function values along axes x:
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
# python 3 workaround
|
||||||
|
mu, sig1, sig2, a = param_tuple
|
||||||
|
|
||||||
def _func(k, mu, sig1, sig2, a):
|
def _func(k, mu, sig1, sig2, a):
|
||||||
mu = float(mu)
|
mu = float(mu)
|
||||||
if k < mu:
|
if k < mu:
|
||||||
@ -236,8 +248,8 @@ class ProbabilityDensityFunction(object):
|
|||||||
self._x = np.array(x)
|
self._x = np.array(x)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_pick(self, lbound, barycentre, rbound, incr=0.001, decfact=0.01,
|
def from_pick(self, lbound, barycentre, rbound, incr=0.1, decfact=0.01,
|
||||||
type='gauss'):
|
type='exp'):
|
||||||
'''
|
'''
|
||||||
Initialize a new ProbabilityDensityFunction object.
|
Initialize a new ProbabilityDensityFunction object.
|
||||||
Takes incr, lbound, barycentre and rbound to derive x0 and the number
|
Takes incr, lbound, barycentre and rbound to derive x0 and the number
|
||||||
@ -304,10 +316,14 @@ class ProbabilityDensityFunction(object):
|
|||||||
:return float: rval
|
:return float: rval
|
||||||
'''
|
'''
|
||||||
|
|
||||||
rval = 0
|
# rval = 0
|
||||||
for x in self.axis:
|
# for x in self.axis:
|
||||||
rval += x * self.data(x)
|
# rval += x * self.data(x)
|
||||||
return rval * self.incr
|
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):
|
def standard_deviation(self):
|
||||||
mu = self.mu
|
mu = self.mu
|
||||||
@ -381,7 +397,6 @@ class ProbabilityDensityFunction(object):
|
|||||||
qu = self.quantile(1 - prob_value)
|
qu = self.quantile(1 - prob_value)
|
||||||
return qu - ql
|
return qu - ql
|
||||||
|
|
||||||
|
|
||||||
def quantile_dist_frac(self, x):
|
def quantile_dist_frac(self, x):
|
||||||
"""
|
"""
|
||||||
takes a probability value and returns the fraction of two
|
takes a probability value and returns the fraction of two
|
||||||
@ -400,7 +415,6 @@ class ProbabilityDensityFunction(object):
|
|||||||
raise ValueError('Value out of range.')
|
raise ValueError('Value out of range.')
|
||||||
return self.quantile_distance(0.5 - x) / self.quantile_distance(x)
|
return self.quantile_distance(0.5 - x) / self.quantile_distance(x)
|
||||||
|
|
||||||
|
|
||||||
def plot(self, label=None):
|
def plot(self, label=None):
|
||||||
import matplotlib.pyplot as plt
|
import matplotlib.pyplot as plt
|
||||||
|
|
||||||
@ -473,4 +487,3 @@ class ProbabilityDensityFunction(object):
|
|||||||
x0, npts = self.commonlimits(incr, other)
|
x0, npts = self.commonlimits(incr, other)
|
||||||
|
|
||||||
return x0, incr, npts
|
return x0, incr, npts
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
import matplotlib.pyplot as plt
|
import matplotlib.pyplot as plt
|
||||||
|
|
||||||
|
|
||||||
def create_bin_list(l_boundary, u_boundary, nbins=100):
|
def create_bin_list(l_boundary, u_boundary, nbins=100):
|
||||||
"""
|
"""
|
||||||
takes two boundaries and a number of bins and creates a list of bins for
|
takes two boundaries and a number of bins and creates a list of bins for
|
||||||
|
@ -1,33 +1,187 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
import sys
|
import sys, os, traceback
|
||||||
from PySide.QtCore import QThread, Signal
|
import multiprocessing
|
||||||
|
from PySide.QtCore import QThread, Signal, Qt, Slot, QRunnable, QObject
|
||||||
|
from PySide.QtGui import QDialog, QProgressBar, QLabel, QHBoxLayout, QPushButton
|
||||||
|
|
||||||
|
|
||||||
class AutoPickThread(QThread):
|
class Thread(QThread):
|
||||||
message = Signal(str)
|
message = Signal(str)
|
||||||
finished = Signal()
|
|
||||||
|
|
||||||
def __init__(self, parent, func, data, param):
|
def __init__(self, parent, func, arg=None, progressText=None,
|
||||||
super(AutoPickThread, self).__init__()
|
pb_widget=None, redirect_stdout=False, abortButton=False):
|
||||||
self.setParent(parent)
|
QThread.__init__(self, parent)
|
||||||
self.func = func
|
self.func = func
|
||||||
self.data = data
|
self.arg = arg
|
||||||
self.param = param
|
self.progressText = progressText
|
||||||
|
self.pb_widget = pb_widget
|
||||||
|
self.redirect_stdout = redirect_stdout
|
||||||
|
self.abortButton = abortButton
|
||||||
|
self.finished.connect(self.hideProgressbar)
|
||||||
|
self.showProgressbar()
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
|
if self.redirect_stdout:
|
||||||
sys.stdout = self
|
sys.stdout = self
|
||||||
|
|
||||||
picks = self.func(self.data, self.param)
|
|
||||||
|
|
||||||
print("Autopicking finished!\n")
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
for station in picks:
|
if self.arg:
|
||||||
self.parent().addPicks(station, picks[station], type='auto')
|
self.data = self.func(self.arg)
|
||||||
except AttributeError:
|
else:
|
||||||
print(picks)
|
self.data = self.func()
|
||||||
|
self._executed = True
|
||||||
|
except Exception as e:
|
||||||
|
self._executed = False
|
||||||
|
self._executedError = e
|
||||||
|
traceback.print_exc()
|
||||||
|
exctype, value = sys.exc_info ()[:2]
|
||||||
|
self._executedErrorInfo = '{} {} {}'.\
|
||||||
|
format(exctype, value, traceback.format_exc())
|
||||||
sys.stdout = sys.__stdout__
|
sys.stdout = sys.__stdout__
|
||||||
self.finished.emit()
|
|
||||||
|
def showProgressbar(self):
|
||||||
|
if self.progressText:
|
||||||
|
|
||||||
|
# generate widget if not given in init
|
||||||
|
if not self.pb_widget:
|
||||||
|
self.pb_widget = QDialog(self.parent())
|
||||||
|
self.pb_widget.setWindowFlags(Qt.SplashScreen)
|
||||||
|
self.pb_widget.setModal(True)
|
||||||
|
|
||||||
|
# add button
|
||||||
|
delete_button = QPushButton('X')
|
||||||
|
delete_button.clicked.connect(self.exit)
|
||||||
|
hl = QHBoxLayout()
|
||||||
|
pb = QProgressBar()
|
||||||
|
pb.setRange(0, 0)
|
||||||
|
hl.addWidget(pb)
|
||||||
|
hl.addWidget(QLabel(self.progressText))
|
||||||
|
if self.abortButton:
|
||||||
|
hl.addWidget(delete_button)
|
||||||
|
self.pb_widget.setLayout(hl)
|
||||||
|
self.pb_widget.show()
|
||||||
|
|
||||||
|
def hideProgressbar(self):
|
||||||
|
if self.pb_widget:
|
||||||
|
self.pb_widget.hide()
|
||||||
|
|
||||||
def write(self, text):
|
def write(self, text):
|
||||||
self.message.emit(text)
|
self.message.emit(text)
|
||||||
|
|
||||||
|
def flush(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class Worker(QRunnable):
|
||||||
|
'''
|
||||||
|
Worker class to be run by MultiThread(QThread).
|
||||||
|
'''
|
||||||
|
def __init__(self, fun, args,
|
||||||
|
progressText=None,
|
||||||
|
pb_widget=None,
|
||||||
|
redirect_stdout=False):
|
||||||
|
super(Worker, self).__init__()
|
||||||
|
self.fun = fun
|
||||||
|
self.args = args
|
||||||
|
#self.kwargs = kwargs
|
||||||
|
self.signals = WorkerSignals()
|
||||||
|
self.progressText = progressText
|
||||||
|
self.pb_widget = pb_widget
|
||||||
|
self.redirect_stdout = redirect_stdout
|
||||||
|
|
||||||
|
@Slot()
|
||||||
|
def run(self):
|
||||||
|
if self.redirect_stdout:
|
||||||
|
sys.stdout = self
|
||||||
|
|
||||||
|
try:
|
||||||
|
result = self.fun(self.args)
|
||||||
|
except:
|
||||||
|
exctype, value = sys.exc_info ()[:2]
|
||||||
|
print(exctype, value, traceback.format_exc())
|
||||||
|
self.signals.error.emit ((exctype, value, traceback.format_exc ()))
|
||||||
|
else:
|
||||||
|
self.signals.result.emit(result)
|
||||||
|
finally:
|
||||||
|
self.signals.finished.emit('Done')
|
||||||
|
sys.stdout = sys.__stdout__
|
||||||
|
|
||||||
|
def write(self, text):
|
||||||
|
self.signals.message.emit(text)
|
||||||
|
|
||||||
|
def flush(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class WorkerSignals(QObject):
|
||||||
|
'''
|
||||||
|
Class to provide signals for Worker Class
|
||||||
|
'''
|
||||||
|
finished = Signal(str)
|
||||||
|
message = Signal(str)
|
||||||
|
error = Signal(tuple)
|
||||||
|
result = Signal(object)
|
||||||
|
|
||||||
|
|
||||||
|
class MultiThread(QThread):
|
||||||
|
finished = Signal(str)
|
||||||
|
message = Signal(str)
|
||||||
|
|
||||||
|
def __init__(self, parent, func, args, ncores=1,
|
||||||
|
progressText=None, pb_widget=None, redirect_stdout=False):
|
||||||
|
QThread.__init__(self, parent)
|
||||||
|
self.func = func
|
||||||
|
self.args = args
|
||||||
|
self.ncores = ncores
|
||||||
|
self.progressText = progressText
|
||||||
|
self.pb_widget = pb_widget
|
||||||
|
self.redirect_stdout = redirect_stdout
|
||||||
|
self.finished.connect(self.hideProgressbar)
|
||||||
|
self.showProgressbar()
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
if self.redirect_stdout:
|
||||||
|
sys.stdout = self
|
||||||
|
try:
|
||||||
|
if not self.ncores:
|
||||||
|
self.ncores = multiprocessing.cpu_count()
|
||||||
|
pool = multiprocessing.Pool(self.ncores)
|
||||||
|
self.data = pool.map_async(self.func, self.args, callback=self.emitDone)
|
||||||
|
#self.data = pool.apply_async(self.func, self.shotlist, callback=self.emitDone) #emit each time returned
|
||||||
|
pool.close()
|
||||||
|
self._executed = True
|
||||||
|
except Exception as e:
|
||||||
|
self._executed = False
|
||||||
|
self._executedError = e
|
||||||
|
exc_type, exc_obj, exc_tb = sys.exc_info()
|
||||||
|
fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
|
||||||
|
print('Exception: {}, file: {}, line: {}'.format(exc_type, fname, exc_tb.tb_lineno))
|
||||||
|
sys.stdout = sys.__stdout__
|
||||||
|
|
||||||
|
def showProgressbar(self):
|
||||||
|
if self.progressText:
|
||||||
|
if not self.pb_widget:
|
||||||
|
self.pb_widget = QDialog(self.parent())
|
||||||
|
self.pb_widget.setWindowFlags(Qt.SplashScreen)
|
||||||
|
self.pb_widget.setModal(True)
|
||||||
|
hl = QHBoxLayout()
|
||||||
|
pb = QProgressBar()
|
||||||
|
pb.setRange(0, 0)
|
||||||
|
hl.addWidget(pb)
|
||||||
|
hl.addWidget(QLabel(self.progressText))
|
||||||
|
self.pb_widget.setLayout(hl)
|
||||||
|
self.pb_widget.show()
|
||||||
|
|
||||||
|
def hideProgressbar(self):
|
||||||
|
if self.pb_widget:
|
||||||
|
self.pb_widget.hide()
|
||||||
|
|
||||||
|
def write(self, text):
|
||||||
|
self.message.emit(text)
|
||||||
|
|
||||||
|
def flush(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def emitDone(self, result):
|
||||||
|
print('emitDone!')
|
||||||
|
self.finished.emit('Done thread!')
|
||||||
|
self.hideProgressbar()
|
||||||
|
@ -2,15 +2,28 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
import hashlib
|
import hashlib
|
||||||
import numpy as np
|
|
||||||
from scipy.interpolate import splrep, splev
|
|
||||||
import os
|
import os
|
||||||
import pwd
|
import platform
|
||||||
import re
|
import re
|
||||||
import subprocess
|
import subprocess
|
||||||
from obspy import UTCDateTime, read
|
|
||||||
from pylot.core.io.inputs import AutoPickParameter
|
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
from obspy import UTCDateTime, read
|
||||||
|
from obspy.core import AttribDict
|
||||||
|
from obspy.signal.rotate import rotate2zne
|
||||||
|
from obspy.io.xseed.utils import SEEDParserException
|
||||||
|
|
||||||
|
from pylot.core.io.inputs import PylotParameter
|
||||||
|
from pylot.styles import style_settings
|
||||||
|
|
||||||
|
from scipy.interpolate import splrep, splev
|
||||||
|
from PySide import QtCore, QtGui
|
||||||
|
|
||||||
|
try:
|
||||||
|
import pyqtgraph as pg
|
||||||
|
except Exception as e:
|
||||||
|
print('PyLoT: Could not import pyqtgraph. {}'.format(e))
|
||||||
|
pg = None
|
||||||
|
|
||||||
def _pickle_method(m):
|
def _pickle_method(m):
|
||||||
if m.im_self is None:
|
if m.im_self is None:
|
||||||
@ -18,9 +31,28 @@ def _pickle_method(m):
|
|||||||
else:
|
else:
|
||||||
return getattr, (m.im_self, m.im_func.func_name)
|
return getattr, (m.im_self, m.im_func.func_name)
|
||||||
|
|
||||||
|
|
||||||
|
def readDefaultFilterInformation(fname):
|
||||||
|
pparam = PylotParameter(fname)
|
||||||
|
return readFilterInformation(pparam)
|
||||||
|
|
||||||
|
|
||||||
|
def readFilterInformation(pylot_parameter):
|
||||||
|
p_filter = {'filtertype': pylot_parameter['filter_type'][0],
|
||||||
|
'freq': [pylot_parameter['minfreq'][0], pylot_parameter['maxfreq'][0]],
|
||||||
|
'order': int(pylot_parameter['filter_order'][0])}
|
||||||
|
s_filter = {'filtertype': pylot_parameter['filter_type'][1],
|
||||||
|
'freq': [pylot_parameter['minfreq'][1], pylot_parameter['maxfreq'][1]],
|
||||||
|
'order': int(pylot_parameter['filter_order'][1])}
|
||||||
|
filter_information = {'P': p_filter,
|
||||||
|
'S': s_filter}
|
||||||
|
return filter_information
|
||||||
|
|
||||||
|
|
||||||
def fit_curve(x, y):
|
def fit_curve(x, y):
|
||||||
return splev, splrep(x, y)
|
return splev, splrep(x, y)
|
||||||
|
|
||||||
|
|
||||||
def getindexbounds(f, eta):
|
def getindexbounds(f, eta):
|
||||||
mi = f.argmax()
|
mi = f.argmax()
|
||||||
m = max(f)
|
m = max(f)
|
||||||
@ -29,19 +61,55 @@ def getindexbounds(f, eta):
|
|||||||
u = find_nearest(f[mi:], b) + mi
|
u = find_nearest(f[mi:], b) + mi
|
||||||
return mi, l, u
|
return mi, l, u
|
||||||
|
|
||||||
def worker(func, input, cores='max', async=False):
|
|
||||||
|
def gen_Pool(ncores=0):
|
||||||
|
'''
|
||||||
|
:param ncores: number of CPU cores for multiprocessing.Pool, if ncores == 0 use all available
|
||||||
|
:return: multiprocessing.Pool object
|
||||||
|
'''
|
||||||
import multiprocessing
|
import multiprocessing
|
||||||
|
|
||||||
if cores == 'max':
|
if ncores == 0:
|
||||||
cores = multiprocessing.cpu_count()
|
ncores = multiprocessing.cpu_count()
|
||||||
|
|
||||||
|
print('gen_Pool: Generated multiprocessing Pool with {} cores\n'.format(ncores))
|
||||||
|
|
||||||
|
pool = multiprocessing.Pool(ncores)
|
||||||
|
return pool
|
||||||
|
|
||||||
|
|
||||||
|
def excludeQualityClasses(picks, qClasses, timeerrorsP, timeerrorsS):
|
||||||
|
'''
|
||||||
|
takes PyLoT picks dictionary and returns a new dictionary with certain classes excluded.
|
||||||
|
:param picks: PyLoT picks dictionary
|
||||||
|
:param qClasses: list (or int) of quality classes (0-4) to exclude
|
||||||
|
:param timeerrorsP: time errors for classes (0-4) for P
|
||||||
|
:param timeerrorsS: time errors for classes (0-4) for S
|
||||||
|
:return: new picks dictionary
|
||||||
|
'''
|
||||||
|
from pylot.core.pick.utils import getQualityFromUncertainty
|
||||||
|
|
||||||
|
if type(qClasses) in [int, float]:
|
||||||
|
qClasses = [qClasses]
|
||||||
|
|
||||||
|
picksdict_new = {}
|
||||||
|
|
||||||
|
phaseError = {'P': timeerrorsP,
|
||||||
|
'S': timeerrorsS}
|
||||||
|
|
||||||
|
for station, phases in picks.items():
|
||||||
|
for phase, pick in phases.items():
|
||||||
|
if not type(pick) in [AttribDict, dict]:
|
||||||
|
continue
|
||||||
|
pickerror = phaseError[identifyPhaseID(phase)]
|
||||||
|
quality = getQualityFromUncertainty(pick['spe'], pickerror)
|
||||||
|
if not quality in qClasses:
|
||||||
|
if not station in picksdict_new:
|
||||||
|
picksdict_new[station] = {}
|
||||||
|
picksdict_new[station][phase] = pick
|
||||||
|
|
||||||
|
return picksdict_new
|
||||||
|
|
||||||
pool = multiprocessing.Pool(cores)
|
|
||||||
if async == True:
|
|
||||||
result = pool.map_async(func, input)
|
|
||||||
else:
|
|
||||||
result = pool.map(func, input)
|
|
||||||
pool.close()
|
|
||||||
return result
|
|
||||||
|
|
||||||
def clims(lim1, lim2):
|
def clims(lim1, lim2):
|
||||||
"""
|
"""
|
||||||
@ -108,6 +176,7 @@ def findComboBoxIndex(combo_box, val):
|
|||||||
"""
|
"""
|
||||||
return combo_box.findText(val) if combo_box.findText(val) is not -1 else 0
|
return combo_box.findText(val) if combo_box.findText(val) is not -1 else 0
|
||||||
|
|
||||||
|
|
||||||
def find_in_list(list, str):
|
def find_in_list(list, str):
|
||||||
"""
|
"""
|
||||||
takes a list of strings and a string and returns the first list item
|
takes a list of strings and a string and returns the first list item
|
||||||
@ -137,6 +206,7 @@ def find_in_list(list, str):
|
|||||||
return rlist[0]
|
return rlist[0]
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def find_nearest(array, value):
|
def find_nearest(array, value):
|
||||||
'''
|
'''
|
||||||
function find_nearest takes an array and a value and returns the
|
function find_nearest takes an array and a value and returns the
|
||||||
@ -184,6 +254,22 @@ def fnConstructor(s):
|
|||||||
return fn
|
return fn
|
||||||
|
|
||||||
|
|
||||||
|
def real_None(value):
|
||||||
|
if value == 'None':
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
def real_Bool(value):
|
||||||
|
if value == 'True':
|
||||||
|
return True
|
||||||
|
elif value == 'False':
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
def four_digits(year):
|
def four_digits(year):
|
||||||
"""
|
"""
|
||||||
takes a two digit year integer and returns the correct four digit equivalent
|
takes a two digit year integer and returns the correct four digit equivalent
|
||||||
@ -260,7 +346,7 @@ def getLogin():
|
|||||||
returns the actual user's login ID
|
returns the actual user's login ID
|
||||||
:return: login ID
|
:return: login ID
|
||||||
'''
|
'''
|
||||||
return pwd.getpwuid(os.getuid())[0]
|
return os.getlogin()
|
||||||
|
|
||||||
|
|
||||||
def getOwner(fn):
|
def getOwner(fn):
|
||||||
@ -270,7 +356,15 @@ def getOwner(fn):
|
|||||||
:type fn: str
|
:type fn: str
|
||||||
:return: login ID of the file's owner
|
:return: login ID of the file's owner
|
||||||
'''
|
'''
|
||||||
|
system_name = platform.system()
|
||||||
|
if system_name in ["Linux", "Darwin"]:
|
||||||
|
import pwd
|
||||||
return pwd.getpwuid(os.stat(fn).st_uid).pw_name
|
return pwd.getpwuid(os.stat(fn).st_uid).pw_name
|
||||||
|
elif system_name == "Windows":
|
||||||
|
import win32security
|
||||||
|
f = win32security.GetFileSecurity(fn, win32security.OWNER_SECURITY_INFORMATION)
|
||||||
|
(username, domain, sid_name_use) = win32security.LookupAccountSid(None, f.GetSecurityDescriptorOwner())
|
||||||
|
return username
|
||||||
|
|
||||||
|
|
||||||
def getPatternLine(fn, pattern):
|
def getPatternLine(fn, pattern):
|
||||||
@ -296,6 +390,7 @@ def getPatternLine(fn, pattern):
|
|||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def is_executable(fn):
|
def is_executable(fn):
|
||||||
"""
|
"""
|
||||||
takes a filename and returns True if the file is executable on the system
|
takes a filename and returns True if the file is executable on the system
|
||||||
@ -364,7 +459,7 @@ def key_for_set_value(d):
|
|||||||
return r
|
return r
|
||||||
|
|
||||||
|
|
||||||
def prepTimeAxis(stime, trace):
|
def prepTimeAxis(stime, trace, verbosity=0):
|
||||||
'''
|
'''
|
||||||
takes a starttime and a trace object and returns a valid time axis for
|
takes a starttime and a trace object and returns a valid time axis for
|
||||||
plotting
|
plotting
|
||||||
@ -378,15 +473,19 @@ def prepTimeAxis(stime, trace):
|
|||||||
etime = stime + nsamp / srate
|
etime = stime + nsamp / srate
|
||||||
time_ax = np.arange(stime, etime, tincr)
|
time_ax = np.arange(stime, etime, tincr)
|
||||||
if len(time_ax) < nsamp:
|
if len(time_ax) < nsamp:
|
||||||
|
if verbosity:
|
||||||
print('elongate time axes by one datum')
|
print('elongate time axes by one datum')
|
||||||
time_ax = np.arange(stime, etime + tincr, tincr)
|
time_ax = np.arange(stime, etime + tincr, tincr)
|
||||||
elif len(time_ax) > nsamp:
|
elif len(time_ax) > nsamp:
|
||||||
|
if verbosity:
|
||||||
print('shorten time axes by one datum')
|
print('shorten time axes by one datum')
|
||||||
time_ax = np.arange(stime, etime - tincr, tincr)
|
time_ax = np.arange(stime, etime - tincr, tincr)
|
||||||
if len(time_ax) != nsamp:
|
if len(time_ax) != nsamp:
|
||||||
raise ValueError('{0} samples of data \n '
|
print('Station {0}, {1} samples of data \n '
|
||||||
'{1} length of time vector \n'
|
'{2} length of time vector \n'
|
||||||
'delta: {2}'.format(nsamp, len(time_ax), tincr))
|
'delta: {3}'.format(trace.stats.station,
|
||||||
|
nsamp, len(time_ax), tincr))
|
||||||
|
time_ax = None
|
||||||
return time_ax
|
return time_ax
|
||||||
|
|
||||||
|
|
||||||
@ -413,6 +512,91 @@ def find_horizontals(data):
|
|||||||
return rval
|
return rval
|
||||||
|
|
||||||
|
|
||||||
|
def make_pen(picktype, phase, key, quality):
|
||||||
|
if pg:
|
||||||
|
rgba = pick_color(picktype, phase, quality)
|
||||||
|
linestyle, width = pick_linestyle_pg(picktype, key)
|
||||||
|
pen = pg.mkPen(rgba, width=width, style=linestyle)
|
||||||
|
return pen
|
||||||
|
|
||||||
|
|
||||||
|
def pick_color(picktype, phase, quality=0):
|
||||||
|
min_quality = 3
|
||||||
|
bpc = base_phase_colors(picktype, phase)
|
||||||
|
rgba = bpc['rgba']
|
||||||
|
modifier = bpc['modifier']
|
||||||
|
intensity = 255.*quality/min_quality
|
||||||
|
rgba = modify_rgba(rgba, modifier, intensity)
|
||||||
|
return rgba
|
||||||
|
|
||||||
|
|
||||||
|
def pick_color_plt(picktype, phase, quality=0):
|
||||||
|
rgba = list(pick_color(picktype, phase, quality))
|
||||||
|
for index, val in enumerate(rgba):
|
||||||
|
rgba[index] /= 255.
|
||||||
|
return rgba
|
||||||
|
|
||||||
|
|
||||||
|
def pick_linestyle_plt(picktype, key):
|
||||||
|
linestyles_manu = {'mpp': ('solid', 2.),
|
||||||
|
'epp': ('dashed', 1.),
|
||||||
|
'lpp': ('dashed', 1.),
|
||||||
|
'spe': ('dashed', 1.)}
|
||||||
|
linestyles_auto = {'mpp': ('dotted', 2.),
|
||||||
|
'epp': ('dashdot', 1.),
|
||||||
|
'lpp': ('dashdot', 1.),
|
||||||
|
'spe': ('dashdot', 1.)}
|
||||||
|
linestyles = {'manual': linestyles_manu,
|
||||||
|
'auto': linestyles_auto}
|
||||||
|
return linestyles[picktype][key]
|
||||||
|
|
||||||
|
|
||||||
|
def pick_linestyle_pg(picktype, key):
|
||||||
|
linestyles_manu = {'mpp': (QtCore.Qt.SolidLine, 2.),
|
||||||
|
'epp': (QtCore.Qt.DashLine, 1.),
|
||||||
|
'lpp': (QtCore.Qt.DashLine, 1.),
|
||||||
|
'spe': (QtCore.Qt.DashLine, 1.)}
|
||||||
|
linestyles_auto = {'mpp': (QtCore.Qt.DotLine, 2.),
|
||||||
|
'epp': (QtCore.Qt.DashDotLine, 1.),
|
||||||
|
'lpp': (QtCore.Qt.DashDotLine, 1.),
|
||||||
|
'spe': (QtCore.Qt.DashDotLine, 1.)}
|
||||||
|
linestyles = {'manual': linestyles_manu,
|
||||||
|
'auto': linestyles_auto}
|
||||||
|
return linestyles[picktype][key]
|
||||||
|
|
||||||
|
|
||||||
|
def modify_rgba(rgba, modifier, intensity):
|
||||||
|
rgba = list(rgba)
|
||||||
|
index = {'r': 0,
|
||||||
|
'g': 1,
|
||||||
|
'b': 2}
|
||||||
|
val = rgba[index[modifier]] + intensity
|
||||||
|
if val > 255.:
|
||||||
|
val = 255.
|
||||||
|
elif val < 0.:
|
||||||
|
val = 0
|
||||||
|
rgba[index[modifier]] = val
|
||||||
|
return tuple(rgba)
|
||||||
|
|
||||||
|
|
||||||
|
def base_phase_colors(picktype, phase):
|
||||||
|
phasecolors = style_settings.phasecolors
|
||||||
|
return phasecolors[picktype][phase]
|
||||||
|
|
||||||
|
def transform_colors_mpl_str(colors, no_alpha=False):
|
||||||
|
colors = list(colors)
|
||||||
|
colors_mpl = tuple([color / 255. for color in colors])
|
||||||
|
if no_alpha:
|
||||||
|
colors_mpl = '({}, {}, {})'.format(*colors_mpl)
|
||||||
|
else:
|
||||||
|
colors_mpl = '({}, {}, {}, {})'.format(*colors_mpl)
|
||||||
|
return colors_mpl
|
||||||
|
|
||||||
|
def transform_colors_mpl(colors):
|
||||||
|
colors = list(colors)
|
||||||
|
colors_mpl = tuple([color / 255. for color in colors])
|
||||||
|
return colors_mpl
|
||||||
|
|
||||||
def remove_underscores(data):
|
def remove_underscores(data):
|
||||||
"""
|
"""
|
||||||
takes a `obspy.core.stream.Stream` object and removes all underscores
|
takes a `obspy.core.stream.Stream` object and removes all underscores
|
||||||
@ -427,6 +611,176 @@ def remove_underscores(data):
|
|||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
def trim_station_components(data, trim_start=True, trim_end=True):
|
||||||
|
'''
|
||||||
|
cut a stream so only the part common to all three traces is kept to avoid dealing with offsets
|
||||||
|
:param data: stream of seismic data
|
||||||
|
:type data: `obspy.core.stream.Stream`
|
||||||
|
:param trim_start: trim start of stream
|
||||||
|
:type trim_start: bool
|
||||||
|
:param trim_end: trim end of stream
|
||||||
|
:type trim_end: bool
|
||||||
|
:return: data stream
|
||||||
|
'''
|
||||||
|
starttime = {False: None}
|
||||||
|
endtime = {False: None}
|
||||||
|
|
||||||
|
stations = get_stations(data)
|
||||||
|
|
||||||
|
print('trim_station_components: Will trim stream for trim_start: {} and for '
|
||||||
|
'trim_end: {}.'.format(trim_start, trim_end))
|
||||||
|
for station in stations:
|
||||||
|
wf_station = data.select(station=station)
|
||||||
|
starttime[True] = max([trace.stats.starttime for trace in wf_station])
|
||||||
|
endtime[True] = min([trace.stats.endtime for trace in wf_station])
|
||||||
|
wf_station.trim(starttime=starttime[trim_start], endtime=endtime[trim_end])
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
def check4gaps(data):
|
||||||
|
'''
|
||||||
|
check for gaps in Stream and remove them
|
||||||
|
:param data: stream of seismic data
|
||||||
|
:return: data stream
|
||||||
|
'''
|
||||||
|
stations = get_stations(data)
|
||||||
|
|
||||||
|
for station in stations:
|
||||||
|
wf_station = data.select(station=station)
|
||||||
|
if wf_station.get_gaps():
|
||||||
|
for trace in wf_station:
|
||||||
|
data.remove(trace)
|
||||||
|
print('check4gaps: Found gaps and removed station {} from waveform data.'.format(station))
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
def check4doubled(data):
|
||||||
|
'''
|
||||||
|
check for doubled stations for same channel in Stream and take only the first one
|
||||||
|
:param data: stream of seismic data
|
||||||
|
:return: data stream
|
||||||
|
'''
|
||||||
|
stations = get_stations(data)
|
||||||
|
|
||||||
|
for station in stations:
|
||||||
|
wf_station = data.select(station=station)
|
||||||
|
# create list of all possible channels
|
||||||
|
channels = []
|
||||||
|
for trace in wf_station:
|
||||||
|
channel = trace.stats.channel
|
||||||
|
if not channel in channels:
|
||||||
|
channels.append(channel)
|
||||||
|
else:
|
||||||
|
print('check4doubled: removed the following trace for station {}, as there is'
|
||||||
|
' already a trace with the same channel given:\n{}'.format(
|
||||||
|
station, trace
|
||||||
|
))
|
||||||
|
data.remove(trace)
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
def get_stations(data):
|
||||||
|
stations = []
|
||||||
|
for tr in data:
|
||||||
|
station = tr.stats.station
|
||||||
|
if not station in stations:
|
||||||
|
stations.append(station)
|
||||||
|
|
||||||
|
return stations
|
||||||
|
|
||||||
|
|
||||||
|
def check4rotated(data, metadata=None, verbosity=1):
|
||||||
|
|
||||||
|
def rotate_components(wfstream, metadata=None):
|
||||||
|
"""rotates components if orientation code is numeric.
|
||||||
|
azimut and dip are fetched from metadata"""
|
||||||
|
try:
|
||||||
|
# indexing fails if metadata is None
|
||||||
|
metadata[0]
|
||||||
|
except:
|
||||||
|
if verbosity:
|
||||||
|
msg = 'Warning: could not rotate traces since no metadata was given\nset Inventory file!'
|
||||||
|
print(msg)
|
||||||
|
return wfstream
|
||||||
|
if metadata[0] is None:
|
||||||
|
# sometimes metadata is (None, (None,))
|
||||||
|
if verbosity:
|
||||||
|
msg = 'Warning: could not rotate traces since no metadata was given\nCheck inventory directory!'
|
||||||
|
print(msg)
|
||||||
|
return wfstream
|
||||||
|
else:
|
||||||
|
parser = metadata[1]
|
||||||
|
|
||||||
|
def get_dip_azimut(parser, trace_id):
|
||||||
|
"""gets azimut and dip for a trace out of the metadata parser"""
|
||||||
|
dip = None
|
||||||
|
azimut = None
|
||||||
|
try:
|
||||||
|
blockettes = parser._select(trace_id)
|
||||||
|
except SEEDParserException as e:
|
||||||
|
print(e)
|
||||||
|
raise ValueError
|
||||||
|
for blockette_ in blockettes:
|
||||||
|
if blockette_.id != 52:
|
||||||
|
continue
|
||||||
|
dip = blockette_.dip
|
||||||
|
azimut = blockette_.azimuth
|
||||||
|
break
|
||||||
|
if dip is None or azimut is None:
|
||||||
|
error_msg = 'Dip and azimuth not available for trace_id {}'.format(trace_id)
|
||||||
|
raise ValueError(error_msg)
|
||||||
|
return dip, azimut
|
||||||
|
|
||||||
|
trace_ids = [trace.id for trace in wfstream]
|
||||||
|
for trace_id in trace_ids:
|
||||||
|
orientation = trace_id[-1]
|
||||||
|
if orientation.isnumeric():
|
||||||
|
# misaligned channels have a number as orientation
|
||||||
|
azimuts = []
|
||||||
|
dips = []
|
||||||
|
for trace_id in trace_ids:
|
||||||
|
try:
|
||||||
|
dip, azimut = get_dip_azimut(parser, trace_id)
|
||||||
|
except ValueError as e:
|
||||||
|
print(e)
|
||||||
|
print('Failed to rotate station {}, no azimuth or dip available in metadata'.format(trace_id))
|
||||||
|
return wfstream
|
||||||
|
azimuts.append(azimut)
|
||||||
|
dips.append(dip)
|
||||||
|
# to rotate all traces must have same length
|
||||||
|
wfstream = trim_station_components(wfstream, trim_start=True, trim_end=True)
|
||||||
|
z, n, e = rotate2zne(wfstream[0], azimuts[0], dips[0],
|
||||||
|
wfstream[1], azimuts[1], dips[1],
|
||||||
|
wfstream[2], azimuts[2], dips[2])
|
||||||
|
print('check4rotated: rotated station {} to ZNE'.format(trace_id))
|
||||||
|
z_index = dips.index(min(dips)) # get z-trace index (dip is measured from 0 to -90
|
||||||
|
wfstream[z_index].data = z
|
||||||
|
wfstream[z_index].stats.channel = wfstream[z_index].stats.channel[0:-1] + 'Z'
|
||||||
|
del trace_ids[z_index]
|
||||||
|
for trace_id in trace_ids:
|
||||||
|
dip, az = get_dip_azimut(parser, trace_id)
|
||||||
|
trace = wfstream.select(id=trace_id)[0]
|
||||||
|
if az > 315 and az <= 45 or az > 135 and az <= 225:
|
||||||
|
trace.data = n
|
||||||
|
trace.stats.channel = trace.stats.channel[0:-1] + 'N'
|
||||||
|
elif az > 45 and az <= 135 or az > 225 and az <= 315:
|
||||||
|
trace.data = e
|
||||||
|
trace.stats.channel = trace.stats.channel[0:-1] + 'E'
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
continue
|
||||||
|
return wfstream
|
||||||
|
|
||||||
|
stations = get_stations(data)
|
||||||
|
|
||||||
|
for station in stations:
|
||||||
|
wf_station = data.select(station=station)
|
||||||
|
wf_station = rotate_components(wf_station, metadata)
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
||||||
def scaleWFData(data, factor=None, components='all'):
|
def scaleWFData(data, factor=None, components='all'):
|
||||||
"""
|
"""
|
||||||
produce scaled waveforms from given waveform data and a scaling factor,
|
produce scaled waveforms from given waveform data and a scaling factor,
|
||||||
@ -477,7 +831,8 @@ def runProgram(cmd, parameter=None):
|
|||||||
|
|
||||||
subprocess.check_output('{} | tee /dev/stderr'.format(cmd), shell=True)
|
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
|
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
|
modified after: http://stackoverflow.com/questions/377017/test-if-executable-exists-in-python
|
||||||
@ -490,9 +845,14 @@ def which(program):
|
|||||||
for key in settings.allKeys():
|
for key in settings.allKeys():
|
||||||
if 'binPath' in key:
|
if 'binPath' in key:
|
||||||
os.environ['PATH'] += ':{0}'.format(settings.value(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):
|
if os.path.exists(bpath):
|
||||||
nllocpath = ":" + AutoPickParameter(bpath).get('nllocbin')
|
nllocpath = ":" + PylotParameter(bpath).get('nllocbin')
|
||||||
os.environ['PATH'] += nllocpath
|
os.environ['PATH'] += nllocpath
|
||||||
except ImportError as e:
|
except ImportError as e:
|
||||||
print(e.message)
|
print(e.message)
|
||||||
@ -518,6 +878,61 @@ def which(program):
|
|||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def loopIdentifyPhase(phase):
|
||||||
|
'''
|
||||||
|
Loop through phase string and try to recognize its type (P or S wave).
|
||||||
|
Global variable ALTSUFFIX gives alternative suffix for phases if they do not end with P, p or S, s.
|
||||||
|
If ALTSUFFIX is not given, the function will cut the last letter of the phase string until string ends
|
||||||
|
with P or S.
|
||||||
|
:param phase: phase name (str)
|
||||||
|
:return:
|
||||||
|
'''
|
||||||
|
from pylot.core.util.defaults import ALTSUFFIX
|
||||||
|
|
||||||
|
phase_copy = phase
|
||||||
|
while not identifyPhase(phase_copy):
|
||||||
|
identified = False
|
||||||
|
for alt_suf in ALTSUFFIX:
|
||||||
|
if phase_copy.endswith(alt_suf):
|
||||||
|
phase_copy = phase_copy.split(alt_suf)[0]
|
||||||
|
identified = True
|
||||||
|
if not identified:
|
||||||
|
phase_copy = phase_copy[:-1]
|
||||||
|
if len(phase_copy) < 1:
|
||||||
|
print('Warning: Could not identify phase {}!'.format(phase))
|
||||||
|
return
|
||||||
|
return phase_copy
|
||||||
|
|
||||||
|
|
||||||
|
def identifyPhase(phase):
|
||||||
|
'''
|
||||||
|
Returns capital P or S if phase string is identified by last letter. Else returns False.
|
||||||
|
:param phase: phase name (str)
|
||||||
|
:return: 'P', 'S' or False
|
||||||
|
'''
|
||||||
|
# common phase suffix for P and S
|
||||||
|
common_P = ['P', 'p']
|
||||||
|
common_S = ['S', 's']
|
||||||
|
if phase[-1] in common_P:
|
||||||
|
return 'P'
|
||||||
|
if phase[-1] in common_S:
|
||||||
|
return 'S'
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def identifyPhaseID(phase):
|
||||||
|
return identifyPhase(loopIdentifyPhase(phase))
|
||||||
|
|
||||||
|
|
||||||
|
def has_spe(pick):
|
||||||
|
if not 'spe' in pick.keys():
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
return pick['spe']
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
import doctest
|
import doctest
|
||||||
|
|
||||||
|