95 Commits
Author SHA1 Message Date
marcel 710ea57503 Merge branch 'github-master' 2017-09-25 15:50:38 +02:00
marcel 8aaad643ec 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:
2017-09-25 14:24:52 +02:00
marcel bc808b66c2 [update] README.md 2017-09-25 10:17:58 +02:00
marcel 472e5b3b9e Merge branch 'develop' 2017-09-21 16:18:53 +02:00
marcel 846da4cab7 [minor] version number changed to 0.2 2017-09-21 15:59:34 +02:00
marcel c8adc24c67 [minor] README update 2017-09-21 15:58:52 +02:00
marcel 255eca3c05 [update] rename QtPylot -> PyLoT (suggestion) 2017-09-21 15:36:17 +02:00
marcel af5953b053 [update] README.md 2017-09-21 15:34:29 +02:00
marcel c19f057abf [update] default pylot.in file updates 2017-09-21 15:20:05 +02:00
marcel 1f2b3147fd [cleanup] remove old files pt.2 2017-09-21 15:03:14 +02:00
marcel 43930a07cb [minor] remove navigation toolbar for tap 2017-09-21 14:42:19 +02:00
marcel 2a987cbdfa [cleanup] removed unused old code and output 2017-09-21 14:38:56 +02:00
marcel 238998e626 [cleanup] removed old unused class 2017-09-21 14:27:42 +02:00
marcel b465ba2111 [minor] color for qstatusbar missing 2017-09-21 14:26:35 +02:00
marcel 370e8a7074 [update] make HELP work again 2017-09-21 13:31:45 +02:00
marcel 259538f0b0 [minor] add some description to exp. histograms 2017-09-21 10:54:34 +02:00
marcel 3096ee4573 [bugfix] usage of unordered dict for comparison
implicit extraction of pdf names (auto, manu) for comparison from a list generated within dict iteration lead to possible flipping (auto - manu .or. manu - auto) of compared pdfs (and with that histograms)
2017-09-21 10:34:21 +02:00
marcel 92b12537eb [update] small improvements on comparison figures 2017-09-21 10:31:29 +02:00
marcel e9ce9635e0 [update] tuneAutoPicker color/pick visualisation 2017-09-20 11:03:30 +02:00
marcel c70222972c [update] small change in comparison figures 2017-09-19 16:08:04 +02:00
marcel 8397856213 [refs #247] array map initiation when loading project 2017-09-18 16:12:02 +02:00
marcel 961be8ccbc [bugfix] ibad referenced before assignment 2017-09-18 15:10:52 +02:00
marcel 7522201e06 [minor] beautiful progressbar 2017-09-18 15:06:50 +02:00
marcel 69ad0bf23b [bugfix] self.pdlg_widget not initiated 2017-09-18 15:06:33 +02:00
marcel 5bb55a8181 [update] move progressbar to bottom of mainwindow 2017-09-18 14:57:48 +02:00
marcel eab416df3f [bugfix] reset stdout in Worker 2017-09-18 14:46:29 +02:00
marcel 0949a6deac [update] apw saved, proper deletion of figures 2017-09-18 14:44:18 +02:00
marcel 6acb0ad580 [minor] wadata/jk improvements 2017-09-18 12:20:48 +02:00
marcel 316d19ba9e [bugfix] one replacement of i -> index missing 2017-09-18 11:39:27 +02:00
marcel 8a2bb65581 Merge remote-tracking branch 'origin/develop' into develop 2017-09-18 11:24:57 +02:00
marcel 330e15441e [bugfix] fig._tight=True tried to be set on None type 2017-09-18 11:23:52 +02:00
marcel 365657064f [cleanup] pycharm code inspection 2017-09-18 10:41:27 +02:00
marcel a5d863bf95 [cleanup] method without usage 2017-09-18 10:15:07 +02:00
Darius Arnold 6d0083040c Merge branch 'feature/fix-tuneautopicker_stationlist' into develop 2017-09-15 20:49:38 +02:00
Darius Arnold 586abea874 [bugfix] same treatment of waveform data in tune autopicker and load waveform
fixes #217. While generating the station list for the tune autopicker dialog, waveform data was loaded and some traces were removed (gaps, doubled, rotated). However, not all the functions were called on wfdat, so some stations would be unavailable in the general waveform overview for the event, but could be selected in the tune autopicker.
2017-09-15 20:48:22 +02:00
Darius Arnold 2ee3c9a304 [change] show more stations in stationbox of tune autopicker dialog 2017-09-15 18:59:17 +02:00
Darius Arnold 2e6c33de45 [bugfix] allow picking of S phase in lower area of waveform plot
Fixes bug report #211
2017-09-15 18:56:04 +02:00
Darius Arnold 864f035456 Merge branch 'improve_jackwada_plots' into develop 2017-09-15 18:32:26 +02:00
Darius Arnold 27a6af6636 improved jackknife/median plot
added different colors to markers for accepted picks, jackknife reject picks and median rejected picks, added lines indicating median tolerance
2017-09-15 18:31:20 +02:00
Darius Arnold 62625d6941 improved wadati plot
added names of stations, added lines indicating wadati tolerance
2017-09-15 18:28:33 +02:00
Darius Arnold 7c528a4bfd [change] jackknife and wadati plot show one instead of two points in legend 2017-09-15 16:48:08 +02:00
Darius Arnold 8dc5be8e49 [bugfix] removed unneccessary command added during tight layout change 2017-09-15 16:47:12 +02:00
Darius Arnold a7fd239574 [bugfix] improvements to removal of NaNs during Cf calculation 2017-09-15 16:28:27 +02:00
marcel 6a40eef3fc Merge branch 'develop' of ariadne.geophysik.ruhr-uni-bochum.de:/data/git/pylot into develop 2017-09-15 14:47:44 +02:00
marcel 183f9e77c0 [fixes #249] stylesheet path relative to style_settings 2017-09-15 14:47:05 +02:00
Darius Arnold c8affae0c2 Merge branch 'tightlayout_tuneauto' into develop 2017-09-15 14:12:33 +02:00
Darius Arnold ec8d471ce1 [change] enabled tight layout for tune autopicker plots 2017-09-15 14:11:28 +02:00
Darius Arnold a96f8dcb7d [add] wadati, jackknife and median test print excluded stations 2017-09-15 13:24:13 +02:00
Darius Arnold c65d6b8376 [bugfix] catch empty pickdics during comparison
Only the P phase might be picked by purpose, or the autopicker might not find any valid S onsets
2017-09-15 13:17:40 +02:00
Darius Arnold ff891cacdc add tight layout to overview plots of tune autopicker dialog 2017-09-15 13:15:30 +02:00
Darius Arnold 00df77e723 [add] remove mean from traces to avoid filtering artifact
Traces with constant offset (mean != 0) produce a large, low period artifact when filtered, even with tapering.
2017-09-15 12:09:56 +02:00
Darius Arnold 219d2d0e5a Merge remote-tracking branch 'origin/develop' into develop 2017-09-15 11:38:06 +02:00
marcel 7496025137 [rename] Ref Button -> Tune Button 2017-09-13 14:44:56 +02:00
marcel 4269256469 [update] make PyLoT icon great again
(bugfix and color change for visibility on dark system background)
2017-09-12 16:37:26 +02:00
marcel f2f908f8b5 [bugfix] missing parameter in getGlobalLimits 2017-09-12 15:31:02 +02:00
marcel 8381782194 [bugfix] missing third value (color) in tuple for autopicker 2017-09-12 14:10:15 +02:00
marcel 518019322d [minor] add event name to Histogram Window 2017-09-12 13:30:51 +02:00
marcel 4bf03ef0d9 [minor] update radioButton StyleSheet 2017-09-12 13:30:38 +02:00
marcel cc0281f9dc [add] color for tune/test events on MultiEventWidget 2017-09-12 12:09:59 +02:00
marcel 1d253b5ee5 [minor] text color changed in stylesheet 2017-09-12 11:58:24 +02:00
marcel 0eeb07583b [change] major change: wadati/JK checked picks REMOVED from autopicks
before, all picks were saved as XML automatically by autoPyLoT (also weight 8, 9), maybe change this to a more convenient way in the futur (e.g. add pick weight as ObsPy.Pick.comment ?)
2017-09-12 11:50:26 +02:00
marcel 0cf46a0cc3 [minor] improve user output on used CPU cores 2017-09-12 11:02:08 +02:00
marcel 7027f9ca58 [update] stylename active used to init combobox 2017-09-11 16:06:25 +02:00
marcel c23fc0f303 [minor] stylesheet changes 2017-09-11 16:01:03 +02:00
marcel ed915f29df Merge branch 'style_options' into develop 2017-09-11 15:53:49 +02:00
marcel 0418acf472 [minor] embellish autoPyLoT button 2017-09-11 15:52:01 +02:00
marcel e333ae0ece [revert] accidently added line for local testing 2017-09-11 15:16:42 +02:00
marcel 197164f849 [issue] trying to solve FigureCanvas already deleted exception WIP 2017-09-11 15:15:33 +02:00
marcel a4c697d250 [minor] solving some parental issues 2017-09-11 14:39:46 +02:00
marcel bed5c8ffcf [minor] stylesheet changes 2017-09-11 14:23:42 +02:00
marcel 330ab9b823 Merge branch 'develop' into style_options 2017-09-11 13:29:22 +02:00
marcel b1a12bf666 [bugfix] workaround: if datastructure not set 2017-09-11 13:28:39 +02:00
marcel f0e4ba5ab2 [add] style settings option 2017-09-11 13:27:32 +02:00
marcel d93a571a51 Merge branch 'develop' into style_options 2017-09-11 12:23:40 +02:00
marcel 1862b6d6e1 [bugfix] QSettings not loaded on setupUI because
application/organization name were not set
2017-09-11 12:18:30 +02:00
marcel 6e43e67172 [minor] stylesheet modifications 2017-09-11 10:24:22 +02:00
marcel e5b0210c27 [update] bright stylesheet 2017-09-08 17:25:29 +02:00
marcel 78ba5484c6 [bugfix] old usage of _parent 2017-09-08 17:19:34 +02:00
marcel f1fdd3b17b [update] bright stylesheet 2017-09-08 17:19:18 +02:00
marcel 104a8dda64 [update] add linecolor settings to autoPyLoT figs 2017-09-08 17:01:36 +02:00
marcel 7ef784f2d2 [minor] color changes 2017-09-08 15:50:08 +02:00
marcel d15828a058 [add] pick trace button color 2017-09-08 12:25:30 +02:00
marcel 51fe48553d [update] bright stylesheet 2017-09-08 12:21:56 +02:00
marcel a97258513e [bugfix] missing variable name change 2017-09-08 10:28:54 +02:00
marcel e310e1b6a6 Merge branch 'develop' into style_options 2017-09-08 09:39:47 +02:00
marcel 38a071ac5b [minor] suppress rotation warning in GUI 2017-09-08 09:36:34 +02:00
marcel 8717df836a [add] bright stylesheet 2017-09-08 09:27:47 +02:00
marcel cacfb37468 [minor] some updates, added bright style sheet 2017-09-07 16:51:56 +02:00
Darius Arnold 49adc5418f [bugfix] calculate slope up to first local maximum only
before it was calculated to global maximum in slope window
2017-09-07 16:47:42 +02:00
marcel 9c63621ba4 [update] style_settings 2017-09-07 16:07:43 +02:00
marcel bab34a23c4 [add] settings for styles 2017-09-07 10:59:09 +02:00
marcel 7e39593b05 [change] dark stylesheet update 2017-09-07 10:52:22 +02:00
marcel 7ecf976401 [add] dark stylesheet 2017-09-06 18:34:59 +02:00
marcel 7f0d3c2ab4 [new] missing parents added, some preperations 2017-09-06 18:02:09 +02:00
Marc S. Boxberg 503ea419c4 release version: 0.1a
release notes:
==============
Features
- consistent manual phase picking through predefined SNR dependant zoom level
- uniform uncertainty estimation from waveform's properties for automatic and manual picks
- pdf representation and comparison of picks taking the uncertainty intrinsically into account
- Richter and moment magnitude estimation
- location determination with external installation of [NonLinLoc](http://alomax.free.fr/nlloc/index.html)
Known issues
- Magnitude estimation from manual PyLoT takes some time (instrument correction)
2016-10-04 09:38:05 +02:00
60 changed files with 15975 additions and 417107 deletions
-4
View File
@@ -1,4 +0,0 @@
\.idea/
*.pyc
Executable → Regular
+266 -128
View File
@@ -39,7 +39,7 @@ from PySide.QtCore import QCoreApplication, QSettings, Signal, QFile, \
from PySide.QtGui import QMainWindow, QInputDialog, QIcon, QFileDialog, \
QWidget, QHBoxLayout, QVBoxLayout, QStyle, QKeySequence, QLabel, QFrame, QAction, \
QDialog, QErrorMessage, QApplication, QPixmap, QMessageBox, QSplashScreen, \
QActionGroup, QListWidget, QDockWidget, QLineEdit, QListView, QAbstractItemView, \
QActionGroup, QListWidget, QLineEdit, QListView, QAbstractItemView, \
QTreeView, QComboBox, QTabWidget, QPushButton, QGridLayout
import numpy as np
from obspy import UTCDateTime
@@ -49,7 +49,7 @@ from obspy.core.util import AttribDict
try:
import pyqtgraph as pg
except Exception as e:
print('QtPyLoT: Could not import pyqtgraph. {}'.format(e))
print('PyLoT: Could not import pyqtgraph. {}'.format(e))
pg = None
try:
@@ -64,18 +64,18 @@ from pylot.core.io.data import Data
from pylot.core.io.inputs import FilterOptions, PylotParameter
from autoPyLoT import autoPyLoT
from pylot.core.pick.compare import Comparison
from pylot.core.pick.utils import symmetrize_error, getQualityFromUncertainty, removePicksAbove
from pylot.core.pick.utils import symmetrize_error, getQualityFromUncertainty
from pylot.core.io.phases import picksdict_from_picks
import pylot.core.loc.nll as nll
from pylot.core.util.defaults import FILTERDEFAULTS, SetChannelComponents
from pylot.core.util.errors import FormatError, DatastructureError, \
from pylot.core.util.errors import DatastructureError, \
OverwriteError
from pylot.core.util.connection import checkurl
from pylot.core.util.dataprocessing import read_metadata, restitute_data
from pylot.core.util.utils import fnConstructor, getLogin, \
full_range, readFilterInformation, trim_station_components, check4gaps, make_pen, pick_color_plt, \
pick_linestyle_plt, remove_underscores, check4doubled, identifyPhaseID, excludeQualityClasses, has_spe, \
check4rotated
check4rotated, transform_colors_mpl, transform_colors_mpl_str
from pylot.core.util.event import Event
from pylot.core.io.location import create_creation_info, create_event
from pylot.core.util.widgets import FilterOptionsDialog, NewEventDlg, \
@@ -87,6 +87,8 @@ from pylot.core.util.structure import DATASTRUCTURE
from pylot.core.util.thread import Thread, Worker
from pylot.core.util.version import get_git_version as _getVersionString
from pylot.styles import style_settings
if sys.version_info.major == 3:
import icons_rc_3 as icons_rc
elif sys.version_info.major == 2:
@@ -110,6 +112,7 @@ class MainWindow(QMainWindow):
print('Using default input file {}'.format(infile))
if os.path.isfile(infile) == False:
infile = QFileDialog().getOpenFileName(caption='Choose PyLoT-input file')
if not os.path.exists(infile[0]):
QMessageBox.warning(self, "PyLoT Warning",
"No PyLoT-input file declared!")
@@ -124,6 +127,7 @@ class MainWindow(QMainWindow):
self.project = Project()
self.project.parameter = self._inputs
self.tap = None
self.apw = None
self.paraBox = None
self.array_map = None
self._metadata = None
@@ -140,12 +144,6 @@ class MainWindow(QMainWindow):
# default factor for dataplot e.g. enabling/disabling scrollarea
self.height_factor = 12
# default colors for ref/test event
self._colors = {
'ref': QtGui.QColor(200, 210, 230, 255),
'test': QtGui.QColor(200, 230, 200, 255)
}
# UI has to be set up before(!) children widgets are about to show up
self.createAction = createAction
# read settings
@@ -174,6 +172,8 @@ class MainWindow(QMainWindow):
self.fnames = None
self._stime = None
structure_setting = settings.value("data/Structure", "PILOT")
if not structure_setting:
structure_setting = 'PILOT'
self.dataStructure = DATASTRUCTURE[structure_setting]()
self.seismicPhase = str(settings.value("phase", "P"))
if settings.value("data/dataRoot", None) is None:
@@ -210,6 +210,8 @@ class MainWindow(QMainWindow):
except:
self.startTime = UTCDateTime()
self.init_styles()
pylot_icon = QIcon()
pylot_icon.addPixmap(QPixmap(':/icons/pylot.png'))
@@ -551,6 +553,13 @@ class MainWindow(QMainWindow):
self.addActions(toolbars["autoPyLoT"], pickActions)
self.addActions(toolbars["LocationTools"], locationToolActions)
# init pyqtgraph
self.pg = pg
# init style
settings = QSettings()
style = settings.value('style')
self.set_style(style)
# add event combo box and ref/test buttons
self.eventBox = self.createEventBox()
@@ -567,21 +576,24 @@ class MainWindow(QMainWindow):
self.eventBox.activated.connect(self.refreshEvents)
# add main tab widget
self.tabs = QTabWidget()
self.tabs = QTabWidget(self)
self._main_layout.addWidget(self.tabs)
self.tabs.currentChanged.connect(self.refreshTabs)
# add progressbar
self.mainProgressBarWidget = QtGui.QWidget()
self._main_layout.addWidget(self.mainProgressBarWidget)
# add scroll area used in case number of traces gets too high
self.wf_scroll_area = QtGui.QScrollArea()
self.wf_scroll_area = QtGui.QScrollArea(self)
# create central matplotlib figure canvas widget
self.pg = pg
self.init_wfWidget()
# init main widgets for main tabs
wf_tab = QtGui.QWidget()
array_tab = QtGui.QWidget()
events_tab = QtGui.QWidget()
wf_tab = QtGui.QWidget(self)
array_tab = QtGui.QWidget(self)
events_tab = QtGui.QWidget(self)
# init main widgets layouts
self.wf_layout = QtGui.QVBoxLayout()
@@ -624,8 +636,8 @@ class MainWindow(QMainWindow):
self.dataPlot = PylotCanvas(parent=self, connect_events=False, multicursor=True)
self.dataPlot.updateWidget(xlab, None, plottitle)
else:
self.pg = True
self.dataPlot = WaveformWidgetPG(parent=self, xlabel=xlab, ylabel=None,
self.pg = pg
self.dataPlot = WaveformWidgetPG(parent=self,
title=plottitle)
self.dataPlot.setCursor(Qt.CrossCursor)
self.wf_scroll_area.setWidget(self.dataPlot)
@@ -636,7 +648,7 @@ class MainWindow(QMainWindow):
'''
Initiate/create buttons for assigning events containing manual picks to reference or test set.
'''
self.ref_event_button = QtGui.QPushButton('Ref')
self.ref_event_button = QtGui.QPushButton('Tune')
self.test_event_button = QtGui.QPushButton('Test')
self.ref_event_button.setToolTip('Set manual picks of current ' +
'event as reference picks for autopicker tuning.')
@@ -644,8 +656,8 @@ class MainWindow(QMainWindow):
'event as test picks for autopicker testing.')
self.ref_event_button.setCheckable(True)
self.test_event_button.setCheckable(True)
self.set_button_color(self.ref_event_button, self._colors['ref'])
self.set_button_color(self.test_event_button, self._colors['test'])
self.set_button_border_color(self.ref_event_button, self._style['ref']['rgba'])
self.set_button_border_color(self.test_event_button, self._style['test']['rgba'])
self.ref_event_button.clicked.connect(self.toggleRef)
self.test_event_button.clicked.connect(self.toggleTest)
self.ref_event_button.setEnabled(False)
@@ -663,6 +675,86 @@ class MainWindow(QMainWindow):
if event.key() == QtCore.Qt.Key.Key_Shift:
self._shift = False
def init_styles(self):
self._styles = {}
styles = ['default', 'dark', 'bright']
stylecolors = style_settings.stylecolors
for style in styles:
if style in stylecolors.keys():
self._styles[style] = stylecolors[style]
self._phasecolors = style_settings.phasecolors
styles_dir = os.path.dirname(style_settings.__file__)
for style, stylecolors in self._styles.items():
stylesheet = stylecolors['stylesheet']['filename']
if stylesheet:
stylesheet_file = open(os.path.join(styles_dir, stylesheet), 'r')
stylesheet = stylesheet_file.read()
stylesheet_file.close()
else:
stylesheet = self.styleSheet()
bg_color = stylecolors['background']['rgba']
line_color = stylecolors['linecolor']['rgba']
multcursor_color = stylecolors['multicursor']['rgba']
# transform to 0-1 values for mpl and update dict
stylecolors['background']['rgba_mpl'] = transform_colors_mpl(bg_color)
stylecolors['linecolor']['rgba_mpl'] = transform_colors_mpl(line_color)
multcursor_color = stylecolors['multicursor']['rgba_mpl'] = transform_colors_mpl(multcursor_color)
stylecolors['stylesheet'] = stylesheet
def set_style(self, stylename=None):
if not stylename:
stylename = 'default'
if not stylename in self._styles:
qmb = QMessageBox.warning(self, 'Could not find style',
'Could not find style with name {}. Using default.'.format(stylename))
self.set_style('default')
return
style = self._styles[stylename]
self._style = style
self._stylename = stylename
self.setStyleSheet(style['stylesheet'])
# colors for ref/test event
self._ref_test_colors = {
'ref': QtGui.QColor(*style['ref']['rgba']),
'test': QtGui.QColor(*style['test']['rgba']),
}
# plot colors
bg_color = style['background']['rgba']
bg_color_mpl_na = transform_colors_mpl_str(bg_color, no_alpha=True)
line_color = style['linecolor']['rgba']
line_color_mpl_na = transform_colors_mpl_str(line_color, no_alpha=True)
for param in matplotlib.rcParams:
if 'color' in param and matplotlib.rcParams[param] in ['k', 'black']:
matplotlib.rcParams[param] = line_color_mpl_na
matplotlib.rc('axes',
edgecolor=line_color_mpl_na,
facecolor=bg_color_mpl_na,
labelcolor=line_color_mpl_na)
matplotlib.rc('xtick',
color=line_color_mpl_na)
matplotlib.rc('ytick',
color=line_color_mpl_na)
matplotlib.rc('figure',
facecolor=bg_color_mpl_na)
if self.pg:
pg.setConfigOption('background', bg_color)
pg.setConfigOption('foreground', line_color)
settings = QSettings()
settings.setValue('style', stylename)
settings.sync()
@property
def metadata(self):
return self._metadata
@@ -714,12 +806,8 @@ class MainWindow(QMainWindow):
settings = QSettings()
return settings.value("data/dataRoot")
def load_autopicks(self, fname=None):
self.load_data(fname, type='auto')
def load_loc(self, fname=None):
type = getDataType(self)
self.load_data(fname, type=type, loc=True)
self.load_data(fname, loc=True)
def load_pilotevent(self):
filt = "PILOT location files (*LOC*.mat)"
@@ -734,10 +822,8 @@ class MainWindow(QMainWindow):
filter=filt, dir=loc_dir)
fn_phases = fn_phases[0]
type = getDataType(self)
fname_dict = dict(phasfn=fn_phases, locfn=fn_loc)
self.load_data(fname_dict, type=type)
self.load_data(fname_dict)
def load_multiple_data(self):
if not self.okToContinue():
@@ -802,20 +888,27 @@ class MainWindow(QMainWindow):
def add_recentfile(self, event):
self.recentfiles.insert(0, event)
def set_button_color(self, button, color=None):
def set_button_border_color(self, button, color=None):
'''
Set background color of a button.
button: type = QtGui.QAbstractButton
color: type = QtGui.QColor or type = str (RGBA)
'''
if type(color) == QtGui.QColor:
button.setStyleSheet({'QPushButton{background-color:transparent}'})
palette = button.palette()
role = button.backgroundRole()
palette.setColor(role, color)
button.setPalette(palette)
button.setAutoFillBackground(True)
elif type(color) == str or not color:
button.setStyleSheet("background-color: {}".format(color))
elif type(color) == str:
button.setStyleSheet('QPushButton{border-color: %s}'
'QPushButton:checked{background-color: rgba%s}'% (color, color))
elif type(color) == tuple:
button.setStyleSheet('QPushButton{border-color: rgba%s}'
'QPushButton:checked{background-color: rgba%s}' % (str(color), str(color)))
elif not color:
button.setStyleSheet(self.orig_parent._style['stylesheet'])
def getWFFnames(self):
try:
@@ -871,7 +964,7 @@ class MainWindow(QMainWindow):
def get_current_event(self, eventbox=None):
'''
Return event (type QtPylot.Event) currently selected in eventbox.
Return event (type PyLoT.Event) currently selected in eventbox.
'''
if not eventbox:
eventbox = self.eventBox
@@ -880,7 +973,7 @@ class MainWindow(QMainWindow):
def get_current_event_path(self, eventbox=None):
'''
Return event path of event (type QtPylot.Event) currently selected in eventbox.
Return event path of event (type PyLoT.Event) currently selected in eventbox.
'''
event = self.get_current_event(eventbox)
if event:
@@ -888,7 +981,7 @@ class MainWindow(QMainWindow):
def get_current_event_name(self, eventbox=None):
'''
Return event path of event (type QtPylot.Event) currently selected in eventbox.
Return event path of event (type PyLoT.Event) currently selected in eventbox.
'''
path = self.get_current_event_path(eventbox)
if path:
@@ -1029,7 +1122,7 @@ class MainWindow(QMainWindow):
'''
# if pick widget is open, refresh tooltips as well
if hasattr(self, 'apw'):
if self.apw:
self.apw.refresh_tooltips()
if hasattr(self, 'cmpw'):
self.cmpw.refresh_tooltips()
@@ -1091,9 +1184,9 @@ class MainWindow(QMainWindow):
item_ref = QtGui.QStandardItem() # str(event_ref))
item_test = QtGui.QStandardItem() # str(event_test))
if event_ref:
item_ref.setBackground(self._colors['ref'])
item_ref.setBackground(self._ref_test_colors['ref'])
if event_test:
item_test.setBackground(self._colors['test'])
item_test.setBackground(self._ref_test_colors['test'])
item_notes = QtGui.QStandardItem(event.notes)
openIcon = self.style().standardIcon(QStyle.SP_DirOpenIcon)
@@ -1249,10 +1342,11 @@ class MainWindow(QMainWindow):
if len(eventdict) < 1:
return
# init event selection options for autopick
self.compareoptions =[('tune events', self.get_ref_events),
('test events', self.get_test_events),
('all (picked) events', self.get_manu_picked_events)]
self.compareoptions =[('tune events', self.get_ref_events, self._style['ref']['rgba']),
('test events', self.get_test_events, self._style['test']['rgba']),
('all (picked) events', self.get_manu_picked_events, None)]
self.cmpw = CompareEventsWidget(self, self.compareoptions, eventdict, comparisons)
self.cmpw.start.connect(self.compareMulti)
@@ -1260,7 +1354,9 @@ class MainWindow(QMainWindow):
self.cmpw.show()
def compareMulti(self):
for key, func in self.compareoptions:
if not self.compareoptions:
return
for key, func, color in self.compareoptions:
if self.cmpw.rb_dict[key].isChecked():
# if radio button is checked break for loop and use func
break
@@ -1274,7 +1370,10 @@ class MainWindow(QMainWindow):
def buildMultiCompareWidget(self, eventlist):
global_comparison = Comparison(eventlist=eventlist)
compare_widget = ComparisonWidget(global_comparison, self)
compare_widget.setWindowTitle('Histograms for all selected events')
for events_name, rb in self.cmpw.rb_dict.items():
if rb.isChecked():
break
compare_widget.setWindowTitle('Histograms for {}'.format(events_name))
compare_widget.hideToolbar()
compare_widget.setHistboxChecked(True)
return compare_widget
@@ -1432,7 +1531,8 @@ class MainWindow(QMainWindow):
'''
if load:
self.wfd_thread = Thread(self, self.loadWaveformData,
progressText='Reading data input...')
progressText='Reading data input...',
pb_widget=self.mainProgressBarWidget)
if load and plot:
self.wfd_thread.finished.connect(self.plotWaveformDataThread)
@@ -1462,7 +1562,7 @@ class MainWindow(QMainWindow):
check4gaps(wfdat)
check4doubled(wfdat)
# check for stations with rotated components
wfdat = check4rotated(wfdat, self.metadata)
wfdat = check4rotated(wfdat, self.metadata, verbosity=0)
# trim station components to same start value
trim_station_components(wfdat, trim_start=True, trim_end=False)
self._stime = full_range(self.get_data().getWFData())[0]
@@ -1522,7 +1622,8 @@ class MainWindow(QMainWindow):
self.getPlotWidget().updateWidget()
plots = self.wfp_thread.data
for times, data in plots:
self.dataPlot.plotWidget.getPlotItem().plot(times, data, pen='k')
self.dataPlot.plotWidget.getPlotItem().plot(times, data,
pen=self.dataPlot.pen_linecolor)
self.dataPlot.reinitMoveProxy()
self.dataPlot.plotWidget.showAxis('left')
self.dataPlot.plotWidget.showAxis('bottom')
@@ -1532,7 +1633,7 @@ class MainWindow(QMainWindow):
if self.pg:
self.finish_pg_plot()
else:
self._max_xlims = self.dataPlot.getXLims()
self._max_xlims = self.dataPlot.getXLims(self.dataPlot.axes[0])
plotWidget = self.getPlotWidget()
plotDict = plotWidget.getPlotDict()
pos = plotDict.keys()
@@ -1570,10 +1671,22 @@ class MainWindow(QMainWindow):
if event.pylot_picks and event.pylot_autopicks:
for station in event.pylot_picks:
if station in event.pylot_autopicks:
autopick_p = event.pylot_autopicks[station]['P']['spe']
manupick_p = event.pylot_picks[station]['P']['spe']
autopick_s = event.pylot_autopicks[station]['S']['spe']
manupick_s = event.pylot_picks[station]['S']['spe']
try:
autopick_p = event.pylot_autopicks[station]['P']['spe']
except KeyError:
autopick_p = None
try:
manupick_p = event.pylot_picks[station]['P']['spe']
except KeyError:
manupick_p = None
try:
autopick_s = event.pylot_autopicks[station]['S']['spe']
except KeyError:
autopick_s = None
try:
manupick_s = event.pylot_picks[station]['S']['spe']
except KeyError:
manupick_s = None
if autopick_p and manupick_p:
return True
elif autopick_s and manupick_s:
@@ -1594,7 +1707,7 @@ class MainWindow(QMainWindow):
self.dataPlot.plotWidget.hideAxis('bottom')
self.dataPlot.plotWidget.hideAxis('left')
else:
self.dataPlot.getAxes().cla()
self.dataPlot.axes[0].cla()
self.loadlocationaction.setEnabled(False)
self.auto_tune.setEnabled(False)
self.auto_pick.setEnabled(False)
@@ -1616,7 +1729,8 @@ class MainWindow(QMainWindow):
'''
self.clearWaveformDataPlot()
self.wfp_thread = Thread(self, self.plotWaveformData,
progressText='Plotting waveform data...')
progressText='Plotting waveform data...',
pb_widget=self.mainProgressBarWidget)
self.wfp_thread.finished.connect(self.finishWaveformDataPlot)
self.wfp_thread.start()
@@ -1752,27 +1866,27 @@ class MainWindow(QMainWindow):
self.checkFilterOptions()
def updateFilterOptions(self):
try:
settings = QSettings()
if settings.value("filterdefaults",
None) is None and not self.getFilters():
for key, value in FILTERDEFAULTS.items():
self.setFilterOptions(FilterOptions(**value), key)
elif settings.value("filterdefaults", None) is not None:
for key, value in settings.value("filterdefaults"):
self.setFilterOptions(FilterOptions(**value), key)
except Exception as e:
self.update_status('Error ...')
emsg = QErrorMessage(self)
emsg.showMessage('Error: {0}'.format(e))
else:
self.update_status('Filter loaded ... '
'[{0}: {1} Hz]'.format(
self.getFilterOptions().getFilterType(),
self.getFilterOptions().getFreq()))
if self.filterAction.isChecked():
self.filterWaveformData()
# def updateFilterOptions(self):
# try:
# settings = QSettings()
# if settings.value("filterdefaults",
# None) is None and not self.getFilters():
# for key, value in FILTERDEFAULTS.items():
# self.setFilterOptions(FilterOptions(**value), key)
# elif settings.value("filterdefaults", None) is not None:
# for key, value in settings.value("filterdefaults"):
# self.setFilterOptions(FilterOptions(**value), key)
# except Exception as e:
# self.update_status('Error ...')
# emsg = QErrorMessage(self)
# emsg.showMessage('Error: {0}'.format(e))
# else:
# self.update_status('Filter loaded ... '
# '[{0}: {1} Hz]'.format(
# self.getFilterOptions().getFilterType(),
# self.getFilterOptions().getFreq()))
# if self.filterAction.isChecked():
# self.filterWaveformData()
def getSeismicPhase(self):
return self.seismicPhase
@@ -1906,27 +2020,36 @@ class MainWindow(QMainWindow):
'el_S1pick',
'el_S2pick',
'refSpick',
'aicARHfig'
'aicARHfig',
'plot_style'
]
for key in self.fig_keys:
fig = Figure()
if key == 'plot_style':
fig = self._style
else:
fig = Figure()
self.fig_dict[key] = fig
def init_canvas_dict(self):
self.canvas_dict = {}
for key in self.fig_keys:
self.canvas_dict[key] = PylotCanvas(self.fig_dict[key])
if not key == 'plot_style':
self.canvas_dict[key] = PylotCanvas(self.fig_dict[key], parent=self)
def init_fig_dict_wadatijack(self, eventIDs):
self.fig_dict_wadatijack = {}
self.fig_keys_wadatijack = [
'jackknife',
'wadati'
'wadati',
'plot_style'
]
for eventID in eventIDs:
self.fig_dict_wadatijack[eventID] = {}
for key in self.fig_keys_wadatijack:
fig = Figure()
if key == 'plot_style':
fig = self._style
else:
fig = Figure()
self.fig_dict_wadatijack[eventID][key] = fig
def init_canvas_dict_wadatijack(self):
@@ -1934,7 +2057,9 @@ class MainWindow(QMainWindow):
for eventID in self.fig_dict_wadatijack.keys():
self.canvas_dict_wadatijack[eventID] = {}
for key in self.fig_keys_wadatijack:
self.canvas_dict_wadatijack[eventID][key] = PylotCanvas(self.fig_dict_wadatijack[eventID][key])
if not key == 'plot_style':
self.canvas_dict_wadatijack[eventID][key] = PylotCanvas(self.fig_dict_wadatijack[eventID][key],
parent=self)
def tune_autopicker(self):
'''
@@ -1967,6 +2092,14 @@ class MainWindow(QMainWindow):
self.tap.fill_tabs(picked=True)
for canvas in self.canvas_dict.values():
canvas.setZoomBorders2content()
if self.tap.pylot_picks:
station = self.tap.get_current_station()
p_pick = self.tap.pylot_picks[station]['P']
s_pick = self.tap.pylot_picks[station]['S']
self.tap.pickDlg.autopicks['P_tuning'] = p_pick
self.tap.pickDlg.autopicks['S_tuning'] = s_pick
self.tap.pickDlg.drawPicks(phase='P_tuning', picktype='auto', picks=p_pick)
self.tap.pickDlg.drawPicks(phase='S_tuning', picktype='auto', picks=s_pick)
def autoPick(self):
autosave = self.get_current_event_path()
@@ -1975,24 +2108,27 @@ class MainWindow(QMainWindow):
"No autoPyLoT output declared!")
return
# init event selection options for autopick
self.pickoptions =[('current event', self.get_current_event),
('tune events', self.get_ref_events),
('test events', self.get_test_events),
('all (picked) events', self.get_manu_picked_events),
('all events', self.get_all_events)]
if not self.apw:
# init event selection options for autopick
self.pickoptions =[('current event', self.get_current_event, None),
('tune events', self.get_ref_events, self._style['ref']['rgba']),
('test events', self.get_test_events, self._style['test']['rgba']),
('all (picked) events', self.get_manu_picked_events, None),
('all events', self.get_all_events, None)]
self.listWidget = QListWidget()
self.setDirty(True)
self.apw = AutoPickWidget(self, self.pickoptions)
self.apw.insert_log_widget(self.listWidget)
self.apw.refresh_tooltips()
self.listWidget = QListWidget()
self.setDirty(True)
self.apw = AutoPickWidget(self, self.pickoptions)
self.apw.insert_log_widget(self.listWidget)
self.apw.refresh_tooltips()
self.apw.start.connect(self.start_autopick)
self.apw.start.connect(self.start_autopick)
self.apw.show()
def start_autopick(self):
for key, func in self.pickoptions:
if not self.pickoptions:
return
for key, func, _ in self.pickoptions:
if self.apw.rb_dict[key].isChecked():
# if radio button is checked break for loop and use func
break
@@ -2052,7 +2188,6 @@ class MainWindow(QMainWindow):
def finalizeAutoPick(self, result):
self.apw.enable(True)
if result:
result = removePicksAbove(result, 3)
self.init_canvas_dict_wadatijack()
for eventID in result.keys():
event = self.get_event_from_id(eventID)
@@ -2179,7 +2314,7 @@ class MainWindow(QMainWindow):
if self.pg:
pw = self.getPlotWidget().plotWidget
else:
ax = self.getPlotWidget().axes
ax = self.getPlotWidget().axes[0]
ylims = np.array([-.5, +.5]) + plotID
stat_picks = self.getPicks(type=picktype)[station]
@@ -2220,6 +2355,7 @@ class MainWindow(QMainWindow):
pen = make_pen(picktype, phaseID, 'lpp', quality)
pw.plot([lpp, lpp], ylims,
alpha=.25, pen=pen, name='LPP')
pen = make_pen(picktype, phaseID, 'mpp', quality)
if spe:
# pen = make_pen(picktype, phaseID, 'spe', quality)
# spe_l = pg.PlotDataItem([mpp - spe, mpp - spe], ylims, pen=pen,
@@ -2236,7 +2372,6 @@ class MainWindow(QMainWindow):
# fb = pw.addItem(fill)
# except:
# print('Warning: drawPicks: Could not create fill for symmetric pick error.')
pen = make_pen(picktype, phaseID, 'mpp', quality)
pw.plot([mpp, mpp], ylims, pen=pen, name='{}-Pick'.format(phase))
else:
pw.plot([mpp, mpp], ylims, pen=pen, name='{}-Pick (NO PICKERROR)'.format(phase))
@@ -2409,7 +2544,8 @@ class MainWindow(QMainWindow):
Start modal thread to init the array_map object.
'''
# Note: basemap generation freezes GUI but cannot be threaded as it generates a Pixmap.
self.amt = Thread(self, self.array_map.init_map, arg=None, progressText='Generating map...')
self.amt = Thread(self, self.array_map.init_map, arg=None, progressText='Generating map...',
pb_widget=self.mainProgressBarWidget)
self.amt.finished.connect(self.finish_array_map)
self.amt.start()
@@ -2436,7 +2572,7 @@ class MainWindow(QMainWindow):
lon = event.origins[0].longitude
self.array_map.eventLoc = (lat, lon)
if self.get_current_event():
self.array_map.refresh_drawings(self.get_current_event().getPicks())
self.array_map.refresh_drawings(self.get_current_event().getAutopicks())
self._eventChanged[1] = False
def init_event_table(self, tabindex=2):
@@ -2500,7 +2636,7 @@ class MainWindow(QMainWindow):
self.events_layout.removeWidget(self.event_table)
# init new qtable
self.event_table = QtGui.QTableWidget()
self.event_table = QtGui.QTableWidget(self)
self.event_table.setColumnCount(12)
self.event_table.setRowCount(len(eventlist))
self.event_table.setHorizontalHeaderLabels(['',
@@ -2554,8 +2690,8 @@ class MainWindow(QMainWindow):
item_notes = QtGui.QTableWidgetItem()
# manipulate items
item_ref.setBackground(self._colors['ref'])
item_test.setBackground(self._colors['test'])
item_ref.setBackground(self._ref_test_colors['ref'])
item_test.setBackground(self._ref_test_colors['test'])
item_path.setText(event.path)
if hasattr(event, 'origins'):
if event.origins:
@@ -2611,7 +2747,8 @@ class MainWindow(QMainWindow):
self.tabs.setCurrentIndex(tabindex)
def read_metadata_thread(self, fninv):
self.rm_thread = Thread(self, read_metadata, arg=fninv, progressText='Reading metadata...')
self.rm_thread = Thread(self, read_metadata, arg=fninv, progressText='Reading metadata...',
pb_widget=self.mainProgressBarWidget)
self.rm_thread.finished.connect(self.set_metadata)
self.rm_thread.start()
@@ -2629,7 +2766,7 @@ class MainWindow(QMainWindow):
def get_new_metadata(self):
self.init_metadata(new=True)
def init_metadata(self, new=False):
def init_metadata(self, new=False, ask_default=True):
def set_inv(settings):
fninv, _ = QFileDialog.getOpenFileName(self, self.tr(
"Select inventory..."), self.tr("Select file"))
@@ -2658,7 +2795,7 @@ class MainWindow(QMainWindow):
settings.setValue("inventoryFile", self.project.inv_path)
fninv = settings.value("inventoryFile", None)
if fninv:
if fninv and ask_default:
ans = QMessageBox.question(self, self.tr("Use default metadata..."),
self.tr(
"Do you want to use the default value for metadata?\n({})".format(fninv)),
@@ -2669,6 +2806,8 @@ class MainWindow(QMainWindow):
return None
elif ans == QMessageBox.Yes:
self.read_metadata_thread(fninv)
if fninv and not ask_default:
self.read_metadata_thread(fninv)
def calc_magnitude(self, type='ML'):
self.init_metadata()
@@ -2681,7 +2820,7 @@ class MainWindow(QMainWindow):
# raise ProcessingError('Restitution of waveform data failed!')
if type == 'ML':
local_mag = LocalMagnitude(corr_wf, self.get_data().get_evt_data(), self.inputs.get('sstop'),
verbosity=True)
verbosity=True) ## MP MP missing parameter wascaling in function call!
return local_mag.updated_event()
elif type == 'Mw':
moment_mag = MomentMagnitude(corr_wf, self.get_data().get_evt_data(), self.inputs.get('vp'),
@@ -2777,7 +2916,7 @@ class MainWindow(QMainWindow):
if not self.okToContinue():
return
if not fnm:
dlg = QFileDialog()
dlg = QFileDialog(parent=self)
fnm = dlg.getOpenFileName(self, 'Open project file...', filter='Pylot project (*.plp)')
if not fnm:
return
@@ -2792,10 +2931,12 @@ class MainWindow(QMainWindow):
self.setDirty(False)
if hasattr(self.project, 'metadata'):
if self.project.metadata:
self.init_array_map(index=0)
self.init_metadata(ask_default=False)
#self.init_array_map(index=0)
return
if hasattr(self.project, 'inv_path'):
self.init_array_map(index=0)
self.init_metadata(ask_default=False)
#self.init_array_map(index=0)
return
self.init_array_tab()
@@ -2804,7 +2945,7 @@ class MainWindow(QMainWindow):
'''
Save back project to new pickle file.
'''
dlg = QFileDialog()
dlg = QFileDialog(self)
fnm = dlg.getSaveFileName(self, 'Create a new project file...', filter='Pylot project (*.plp)')
filename = fnm[0]
if not len(fnm[0]):
@@ -2866,7 +3007,7 @@ class MainWindow(QMainWindow):
def setParameter(self, show=True):
if not self.paraBox:
self.paraBox = PylotParaBox(self._inputs)
self.paraBox = PylotParaBox(self._inputs, parent=self, windowflag=1)
self.paraBox.accepted.connect(self._setDirty)
self.paraBox.accepted.connect(self.filterOptionsFromParameter)
if show:
@@ -2884,16 +3025,16 @@ class MainWindow(QMainWindow):
def helpHelp(self):
if checkurl():
form = HelpForm(
form = HelpForm(self,
'https://ariadne.geophysik.ruhr-uni-bochum.de/trac/PyLoT/wiki')
else:
form = HelpForm(':/help.html')
form = HelpForm(self, ':/help.html')
form.show()
class Project(object):
'''
Pickable class containing information of a QtPyLoT project, like event lists and file locations.
Pickable class containing information of a PyLoT project, like event lists and file locations.
'''
def __init__(self):
@@ -2958,7 +3099,7 @@ class Project(object):
print(e, datetime, filename)
continue
for event in self.eventlist:
if eventID in str(event.resource_id) or eventID in event.origins:
if eventID in str(event.resource_id) or event.origins:
if event.origins:
origin = event.origins[0] # should have only one origin
if origin.time == datetime:
@@ -3078,9 +3219,10 @@ def create_window():
if app is None:
app = QApplication(sys.argv)
app_created = True
app.setOrganizationName("QtPyLoT");
app.setOrganizationDomain("rub.de");
app.setApplicationName("RUB");
# set aplication/organization name, domain (important to do this BEFORE setupUI is called for correct QSettings)
app.setOrganizationName("Ruhr-University Bochum / BESTEC")
app.setOrganizationDomain("rub.de")
app.setApplicationName("PyLoT")
app.references = set()
# app.references.add(window)
# window.show()
@@ -3089,6 +3231,7 @@ def create_window():
def main(args=None):
project_filename = None
#args.project_filename = 'C:/Shared/AlpArray/alparray_data/project_alparray_test.plp'
pylot_infile = None
if args:
if args.project_filename:
@@ -3108,22 +3251,17 @@ def main(args=None):
# create the main window
pylot_form = MainWindow(infile=pylot_infile)
icon = QIcon()
pylot_form.setWindowIcon(icon)
pylot_form.setWindowIcon(app_icon)
pylot_form.setIconSize(QSize(60, 60))
splash.showMessage('Loading. Please wait ...')
pylot_app.processEvents()
# set Application Information
pylot_app.setOrganizationName("Ruhr-University Bochum / BESTEC")
pylot_app.setOrganizationDomain("rub.de")
pylot_app.processEvents()
pylot_app.setApplicationName("PyLoT")
# set other App information
pylot_app.setApplicationVersion(pylot_form.__version__)
pylot_app.setWindowIcon(app_icon)
pylot_app.processEvents()
splash.showMessage('Loading. Please wait ...')
pylot_app.processEvents()
# Show main window and run the app
pylot_form.showMaximized()
pylot_app.processEvents()
+110 -90
View File
@@ -1,90 +1,110 @@
# PyLoT
version: 0.1a
The Python picking and Localisation Tool
This python library contains a graphical user interfaces for picking
seismic phases. This software needs [ObsPy][ObsPy]
and the PySide Qt4 bindings for python to be installed first.
PILOT has originally been developed in Mathworks' MatLab. In order to
distribute PILOT without facing portability problems, it has been decided
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
benefit a lot compared to the former MatLab version.
The development of PyLoT is part of the joint research project MAGS2.
## 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:
In order to run PyLoT you need to install:
- python
- scipy
- numpy
- matplotlib
- obspy
- pyside
#### Some handwork:
PyLoT needs a properties folder on your system to work. It should be situated in your home directory:
mkdir ~/.pylot
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
cp path-to-pylot/inputs/autoPyLoT_local.in ~/.pylot/autoPyLoT.in
for regional distance seismicity
cp path-to-pylot/inputs/autoPyLoT_regional.in ~/.pylot/autoPyLoT.in
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.
PyLoT has been tested on Mac OSX (10.11) and Debian Linux 8.
## Release notes
#### Features:
- consistent manual phase picking through predefined SNR dependant zoom level
- uniform uncertainty estimation from waveform's properties for automatic and manual picks
- pdf representation and comparison of picks taking the uncertainty intrinsically into account
- Richter and moment magnitude estimation
- location determination with external installation of [NonLinLoc](http://alomax.free.fr/nlloc/index.html)
#### Known issues:
- Magnitude estimation from manual PyLoT takes some time (instrument correction)
We hope to solve these with the next release.
## Staff
Original author(s): L. Kueperkoch, S. Wehling-Benatelli, M. Bischoff (PILOT)
Developer(s): S. Wehling-Benatelli, L. Kueperkoch, K. Olbert, M. Bischoff,
C. Wollin, M. Rische, M. Paffrath
Others: A. Bruestle, T. Meier, W. Friederich
[ObsPy]: http://github.com/obspy/obspy/wiki
October 2016
# PyLoT
version: 0.2
The Python picking and Localisation Tool
This python library contains a graphical user interfaces for picking
seismic phases. This software needs [ObsPy][ObsPy]
and the PySide Qt4 bindings for python to be installed first.
PILOT has originally been developed in Mathworks' MatLab. In order to
distribute PILOT without facing portability problems, it has been decided
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
benefit a lot compared to the former MatLab version.
The development of PyLoT is part of the joint research project MAGS2 and AlpArray.
## 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:
In order to run PyLoT you need to install:
- python 2 or 3
- scipy
- numpy
- matplotlib
- obspy
- pyside
#### Some handwork:
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
In the next step you have to copy some files to this directory:
*for local distance seismicity*
cp path-to-pylot/inputs/pylot_local.in ~/.pylot/pylot.in
*for regional distance seismicity*
cp path-to-pylot/inputs/pylot_regional.in ~/.pylot/pylot.in
*for global distance seismicity*
cp path-to-pylot/inputs/pylot_global.in ~/.pylot/pylot.in
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.
PyLoT has been tested on Mac OSX (10.11), Debian Linux 8 and on Windows 10.
## 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:
- 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
## Staff
Original author(s): L. Kueperkoch, S. Wehling-Benatelli, M. Bischoff (PILOT)
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
September 2017
+4 -4
View File
@@ -311,7 +311,7 @@ def autoPyLoT(input_dict=None, parameter=None, inputfile=None, fnames=None, even
# calculate seismic moment Mo and moment magnitude Mw
moment_mag = MomentMagnitude(corr_dat, evt, parameter.get('vp'),
parameter.get('Qp'),
parameter.get('rho'), True, \
parameter.get('rho'), True,
iplot)
# update pick with moment property values (w0, fc, Mo)
for stats, props in moment_mag.moment_props.items():
@@ -374,7 +374,7 @@ def autoPyLoT(input_dict=None, parameter=None, inputfile=None, fnames=None, even
for key in picks:
if picks[key]['P']['weight'] >= 4 or picks[key]['S']['weight'] >= 4:
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)))
if len(badpicks) == 0:
print("autoPyLoT: No more bad onsets found, stop iterative picking!")
@@ -384,7 +384,7 @@ def autoPyLoT(input_dict=None, parameter=None, inputfile=None, fnames=None, even
# calculate seismic moment Mo and moment magnitude Mw
moment_mag = MomentMagnitude(corr_dat, evt, parameter.get('vp'),
parameter.get('Qp'),
parameter.get('rho'), True, \
parameter.get('rho'), True,
iplot)
# update pick with moment property values (w0, fc, Mo)
for stats, props in moment_mag.moment_props.items():
@@ -502,4 +502,4 @@ if __name__ == "__main__":
picks = autoPyLoT(inputfile=str(cla.inputfile), fnames=str(cla.fnames),
eventid=str(cla.eventid), savepath=str(cla.spath),
ncores=cla.ncores, iplot=str(cla.iplot))
ncores=cla.ncores, iplot=int(cla.iplot))
-8
View File
@@ -1,8 +0,0 @@
git pull
Entferne qrc_resources.py
KONFLIKT (ändern/löschen): pylot/core/pick/getSNR.py gelöscht in HEAD und geändert in 67dd66535a213ba5c7cfe2be52aa6d5a7e8b7324. Stand 67dd66535a213ba5c7cfe2be52aa6d5a7e8b7324 von pylot/core/pick/getSNR.py wurde im Arbeitsbereich gelassen.
KONFLIKT (ändern/löschen): pylot/core/pick/fmpicker.py gelöscht in HEAD und geändert in 67dd66535a213ba5c7cfe2be52aa6d5a7e8b7324. Stand 67dd66535a213ba5c7cfe2be52aa6d5a7e8b7324 von pylot/core/pick/fmpicker.py wurde im Arbeitsbereich gelassen.
KONFLIKT (ändern/löschen): pylot/core/pick/earllatepicker.py gelöscht in HEAD und geändert in 67dd66535a213ba5c7cfe2be52aa6d5a7e8b7324. Stand 67dd66535a213ba5c7cfe2be52aa6d5a7e8b7324 von pylot/core/pick/earllatepicker.py wurde im Arbeitsbereich gelassen.
Automatisches Zusammenfügen von icons.qrc
Automatischer Merge fehlgeschlagen; beheben Sie die Konflikte und committen Sie dann das Ergebnis.
+2
View File
@@ -2,6 +2,8 @@
<qresource>
<file>icons/pylot.ico</file>
<file>icons/pylot.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>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

After

Width:  |  Height:  |  Size: 30 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 39 KiB

+7132 -4927
View File
File diff suppressed because it is too large Load Diff
+7132 -4927
View File
File diff suppressed because it is too large Load Diff
-100
View 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
-99
View File
@@ -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.05 0.10 0.20 0.40 #timeerrorsP# %discrete time errors [s] corresponding to picking weights [0 1 2 3] for P
0.10 0.20 0.40 0.80 #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
View 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!
%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
-2
View File
@@ -1,2 +0,0 @@
P bandpass 4 2.0 20.0
S bandpass 4 2.0 15.0
+40 -38
View File
@@ -4,19 +4,19 @@
%Parameters are optimized for %extent data sets!
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
#main settings#
/home/marcel/marcel_scratch #rootpath# %project path
alparray #datapath# %data path
waveforms #database# %name of data base
e0006.036.13 #eventID# %event ID for single event processing (* for all events found in database)
None #invdir# %full path to inventory or dataless-seed file
#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#
/progs/bin #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
Insheim_min1d032016_auto.in #ctrfile# %name of autoPyLoT-output control file for NLLoc
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
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -37,62 +37,64 @@ bandpass bandpass #filter_type# %filter type
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
#common settings picker#
global #extent# %extent of array ("local", "regional" or "global")
50.0 #pstart# %start time [s] for calculating CF for P-picking
600.0 #pstop# %end time [s] for calculating CF for P-picking
-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
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.01 0.5 #bpz2# %lower/upper corner freq. of second 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.01 0.5 #bph2# %lower/upper corner freq. of second band pass filter z-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)
15.0 #tlta# %for HOS-/AR-AIC-picker, length of LTA window [s]
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
6.0 #tdet1z# %for AR-picker, length of AR determination window [s] for Z-component, 1st pick
2.0 #tpred1z# %for AR-picker, length of AR prediction window [s] for Z-component, 1st pick
3.0 #tdet2z# %for AR-picker, length of AR determination window [s] for Z-component, 2nd pick
1.0 #tpred2z# %for AR-picker, length of AR prediction window [s] for Z-component, 2nd pick
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 150.0 3.0 #tsnrz# %for HOS/AR, window lengths for SNR-and slope estimation [tnoise, tsafetey, tsignal, tslope] [s]
10.0 #pickwinP# %for initial AIC pick, length of P-pick window [s]
20.0 #Precalcwin# %for HOS/AR, window length [s] for recalculation of CF (relative to 1st pick)
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)
6.0 #tdet1h# %for HOS/AR, length of AR-determination window [s], H-components, 1st pick
4.0 #tpred1h# %for HOS/AR, length of AR-prediction window [s], H-components, 1st pick
6.0 #tdet2h# %for HOS/AR, length of AR-determinaton window [s], H-components, 2nd pick
3.0 #tpred2h# %for HOS/AR, length of AR-prediction window [s], H-components, 2nd pick
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
5.0 #Srecalcwin# %for AR-picker, window length [s] for recalculation of CF (2nd pick) (H)
15.0 #pickwinS# %for initial AIC pick, length of S-pick window [s]
100.0 10.0 40.0 6.0 #tsnrh# %for ARH/AR3, window lengths for SNR-and slope estimation [tnoise, tsafetey, tsignal, tslope] [s]
2.0 #aictsmoothS# %for AIC-picker, take average of samples for smoothing of AIC-function [s]
3.0 #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)
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
2.0 #minFMSNR# %miniumum required SNR for first-motion determination
0.2 #fmpickwin# %pick window around P onset for calculating zero crossings
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.5 #minAICSSNR# %below this SNR 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.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
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
View 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
View 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
+11 -5
View File
@@ -158,23 +158,29 @@ def buildPyLoT(verbosity=None):
def installPyLoT(verbosity=None):
files_to_copy = {'autoPyLoT_local.in': ['~', '.pylot'],
'autoPyLoT_regional.in': ['~', '.pylot']}
files_to_copy = {'pylot_local.in': ['~', '.pylot'],
'pylot_regional.in': ['~', '.pylot'],
'pylot_global.in': ['~', '.pylot']}
if verbosity > 0:
print('starting installation of PyLoT ...')
if verbosity > 1:
print('copying input files into destination folder ...')
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):
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 = []
for file, destination in files_to_copy.items():
link_file = ans in file
if link_file:
link_dest = copy.deepcopy(destination)
link_dest.append('autoPyLoT.in')
link_dest.append('pylot.in')
link_dest = os.path.join(*link_dest)
destination.append(file)
destination = os.path.join(*destination)
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

+3 -3
View File
@@ -617,9 +617,9 @@ def calcsourcespec(wfstream, onset, vp, delta, azimuth, incidence,
p3, = plt.loglog(F, YYcor, 'r')
p4, = plt.loglog(F, fit, 'g')
plt.loglog([fc, fc], [w0 / 100, w0], 'g')
plt.legend([p1, p2, p3, p4], ['Raw Spectrum', \
'Used Raw Spectrum', \
'Q-Corrected Spectrum', \
plt.legend([p1, p2, p3, p4], ['Raw Spectrum',
'Used Raw Spectrum',
'Q-Corrected Spectrum',
'Fit to Spectrum'])
plt.title('Source Spectrum from P Pulse, w0=%e m/Hz, fc=%6.2f Hz' \
% (w0, fc))
-240
View File
@@ -1,240 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Created August/September 2015.
:author: Ludger Küperkoch / MAGS2 EP3 working group
"""
import matplotlib.pyplot as plt
import numpy as np
from obspy.core import Stream
from pylot.core.pick.utils import getsignalwin
from scipy.optimize import curve_fit
class Magnitude(object):
'''
Superclass for calculating Wood-Anderson peak-to-peak
amplitudes, local magnitudes and moment magnitudes.
'''
def __init__(self, wfstream, To, pwin, iplot):
'''
:param: wfstream
:type: `~obspy.core.stream.Stream
:param: To, onset time, P- or S phase
:type: float
:param: pwin, pick window [To To+pwin] to get maximum
peak-to-peak amplitude (WApp) or to calculate
source spectrum (DCfc)
:type: float
:param: iplot, no. of figure window for plotting interims results
:type: integer
'''
assert isinstance(wfstream, Stream), "%s is not a stream object" % str(wfstream)
self.setwfstream(wfstream)
self.setTo(To)
self.setpwin(pwin)
self.setiplot(iplot)
self.calcwapp()
self.calcsourcespec()
def getwfstream(self):
return self.wfstream
def setwfstream(self, wfstream):
self.wfstream = wfstream
def getTo(self):
return self.To
def setTo(self, To):
self.To = To
def getpwin(self):
return self.pwin
def setpwin(self, pwin):
self.pwin = pwin
def getiplot(self):
return self.iplot
def setiplot(self, iplot):
self.iplot = iplot
def getwapp(self):
return self.wapp
def getw0(self):
return self.w0
def getfc(self):
return self.fc
def calcwapp(self):
self.wapp = None
def calcsourcespec(self):
self.sourcespek = None
class WApp(Magnitude):
'''
Method to derive peak-to-peak amplitude as seen on a Wood-Anderson-
seismograph. Has to be derived from instrument corrected traces!
'''
def calcwapp(self):
print("Getting Wood-Anderson peak-to-peak amplitude ...")
print("Simulating Wood-Anderson seismograph ...")
self.wapp = None
stream = self.getwfstream()
# poles, zeros and sensitivity of WA seismograph
# (see Uhrhammer & Collins, 1990, BSSA, pp. 702-716)
paz_wa = {
'poles': [5.6089 - 5.4978j, -5.6089 - 5.4978j],
'zeros': [0j, 0j],
'gain': 2080,
'sensitivity': 1}
stream.simulate(paz_remove=None, paz_simulate=paz_wa)
trH1 = stream[0].data
trH2 = stream[1].data
ilen = min([len(trH1), len(trH2)])
# get RMS of both horizontal components
sqH = np.sqrt(np.power(trH1[0:ilen], 2) + np.power(trH2[0:ilen], 2))
# get time array
th = np.arange(0, len(sqH) * stream[0].stats.delta, stream[0].stats.delta)
# get maximum peak within pick window
iwin = getsignalwin(th, self.getTo(), self.getpwin())
self.wapp = np.max(sqH[iwin])
print("Determined Wood-Anderson peak-to-peak amplitude: %f mm") % self.wapp
if self.getiplot() > 1:
stream.plot()
f = plt.figure(2)
plt.plot(th, sqH)
plt.plot(th[iwin], sqH[iwin], 'g')
plt.plot([self.getTo(), self.getTo()], [0, max(sqH)], 'r', linewidth=2)
plt.title('Station %s, RMS Horizontal Traces, WA-peak-to-peak=%4.1f mm' \
% (stream[0].stats.station, self.wapp))
plt.xlabel('Time [s]')
plt.ylabel('Displacement [mm]')
plt.show()
raw_input()
plt.close(f)
class DCfc(Magnitude):
'''
Method to calculate the source spectrum and to derive from that the plateau
(so-called DC-value) and the corner frequency assuming Aki's omega-square
source model. Has to be derived from instrument corrected displacement traces!
'''
def calcsourcespec(self):
print("Calculating source spectrum ....")
self.w0 = None # DC-value
self.fc = None # corner frequency
stream = self.getwfstream()
tr = stream[0]
# get time array
t = np.arange(0, len(tr) * tr.stats.delta, tr.stats.delta)
iwin = getsignalwin(t, self.getTo(), self.getpwin())
xdat = tr.data[iwin]
# fft
fny = tr.stats.sampling_rate / 2
l = len(xdat) / tr.stats.sampling_rate
n = tr.stats.sampling_rate * l # number of fft bins after Bath
# find next power of 2 of data length
m = pow(2, np.ceil(np.log(len(xdat)) / np.log(2)))
N = int(np.power(m, 2))
y = tr.stats.delta * np.fft.fft(xdat, N)
Y = abs(y[: N / 2])
L = (N - 1) / tr.stats.sampling_rate
f = np.arange(0, fny, 1 / L)
# remove zero-frequency and frequencies above
# corner frequency of seismometer (assumed
# to be 100 Hz)
fi = np.where((f >= 1) & (f < 100))
F = f[fi]
YY = Y[fi]
# get plateau (DC value) and corner frequency
# initial guess of plateau
DCin = np.mean(YY[0:100])
# initial guess of corner frequency
# where spectral level reached 50% of flat level
iin = np.where(YY >= 0.5 * DCin)
Fcin = F[iin[0][np.size(iin) - 1]]
fit = synthsourcespec(F, DCin, Fcin)
[optspecfit, pcov] = curve_fit(synthsourcespec, F, YY.real, [DCin, Fcin])
self.w0 = optspecfit[0]
self.fc = optspecfit[1]
print("DCfc: Determined DC-value: %e m/Hz, \n" \
"Determined corner frequency: %f Hz" % (self.w0, self.fc))
# if self.getiplot() > 1:
iplot = 2
if iplot > 1:
print("DCfc: Determined DC-value: %e m/Hz, \n"
"Determined corner frequency: %f Hz" % (self.w0, self.fc))
if self.getiplot() > 1:
f1 = plt.figure()
plt.subplot(2, 1, 1)
# show displacement in mm
plt.plot(t, np.multiply(tr, 1000), 'k')
plt.plot(t[iwin], np.multiply(xdat, 1000), 'g')
plt.title('Seismogram and P pulse, station %s' % tr.stats.station)
plt.xlabel('Time since %s' % tr.stats.starttime)
plt.ylabel('Displacement [mm]')
plt.subplot(2, 1, 2)
plt.loglog(f, Y.real, 'k')
plt.loglog(F, YY.real)
plt.loglog(F, fit, 'g')
plt.title('Source Spectrum from P Pulse, DC=%e m/Hz, fc=%4.1f Hz' \
% (self.w0, self.fc))
plt.xlabel('Frequency [Hz]')
plt.ylabel('Amplitude [m/Hz]')
plt.grid()
plt.show()
raw_input()
plt.close(f1)
def synthsourcespec(f, omega0, fcorner):
'''
Calculates synthetic source spectrum from given plateau and corner
frequency assuming Akis omega-square model.
:param: f, frequencies
:type: array
:param: omega0, DC-value (plateau) of source spectrum
:type: float
:param: fcorner, corner frequency of source spectrum
:type: float
'''
# ssp = omega0 / (pow(2, (1 + f / fcorner)))
ssp = omega0 / (1 + pow(2, (f / fcorner)))
return ssp
+2 -3
View File
@@ -240,8 +240,8 @@ class Data(object):
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 \
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
@@ -442,7 +442,6 @@ class Data(object):
else:
if self.get_evt_data().picks:
raise OverwriteError('Existing picks would be overwritten!')
break
else:
picks = picks_from_picksdict(picks)
break
+2 -26
View File
@@ -273,26 +273,6 @@ defaults = {'rootpath': {'type': str,
'value': 1.5,
'namestring': 'Noise factor S'},
'checkwindowP': {'type': float,
'tooltip': 'time window before HOS/AR-maximum to check for smaller maxima [s]',
'value': 10.0,
'namestring': 'Check Window P'},
'minfactorP': {'type': float,
'tooltip': 'Second maximum must be at least minfactor * first maximum [-]',
'value': 0.7,
'namestring': 'Minimum Factor P'},
'checkwindowS': {'type': float,
'tooltip': 'time window before AR-maximum to check for smaller maxima [s]',
'value': 10.0,
'namestring': 'Check Window S'},
'minfactorS': {'type': float,
'tooltip': 'Second maximum must be at least minfactor * first maximum [-]',
'value': 0.7,
'namestring': 'Minimum Factor S'},
'minfmweight': {'type': int,
'tooltip': 'minimum required P weight for first-motion determination',
'value': 1,
@@ -475,9 +455,7 @@ settings_special_pick = {
'aictsmooth',
'tsmoothP',
'ausP',
'nfacP',
'checkwindowP',
'minfactorP'],
'nfacP'],
'h': [
'algoS',
'tdet1h',
@@ -491,9 +469,7 @@ settings_special_pick = {
'aictsmoothS',
'tsmoothS',
'ausS',
'nfacS',
'checkwindowS',
'minfactorS'],
'nfacS'],
'fm': [
'minfmweight',
'minFMSNR',
+6 -6
View File
@@ -865,8 +865,8 @@ def merge_picks(event, picks):
if p.waveform_id.station_code == station\
and p.waveform_id.network_code == network\
and p.phase_hint == phase\
and (str(p.method_id) in str(method)\
or str(method) in str(p.method_id)):
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
@@ -907,15 +907,15 @@ def getQualitiesfromxml(xmlnames, ErrorsP, ErrorsS, plotflag=1):
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 \
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 \
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
+69 -29
View File
@@ -38,7 +38,7 @@ def autopickevent(data, param, iplot=0, fig_dict=None, fig_dict_wadatijack=None,
# get some parameters for quality control from
# parameter input file (usually autoPyLoT.in).
# parameter input file (usually pylot.in).
wdttolerance = param.get('wdttolerance')
mdttolerance = param.get('mdttolerance')
jackfactor = param.get('jackfactor')
@@ -64,8 +64,11 @@ def autopickevent(data, param, iplot=0, fig_dict=None, fig_dict_wadatijack=None,
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))
'stations on {} cores.'.format(len(input_tuples), ncores_str))
pool = gen_Pool(ncores)
result = pool.map(call_autopickstation, input_tuples)
@@ -110,7 +113,7 @@ def autopickstation(wfstream, pickparam, verbose=False,
:type wfstream: obspy.core.stream.Stream
:param pickparam: container of picking parameters from input file,
usually autoPyLoT.in
usually pylot.in
:type pickparam: PylotParameter
:param verbose:
:type verbose: bool
@@ -118,7 +121,7 @@ def autopickstation(wfstream, pickparam, verbose=False,
"""
# 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
@@ -177,10 +180,6 @@ def autopickstation(wfstream, pickparam, verbose=False,
# parameter to check for spuriously picked S onset
zfac = pickparam.get('zfac')
# path to inventory-, dataless- or resp-files
checkwindowP = pickparam.get('checkwindowP')
minfactorP = pickparam.get('minfactorP')
checkwindowS = pickparam.get('checkwindowS')
minfactorS = pickparam.get('minfactorS')
# initialize output
Pweight = 4 # weight for P onset
@@ -229,8 +228,10 @@ def autopickstation(wfstream, pickparam, verbose=False,
data=str(zdat))
if verbose: print(msg)
z_copy = zdat.copy()
# filter and taper data
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],
zerophase=False)
tr_filt.taper(max_percentage=0.05, type='hann')
@@ -326,10 +327,11 @@ def autopickstation(wfstream, pickparam, verbose=False,
key = 'aicFig'
if fig_dict:
fig = fig_dict[key]
linecolor = fig_dict['plot_style']['linecolor']['rgba_mpl']
else:
fig = None
aicpick = AICPicker(aiccf, tsnrz, pickwinP, checkwindow=checkwindowP, minfactor=minfactorP,
iplot=iplot, Tsmooth=tsmoothP, fig=fig)
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:
@@ -352,16 +354,21 @@ def autopickstation(wfstream, pickparam, verbose=False,
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,
minsiglength / 2,
nfacsl, minpercent, iplot,
fig)
fig, linecolor)
else:
# filter and taper horizontal traces
trH1_filt = edat.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],
freqmax=bph1[1],
zerophase=False)
@@ -374,12 +381,14 @@ def autopickstation(wfstream, pickparam, verbose=False,
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,
minsiglength,
nfacsl, minpercent, iplot,
fig)
fig, linecolor)
if Pflag == 1:
# check for spuriously picked S onset
@@ -392,10 +401,12 @@ def autopickstation(wfstream, pickparam, verbose=False,
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,
tsnrz[2], iplot, fig)
tsnrz[2], iplot, fig, linecolor)
if Pflag == 0:
Pmarker = 'SinsteadP'
Pweight = 9
@@ -418,6 +429,7 @@ def autopickstation(wfstream, pickparam, verbose=False,
# re-filter waveform with larger bandpass
z_copy = zdat.copy()
tr_filt = zdat[0].copy()
tr_filt.detrend(type='demean')
tr_filt.filter('bandpass', freqmin=bpz2[0], freqmax=bpz2[1],
zerophase=False)
tr_filt.taper(max_percentage=0.05, type='hann')
@@ -447,10 +459,12 @@ def autopickstation(wfstream, pickparam, verbose=False,
algoP=algoP)
if fig_dict:
fig = fig_dict['refPpick']
linecolor = fig_dict['plot_style']['linecolor']['rgba_mpl']
else:
fig = None
refPpick = PragPicker(cf2, tsnrz, pickwinP, iplot=iplot, aus=ausP, Tsmooth=tsmoothP,
Pick1 = aicpick.getpick(), fig=fig)
linecolor = 'k'
refPpick = PragPicker(cf2, tsnrz, pickwinP, iplot, ausP, tsmoothP,
aicpick.getpick(), fig, linecolor)
mpickP = refPpick.getpick()
#############################################################
if mpickP is not None:
@@ -459,10 +473,13 @@ def autopickstation(wfstream, pickparam, verbose=False,
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)
mpickP, iplot, fig=fig,
linecolor=linecolor)
else:
epickP, lpickP, Perror = earllatepicker(z_copy, nfacP, tsnrz,
mpickP, iplot)
@@ -492,9 +509,10 @@ def autopickstation(wfstream, pickparam, verbose=False,
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)
FM = fmpicker(zdat, z_copy, fmpickwin, mpickP, iplot, fig, linecolor)
else:
FM = fmpicker(zdat, z_copy, fmpickwin, mpickP, iplot)
else:
@@ -574,6 +592,8 @@ def autopickstation(wfstream, pickparam, verbose=False,
# filter and taper data
trH1_filt = hdat[0].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],
zerophase=False)
trH2_filt.filter('bandpass', freqmin=bph1[0], freqmax=bph1[1],
@@ -592,6 +612,9 @@ def autopickstation(wfstream, pickparam, verbose=False,
trH1_filt = hdat[0].copy()
trH2_filt = hdat[1].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],
zerophase=False)
trH2_filt.filter('bandpass', freqmin=bph1[0], freqmax=bph1[1],
@@ -629,11 +652,12 @@ def autopickstation(wfstream, pickparam, verbose=False,
# of class AutoPicking
if fig_dict:
fig = fig_dict['aicARHfig']
linecolor = fig_dict['plot_style']['linecolor']['rgba_mpl']
else:
fig = None
aicarhpick = AICPicker(haiccf, tsnrh, pickwinS, checkwindow=checkwindowS,
minfactor=minfactorS, iplot=iplot, Tsmooth=aictsmoothS,
fig=fig)
linecolor = 'k'
aicarhpick = AICPicker(haiccf, tsnrh, pickwinS, iplot, None,
aictsmoothS, fig=fig, linecolor=linecolor)
###############################################################
# go on with processing if AIC onset passes quality control
slope = aicarhpick.getSlope()
@@ -658,6 +682,8 @@ def autopickstation(wfstream, pickparam, verbose=False,
if algoS == 'ARH':
trH1_filt = hdat[0].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],
zerophase=False)
trH2_filt.filter('bandpass', freqmin=bph2[0], freqmax=bph2[1],
@@ -673,6 +699,9 @@ def autopickstation(wfstream, pickparam, verbose=False,
trH1_filt = hdat[0].copy()
trH2_filt = hdat[1].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],
zerophase=False)
trH2_filt.filter('bandpass', freqmin=bph2[0], freqmax=bph2[1],
@@ -692,10 +721,12 @@ def autopickstation(wfstream, pickparam, verbose=False,
# 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
refSpick = PragPicker(arhcf2, tsnrh, pickwinS, iplot=iplot, aus=ausS,
Tsmooth=tsmoothS, Pick1=aicarhpick.getpick(), fig=fig)
linecolor = 'k'
refSpick = PragPicker(arhcf2, tsnrh, pickwinS, iplot, ausS,
tsmoothS, aicarhpick.getpick(), fig, linecolor)
mpickS = refSpick.getpick()
#############################################################
if mpickS is not None:
@@ -705,12 +736,15 @@ def autopickstation(wfstream, pickparam, verbose=False,
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)
fig=fig,
linecolor=linecolor)
else:
epickS1, lpickS1, Serror1 = earllatepicker(h_copy, nfacS,
tsnrh,
@@ -720,12 +754,15 @@ def autopickstation(wfstream, pickparam, verbose=False,
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)
fig=fig,
linecolor=linecolor)
else:
epickS2, lpickS2, Serror2 = earllatepicker(h_copy, nfacS,
tsnrh,
@@ -817,7 +854,7 @@ def autopickstation(wfstream, pickparam, verbose=False,
hdat += ndat
else:
print('autopickstation: No horizontal component data available or ' \
print('autopickstation: No horizontal component data available or '
'bad P onset, skipping S picking!')
##############################################################
@@ -834,8 +871,11 @@ def autopickstation(wfstream, pickparam, verbose=False,
if fig_dict == None or fig_dict == 'None':
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,
tr_filt.stats.delta)
@@ -843,7 +883,7 @@ def autopickstation(wfstream, pickparam, verbose=False,
wfldiff = len(tr_filt.data) - len(tdata)
if wfldiff < 0:
tdata = tdata[0:len(tdata) - abs(wfldiff)]
ax1.plot(tdata, tr_filt.data / max(tr_filt.data), 'k', label='Data')
ax1.plot(tdata, tr_filt.data / max(tr_filt.data), color=linecolor, linewidth=0.7, label='Data')
if Pweight < 4:
ax1.plot(cf1.getTimeArray(), cf1.getCF() / max(cf1.getCF()),
'b', label='CF1')
@@ -902,7 +942,7 @@ def autopickstation(wfstream, pickparam, verbose=False,
wfldiff = len(trH1_filt.data) - len(th1data)
if wfldiff < 0:
th1data = th1data[0:len(th1data) - abs(wfldiff)]
ax2.plot(th1data, trH1_filt.data / max(trH1_filt.data), 'k', label='Data')
ax2.plot(th1data, trH1_filt.data / max(trH1_filt.data), color=linecolor, linewidth=0.7, label='Data')
if Pweight < 4:
ax2.plot(arhcf1.getTimeArray(),
arhcf1.getCF() / max(arhcf1.getCF()), 'b', label='CF1')
@@ -951,7 +991,7 @@ def autopickstation(wfstream, pickparam, verbose=False,
wfldiff = len(trH2_filt.data) - len(th2data)
if wfldiff < 0:
th2data = th2data[0:len(th2data) - abs(wfldiff)]
ax3.plot(th2data, trH2_filt.data / max(trH2_filt.data), 'k', label='Data')
ax3.plot(th2data, trH2_filt.data / max(trH2_filt.data), color=linecolor, linewidth=0.7, label='Data')
if Pweight < 4:
p22, = ax3.plot(arhcf1.getTimeArray(),
arhcf1.getCF() / max(arhcf1.getCF()), 'b', label='CF1')
+10 -17
View File
@@ -26,7 +26,7 @@ class CharacteristicFunction(object):
SuperClass for different types of characteristic functions.
'''
def __init__(self, data, cut, t2=None, order=None, t1=None, fnoise=None, stealthMode=False):
def __init__(self, data, cut, t2=None, order=None, t1=None, fnoise=None):
'''
Initialize data type object with information from the original
Seismogram.
@@ -63,7 +63,6 @@ class CharacteristicFunction(object):
self.calcCF(self.getDataArray())
self.arpara = np.array([])
self.xpred = np.array([])
self._stealthMode = stealthMode
def __str__(self):
return '''\n\t{name} object:\n
@@ -137,9 +136,6 @@ class CharacteristicFunction(object):
def getXCF(self):
return self.xcf
def _getStealthMode(self):
return self._stealthMode()
def getDataArray(self, cut=None):
'''
If cut times are given, time series is cut from cut[0] (start time)
@@ -224,13 +220,11 @@ class AICcf(CharacteristicFunction):
def calcCF(self, data):
# if self._getStealthMode() is False:
# print 'Calculating AIC ...'
x = self.getDataArray()
xnp = x[0].data
nn = np.isnan(xnp)
if len(nn) > 1:
xnp[nn] = 0
ind = np.where(~np.isnan(xnp))[0]
if ind.size:
xnp[:ind[0]] = xnp[ind[0]]
datlen = len(xnp)
k = np.arange(1, datlen)
cf = np.zeros(datlen)
@@ -264,13 +258,9 @@ class HOScf(CharacteristicFunction):
if len(nn) > 1:
xnp[nn] = 0
if self.getOrder() == 3: # this is skewness
# if self._getStealthMode() is False:
# print 'Calculating skewness ...'
y = np.power(xnp, 3)
y1 = np.power(xnp, 2)
elif self.getOrder() == 4: # this is kurtosis
# if self._getStealthMode() is False:
# print 'Calculating kurtosis ...'
y = np.power(xnp, 4)
y1 = np.power(xnp, 2)
@@ -345,7 +335,8 @@ class ARZcf(CharacteristicFunction):
cf = tap * cf
io = np.where(cf == 0)
ino = np.where(cf > 0)
cf[io] = cf[ino[0][0]]
if np.size(ino):
cf[io] = cf[ino[0][0]]
self.cf = cf
self.xcf = x
@@ -477,7 +468,8 @@ class ARHcf(CharacteristicFunction):
cf = tap * cf
io = np.where(cf == 0)
ino = np.where(cf > 0)
cf[io] = cf[ino[0][0]]
if np.size(ino):
cf[io] = cf[ino[0][0]]
self.cf = cf
self.xcf = xnp
@@ -619,7 +611,8 @@ class AR3Ccf(CharacteristicFunction):
cf = tap * cf
io = np.where(cf == 0)
ino = np.where(cf > 0)
cf[io] = cf[ino[0][0]]
if np.size(ino):
cf[io] = cf[ino[0][0]]
self.cf = cf
self.xcf = xnp
+2 -2
View File
@@ -118,8 +118,8 @@ class Comparison(object):
"""
compare_pdfs = dict()
pdf_a = self.get(self.names[0]).generate_pdf_data(type)
pdf_b = self.get(self.names[1]).generate_pdf_data(type)
pdf_a = self.get('auto').generate_pdf_data(type)
pdf_b = self.get('manu').generate_pdf_data(type)
for station, phases in pdf_a.items():
if station in pdf_b.keys():
+21 -20
View File
@@ -23,8 +23,9 @@ 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, get_maximum_index
from pylot.core.pick.utils import getnoisewin, getsignalwin
class AutoPicker(object):
@@ -35,7 +36,7 @@ class AutoPicker(object):
warnings.simplefilter('ignore')
def __init__(self, cf, TSNR, PickWindow, checkwindow=None, minfactor=None, iplot=0, aus=None, Tsmooth=None, Pick1=None, fig=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
:type: `~pylot.core.pick.CharFuns.CharacteristicFunction` object
@@ -62,7 +63,8 @@ class AutoPicker(object):
'''
assert isinstance(cf, CharacteristicFunction), "%s is not a CharacteristicFunction object" % str(cf)
self._linecolor = linecolor
self._pickcolor_p = 'b'
self.cf = cf.getCF()
self.Tcf = cf.getTimeArray()
self.Data = cf.getXCF()
@@ -74,8 +76,6 @@ class AutoPicker(object):
self.setTsmooth(Tsmooth)
self.setpick1(Pick1)
self.fig = fig
self.setCheckWindow(checkwindow)
self.minfactor = minfactor
self.calcPick()
def __str__(self):
@@ -91,10 +91,6 @@ class AutoPicker(object):
aus=self.getaus(),
Tsmooth=self.getTsmooth(),
Pick1=self.getpick1())
def setCheckWindow(self, checkwindow):
'''convert checkwindow to samples'''
if checkwindow:
self.checkwindow = int(checkwindow / self.Data[0].stats.delta)
def getTSNR(self):
return self.TSNR
@@ -193,9 +189,8 @@ class AICPicker(AutoPicker):
offset = abs(min(aic) - min(aicsmooth))
aicsmooth = aicsmooth - offset
# get maximum of HOS/AR-CF as startimg point for searching
# minimum in AIC function
icfmax = get_maximum_index(self.Data[0].data, self.checkwindow, self.minfactor,
int(self.TSNR[1]/self.Data[0].stats.delta))
# minimum in AIC function
icfmax = np.argmax(self.Data[0].data)
# find minimum in AIC-CF front of maximum of HOS/AR-CF
lpickwindow = int(round(self.PickWindow / self.dt))
@@ -259,8 +254,12 @@ class AICPicker(AutoPicker):
if len(dataslope) < 1:
print('No data in slope window found!')
return
imax = np.argmax(dataslope)
iislope = islope[0][0:imax+1]
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!")
@@ -271,13 +270,13 @@ class AICPicker(AutoPicker):
print("Choose longer slope determination window!")
if self.iplot > 1:
if self.fig == None or self.fig == 'None':
fig = plt.figure() # self.iplot) ### WHY? MP MP
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), 'k', label='(HOS-/AR-) 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)
@@ -310,11 +309,12 @@ class AICPicker(AutoPicker):
plt_flag = 1
else:
fig = self.fig
fig._tight = True
ax1 = fig.add_subplot(211)
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), 'k', label='(HOS-/AR-) Data')
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')
@@ -324,7 +324,7 @@ class AICPicker(AutoPicker):
if self.Pick is not None:
ax2 = fig.add_subplot(2, 1, 2, sharex=ax1)
ax2.plot(self.Tcf, x, 'k', label='Data')
ax2.plot(self.Tcf, x, color=self._linecolor, linewidth=0.7, label='Data')
ax1.axvspan(self.Tcf[inoise[0]], self.Tcf[inoise[-1]], color='y', alpha=0.2, lw=0, label='Noise Window')
ax1.axvspan(self.Tcf[isignal[0]], self.Tcf[isignal[-1]], color='b', alpha=0.2, lw=0,
label='Signal Window')
@@ -479,11 +479,12 @@ class PragPicker(AutoPicker):
plt_flag = 1
else:
fig = self.fig
fig._tight = True
ax = fig.add_subplot(111)
ax.plot(Tcfpick, cfipick, 'k', label='CF')
ax.plot(Tcfpick, cfipick, color=self._linecolor, linewidth=0.7, label='CF')
ax.plot(Tcfpick, cfsmoothipick, 'r', label='Smoothed CF')
if pickflag > 0:
ax.plot([self.Pick, self.Pick], [min(cfipick), max(cfipick)], 'b', linewidth=2, label='Pick')
ax.plot([self.Pick, self.Pick], [min(cfipick), max(cfipick)], self._pickcolor_p, linewidth=2, label='Pick')
ax.set_xlabel('Time [s] since %s' % self.Data[0].stats.starttime)
ax.set_yticks([])
ax.set_title(self.Data[0].stats.station)
+77 -100
View File
@@ -13,10 +13,9 @@ import warnings
import matplotlib.pyplot as plt
import numpy as np
from obspy.core import Stream, UTCDateTime
from scipy.signal import argrelextrema
def earllatepicker(X, nfac, TSNR, Pick1, iplot=0, verbosity=1, fig=None):
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)
as reasonable uncertainties. Latest possible pick is based on noise level,
@@ -95,7 +94,7 @@ def earllatepicker(X, nfac, TSNR, Pick1, iplot=0, verbosity=1, fig=None):
# get earliest possible pick
EPick = np.nan;
EPick = np.nan
count = 0
pis = isignal
@@ -131,17 +130,18 @@ def earllatepicker(X, nfac, TSNR, Pick1, iplot=0, verbosity=1, fig=None):
if fig == None or fig == 'None':
fig = plt.figure() # iplot)
plt_flag = 1
fig._tight = True
ax = fig.add_subplot(111)
ax.plot(t, x, 'k', label='Data')
ax.plot(t, x, color=linecolor, linewidth=0.7, label='Data')
ax.axvspan(t[inoise[0]], t[inoise[-1]], color='y', alpha=0.2, lw=0, label='Noise Window')
ax.axvspan(t[isignal[0]], t[isignal[-1]], color='b', alpha=0.2, lw=0, label='Signal Window')
ax.plot([t[0], t[int(len(t)) - 1]], [nlevel, nlevel], '--k', label='Noise Level')
ax.plot([t[0], t[int(len(t)) - 1]], [nlevel, nlevel], color=linecolor, linewidth=0.7, linestyle='dashed', label='Noise Level')
ax.plot(t[pis[zc]], np.zeros(len(zc)), '*g',
markersize=14, label='Zero Crossings')
ax.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')
ax.plot([Pick1, Pick1], [max(x), -max(x)], 'b', linewidth=2, label='mpp')
ax.plot([LPick, LPick], [max(x) / 2, -max(x) / 2], '--k', label='lpp')
ax.plot([EPick, EPick], [max(x) / 2, -max(x) / 2], '--k', label='epp')
ax.plot([LPick, LPick], [max(x) / 2, -max(x) / 2], color=linecolor, linewidth=0.7, linestyle='dashed', label='lpp')
ax.plot([EPick, EPick], [max(x) / 2, -max(x) / 2], color=linecolor, linewidth=0.7, linestyle='dashed', label='epp')
ax.plot([Pick1 + PickError, Pick1 + PickError],
[max(x) / 2, -max(x) / 2], 'r--', label='spe')
ax.plot([Pick1 - PickError, Pick1 - PickError],
@@ -161,7 +161,7 @@ def earllatepicker(X, nfac, TSNR, Pick1, iplot=0, verbosity=1, fig=None):
return EPick, LPick, PickError
def fmpicker(Xraw, Xfilt, pickwin, Pick, iplot=0, fig=None):
def fmpicker(Xraw, Xfilt, pickwin, Pick, iplot=0, fig=None, linecolor='k'):
'''
Function to derive first motion (polarity) of given phase onset Pick.
Calculation is based on zero crossings determined within time window pickwin
@@ -324,8 +324,9 @@ def fmpicker(Xraw, Xfilt, pickwin, Pick, iplot=0, fig=None):
if fig == None or fig == 'None':
fig = plt.figure() # iplot)
plt_flag = 1
fig._tight = True
ax1 = fig.add_subplot(211)
ax1.plot(t, xraw, 'k')
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:
ax1.plot(t[islope1], xraw[islope1], label='Slope Window')
@@ -339,7 +340,7 @@ def fmpicker(Xraw, Xfilt, pickwin, Pick, iplot=0, fig=None):
ax2 = fig.add_subplot(2, 1, 2, sharex=ax1)
ax2.set_title('First-Motion Determination, Filtered Data')
ax2.plot(t, xfilt, 'k')
ax2.plot(t, xfilt, color=linecolor, linewidth=0.7)
ax2.plot([Pick, Pick], [max(xfilt), -max(xfilt)], 'b',
linewidth=2)
if P2 is not None:
@@ -590,7 +591,10 @@ def wadaticheck(pickdic, dttolerance, iplot=0, fig_dict=None):
Ppicks = []
Spicks = []
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:
# calculate S-P time
spt = pickdic[key]['S']['mpp'] - pickdic[key]['P']['mpp']
@@ -620,17 +624,19 @@ def wadaticheck(pickdic, dttolerance, iplot=0, fig_dict=None):
badstations = []
# calculate deviations from Wadati regression
ii = 0
ibad = 0
for key in pickdic:
for key in list(pickdic.keys()):
if 'SPt' in pickdic[key]:
stations.append(key)
wddiff = abs(pickdic[key]['SPt'] - wdfit[ii])
ii += 1
# check, if deviation is larger than adjusted
if wddiff > dttolerance:
# mark onset and downgrade S-weight to 9
# (not used anymore)
marker = 'badWadatiCheck'
pickdic[key]['S']['weight'] = 9
# remove pick from dictionary
pickdic.pop(key)
# # mark onset and downgrade S-weight to 9
# # (not used anymore)
# marker = 'badWadatiCheck'
# pickdic[key]['S']['weight'] = 9
badstations.append(key)
ibad += 1
else:
@@ -642,7 +648,8 @@ def wadaticheck(pickdic, dttolerance, iplot=0, fig_dict=None):
checkedSPtime = pickdic[key]['S']['mpp'] - pickdic[key]['P']['mpp']
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)
@@ -673,19 +680,28 @@ def wadaticheck(pickdic, dttolerance, iplot=0, fig_dict=None):
if iplot > 0:
if fig_dict:
fig = fig_dict['wadati']
linecolor = fig_dict['plot_style']['linecolor']['rgba_mpl']
plt_flag = 0
else:
fig = plt.figure()
linecolor = 'k'
plt_flag = 1
ax = fig.add_subplot(111)
ax.plot(Ppicks, SPtimes, 'ro', label='Skipped S-Picks')
if ibad > 0:
ax.plot(Ppicks, SPtimes, 'ro', label='Skipped S-Picks')
if wfitflag == 0:
ax.plot(Ppicks, wdfit, 'k', label='Wadati 1')
ax.plot(checkedPpicks, checkedSPtimes, 'ko', label='Reliable S-Picks')
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')
ax.set_title('Wadati-Diagram, %d S-P Times, Vp/Vs(raw)=%5.2f,' \
'Vp/Vs(checked)=%5.2f' % (len(SPtimes), vpvsr, cvpvsr))
ax.legend(loc=1)
ax.legend(loc=1, numpoints=1)
else:
ax.set_title('Wadati-Diagram, %d S-P Times' % len(SPtimes))
@@ -704,7 +720,7 @@ def RMS(X):
return np.sqrt(np.sum(np.power(X, 2)) / len(X))
def checksignallength(X, pick, TSNR, minsiglength, nfac, minpercent, iplot=0, fig=None):
def checksignallength(X, pick, TSNR, minsiglength, nfac, minpercent, iplot=0, fig=None, linecolor='k'):
'''
Function to detect spuriously picked noise peaks.
Uses RMS trace of all 3 components (if available) to determine,
@@ -789,8 +805,9 @@ def checksignallength(X, pick, TSNR, minsiglength, nfac, minpercent, iplot=0, fi
if fig == None or fig == 'None':
fig = plt.figure() # iplot)
plt_flag = 1
fig._tight = True
ax = fig.add_subplot(111)
ax.plot(t, rms, 'k', label='RMS Data')
ax.plot(t, rms, color=linecolor, linewidth=0.7, label='RMS Data')
ax.axvspan(t[inoise[0]], t[inoise[-1]], color='y', alpha=0.2, lw=0, label='Noise Window')
ax.axvspan(t[isignal[0]], t[isignal[-1]], color='b', alpha=0.2, lw=0, label='Signal Window')
ax.plot([t[isignal[0]], t[isignal[len(isignal) - 1]]],
@@ -865,9 +882,9 @@ def checkPonsets(pickdic, dttolerance, jackfactor=5, iplot=0, fig_dict=None):
badstations = np.array(stations)[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) \
+ len(badjkstations), len(stations)))
print(badstations)
goodmarker = 'goodPonsetcheck'
badmarker = 'badPonsetcheck'
@@ -876,15 +893,21 @@ def checkPonsets(pickdic, dttolerance, jackfactor=5, iplot=0, fig_dict=None):
# mark P onset as checked and keep P weight
pickdic[goodstations[i]]['P']['marked'] = goodmarker
for i in range(0, len(badstations)):
# mark P onset and downgrade P weight to 9
# (not used anymore)
pickdic[badstations[i]]['P']['marked'] = badmarker
pickdic[badstations[i]]['P']['weight'] = 9
# remove pick from dictionary
pickdic.pop(badstations[i])
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
# remove pick from dictionary
pickdic.pop(badjkstations[i])
# for i in range(0, len(badstations)):
# # 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
@@ -897,19 +920,22 @@ def checkPonsets(pickdic, dttolerance, jackfactor=5, iplot=0, fig_dict=None):
plt_flag = 1
ax = fig.add_subplot(111)
ax.plot(np.arange(0, len(Ppicks)), Ppicks, 'ro', markersize=14)
if len(badstations) < 1 and len(badjkstations) < 1:
ax.plot(np.arange(0, len(Ppicks)), Ppicks, 'go', markersize=14, label='Skipped P Picks')
else:
ax.plot(igood, np.array(Ppicks)[igood], 'go', markersize=14, label='Good P Picks')
ax.plot([0, len(Ppicks) - 1], [pmedian, pmedian], 'g',
linewidth=2, label='Median')
for i in range(0, len(Ppicks)):
ax.text(i, Ppicks[i] + 0.01, '{0}'.format(stations[i]))
if len(badstations) > 0:
ax.plot(ibad, np.array(Ppicks)[ibad], marker ='o', markerfacecolor='orange', markersize=14,
linestyle='None', label='Median Skipped P Picks')
if len(badjkstations) > 0:
ax.plot(badjk[0], np.array(Ppicks)[badjk], 'ro', markersize=14, label='Jackknife Skipped P Picks')
ax.plot(igood, np.array(Ppicks)[igood], 'go', markersize=14, label='Good P Picks')
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')
ax.legend(loc=1)
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()
@@ -941,9 +967,8 @@ def jackknife(X, phi, h):
PHI_sub = None
# determine number of subgroups
g = int(len(X) / h)
if (len(X) / h) % 1 != 0:
if len(X) % h:
print("jackknife: Cannot divide quantity X in equal sized subgroups!")
print("Choose another size for subgroups!")
return PHI_jack, PHI_pseudo, PHI_sub
@@ -960,7 +985,7 @@ def jackknife(X, phi, h):
# estimators of subgroups
PHI_pseudo = []
PHI_sub = []
for i in range(0, g):
for i in range(0, g - 1):
# subgroup i, remove i-th sample
xx = X[:]
del xx[i]
@@ -982,7 +1007,7 @@ def jackknife(X, phi, h):
return PHI_jack, PHI_pseudo, PHI_sub
def checkZ4S(X, pick, zfac, checkwin, iplot, fig=None):
def checkZ4S(X, pick, zfac, checkwin, iplot, fig=None, linecolor='k'):
'''
Function to compare energy content of vertical trace with
energy content of horizontal traces to detect spuriously
@@ -1109,8 +1134,9 @@ def checkZ4S(X, pick, zfac, checkwin, iplot, 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='k')
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')
@@ -1154,55 +1180,6 @@ def getQualityFromUncertainty(uncertainty, Errors):
return quality
def removePicksAbove(pickDic, minWeight):
'''remove picks from pick dicitonary with a weight > minweight'''
newdic = {}
for event in pickDic.keys():
newdic[event] = {}
for eventKey, eventDic in pickDic.items():
for station, phases in eventDic.items():
if phases['P']['weight'] < minWeight or phases['S']['weight'] < minWeight:
# dont append stations that will be empty to output dict
newdic[eventKey][station] = {}
if len(phases) > 2:
# copy over other values beside P/S information
additional_info = phases.copy()
if 'P' in phases.keys():
additional_info.pop('P')
if 'S' in phases.keys():
additional_info.pop('S')
newdic[eventKey][station].update(additional_info)
for phasename, phaseinfo in phases.items():
if phasename in ('P', 'S') and phaseinfo['weight'] < minWeight:
newdic[eventKey][station].update({phasename: phaseinfo})
return newdic
def get_maximum_index(data, checkwindow, minfactor, safetygap):
'''get maximum of CF as starting point, then check for highest local maximum
in front of it.
return second maximum if its larger than first maximum * minfactor, else
return first maximum.
checkwindow and safetygap are given in samples'''
icfmax1 = np.argmax(data)
imax_local = argrelextrema(data[icfmax1 - checkwindow:icfmax1 - safetygap], np.greater)[0] # indices of local maxima
if imax_local.size > 0:
imax_local = imax_local + icfmax1 - checkwindow
local_maxima = (imax_local, data[imax_local])
largest_local_max = np.where(local_maxima[1] == max(local_maxima[1]))
icfmax2 = local_maxima[0][largest_local_max]
if data[icfmax2] > data[icfmax1] * minfactor:
print("Found valid local maximum in front of first maximum")
return icfmax2[0]
else:
print("First maximum is the largest: {}>{}".format(data[icfmax1],
data[icfmax2]))
return icfmax1
else:
print("No local maxima found in check window")
return icfmax1
if __name__ == '__main__':
import doctest
-998
View File
@@ -1,998 +0,0 @@
#!/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
"""
import warnings
import matplotlib.pyplot as plt
import numpy as np
from obspy.core import Stream, UTCDateTime
def earllatepicker(X, nfac, TSNR, Pick1, iplot=0, stealthMode=False):
'''
Function to derive earliest and latest possible pick after Diehl & Kissling (2009)
as reasonable uncertainties. Latest possible pick is based on noise level,
earliest possible pick is half a signal wavelength in front of most likely
pick given by PragPicker or manually set by analyst. Most likely pick
(initial pick Pick1) must be given.
:param: X, time series (seismogram)
:type: `~obspy.core.stream.Stream`
:param: nfac (noise factor), nfac times noise level to calculate latest possible pick
:type: int
:param: TSNR, length of time windows around pick used to determine SNR [s]
:type: tuple (T_noise, T_gap, T_signal)
:param: Pick1, initial (most likely) onset time, starting point for earllatepicker
:type: float
:param: iplot, if given, results are plotted in figure(iplot)
:type: int
'''
assert isinstance(X, Stream), "%s is not a stream object" % str(X)
LPick = None
EPick = None
PickError = None
if stealthMode is False:
print
'earllatepicker: Get earliest and latest possible pick relative to most likely pick ...'
x = X[0].data
t = np.arange(0, X[0].stats.npts / X[0].stats.sampling_rate,
X[0].stats.delta)
inoise = getnoisewin(t, Pick1, TSNR[0], TSNR[1])
# get signal window
isignal = getsignalwin(t, Pick1, TSNR[2])
# remove mean
x = x - np.mean(x[inoise])
# calculate noise level
nlevel = np.sqrt(np.mean(np.square(x[inoise]))) * nfac
# get time where signal exceeds nlevel
ilup, = np.where(x[isignal] > nlevel)
ildown, = np.where(x[isignal] < -nlevel)
if not ilup.size and not ildown.size:
print("earllatepicker: Signal lower than noise level!")
print("Skip this trace!")
return LPick, EPick, PickError
il = min(np.min(ilup) if ilup.size else float('inf'),
np.min(ildown) if ildown.size else float('inf'))
LPick = t[isignal][il]
# get earliest possible pick
EPick = np.nan;
count = 0
pis = isignal
# if EPick stays NaN the signal window size will be doubled
while np.isnan(EPick):
if count > 0:
print("earllatepicker: Doubled signal window size %s time(s) "
"because of NaN for earliest pick." % count)
if stealthMode is False:
print("\nearllatepicker: Doubled signal window size %s time(s) "
"because of NaN for earliest pick." % count)
isigDoubleWinStart = pis[-1] + 1
isignalDoubleWin = np.arange(isigDoubleWinStart,
isigDoubleWinStart + len(pis))
if (isigDoubleWinStart + len(pis)) < X[0].data.size:
pis = np.concatenate((pis, isignalDoubleWin))
else:
print("Could not double signal window. Index out of bounds.")
break
count += 1
# determine all zero crossings in signal window (demeaned)
zc = crossings_nonzero_all(x[pis] - x[pis].mean())
# calculate mean half period T0 of signal as the average of the
T0 = np.mean(np.diff(zc)) * X[0].stats.delta # this is half wave length
# T0/4 is assumed as time difference between most likely and earliest possible pick!
EPick = Pick1 - T0 / 2
# get symmetric pick error as mean from earliest and latest possible pick
# by weighting latest possible pick two times earliest possible pick
diffti_tl = LPick - Pick1
diffti_te = Pick1 - EPick
PickError = (diffti_te + 2 * diffti_tl) / 3
if iplot > 1:
p = plt.figure(iplot)
p1, = plt.plot(t, x, 'k')
p2, = plt.plot(t[inoise], x[inoise])
p3, = plt.plot(t[isignal], x[isignal], 'r')
p4, = plt.plot([t[0], t[int(len(t)) - 1]], [nlevel, nlevel], '--k')
p5, = plt.plot(t[isignal[zc]], np.zeros(len(zc)), '*g',
markersize=14)
plt.legend([p1, p2, p3, p4, p5],
['Data', 'Noise Window', 'Signal Window', 'Noise Level',
'Zero Crossings'],
loc='best')
plt.plot([t[0], t[int(len(t)) - 1]], [-nlevel, -nlevel], '--k')
plt.plot([Pick1, Pick1], [max(x), -max(x)], 'b', linewidth=2)
plt.plot([LPick, LPick], [max(x) / 2, -max(x) / 2], '--k')
plt.plot([EPick, EPick], [max(x) / 2, -max(x) / 2], '--k')
plt.plot([Pick1 + PickError, Pick1 + PickError],
[max(x) / 2, -max(x) / 2], 'r--')
plt.plot([Pick1 - PickError, Pick1 - PickError],
[max(x) / 2, -max(x) / 2], 'r--')
plt.xlabel('Time [s] since %s' % X[0].stats.starttime)
plt.yticks([])
plt.title(
'Earliest-/Latest Possible/Most Likely Pick & Symmetric Pick Error, %s' %
X[0].stats.station)
plt.show()
raw_input()
plt.close(p)
return EPick, LPick, PickError
def fmpicker(Xraw, Xfilt, pickwin, Pick, iplot=0):
'''
Function to derive first motion (polarity) of given phase onset Pick.
Calculation is based on zero crossings determined within time window pickwin
after given onset time.
:param: Xraw, unfiltered time series (seismogram)
:type: `~obspy.core.stream.Stream`
:param: Xfilt, filtered time series (seismogram)
:type: `~obspy.core.stream.Stream`
:param: pickwin, time window after onset Pick within zero crossings are calculated
:type: float
:param: Pick, initial (most likely) onset time, starting point for fmpicker
:type: float
:param: iplot, if given, results are plotted in figure(iplot)
:type: int
'''
warnings.simplefilter('ignore', np.RankWarning)
assert isinstance(Xraw, Stream), "%s is not a stream object" % str(Xraw)
assert isinstance(Xfilt, Stream), "%s is not a stream object" % str(Xfilt)
FM = None
if Pick is not None:
print("fmpicker: Get first motion (polarity) of onset using unfiltered seismogram...")
xraw = Xraw[0].data
xfilt = Xfilt[0].data
t = np.arange(0, Xraw[0].stats.npts / Xraw[0].stats.sampling_rate,
Xraw[0].stats.delta)
# get pick window
ipick = np.where(
(t <= min([Pick + pickwin, len(Xraw[0])])) & (t >= Pick))
# remove mean
xraw[ipick] = xraw[ipick] - np.mean(xraw[ipick])
xfilt[ipick] = xfilt[ipick] - np.mean(xfilt[ipick])
# get zero crossings after most likely pick
# initial onset is assumed to be the first zero crossing
# first from unfiltered trace
zc1 = []
zc1.append(Pick)
index1 = []
i = 0
for j in range(ipick[0][1], ipick[0][len(t[ipick]) - 1]):
i = i + 1
if xraw[j - 1] <= 0 <= xraw[j]:
zc1.append(t[ipick][i])
index1.append(i)
elif xraw[j - 1] > 0 >= xraw[j]:
zc1.append(t[ipick][i])
index1.append(i)
if len(zc1) == 3:
break
# if time difference betweeen 1st and 2cnd zero crossing
# is too short, get time difference between 1st and 3rd
# to derive maximum
if zc1[1] - zc1[0] <= Xraw[0].stats.delta:
li1 = index1[1]
else:
li1 = index1[0]
if np.size(xraw[ipick[0][1]:ipick[0][li1]]) == 0:
print("fmpicker: Onset on unfiltered trace too emergent for first motion determination!")
P1 = None
else:
imax1 = np.argmax(abs(xraw[ipick[0][1]:ipick[0][li1]]))
if imax1 == 0:
imax1 = np.argmax(abs(xraw[ipick[0][1]:ipick[0][index1[1]]]))
if imax1 == 0:
print("fmpicker: Zero crossings too close!")
print("Skip first motion determination!")
return FM
islope1 = np.where((t >= Pick) & (t <= Pick + t[imax1]))
# calculate slope as polynomal fit of order 1
xslope1 = np.arange(0, len(xraw[islope1]), 1)
P1 = np.polyfit(xslope1, xraw[islope1], 1)
datafit1 = np.polyval(P1, xslope1)
# now using filterd trace
# next zero crossings after most likely pick
zc2 = []
zc2.append(Pick)
index2 = []
i = 0
for j in range(ipick[0][1], ipick[0][len(t[ipick]) - 1]):
i = i + 1
if xfilt[j - 1] <= 0 <= xfilt[j]:
zc2.append(t[ipick][i])
index2.append(i)
elif xfilt[j - 1] > 0 >= xfilt[j]:
zc2.append(t[ipick][i])
index2.append(i)
if len(zc2) == 3:
break
# if time difference betweeen 1st and 2cnd zero crossing
# is too short, get time difference between 1st and 3rd
# to derive maximum
if zc2[1] - zc2[0] <= Xfilt[0].stats.delta:
li2 = index2[1]
else:
li2 = index2[0]
if np.size(xfilt[ipick[0][1]:ipick[0][li2]]) == 0:
print("fmpicker: Onset on filtered trace too emergent for first motion determination!")
P2 = None
else:
imax2 = np.argmax(abs(xfilt[ipick[0][1]:ipick[0][li2]]))
if imax2 == 0:
imax2 = np.argmax(abs(xfilt[ipick[0][1]:ipick[0][index2[1]]]))
if imax2 == 0:
print("fmpicker: Zero crossings too close!")
print("Skip first motion determination!")
return FM
islope2 = np.where((t >= Pick) & (t <= Pick + t[imax2]))
# calculate slope as polynomal fit of order 1
xslope2 = np.arange(0, len(xfilt[islope2]), 1)
P2 = np.polyfit(xslope2, xfilt[islope2], 1)
datafit2 = np.polyval(P2, xslope2)
# compare results
if P1 is not None and P2 is not None:
if P1[0] < 0 and P2[0] < 0:
FM = 'D'
elif P1[0] >= 0 > P2[0]:
FM = '-'
elif P1[0] < 0 <= P2[0]:
FM = '-'
elif P1[0] > 0 and P2[0] > 0:
FM = 'U'
elif P1[0] <= 0 < P2[0]:
FM = '+'
elif P1[0] > 0 >= P2[0]:
FM = '+'
print("fmpicker: Found polarity %s" % FM)
if iplot > 1:
plt.figure(iplot)
plt.subplot(2, 1, 1)
plt.plot(t, xraw, 'k')
p1, = plt.plot([Pick, Pick], [max(xraw), -max(xraw)], 'b', linewidth=2)
if P1 is not None:
p2, = plt.plot(t[islope1], xraw[islope1])
p3, = plt.plot(zc1, np.zeros(len(zc1)), '*g', markersize=14)
p4, = plt.plot(t[islope1], datafit1, '--g', linewidth=2)
plt.legend([p1, p2, p3, p4],
['Pick', 'Slope Window', 'Zero Crossings', 'Slope'],
loc='best')
plt.text(Pick + 0.02, max(xraw) / 2, '%s' % FM, fontsize=14)
ax = plt.gca()
plt.yticks([])
plt.title('First-Motion Determination, %s, Unfiltered Data' % Xraw[
0].stats.station)
plt.subplot(2, 1, 2)
plt.title('First-Motion Determination, Filtered Data')
plt.plot(t, xfilt, 'k')
p1, = plt.plot([Pick, Pick], [max(xfilt), -max(xfilt)], 'b',
linewidth=2)
if P2 is not None:
p2, = plt.plot(t[islope2], xfilt[islope2])
p3, = plt.plot(zc2, np.zeros(len(zc2)), '*g', markersize=14)
p4, = plt.plot(t[islope2], datafit2, '--g', linewidth=2)
plt.text(Pick + 0.02, max(xraw) / 2, '%s' % FM, fontsize=14)
ax = plt.gca()
plt.xlabel('Time [s] since %s' % Xraw[0].stats.starttime)
plt.yticks([])
plt.show()
raw_input()
plt.close(iplot)
return FM
def crossings_nonzero_all(data):
pos = data > 0
npos = ~pos
return ((pos[:-1] & npos[1:]) | (npos[:-1] & pos[1:])).nonzero()[0]
def getSNR(X, TSNR, t1):
'''
Function to calculate SNR of certain part of seismogram relative to
given time (onset) out of given noise and signal windows. A safety gap
between noise and signal part can be set. Returns SNR and SNR [dB] and
noiselevel.
:param: X, time series (seismogram)
:type: `~obspy.core.stream.Stream`
:param: TSNR, length of time windows [s] around t1 (onset) used to determine SNR
:type: tuple (T_noise, T_gap, T_signal)
:param: t1, initial time (onset) from which noise and signal windows are calculated
:type: float
'''
assert isinstance(X, Stream), "%s is not a stream object" % str(X)
x = X[0].data
t = np.arange(0, X[0].stats.npts / X[0].stats.sampling_rate,
X[0].stats.delta)
# get noise window
inoise = getnoisewin(t, t1, TSNR[0], TSNR[1])
# get signal window
isignal = getsignalwin(t, t1, TSNR[2])
if np.size(inoise) < 1:
print("getSNR: Empty array inoise, check noise window!")
return
elif np.size(isignal) < 1:
print("getSNR: Empty array isignal, check signal window!")
return
# demean over entire waveform
x = x - np.mean(x[inoise])
# calculate ratios
noiselevel = np.sqrt(np.mean(np.square(x[inoise])))
signallevel = np.sqrt(np.mean(np.square(x[isignal])))
SNR = signallevel / noiselevel
SNRdB = 10 * np.log10(SNR)
return SNR, SNRdB, noiselevel
def getnoisewin(t, t1, tnoise, tgap):
'''
Function to extract indeces of data out of time series for noise calculation.
Returns an array of indeces.
:param: t, array of time stamps
:type: numpy array
:param: t1, time from which relativ to it noise window is extracted
:type: float
:param: tnoise, length of time window [s] for noise part extraction
:type: float
:param: tgap, safety gap between t1 (onset) and noise window to
ensure, that noise window contains no signal
:type: float
'''
# get noise window
inoise, = np.where((t <= max([t1 - tgap, 0])) \
& (t >= max([t1 - tnoise - tgap, 0])))
if np.size(inoise) < 1:
print("getnoisewin: Empty array inoise, check noise window!")
return inoise
def getsignalwin(t, t1, tsignal):
'''
Function to extract data out of time series for signal level calculation.
Returns an array of indeces.
:param: t, array of time stamps
:type: numpy array
:param: t1, time from which relativ to it signal window is extracted
:type: float
:param: tsignal, length of time window [s] for signal level calculation
:type: float
'''
# get signal window
isignal, = np.where((t <= min([t1 + tsignal, len(t)])) \
& (t >= t1))
if np.size(isignal) < 1:
print("getsignalwin: Empty array isignal, check signal window!")
return isignal
def getResolutionWindow(snr):
"""
Number -> Float
produce the half of the time resolution window width from given SNR
value
SNR >= 3 -> 2 sec HRW
3 > SNR >= 2 -> 5 sec MRW
2 > SNR >= 1.5 -> 10 sec LRW
1.5 > SNR -> 15 sec VLRW
see also Diehl et al. 2009
>>> getResolutionWindow(0.5)
7.5
>>> getResolutionWindow(1.8)
5.0
>>> getResolutionWindow(2.3)
2.5
>>> getResolutionWindow(4)
1.0
>>> getResolutionWindow(2)
2.5
"""
res_wins = {'HRW': 2., 'MRW': 5., 'LRW': 10., 'VLRW': 15.}
if snr < 1.5:
time_resolution = res_wins['VLRW']
elif snr < 2.:
time_resolution = res_wins['LRW']
elif snr < 3.:
time_resolution = res_wins['MRW']
else:
time_resolution = res_wins['HRW']
return time_resolution / 2
def wadaticheck(pickdic, dttolerance, iplot):
'''
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
from regression of S-P time the S pick is marked and down graded.
: param: pickdic, dictionary containing picks and quality parameters
: type: dictionary
: param: dttolerance, maximum adjusted deviation of S-P time from
S-P time regression
: type: float
: param: iplot, if iplot > 1, Wadati diagram is shown
: type: int
'''
checkedonsets = pickdic
# search for good quality picks and calculate S-P time
Ppicks = []
Spicks = []
SPtimes = []
for key in pickdic:
if pickdic[key]['P']['weight'] < 4 and pickdic[key]['S']['weight'] < 4:
# calculate S-P time
spt = pickdic[key]['S']['mpp'] - pickdic[key]['P']['mpp']
# add S-P time to dictionary
pickdic[key]['SPt'] = spt
# add P onsets and corresponding S-P times to list
UTCPpick = UTCDateTime(pickdic[key]['P']['mpp'])
UTCSpick = UTCDateTime(pickdic[key]['S']['mpp'])
Ppicks.append(UTCPpick.timestamp)
Spicks.append(UTCSpick.timestamp)
SPtimes.append(spt)
if len(SPtimes) >= 3:
# calculate slope
p1 = np.polyfit(Ppicks, SPtimes, 1)
wdfit = np.polyval(p1, Ppicks)
wfitflag = 0
# calculate vp/vs ratio before check
vpvsr = p1[0] + 1
print("###############################################")
print("wadaticheck: Average Vp/Vs ratio before check: %f" % vpvsr)
checkedPpicks = []
checkedSpicks = []
checkedSPtimes = []
# calculate deviations from Wadati regression
ii = 0
ibad = 0
for key in pickdic:
if pickdic[key].has_key('SPt'):
wddiff = abs(pickdic[key]['SPt'] - wdfit[ii])
ii += 1
# check, if deviation is larger than adjusted
if wddiff > dttolerance:
# mark onset and downgrade S-weight to 9
# (not used anymore)
marker = 'badWadatiCheck'
pickdic[key]['S']['weight'] = 9
ibad += 1
else:
marker = 'goodWadatiCheck'
checkedPpick = UTCDateTime(pickdic[key]['P']['mpp'])
checkedPpicks.append(checkedPpick.timestamp)
checkedSpick = UTCDateTime(pickdic[key]['S']['mpp'])
checkedSpicks.append(checkedSpick.timestamp)
checkedSPtime = pickdic[key]['S']['mpp'] - pickdic[key]['P']['mpp']
checkedSPtimes.append(checkedSPtime)
pickdic[key]['S']['marked'] = marker
if len(checkedPpicks) >= 3:
# calculate new slope
p2 = np.polyfit(checkedPpicks, checkedSPtimes, 1)
wdfit2 = np.polyval(p2, checkedPpicks)
# calculate vp/vs ratio after check
cvpvsr = p2[0] + 1
print("wadaticheck: Average Vp/Vs ratio after check: %f" % cvpvsr)
print("wadatacheck: Skipped %d S pick(s)" % ibad)
else:
print("###############################################")
print("wadatacheck: Not enough checked S-P times available!")
print("Skip Wadati check!")
checkedonsets = pickdic
else:
print("wadaticheck: Not enough S-P times available for reliable regression!")
print("Skip wadati check!")
wfitflag = 1
# plot results
if iplot > 1:
plt.figure(iplot)
f1, = plt.plot(Ppicks, SPtimes, 'ro')
if wfitflag == 0:
f2, = plt.plot(Ppicks, wdfit, 'k')
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:
plt.title('Wadati-Diagram, %d S-P Times' % len(SPtimes))
plt.ylabel('S-P Times [s]')
plt.xlabel('P Times [s]')
plt.show()
raw_input()
plt.close(iplot)
return checkedonsets
def checksignallength(X, pick, TSNR, minsiglength, nfac, minpercent, iplot):
'''
Function to detect spuriously picked noise peaks.
Uses RMS trace of all 3 components (if available) to determine,
how many samples [per cent] after P onset are below certain
threshold, calculated from noise level times noise factor.
: param: X, time series (seismogram)
: type: `~obspy.core.stream.Stream`
: param: pick, initial (AIC) P onset time
: type: float
: param: TSNR, length of time windows around initial pick [s]
: type: tuple (T_noise, T_gap, T_signal)
: param: minsiglength, minium required signal length [s] to
declare pick as P onset
: type: float
: param: nfac, noise factor (nfac * noise level = threshold)
: type: float
: param: minpercent, minimum required percentage of samples
above calculated threshold
: type: float
: param: iplot, if iplot > 1, results are shown in figure
: type: int
'''
assert isinstance(X, Stream), "%s is not a stream object" % str(X)
print("Checking signal length ...")
if len(X) > 1:
# all three components available
# make sure, all components have equal lengths
ilen = min([len(X[0].data), len(X[1].data), len(X[2].data)])
x1 = X[0][0:ilen]
x2 = X[1][0:ilen]
x3 = X[2][0:ilen]
# get RMS trace
rms = np.sqrt((np.power(x1, 2) + np.power(x2, 2) + np.power(x3, 2)) / 3)
else:
x1 = X[0].data
rms = np.sqrt(np.power(2, x1))
t = np.arange(0, ilen / X[0].stats.sampling_rate,
X[0].stats.delta)
# get noise window in front of pick plus saftey gap
inoise = getnoisewin(t, pick - 0.5, TSNR[0], TSNR[1])
# get signal window
isignal = getsignalwin(t, pick, minsiglength)
# calculate minimum adjusted signal level
minsiglevel = max(rms[inoise]) * nfac
# minimum adjusted number of samples over minimum signal level
minnum = len(isignal) * minpercent / 100
# get number of samples above minimum adjusted signal level
numoverthr = len(np.where(rms[isignal] >= minsiglevel)[0])
if numoverthr >= minnum:
print("checksignallength: Signal reached required length.")
returnflag = 1
else:
print("checksignallength: Signal shorter than required minimum signal length!")
print("Presumably picked noise peak, pick is rejected!")
print("(min. signal length required: %s s)" % minsiglength)
returnflag = 0
if iplot == 2:
plt.figure(iplot)
p1, = plt.plot(t, rms, 'k')
p2, = plt.plot(t[inoise], rms[inoise], 'c')
p3, = plt.plot(t[isignal], rms[isignal], 'r')
p4, = plt.plot([t[isignal[0]], t[isignal[len(isignal) - 1]]],
[minsiglevel, minsiglevel], 'g', linewidth=2)
p5, = plt.plot([pick, pick], [min(rms), max(rms)], 'b', linewidth=2)
plt.legend([p1, p2, p3, p4, p5], ['RMS Data', 'RMS Noise Window',
'RMS Signal Window', 'Minimum Signal Level',
'Onset'], loc='best')
plt.xlabel('Time [s] since %s' % X[0].stats.starttime)
plt.ylabel('Counts')
plt.title('Check for Signal Length, Station %s' % X[0].stats.station)
plt.yticks([])
plt.show()
raw_input()
plt.close(iplot)
return returnflag
def checkPonsets(pickdic, dttolerance, iplot):
'''
Function to check statistics of P-onset times: Control deviation from
median (maximum adjusted deviation = dttolerance) and apply pseudo-
bootstrapping jackknife.
: param: pickdic, dictionary containing picks and quality parameters
: type: dictionary
: param: dttolerance, maximum adjusted deviation of P-onset time from
median of all P onsets
: type: float
: param: iplot, if iplot > 1, Wadati diagram is shown
: type: int
'''
checkedonsets = pickdic
# search for good quality P picks
Ppicks = []
stations = []
for key in pickdic:
if pickdic[key]['P']['weight'] < 4:
# add P onsets to list
UTCPpick = UTCDateTime(pickdic[key]['P']['mpp'])
Ppicks.append(UTCPpick.timestamp)
stations.append(key)
# apply jackknife bootstrapping on variance of P onsets
print("###############################################")
print("checkPonsets: Apply jackknife bootstrapping on P-onset times ...")
[xjack, PHI_pseudo, PHI_sub] = jackknife(Ppicks, 'VAR', 1)
# get pseudo variances smaller than average variances
# (times safety factor), these picks passed jackknife test
ij = np.where(PHI_pseudo <= 2 * xjack)
# these picks did not pass jackknife test
badjk = np.where(PHI_pseudo > 2 * xjack)
badjkstations = np.array(stations)[badjk]
print("checkPonsets: %d pick(s) did not pass jackknife test!" % len(badjkstations))
# calculate median from these picks
pmedian = np.median(np.array(Ppicks)[ij])
# find picks that deviate less than dttolerance from median
ii = np.where(abs(np.array(Ppicks)[ij] - pmedian) <= dttolerance)
jj = np.where(abs(np.array(Ppicks)[ij] - pmedian) > dttolerance)
igood = ij[0][ii]
ibad = ij[0][jj]
goodstations = np.array(stations)[igood]
badstations = np.array(stations)[ibad]
print("checkPonsets: %d pick(s) deviate too much from median!" % len(ibad))
print("checkPonsets: Skipped %d P pick(s) out of %d" % (len(badstations) \
+ len(badjkstations), len(stations)))
goodmarker = 'goodPonsetcheck'
badmarker = 'badPonsetcheck'
badjkmarker = 'badjkcheck'
for i in range(0, len(goodstations)):
# mark P onset as checked and keep P weight
pickdic[goodstations[i]]['P']['marked'] = goodmarker
for i in range(0, len(badstations)):
# 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
if iplot > 1:
p1, = plt.plot(np.arange(0, len(Ppicks)), Ppicks, 'r+', markersize=14)
p2, = plt.plot(igood, np.array(Ppicks)[igood], 'g*', markersize=14)
p3, = plt.plot([0, len(Ppicks) - 1], [pmedian, pmedian], 'g',
linewidth=2)
for i in range(0, len(Ppicks)):
plt.text(i, Ppicks[i] + 0.2, stations[i])
plt.xlabel('Number of P Picks')
plt.ylabel('Onset Time [s] from 1.1.1970')
plt.legend([p1, p2, p3], ['Skipped P Picks', 'Good P Picks', 'Median'],
loc='best')
plt.title('Check P Onsets')
plt.show()
raw_input()
return checkedonsets
def jackknife(X, phi, h):
'''
Function to calculate the Jackknife Estimator for a given quantity,
special type of boot strapping. Returns the jackknife estimator PHI_jack
the pseudo values PHI_pseudo and the subgroup parameters PHI_sub.
: param: X, given quantity
: type: list
: param: phi, chosen estimator, choose between:
"MED" for median
"MEA" for arithmetic mean
"VAR" for variance
: type: string
: param: h, size of subgroups, optinal, default = 1
: type: integer
'''
PHI_jack = None
PHI_pseudo = None
PHI_sub = None
# determine number of subgroups
g = len(X) / h
if type(g) is not int:
print("jackknife: Cannot divide quantity X in equal sized subgroups!")
print("Choose another size for subgroups!")
return PHI_jack, PHI_pseudo, PHI_sub
else:
# estimator of undisturbed spot check
if phi == 'MEA':
phi_sc = np.mean(X)
elif phi == 'VAR':
phi_sc = np.var(X)
elif phi == 'MED':
phi_sc = np.median(X)
# estimators of subgroups
PHI_pseudo = []
PHI_sub = []
for i in range(0, g - 1):
# subgroup i, remove i-th sample
xx = X[:]
del xx[i]
# calculate estimators of disturbed spot check
if phi == 'MEA':
phi_sub = np.mean(xx)
elif phi == 'VAR':
phi_sub = np.var(xx)
elif phi == 'MED':
phi_sub = np.median(xx)
PHI_sub.append(phi_sub)
# pseudo values
phi_pseudo = g * phi_sc - ((g - 1) * phi_sub)
PHI_pseudo.append(phi_pseudo)
# jackknife estimator
PHI_jack = np.mean(PHI_pseudo)
return PHI_jack, PHI_pseudo, PHI_sub
def checkZ4S(X, pick, zfac, checkwin, iplot):
'''
Function to compare energy content of vertical trace with
energy content of horizontal traces to detect spuriously
picked S onsets instead of P onsets. Usually, P coda shows
larger longitudal energy on vertical trace than on horizontal
traces, where the transversal energy is larger within S coda.
Be careful: there are special circumstances, where this is not
the case!
: param: X, fitered(!) time series, three traces
: type: `~obspy.core.stream.Stream`
: param: pick, initial (AIC) P onset time
: type: float
: param: zfac, factor for threshold determination,
vertical energy must exceed coda level times zfac
to declare a pick as P onset
: type: float
: param: checkwin, window length [s] for calculating P-coda
energy content
: type: float
: param: iplot, if iplot > 1, energy content and threshold
are shown
: type: int
'''
assert isinstance(X, Stream), "%s is not a stream object" % str(X)
print("Check for spuriously picked S onset instead of P onset ...")
returnflag = 0
# split components
zdat = X.select(component="Z")
edat = X.select(component="E")
if len(edat) == 0: # check for other components
edat = X.select(component="2")
ndat = X.select(component="N")
if len(ndat) == 0: # check for other components
ndat = X.select(component="1")
z = zdat[0].data
tz = np.arange(0, zdat[0].stats.npts / zdat[0].stats.sampling_rate,
zdat[0].stats.delta)
# calculate RMS trace from vertical component
absz = np.sqrt(np.power(z, 2))
# calculate RMS trace from both horizontal traces
# 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
isignal = getsignalwin(tz, pick, checkwin)
# calculate energy levels
zcodalevel = max(absz[isignal])
encodalevel = max(absen[isignal])
# calculate threshold
minsiglevel = encodalevel * zfac
# vertical P-coda level must exceed horizontal P-coda level
# zfac times encodalevel
if zcodalevel < minsiglevel:
print("checkZ4S: Maybe S onset? Skip this P pick!")
else:
print("checkZ4S: P onset passes checkZ4S test!")
returnflag = 1
if iplot > 1:
te = np.arange(0, edat[0].stats.npts / edat[0].stats.sampling_rate,
edat[0].stats.delta)
tn = np.arange(0, ndat[0].stats.npts / ndat[0].stats.sampling_rate,
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()
return returnflag
def writephases(arrivals, fformat, filename):
'''
Function of methods to write phases to the following standard file
formats used for locating earthquakes:
HYPO71, NLLoc, VELEST, HYPOSAT, HYPOINVERSE and hypoDD
:param: arrivals
:type: dictionary containing all phase information including
station ID, phase, first motion, weight (uncertainty),
....
:param: fformat
:type: string, chosen file format (location routine),
choose between NLLoc, HYPO71, HYPOSAT, VELEST,
HYPOINVERSE, and hypoDD
:param: filename, full path and name of phase file
:type: string
'''
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')
for key in arrivals:
if arrivals[key]['P']['weight'] < 4:
# write phase information to NLLoc-phase file
# see the NLLoc tutorial at www.alomax.free.fr/nlloc/
fm = arrivals[key]['P']['fm']
onset = arrivals[key]['P']['mpp']
year = onset.year
month = onset.month
day = onset.day
hh = onset.hour
mm = onset.minute
ss = onset.second
ms = onset.microsecond
ss_ms = ss + (ms / 1E06)
fid.write('%s ? ? ? P %s %d%02d%02d %02d%02d %7.4f GAU 0 0 0 0 1 \n' \
% (key, fm, year, month, day, hh, mm, ss_ms))
if arrivals[key]['S']['weight'] < 4:
fm = '?'
onset = arrivals[key]['S']['mpp']
year = onset.year
month = onset.month
day = onset.day
hh = onset.hour
mm = onset.minute
ss = onset.second
ms = onset.microsecond
ss_ms = ss + (ms / 1E06)
fid.write('%s ? ? ? S %s %d%02d%02d %02d%02d %7.4f GAU 0 0 0 0 1 \n' \
% (key, fm, year, month, day, hh, mm, ss_ms))
fid.close()
if __name__ == '__main__':
import doctest
doctest.testmod()
+1 -1
View File
@@ -7,7 +7,7 @@ except:
from urllib.request import urlopen
def checkurl(url='https://ariadne.geophysik.rub.de/trac/PyLoT'):
def checkurl(url='https://ariadne.geophysik.ruhr-uni-bochum.de/trac/PyLoT/'):
try:
urlopen(url, timeout=1)
return True
+1 -36
View File
@@ -5,41 +5,6 @@ from PySide.QtCore import QThread, Signal, Qt, Slot, QRunnable, QObject
from PySide.QtGui import QDialog, QProgressBar, QLabel, QHBoxLayout, QPushButton
class AutoPickThread(QThread):
message = Signal(str)
finished = Signal()
def __init__(self, parent, func, infile, fnames, eventid, savepath):
super(AutoPickThread, self).__init__()
self.setParent(parent)
self.func = func
self.infile = infile
self.fnames = fnames
self.eventid = eventid
self.savepath = savepath
def run(self):
sys.stdout = self
picks = self.func(None, None, self.infile, self.fnames, self.eventid, self.savepath)
print("Autopicking finished!\n")
try:
for station in picks:
self.parent().addPicks(station, picks[station], type='auto')
except AttributeError:
print(picks)
sys.stdout = sys.__stdout__
self.finished.emit()
def write(self, text):
self.message.emit(text)
def flush(self):
pass
class Thread(QThread):
message = Signal(str)
@@ -131,7 +96,6 @@ class Worker(QRunnable):
try:
result = self.fun(self.args)
except:
#traceback.print_exc()
exctype, value = sys.exc_info ()[:2]
print(exctype, value, traceback.format_exc())
self.signals.error.emit ((exctype, value, traceback.format_exc ()))
@@ -139,6 +103,7 @@ class Worker(QRunnable):
self.signals.result.emit(result)
finally:
self.signals.finished.emit('Done')
sys.stdout = sys.__stdout__
def write(self, text):
self.signals.message.emit(text)
+26 -35
View File
@@ -14,6 +14,7 @@ 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
@@ -21,7 +22,7 @@ from PySide import QtCore, QtGui
try:
import pyqtgraph as pg
except Exception as e:
print('QtPyLoT: Could not import pyqtgraph. {}'.format(e))
print('PyLoT: Could not import pyqtgraph. {}'.format(e))
pg = None
def _pickle_method(m):
@@ -71,6 +72,8 @@ def gen_Pool(ncores=0):
if ncores == 0:
ncores = multiprocessing.cpu_count()
print('gen_Pool: Generated multiprocessing Pool with {} cores\n'.format(ncores))
pool = multiprocessing.Pool(ncores)
return pool
@@ -577,36 +580,22 @@ def modify_rgba(rgba, modifier, intensity):
def base_phase_colors(picktype, phase):
phases = {
'manual':
{
'P':
{
'rgba': (0, 0, 255, 255),
'modifier': 'g'
},
'S':
{
'rgba': (255, 0, 0, 255),
'modifier': 'b'
}
},
'auto':
{
'P':
{
'rgba': (140, 0, 255, 255),
'modifier': 'g'
},
'S':
{
'rgba': (255, 140, 0, 255),
'modifier': 'b'
}
}
}
return phases[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):
"""
@@ -702,7 +691,7 @@ def get_stations(data):
return stations
def check4rotated(data, metadata=None):
def check4rotated(data, metadata=None, verbosity=1):
def rotate_components(wfstream, metadata=None):
"""rotates components if orientation code is numeric.
@@ -711,13 +700,15 @@ def check4rotated(data, metadata=None):
# indexing fails if metadata is None
metadata[0]
except:
msg = 'Warning: could not rotate traces since no metadata was given\nset Inventory file!'
print(msg)
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,))
msg = 'Warning: could not rotate traces since no metadata was given\nCheck inventory directory!'
print(msg)
if verbosity:
msg = 'Warning: could not rotate traces since no metadata was given\nCheck inventory directory!'
print(msg)
return wfstream
else:
parser = metadata[1]
+268 -173
View File
@@ -16,11 +16,6 @@ import time
import numpy as np
try:
import pyqtgraph as pg
except:
pg = None
from matplotlib.figure import Figure
from pylot.core.util.utils import find_horizontals, identifyPhase, loopIdentifyPhase, trim_station_components, \
identifyPhaseID, check4rotated
@@ -53,23 +48,18 @@ from pylot.core.pick.compare import Comparison
from pylot.core.util.defaults import OUTPUTFORMATS, FILTERDEFAULTS, \
SetChannelComponents
from pylot.core.util.utils import prepTimeAxis, full_range, scaleWFData, \
demeanTrace, isSorted, findComboBoxIndex, clims, pick_linestyle_plt, pick_color_plt
demeanTrace, isSorted, findComboBoxIndex, clims, pick_linestyle_plt, pick_color_plt, \
check4rotated, check4doubled, check4gaps, remove_underscores
from autoPyLoT import autoPyLoT
from pylot.core.util.thread import Thread
if sys.version_info.major == 3:
pass
import icons_rc_3 as icons_rc
elif sys.version_info.major == 2:
pass
import icons_rc_2 as icons_rc
else:
raise ImportError('Could not determine python version.')
if pg:
pg.setConfigOption('background', 'w')
pg.setConfigOption('foreground', 'k')
pg.setConfigOptions(antialias=True)
# pg.setConfigOption('leftButtonPan', False)
def getDataType(parent):
type = QInputDialog().getItem(parent, "Select phases type", "Type:",
@@ -99,6 +89,7 @@ def plot_pdf(_axes, x, y, annotation, bbox_props, xlabel=None, ylabel=None,
_axes.set_ylabel(ylabel)
_anno = _axes.annotate(annotation, xy=(.05, .5), xycoords='axes fraction')
_anno.set_bbox(bbox_props)
_anno.draggable()
return _axes
@@ -272,9 +263,11 @@ class ComparisonWidget(QWidget):
_gs = gridspec.GridSpec(3, 2)
self.clf()
self.canvas.figure._tight = True
_axes = self.canvas.figure.add_subplot(_gs[0:2, :])
_ax1 = self.canvas.figure.add_subplot(_gs[2, 0])
_ax2 = self.canvas.figure.add_subplot(_gs[2, 1])
self.canvas.figure.tight_layout()
# _axes.cla()
station = self.plotprops['station']
@@ -347,6 +340,7 @@ class ComparisonWidget(QWidget):
if wname != name:
self.widgets[wname].setEnabled(False)
self.canvas.figure.clf()
self.canvas.figure._tight = True
_axPstd, _axPexp = self.canvas.figure.add_subplot(221), self.canvas.figure.add_subplot(223)
_axSstd, _axSexp = self.canvas.figure.add_subplot(222), self.canvas.figure.add_subplot(224)
axes_dict = dict(P=dict(std=_axPstd, exp=_axPexp),
@@ -368,16 +362,26 @@ class ComparisonWidget(QWidget):
"number of samples: {nsamples}".format(phase=phase, nsamples=len(std))
_anno_std = axes_dict[phase]['std'].annotate(std_annotation, xy=(.05, .8), xycoords='axes fraction')
_anno_std.set_bbox(bbox_props)
_anno_std.draggable()
exp_annotation = "Distribution curve for {phase} differences'\n" \
"expectations (all stations)\n" \
"number of samples: {nsamples}".format(phase=phase, nsamples=len(exp))
_anno_exp = axes_dict[phase]['exp'].annotate(exp_annotation, xy=(.05, .8), xycoords='axes fraction')
_anno_exp.set_bbox(bbox_props)
axes_dict[phase]['exp'].set_xlabel('expectation [s]')
axes_dict[phase]['std'].set_xlabel('standard deviation [s]')
_anno_exp.draggable()
axes_dict[phase]['exp'].set_xlabel('Time [s]')
# add colors (early, late) for expectation
ax = axes_dict[phase]['exp']
xlims = ax.get_xlim()
ylims = ax.get_ylim()
ax.fill_between([xlims[0], 0], ylims[0], ylims[1], color=(0.9, 1.0, 0.9, 0.5), label='earlier than manual')
ax.fill_between([0, xlims[1]], ylims[0], ylims[1], color=(1.0, 0.9, 0.9, 0.5), label='later than manual')
legend = ax.legend()
legend.draggable()
for ax in axes_dict['P'].values():
ax.set_ylabel('number of picks [-]')
ax.set_ylabel('Frequency [-]')
self.canvas.draw()
else:
@@ -435,29 +439,32 @@ class PlotWidget(FigureCanvas):
class WaveformWidgetPG(QtGui.QWidget):
def __init__(self, parent=None, xlabel='x', ylabel='y', title='Title'):
QtGui.QWidget.__init__(self, parent) # , 1)
self.setParent(parent)
self._parent = parent
def __init__(self, parent, title='Title'):
QtGui.QWidget.__init__(self, parent=parent)
self.pg = self.parent().pg
# added because adding widget to scrollArea will set scrollArea to parent
self.orig_parent = parent
# attribute plotdict is a dictionary connecting position and a name
self.plotdict = dict()
# create plot
self.main_layout = QtGui.QVBoxLayout()
self.label = QtGui.QLabel()
self.setLayout(self.main_layout)
self.plotWidget = pg.PlotWidget(title=title, autoDownsample=True)
self.plotWidget = self.pg.PlotWidget(self.parent(), title=title, autoDownsample=True)
self.main_layout.addWidget(self.plotWidget)
self.main_layout.addWidget(self.label)
self.plotWidget.showGrid(x=False, y=True, alpha=0.2)
self.plotWidget.showGrid(x=False, y=True, alpha=0.3)
self.plotWidget.hideAxis('bottom')
self.plotWidget.hideAxis('left')
self.wfstart, self.wfend = 0, 0
self.pen_multicursor = self.pg.mkPen(self.parent()._style['multicursor']['rgba'])
self.pen_linecolor = self.pg.mkPen(self.parent()._style['linecolor']['rgba'])
self.reinitMoveProxy()
self._proxy = pg.SignalProxy(self.plotWidget.scene().sigMouseMoved, rateLimit=60, slot=self.mouseMoved)
self._proxy = self.pg.SignalProxy(self.plotWidget.scene().sigMouseMoved, rateLimit=60, slot=self.mouseMoved)
def reinitMoveProxy(self):
self.vLine = pg.InfiniteLine(angle=90, movable=False)
self.hLine = pg.InfiniteLine(angle=0, movable=False)
self.vLine = self.pg.InfiniteLine(angle=90, movable=False, pen=self.pen_multicursor)
self.hLine = self.pg.InfiniteLine(angle=0, movable=False, pen=self.pen_multicursor)
self.plotWidget.addItem(self.vLine, ignoreBounds=True)
self.plotWidget.addItem(self.hLine, ignoreBounds=True)
@@ -467,10 +474,10 @@ class WaveformWidgetPG(QtGui.QWidget):
mousePoint = self.plotWidget.getPlotItem().vb.mapSceneToView(pos)
x, y, = (mousePoint.x(), mousePoint.y())
# if x > 0:# and index < len(data1):
wfID = self._parent.getWFID(y)
station = self._parent.getStationName(wfID)
wfID = self.orig_parent.getWFID(y)
station = self.orig_parent.getStationName(wfID)
abstime = self.wfstart + x
if self._parent.get_current_event():
if self.orig_parent.get_current_event():
self.label.setText("station = {}, T = {}, t = {} [s]".format(station, abstime, x))
self.vLine.setPos(mousePoint.x())
self.hLine.setPos(mousePoint.y())
@@ -484,12 +491,6 @@ class WaveformWidgetPG(QtGui.QWidget):
def clearPlotDict(self):
self.plotdict = dict()
def getParent(self):
return self._parent
def setParent(self, parent):
self._parent = parent
def plotWFData(self, wfdata, title=None, zoomx=None, zoomy=None,
noiselevel=None, scaleddata=False, mapping=True,
component='*', nth_sample=1, iniPick=None, verbosity=0):
@@ -610,7 +611,6 @@ class WaveformWidgetPG(QtGui.QWidget):
class PylotCanvas(FigureCanvas):
def __init__(self, figure=None, parent=None, connect_events=True, multicursor=False,
panZoomX=True, panZoomY=True):
self._parent = parent
if not figure:
figure = Figure()
# create axes
@@ -618,17 +618,19 @@ class PylotCanvas(FigureCanvas):
self.axes = figure.axes
self.figure = figure
self.figure.set_facecolor((1., 1., 1.))
self.figure.set_facecolor(parent._style['background']['rgba_mpl'])
# attribute plotdict is a dictionary connecting position and a name
self.plotdict = dict()
# initialize super class
super(PylotCanvas, self).__init__(self.figure)
self.setParent(parent)
self.orig_parent = parent
if multicursor:
# add a cursor for station selection
self.multiCursor = MultiCursor(self.figure.canvas, self.axes,
horizOn=True, useblit=True,
color='m', lw=1)
color=parent._style['multicursor']['rgba_mpl'], lw=1)
# initialize panning attributes
self.press = None
@@ -743,7 +745,7 @@ class PylotCanvas(FigureCanvas):
def saveFigure(self):
if self.figure:
fd = QtGui.QFileDialog()
fname, filter = fd.getSaveFileName(self._parent, filter='Images (*.png)')
fname, filter = fd.getSaveFileName(self.parent(), filter='Images (*.png)')
if not fname:
return
if not fname.endswith('.png'):
@@ -884,12 +886,6 @@ class PylotCanvas(FigureCanvas):
def clearPlotDict(self):
self.plotdict = dict()
def getParent(self):
return self._parent
def setParent(self, parent):
self._parent = parent
def plotWFData(self, wfdata, title=None, zoomx=None, zoomy=None,
noiselevel=None, scaleddata=False, mapping=True,
component='*', nth_sample=1, iniPick=None, verbosity=0):
@@ -922,6 +918,9 @@ class PylotCanvas(FigureCanvas):
nsc.sort()
nsc.reverse()
style = self.orig_parent._style
linecolor = style['linecolor']['rgba_mpl']
for n, (network, station, channel) in enumerate(nsc):
st = st_select.select(network=network, station=station, channel=channel)
trace = st[0]
@@ -942,11 +941,13 @@ class PylotCanvas(FigureCanvas):
trace.normalize(np.max(np.abs(trace.data)) * 2)
times = [time for index, time in enumerate(time_ax) if not index % nth_sample]
data = [datum + n for index, datum in enumerate(trace.data) if not index % nth_sample]
ax.plot(times, data, 'k', linewidth=0.7)
ax.plot(times, data, color=linecolor, linewidth=0.7)
if noiselevel is not None:
for level in noiselevel:
ax.plot([time_ax[0], time_ax[-1]],
[level, level], '--k')
[level, level],
color = linecolor,
linestyle = 'dashed')
self.setPlotDict(n, (station, channel, network))
if iniPick:
ax.vlines(iniPick, ax.get_ylim()[0], ax.get_ylim()[1],
@@ -1109,7 +1110,8 @@ class PickDlg(QDialog):
def __init__(self, parent=None, data=None, station=None, network=None, picks=None,
autopicks=None, rotate=False, parameter=None, embedded=False, metadata=None,
event=None, filteroptions=None, model='iasp91'):
super(PickDlg, self).__init__(parent)
super(PickDlg, self).__init__(parent, 1)
self.orig_parent = parent
# initialize attributes
self.parameter = parameter
@@ -1129,6 +1131,7 @@ class PickDlg(QDialog):
pylot_user = getpass.getuser()
self._user = settings.value('user/Login', pylot_user)
self._dirty = False
self._style = parent._style
if picks:
self.picks = copy.deepcopy(picks)
self._init_picks = picks
@@ -1267,8 +1270,8 @@ class PickDlg(QDialog):
self.plot_arrivals_button.setCheckable(True)
# create accept/reject button
self.accept_button = QPushButton('&Accept Picks')
self.reject_button = QPushButton('&Reject Picks')
self.accept_button = QPushButton('&Accept')
self.reject_button = QPushButton('&Reject')
self.disable_ar_buttons()
# add hotkeys
@@ -1292,10 +1295,20 @@ class PickDlg(QDialog):
_dialtoolbar.addSeparator()
_dialtoolbar.addAction(self.resetPicksAction)
if self._embedded:
manu_label = QLabel('Manual Onsets:')
manu_label.setStyleSheet('QLabel {'
'padding:2px;'
'padding-left:5px}')
_dialtoolbar.addWidget(manu_label)
_dialtoolbar.addWidget(self.accept_button)
_dialtoolbar.addWidget(self.reject_button)
else:
_dialtoolbar.addWidget(self.nextStation)
est_label = QLabel('Estimated onsets:')
est_label.setStyleSheet('QLabel {'
'padding:2px;'
'padding-left:5px}')
_dialtoolbar.addWidget(est_label)
_dialtoolbar.addWidget(self.plot_arrivals_button)
# layout the innermost widget
@@ -1397,7 +1410,7 @@ class PickDlg(QDialog):
return
ax = self.multicompfig.axes[0]
if not textOnly:
ylims = self.getGlobalLimits('y')
ylims = self.getGlobalLimits(ax, 'y')
else:
ylims = self.multicompfig.getYLims(ax)
stime = self.getStartTime()
@@ -1525,36 +1538,46 @@ class PickDlg(QDialog):
self.leave_picking_mode()
def init_p_pick(self):
self.set_button_color(self.p_button, 'yellow')
self.set_button_border_color(self.p_button, 'yellow')
self.activatePicking()
self.currentPhase = str(self.p_button.text())
def init_s_pick(self):
self.set_button_color(self.s_button, 'yellow')
self.set_button_border_color(self.s_button, 'yellow')
self.activatePicking()
self.currentPhase = str(self.s_button.text())
def getPhaseID(self, phase):
return identifyPhaseID(phase)
def set_button_color(self, button, color=None):
def set_button_border_color(self, button, color=None):
'''
Set background color of a button.
button: type = QtGui.QAbstractButton
color: type = QtGui.QColor or type = str (RGBA)
'''
if type(color) == QtGui.QColor:
button.setStyleSheet({'QPushButton{background-color:transparent}'})
palette = button.palette()
role = button.backgroundRole()
palette.setColor(role, color)
button.setPalette(palette)
button.setAutoFillBackground(True)
elif type(color) == str or not color:
button.setStyleSheet("background-color: {}".format(color))
elif type(color) == str:
button.setStyleSheet('QPushButton{border-color: %s}' % color)
elif type(color) == tuple:
button.setStyleSheet('QPushButton{border-color: rgba%s}' % str(color))
elif not color:
button.setStyleSheet(self.orig_parent._style['stylesheet'])
def reset_p_button(self):
self.set_button_color(self.p_button)
self.set_button_border_color(self.p_button)
self.p_button.setEnabled(True)
self.p_button.setChecked(False)
self.p_button.setText('P')
def reset_s_button(self):
self.set_button_color(self.s_button)
self.set_button_border_color(self.s_button)
self.s_button.setEnabled(True)
self.s_button.setChecked(False)
self.s_button.setText('S')
@@ -1604,6 +1627,7 @@ class PickDlg(QDialog):
return self.station
def getChannelID(self, key):
if key < 0: key = 0
return self.multicompfig.getPlotDict()[int(key)][1]
def getTraceID(self, channels):
@@ -1638,8 +1662,8 @@ class PickDlg(QDialog):
def setYLims(self, limits):
self.cur_ylim = limits
def getGlobalLimits(self, axis):
return self.multicompfig.getGlobalLimits(axis)
def getGlobalLimits(self, ax, axis):
return self.multicompfig.getGlobalLimits(ax, axis)
def getWFData(self):
return self.data
@@ -1693,10 +1717,10 @@ class PickDlg(QDialog):
self.cidpress = self.multicompfig.connectPressEvent(self.setPick)
if self.getPhaseID(self.currentPhase) == 'P':
self.set_button_color(self.p_button, 'green')
self.set_button_border_color(self.p_button, 'green')
self.setIniPickP(gui_event, wfdata, trace_number)
elif self.getPhaseID(self.currentPhase) == 'S':
self.set_button_color(self.s_button, 'green')
self.set_button_border_color(self.s_button, 'green')
self.setIniPickS(gui_event, wfdata)
self.zoomAction.setEnabled(False)
@@ -1931,26 +1955,27 @@ class PickDlg(QDialog):
self.drawPicks(picktype='manual')
self.drawPicks(picktype='auto')
def drawPicks(self, phase=None, picktype='manual', textOnly=False):
def drawPicks(self, phase=None, picktype='manual', textOnly=False, picks=None):
# plotting picks
ax = self.multicompfig.axes[0]
if not textOnly:
ylims = self.multicompfig.getGlobalLimits(ax, 'y')
else:
ylims = ax.get_ylim()
if self.getPicks(picktype):
if phase is not None and not phase == 'SPt':
if (type(self.getPicks(picktype)[phase]) is dict
or type(self.getPicks(picktype)[phase]) is AttribDict):
picks = self.getPicks(picktype)[phase]
elif phase is None:
for phase in self.getPicks(picktype):
self.drawPicks(phase, picktype, textOnly)
return
if not picks:
if self.getPicks(picktype):
if phase is not None and not phase == 'SPt':
if (type(self.getPicks(picktype)[phase]) is dict
or type(self.getPicks(picktype)[phase]) is AttribDict):
picks = self.getPicks(picktype)[phase]
elif phase is None:
for phase in self.getPicks(picktype):
self.drawPicks(phase, picktype, textOnly)
return
else:
return
else:
return
else:
return
# get quality classes
if self.getPhaseID(phase) == 'P':
@@ -2235,9 +2260,20 @@ class MultiEventWidget(QWidget):
self.start_button = QtGui.QPushButton('Start')
for index, (key, func) in enumerate(self.options):
for index, (key, func, color) in enumerate(self.options):
rb = QtGui.QRadioButton(key)
rb.toggled.connect(self.check_rb_selection)
if color:
color = 'rgba{}'.format(color)
else:
color = 'transparent'
rb.setStyleSheet('QRadioButton{'
'background-color: %s;'
'border-style:outset;'
'border-width:1px;'
'border-radius:5px;'
'padding:5px;'
'}' % str(color))
if index == 0:
rb.setChecked(True)
self.rb_dict[key] = rb
@@ -2252,7 +2288,7 @@ class MultiEventWidget(QWidget):
self.main_layout.insertLayout(0, self.rb_layout)
def refresh_tooltips(self):
for key, func in self.options:
for key, func, color in self.options:
eventlist = func()
if not type(eventlist) == list:
eventlist = [eventlist]
@@ -2288,6 +2324,7 @@ class AutoPickWidget(MultiEventWidget):
def __init__(self, parent, options):
MultiEventWidget.__init__(self, options, parent, 1)
self.events2plot = {}
self.connect_buttons()
self.init_plot_layout()
self.init_log_layout()
@@ -2355,6 +2392,9 @@ class AutoPickWidget(MultiEventWidget):
self.main_layout.setStretch(1, 1)
def reinitEvents2plot(self):
for eventID, eventDict in self.events2plot.items():
for widget_key, widget in eventDict.items():
widget.setParent(None)
self.events2plot = {}
self.eventbox.clear()
self.refresh_plot_tabs()
@@ -2433,17 +2473,18 @@ class TuneAutopicker(QWidget):
QWidget used to modifiy and test picking parameters for autopicking algorithm.
:param: parent
:type: QtPyLoT Mainwindow
:type: PyLoT Mainwindow
'''
def __init__(self, parent):
QtGui.QWidget.__init__(self, parent, 1)
self.parent = parent
self.setParent(parent)
self._style = parent._style
self.setWindowTitle('PyLoT - Tune Autopicker')
self.parameter = parent._inputs
self.set_fig_dict(parent.fig_dict)
self.parameter = self.parent()._inputs
self.fig_dict = self.parent().fig_dict
self.data = Data()
self.pdlg_widget = None
self.pylot_picks = None
self.init_main_layouts()
self.init_eventlist()
self.init_figure_tabs()
@@ -2455,8 +2496,9 @@ class TuneAutopicker(QWidget):
self.add_log()
self.set_stretch()
self.resize(1280, 720)
if hasattr(parent, 'metadata'):
self.metadata = self.parent.metadata
self._manual_pick_plots = []
if hasattr(self.parent(), 'metadata'):
self.metadata = self.parent().metadata
else:
self.metadata = None
# self.setWindowModality(QtCore.Qt.WindowModality.ApplicationModal)
@@ -2464,7 +2506,8 @@ class TuneAutopicker(QWidget):
def set_fig_dict(self, fig_dict):
for key, value in fig_dict.items():
value._tight = True
if key is not 'mainFig':
value._tight = True
self.fig_dict = fig_dict
def init_main_layouts(self):
@@ -2478,7 +2521,7 @@ class TuneAutopicker(QWidget):
self.setLayout(self.main_layout)
def init_eventlist(self):
self.eventBox = self.parent.createEventBox()
self.eventBox = self.parent().createEventBox()
self.eventBox.setMaxVisibleItems(20)
self.fill_eventbox()
self.trace_layout.addWidget(self.eventBox)
@@ -2497,13 +2540,18 @@ class TuneAutopicker(QWidget):
self.stationBox.activated.connect(self.fill_tabs)
def fill_stationbox(self):
fnames = self.parent.getWFFnames_from_eventbox(eventbox=self.eventBox)
fnames = self.parent().getWFFnames_from_eventbox(eventbox=self.eventBox)
self.data.setWFData(fnames)
wfdat = self.data.getWFData() # all available streams
# remove possible underscores in station names
wfdat = remove_underscores(wfdat)
# rotate misaligned stations to ZNE
# check for gaps and doubled channels
check4gaps(wfdat)
check4doubled(wfdat)
wfdat = check4rotated(wfdat, self.parent().metadata, verbosity=0)
# trim station components to same start value
trim_station_components(wfdat, trim_start=True, trim_end=False)
# rotate misaligned stations to ZNE
wfdat = check4rotated(wfdat, self.parent.metadata)
self.stationBox.clear()
stations = []
for trace in self.data.getWFData():
@@ -2517,7 +2565,7 @@ class TuneAutopicker(QWidget):
for network, station in stations:
item = QtGui.QStandardItem(network + '.' + station)
if station in self.get_current_event().pylot_picks:
item.setBackground(self.parent._colors['ref'])
item.setBackground(self.parent()._ref_test_colors['ref'])
model.appendRow(item)
def init_figure_tabs(self):
@@ -2532,7 +2580,7 @@ class TuneAutopicker(QWidget):
self.stb_names = ['aicARHfig', 'refSpick', 'el_S1pick', 'el_S2pick']
def add_parameters(self):
self.paraBox = PylotParaBox(self.parameter)
self.paraBox = PylotParaBox(self.parameter, parent=self, windowflag=0)
self.paraBox.set_tune_mode(True)
self.update_eventID()
self.parameter_layout.addWidget(self.paraBox)
@@ -2541,6 +2589,7 @@ class TuneAutopicker(QWidget):
def add_buttons(self):
self.pick_button = QtGui.QPushButton('Pick Trace')
self.pick_button.setStyleSheet('QPushButton{border-color: rgba(110, 200, 0, 255)}')
self.pick_button.clicked.connect(self.call_picker)
self.close_button = QtGui.QPushButton('Close')
self.close_button.clicked.connect(self.hide)
@@ -2558,7 +2607,7 @@ class TuneAutopicker(QWidget):
def get_current_event(self):
path = self.eventBox.currentText()
return self.parent.project.getEventFromPath(path)
return self.parent().project.getEventFromPath(path)
def get_current_event_name(self):
return self.eventBox.currentText().split('/')[-1]
@@ -2574,10 +2623,7 @@ class TuneAutopicker(QWidget):
def get_current_event_autopicks(self, station):
event = self.get_current_event()
if event.pylot_autopicks:
if station in event.pylot_autopicks:
return event.pylot_autopicks[station]
else:
return
return event.pylot_autopicks[station]
def get_current_station(self):
return str(self.stationBox.currentText()).split('.')[-1]
@@ -2586,51 +2632,66 @@ class TuneAutopicker(QWidget):
widget = QtGui.QWidget()
v_layout = QtGui.QVBoxLayout()
v_layout.addWidget(canvas)
v_layout.addWidget(NavigationToolbar2QT(canvas, self))
widget.setLayout(v_layout)
return widget
def gen_pick_dlg(self):
if not self.get_current_event():
self.pickDlg = None
if self.pdlg_widget:
self.pdlg_widget.setParent(None)
self.pdlg_widget = None
return
station = self.get_current_station()
data = self.data.getWFData()
metadata = self.parent.metadata
metadata = self.parent().metadata
event = self.get_current_event()
filteroptions = self.parent.filteroptions
pickDlg = PickDlg(self, data=data.select(station=station),
station=station, parameter=self.parameter,
picks=self.get_current_event_picks(station),
autopicks=self.get_current_event_autopicks(station),
metadata=metadata, event=event, filteroptions=filteroptions,
embedded=True)
pickDlg.update_picks.connect(self.picks_from_pickdlg)
pickDlg.update_picks.connect(self.fill_eventbox)
pickDlg.update_picks.connect(self.fill_stationbox)
pickDlg.update_picks.connect(lambda: self.parent.setDirty(True))
pickDlg.update_picks.connect(self.parent.enableSaveEventAction)
self.pickDlg = QtGui.QWidget()
filteroptions = self.parent().filteroptions
self.pickDlg = PickDlg(self, data=data.select(station=station),
station=station, parameter=self.parameter,
picks=self.get_current_event_picks(station),
autopicks=self.get_current_event_autopicks(station),
metadata=metadata, event=event, filteroptions=filteroptions,
embedded=True)
self.pickDlg.update_picks.connect(self.picks_from_pickdlg)
self.pickDlg.update_picks.connect(self.fill_eventbox)
self.pickDlg.update_picks.connect(self.fill_stationbox)
self.pickDlg.update_picks.connect(lambda: self.parent().setDirty(True))
self.pickDlg.update_picks.connect(self.parent().enableSaveEventAction)
self.pickDlg.update_picks.connect(self.plot_manual_picks_to_figs)
self.pdlg_widget = QtGui.QWidget(self)
hl = QtGui.QHBoxLayout()
self.pickDlg.setLayout(hl)
hl.addWidget(pickDlg)
self.pdlg_widget.setLayout(hl)
hl.addWidget(self.pickDlg)
def picks_from_pickdlg(self, picks=None):
station = self.get_current_station()
replot = self.parent.addPicks(station, picks)
replot = self.parent().addPicks(station, picks)
self.get_current_event().setPick(station, picks)
if self.get_current_event() == self.parent.get_current_event():
if self.get_current_event() == self.parent().get_current_event():
if replot:
self.parent.plotWaveformDataThread()
self.parent.drawPicks()
self.parent().plotWaveformDataThread()
self.parent().drawPicks()
else:
self.parent.drawPicks(station)
self.parent.draw()
self.parent().drawPicks(station)
self.parent().draw()
def clear_plotitem(self, plotitem):
if type(plotitem) == list:
for item in plotitem:
self.clear_plotitem(item)
return
try:
plotitem.remove()
except Exception as e:
print('Warning could not remove item {}: {}'.format(plotitem, e))
def plot_manual_picks_to_figs(self):
picks = self.get_current_event_picks(self.get_current_station())
if not picks:
return
for plotitem in self._manual_pick_plots:
self.clear_plotitem(plotitem)
self._manual_pick_plots = []
st = self.data.getWFData()
tr = st.select(station=self.get_current_station())[0]
starttime = tr.stats.starttime
@@ -2649,47 +2710,48 @@ class TuneAutopicker(QWidget):
('refSpick', 0),
('el_S1pick', 0),
('el_S2pick', 0)]
qualityPpick = getQualityFromUncertainty(picks['P']['spe'], self.parameter['timeerrorsP'])
qualitySpick = getQualityFromUncertainty(picks['S']['spe'], self.parameter['timeerrorsS'])
for p_ax in p_axes:
axes = self.parent.fig_dict[p_ax[0]].axes
axes = self.parent().fig_dict[p_ax[0]].axes
if not axes:
continue
ax = axes[p_ax[1]]
self.plot_manual_Ppick_to_ax(ax, (picks['P']['mpp'] - starttime))
self.plot_manual_pick_to_ax(ax=ax, picks=picks, phase='P',
starttime=starttime, quality=qualityPpick)
for s_ax in s_axes:
axes = self.parent.fig_dict[s_ax[0]].axes
axes = self.parent().fig_dict[s_ax[0]].axes
if not axes:
continue
ax = axes[s_ax[1]]
self.plot_manual_Spick_to_ax(ax, (picks['S']['mpp'] - starttime))
self.plot_manual_pick_to_ax(ax=ax, picks=picks, phase='S',
starttime=starttime, quality=qualitySpick)
for canvas in self.parent().canvas_dict.values():
canvas.draw()
def plot_manual_pick_to_ax(self, ax, picks, phase, starttime, quality):
mpp = picks[phase]['mpp'] - starttime
color = pick_color_plt('manual', phase, quality)
def plot_manual_Ppick_to_ax(self, ax, pick):
y_top = 0.9 * ax.get_ylim()[1]
y_bot = 0.9 * ax.get_ylim()[0]
ax.vlines(pick, y_bot, y_top,
color='teal', linewidth=2, label='manual P Onset')
ax.plot([pick - 0.5, pick + 0.5],
[y_bot, y_bot], linewidth=2, color='teal')
ax.plot([pick - 0.5, pick + 0.5],
[y_top, y_top], linewidth=2, color='teal')
ax.legend(loc=1)
def plot_manual_Spick_to_ax(self, ax, pick):
y_top = 0.9 * ax.get_ylim()[1]
y_bot = 0.9 * ax.get_ylim()[0]
ax.vlines(pick, y_bot, y_top,
color='magenta', linewidth=2, label='manual S Onset')
ax.plot([pick - 0.5, pick + 0.5],
[y_bot, y_bot], linewidth=2, color='magenta')
ax.plot([pick - 0.5, pick + 0.5],
[y_top, y_top], linewidth=2, color='magenta')
self._manual_pick_plots.append(ax.vlines(mpp, y_bot, y_top,
color=color, linewidth=2,
label='manual {} Onset (quality: {})'.format(phase, quality)))
self._manual_pick_plots.append(ax.plot([mpp - 0.5, mpp + 0.5],
[y_bot, y_bot], linewidth=2,
color=color))
self._manual_pick_plots.append(ax.plot([mpp - 0.5, mpp + 0.5],
[y_top, y_top], linewidth=2,
color=color))
ax.legend(loc=1)
def fill_tabs(self, event=None, picked=False):
self.clear_all()
canvas_dict = self.parent.canvas_dict
self.gen_pick_dlg()
canvas_dict = self.parent().canvas_dict
self.overview = self.gen_tab_widget('Overview', canvas_dict['mainFig'])
id0 = self.figure_tabs.insertTab(0, self.pickDlg, 'Traces Plot')
id0 = self.figure_tabs.insertTab(0, self.pdlg_widget, 'Traces Plot')
id1 = self.figure_tabs.insertTab(1, self.overview, 'Overview')
id2 = self.figure_tabs.insertTab(2, self.p_tabs, 'P')
id3 = self.figure_tabs.insertTab(3, self.s_tabs, 'S')
@@ -2732,12 +2794,12 @@ class TuneAutopicker(QWidget):
self.init_tab_names()
def fill_eventbox(self):
project = self.parent.project
project = self.parent().project
if not project:
return
# update own list
self.parent.fill_eventbox(eventBox=self.eventBox, select_events='ref')
index_start = self.parent.eventBox.currentIndex()
self.parent().fill_eventbox(eventBox=self.eventBox, select_events='ref')
index_start = self.parent().eventBox.currentIndex()
index = index_start
if index == -1:
index += 1
@@ -2756,7 +2818,7 @@ class TuneAutopicker(QWidget):
if not index == index_start:
self.eventBox.activated.emit(index)
# update parent
self.parent.fill_eventbox()
self.parent().fill_eventbox()
def update_eventID(self):
self.paraBox.boxes['eventID'].setText(
@@ -2778,7 +2840,8 @@ class TuneAutopicker(QWidget):
'locflag': 0,
'savexml': False}
for key in self.fig_dict.keys():
self.fig_dict[key].clear()
if not key == 'plot_style':
self.fig_dict[key].clear()
self.ap_thread = Thread(self, autoPyLoT, arg=args,
progressText='Picking trace...',
pb_widget=self.pb_widget,
@@ -2819,8 +2882,8 @@ class TuneAutopicker(QWidget):
def params_from_gui(self):
parameters = self.paraBox.params_from_gui()
if self.parent:
self.parent._inputs = parameters
if self.parent():
self.parent()._inputs = parameters
return parameters
def set_stretch(self):
@@ -2828,10 +2891,11 @@ class TuneAutopicker(QWidget):
self.tune_layout.setStretch(1, 1)
def clear_all(self):
if hasattr(self, 'pickDlg'):
if self.pickDlg:
self.pickDlg.setParent(None)
del (self.pickDlg)
if hasattr(self, 'pdlg_widget'):
if self.pdlg_widget:
self.pdlg_widget.setParent(None)
# TODO: removing widget by parent deletion raises exception when activating stationbox:
# RuntimeError: Internal C++ object (PylotCanvas) already deleted.
if hasattr(self, 'overview'):
self.overview.setParent(None)
if hasattr(self, 'p_tabs'):
@@ -2860,7 +2924,7 @@ class PylotParaBox(QtGui.QWidget):
accepted = QtCore.Signal(str)
rejected = QtCore.Signal(str)
def __init__(self, parameter, parent=None):
def __init__(self, parameter, parent=None, windowflag=1):
'''
Generate Widget containing parameters for PyLoT.
@@ -2868,7 +2932,7 @@ class PylotParaBox(QtGui.QWidget):
:type: PylotParameter (object)
'''
QtGui.QWidget.__init__(self, parent)
QtGui.QWidget.__init__(self, parent, windowflag)
self.parameter = parameter
self.tabs = QtGui.QTabWidget()
self.layout = QtGui.QVBoxLayout()
@@ -3411,9 +3475,6 @@ class SubmitLocal(QWidget):
self.main_layout.addWidget(self.button)
def start(self):
print('subprocess Popen')
def start(self, pp_export, ncores):
self.execute_command(pp_export, ncores)
@@ -3433,6 +3494,7 @@ class SubmitLocal(QWidget):
class PropertiesDlg(QDialog):
def __init__(self, parent=None, infile=None, inputs=None):
super(PropertiesDlg, self).__init__(parent)
self._pylot_mainwindow = self.parent()
self.infile = infile
self.inputs = inputs
@@ -3733,14 +3795,29 @@ class PhasesTab(PropTab):
class GraphicsTab(PropTab):
def __init__(self, parent=None):
super(GraphicsTab, self).__init__(parent)
self.pylot_mainwindow = parent._pylot_mainwindow
self.init_layout()
self.add_pg_cb()
self.add_nth_sample()
self.add_style_settings()
self.setLayout(self.main_layout)
def init_layout(self):
self.main_layout = QGridLayout()
def add_style_settings(self):
styles = self.pylot_mainwindow._styles
active_stylename = self.pylot_mainwindow._stylename
label = QtGui.QLabel('Application style (might require Application restart):')
self.style_cb = QComboBox()
for stylename, style in styles.items():
self.style_cb.addItem(stylename, style)
index_current_style = self.style_cb.findText(active_stylename)
self.style_cb.setCurrentIndex(index_current_style)
self.main_layout.addWidget(label, 2, 0)
self.main_layout.addWidget(self.style_cb, 2, 1)
self.style_cb.activated.connect(self.set_current_style)
def add_nth_sample(self):
settings = QSettings()
nth_sample = settings.value("nth_sample")
@@ -3757,6 +3834,12 @@ class GraphicsTab(PropTab):
self.main_layout.addWidget(self.spinbox_nth_sample, 1, 1)
def add_pg_cb(self):
try:
import pyqtgraph as pg
pg = True
except:
pg = False
text = {True: 'Use pyqtgraphic library for plotting',
False: 'Cannot use library: pyqtgraphic not found on system'}
label = QLabel('PyQt graphic')
@@ -3768,6 +3851,10 @@ class GraphicsTab(PropTab):
self.main_layout.addWidget(label, 0, 0)
self.main_layout.addWidget(self.checkbox_pg, 0, 1)
def set_current_style(self):
selected_style = self.style_cb.currentText()
self.pylot_mainwindow.set_style(selected_style)
def getValues(self):
values = {'nth_sample': self.spinbox_nth_sample.value(),
'pyqtgraphic': self.checkbox_pg.isChecked()}
@@ -4215,15 +4302,23 @@ class LoadDataDlg(QDialog):
class HelpForm(QDialog):
def __init__(self, page=QUrl('https://ariadne.geophysik.rub.de/trac/PyLoT'),
parent=None):
super(HelpForm, self).__init__(parent)
def __init__(self, parent=None,
page=QUrl('https://ariadne.geophysik.ruhr-uni-bochum.de/trac/PyLoT/')):
super(HelpForm, self).__init__(parent, 1)
self.setAttribute(Qt.WA_DeleteOnClose)
self.setAttribute(Qt.WA_GroupLeader)
backAction = QAction(QIcon(":/back.png"), "&Back", self)
self.home_page = page
back_icon = QIcon()
back_icon.addPixmap(QPixmap(':/icons/back.png'))
home_icon = QIcon()
home_icon.addPixmap(QPixmap(':/icons/home.png'))
backAction = QAction(back_icon, "&Back", self)
backAction.setShortcut(QKeySequence.Back)
homeAction = QAction(QIcon(":/home.png"), "&Home", self)
homeAction = QAction(home_icon, "&Home", self)
homeAction.setShortcut("Home")
self.pageLabel = QLabel()
@@ -4236,21 +4331,21 @@ class HelpForm(QDialog):
layout = QVBoxLayout()
layout.addWidget(toolBar)
layout.addWidget(self.webBrowser, 1)
layout.addWidget(self.webBrowser)
self.setLayout(layout)
self.connect(backAction, Signal("triggered()"),
self.webBrowser, Slot("backward()"))
self.connect(homeAction, Signal("triggered()"),
self.webBrowser, Slot("home()"))
self.connect(self.webBrowser, Signal("sourceChanged(QUrl)"),
self.updatePageTitle)
backAction.triggered.connect(self.webBrowser.back)
homeAction.triggered.connect(self.home)
self.webBrowser.urlChanged.connect(self.updatePageTitle)
self.resize(400, 600)
self.resize(1280, 720)
self.setWindowTitle("{0} Help".format(QApplication.applicationName()))
def home(self):
self.webBrowser.load(self.home_page)
def updatePageTitle(self):
self.pageLabel.setText(self.webBrowser.documentTitle())
self.pageLabel.setText(self.webBrowser.title())
if __name__ == '__main__':
-319295
View File
File diff suppressed because it is too large Load Diff
-84755
View File
File diff suppressed because it is too large Load Diff
+1
View File
@@ -0,0 +1 @@
# -*- coding: utf-8 -*-
+259
View File
@@ -0,0 +1,259 @@
QMainWindow{
background-color: qlineargradient(spread:reflect, x1:0, y1:0, x2:0, y2:0.5, stop:0 rgba(230, 230, 230, 255), stop:1 rgba(255, 255, 255, 255));
color: rgba(0, 0, 0, 255);
}
QWidget{
background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, stop:0 rgba(235, 235, 235, 255), stop:1 rgba(230, 230, 230, 255));
color: rgba(0, 0, 0, 255);
}
QToolBar QWidget:checked{
background-color: transparent;
border-color: rgba(230, 230, 230, 255);
border-width: 2px;
border-style:inset;
}
QComboBox{
background-color: rgba(255, 255, 255, 255);
color: rgba(0, 0, 0, 255);
min-height: 1.5em;
selection-background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 rgba(0, 55, 140, 150), stop:1 rgba(0, 70, 180, 150));
}
QComboBox *{
background-color: rgba(255, 255, 255, 255);
color: rgba(0, 0, 0, 255);
selection-background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 rgba(0, 55, 140, 150), stop:1 rgba(0, 70, 180, 150));
selection-color: rgba(255, 255, 255, 255);
}
QMenuBar{
background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:2, stop:0 rgba(240, 240, 240, 255), stop:1 rgba(230, 230, 230, 255));
padding:1px;
}
QMenuBar::item{
background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:2, stop:0 rgba(240, 240, 240, 255), stop:1 rgba(230, 230, 230, 255));
color: rgba(0, 0, 0, 255);
padding:3px;
padding-left:5px;
padding-right:5px;
}
QMenu{
background-color: qlineargradient(spread:reflect, x1:0, y1:0, x2:0, y2:0.5, stop:0 rgba(230, 230, 230, 255), stop:1 rgba(230, 230, 230 255));
color: rgba(0, 0, 0, 255);
padding:0;
}
*::item:selected{
color: rgba(0, 0, 0, 255);
background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 rgba(0, 55, 140, 150), stop:1 rgba(0, 70, 180, 150));
}
QToolBar{
background-color: qlineargradient(spread:reflect, x1:0, y1:0, x2:0, y2:0.5, stop:0 rgba(230, 230, 230, 255), stop:1 rgba(255, 255, 255, 255));
border-style:solid;
border-color:rgba(200, 200, 200, 150);
border-width:1px;
}
QToolBar *{
background-color: qlineargradient(spread:reflect, x1:0, y1:0, x2:0, y2:0.5, stop:0 rgba(230, 230, 230, 255), stop:1 rgba(255, 255, 255, 255));
}
QMessageBox{
background-color: rgba(255, 255, 255, 255);
color: rgba(0, 0, 0, 255);
}
QTableWidget{
background-color: rgba(255, 255, 255, 255);
color:rgba(0, 0, 0, 255);
border-color:rgba(0, 0, 0, 255);
selection-background-color: rgba(200, 210, 230, 255);
}
QTableCornerButton::section{
border: none;
background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 rgba(255, 255, 255, 255), stop:1 rgba(230, 230, 230, 255));
}
QHeaderView::section{
background-color:qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 rgba(255, 255, 255, 255), stop:1 rgba(230, 230, 230, 255));
border:none;
border-top-style:solid;
border-width:1px;
border-top-color:qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 rgba(255, 255, 255, 255), stop:1 rgba(230, 230, 230, 255));
color:rgba(0, 0, 0, 255);
padding:5px;
}
QHeaderView::section:checked{
background-color:qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 rgba(0, 55, 140, 150), stop:1 rgba(0, 70, 180, 150));
border-top-color:qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 rgba(0, 55, 140, 150), stop:1 rgba(0, 70, 180, 150));
}
QHeaderView{
background-color:qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 rgba(255, 255, 255, 255), stop:1 rgba(230, 230, 230, 255));
border:none;
border-top-style:solid;
border-width:1px;
border-top-color:rgba(230, 230, 230, 255);
color:rgba(0, 0, 0, 255);
}
QListWidget{
background-color:rgba(230, 230, 230, 255);
color:rgba(0, 0, 0, 255);
}
QStatusBar{
background-color:rgba(255, 255, 255, 255);
color:rgba(0, 0, 0, 255);
}
QPushButton{
background-color:qlineargradient(spread:reflect, x1:0, y1:0, x2:0, y2:0.5, stop:0 rgba(230, 230, 230, 255), stop:1 rgba(245, 245, 245, 255));
color:rgba(0, 0, 0, 255);
border-style: outset;
border-width: 1px;
border-color: rgba(100, 100, 120, 255);
min-width: 6em;
padding: 4px;
padding-left:5px;
padding-right:5px;
border-radius: 2px;
}
QPushButton:pressed{
background-color: rgba(230, 230, 230, 255);
border-style: inset;
}
QPushButton:checked{
background-color: rgba(230, 230, 230, 255);
border-style: inset;
}
*:disabled{
color:rgba(100, 100, 120, 255);
}
QTabBar{
background-color:transparent;
}
QTabBar::tab{
background-color:qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, stop:0 rgba(230, 230, 230, 255), stop:1 rgba(210, 210, 210, 255));
color: rgba(0, 0, 0, 255);
border-style:solid;
border-color:rgba(210, 210, 210 255);
border-bottom-color: transparent;
border-width:1px;
padding:5px;
}
QTabBar::tab:selected{
background-color:qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, stop:0 rgba(255, 255, 255, 255), stop:1 rgba(245, 245, 245, 255));
color: rgba(0, 0, 0, 255);
border-style:solid;
border-color:rgba(245, 245, 245, 255);
border-bottom-color: transparent;
border-width:1px;
padding:5px;
}
QTabBar::tab:disabled{
background-color:qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, stop:0 rgba(230, 230, 230, 255), stop:1 rgba(210, 210, 210, 255));
color: rgba(100, 100, 120, 255);
}
QTabWidget{
background-color:transparent;
}
QTabWidget::pane{
background-color:rgba(0, 0, 0, 255);
border-style:solid;
border-color:rgba(245, 245, 245, 255);
border-width:1px;
}
QTabWidget::tab{
background-color:rgba(255, 255, 255, 255);
}
QTabWidget > QWidget{
background-color: rgba(245, 245, 245, 255);
color: rgba(0, 0, 0, 255);
}
QScrollArea{
background: transparent;
}
QScrollArea>QWidget>QWidget{
background: transparent;
}
QLabel{
color: rgba(0, 0, 0, 255);
background-color: transparent;
}
QTextEdit{
color: rgba(0, 0, 0, 255);
background-color: rgba(255, 255, 255, 255);
}
QSpinBox{
color: rgba(0, 0, 0, 255);
background-color: rgba(255, 255, 255, 255);
}
QDoubleSpinBox{
color: rgba(0, 0, 0, 255);
background-color: rgba(255, 255, 255, 255);
}
QCheckBox{
background-color:transparent;
border:none;
}
QLineEdit{
background-color: rgba(255, 255, 255, 255);
border: 1px inset;
border-radius:0;
border-color: rgba(100, 100, 120, 255);
}
QLineEdit:disabled{
background-color: rgba(255, 255, 255, 255);
border: 1px inset;
border-radius:0;
border-color: rgba(200, 200, 200, 255);
}
QListWidget{
background-color:rgba(255, 255, 255, 255)
}
QProgressBar{
background-color:rgba(230, 230, 230, 255);
}
QProgressBar::chunk{
background-color:qlineargradient(spread:reflect, x1:0, y1:0, x2:0.5, y2:0, stop:0 transparent, stop:1 rgba(0, 70, 180, 150));
}
QStatusBar{
background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, stop:0 rgba(235, 235, 235, 255), stop:1 rgba(230, 230, 230, 255));
color: rgba(0, 0, 0, 255);
}
+258
View File
@@ -0,0 +1,258 @@
QMainWindow{
background-color: qlineargradient(spread:reflect, x1:0, y1:0, x2:0, y2:0.5, stop:0 rgba(70, 70, 80, 255), stop:1 rgba(60, 60, 70, 255));
color: rgba(255, 255, 255, 255);
}
QWidget{
background-color: qlineargradient(spread:reflect, x1:0, y1:0, x2:0, y2:0.5, stop:0 rgba(70, 70, 80, 255), stop:1 rgba(60, 60, 70, 255));
color: rgba(255, 255, 255, 255);
}
QToolBar QWidget:checked{
background-color: transparent;
border-color: rgba(100, 100, 120, 255);
border-width: 2px;
border-style:inset;
}
QComboBox{
background-color: rgba(90, 90, 100, 255);
color: rgba(255, 255, 255, 255);
min-height: 1.5em;
selection-background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 rgba(0, 144, 180, 255), stop:1 rgba(0, 150, 190, 255));
}
QComboBox *{
background-color: rgba(90, 90, 100, 255);
color: rgba(255, 255, 255, 255);
selection-background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 rgba(0, 144, 180, 255), stop:1 rgba(0, 150, 190, 255));
selection-color: rgba(255, 255, 255, 255);
}
QMenuBar{
background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, stop:0 rgba(70, 70, 80, 255), stop:1 rgba(60, 60, 70, 255));
padding:1px;
}
QMenuBar::item{
background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, stop:0 rgba(70, 70, 80, 255), stop:1 rgba(60, 60, 70, 255));
color: rgba(255, 255, 255, 255);
padding:3px;
padding-left:5px;
padding-right:5px;
}
QMenu{
background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, stop:0 rgba(70, 70, 80, 255), stop:1 rgba(60, 60, 70, 255));
color: rgba(255, 255, 255, 255);
padding:0;
}
*::item:selected{
color: rgba(255, 255, 255, 255);
background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 rgba(0, 144, 180, 255), stop:1 rgba(0, 150, 190, 255));
}
QToolBar{
background-color: qlineargradient(spread:reflect, x1:0, y1:0, x2:0, y2:0.5, stop:0 rgba(70, 70, 80, 255), stop:1 rgba(60, 60, 70, 255));
border-style:solid;
border-color:rgba(80, 80, 90, 255);
border-width:1px;
}
QToolBar *{
background-color: qlineargradient(spread:reflect, x1:0, y1:0, x2:0, y2:0.5, stop:0 rgba(70, 70, 80, 255), stop:1 rgba(60, 60, 70, 255));
}
QMessageBox{
background-color: rgba(60, 60, 70, 255);
color: rgba(255, 255, 255, 255);
}
QTableWidget{
background-color: rgba(80, 80, 90, 255);
color:rgba(255, 255, 255, 255);
border-color:rgba(255, 255, 255, 255);
selection-background-color: rgba(200, 210, 230, 255);
}
QTableCornerButton::section{
border: none;
background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 rgba(60, 60, 70, 255), stop:1 rgba(70, 70, 80, 255));
}
QHeaderView::section{
background-color:qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 rgba(60, 60, 70, 255), stop:1 rgba(70, 70, 80, 255));
border:none;
border-top-style:solid;
border-width:1px;
border-top-color:qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 rgba(60, 60, 70, 255), stop:1 rgba(70, 70, 80, 255));
color:rgba(255, 255, 255, 255);
padding:5px;
}
QHeaderView::section:checked{
background-color:qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 rgba(0, 120, 150, 255), stop:1 rgba(0, 150, 190, 255));
border-top-color:qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 rgba(0, 120, 150, 255), stop:1 rgba(0, 150, 190, 255));
}
QHeaderView{
background-color:qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 rgba(60, 60, 70, 255), stop:1 rgba(70, 70, 80, 255));
border:none;
border-top-style:solid;
border-width:1px;
border-top-color:rgba(70, 70, 80, 255);
color:rgba(255, 255, 255, 255);
}
QListWidget{
background-color:rgba(200, 200, 200, 255);
color:rgba(255, 255, 255, 255);
}
QStatusBar{
background-color:rgba(60, 60, 70, 255);
color:rgba(255, 255, 255, 255);
}
QPushButton{
background-color:qlineargradient(spread:reflect, x1:0, y1:0, x2:0, y2:0.5, stop:0 rgba(70, 70, 80, 255), stop:1 rgba(60, 60, 70, 255));
color:rgba(255, 255, 255, 255);
border-style: outset;
border-width: 2px;
border-color: rgba(50, 50, 60, 255);
min-width: 6em;
padding: 4px;
padding-left:5px;
padding-right:5px;
border-radius: 2px;
}
QPushButton:pressed{
background-color: qlineargradient(spread:reflect, x1:0, y1:0, x2:0, y2:0.5, stop:0 rgba(80, 80, 90, 255), stop:1 rgba(70, 70, 80, 255));
border-style: inset;
}
QPushButton:checked{
background-color: qlineargradient(spread:reflect, x1:0, y1:0, x2:0, y2:0.5, stop:0 rgba(80, 80, 90, 255), stop:1 rgba(70, 70, 80, 255));
border-style: inset;
}
*:disabled{
color: rgba(130, 130, 130, 255);
}
QTabBar{
background-color:transparent;
}
QTabBar::tab{
background-color:qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, stop:0 rgba(70, 70, 80, 255), stop:1 rgba(60, 60, 70, 255));
color: rgba(255, 255, 255, 255);
border-style:solid;
border-color:rgba(70, 70, 80, 255);
border-bottom-color: transparent;
border-width:1px;
padding:5px;
}
QTabBar::tab:selected{
background-color:qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, stop:0 rgba(80, 80, 90, 255), stop:1 rgba(70, 70, 80, 255));
color: rgba(255, 255, 255, 255);
border-style:solid;
border-color:rgba(70, 70, 80, 255);
border-bottom-color: transparent;
border-width:1px;
padding:5px;
}
QTabBar::tab:disabled{
background-color:qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, stop:0 rgba(70, 70, 80, 255), stop:1 rgba(60, 60, 70, 255));
color: rgba(100, 100, 120, 255);
}
QTabWidget{
background-color:transparent;
}
QTabWidget::pane{
background-color:rgba(70, 70, 80, 255);
border-style:solid;
border-color:rgba(70, 70, 80, 255);
border-width:1px;
}
QTabWidget::tab{
background-color:rgba(70, 70, 80, 255);
}
QTabWidget > QWidget{
background-color: rgba(70, 70, 80, 255);
color: rgba(255, 255, 255, 255);
}
QScrollArea{
background: transparent;
}
QScrollArea>QWidget>QWidget{
background: transparent;
}
QLabel{
color: rgba(255, 255, 255, 255);
background-color: transparent;
}
QTextEdit{
color: rgba(255, 255, 255, 255);
background-color: rgba(90, 90, 100, 255);
}
QSpinBox{
color: rgba(255, 255, 255, 255);
background-color: rgba(90, 90, 100, 255);
}
QDoubleSpinBox{
color: rgba(255, 255, 255, 255);
background-color: rgba(90, 90, 100, 255);
}
QCheckBox{
background-color:transparent;
border:none;
}
QLineEdit{
background-color: rgba(90, 90, 100, 255);
border: 1px inset;
border-radius:0;
border-color: rgba(100, 100, 120, 255);
}
QLineEdit:disabled{
background-color: rgba(90, 90, 100, 255);
border: 1px inset;
border-radius:0;
border-color: rgba(200, 200, 200, 255);
}
QListWidget{
background-color:rgba(60, 60, 70, 255)
}
QProgressBar{
background-color:rgba(60, 60, 70, 255);
}
QProgressBar::chunk{
background-color:qlineargradient(spread:reflect, x1:0, y1:0, x2:0.5, y2:0, stop:0 transparent, stop:1 rgba(0, 150, 190, 255));
}
QStatusBar{
background-color: qlineargradient(spread:reflect, x1:0, y1:0, x2:0, y2:0.5, stop:0 rgba(70, 70, 80, 255), stop:1 rgba(60, 60, 70, 255));
color: rgba(255, 255, 255, 255);
}
+70
View File
@@ -0,0 +1,70 @@
# -*- coding: utf-8 -*-
# Set base phase colors for manual and automatic picks
# together with a modifier (r, g, or b) used to alternate
# the base color
phasecolors = {
'manual': {
'P':{
'rgba': (0, 0, 255, 255),
'modifier': 'g'},
'S':{
'rgba': (255, 0, 0, 255),
'modifier': 'b'}
},
'auto':{
'P':{
'rgba': (140, 0, 255, 255),
'modifier': 'g'},
'S':{
'rgba': (255, 140, 0, 255),
'modifier': 'b'}
}
}
# Set plot colors and stylesheet for each style
stylecolors = {
'default':{
'linecolor':{
'rgba': (0, 0, 0, 255)},
'background': {
'rgba': (255, 255, 255, 255)},
'multicursor': {
'rgba': (255, 190, 0, 255)},
'ref': {
'rgba': (200, 210, 230, 255)},
'test': {
'rgba': (200, 230, 200, 255)},
'stylesheet': {
'filename': None}
},
'dark': {
'linecolor': {
'rgba': (230, 230, 230, 255)},
'background': {
'rgba': (50, 50, 60, 255)},
'multicursor': {
'rgba': (0, 150, 190, 255)},
'ref': {
'rgba': (80, 110, 170, 255)},
'test': {
'rgba': (130, 190, 100, 255)},
'stylesheet': {
'filename': 'dark.qss'}
},
'bright': {
'linecolor': {
'rgba': (0, 0, 0, 255)},
'background': {
'rgba': (255, 255, 255, 255)},
'multicursor': {
'rgba': (100, 100, 190, 255)},
'ref': {
'rgba': (200, 210, 230, 255)},
'test': {
'rgba': (200, 230, 200, 255)},
'stylesheet': {
'filename': 'bright.qss'}
}
}
View File
-13
View File
@@ -1,13 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
from PySide.QtGui import QApplication
from pylot.core.util.widgets import HelpForm
app = QApplication(sys.argv)
win = HelpForm()
win.show()
app.exec_()
-20
View File
@@ -1,20 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
import matplotlib
matplotlib.use('Qt4Agg')
matplotlib.rcParams['backend.qt4'] = 'PySide'
from PySide.QtGui import QApplication
from obspy.core import read
from pylot.core.util.widgets import PickDlg
app = QApplication(sys.argv)
data = read()
win = PickDlg(data=data)
win.show()
app.exec_()
-13
View File
@@ -1,13 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
from PySide.QtGui import QApplication
from pylot.core.util.widgets import PropertiesDlg
app = QApplication(sys.argv)
win = PropertiesDlg()
win.show()
app.exec_()
-19
View File
@@ -1,19 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
import time
from PySide.QtGui import QApplication
from pylot.core.util.widgets import FilterOptionsDialog, PropertiesDlg, HelpForm
dialogs = [FilterOptionsDialog, PropertiesDlg, HelpForm]
app = QApplication(sys.argv)
for dlg in dialogs:
win = dlg()
win.show()
time.sleep(1)
win.destroy()
-23
View File
@@ -1,23 +0,0 @@
# -*- coding: utf-8 -*-
'''
Created on 10.11.2014
@author: sebastianw
'''
import unittest
class Test(unittest.TestCase):
def setUp(self):
pass
def tearDown(self):
pass
def testName(self):
pass
if __name__ == "__main__":
# import sys;sys.argv = ['', 'Test.testName']
unittest.main()
-17
View File
@@ -1,17 +0,0 @@
# -*- coding: utf-8 -*-
'''
Created on 10.11.2014
@author: sebastianw
'''
import unittest
class Test(unittest.TestCase):
def testName(self):
pass
if __name__ == "__main__":
# import sys;sys.argv = ['', 'Test.testName']
unittest.main()
-311
View File
@@ -1,311 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Script to run autoPyLoT-script "makeCF.py".
Only for test purposes!
"""
import argparse
import glob
from obspy.core import read
from pylot.core.pick.charfuns import *
from pylot.core.pick.picker import *
def run_makeCF(project, database, event, iplot, station=None):
# parameters for CF calculation
t2 = 7 # length of moving window for HOS calculation [sec]
p = 4 # order of HOS
cuttimes = [10, 50] # start and end time for CF calculation
bpz = [2, 30] # corner frequencies of bandpass filter, vertical component
bph = [2, 15] # corner frequencies of bandpass filter, horizontal components
tdetz = 1.2 # length of AR-determination window [sec], vertical component
tdeth = 0.8 # length of AR-determination window [sec], horizontal components
tpredz = 0.4 # length of AR-prediction window [sec], vertical component
tpredh = 0.4 # length of AR-prediction window [sec], horizontal components
addnoise = 0.001 # add noise to seismogram for stable AR prediction
arzorder = 2 # chosen order of AR process, vertical component
arhorder = 4 # chosen order of AR process, horizontal components
TSNRhos = [5, 0.5, 1, 0.1] # window lengths [s] for calculating SNR for earliest/latest pick and quality assessment
# from HOS-CF [noise window, safety gap, signal window, slope determination window]
TSNRarz = [5, 0.5, 1, 0.5] # window lengths [s] for calculating SNR for earliest/lates pick and quality assessment
# from ARZ-CF
# get waveform data
if station:
dpz = '/data/%s/EVENT_DATA/LOCAL/%s/%s/%s*HZ.msd' % (project, database, event, station)
dpe = '/data/%s/EVENT_DATA/LOCAL/%s/%s/%s*HE.msd' % (project, database, event, station)
dpn = '/data/%s/EVENT_DATA/LOCAL/%s/%s/%s*HN.msd' % (project, database, event, station)
# dpz = '/DATA/%s/EVENT_DATA/LOCAL/%s/%s/%s*_z.gse' % (project, database, event, station)
# dpe = '/DATA/%s/EVENT_DATA/LOCAL/%s/%s/%s*_e.gse' % (project, database, event, station)
# dpn = '/DATA/%s/EVENT_DATA/LOCAL/%s/%s/%s*_n.gse' % (project, database, event, station)
else:
# dpz = '/DATA/%s/EVENT_DATA/LOCAL/%s/%s/*_z.gse' % (project, database, event)
# dpe = '/DATA/%s/EVENT_DATA/LOCAL/%s/%s/*_e.gse' % (project, database, event)
# dpn = '/DATA/%s/EVENT_DATA/LOCAL/%s/%s/*_n.gse' % (project, database, event)
dpz = '/data/%s/EVENT_DATA/LOCAL/%s/%s/*HZ.msd' % (project, database, event)
dpe = '/data/%s/EVENT_DATA/LOCAL/%s/%s/*HE.msd' % (project, database, event)
dpn = '/data/%s/EVENT_DATA/LOCAL/%s/%s/*HN.msd' % (project, database, event)
wfzfiles = glob.glob(dpz)
wfefiles = glob.glob(dpe)
wfnfiles = glob.glob(dpn)
if wfzfiles:
for i in range(len(wfzfiles)):
print
'Vertical component data found ...'
print
wfzfiles[i]
st = read('%s' % wfzfiles[i])
st_copy = st.copy()
# filter and taper data
tr_filt = st[0].copy()
tr_filt.filter('bandpass', freqmin=bpz[0], freqmax=bpz[1], zerophase=False)
tr_filt.taper(max_percentage=0.05, type='hann')
st_copy[0].data = tr_filt.data
##############################################################
# calculate HOS-CF using subclass HOScf of class CharacteristicFunction
hoscf = HOScf(st_copy, cuttimes, t2, p) # instance of HOScf
##############################################################
# calculate AIC-HOS-CF using subclass AICcf of class CharacteristicFunction
# class needs stream object => build it
tr_aic = tr_filt.copy()
tr_aic.data = hoscf.getCF()
st_copy[0].data = tr_aic.data
aiccf = AICcf(st_copy, cuttimes) # instance of AICcf
##############################################################
# get prelimenary onset time from AIC-HOS-CF using subclass AICPicker of class AutoPicking
aicpick = AICPicker(aiccf, None, TSNRhos, 3, 10, None, 0.1)
##############################################################
# get refined onset time from HOS-CF using class Picker
hospick = PragPicker(hoscf, None, TSNRhos, 2, 10, 0.001, 0.2, aicpick.getpick())
# get earliest and latest possible picks
hosELpick = EarlLatePicker(hoscf, 1.5, TSNRhos, None, 10, None, None, hospick.getpick())
##############################################################
# calculate ARZ-CF using subclass ARZcf of class CharcteristicFunction
# get stream object of filtered data
st_copy[0].data = tr_filt.data
arzcf = ARZcf(st_copy, cuttimes, tpredz, arzorder, tdetz, addnoise) # instance of ARZcf
##############################################################
# calculate AIC-ARZ-CF using subclass AICcf of class CharacteristicFunction
# class needs stream object => build it
tr_arzaic = tr_filt.copy()
tr_arzaic.data = arzcf.getCF()
st_copy[0].data = tr_arzaic.data
araiccf = AICcf(st_copy, cuttimes, tpredz, 0, tdetz) # instance of AICcf
##############################################################
# get onset time from AIC-ARZ-CF using subclass AICPicker of class AutoPicking
aicarzpick = AICPicker(araiccf, 1.5, TSNRarz, 2, 10, None, 0.1)
##############################################################
# get refined onset time from ARZ-CF using class Picker
arzpick = PragPicker(arzcf, 1.5, TSNRarz, 2.0, 10, 0.1, 0.05, aicarzpick.getpick())
# get earliest and latest possible picks
arzELpick = EarlLatePicker(arzcf, 1.5, TSNRarz, None, 10, None, None, arzpick.getpick())
elif not wfzfiles:
print
'No vertical component data found!'
if wfefiles and wfnfiles:
for i in range(len(wfefiles)):
print
'Horizontal component data found ...'
print
wfefiles[i]
print
wfnfiles[i]
# merge streams
H = read('%s' % wfefiles[i])
H += read('%s' % wfnfiles[i])
H_copy = H.copy()
# filter and taper data
trH1_filt = H[0].copy()
trH2_filt = H[1].copy()
trH1_filt.filter('bandpass', freqmin=bph[0], freqmax=bph[1], zerophase=False)
trH2_filt.filter('bandpass', freqmin=bph[0], freqmax=bph[1], zerophase=False)
trH1_filt.taper(max_percentage=0.05, type='hann')
trH2_filt.taper(max_percentage=0.05, type='hann')
H_copy[0].data = trH1_filt.data
H_copy[1].data = trH2_filt.data
##############################################################
# calculate ARH-CF using subclass ARHcf of class CharcteristicFunction
arhcf = ARHcf(H_copy, cuttimes, tpredh, arhorder, tdeth, addnoise) # instance of ARHcf
##############################################################
# calculate AIC-ARH-CF using subclass AICcf of class CharacteristicFunction
# class needs stream object => build it
tr_arhaic = trH1_filt.copy()
tr_arhaic.data = arhcf.getCF()
H_copy[0].data = tr_arhaic.data
# calculate ARH-AIC-CF
arhaiccf = AICcf(H_copy, cuttimes, tpredh, 0, tdeth) # instance of AICcf
##############################################################
# get onset time from AIC-ARH-CF using subclass AICPicker of class AutoPicking
aicarhpick = AICPicker(arhaiccf, 1.5, TSNRarz, 4, 10, None, 0.1)
###############################################################
# get refined onset time from ARH-CF using class Picker
arhpick = PragPicker(arhcf, 1.5, TSNRarz, 2.5, 10, 0.1, 0.05, aicarhpick.getpick())
# get earliest and latest possible picks
arhELpick = EarlLatePicker(arhcf, 1.5, TSNRarz, None, 10, None, None, arhpick.getpick())
# create stream with 3 traces
# merge streams
AllC = read('%s' % wfefiles[i])
AllC += read('%s' % wfnfiles[i])
AllC += read('%s' % wfzfiles[i])
# filter and taper data
All1_filt = AllC[0].copy()
All2_filt = AllC[1].copy()
All3_filt = AllC[2].copy()
All1_filt.filter('bandpass', freqmin=bph[0], freqmax=bph[1], zerophase=False)
All2_filt.filter('bandpass', freqmin=bph[0], freqmax=bph[1], zerophase=False)
All3_filt.filter('bandpass', freqmin=bpz[0], freqmax=bpz[1], zerophase=False)
All1_filt.taper(max_percentage=0.05, type='hann')
All2_filt.taper(max_percentage=0.05, type='hann')
All3_filt.taper(max_percentage=0.05, type='hann')
AllC[0].data = All1_filt.data
AllC[1].data = All2_filt.data
AllC[2].data = All3_filt.data
# calculate AR3C-CF using subclass AR3Ccf of class CharacteristicFunction
ar3ccf = AR3Ccf(AllC, cuttimes, tpredz, arhorder, tdetz, addnoise) # instance of AR3Ccf
# get earliest and latest possible pick from initial ARH-pick
ar3cELpick = EarlLatePicker(ar3ccf, 1.5, TSNRarz, None, 10, None, None, arhpick.getpick())
##############################################################
if iplot:
# plot vertical trace
plt.figure()
tr = st[0]
tdata = np.arange(0, tr.stats.npts / tr.stats.sampling_rate, tr.stats.delta)
p1, = plt.plot(tdata, tr_filt.data / max(tr_filt.data), 'k')
p2, = plt.plot(hoscf.getTimeArray(), hoscf.getCF() / max(hoscf.getCF()), 'r')
p3, = plt.plot(aiccf.getTimeArray(), aiccf.getCF() / max(aiccf.getCF()), 'b')
p4, = plt.plot(arzcf.getTimeArray(), arzcf.getCF() / max(arzcf.getCF()), 'g')
p5, = plt.plot(araiccf.getTimeArray(), araiccf.getCF() / max(araiccf.getCF()), 'y')
plt.plot([aicpick.getpick(), aicpick.getpick()], [-1, 1], 'b--')
plt.plot([aicpick.getpick() - 0.5, aicpick.getpick() + 0.5], [1, 1], 'b')
plt.plot([aicpick.getpick() - 0.5, aicpick.getpick() + 0.5], [-1, -1], 'b')
plt.plot([hospick.getpick(), hospick.getpick()], [-1.3, 1.3], 'r', linewidth=2)
plt.plot([hospick.getpick() - 0.5, hospick.getpick() + 0.5], [1.3, 1.3], 'r')
plt.plot([hospick.getpick() - 0.5, hospick.getpick() + 0.5], [-1.3, -1.3], 'r')
plt.plot([hosELpick.getLpick(), hosELpick.getLpick()], [-1.1, 1.1], 'r--')
plt.plot([hosELpick.getEpick(), hosELpick.getEpick()], [-1.1, 1.1], 'r--')
plt.plot([aicarzpick.getpick(), aicarzpick.getpick()], [-1.2, 1.2], 'y', linewidth=2)
plt.plot([aicarzpick.getpick() - 0.5, aicarzpick.getpick() + 0.5], [1.2, 1.2], 'y')
plt.plot([aicarzpick.getpick() - 0.5, aicarzpick.getpick() + 0.5], [-1.2, -1.2], 'y')
plt.plot([arzpick.getpick(), arzpick.getpick()], [-1.4, 1.4], 'g', linewidth=2)
plt.plot([arzpick.getpick() - 0.5, arzpick.getpick() + 0.5], [1.4, 1.4], 'g')
plt.plot([arzpick.getpick() - 0.5, arzpick.getpick() + 0.5], [-1.4, -1.4], 'g')
plt.plot([arzELpick.getLpick(), arzELpick.getLpick()], [-1.2, 1.2], 'g--')
plt.plot([arzELpick.getEpick(), arzELpick.getEpick()], [-1.2, 1.2], 'g--')
plt.yticks([])
plt.ylim([-1.5, 1.5])
plt.xlabel('Time [s]')
plt.ylabel('Normalized Counts')
plt.title('%s, %s, CF-SNR=%7.2f, CF-Slope=%12.2f' % (tr.stats.station, \
tr.stats.channel, aicpick.getSNR(),
aicpick.getSlope()))
plt.suptitle(tr.stats.starttime)
plt.legend([p1, p2, p3, p4, p5], ['Data', 'HOS-CF', 'HOSAIC-CF', 'ARZ-CF', 'ARZAIC-CF'])
# plot horizontal traces
plt.figure(2)
plt.subplot(2, 1, 1)
tsteph = tpredh / 4
th1data = np.arange(0, trH1_filt.stats.npts / trH1_filt.stats.sampling_rate, trH1_filt.stats.delta)
th2data = np.arange(0, trH2_filt.stats.npts / trH2_filt.stats.sampling_rate, trH2_filt.stats.delta)
tarhcf = np.arange(0, len(arhcf.getCF()) * tsteph, tsteph) + cuttimes[0] + tdeth + tpredh
p21, = plt.plot(th1data, trH1_filt.data / max(trH1_filt.data), 'k')
p22, = plt.plot(arhcf.getTimeArray(), arhcf.getCF() / max(arhcf.getCF()), 'r')
p23, = plt.plot(arhaiccf.getTimeArray(), arhaiccf.getCF() / max(arhaiccf.getCF()))
plt.plot([aicarhpick.getpick(), aicarhpick.getpick()], [-1, 1], 'b')
plt.plot([aicarhpick.getpick() - 0.5, aicarhpick.getpick() + 0.5], [1, 1], 'b')
plt.plot([aicarhpick.getpick() - 0.5, aicarhpick.getpick() + 0.5], [-1, -1], 'b')
plt.plot([arhpick.getpick(), arhpick.getpick()], [-1, 1], 'r')
plt.plot([arhpick.getpick() - 0.5, arhpick.getpick() + 0.5], [1, 1], 'r')
plt.plot([arhpick.getpick() - 0.5, arhpick.getpick() + 0.5], [-1, -1], 'r')
plt.plot([arhELpick.getLpick(), arhELpick.getLpick()], [-0.8, 0.8], 'r--')
plt.plot([arhELpick.getEpick(), arhELpick.getEpick()], [-0.8, 0.8], 'r--')
plt.plot([arhpick.getpick() + arhELpick.getPickError(), arhpick.getpick() + arhELpick.getPickError()], \
[-0.2, 0.2], 'r--')
plt.plot([arhpick.getpick() - arhELpick.getPickError(), arhpick.getpick() - arhELpick.getPickError()], \
[-0.2, 0.2], 'r--')
plt.yticks([])
plt.ylim([-1.5, 1.5])
plt.ylabel('Normalized Counts')
plt.title([trH1_filt.stats.station, trH1_filt.stats.channel])
plt.suptitle(trH1_filt.stats.starttime)
plt.legend([p21, p22, p23], ['Data', 'ARH-CF', 'ARHAIC-CF'])
plt.subplot(2, 1, 2)
plt.plot(th2data, trH2_filt.data / max(trH2_filt.data), 'k')
plt.plot(arhcf.getTimeArray(), arhcf.getCF() / max(arhcf.getCF()), 'r')
plt.plot(arhaiccf.getTimeArray(), arhaiccf.getCF() / max(arhaiccf.getCF()))
plt.plot([aicarhpick.getpick(), aicarhpick.getpick()], [-1, 1], 'b')
plt.plot([aicarhpick.getpick() - 0.5, aicarhpick.getpick() + 0.5], [1, 1], 'b')
plt.plot([aicarhpick.getpick() - 0.5, aicarhpick.getpick() + 0.5], [-1, -1], 'b')
plt.plot([arhpick.getpick(), arhpick.getpick()], [-1, 1], 'r')
plt.plot([arhpick.getpick() - 0.5, arhpick.getpick() + 0.5], [1, 1], 'r')
plt.plot([arhpick.getpick() - 0.5, arhpick.getpick() + 0.5], [-1, -1], 'r')
plt.plot([arhELpick.getLpick(), arhELpick.getLpick()], [-0.8, 0.8], 'r--')
plt.plot([arhELpick.getEpick(), arhELpick.getEpick()], [-0.8, 0.8], 'r--')
plt.plot([arhpick.getpick() + arhELpick.getPickError(), arhpick.getpick() + arhELpick.getPickError()], \
[-0.2, 0.2], 'r--')
plt.plot([arhpick.getpick() - arhELpick.getPickError(), arhpick.getpick() - arhELpick.getPickError()], \
[-0.2, 0.2], 'r--')
plt.title([trH2_filt.stats.station, trH2_filt.stats.channel])
plt.yticks([])
plt.ylim([-1.5, 1.5])
plt.xlabel('Time [s]')
plt.ylabel('Normalized Counts')
# plot 3-component window
plt.figure(3)
plt.subplot(3, 1, 1)
p31, = plt.plot(tdata, tr_filt.data / max(tr_filt.data), 'k')
p32, = plt.plot(ar3ccf.getTimeArray(), ar3ccf.getCF() / max(ar3ccf.getCF()), 'r')
plt.plot([arhpick.getpick(), arhpick.getpick()], [-1, 1], 'b')
plt.plot([arhpick.getpick() - 0.5, arhpick.getpick() + 0.5], [-1, -1], 'b')
plt.plot([arhpick.getpick() - 0.5, arhpick.getpick() + 0.5], [1, 1], 'b')
plt.plot([ar3cELpick.getLpick(), ar3cELpick.getLpick()], [-0.8, 0.8], 'b--')
plt.plot([ar3cELpick.getEpick(), ar3cELpick.getEpick()], [-0.8, 0.8], 'b--')
plt.yticks([])
plt.xticks([])
plt.ylabel('Normalized Counts')
plt.title([tr.stats.station, tr.stats.channel])
plt.suptitle(trH1_filt.stats.starttime)
plt.legend([p31, p32], ['Data', 'AR3C-CF'])
plt.subplot(3, 1, 2)
plt.plot(th1data, trH1_filt.data / max(trH1_filt.data), 'k')
plt.plot(ar3ccf.getTimeArray(), ar3ccf.getCF() / max(ar3ccf.getCF()), 'r')
plt.plot([arhpick.getpick(), arhpick.getpick()], [-1, 1], 'b')
plt.plot([arhpick.getpick() - 0.5, arhpick.getpick() + 0.5], [-1, -1], 'b')
plt.plot([arhpick.getpick() - 0.5, arhpick.getpick() + 0.5], [1, 1], 'b')
plt.plot([ar3cELpick.getLpick(), ar3cELpick.getLpick()], [-0.8, 0.8], 'b--')
plt.plot([ar3cELpick.getEpick(), ar3cELpick.getEpick()], [-0.8, 0.8], 'b--')
plt.yticks([])
plt.xticks([])
plt.ylabel('Normalized Counts')
plt.title([trH1_filt.stats.station, trH1_filt.stats.channel])
plt.subplot(3, 1, 3)
plt.plot(th2data, trH2_filt.data / max(trH2_filt.data), 'k')
plt.plot(ar3ccf.getTimeArray(), ar3ccf.getCF() / max(ar3ccf.getCF()), 'r')
plt.plot([arhpick.getpick(), arhpick.getpick()], [-1, 1], 'b')
plt.plot([arhpick.getpick() - 0.5, arhpick.getpick() + 0.5], [-1, -1], 'b')
plt.plot([arhpick.getpick() - 0.5, arhpick.getpick() + 0.5], [1, 1], 'b')
plt.plot([ar3cELpick.getLpick(), ar3cELpick.getLpick()], [-0.8, 0.8], 'b--')
plt.plot([ar3cELpick.getEpick(), ar3cELpick.getEpick()], [-0.8, 0.8], 'b--')
plt.yticks([])
plt.ylabel('Normalized Counts')
plt.title([trH2_filt.stats.station, trH2_filt.stats.channel])
plt.xlabel('Time [s]')
plt.show()
raw_input()
plt.close()
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('--project', type=str, help='project name (e.g. Insheim)')
parser.add_argument('--database', type=str, help='event data base (e.g. 2014.09_Insheim)')
parser.add_argument('--event', type=str, help='event ID (e.g. e0010.015.14)')
parser.add_argument('--iplot', help='anything, if set, figure occurs')
parser.add_argument('--station', type=str, help='Station ID (e.g. INS3) (optional)')
args = parser.parse_args()
run_makeCF(args.project, args.database, args.event, args.iplot, args.station)
-8
View File
@@ -1,8 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from pylot.core.util.pdf import ProbabilityDensityFunction
pdf = ProbabilityDensityFunction.from_pick(0.34, 0.5, 0.54, type='exp')
pdf2 = ProbabilityDensityFunction.from_pick(0.34, 0.5, 0.54, type='exp')
diff = pdf - pdf2
-16
View File
@@ -1,16 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import argparse
import numpy
from pylot.core.pick.utils import getnoisewin
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument('--t', type=numpy.array, help='numpy array of time stamps')
parser.add_argument('--t1', type=float, help='time from which relativ to it noise window is extracted')
parser.add_argument('--tnoise', type=float, help='length of time window [s] for noise part extraction')
parser.add_argument('--tgap', type=float, help='safety gap between signal (t1=onset) and noise')
args = parser.parse_args()
getnoisewin(args.t, args.t1, args.tnoise, args.tgap)
-29
View File
@@ -1,29 +0,0 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
Created Mar 2015
Transcription of the rezipe of Diehl et al. (2009) for consistent phase
picking. For a given inital (the most likely) pick, the corresponding earliest
and latest possible pick is calculated based on noise measurements in front of
the most likely pick and signal wavelength derived from zero crossings.
:author: Ludger Kueperkoch / MAGS2 EP3 working group
"""
import argparse
import obspy
from pylot.core.pick.utils import earllatepicker
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument('--X', type=~obspy.core.stream.Stream,
help='time series (seismogram) read with obspy module read')
parser.add_argument('--nfac', type=int,
help='(noise factor), nfac times noise level to calculate latest possible pick')
parser.add_argument('--TSNR', type=tuple, help='length of time windows around pick used to determine SNR \
[s] (Tnoise, Tgap, Tsignal)')
parser.add_argument('--Pick1', type=float, help='Onset time of most likely pick')
parser.add_argument('--iplot', type=int, help='if set, figure no. iplot occurs')
args = parser.parse_args()
earllatepicker(args.X, args.nfac, args.TSNR, args.Pick1, args.iplot)
-25
View File
@@ -1,25 +0,0 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
Created Mar 2015
Function to derive first motion (polarity) for given phase onset based on zero crossings.
:author: MAGS2 EP3 working group / Ludger Kueperkoch
"""
import argparse
import obspy
from pylot.core.pick.utils import fmpicker
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument('--Xraw', type=obspy.core.stream.Stream,
help='unfiltered time series (seismogram) read with obspy module read')
parser.add_argument('--Xfilt', type=obspy.core.stream.Stream,
help='filtered time series (seismogram) read with obspy module read')
parser.add_argument('--pickwin', type=float, help='length of pick window [s] for first motion determination')
parser.add_argument('--Pick', type=float, help='Onset time of most likely pick')
parser.add_argument('--iplot', type=int, help='if set, figure no. iplot occurs')
args = parser.parse_args()
fmpicker(args.Xraw, args.Xfilt, args.pickwin, args.Pick, args.iplot)
-41
View File
@@ -1,41 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import argparse
from pylot.core.io.phases import reassess_pilot_db
from pylot.core.util.version import get_git_version as _getVersionString
__version__ = _getVersionString()
__author__ = 'S. Wehling-Benatelli'
if __name__ == '__main__':
parser = argparse.ArgumentParser(
description='reassess old PILOT event data base in terms of consistent '
'automatic uncertainty estimation',
epilog='Script written by {author} belonging to PyLoT version'
' {version}\n'.format(author=__author__,
version=__version__)
)
parser.add_argument(
'root', type=str, help='specifies the root directory'
)
parser.add_argument(
'db', type=str, help='specifies the database name'
)
parser.add_argument(
'--output', '-o', type=str, help='path to the output directory',
dest='output'
)
parser.add_argument(
'--parameterfile', '-p', type=str,
help='full path to the parameterfile', dest='parfile'
)
parser.add_argument(
'--verbosity', '-v', action='count', help='increase output verbosity',
default=0, dest='verbosity'
)
args = parser.parse_args()
reassess_pilot_db(args.root, args.db, args.output, args.parfile, args.verbosity)
-38
View File
@@ -1,38 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import argparse
from pylot.core.io.phases import reassess_pilot_event
from pylot.core.util.version import get_git_version as _getVersionString
__version__ = _getVersionString()
__author__ = 'S. Wehling-Benatelli'
if __name__ == '__main__':
parser = argparse.ArgumentParser(
description='reassess old PILOT event data in terms of consistent '
'automatic uncertainty estimation',
epilog='Script written by {author} belonging to PyLoT version'
' {version}\n'.format(author=__author__,
version=__version__)
)
parser.add_argument(
'root', type=str, help='specifies the root directory'
)
parser.add_argument(
'db', type=str, help='specifies the database name'
)
parser.add_argument(
'id', type=str, help='PILOT event identifier'
)
parser.add_argument(
'--output', '-o', type=str, help='path to the output directory', dest='output'
)
parser.add_argument(
'--parameterfile', '-p', type=str, help='full path to the parameterfile', dest='parfile'
)
args = parser.parse_args()
reassess_pilot_event(args.root, args.db, args.id, args.output, args.parfile)
-15
View File
@@ -1,15 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import argparse
import numpy
from pylot.core.pick.utils import getsignalwin
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument('--t', type=numpy.array, help='numpy array of time stamps')
parser.add_argument('--t1', type=float, help='time from which relativ to it signal window is extracted')
parser.add_argument('--tsignal', type=float, help='length of time window [s] for signal part extraction')
args = parser.parse_args()
getsignalwin(args.t, args.t1, args.tsignal)
-32
View File
@@ -1,32 +0,0 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
Created Mar/Apr 2015
Function to calculate SNR of certain part of seismogram relative
to given time. Returns SNR and SNR [dB].
:author: Ludger Kueperkoch /MAGS EP3 working group
"""
import argparse
import obspy
from pylot.core.pick.utils import getSNR
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument('--data', '-d', type=obspy.core.stream.Stream,
help='time series (seismogram) read with obspy module '
'read',
dest='data')
parser.add_argument('--tsnr', '-s', type=tuple,
help='length of time windows around pick used to '
'determine SNR [s] (Tnoise, Tgap, Tsignal)',
dest='tsnr')
parser.add_argument('--time', '-t', type=float,
help='initial time from which noise and signal windows '
'are calculated',
dest='time')
args = parser.parse_args()
print
getSNR(args.data, args.tsnr, args.time)
-314
View File
@@ -1,314 +0,0 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
Script to run autoPyLoT-script "run_makeCF.py".
Only for test purposes!
"""
import argparse
import glob
from obspy.core import read
from pylot.core.pick.utils import *
def run_makeCF(project, database, event, iplot, station=None):
# parameters for CF calculation
t2 = 7 # length of moving window for HOS calculation [sec]
p = 4 # order of HOS
cuttimes = [10, 50] # start and end time for CF calculation
bpz = [2, 30] # corner frequencies of bandpass filter, vertical component
bph = [2, 15] # corner frequencies of bandpass filter, horizontal components
tdetz = 1.2 # length of AR-determination window [sec], vertical component
tdeth = 0.8 # length of AR-determination window [sec], horizontal components
tpredz = 0.4 # length of AR-prediction window [sec], vertical component
tpredh = 0.4 # length of AR-prediction window [sec], horizontal components
addnoise = 0.001 # add noise to seismogram for stable AR prediction
arzorder = 2 # chosen order of AR process, vertical component
arhorder = 4 # chosen order of AR process, horizontal components
TSNRhos = [5, 0.5, 1, .6] # window lengths [s] for calculating SNR for earliest/latest pick and quality assessment
# from HOS-CF [noise window, safety gap, signal window, slope determination window]
TSNRarz = [5, 0.5, 1, 1.0] # window lengths [s] for calculating SNR for earliest/lates pick and quality assessment
# from ARZ-CF
# get waveform data
if station:
dpz = '/DATA/%s/EVENT_DATA/LOCAL/%s/%s/%s*HZ.msd' % (project, database, event, station)
dpe = '/DATA/%s/EVENT_DATA/LOCAL/%s/%s/%s*HE.msd' % (project, database, event, station)
dpn = '/DATA/%s/EVENT_DATA/LOCAL/%s/%s/%s*HN.msd' % (project, database, event, station)
# dpz = '/DATA/%s/EVENT_DATA/LOCAL/%s/%s/%s*_z.gse' % (project, database, event, station)
# dpe = '/DATA/%s/EVENT_DATA/LOCAL/%s/%s/%s*_e.gse' % (project, database, event, station)
# dpn = '/DATA/%s/EVENT_DATA/LOCAL/%s/%s/%s*_n.gse' % (project, database, event, station)
else:
dpz = '/DATA/%s/EVENT_DATA/LOCAL/%s/%s/*HZ.msd' % (project, database, event)
dpe = '/DATA/%s/EVENT_DATA/LOCAL/%s/%s/*HE.msd' % (project, database, event)
dpn = '/DATA/%s/EVENT_DATA/LOCAL/%s/%s/*HN.msd' % (project, database, event)
wfzfiles = glob.glob(dpz)
wfefiles = glob.glob(dpe)
wfnfiles = glob.glob(dpn)
if wfzfiles:
for i in range(len(wfzfiles)):
print
'Vertical component data found ...'
print
wfzfiles[i]
st = read('%s' % wfzfiles[i])
st_copy = st.copy()
# filter and taper data
tr_filt = st[0].copy()
tr_filt.filter('bandpass', freqmin=bpz[0], freqmax=bpz[1], zerophase=False)
tr_filt.taper(max_percentage=0.05, type='hann')
st_copy[0].data = tr_filt.data
##############################################################
# calculate HOS-CF using subclass HOScf of class CharacteristicFunction
hoscf = HOScf(st_copy, cuttimes, t2, p) # instance of HOScf
##############################################################
# calculate AIC-HOS-CF using subclass AICcf of class CharacteristicFunction
# class needs stream object => build it
tr_aic = tr_filt.copy()
tr_aic.data = hoscf.getCF()
st_copy[0].data = tr_aic.data
aiccf = AICcf(st_copy, cuttimes) # instance of AICcf
##############################################################
# get prelimenary onset time from AIC-HOS-CF using subclass AICPicker of class AutoPicking
aicpick = AICPicker(aiccf, TSNRhos, 3, 10, None, 0.1)
##############################################################
# get refined onset time from HOS-CF using class Picker
hospick = PragPicker(hoscf, TSNRhos, 2, 10, 0.001, 0.2, aicpick.getpick())
#############################################################
# get earliest and latest possible picks
st_copy[0].data = tr_filt.data
[lpickhos, epickhos, pickerrhos] = earllatepicker(st_copy, 1.5, TSNRhos, hospick.getpick(), 10)
#############################################################
# get SNR
[SNR, SNRdB] = getSNR(st_copy, TSNRhos, hospick.getpick())
print
'SNR:', SNR, 'SNR[dB]:', SNRdB
##########################################################
# get first motion of onset
hosfm = fmpicker(st, st_copy, 0.2, hospick.getpick(), 11)
##############################################################
# calculate ARZ-CF using subclass ARZcf of class CharcteristicFunction
arzcf = ARZcf(st, cuttimes, tpredz, arzorder, tdetz, addnoise) # instance of ARZcf
##############################################################
# calculate AIC-ARZ-CF using subclass AICcf of class CharacteristicFunction
# class needs stream object => build it
tr_arzaic = tr_filt.copy()
tr_arzaic.data = arzcf.getCF()
st_copy[0].data = tr_arzaic.data
araiccf = AICcf(st_copy, cuttimes, tpredz, 0, tdetz) # instance of AICcf
##############################################################
# get onset time from AIC-ARZ-CF using subclass AICPicker of class AutoPicking
aicarzpick = AICPicker(araiccf, TSNRarz, 2, 10, None, 0.1)
##############################################################
# get refined onset time from ARZ-CF using class Picker
arzpick = PragPicker(arzcf, TSNRarz, 2.0, 10, 0.1, 0.05, aicarzpick.getpick())
# get earliest and latest possible picks
st_copy[0].data = tr_filt.data
[lpickarz, epickarz, pickerrarz] = earllatepicker(st_copy, 1.5, TSNRarz, arzpick.getpick(), 10)
elif not wfzfiles:
print
'No vertical component data found!'
if wfefiles and wfnfiles:
for i in range(len(wfefiles)):
print
'Horizontal component data found ...'
print
wfefiles[i]
print
wfnfiles[i]
# merge streams
H = read('%s' % wfefiles[i])
H += read('%s' % wfnfiles[i])
H_copy = H.copy()
# filter and taper data
trH1_filt = H[0].copy()
trH2_filt = H[1].copy()
trH1_filt.filter('bandpass', freqmin=bph[0], freqmax=bph[1], zerophase=False)
trH2_filt.filter('bandpass', freqmin=bph[0], freqmax=bph[1], zerophase=False)
trH1_filt.taper(max_percentage=0.05, type='hann')
trH2_filt.taper(max_percentage=0.05, type='hann')
H_copy[0].data = trH1_filt.data
H_copy[1].data = trH2_filt.data
##############################################################
# calculate ARH-CF using subclass ARHcf of class CharcteristicFunction
arhcf = ARHcf(H_copy, cuttimes, tpredh, arhorder, tdeth, addnoise) # instance of ARHcf
##############################################################
# calculate AIC-ARH-CF using subclass AICcf of class CharacteristicFunction
# class needs stream object => build it
tr_arhaic = trH1_filt.copy()
tr_arhaic.data = arhcf.getCF()
H_copy[0].data = tr_arhaic.data
# calculate ARH-AIC-CF
arhaiccf = AICcf(H_copy, cuttimes, tpredh, 0, tdeth) # instance of AICcf
##############################################################
# get onset time from AIC-ARH-CF using subclass AICPicker of class AutoPicking
aicarhpick = AICPicker(arhaiccf, TSNRarz, 4, 10, None, 0.1)
###############################################################
# get refined onset time from ARH-CF using class Picker
arhpick = PragPicker(arhcf, TSNRarz, 2.5, 10, 0.1, 0.05, aicarhpick.getpick())
# get earliest and latest possible picks
H_copy[0].data = trH1_filt.data
[lpickarh1, epickarh1, pickerrarh1] = earllatepicker(H_copy, 1.5, TSNRarz, arhpick.getpick(), 10)
H_copy[0].data = trH2_filt.data
[lpickarh2, epickarh2, pickerrarh2] = earllatepicker(H_copy, 1.5, TSNRarz, arhpick.getpick(), 10)
# get earliest pick of both earliest possible picks
epick = [epickarh1, epickarh2]
lpick = [lpickarh1, lpickarh2]
pickerr = [pickerrarh1, pickerrarh2]
ipick = np.argmin([epickarh1, epickarh2])
epickarh = epick[ipick]
lpickarh = lpick[ipick]
pickerrarh = pickerr[ipick]
# create stream with 3 traces
# merge streams
AllC = read('%s' % wfefiles[i])
AllC += read('%s' % wfnfiles[i])
AllC += read('%s' % wfzfiles[i])
# filter and taper data
All1_filt = AllC[0].copy()
All2_filt = AllC[1].copy()
All3_filt = AllC[2].copy()
All1_filt.filter('bandpass', freqmin=bph[0], freqmax=bph[1], zerophase=False)
All2_filt.filter('bandpass', freqmin=bph[0], freqmax=bph[1], zerophase=False)
All3_filt.filter('bandpass', freqmin=bpz[0], freqmax=bpz[1], zerophase=False)
All1_filt.taper(max_percentage=0.05, type='hann')
All2_filt.taper(max_percentage=0.05, type='hann')
All3_filt.taper(max_percentage=0.05, type='hann')
AllC[0].data = All1_filt.data
AllC[1].data = All2_filt.data
AllC[2].data = All3_filt.data
# calculate AR3C-CF using subclass AR3Ccf of class CharacteristicFunction
ar3ccf = AR3Ccf(AllC, cuttimes, tpredz, arhorder, tdetz, addnoise) # instance of AR3Ccf
##############################################################
if iplot:
# plot vertical trace
plt.figure()
tr = st[0]
tdata = np.arange(0, tr.stats.npts / tr.stats.sampling_rate, tr.stats.delta)
p1, = plt.plot(tdata, tr_filt.data / max(tr_filt.data), 'k')
p2, = plt.plot(hoscf.getTimeArray(), hoscf.getCF() / max(hoscf.getCF()), 'r')
p3, = plt.plot(aiccf.getTimeArray(), aiccf.getCF() / max(aiccf.getCF()), 'b')
p4, = plt.plot(arzcf.getTimeArray(), arzcf.getCF() / max(arzcf.getCF()), 'g')
p5, = plt.plot(araiccf.getTimeArray(), araiccf.getCF() / max(araiccf.getCF()), 'y')
plt.plot([aicpick.getpick(), aicpick.getpick()], [-1, 1], 'b--')
plt.plot([aicpick.getpick() - 0.5, aicpick.getpick() + 0.5], [1, 1], 'b')
plt.plot([aicpick.getpick() - 0.5, aicpick.getpick() + 0.5], [-1, -1], 'b')
plt.plot([hospick.getpick(), hospick.getpick()], [-1.3, 1.3], 'r', linewidth=2)
plt.plot([hospick.getpick() - 0.5, hospick.getpick() + 0.5], [1.3, 1.3], 'r')
plt.plot([hospick.getpick() - 0.5, hospick.getpick() + 0.5], [-1.3, -1.3], 'r')
plt.plot([lpickhos, lpickhos], [-1.1, 1.1], 'r--')
plt.plot([epickhos, epickhos], [-1.1, 1.1], 'r--')
plt.plot([aicarzpick.getpick(), aicarzpick.getpick()], [-1.2, 1.2], 'y', linewidth=2)
plt.plot([aicarzpick.getpick() - 0.5, aicarzpick.getpick() + 0.5], [1.2, 1.2], 'y')
plt.plot([aicarzpick.getpick() - 0.5, aicarzpick.getpick() + 0.5], [-1.2, -1.2], 'y')
plt.plot([arzpick.getpick(), arzpick.getpick()], [-1.4, 1.4], 'g', linewidth=2)
plt.plot([arzpick.getpick() - 0.5, arzpick.getpick() + 0.5], [1.4, 1.4], 'g')
plt.plot([arzpick.getpick() - 0.5, arzpick.getpick() + 0.5], [-1.4, -1.4], 'g')
plt.plot([lpickarz, lpickarz], [-1.2, 1.2], 'g--')
plt.plot([epickarz, epickarz], [-1.2, 1.2], 'g--')
plt.yticks([])
plt.ylim([-1.5, 1.5])
plt.xlabel('Time [s]')
plt.ylabel('Normalized Counts')
plt.title('%s, %s, CF-SNR=%7.2f, CF-Slope=%12.2f' % (tr.stats.station,
tr.stats.channel, aicpick.getSNR(),
aicpick.getSlope()))
plt.suptitle(tr.stats.starttime)
plt.legend([p1, p2, p3, p4, p5], ['Data', 'HOS-CF', 'HOSAIC-CF', 'ARZ-CF', 'ARZAIC-CF'])
# plot horizontal traces
plt.figure(2)
plt.subplot(2, 1, 1)
tsteph = tpredh / 4
th1data = np.arange(0, trH1_filt.stats.npts / trH1_filt.stats.sampling_rate, trH1_filt.stats.delta)
th2data = np.arange(0, trH2_filt.stats.npts / trH2_filt.stats.sampling_rate, trH2_filt.stats.delta)
tarhcf = np.arange(0, len(arhcf.getCF()) * tsteph, tsteph) + cuttimes[0] + tdeth + tpredh
p21, = plt.plot(th1data, trH1_filt.data / max(trH1_filt.data), 'k')
p22, = plt.plot(arhcf.getTimeArray(), arhcf.getCF() / max(arhcf.getCF()), 'r')
p23, = plt.plot(arhaiccf.getTimeArray(), arhaiccf.getCF() / max(arhaiccf.getCF()))
plt.plot([aicarhpick.getpick(), aicarhpick.getpick()], [-1, 1], 'b')
plt.plot([aicarhpick.getpick() - 0.5, aicarhpick.getpick() + 0.5], [1, 1], 'b')
plt.plot([aicarhpick.getpick() - 0.5, aicarhpick.getpick() + 0.5], [-1, -1], 'b')
plt.plot([arhpick.getpick(), arhpick.getpick()], [-1, 1], 'r')
plt.plot([arhpick.getpick() - 0.5, arhpick.getpick() + 0.5], [1, 1], 'r')
plt.plot([arhpick.getpick() - 0.5, arhpick.getpick() + 0.5], [-1, -1], 'r')
plt.plot([lpickarh, lpickarh], [-0.8, 0.8], 'r--')
plt.plot([epickarh, epickarh], [-0.8, 0.8], 'r--')
plt.plot([arhpick.getpick() + pickerrarh, arhpick.getpick() + pickerrarh], [-0.2, 0.2], 'r--')
plt.plot([arhpick.getpick() - pickerrarh, arhpick.getpick() - pickerrarh], [-0.2, 0.2], 'r--')
plt.yticks([])
plt.ylim([-1.5, 1.5])
plt.ylabel('Normalized Counts')
plt.title([trH1_filt.stats.station, trH1_filt.stats.channel])
plt.suptitle(trH1_filt.stats.starttime)
plt.legend([p21, p22, p23], ['Data', 'ARH-CF', 'ARHAIC-CF'])
plt.subplot(2, 1, 2)
plt.plot(th2data, trH2_filt.data / max(trH2_filt.data), 'k')
plt.plot(arhcf.getTimeArray(), arhcf.getCF() / max(arhcf.getCF()), 'r')
plt.plot(arhaiccf.getTimeArray(), arhaiccf.getCF() / max(arhaiccf.getCF()))
plt.plot([aicarhpick.getpick(), aicarhpick.getpick()], [-1, 1], 'b')
plt.plot([aicarhpick.getpick() - 0.5, aicarhpick.getpick() + 0.5], [1, 1], 'b')
plt.plot([aicarhpick.getpick() - 0.5, aicarhpick.getpick() + 0.5], [-1, -1], 'b')
plt.plot([arhpick.getpick(), arhpick.getpick()], [-1, 1], 'r')
plt.plot([arhpick.getpick() - 0.5, arhpick.getpick() + 0.5], [1, 1], 'r')
plt.plot([arhpick.getpick() - 0.5, arhpick.getpick() + 0.5], [-1, -1], 'r')
plt.plot([lpickarh, lpickarh], [-0.8, 0.8], 'r--')
plt.plot([epickarh, epickarh], [-0.8, 0.8], 'r--')
plt.plot([arhpick.getpick() + pickerrarh, arhpick.getpick() + pickerrarh], [-0.2, 0.2], 'r--')
plt.plot([arhpick.getpick() - pickerrarh, arhpick.getpick() - pickerrarh], [-0.2, 0.2], 'r--')
plt.title([trH2_filt.stats.station, trH2_filt.stats.channel])
plt.yticks([])
plt.ylim([-1.5, 1.5])
plt.xlabel('Time [s]')
plt.ylabel('Normalized Counts')
# plot 3-component window
plt.figure(3)
plt.subplot(3, 1, 1)
p31, = plt.plot(tdata, tr_filt.data / max(tr_filt.data), 'k')
p32, = plt.plot(ar3ccf.getTimeArray(), ar3ccf.getCF() / max(ar3ccf.getCF()), 'r')
plt.plot([arhpick.getpick(), arhpick.getpick()], [-1, 1], 'b')
plt.plot([arhpick.getpick() - 0.5, arhpick.getpick() + 0.5], [-1, -1], 'b')
plt.plot([arhpick.getpick() - 0.5, arhpick.getpick() + 0.5], [1, 1], 'b')
plt.yticks([])
plt.xticks([])
plt.ylabel('Normalized Counts')
plt.title([tr.stats.station, tr.stats.channel])
plt.suptitle(trH1_filt.stats.starttime)
plt.legend([p31, p32], ['Data', 'AR3C-CF'])
plt.subplot(3, 1, 2)
plt.plot(th1data, trH1_filt.data / max(trH1_filt.data), 'k')
plt.plot(ar3ccf.getTimeArray(), ar3ccf.getCF() / max(ar3ccf.getCF()), 'r')
plt.plot([arhpick.getpick(), arhpick.getpick()], [-1, 1], 'b')
plt.plot([arhpick.getpick() - 0.5, arhpick.getpick() + 0.5], [-1, -1], 'b')
plt.plot([arhpick.getpick() - 0.5, arhpick.getpick() + 0.5], [1, 1], 'b')
plt.yticks([])
plt.xticks([])
plt.ylabel('Normalized Counts')
plt.title([trH1_filt.stats.station, trH1_filt.stats.channel])
plt.subplot(3, 1, 3)
plt.plot(th2data, trH2_filt.data / max(trH2_filt.data), 'k')
plt.plot(ar3ccf.getTimeArray(), ar3ccf.getCF() / max(ar3ccf.getCF()), 'r')
plt.plot([arhpick.getpick(), arhpick.getpick()], [-1, 1], 'b')
plt.plot([arhpick.getpick() - 0.5, arhpick.getpick() + 0.5], [-1, -1], 'b')
plt.plot([arhpick.getpick() - 0.5, arhpick.getpick() + 0.5], [1, 1], 'b')
plt.yticks([])
plt.ylabel('Normalized Counts')
plt.title([trH2_filt.stats.station, trH2_filt.stats.channel])
plt.xlabel('Time [s]')
plt.show()
raw_input()
plt.close()
parser = argparse.ArgumentParser()
parser.add_argument('--project', type=str, help='project name (e.g. Insheim)')
parser.add_argument('--database', type=str, help='event data base (e.g. 2014.09_Insheim)')
parser.add_argument('--event', type=str, help='event ID (e.g. e0010.015.14)')
parser.add_argument('--iplot', help='anything, if set, figure occurs')
parser.add_argument('--station', type=str, help='Station ID (e.g. INS3) (optional)')
args = parser.parse_args()
run_makeCF(args.project, args.database, args.event, args.iplot, args.station)
+2 -2
View File
@@ -4,11 +4,11 @@ from distutils.core import setup
setup(
name='PyLoT',
version='0.1a1',
version='0.2',
packages=['pylot', 'pylot.core', 'pylot.core.loc', 'pylot.core.pick',
'pylot.core.io', 'pylot.core.util', 'pylot.core.active',
'pylot.core.analysis', 'pylot.testing'],
requires=['obspy', 'PySide'],
requires=['obspy', 'PySide', 'matplotlib', 'numpy'],
url='dummy',
license='LGPLv3',
author='Sebastian Wehling-Benatelli',