coppied files from Ludgers Laptop
97
QtPyLoT.py
@ -15,7 +15,7 @@ Some icons are out of a free of charge icon set, which can be found here:
|
||||
https://www.iconfinder.com/iconsets/flavour
|
||||
|
||||
:author:
|
||||
Sebastian Wehling-Benatelli
|
||||
Sebastian Wehling-Benatelli / Ludger Küperkoch
|
||||
:copyright:
|
||||
The PyLoT Development Team (https://ariadne.geophysik.rub.de/trac/PyLoT)
|
||||
:license:
|
||||
@ -25,14 +25,13 @@ https://www.iconfinder.com/iconsets/flavour
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
import matplotlib
|
||||
|
||||
matplotlib.use('Qt4Agg')
|
||||
matplotlib.rcParams['backend.qt4'] = 'PySide'
|
||||
|
||||
from PySide.QtCore import QCoreApplication, QSettings, Signal, QFile, \
|
||||
QFileInfo, Qt
|
||||
QFileInfo, Qt, QSize
|
||||
from PySide.QtGui import QMainWindow, QInputDialog, QIcon, QFileDialog, \
|
||||
QWidget, QHBoxLayout, QStyle, QKeySequence, QLabel, QFrame, QAction, \
|
||||
QDialog, QErrorMessage, QApplication, QPixmap, QMessageBox, QSplashScreen, \
|
||||
@ -43,13 +42,13 @@ from obspy import UTCDateTime
|
||||
from pylot.core.analysis.magnitude import RichterMagnitude, MomentMagnitude
|
||||
from pylot.core.io.data import Data
|
||||
from pylot.core.io.inputs import FilterOptions, AutoPickParameter
|
||||
from pylot.core.pick.autopick import autopickevent
|
||||
#from pylot.core.pick.autopick import autopickevent
|
||||
from autoPyLoT import autoPyLoT
|
||||
from pylot.core.pick.compare import Comparison
|
||||
from pylot.core.pick.utils import symmetrize_error
|
||||
from pylot.core.io.phases import picksdict_from_picks
|
||||
import pylot.core.loc.nll as nll
|
||||
from pylot.core.util.defaults import FILTERDEFAULTS, COMPNAME_MAP, \
|
||||
AUTOMATIC_DEFAULTS
|
||||
from pylot.core.util.defaults import FILTERDEFAULTS, COMPNAME_MAP
|
||||
from pylot.core.util.errors import FormatError, DatastructureError, \
|
||||
OverwriteError, ProcessingError
|
||||
from pylot.core.util.connection import checkurl
|
||||
@ -78,15 +77,23 @@ class MainWindow(QMainWindow):
|
||||
self.createAction = createAction
|
||||
# read settings
|
||||
settings = QSettings()
|
||||
# check for default pylot.in-file
|
||||
infile = os.path.join(os.path.expanduser('~'), '.pylot', 'pylot.in')
|
||||
self._inputs = AutoPickParameter(infile)
|
||||
if os.path.isfile(infile)== False:
|
||||
infile = QFileDialog().getOpenFileName(caption='Choose PyLoT-input file',
|
||||
filter='*.in')
|
||||
self.infile = infile[0]
|
||||
else:
|
||||
self.infile = infile
|
||||
|
||||
self._inputs = AutoPickParameter(self.infile)
|
||||
if settings.value("user/FullName", None) is None:
|
||||
fulluser = QInputDialog.getText(self, "Enter Name:", "Full name")
|
||||
settings.setValue("user/FullName", fulluser)
|
||||
settings.setValue("user/Login", getLogin())
|
||||
if settings.value("agency_id", None) is None:
|
||||
agency = QInputDialog.getText(self,
|
||||
"Enter authority name (e.g. BUG):",
|
||||
"Enter authority/institution name:",
|
||||
"Authority")
|
||||
settings.setValue("agency_id", agency)
|
||||
self.recentfiles = settings.value("data/recentEvents", [])
|
||||
@ -164,16 +171,20 @@ class MainWindow(QMainWindow):
|
||||
lambda event: self.tutor_user())
|
||||
_layout.addWidget(self.DataPlot)
|
||||
|
||||
manupicksicon = self.style().standardIcon(QStyle.SP_DialogYesButton)
|
||||
autopicksicon = self.style().standardIcon(QStyle.SP_DialogNoButton)
|
||||
locactionicon = self.style().standardIcon(QStyle.SP_DirOpenIcon)
|
||||
loadpiloticon = self.style().standardIcon(QStyle.SP_ComputerIcon)
|
||||
quitIcon = self.style().standardIcon(QStyle.SP_MediaStop)
|
||||
saveIcon = self.style().standardIcon(QStyle.SP_DriveHDIcon)
|
||||
helpIcon = self.style().standardIcon(QStyle.SP_DialogHelpButton)
|
||||
newIcon = self.style().standardIcon(QStyle.SP_FileIcon)
|
||||
|
||||
# create resource icons
|
||||
locactionicon = QIcon()
|
||||
locactionicon.addPixmap(QPixmap(':/icons/locactionicon.png'))
|
||||
manupicksicon = QIcon()
|
||||
manupicksicon.addPixmap(QPixmap(':/icons/manupicsicon.png'))
|
||||
autopicksicon = QIcon()
|
||||
autopicksicon.addPixmap(QPixmap(':/icons/autopicsicon.png'))
|
||||
loadpiloticon = QIcon()
|
||||
loadpiloticon.addPixmap(QPixmap(':/icons/Matlab_PILOT_icon.png'))
|
||||
p_icon = QIcon()
|
||||
p_icon.addPixmap(QPixmap(':/icons/key_P.png'))
|
||||
s_icon = QIcon()
|
||||
@ -189,12 +200,11 @@ class MainWindow(QMainWindow):
|
||||
e_icon = QIcon()
|
||||
e_icon.addPixmap(QPixmap(':/icons/key_E.png'))
|
||||
auto_icon = QIcon()
|
||||
auto_icon.addPixmap(QPixmap(':/icons/sync.png'))
|
||||
auto_icon.addPixmap(QPixmap(':/icons/autopick_button.png'))
|
||||
locate_icon = QIcon()
|
||||
locate_icon.addPixmap(QPixmap(':/icons/locate.png'))
|
||||
locate_icon.addPixmap(QPixmap(':/icons/locate_button.png'))
|
||||
compare_icon = QIcon()
|
||||
compare_icon.addPixmap(QPixmap(':/icons/compare.png'))
|
||||
|
||||
compare_icon.addPixmap(QPixmap(':/icons/compare_button.png'))
|
||||
newEventAction = self.createAction(self, "&New event ...",
|
||||
self.createNewEvent,
|
||||
QKeySequence.New, newIcon,
|
||||
@ -203,28 +213,29 @@ class MainWindow(QMainWindow):
|
||||
self.load_data,
|
||||
QKeySequence.Open,
|
||||
manupicksicon,
|
||||
"Load pick data for "
|
||||
"the actual event.")
|
||||
"Load manual picks for "
|
||||
"the displayed event.")
|
||||
openmanualpicksaction.setData(None)
|
||||
openautopicksaction = self.createAction(self, "Load &automatic picks "
|
||||
"...",
|
||||
self.load_autopicks,
|
||||
"Ctrl+A",
|
||||
autopicksicon,
|
||||
"Load automatic pick data "
|
||||
"for the actual event.")
|
||||
"Load automatic picks "
|
||||
"for the displayed event.")
|
||||
openautopicksaction.setData(None)
|
||||
|
||||
loadlocationaction = self.createAction(self, "Load &location ...",
|
||||
self.load_loc, "Ctrl+L",
|
||||
locactionicon,
|
||||
"Load location information on "
|
||||
"the actual event.")
|
||||
"the displayed event.")
|
||||
loadpilotevent = self.createAction(self, "Load PILOT &event ...",
|
||||
self.load_pilotevent, "Ctrl+E",
|
||||
loadpiloticon,
|
||||
"Load PILOT event from information "
|
||||
"Matlab binary collections.")
|
||||
"MatLab binary collections (created"
|
||||
" in former MatLab based version).")
|
||||
saveEventAction = self.createAction(self, "&Save event ...",
|
||||
self.saveData, QKeySequence.Save,
|
||||
saveIcon, "Save actual event data.")
|
||||
@ -269,7 +280,7 @@ class MainWindow(QMainWindow):
|
||||
printAction = self.createAction(self, "&Print event ...",
|
||||
self.show_event_information, QKeySequence.Print,
|
||||
print_icon,
|
||||
"Print waveform overview.")
|
||||
"Print waveform section.")
|
||||
helpAction = self.createAction(self, "&Help ...", self.helpHelp,
|
||||
QKeySequence.HelpContents, helpIcon,
|
||||
"""Show either the documentation
|
||||
@ -347,13 +358,12 @@ class MainWindow(QMainWindow):
|
||||
# pickToolActions = (selectStation, )
|
||||
# pickToolBar.setObjectName("PickTools")
|
||||
# self.addActions(pickToolBar, pickToolActions)
|
||||
|
||||
locateEvent = self.createAction(parent=self, text='locate_event',
|
||||
locateEvent = self.createAction(parent=self, text='locate the event',
|
||||
slot=self.locate_event,
|
||||
shortcut='Alt+Ctrl+L',
|
||||
icon=locate_icon,
|
||||
tip='Locate the event using '
|
||||
'the picked arrivals.')
|
||||
'the displayed manual arrivals.')
|
||||
|
||||
locationToolBar = self.addToolBar("LocationTools")
|
||||
locationToolActions = (locateEvent,)
|
||||
@ -586,8 +596,7 @@ class MainWindow(QMainWindow):
|
||||
ans = QMessageBox.question(self, self.tr("Overwrite file..."),
|
||||
self.tr("File already exists: {0}\n".format(fbasename + exform) + \
|
||||
"Overwrite file anyway?"),
|
||||
QMessageBox.Cancel, QMessageBox.Yes | QMessageBox.No,
|
||||
QMessageBox.Cancel)
|
||||
QMessageBox.Yes | QMessageBox.No | QMessageBox.Cancel)
|
||||
# only negative answers have to be caught
|
||||
if ans == QMessageBox.No:
|
||||
self.saveData()
|
||||
@ -601,6 +610,9 @@ class MainWindow(QMainWindow):
|
||||
self.update_status('Event saved as %s' % (fbasename + exform))
|
||||
return True
|
||||
|
||||
def getinfile(self):
|
||||
return self.infile
|
||||
|
||||
def getComponent(self):
|
||||
return self.dispComponent
|
||||
|
||||
@ -804,7 +816,8 @@ class MainWindow(QMainWindow):
|
||||
station = self.getStationName(wfID)
|
||||
self.update_status('picking on station {0}'.format(station))
|
||||
data = self.get_data().getWFData()
|
||||
pickDlg = PickDlg(self, data=data.select(station=station),
|
||||
pickDlg = PickDlg(self, infile=self.getinfile(),
|
||||
data=data.select(station=station),
|
||||
station=station,
|
||||
picks=self.getPicksOnStation(station))
|
||||
if pickDlg.exec_():
|
||||
@ -830,6 +843,7 @@ class MainWindow(QMainWindow):
|
||||
self.listWidget.scrollToBottom()
|
||||
|
||||
def autoPick(self):
|
||||
self.autosave = QFileDialog().getExistingDirectory(caption='Select autoPyLoT output')
|
||||
self.listWidget = QListWidget()
|
||||
self.setDirty(True)
|
||||
self.logDockWidget = QDockWidget("AutoPickLog", self)
|
||||
@ -838,18 +852,17 @@ class MainWindow(QMainWindow):
|
||||
Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea)
|
||||
self.logDockWidget.setWidget(self.listWidget)
|
||||
self.addDockWidget(Qt.LeftDockWidgetArea, self.logDockWidget)
|
||||
self.addListItem('loading default values for local data ...')
|
||||
# may become obsolete if generalized input parameter a read from disc
|
||||
# during initialization
|
||||
# TODO double check for obsolete read in of parameters
|
||||
autopick_parameter = AutoPickParameter(AUTOMATIC_DEFAULTS)
|
||||
self.addListItem('Loading default values from PyLoT-input file %s'
|
||||
% self.infile)
|
||||
autopick_parameter = self._inputs
|
||||
self.addListItem(str(autopick_parameter))
|
||||
|
||||
# Create the worker thread and run it
|
||||
self.thread = AutoPickThread(parent=self,
|
||||
func=autopickevent,
|
||||
data=self.get_data().getWFData(),
|
||||
param=autopick_parameter)
|
||||
func=autoPyLoT,
|
||||
infile = self.infile,
|
||||
fnames=self.fnames,
|
||||
savepath=self.autosave)
|
||||
|
||||
self.thread.message.connect(self.addListItem)
|
||||
self.thread.start()
|
||||
self.thread.finished.connect(self.finalizeAutoPick)
|
||||
@ -1128,7 +1141,7 @@ class MainWindow(QMainWindow):
|
||||
QMainWindow.closeEvent(self, event)
|
||||
|
||||
def PyLoTprefs(self):
|
||||
props = PropertiesDlg(self)
|
||||
props = PropertiesDlg(self, infile=self.getinfile())
|
||||
if props.exec_():
|
||||
return
|
||||
|
||||
@ -1153,11 +1166,15 @@ def main():
|
||||
|
||||
# create the main window
|
||||
pylot_form = MainWindow()
|
||||
icon = QIcon()
|
||||
pylot_form.setWindowIcon(icon)
|
||||
pylot_form.setIconSize(QSize(60, 60))
|
||||
|
||||
splash.showMessage('Loading. Please wait ...')
|
||||
pylot_app.processEvents()
|
||||
|
||||
# set Application Information
|
||||
pylot_app.setOrganizationName("Ruhr-University Bochum / MAGS2")
|
||||
pylot_app.setOrganizationName("Ruhr-University Bochum / BESTEC")
|
||||
pylot_app.setOrganizationDomain("rub.de")
|
||||
pylot_app.processEvents()
|
||||
pylot_app.setApplicationName("PyLoT")
|
||||
|
22
README.md
@ -16,12 +16,12 @@ benefit a lot compared to the former MatLab version.
|
||||
|
||||
The development of PyLoT is part of the joint research project MAGS2.
|
||||
|
||||
##Installation
|
||||
## Installation
|
||||
|
||||
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.
|
||||
|
||||
####prerequisites:
|
||||
#### Prerequisites:
|
||||
|
||||
In order to run PyLoT you need to install:
|
||||
|
||||
@ -32,7 +32,7 @@ In order to run PyLoT you need to install:
|
||||
- obspy
|
||||
- pyside
|
||||
|
||||
####some handwork
|
||||
#### Some handwork:
|
||||
|
||||
PyLoT needs a properties folder on your system to work. It should be situated in your home directory:
|
||||
|
||||
@ -59,10 +59,9 @@ You may need to do some modifications to these files. Especially folder names sh
|
||||
PyLoT has been tested on Mac OSX (10.11) and Debian Linux 8.
|
||||
|
||||
|
||||
##release notes:
|
||||
==============
|
||||
## Release notes
|
||||
|
||||
#### Features
|
||||
#### Features:
|
||||
|
||||
- consistent manual phase picking through predefined SNR dependant zoom level
|
||||
- uniform uncertainty estimation from waveform's properties for automatic and manual picks
|
||||
@ -70,21 +69,20 @@ PyLoT has been tested on Mac OSX (10.11) and Debian Linux 8.
|
||||
- Richter and moment magnitude estimation
|
||||
- location determination with external installation of [NonLinLoc](http://alomax.free.fr/nlloc/index.html)
|
||||
|
||||
#### Known issues
|
||||
#### Known issues:
|
||||
|
||||
- Magnitude estimation from manual PyLoT takes some time (instrument correction)
|
||||
|
||||
We hope to solve these with the next release.
|
||||
|
||||
####staff:
|
||||
======
|
||||
## Staff
|
||||
|
||||
original author(s): L. Kueperkoch, S. Wehling-Benatelli, M. Bischoff (PILOT)
|
||||
Original author(s): L. Kueperkoch, S. Wehling-Benatelli, M. Bischoff (PILOT)
|
||||
|
||||
developer(s): S. Wehling-Benatelli, L. Kueperkoch, K. Olbert, M. Bischoff,
|
||||
Developer(s): S. Wehling-Benatelli, L. Kueperkoch, K. Olbert, M. Bischoff,
|
||||
C. Wollin, M. Rische, M. Paffrath
|
||||
|
||||
others: A. Bruestle, T. Meier, W. Friederich
|
||||
Others: A. Bruestle, T. Meier, W. Friederich
|
||||
|
||||
|
||||
[ObsPy]: http://github.com/obspy/obspy/wiki
|
||||
|
124
autoPyLoT.py
Executable file → Normal file
@ -6,11 +6,17 @@ from __future__ import print_function
|
||||
import argparse
|
||||
import glob
|
||||
import os
|
||||
|
||||
import datetime
|
||||
from obspy import read_events
|
||||
|
||||
import pylot.core.loc.hsat as hsat
|
||||
import pylot.core.loc.hyposat as hyposat
|
||||
import pylot.core.loc.hypo71 as hypo71
|
||||
import pylot.core.loc.velest as velest
|
||||
import pylot.core.loc.hypodd as hypodd
|
||||
import pylot.core.loc.focmec as focmec
|
||||
import pylot.core.loc.hash as hash
|
||||
import pylot.core.loc.nll as nll
|
||||
#from PySide.QtGui import QWidget, QInputDialog
|
||||
from pylot.core.analysis.magnitude import MomentMagnitude, RichterMagnitude
|
||||
from pylot.core.io.data import Data
|
||||
from pylot.core.io.inputs import AutoPickParameter
|
||||
@ -23,7 +29,7 @@ from pylot.core.util.version import get_git_version as _getVersionString
|
||||
__version__ = _getVersionString()
|
||||
|
||||
|
||||
def autoPyLoT(inputfile):
|
||||
def autoPyLoT(inputfile, fnames=None, savepath=None):
|
||||
"""
|
||||
Determine phase onsets automatically utilizing the automatic picking
|
||||
algorithms by Kueperkoch et al. 2010/2012.
|
||||
@ -43,14 +49,13 @@ def autoPyLoT(inputfile):
|
||||
Version {version} 2015\n
|
||||
\n
|
||||
Authors:\n
|
||||
S. Wehling-Benatelli (Ruhr-Universität Bochum)\n
|
||||
L. Küperkoch (BESTEC GmbH, Landau i. d. Pfalz)\n
|
||||
K. Olbert (Christian-Albrechts Universität zu Kiel)\n
|
||||
S. Wehling-Benatelli (Ruhr-Universitaet Bochum)\n
|
||||
L. Kueperkoch (BESTEC GmbH, Landau i. d. Pfalz)\n
|
||||
K. Olbert (Christian-Albrechts Universitaet zu Kiel)\n
|
||||
***********************************'''.format(version=_getVersionString())
|
||||
print(splash)
|
||||
|
||||
# reading parameter file
|
||||
|
||||
parameter = AutoPickParameter(inputfile)
|
||||
|
||||
data = Data()
|
||||
@ -65,8 +70,8 @@ def autoPyLoT(inputfile):
|
||||
'dbase': parameter.get('database')}
|
||||
|
||||
exf = ['root', 'dpath', 'dbase']
|
||||
|
||||
if parameter.hasParam('eventID'):
|
||||
|
||||
if parameter.hasParam('eventID') and fnames == 'None':
|
||||
dsfields['eventID'] = parameter.get('eventID')
|
||||
exf.append('eventID')
|
||||
|
||||
@ -100,22 +105,51 @@ def autoPyLoT(inputfile):
|
||||
print(" !!! ")
|
||||
|
||||
datapath = datastructure.expandDataPath()
|
||||
if not parameter.hasParam('eventID'):
|
||||
if fnames == 'None' and not parameter.hasParam('eventID'):
|
||||
# multiple event processing
|
||||
# read each event in database
|
||||
events = [events for events in glob.glob(os.path.join(datapath, '*')) if os.path.isdir(events)]
|
||||
else:
|
||||
elif fnames == 'None' and parameter.hasParam('eventID'):
|
||||
# single event processing
|
||||
events = glob.glob(os.path.join(datapath, parameter.get('eventID')))
|
||||
else:
|
||||
# autoPyLoT was initialized from GUI
|
||||
events = fnames
|
||||
|
||||
for event in events:
|
||||
data.setWFData(glob.glob(os.path.join(datapath, event, '*')))
|
||||
evID = os.path.split(event)[-1]
|
||||
print('Working on event %s' % event)
|
||||
print(data)
|
||||
if fnames == 'None':
|
||||
data.setWFData(glob.glob(os.path.join(datapath, event, '*')))
|
||||
evID = os.path.split(event)[-1]
|
||||
# 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)
|
||||
event = savepath
|
||||
now = datetime.datetime.now()
|
||||
evID = '%d%02d%02d%02d%02d' % (now.year,
|
||||
now.month,
|
||||
now.day,
|
||||
now.hour,
|
||||
now.minute)
|
||||
parameter.setParam(eventID=evID)
|
||||
wfdat = data.getWFData() # all available streams
|
||||
wfdat = remove_underscores(wfdat)
|
||||
metadata = read_metadata(parameter.get('invdir'))
|
||||
corr_dat, rest_flag = restitute_data(wfdat.copy(), *metadata)
|
||||
|
||||
print('Working on event %s' % event)
|
||||
print(data)
|
||||
##########################################################
|
||||
# !automated picking starts here!
|
||||
picks = autopickevent(wfdat, parameter)
|
||||
@ -123,7 +157,7 @@ def autoPyLoT(inputfile):
|
||||
# locating
|
||||
if locflag == 1:
|
||||
# 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!
|
||||
nllocout = '%s_%s' % (evID, nllocoutpatter)
|
||||
@ -132,7 +166,7 @@ def autoPyLoT(inputfile):
|
||||
ttpat)
|
||||
|
||||
# locate the event
|
||||
nll.locate(ctrfile)
|
||||
nll.locate(ctrfile, inputfile)
|
||||
|
||||
# !iterative picking if traces remained unpicked or occupied with bad picks!
|
||||
# get theoretical onset times for picks with weights >= 4
|
||||
@ -157,13 +191,15 @@ def autoPyLoT(inputfile):
|
||||
# calculating seismic moment Mo and moment magnitude Mw
|
||||
moment_mag = MomentMagnitude(corr_dat, evt, parameter.get('vp'),
|
||||
parameter.get('Qp'),
|
||||
parameter.get('rho'), True, 0)
|
||||
parameter.get('rho'), True, \
|
||||
parameter.get('iplot'))
|
||||
# update pick with moment property values (w0, fc, Mo)
|
||||
for station, props in moment_mag.moment_props.items():
|
||||
picks[station]['P'].update(props)
|
||||
evt = moment_mag.updated_event()
|
||||
local_mag = RichterMagnitude(corr_dat, evt,
|
||||
parameter.get('sstop'), True, 0)
|
||||
parameter.get('sstop'), True,\
|
||||
parameter.get('iplot'))
|
||||
for station, amplitude in local_mag.amplitudes.items():
|
||||
picks[station]['S']['Ao'] = amplitude.generic_amplitude
|
||||
evt = local_mag.updated_event()
|
||||
@ -185,11 +221,11 @@ def autoPyLoT(inputfile):
|
||||
print("autoPyLoT: Starting with iteration No. %d ..." % nlloccounter)
|
||||
picks = iteratepicker(wfdat, nllocfile, picks, badpicks, parameter)
|
||||
# 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
|
||||
os.remove(nllocfile)
|
||||
# locate the event
|
||||
nll.locate(ctrfile)
|
||||
nll.locate(ctrfile, inputfile)
|
||||
print("autoPyLoT: Iteration No. %d finished." % nlloccounter)
|
||||
# get updated NLLoc-location file
|
||||
nllocfile = max(glob.glob(locsearch), key=os.path.getctime)
|
||||
@ -207,13 +243,15 @@ def autoPyLoT(inputfile):
|
||||
# calculating seismic moment Mo and moment magnitude Mw
|
||||
moment_mag = MomentMagnitude(corr_dat, evt, parameter.get('vp'),
|
||||
parameter.get('Qp'),
|
||||
parameter.get('rho'), True, 0)
|
||||
parameter.get('rho'), True, \
|
||||
parameter.get('iplot'))
|
||||
# update pick with moment property values (w0, fc, Mo)
|
||||
for station, props in moment_mag.moment_props.items():
|
||||
picks[station]['P'].update(props)
|
||||
evt = moment_mag.updated_event()
|
||||
local_mag = RichterMagnitude(corr_dat, evt,
|
||||
parameter.get('sstop'), True, 0)
|
||||
parameter.get('sstop'), True, \
|
||||
parameter.get('iplot'))
|
||||
for station, amplitude in local_mag.amplitudes.items():
|
||||
picks[station]['S']['Ao'] = amplitude.generic_amplitude
|
||||
evt = local_mag.updated_event()
|
||||
@ -221,16 +259,35 @@ def autoPyLoT(inputfile):
|
||||
print("Network moment magnitude: %4.1f" % net_mw.mag)
|
||||
else:
|
||||
print("autoPyLoT: No NLLoc-location file available! Stop iteration!")
|
||||
locflag = 9
|
||||
##########################################################
|
||||
# write phase files for various location routines
|
||||
# HYPO71
|
||||
hypo71file = '%s/autoPyLoT_HYPO71.pha' % event
|
||||
hsat.export(picks, hypo71file)
|
||||
# write phase files for various location
|
||||
# and fault mechanism calculation routines
|
||||
# ObsPy event object
|
||||
data.applyEVTData(picks)
|
||||
if evt is not None:
|
||||
data.applyEVTData(evt, 'event')
|
||||
fnqml = '%s/autoPyLoT' % event
|
||||
data.exportEvent(fnqml)
|
||||
# HYPO71
|
||||
hypo71file = '%s/autoPyLoT_HYPO71_phases' % event
|
||||
hypo71.export(picks, hypo71file, parameter)
|
||||
# HYPOSAT
|
||||
hyposatfile = '%s/autoPyLoT_HYPOSAT_phases' % event
|
||||
hyposat.export(picks, hyposatfile, parameter)
|
||||
if locflag == 1:
|
||||
# VELEST
|
||||
velestfile = '%s/autoPyLoT_VELEST_phases.cnv' % event
|
||||
velest.export(picks, velestfile, parameter, evt)
|
||||
# hypoDD
|
||||
hypoddfile = '%s/autoPyLoT_hypoDD_phases.pha' % event
|
||||
hypodd.export(picks, hypoddfile, parameter, evt)
|
||||
# FOCMEC
|
||||
focmecfile = '%s/autoPyLoT_FOCMEC.in' % event
|
||||
focmec.export(picks, focmecfile, parameter, evt)
|
||||
# HASH
|
||||
hashfile = '%s/autoPyLoT_HASH' % event
|
||||
hash.export(picks, hashfile, parameter, evt)
|
||||
|
||||
endsplash = '''------------------------------------------\n'
|
||||
-----Finished event %s!-----\n'
|
||||
@ -249,7 +306,6 @@ def autoPyLoT(inputfile):
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
from pylot.core.util.defaults import AUTOMATIC_DEFAULTS
|
||||
# parse arguments
|
||||
parser = argparse.ArgumentParser(
|
||||
description='''autoPyLoT automatically picks phase onset times using higher order statistics,
|
||||
@ -258,13 +314,17 @@ if __name__ == "__main__":
|
||||
parser.add_argument('-i', '-I', '--inputfile', type=str,
|
||||
action='store',
|
||||
help='''full path to the file containing the input
|
||||
parameters for autoPyLoT''',
|
||||
default=AUTOMATIC_DEFAULTS
|
||||
)
|
||||
parameters for autoPyLoT''')
|
||||
parser.add_argument('-f', '-F', '--fnames', type=str,
|
||||
action='store',
|
||||
help='''optional, list of data file names''')
|
||||
parser.add_argument('-s', '-S', '--spath', type=str,
|
||||
action=store,
|
||||
help='''optional, save path for autoPyLoT output''')
|
||||
parser.add_argument('-v', '-V', '--version', action='version',
|
||||
version='autoPyLoT ' + __version__,
|
||||
help='show version information and exit')
|
||||
|
||||
cla = parser.parse_args()
|
||||
|
||||
autoPyLoT(str(cla.inputfile))
|
||||
autoPyLoT(str(cla.inputfile), str(cla.fnames), str(cla.spath))
|
||||
|
@ -2,10 +2,15 @@
|
||||
<qresource>
|
||||
<file>icons/pylot.ico</file>
|
||||
<file>icons/pylot.png</file>
|
||||
<file>icons/locate.png</file>
|
||||
<file>icons/manupicsicon.png</file>
|
||||
<file>icons/autopicsicon.png</file>
|
||||
<file>icons/autopick_button.png</file>
|
||||
<file>icons/locactionicon.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/delete.png</file>
|
||||
<file>icons/compare.png</file>
|
||||
<file>icons/key_E.png</file>
|
||||
<file>icons/key_N.png</file>
|
||||
<file>icons/key_P.png</file>
|
||||
|
Before Width: | Height: | Size: 3.0 KiB |
0
icons/delete.png
Executable file → Normal file
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 5.0 KiB |
0
icons/key_E.png
Executable file → Normal file
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 3.9 KiB |
0
icons/key_N.png
Executable file → Normal file
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 4.0 KiB |
0
icons/key_P.png
Executable file → Normal file
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 3.9 KiB |
0
icons/key_Q.png
Executable file → Normal file
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 4.1 KiB |
0
icons/key_R.png
Executable file → Normal file
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 4.0 KiB |
0
icons/key_S.png
Executable file → Normal file
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 4.0 KiB |
BIN
icons/key_T.png
Executable file → Normal file
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 0 B |
0
icons/key_U.png
Executable file → Normal file
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 3.9 KiB |
0
icons/key_V.png
Executable file → Normal file
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 4.0 KiB |
0
icons/key_W.png
Executable file → Normal file
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 4.1 KiB |
0
icons/key_Z.png
Executable file → Normal file
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 3.9 KiB |
BIN
icons/locate.png
Before Width: | Height: | Size: 7.1 KiB |
0
icons/sync.png
Executable file → Normal file
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 4.2 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 |
63325
icons_rc.py
@ -1 +1 @@
|
||||
0.1a
|
||||
f5c0-dirty
|
||||
|
0
pylot/__init__.py
Executable file → Normal file
0
pylot/core/__init__.py
Executable file → Normal file
@ -6,19 +6,16 @@ Created autumn/winter 2015.
|
||||
:author: Ludger Küperkoch / MAGS2 EP3 working group
|
||||
"""
|
||||
import os
|
||||
|
||||
import matplotlib.pyplot as plt
|
||||
import numpy as np
|
||||
import obspy.core.event as ope
|
||||
from obspy.geodetics import degrees2kilometers
|
||||
from scipy import integrate, signal
|
||||
from scipy.optimize import curve_fit
|
||||
|
||||
from pylot.core.pick.utils import getsignalwin, crossings_nonzero_all, \
|
||||
select_for_phase
|
||||
from pylot.core.util.utils import common_range, fit_curve
|
||||
|
||||
|
||||
def richter_magnitude_scaling(delta):
|
||||
relation = np.loadtxt(os.path.join(os.path.expanduser('~'),
|
||||
'.pylot', 'richter_scaling.data'))
|
||||
@ -200,8 +197,8 @@ class RichterMagnitude(Magnitude):
|
||||
iwin = getsignalwin(th, t0 - stime, self.calc_win)
|
||||
wapp = np.max(sqH[iwin])
|
||||
if self.verbose:
|
||||
print("Determined Wood-Anderson peak-to-peak amplitude: {0} "
|
||||
"mm".format(wapp))
|
||||
print("Determined Wood-Anderson peak-to-peak amplitude for station {0}: {1} "
|
||||
"mm".format(st[0].stats.station, wapp))
|
||||
|
||||
# check for plot flag (for debugging only)
|
||||
if self.plot_flag > 1:
|
||||
@ -317,8 +314,8 @@ class MomentMagnitude(Magnitude):
|
||||
continue
|
||||
pick = a.pick_id.get_referred_object()
|
||||
station = pick.waveform_id.station_code
|
||||
wf = select_for_phase(self.stream.select(
|
||||
station=station), a.phase)
|
||||
scopy = self.stream.copy()
|
||||
wf = scopy.select(station=station)
|
||||
if not wf:
|
||||
continue
|
||||
onset = pick.time
|
||||
@ -326,15 +323,16 @@ class MomentMagnitude(Magnitude):
|
||||
azimuth = a.azimuth
|
||||
incidence = a.takeoff_angle
|
||||
w0, fc = calcsourcespec(wf, onset, self.p_velocity, distance,
|
||||
azimuth,
|
||||
incidence, self.p_attenuation,
|
||||
azimuth, incidence, self.p_attenuation,
|
||||
self.plot_flag, self.verbose)
|
||||
if w0 is None or fc is None:
|
||||
if self.verbose:
|
||||
print("WARNING: insufficient frequency information")
|
||||
continue
|
||||
wf = select_for_phase(wf, "P")
|
||||
m0, mw = calcMoMw(wf, w0, self.rock_density, self.p_velocity,
|
||||
WF = select_for_phase(self.stream.select(
|
||||
station=station), a.phase)
|
||||
WF = select_for_phase(WF, "P")
|
||||
m0, mw = calcMoMw(WF, w0, self.rock_density, self.p_velocity,
|
||||
distance, self.verbose)
|
||||
self.moment_props = (station, dict(w0=w0, fc=fc, Mo=m0))
|
||||
magnitude = ope.StationMagnitude(mag=mw)
|
||||
@ -426,7 +424,7 @@ def calcsourcespec(wfstream, onset, vp, delta, azimuth, incidence,
|
||||
:type: integer
|
||||
'''
|
||||
if verbosity:
|
||||
print ("Calculating source spectrum ....")
|
||||
print ("Calculating source spectrum for station %s ...." % wfstream[0].stats.station)
|
||||
|
||||
# get Q value
|
||||
Q, A = qp
|
||||
@ -453,18 +451,21 @@ def calcsourcespec(wfstream, onset, vp, delta, azimuth, incidence,
|
||||
LQT = wfstream.rotate('ZNE->LQT', azimuth, incidence)
|
||||
ldat = LQT.select(component="L")
|
||||
if len(ldat) == 0:
|
||||
# if horizontal channels are 2 and 3
|
||||
# if horizontal channels are 1 and 2
|
||||
# no azimuth information is available and thus no
|
||||
# rotation is possible!
|
||||
if verbosity:
|
||||
print("calcsourcespec: Azimuth information is missing, "
|
||||
"no rotation of components possible!")
|
||||
ldat = LQT.select(component="Z")
|
||||
# instead, use component 3
|
||||
ldat = LQT.select(component="3")
|
||||
if len(ldat) == 0:
|
||||
# maybe component z available
|
||||
ldat = LQT.select(component="Z")
|
||||
|
||||
# integrate to displacement
|
||||
# unrotated vertical component (for comparison)
|
||||
inttrz = signal.detrend(integrate.cumtrapz(zdat[0].data, None, dt))
|
||||
|
||||
# rotated component Z => L
|
||||
Ldat = signal.detrend(integrate.cumtrapz(ldat[0].data, None, dt))
|
||||
|
||||
@ -527,22 +528,24 @@ def calcsourcespec(wfstream, onset, vp, delta, azimuth, incidence,
|
||||
# use of implicit scipy otimization function
|
||||
fit = synthsourcespec(F, w0in, Fcin)
|
||||
[optspecfit, _] = curve_fit(synthsourcespec, F, YYcor, [w0in, Fcin])
|
||||
w01 = optspecfit[0]
|
||||
fc1 = optspecfit[1]
|
||||
w0 = optspecfit[0]
|
||||
fc = optspecfit[1]
|
||||
#w01 = optspecfit[0]
|
||||
#fc1 = optspecfit[1]
|
||||
if verbosity:
|
||||
print ("calcsourcespec: Determined w0-value: %e m/Hz, \n"
|
||||
"Determined corner frequency: %f Hz" % (w01, fc1))
|
||||
"calcsourcespec: Determined corner frequency: %f Hz" % (w0, fc))
|
||||
|
||||
# use of conventional fitting
|
||||
[w02, fc2] = fitSourceModel(F, YYcor, Fcin, iplot, verbosity)
|
||||
# [w02, fc2] = fitSourceModel(F, YYcor, Fcin, iplot, verbosity)
|
||||
|
||||
# get w0 and fc as median of both
|
||||
# source spectrum fits
|
||||
w0 = np.median([w01, w02])
|
||||
fc = np.median([fc1, fc2])
|
||||
if verbosity:
|
||||
print("calcsourcespec: Using w0-value = %e m/Hz and fc = %f Hz" % (
|
||||
w0, fc))
|
||||
#w0 = np.median([w01, w02])
|
||||
#fc = np.median([fc1, fc2])
|
||||
#if verbosity:
|
||||
# print("calcsourcespec: Using w0-value = %e m/Hz and fc = %f Hz" % (
|
||||
# w0, fc))
|
||||
|
||||
if iplot > 1:
|
||||
f1 = plt.figure()
|
||||
@ -627,18 +630,35 @@ def fitSourceModel(f, S, fc0, iplot, verbosity=False):
|
||||
fc = []
|
||||
stdfc = []
|
||||
STD = []
|
||||
|
||||
# get window around initial corner frequency for trials
|
||||
fcstopl = fc0 - max(1, len(f) / 10)
|
||||
il = np.argmin(abs(f - fcstopl))
|
||||
fcstopl = f[il]
|
||||
fcstopr = fc0 + min(len(f), len(f) / 10)
|
||||
ir = np.argmin(abs(f - fcstopr))
|
||||
fcstopr = f[ir]
|
||||
iF = np.where((f >= fcstopl) & (f <= fcstopr))
|
||||
# left side of initial corner frequency
|
||||
fcstopl = max(f[0], fc0 - max(1, fc0 / 2))
|
||||
il = np.where(f <= fcstopl)
|
||||
il = il[0][np.size(il) - 1]
|
||||
# right side of initial corner frequency
|
||||
fcstopr = min(fc0 + (fc0 / 2), f[len(f) - 1])
|
||||
ir = np.where(f >= fcstopr)
|
||||
# check, if fcstopr is available
|
||||
if np.size(ir) == 0:
|
||||
fcstopr = fc0
|
||||
ir = len(f) - 1
|
||||
else:
|
||||
ir = ir[0][0]
|
||||
|
||||
# vary corner frequency around initial point
|
||||
for i in range(il, ir):
|
||||
print("fitSourceModel: Varying corner frequency "
|
||||
"around initial corner frequency ...")
|
||||
# check difference of il and ir in order to
|
||||
# keep calculation time acceptable
|
||||
idiff = ir - il
|
||||
if idiff > 10000:
|
||||
increment = 100
|
||||
elif idiff <= 20:
|
||||
increment = 1
|
||||
else:
|
||||
increment = 10
|
||||
|
||||
for i in range(il, ir, increment):
|
||||
FC = f[i]
|
||||
indexdc = np.where((f > 0) & (f <= FC))
|
||||
dc = np.mean(S[indexdc])
|
||||
|
@ -6,13 +6,11 @@ import os
|
||||
from obspy import read_events
|
||||
from obspy.core import read, Stream, UTCDateTime
|
||||
from obspy.core.event import Event
|
||||
|
||||
from pylot.core.io.phases import readPILOTEvent, picks_from_picksdict, \
|
||||
picksdict_from_pilot, merge_picks
|
||||
from pylot.core.util.errors import FormatError, OverwriteError
|
||||
from pylot.core.util.utils import fnConstructor, full_range
|
||||
|
||||
|
||||
class Data(object):
|
||||
"""
|
||||
Data container with attributes wfdata holding ~obspy.core.stream.
|
||||
@ -298,10 +296,20 @@ class Data(object):
|
||||
"""
|
||||
|
||||
#firstonset = find_firstonset(picks)
|
||||
if self.get_evt_data().picks:
|
||||
raise OverwriteError('Actual picks would be overwritten!')
|
||||
else:
|
||||
picks = picks_from_picksdict(picks)
|
||||
# check for automatic picks
|
||||
print("Writing phases to ObsPy-quakeml file")
|
||||
for key in picks:
|
||||
if picks[key]['P']['picker'] == 'auto':
|
||||
print("Existing picks will be overwritten!")
|
||||
picks = picks_from_picksdict(picks)
|
||||
break
|
||||
else:
|
||||
if self.get_evt_data().picks:
|
||||
raise OverwriteError('Existing picks would be overwritten!')
|
||||
break
|
||||
else:
|
||||
picks = picks_from_picksdict(picks)
|
||||
break
|
||||
self.get_evt_data().picks = picks
|
||||
# if 'smi:local' in self.getID() and firstonset:
|
||||
# fonset_str = firstonset.strftime('%Y_%m_%d_%H_%M_%S')
|
||||
|
@ -14,7 +14,6 @@ from pylot.core.io.location import create_arrival, create_event, \
|
||||
from pylot.core.pick.utils import select_for_phase
|
||||
from pylot.core.util.utils import getOwner, full_range, four_digits
|
||||
|
||||
|
||||
def add_amplitudes(event, amplitudes):
|
||||
amplitude_list = []
|
||||
for pick in event.picks:
|
||||
@ -233,6 +232,8 @@ def picks_from_picksdict(picks, creation_info=None):
|
||||
if not isinstance(phase, dict):
|
||||
continue
|
||||
onset = phase['mpp']
|
||||
ccode = phase['channel']
|
||||
ncode = phase['network']
|
||||
pick = ope.Pick()
|
||||
if creation_info:
|
||||
pick.creation_info = creation_info
|
||||
@ -253,7 +254,9 @@ def picks_from_picksdict(picks, creation_info=None):
|
||||
picker = 'Unknown'
|
||||
pick.phase_hint = label
|
||||
pick.method_id = ope.ResourceIdentifier(id=picker)
|
||||
pick.waveform_id = ope.WaveformStreamID(station_code=station)
|
||||
pick.waveform_id = ope.WaveformStreamID(station_code=station,
|
||||
channel_code=ccode,
|
||||
network_code=ncode)
|
||||
try:
|
||||
polarity = phase['fm']
|
||||
if polarity == 'U' or '+':
|
||||
@ -384,7 +387,7 @@ def reassess_pilot_event(root_dir, db_dir, event_id, out_dir=None, fn_param=None
|
||||
#evt.write(fnout_prefix + 'cnv', format='VELEST')
|
||||
|
||||
|
||||
def writephases(arrivals, fformat, filename):
|
||||
def writephases(arrivals, fformat, filename, parameter, eventinfo=None):
|
||||
"""
|
||||
Function of methods to write phases to the following standard file
|
||||
formats used for locating earthquakes:
|
||||
@ -402,17 +405,25 @@ def writephases(arrivals, fformat, filename):
|
||||
HYPOINVERSE, and hypoDD
|
||||
|
||||
:param: filename, full path and name of phase file
|
||||
:type: string
|
||||
"""
|
||||
:type: string
|
||||
|
||||
:param: parameter, all input information
|
||||
:type: object
|
||||
|
||||
:param: eventinfo, optional, needed for VELEST-cnv file
|
||||
and FOCMEC- and HASH-input files
|
||||
:type: `obspy.core.event.Event` object
|
||||
"""
|
||||
|
||||
if fformat == 'NLLoc':
|
||||
print ("Writing phases to %s for NLLoc" % filename)
|
||||
fid = open("%s" % filename, 'w')
|
||||
# write header
|
||||
fid.write('# EQEVENT: Label: EQ001 Loc: X 0.00 Y 0.00 Z 10.00 OT 0.00 \n')
|
||||
fid.write('# EQEVENT: %s Label: EQ%s Loc: X 0.00 Y 0.00 Z 10.00 OT 0.00 \n' %
|
||||
(parameter.get('database'), parameter.get('eventID')))
|
||||
for key in arrivals:
|
||||
# P onsets
|
||||
if arrivals[key]['P']:
|
||||
if arrivals[key].has_key('P'):
|
||||
try:
|
||||
fm = arrivals[key]['P']['fm']
|
||||
except KeyError as e:
|
||||
@ -477,9 +488,13 @@ def writephases(arrivals, fformat, filename):
|
||||
print ("Writing phases to %s for HYPO71" % filename)
|
||||
fid = open("%s" % filename, 'w')
|
||||
# write header
|
||||
fid.write(' EQ001\n')
|
||||
fid.write(' %s\n' %
|
||||
parameter.get('eventID'))
|
||||
for key in arrivals:
|
||||
if arrivals[key]['P']['weight'] < 4:
|
||||
stat = key
|
||||
if len(stat) > 4: # HYPO71 handles only 4-string station IDs
|
||||
stat = stat[1:5]
|
||||
Ponset = arrivals[key]['P']['mpp']
|
||||
Sonset = arrivals[key]['S']['mpp']
|
||||
pweight = arrivals[key]['P']['weight']
|
||||
@ -517,7 +532,7 @@ def writephases(arrivals, fformat, filename):
|
||||
sstr = 'I'
|
||||
elif sweight >= 2:
|
||||
sstr = 'E'
|
||||
fid.write('%s%sP%s%d %02d%02d%02d%02d%02d%5.2f %s%sS %d %s\n' % (key,
|
||||
fid.write('%-4s%sP%s%d %02d%02d%02d%02d%02d%5.2f %s%sS %d %s\n' % (stat,
|
||||
pstr,
|
||||
fm,
|
||||
pweight,
|
||||
@ -532,7 +547,7 @@ def writephases(arrivals, fformat, filename):
|
||||
sweight,
|
||||
Ao))
|
||||
else:
|
||||
fid.write('%s%sP%s%d %02d%02d%02d%02d%02d%5.2f %s\n' % (key,
|
||||
fid.write('%-4s%sP%s%d %02d%02d%02d%02d%02d%5.2f %s\n' % (stat,
|
||||
pstr,
|
||||
fm,
|
||||
pweight,
|
||||
@ -546,6 +561,258 @@ def writephases(arrivals, fformat, filename):
|
||||
|
||||
fid.close()
|
||||
|
||||
elif fformat == 'HYPOSAT':
|
||||
print ("Writing phases to %s for HYPOSAT" % filename)
|
||||
fid = open("%s" % filename, 'w')
|
||||
# write header
|
||||
fid.write('%s, event %s \n' % (parameter.get('database'), parameter.get('eventID')))
|
||||
errP = parameter.get('timeerrorsP')
|
||||
errS = parameter.get('timeerrorsS')
|
||||
for key in arrivals:
|
||||
# P onsets
|
||||
if arrivals[key].has_key('P'):
|
||||
if arrivals[key]['P']['weight'] < 4:
|
||||
Ponset = arrivals[key]['P']['mpp']
|
||||
pyear = Ponset.year
|
||||
pmonth = Ponset.month
|
||||
pday = Ponset.day
|
||||
phh = Ponset.hour
|
||||
pmm = Ponset.minute
|
||||
pss = Ponset.second
|
||||
pms = Ponset.microsecond
|
||||
Pss = pss + pms / 1000000.0
|
||||
# use symmetrized picking error as std
|
||||
# (read the HYPOSAT manual)
|
||||
pstd = arrivals[key]['P']['spe']
|
||||
fid.write('%-5s P1 %4.0f %02d %02d %02d %02d %05.02f %5.3f -999. 0.00 -999. 0.00\n'
|
||||
% (key, pyear, pmonth, pday, phh, pmm, Pss, pstd))
|
||||
# S onsets
|
||||
if arrivals[key].has_key('S') and arrivals[key]['S']:
|
||||
if arrivals[key]['S']['weight'] < 4:
|
||||
Sonset = arrivals[key]['S']['mpp']
|
||||
syear = Sonset.year
|
||||
smonth = Sonset.month
|
||||
sday = Sonset.day
|
||||
shh = Sonset.hour
|
||||
smm = Sonset.minute
|
||||
sss = Sonset.second
|
||||
sms = Sonset.microsecond
|
||||
Sss = sss + sms / 1000000.0
|
||||
sstd = arrivals[key]['S']['spe']
|
||||
fid.write('%-5s S1 %4.0f %02d %02d %02d %02d %05.02f %5.3f -999. 0.00 -999. 0.00\n'
|
||||
% (key, syear, smonth, sday, shh, smm, Sss, sstd))
|
||||
fid.close()
|
||||
|
||||
elif fformat == 'VELEST':
|
||||
print ("Writing phases to %s for VELEST" % filename)
|
||||
fid = open("%s" % filename, 'w')
|
||||
# get informations needed in cnv-file
|
||||
# check, whether latitude is N or S and longitude is E or W
|
||||
eventsource = eventinfo.origins[0]
|
||||
if eventsource['latitude'] < 0:
|
||||
cns = 'S'
|
||||
else:
|
||||
cns = 'N'
|
||||
if eventsource['longitude'] < 0:
|
||||
cew = 'W'
|
||||
else:
|
||||
cew = 'E'
|
||||
# get last two integers of origin year
|
||||
stime = eventsource['time']
|
||||
if stime.year - 2000 >= 0:
|
||||
syear = stime.year - 2000
|
||||
else:
|
||||
syear = stime.year - 1900
|
||||
ifx = 0 # default value, see VELEST manual, pp. 22-23
|
||||
# write header
|
||||
fid.write('%s%02d%02d %02d%02d %05.2f %7.4f%c %8.4f%c %7.2f %6.2f %02.0f 0.0 0.03 1.0 1.0\n' % (
|
||||
syear, stime.month, stime.day, stime.hour, stime.minute, stime.second, eventsource['latitude'],
|
||||
cns, eventsource['longitude'], cew, eventsource['depth'],eventinfo.magnitudes[0]['mag'], ifx))
|
||||
n = 0
|
||||
for key in arrivals:
|
||||
# P onsets
|
||||
if arrivals[key].has_key('P'):
|
||||
if arrivals[key]['P']['weight'] < 4:
|
||||
n += 1
|
||||
stat = key
|
||||
if len(stat) > 4: # VELEST handles only 4-string station IDs
|
||||
stat = stat[1:5]
|
||||
Ponset = arrivals[key]['P']['mpp']
|
||||
Pweight = arrivals[key]['P']['weight']
|
||||
Prt = Ponset - stime # onset time relative to source time
|
||||
if n % 6 is not 0:
|
||||
fid.write('%-4sP%d%6.2f' % (stat, Pweight, Prt))
|
||||
else:
|
||||
fid.write('%-4sP%d%6.2f\n' % (stat, Pweight, Prt))
|
||||
# S onsets
|
||||
if arrivals[key].has_key('S'):
|
||||
if arrivals[key]['S']['weight'] < 4:
|
||||
n += 1
|
||||
stat = key
|
||||
if len(stat) > 4: # VELEST handles only 4-string station IDs
|
||||
stat = stat[1:5]
|
||||
Sonset = arrivals[key]['S']['mpp']
|
||||
Sweight = arrivals[key]['S']['weight']
|
||||
Srt = Ponset - stime # onset time relative to source time
|
||||
if n % 6 is not 0:
|
||||
fid.write('%-4sS%d%6.2f' % (stat, Sweight, Srt))
|
||||
else:
|
||||
fid.write('%-4sS%d%6.2f\n' % (stat, Sweight, Srt))
|
||||
fid.close()
|
||||
|
||||
elif fformat == 'hypoDD':
|
||||
print ("Writing phases to %s for hypoDD" % filename)
|
||||
fid = open("%s" % filename, 'w')
|
||||
# get event information needed for hypoDD-phase file
|
||||
eventsource = eventinfo.origins[0]
|
||||
stime = eventsource['time']
|
||||
event = parameter.get('eventID')
|
||||
hddID = event.split('.')[0][1:5]
|
||||
# write header
|
||||
fid.write('# %d %d %d %d %d %5.2f %7.4f +%6.4f %7.4f %4.2f 0.1 0.5 %4.2f %s\n' % (
|
||||
stime.year, stime.month, stime.day, stime.hour, stime.minute, stime.second,
|
||||
eventsource['latitude'], eventsource['longitude'], eventsource['depth'] / 1000,
|
||||
eventinfo.magnitudes[0]['mag'], eventsource['quality']['standard_error'], hddID))
|
||||
for key in arrivals:
|
||||
if arrivals[key].has_key('P'):
|
||||
# P onsets
|
||||
if arrivals[key]['P']['weight'] < 4:
|
||||
Ponset = arrivals[key]['P']['mpp']
|
||||
Prt = Ponset - stime # onset time relative to source time
|
||||
fid.write('%s %6.3f 1 P\n' % (key, Prt))
|
||||
# S onsets
|
||||
if arrivals[key]['S']['weight'] < 4:
|
||||
Sonset = arrivals[key]['S']['mpp']
|
||||
Srt = Sonset - stime # onset time relative to source time
|
||||
fid.write('%-5s %6.3f 1 S\n' % (key, Srt))
|
||||
|
||||
fid.close()
|
||||
|
||||
elif fformat == 'FOCMEC':
|
||||
print ("Writing phases to %s for FOCMEC" % filename)
|
||||
fid = open("%s" % filename, 'w')
|
||||
# get event information needed for FOCMEC-input file
|
||||
eventsource = eventinfo.origins[0]
|
||||
stime = eventsource['time']
|
||||
# write header line including event information
|
||||
fid.write('%s %d%02d%02d%02d%02d%02.0f %7.4f %6.4f %3.1f %3.1f\n' % (parameter.get('eventID'),
|
||||
stime.year, stime.month, stime.day, stime.hour, stime.minute, stime.second,
|
||||
eventsource['latitude'], eventsource['longitude'], eventsource['depth'] / 1000,
|
||||
eventinfo.magnitudes[0]['mag']))
|
||||
picks = eventinfo.picks
|
||||
for key in arrivals:
|
||||
if arrivals[key].has_key('P'):
|
||||
if arrivals[key]['P']['weight'] < 4 and arrivals[key]['P']['fm'] is not None:
|
||||
stat = key
|
||||
for i in range(len(picks)):
|
||||
station = picks[i].waveform_id.station_code
|
||||
if station == stat:
|
||||
# get resource ID
|
||||
resid_picks = picks[i].get('resource_id')
|
||||
# find same ID in eventinfo
|
||||
# there it is the pick_id!!
|
||||
for j in range(len(eventinfo.origins[0].arrivals)):
|
||||
resid_eventinfo = eventinfo.origins[0].arrivals[j].get('pick_id')
|
||||
if resid_eventinfo == resid_picks and eventinfo.origins[0].arrivals[j].phase == 'P':
|
||||
if len(stat) > 4: # FOCMEC handles only 4-string station IDs
|
||||
stat = stat[1:5]
|
||||
az = eventinfo.origins[0].arrivals[j].get('azimuth')
|
||||
inz = eventinfo.origins[0].arrivals[j].get('takeoff_angle')
|
||||
fid.write('%-4s %6.2f %6.2f%s \n' % (stat,
|
||||
az,
|
||||
inz,
|
||||
arrivals[key]['P']['fm']))
|
||||
break
|
||||
|
||||
fid.close()
|
||||
|
||||
elif fformat == 'HASH':
|
||||
# two different input files for
|
||||
# HASH-driver 1 and 2 (see HASH manual!)
|
||||
filename1 = filename + 'drv1' + '.phase'
|
||||
filename2 = filename + 'drv2' + '.phase'
|
||||
print ("Writing phases to %s for HASH for HASH-driver 1" % filename1)
|
||||
fid1 = open("%s" % filename1, 'w')
|
||||
print ("Writing phases to %s for HASH for HASH-driver 2" % filename2)
|
||||
fid2 = open("%s" % filename2, 'w')
|
||||
# get event information needed for HASH-input file
|
||||
eventsource = eventinfo.origins[0]
|
||||
event = parameter.get('eventID')
|
||||
hashID = event.split('.')[0][1:5]
|
||||
latdeg = eventsource['latitude']
|
||||
latmin = eventsource['latitude'] * 60 / 10000
|
||||
londeg = eventsource['longitude']
|
||||
lonmin = eventsource['longitude'] * 60 / 10000
|
||||
erh = 1 / 2 * (eventsource.origin_uncertainty['min_horizontal_uncertainty'] +
|
||||
eventsource.origin_uncertainty['max_horizontal_uncertainty']) / 1000
|
||||
erz = eventsource.depth_errors['uncertainty']
|
||||
stime = eventsource['time']
|
||||
if stime.year - 2000 >= 0:
|
||||
syear = stime.year - 2000
|
||||
else:
|
||||
syear = stime.year - 1900
|
||||
picks = eventinfo.picks
|
||||
# write header line including event information
|
||||
# for HASH-driver 1
|
||||
fid1.write('%s%02d%02d%02d%02d%5.2f%2dN%5.2f%3dE%5.2f%6.3f%4.2f%5.2f%5.2f%s\n' % (syear,
|
||||
stime.month, stime.day, stime.hour, stime.minute, stime.second,
|
||||
latdeg, latmin, londeg, lonmin, eventsource['depth'],
|
||||
eventinfo.magnitudes[0]['mag'], erh, erz,
|
||||
hashID))
|
||||
# write header line including event information
|
||||
# for HASH-driver 2
|
||||
fid2.write('%d%02d%02d%02d%02d%5.2f%dN%5.2f%3dE%6.2f%5.2f %d %5.2f %5.2f %4.2f %s \n' % (syear, stime.month, stime.day,
|
||||
stime.hour, stime.minute, stime.second,
|
||||
latdeg,latmin,londeg, lonmin,
|
||||
eventsource['depth'],
|
||||
eventsource['quality']['used_phase_count'],
|
||||
erh, erz, eventinfo.magnitudes[0]['mag'],
|
||||
hashID))
|
||||
|
||||
# write phase lines
|
||||
for key in arrivals:
|
||||
if arrivals[key].has_key('P'):
|
||||
if arrivals[key]['P']['weight'] < 4 and arrivals[key]['P']['fm'] is not None:
|
||||
stat = key
|
||||
ccode = arrivals[key]['P']['channel']
|
||||
ncode = arrivals[key]['P']['network']
|
||||
|
||||
if arrivals[key]['P']['weight'] < 2:
|
||||
Pqual='I'
|
||||
else:
|
||||
Pqual='E'
|
||||
|
||||
for i in range(len(picks)):
|
||||
station = picks[i].waveform_id.station_code
|
||||
if station == stat:
|
||||
# get resource ID
|
||||
resid_picks = picks[i].get('resource_id')
|
||||
# find same ID in eventinfo
|
||||
# there it is the pick_id!!
|
||||
for j in range(len(eventinfo.origins[0].arrivals)):
|
||||
resid_eventinfo = eventinfo.origins[0].arrivals[j].get('pick_id')
|
||||
if resid_eventinfo == resid_picks and eventinfo.origins[0].arrivals[j].phase == 'P':
|
||||
if len(stat) > 4: # HASH handles only 4-string station IDs
|
||||
stat = stat[1:5]
|
||||
az = eventinfo.origins[0].arrivals[j].get('azimuth')
|
||||
inz = eventinfo.origins[0].arrivals[j].get('takeoff_angle')
|
||||
dist = eventinfo.origins[0].arrivals[j].get('distance')
|
||||
# write phase line for HASH-driver 1
|
||||
fid1.write('%-4s%sP%s%d 0 %3.1f %03d %03d 2 1 %s\n' % (stat, Pqual, arrivals[key]['P']['fm'], arrivals[key]['P']['weight'],
|
||||
dist, inz, az, ccode))
|
||||
# write phase line for HASH-driver 2
|
||||
fid2.write('%-4s %s %s %s %s \n' % (
|
||||
stat,
|
||||
ncode,
|
||||
ccode,
|
||||
Pqual,
|
||||
arrivals[key]['P']['fm']))
|
||||
break
|
||||
|
||||
fid1.write(' %s' % hashID)
|
||||
fid1.close()
|
||||
fid2.close()
|
||||
|
||||
|
||||
def merge_picks(event, picks):
|
||||
"""
|
||||
|
@ -1,21 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from pylot.core.io.phases import writephases
|
||||
from pylot.core.util.version import get_git_version as _getVersionString
|
||||
|
||||
__version__ = _getVersionString()
|
||||
|
||||
def export(picks, fnout):
|
||||
'''
|
||||
Take <picks> dictionary and exports picking data to a NLLOC-obs
|
||||
<phasefile> without creating an ObsPy event object.
|
||||
|
||||
:param picks: picking data dictionary
|
||||
:type picks: dict
|
||||
|
||||
:param fnout: complete path to the exporting obs file
|
||||
:type fnout: str
|
||||
'''
|
||||
# write phases to NLLoc-phase file
|
||||
writephases(picks, 'HYPO71', fnout)
|
@ -14,7 +14,7 @@ __version__ = _getVersionString()
|
||||
class NLLocError(EnvironmentError):
|
||||
pass
|
||||
|
||||
def export(picks, fnout):
|
||||
def export(picks, fnout, parameter):
|
||||
'''
|
||||
Take <picks> dictionary and exports picking data to a NLLOC-obs
|
||||
<phasefile> without creating an ObsPy event object.
|
||||
@ -24,9 +24,12 @@ def export(picks, fnout):
|
||||
|
||||
:param fnout: complete path to the exporting obs file
|
||||
:type fnout: str
|
||||
|
||||
:param: parameter, all input information
|
||||
:type: object
|
||||
'''
|
||||
# write phases to NLLoc-phase file
|
||||
writephases(picks, 'NLLoc', fnout)
|
||||
writephases(picks, 'NLLoc', fnout, parameter)
|
||||
|
||||
|
||||
def modify_inputs(ctrfn, root, nllocoutn, phasefn, tttn):
|
||||
@ -67,14 +70,17 @@ def modify_inputs(ctrfn, root, nllocoutn, phasefn, tttn):
|
||||
nllfile.close()
|
||||
|
||||
|
||||
def locate(fnin):
|
||||
def locate(fnin, infile=None):
|
||||
"""
|
||||
takes an external program name
|
||||
:param fnin:
|
||||
:return:
|
||||
"""
|
||||
|
||||
exe_path = which('NLLoc')
|
||||
if infile is None:
|
||||
exe_path = which('NLLoc')
|
||||
else:
|
||||
exe_path = which('NLLoc', infile)
|
||||
if exe_path is None:
|
||||
raise NLLocError('NonLinLoc executable not found; check your '
|
||||
'environment variables')
|
||||
|
@ -1,2 +1,27 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from pylot.core.io.phases import writephases
|
||||
from pylot.core.util.version import get_git_version as _getVersionString
|
||||
|
||||
__version__ = _getVersionString()
|
||||
|
||||
def export(picks, fnout, parameter, eventinfo):
|
||||
'''
|
||||
Take <picks> dictionary and exports picking data to a VELEST-cnv
|
||||
<phasefile> without creating an ObsPy event object.
|
||||
|
||||
:param picks: picking data dictionary
|
||||
:type picks: dict
|
||||
|
||||
:param fnout: complete path to the exporting obs file
|
||||
:type fnout: str
|
||||
|
||||
:param: parameter, all input information
|
||||
:type: object
|
||||
|
||||
:param: eventinfo, source time needed for VELEST-cnv format
|
||||
:type: list object
|
||||
'''
|
||||
# write phases to VELEST-phase file
|
||||
writephases(picks, 'VELEST', fnout, parameter, eventinfo)
|
||||
|
20
pylot/core/pick/autopick.py
Executable file → Normal file
@ -143,7 +143,7 @@ def autopickstation(wfstream, pickparam, verbose=False):
|
||||
Sflag = 0
|
||||
Pmarker = []
|
||||
Ao = None # Wood-Anderson peak-to-peak amplitude
|
||||
picker = 'autoPyLoT' # name of the picking programm
|
||||
picker = 'auto' # type of picks
|
||||
|
||||
# split components
|
||||
zdat = wfstream.select(component="Z")
|
||||
@ -157,7 +157,7 @@ def autopickstation(wfstream, pickparam, verbose=False):
|
||||
ndat = wfstream.select(component="1")
|
||||
|
||||
if algoP == 'HOS' or algoP == 'ARZ' and zdat is not None:
|
||||
msg = '##########################################\nautopickstation:' \
|
||||
msg = '##################################################\nautopickstation:' \
|
||||
' Working on P onset of station {station}\nFiltering vertical ' \
|
||||
'trace ...\n{data}'.format(station=zdat[0].stats.station,
|
||||
data=str(zdat))
|
||||
@ -552,7 +552,7 @@ def autopickstation(wfstream, pickparam, verbose=False):
|
||||
|
||||
print('autopickstation: S-weight: {0}, SNR: {1}, '
|
||||
'SNR[dB]: {2}\n'
|
||||
'################################################'
|
||||
'##################################################'
|
||||
''.format(Sweight, SNRS, SNRSdB))
|
||||
################################################################
|
||||
# get Wood-Anderson peak-to-peak amplitude
|
||||
@ -566,7 +566,7 @@ def autopickstation(wfstream, pickparam, verbose=False):
|
||||
'AIC-SNR={0}, AIC-Slope={1}counts/s\n' \
|
||||
'(min. AIC-SNR={2}, ' \
|
||||
'min. AIC-Slope={3}counts/s)\n' \
|
||||
'################################################' \
|
||||
'##################################################' \
|
||||
''.format(aicarhpick.getSNR(),
|
||||
aicarhpick.getSlope(),
|
||||
minAICSSNR,
|
||||
@ -778,11 +778,15 @@ def autopickstation(wfstream, pickparam, verbose=False):
|
||||
|
||||
# create dictionary
|
||||
# for P phase
|
||||
ppick = dict(lpp=lpickP, epp=epickP, mpp=mpickP, spe=Perror, snr=SNRP,
|
||||
ccode = zdat[0].stats.channel
|
||||
ncode = zdat[0].stats.network
|
||||
ppick = dict(channel=ccode, network=ncode, lpp=lpickP, epp=epickP, mpp=mpickP, spe=Perror, snr=SNRP,
|
||||
snrdb=SNRPdB, weight=Pweight, fm=FM, w0=None, fc=None, Mo=None,
|
||||
Mw=None, picker=picker, marked=Pmarker)
|
||||
# add S phase
|
||||
spick = dict(lpp=lpickS, epp=epickS, mpp=mpickS, spe=Serror, snr=SNRS,
|
||||
ccode = edat[0].stats.channel
|
||||
ncode = edat[0].stats.network
|
||||
spick = dict(channel=ccode, network=ncode, lpp=lpickS, epp=epickS, mpp=mpickS, spe=Serror, snr=SNRS,
|
||||
snrdb=SNRSdB, weight=Sweight, fm=None, picker=picker, Ao=Ao)
|
||||
# merge picks into returning dictionary
|
||||
picks = dict(P=ppick, S=spick)
|
||||
@ -804,7 +808,7 @@ def iteratepicker(wf, NLLocfile, picks, badpicks, pickparameter):
|
||||
:param pickparameter: picking parameters from autoPyLoT-input file
|
||||
'''
|
||||
|
||||
msg = '#######################################################\n' \
|
||||
msg = '##################################################\n' \
|
||||
'autoPyLoT: Found {0} bad onsets at station(s) {1}, ' \
|
||||
'starting re-picking them ...'.format(len(badpicks), badpicks)
|
||||
print(msg)
|
||||
@ -823,7 +827,7 @@ def iteratepicker(wf, NLLocfile, picks, badpicks, pickparameter):
|
||||
badpicks[i][1] = picks[badpicks[i][0]]['P']['mpp'] - float(res)
|
||||
|
||||
# get corresponding waveform stream
|
||||
msg = '#######################################################\n' \
|
||||
msg = '##################################################\n' \
|
||||
'iteratepicker: Re-picking station {0}'.format(badpicks[i][0])
|
||||
print(msg)
|
||||
wf2pick = wf.select(station=badpicks[i][0])
|
||||
|
@ -7,7 +7,6 @@ import os
|
||||
import numpy as np
|
||||
import glob
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
from obspy import read_events
|
||||
|
||||
from pylot.core.io.phases import picksdict_from_picks
|
||||
@ -289,7 +288,6 @@ class PDFDictionary(object):
|
||||
values['mpp'],
|
||||
values['lpp'],
|
||||
type=type)
|
||||
|
||||
return pdf_picks
|
||||
|
||||
def plot(self, stations=None):
|
||||
@ -493,4 +491,4 @@ if __name__ == "__main__":
|
||||
main()
|
||||
pr.disable()
|
||||
# after your program ends
|
||||
pr.print_stats(sort="calls")
|
||||
pr.print_stats(sort="calls")
|
||||
|
@ -1,12 +1,11 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Created Mar/Apr 2015
|
||||
Collection of helpful functions for manual and automatic picking.
|
||||
|
||||
:author: Ludger Kueperkoch / MAGS2 EP3 working group
|
||||
:author: Ludger Kueperkoch, BESTEC GmbH
|
||||
"""
|
||||
|
||||
import warnings
|
||||
|
0
pylot/core/util/__init__.py
Executable file → Normal file
@ -180,8 +180,10 @@ def read_metadata(path_to_inventory):
|
||||
invtype = key_for_set_value(inv)
|
||||
|
||||
if invtype is None:
|
||||
raise IOError("Neither dataless-SEED file, inventory-xml file nor "
|
||||
"RESP-file found!")
|
||||
print("Neither dataless-SEED file, inventory-xml file nor "
|
||||
"RESP-file found!")
|
||||
print("!!WRONG CALCULATION OF SOURCE PARAMETERS!!")
|
||||
robj = None,
|
||||
elif invtype == 'dless': # prevent multiple read of large dlsv
|
||||
print("Reading metadata information from dataless-SEED file ...")
|
||||
if len(inv[invtype]) == 1:
|
||||
@ -250,13 +252,23 @@ def restitute_data(data, invtype, inobj, unit='VEL', force=False):
|
||||
else:
|
||||
finv = invlist[0]
|
||||
inventory = read_inventory(finv, format='STATIONXML')
|
||||
elif invtype == None:
|
||||
print("No restitution possible, as there are no station-meta data available!")
|
||||
break
|
||||
else:
|
||||
data.remove(tr)
|
||||
continue
|
||||
# apply restitution to data
|
||||
print("Correcting instrument at station %s, channel %s" \
|
||||
% (tr.stats.station, tr.stats.channel))
|
||||
try:
|
||||
if invtype in ['resp', 'dless']:
|
||||
tr.simulate(**kwargs)
|
||||
try:
|
||||
tr.simulate(**kwargs)
|
||||
except ValueError as e:
|
||||
vmsg = '{0}'.format(e)
|
||||
print(vmsg)
|
||||
|
||||
else:
|
||||
tr.attach_response(inventory)
|
||||
tr.remove_response(output=unit,
|
||||
|
@ -8,7 +8,9 @@ Created on Wed Feb 26 12:31:25 2014
|
||||
|
||||
import os
|
||||
from pylot.core.loc import nll
|
||||
from pylot.core.loc import hsat
|
||||
from pylot.core.loc import hyposat
|
||||
from pylot.core.loc import hypo71
|
||||
from pylot.core.loc import hypodd
|
||||
from pylot.core.loc import velest
|
||||
|
||||
|
||||
@ -43,10 +45,6 @@ FILTERDEFAULTS = readFilterInformation(os.path.join(os.path.expanduser('~'),
|
||||
'.pylot',
|
||||
'filter.in'))
|
||||
|
||||
AUTOMATIC_DEFAULTS = os.path.join(os.path.expanduser('~'),
|
||||
'.pylot',
|
||||
'autoPyLoT.in')
|
||||
|
||||
TIMEERROR_DEFAULTS = os.path.join(os.path.expanduser('~'),
|
||||
'.pylot',
|
||||
'PILOT_TimeErrors.in')
|
||||
@ -55,7 +53,7 @@ OUTPUTFORMATS = {'.xml': 'QUAKEML',
|
||||
'.cnv': 'CNV',
|
||||
'.obs': 'NLLOC_OBS'}
|
||||
|
||||
LOCTOOLS = dict(nll=nll, hsat=hsat, velest=velest)
|
||||
LOCTOOLS = dict(nll=nll, hyposat=hyposat, velest=velest, hypo71=hypo71, hypodd=hypodd)
|
||||
|
||||
COMPPOSITION_MAP = dict(Z=2, N=1, E=0)
|
||||
COMPPOSITION_MAP['1'] = 1
|
||||
|
@ -51,8 +51,11 @@ def exp_parameter(te, tm, tl, eta):
|
||||
|
||||
sig1 = np.log(eta) / (te - tm)
|
||||
sig2 = np.log(eta) / (tm - tl)
|
||||
if np.isinf(sig1) == True:
|
||||
sig1 = np.log(eta) / (tm - tl)
|
||||
if np.isinf(sig2) == True:
|
||||
sig2 = np.log(eta) / (te - tm)
|
||||
a = 1 / (1 / sig1 + 1 / sig2)
|
||||
|
||||
return tm, sig1, sig2, a
|
||||
|
||||
|
||||
@ -237,7 +240,7 @@ class ProbabilityDensityFunction(object):
|
||||
|
||||
@classmethod
|
||||
def from_pick(self, lbound, barycentre, rbound, incr=0.001, decfact=0.01,
|
||||
type='gauss'):
|
||||
type='exp'):
|
||||
'''
|
||||
Initialize a new ProbabilityDensityFunction object.
|
||||
Takes incr, lbound, barycentre and rbound to derive x0 and the number
|
||||
@ -304,10 +307,14 @@ class ProbabilityDensityFunction(object):
|
||||
:return float: rval
|
||||
'''
|
||||
|
||||
rval = 0
|
||||
for x in self.axis:
|
||||
rval += x * self.data(x)
|
||||
return rval * self.incr
|
||||
#rval = 0
|
||||
#for x in self.axis:
|
||||
# rval += x * self.data(x)
|
||||
rval = self.mu
|
||||
# Not sure about this! That might not be the barycentre.
|
||||
# However, for std calculation (next function)
|
||||
# self.mu is also used!! (LK, 02/2017)
|
||||
return rval
|
||||
|
||||
def standard_deviation(self):
|
||||
mu = self.mu
|
||||
|
@ -7,17 +7,18 @@ class AutoPickThread(QThread):
|
||||
message = Signal(str)
|
||||
finished = Signal()
|
||||
|
||||
def __init__(self, parent, func, data, param):
|
||||
def __init__(self, parent, func, infile, fnames, savepath):
|
||||
super(AutoPickThread, self).__init__()
|
||||
self.setParent(parent)
|
||||
self.func = func
|
||||
self.data = data
|
||||
self.param = param
|
||||
self.infile = infile
|
||||
self.fnames = fnames
|
||||
self.savepath = savepath
|
||||
|
||||
def run(self):
|
||||
sys.stdout = self
|
||||
|
||||
picks = self.func(self.data, self.param)
|
||||
picks = self.func(self.infile, self.fnames, self.savepath)
|
||||
|
||||
print("Autopicking finished!\n")
|
||||
|
||||
|
@ -477,7 +477,7 @@ def runProgram(cmd, parameter=None):
|
||||
|
||||
subprocess.check_output('{} | tee /dev/stderr'.format(cmd), shell=True)
|
||||
|
||||
def which(program):
|
||||
def which(program, infile=None):
|
||||
"""
|
||||
takes a program name and returns the full path to the executable or None
|
||||
modified after: http://stackoverflow.com/questions/377017/test-if-executable-exists-in-python
|
||||
@ -490,7 +490,12 @@ def which(program):
|
||||
for key in settings.allKeys():
|
||||
if 'binPath' in key:
|
||||
os.environ['PATH'] += ':{0}'.format(settings.value(key))
|
||||
bpath = os.path.join(os.path.expanduser('~'), '.pylot', 'autoPyLoT.in')
|
||||
if infile is None:
|
||||
# use default parameter-file name
|
||||
bpath = os.path.join(os.path.expanduser('~'), '.pylot', 'pylot.in')
|
||||
else:
|
||||
bpath = os.path.join(os.path.expanduser('~'), '.pylot', infile)
|
||||
|
||||
if os.path.exists(bpath):
|
||||
nllocpath = ":" + AutoPickParameter(bpath).get('nllocbin')
|
||||
os.environ['PATH'] += nllocpath
|
||||
|
0
pylot/core/util/version.py
Executable file → Normal file
@ -5,12 +5,15 @@ Created on Wed Mar 19 11:27:35 2014
|
||||
@author: sebastianw
|
||||
"""
|
||||
|
||||
import os
|
||||
import getpass
|
||||
import warnings
|
||||
import copy
|
||||
import datetime
|
||||
import numpy as np
|
||||
|
||||
from matplotlib.figure import Figure
|
||||
from pylot.core.util.utils import find_horizontals
|
||||
|
||||
try:
|
||||
from matplotlib.backends.backend_qt4agg import FigureCanvas
|
||||
@ -26,7 +29,7 @@ from PySide.QtGui import QAction, QApplication, QCheckBox, QComboBox, \
|
||||
from PySide.QtCore import QSettings, Qt, QUrl, Signal, Slot
|
||||
from PySide.QtWebKit import QWebView
|
||||
from obspy import Stream, UTCDateTime
|
||||
from pylot.core.io.inputs import FilterOptions
|
||||
from pylot.core.io.inputs import FilterOptions, AutoPickParameter
|
||||
from pylot.core.pick.utils import getSNR, earllatepicker, getnoisewin, \
|
||||
getResolutionWindow
|
||||
from pylot.core.pick.compare import Comparison
|
||||
@ -49,7 +52,12 @@ def getDataType(parent):
|
||||
|
||||
def plot_pdf(_axes, x, y, annotation, bbox_props, xlabel=None, ylabel=None,
|
||||
title=None):
|
||||
_axes.plot(x, y)
|
||||
# try method or data
|
||||
try:
|
||||
_axes.plot(x, y()) # y provided as method
|
||||
except:
|
||||
_axes.plot(x, y) # y provided as data
|
||||
|
||||
if title:
|
||||
_axes.set_title(title)
|
||||
if xlabel:
|
||||
@ -235,23 +243,23 @@ class ComparisonDialog(QDialog):
|
||||
x, y, std, exp = pdf.axis, pdf.data, pdf.standard_deviation(), \
|
||||
pdf.expectation()
|
||||
|
||||
annotation = "{phase} difference on {station}\n" \
|
||||
"expectation: {exp}\n" \
|
||||
"std: {std}".format(station=station, phase=phase,
|
||||
std=std, exp=exp)
|
||||
annotation = "%s difference on %s\n" \
|
||||
"expectation: %7.4f s\n" \
|
||||
"std: %7.4f s" % (phase, station,
|
||||
exp, std)
|
||||
bbox_props = dict(boxstyle='round', facecolor='lightgrey', alpha=.7)
|
||||
|
||||
plot_pdf(_axes, x, y, annotation, bbox_props, 'time difference [s]',
|
||||
'propability density [-]', phase)
|
||||
'propability density [-]', phase)
|
||||
|
||||
pdf_a = copy.deepcopy(self.data.get('auto')[station][phase])
|
||||
pdf_m = copy.deepcopy(self.data.get('manu')[station][phase])
|
||||
|
||||
xauto, yauto, stdauto, expauto, alim = pdf_a.axis, pdf_a.data, \
|
||||
xauto, yauto, stdauto, expauto, alim = pdf_a.axis, pdf_a.data(), \
|
||||
pdf_a.standard_deviation(), \
|
||||
pdf_a.expectation(), \
|
||||
pdf_a.limits()
|
||||
xmanu, ymanu, stdmanu, expmanu, mlim = pdf_m.axis, pdf_m.data, \
|
||||
xmanu, ymanu, stdmanu, expmanu, mlim = pdf_m.axis, pdf_m.data(), \
|
||||
pdf_m.standard_deviation(), \
|
||||
pdf_m.expectation(), \
|
||||
pdf_m.limits()
|
||||
@ -259,21 +267,19 @@ class ComparisonDialog(QDialog):
|
||||
lims = clims(alim, mlim)
|
||||
# relative x axis
|
||||
x0 = lims[0]
|
||||
xmanu -= x0
|
||||
xmanu -= x0
|
||||
xauto -= x0
|
||||
lims = [lim - x0 for lim in lims]
|
||||
x0 = UTCDateTime(x0)
|
||||
|
||||
# set annotation text
|
||||
mannotation = "probability density for manual pick\n" \
|
||||
"expectation: {exp}\n" \
|
||||
"std: {std}".format(std=stdmanu,
|
||||
exp=expmanu-x0.timestamp)
|
||||
mannotation = "probability density of manual pick\n" \
|
||||
"expectation: %7.4f s\n" \
|
||||
"std: %7.4f s" % (expmanu-x0.timestamp, stdmanu)
|
||||
|
||||
aannotation = "probability density for automatic pick\n" \
|
||||
"expectation: {exp}\n" \
|
||||
"std: {std}".format(std=stdauto,
|
||||
exp=expauto-x0.timestamp)
|
||||
aannotation = "probability density of automatic pick\n" \
|
||||
"expectation: %7.4f s\n" \
|
||||
"std: %7.4f s" % (expauto-x0.timestamp, stdauto)
|
||||
|
||||
_ax1 = plot_pdf(_ax1, xmanu, ymanu, mannotation,
|
||||
bbox_props=bbox_props, xlabel='seconds since '
|
||||
@ -504,15 +510,17 @@ class WaveformWidget(FigureCanvas):
|
||||
|
||||
class PickDlg(QDialog):
|
||||
def __init__(self, parent=None, data=None, station=None, picks=None,
|
||||
rotate=False):
|
||||
rotate=False, infile=None):
|
||||
super(PickDlg, self).__init__(parent)
|
||||
|
||||
# initialize attributes
|
||||
self.infile = infile
|
||||
self.station = station
|
||||
self.rotate = rotate
|
||||
self.components = 'ZNE'
|
||||
settings = QSettings()
|
||||
self._user = settings.value('user/Login', 'anonymous')
|
||||
pylot_user = getpass.getuser()
|
||||
self._user = settings.value('user/Login', pylot_user)
|
||||
if picks:
|
||||
self.picks = picks
|
||||
else:
|
||||
@ -704,6 +712,9 @@ class PickDlg(QDialog):
|
||||
self.cidrelease = self.connectReleaseEvent(self.panRelease)
|
||||
self.cidscroll = self.connectScrollEvent(self.scrollZoom)
|
||||
|
||||
def getinfile(self):
|
||||
return self.infile
|
||||
|
||||
def getStartTime(self):
|
||||
return self.stime
|
||||
|
||||
@ -806,6 +817,7 @@ class PickDlg(QDialog):
|
||||
self.disconnectMotionEvent()
|
||||
self.cidpress = self.connectPressEvent(self.setPick)
|
||||
|
||||
print(self.selectPhase.currentText())
|
||||
if self.selectPhase.currentText().upper().startswith('P'):
|
||||
self.setIniPickP(gui_event, wfdata, trace_number)
|
||||
elif self.selectPhase.currentText().upper().startswith('S'):
|
||||
@ -819,14 +831,14 @@ class PickDlg(QDialog):
|
||||
|
||||
def setIniPickP(self, gui_event, wfdata, trace_number):
|
||||
|
||||
parameter = AutoPickParameter(self.getinfile())
|
||||
ini_pick = gui_event.xdata
|
||||
|
||||
settings = QSettings()
|
||||
|
||||
nfac = settings.value('picking/nfac_P', 1.3)
|
||||
noise_win = settings.value('picking/noise_win_P', 5.)
|
||||
gap_win = settings.value('picking/gap_win_P', .2)
|
||||
signal_win = settings.value('picking/signal_win_P', 3.)
|
||||
nfac = parameter.get('nfacP')
|
||||
twins = parameter.get('tsnrz')
|
||||
noise_win = twins[0]
|
||||
gap_win = twins[1]
|
||||
signal_win = twins[2]
|
||||
itrace = int(trace_number)
|
||||
|
||||
while itrace > len(wfdata) - 1:
|
||||
@ -868,14 +880,14 @@ class PickDlg(QDialog):
|
||||
|
||||
def setIniPickS(self, gui_event, wfdata):
|
||||
|
||||
parameter = AutoPickParameter(self.getinfile())
|
||||
ini_pick = gui_event.xdata
|
||||
|
||||
settings = QSettings()
|
||||
|
||||
nfac = settings.value('picking/nfac_S', 1.5)
|
||||
noise_win = settings.value('picking/noise_win_S', 5.)
|
||||
gap_win = settings.value('picking/gap_win_S', .2)
|
||||
signal_win = settings.value('picking/signal_win_S', 3.)
|
||||
nfac = parameter.get('nfacS')
|
||||
twins = parameter.get('tsnrh')
|
||||
noise_win = twins[0]
|
||||
gap_win = twins[1]
|
||||
signal_win = twins[2]
|
||||
|
||||
# copy data for plotting
|
||||
data = self.getWFData().copy()
|
||||
@ -922,6 +934,8 @@ class PickDlg(QDialog):
|
||||
|
||||
def setPick(self, gui_event):
|
||||
|
||||
parameter = AutoPickParameter(self.getinfile())
|
||||
|
||||
# get axes limits
|
||||
self.updateCurrentLimits()
|
||||
|
||||
@ -941,7 +955,14 @@ class PickDlg(QDialog):
|
||||
wfdata.filter(**filteroptions)
|
||||
|
||||
# get earliest and latest possible pick and symmetric pick error
|
||||
[epp, lpp, spe] = earllatepicker(wfdata, 1.5, (5., .5, 2.), pick)
|
||||
if wfdata[0].stats.channel[2] == 'Z' or wfdata[0].stats.channel[2] == '3':
|
||||
nfac = parameter.get('nfacP')
|
||||
TSNR = parameter.get('tsnrz')
|
||||
else:
|
||||
nfac = parameter.get('nfacS')
|
||||
TSNR = parameter.get('tsnrh')
|
||||
|
||||
[epp, lpp, spe] = earllatepicker(wfdata, nfac, (TSNR[0], TSNR[1], TSNR[2]), pick)
|
||||
|
||||
# return absolute time values for phases
|
||||
stime = self.getStartTime()
|
||||
@ -951,7 +972,8 @@ class PickDlg(QDialog):
|
||||
|
||||
# save pick times for actual phase
|
||||
phasepicks = dict(epp=epp, lpp=lpp, mpp=mpp, spe=spe,
|
||||
picker=self.getUser())
|
||||
picker='manual', channel=channel,
|
||||
network=wfdata[0].stats.network)
|
||||
|
||||
try:
|
||||
oldphasepick = self.picks[phase]
|
||||
@ -1171,13 +1193,15 @@ class PickDlg(QDialog):
|
||||
|
||||
|
||||
class PropertiesDlg(QDialog):
|
||||
def __init__(self, parent=None):
|
||||
def __init__(self, parent=None, infile=None):
|
||||
super(PropertiesDlg, self).__init__(parent)
|
||||
|
||||
self.infile = infile
|
||||
|
||||
|
||||
appName = QApplication.applicationName()
|
||||
|
||||
self.setWindowTitle("{0} Properties".format(appName))
|
||||
|
||||
self.tabWidget = QTabWidget()
|
||||
self.tabWidget.addTab(InputsTab(self), "Inputs")
|
||||
self.tabWidget.addTab(OutputsTab(self), "Outputs")
|
||||
@ -1186,7 +1210,8 @@ class PropertiesDlg(QDialog):
|
||||
self.tabWidget.addTab(LocalisationTab(self), "Loc Tools")
|
||||
self.buttonBox = QDialogButtonBox(QDialogButtonBox.Ok |
|
||||
QDialogButtonBox.Apply |
|
||||
QDialogButtonBox.Close)
|
||||
QDialogButtonBox.Close |
|
||||
QDialogButtonBox.RestoreDefaults)
|
||||
|
||||
layout = QVBoxLayout()
|
||||
layout.addWidget(self.tabWidget)
|
||||
@ -1195,8 +1220,11 @@ class PropertiesDlg(QDialog):
|
||||
|
||||
self.buttonBox.accepted.connect(self.accept)
|
||||
self.buttonBox.rejected.connect(self.reject)
|
||||
self.buttonBox.button(QDialogButtonBox.Apply).clicked.connect(
|
||||
self.apply)
|
||||
self.buttonBox.button(QDialogButtonBox.Apply).clicked.connect(self.apply)
|
||||
self.buttonBox.button(QDialogButtonBox.RestoreDefaults).clicked.connect(self.restore)
|
||||
|
||||
def getinfile(self):
|
||||
return self.infile
|
||||
|
||||
def accept(self, *args, **kwargs):
|
||||
self.apply()
|
||||
@ -1209,6 +1237,14 @@ class PropertiesDlg(QDialog):
|
||||
if values is not None:
|
||||
self.setValues(values)
|
||||
|
||||
def restore(self):
|
||||
for widint in range(self.tabWidget.count()):
|
||||
curwid = self.tabWidget.widget(widint)
|
||||
values = curwid.resetValues(self.getinfile())
|
||||
if values is not None:
|
||||
self.setValues(values)
|
||||
|
||||
|
||||
@staticmethod
|
||||
def setValues(tabValues):
|
||||
settings = QSettings()
|
||||
@ -1224,16 +1260,19 @@ class PropTab(QWidget):
|
||||
def getValues(self):
|
||||
return None
|
||||
|
||||
def resetValues(self, infile=None):
|
||||
return None
|
||||
|
||||
class InputsTab(PropTab):
|
||||
def __init__(self, parent):
|
||||
def __init__(self, parent, infile=None):
|
||||
super(InputsTab, self).__init__(parent)
|
||||
|
||||
settings = QSettings()
|
||||
pylot_user = getpass.getuser()
|
||||
fulluser = settings.value("user/FullName")
|
||||
login = settings.value("user/Login")
|
||||
|
||||
fullNameLabel = QLabel("Full name for user '{0}': ".format(login))
|
||||
fullNameLabel = QLabel("Full name for user '{0}': ".format(pylot_user))
|
||||
|
||||
# get the full name of the actual user
|
||||
self.fullNameEdit = QLineEdit()
|
||||
@ -1276,9 +1315,24 @@ class InputsTab(PropTab):
|
||||
"data/Structure": self.structureSelect.currentText()}
|
||||
return values
|
||||
|
||||
def resetValues(self, infile):
|
||||
para = AutoPickParameter(infile)
|
||||
datstruct = para.get('datastructure')
|
||||
if datstruct == 'SeisComp':
|
||||
index = 0
|
||||
else:
|
||||
index = 2
|
||||
datapath = para.get('datapath')
|
||||
rootpath = para.get('rootpath')
|
||||
database = para.get('database')
|
||||
path = os.path.join(os.path.expanduser('~'), rootpath, datapath, database)
|
||||
values = {"data/dataRoot": self.dataDirEdit.setText("%s" % path),
|
||||
"user/FullName": self.fullNameEdit.text(),
|
||||
"data/Structure": self.structureSelect.setCurrentIndex(index)}
|
||||
return values
|
||||
|
||||
class OutputsTab(PropTab):
|
||||
def __init__(self, parent=None):
|
||||
def __init__(self, parent=None, infile=None):
|
||||
super(OutputsTab, self).__init__(parent)
|
||||
|
||||
settings = QSettings()
|
||||
@ -1302,6 +1356,9 @@ class OutputsTab(PropTab):
|
||||
values = {"output/Format": self.eventOutputComboBox.currentText()}
|
||||
return values
|
||||
|
||||
def resetValues(self, infile):
|
||||
values = {"output/Format": self.eventOutputComboBox.setCurrentIndex(1)}
|
||||
return values
|
||||
|
||||
class PhasesTab(PropTab):
|
||||
def __init__(self, parent=None):
|
||||
@ -1318,7 +1375,7 @@ class GraphicsTab(PropTab):
|
||||
|
||||
|
||||
class LocalisationTab(PropTab):
|
||||
def __init__(self, parent=None):
|
||||
def __init__(self, parent=None, infile=None):
|
||||
super(LocalisationTab, self).__init__(parent)
|
||||
|
||||
settings = QSettings()
|
||||
@ -1388,6 +1445,13 @@ class LocalisationTab(PropTab):
|
||||
"loc/tool": loctool}
|
||||
return values
|
||||
|
||||
def resetValues(self, infile):
|
||||
para = AutoPickParameter(infile)
|
||||
nllocroot = para.get('nllocroot')
|
||||
nllocbin = para.get('nllocbin')
|
||||
loctool = self.locToolComboBox.setCurrentIndex(3)
|
||||
values = {"nll/rootPath": self.rootedit.setText("%s" % nllocroot),
|
||||
"nll/binPath": self.binedit.setText("%s" % nllocbin)}
|
||||
|
||||
class NewEventDlg(QDialog):
|
||||
def __init__(self, parent=None, titleString="Create a new event"):
|
||||
|