[refactor] automatic code reformatting (Pycharm)
This commit is contained in:
parent
79f3d40714
commit
e35d5d6df9
100
PyLoT.py
100
PyLoT.py
@ -24,18 +24,16 @@ https://www.iconfinder.com/iconsets/flavour
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import matplotlib
|
import json
|
||||||
import os
|
import os
|
||||||
import platform
|
import platform
|
||||||
import shutil
|
import shutil
|
||||||
import sys
|
import sys
|
||||||
import copy
|
|
||||||
|
|
||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
import json
|
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
|
import matplotlib
|
||||||
|
|
||||||
matplotlib.use('Qt5Agg')
|
matplotlib.use('Qt5Agg')
|
||||||
|
|
||||||
from PySide2 import QtGui, QtCore, QtWidgets
|
from PySide2 import QtGui, QtCore, QtWidgets
|
||||||
@ -44,8 +42,8 @@ from PySide2.QtCore import QCoreApplication, QSettings, Signal, QFile, \
|
|||||||
from PySide2.QtGui import QIcon, QKeySequence, QPixmap, QStandardItem
|
from PySide2.QtGui import QIcon, QKeySequence, QPixmap, QStandardItem
|
||||||
from PySide2.QtWidgets import QMainWindow, QInputDialog, QFileDialog, \
|
from PySide2.QtWidgets import QMainWindow, QInputDialog, QFileDialog, \
|
||||||
QWidget, QHBoxLayout, QVBoxLayout, QStyle, QLabel, QFrame, QAction, \
|
QWidget, QHBoxLayout, QVBoxLayout, QStyle, QLabel, QFrame, QAction, \
|
||||||
QDialog, QErrorMessage, QApplication, QMessageBox, QSplashScreen, \
|
QDialog, QApplication, QMessageBox, QSplashScreen, \
|
||||||
QActionGroup, QListWidget, QLineEdit, QListView, QAbstractItemView, \
|
QActionGroup, QListWidget, QListView, QAbstractItemView, \
|
||||||
QTreeView, QComboBox, QTabWidget, QPushButton, QGridLayout, QTableWidgetItem, QTableWidget
|
QTreeView, QComboBox, QTabWidget, QPushButton, QGridLayout, QTableWidgetItem, QTableWidget
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from obspy import UTCDateTime, Stream
|
from obspy import UTCDateTime, Stream
|
||||||
@ -60,7 +58,6 @@ try:
|
|||||||
from matplotlib.backends.backend_qt5agg import FigureCanvas
|
from matplotlib.backends.backend_qt5agg import FigureCanvas
|
||||||
except ImportError:
|
except ImportError:
|
||||||
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
|
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
|
||||||
from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar
|
|
||||||
from matplotlib.figure import Figure
|
from matplotlib.figure import Figure
|
||||||
|
|
||||||
from pylot.core.analysis.magnitude import LocalMagnitude, MomentMagnitude
|
from pylot.core.analysis.magnitude import LocalMagnitude, MomentMagnitude
|
||||||
@ -68,8 +65,8 @@ from pylot.core.io.data import Data
|
|||||||
from pylot.core.io.inputs import FilterOptions, PylotParameter
|
from pylot.core.io.inputs import FilterOptions, PylotParameter
|
||||||
from autoPyLoT import autoPyLoT
|
from autoPyLoT import autoPyLoT
|
||||||
from pylot.core.pick.compare import Comparison
|
from pylot.core.pick.compare import Comparison
|
||||||
from pylot.core.pick.utils import symmetrize_error, getQualityFromUncertainty, getPickQuality, get_quality_class
|
from pylot.core.pick.utils import getQualityFromUncertainty
|
||||||
from pylot.core.io.phases import picksdict_from_picks, picks_from_picksdict
|
from pylot.core.io.phases import picksdict_from_picks
|
||||||
import pylot.core.loc.nll as nll
|
import pylot.core.loc.nll as nll
|
||||||
from pylot.core.util.errors import DatastructureError, \
|
from pylot.core.util.errors import DatastructureError, \
|
||||||
OverwriteError
|
OverwriteError
|
||||||
@ -79,7 +76,7 @@ from pylot.core.util.utils import fnConstructor, getLogin, \
|
|||||||
full_range, readFilterInformation, pick_color_plt, \
|
full_range, readFilterInformation, pick_color_plt, \
|
||||||
pick_linestyle_plt, identifyPhaseID, excludeQualityClasses, \
|
pick_linestyle_plt, identifyPhaseID, excludeQualityClasses, \
|
||||||
transform_colors_mpl, transform_colors_mpl_str, getAutoFilteroptions, check_all_obspy, \
|
transform_colors_mpl, transform_colors_mpl_str, getAutoFilteroptions, check_all_obspy, \
|
||||||
check_all_pylot, get_Bool, get_None, SetChannelComponents
|
check_all_pylot, get_Bool, get_None
|
||||||
from pylot.core.util.gui import make_pen
|
from pylot.core.util.gui import make_pen
|
||||||
from pylot.core.util.event import Event
|
from pylot.core.util.event import Event
|
||||||
from pylot.core.io.location import create_creation_info, create_event
|
from pylot.core.io.location import create_creation_info, create_event
|
||||||
@ -91,7 +88,7 @@ from pylot.core.util.array_map import Array_map
|
|||||||
from pylot.core.util.structure import DATASTRUCTURE
|
from pylot.core.util.structure import DATASTRUCTURE
|
||||||
from pylot.core.util.thread import Thread, Worker
|
from pylot.core.util.thread import Thread, Worker
|
||||||
from pylot.core.util.version import get_git_version as _getVersionString
|
from pylot.core.util.version import get_git_version as _getVersionString
|
||||||
from pylot.core.io.getEventListFromXML import geteventlistfromxml
|
from pylot.core.io.getEventListFromXML import geteventlistfromxml
|
||||||
from pylot.core.io.getQualitiesfromxml import getQualitiesfromxml
|
from pylot.core.io.getQualitiesfromxml import getQualitiesfromxml
|
||||||
|
|
||||||
from pylot.styles import style_settings
|
from pylot.styles import style_settings
|
||||||
@ -436,9 +433,9 @@ class MainWindow(QMainWindow):
|
|||||||
None, paraIcon,
|
None, paraIcon,
|
||||||
"Modify Parameter")
|
"Modify Parameter")
|
||||||
self.deleteAutopicksAction = self.createAction(self, "Delete Autopicks",
|
self.deleteAutopicksAction = self.createAction(self, "Delete Autopicks",
|
||||||
self.deleteAllAutopicks,
|
self.deleteAllAutopicks,
|
||||||
None, deleteIcon,
|
None, deleteIcon,
|
||||||
"Delete all automatic picks from Project.")
|
"Delete all automatic picks from Project.")
|
||||||
self.filterActionP = createAction(parent=self, text='Apply P Filter',
|
self.filterActionP = createAction(parent=self, text='Apply P Filter',
|
||||||
slot=self.filterP,
|
slot=self.filterP,
|
||||||
icon=self.filter_icon_p,
|
icon=self.filter_icon_p,
|
||||||
@ -492,8 +489,9 @@ class MainWindow(QMainWindow):
|
|||||||
self.qualities_action.setVisible(True)
|
self.qualities_action.setVisible(True)
|
||||||
|
|
||||||
self.eventlist_xml_action = self.createAction(parent=self, text='Create Eventlist from XML',
|
self.eventlist_xml_action = self.createAction(parent=self, text='Create Eventlist from XML',
|
||||||
slot=self.eventlistXml, shortcut='Alt+X',
|
slot=self.eventlistXml, shortcut='Alt+X',
|
||||||
icon=eventlist_xml_icon, tip='Create an Eventlist from a XML File')
|
icon=eventlist_xml_icon,
|
||||||
|
tip='Create an Eventlist from a XML File')
|
||||||
self.eventlist_xml_action.setEnabled(False)
|
self.eventlist_xml_action.setEnabled(False)
|
||||||
|
|
||||||
printAction = self.createAction(self, "&Print event ...",
|
printAction = self.createAction(self, "&Print event ...",
|
||||||
@ -561,7 +559,8 @@ class MainWindow(QMainWindow):
|
|||||||
' the complete project on grid engine.')
|
' the complete project on grid engine.')
|
||||||
self.auto_pick_sge.setEnabled(False)
|
self.auto_pick_sge.setEnabled(False)
|
||||||
|
|
||||||
pickActions = (self.auto_tune, self.auto_pick, self.compare_action, self.qualities_action, self.eventlist_xml_action)
|
pickActions = (
|
||||||
|
self.auto_tune, self.auto_pick, self.compare_action, self.qualities_action, self.eventlist_xml_action)
|
||||||
|
|
||||||
# pickToolBar = self.addToolBar("PickTools")
|
# pickToolBar = self.addToolBar("PickTools")
|
||||||
# pickToolActions = (selectStation, )
|
# pickToolActions = (selectStation, )
|
||||||
@ -572,7 +571,7 @@ class MainWindow(QMainWindow):
|
|||||||
shortcut='Alt+Ctrl+L',
|
shortcut='Alt+Ctrl+L',
|
||||||
icon=locate_icon,
|
icon=locate_icon,
|
||||||
tip='Locate the event using '
|
tip='Locate the event using '
|
||||||
'the displayed manual arrivals.')
|
'the displayed manual arrivals.')
|
||||||
self.locateEventAction.setEnabled(False)
|
self.locateEventAction.setEnabled(False)
|
||||||
|
|
||||||
locationToolActions = (self.locateEventAction,)
|
locationToolActions = (self.locateEventAction,)
|
||||||
@ -602,11 +601,10 @@ class MainWindow(QMainWindow):
|
|||||||
self.autoPickMenu = self.pickMenu.addMenu(self.autopicksicon_small, 'Automatic picking')
|
self.autoPickMenu = self.pickMenu.addMenu(self.autopicksicon_small, 'Automatic picking')
|
||||||
self.autoPickMenu.setEnabled(False)
|
self.autoPickMenu.setEnabled(False)
|
||||||
|
|
||||||
|
|
||||||
autoPickActions = (self.auto_pick, self.auto_pick_local, self.auto_pick_sge)
|
autoPickActions = (self.auto_pick, self.auto_pick_local, self.auto_pick_sge)
|
||||||
|
|
||||||
self.helpMenu = self.menuBar().addMenu('&Help')
|
self.helpMenu = self.menuBar().addMenu('&Help')
|
||||||
helpActions = (helpAction,logAction)
|
helpActions = (helpAction, logAction)
|
||||||
|
|
||||||
fileToolActions = (self.newProjectAction,
|
fileToolActions = (self.newProjectAction,
|
||||||
self.openProjectAction, self.saveProjectAction,
|
self.openProjectAction, self.saveProjectAction,
|
||||||
@ -808,7 +806,7 @@ class MainWindow(QMainWindow):
|
|||||||
def modify_gain(self, direction, factor):
|
def modify_gain(self, direction, factor):
|
||||||
assert (direction in ['+', '-']), 'unknown direction'
|
assert (direction in ['+', '-']), 'unknown direction'
|
||||||
if self._ctrl:
|
if self._ctrl:
|
||||||
factor = factor**3
|
factor = factor ** 3
|
||||||
if direction == '+':
|
if direction == '+':
|
||||||
self.gain *= factor
|
self.gain *= factor
|
||||||
elif direction == '-':
|
elif direction == '-':
|
||||||
@ -960,7 +958,6 @@ class MainWindow(QMainWindow):
|
|||||||
|
|
||||||
self.recentProjectsMenu.addAction(action)
|
self.recentProjectsMenu.addAction(action)
|
||||||
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def inputs(self):
|
def inputs(self):
|
||||||
return self._inputs
|
return self._inputs
|
||||||
@ -998,7 +995,7 @@ class MainWindow(QMainWindow):
|
|||||||
if not sld.exec_():
|
if not sld.exec_():
|
||||||
return
|
return
|
||||||
fext = sld.lineEdit.text()
|
fext = sld.lineEdit.text()
|
||||||
#fext = '.xml'
|
# fext = '.xml'
|
||||||
for event in events:
|
for event in events:
|
||||||
path = event.path
|
path = event.path
|
||||||
eventname = path.split('/')[-1] # or event.pylot_id
|
eventname = path.split('/')[-1] # or event.pylot_id
|
||||||
@ -1030,7 +1027,7 @@ class MainWindow(QMainWindow):
|
|||||||
data_new = Data(self, evtdata=str(fname))
|
data_new = Data(self, evtdata=str(fname))
|
||||||
# MP MP commented because adding several picks might cause inconsistencies
|
# MP MP commented because adding several picks might cause inconsistencies
|
||||||
data = data_new
|
data = data_new
|
||||||
#data += data_new
|
# data += data_new
|
||||||
except ValueError:
|
except ValueError:
|
||||||
qmb = QMessageBox(self, icon=QMessageBox.Question,
|
qmb = QMessageBox(self, icon=QMessageBox.Question,
|
||||||
text='Warning: Missmatch in event identifiers {} and {}. Continue?'.format(
|
text='Warning: Missmatch in event identifiers {} and {}. Continue?'.format(
|
||||||
@ -1179,7 +1176,8 @@ class MainWindow(QMainWindow):
|
|||||||
eventlist_file = os.path.join(basepath, 'eventlist.txt')
|
eventlist_file = os.path.join(basepath, 'eventlist.txt')
|
||||||
if os.path.isfile(eventlist_file):
|
if os.path.isfile(eventlist_file):
|
||||||
with open(eventlist_file, 'r') as infile:
|
with open(eventlist_file, 'r') as infile:
|
||||||
eventlist_subset = [os.path.join(basepath, filename.split('\n')[0]) for filename in infile.readlines()]
|
eventlist_subset = [os.path.join(basepath, filename.split('\n')[0]) for filename in
|
||||||
|
infile.readlines()]
|
||||||
msg = 'Found file "eventlist.txt" in database path. WILL ONLY USE SELECTED EVENTS out of {} events ' \
|
msg = 'Found file "eventlist.txt" in database path. WILL ONLY USE SELECTED EVENTS out of {} events ' \
|
||||||
'contained in this subset'
|
'contained in this subset'
|
||||||
print(msg.format(len(eventlist_subset)))
|
print(msg.format(len(eventlist_subset)))
|
||||||
@ -1230,7 +1228,7 @@ class MainWindow(QMainWindow):
|
|||||||
print('Warning: Could not automatically init folder structure. ({})'.format(e))
|
print('Warning: Could not automatically init folder structure. ({})'.format(e))
|
||||||
|
|
||||||
settings = QSettings()
|
settings = QSettings()
|
||||||
settings.setValue("data/dataRoot", dirs['datapath']) #d irs['rootpath'])
|
settings.setValue("data/dataRoot", dirs['datapath']) # d irs['rootpath'])
|
||||||
settings.sync()
|
settings.sync()
|
||||||
|
|
||||||
if not self.project.eventlist:
|
if not self.project.eventlist:
|
||||||
@ -1544,6 +1542,7 @@ class MainWindow(QMainWindow):
|
|||||||
event = self.get_current_event()
|
event = self.get_current_event()
|
||||||
if not type(outformats) == list:
|
if not type(outformats) == list:
|
||||||
outformats = [outformats]
|
outformats = [outformats]
|
||||||
|
|
||||||
def getSavePath(event, directory, outformats):
|
def getSavePath(event, directory, outformats):
|
||||||
if not directory:
|
if not directory:
|
||||||
title = 'Save event data as {} to directory ...'.format(outformats)
|
title = 'Save event data as {} to directory ...'.format(outformats)
|
||||||
@ -1666,14 +1665,14 @@ class MainWindow(QMainWindow):
|
|||||||
self.cmpw.show()
|
self.cmpw.show()
|
||||||
|
|
||||||
def pickQualities(self):
|
def pickQualities(self):
|
||||||
path = self._inputs['rootpath'] + '/' + self._inputs['datapath'] + '/' + self._inputs['database']
|
path = self._inputs['rootpath'] + '/' + self._inputs['datapath'] + '/' + self._inputs['database']
|
||||||
getQualitiesfromxml(path)
|
getQualitiesfromxml(path)
|
||||||
return
|
return
|
||||||
|
|
||||||
def eventlistXml(self):
|
def eventlistXml(self):
|
||||||
path = self._inputs['rootpath'] + '/' + self._inputs['datapath'] + '/' + self._inputs['database']
|
path = self._inputs['rootpath'] + '/' + self._inputs['datapath'] + '/' + self._inputs['database']
|
||||||
outpath = self.project.location[:self.project.location.rfind('/')]
|
outpath = self.project.location[:self.project.location.rfind('/')]
|
||||||
geteventlistfromxml(path, outpath)
|
geteventlistfromxml(path, outpath)
|
||||||
return
|
return
|
||||||
|
|
||||||
def compareMulti(self):
|
def compareMulti(self):
|
||||||
@ -1916,7 +1915,7 @@ class MainWindow(QMainWindow):
|
|||||||
if not curr_event:
|
if not curr_event:
|
||||||
print('Could not find current event. Try reload?')
|
print('Could not find current event. Try reload?')
|
||||||
return
|
return
|
||||||
|
|
||||||
if len(curr_event.origins) > 0:
|
if len(curr_event.origins) > 0:
|
||||||
origin_time = curr_event.origins[0].time
|
origin_time = curr_event.origins[0].time
|
||||||
tstart = settings.value('tstart') if get_None(settings.value('tstart')) else 0
|
tstart = settings.value('tstart') if get_None(settings.value('tstart')) else 0
|
||||||
@ -1932,7 +1931,7 @@ class MainWindow(QMainWindow):
|
|||||||
checkRotated=True,
|
checkRotated=True,
|
||||||
metadata=self.metadata,
|
metadata=self.metadata,
|
||||||
tstart=tstart,
|
tstart=tstart,
|
||||||
tstop=tstop,)
|
tstop=tstop, )
|
||||||
|
|
||||||
def prepareObspyDMT_data(self, eventpath):
|
def prepareObspyDMT_data(self, eventpath):
|
||||||
qcbox_processed = self.dataPlot.qcombo_processed
|
qcbox_processed = self.dataPlot.qcombo_processed
|
||||||
@ -2129,7 +2128,7 @@ class MainWindow(QMainWindow):
|
|||||||
if self.obspy_dmt:
|
if self.obspy_dmt:
|
||||||
invpath = os.path.join(self.get_current_event_path(), 'resp')
|
invpath = os.path.join(self.get_current_event_path(), 'resp')
|
||||||
if not invpath in self.metadata.inventories:
|
if not invpath in self.metadata.inventories:
|
||||||
self.metadata.add_inventory(invpath, obspy_dmt_inv = True)
|
self.metadata.add_inventory(invpath, obspy_dmt_inv=True)
|
||||||
# check if directory is empty
|
# check if directory is empty
|
||||||
if os.listdir(invpath):
|
if os.listdir(invpath):
|
||||||
self.init_map_button.setEnabled(True)
|
self.init_map_button.setEnabled(True)
|
||||||
@ -2702,9 +2701,9 @@ class MainWindow(QMainWindow):
|
|||||||
# init event selection options for autopick
|
# init event selection options for autopick
|
||||||
self.pickoptions = [('current event', self.get_current_event, None),
|
self.pickoptions = [('current event', self.get_current_event, None),
|
||||||
('tune events', self.get_ref_events, self._style['ref']['rgba']),
|
('tune events', self.get_ref_events, self._style['ref']['rgba']),
|
||||||
('test events', self.get_test_events, self._style['test']['rgba']),]
|
('test events', self.get_test_events, self._style['test']['rgba']), ]
|
||||||
#('all (picked) events', self.get_manu_picked_events, None),
|
# ('all (picked) events', self.get_manu_picked_events, None),
|
||||||
#('all events', self.get_all_events, None)]
|
# ('all events', self.get_all_events, None)]
|
||||||
|
|
||||||
self.listWidget = QListWidget()
|
self.listWidget = QListWidget()
|
||||||
self.setDirty(True)
|
self.setDirty(True)
|
||||||
@ -2902,7 +2901,7 @@ class MainWindow(QMainWindow):
|
|||||||
|
|
||||||
def safetyCopy(self, event_path):
|
def safetyCopy(self, event_path):
|
||||||
fpath = self.get_deleted_picks_fpath(event_path)
|
fpath = self.get_deleted_picks_fpath(event_path)
|
||||||
fpath_new = fpath.split('.json')[0] + '_copy_{}.json'.format(datetime.now()).replace(' ', '_')
|
fpath_new = fpath.split('.json')[0] + '_copy_{}.json'.format(datetime.now()).replace(' ', '_')
|
||||||
shutil.move(fpath, fpath_new)
|
shutil.move(fpath, fpath_new)
|
||||||
|
|
||||||
def load_deleted_picks(self, event_path):
|
def load_deleted_picks(self, event_path):
|
||||||
@ -3136,7 +3135,7 @@ class MainWindow(QMainWindow):
|
|||||||
Try to init array map widget. If no metadata are given,
|
Try to init array map widget. If no metadata are given,
|
||||||
self.get_metadata will be called.
|
self.get_metadata will be called.
|
||||||
'''
|
'''
|
||||||
if checked: pass # dummy argument for QAction trigger signal
|
if checked: pass # dummy argument for QAction trigger signal
|
||||||
self.tabs.setCurrentIndex(1)
|
self.tabs.setCurrentIndex(1)
|
||||||
# if there is no metadata (invetories is an empty list), just initialize the default empty tab
|
# if there is no metadata (invetories is an empty list), just initialize the default empty tab
|
||||||
if not self.metadata.inventories:
|
if not self.metadata.inventories:
|
||||||
@ -3271,7 +3270,7 @@ class MainWindow(QMainWindow):
|
|||||||
|
|
||||||
# iterate through eventlist and generate items for table rows
|
# iterate through eventlist and generate items for table rows
|
||||||
self.project._table = []
|
self.project._table = []
|
||||||
for index, event in enumerate(eventlist):
|
for index, event in enumerate(eventlist):
|
||||||
phaseErrors = {'P': self._inputs['timeerrorsP'],
|
phaseErrors = {'P': self._inputs['timeerrorsP'],
|
||||||
'S': self._inputs['timeerrorsS']}
|
'S': self._inputs['timeerrorsS']}
|
||||||
|
|
||||||
@ -3299,9 +3298,9 @@ class MainWindow(QMainWindow):
|
|||||||
item_depth = QTableWidgetItem()
|
item_depth = QTableWidgetItem()
|
||||||
item_momentmag = QTableWidgetItem()
|
item_momentmag = QTableWidgetItem()
|
||||||
item_localmag = QTableWidgetItem()
|
item_localmag = QTableWidgetItem()
|
||||||
item_nmp = QTableWidgetItem('{}'.format(ma_count['manual']))#, ma_count_total['manual']))
|
item_nmp = QTableWidgetItem('{}'.format(ma_count['manual'])) # , ma_count_total['manual']))
|
||||||
item_nmp.setIcon(self.manupicksicon_small)
|
item_nmp.setIcon(self.manupicksicon_small)
|
||||||
item_nap = QTableWidgetItem('{}'.format(ma_count['auto']))#, ma_count_total['auto']))
|
item_nap = QTableWidgetItem('{}'.format(ma_count['auto'])) # , ma_count_total['auto']))
|
||||||
item_nap.setIcon(self.autopicksicon_small)
|
item_nap.setIcon(self.autopicksicon_small)
|
||||||
item_ref = QTableWidgetItem()
|
item_ref = QTableWidgetItem()
|
||||||
item_test = QTableWidgetItem()
|
item_test = QTableWidgetItem()
|
||||||
@ -3428,7 +3427,7 @@ class MainWindow(QMainWindow):
|
|||||||
event, time, lat, lon, depth, ml, mw, nmp, nap, tune, test, notes = row
|
event, time, lat, lon, depth, ml, mw, nmp, nap, tune, test, notes = row
|
||||||
row_str = ''
|
row_str = ''
|
||||||
for index in range(len(row)):
|
for index in range(len(row)):
|
||||||
row_str += '{}'+'{}'.format(separator)
|
row_str += '{}' + '{}'.format(separator)
|
||||||
|
|
||||||
row_str = row_str.format(event.text(), time.text(), lat.text(), lon.text(), depth.text(), ml.text(),
|
row_str = row_str.format(event.text(), time.text(), lat.text(), lon.text(), depth.text(), ml.text(),
|
||||||
mw.text(), nmp.text(), nap.text(), bool(tune.checkState()),
|
mw.text(), nmp.text(), nap.text(), bool(tune.checkState()),
|
||||||
@ -3457,7 +3456,6 @@ class MainWindow(QMainWindow):
|
|||||||
if event == current_event:
|
if event == current_event:
|
||||||
set_background_color(item_list, QtGui.QColor(*(0, 143, 143, 255)))
|
set_background_color(item_list, QtGui.QColor(*(0, 143, 143, 255)))
|
||||||
|
|
||||||
|
|
||||||
def set_metadata(self):
|
def set_metadata(self):
|
||||||
self.project.inventories = self.metadata.inventories
|
self.project.inventories = self.metadata.inventories
|
||||||
if self.metadata.inventories:
|
if self.metadata.inventories:
|
||||||
@ -3469,7 +3467,7 @@ class MainWindow(QMainWindow):
|
|||||||
self.init_map_button.setEnabled(False)
|
self.init_map_button.setEnabled(False)
|
||||||
self.initMapAction.setEnabled(False)
|
self.initMapAction.setEnabled(False)
|
||||||
self.inventory_label.setText("No inventory set...")
|
self.inventory_label.setText("No inventory set...")
|
||||||
#self.setDirty(False)
|
# self.setDirty(False)
|
||||||
|
|
||||||
def add_metadata(self):
|
def add_metadata(self):
|
||||||
self.add_metadata_widget = AddMetadataWidget(self, metadata=self.metadata)
|
self.add_metadata_widget = AddMetadataWidget(self, metadata=self.metadata)
|
||||||
@ -3717,7 +3715,7 @@ class MainWindow(QMainWindow):
|
|||||||
else:
|
else:
|
||||||
self.dataPlot.setPermText(1)
|
self.dataPlot.setPermText(1)
|
||||||
self.dataPlot.setPermText(0, '| Number of traces: {} | Gain: {}'.format(len(self.getPlotWidget().getPlotDict()),
|
self.dataPlot.setPermText(0, '| Number of traces: {} | Gain: {}'.format(len(self.getPlotWidget().getPlotDict()),
|
||||||
self.gain))
|
self.gain))
|
||||||
|
|
||||||
def _setDirty(self):
|
def _setDirty(self):
|
||||||
self.setDirty(True)
|
self.setDirty(True)
|
||||||
@ -3738,7 +3736,7 @@ class MainWindow(QMainWindow):
|
|||||||
# QMainWindow.closeEvent(self, event)
|
# QMainWindow.closeEvent(self, event)
|
||||||
|
|
||||||
def setParameter(self, checked=0, show=True):
|
def setParameter(self, checked=0, show=True):
|
||||||
if checked: pass # dummy argument to receive trigger signal (checked) if called by QAction
|
if checked: pass # dummy argument to receive trigger signal (checked) if called by QAction
|
||||||
if not self.paraBox:
|
if not self.paraBox:
|
||||||
self.paraBox = PylotParaBox(self._inputs, parent=self, windowflag=Qt.Window)
|
self.paraBox = PylotParaBox(self._inputs, parent=self, windowflag=Qt.Window)
|
||||||
self.paraBox.accepted.connect(self._setDirty)
|
self.paraBox.accepted.connect(self._setDirty)
|
||||||
@ -3763,7 +3761,6 @@ class MainWindow(QMainWindow):
|
|||||||
self.plotWaveformDataThread()
|
self.plotWaveformDataThread()
|
||||||
self.refreshTabs()
|
self.refreshTabs()
|
||||||
|
|
||||||
|
|
||||||
def PyLoTprefs(self):
|
def PyLoTprefs(self):
|
||||||
if not self._props:
|
if not self._props:
|
||||||
self._props = PropertiesDlg(self, infile=self.infile,
|
self._props = PropertiesDlg(self, infile=self.infile,
|
||||||
@ -3792,6 +3789,7 @@ class Project(object):
|
|||||||
'''
|
'''
|
||||||
Pickable class containing information of a PyLoT project, like event lists and file locations.
|
Pickable class containing information of a PyLoT project, like event lists and file locations.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
# TODO: remove rootpath
|
# TODO: remove rootpath
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.eventlist = []
|
self.eventlist = []
|
||||||
@ -3933,18 +3931,18 @@ class Project(object):
|
|||||||
else:
|
else:
|
||||||
filename = self.location
|
filename = self.location
|
||||||
|
|
||||||
table = self._table # MP: see below
|
table = self._table # MP: see below
|
||||||
try:
|
try:
|
||||||
outfile = open(filename, 'wb')
|
outfile = open(filename, 'wb')
|
||||||
self._table = [] # MP: Workaround as long as table cannot be saved as part of project
|
self._table = [] # MP: Workaround as long as table cannot be saved as part of project
|
||||||
pickle.dump(self, outfile, protocol=pickle.HIGHEST_PROTOCOL)
|
pickle.dump(self, outfile, protocol=pickle.HIGHEST_PROTOCOL)
|
||||||
self.setDirty(False)
|
self.setDirty(False)
|
||||||
self._table = table # MP: see above
|
self._table = table # MP: see above
|
||||||
return True
|
return True
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print('Could not pickle PyLoT project. Reason: {}'.format(e))
|
print('Could not pickle PyLoT project. Reason: {}'.format(e))
|
||||||
self.setDirty()
|
self.setDirty()
|
||||||
self._table = table # MP: see above
|
self._table = table # MP: see above
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
26
README.md
26
README.md
@ -4,22 +4,19 @@ version: 0.2
|
|||||||
|
|
||||||
The Python picking and Localisation Tool
|
The Python picking and Localisation Tool
|
||||||
|
|
||||||
This python library contains a graphical user interfaces for picking
|
This python library contains a graphical user interfaces for picking seismic phases. This software needs [ObsPy][ObsPy]
|
||||||
seismic phases. This software needs [ObsPy][ObsPy]
|
|
||||||
and the PySide Qt4 bindings for python to be installed first.
|
and the PySide Qt4 bindings for python to be installed first.
|
||||||
|
|
||||||
PILOT has originally been developed in Mathworks' MatLab. In order to
|
PILOT has originally been developed in Mathworks' MatLab. In order to distribute PILOT without facing portability
|
||||||
distribute PILOT without facing portability problems, it has been decided
|
problems, it has been decided to redevelop the software package in Python. The great work of the ObsPy group allows easy
|
||||||
to redevelop the software package in Python. The great work of the ObsPy
|
handling of a bunch of seismic data and PyLoT will benefit a lot compared to the former MatLab version.
|
||||||
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.
|
The development of PyLoT is part of the joint research project MAGS2 and AlpArray.
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
At the moment there is no automatic installation procedure available for PyLoT.
|
At the moment there is no automatic installation procedure available for PyLoT. Best way to install is to clone the
|
||||||
Best way to install is to clone the repository and add the path to your Python path.
|
repository and add the path to your Python path.
|
||||||
|
|
||||||
#### Prerequisites:
|
#### Prerequisites:
|
||||||
|
|
||||||
@ -34,7 +31,7 @@ In order to run PyLoT you need to install:
|
|||||||
|
|
||||||
#### Some handwork:
|
#### Some handwork:
|
||||||
|
|
||||||
PyLoT needs a properties folder on your system to work. It should be situated in your home directory
|
PyLoT needs a properties folder on your system to work. It should be situated in your home directory
|
||||||
(on Windows usually C:/Users/*username*):
|
(on Windows usually C:/Users/*username*):
|
||||||
|
|
||||||
mkdir ~/.pylot
|
mkdir ~/.pylot
|
||||||
@ -53,7 +50,8 @@ In the next step you have to copy some files to this directory:
|
|||||||
|
|
||||||
cp path-to-pylot/inputs/pylot_global.in ~/.pylot/pylot.in
|
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
|
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/
|
cp path-to-pylot/inputs/PILOT_TimeErrors.in path-to-pylot/inputs/richter_scaling.data ~/.pylot/
|
||||||
|
|
||||||
@ -61,7 +59,6 @@ You may need to do some modifications to these files. Especially folder names sh
|
|||||||
|
|
||||||
PyLoT has been tested on Mac OSX (10.11), Debian Linux 8 and on Windows 10.
|
PyLoT has been tested on Mac OSX (10.11), Debian Linux 8 and on Windows 10.
|
||||||
|
|
||||||
|
|
||||||
## Release notes
|
## Release notes
|
||||||
|
|
||||||
#### Features:
|
#### Features:
|
||||||
@ -71,7 +68,7 @@ PyLoT has been tested on Mac OSX (10.11), Debian Linux 8 and on Windows 10.
|
|||||||
- consistent automatic phase picking routines using Higher Order Statistics, AIC and Autoregression
|
- consistent automatic phase picking routines using Higher Order Statistics, AIC and Autoregression
|
||||||
- interactive tuning of auto-pick parameters
|
- interactive tuning of auto-pick parameters
|
||||||
- uniform uncertainty estimation from waveform's properties for automatic and manual picks
|
- uniform uncertainty estimation from waveform's properties for automatic and manual picks
|
||||||
- pdf representation and comparison of picks taking the uncertainty intrinsically into account
|
- pdf representation and comparison of picks taking the uncertainty intrinsically into account
|
||||||
- Richter and moment magnitude estimation
|
- Richter and moment magnitude estimation
|
||||||
- location determination with external installation of [NonLinLoc](http://alomax.free.fr/nlloc/index.html)
|
- location determination with external installation of [NonLinLoc](http://alomax.free.fr/nlloc/index.html)
|
||||||
|
|
||||||
@ -85,8 +82,7 @@ We hope to solve these with the next release.
|
|||||||
|
|
||||||
Original author(s): L. Kueperkoch, S. Wehling-Benatelli, M. Bischoff (PILOT)
|
Original author(s): L. Kueperkoch, S. Wehling-Benatelli, M. Bischoff (PILOT)
|
||||||
|
|
||||||
Developer(s): S. Wehling-Benatelli, L. Kueperkoch, K. Olbert, M. Bischoff,
|
Developer(s): S. Wehling-Benatelli, L. Kueperkoch, K. Olbert, M. Bischoff, C. Wollin, M. Rische, M. Paffrath
|
||||||
C. Wollin, M. Rische, M. Paffrath
|
|
||||||
|
|
||||||
Others: A. Bruestle, T. Meier, W. Friederich
|
Others: A. Bruestle, T. Meier, W. Friederich
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@ import datetime
|
|||||||
import glob
|
import glob
|
||||||
import os
|
import os
|
||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
from obspy import read_events
|
from obspy import read_events
|
||||||
from obspy.core.event import ResourceIdentifier
|
from obspy.core.event import ResourceIdentifier
|
||||||
|
|
||||||
@ -277,7 +278,7 @@ def autoPyLoT(input_dict=None, parameter=None, inputfile=None, fnames=None, even
|
|||||||
if not wfdat:
|
if not wfdat:
|
||||||
print('Could not find station {}. STOP!'.format(station))
|
print('Could not find station {}. STOP!'.format(station))
|
||||||
return
|
return
|
||||||
#wfdat = remove_underscores(wfdat)
|
# wfdat = remove_underscores(wfdat)
|
||||||
# trim components for each station to avoid problems with different trace starttimes for one station
|
# trim components for each station to avoid problems with different trace starttimes for one station
|
||||||
wfdat = check4gapsAndRemove(wfdat)
|
wfdat = check4gapsAndRemove(wfdat)
|
||||||
wfdat = check4doubled(wfdat)
|
wfdat = check4doubled(wfdat)
|
||||||
|
333
docs/gui.md
333
docs/gui.md
@ -2,36 +2,36 @@
|
|||||||
|
|
||||||
- [PyLoT Documentation](#pylot-documentation)
|
- [PyLoT Documentation](#pylot-documentation)
|
||||||
- [PyLoT GUI](#pylot-gui)
|
- [PyLoT GUI](#pylot-gui)
|
||||||
- [First start](#first-start)
|
- [First start](#first-start)
|
||||||
- [Main Screen](#main-screen)
|
- [Main Screen](#main-screen)
|
||||||
- [Waveform Plot](#waveform-plot)
|
- [Waveform Plot](#waveform-plot)
|
||||||
- [Mouse view controls](#mouse-view-controls)
|
- [Mouse view controls](#mouse-view-controls)
|
||||||
- [Buttons](#buttons)
|
- [Buttons](#buttons)
|
||||||
- [Array Map](#array-map)
|
- [Array Map](#array-map)
|
||||||
- [Eventlist](#eventlist)
|
- [Eventlist](#eventlist)
|
||||||
- [Usage](#usage)
|
- [Usage](#usage)
|
||||||
- [Projects and Events](#projects-and-events)
|
- [Projects and Events](#projects-and-events)
|
||||||
- [Event folder structure](#event-folder-structure)
|
- [Event folder structure](#event-folder-structure)
|
||||||
- [Loading event information from CSV file](#loading-event-information-from-csv-file)
|
- [Loading event information from CSV file](#loading-event-information-from-csv-file)
|
||||||
- [Adding events to project](#adding-events-to-project)
|
- [Adding events to project](#adding-events-to-project)
|
||||||
- [Saving projects](#saving-projects)
|
- [Saving projects](#saving-projects)
|
||||||
- [Adding metadata](#adding-metadata)
|
- [Adding metadata](#adding-metadata)
|
||||||
- [Picking](#picking)
|
- [Picking](#picking)
|
||||||
- [Manual Picking](#manual-picking)
|
- [Manual Picking](#manual-picking)
|
||||||
- [Picking window](#picking-window)
|
- [Picking window](#picking-window)
|
||||||
- [Picking Window Settings](#picking-window-settings)
|
- [Picking Window Settings](#picking-window-settings)
|
||||||
- [Filtering](#filtering)
|
- [Filtering](#filtering)
|
||||||
- [Export and Import of manual picks](#export-and-import-of-manual-picks)
|
- [Export and Import of manual picks](#export-and-import-of-manual-picks)
|
||||||
- [Export](#export)
|
- [Export](#export)
|
||||||
- [Import](#import)
|
- [Import](#import)
|
||||||
- [Automatic Picking](#automatic-picking)
|
- [Automatic Picking](#automatic-picking)
|
||||||
- [Tuning](#tuning)
|
- [Tuning](#tuning)
|
||||||
- [Production run of the autopicker](#production-run-of-the-autopicker)
|
- [Production run of the autopicker](#production-run-of-the-autopicker)
|
||||||
- [Evaluation of automatic picks](#evaluation-of-automatic-picks)
|
- [Evaluation of automatic picks](#evaluation-of-automatic-picks)
|
||||||
- [1. Jackknife check](#1-jackknife-check)
|
- [1. Jackknife check](#1-jackknife-check)
|
||||||
- [2. Wadati check](#2-wadati-check)
|
- [2. Wadati check](#2-wadati-check)
|
||||||
- [Comparison between automatic and manual picks](#comparison-between-automatic-and-manual-picks)
|
- [Comparison between automatic and manual picks](#comparison-between-automatic-and-manual-picks)
|
||||||
- [Export and Import of automatic picks](#export-and-import-of-automatic-picks)
|
- [Export and Import of automatic picks](#export-and-import-of-automatic-picks)
|
||||||
- [Location determination](#location-determination)
|
- [Location determination](#location-determination)
|
||||||
- [FAQ](#faq)
|
- [FAQ](#faq)
|
||||||
|
|
||||||
@ -44,15 +44,17 @@ This section describes how to use PyLoT graphically to view waveforms and create
|
|||||||
After opening PyLoT for the first time, the setup routine asks for the following information:
|
After opening PyLoT for the first time, the setup routine asks for the following information:
|
||||||
|
|
||||||
Questions:
|
Questions:
|
||||||
|
|
||||||
1. Full Name
|
1. Full Name
|
||||||
2. Authority: Enter authority/institution name
|
2. Authority: Enter authority/institution name
|
||||||
3. Format: Enter output format (*.xml, *.cnv, *.obs)
|
3. Format: Enter output format (*.xml, *.cnv, *.obs)
|
||||||
|
|
||||||
[//]: <> (TODO: explain what these things mean, where they are used)
|
[//]: <> (TODO: explain what these things mean, where they are used)
|
||||||
|
|
||||||
## Main Screen
|
## Main Screen
|
||||||
|
|
||||||
After entering the [information](#first-start), PyLoTs main window is shown. It defaults to a view of the [Waveform Plot](#waveform-plot), which starts empty.
|
After entering the [information](#first-start), PyLoTs main window is shown. It defaults to a view of
|
||||||
|
the [Waveform Plot](#waveform-plot), which starts empty.
|
||||||
|
|
||||||
<img src=images/gui/pylot-main-screen.png alt="Tune autopicks button" title="Tune autopicks button">
|
<img src=images/gui/pylot-main-screen.png alt="Tune autopicks button" title="Tune autopicks button">
|
||||||
|
|
||||||
@ -61,24 +63,21 @@ Add trace data by [loading a project](#projects-and-events) or by [adding event
|
|||||||
### Waveform Plot
|
### Waveform Plot
|
||||||
|
|
||||||
The waveform plot shows a trace list of all stations of an event.
|
The waveform plot shows a trace list of all stations of an event.
|
||||||
Click on any trace to open the stations [picking window](#picking-window), where you can review automatic and manual picks.
|
Click on any trace to open the stations [picking window](#picking-window), where you can review automatic and manual
|
||||||
|
picks.
|
||||||
|
|
||||||
<img src=images/gui/pylot-waveform-plot.png alt="A Waveform Plot showing traces of one event">
|
<img src=images/gui/pylot-waveform-plot.png alt="A Waveform Plot showing traces of one event">
|
||||||
|
|
||||||
Above the traces the currently displayed event can be selected.
|
Above the traces the currently displayed event can be selected. In the bottom bar information about the trace under the
|
||||||
In the bottom bar information about the trace under the mouse cursor is shown. This information includes the station name (station), the absolute UTC time (T) of the point under the mouse cursor and the relative time since the first trace start in seconds (t) as well as a trace count.
|
mouse cursor is shown. This information includes the station name (station), the absolute UTC time (T) of the point
|
||||||
|
under the mouse cursor and the relative time since the first trace start in seconds (t) as well as a trace count.
|
||||||
|
|
||||||
#### Mouse view controls
|
#### Mouse view controls
|
||||||
|
|
||||||
Hold left mouse button and drag to pan view.
|
Hold left mouse button and drag to pan view.
|
||||||
|
|
||||||
Hold right mouse button and
|
Hold right mouse button and Direction | Result --- | --- Move the mouse up | Increase amplitude scale Move the mouse
|
||||||
Direction | Result
|
down | Decrease amplitude scale Move the mouse right | Increase time scale Move the mouse left | Decrease time scale
|
||||||
--- | ---
|
|
||||||
Move the mouse up | Increase amplitude scale
|
|
||||||
Move the mouse down | Decrease amplitude scale
|
|
||||||
Move the mouse right | Increase time scale
|
|
||||||
Move the mouse left | Decrease time scale
|
|
||||||
|
|
||||||
Press right mouse button and click "View All" from the context menu to reset the view.
|
Press right mouse button and click "View All" from the context menu to reset the view.
|
||||||
|
|
||||||
@ -108,21 +107,31 @@ Press right mouse button and click "View All" from the context menu to reset the
|
|||||||
|
|
||||||
### Array Map
|
### Array Map
|
||||||
|
|
||||||
The array map will display a color diagram to allow a visual check of the consistency of picks across multiple stations. This works by calculating the time difference of every onset to the earliest onset. Then isolines are drawn between stations with the same time difference and the areas between isolines are colored.
|
The array map will display a color diagram to allow a visual check of the consistency of picks across multiple stations.
|
||||||
The result should resemble a color gradient as the wavefront rolls over the network area. Stations where picks are earlier/later than their neighbours can be reviewed by clicking on them, which opens the [picking window](#picking-window).
|
This works by calculating the time difference of every onset to the earliest onset. Then isolines are drawn between
|
||||||
|
stations with the same time difference and the areas between isolines are colored.
|
||||||
|
The result should resemble a color gradient as the wavefront rolls over the network area. Stations where picks are
|
||||||
|
earlier/later than their neighbours can be reviewed by clicking on them, which opens
|
||||||
|
the [picking window](#picking-window).
|
||||||
|
|
||||||
Above the Array Map the picks that are used to create the map can be customized.
|
Above the Array Map the picks that are used to create the map can be customized. The phase of picks that should be used
|
||||||
The phase of picks that should be used can be selected, which allows checking the consistency of the P- and S-phase separately.
|
can be selected, which allows checking the consistency of the P- and S-phase separately. Additionally the pick type can
|
||||||
Additionally the pick type can be set to manual, automatic or hybrid, meaning display only manual picks, automatic picks or only display automatic picks for stations where there are no manual ones.
|
be set to manual, automatic or hybrid, meaning display only manual picks, automatic picks or only display automatic
|
||||||
|
picks for stations where there are no manual ones.
|
||||||
|
|
||||||
![Array Map](images/gui/arraymap-example.png "Array Map")
|
![Array Map](images/gui/arraymap-example.png "Array Map")
|
||||||
*Array Map for an event at the Northern Mid Atlantic Ridge, between North Africa and Mexico (Lat. 22.58, Lon. -45.11). The wavefront moved from west to east over the network area (Alps and Balcan region), with the earliest onsets in blue in the west.*
|
*Array Map for an event at the Northern Mid Atlantic Ridge, between North Africa and Mexico (Lat. 22.58, Lon. -45.11).
|
||||||
|
The wavefront moved from west to east over the network area (Alps and Balcan region), with the earliest onsets in blue
|
||||||
|
in the west.*
|
||||||
|
|
||||||
To be able to display an array map PyLoT needs to load an inventory file, where the metadata of seismic stations is kept. For more information see [Metadata](#adding-metadata). Additionally automatic or manual picks need to exist for the current event.
|
To be able to display an array map PyLoT needs to load an inventory file, where the metadata of seismic stations is
|
||||||
|
kept. For more information see [Metadata](#adding-metadata). Additionally automatic or manual picks need to exist for
|
||||||
|
the current event.
|
||||||
|
|
||||||
### Eventlist
|
### Eventlist
|
||||||
|
|
||||||
The eventlist displays event parameters. The displayed parameters are saved in the .xml file in the event folder. Events can be deleted from the project by pressing the red X in the leftmost column of the corresponding event.
|
The eventlist displays event parameters. The displayed parameters are saved in the .xml file in the event folder. Events
|
||||||
|
can be deleted from the project by pressing the red X in the leftmost column of the corresponding event.
|
||||||
|
|
||||||
<img src="images/gui/eventlist.png" alt="Eventlist">
|
<img src="images/gui/eventlist.png" alt="Eventlist">
|
||||||
|
|
||||||
@ -144,22 +153,32 @@ The eventlist displays event parameters. The displayed parameters are saved in t
|
|||||||
|
|
||||||
### Projects and Events
|
### Projects and Events
|
||||||
|
|
||||||
PyLoT uses projects to categorize different seismic data. A project consists of one or multiple events. Events contain seismic traces from one or multiple stations. An event also contains further information, e.g. origin time, source parameters and automatic as well as manual picks.
|
PyLoT uses projects to categorize different seismic data. A project consists of one or multiple events. Events contain
|
||||||
Projects are used to group events which should be analysed together. A project could contain all events from a specific region within a timeframe of interest or all recorded events of a seismological experiment.
|
seismic traces from one or multiple stations. An event also contains further information, e.g. origin time, source
|
||||||
|
parameters and automatic as well as manual picks. Projects are used to group events which should be analysed together. A
|
||||||
|
project could contain all events from a specific region within a timeframe of interest or all recorded events of a
|
||||||
|
seismological experiment.
|
||||||
|
|
||||||
### Event folder structure
|
### Event folder structure
|
||||||
|
|
||||||
PyLoT expects the following folder structure for seismic data:
|
PyLoT expects the following folder structure for seismic data:
|
||||||
|
|
||||||
* Every event should be in it's own folder with the following naming scheme for the folders:
|
* Every event should be in it's own folder with the following naming scheme for the folders:
|
||||||
``e[id].[doy].[yy]``, where ``[id]`` is a four-digit numerical id increasing from 0001, ``[doy]`` the three digit day of year and ``[yy]`` the last two digits of the year of the event. This structure has to be created by the user of PyLoT manually.
|
``e[id].[doy].[yy]``, where ``[id]`` is a four-digit numerical id increasing from 0001, ``[doy]`` the three digit day
|
||||||
|
of year and ``[yy]`` the last two digits of the year of the event. This structure has to be created by the user of
|
||||||
|
PyLoT manually.
|
||||||
* These folders should contain the seismic data for their event as ``.mseed`` or other supported filetype
|
* These folders should contain the seismic data for their event as ``.mseed`` or other supported filetype
|
||||||
* All automatic and manual picks should be in an ``.xml`` file in their event folder. PyLoT saves picks in this file. This file does not have to be added manually unless there are picks to be imported. The format used to save picks is QUAKEML.
|
* All automatic and manual picks should be in an ``.xml`` file in their event folder. PyLoT saves picks in this file.
|
||||||
Picks are saved in a file with the same filename as the event folder with ``PyLoT_`` prepended.
|
This file does not have to be added manually unless there are picks to be imported. The format used to save picks is
|
||||||
* The file ``notes.txt`` is used for saving analysts comments. Everything saved here will be displayed in the 'Notes' column of the eventlist.
|
QUAKEML.
|
||||||
|
Picks are saved in a file with the same filename as the event folder with ``PyLoT_`` prepended.
|
||||||
|
* The file ``notes.txt`` is used for saving analysts comments. Everything saved here will be displayed in the 'Notes'
|
||||||
|
column of the eventlist.
|
||||||
|
|
||||||
### Loading event information from CSV file
|
### Loading event information from CSV file
|
||||||
|
|
||||||
Event information can be saved in a ``.csv`` file located in the rootpath. The file is made from one header line, which is followed by one or multiple data lines. Values are separated by comma, while a dot is used as a decimal separator.
|
Event information can be saved in a ``.csv`` file located in the rootpath. The file is made from one header line, which
|
||||||
|
is followed by one or multiple data lines. Values are separated by comma, while a dot is used as a decimal separator.
|
||||||
This information is then shown in the table in the [Eventlist tab](#Eventlist).
|
This information is then shown in the table in the [Eventlist tab](#Eventlist).
|
||||||
|
|
||||||
One example header and data line is shown below.
|
One example header and data line is shown below.
|
||||||
@ -181,36 +200,50 @@ The meaning of the header entries is:
|
|||||||
|
|
||||||
### Adding events to project
|
### Adding events to project
|
||||||
|
|
||||||
PyLoT GUI starts with an empty project. To add events, use the add event data button. Select one or multiple folders containing events.
|
PyLoT GUI starts with an empty project. To add events, use the add event data button. Select one or multiple folders
|
||||||
|
containing events.
|
||||||
|
|
||||||
[//]: <> (TODO: explain _Directories: Root path, Data path, Database path_)
|
[//]: <> (TODO: explain _Directories: Root path, Data path, Database path_)
|
||||||
|
|
||||||
### Saving projects
|
### Saving projects
|
||||||
|
|
||||||
Save the current project from the menu with File->Save project or File->Save project as.
|
Save the current project from the menu with File->Save project or File->Save project as. PyLoT uses ``.plp`` files to
|
||||||
PyLoT uses ``.plp`` files to save project information. This file format is not interchangeable between different versions of Python interpreters.
|
save project information. This file format is not interchangeable between different versions of Python interpreters.
|
||||||
Saved projects contain the automatic and manual picks. Seismic trace data is not included into the ``.plp`` file, but read from its location used when saving the file.
|
Saved projects contain the automatic and manual picks. Seismic trace data is not included into the ``.plp`` file, but
|
||||||
|
read from its location used when saving the file.
|
||||||
|
|
||||||
### Adding metadata
|
### Adding metadata
|
||||||
|
|
||||||
[//]: <> (TODO: Add picture of metadata "manager" when it is done)
|
[//]: <> (TODO: Add picture of metadata "manager" when it is done)
|
||||||
|
|
||||||
PyLoT can handle ``.dless``, ``.xml``, ``.resp`` and ``.dseed`` file formats for Metadata. Metadata files stored on disk can be added to a project by clicking *Edit*->*Manage Inventories*. This opens up a window where the folders which contain metadata files can be selected. PyLoT will then search these files for the station names when it needs the information.
|
PyLoT can handle ``.dless``, ``.xml``, ``.resp`` and ``.dseed`` file formats for Metadata. Metadata files stored on disk
|
||||||
|
can be added to a project by clicking *Edit*->*Manage Inventories*. This opens up a window where the folders which
|
||||||
|
contain metadata files can be selected. PyLoT will then search these files for the station names when it needs the
|
||||||
|
information.
|
||||||
|
|
||||||
# Picking
|
# Picking
|
||||||
|
|
||||||
PyLoTs automatic and manual pick determination works as following:
|
PyLoTs automatic and manual pick determination works as following:
|
||||||
* Using certain parameters, a first initial/coarse pick is determined. The first manual pick is determined by visual review of the whole waveform and selection of the most likely onset by the analyst. The first automatic pick is determined by calculation of a characteristic function (CF) for the seismic trace. When a wave arrives, the CFs properties change, which is determined as the signals onset.
|
|
||||||
* Afterwards, a refined set of parameters is applied to a small part of the waveform around the initial onset. For manual picks this means a closer view of the trace, for automatic picks this is done by a recalculated CF with different parameters.
|
* Using certain parameters, a first initial/coarse pick is determined. The first manual pick is determined by visual
|
||||||
|
review of the whole waveform and selection of the most likely onset by the analyst. The first automatic pick is
|
||||||
|
determined by calculation of a characteristic function (CF) for the seismic trace. When a wave arrives, the CFs
|
||||||
|
properties change, which is determined as the signals onset.
|
||||||
|
* Afterwards, a refined set of parameters is applied to a small part of the waveform around the initial onset. For
|
||||||
|
manual picks this means a closer view of the trace, for automatic picks this is done by a recalculated CF with
|
||||||
|
different parameters.
|
||||||
* This second picking phase results in the precise pick, which is treated as the onset time.
|
* This second picking phase results in the precise pick, which is treated as the onset time.
|
||||||
|
|
||||||
## Manual Picking
|
## Manual Picking
|
||||||
|
|
||||||
To create manual picks, you will need to open or create a project that contains seismic trace data (see [Adding events to projects](#adding-events-to-project)). Click on a trace to open the [Picking window](#picking-window).
|
To create manual picks, you will need to open or create a project that contains seismic trace data (
|
||||||
|
see [Adding events to projects](#adding-events-to-project)). Click on a trace to open
|
||||||
|
the [Picking window](#picking-window).
|
||||||
|
|
||||||
### Picking window
|
### Picking window
|
||||||
|
|
||||||
Open the picking window of a station by leftclicking on any trace in the waveform plot. Here you can create manual picks for the selected station.
|
Open the picking window of a station by leftclicking on any trace in the waveform plot. Here you can create manual picks
|
||||||
|
for the selected station.
|
||||||
|
|
||||||
<img src="images/gui/picking/pickwindow.png" alt="Picking window">
|
<img src="images/gui/picking/pickwindow.png" alt="Picking window">
|
||||||
|
|
||||||
@ -243,105 +276,167 @@ Access the Filter options by pressing Ctrl+f on the Waveform plot or by the menu
|
|||||||
|
|
||||||
<img src=images/gui/pylot-filter-options.png>
|
<img src=images/gui/pylot-filter-options.png>
|
||||||
|
|
||||||
Here you are able to select filter type, order and frequencies for the P and S pick separately. These settings are used in the GUI for displaying the filtered waveform data and during manual picking. The values used by PyLoT for automatic picking are displayed next to the manual values. They can be changed in the [Tune Autopicker dialog](#tuning).
|
Here you are able to select filter type, order and frequencies for the P and S pick separately. These settings are used
|
||||||
A green value automatic value means the automatic and manual filter parameter is configured the same, red means they are configured differently.
|
in the GUI for displaying the filtered waveform data and during manual picking. The values used by PyLoT for automatic
|
||||||
By toggling the "Overwrite filteroptions" checkmark you can set whether the manual precise/second pick uses the filter settings for the automatic picker (unchecked) or whether it uses the filter options in this dialog (checked).
|
picking are displayed next to the manual values. They can be changed in the [Tune Autopicker dialog](#tuning).
|
||||||
To guarantee consistent picking results between automatic and manual picking it is recommended to use the same filter settings for the determination of automatic and manual picks.
|
A green value automatic value means the automatic and manual filter parameter is configured the same, red means they are
|
||||||
|
configured differently. By toggling the "Overwrite filteroptions" checkmark you can set whether the manual
|
||||||
|
precise/second pick uses the filter settings for the automatic picker (unchecked) or whether it uses the filter options
|
||||||
|
in this dialog (checked). To guarantee consistent picking results between automatic and manual picking it is recommended
|
||||||
|
to use the same filter settings for the determination of automatic and manual picks.
|
||||||
|
|
||||||
### Export and Import of manual picks
|
### Export and Import of manual picks
|
||||||
|
|
||||||
#### Export
|
#### Export
|
||||||
|
|
||||||
After the creation of manual picks they can either be saved in the project file (see [Saving projects](#saving-projects)). Alternatively the picks can be exported by pressing the <img src="../icons/savepicks.png" alt="Save event information button" title="Save picks button" height=24 width=24> button above the waveform plot or in the menu File->Save event information (shortcut Ctrl+p). Select the event directory in which to save the file. The filename will be ``PyLoT_[event_folder_name].[filetype selected during first startup]``.
|
After the creation of manual picks they can either be saved in the project file (
|
||||||
You can rename and copy this file, but PyLoT will then no longer be able to automatically recognize the correct picks for an event and the file will have to be manually selected when loading.
|
see [Saving projects](#saving-projects)). Alternatively the picks can be exported by pressing
|
||||||
|
the <img src="../icons/savepicks.png" alt="Save event information button" title="Save picks button" height=24 width=24>
|
||||||
|
button above the waveform plot or in the menu File->Save event information (shortcut Ctrl+p). Select the event directory
|
||||||
|
in which to save the file. The filename will be ``PyLoT_[event_folder_name].[filetype selected during first startup]``
|
||||||
|
.
|
||||||
|
You can rename and copy this file, but PyLoT will then no longer be able to automatically recognize the correct picks
|
||||||
|
for an event and the file will have to be manually selected when loading.
|
||||||
|
|
||||||
#### Import
|
#### Import
|
||||||
|
|
||||||
To import previously saved picks press the <img src="../icons/openpick.png" alt="Load event information button" width="24" height="24"> button and select the file to load. You will be asked to save the current state of your project if you have not done so before. You can continue without saving by pressing "Discard". This does not delete any information from your project, it just means that no project file is saved before the changes of importing picks are applied.
|
To import previously saved picks press
|
||||||
PyLoT will automatically load files named after the scheme it uses when saving picks, described in the paragraph above. If it can't find any matching files, a file dialogue will open and you can select the file you wish to load.
|
the <img src="../icons/openpick.png" alt="Load event information button" width="24" height="24"> button and select the
|
||||||
|
file to load. You will be asked to save the current state of your project if you have not done so before. You can
|
||||||
|
continue without saving by pressing "Discard". This does not delete any information from your project, it just means
|
||||||
|
that no project file is saved before the changes of importing picks are applied. PyLoT will automatically load files
|
||||||
|
named after the scheme it uses when saving picks, described in the paragraph above. If it can't find any matching files,
|
||||||
|
a file dialogue will open and you can select the file you wish to load.
|
||||||
|
|
||||||
If you see a warning "Mismatch in event identifiers" and are asked whether to continue loading the picks, this means that PyLoT doesn't recognize the picks in the file as belonging to this specific event. They could have either been saved under a different installation of PyLoT but with the same waveform data, which means they are still compatible and you can continue loading them. Or they could be picks from a different event, in which case loading them is not recommended.
|
If you see a warning "Mismatch in event identifiers" and are asked whether to continue loading the picks, this means
|
||||||
|
that PyLoT doesn't recognize the picks in the file as belonging to this specific event. They could have either been
|
||||||
|
saved under a different installation of PyLoT but with the same waveform data, which means they are still compatible and
|
||||||
|
you can continue loading them. Or they could be picks from a different event, in which case loading them is not
|
||||||
|
recommended.
|
||||||
|
|
||||||
## Automatic Picking
|
## Automatic Picking
|
||||||
|
|
||||||
|
|
||||||
The general workflow for automatic picking is as following:
|
The general workflow for automatic picking is as following:
|
||||||
- After setting up the project by loading waveforms and optionally metadata, the right parameters for the autopicker have to be determined
|
|
||||||
|
- After setting up the project by loading waveforms and optionally metadata, the right parameters for the autopicker
|
||||||
|
have to be determined
|
||||||
- This [tuning](#tuning) is done for single stations with immediate graphical feedback of all picking results
|
- This [tuning](#tuning) is done for single stations with immediate graphical feedback of all picking results
|
||||||
- Afterwards the autopicker can be run for all or a subset of events from the project
|
- Afterwards the autopicker can be run for all or a subset of events from the project
|
||||||
|
|
||||||
For automatic picking PyLoT discerns between tune and test events, which the user has to set as such. Tune events are used to calibrate the autopicking algorithm, test events are then used to test the calibration. The purpose of that is controlling whether the parameters found during tuning are able to reliably pick the "unknown" test events.
|
For automatic picking PyLoT discerns between tune and test events, which the user has to set as such. Tune events are
|
||||||
If this behaviour is not desired and all events should be handled the same, dont mark any events. Since this is just a way to group events to compare the picking results, nothing else will change.
|
used to calibrate the autopicking algorithm, test events are then used to test the calibration. The purpose of that is
|
||||||
|
controlling whether the parameters found during tuning are able to reliably pick the "unknown" test events.
|
||||||
|
If this behaviour is not desired and all events should be handled the same, dont mark any events. Since this is just a
|
||||||
|
way to group events to compare the picking results, nothing else will change.
|
||||||
|
|
||||||
### Tuning
|
### Tuning
|
||||||
|
|
||||||
Tuning describes the process of adjusting the autopicker settings to the characteristics of your data set. To do this in PyLoT, use the <img src=../icons/tune.png height=24 alt="Tune autopicks button" title="Tune autopicks button"> button to open the Tune Autopicker.
|
Tuning describes the process of adjusting the autopicker settings to the characteristics of your data set. To do this in
|
||||||
|
PyLoT, use the <img src=../icons/tune.png height=24 alt="Tune autopicks button" title="Tune autopicks button"> button to
|
||||||
|
open the Tune Autopicker.
|
||||||
|
|
||||||
<img src=images/gui/tuning/tune_autopicker.png>
|
<img src=images/gui/tuning/tune_autopicker.png>
|
||||||
|
|
||||||
View of a station in the Tune Autopicker window.
|
View of a station in the Tune Autopicker window.
|
||||||
|
|
||||||
1. Select the event to be displayed and processed.
|
1. Select the event to be displayed and processed.
|
||||||
2. Select the station from the event.
|
2. Select the station from the event.
|
||||||
3. To pick the currently displayed trace, click the <img src=images/gui/tuning/autopick_trace_button.png alt="Pick trace button" title="Autopick trace button" height=16> button.
|
3. To pick the currently displayed trace, click
|
||||||
4. These tabs are used to select the current view. __Traces Plot__ contains a plot of the stations traces, where manual picks can be created/edited. __Overview__ contains graphical results of the automatic picking process. The __P and S tabs__ contain the automatic picking results of the P and S phase, while __log__ contains a useful text output of automatic picking.
|
the <img src=images/gui/tuning/autopick_trace_button.png alt="Pick trace button" title="Autopick trace button" height=16>
|
||||||
5. These buttons are used to load/save/reset settings for automatic picking. The parameters can be saved in PyLoT input files, which have the file ending *.in*. They are human readable text files, which can also be edited by hand. Saving the parameters allows you to load them again later, even on different machines.
|
button.
|
||||||
6. These menus control the behaviour of the creation of manual picks from the Tune Autopicker window. Picks allows to select the phase for which a manual pick should be created, Filter allows to filter waveforms and edit the filter parameters. P-Channels and S-Channels allow to select the channels that should be displayed when creating a manual P or S pick.
|
4. These tabs are used to select the current view. __Traces Plot__ contains a plot of the stations traces, where manual
|
||||||
7. This menu is the same as in the [Picking Window](#picking-window-settings), with the exception of the __Manual Onsets__ options. The __Manual Onsets__ buttons accepts or reject the manual picks created in the Tune Autopicker window, pressing accept adds them to the manual picks for the event, while reject removes them.
|
picks can be created/edited. __Overview__ contains graphical results of the automatic picking process. The __P and S
|
||||||
|
tabs__ contain the automatic picking results of the P and S phase, while __log__ contains a useful text output of
|
||||||
|
automatic picking.
|
||||||
|
5. These buttons are used to load/save/reset settings for automatic picking. The parameters can be saved in PyLoT input
|
||||||
|
files, which have the file ending *.in*. They are human readable text files, which can also be edited by hand. Saving
|
||||||
|
the parameters allows you to load them again later, even on different machines.
|
||||||
|
6. These menus control the behaviour of the creation of manual picks from the Tune Autopicker window. Picks allows to
|
||||||
|
select the phase for which a manual pick should be created, Filter allows to filter waveforms and edit the filter
|
||||||
|
parameters. P-Channels and S-Channels allow to select the channels that should be displayed when creating a manual P
|
||||||
|
or S pick.
|
||||||
|
7. This menu is the same as in the [Picking Window](#picking-window-settings), with the exception of the __Manual
|
||||||
|
Onsets__ options. The __Manual Onsets__ buttons accepts or reject the manual picks created in the Tune Autopicker
|
||||||
|
window, pressing accept adds them to the manual picks for the event, while reject removes them.
|
||||||
8. The traces plot in the centre allows creating manual picks and viewing the waveforms.
|
8. The traces plot in the centre allows creating manual picks and viewing the waveforms.
|
||||||
9. The parameters which influence the autopicking result are in the Main settings and Advanced settings tabs on the left side. For a description of all the parameters see the [tuning documentation](tuning.md).
|
9. The parameters which influence the autopicking result are in the Main settings and Advanced settings tabs on the left
|
||||||
|
side. For a description of all the parameters see the [tuning documentation](tuning.md).
|
||||||
|
|
||||||
### Production run of the autopicker
|
### Production run of the autopicker
|
||||||
|
|
||||||
After the settings used during tuning give the desired results, the autopicker can be used on the complete dataset. To invoke the autopicker on the whole set of events, click the <img src=../icons/autopylot_button.png alt="Autopick" title="Autopick" height=32> button.
|
After the settings used during tuning give the desired results, the autopicker can be used on the complete dataset. To
|
||||||
|
invoke the autopicker on the whole set of events, click
|
||||||
|
the <img src=../icons/autopylot_button.png alt="Autopick" title="Autopick" height=32> button.
|
||||||
|
|
||||||
### Evaluation of automatic picks
|
### Evaluation of automatic picks
|
||||||
|
|
||||||
PyLoT has two internal consistency checks for automatic picks that were determined for an event:
|
PyLoT has two internal consistency checks for automatic picks that were determined for an event:
|
||||||
|
|
||||||
1. Jackknife check
|
1. Jackknife check
|
||||||
2. Wadati check
|
2. Wadati check
|
||||||
|
|
||||||
#### 1. Jackknife check
|
#### 1. Jackknife check
|
||||||
|
|
||||||
The jackknife test in PyLoT checks the consistency of automatically determined P-picks by checking the statistical variance of the picks. The variance of all P-picks is calculated and compared to the variance of subsets, in which one pick is removed.
|
The jackknife test in PyLoT checks the consistency of automatically determined P-picks by checking the statistical
|
||||||
The idea is, that picks that are close together in time should not influence the estimation of the variance much, while picks whose positions deviates from the norm influence the variance to a greater extent. If the estimated variance of a subset with a pick removed differs to much from the estimated variance of all picks, the pick that was removed from the subset will be marked as invalid.
|
variance of the picks. The variance of all P-picks is calculated and compared to the variance of subsets, in which one
|
||||||
The factor by which picks are allowed to skew from the estimation of variance can be configured, it is called *jackfactor*, see [here](tuning.md#Pick-quality-control).
|
pick is removed.
|
||||||
|
The idea is, that picks that are close together in time should not influence the estimation of the variance much, while
|
||||||
|
picks whose positions deviates from the norm influence the variance to a greater extent. If the estimated variance of a
|
||||||
|
subset with a pick removed differs to much from the estimated variance of all picks, the pick that was removed from the
|
||||||
|
subset will be marked as invalid.
|
||||||
|
The factor by which picks are allowed to skew from the estimation of variance can be configured, it is called *
|
||||||
|
jackfactor*, see [here](tuning.md#Pick-quality-control).
|
||||||
|
|
||||||
Additionally, the deviation of picks from the median is checked. For that, the median of all P-picks that passed the Jackknife test is calculated. Picks whose onset times deviate from the mean onset time by more than the *mdttolerance* are marked as invalid.
|
Additionally, the deviation of picks from the median is checked. For that, the median of all P-picks that passed the
|
||||||
|
Jackknife test is calculated. Picks whose onset times deviate from the mean onset time by more than the *mdttolerance*
|
||||||
|
are marked as invalid.
|
||||||
|
|
||||||
<img src=images/gui/jackknife_plot.png title="Jackknife/Median test diagram">
|
<img src=images/gui/jackknife_plot.png title="Jackknife/Median test diagram">
|
||||||
|
|
||||||
*The result of both tests (Jackknife and Median) is shown in a diagram afterwards. The onset time is plotted against a running number of stations. Picks that failed either the Jackknife or the median test are colored red. The median is plotted as a green line.*
|
*The result of both tests (Jackknife and Median) is shown in a diagram afterwards. The onset time is plotted against a
|
||||||
|
running number of stations. Picks that failed either the Jackknife or the median test are colored red. The median is
|
||||||
|
plotted as a green line.*
|
||||||
|
|
||||||
The Jackknife and median check are suitable to check for picks that are outside of the expected time window, for example, when a wrong phase was picked. It won't recognize picks that are in close proximity to the right onset which are just slightly to late/early.
|
The Jackknife and median check are suitable to check for picks that are outside of the expected time window, for
|
||||||
|
example, when a wrong phase was picked. It won't recognize picks that are in close proximity to the right onset which
|
||||||
|
are just slightly to late/early.
|
||||||
|
|
||||||
#### 2. Wadati check
|
#### 2. Wadati check
|
||||||
|
|
||||||
The Wadati check checks the consistency of S picks. For this the SP-time, the time difference between S and P onset is plotted against the P onset time. A line is fitted to the points, which minimizes the error. Then the deviation of single picks to this line is checked. If the deviation in seconds is above the *wdttolerance* parameter ([see here](tuning.md#Pick-quality-control)), the pick is marked as invalid.
|
The Wadati check checks the consistency of S picks. For this the SP-time, the time difference between S and P onset is
|
||||||
|
plotted against the P onset time. A line is fitted to the points, which minimizes the error. Then the deviation of
|
||||||
|
single picks to this line is checked. If the deviation in seconds is above the *wdttolerance*
|
||||||
|
parameter ([see here](tuning.md#Pick-quality-control)), the pick is marked as invalid.
|
||||||
|
|
||||||
<img src=images/gui/wadati_plot.png title="Output diagram of Wadati check">
|
<img src=images/gui/wadati_plot.png title="Output diagram of Wadati check">
|
||||||
|
|
||||||
*The Wadati plot in PyLoT shows the SP onset time difference over the P onset time. A first line is fitted (black). All picks which deviate to much from this line are marked invalid (red). Then a second line is fitted which excludes the invalid picks. From this lines slope, the ratio of P and S wave velocity is determined.*
|
*The Wadati plot in PyLoT shows the SP onset time difference over the P onset time. A first line is fitted (black). All
|
||||||
|
picks which deviate to much from this line are marked invalid (red). Then a second line is fitted which excludes the
|
||||||
|
invalid picks. From this lines slope, the ratio of P and S wave velocity is determined.*
|
||||||
|
|
||||||
### Comparison between automatic and manual picks
|
### Comparison between automatic and manual picks
|
||||||
|
|
||||||
Every pick in PyLoT consists of an earliest possible, latest possible and most likely onset time.
|
Every pick in PyLoT consists of an earliest possible, latest possible and most likely onset time. The earliest and
|
||||||
The earliest and latest possible onset time characterize the uncertainty of a pick.
|
latest possible onset time characterize the uncertainty of a pick. This approach is described in Diel, Kissling and
|
||||||
This approach is described in Diel, Kissling and Bormann (2012) - Tutorial for consistent phase picking at local to regional distances.
|
Bormann (2012) - Tutorial for consistent phase picking at local to regional distances. These times are represented as a
|
||||||
These times are represented as a Probability Density Function (PDF) for every pick.
|
Probability Density Function (PDF) for every pick. The PDF is implemented as two exponential distributions around the
|
||||||
The PDF is implemented as two exponential distributions around the most likely onset as the expected value.
|
most likely onset as the expected value.
|
||||||
|
|
||||||
To compare two single picks, their PDFs are cross correlated to create a new PDF.
|
To compare two single picks, their PDFs are cross correlated to create a new PDF. This corresponds to the subtraction of
|
||||||
This corresponds to the subtraction of the automatic pick from the manual pick.
|
the automatic pick from the manual pick.
|
||||||
|
|
||||||
<img src=images/gui/comparison/comparison_pdf.png title="Comparison between automatic and manual pick">
|
<img src=images/gui/comparison/comparison_pdf.png title="Comparison between automatic and manual pick">
|
||||||
|
|
||||||
*Comparison between an automatic and a manual pick for a station in PyLoT by comparing their PDFs.*
|
*Comparison between an automatic and a manual pick for a station in PyLoT by comparing their PDFs.*
|
||||||
*The upper plot shows the difference between the two single picks that are shown in the lower plot.*
|
*The upper plot shows the difference between the two single picks that are shown in the lower plot.*
|
||||||
*The difference is implemented as a cross correlation between the two PDFs. and results in a new PDF, the comparison PDF.*
|
*The difference is implemented as a cross correlation between the two PDFs. and results in a new PDF, the comparison
|
||||||
*The expected value of the comparison PDF corresponds to the time distance between the automatic and manual picks most likely onset.*
|
PDF.*
|
||||||
*The standard deviation corresponds to the combined uncertainty.*
|
*The expected value of the comparison PDF corresponds to the time distance between the automatic and manual picks most
|
||||||
|
likely onset.*
|
||||||
|
*The standard deviation corresponds to the combined uncertainty.*
|
||||||
|
|
||||||
To compare the automatic and manual picks between multiple stations of an event, the properties of all the comparison PDFs are shown in a histogram.
|
To compare the automatic and manual picks between multiple stations of an event, the properties of all the comparison
|
||||||
|
PDFs are shown in a histogram.
|
||||||
|
|
||||||
<img src=images/gui/comparison/compare_widget.png title="Comparison between picks of an event">
|
<img src=images/gui/comparison/compare_widget.png title="Comparison between picks of an event">
|
||||||
|
|
||||||
@ -350,11 +445,13 @@ To compare the automatic and manual picks between multiple stations of an event,
|
|||||||
*The bottom left plot shows the expected values of the comparison PDFs for P picks.*
|
*The bottom left plot shows the expected values of the comparison PDFs for P picks.*
|
||||||
*The top right plot shows the standard deviation of the comparison PDFs for S picks.*
|
*The top right plot shows the standard deviation of the comparison PDFs for S picks.*
|
||||||
*The bottom right plot shows the expected values of the comparison PDFs for S picks.*
|
*The bottom right plot shows the expected values of the comparison PDFs for S picks.*
|
||||||
*The standard deviation plots show that most P picks have an uncertainty between 1 and 2 seconds, while S pick uncertainties have a much larger spread between 1 to 15 seconds.*
|
*The standard deviation plots show that most P picks have an uncertainty between 1 and 2 seconds, while S pick
|
||||||
|
uncertainties have a much larger spread between 1 to 15 seconds.*
|
||||||
*This means P picks have higher quality classes on average than S picks.*
|
*This means P picks have higher quality classes on average than S picks.*
|
||||||
*The expected values are largely negative, meaning that the algorithm tends to pick earlier than the analyst with the applied settings (Manual - Automatic).*
|
*The expected values are largely negative, meaning that the algorithm tends to pick earlier than the analyst with the
|
||||||
*The number of samples mentioned in the plots legends is the amount of stations that have an automatic and a manual P pick.*
|
applied settings (Manual - Automatic).*
|
||||||
|
*The number of samples mentioned in the plots legends is the amount of stations that have an automatic and a manual P
|
||||||
|
pick.*
|
||||||
|
|
||||||
### Export and Import of automatic picks
|
### Export and Import of automatic picks
|
||||||
|
|
||||||
@ -367,7 +464,11 @@ To be added.
|
|||||||
# FAQ
|
# FAQ
|
||||||
|
|
||||||
Q: During manual picking the error "No channel to plot for phase ..." is displayed, and I am unable to create a pick.
|
Q: During manual picking the error "No channel to plot for phase ..." is displayed, and I am unable to create a pick.
|
||||||
A: Select a channel that should be used for the corresponding phase in the Pickwindow. For further information read [Picking Window settings](#picking-window-settings).
|
A: Select a channel that should be used for the corresponding phase in the Pickwindow. For further information
|
||||||
|
read [Picking Window settings](#picking-window-settings).
|
||||||
|
|
||||||
Q: I see a warning "Mismatch in event identifiers" when loading picks from a file.
|
Q: I see a warning "Mismatch in event identifiers" when loading picks from a file.
|
||||||
A: This means that PyLoT doesn't recognize the picks in the file as belonging to this specific event. They could have been saved under a different installation of PyLoT but with the same waveform data, which means they are still compatible and you can continue loading them or they could be the picks of a different event, in which case loading them is not recommended.
|
A: This means that PyLoT doesn't recognize the picks in the file as belonging to this specific event. They could have
|
||||||
|
been saved under a different installation of PyLoT but with the same waveform data, which means they are still
|
||||||
|
compatible and you can continue loading them or they could be the picks of a different event, in which case loading them
|
||||||
|
is not recommended.
|
||||||
|
143
docs/tuning.md
143
docs/tuning.md
@ -8,12 +8,18 @@ Parameters applied to the traces before picking algorithm starts.
|
|||||||
|
|
||||||
| Name | Description |
|
| Name | Description |
|
||||||
|---------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|---------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||||
| *P Start*, *P Stop* | Define time interval relative to trace start time for CF calculation on vertical trace. Value is relative to theoretical onset time if 'Use TauPy' option is enabled in main settings of 'Tune Autopicker' dialogue. |
|
| *P Start*, *P
|
||||||
| *S Start*, *S Stop* | Define time interval relative to trace start time for CF calculation on horizontal traces. Value is relative to theoretical onset time if 'Use TauPy' option is enabled in main settings of 'Tune Autopicker' dialogue. |
|
Stop* | Define time interval relative to trace start time for CF calculation on vertical trace. Value is relative to theoretical onset time if 'Use TauPy' option is enabled in main settings of 'Tune Autopicker' dialogue. |
|
||||||
| *Bandpass Z1* | Filter settings for Butterworth bandpass applied to vertical trace for calculation of initial P pick. |
|
| *S Start*, *S
|
||||||
| *Bandpass Z2* | Filter settings for Butterworth bandpass applied to vertical trace for calculation of precise P pick. |
|
Stop* | Define time interval relative to trace start time for CF calculation on horizontal traces. Value is relative to theoretical onset time if 'Use TauPy' option is enabled in main settings of 'Tune Autopicker' dialogue. |
|
||||||
| *Bandpass H1* | Filter settings for Butterworth bandpass applied to horizontal traces for calculation of initial S pick. |
|
| *Bandpass
|
||||||
| *Bandpass H2* | Filter settings for Butterworth bandpass applied to horizontal traces for calculation of precise S pick. |
|
Z1* | Filter settings for Butterworth bandpass applied to vertical trace for calculation of initial P pick. |
|
||||||
|
| *Bandpass
|
||||||
|
Z2* | Filter settings for Butterworth bandpass applied to vertical trace for calculation of precise P pick. |
|
||||||
|
| *Bandpass
|
||||||
|
H1* | Filter settings for Butterworth bandpass applied to horizontal traces for calculation of initial S pick. |
|
||||||
|
| *Bandpass
|
||||||
|
H2* | Filter settings for Butterworth bandpass applied to horizontal traces for calculation of precise S pick. |
|
||||||
|
|
||||||
## Inital P pick
|
## Inital P pick
|
||||||
|
|
||||||
@ -21,15 +27,24 @@ Parameters used for determination of initial P pick.
|
|||||||
|
|
||||||
| Name | Description |
|
| Name | Description |
|
||||||
|--------------|------------------------------------------------------------------------------------------------------------------------------|
|
|--------------|------------------------------------------------------------------------------------------------------------------------------|
|
||||||
| *tLTA* | Size of gliding LTA window in seconds used for calculation of HOS-CF. |
|
| *
|
||||||
| *pickwin P* | Size of time window in seconds in which the minimum of the AIC-CF in front of the maximum of the HOS-CF is determined. |
|
tLTA* | Size of gliding LTA window in seconds used for calculation of HOS-CF. |
|
||||||
| *AICtsmooth* | Average of samples in this time window will be used for smoothing of the AIC-CF. |
|
| *pickwin
|
||||||
| *checkwinP* | Time in front of the global maximum of the HOS-CF in which to search for a second local extrema. |
|
P* | Size of time window in seconds in which the minimum of the AIC-CF in front of the maximum of the HOS-CF is determined. |
|
||||||
| *minfactorP* | Used with *checkwinP*. If a second local maximum is found, it has to be at least as big as the first maximum * *minfactorP*. |
|
| *
|
||||||
| *tsignal* | Time window in seconds after the initial P pick used for determining signal amplitude. |
|
AICtsmooth* | Average of samples in this time window will be used for smoothing of the AIC-CF. |
|
||||||
| *tnoise* | Time window in seconds in front of initial P pick used for determining noise amplitude. |
|
| *
|
||||||
| *tsafetey* | Time in seconds between *tsignal* and *tnoise*. |
|
checkwinP* | Time in front of the global maximum of the HOS-CF in which to search for a second local extrema. |
|
||||||
| *tslope* | Time window in seconds after initial P pick in which the slope of the onset is calculated. |
|
| *minfactorP* | Used with *
|
||||||
|
checkwinP*. If a second local maximum is found, it has to be at least as big as the first maximum * *minfactorP*. |
|
||||||
|
| *
|
||||||
|
tsignal* | Time window in seconds after the initial P pick used for determining signal amplitude. |
|
||||||
|
| *
|
||||||
|
tnoise* | Time window in seconds in front of initial P pick used for determining noise amplitude. |
|
||||||
|
| *tsafetey* | Time in seconds between *tsignal* and *
|
||||||
|
tnoise*. |
|
||||||
|
| *
|
||||||
|
tslope* | Time window in seconds after initial P pick in which the slope of the onset is calculated. |
|
||||||
|
|
||||||
## Inital S pick
|
## Inital S pick
|
||||||
|
|
||||||
@ -37,16 +52,26 @@ Parameters used for determination of initial S pick
|
|||||||
|
|
||||||
| Name | Description |
|
| Name | Description |
|
||||||
|---------------|------------------------------------------------------------------------------------------------------------------------------|
|
|---------------|------------------------------------------------------------------------------------------------------------------------------|
|
||||||
| *tdet1h* | Length of time window in seconds in which AR params of the waveform are determined. |
|
| *
|
||||||
| *tpred1h* | Length of time window in seconds in which the waveform is predicted using the AR model. |
|
tdet1h* | Length of time window in seconds in which AR params of the waveform are determined. |
|
||||||
| *AICtsmoothS* | Average of samples in this time window is used for smoothing the AIC-CF. |
|
| *
|
||||||
| *pickwinS* | Time window in which the minimum in the AIC-CF in front of the maximum in the ARH-CF is determined. |
|
tpred1h* | Length of time window in seconds in which the waveform is predicted using the AR model. |
|
||||||
| *checkwinS* | Time in front of the global maximum of the ARH-CF in which to search for a second local extrema. |
|
| *
|
||||||
| *minfactorP* | Used with *checkwinS*. If a second local maximum is found, it has to be at least as big as the first maximum * *minfactorS*. |
|
AICtsmoothS* | Average of samples in this time window is used for smoothing the AIC-CF. |
|
||||||
| *tsignal* | Time window in seconds after the initial P pick used for determining signal amplitude. |
|
| *
|
||||||
| *tnoise* | Time window in seconds in front of initial P pick used for determining noise amplitude. |
|
pickwinS* | Time window in which the minimum in the AIC-CF in front of the maximum in the ARH-CF is determined. |
|
||||||
| *tsafetey* | Time in seconds between *tsignal* and *tnoise*. |
|
| *
|
||||||
| *tslope* | Time window in seconds after initial P pick in which the slope of the onset is calculated. |
|
checkwinS* | Time in front of the global maximum of the ARH-CF in which to search for a second local extrema. |
|
||||||
|
| *minfactorP* | Used with *
|
||||||
|
checkwinS*. If a second local maximum is found, it has to be at least as big as the first maximum * *minfactorS*. |
|
||||||
|
| *
|
||||||
|
tsignal* | Time window in seconds after the initial P pick used for determining signal amplitude. |
|
||||||
|
| *
|
||||||
|
tnoise* | Time window in seconds in front of initial P pick used for determining noise amplitude. |
|
||||||
|
| *tsafetey* | Time in seconds between *tsignal* and *
|
||||||
|
tnoise*. |
|
||||||
|
| *
|
||||||
|
tslope* | Time window in seconds after initial P pick in which the slope of the onset is calculated. |
|
||||||
|
|
||||||
## Precise P pick
|
## Precise P pick
|
||||||
|
|
||||||
@ -54,9 +79,13 @@ Parameters used for determination of precise P pick.
|
|||||||
|
|
||||||
| Name | Description |
|
| Name | Description |
|
||||||
|--------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|--------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||||
| *Precalcwin* | Time window in seconds for recalculation of the HOS-CF. The new CF will be two times the size of *Precalcwin*, since it will be calculated from the initial pick to +/- *Precalcwin*. |
|
| *Precalcwin* | Time window in seconds for recalculation of the HOS-CF. The new CF will be two times the size of *
|
||||||
| *tsmoothP* | Average of samples in this time window will be used for smoothing the second HOS-CF. |
|
Precalcwin*, since it will be calculated from the initial pick to +/- *Precalcwin*. |
|
||||||
| *ausP* | Controls artificial uplift of samples during precise picking. A common local minimum of the smoothed and unsmoothed HOS-CF is found when the previous sample is larger or equal to the current sample times (1+*ausP*). |
|
| *
|
||||||
|
tsmoothP* | Average of samples in this time window will be used for smoothing the second HOS-CF. |
|
||||||
|
| *
|
||||||
|
ausP* | Controls artificial uplift of samples during precise picking. A common local minimum of the smoothed and unsmoothed HOS-CF is found when the previous sample is larger or equal to the current sample times (1+*
|
||||||
|
ausP*). |
|
||||||
|
|
||||||
## Precise S pick
|
## Precise S pick
|
||||||
|
|
||||||
@ -64,12 +93,19 @@ Parameters used for determination of precise S pick.
|
|||||||
|
|
||||||
| Name | Description |
|
| Name | Description |
|
||||||
|--------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|--------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||||
| *tdet2h* | Time window for determination of AR coefficients. |
|
| *
|
||||||
| *tpred2h* | Time window in which the waveform is predicted using the determined AR parameters. |
|
tdet2h* | Time window for determination of AR coefficients. |
|
||||||
| *Srecalcwin* | Time window for recalculation of ARH-CF. New CF will be calculated from initial pick +/- *Srecalcwin*. |
|
| *
|
||||||
| *tsmoothS* | Average of samples in this time window will be used for smoothing the second ARH-CF. |
|
tpred2h* | Time window in which the waveform is predicted using the determined AR parameters. |
|
||||||
| *ausS* | Controls artificial uplift of samples during precise picking. A common local minimum of the smoothed and unsmoothed ARH-CF is found when the previous sample is larger or equal to the current sample times (1+*ausS*). |
|
| *Srecalcwin* | Time window for recalculation of ARH-CF. New CF will be calculated from initial pick +/- *
|
||||||
| *pickwinS* | Time window around initial pick in which to look for a precise pick. |
|
Srecalcwin*. |
|
||||||
|
| *
|
||||||
|
tsmoothS* | Average of samples in this time window will be used for smoothing the second ARH-CF. |
|
||||||
|
| *
|
||||||
|
ausS* | Controls artificial uplift of samples during precise picking. A common local minimum of the smoothed and unsmoothed ARH-CF is found when the previous sample is larger or equal to the current sample times (1+*
|
||||||
|
ausS*). |
|
||||||
|
| *
|
||||||
|
pickwinS* | Time window around initial pick in which to look for a precise pick. |
|
||||||
|
|
||||||
## Pick quality control
|
## Pick quality control
|
||||||
|
|
||||||
@ -77,15 +113,27 @@ Parameters used for checking quality and integrity of automatic picks.
|
|||||||
|
|
||||||
| Name | Description |
|
| Name | Description |
|
||||||
|--------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|--------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||||
| *minAICPslope* | Initial P picks with a slope lower than this value will be discared. |
|
| *
|
||||||
| *minAICPSNR* | Initial P picks with a SNR below this value will be discarded. |
|
minAICPslope* | Initial P picks with a slope lower than this value will be discared. |
|
||||||
| *minAICSslope* | Initial S picks with a slope lower than this value will be discarded. |
|
| *
|
||||||
| *minAICSSNR* | Initial S picks with a SNR below this value will be discarded. |
|
minAICPSNR* | Initial P picks with a SNR below this value will be discarded. |
|
||||||
| *minsiglength*, *noisefacor*. *minpercent* | Parameters for checking signal length. In the time window of size *minsiglength* after the initial P pick *minpercent* of samples have to be larger than the RMS value. |
|
| *
|
||||||
| *zfac* | To recognize misattributed S picks, the RMS amplitude of vertical and horizontal traces are compared. The RMS amplitude of the vertical traces has to be at least *zfac* higher than the RMS amplitude on the horizontal traces for the pick to be accepted as a valid P pick. |
|
minAICSslope* | Initial S picks with a slope lower than this value will be discarded. |
|
||||||
| *jackfactor* | A P pick is removed if the jackknife pseudo value of the variance of his subgroup is larger than the variance of all picks multiplied with the *jackfactor*. |
|
| *
|
||||||
| *mdttolerance* | Maximum allowed deviation of P onset times from the median. Value in seconds. |
|
minAICSSNR* | Initial S picks with a SNR below this value will be discarded. |
|
||||||
| *wdttolerance* | Maximum allowed deviation of S onset times from the line during the Wadati test. Value in seconds. |
|
| *minsiglength*, *noisefacor*. *minpercent* | Parameters for checking signal length. In the time window of size *
|
||||||
|
minsiglength* after the initial P pick *
|
||||||
|
minpercent* of samples have to be larger than the RMS value. |
|
||||||
|
| *
|
||||||
|
zfac* | To recognize misattributed S picks, the RMS amplitude of vertical and horizontal traces are compared. The RMS amplitude of the vertical traces has to be at least *
|
||||||
|
zfac* higher than the RMS amplitude on the horizontal traces for the pick to be accepted as a valid P pick. |
|
||||||
|
| *
|
||||||
|
jackfactor* | A P pick is removed if the jackknife pseudo value of the variance of his subgroup is larger than the variance of all picks multiplied with the *
|
||||||
|
jackfactor*. |
|
||||||
|
| *
|
||||||
|
mdttolerance* | Maximum allowed deviation of P onset times from the median. Value in seconds. |
|
||||||
|
| *
|
||||||
|
wdttolerance* | Maximum allowed deviation of S onset times from the line during the Wadati test. Value in seconds. |
|
||||||
|
|
||||||
## Pick quality determination
|
## Pick quality determination
|
||||||
|
|
||||||
@ -93,7 +141,10 @@ Parameters for discrete quality classes.
|
|||||||
|
|
||||||
| Name | Description |
|
| Name | Description |
|
||||||
|------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||||
| *timeerrorsP* | Width of the time windows in seconds between earliest and latest possible pick which represent the quality classes 0, 1, 2, 3 for P onsets. |
|
| *
|
||||||
| *timeerrorsS* | Width of the time windows in seconds between earliest and latest possible pick which represent the quality classes 0, 1, 2, 3 for S onsets. |
|
timeerrorsP* | Width of the time windows in seconds between earliest and latest possible pick which represent the quality classes 0, 1, 2, 3 for P onsets. |
|
||||||
| *nfacP*, *nfacS* | For determination of latest possible onset time. The time when the signal reaches an amplitude of *nfac* * mean value of the RMS amplitude in the time window *tnoise* corresponds to the latest possible onset time. |
|
| *
|
||||||
|
timeerrorsS* | Width of the time windows in seconds between earliest and latest possible pick which represent the quality classes 0, 1, 2, 3 for S onsets. |
|
||||||
|
| *nfacP*, *nfacS* | For determination of latest possible onset time. The time when the signal reaches an amplitude of *
|
||||||
|
nfac* * mean value of the RMS amplitude in the time window *tnoise* corresponds to the latest possible onset time. |
|
||||||
|
|
||||||
|
@ -223,14 +223,14 @@ class LocalMagnitude(Magnitude):
|
|||||||
in 'Z3']
|
in 'Z3']
|
||||||
# checking horizontal count and calculating power_sum accordingly
|
# checking horizontal count and calculating power_sum accordingly
|
||||||
if len(power) == 1:
|
if len(power) == 1:
|
||||||
print ('WARNING: Only one horizontal found for station {0}.'.format(st[0].stats.station))
|
print('WARNING: Only one horizontal found for station {0}.'.format(st[0].stats.station))
|
||||||
power_sum = power[0]
|
power_sum = power[0]
|
||||||
elif len(power) == 2:
|
elif len(power) == 2:
|
||||||
power_sum = power[0] + power[1]
|
power_sum = power[0] + power[1]
|
||||||
else:
|
else:
|
||||||
raise ValueError('Wood-Anderson aomplitude defintion only valid for'
|
raise ValueError('Wood-Anderson aomplitude defintion only valid for'
|
||||||
' up to two horizontals: {0} given'.format(len(power)))
|
' up to two horizontals: {0} given'.format(len(power)))
|
||||||
|
|
||||||
sqH = np.sqrt(power_sum)
|
sqH = np.sqrt(power_sum)
|
||||||
|
|
||||||
# get time array
|
# get time array
|
||||||
@ -325,7 +325,7 @@ class LocalMagnitude(Magnitude):
|
|||||||
if self.verbose:
|
if self.verbose:
|
||||||
print(
|
print(
|
||||||
"Local Magnitude for station {0}: ML = {1:3.1f}".format(
|
"Local Magnitude for station {0}: ML = {1:3.1f}".format(
|
||||||
station, magnitude.mag))
|
station, magnitude.mag))
|
||||||
magnitude.origin_id = self.origin_id
|
magnitude.origin_id = self.origin_id
|
||||||
magnitude.waveform_id = pick.waveform_id
|
magnitude.waveform_id = pick.waveform_id
|
||||||
magnitude.amplitude_id = amplitude.resource_id
|
magnitude.amplitude_id = amplitude.resource_id
|
||||||
@ -404,7 +404,7 @@ class MomentMagnitude(Magnitude):
|
|||||||
if not wf:
|
if not wf:
|
||||||
continue
|
continue
|
||||||
try:
|
try:
|
||||||
scopy = wf.copy()
|
scopy = wf.copy()
|
||||||
except AssertionError:
|
except AssertionError:
|
||||||
print("WARNING: Something's wrong with the data,"
|
print("WARNING: Something's wrong with the data,"
|
||||||
"station {},"
|
"station {},"
|
||||||
@ -464,7 +464,7 @@ def calcMoMw(wfstream, w0, rho, vp, delta, verbosity=False):
|
|||||||
|
|
||||||
# additional common parameters for calculating Mo
|
# additional common parameters for calculating Mo
|
||||||
# average radiation pattern of P waves (Aki & Richards, 1980)
|
# average radiation pattern of P waves (Aki & Richards, 1980)
|
||||||
rP = 2 / np.sqrt(15)
|
rP = 2 / np.sqrt(15)
|
||||||
freesurf = 2.0 # free surface correction, assuming vertical incidence
|
freesurf = 2.0 # free surface correction, assuming vertical incidence
|
||||||
|
|
||||||
Mo = w0 * 4 * np.pi * rho * np.power(vp, 3) * delta / (rP * freesurf)
|
Mo = w0 * 4 * np.pi * rho * np.power(vp, 3) * delta / (rP * freesurf)
|
||||||
@ -524,7 +524,7 @@ def calcsourcespec(wfstream, onset, vp, delta, azimuth, incidence,
|
|||||||
iplot = 2
|
iplot = 2
|
||||||
else:
|
else:
|
||||||
iplot = 0
|
iplot = 0
|
||||||
|
|
||||||
# get Q value
|
# get Q value
|
||||||
Q, A = qp
|
Q, A = qp
|
||||||
|
|
||||||
@ -594,13 +594,13 @@ def calcsourcespec(wfstream, onset, vp, delta, azimuth, incidence,
|
|||||||
|
|
||||||
# fft
|
# fft
|
||||||
fny = freq / 2
|
fny = freq / 2
|
||||||
#l = len(xdat) / freq
|
# l = len(xdat) / freq
|
||||||
# number of fft bins after Bath
|
# number of fft bins after Bath
|
||||||
#n = freq * l
|
# n = freq * l
|
||||||
# find next power of 2 of data length
|
# find next power of 2 of data length
|
||||||
m = pow(2, np.ceil(np.log(len(xdat)) / np.log(2)))
|
m = pow(2, np.ceil(np.log(len(xdat)) / np.log(2)))
|
||||||
N = min(int(np.power(m, 2)), 16384)
|
N = min(int(np.power(m, 2)), 16384)
|
||||||
#N = int(np.power(m, 2))
|
# N = int(np.power(m, 2))
|
||||||
y = dt * np.fft.fft(xdat, N)
|
y = dt * np.fft.fft(xdat, N)
|
||||||
Y = abs(y[: N / 2])
|
Y = abs(y[: N / 2])
|
||||||
L = (N - 1) / freq
|
L = (N - 1) / freq
|
||||||
@ -643,8 +643,8 @@ def calcsourcespec(wfstream, onset, vp, delta, azimuth, incidence,
|
|||||||
w0 = np.median([w01, w02])
|
w0 = np.median([w01, w02])
|
||||||
Fc = np.median([fc1, fc2])
|
Fc = np.median([fc1, fc2])
|
||||||
if verbosity:
|
if verbosity:
|
||||||
print("calcsourcespec: Using w0-value = %e m/Hz and fc = %f Hz" % (
|
print("calcsourcespec: Using w0-value = %e m/Hz and fc = %f Hz" % (
|
||||||
w0, Fc))
|
w0, Fc))
|
||||||
if iplot >= 1:
|
if iplot >= 1:
|
||||||
f1 = plt.figure()
|
f1 = plt.figure()
|
||||||
tLdat = np.arange(0, len(Ldat) * dt, dt)
|
tLdat = np.arange(0, len(Ldat) * dt, dt)
|
||||||
@ -733,7 +733,7 @@ def fitSourceModel(f, S, fc0, iplot, verbosity=False):
|
|||||||
iplot = 2
|
iplot = 2
|
||||||
else:
|
else:
|
||||||
iplot = 0
|
iplot = 0
|
||||||
|
|
||||||
w0 = []
|
w0 = []
|
||||||
stdw0 = []
|
stdw0 = []
|
||||||
fc = []
|
fc = []
|
||||||
|
@ -3,16 +3,16 @@
|
|||||||
|
|
||||||
import copy
|
import copy
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
from PySide2.QtWidgets import QMessageBox
|
||||||
from obspy import read_events
|
from obspy import read_events
|
||||||
from obspy.core import read, Stream, UTCDateTime
|
from obspy.core import read, Stream, UTCDateTime
|
||||||
from obspy.core.event import Event as ObsPyEvent
|
from obspy.core.event import Event as ObsPyEvent
|
||||||
from obspy.io.sac import SacIOError
|
from obspy.io.sac import SacIOError
|
||||||
|
|
||||||
from PySide2.QtWidgets import QMessageBox
|
|
||||||
|
|
||||||
import pylot.core.loc.velest as velest
|
|
||||||
import pylot.core.loc.focmec as focmec
|
import pylot.core.loc.focmec as focmec
|
||||||
import pylot.core.loc.hypodd as hypodd
|
import pylot.core.loc.hypodd as hypodd
|
||||||
|
import pylot.core.loc.velest as velest
|
||||||
from pylot.core.io.phases import readPILOTEvent, picks_from_picksdict, \
|
from pylot.core.io.phases import readPILOTEvent, picks_from_picksdict, \
|
||||||
picksdict_from_pilot, merge_picks, PylotParameter
|
picksdict_from_pilot, merge_picks, PylotParameter
|
||||||
from pylot.core.util.errors import FormatError, OverwriteError
|
from pylot.core.util.errors import FormatError, OverwriteError
|
||||||
@ -100,7 +100,7 @@ class Data(object):
|
|||||||
old_pick.phase_hint == new_pick.phase_hint,
|
old_pick.phase_hint == new_pick.phase_hint,
|
||||||
old_pick.method_id == new_pick.method_id]
|
old_pick.method_id == new_pick.method_id]
|
||||||
if all(comparison):
|
if all(comparison):
|
||||||
del(old_pick)
|
del (old_pick)
|
||||||
old_picks.append(new_pick)
|
old_picks.append(new_pick)
|
||||||
elif not other.isNew() and self.isNew():
|
elif not other.isNew() and self.isNew():
|
||||||
new = other + self
|
new = other + self
|
||||||
@ -112,7 +112,7 @@ class Data(object):
|
|||||||
return self + other
|
return self + other
|
||||||
else:
|
else:
|
||||||
raise ValueError("both Data objects have differing "
|
raise ValueError("both Data objects have differing "
|
||||||
"unique Event identifiers")
|
"unique Event identifiers")
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def getPicksStr(self):
|
def getPicksStr(self):
|
||||||
@ -250,7 +250,7 @@ class Data(object):
|
|||||||
for pick in self.get_evt_data().picks:
|
for pick in self.get_evt_data().picks:
|
||||||
if picktype in str(pick.method_id.id):
|
if picktype in str(pick.method_id.id):
|
||||||
picks.append(pick)
|
picks.append(pick)
|
||||||
|
|
||||||
def exportEvent(self, fnout, fnext='.xml', fcheck='auto', upperErrors=None):
|
def exportEvent(self, fnout, fnext='.xml', fcheck='auto', upperErrors=None):
|
||||||
"""
|
"""
|
||||||
Export event to file
|
Export event to file
|
||||||
@ -260,7 +260,7 @@ class Data(object):
|
|||||||
can be a str or a list of strings of ['manual', 'auto', 'origin', 'magnitude']
|
can be a str or a list of strings of ['manual', 'auto', 'origin', 'magnitude']
|
||||||
"""
|
"""
|
||||||
from pylot.core.util.defaults import OUTPUTFORMATS
|
from pylot.core.util.defaults import OUTPUTFORMATS
|
||||||
|
|
||||||
if not type(fcheck) == list:
|
if not type(fcheck) == list:
|
||||||
fcheck = [fcheck]
|
fcheck = [fcheck]
|
||||||
|
|
||||||
@ -293,7 +293,7 @@ class Data(object):
|
|||||||
return
|
return
|
||||||
self.checkEvent(event, fcheck)
|
self.checkEvent(event, fcheck)
|
||||||
self.setEvtData(event)
|
self.setEvtData(event)
|
||||||
|
|
||||||
self.get_evt_data().write(fnout + fnext, format=evtformat)
|
self.get_evt_data().write(fnout + fnext, format=evtformat)
|
||||||
|
|
||||||
# try exporting event
|
# try exporting event
|
||||||
@ -360,13 +360,13 @@ class Data(object):
|
|||||||
nllocfile = open(fnout + fnext)
|
nllocfile = open(fnout + fnext)
|
||||||
l = nllocfile.readlines()
|
l = nllocfile.readlines()
|
||||||
# Adding A0/Generic Amplitude to .obs file
|
# Adding A0/Generic Amplitude to .obs file
|
||||||
#l2 = []
|
# l2 = []
|
||||||
#for li in l:
|
# for li in l:
|
||||||
# for amp in evtdata_org.amplitudes:
|
# for amp in evtdata_org.amplitudes:
|
||||||
# if amp.waveform_id.station_code == li[0:5].strip():
|
# if amp.waveform_id.station_code == li[0:5].strip():
|
||||||
# li = li[0:64] + '{:0.2e}'.format(amp.generic_amplitude) + li[73:-1] + '\n'
|
# li = li[0:64] + '{:0.2e}'.format(amp.generic_amplitude) + li[73:-1] + '\n'
|
||||||
# l2.append(li)
|
# l2.append(li)
|
||||||
#l = l2
|
# l = l2
|
||||||
nllocfile.close()
|
nllocfile.close()
|
||||||
l.insert(0, header)
|
l.insert(0, header)
|
||||||
nllocfile = open(fnout + fnext, 'w')
|
nllocfile = open(fnout + fnext, 'w')
|
||||||
@ -503,7 +503,8 @@ class Data(object):
|
|||||||
real_or_syn_data[synthetic] += read(fname, format='GSE2', starttime=self.tstart, endtime=self.tstop)
|
real_or_syn_data[synthetic] += read(fname, format='GSE2', starttime=self.tstart, endtime=self.tstop)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
try:
|
try:
|
||||||
real_or_syn_data[synthetic] += read(fname, format='SEGY', starttime=self.tstart, endtime=self.tstop)
|
real_or_syn_data[synthetic] += read(fname, format='SEGY', starttime=self.tstart,
|
||||||
|
endtime=self.tstop)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
warnmsg += '{0}\n{1}\n'.format(fname, e)
|
warnmsg += '{0}\n{1}\n'.format(fname, e)
|
||||||
except SacIOError as se:
|
except SacIOError as se:
|
||||||
|
@ -515,9 +515,9 @@ defaults = {'rootpath': {'type': str,
|
|||||||
'namestring': 'TauPy model'},
|
'namestring': 'TauPy model'},
|
||||||
|
|
||||||
'taup_phases': {'type': str,
|
'taup_phases': {'type': str,
|
||||||
'tooltip': 'Specify possible phases for TauPy (comma separated). See Obspy TauPy documentation for possible values.',
|
'tooltip': 'Specify possible phases for TauPy (comma separated). See Obspy TauPy documentation for possible values.',
|
||||||
'value': 'ttall',
|
'value': 'ttall',
|
||||||
'namestring': 'TauPy phases'},
|
'namestring': 'TauPy phases'},
|
||||||
}
|
}
|
||||||
|
|
||||||
settings_main = {
|
settings_main = {
|
||||||
|
@ -8,14 +8,10 @@
|
|||||||
Edited for use in PyLoT
|
Edited for use in PyLoT
|
||||||
JG, igem, 01/2022
|
JG, igem, 01/2022
|
||||||
"""
|
"""
|
||||||
import pdb
|
import glob
|
||||||
import os
|
|
||||||
import argparse
|
|
||||||
import numpy as np
|
|
||||||
import matplotlib.pyplot as plt
|
|
||||||
from obspy.core.event import read_events
|
from obspy.core.event import read_events
|
||||||
from pyproj import Proj
|
from pyproj import Proj
|
||||||
import glob
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Creates an eventlist file summarizing all events found in a certain folder. Only called by pressing UI Button eventlis_xml_action
|
Creates an eventlist file summarizing all events found in a certain folder. Only called by pressing UI Button eventlis_xml_action
|
||||||
@ -24,14 +20,15 @@ Creates an eventlist file summarizing all events found in a certain folder. Only
|
|||||||
:param path: Path to root folder where single Event folder are to found
|
:param path: Path to root folder where single Event folder are to found
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
def geteventlistfromxml(path, outpath):
|
def geteventlistfromxml(path, outpath):
|
||||||
p = Proj(proj='utm', zone=32, ellps='WGS84')
|
p = Proj(proj='utm', zone=32, ellps='WGS84')
|
||||||
|
|
||||||
|
|
||||||
# open eventlist file and write header
|
# open eventlist file and write header
|
||||||
evlist = outpath + '/eventlist'
|
evlist = outpath + '/eventlist'
|
||||||
evlistobj = open(evlist, 'w')
|
evlistobj = open(evlist, 'w')
|
||||||
evlistobj.write('EventID Date To Lat Lon EAST NORTH Dep Ml NoP NoS RMS errH errZ Gap \n')
|
evlistobj.write(
|
||||||
|
'EventID Date To Lat Lon EAST NORTH Dep Ml NoP NoS RMS errH errZ Gap \n')
|
||||||
|
|
||||||
# data path
|
# data path
|
||||||
dp = path + "/e*/*.xml"
|
dp = path + "/e*/*.xml"
|
||||||
@ -52,28 +49,31 @@ def geteventlistfromxml(path, outpath):
|
|||||||
NoP = []
|
NoP = []
|
||||||
NoS = []
|
NoS = []
|
||||||
except IndexError:
|
except IndexError:
|
||||||
print ('Insufficient data found for event (not localised): ' + names.split('/')[-1].split('_')[-1][:-4] + ' Skipping event for eventlist.' )
|
print('Insufficient data found for event (not localised): ' + names.split('/')[-1].split('_')[-1][
|
||||||
|
:-4] + ' Skipping event for eventlist.')
|
||||||
continue
|
continue
|
||||||
|
|
||||||
for i in range(len(cat.events[0].origins[0].arrivals)):
|
for i in range(len(cat.events[0].origins[0].arrivals)):
|
||||||
if cat.events[0].origins[0].arrivals[i].phase == 'P':
|
if cat.events[0].origins[0].arrivals[i].phase == 'P':
|
||||||
NoP.append(cat.events[0].origins[0].arrivals[i].phase)
|
NoP.append(cat.events[0].origins[0].arrivals[i].phase)
|
||||||
elif cat.events[0].origins[0].arrivals[i].phase == 'S':
|
elif cat.events[0].origins[0].arrivals[i].phase == 'S':
|
||||||
NoS.append(cat.events[0].origins[0].arrivals[i].phase)
|
NoS.append(cat.events[0].origins[0].arrivals[i].phase)
|
||||||
#NoP = cat.events[0].origins[0].quality.used_station_count
|
# NoP = cat.events[0].origins[0].quality.used_station_count
|
||||||
errH = cat.events[0].origins[0].origin_uncertainty.max_horizontal_uncertainty
|
errH = cat.events[0].origins[0].origin_uncertainty.max_horizontal_uncertainty
|
||||||
errZ = cat.events[0].origins[0].depth_errors.uncertainty
|
errZ = cat.events[0].origins[0].depth_errors.uncertainty
|
||||||
Gap = cat.events[0].origins[0].quality.azimuthal_gap
|
Gap = cat.events[0].origins[0].quality.azimuthal_gap
|
||||||
#evID = names.split('/')[6]
|
# evID = names.split('/')[6]
|
||||||
evID = names.split('/')[-1].split('_')[-1][:-4]
|
evID = names.split('/')[-1].split('_')[-1][:-4]
|
||||||
Date = str(st.year) + str('%02d' % st.month) + str('%02d' % st.day)
|
Date = str(st.year) + str('%02d' % st.month) + str('%02d' % st.day)
|
||||||
To = str('%02d' % st.hour) + str('%02d' % st.minute) + str('%02d' % st.second) + \
|
To = str('%02d' % st.hour) + str('%02d' % st.minute) + str('%02d' % st.second) + \
|
||||||
'.' + str('%06d' % st.microsecond)
|
'.' + str('%06d' % st.microsecond)
|
||||||
|
|
||||||
# write into eventlist
|
# write into eventlist
|
||||||
evlistobj.write('%s %s %s %9.6f %9.6f %13.6f %13.6f %8.6f %3.1f %d %d NaN %d %d %d\n' %(evID, \
|
evlistobj.write('%s %s %s %9.6f %9.6f %13.6f %13.6f %8.6f %3.1f %d %d NaN %d %d %d\n' % (evID, \
|
||||||
Date, To, Lat, Lon, EAST, NORTH, Dep, Ml, len(NoP), len(NoS), errH, errZ, Gap))
|
Date, To, Lat, Lon,
|
||||||
print ('Adding Event ' + names.split('/')[-1].split('_')[-1][:-4] + ' to eventlist')
|
EAST, NORTH, Dep, Ml,
|
||||||
|
len(NoP), len(NoS),
|
||||||
|
errH, errZ, Gap))
|
||||||
|
print('Adding Event ' + names.split('/')[-1].split('_')[-1][:-4] + ' to eventlist')
|
||||||
print('Eventlist created and saved in: ' + outpath)
|
print('Eventlist created and saved in: ' + outpath)
|
||||||
evlistobj.close()
|
evlistobj.close()
|
||||||
|
|
||||||
|
@ -9,15 +9,15 @@
|
|||||||
Edited for usage in PyLoT: Jeldrik Gaal, igem, 01/2022
|
Edited for usage in PyLoT: Jeldrik Gaal, igem, 01/2022
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import argparse
|
|
||||||
import numpy as np
|
|
||||||
import matplotlib.pyplot as plt
|
|
||||||
from obspy.core.event import read_events
|
|
||||||
import glob
|
import glob
|
||||||
|
|
||||||
def getQualitiesfromxml(path):
|
import matplotlib.pyplot as plt
|
||||||
|
import numpy as np
|
||||||
|
from obspy.core.event import read_events
|
||||||
|
|
||||||
# uncertainties
|
|
||||||
|
def getQualitiesfromxml(path):
|
||||||
|
# uncertainties
|
||||||
ErrorsP = [0.02, 0.04, 0.08, 0.16]
|
ErrorsP = [0.02, 0.04, 0.08, 0.16]
|
||||||
ErrorsS = [0.04, 0.08, 0.16, 0.32]
|
ErrorsS = [0.04, 0.08, 0.16, 0.32]
|
||||||
|
|
||||||
@ -31,48 +31,48 @@ def getQualitiesfromxml(path):
|
|||||||
Sw2 = []
|
Sw2 = []
|
||||||
Sw3 = []
|
Sw3 = []
|
||||||
Sw4 = []
|
Sw4 = []
|
||||||
|
|
||||||
# data path
|
# data path
|
||||||
dp = path + '/e*/*.xml'
|
dp = path + '/e*/*.xml'
|
||||||
# list of all available xml-files
|
# list of all available xml-files
|
||||||
xmlnames = glob.glob(dp)
|
xmlnames = glob.glob(dp)
|
||||||
|
|
||||||
# read all onset weights
|
# read all onset weights
|
||||||
for names in xmlnames:
|
for names in xmlnames:
|
||||||
print("Getting onset weights from {}".format(names))
|
print("Getting onset weights from {}".format(names))
|
||||||
cat = read_events(names)
|
cat = read_events(names)
|
||||||
arrivals = cat.events[0].picks
|
arrivals = cat.events[0].picks
|
||||||
for Pick in arrivals:
|
for Pick in arrivals:
|
||||||
if Pick.phase_hint[0] == 'P':
|
if Pick.phase_hint[0] == 'P':
|
||||||
if Pick.time_errors.uncertainty <= ErrorsP[0]:
|
if Pick.time_errors.uncertainty <= ErrorsP[0]:
|
||||||
Pw0.append(Pick.time_errors.uncertainty)
|
Pw0.append(Pick.time_errors.uncertainty)
|
||||||
elif Pick.time_errors.uncertainty > ErrorsP[0] and \
|
elif Pick.time_errors.uncertainty > ErrorsP[0] and \
|
||||||
Pick.time_errors.uncertainty <= ErrorsP[1]:
|
Pick.time_errors.uncertainty <= ErrorsP[1]:
|
||||||
Pw1.append(Pick.time_errors.uncertainty)
|
Pw1.append(Pick.time_errors.uncertainty)
|
||||||
elif Pick.time_errors.uncertainty > ErrorsP[1] and \
|
elif Pick.time_errors.uncertainty > ErrorsP[1] and \
|
||||||
Pick.time_errors.uncertainty <= ErrorsP[2]:
|
Pick.time_errors.uncertainty <= ErrorsP[2]:
|
||||||
Pw2.append(Pick.time_errors.uncertainty)
|
Pw2.append(Pick.time_errors.uncertainty)
|
||||||
elif Pick.time_errors.uncertainty > ErrorsP[2] and \
|
elif Pick.time_errors.uncertainty > ErrorsP[2] and \
|
||||||
Pick.time_errors.uncertainty <= ErrorsP[3]:
|
Pick.time_errors.uncertainty <= ErrorsP[3]:
|
||||||
Pw3.append(Pick.time_errors.uncertainty)
|
Pw3.append(Pick.time_errors.uncertainty)
|
||||||
elif Pick.time_errors.uncertainty > ErrorsP[3]:
|
elif Pick.time_errors.uncertainty > ErrorsP[3]:
|
||||||
Pw4.append(Pick.time_errors.uncertainty)
|
Pw4.append(Pick.time_errors.uncertainty)
|
||||||
else:
|
else:
|
||||||
pass
|
pass
|
||||||
elif Pick.phase_hint[0] == 'S':
|
elif Pick.phase_hint[0] == 'S':
|
||||||
if Pick.time_errors.uncertainty <= ErrorsS[0]:
|
if Pick.time_errors.uncertainty <= ErrorsS[0]:
|
||||||
Sw0.append(Pick.time_errors.uncertainty)
|
Sw0.append(Pick.time_errors.uncertainty)
|
||||||
elif Pick.time_errors.uncertainty > ErrorsS[0] and \
|
elif Pick.time_errors.uncertainty > ErrorsS[0] and \
|
||||||
Pick.time_errors.uncertainty <= ErrorsS[1]:
|
Pick.time_errors.uncertainty <= ErrorsS[1]:
|
||||||
Sw1.append(Pick.time_errors.uncertainty)
|
Sw1.append(Pick.time_errors.uncertainty)
|
||||||
elif Pick.time_errors.uncertainty > ErrorsS[1] and \
|
elif Pick.time_errors.uncertainty > ErrorsS[1] and \
|
||||||
Pick.time_errors.uncertainty <= ErrorsS[2]:
|
Pick.time_errors.uncertainty <= ErrorsS[2]:
|
||||||
Sw2.append(Pick.time_errors.uncertainty)
|
Sw2.append(Pick.time_errors.uncertainty)
|
||||||
elif Pick.time_errors.uncertainty > ErrorsS[2] and \
|
elif Pick.time_errors.uncertainty > ErrorsS[2] and \
|
||||||
Pick.time_errors.uncertainty <= ErrorsS[3]:
|
Pick.time_errors.uncertainty <= ErrorsS[3]:
|
||||||
Sw3.append(Pick.time_errors.uncertainty)
|
Sw3.append(Pick.time_errors.uncertainty)
|
||||||
elif Pick.time_errors.uncertainty > ErrorsS[3]:
|
elif Pick.time_errors.uncertainty > ErrorsS[3]:
|
||||||
Sw4.append(Pick.time_errors.uncertainty)
|
Sw4.append(Pick.time_errors.uncertainty)
|
||||||
else:
|
else:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
@ -133,7 +133,6 @@ def getQualitiesfromxml(path):
|
|||||||
plt.xticks(y_pos, weights)
|
plt.xticks(y_pos, weights)
|
||||||
plt.xlim([-0.5, 4.5])
|
plt.xlim([-0.5, 4.5])
|
||||||
plt.xlabel('Qualities')
|
plt.xlabel('Qualities')
|
||||||
plt.title('{0} P-Qualities, {1} S-Qualities'.format(numPweights, numSweights))
|
plt.title('{0} P-Qualities, {1} S-Qualities'.format(numPweights, numSweights))
|
||||||
plt.legend([p1, p2], ['P-Weights', 'S-Weights'])
|
plt.legend([p1, p2], ['P-Weights', 'S-Weights'])
|
||||||
plt.show()
|
plt.show()
|
||||||
|
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
import glob
|
import glob
|
||||||
|
import os
|
||||||
|
import warnings
|
||||||
|
|
||||||
import matplotlib.pyplot as plt
|
import matplotlib.pyplot as plt
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import obspy.core.event as ope
|
import obspy.core.event as ope
|
||||||
import os
|
|
||||||
import scipy.io as sio
|
import scipy.io as sio
|
||||||
import warnings
|
|
||||||
from obspy.core import UTCDateTime
|
from obspy.core import UTCDateTime
|
||||||
from obspy.core.event import read_events
|
from obspy.core.event import read_events
|
||||||
from obspy.core.util import AttribDict
|
from obspy.core.util import AttribDict
|
||||||
@ -507,14 +508,14 @@ def writephases(arrivals, fformat, filename, parameter=None, eventinfo=None):
|
|||||||
:param eventinfo: optional, needed for VELEST-cnv file
|
:param eventinfo: optional, needed for VELEST-cnv file
|
||||||
and FOCMEC- and HASH-input files
|
and FOCMEC- and HASH-input files
|
||||||
:type eventinfo: `obspy.core.event.Event` object
|
:type eventinfo: `obspy.core.event.Event` object
|
||||||
"""
|
"""
|
||||||
if fformat == 'NLLoc':
|
if fformat == 'NLLoc':
|
||||||
print("Writing phases to %s for NLLoc" % filename)
|
print("Writing phases to %s for NLLoc" % filename)
|
||||||
fid = open("%s" % filename, 'w')
|
fid = open("%s" % filename, 'w')
|
||||||
# write header
|
# write header
|
||||||
fid.write('# EQEVENT: %s Label: EQ%s Loc: X 0.00 Y 0.00 Z 10.00 OT 0.00 \n' %
|
fid.write('# EQEVENT: %s Label: EQ%s Loc: X 0.00 Y 0.00 Z 10.00 OT 0.00 \n' %
|
||||||
(parameter.get('database'), parameter.get('eventID')))
|
(parameter.get('database'), parameter.get('eventID')))
|
||||||
arrivals = chooseArrivals(arrivals) # MP MP what is chooseArrivals? It is not defined anywhere
|
arrivals = chooseArrivals(arrivals) # MP MP what is chooseArrivals? It is not defined anywhere
|
||||||
for key in arrivals:
|
for key in arrivals:
|
||||||
# P onsets
|
# P onsets
|
||||||
if arrivals[key].has_key('P'):
|
if arrivals[key].has_key('P'):
|
||||||
@ -568,20 +569,20 @@ def writephases(arrivals, fformat, filename, parameter=None, eventinfo=None):
|
|||||||
sweight = 0 # do not use pick
|
sweight = 0 # do not use pick
|
||||||
except KeyError as e:
|
except KeyError as e:
|
||||||
print(str(e) + '; no weight set during processing')
|
print(str(e) + '; no weight set during processing')
|
||||||
Ao = arrivals[key]['S']['Ao'] # peak-to-peak amplitude
|
Ao = arrivals[key]['S']['Ao'] # peak-to-peak amplitude
|
||||||
if Ao == None:
|
if Ao == None:
|
||||||
Ao = 0.0
|
Ao = 0.0
|
||||||
#fid.write('%s ? ? ? S %s %d%02d%02d %02d%02d %7.4f GAU 0 0 0 0 %d \n' % (key,
|
# fid.write('%s ? ? ? S %s %d%02d%02d %02d%02d %7.4f GAU 0 0 0 0 %d \n' % (key,
|
||||||
fid.write('%s ? ? ? S %s %d%02d%02d %02d%02d %7.4f GAU 0 %9.2f 0 0 %d \n' % (key,
|
fid.write('%s ? ? ? S %s %d%02d%02d %02d%02d %7.4f GAU 0 %9.2f 0 0 %d \n' % (key,
|
||||||
fm,
|
fm,
|
||||||
year,
|
year,
|
||||||
month,
|
month,
|
||||||
day,
|
day,
|
||||||
hh,
|
hh,
|
||||||
mm,
|
mm,
|
||||||
ss_ms,
|
ss_ms,
|
||||||
Ao,
|
Ao,
|
||||||
sweight))
|
sweight))
|
||||||
|
|
||||||
fid.close()
|
fid.close()
|
||||||
elif fformat == 'HYPO71':
|
elif fformat == 'HYPO71':
|
||||||
@ -590,7 +591,7 @@ def writephases(arrivals, fformat, filename, parameter=None, eventinfo=None):
|
|||||||
# write header
|
# write header
|
||||||
fid.write(' %s\n' %
|
fid.write(' %s\n' %
|
||||||
parameter.get('eventID'))
|
parameter.get('eventID'))
|
||||||
arrivals = chooseArrivals(arrivals) # MP MP what is chooseArrivals? It is not defined anywhere
|
arrivals = chooseArrivals(arrivals) # MP MP what is chooseArrivals? It is not defined anywhere
|
||||||
for key in arrivals:
|
for key in arrivals:
|
||||||
if arrivals[key]['P']['weight'] < 4:
|
if arrivals[key]['P']['weight'] < 4:
|
||||||
stat = key
|
stat = key
|
||||||
@ -765,7 +766,7 @@ def writephases(arrivals, fformat, filename, parameter=None, eventinfo=None):
|
|||||||
arrivals = picksdict_from_picks(evt)
|
arrivals = picksdict_from_picks(evt)
|
||||||
# check for automatic and manual picks
|
# check for automatic and manual picks
|
||||||
# prefer manual picks
|
# prefer manual picks
|
||||||
usedarrivals = chooseArrival(arrivals)
|
usedarrivals = chooseArrival(arrivals)
|
||||||
for key in usedarrivals:
|
for key in usedarrivals:
|
||||||
# P onsets
|
# P onsets
|
||||||
if usedarrivals[key].has_key('P'):
|
if usedarrivals[key].has_key('P'):
|
||||||
@ -811,9 +812,9 @@ def writephases(arrivals, fformat, filename, parameter=None, eventinfo=None):
|
|||||||
event = eventinfo['pylot_id']
|
event = eventinfo['pylot_id']
|
||||||
hddID = event.split('.')[0][1:5]
|
hddID = event.split('.')[0][1:5]
|
||||||
except:
|
except:
|
||||||
print ("Error 1111111!")
|
print("Error 1111111!")
|
||||||
hddID = "00000"
|
hddID = "00000"
|
||||||
# write header
|
# write header
|
||||||
fid.write('# %d %d %d %d %d %5.2f %7.4f +%6.4f %7.4f %4.2f 0.1 0.5 %4.2f %s\n' % (
|
fid.write('# %d %d %d %d %d %5.2f %7.4f +%6.4f %7.4f %4.2f 0.1 0.5 %4.2f %s\n' % (
|
||||||
stime.year, stime.month, stime.day, stime.hour, stime.minute, stime.second,
|
stime.year, stime.month, stime.day, stime.hour, stime.minute, stime.second,
|
||||||
eventsource['latitude'], eventsource['longitude'], eventsource['depth'] / 1000,
|
eventsource['latitude'], eventsource['longitude'], eventsource['depth'] / 1000,
|
||||||
@ -1005,6 +1006,7 @@ def writephases(arrivals, fformat, filename, parameter=None, eventinfo=None):
|
|||||||
fid1.close()
|
fid1.close()
|
||||||
fid2.close()
|
fid2.close()
|
||||||
|
|
||||||
|
|
||||||
def chooseArrival(arrivals):
|
def chooseArrival(arrivals):
|
||||||
"""
|
"""
|
||||||
takes arrivals and returns the manual picks if manual and automatic ones are there
|
takes arrivals and returns the manual picks if manual and automatic ones are there
|
||||||
|
@ -4,11 +4,12 @@
|
|||||||
import glob
|
import glob
|
||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
from obspy import read_events
|
from obspy import read_events
|
||||||
|
|
||||||
from pylot.core.io.phases import writephases
|
from pylot.core.io.phases import writephases
|
||||||
from pylot.core.util.utils import getPatternLine, runProgram
|
|
||||||
from pylot.core.util.gui import which
|
from pylot.core.util.gui import which
|
||||||
|
from pylot.core.util.utils import getPatternLine, runProgram
|
||||||
from pylot.core.util.version import get_git_version as _getVersionString
|
from pylot.core.util.version import get_git_version as _getVersionString
|
||||||
|
|
||||||
__version__ = _getVersionString()
|
__version__ = _getVersionString()
|
||||||
|
@ -9,21 +9,21 @@ function conglomerate utils.
|
|||||||
:author: MAGS2 EP3 working group / Ludger Kueperkoch
|
:author: MAGS2 EP3 working group / Ludger Kueperkoch
|
||||||
"""
|
"""
|
||||||
import copy
|
import copy
|
||||||
|
import traceback
|
||||||
|
|
||||||
import matplotlib.pyplot as plt
|
import matplotlib.pyplot as plt
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import traceback
|
from obspy import Trace
|
||||||
from obspy.taup import TauPyModel
|
from obspy.taup import TauPyModel
|
||||||
|
|
||||||
from pylot.core.pick.charfuns import CharacteristicFunction
|
from pylot.core.pick.charfuns import CharacteristicFunction
|
||||||
from pylot.core.pick.charfuns import HOScf, AICcf, ARZcf, ARHcf, AR3Ccf
|
from pylot.core.pick.charfuns import HOScf, AICcf, ARZcf, ARHcf, AR3Ccf
|
||||||
from pylot.core.pick.picker import AICPicker, PragPicker
|
from pylot.core.pick.picker import AICPicker, PragPicker
|
||||||
from pylot.core.pick.utils import checksignallength, checkZ4S, earllatepicker, \
|
from pylot.core.pick.utils import checksignallength, checkZ4S, earllatepicker, \
|
||||||
getSNR, fmpicker, checkPonsets, wadaticheck, get_pickparams, get_quality_class
|
getSNR, fmpicker, checkPonsets, wadaticheck, get_quality_class
|
||||||
from pylot.core.util.utils import getPatternLine, gen_Pool,\
|
from pylot.core.util.utils import getPatternLine, gen_Pool, \
|
||||||
get_Bool, identifyPhaseID, get_None, correct_iplot
|
get_Bool, identifyPhaseID, get_None, correct_iplot
|
||||||
|
|
||||||
from obspy.taup import TauPyModel
|
|
||||||
from obspy import Trace
|
|
||||||
|
|
||||||
def autopickevent(data, param, iplot=0, fig_dict=None, fig_dict_wadatijack=None, ncores=0, metadata=None, origin=None):
|
def autopickevent(data, param, iplot=0, fig_dict=None, fig_dict_wadatijack=None, ncores=0, metadata=None, origin=None):
|
||||||
"""
|
"""
|
||||||
@ -182,25 +182,25 @@ class PickingResults(dict):
|
|||||||
# TODO What are those?
|
# TODO What are those?
|
||||||
self.w0 = None
|
self.w0 = None
|
||||||
self.fc = None
|
self.fc = None
|
||||||
self.Ao = None # Wood-Anderson peak-to-peak amplitude
|
self.Ao = None # Wood-Anderson peak-to-peak amplitude
|
||||||
|
|
||||||
# Station information
|
# Station information
|
||||||
self.network = None
|
self.network = None
|
||||||
self.channel = None
|
self.channel = None
|
||||||
|
|
||||||
# pick information
|
# pick information
|
||||||
self.picker = 'auto' # type of pick
|
self.picker = 'auto' # type of pick
|
||||||
self.marked = []
|
self.marked = []
|
||||||
|
|
||||||
# pick results
|
# pick results
|
||||||
self.epp = None # earliest possible pick
|
self.epp = None # earliest possible pick
|
||||||
self.mpp = None # most likely onset
|
self.mpp = None # most likely onset
|
||||||
self.lpp = None # latest possible pick
|
self.lpp = None # latest possible pick
|
||||||
self.fm = 'N' # first motion polarity, can be set to 'U' (Up) or 'D' (Down)
|
self.fm = 'N' # first motion polarity, can be set to 'U' (Up) or 'D' (Down)
|
||||||
self.snr = None # signal-to-noise ratio of onset
|
self.snr = None # signal-to-noise ratio of onset
|
||||||
self.snrdb = None # signal-to-noise ratio of onset [dB]
|
self.snrdb = None # signal-to-noise ratio of onset [dB]
|
||||||
self.spe = None # symmetrized picking error
|
self.spe = None # symmetrized picking error
|
||||||
self.weight = 4 # weight of onset
|
self.weight = 4 # weight of onset
|
||||||
|
|
||||||
# to correctly provide dot access to dictionary attributes, all attribute access of the class is forwarded to the
|
# to correctly provide dot access to dictionary attributes, all attribute access of the class is forwarded to the
|
||||||
# dictionary
|
# dictionary
|
||||||
@ -335,9 +335,10 @@ class AutopickStation(object):
|
|||||||
"""
|
"""
|
||||||
waveform_data = {}
|
waveform_data = {}
|
||||||
for key in self.channelorder:
|
for key in self.channelorder:
|
||||||
waveform_data[key] = self.wfstream.select(component=key) # try ZNE first
|
waveform_data[key] = self.wfstream.select(component=key) # try ZNE first
|
||||||
if len(waveform_data[key]) == 0:
|
if len(waveform_data[key]) == 0:
|
||||||
waveform_data[key] = self.wfstream.select(component=str(self.channelorder[key])) # use 123 as second option
|
waveform_data[key] = self.wfstream.select(
|
||||||
|
component=str(self.channelorder[key])) # use 123 as second option
|
||||||
return waveform_data['Z'], waveform_data['N'], waveform_data['E']
|
return waveform_data['Z'], waveform_data['N'], waveform_data['E']
|
||||||
|
|
||||||
def get_traces_from_streams(self):
|
def get_traces_from_streams(self):
|
||||||
@ -524,7 +525,7 @@ class AutopickStation(object):
|
|||||||
|
|
||||||
self.plot_pick_results()
|
self.plot_pick_results()
|
||||||
self.finish_picking()
|
self.finish_picking()
|
||||||
return [{'P': self.p_results, 'S':self.s_results}, self.ztrace.stats.station]
|
return [{'P': self.p_results, 'S': self.s_results}, self.ztrace.stats.station]
|
||||||
|
|
||||||
def finish_picking(self):
|
def finish_picking(self):
|
||||||
|
|
||||||
@ -573,7 +574,7 @@ class AutopickStation(object):
|
|||||||
|
|
||||||
self.s_results.channel = self.etrace.stats.channel
|
self.s_results.channel = self.etrace.stats.channel
|
||||||
self.s_results.network = self.etrace.stats.network
|
self.s_results.network = self.etrace.stats.network
|
||||||
self.s_results.fm = None # override default value 'N'
|
self.s_results.fm = None # override default value 'N'
|
||||||
|
|
||||||
def plot_pick_results(self):
|
def plot_pick_results(self):
|
||||||
if self.iplot > 0:
|
if self.iplot > 0:
|
||||||
@ -588,12 +589,14 @@ class AutopickStation(object):
|
|||||||
plt_flag = 0
|
plt_flag = 0
|
||||||
fig._tight = True
|
fig._tight = True
|
||||||
ax1 = fig.add_subplot(311)
|
ax1 = fig.add_subplot(311)
|
||||||
tdata = np.linspace(start=0, stop=self.ztrace.stats.endtime-self.ztrace.stats.starttime, num=self.ztrace.stats.npts)
|
tdata = np.linspace(start=0, stop=self.ztrace.stats.endtime - self.ztrace.stats.starttime,
|
||||||
|
num=self.ztrace.stats.npts)
|
||||||
# plot tapered trace filtered with bpz2 filter settings
|
# plot tapered trace filtered with bpz2 filter settings
|
||||||
ax1.plot(tdata, self.tr_filt_z_bpz2.data/max(self.tr_filt_z_bpz2.data), color=linecolor, linewidth=0.7, label='Data')
|
ax1.plot(tdata, self.tr_filt_z_bpz2.data / max(self.tr_filt_z_bpz2.data), color=linecolor, linewidth=0.7,
|
||||||
|
label='Data')
|
||||||
if self.p_results.weight < 4:
|
if self.p_results.weight < 4:
|
||||||
# plot CF of initial onset (HOScf or ARZcf)
|
# plot CF of initial onset (HOScf or ARZcf)
|
||||||
ax1.plot(self.cf1.getTimeArray(), self.cf1.getCF()/max(self.cf1.getCF()), 'b', label='CF1')
|
ax1.plot(self.cf1.getTimeArray(), self.cf1.getCF() / max(self.cf1.getCF()), 'b', label='CF1')
|
||||||
if self.p_data.p_aic_plot_flag == 1:
|
if self.p_data.p_aic_plot_flag == 1:
|
||||||
aicpick = self.p_data.aicpick
|
aicpick = self.p_data.aicpick
|
||||||
refPpick = self.p_data.refPpick
|
refPpick = self.p_data.refPpick
|
||||||
@ -631,23 +634,28 @@ class AutopickStation(object):
|
|||||||
if self.horizontal_traces_exist() and self.s_data.Sflag == 1:
|
if self.horizontal_traces_exist() and self.s_data.Sflag == 1:
|
||||||
# plot E trace
|
# plot E trace
|
||||||
ax2 = fig.add_subplot(3, 1, 2, sharex=ax1)
|
ax2 = fig.add_subplot(3, 1, 2, sharex=ax1)
|
||||||
th1data = np.linspace(0, self.etrace.stats.endtime-self.etrace.stats.starttime, self.etrace.stats.npts)
|
th1data = np.linspace(0, self.etrace.stats.endtime - self.etrace.stats.starttime,
|
||||||
|
self.etrace.stats.npts)
|
||||||
# plot filtered and tapered waveform
|
# plot filtered and tapered waveform
|
||||||
ax2.plot(th1data, self.etrace.data / max(self.etrace.data), color=linecolor, linewidth=0.7, label='Data')
|
ax2.plot(th1data, self.etrace.data / max(self.etrace.data), color=linecolor, linewidth=0.7,
|
||||||
|
label='Data')
|
||||||
if self.p_results.weight < 4:
|
if self.p_results.weight < 4:
|
||||||
# plot initial CF (ARHcf or AR3Ccf)
|
# plot initial CF (ARHcf or AR3Ccf)
|
||||||
ax2.plot(self.arhcf1.getTimeArray(), self.arhcf1.getCF() / max(self.arhcf1.getCF()), 'b', label='CF1')
|
ax2.plot(self.arhcf1.getTimeArray(), self.arhcf1.getCF() / max(self.arhcf1.getCF()), 'b',
|
||||||
|
label='CF1')
|
||||||
if self.s_data.aicSflag == 1 and self.s_results.weight <= 4:
|
if self.s_data.aicSflag == 1 and self.s_results.weight <= 4:
|
||||||
aicarhpick = self.aicarhpick
|
aicarhpick = self.aicarhpick
|
||||||
refSpick = self.refSpick
|
refSpick = self.refSpick
|
||||||
# plot second cf, used for determing precise onset (ARHcf or AR3Ccf)
|
# plot second cf, used for determing precise onset (ARHcf or AR3Ccf)
|
||||||
ax2.plot(self.arhcf2.getTimeArray(), self.arhcf2.getCF() / max(self.arhcf2.getCF()), 'm', label='CF2')
|
ax2.plot(self.arhcf2.getTimeArray(), self.arhcf2.getCF() / max(self.arhcf2.getCF()), 'm',
|
||||||
|
label='CF2')
|
||||||
# plot preliminary onset time, calculated from CF1
|
# plot preliminary onset time, calculated from CF1
|
||||||
ax2.plot([aicarhpick.getpick(), aicarhpick.getpick()], [-1, 1], 'g', label='Initial S Onset')
|
ax2.plot([aicarhpick.getpick(), aicarhpick.getpick()], [-1, 1], 'g', label='Initial S Onset')
|
||||||
ax2.plot([aicarhpick.getpick() - 0.5, aicarhpick.getpick() + 0.5], [1, 1], 'g')
|
ax2.plot([aicarhpick.getpick() - 0.5, aicarhpick.getpick() + 0.5], [1, 1], 'g')
|
||||||
ax2.plot([aicarhpick.getpick() - 0.5, aicarhpick.getpick() + 0.5], [-1, -1], 'g')
|
ax2.plot([aicarhpick.getpick() - 0.5, aicarhpick.getpick() + 0.5], [-1, -1], 'g')
|
||||||
# plot precise onset time, calculated from CF2
|
# plot precise onset time, calculated from CF2
|
||||||
ax2.plot([refSpick.getpick(), refSpick.getpick()], [-1.3, 1.3], 'g', linewidth=2, label='Final S Pick')
|
ax2.plot([refSpick.getpick(), refSpick.getpick()], [-1.3, 1.3], 'g', linewidth=2,
|
||||||
|
label='Final S Pick')
|
||||||
ax2.plot([refSpick.getpick() - 0.5, refSpick.getpick() + 0.5], [1.3, 1.3], 'g', linewidth=2)
|
ax2.plot([refSpick.getpick() - 0.5, refSpick.getpick() + 0.5], [1.3, 1.3], 'g', linewidth=2)
|
||||||
ax2.plot([refSpick.getpick() - 0.5, refSpick.getpick() + 0.5], [-1.3, -1.3], 'g', linewidth=2)
|
ax2.plot([refSpick.getpick() - 0.5, refSpick.getpick() + 0.5], [-1.3, -1.3], 'g', linewidth=2)
|
||||||
ax2.plot([self.s_results.lpp, self.s_results.lpp], [-1.1, 1.1], 'g--', label='lpp')
|
ax2.plot([self.s_results.lpp, self.s_results.lpp], [-1.1, 1.1], 'g--', label='lpp')
|
||||||
@ -667,15 +675,19 @@ class AutopickStation(object):
|
|||||||
|
|
||||||
# plot N trace
|
# plot N trace
|
||||||
ax3 = fig.add_subplot(3, 1, 3, sharex=ax1)
|
ax3 = fig.add_subplot(3, 1, 3, sharex=ax1)
|
||||||
th2data= np.linspace(0, self.ntrace.stats.endtime-self.ntrace.stats.starttime, self.ntrace.stats.npts)
|
th2data = np.linspace(0, self.ntrace.stats.endtime - self.ntrace.stats.starttime,
|
||||||
|
self.ntrace.stats.npts)
|
||||||
# plot trace
|
# plot trace
|
||||||
ax3.plot(th2data, self.ntrace.data / max(self.ntrace.data), color=linecolor, linewidth=0.7, label='Data')
|
ax3.plot(th2data, self.ntrace.data / max(self.ntrace.data), color=linecolor, linewidth=0.7,
|
||||||
|
label='Data')
|
||||||
if self.p_results.weight < 4:
|
if self.p_results.weight < 4:
|
||||||
p22, = ax3.plot(self.arhcf1.getTimeArray(), self.arhcf1.getCF() / max(self.arhcf1.getCF()), 'b', label='CF1')
|
p22, = ax3.plot(self.arhcf1.getTimeArray(), self.arhcf1.getCF() / max(self.arhcf1.getCF()), 'b',
|
||||||
|
label='CF1')
|
||||||
if self.s_data.aicSflag == 1:
|
if self.s_data.aicSflag == 1:
|
||||||
aicarhpick = self.aicarhpick
|
aicarhpick = self.aicarhpick
|
||||||
refSpick = self.refSpick
|
refSpick = self.refSpick
|
||||||
ax3.plot(self.arhcf2.getTimeArray(), self.arhcf2.getCF() / max(self.arhcf2.getCF()), 'm', label='CF2')
|
ax3.plot(self.arhcf2.getTimeArray(), self.arhcf2.getCF() / max(self.arhcf2.getCF()), 'm',
|
||||||
|
label='CF2')
|
||||||
ax3.plot([aicarhpick.getpick(), aicarhpick.getpick()], [-1, 1], 'g', label='Initial S Onset')
|
ax3.plot([aicarhpick.getpick(), aicarhpick.getpick()], [-1, 1], 'g', label='Initial S Onset')
|
||||||
ax3.plot([aicarhpick.getpick() - 0.5, aicarhpick.getpick() + 0.5], [1, 1], 'g')
|
ax3.plot([aicarhpick.getpick() - 0.5, aicarhpick.getpick() + 0.5], [1, 1], 'g')
|
||||||
ax3.plot([aicarhpick.getpick() - 0.5, aicarhpick.getpick() + 0.5], [-1, -1], 'g')
|
ax3.plot([aicarhpick.getpick() - 0.5, aicarhpick.getpick() + 0.5], [-1, -1], 'g')
|
||||||
@ -716,7 +728,8 @@ class AutopickStation(object):
|
|||||||
if aicpick.getpick() is None:
|
if aicpick.getpick() is None:
|
||||||
msg = "Bad initial (AIC) P-pick, skipping this onset!\nAIC-SNR={0}, AIC-Slope={1}counts/s\n " \
|
msg = "Bad initial (AIC) P-pick, skipping this onset!\nAIC-SNR={0}, AIC-Slope={1}counts/s\n " \
|
||||||
"(min. AIC-SNR={2}, min. AIC-Slope={3}counts/s)"
|
"(min. AIC-SNR={2}, min. AIC-Slope={3}counts/s)"
|
||||||
msg = msg.format(aicpick.getSNR(), aicpick.getSlope(), self.pickparams["minAICPSNR"], self.pickparams["minAICPslope"])
|
msg = msg.format(aicpick.getSNR(), aicpick.getSlope(), self.pickparams["minAICPSNR"],
|
||||||
|
self.pickparams["minAICPslope"])
|
||||||
self.vprint(msg)
|
self.vprint(msg)
|
||||||
return 0
|
return 0
|
||||||
# Quality check initial pick with minimum signal length
|
# Quality check initial pick with minimum signal length
|
||||||
@ -726,14 +739,16 @@ class AutopickStation(object):
|
|||||||
if len(self.nstream) == 0 or len(self.estream) == 0:
|
if len(self.nstream) == 0 or len(self.estream) == 0:
|
||||||
msg = 'One or more horizontal component(s) missing!\n' \
|
msg = 'One or more horizontal component(s) missing!\n' \
|
||||||
'Signal length only checked on vertical component!\n' \
|
'Signal length only checked on vertical component!\n' \
|
||||||
'Decreasing minsiglengh from {0} to {1}'\
|
'Decreasing minsiglengh from {0} to {1}' \
|
||||||
.format(minsiglength, minsiglength / 2)
|
.format(minsiglength, minsiglength / 2)
|
||||||
self.vprint(msg)
|
self.vprint(msg)
|
||||||
minsiglength = minsiglength / 2
|
minsiglength = minsiglength / 2
|
||||||
else:
|
else:
|
||||||
# filter, taper other traces as well since signal length is compared on all traces
|
# filter, taper other traces as well since signal length is compared on all traces
|
||||||
trH1_filt, _ = self.prepare_wfstream(self.estream, freqmin=self.pickparams["bph1"][0], freqmax=self.pickparams["bph1"][1])
|
trH1_filt, _ = self.prepare_wfstream(self.estream, freqmin=self.pickparams["bph1"][0],
|
||||||
trH2_filt, _ = self.prepare_wfstream(self.nstream, freqmin=self.pickparams["bph1"][0], freqmax=self.pickparams["bph1"][1])
|
freqmax=self.pickparams["bph1"][1])
|
||||||
|
trH2_filt, _ = self.prepare_wfstream(self.nstream, freqmin=self.pickparams["bph1"][0],
|
||||||
|
freqmax=self.pickparams["bph1"][1])
|
||||||
zne += trH1_filt
|
zne += trH1_filt
|
||||||
zne += trH2_filt
|
zne += trH2_filt
|
||||||
minsiglength = minsiglength
|
minsiglength = minsiglength
|
||||||
@ -819,15 +834,18 @@ class AutopickStation(object):
|
|||||||
# get preliminary onset time from AIC-CF
|
# get preliminary onset time from AIC-CF
|
||||||
self.set_current_figure('aicFig')
|
self.set_current_figure('aicFig')
|
||||||
aicpick = AICPicker(aiccf, self.pickparams["tsnrz"], self.pickparams["pickwinP"], self.iplot,
|
aicpick = AICPicker(aiccf, self.pickparams["tsnrz"], self.pickparams["pickwinP"], self.iplot,
|
||||||
Tsmooth=self.pickparams["aictsmooth"], fig=self.current_figure, linecolor=self.current_linecolor)
|
Tsmooth=self.pickparams["aictsmooth"], fig=self.current_figure,
|
||||||
|
linecolor=self.current_linecolor)
|
||||||
# save aicpick for plotting later
|
# save aicpick for plotting later
|
||||||
self.p_data.aicpick = aicpick
|
self.p_data.aicpick = aicpick
|
||||||
# add pstart and pstop to aic plot
|
# add pstart and pstop to aic plot
|
||||||
if self.current_figure:
|
if self.current_figure:
|
||||||
# TODO remove plotting from picking, make own plot function
|
# TODO remove plotting from picking, make own plot function
|
||||||
for ax in self.current_figure.axes:
|
for ax in self.current_figure.axes:
|
||||||
ax.vlines(self.pickparams["pstart"], ax.get_ylim()[0], ax.get_ylim()[1], color='c', linestyles='dashed', label='P start')
|
ax.vlines(self.pickparams["pstart"], ax.get_ylim()[0], ax.get_ylim()[1], color='c', linestyles='dashed',
|
||||||
ax.vlines(self.pickparams["pstop"], ax.get_ylim()[0], ax.get_ylim()[1], color='c', linestyles='dashed', label='P stop')
|
label='P start')
|
||||||
|
ax.vlines(self.pickparams["pstop"], ax.get_ylim()[0], ax.get_ylim()[1], color='c', linestyles='dashed',
|
||||||
|
label='P stop')
|
||||||
ax.legend(loc=1)
|
ax.legend(loc=1)
|
||||||
|
|
||||||
Pflag = self._pick_p_quality_control(aicpick, z_copy, tr_filt)
|
Pflag = self._pick_p_quality_control(aicpick, z_copy, tr_filt)
|
||||||
@ -841,7 +859,8 @@ class AutopickStation(object):
|
|||||||
error_msg = 'AIC P onset slope to small: got {}, min {}'.format(slope, self.pickparams["minAICPslope"])
|
error_msg = 'AIC P onset slope to small: got {}, min {}'.format(slope, self.pickparams["minAICPslope"])
|
||||||
raise PickingFailedException(error_msg)
|
raise PickingFailedException(error_msg)
|
||||||
if aicpick.getSNR() < self.pickparams["minAICPSNR"]:
|
if aicpick.getSNR() < self.pickparams["minAICPSNR"]:
|
||||||
error_msg = 'AIC P onset SNR to small: got {}, min {}'.format(aicpick.getSNR(), self.pickparams["minAICPSNR"])
|
error_msg = 'AIC P onset SNR to small: got {}, min {}'.format(aicpick.getSNR(),
|
||||||
|
self.pickparams["minAICPSNR"])
|
||||||
raise PickingFailedException(error_msg)
|
raise PickingFailedException(error_msg)
|
||||||
|
|
||||||
self.p_data.p_aic_plot_flag = 1
|
self.p_data.p_aic_plot_flag = 1
|
||||||
@ -849,7 +868,8 @@ class AutopickStation(object):
|
|||||||
'autopickstation: re-filtering vertical trace...'.format(aicpick.getSlope(), aicpick.getSNR())
|
'autopickstation: re-filtering vertical trace...'.format(aicpick.getSlope(), aicpick.getSNR())
|
||||||
self.vprint(msg)
|
self.vprint(msg)
|
||||||
# refilter waveform with larger bandpass
|
# refilter waveform with larger bandpass
|
||||||
tr_filt, z_copy = self.prepare_wfstream(self.zstream, freqmin=self.pickparams["bpz2"][0], freqmax=self.pickparams["bpz2"][1])
|
tr_filt, z_copy = self.prepare_wfstream(self.zstream, freqmin=self.pickparams["bpz2"][0],
|
||||||
|
freqmax=self.pickparams["bpz2"][1])
|
||||||
# save filtered trace in instance for later plotting
|
# save filtered trace in instance for later plotting
|
||||||
self.tr_filt_z_bpz2 = tr_filt
|
self.tr_filt_z_bpz2 = tr_filt
|
||||||
# determine new times around initial onset
|
# determine new times around initial onset
|
||||||
@ -861,25 +881,29 @@ class AutopickStation(object):
|
|||||||
else:
|
else:
|
||||||
self.cf2 = None
|
self.cf2 = None
|
||||||
assert isinstance(self.cf2, CharacteristicFunction), 'cf2 is not set correctly: maybe the algorithm name () is ' \
|
assert isinstance(self.cf2, CharacteristicFunction), 'cf2 is not set correctly: maybe the algorithm name () is ' \
|
||||||
'corrupted'.format(self.pickparams["algoP"])
|
'corrupted'.format(self.pickparams["algoP"])
|
||||||
self.set_current_figure('refPpick')
|
self.set_current_figure('refPpick')
|
||||||
# get refined onset time from CF2
|
# get refined onset time from CF2
|
||||||
refPpick = PragPicker(self.cf2, self.pickparams["tsnrz"], self.pickparams["pickwinP"], self.iplot, self.pickparams["ausP"],
|
refPpick = PragPicker(self.cf2, self.pickparams["tsnrz"], self.pickparams["pickwinP"], self.iplot,
|
||||||
self.pickparams["tsmoothP"], aicpick.getpick(), self.current_figure, self.current_linecolor)
|
self.pickparams["ausP"],
|
||||||
|
self.pickparams["tsmoothP"], aicpick.getpick(), self.current_figure,
|
||||||
|
self.current_linecolor)
|
||||||
# save PragPicker result for plotting
|
# save PragPicker result for plotting
|
||||||
self.p_data.refPpick = refPpick
|
self.p_data.refPpick = refPpick
|
||||||
self.p_results.mpp = refPpick.getpick()
|
self.p_results.mpp = refPpick.getpick()
|
||||||
if self.p_results.mpp is None:
|
if self.p_results.mpp is None:
|
||||||
msg = 'Bad initial (AIC) P-pick, skipping this onset!\n AIC-SNR={}, AIC-Slope={}counts/s\n' \
|
msg = 'Bad initial (AIC) P-pick, skipping this onset!\n AIC-SNR={}, AIC-Slope={}counts/s\n' \
|
||||||
'(min. AIC-SNR={}, min. AIC-Slope={}counts/s)'
|
'(min. AIC-SNR={}, min. AIC-Slope={}counts/s)'
|
||||||
msg.format(aicpick.getSNR(), aicpick.getSlope(), self.pickparams["minAICPSNR"], self.pickparams["minAICPslope"])
|
msg.format(aicpick.getSNR(), aicpick.getSlope(), self.pickparams["minAICPSNR"],
|
||||||
|
self.pickparams["minAICPslope"])
|
||||||
self.vprint(msg)
|
self.vprint(msg)
|
||||||
self.s_data.Sflag = 0
|
self.s_data.Sflag = 0
|
||||||
raise PickingFailedException(msg)
|
raise PickingFailedException(msg)
|
||||||
# quality assessment, get earliest/latest pick and symmetrized uncertainty
|
# quality assessment, get earliest/latest pick and symmetrized uncertainty
|
||||||
#todo quality assessment in own function
|
# todo quality assessment in own function
|
||||||
self.set_current_figure('el_Ppick')
|
self.set_current_figure('el_Ppick')
|
||||||
elpicker_results = earllatepicker(z_copy, self.pickparams["nfacP"], self.pickparams["tsnrz"], self.p_results.mpp,
|
elpicker_results = earllatepicker(z_copy, self.pickparams["nfacP"], self.pickparams["tsnrz"],
|
||||||
|
self.p_results.mpp,
|
||||||
self.iplot, fig=self.current_figure, linecolor=self.current_linecolor)
|
self.iplot, fig=self.current_figure, linecolor=self.current_linecolor)
|
||||||
self.p_results.epp, self.p_results.lpp, self.p_results.spe = elpicker_results
|
self.p_results.epp, self.p_results.lpp, self.p_results.spe = elpicker_results
|
||||||
snr_results = getSNR(z_copy, self.pickparams["tsnrz"], self.p_results.mpp)
|
snr_results = getSNR(z_copy, self.pickparams["tsnrz"], self.p_results.mpp)
|
||||||
@ -887,7 +911,8 @@ class AutopickStation(object):
|
|||||||
|
|
||||||
# weight P-onset using symmetric error
|
# weight P-onset using symmetric error
|
||||||
self.p_results.weight = get_quality_class(self.p_results.spe, self.pickparams["timeerrorsP"])
|
self.p_results.weight = get_quality_class(self.p_results.spe, self.pickparams["timeerrorsP"])
|
||||||
if self.p_results.weight <= self.pickparams["minfmweight"] and self.p_results.snr >= self.pickparams["minFMSNR"]:
|
if self.p_results.weight <= self.pickparams["minfmweight"] and self.p_results.snr >= self.pickparams[
|
||||||
|
"minFMSNR"]:
|
||||||
# if SNR is high enough, try to determine first motion of onset
|
# if SNR is high enough, try to determine first motion of onset
|
||||||
self.set_current_figure('fm_picker')
|
self.set_current_figure('fm_picker')
|
||||||
self.p_results.fm = fmpicker(self.zstream, z_copy, self.pickparams["fmpickwin"], self.p_results.mpp,
|
self.p_results.fm = fmpicker(self.zstream, z_copy, self.pickparams["fmpickwin"], self.p_results.mpp,
|
||||||
@ -960,7 +985,7 @@ class AutopickStation(object):
|
|||||||
trH1_filt, _ = self.prepare_wfstream(self.zstream, filter_freq_min, filter_freq_max)
|
trH1_filt, _ = self.prepare_wfstream(self.zstream, filter_freq_min, filter_freq_max)
|
||||||
trH2_filt, _ = self.prepare_wfstream(self.estream, filter_freq_min, filter_freq_max)
|
trH2_filt, _ = self.prepare_wfstream(self.estream, filter_freq_min, filter_freq_max)
|
||||||
trH3_filt, _ = self.prepare_wfstream(self.nstream, filter_freq_min, filter_freq_max)
|
trH3_filt, _ = self.prepare_wfstream(self.nstream, filter_freq_min, filter_freq_max)
|
||||||
h_copy =self. hdat.copy()
|
h_copy = self.hdat.copy()
|
||||||
h_copy[0].data = trH1_filt.data
|
h_copy[0].data = trH1_filt.data
|
||||||
h_copy[1].data = trH2_filt.data
|
h_copy[1].data = trH2_filt.data
|
||||||
h_copy[2].data = trH3_filt.data
|
h_copy[2].data = trH3_filt.data
|
||||||
@ -1115,7 +1140,8 @@ class AutopickStation(object):
|
|||||||
# get preliminary onset time from AIC cf
|
# get preliminary onset time from AIC cf
|
||||||
self.set_current_figure('aicARHfig')
|
self.set_current_figure('aicARHfig')
|
||||||
aicarhpick = AICPicker(haiccf, self.pickparams["tsnrh"], self.pickparams["pickwinS"], self.iplot,
|
aicarhpick = AICPicker(haiccf, self.pickparams["tsnrh"], self.pickparams["pickwinS"], self.iplot,
|
||||||
Tsmooth=self.pickparams["aictsmoothS"], fig=self.current_figure, linecolor=self.current_linecolor)
|
Tsmooth=self.pickparams["aictsmoothS"], fig=self.current_figure,
|
||||||
|
linecolor=self.current_linecolor)
|
||||||
# save pick for later plotting
|
# save pick for later plotting
|
||||||
self.aicarhpick = aicarhpick
|
self.aicarhpick = aicarhpick
|
||||||
|
|
||||||
@ -1126,8 +1152,10 @@ class AutopickStation(object):
|
|||||||
|
|
||||||
# get refined onset time from CF2
|
# get refined onset time from CF2
|
||||||
self.set_current_figure('refSpick')
|
self.set_current_figure('refSpick')
|
||||||
refSpick = PragPicker(arhcf2, self.pickparams["tsnrh"], self.pickparams["pickwinS"], self.iplot, self.pickparams["ausS"],
|
refSpick = PragPicker(arhcf2, self.pickparams["tsnrh"], self.pickparams["pickwinS"], self.iplot,
|
||||||
self.pickparams["tsmoothS"], aicarhpick.getpick(), self.current_figure, self.current_linecolor)
|
self.pickparams["ausS"],
|
||||||
|
self.pickparams["tsmoothS"], aicarhpick.getpick(), self.current_figure,
|
||||||
|
self.current_linecolor)
|
||||||
# save refSpick for later plotitng
|
# save refSpick for later plotitng
|
||||||
self.refSpick = refSpick
|
self.refSpick = refSpick
|
||||||
self.s_results.mpp = refSpick.getpick()
|
self.s_results.mpp = refSpick.getpick()
|
||||||
@ -1151,7 +1179,6 @@ class AutopickStation(object):
|
|||||||
self.current_linecolor = plot_style['linecolor']['rgba_mpl']
|
self.current_linecolor = plot_style['linecolor']['rgba_mpl']
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def autopickstation(wfstream, pickparam, verbose=False, iplot=0, fig_dict=None, metadata=None, origin=None):
|
def autopickstation(wfstream, pickparam, verbose=False, iplot=0, fig_dict=None, metadata=None, origin=None):
|
||||||
"""
|
"""
|
||||||
Main function to calculate picks for the station.
|
Main function to calculate picks for the station.
|
||||||
@ -1239,11 +1266,11 @@ def iteratepicker(wf, NLLocfile, picks, badpicks, pickparameter, fig_dict=None):
|
|||||||
print(
|
print(
|
||||||
"iteratepicker: The following picking parameters have been modified for iterative picking:")
|
"iteratepicker: The following picking parameters have been modified for iterative picking:")
|
||||||
print(
|
print(
|
||||||
"pstart: %fs => %fs" % (pstart_old, pickparameter.get('pstart')))
|
"pstart: %fs => %fs" % (pstart_old, pickparameter.get('pstart')))
|
||||||
print(
|
print(
|
||||||
"pstop: %fs => %fs" % (pstop_old, pickparameter.get('pstop')))
|
"pstop: %fs => %fs" % (pstop_old, pickparameter.get('pstop')))
|
||||||
print(
|
print(
|
||||||
"sstop: %fs => %fs" % (sstop_old, pickparameter.get('sstop')))
|
"sstop: %fs => %fs" % (sstop_old, pickparameter.get('sstop')))
|
||||||
print("pickwinP: %fs => %fs" % (
|
print("pickwinP: %fs => %fs" % (
|
||||||
pickwinP_old, pickparameter.get('pickwinP')))
|
pickwinP_old, pickparameter.get('pickwinP')))
|
||||||
print("Precalcwin: %fs => %fs" % (
|
print("Precalcwin: %fs => %fs" % (
|
||||||
|
@ -18,8 +18,8 @@ autoregressive prediction: application ot local and regional distances, Geophys.
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from scipy import signal
|
|
||||||
from obspy.core import Stream
|
from obspy.core import Stream
|
||||||
|
from scipy import signal
|
||||||
|
|
||||||
|
|
||||||
class CharacteristicFunction(object):
|
class CharacteristicFunction(object):
|
||||||
@ -159,7 +159,7 @@ class CharacteristicFunction(object):
|
|||||||
zz = self.orig_data.copy()
|
zz = self.orig_data.copy()
|
||||||
z1 = zz[0].copy()
|
z1 = zz[0].copy()
|
||||||
zz[0].data = z1.data[int(start):int(stop)]
|
zz[0].data = z1.data[int(start):int(stop)]
|
||||||
if zz[0].stats.npts == 0: # cut times do not fit data length!
|
if zz[0].stats.npts == 0: # cut times do not fit data length!
|
||||||
zz[0].data = z1.data # take entire data
|
zz[0].data = z1.data # take entire data
|
||||||
data = zz
|
data = zz
|
||||||
return data
|
return data
|
||||||
@ -241,7 +241,7 @@ class AICcf(CharacteristicFunction):
|
|||||||
ff = np.where(inf is True)
|
ff = np.where(inf is True)
|
||||||
if len(ff) >= 1:
|
if len(ff) >= 1:
|
||||||
cf[ff] = 0
|
cf[ff] = 0
|
||||||
|
|
||||||
self.cf = cf - np.mean(cf)
|
self.cf = cf - np.mean(cf)
|
||||||
self.xcf = x
|
self.xcf = x
|
||||||
|
|
||||||
@ -305,7 +305,7 @@ class HOScf(CharacteristicFunction):
|
|||||||
if ind.size:
|
if ind.size:
|
||||||
first = ind[0]
|
first = ind[0]
|
||||||
LTA[:first] = LTA[first]
|
LTA[:first] = LTA[first]
|
||||||
|
|
||||||
self.cf = LTA
|
self.cf = LTA
|
||||||
self.xcf = x
|
self.xcf = x
|
||||||
|
|
||||||
@ -313,7 +313,8 @@ class HOScf(CharacteristicFunction):
|
|||||||
class ARZcf(CharacteristicFunction):
|
class ARZcf(CharacteristicFunction):
|
||||||
|
|
||||||
def __init__(self, data, cut, t1, t2, pickparams):
|
def __init__(self, data, cut, t1, t2, pickparams):
|
||||||
super(ARZcf, self).__init__(data, cut, t1=t1, t2=t2, order=pickparams["Parorder"], fnoise=pickparams["addnoise"])
|
super(ARZcf, self).__init__(data, cut, t1=t1, t2=t2, order=pickparams["Parorder"],
|
||||||
|
fnoise=pickparams["addnoise"])
|
||||||
|
|
||||||
def calcCF(self, data):
|
def calcCF(self, data):
|
||||||
"""
|
"""
|
||||||
@ -448,7 +449,8 @@ class ARZcf(CharacteristicFunction):
|
|||||||
class ARHcf(CharacteristicFunction):
|
class ARHcf(CharacteristicFunction):
|
||||||
|
|
||||||
def __init__(self, data, cut, t1, t2, pickparams):
|
def __init__(self, data, cut, t1, t2, pickparams):
|
||||||
super(ARHcf, self).__init__(data, cut, t1=t1, t2=t2, order=pickparams["Sarorder"], fnoise=pickparams["addnoise"])
|
super(ARHcf, self).__init__(data, cut, t1=t1, t2=t2, order=pickparams["Sarorder"],
|
||||||
|
fnoise=pickparams["addnoise"])
|
||||||
|
|
||||||
def calcCF(self, data):
|
def calcCF(self, data):
|
||||||
"""
|
"""
|
||||||
@ -600,7 +602,8 @@ class ARHcf(CharacteristicFunction):
|
|||||||
class AR3Ccf(CharacteristicFunction):
|
class AR3Ccf(CharacteristicFunction):
|
||||||
|
|
||||||
def __init__(self, data, cut, t1, t2, pickparams):
|
def __init__(self, data, cut, t1, t2, pickparams):
|
||||||
super(AR3Ccf, self).__init__(data, cut, t1=t1, t2=t2, order=pickparams["Sarorder"], fnoise=pickparams["addnoise"])
|
super(AR3Ccf, self).__init__(data, cut, t1=t1, t2=t2, order=pickparams["Sarorder"],
|
||||||
|
fnoise=pickparams["addnoise"])
|
||||||
|
|
||||||
def calcCF(self, data):
|
def calcCF(self, data):
|
||||||
"""
|
"""
|
||||||
|
@ -2,10 +2,11 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
import copy
|
import copy
|
||||||
import matplotlib.pyplot as plt
|
|
||||||
import numpy as np
|
|
||||||
import operator
|
import operator
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
import numpy as np
|
||||||
from obspy.core import AttribDict
|
from obspy.core import AttribDict
|
||||||
|
|
||||||
from pylot.core.util.pdf import ProbabilityDensityFunction
|
from pylot.core.util.pdf import ProbabilityDensityFunction
|
||||||
@ -117,7 +118,7 @@ class Comparison(object):
|
|||||||
|
|
||||||
pdf_a = self.get('auto').generate_pdf_data(type)
|
pdf_a = self.get('auto').generate_pdf_data(type)
|
||||||
pdf_b = self.get('manu').generate_pdf_data(type)
|
pdf_b = self.get('manu').generate_pdf_data(type)
|
||||||
|
|
||||||
for station, phases in pdf_a.items():
|
for station, phases in pdf_a.items():
|
||||||
if station in pdf_b.keys():
|
if station in pdf_b.keys():
|
||||||
compare_pdf = dict()
|
compare_pdf = dict()
|
||||||
@ -400,6 +401,7 @@ class PDFstatistics(object):
|
|||||||
This object can be used to get various statistic values from probability density functions.
|
This object can be used to get various statistic values from probability density functions.
|
||||||
Takes a path as argument.
|
Takes a path as argument.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# TODO: change root to datapath
|
# TODO: change root to datapath
|
||||||
|
|
||||||
def __init__(self, directory):
|
def __init__(self, directory):
|
||||||
|
@ -19,9 +19,10 @@ calculated after Diehl & Kissling (2009).
|
|||||||
:author: MAGS2 EP3 working group / Ludger Kueperkoch
|
:author: MAGS2 EP3 working group / Ludger Kueperkoch
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import warnings
|
||||||
|
|
||||||
import matplotlib.pyplot as plt
|
import matplotlib.pyplot as plt
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import warnings
|
|
||||||
from scipy.signal import argrelmax, argrelmin
|
from scipy.signal import argrelmax, argrelmin
|
||||||
|
|
||||||
from pylot.core.pick.charfuns import CharacteristicFunction
|
from pylot.core.pick.charfuns import CharacteristicFunction
|
||||||
@ -476,7 +477,7 @@ class PragPicker(AutoPicker):
|
|||||||
cfpick_r = 0
|
cfpick_r = 0
|
||||||
cfpick_l = 0
|
cfpick_l = 0
|
||||||
lpickwindow = int(round(self.PickWindow / self.dt))
|
lpickwindow = int(round(self.PickWindow / self.dt))
|
||||||
#for i in range(max(np.insert(ipick, 0, 2)), min([ipick1 + lpickwindow + 1, len(self.cf) - 1])):
|
# for i in range(max(np.insert(ipick, 0, 2)), min([ipick1 + lpickwindow + 1, len(self.cf) - 1])):
|
||||||
# # local minimum
|
# # local minimum
|
||||||
# if self.cf[i + 1] > self.cf[i] <= self.cf[i - 1]:
|
# if self.cf[i + 1] > self.cf[i] <= self.cf[i - 1]:
|
||||||
# if cfsmooth[i - 1] * (1 + aus1) >= cfsmooth[i]:
|
# if cfsmooth[i - 1] * (1 + aus1) >= cfsmooth[i]:
|
||||||
@ -509,7 +510,7 @@ class PragPicker(AutoPicker):
|
|||||||
self.Pick = pick_l
|
self.Pick = pick_l
|
||||||
pickflag = 1
|
pickflag = 1
|
||||||
elif flagpick_l > 0 and flagpick_r > 0 and cfpick_l >= cfpick_r:
|
elif flagpick_l > 0 and flagpick_r > 0 and cfpick_l >= cfpick_r:
|
||||||
self.Pick = pick_r # MP MP there is no pick_r defined, commented out after commit of LK on 29.07.2020 (see above)
|
self.Pick = pick_r # MP MP there is no pick_r defined, commented out after commit of LK on 29.07.2020 (see above)
|
||||||
pickflag = 1
|
pickflag = 1
|
||||||
elif flagpick_l == 0 and flagpick_r > 0 and cfpick_l >= cfpick_r:
|
elif flagpick_l == 0 and flagpick_r > 0 and cfpick_l >= cfpick_r:
|
||||||
self.Pick = pick_l
|
self.Pick = pick_l
|
||||||
|
@ -9,10 +9,11 @@
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import warnings
|
import warnings
|
||||||
|
|
||||||
import matplotlib.pyplot as plt
|
import matplotlib.pyplot as plt
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from scipy.signal import argrelmax
|
|
||||||
from obspy.core import Stream, UTCDateTime
|
from obspy.core import Stream, UTCDateTime
|
||||||
|
from scipy.signal import argrelmax
|
||||||
|
|
||||||
from pylot.core.util.utils import get_Bool, get_None, SetChannelComponents
|
from pylot.core.util.utils import get_Bool, get_None, SetChannelComponents
|
||||||
|
|
||||||
@ -73,7 +74,7 @@ def earllatepicker(X, nfac, TSNR, Pick1, iplot=0, verbosity=1, fig=None, linecol
|
|||||||
|
|
||||||
x = X[0].data
|
x = X[0].data
|
||||||
t = np.linspace(0, X[0].stats.endtime - X[0].stats.starttime,
|
t = np.linspace(0, X[0].stats.endtime - X[0].stats.starttime,
|
||||||
X[0].stats.npts)
|
X[0].stats.npts)
|
||||||
inoise = getnoisewin(t, Pick1, TSNR[0], TSNR[1])
|
inoise = getnoisewin(t, Pick1, TSNR[0], TSNR[1])
|
||||||
# get signal window
|
# get signal window
|
||||||
isignal = getsignalwin(t, Pick1, TSNR[2])
|
isignal = getsignalwin(t, Pick1, TSNR[2])
|
||||||
@ -218,7 +219,7 @@ def fmpicker(Xraw, Xfilt, pickwin, Pick, iplot=0, fig=None, linecolor='k'):
|
|||||||
xraw = Xraw[0].data
|
xraw = Xraw[0].data
|
||||||
xfilt = Xfilt[0].data
|
xfilt = Xfilt[0].data
|
||||||
t = np.linspace(0, Xraw[0].stats.endtime - Xraw[0].stats.starttime,
|
t = np.linspace(0, Xraw[0].stats.endtime - Xraw[0].stats.starttime,
|
||||||
Xraw[0].stats.npts)
|
Xraw[0].stats.npts)
|
||||||
# get pick window
|
# get pick window
|
||||||
ipick = np.where((t <= min([Pick + pickwin, len(Xraw[0])])) & (t >= Pick))
|
ipick = np.where((t <= min([Pick + pickwin, len(Xraw[0])])) & (t >= Pick))
|
||||||
if len(ipick[0]) <= 1:
|
if len(ipick[0]) <= 1:
|
||||||
@ -536,9 +537,10 @@ def getslopewin(Tcf, Pick, tslope):
|
|||||||
:rtype: `numpy.ndarray`
|
:rtype: `numpy.ndarray`
|
||||||
"""
|
"""
|
||||||
# TODO: fill out docstring
|
# TODO: fill out docstring
|
||||||
slope = np.where( (Tcf <= min(Pick + tslope, Tcf[-1])) & (Tcf >= Pick) )
|
slope = np.where((Tcf <= min(Pick + tslope, Tcf[-1])) & (Tcf >= Pick))
|
||||||
return slope[0]
|
return slope[0]
|
||||||
|
|
||||||
|
|
||||||
def getResolutionWindow(snr, extent):
|
def getResolutionWindow(snr, extent):
|
||||||
"""
|
"""
|
||||||
Produce the half of the time resolution window width from given SNR value
|
Produce the half of the time resolution window width from given SNR value
|
||||||
@ -848,7 +850,7 @@ def checksignallength(X, pick, minsiglength, pickparams, iplot=0, fig=None, line
|
|||||||
print("Presumably picked noise peak, pick is rejected!")
|
print("Presumably picked noise peak, pick is rejected!")
|
||||||
print("(min. signal length required: %s s)" % minsiglength)
|
print("(min. signal length required: %s s)" % minsiglength)
|
||||||
returnflag = 0
|
returnflag = 0
|
||||||
else:
|
else:
|
||||||
# calculate minimum adjusted signal level
|
# calculate minimum adjusted signal level
|
||||||
minsiglevel = np.mean(rms[inoise]) * nfac
|
minsiglevel = np.mean(rms[inoise]) * nfac
|
||||||
# minimum adjusted number of samples over minimum signal level
|
# minimum adjusted number of samples over minimum signal level
|
||||||
@ -1207,7 +1209,7 @@ def checkZ4S(X, pick, pickparams, iplot, fig=None, linecolor='k'):
|
|||||||
rms = rms_dict[key]
|
rms = rms_dict[key]
|
||||||
trace = traces_dict[key]
|
trace = traces_dict[key]
|
||||||
t = np.linspace(diff_dict[key], trace.stats.endtime - trace.stats.starttime + diff_dict[key],
|
t = np.linspace(diff_dict[key], trace.stats.endtime - trace.stats.starttime + diff_dict[key],
|
||||||
trace.stats.npts)
|
trace.stats.npts)
|
||||||
if i == 0:
|
if i == 0:
|
||||||
if get_None(fig) is None:
|
if get_None(fig) is None:
|
||||||
fig = plt.figure() # self.iplot) ### WHY? MP MP
|
fig = plt.figure() # self.iplot) ### WHY? MP MP
|
||||||
@ -1329,6 +1331,7 @@ def get_quality_class(uncertainty, weight_classes):
|
|||||||
quality = len(weight_classes)
|
quality = len(weight_classes)
|
||||||
return quality
|
return quality
|
||||||
|
|
||||||
|
|
||||||
def set_NaNs_to(data, nan_value):
|
def set_NaNs_to(data, nan_value):
|
||||||
"""
|
"""
|
||||||
Replace all NaNs in data with nan_value
|
Replace all NaNs in data with nan_value
|
||||||
@ -1344,6 +1347,7 @@ def set_NaNs_to(data, nan_value):
|
|||||||
data[nn] = nan_value
|
data[nn] = nan_value
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
||||||
def taper_cf(cf):
|
def taper_cf(cf):
|
||||||
"""
|
"""
|
||||||
Taper cf data to get rid off of side maximas
|
Taper cf data to get rid off of side maximas
|
||||||
@ -1355,6 +1359,7 @@ def taper_cf(cf):
|
|||||||
tap = np.hanning(len(cf))
|
tap = np.hanning(len(cf))
|
||||||
return tap * cf
|
return tap * cf
|
||||||
|
|
||||||
|
|
||||||
def cf_positive(cf):
|
def cf_positive(cf):
|
||||||
"""
|
"""
|
||||||
Shifts cf so that all values are positive
|
Shifts cf so that all values are positive
|
||||||
@ -1365,6 +1370,7 @@ def cf_positive(cf):
|
|||||||
"""
|
"""
|
||||||
return cf + max(abs(cf))
|
return cf + max(abs(cf))
|
||||||
|
|
||||||
|
|
||||||
def smooth_cf(cf, t_smooth, delta):
|
def smooth_cf(cf, t_smooth, delta):
|
||||||
"""
|
"""
|
||||||
Smooth cf by taking samples over t_smooth length
|
Smooth cf by taking samples over t_smooth length
|
||||||
@ -1393,6 +1399,7 @@ def smooth_cf(cf, t_smooth, delta):
|
|||||||
cf_smooth -= offset # remove offset from smoothed function
|
cf_smooth -= offset # remove offset from smoothed function
|
||||||
return cf_smooth
|
return cf_smooth
|
||||||
|
|
||||||
|
|
||||||
def check_counts_ms(data):
|
def check_counts_ms(data):
|
||||||
"""
|
"""
|
||||||
check if data is in counts or m/s
|
check if data is in counts or m/s
|
||||||
@ -1452,9 +1459,9 @@ def calcSlope(Data, datasmooth, Tcf, Pick, TSNR):
|
|||||||
if imax == 0:
|
if imax == 0:
|
||||||
print("AICPicker: Maximum for slope determination right at the beginning of the window!")
|
print("AICPicker: Maximum for slope determination right at the beginning of the window!")
|
||||||
print("Choose longer slope determination window!")
|
print("Choose longer slope determination window!")
|
||||||
raise IndexError
|
raise IndexError
|
||||||
iislope = islope[0][0:imax + 1] # cut index so it contains only the first maximum
|
iislope = islope[0][0:imax + 1] # cut index so it contains only the first maximum
|
||||||
dataslope = Data[0].data[iislope] # slope will only be calculated to the first maximum
|
dataslope = Data[0].data[iislope] # slope will only be calculated to the first maximum
|
||||||
# calculate slope as polynomal fit of order 1
|
# calculate slope as polynomal fit of order 1
|
||||||
xslope = np.arange(0, len(dataslope))
|
xslope = np.arange(0, len(dataslope))
|
||||||
P = np.polyfit(xslope, dataslope, 1)
|
P = np.polyfit(xslope, dataslope, 1)
|
||||||
@ -1475,8 +1482,10 @@ def get_pickparams(pickparam):
|
|||||||
:rtype: (dict, dict, dict, dict)
|
:rtype: (dict, dict, dict, dict)
|
||||||
"""
|
"""
|
||||||
# Define names of all parameters in different groups
|
# Define names of all parameters in different groups
|
||||||
p_parameter_names = 'algoP pstart pstop use_taup taup_model tlta tsnrz hosorder bpz1 bpz2 pickwinP aictsmooth tsmoothP ausP nfacP tpred1z tdet1z Parorder addnoise Precalcwin minAICPslope minAICPSNR timeerrorsP checkwindowP minfactorP'.split(' ')
|
p_parameter_names = 'algoP pstart pstop use_taup taup_model tlta tsnrz hosorder bpz1 bpz2 pickwinP aictsmooth tsmoothP ausP nfacP tpred1z tdet1z Parorder addnoise Precalcwin minAICPslope minAICPSNR timeerrorsP checkwindowP minfactorP'.split(
|
||||||
s_parameter_names = 'algoS sstart sstop bph1 bph2 tsnrh pickwinS tpred1h tdet1h tpred2h tdet2h Sarorder aictsmoothS tsmoothS ausS minAICSslope minAICSSNR Srecalcwin nfacS timeerrorsS zfac checkwindowS minfactorS'.split(' ')
|
' ')
|
||||||
|
s_parameter_names = 'algoS sstart sstop bph1 bph2 tsnrh pickwinS tpred1h tdet1h tpred2h tdet2h Sarorder aictsmoothS tsmoothS ausS minAICSslope minAICSSNR Srecalcwin nfacS timeerrorsS zfac checkwindowS minfactorS'.split(
|
||||||
|
' ')
|
||||||
first_motion_names = 'minFMSNR fmpickwin minfmweight'.split(' ')
|
first_motion_names = 'minFMSNR fmpickwin minfmweight'.split(' ')
|
||||||
signal_length_names = 'minsiglength minpercent noisefactor'.split(' ')
|
signal_length_names = 'minsiglength minpercent noisefactor'.split(' ')
|
||||||
# Get list of values from pickparam by name
|
# Get list of values from pickparam by name
|
||||||
@ -1494,6 +1503,7 @@ def get_pickparams(pickparam):
|
|||||||
|
|
||||||
return p_params, s_params, first_motion_params, signal_length_params
|
return p_params, s_params, first_motion_params, signal_length_params
|
||||||
|
|
||||||
|
|
||||||
def getQualityFromUncertainty(uncertainty, Errors):
|
def getQualityFromUncertainty(uncertainty, Errors):
|
||||||
# set initial quality to 4 (worst) and change only if one condition is hit
|
# set initial quality to 4 (worst) and change only if one condition is hit
|
||||||
quality = 4
|
quality = 4
|
||||||
@ -1517,6 +1527,7 @@ def getQualityFromUncertainty(uncertainty, Errors):
|
|||||||
|
|
||||||
return quality
|
return quality
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
import doctest
|
import doctest
|
||||||
|
|
||||||
|
@ -1,27 +1,22 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
import sys
|
import traceback
|
||||||
import os
|
|
||||||
import matplotlib
|
|
||||||
|
|
||||||
from PySide2 import QtCore, QtGui, QtWidgets
|
|
||||||
from PySide2.QtCore import Qt
|
|
||||||
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
|
|
||||||
import matplotlib.patheffects as PathEffects
|
|
||||||
|
|
||||||
import cartopy.crs as ccrs
|
import cartopy.crs as ccrs
|
||||||
import matplotlib.pyplot as plt
|
|
||||||
import cartopy.feature as cf
|
import cartopy.feature as cf
|
||||||
from cartopy.mpl.gridliner import LongitudeFormatter, LatitudeFormatter
|
import matplotlib
|
||||||
|
import matplotlib.patheffects as PathEffects
|
||||||
import traceback
|
import matplotlib.pyplot as plt
|
||||||
import obspy
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
import obspy
|
||||||
|
from PySide2 import QtWidgets
|
||||||
|
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
|
||||||
from mpl_toolkits.axes_grid1.inset_locator import inset_axes
|
from mpl_toolkits.axes_grid1.inset_locator import inset_axes
|
||||||
from scipy.interpolate import griddata
|
from scipy.interpolate import griddata
|
||||||
from pylot.core.util.widgets import PickDlg
|
|
||||||
from pylot.core.pick.utils import get_quality_class
|
from pylot.core.pick.utils import get_quality_class
|
||||||
|
from pylot.core.util.widgets import PickDlg
|
||||||
|
|
||||||
matplotlib.use('Qt5Agg')
|
matplotlib.use('Qt5Agg')
|
||||||
|
|
||||||
@ -173,7 +168,8 @@ class Array_map(QtWidgets.QWidget):
|
|||||||
self.canvas.fig.tight_layout()
|
self.canvas.fig.tight_layout()
|
||||||
|
|
||||||
def add_merid_paral(self):
|
def add_merid_paral(self):
|
||||||
self.gridlines = self.canvas.axes.gridlines(draw_labels=False, alpha=0.6, color='gray', linewidth=self.linewidth/2, zorder=7)
|
self.gridlines = self.canvas.axes.gridlines(draw_labels=False, alpha=0.6, color='gray',
|
||||||
|
linewidth=self.linewidth / 2, zorder=7)
|
||||||
# TODO: current cartopy version does not support label removal. Devs are working on it.
|
# TODO: current cartopy version does not support label removal. Devs are working on it.
|
||||||
# Should be fixed in coming cartopy versions
|
# Should be fixed in coming cartopy versions
|
||||||
# self.gridlines.xformatter = LONGITUDE_FORMATTER
|
# self.gridlines.xformatter = LONGITUDE_FORMATTER
|
||||||
@ -513,7 +509,7 @@ class Array_map(QtWidgets.QWidget):
|
|||||||
levels = np.linspace(self.get_min_from_picks(), self.get_max_from_picks(), nlevel)
|
levels = np.linspace(self.get_min_from_picks(), self.get_max_from_picks(), nlevel)
|
||||||
|
|
||||||
self.contourf = self.canvas.axes.contourf(self.longrid, self.latgrid, self.picksgrid_active, levels,
|
self.contourf = self.canvas.axes.contourf(self.longrid, self.latgrid, self.picksgrid_active, levels,
|
||||||
linewidths=self.linewidth*5, transform=ccrs.PlateCarree(),
|
linewidths=self.linewidth * 5, transform=ccrs.PlateCarree(),
|
||||||
alpha=0.4, zorder=8, cmap=self.get_colormap())
|
alpha=0.4, zorder=8, cmap=self.get_colormap())
|
||||||
|
|
||||||
def get_colormap(self):
|
def get_colormap(self):
|
||||||
|
@ -2,9 +2,10 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
import glob
|
import glob
|
||||||
import numpy as np
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
from obspy import UTCDateTime, read_inventory, read
|
from obspy import UTCDateTime, read_inventory, read
|
||||||
from obspy.io.xseed import Parser
|
from obspy.io.xseed import Parser
|
||||||
|
|
||||||
@ -46,7 +47,7 @@ class Metadata(object):
|
|||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return self.__str__()
|
return self.__str__()
|
||||||
|
|
||||||
def add_inventory(self, path_to_inventory, obspy_dmt_inv = False):
|
def add_inventory(self, path_to_inventory, obspy_dmt_inv=False):
|
||||||
"""
|
"""
|
||||||
Add path to list of inventories.
|
Add path to list of inventories.
|
||||||
:param path_to_inventory: Path to a folder
|
:param path_to_inventory: Path to a folder
|
||||||
@ -211,6 +212,7 @@ class Metadata(object):
|
|||||||
self.stations_dict[st_id] = {'latitude': station[0].latitude,
|
self.stations_dict[st_id] = {'latitude': station[0].latitude,
|
||||||
'longitude': station[0].longitude,
|
'longitude': station[0].longitude,
|
||||||
'elevation': station[0].elevation}
|
'elevation': station[0].elevation}
|
||||||
|
|
||||||
read_stat = {'xml': stat_info_from_inventory,
|
read_stat = {'xml': stat_info_from_inventory,
|
||||||
'dless': stat_info_from_parser}
|
'dless': stat_info_from_parser}
|
||||||
|
|
||||||
@ -380,6 +382,7 @@ def check_time(datetime):
|
|||||||
except ValueError:
|
except ValueError:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
# TODO: change root to datapath
|
# TODO: change root to datapath
|
||||||
def get_file_list(root_dir):
|
def get_file_list(root_dir):
|
||||||
"""
|
"""
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from obspy import UTCDateTime
|
from obspy import UTCDateTime
|
||||||
from obspy.core.event import Event as ObsPyEvent
|
from obspy.core.event import Event as ObsPyEvent
|
||||||
from obspy.core.event import Origin, ResourceIdentifier
|
from obspy.core.event import Origin, ResourceIdentifier
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
# small script that creates array maps for each event within a previously generated PyLoT project
|
# small script that creates array maps for each event within a previously generated PyLoT project
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
num_thread = "16"
|
num_thread = "16"
|
||||||
os.environ["OMP_NUM_THREADS"] = num_thread
|
os.environ["OMP_NUM_THREADS"] = num_thread
|
||||||
os.environ["OPENBLAS_NUM_THREADS"] = num_thread
|
os.environ["OPENBLAS_NUM_THREADS"] = num_thread
|
||||||
@ -15,6 +16,7 @@ import multiprocessing
|
|||||||
import sys
|
import sys
|
||||||
import glob
|
import glob
|
||||||
import matplotlib
|
import matplotlib
|
||||||
|
|
||||||
matplotlib.use('Qt5Agg')
|
matplotlib.use('Qt5Agg')
|
||||||
sys.path.append(os.path.join('/'.join(sys.argv[0].split('/')[:-1]), '../../..'))
|
sys.path.append(os.path.join('/'.join(sys.argv[0].split('/')[:-1]), '../../..'))
|
||||||
|
|
||||||
@ -52,7 +54,8 @@ def array_map_worker(input_dict):
|
|||||||
print('Working on event: {} ({}/{})'.format(eventdir, input_dict['index'] + 1, input_dict['nEvents']))
|
print('Working on event: {} ({}/{})'.format(eventdir, input_dict['index'] + 1, input_dict['nEvents']))
|
||||||
xml_picks = glob.glob(os.path.join(eventdir, f'*{input_dict["f_ext"]}.xml'))
|
xml_picks = glob.glob(os.path.join(eventdir, f'*{input_dict["f_ext"]}.xml'))
|
||||||
if not len(xml_picks):
|
if not len(xml_picks):
|
||||||
print('Event {} does not have any picks associated with event file extension {}'. format(eventdir, input_dict['f_ext']))
|
print('Event {} does not have any picks associated with event file extension {}'.format(eventdir,
|
||||||
|
input_dict['f_ext']))
|
||||||
return
|
return
|
||||||
# check for picks
|
# check for picks
|
||||||
manualpicks = event.getPicks()
|
manualpicks = event.getPicks()
|
||||||
@ -92,4 +95,3 @@ if __name__ == '__main__':
|
|||||||
|
|
||||||
for infile in args.infiles:
|
for infile in args.infiles:
|
||||||
main(os.path.join(args.dataroot, infile), f_ext='_correlated_0.03-0.1', ncores=args.ncores)
|
main(os.path.join(args.dataroot, infile), f_ext='_correlated_0.03-0.1', ncores=args.ncores)
|
||||||
|
|
||||||
|
@ -11,7 +11,6 @@ try:
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
print('Warning: Could not import module QtCore.')
|
print('Warning: Could not import module QtCore.')
|
||||||
|
|
||||||
|
|
||||||
from pylot.core.util.utils import pick_color
|
from pylot.core.util.utils import pick_color
|
||||||
|
|
||||||
|
|
||||||
@ -53,7 +52,7 @@ def which(program, parameter):
|
|||||||
settings = QSettings()
|
settings = QSettings()
|
||||||
for key in settings.allKeys():
|
for key in settings.allKeys():
|
||||||
if 'binPath' in key:
|
if 'binPath' in key:
|
||||||
os.environ['PATH'] += ':{0}'.format(settings.value(key))
|
os.environ['PATH'] += ':{0}'.format(settings.value(key))
|
||||||
nllocpath = ":" + parameter.get('nllocbin')
|
nllocpath = ":" + parameter.get('nllocbin')
|
||||||
os.environ['PATH'] += nllocpath
|
os.environ['PATH'] += nllocpath
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@ -73,7 +72,7 @@ def which(program, parameter):
|
|||||||
return program
|
return program
|
||||||
else:
|
else:
|
||||||
for path in os.environ["PATH"].split(os.pathsep):
|
for path in os.environ["PATH"].split(os.pathsep):
|
||||||
exe_file = os.path.join(path, program)
|
exe_file = os.path.join(path, program)
|
||||||
for candidate in ext_candidates(exe_file):
|
for candidate in ext_candidates(exe_file):
|
||||||
if is_exe(candidate):
|
if is_exe(candidate):
|
||||||
return candidate
|
return candidate
|
||||||
@ -101,4 +100,3 @@ def make_pen(picktype, phase, key, quality):
|
|||||||
linestyle, width = pick_linestyle_pg(picktype, key)
|
linestyle, width = pick_linestyle_pg(picktype, key)
|
||||||
pen = pg.mkPen(rgba, width=width, style=linestyle)
|
pen = pg.mkPen(rgba, width=width, style=linestyle)
|
||||||
return pen
|
return pen
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from obspy import UTCDateTime
|
from obspy import UTCDateTime
|
||||||
|
|
||||||
|
|
||||||
@ -36,12 +37,12 @@ def qml_from_obspyDMT(path):
|
|||||||
return IOError('Could not find Event at {}'.format(path))
|
return IOError('Could not find Event at {}'.format(path))
|
||||||
|
|
||||||
with open(path, 'rb') as infile:
|
with open(path, 'rb') as infile:
|
||||||
event_dmt = pickle.load(infile)#, fix_imports=True)
|
event_dmt = pickle.load(infile) # , fix_imports=True)
|
||||||
|
|
||||||
event_dmt['origin_id'].id = str(event_dmt['origin_id'].id)
|
event_dmt['origin_id'].id = str(event_dmt['origin_id'].id)
|
||||||
|
|
||||||
ev = Event(resource_id=event_dmt['event_id'])
|
ev = Event(resource_id=event_dmt['event_id'])
|
||||||
#small bugfix "unhashable type: 'newstr' "
|
# small bugfix "unhashable type: 'newstr' "
|
||||||
event_dmt['origin_id'].id = str(event_dmt['origin_id'].id)
|
event_dmt['origin_id'].id = str(event_dmt['origin_id'].id)
|
||||||
|
|
||||||
origin = Origin(resource_id=event_dmt['origin_id'],
|
origin = Origin(resource_id=event_dmt['origin_id'],
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
import numpy as np
|
|
||||||
import warnings
|
import warnings
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
from obspy import UTCDateTime
|
from obspy import UTCDateTime
|
||||||
|
|
||||||
from pylot.core.util.utils import fit_curve, clims
|
from pylot.core.util.utils import fit_curve, clims
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
import sys, os, traceback
|
|
||||||
import multiprocessing
|
import multiprocessing
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import traceback
|
||||||
|
|
||||||
from PySide2.QtCore import QThread, Signal, Qt, Slot, QRunnable, QObject
|
from PySide2.QtCore import QThread, Signal, Qt, Slot, QRunnable, QObject
|
||||||
from PySide2.QtWidgets import QDialog, QProgressBar, QLabel, QHBoxLayout, QPushButton
|
from PySide2.QtWidgets import QDialog, QProgressBar, QLabel, QHBoxLayout, QPushButton
|
||||||
|
|
||||||
@ -102,9 +105,9 @@ class Worker(QRunnable):
|
|||||||
try:
|
try:
|
||||||
result = self.fun(self.args)
|
result = self.fun(self.args)
|
||||||
except:
|
except:
|
||||||
exctype, value = sys.exc_info ()[:2]
|
exctype, value = sys.exc_info()[:2]
|
||||||
print(exctype, value, traceback.format_exc())
|
print(exctype, value, traceback.format_exc())
|
||||||
self.signals.error.emit ((exctype, value, traceback.format_exc ()))
|
self.signals.error.emit((exctype, value, traceback.format_exc()))
|
||||||
else:
|
else:
|
||||||
self.signals.result.emit(result)
|
self.signals.result.emit(result)
|
||||||
finally:
|
finally:
|
||||||
|
@ -2,12 +2,13 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
import hashlib
|
import hashlib
|
||||||
import numpy as np
|
|
||||||
import os
|
import os
|
||||||
import platform
|
import platform
|
||||||
import re
|
import re
|
||||||
import subprocess
|
import subprocess
|
||||||
import warnings
|
import warnings
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
from obspy import UTCDateTime, read
|
from obspy import UTCDateTime, read
|
||||||
from obspy.core import AttribDict
|
from obspy.core import AttribDict
|
||||||
from obspy.signal.rotate import rotate2zne
|
from obspy.signal.rotate import rotate2zne
|
||||||
|
@ -35,9 +35,9 @@ from __future__ import print_function
|
|||||||
|
|
||||||
__all__ = "get_git_version"
|
__all__ = "get_git_version"
|
||||||
|
|
||||||
|
import inspect
|
||||||
# NO IMPORTS FROM PYLOT IN THIS FILE! (file gets used at installation time)
|
# NO IMPORTS FROM PYLOT IN THIS FILE! (file gets used at installation time)
|
||||||
import os
|
import os
|
||||||
import inspect
|
|
||||||
from subprocess import Popen, PIPE
|
from subprocess import Popen, PIPE
|
||||||
|
|
||||||
# NO IMPORTS FROM PYLOT IN THIS FILE! (file gets used at installation time)
|
# NO IMPORTS FROM PYLOT IN THIS FILE! (file gets used at installation time)
|
||||||
|
@ -8,15 +8,16 @@ Created on Wed Mar 19 11:27:35 2014
|
|||||||
import copy
|
import copy
|
||||||
import datetime
|
import datetime
|
||||||
import getpass
|
import getpass
|
||||||
import matplotlib
|
|
||||||
import multiprocessing
|
import multiprocessing
|
||||||
import numpy as np
|
|
||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
|
import matplotlib
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
matplotlib.use('QT5Agg')
|
matplotlib.use('QT5Agg')
|
||||||
|
|
||||||
from matplotlib.figure import Figure
|
from matplotlib.figure import Figure
|
||||||
@ -36,7 +37,7 @@ from PySide2.QtWidgets import QAction, QApplication, QCheckBox, QComboBox, \
|
|||||||
QGridLayout, QLabel, QLineEdit, QMessageBox, \
|
QGridLayout, QLabel, QLineEdit, QMessageBox, \
|
||||||
QTabWidget, QToolBar, QVBoxLayout, QHBoxLayout, QWidget, \
|
QTabWidget, QToolBar, QVBoxLayout, QHBoxLayout, QWidget, \
|
||||||
QPushButton, QFileDialog, QInputDialog
|
QPushButton, QFileDialog, QInputDialog
|
||||||
from PySide2.QtCore import QSettings, Qt, QUrl, Signal, Slot
|
from PySide2.QtCore import QSettings, Qt, QUrl, Signal
|
||||||
from PySide2.QtWebEngineWidgets import QWebEngineView as QWebView
|
from PySide2.QtWebEngineWidgets import QWebEngineView as QWebView
|
||||||
from obspy import Stream, Trace, UTCDateTime
|
from obspy import Stream, Trace, UTCDateTime
|
||||||
from obspy.core.util import AttribDict
|
from obspy.core.util import AttribDict
|
||||||
@ -65,19 +66,20 @@ else:
|
|||||||
raise ImportError(f'Python version {sys.version_info.major} of current interpreter not supported.'
|
raise ImportError(f'Python version {sys.version_info.major} of current interpreter not supported.'
|
||||||
f'\nPlease use Python 3+.')
|
f'\nPlease use Python 3+.')
|
||||||
|
|
||||||
|
|
||||||
# workaround to prevent PyCharm from deleting icons_rc import when optimizing imports
|
# workaround to prevent PyCharm from deleting icons_rc import when optimizing imports
|
||||||
# icons_rc = icons_rc
|
icons_rc = icons_rc
|
||||||
|
|
||||||
|
|
||||||
class QSpinBox(QtWidgets.QSpinBox):
|
class QSpinBox(QtWidgets.QSpinBox):
|
||||||
''' Custom SpinBox, insensitive to Mousewheel (prevents accidental changes when scrolling through parameters) '''
|
''' Custom SpinBox, insensitive to Mousewheel (prevents accidental changes when scrolling through parameters) '''
|
||||||
|
|
||||||
def wheelEvent(self, event):
|
def wheelEvent(self, event):
|
||||||
event.ignore()
|
event.ignore()
|
||||||
|
|
||||||
|
|
||||||
class QDoubleSpinBox(QtWidgets.QDoubleSpinBox):
|
class QDoubleSpinBox(QtWidgets.QDoubleSpinBox):
|
||||||
''' Custom DoubleSpinBox, insensitive to Mousewheel (prevents accidental changes when scrolling through parameters) '''
|
''' Custom DoubleSpinBox, insensitive to Mousewheel (prevents accidental changes when scrolling through parameters) '''
|
||||||
|
|
||||||
def wheelEvent(self, event):
|
def wheelEvent(self, event):
|
||||||
event.ignore()
|
event.ignore()
|
||||||
|
|
||||||
@ -131,7 +133,7 @@ class LogWidget(QtWidgets.QWidget):
|
|||||||
def reset_error(self):
|
def reset_error(self):
|
||||||
# used to make sure that write errors is finished before raising new Message box etc.
|
# used to make sure that write errors is finished before raising new Message box etc.
|
||||||
self.current_active_error = False
|
self.current_active_error = False
|
||||||
self.stderr.append(60*'#' + '\n\n')
|
self.stderr.append(60 * '#' + '\n\n')
|
||||||
|
|
||||||
|
|
||||||
def getDataType(parent):
|
def getDataType(parent):
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
from pylot.core.pick.autopick import PickingResults
|
from pylot.core.pick.autopick import PickingResults
|
||||||
|
|
||||||
|
|
||||||
class TestPickingResults(unittest.TestCase):
|
class TestPickingResults(unittest.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
@ -70,9 +72,9 @@ class TestPickingResults(unittest.TestCase):
|
|||||||
curr_len = len(self.pr)
|
curr_len = len(self.pr)
|
||||||
except Exception:
|
except Exception:
|
||||||
self.fail("test_dunder_attributes overwrote an instance internal dunder method")
|
self.fail("test_dunder_attributes overwrote an instance internal dunder method")
|
||||||
self.assertEqual(prev_len+1, curr_len) # +1 for the added __len__ key/value-pair
|
self.assertEqual(prev_len + 1, curr_len) # +1 for the added __len__ key/value-pair
|
||||||
|
|
||||||
self.pr.__len__ = 42
|
self.pr.__len__ = 42
|
||||||
|
|
||||||
self.assertEqual(42, self.pr['__len__'])
|
self.assertEqual(42, self.pr['__len__'])
|
||||||
self.assertEqual(prev_len+1, curr_len, msg="__len__ was overwritten")
|
self.assertEqual(prev_len + 1, curr_len, msg="__len__ was overwritten")
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import os
|
import os
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
from obspy import UTCDateTime
|
from obspy import UTCDateTime
|
||||||
from obspy.io.xseed import Parser
|
from obspy.io.xseed import Parser
|
||||||
from obspy.io.xseed.utils import SEEDParserException
|
from obspy.io.xseed.utils import SEEDParserException
|
||||||
@ -27,7 +28,7 @@ class TestMetadata(unittest.TestCase):
|
|||||||
result = {}
|
result = {}
|
||||||
for channel in ('Z', 'N', 'E'):
|
for channel in ('Z', 'N', 'E'):
|
||||||
with HidePrints():
|
with HidePrints():
|
||||||
coords = self.m.get_coordinates(self.station_id+channel, time=self.time)
|
coords = self.m.get_coordinates(self.station_id + channel, time=self.time)
|
||||||
result[channel] = coords
|
result[channel] = coords
|
||||||
self.assertDictEqual(result[channel], expected[channel])
|
self.assertDictEqual(result[channel], expected[channel])
|
||||||
|
|
||||||
@ -42,7 +43,7 @@ class TestMetadata(unittest.TestCase):
|
|||||||
result = {}
|
result = {}
|
||||||
for channel in ('Z', 'N', 'E'):
|
for channel in ('Z', 'N', 'E'):
|
||||||
with HidePrints():
|
with HidePrints():
|
||||||
coords = self.m.get_coordinates(self.station_id+channel)
|
coords = self.m.get_coordinates(self.station_id + channel)
|
||||||
result[channel] = coords
|
result[channel] = coords
|
||||||
self.assertDictEqual(result[channel], expected[channel])
|
self.assertDictEqual(result[channel], expected[channel])
|
||||||
|
|
||||||
@ -145,7 +146,7 @@ class TestMetadata_read_single_file(unittest.TestCase):
|
|||||||
|
|
||||||
def test_read_single_file(self):
|
def test_read_single_file(self):
|
||||||
"""Test if reading a single file works"""
|
"""Test if reading a single file works"""
|
||||||
fname = os.path.join(self.metadata_folders[0], 'DATALESS.'+self.station_id)
|
fname = os.path.join(self.metadata_folders[0], 'DATALESS.' + self.station_id)
|
||||||
with HidePrints():
|
with HidePrints():
|
||||||
res = self.m.read_single_file(fname)
|
res = self.m.read_single_file(fname)
|
||||||
# method should return true if file is successfully read
|
# method should return true if file is successfully read
|
||||||
@ -172,7 +173,7 @@ class TestMetadata_read_single_file(unittest.TestCase):
|
|||||||
|
|
||||||
def test_read_single_file_multiple_times(self):
|
def test_read_single_file_multiple_times(self):
|
||||||
"""Test if reading a file twice doesnt add it twice to the metadata object"""
|
"""Test if reading a file twice doesnt add it twice to the metadata object"""
|
||||||
fname = os.path.join(self.metadata_folders[0], 'DATALESS.'+self.station_id)
|
fname = os.path.join(self.metadata_folders[0], 'DATALESS.' + self.station_id)
|
||||||
with HidePrints():
|
with HidePrints():
|
||||||
res1 = self.m.read_single_file(fname)
|
res1 = self.m.read_single_file(fname)
|
||||||
res2 = self.m.read_single_file(fname)
|
res2 = self.m.read_single_file(fname)
|
||||||
@ -197,7 +198,8 @@ class TestMetadataMultipleTime(unittest.TestCase):
|
|||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.seed_id = 'LE.ROTT..HN'
|
self.seed_id = 'LE.ROTT..HN'
|
||||||
path = os.path.dirname(__file__) # gets path to currently running script
|
path = os.path.dirname(__file__) # gets path to currently running script
|
||||||
metadata = os.path.join('test_data', 'dless_multiple_times', 'MAGS2_LE_ROTT.dless') # specific subfolder of test data
|
metadata = os.path.join('test_data', 'dless_multiple_times',
|
||||||
|
'MAGS2_LE_ROTT.dless') # specific subfolder of test data
|
||||||
metadata_path = os.path.join(path, metadata)
|
metadata_path = os.path.join(path, metadata)
|
||||||
self.m = Metadata(metadata_path)
|
self.m = Metadata(metadata_path)
|
||||||
self.p = Parser(metadata_path)
|
self.p = Parser(metadata_path)
|
||||||
@ -299,7 +301,8 @@ Channels:
|
|||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.seed_id = 'KB.TMO07.00.HHZ'
|
self.seed_id = 'KB.TMO07.00.HHZ'
|
||||||
path = os.path.dirname(__file__) # gets path to currently running script
|
path = os.path.dirname(__file__) # gets path to currently running script
|
||||||
metadata = os.path.join('test_data', 'dless_multiple_instruments', 'MAGS2_KB_TMO07.dless') # specific subfolder of test data
|
metadata = os.path.join('test_data', 'dless_multiple_instruments',
|
||||||
|
'MAGS2_KB_TMO07.dless') # specific subfolder of test data
|
||||||
metadata_path = os.path.join(path, metadata)
|
metadata_path = os.path.join(path, metadata)
|
||||||
self.m = Metadata(metadata_path)
|
self.m = Metadata(metadata_path)
|
||||||
self.p = Parser(metadata_path)
|
self.p = Parser(metadata_path)
|
||||||
|
@ -1,21 +1,21 @@
|
|||||||
<?xml version='1.0' encoding='utf-8'?>
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
<q:quakeml xmlns:q="http://quakeml.org/xmlns/quakeml/1.2" xmlns="http://quakeml.org/xmlns/bed/1.2">
|
<q:quakeml xmlns:q="http://quakeml.org/xmlns/quakeml/1.2" xmlns="http://quakeml.org/xmlns/bed/1.2">
|
||||||
<eventParameters publicID="smi:local/53a38563-739a-48b2-9f34-bf40ee7b656a">
|
<eventParameters publicID="smi:local/53a38563-739a-48b2-9f34-bf40ee7b656a">
|
||||||
<event publicID="smi:local/e0001.024.16">
|
<event publicID="smi:local/e0001.024.16">
|
||||||
<origin publicID="smi:local/e0001.024.16">
|
<origin publicID="smi:local/e0001.024.16">
|
||||||
<time>
|
<time>
|
||||||
<value>2016-01-24T10:30:30.000000Z</value>
|
<value>2016-01-24T10:30:30.000000Z</value>
|
||||||
</time>
|
</time>
|
||||||
<latitude>
|
<latitude>
|
||||||
<value>59.66</value>
|
<value>59.66</value>
|
||||||
</latitude>
|
</latitude>
|
||||||
<longitude>
|
<longitude>
|
||||||
<value>-153.45</value>
|
<value>-153.45</value>
|
||||||
</longitude>
|
</longitude>
|
||||||
<depth>
|
<depth>
|
||||||
<value>128.0</value>
|
<value>128.0</value>
|
||||||
</depth>
|
</depth>
|
||||||
</origin>
|
</origin>
|
||||||
</event>
|
</event>
|
||||||
</eventParameters>
|
</eventParameters>
|
||||||
</q:quakeml>
|
</q:quakeml>
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
import unittest
|
|
||||||
from unittest import skip
|
|
||||||
import obspy
|
|
||||||
from obspy import UTCDateTime
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
from pylot.core.pick.autopick import autopickstation
|
import unittest
|
||||||
from pylot.core.io.inputs import PylotParameter
|
|
||||||
|
import obspy
|
||||||
|
from obspy import UTCDateTime
|
||||||
|
|
||||||
from pylot.core.io.data import Data
|
from pylot.core.io.data import Data
|
||||||
|
from pylot.core.io.inputs import PylotParameter
|
||||||
|
from pylot.core.pick.autopick import autopickstation
|
||||||
from pylot.core.util.utils import trim_station_components
|
from pylot.core.util.utils import trim_station_components
|
||||||
|
|
||||||
|
|
||||||
@ -93,51 +94,100 @@ class TestAutopickStation(unittest.TestCase):
|
|||||||
self.inputfile_taupy_disabled = os.path.join(os.path.dirname(__file__), 'autoPyLoT_global_taupy_false.in')
|
self.inputfile_taupy_disabled = os.path.join(os.path.dirname(__file__), 'autoPyLoT_global_taupy_false.in')
|
||||||
self.pickparam_taupy_enabled = PylotParameter(fnin=self.inputfile_taupy_enabled)
|
self.pickparam_taupy_enabled = PylotParameter(fnin=self.inputfile_taupy_enabled)
|
||||||
self.pickparam_taupy_disabled = PylotParameter(fnin=self.inputfile_taupy_disabled)
|
self.pickparam_taupy_disabled = PylotParameter(fnin=self.inputfile_taupy_disabled)
|
||||||
self.xml_file = os.path.join(os.path.dirname(__file__),self.event_id, 'PyLoT_'+self.event_id+'.xml')
|
self.xml_file = os.path.join(os.path.dirname(__file__), self.event_id, 'PyLoT_' + self.event_id + '.xml')
|
||||||
self.data = Data(evtdata=self.xml_file)
|
self.data = Data(evtdata=self.xml_file)
|
||||||
# create origin for taupy testing
|
# create origin for taupy testing
|
||||||
self.origin = [obspy.core.event.origin.Origin(magnitude=7.1, latitude=59.66, longitude=-153.45, depth=128.0, time=UTCDateTime("2016-01-24T10:30:30.0"))]
|
self.origin = [obspy.core.event.origin.Origin(magnitude=7.1, latitude=59.66, longitude=-153.45, depth=128.0,
|
||||||
|
time=UTCDateTime("2016-01-24T10:30:30.0"))]
|
||||||
# mocking metadata since reading it takes a long time to read from file
|
# mocking metadata since reading it takes a long time to read from file
|
||||||
self.metadata = MockMetadata()
|
self.metadata = MockMetadata()
|
||||||
|
|
||||||
# show complete diff when difference in results dictionaries are found
|
# show complete diff when difference in results dictionaries are found
|
||||||
self.maxDiff = None
|
self.maxDiff = None
|
||||||
|
|
||||||
#@skip("Works")
|
# @skip("Works")
|
||||||
def test_autopickstation_taupy_disabled_gra1(self):
|
def test_autopickstation_taupy_disabled_gra1(self):
|
||||||
expected = {'P': {'picker': 'auto', 'snrdb': 15.405649120980094, 'weight': 0, 'Mo': None, 'marked': [], 'Mw': None, 'fc': None, 'snr': 34.718816470730317, 'mpp': UTCDateTime(2016, 1, 24, 10, 41, 31, 690000), 'w0': None, 'spe': 0.93333333333333235, 'network': u'GR', 'epp': UTCDateTime(2016, 1, 24, 10, 41, 28, 890000), 'lpp': UTCDateTime(2016, 1, 24, 10, 41, 32, 690000), 'fm': 'D', 'channel': u'LHZ'}, 'S': {'picker': 'auto', 'snrdb': 10.669661906545489, 'network': u'GR', 'weight': 0, 'Ao': None, 'lpp': UTCDateTime(2016, 1, 24, 10, 50, 30, 690000), 'snr': 11.667187857573905, 'epp': UTCDateTime(2016, 1, 24, 10, 50, 21, 690000), 'mpp': UTCDateTime(2016, 1, 24, 10, 50, 29, 690000), 'fm': None, 'spe': 2.6666666666666665, 'channel': u'LHE'}}
|
expected = {
|
||||||
|
'P': {'picker': 'auto', 'snrdb': 15.405649120980094, 'weight': 0, 'Mo': None, 'marked': [], 'Mw': None,
|
||||||
|
'fc': None, 'snr': 34.718816470730317, 'mpp': UTCDateTime(2016, 1, 24, 10, 41, 31, 690000),
|
||||||
|
'w0': None, 'spe': 0.93333333333333235, 'network': u'GR',
|
||||||
|
'epp': UTCDateTime(2016, 1, 24, 10, 41, 28, 890000),
|
||||||
|
'lpp': UTCDateTime(2016, 1, 24, 10, 41, 32, 690000), 'fm': 'D', 'channel': u'LHZ'},
|
||||||
|
'S': {'picker': 'auto', 'snrdb': 10.669661906545489, 'network': u'GR', 'weight': 0, 'Ao': None,
|
||||||
|
'lpp': UTCDateTime(2016, 1, 24, 10, 50, 30, 690000), 'snr': 11.667187857573905,
|
||||||
|
'epp': UTCDateTime(2016, 1, 24, 10, 50, 21, 690000),
|
||||||
|
'mpp': UTCDateTime(2016, 1, 24, 10, 50, 29, 690000), 'fm': None, 'spe': 2.6666666666666665,
|
||||||
|
'channel': u'LHE'}}
|
||||||
with HidePrints():
|
with HidePrints():
|
||||||
result, station = autopickstation(wfstream=self.gra1, pickparam=self.pickparam_taupy_disabled, metadata=(None, None))
|
result, station = autopickstation(wfstream=self.gra1, pickparam=self.pickparam_taupy_disabled,
|
||||||
|
metadata=(None, None))
|
||||||
self.assertDictContainsSubset(expected=expected['P'], actual=result['P'])
|
self.assertDictContainsSubset(expected=expected['P'], actual=result['P'])
|
||||||
self.assertDictContainsSubset(expected=expected['S'], actual=result['S'])
|
self.assertDictContainsSubset(expected=expected['S'], actual=result['S'])
|
||||||
self.assertEqual('GRA1', station)
|
self.assertEqual('GRA1', station)
|
||||||
|
|
||||||
def test_autopickstation_taupy_enabled_gra1(self):
|
def test_autopickstation_taupy_enabled_gra1(self):
|
||||||
expected = {'P': {'picker': 'auto', 'snrdb': 15.599905299126778, 'weight': 0, 'Mo': None, 'marked': [], 'Mw': None, 'fc': None, 'snr': 36.307013769185403, 'mpp': UTCDateTime(2016, 1, 24, 10, 41, 27, 690000), 'w0': None, 'spe': 0.93333333333333235, 'network': u'GR', 'epp': UTCDateTime(2016, 1, 24, 10, 41, 24, 890000), 'lpp': UTCDateTime(2016, 1, 24, 10, 41, 28, 690000), 'fm': 'U', 'channel': u'LHZ'}, 'S': {'picker': 'auto', 'snrdb': 10.669661906545489, 'network': u'GR', 'weight': 0, 'Ao': None, 'lpp': UTCDateTime(2016, 1, 24, 10, 50, 30, 690000), 'snr': 11.667187857573905, 'epp': UTCDateTime(2016, 1, 24, 10, 50, 21, 690000), 'mpp': UTCDateTime(2016, 1, 24, 10, 50, 29, 690000), 'fm': None, 'spe': 2.6666666666666665, 'channel': u'LHE'}}
|
expected = {
|
||||||
|
'P': {'picker': 'auto', 'snrdb': 15.599905299126778, 'weight': 0, 'Mo': None, 'marked': [], 'Mw': None,
|
||||||
|
'fc': None, 'snr': 36.307013769185403, 'mpp': UTCDateTime(2016, 1, 24, 10, 41, 27, 690000),
|
||||||
|
'w0': None, 'spe': 0.93333333333333235, 'network': u'GR',
|
||||||
|
'epp': UTCDateTime(2016, 1, 24, 10, 41, 24, 890000),
|
||||||
|
'lpp': UTCDateTime(2016, 1, 24, 10, 41, 28, 690000), 'fm': 'U', 'channel': u'LHZ'},
|
||||||
|
'S': {'picker': 'auto', 'snrdb': 10.669661906545489, 'network': u'GR', 'weight': 0, 'Ao': None,
|
||||||
|
'lpp': UTCDateTime(2016, 1, 24, 10, 50, 30, 690000), 'snr': 11.667187857573905,
|
||||||
|
'epp': UTCDateTime(2016, 1, 24, 10, 50, 21, 690000),
|
||||||
|
'mpp': UTCDateTime(2016, 1, 24, 10, 50, 29, 690000), 'fm': None, 'spe': 2.6666666666666665,
|
||||||
|
'channel': u'LHE'}}
|
||||||
with HidePrints():
|
with HidePrints():
|
||||||
result, station = autopickstation(wfstream=self.gra1, pickparam=self.pickparam_taupy_enabled, metadata=self.metadata, origin=self.origin)
|
result, station = autopickstation(wfstream=self.gra1, pickparam=self.pickparam_taupy_enabled,
|
||||||
|
metadata=self.metadata, origin=self.origin)
|
||||||
self.assertDictContainsSubset(expected=expected['P'], actual=result['P'])
|
self.assertDictContainsSubset(expected=expected['P'], actual=result['P'])
|
||||||
self.assertDictContainsSubset(expected=expected['S'], actual=result['S'])
|
self.assertDictContainsSubset(expected=expected['S'], actual=result['S'])
|
||||||
self.assertEqual('GRA1', station)
|
self.assertEqual('GRA1', station)
|
||||||
|
|
||||||
def test_autopickstation_taupy_disabled_gra2(self):
|
def test_autopickstation_taupy_disabled_gra2(self):
|
||||||
expected = {'P': {'picker': 'auto', 'snrdb': None, 'weight': 9, 'Mo': None, 'marked': 'shortsignallength', 'Mw': None, 'fc': None, 'snr': None, 'mpp': UTCDateTime(2016, 1, 24, 10, 36, 59, 150000), 'w0': None, 'spe': None, 'network': u'GR', 'epp': UTCDateTime(2016, 1, 24, 10, 36, 43, 150000), 'lpp': UTCDateTime(2016, 1, 24, 10, 37, 15, 150000), 'fm': 'N', 'channel': u'LHZ'}, 'S': {'picker': 'auto', 'snrdb': None, 'network': u'GR', 'weight': 4, 'Ao': None, 'lpp': UTCDateTime(2016, 1, 24, 10, 37, 15, 150000), 'snr': None, 'epp': UTCDateTime(2016, 1, 24, 10, 36, 43, 150000), 'mpp': UTCDateTime(2016, 1, 24, 10, 36, 59, 150000), 'fm': None, 'spe': None, 'channel': u'LHE'}}
|
expected = {
|
||||||
|
'P': {'picker': 'auto', 'snrdb': None, 'weight': 9, 'Mo': None, 'marked': 'shortsignallength', 'Mw': None,
|
||||||
|
'fc': None, 'snr': None, 'mpp': UTCDateTime(2016, 1, 24, 10, 36, 59, 150000), 'w0': None, 'spe': None,
|
||||||
|
'network': u'GR', 'epp': UTCDateTime(2016, 1, 24, 10, 36, 43, 150000),
|
||||||
|
'lpp': UTCDateTime(2016, 1, 24, 10, 37, 15, 150000), 'fm': 'N', 'channel': u'LHZ'},
|
||||||
|
'S': {'picker': 'auto', 'snrdb': None, 'network': u'GR', 'weight': 4, 'Ao': None,
|
||||||
|
'lpp': UTCDateTime(2016, 1, 24, 10, 37, 15, 150000), 'snr': None,
|
||||||
|
'epp': UTCDateTime(2016, 1, 24, 10, 36, 43, 150000),
|
||||||
|
'mpp': UTCDateTime(2016, 1, 24, 10, 36, 59, 150000), 'fm': None, 'spe': None, 'channel': u'LHE'}}
|
||||||
with HidePrints():
|
with HidePrints():
|
||||||
result, station = autopickstation(wfstream=self.gra2, pickparam=self.pickparam_taupy_disabled, metadata=(None, None))
|
result, station = autopickstation(wfstream=self.gra2, pickparam=self.pickparam_taupy_disabled,
|
||||||
|
metadata=(None, None))
|
||||||
self.assertDictContainsSubset(expected=expected['P'], actual=result['P'])
|
self.assertDictContainsSubset(expected=expected['P'], actual=result['P'])
|
||||||
self.assertDictContainsSubset(expected=expected['S'], actual=result['S'])
|
self.assertDictContainsSubset(expected=expected['S'], actual=result['S'])
|
||||||
self.assertEqual('GRA2', station)
|
self.assertEqual('GRA2', station)
|
||||||
|
|
||||||
def test_autopickstation_taupy_enabled_gra2(self):
|
def test_autopickstation_taupy_enabled_gra2(self):
|
||||||
expected = {'P': {'picker': 'auto', 'snrdb': 13.957959025719253, 'weight': 0, 'Mo': None, 'marked': [], 'Mw': None, 'fc': None, 'snr': 24.876879503607871, 'mpp': UTCDateTime(2016, 1, 24, 10, 41, 29, 150000), 'w0': None, 'spe': 1.0, 'network': u'GR', 'epp': UTCDateTime(2016, 1, 24, 10, 41, 26, 150000), 'lpp': UTCDateTime(2016, 1, 24, 10, 41, 30, 150000), 'fm': None, 'channel': u'LHZ'}, 'S': {'picker': 'auto', 'snrdb': 10.573236990555648, 'network': u'GR', 'weight': 1, 'Ao': None, 'lpp': UTCDateTime(2016, 1, 24, 10, 50, 34, 150000), 'snr': 11.410999834108294, 'epp': UTCDateTime(2016, 1, 24, 10, 50, 21, 150000), 'mpp': UTCDateTime(2016, 1, 24, 10, 50, 33, 150000), 'fm': None, 'spe': 4.666666666666667, 'channel': u'LHE'}}
|
expected = {
|
||||||
|
'P': {'picker': 'auto', 'snrdb': 13.957959025719253, 'weight': 0, 'Mo': None, 'marked': [], 'Mw': None,
|
||||||
|
'fc': None, 'snr': 24.876879503607871, 'mpp': UTCDateTime(2016, 1, 24, 10, 41, 29, 150000),
|
||||||
|
'w0': None, 'spe': 1.0, 'network': u'GR', 'epp': UTCDateTime(2016, 1, 24, 10, 41, 26, 150000),
|
||||||
|
'lpp': UTCDateTime(2016, 1, 24, 10, 41, 30, 150000), 'fm': None, 'channel': u'LHZ'},
|
||||||
|
'S': {'picker': 'auto', 'snrdb': 10.573236990555648, 'network': u'GR', 'weight': 1, 'Ao': None,
|
||||||
|
'lpp': UTCDateTime(2016, 1, 24, 10, 50, 34, 150000), 'snr': 11.410999834108294,
|
||||||
|
'epp': UTCDateTime(2016, 1, 24, 10, 50, 21, 150000),
|
||||||
|
'mpp': UTCDateTime(2016, 1, 24, 10, 50, 33, 150000), 'fm': None, 'spe': 4.666666666666667,
|
||||||
|
'channel': u'LHE'}}
|
||||||
with HidePrints():
|
with HidePrints():
|
||||||
result, station = autopickstation(wfstream=self.gra2, pickparam=self.pickparam_taupy_enabled, metadata=self.metadata, origin = self.origin)
|
result, station = autopickstation(wfstream=self.gra2, pickparam=self.pickparam_taupy_enabled,
|
||||||
|
metadata=self.metadata, origin=self.origin)
|
||||||
self.assertDictContainsSubset(expected=expected['P'], actual=result['P'])
|
self.assertDictContainsSubset(expected=expected['P'], actual=result['P'])
|
||||||
self.assertDictContainsSubset(expected=expected['S'], actual=result['S'])
|
self.assertDictContainsSubset(expected=expected['S'], actual=result['S'])
|
||||||
self.assertEqual('GRA2', station)
|
self.assertEqual('GRA2', station)
|
||||||
|
|
||||||
def test_autopickstation_taupy_disabled_ech(self):
|
def test_autopickstation_taupy_disabled_ech(self):
|
||||||
expected = {'P': {'picker': 'auto', 'snrdb': None, 'weight': 9, 'Mo': None, 'marked': 'SinsteadP', 'Mw': None, 'fc': None, 'snr': None, 'mpp': UTCDateTime(2016, 1, 24, 10, 26, 57), 'w0': None, 'spe': None, 'network': u'G', 'epp': UTCDateTime(2016, 1, 24, 10, 26, 41), 'lpp': UTCDateTime(2016, 1, 24, 10, 27, 13), 'fm': 'N', 'channel': u'LHZ'}, 'S': {'picker': 'auto', 'snrdb': None, 'network': u'G', 'weight': 4, 'Ao': None, 'lpp': UTCDateTime(2016, 1, 24, 10, 27, 13), 'snr': None, 'epp': UTCDateTime(2016, 1, 24, 10, 26, 41), 'mpp': UTCDateTime(2016, 1, 24, 10, 26, 57), 'fm': None, 'spe': None, 'channel': u'LHE'}}
|
expected = {'P': {'picker': 'auto', 'snrdb': None, 'weight': 9, 'Mo': None, 'marked': 'SinsteadP', 'Mw': None,
|
||||||
|
'fc': None, 'snr': None, 'mpp': UTCDateTime(2016, 1, 24, 10, 26, 57), 'w0': None, 'spe': None,
|
||||||
|
'network': u'G', 'epp': UTCDateTime(2016, 1, 24, 10, 26, 41),
|
||||||
|
'lpp': UTCDateTime(2016, 1, 24, 10, 27, 13), 'fm': 'N', 'channel': u'LHZ'},
|
||||||
|
'S': {'picker': 'auto', 'snrdb': None, 'network': u'G', 'weight': 4, 'Ao': None,
|
||||||
|
'lpp': UTCDateTime(2016, 1, 24, 10, 27, 13), 'snr': None,
|
||||||
|
'epp': UTCDateTime(2016, 1, 24, 10, 26, 41), 'mpp': UTCDateTime(2016, 1, 24, 10, 26, 57),
|
||||||
|
'fm': None, 'spe': None, 'channel': u'LHE'}}
|
||||||
with HidePrints():
|
with HidePrints():
|
||||||
result, station = autopickstation(wfstream=self.ech, pickparam=self.pickparam_taupy_disabled)
|
result, station = autopickstation(wfstream=self.ech, pickparam=self.pickparam_taupy_disabled)
|
||||||
self.assertDictContainsSubset(expected=expected['P'], actual=result['P'])
|
self.assertDictContainsSubset(expected=expected['P'], actual=result['P'])
|
||||||
@ -146,16 +196,32 @@ class TestAutopickStation(unittest.TestCase):
|
|||||||
|
|
||||||
def test_autopickstation_taupy_enabled_ech(self):
|
def test_autopickstation_taupy_enabled_ech(self):
|
||||||
# this station has a long time of before the first onset, so taupy will help during picking
|
# this station has a long time of before the first onset, so taupy will help during picking
|
||||||
expected = {'P': {'picker': 'auto', 'snrdb': 9.9753586609166316, 'weight': 0, 'Mo': None, 'marked': [], 'Mw': None, 'fc': None, 'snr': 9.9434218804137107, 'mpp': UTCDateTime(2016, 1, 24, 10, 41, 34), 'w0': None, 'spe': 1.6666666666666667, 'network': u'G', 'epp': UTCDateTime(2016, 1, 24, 10, 41, 29), 'lpp': UTCDateTime(2016, 1, 24, 10, 41, 35), 'fm': None, 'channel': u'LHZ'}, 'S': {'picker': 'auto', 'snrdb': 12.698999454169567, 'network': u'G', 'weight': 0, 'Ao': None, 'lpp': UTCDateTime(2016, 1, 24, 10, 50, 44), 'snr': 18.616581906366577, 'epp': UTCDateTime(2016, 1, 24, 10, 50, 33), 'mpp': UTCDateTime(2016, 1, 24, 10, 50, 43), 'fm': None, 'spe': 3.3333333333333335, 'channel': u'LHE'}}
|
expected = {
|
||||||
|
'P': {'picker': 'auto', 'snrdb': 9.9753586609166316, 'weight': 0, 'Mo': None, 'marked': [], 'Mw': None,
|
||||||
|
'fc': None, 'snr': 9.9434218804137107, 'mpp': UTCDateTime(2016, 1, 24, 10, 41, 34), 'w0': None,
|
||||||
|
'spe': 1.6666666666666667, 'network': u'G', 'epp': UTCDateTime(2016, 1, 24, 10, 41, 29),
|
||||||
|
'lpp': UTCDateTime(2016, 1, 24, 10, 41, 35), 'fm': None, 'channel': u'LHZ'},
|
||||||
|
'S': {'picker': 'auto', 'snrdb': 12.698999454169567, 'network': u'G', 'weight': 0, 'Ao': None,
|
||||||
|
'lpp': UTCDateTime(2016, 1, 24, 10, 50, 44), 'snr': 18.616581906366577,
|
||||||
|
'epp': UTCDateTime(2016, 1, 24, 10, 50, 33), 'mpp': UTCDateTime(2016, 1, 24, 10, 50, 43), 'fm': None,
|
||||||
|
'spe': 3.3333333333333335, 'channel': u'LHE'}}
|
||||||
with HidePrints():
|
with HidePrints():
|
||||||
result, station = autopickstation(wfstream=self.ech, pickparam=self.pickparam_taupy_enabled, metadata=self.metadata, origin=self.origin)
|
result, station = autopickstation(wfstream=self.ech, pickparam=self.pickparam_taupy_enabled,
|
||||||
|
metadata=self.metadata, origin=self.origin)
|
||||||
self.assertDictContainsSubset(expected=expected['P'], actual=result['P'])
|
self.assertDictContainsSubset(expected=expected['P'], actual=result['P'])
|
||||||
self.assertDictContainsSubset(expected=expected['S'], actual=result['S'])
|
self.assertDictContainsSubset(expected=expected['S'], actual=result['S'])
|
||||||
self.assertEqual('ECH', station)
|
self.assertEqual('ECH', station)
|
||||||
|
|
||||||
def test_autopickstation_taupy_disabled_fiesa(self):
|
def test_autopickstation_taupy_disabled_fiesa(self):
|
||||||
# this station has a long time of before the first onset, so taupy will help during picking
|
# this station has a long time of before the first onset, so taupy will help during picking
|
||||||
expected = {'P': {'picker': 'auto', 'snrdb': None, 'weight': 9, 'Mo': None, 'marked': 'SinsteadP', 'Mw': None, 'fc': None, 'snr': None, 'mpp': UTCDateTime(2016, 1, 24, 10, 35, 58), 'w0': None, 'spe': None, 'network': u'CH', 'epp': UTCDateTime(2016, 1, 24, 10, 35, 42), 'lpp': UTCDateTime(2016, 1, 24, 10, 36, 14), 'fm': 'N', 'channel': u'LHZ'}, 'S': {'picker': 'auto', 'snrdb': None, 'network': u'CH', 'weight': 4, 'Ao': None, 'lpp': UTCDateTime(2016, 1, 24, 10, 36, 14), 'snr': None, 'epp': UTCDateTime(2016, 1, 24, 10, 35, 42), 'mpp': UTCDateTime(2016, 1, 24, 10, 35, 58), 'fm': None, 'spe': None, 'channel': u'LHE'}}
|
expected = {'P': {'picker': 'auto', 'snrdb': None, 'weight': 9, 'Mo': None, 'marked': 'SinsteadP', 'Mw': None,
|
||||||
|
'fc': None, 'snr': None, 'mpp': UTCDateTime(2016, 1, 24, 10, 35, 58), 'w0': None, 'spe': None,
|
||||||
|
'network': u'CH', 'epp': UTCDateTime(2016, 1, 24, 10, 35, 42),
|
||||||
|
'lpp': UTCDateTime(2016, 1, 24, 10, 36, 14), 'fm': 'N', 'channel': u'LHZ'},
|
||||||
|
'S': {'picker': 'auto', 'snrdb': None, 'network': u'CH', 'weight': 4, 'Ao': None,
|
||||||
|
'lpp': UTCDateTime(2016, 1, 24, 10, 36, 14), 'snr': None,
|
||||||
|
'epp': UTCDateTime(2016, 1, 24, 10, 35, 42), 'mpp': UTCDateTime(2016, 1, 24, 10, 35, 58),
|
||||||
|
'fm': None, 'spe': None, 'channel': u'LHE'}}
|
||||||
with HidePrints():
|
with HidePrints():
|
||||||
result, station = autopickstation(wfstream=self.fiesa, pickparam=self.pickparam_taupy_disabled)
|
result, station = autopickstation(wfstream=self.fiesa, pickparam=self.pickparam_taupy_disabled)
|
||||||
self.assertDictContainsSubset(expected=expected['P'], actual=result['P'])
|
self.assertDictContainsSubset(expected=expected['P'], actual=result['P'])
|
||||||
@ -164,9 +230,18 @@ class TestAutopickStation(unittest.TestCase):
|
|||||||
|
|
||||||
def test_autopickstation_taupy_enabled_fiesa(self):
|
def test_autopickstation_taupy_enabled_fiesa(self):
|
||||||
# this station has a long time of before the first onset, so taupy will help during picking
|
# this station has a long time of before the first onset, so taupy will help during picking
|
||||||
expected = {'P': {'picker': 'auto', 'snrdb': 13.921049277904373, 'weight': 0, 'Mo': None, 'marked': [], 'Mw': None, 'fc': None, 'snr': 24.666352170589487, 'mpp': UTCDateTime(2016, 1, 24, 10, 41, 47), 'w0': None, 'spe': 1.2222222222222285, 'network': u'CH', 'epp': UTCDateTime(2016, 1, 24, 10, 41, 43, 333333), 'lpp': UTCDateTime(2016, 1, 24, 10, 41, 48), 'fm': None, 'channel': u'LHZ'}, 'S': {'picker': 'auto', 'snrdb': 10.893086316477728, 'network': u'CH', 'weight': 0, 'Ao': None, 'lpp': UTCDateTime(2016, 1, 24, 10, 51, 5), 'snr': 12.283118216397849, 'epp': UTCDateTime(2016, 1, 24, 10, 50, 59, 333333), 'mpp': UTCDateTime(2016, 1, 24, 10, 51, 2), 'fm': None, 'spe': 2.8888888888888764, 'channel': u'LHE'}}
|
expected = {
|
||||||
|
'P': {'picker': 'auto', 'snrdb': 13.921049277904373, 'weight': 0, 'Mo': None, 'marked': [], 'Mw': None,
|
||||||
|
'fc': None, 'snr': 24.666352170589487, 'mpp': UTCDateTime(2016, 1, 24, 10, 41, 47), 'w0': None,
|
||||||
|
'spe': 1.2222222222222285, 'network': u'CH', 'epp': UTCDateTime(2016, 1, 24, 10, 41, 43, 333333),
|
||||||
|
'lpp': UTCDateTime(2016, 1, 24, 10, 41, 48), 'fm': None, 'channel': u'LHZ'},
|
||||||
|
'S': {'picker': 'auto', 'snrdb': 10.893086316477728, 'network': u'CH', 'weight': 0, 'Ao': None,
|
||||||
|
'lpp': UTCDateTime(2016, 1, 24, 10, 51, 5), 'snr': 12.283118216397849,
|
||||||
|
'epp': UTCDateTime(2016, 1, 24, 10, 50, 59, 333333), 'mpp': UTCDateTime(2016, 1, 24, 10, 51, 2),
|
||||||
|
'fm': None, 'spe': 2.8888888888888764, 'channel': u'LHE'}}
|
||||||
with HidePrints():
|
with HidePrints():
|
||||||
result, station = autopickstation(wfstream=self.fiesa, pickparam=self.pickparam_taupy_enabled, metadata=self.metadata, origin=self.origin)
|
result, station = autopickstation(wfstream=self.fiesa, pickparam=self.pickparam_taupy_enabled,
|
||||||
|
metadata=self.metadata, origin=self.origin)
|
||||||
self.assertDictContainsSubset(expected=expected['P'], actual=result['P'])
|
self.assertDictContainsSubset(expected=expected['P'], actual=result['P'])
|
||||||
self.assertDictContainsSubset(expected=expected['S'], actual=result['S'])
|
self.assertDictContainsSubset(expected=expected['S'], actual=result['S'])
|
||||||
self.assertEqual('FIESA', station)
|
self.assertEqual('FIESA', station)
|
||||||
@ -176,7 +251,8 @@ class TestAutopickStation(unittest.TestCase):
|
|||||||
wfstream = self.gra1.copy()
|
wfstream = self.gra1.copy()
|
||||||
wfstream = wfstream.select(channel='*E') + wfstream.select(channel='*N')
|
wfstream = wfstream.select(channel='*E') + wfstream.select(channel='*N')
|
||||||
with HidePrints():
|
with HidePrints():
|
||||||
result, station = autopickstation(wfstream=wfstream, pickparam=self.pickparam_taupy_disabled, metadata=(None, None))
|
result, station = autopickstation(wfstream=wfstream, pickparam=self.pickparam_taupy_disabled,
|
||||||
|
metadata=(None, None))
|
||||||
self.assertIsNone(result)
|
self.assertIsNone(result)
|
||||||
self.assertEqual('GRA1', station)
|
self.assertEqual('GRA1', station)
|
||||||
|
|
||||||
@ -184,17 +260,36 @@ class TestAutopickStation(unittest.TestCase):
|
|||||||
"""Picking on a stream without horizontal traces should still pick the P phase on the vertical component"""
|
"""Picking on a stream without horizontal traces should still pick the P phase on the vertical component"""
|
||||||
wfstream = self.gra1.copy()
|
wfstream = self.gra1.copy()
|
||||||
wfstream = wfstream.select(channel='*Z')
|
wfstream = wfstream.select(channel='*Z')
|
||||||
expected = {'P': {'picker': 'auto', 'snrdb': 15.405649120980094, 'network': u'GR', 'weight': 0, 'Ao': None, 'Mo': None, 'marked': [], 'lpp': UTCDateTime(2016, 1, 24, 10, 41, 32, 690000), 'Mw': None, 'fc': None, 'snr': 34.718816470730317, 'epp': UTCDateTime(2016, 1, 24, 10, 41, 28, 890000), 'mpp': UTCDateTime(2016, 1, 24, 10, 41, 31, 690000), 'w0': None, 'spe': 0.9333333333333323, 'fm': 'D', 'channel': u'LHZ'}, 'S': {'picker': 'auto', 'snrdb': None, 'network': None, 'weight': 4, 'Mo': None, 'Ao': None, 'lpp': None, 'Mw': None, 'fc': None, 'snr': None, 'marked': [], 'mpp': None, 'w0': None, 'spe': None, 'epp': None, 'fm': 'N', 'channel': None}}
|
expected = {
|
||||||
|
'P': {'picker': 'auto', 'snrdb': 15.405649120980094, 'network': u'GR', 'weight': 0, 'Ao': None, 'Mo': None,
|
||||||
|
'marked': [], 'lpp': UTCDateTime(2016, 1, 24, 10, 41, 32, 690000), 'Mw': None, 'fc': None,
|
||||||
|
'snr': 34.718816470730317, 'epp': UTCDateTime(2016, 1, 24, 10, 41, 28, 890000),
|
||||||
|
'mpp': UTCDateTime(2016, 1, 24, 10, 41, 31, 690000), 'w0': None, 'spe': 0.9333333333333323, 'fm': 'D',
|
||||||
|
'channel': u'LHZ'},
|
||||||
|
'S': {'picker': 'auto', 'snrdb': None, 'network': None, 'weight': 4, 'Mo': None, 'Ao': None, 'lpp': None,
|
||||||
|
'Mw': None, 'fc': None, 'snr': None, 'marked': [], 'mpp': None, 'w0': None, 'spe': None, 'epp': None,
|
||||||
|
'fm': 'N', 'channel': None}}
|
||||||
with HidePrints():
|
with HidePrints():
|
||||||
result, station = autopickstation(wfstream=wfstream, pickparam=self.pickparam_taupy_disabled, metadata=(None, None))
|
result, station = autopickstation(wfstream=wfstream, pickparam=self.pickparam_taupy_disabled,
|
||||||
|
metadata=(None, None))
|
||||||
self.assertEqual(expected, result)
|
self.assertEqual(expected, result)
|
||||||
self.assertEqual('GRA1', station)
|
self.assertEqual('GRA1', station)
|
||||||
|
|
||||||
def test_autopickstation_a106_taupy_enabled(self):
|
def test_autopickstation_a106_taupy_enabled(self):
|
||||||
"""This station has invalid values recorded on both N and E component, but a pick can still be found on Z"""
|
"""This station has invalid values recorded on both N and E component, but a pick can still be found on Z"""
|
||||||
expected = {'P': {'picker': 'auto', 'snrdb': 12.862128789922826, 'network': u'Z3', 'weight': 0, 'Ao': None, 'Mo': None, 'marked': [], 'lpp': UTCDateTime(2016, 1, 24, 10, 41, 34), 'Mw': None, 'fc': None, 'snr': 19.329155459132608, 'epp': UTCDateTime(2016, 1, 24, 10, 41, 30), 'mpp': UTCDateTime(2016, 1, 24, 10, 41, 33), 'w0': None, 'spe': 1.6666666666666667, 'fm': None, 'channel': u'LHZ'}, 'S': {'picker': 'auto', 'snrdb': None, 'network': u'Z3', 'weight': 4, 'Ao': None, 'Mo': None, 'marked': [], 'lpp': UTCDateTime(2016, 1, 24, 10, 28, 56), 'Mw': None, 'fc': None, 'snr': None, 'epp': UTCDateTime(2016, 1, 24, 10, 28, 24), 'mpp': UTCDateTime(2016, 1, 24, 10, 28, 40), 'w0': None, 'spe': None, 'fm': None, 'channel': u'LHE'}}
|
expected = {
|
||||||
|
'P': {'picker': 'auto', 'snrdb': 12.862128789922826, 'network': u'Z3', 'weight': 0, 'Ao': None, 'Mo': None,
|
||||||
|
'marked': [], 'lpp': UTCDateTime(2016, 1, 24, 10, 41, 34), 'Mw': None, 'fc': None,
|
||||||
|
'snr': 19.329155459132608, 'epp': UTCDateTime(2016, 1, 24, 10, 41, 30),
|
||||||
|
'mpp': UTCDateTime(2016, 1, 24, 10, 41, 33), 'w0': None, 'spe': 1.6666666666666667, 'fm': None,
|
||||||
|
'channel': u'LHZ'},
|
||||||
|
'S': {'picker': 'auto', 'snrdb': None, 'network': u'Z3', 'weight': 4, 'Ao': None, 'Mo': None, 'marked': [],
|
||||||
|
'lpp': UTCDateTime(2016, 1, 24, 10, 28, 56), 'Mw': None, 'fc': None, 'snr': None,
|
||||||
|
'epp': UTCDateTime(2016, 1, 24, 10, 28, 24), 'mpp': UTCDateTime(2016, 1, 24, 10, 28, 40), 'w0': None,
|
||||||
|
'spe': None, 'fm': None, 'channel': u'LHE'}}
|
||||||
with HidePrints():
|
with HidePrints():
|
||||||
result, station = autopickstation(wfstream=self.a106, pickparam=self.pickparam_taupy_enabled, metadata=self.metadata, origin=self.origin)
|
result, station = autopickstation(wfstream=self.a106, pickparam=self.pickparam_taupy_enabled,
|
||||||
|
metadata=self.metadata, origin=self.origin)
|
||||||
self.assertEqual(expected, result)
|
self.assertEqual(expected, result)
|
||||||
|
|
||||||
def test_autopickstation_station_missing_in_metadata(self):
|
def test_autopickstation_station_missing_in_metadata(self):
|
||||||
@ -202,10 +297,22 @@ class TestAutopickStation(unittest.TestCase):
|
|||||||
relative to the theoretical onset to one relative to the traces starttime, eg never negative.
|
relative to the theoretical onset to one relative to the traces starttime, eg never negative.
|
||||||
"""
|
"""
|
||||||
self.pickparam_taupy_enabled.setParamKV('pstart', -100) # modify starttime to be relative to theoretical onset
|
self.pickparam_taupy_enabled.setParamKV('pstart', -100) # modify starttime to be relative to theoretical onset
|
||||||
expected = {'P': {'picker': 'auto', 'snrdb': 14.464757855513506, 'network': u'Z3', 'weight': 0, 'Mo': None, 'Ao': None, 'lpp': UTCDateTime(2016, 1, 24, 10, 41, 39, 605000), 'Mw': None, 'fc': None, 'snr': 27.956048519707181, 'marked': [], 'mpp': UTCDateTime(2016, 1, 24, 10, 41, 38, 605000), 'w0': None, 'spe': 1.6666666666666667, 'epp': UTCDateTime(2016, 1, 24, 10, 41, 35, 605000), 'fm': None, 'channel': u'LHZ'}, 'S': {'picker': 'auto', 'snrdb': 10.112844176301248, 'network': u'Z3', 'weight': 1, 'Mo': None, 'Ao': None, 'lpp': UTCDateTime(2016, 1, 24, 10, 50, 51, 605000), 'Mw': None, 'fc': None, 'snr': 10.263238413785425, 'marked': [], 'mpp': UTCDateTime(2016, 1, 24, 10, 50, 48, 605000), 'w0': None, 'spe': 4.666666666666667, 'epp': UTCDateTime(2016, 1, 24, 10, 50, 40, 605000), 'fm': None, 'channel': u'LHE'}}
|
expected = {
|
||||||
|
'P': {'picker': 'auto', 'snrdb': 14.464757855513506, 'network': u'Z3', 'weight': 0, 'Mo': None, 'Ao': None,
|
||||||
|
'lpp': UTCDateTime(2016, 1, 24, 10, 41, 39, 605000), 'Mw': None, 'fc': None,
|
||||||
|
'snr': 27.956048519707181, 'marked': [], 'mpp': UTCDateTime(2016, 1, 24, 10, 41, 38, 605000),
|
||||||
|
'w0': None, 'spe': 1.6666666666666667, 'epp': UTCDateTime(2016, 1, 24, 10, 41, 35, 605000),
|
||||||
|
'fm': None, 'channel': u'LHZ'},
|
||||||
|
'S': {'picker': 'auto', 'snrdb': 10.112844176301248, 'network': u'Z3', 'weight': 1, 'Mo': None, 'Ao': None,
|
||||||
|
'lpp': UTCDateTime(2016, 1, 24, 10, 50, 51, 605000), 'Mw': None, 'fc': None,
|
||||||
|
'snr': 10.263238413785425, 'marked': [], 'mpp': UTCDateTime(2016, 1, 24, 10, 50, 48, 605000),
|
||||||
|
'w0': None, 'spe': 4.666666666666667, 'epp': UTCDateTime(2016, 1, 24, 10, 50, 40, 605000), 'fm': None,
|
||||||
|
'channel': u'LHE'}}
|
||||||
with HidePrints():
|
with HidePrints():
|
||||||
result, station = autopickstation(wfstream = self.a005a, pickparam=self.pickparam_taupy_enabled, metadata=self.metadata, origin=self.origin)
|
result, station = autopickstation(wfstream=self.a005a, pickparam=self.pickparam_taupy_enabled,
|
||||||
|
metadata=self.metadata, origin=self.origin)
|
||||||
self.assertEqual(expected, result)
|
self.assertEqual(expected, result)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
from pylot.core.pick.utils import get_quality_class
|
from pylot.core.pick.utils import get_quality_class
|
||||||
|
|
||||||
|
|
||||||
@ -52,5 +53,6 @@ class TestQualityClassFromUncertainty(unittest.TestCase):
|
|||||||
# Error exactly in class 3
|
# Error exactly in class 3
|
||||||
self.assertEqual(3, get_quality_class(5.6, self.error_classes))
|
self.assertEqual(3, get_quality_class(5.6, self.error_classes))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
@ -33,6 +33,7 @@ class HidePrints:
|
|||||||
def silencer(*args, **kwargs):
|
def silencer(*args, **kwargs):
|
||||||
with HidePrints():
|
with HidePrints():
|
||||||
func(*args, **kwargs)
|
func(*args, **kwargs)
|
||||||
|
|
||||||
return silencer
|
return silencer
|
||||||
|
|
||||||
def __init__(self, hide_prints=True):
|
def __init__(self, hide_prints=True):
|
||||||
@ -49,4 +50,4 @@ class HidePrints:
|
|||||||
def __exit__(self, exc_type, exc_val, exc_tb):
|
def __exit__(self, exc_type, exc_val, exc_tb):
|
||||||
"""Reinstate old stdout"""
|
"""Reinstate old stdout"""
|
||||||
if self.hide:
|
if self.hide:
|
||||||
sys.stdout = self._original_stdout
|
sys.stdout = self._original_stdout
|
||||||
|
Loading…
Reference in New Issue
Block a user