Merge branch 'develop' into filterOptions
529
QtPyLoT.py
@ -41,6 +41,8 @@ from PySide.QtGui import QMainWindow, QInputDialog, QIcon, QFileDialog, \
|
|||||||
QTreeView, QComboBox, QTabWidget, QPushButton, QGridLayout
|
QTreeView, QComboBox, QTabWidget, QPushButton, QGridLayout
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from obspy import UTCDateTime
|
from obspy import UTCDateTime
|
||||||
|
from obspy.core.event import Magnitude
|
||||||
|
from obspy.core.util import AttribDict
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import pyqtgraph as pg
|
import pyqtgraph as pg
|
||||||
@ -70,6 +72,7 @@ from pylot.core.util.connection import checkurl
|
|||||||
from pylot.core.util.dataprocessing import read_metadata, restitute_data
|
from pylot.core.util.dataprocessing import read_metadata, restitute_data
|
||||||
from pylot.core.util.utils import fnConstructor, getLogin, \
|
from pylot.core.util.utils import fnConstructor, getLogin, \
|
||||||
full_range
|
full_range
|
||||||
|
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
|
||||||
from pylot.core.util.widgets import FilterOptionsDialog, NewEventDlg, \
|
from pylot.core.util.widgets import FilterOptionsDialog, NewEventDlg, \
|
||||||
WaveformWidget, WaveformWidgetPG, PropertiesDlg, HelpForm, createAction, PickDlg, \
|
WaveformWidget, WaveformWidgetPG, PropertiesDlg, HelpForm, createAction, PickDlg, \
|
||||||
@ -143,6 +146,7 @@ class MainWindow(QMainWindow):
|
|||||||
self.data = Data(self, lastEvent)
|
self.data = Data(self, lastEvent)
|
||||||
else:
|
else:
|
||||||
self.data = Data(self)
|
self.data = Data(self)
|
||||||
|
self.data._new = False
|
||||||
self.autodata = Data(self)
|
self.autodata = Data(self)
|
||||||
|
|
||||||
if settings.value("user/FullName", None) is None:
|
if settings.value("user/FullName", None) is None:
|
||||||
@ -166,14 +170,19 @@ class MainWindow(QMainWindow):
|
|||||||
settings.setValue("data/dataRoot", dirname)
|
settings.setValue("data/dataRoot", dirname)
|
||||||
if settings.value('compclass', None) is None:
|
if settings.value('compclass', None) is None:
|
||||||
settings.setValue('compclass', SetChannelComponents())
|
settings.setValue('compclass', SetChannelComponents())
|
||||||
|
if settings.value('output/Format', None) is None:
|
||||||
|
outformat = QInputDialog.getText(self,
|
||||||
|
"Enter output format (*.xml, *.cnv, *.obs):",
|
||||||
|
"Format")
|
||||||
|
settings.setValue("output/Format", outformat)
|
||||||
settings.sync()
|
settings.sync()
|
||||||
|
|
||||||
# setup UI
|
# setup UI
|
||||||
self.setupUi()
|
self.setupUi()
|
||||||
|
|
||||||
self.filteroptions = {}
|
self.filteroptions = {}
|
||||||
self.picks = {}
|
self.pylot_picks = {}
|
||||||
self.autopicks = {}
|
self.pylot_autopicks = {}
|
||||||
self.loc = False
|
self.loc = False
|
||||||
|
|
||||||
def setupUi(self):
|
def setupUi(self):
|
||||||
@ -243,25 +252,42 @@ class MainWindow(QMainWindow):
|
|||||||
self.tabs.setCurrentIndex(0)
|
self.tabs.setCurrentIndex(0)
|
||||||
|
|
||||||
quitIcon = self.style().standardIcon(QStyle.SP_MediaStop)
|
quitIcon = self.style().standardIcon(QStyle.SP_MediaStop)
|
||||||
saveIcon = self.style().standardIcon(QStyle.SP_DriveHDIcon)
|
|
||||||
openIcon = self.style().standardIcon(QStyle.SP_DirOpenIcon)
|
|
||||||
helpIcon = self.style().standardIcon(QStyle.SP_DialogHelpButton)
|
helpIcon = self.style().standardIcon(QStyle.SP_DialogHelpButton)
|
||||||
newIcon = self.style().standardIcon(QStyle.SP_FileIcon)
|
|
||||||
newFolderIcon = self.style().standardIcon(QStyle.SP_FileDialogNewFolder)
|
newFolderIcon = self.style().standardIcon(QStyle.SP_FileDialogNewFolder)
|
||||||
|
|
||||||
# create resource icons
|
# create resource icons
|
||||||
locactionicon = QIcon()
|
newIcon = QIcon()
|
||||||
locactionicon.addPixmap(QPixmap(':/icons/locactionicon.png'))
|
newIcon.addPixmap(QPixmap(':/icons/newfile.png'))
|
||||||
manupicksicon = QIcon()
|
addIcon = QIcon()
|
||||||
manupicksicon.addPixmap(QPixmap(':/icons/manupicsicon.png'))
|
addIcon.addPixmap(QPixmap(':/icons/add.png'))
|
||||||
autopicksicon = QIcon()
|
saveIcon = QIcon()
|
||||||
autopicksicon.addPixmap(QPixmap(':/icons/autopicsicon.png'))
|
saveIcon.addPixmap(QPixmap(':/icons/save.png'))
|
||||||
|
saveasIcon = QIcon()
|
||||||
|
saveasIcon.addPixmap(QPixmap(':/icons/saveas.png'))
|
||||||
|
saveProjectIcon = QIcon()
|
||||||
|
saveProjectIcon.addPixmap(QPixmap(':/icons/saveproject.png'))
|
||||||
|
saveProjectAsIcon = QIcon()
|
||||||
|
saveProjectAsIcon.addPixmap(QPixmap(':/icons/saveprojectas.png'))
|
||||||
|
openIcon = QIcon()
|
||||||
|
openIcon.addPixmap(QPixmap(':/icons/openfile.png'))
|
||||||
|
openProjectIcon = QIcon()
|
||||||
|
openProjectIcon.addPixmap(QPixmap(':/icons/openproject.png'))
|
||||||
|
openLocIcon = QIcon()
|
||||||
|
openLocIcon.addPixmap(QPixmap(':/icons/openloc.png'))
|
||||||
|
openEventIcon = QIcon()
|
||||||
|
openEventIcon.addPixmap(QPixmap(':/icons/openpick.png'))
|
||||||
|
openEventsIcon = QIcon()
|
||||||
|
openEventsIcon.addPixmap(QPixmap(':/icons/openpicks.png'))
|
||||||
|
saveEventsIcon = QIcon()
|
||||||
|
saveEventsIcon.addPixmap(QPixmap(':/icons/savepicks.png'))
|
||||||
|
prefIcon = QIcon()
|
||||||
|
prefIcon.addPixmap(QPixmap(':/icons/preferences.png'))
|
||||||
|
paraIcon = QIcon()
|
||||||
|
paraIcon.addPixmap(QPixmap(':/icons/parameter.png'))
|
||||||
self.autopicksicon_small = QIcon()
|
self.autopicksicon_small = QIcon()
|
||||||
self.autopicksicon_small.addPixmap(QPixmap(':/icons/autopicksicon_small.png'))
|
self.autopicksicon_small.addPixmap(QPixmap(':/icons/autopicksicon_small.png'))
|
||||||
self.manupicksicon_small = QIcon()
|
self.manupicksicon_small = QIcon()
|
||||||
self.manupicksicon_small.addPixmap(QPixmap(':/icons/manupicksicon_small.png'))
|
self.manupicksicon_small.addPixmap(QPixmap(':/icons/manupicksicon_small.png'))
|
||||||
saveProjectIcon = QIcon()
|
|
||||||
saveProjectIcon.addPixmap(QPixmap(':/icons/Library-icon.png'))
|
|
||||||
loadpiloticon = QIcon()
|
loadpiloticon = QIcon()
|
||||||
loadpiloticon.addPixmap(QPixmap(':/icons/Matlab_PILOT_icon.png'))
|
loadpiloticon.addPixmap(QPixmap(':/icons/Matlab_PILOT_icon.png'))
|
||||||
p_icon = QIcon()
|
p_icon = QIcon()
|
||||||
@ -279,7 +305,7 @@ class MainWindow(QMainWindow):
|
|||||||
e_icon = QIcon()
|
e_icon = QIcon()
|
||||||
e_icon.addPixmap(QPixmap(':/icons/key_E.png'))
|
e_icon.addPixmap(QPixmap(':/icons/key_E.png'))
|
||||||
autotune_icon = QIcon()
|
autotune_icon = QIcon()
|
||||||
autotune_icon.addPixmap(QPixmap(':/icons/autopick_button.png'))
|
autotune_icon.addPixmap(QPixmap(':/icons/tune.png'))
|
||||||
autopylot_icon = QIcon()
|
autopylot_icon = QIcon()
|
||||||
autopylot_icon.addPixmap(QPixmap(':/icons/autopylot_button'))
|
autopylot_icon.addPixmap(QPixmap(':/icons/autopylot_button'))
|
||||||
locate_icon = QIcon()
|
locate_icon = QIcon()
|
||||||
@ -293,7 +319,7 @@ class MainWindow(QMainWindow):
|
|||||||
self.openProjectAction = self.createAction(self, "&Open project ...",
|
self.openProjectAction = self.createAction(self, "&Open project ...",
|
||||||
self.loadProject,
|
self.loadProject,
|
||||||
QKeySequence.Open,
|
QKeySequence.Open,
|
||||||
openIcon,
|
openProjectIcon,
|
||||||
"Load project file")
|
"Load project file")
|
||||||
self.saveProjectAction = self.createAction(self, "&Save project ...",
|
self.saveProjectAction = self.createAction(self, "&Save project ...",
|
||||||
self.saveProject,
|
self.saveProject,
|
||||||
@ -304,34 +330,34 @@ class MainWindow(QMainWindow):
|
|||||||
self.saveProjectAsAction = self.createAction(self, "Save project as ...",
|
self.saveProjectAsAction = self.createAction(self, "Save project as ...",
|
||||||
self.saveProjectAs,
|
self.saveProjectAs,
|
||||||
QKeySequence.SaveAs,
|
QKeySequence.SaveAs,
|
||||||
saveProjectIcon,
|
saveProjectAsIcon,
|
||||||
"Save project file as...")
|
"Save project file as...")
|
||||||
self.saveProjectAsAction.setEnabled(False)
|
self.saveProjectAsAction.setEnabled(False)
|
||||||
# newEventAction = self.createAction(self, "&New event ...",
|
# newEventAction = self.createAction(self, "&New event ...",
|
||||||
# self.createNewEvent,
|
# self.createNewEvent,
|
||||||
# QKeySequence.New, newIcon,
|
# QKeySequence.New, newIcon,
|
||||||
# "Create a new event.")
|
# "Create a new event.")
|
||||||
self.openmanualpicksaction = self.createAction(self, "Load &manual picks ...",
|
self.openmanualpicksaction = self.createAction(self, "Load event ...",
|
||||||
self.load_data,
|
self.load_data,
|
||||||
"Ctrl+M",
|
"Ctrl+M",
|
||||||
manupicksicon,
|
openEventIcon,
|
||||||
"Load manual picks for "
|
"Load event information for "
|
||||||
"the displayed event.")
|
"the displayed event.")
|
||||||
self.openmanualpicksaction.setEnabled(False)
|
self.openmanualpicksaction.setEnabled(False)
|
||||||
self.openmanualpicksaction.setData(None)
|
self.openmanualpicksaction.setData(None)
|
||||||
|
|
||||||
self.openautopicksaction = self.createAction(self, "Load &automatic picks ... ",
|
self.openautopicksaction = self.createAction(self, "Load event information &automatically ... ",
|
||||||
self.load_autopicks,
|
self.load_multiple_data,
|
||||||
"Ctrl+A",
|
"Ctrl+A",
|
||||||
autopicksicon,
|
openEventsIcon,
|
||||||
"Load automatic picks "
|
"Load event data automatically "
|
||||||
"for the displayed event.")
|
"for for all events.")
|
||||||
self.openautopicksaction.setEnabled(False)
|
self.openautopicksaction.setEnabled(False)
|
||||||
self.openautopicksaction.setData(None)
|
self.openautopicksaction.setData(None)
|
||||||
|
|
||||||
self.loadlocationaction = self.createAction(self, "Load &location ...",
|
self.loadlocationaction = self.createAction(self, "Load &location ...",
|
||||||
self.load_loc, "Ctrl+L",
|
self.load_loc, "Ctrl+L",
|
||||||
locactionicon,
|
openLocIcon,
|
||||||
"Load location information on "
|
"Load location information on "
|
||||||
"the displayed event.")
|
"the displayed event.")
|
||||||
self.loadlocationaction.setEnabled(False)
|
self.loadlocationaction.setEnabled(False)
|
||||||
@ -345,17 +371,17 @@ class MainWindow(QMainWindow):
|
|||||||
|
|
||||||
self.saveManualPicksAction = self.createAction(self, "Save &picks ...",
|
self.saveManualPicksAction = self.createAction(self, "Save &picks ...",
|
||||||
self.saveData, "Ctrl+P",
|
self.saveData, "Ctrl+P",
|
||||||
saveIcon, "Save event pick data.")
|
saveEventsIcon, "Save event pick data.")
|
||||||
self.disableSaveManualPicksAction()
|
self.disableSaveManualPicksAction()
|
||||||
|
|
||||||
self.addEventDataAction = self.createAction(self, "Add &events ...",
|
self.addEventDataAction = self.createAction(self, "Add &events ...",
|
||||||
self.add_events,
|
self.add_events,
|
||||||
"Ctrl+E", newFolderIcon,
|
"Ctrl+E", addIcon,
|
||||||
"Add event data")
|
"Add event data")
|
||||||
prefsEventAction = self.createAction(self, "Preferences",
|
prefsEventAction = self.createAction(self, "Preferences",
|
||||||
self.PyLoTprefs,
|
self.PyLoTprefs,
|
||||||
QKeySequence.Preferences,
|
QKeySequence.Preferences,
|
||||||
QIcon(None),
|
prefIcon,
|
||||||
"Edit PyLoT app preferences.")
|
"Edit PyLoT app preferences.")
|
||||||
quitAction = self.createAction(self, "&Quit",
|
quitAction = self.createAction(self, "&Quit",
|
||||||
QCoreApplication.instance().quit,
|
QCoreApplication.instance().quit,
|
||||||
@ -363,7 +389,7 @@ class MainWindow(QMainWindow):
|
|||||||
"Close event and quit PyLoT")
|
"Close event and quit PyLoT")
|
||||||
self.parameterAction = self.createAction(self, "Parameter",
|
self.parameterAction = self.createAction(self, "Parameter",
|
||||||
self.setParameter,
|
self.setParameter,
|
||||||
None, QIcon(None),
|
None, paraIcon,
|
||||||
"Modify Parameter")
|
"Modify Parameter")
|
||||||
self.filterAction = self.createAction(self, "&Filter ...",
|
self.filterAction = self.createAction(self, "&Filter ...",
|
||||||
self.filterWaveformData,
|
self.filterWaveformData,
|
||||||
@ -373,7 +399,7 @@ class MainWindow(QMainWindow):
|
|||||||
desired seismic phase.""", True)
|
desired seismic phase.""", True)
|
||||||
filterEditAction = self.createAction(self, "&Filter parameter ...",
|
filterEditAction = self.createAction(self, "&Filter parameter ...",
|
||||||
self.adjustFilterOptions,
|
self.adjustFilterOptions,
|
||||||
"Alt+F", QIcon(None),
|
"Alt+F", filter_icon,
|
||||||
"""Adjust filter parameters.""")
|
"""Adjust filter parameters.""")
|
||||||
self.selectPAction = self.createAction(self, "&P", self.alterPhase,
|
self.selectPAction = self.createAction(self, "&P", self.alterPhase,
|
||||||
"Alt+P",
|
"Alt+P",
|
||||||
@ -422,11 +448,15 @@ class MainWindow(QMainWindow):
|
|||||||
fileToolBar = self.addToolBar("FileTools")
|
fileToolBar = self.addToolBar("FileTools")
|
||||||
fileToolActions = (self.newProjectAction, self.addEventDataAction,
|
fileToolActions = (self.newProjectAction, self.addEventDataAction,
|
||||||
self.openProjectAction, self.saveProjectAction,
|
self.openProjectAction, self.saveProjectAction,
|
||||||
self.saveProjectAsAction, self.openmanualpicksaction,
|
self.saveProjectAsAction)
|
||||||
self.openautopicksaction, self.loadlocationaction,
|
|
||||||
self.loadpilotevent, self.saveManualPicksAction)
|
|
||||||
fileToolBar.setObjectName("FileTools")
|
fileToolBar.setObjectName("FileTools")
|
||||||
self.addActions(fileToolBar, fileToolActions)
|
self.addActions(fileToolBar, fileToolActions)
|
||||||
|
eventToolActions = (self.openmanualpicksaction, self.openautopicksaction,
|
||||||
|
self.saveManualPicksAction, self.loadlocationaction,
|
||||||
|
self.loadpilotevent)
|
||||||
|
eventToolBar = self.addToolBar("EventTools")
|
||||||
|
eventToolBar.setObjectName("EventTools")
|
||||||
|
self.addActions(eventToolBar, eventToolActions)
|
||||||
|
|
||||||
# phaseToolBar = self.addToolBar("PhaseTools")
|
# phaseToolBar = self.addToolBar("PhaseTools")
|
||||||
# phaseToolActions = (self.selectPAction, self.selectSAction)
|
# phaseToolActions = (self.selectPAction, self.selectSAction)
|
||||||
@ -637,23 +667,66 @@ class MainWindow(QMainWindow):
|
|||||||
fname_dict = dict(phasfn=fn_phases, locfn=fn_loc)
|
fname_dict = dict(phasfn=fn_phases, locfn=fn_loc)
|
||||||
self.load_data(fname_dict, type=type)
|
self.load_data(fname_dict, type=type)
|
||||||
|
|
||||||
def load_data(self, fname=None, type='manual', loc=False):
|
def load_multiple_data(self, type='manual'):
|
||||||
if not self.okToContinue():
|
if not self.okToContinue():
|
||||||
return
|
return
|
||||||
|
refresh=False
|
||||||
|
events = self.project.eventlist
|
||||||
|
fext = '.xml'
|
||||||
|
for event in events:
|
||||||
|
path = event.path
|
||||||
|
eventname = path.split('/')[-1]
|
||||||
|
filename = os.path.join(path, 'PyLoT_'+eventname+fext)
|
||||||
|
if os.path.isfile(filename):
|
||||||
|
self.load_data(filename, draw=False, event=event, overwrite=True)
|
||||||
|
refresh=True
|
||||||
|
if not refresh:
|
||||||
|
return
|
||||||
|
if self.get_current_event().pylot_picks:
|
||||||
|
self.refreshEvents()
|
||||||
|
self.setDirty(True)
|
||||||
|
|
||||||
|
def load_data(self, fname=None, type='manual', loc=False, draw=True, event=None, overwrite=False):
|
||||||
|
if not overwrite:
|
||||||
|
if not self.okToContinue():
|
||||||
|
return
|
||||||
if fname is None:
|
if fname is None:
|
||||||
action = self.sender()
|
action = self.sender()
|
||||||
if isinstance(action, QAction):
|
if isinstance(action, QAction):
|
||||||
fname = self.filename_from_action(action)
|
fname = self.filename_from_action(action)
|
||||||
|
if not fname:
|
||||||
|
return
|
||||||
self.set_fname(fname, type)
|
self.set_fname(fname, type)
|
||||||
data = dict(auto=self.autodata, manual=self.data)
|
#data = dict(auto=self.autodata, manual=self.data)
|
||||||
data[type] += Data(self, evtdata=fname)
|
if not event:
|
||||||
|
event = self.get_current_event()
|
||||||
|
data = Data(self, event)
|
||||||
|
try:
|
||||||
|
data_new = Data(self, evtdata=fname)
|
||||||
|
data += data_new
|
||||||
|
except ValueError:
|
||||||
|
qmb = QMessageBox(self, icon=QMessageBox.Question,
|
||||||
|
text='Warning: Missmatch in event identifiers {} and {}. Continue?'.format(
|
||||||
|
data_new.get_evt_data().resource_id,
|
||||||
|
data.get_evt_data().resource_id),
|
||||||
|
windowTitle='PyLoT - Load data warning')
|
||||||
|
qmb.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
|
||||||
|
qmb.setDefaultButton(QMessageBox.No)
|
||||||
|
ret = qmb.exec_()
|
||||||
|
if ret == qmb.Yes:
|
||||||
|
data_new.setNew()
|
||||||
|
data += data_new
|
||||||
|
else:
|
||||||
|
return
|
||||||
|
|
||||||
|
self.data = data
|
||||||
|
print('Loading {} picks from file {}.'.format(type, fname))
|
||||||
if not loc:
|
if not loc:
|
||||||
self.updatePicks(type=type)
|
self.updatePicks(type=type, event=event)
|
||||||
if self.get_current_event().picks:
|
if draw:
|
||||||
self.plotWaveformDataThread()
|
if self.get_current_event().pylot_picks:
|
||||||
self.drawPicks(picktype=type)
|
self.refreshEvents()
|
||||||
self.draw()
|
self.setDirty(True)
|
||||||
self.setDirty(True)
|
|
||||||
|
|
||||||
def add_recentfile(self, event):
|
def add_recentfile(self, event):
|
||||||
self.recentfiles.insert(0, event)
|
self.recentfiles.insert(0, event)
|
||||||
@ -676,8 +749,8 @@ class MainWindow(QMainWindow):
|
|||||||
def getWFFnames(self):
|
def getWFFnames(self):
|
||||||
try:
|
try:
|
||||||
evt = self.get_data().get_evt_data()
|
evt = self.get_data().get_evt_data()
|
||||||
if evt.picks:
|
if evt.pylot_picks:
|
||||||
for pick in evt.picks:
|
for pick in evt.pylot_picks:
|
||||||
try:
|
try:
|
||||||
if pick.waveform_id is not None:
|
if pick.waveform_id is not None:
|
||||||
fname = pick.waveform_id.getSEEDstring()
|
fname = pick.waveform_id.getSEEDstring()
|
||||||
@ -728,8 +801,8 @@ class MainWindow(QMainWindow):
|
|||||||
'''
|
'''
|
||||||
if not eventbox:
|
if not eventbox:
|
||||||
eventbox = self.eventBox
|
eventbox = self.eventBox
|
||||||
index = eventbox.currentIndex()
|
path = eventbox.currentText()
|
||||||
return eventbox.itemData(index)
|
return self.project.getEventFromPath(path)
|
||||||
|
|
||||||
def get_current_event_path(self, eventbox=None):
|
def get_current_event_path(self, eventbox=None):
|
||||||
'''
|
'''
|
||||||
@ -778,7 +851,7 @@ class MainWindow(QMainWindow):
|
|||||||
dirs = {
|
dirs = {
|
||||||
'database': path.split('/')[-2],
|
'database': path.split('/')[-2],
|
||||||
'datapath': path.split('/')[-3],
|
'datapath': path.split('/')[-3],
|
||||||
'rootpath': os.path.join(*path.split('/')[:-3])
|
'rootpath': '/'+os.path.join(*path.split('/')[:-3])
|
||||||
}
|
}
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
dirs = {
|
dirs = {
|
||||||
@ -788,6 +861,10 @@ 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.setValue("data/dataRoot", dirs['rootpath'])
|
||||||
|
settings.sync()
|
||||||
|
|
||||||
if not self.project.eventlist:
|
if not self.project.eventlist:
|
||||||
#init parameter object
|
#init parameter object
|
||||||
self.setParameter(show=False)
|
self.setParameter(show=False)
|
||||||
@ -880,10 +957,10 @@ class MainWindow(QMainWindow):
|
|||||||
event_path = event.path
|
event_path = event.path
|
||||||
event_npicks = 0
|
event_npicks = 0
|
||||||
event_nautopicks = 0
|
event_nautopicks = 0
|
||||||
if event.picks:
|
if event.pylot_picks:
|
||||||
event_npicks = len(event.picks)
|
event_npicks = len(event.pylot_picks)
|
||||||
if event.autopicks:
|
if event.pylot_autopicks:
|
||||||
event_nautopicks = len(event.autopicks)
|
event_nautopicks = len(event.pylot_autopicks)
|
||||||
event_ref = event.isRefEvent()
|
event_ref = event.isRefEvent()
|
||||||
event_test = event.isTestEvent()
|
event_test = event.isTestEvent()
|
||||||
|
|
||||||
@ -929,7 +1006,8 @@ class MainWindow(QMainWindow):
|
|||||||
'{} unequal {}.'
|
'{} unequal {}.'
|
||||||
.format(event.path, self.eventBox.itemText(id)))
|
.format(event.path, self.eventBox.itemText(id)))
|
||||||
raise ValueError(message)
|
raise ValueError(message)
|
||||||
eventBox.setItemData(id, event)
|
#not working with obspy events
|
||||||
|
#eventBox.setItemData(id, event)
|
||||||
eventBox.setCurrentIndex(index)
|
eventBox.setCurrentIndex(index)
|
||||||
self.refreshRefTestButtons()
|
self.refreshRefTestButtons()
|
||||||
|
|
||||||
@ -940,7 +1018,7 @@ class MainWindow(QMainWindow):
|
|||||||
caption = "Open an event file"
|
caption = "Open an event file"
|
||||||
fname = QFileDialog().getOpenFileName(self, caption=caption,
|
fname = QFileDialog().getOpenFileName(self, caption=caption,
|
||||||
filter=filt,
|
filter=filt,
|
||||||
dir=self.getRoot())
|
dir=self.get_current_event_path())
|
||||||
fname = fname[0]
|
fname = fname[0]
|
||||||
else:
|
else:
|
||||||
fname = str(action.data().toString())
|
fname = str(action.data().toString())
|
||||||
@ -959,27 +1037,42 @@ class MainWindow(QMainWindow):
|
|||||||
self.set_fname(self.get_data().getEventFileName(), type)
|
self.set_fname(self.get_data().getEventFileName(), type)
|
||||||
return self.get_fnames(type)
|
return self.get_fnames(type)
|
||||||
|
|
||||||
def saveData(self):
|
def saveData(self, directory=None, outformat=None):
|
||||||
|
|
||||||
def getSavePath(e):
|
def getSavePath(e, directory, outformat):
|
||||||
print('warning: {0}'.format(e))
|
print('warning: {0}'.format(e))
|
||||||
directory = self.get_current_event_path()
|
if not directory:
|
||||||
|
dlgflag = 1
|
||||||
|
directory = self.get_current_event_path()
|
||||||
|
else:
|
||||||
|
dlgflag = 0
|
||||||
eventname = self.get_current_event_name()
|
eventname = self.get_current_event_name()
|
||||||
filename = 'picks_'+eventname
|
filename = 'PyLoT_'+eventname
|
||||||
outpath = os.path.join(directory, filename)
|
outpath = os.path.join(directory, filename)
|
||||||
file_filter = "QuakeML file (*.xml);;VELEST observation file " \
|
|
||||||
"format (*.cnv);;NonLinLoc observation file (*.obs)"
|
|
||||||
title = 'Save pick data ...'
|
title = 'Save pick data ...'
|
||||||
fname, selected_filter = QFileDialog.getSaveFileName(self,
|
if not outformat:
|
||||||
title,
|
outformat = settings.value('output/Format')
|
||||||
outpath,
|
outformat = outformat[0:4]
|
||||||
file_filter)
|
else:
|
||||||
|
selected_filter = "NonLinLoc observation file (*.obs)"
|
||||||
|
fname = outpath
|
||||||
|
if outformat == '.obs':
|
||||||
|
file_filter = "NonLinLoc observation file (*.obs)"
|
||||||
|
elif outformat == '.cnv':
|
||||||
|
file_filter = "VELEST observation file format (*.cnv)"
|
||||||
|
elif outformat == '.xml':
|
||||||
|
file_filter = "QuakeML file (*.xml)"
|
||||||
|
|
||||||
|
if dlgflag == 1:
|
||||||
|
fname, selected_filter = QFileDialog.getSaveFileName(self,
|
||||||
|
title,
|
||||||
|
outpath,
|
||||||
|
file_filter)
|
||||||
|
|
||||||
fbasename, exform = os.path.splitext(fname)
|
fbasename, exform = os.path.splitext(fname)
|
||||||
|
|
||||||
if not exform and selected_filter or not exform in OUTPUTFORMATS:
|
if not exform and selected_filter or not exform in OUTPUTFORMATS:
|
||||||
exform = selected_filter.split('*')[1][:-1]
|
exform = selected_filter.split('*')[1][:-1]
|
||||||
if not exform in OUTPUTFORMATS:
|
|
||||||
return fname, exform
|
return fname, exform
|
||||||
return fbasename, exform
|
return fbasename, exform
|
||||||
|
|
||||||
@ -987,7 +1080,7 @@ class MainWindow(QMainWindow):
|
|||||||
fbasename = self.getEventFileName()
|
fbasename = self.getEventFileName()
|
||||||
exform = settings.value('data/exportFormat', 'QUAKEML')
|
exform = settings.value('data/exportFormat', 'QUAKEML')
|
||||||
try:
|
try:
|
||||||
self.get_data().applyEVTData(self.getPicks())
|
self.get_data().applyEVTData(self.get_current_event(), typ='event')#getPicks())
|
||||||
except OverwriteError:
|
except OverwriteError:
|
||||||
# msgBox = QMessageBox()
|
# msgBox = QMessageBox()
|
||||||
# msgBox.setText("Picks have been modified!")
|
# msgBox.setText("Picks have been modified!")
|
||||||
@ -1006,9 +1099,9 @@ class MainWindow(QMainWindow):
|
|||||||
try:
|
try:
|
||||||
self.get_data().exportEvent(fbasename, exform)
|
self.get_data().exportEvent(fbasename, exform)
|
||||||
except FormatError as e:
|
except FormatError as e:
|
||||||
fbasename, exform = getSavePath(e)
|
fbasename, exform = getSavePath(e, directory, outformat)
|
||||||
except AttributeError as e:
|
except AttributeError as e:
|
||||||
fbasename, exform = getSavePath(e)
|
fbasename, exform = getSavePath(e, directory, outformat)
|
||||||
|
|
||||||
# catch all possible cases before going on
|
# catch all possible cases before going on
|
||||||
if not fbasename:
|
if not fbasename:
|
||||||
@ -1057,7 +1150,7 @@ class MainWindow(QMainWindow):
|
|||||||
return self.get_current_event().getPicks()
|
return self.get_current_event().getPicks()
|
||||||
if type == 'auto':
|
if type == 'auto':
|
||||||
return self.get_current_event().getAutopicks()
|
return self.get_current_event().getAutopicks()
|
||||||
# rdict = dict(auto=self.autopicks, manual=self.picks)
|
# rdict = dict(auto=self.pylot_autopicks, manual=self.pylot_picks)
|
||||||
# return rdict[type]
|
# return rdict[type]
|
||||||
|
|
||||||
def getPicksOnStation(self, station, type='manual'):
|
def getPicksOnStation(self, station, type='manual'):
|
||||||
@ -1131,7 +1224,7 @@ class MainWindow(QMainWindow):
|
|||||||
if event:
|
if event:
|
||||||
self.ref_event_button.setChecked(event.isRefEvent())
|
self.ref_event_button.setChecked(event.isRefEvent())
|
||||||
self.test_event_button.setChecked(event.isTestEvent())
|
self.test_event_button.setChecked(event.isTestEvent())
|
||||||
self.enableRefTestButtons(bool(self.get_current_event().picks))
|
self.enableRefTestButtons(bool(self.get_current_event().pylot_picks))
|
||||||
return
|
return
|
||||||
self.ref_event_button.setChecked(False)
|
self.ref_event_button.setChecked(False)
|
||||||
self.test_event_button.setChecked(False)
|
self.test_event_button.setChecked(False)
|
||||||
@ -1190,14 +1283,14 @@ class MainWindow(QMainWindow):
|
|||||||
if not event:
|
if not event:
|
||||||
return
|
return
|
||||||
# update picks saved in GUI mainwindow (to be changed in future!!) MP MP
|
# update picks saved in GUI mainwindow (to be changed in future!!) MP MP
|
||||||
if not event.picks:
|
if not event.pylot_picks:
|
||||||
self.picks = {}
|
self.pylot_picks = {}
|
||||||
else:
|
else:
|
||||||
self.picks = event.picks
|
self.pylot_picks = event.pylot_picks
|
||||||
if not event.autopicks:
|
if not event.pylot_autopicks:
|
||||||
self.autopicks = {}
|
self.pylot_autopicks = {}
|
||||||
else:
|
else:
|
||||||
self.autopicks = event.autopicks
|
self.pylot_autopicks = event.pylot_autopicks
|
||||||
# if current tab is waveformPlot-tab and the data in this tab was not yet refreshed
|
# if current tab is waveformPlot-tab and the data in this tab was not yet refreshed
|
||||||
if self.tabs.currentIndex() == 0:
|
if self.tabs.currentIndex() == 0:
|
||||||
if self._eventChanged[0]:
|
if self._eventChanged[0]:
|
||||||
@ -1343,12 +1436,13 @@ class MainWindow(QMainWindow):
|
|||||||
self.openautopicksaction.setEnabled(True)
|
self.openautopicksaction.setEnabled(True)
|
||||||
self.loadpilotevent.setEnabled(True)
|
self.loadpilotevent.setEnabled(True)
|
||||||
event = self.get_current_event()
|
event = self.get_current_event()
|
||||||
if event.picks:
|
if event.pylot_picks:
|
||||||
self.picks = event.picks
|
self.pylot_picks = event.pylot_picks
|
||||||
self.drawPicks(picktype='manual')
|
self.drawPicks(picktype='manual')
|
||||||
self.enableSaveManualPicksAction()
|
self.enableSaveManualPicksAction()
|
||||||
if event.autopicks:
|
self.locateEvent.setEnabled(True)
|
||||||
self.autopicks = event.autopicks
|
if event.pylot_autopicks:
|
||||||
|
self.pylot_autopicks = event.pylot_autopicks
|
||||||
self.drawPicks(picktype='auto')
|
self.drawPicks(picktype='auto')
|
||||||
self.compare_action.setEnabled(True)
|
self.compare_action.setEnabled(True)
|
||||||
self.draw()
|
self.draw()
|
||||||
@ -1506,6 +1600,11 @@ class MainWindow(QMainWindow):
|
|||||||
if wfID in plot_dict.keys():
|
if wfID in plot_dict.keys():
|
||||||
return plot_dict[wfID][0]
|
return plot_dict[wfID][0]
|
||||||
|
|
||||||
|
def getNetworkName(self, wfID):
|
||||||
|
plot_dict = self.getPlotWidget().getPlotDict()
|
||||||
|
if wfID in plot_dict.keys():
|
||||||
|
return plot_dict[wfID][2]
|
||||||
|
|
||||||
def alterPhase(self):
|
def alterPhase(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@ -1570,13 +1669,14 @@ class MainWindow(QMainWindow):
|
|||||||
|
|
||||||
def pickDialog(self, wfID, nextStation=False):
|
def pickDialog(self, wfID, nextStation=False):
|
||||||
station = self.getStationName(wfID)
|
station = self.getStationName(wfID)
|
||||||
|
network = self.getNetworkName(wfID)
|
||||||
if not station:
|
if not station:
|
||||||
return
|
return
|
||||||
self.update_status('picking on station {0}'.format(station))
|
self.update_status('picking on station {0}'.format(station))
|
||||||
data = self.get_data().getWFData()
|
data = self.get_data().getWFData()
|
||||||
pickDlg = PickDlg(self, parameter=self._inputs,
|
pickDlg = PickDlg(self, parameter=self._inputs,
|
||||||
data=data.select(station=station),
|
data=data.select(station=station),
|
||||||
station=station,
|
station=station, network=network,
|
||||||
picks=self.getPicksOnStation(station, 'manual'),
|
picks=self.getPicksOnStation(station, 'manual'),
|
||||||
autopicks=self.getPicksOnStation(station, 'auto'))
|
autopicks=self.getPicksOnStation(station, 'auto'))
|
||||||
pickDlg.nextStation.setChecked(nextStation)
|
pickDlg.nextStation.setChecked(nextStation)
|
||||||
@ -1725,14 +1825,16 @@ class MainWindow(QMainWindow):
|
|||||||
# raise Exception('FATAL: Should never occur!')
|
# raise Exception('FATAL: Should never occur!')
|
||||||
# MP MP prompt redundant because new picks have to be accepted in the first place closing PickDlg
|
# MP MP prompt redundant because new picks have to be accepted in the first place closing PickDlg
|
||||||
|
|
||||||
def updatePicks(self, type='manual'):
|
def updatePicks(self, type='manual', event=None):
|
||||||
|
if not event:
|
||||||
|
event = self.get_current_event()
|
||||||
picks = picksdict_from_picks(evt=self.get_data(type).get_evt_data())
|
picks = picksdict_from_picks(evt=self.get_data(type).get_evt_data())
|
||||||
if type == 'manual':
|
if type == 'manual':
|
||||||
self.get_current_event().addPicks(picks)
|
event.addPicks(picks)
|
||||||
self.picks.update(picks)
|
self.pylot_picks.update(picks)
|
||||||
elif type == 'auto':
|
elif type == 'auto':
|
||||||
self.get_current_event().addAutopicks(picks)
|
event.addAutopicks(picks)
|
||||||
self.autopicks.update(picks)
|
self.pylot_autopicks.update(picks)
|
||||||
self.check4Comparison()
|
self.check4Comparison()
|
||||||
|
|
||||||
def drawPicks(self, station=None, picktype='manual'):
|
def drawPicks(self, station=None, picktype='manual'):
|
||||||
@ -1769,7 +1871,7 @@ class MainWindow(QMainWindow):
|
|||||||
|
|
||||||
for phase in stat_picks:
|
for phase in stat_picks:
|
||||||
picks = stat_picks[phase]
|
picks = stat_picks[phase]
|
||||||
if type(stat_picks[phase]) is not dict:
|
if type(stat_picks[phase]) is not dict and type(stat_picks[phase]) is not AttribDict:
|
||||||
return
|
return
|
||||||
colors = phase_col[phase[0].upper()]
|
colors = phase_col[phase[0].upper()]
|
||||||
|
|
||||||
@ -1871,11 +1973,14 @@ class MainWindow(QMainWindow):
|
|||||||
|
|
||||||
outfile = settings.value("{0}/outputFile".format(loctool),
|
outfile = settings.value("{0}/outputFile".format(loctool),
|
||||||
os.path.split(os.tempnam())[-1])
|
os.path.split(os.tempnam())[-1])
|
||||||
phasefile = os.path.split(os.tempnam())[-1]
|
obsdir = os.path.join(locroot, 'obs')
|
||||||
|
self.saveData(directory=obsdir, outformat='.obs')
|
||||||
|
eventname = self.get_current_event_name()
|
||||||
|
filename = 'PyLoT_'+eventname
|
||||||
|
locpath = os.path.join(locroot, 'loc', filename)
|
||||||
|
phasefile = os.path.join(obsdir, filename + '.obs')
|
||||||
phasepath = os.path.join(locroot, 'obs', phasefile)
|
phasepath = os.path.join(locroot, 'obs', phasefile)
|
||||||
locpath = os.path.join(locroot, 'loc', outfile)
|
lt.modify_inputs(infile, locroot, filename, phasefile, ttt)
|
||||||
lt.export(self.getPicks(), phasepath)
|
|
||||||
lt.modify_inputs(infile, locroot, outfile, phasefile, ttt)
|
|
||||||
try:
|
try:
|
||||||
lt.locate(infile)
|
lt.locate(infile)
|
||||||
except RuntimeError as e:
|
except RuntimeError as e:
|
||||||
@ -1883,8 +1988,8 @@ class MainWindow(QMainWindow):
|
|||||||
finally:
|
finally:
|
||||||
os.remove(phasepath)
|
os.remove(phasepath)
|
||||||
|
|
||||||
self.get_data().applyEVTData(lt.read_location(locpath), type='event')
|
self.get_data().applyEVTData(lt.read_location(locpath), typ='event')
|
||||||
self.get_data().applyEVTData(self.calc_magnitude(), type='event')
|
#self.get_data().applyEVTData(self.calc_magnitude(), typ='event')
|
||||||
|
|
||||||
def init_array_tab(self):
|
def init_array_tab(self):
|
||||||
'''
|
'''
|
||||||
@ -1969,6 +2074,12 @@ class MainWindow(QMainWindow):
|
|||||||
if not self.array_map:
|
if not self.array_map:
|
||||||
return
|
return
|
||||||
# refresh with new picks here!!!
|
# refresh with new picks here!!!
|
||||||
|
event = self.get_current_event()
|
||||||
|
if hasattr(event, 'origins'):
|
||||||
|
if event.origins:
|
||||||
|
lat = event.origins[0].latitude
|
||||||
|
lon = event.origins[0].longitude
|
||||||
|
self.array_map.eventLoc = (lat, lon)
|
||||||
self.array_map.refresh_drawings(self.get_current_event().getPicks())
|
self.array_map.refresh_drawings(self.get_current_event().getPicks())
|
||||||
self._eventChanged[1] = False
|
self._eventChanged[1] = False
|
||||||
|
|
||||||
@ -1995,19 +2106,19 @@ class MainWindow(QMainWindow):
|
|||||||
# changes attributes of the corresponding event
|
# changes attributes of the corresponding event
|
||||||
table = self.project._table
|
table = self.project._table
|
||||||
event = self.project.getEventFromPath(table[row][0].text())
|
event = self.project.getEventFromPath(table[row][0].text())
|
||||||
if column == 3 or column == 4:
|
if column == 8 or column == 9:
|
||||||
#toggle checked states (exclusive)
|
#toggle checked states (exclusive)
|
||||||
item_ref = table[row][3]
|
item_ref = table[row][8]
|
||||||
item_test = table[row][4]
|
item_test = table[row][9]
|
||||||
if column == 3 and item_ref.checkState():
|
if column == 8 and item_ref.checkState():
|
||||||
item_test.setCheckState(QtCore.Qt.Unchecked)
|
item_test.setCheckState(QtCore.Qt.Unchecked)
|
||||||
event.setRefEvent(True)
|
event.setRefEvent(True)
|
||||||
elif column == 3 and not item_ref.checkState():
|
elif column == 8 and not item_ref.checkState():
|
||||||
event.setRefEvent(False)
|
event.setRefEvent(False)
|
||||||
elif column == 4 and item_test.checkState():
|
elif column == 9 and item_test.checkState():
|
||||||
item_ref.setCheckState(QtCore.Qt.Unchecked)
|
item_ref.setCheckState(QtCore.Qt.Unchecked)
|
||||||
event.setTestEvent(True)
|
event.setTestEvent(True)
|
||||||
elif column == 4 and not item_test.checkState():
|
elif column == 9 and not item_test.checkState():
|
||||||
event.setTestEvent(False)
|
event.setTestEvent(False)
|
||||||
self.fill_eventbox()
|
self.fill_eventbox()
|
||||||
elif column == 5:
|
elif column == 5:
|
||||||
@ -2023,22 +2134,35 @@ class MainWindow(QMainWindow):
|
|||||||
|
|
||||||
# init new qtable
|
# init new qtable
|
||||||
self.event_table = QtGui.QTableWidget()
|
self.event_table = QtGui.QTableWidget()
|
||||||
self.event_table.setColumnCount(6)
|
self.event_table.setColumnCount(11)
|
||||||
self.event_table.setRowCount(len(eventlist))
|
self.event_table.setRowCount(len(eventlist))
|
||||||
self.event_table.setHorizontalHeaderLabels(['Event', '[N] MP',
|
self.event_table.setHorizontalHeaderLabels(['Event',
|
||||||
'[N] AP', 'Tuning Set',
|
'Time',
|
||||||
'Test Set', 'Notes'])
|
'Lat',
|
||||||
|
'Lon',
|
||||||
|
'Depth',
|
||||||
|
'Mag',
|
||||||
|
'[N] MP',
|
||||||
|
'[N] AP',
|
||||||
|
'Tuning Set',
|
||||||
|
'Test Set',
|
||||||
|
'Notes'])
|
||||||
|
|
||||||
# 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):
|
||||||
event_npicks = 0
|
event_npicks = 0
|
||||||
event_nautopicks = 0
|
event_nautopicks = 0
|
||||||
if event.picks:
|
if event.pylot_picks:
|
||||||
event_npicks = len(event.picks)
|
event_npicks = len(event.pylot_picks)
|
||||||
if event.autopicks:
|
if event.pylot_autopicks:
|
||||||
event_nautopicks = len(event.autopicks)
|
event_nautopicks = len(event.pylot_autopicks)
|
||||||
item_path = QtGui.QTableWidgetItem()
|
item_path = QtGui.QTableWidgetItem()
|
||||||
|
item_time = QtGui.QTableWidgetItem()
|
||||||
|
item_lat = QtGui.QTableWidgetItem()
|
||||||
|
item_lon = QtGui.QTableWidgetItem()
|
||||||
|
item_depth = QtGui.QTableWidgetItem()
|
||||||
|
item_mag = QtGui.QTableWidgetItem()
|
||||||
item_nmp = QtGui.QTableWidgetItem(str(event_npicks))
|
item_nmp = QtGui.QTableWidgetItem(str(event_npicks))
|
||||||
item_nmp.setIcon(self.manupicksicon_small)
|
item_nmp.setIcon(self.manupicksicon_small)
|
||||||
item_nap = QtGui.QTableWidgetItem(str(event_nautopicks))
|
item_nap = QtGui.QTableWidgetItem(str(event_nautopicks))
|
||||||
@ -2050,11 +2174,23 @@ class MainWindow(QMainWindow):
|
|||||||
item_ref.setBackground(self._colors['ref'])
|
item_ref.setBackground(self._colors['ref'])
|
||||||
item_test.setBackground(self._colors['test'])
|
item_test.setBackground(self._colors['test'])
|
||||||
item_path.setText(event.path)
|
item_path.setText(event.path)
|
||||||
|
if hasattr(event, 'origins'):
|
||||||
|
if event.origins:
|
||||||
|
origin = event.origins[0]
|
||||||
|
item_time.setText(str(origin.time).split('.')[0])
|
||||||
|
item_lon.setText(str(origin.longitude))
|
||||||
|
item_lat.setText(str(origin.latitude))
|
||||||
|
item_depth.setText(str(origin.depth))
|
||||||
|
if hasattr(event, 'magnitudes'):
|
||||||
|
if event.magnitudes:
|
||||||
|
magnitude = event.magnitudes[0]
|
||||||
|
item_mag.setText(str(magnitude.mag))
|
||||||
item_notes.setText(event.notes)
|
item_notes.setText(event.notes)
|
||||||
|
|
||||||
set_enabled(item_path, True, False)
|
set_enabled(item_path, True, False)
|
||||||
set_enabled(item_nmp, True, False)
|
set_enabled(item_nmp, True, False)
|
||||||
set_enabled(item_nap, True, False)
|
set_enabled(item_nap, True, False)
|
||||||
if event.picks:
|
if event.pylot_picks:
|
||||||
set_enabled(item_ref, True, True)
|
set_enabled(item_ref, True, True)
|
||||||
set_enabled(item_test, True, True)
|
set_enabled(item_test, True, True)
|
||||||
else:
|
else:
|
||||||
@ -2070,7 +2206,8 @@ class MainWindow(QMainWindow):
|
|||||||
else:
|
else:
|
||||||
item_test.setCheckState(QtCore.Qt.Unchecked)
|
item_test.setCheckState(QtCore.Qt.Unchecked)
|
||||||
|
|
||||||
column=[item_path, item_nmp, item_nap, item_ref, item_test, item_notes]
|
column=[item_path, item_time, item_lat, item_lon, item_depth, item_mag,
|
||||||
|
item_nmp, item_nap, item_ref, item_test, item_notes]
|
||||||
self.project._table.append(column)
|
self.project._table.append(column)
|
||||||
|
|
||||||
for r_index, row in enumerate(self.project._table):
|
for r_index, row in enumerate(self.project._table):
|
||||||
@ -2389,6 +2526,63 @@ class Project(object):
|
|||||||
self.setDirty()
|
self.setDirty()
|
||||||
else:
|
else:
|
||||||
print('Skipping event with path {}. Already part of project.'.format(event.path))
|
print('Skipping event with path {}. Already part of project.'.format(event.path))
|
||||||
|
self.search_eventfile_info()
|
||||||
|
|
||||||
|
def read_eventfile_info(self, filename, separator=','):
|
||||||
|
'''
|
||||||
|
Try to read event information from file (:param:filename) comparing specific event datetimes.
|
||||||
|
File structure (each row): event, date, time, magnitude, latitude, longitude, depth
|
||||||
|
separated by :param:separator each.
|
||||||
|
'''
|
||||||
|
infile = open(filename, 'r')
|
||||||
|
for line in infile.readlines():
|
||||||
|
event, date, time, mag, lat, lon, depth = line.split(separator)[:7]
|
||||||
|
#skip first line
|
||||||
|
try:
|
||||||
|
month, day, year = date.split('/')
|
||||||
|
except:
|
||||||
|
continue
|
||||||
|
year = int(year)
|
||||||
|
#hardcoded, if year only consists of 2 digits (e.g. 16 instead of 2016)
|
||||||
|
if year<100:
|
||||||
|
year += 2000
|
||||||
|
datetime = '{}-{}-{}T{}'.format(year, month, day, time)
|
||||||
|
try:
|
||||||
|
datetime = UTCDateTime(datetime)
|
||||||
|
except Exception as e:
|
||||||
|
print(e, datetime, filename)
|
||||||
|
continue
|
||||||
|
for event in self.eventlist:
|
||||||
|
if not event.origins:
|
||||||
|
continue
|
||||||
|
origin = event.origins[0] #should have only one origin
|
||||||
|
if origin.time == datetime:
|
||||||
|
origin.latitude = float(lat)
|
||||||
|
origin.longitude = float(lon)
|
||||||
|
origin.depth = float(depth)
|
||||||
|
event.magnitudes.append(Magnitude(resource_id=event.resource_id,
|
||||||
|
mag=float(mag),
|
||||||
|
mag_type='M'))
|
||||||
|
|
||||||
|
def search_eventfile_info(self):
|
||||||
|
'''
|
||||||
|
Search all datapaths in rootpath for filenames with given file extension fext
|
||||||
|
and try to read event info from it
|
||||||
|
'''
|
||||||
|
datapaths = []
|
||||||
|
fext='.csv'
|
||||||
|
for event in self.eventlist:
|
||||||
|
if not event.datapath in datapaths:
|
||||||
|
datapaths.append(event.datapath)
|
||||||
|
for datapath in datapaths:
|
||||||
|
datapath = os.path.join(self.rootpath, datapath)
|
||||||
|
for filename in os.listdir(datapath):
|
||||||
|
filename = os.path.join(datapath, filename)
|
||||||
|
if os.path.isfile(filename) and filename.endswith(fext):
|
||||||
|
try:
|
||||||
|
self.read_eventfile_info(filename)
|
||||||
|
except Exception as e:
|
||||||
|
print('Failed on reading eventfile info from file {}: {}'.format(filename, e))
|
||||||
|
|
||||||
def getPaths(self):
|
def getPaths(self):
|
||||||
'''
|
'''
|
||||||
@ -2449,123 +2643,6 @@ class Project(object):
|
|||||||
return project
|
return project
|
||||||
|
|
||||||
|
|
||||||
class Event(object):
|
|
||||||
'''
|
|
||||||
Pickable class containing information on a single event.
|
|
||||||
'''
|
|
||||||
def __init__(self, path):
|
|
||||||
self.path = path
|
|
||||||
self.database = path.split('/')[-2]
|
|
||||||
self.datapath = path.split('/')[-3]
|
|
||||||
self.rootpath = os.path.join(*path.split('/')[:-3])
|
|
||||||
self.autopicks = {}
|
|
||||||
self.picks = {}
|
|
||||||
self.notes = ''
|
|
||||||
self._testEvent = False
|
|
||||||
self._refEvent = False
|
|
||||||
try:
|
|
||||||
self.get_notes()
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
|
|
||||||
def get_notes_path(self):
|
|
||||||
notesfile = os.path.join(self.path, 'notes.txt')
|
|
||||||
return notesfile
|
|
||||||
|
|
||||||
def get_notes(self):
|
|
||||||
notesfile = self.get_notes_path()
|
|
||||||
if os.path.isfile(notesfile):
|
|
||||||
with open(notesfile) as infile:
|
|
||||||
text = '[eventInfo: '+str(infile.readlines()[0].split('\n')[0])+']'
|
|
||||||
self.addNotes(text)
|
|
||||||
|
|
||||||
def addNotes(self, notes):
|
|
||||||
self.notes = str(notes)
|
|
||||||
|
|
||||||
def clearNotes(self):
|
|
||||||
self.notes = None
|
|
||||||
|
|
||||||
def isRefEvent(self):
|
|
||||||
return self._refEvent
|
|
||||||
|
|
||||||
def isTestEvent(self):
|
|
||||||
return self._testEvent
|
|
||||||
|
|
||||||
def setRefEvent(self, bool):
|
|
||||||
self._refEvent = bool
|
|
||||||
if bool: self._testEvent = False
|
|
||||||
|
|
||||||
def setTestEvent(self, bool):
|
|
||||||
self._testEvent = bool
|
|
||||||
if bool: self._refEvent = False
|
|
||||||
|
|
||||||
def addPicks(self, picks):
|
|
||||||
for station in picks:
|
|
||||||
self.picks[station] = picks[station]
|
|
||||||
|
|
||||||
def addAutopicks(self, autopicks):
|
|
||||||
for station in autopicks:
|
|
||||||
self.autopicks[station] = autopicks[station]
|
|
||||||
|
|
||||||
def setPick(self, station, pick):
|
|
||||||
if pick:
|
|
||||||
self.picks[station] = pick
|
|
||||||
|
|
||||||
def setPicks(self, picks):
|
|
||||||
self.picks = picks
|
|
||||||
|
|
||||||
def getPick(self, station):
|
|
||||||
if station in self.picks.keys():
|
|
||||||
return self.picks[station]
|
|
||||||
|
|
||||||
def getPicks(self):
|
|
||||||
return self.picks
|
|
||||||
|
|
||||||
def setAutopick(self, station, autopick):
|
|
||||||
if autopick:
|
|
||||||
self.autopicks[station] = autopick
|
|
||||||
|
|
||||||
def setAutopicks(self, autopicks):
|
|
||||||
self.autopicks = autopicks
|
|
||||||
|
|
||||||
def getAutopick(self, station):
|
|
||||||
if station in self.autopicks.keys():
|
|
||||||
return self.autopicks[station]
|
|
||||||
|
|
||||||
def getAutopicks(self):
|
|
||||||
return self.autopicks
|
|
||||||
|
|
||||||
def save(self, filename):
|
|
||||||
'''
|
|
||||||
Save PyLoT Event to a file.
|
|
||||||
Can be loaded by using event.load(filename).
|
|
||||||
'''
|
|
||||||
try:
|
|
||||||
import cPickle
|
|
||||||
except ImportError:
|
|
||||||
import _pickle as cPickle
|
|
||||||
|
|
||||||
try:
|
|
||||||
outfile = open(filename, 'wb')
|
|
||||||
cPickle.dump(self, outfile, -1)
|
|
||||||
except Exception as e:
|
|
||||||
print('Could not pickle PyLoT event. Reason: {}'.format(e))
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def load(filename):
|
|
||||||
'''
|
|
||||||
Load project from filename.
|
|
||||||
'''
|
|
||||||
try:
|
|
||||||
import cPickle
|
|
||||||
except ImportError:
|
|
||||||
import _pickle as cPickle
|
|
||||||
infile = open(filename, 'rb')
|
|
||||||
event = cPickle.load(infile)
|
|
||||||
print('Loaded %s' % filename)
|
|
||||||
return event
|
|
||||||
|
|
||||||
|
|
||||||
class getExistingDirectories(QFileDialog):
|
class getExistingDirectories(QFileDialog):
|
||||||
'''
|
'''
|
||||||
File dialog with possibility to select multiple folders.
|
File dialog with possibility to select multiple folders.
|
||||||
|
81
autoPyLoT.py
@ -98,8 +98,8 @@ def autoPyLoT(input_dict=None, parameter=None, inputfile=None, fnames=None, even
|
|||||||
|
|
||||||
exf = ['root', 'dpath', 'dbase']
|
exf = ['root', 'dpath', 'dbase']
|
||||||
|
|
||||||
if parameter.hasParam('eventID') and fnames == 'None':
|
if parameter['eventID'] is not '*' and fnames == 'None':
|
||||||
dsfields['eventID'] = parameter.get('eventID')
|
dsfields['eventID'] = parameter['eventID']
|
||||||
exf.append('eventID')
|
exf.append('eventID')
|
||||||
|
|
||||||
datastructure.modifyFields(**dsfields)
|
datastructure.modifyFields(**dsfields)
|
||||||
@ -133,13 +133,13 @@ def autoPyLoT(input_dict=None, parameter=None, inputfile=None, fnames=None, even
|
|||||||
if not input_dict:
|
if not input_dict:
|
||||||
# started in production mode
|
# started in production mode
|
||||||
datapath = datastructure.expandDataPath()
|
datapath = datastructure.expandDataPath()
|
||||||
if fnames == 'None' and not parameter['eventID']:
|
if fnames == 'None' and parameter['eventID'] is '*':
|
||||||
# multiple event processing
|
# multiple event processing
|
||||||
# read each event in database
|
# read each event in database
|
||||||
events = [events for events in glob.glob(os.path.join(datapath, '*')) if os.path.isdir(events)]
|
events = [events for events in glob.glob(os.path.join(datapath, '*')) if os.path.isdir(events)]
|
||||||
elif fnames == 'None' and parameter['eventID']:
|
elif fnames == 'None' and parameter['eventID'] is not '*':
|
||||||
# single event processing
|
# single event processing
|
||||||
events = glob.glob(os.path.join(datapath, parameter.get('eventID')))
|
events = glob.glob(os.path.join(datapath, parameter['eventID']))
|
||||||
else:
|
else:
|
||||||
# autoPyLoT was initialized from GUI
|
# autoPyLoT was initialized from GUI
|
||||||
events = []
|
events = []
|
||||||
@ -243,7 +243,7 @@ def autoPyLoT(input_dict=None, parameter=None, inputfile=None, fnames=None, even
|
|||||||
# get latest NLLoc-location file if several are available
|
# get latest NLLoc-location file if several are available
|
||||||
nllocfile = max(glob.glob(locsearch), key=os.path.getctime)
|
nllocfile = max(glob.glob(locsearch), key=os.path.getctime)
|
||||||
evt = read_events(nllocfile)[0]
|
evt = read_events(nllocfile)[0]
|
||||||
# calculating seismic moment Mo and moment magnitude Mw
|
# calculate seismic moment Mo and moment magnitude Mw
|
||||||
moment_mag = MomentMagnitude(corr_dat, evt, parameter.get('vp'),
|
moment_mag = MomentMagnitude(corr_dat, evt, parameter.get('vp'),
|
||||||
parameter.get('Qp'),
|
parameter.get('Qp'),
|
||||||
parameter.get('rho'), True, \
|
parameter.get('rho'), True, \
|
||||||
@ -252,15 +252,29 @@ def autoPyLoT(input_dict=None, parameter=None, inputfile=None, fnames=None, even
|
|||||||
for station, props in moment_mag.moment_props.items():
|
for station, props in moment_mag.moment_props.items():
|
||||||
picks[station]['P'].update(props)
|
picks[station]['P'].update(props)
|
||||||
evt = moment_mag.updated_event()
|
evt = moment_mag.updated_event()
|
||||||
|
net_mw = moment_mag.net_magnitude()
|
||||||
|
print("Network moment magnitude: %4.1f" % net_mw.mag)
|
||||||
|
# calculate local (Richter) magntiude
|
||||||
|
WAscaling = parameter.get('WAscaling')
|
||||||
|
magscaling = parameter.get('magscaling')
|
||||||
local_mag = LocalMagnitude(corr_dat, evt,
|
local_mag = LocalMagnitude(corr_dat, evt,
|
||||||
parameter.get('sstop'), parameter.get('WAscaling'), \
|
parameter.get('sstop'),
|
||||||
True, iplot)
|
WAscaling, True, iplot)
|
||||||
for station, amplitude in local_mag.amplitudes.items():
|
for station, amplitude in local_mag.amplitudes.items():
|
||||||
picks[station]['S']['Ao'] = amplitude.generic_amplitude
|
picks[station]['S']['Ao'] = amplitude.generic_amplitude
|
||||||
evt = local_mag.updated_event()
|
print("Local station magnitudes scaled with:")
|
||||||
|
print("log(Ao) + %f * log(r) + %f * r + %f" % (WAscaling[0],
|
||||||
|
WAscaling[1],
|
||||||
|
WAscaling[2]))
|
||||||
|
evt = local_mag.updated_event(magscaling)
|
||||||
|
net_ml = local_mag.net_magnitude(magscaling)
|
||||||
|
print("Network local magnitude: %4.1f" % net_ml.mag)
|
||||||
|
print("Network local magnitude scaled with:")
|
||||||
|
print("%f * Ml + %f" % (magscaling[0], magscaling[1]))
|
||||||
else:
|
else:
|
||||||
print("autoPyLoT: No NLLoc-location file available!")
|
print("autoPyLoT: No NLLoc-location file available!")
|
||||||
print("No source parameter estimation possible!")
|
print("No source parameter estimation possible!")
|
||||||
|
locflag = 9
|
||||||
else:
|
else:
|
||||||
# get theoretical P-onset times from NLLoc-location file
|
# get theoretical P-onset times from NLLoc-location file
|
||||||
locsearch = '%s/loc/%s.????????.??????.grid?.loc.hyp' % (nllocroot, nllocout)
|
locsearch = '%s/loc/%s.????????.??????.grid?.loc.hyp' % (nllocroot, nllocout)
|
||||||
@ -301,7 +315,7 @@ def autoPyLoT(input_dict=None, parameter=None, inputfile=None, fnames=None, even
|
|||||||
nlloccounter = maxnumit
|
nlloccounter = maxnumit
|
||||||
evt = read_events(nllocfile)[0]
|
evt = read_events(nllocfile)[0]
|
||||||
if locflag < 2:
|
if locflag < 2:
|
||||||
# calculating seismic moment Mo and moment magnitude Mw
|
# calculate seismic moment Mo and moment magnitude Mw
|
||||||
moment_mag = MomentMagnitude(corr_dat, evt, parameter.get('vp'),
|
moment_mag = MomentMagnitude(corr_dat, evt, parameter.get('vp'),
|
||||||
parameter.get('Qp'),
|
parameter.get('Qp'),
|
||||||
parameter.get('rho'), True, \
|
parameter.get('rho'), True, \
|
||||||
@ -310,14 +324,25 @@ def autoPyLoT(input_dict=None, parameter=None, inputfile=None, fnames=None, even
|
|||||||
for station, props in moment_mag.moment_props.items():
|
for station, props in moment_mag.moment_props.items():
|
||||||
picks[station]['P'].update(props)
|
picks[station]['P'].update(props)
|
||||||
evt = moment_mag.updated_event()
|
evt = moment_mag.updated_event()
|
||||||
local_mag = LocalMagnitude(corr_dat, evt,
|
|
||||||
parameter.get('sstop'), parameter.get('WAscaling'), \
|
|
||||||
True, iplot)
|
|
||||||
for station, amplitude in local_mag.amplitudes.items():
|
|
||||||
picks[station]['S']['Ao'] = amplitude.generic_amplitude
|
|
||||||
evt = local_mag.updated_event()
|
|
||||||
net_mw = moment_mag.net_magnitude()
|
net_mw = moment_mag.net_magnitude()
|
||||||
print("Network moment magnitude: %4.1f" % net_mw.mag)
|
print("Network moment magnitude: %4.1f" % net_mw.mag)
|
||||||
|
# calculate local (Richter) magntiude
|
||||||
|
WAscaling = parameter.get('WAscaling')
|
||||||
|
magscaling = parameter.get('magscaling')
|
||||||
|
local_mag = LocalMagnitude(corr_dat, evt,
|
||||||
|
parameter.get('sstop'),
|
||||||
|
WAscaling, True, iplot)
|
||||||
|
for station, amplitude in local_mag.amplitudes.items():
|
||||||
|
picks[station]['S']['Ao'] = amplitude.generic_amplitude
|
||||||
|
print("Local station magnitudes scaled with:")
|
||||||
|
print("log(Ao) + %f * log(r) + %f * r + %f" % (WAscaling[0],
|
||||||
|
WAscaling[1],
|
||||||
|
WAscaling[2]))
|
||||||
|
evt = local_mag.updated_event(magscaling)
|
||||||
|
net_ml = local_mag.net_magnitude(magscaling)
|
||||||
|
print("Network local magnitude: %4.1f" % net_ml.mag)
|
||||||
|
print("Network local magnitude scaled with:")
|
||||||
|
print("%f * Ml + %f" % (magscaling[0], magscaling[1]))
|
||||||
else:
|
else:
|
||||||
print("autoPyLoT: No NLLoc-location file available! Stop iteration!")
|
print("autoPyLoT: No NLLoc-location file available! Stop iteration!")
|
||||||
locflag = 9
|
locflag = 9
|
||||||
@ -328,26 +353,26 @@ def autoPyLoT(input_dict=None, parameter=None, inputfile=None, fnames=None, even
|
|||||||
data.applyEVTData(picks)
|
data.applyEVTData(picks)
|
||||||
if evt is not None:
|
if evt is not None:
|
||||||
data.applyEVTData(evt, 'event')
|
data.applyEVTData(evt, 'event')
|
||||||
fnqml = '%s/autoPyLoT' % event
|
fnqml = '%s/PyLoT_%s' % (event, evID)
|
||||||
data.exportEvent(fnqml)
|
data.exportEvent(fnqml, fnext='.xml', fcheck='manual')
|
||||||
# HYPO71
|
|
||||||
hypo71file = '%s/autoPyLoT_HYPO71_phases' % event
|
|
||||||
hypo71.export(picks, hypo71file, parameter)
|
|
||||||
# HYPOSAT
|
|
||||||
hyposatfile = '%s/autoPyLoT_HYPOSAT_phases' % event
|
|
||||||
hyposat.export(picks, hyposatfile, parameter)
|
|
||||||
if locflag == 1:
|
if locflag == 1:
|
||||||
|
# HYPO71
|
||||||
|
hypo71file = '%s/PyLoT_%s_HYPO71_phases' % (event, evID)
|
||||||
|
hypo71.export(picks, hypo71file, parameter)
|
||||||
|
# HYPOSAT
|
||||||
|
hyposatfile = '%s/PyLoT_%s_HYPOSAT_phases' % (event, evID)
|
||||||
|
hyposat.export(picks, hyposatfile, parameter)
|
||||||
# VELEST
|
# VELEST
|
||||||
velestfile = '%s/autoPyLoT_VELEST_phases.cnv' % event
|
velestfile = '%s/PyLoT_%s_VELEST_phases.cnv' % (event, evID)
|
||||||
velest.export(picks, velestfile, parameter, evt)
|
velest.export(picks, velestfile, parameter, evt)
|
||||||
# hypoDD
|
# hypoDD
|
||||||
hypoddfile = '%s/autoPyLoT_hypoDD_phases.pha' % event
|
hypoddfile = '%s/PyLoT_%s_hypoDD_phases.pha' % (event, evID)
|
||||||
hypodd.export(picks, hypoddfile, parameter, evt)
|
hypodd.export(picks, hypoddfile, parameter, evt)
|
||||||
# FOCMEC
|
# FOCMEC
|
||||||
focmecfile = '%s/autoPyLoT_FOCMEC.in' % event
|
focmecfile = '%s/PyLoT_%s_FOCMEC.in' % (event, evID)
|
||||||
focmec.export(picks, focmecfile, parameter, evt)
|
focmec.export(picks, focmecfile, parameter, evt)
|
||||||
# HASH
|
# HASH
|
||||||
hashfile = '%s/autoPyLoT_HASH' % event
|
hashfile = '%s/PyLoT_%s_HASH' % (event, evID)
|
||||||
hash.export(picks, hashfile, parameter, evt)
|
hash.export(picks, hashfile, parameter, evt)
|
||||||
|
|
||||||
endsplash = '''------------------------------------------\n'
|
endsplash = '''------------------------------------------\n'
|
||||||
|
26
icons.qrc
@ -1,15 +1,29 @@
|
|||||||
<RCC>
|
<RCC>
|
||||||
<qresource>
|
<qresource>
|
||||||
<file>icons/Library-icon.png</file>
|
|
||||||
<file>icons/pylot.ico</file>
|
<file>icons/pylot.ico</file>
|
||||||
<file>icons/pylot.png</file>
|
<file>icons/pylot.png</file>
|
||||||
<file>icons/manupicsicon.png</file>
|
<file>icons/newfile.png</file>
|
||||||
<file>icons/autopicsicon.png</file>
|
<file>icons/open.png</file>
|
||||||
<file>icons/autopylot_button.png</file>
|
<file>icons/openproject.png</file>
|
||||||
|
<file>icons/add.png</file>
|
||||||
|
<file>icons/save.png</file>
|
||||||
|
<file>icons/saveas.png</file>
|
||||||
|
<file>icons/saveproject.png</file>
|
||||||
|
<file>icons/saveprojectas.png</file>
|
||||||
<file>icons/manupicksicon_small.png</file>
|
<file>icons/manupicksicon_small.png</file>
|
||||||
<file>icons/autopicksicon_small.png</file>
|
<file>icons/autopicksicon_small.png</file>
|
||||||
<file>icons/autopick_button.png</file>
|
<file>icons/tune.png</file>
|
||||||
<file>icons/locactionicon.png</file>
|
<file>icons/autopylot_button.png</file>
|
||||||
|
<file>icons/pick.png</file>
|
||||||
|
<file>icons/waveform.png</file>
|
||||||
|
<file>icons/openpick.png</file>
|
||||||
|
<file>icons/openpicks.png</file>
|
||||||
|
<file>icons/openpick.png</file>
|
||||||
|
<file>icons/openpicks.png</file>
|
||||||
|
<file>icons/savepicks.png</file>
|
||||||
|
<file>icons/preferences.png</file>
|
||||||
|
<file>icons/parameter.png</file>
|
||||||
|
<file>icons/openloc.png</file>
|
||||||
<file>icons/compare_button.png</file>
|
<file>icons/compare_button.png</file>
|
||||||
<file>icons/locate_button.png</file>
|
<file>icons/locate_button.png</file>
|
||||||
<file>icons/Matlab_PILOT_icon.png</file>
|
<file>icons/Matlab_PILOT_icon.png</file>
|
||||||
|
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 50 KiB |
BIN
icons/add.png
Normal file
After Width: | Height: | Size: 44 KiB |
Before Width: | Height: | Size: 629 KiB |
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 31 KiB |
BIN
icons/autopylot_button.png
Normal file
After Width: | Height: | Size: 52 KiB |
Before Width: | Height: | Size: 7.5 KiB After Width: | Height: | Size: 18 KiB |
BIN
icons/key_E.png
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 37 KiB |
BIN
icons/key_N.png
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 44 KiB |
BIN
icons/key_P.png
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 43 KiB |
BIN
icons/key_Q.png
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 59 KiB |
BIN
icons/key_R.png
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 47 KiB |
BIN
icons/key_S.png
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 55 KiB |
BIN
icons/key_T.png
Before Width: | Height: | Size: 0 B After Width: | Height: | Size: 36 KiB |
BIN
icons/key_U.png
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 44 KiB |
BIN
icons/key_V.png
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 48 KiB |
BIN
icons/key_W.png
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 54 KiB |
BIN
icons/key_Z.png
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 45 KiB |
Before Width: | Height: | Size: 124 KiB |
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 25 KiB |
BIN
icons/newfile.png
Normal file
After Width: | Height: | Size: 19 KiB |
BIN
icons/open.png
Normal file
After Width: | Height: | Size: 37 KiB |
BIN
icons/openfile.png
Normal file
After Width: | Height: | Size: 50 KiB |
BIN
icons/openloc.png
Normal file
After Width: | Height: | Size: 57 KiB |
BIN
icons/openpick.png
Normal file
After Width: | Height: | Size: 50 KiB |
BIN
icons/openpicks.png
Normal file
After Width: | Height: | Size: 52 KiB |
BIN
icons/openproject.png
Normal file
After Width: | Height: | Size: 58 KiB |
BIN
icons/parameter.png
Normal file
After Width: | Height: | Size: 38 KiB |
BIN
icons/pick.png
Normal file
After Width: | Height: | Size: 23 KiB |
BIN
icons/preferences.png
Normal file
After Width: | Height: | Size: 38 KiB |
BIN
icons/save.png
Normal file
After Width: | Height: | Size: 19 KiB |
BIN
icons/saveas.png
Normal file
After Width: | Height: | Size: 25 KiB |
BIN
icons/savepicks.png
Normal file
After Width: | Height: | Size: 28 KiB |
BIN
icons/saveproject.png
Normal file
After Width: | Height: | Size: 35 KiB |
BIN
icons/saveprojectas.png
Normal file
After Width: | Height: | Size: 41 KiB |
BIN
icons/tune.png
Normal file
After Width: | Height: | Size: 37 KiB |
BIN
icons/waveform.png
Normal file
After Width: | Height: | Size: 16 KiB |
157989
icons_rc.py
@ -1 +0,0 @@
|
|||||||
97ee-dirty
|
|
@ -2,6 +2,7 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
"""
|
"""
|
||||||
Created autumn/winter 2015.
|
Created autumn/winter 2015.
|
||||||
|
Revised/extended summer 2017.
|
||||||
|
|
||||||
:author: Ludger Küperkoch / MAGS2 EP3 working group
|
:author: Ludger Küperkoch / MAGS2 EP3 working group
|
||||||
"""
|
"""
|
||||||
@ -115,23 +116,30 @@ class Magnitude(object):
|
|||||||
def calc(self):
|
def calc(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def updated_event(self):
|
def updated_event(self, magscaling=None):
|
||||||
self.event.magnitudes.append(self.net_magnitude())
|
self.event.magnitudes.append(self.net_magnitude(magscaling))
|
||||||
return self.event
|
return self.event
|
||||||
|
|
||||||
def net_magnitude(self):
|
def net_magnitude(self, magscaling=None):
|
||||||
if self:
|
if self:
|
||||||
# TODO if an average Magnitude instead of the median is calculated
|
if magscaling is not None and str(magscaling) is not '[0.0, 0.0]':
|
||||||
# StationMagnitudeContributions should be added to the returned
|
# scaling necessary
|
||||||
# Magnitude object
|
print("Scaling network magnitude ...")
|
||||||
# mag_error => weights (magnitude error estimate from peak_to_peak, calcsourcespec?)
|
mag = ope.Magnitude(
|
||||||
# weights => StationMagnitdeContribution
|
mag=np.median([M.mag for M in self.magnitudes.values()]) *\
|
||||||
mag = ope.Magnitude(
|
magscaling[0] + magscaling[1],
|
||||||
mag=np.median([M.mag for M in self.magnitudes.values()]),
|
magnitude_type=self.type,
|
||||||
magnitude_type=self.type,
|
origin_id=self.origin_id,
|
||||||
origin_id=self.origin_id,
|
station_count=len(self.magnitudes),
|
||||||
station_count=len(self.magnitudes),
|
azimuthal_gap=self.origin_id.get_referred_object().quality.azimuthal_gap)
|
||||||
azimuthal_gap=self.origin_id.get_referred_object().quality.azimuthal_gap)
|
else:
|
||||||
|
# no saling necessary
|
||||||
|
mag = ope.Magnitude(
|
||||||
|
mag=np.median([M.mag for M in self.magnitudes.values()]),
|
||||||
|
magnitude_type=self.type,
|
||||||
|
origin_id=self.origin_id,
|
||||||
|
station_count=len(self.magnitudes),
|
||||||
|
azimuthal_gap=self.origin_id.get_referred_object().quality.azimuthal_gap)
|
||||||
return mag
|
return mag
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@ -153,7 +161,7 @@ class LocalMagnitude(Magnitude):
|
|||||||
|
|
||||||
_amplitudes = dict()
|
_amplitudes = dict()
|
||||||
|
|
||||||
def __init__(self, stream, event, calc_win, wascaling=None, verbosity=False, iplot=0):
|
def __init__(self, stream, event, calc_win, wascaling, verbosity=False, iplot=0):
|
||||||
super(LocalMagnitude, self).__init__(stream, event, verbosity, iplot)
|
super(LocalMagnitude, self).__init__(stream, event, verbosity, iplot)
|
||||||
|
|
||||||
self._calc_win = calc_win
|
self._calc_win = calc_win
|
||||||
@ -207,6 +215,8 @@ class LocalMagnitude(Magnitude):
|
|||||||
th = np.arange(0, len(sqH) * dt, dt)
|
th = np.arange(0, len(sqH) * dt, dt)
|
||||||
# get maximum peak within pick window
|
# get maximum peak within pick window
|
||||||
iwin = getsignalwin(th, t0 - stime, self.calc_win)
|
iwin = getsignalwin(th, t0 - stime, self.calc_win)
|
||||||
|
ii = min([iwin[len(iwin)-1], len(th)])
|
||||||
|
iwin = iwin[0:ii]
|
||||||
wapp = np.max(sqH[iwin])
|
wapp = np.max(sqH[iwin])
|
||||||
if self.verbose:
|
if self.verbose:
|
||||||
print("Determined Wood-Anderson peak-to-peak amplitude for station {0}: {1} "
|
print("Determined Wood-Anderson peak-to-peak amplitude for station {0}: {1} "
|
||||||
@ -257,12 +267,13 @@ class LocalMagnitude(Magnitude):
|
|||||||
self.amplitudes = (station, amplitude)
|
self.amplitudes = (station, amplitude)
|
||||||
# using standard Gutenberg-Richter relation
|
# using standard Gutenberg-Richter relation
|
||||||
# or scale WA amplitude with given scaling relation
|
# or scale WA amplitude with given scaling relation
|
||||||
if self.wascaling == None:
|
if str(self.wascaling) == '[0.0, 0.0, 0.0]':
|
||||||
print("Calculating original Richter magnitude ...")
|
print("Calculating original Richter magnitude ...")
|
||||||
magnitude = ope.StationMagnitude(mag=np.log10(a0) \
|
magnitude = ope.StationMagnitude(mag=np.log10(a0) \
|
||||||
+ richter_magnitude_scaling(delta))
|
+ richter_magnitude_scaling(delta))
|
||||||
else:
|
else:
|
||||||
print("Calculating scaled local magnitude ...")
|
print("Calculating scaled local magnitude ...")
|
||||||
|
a0 = a0 * 1e03 # mm to nm (see Havskov & Ottemöller, 2010)
|
||||||
magnitude = ope.StationMagnitude(mag=np.log10(a0) \
|
magnitude = ope.StationMagnitude(mag=np.log10(a0) \
|
||||||
+ self.wascaling[0] * np.log10(delta) + self.wascaling[1]
|
+ self.wascaling[0] * np.log10(delta) + self.wascaling[1]
|
||||||
* delta + self.wascaling[2])
|
* delta + self.wascaling[2])
|
||||||
|
@ -6,11 +6,12 @@ import os
|
|||||||
from obspy import read_events
|
from obspy import read_events
|
||||||
from obspy.core import read, Stream, UTCDateTime
|
from obspy.core import read, Stream, UTCDateTime
|
||||||
from obspy.io.sac import SacIOError
|
from obspy.io.sac import SacIOError
|
||||||
from obspy.core.event import Event
|
from obspy.core.event import Event as ObsPyEvent
|
||||||
from pylot.core.io.phases import readPILOTEvent, picks_from_picksdict, \
|
from pylot.core.io.phases import readPILOTEvent, picks_from_picksdict, \
|
||||||
picksdict_from_pilot, merge_picks
|
picksdict_from_pilot, merge_picks
|
||||||
from pylot.core.util.errors import FormatError, OverwriteError
|
from pylot.core.util.errors import FormatError, OverwriteError
|
||||||
from pylot.core.util.utils import fnConstructor, full_range
|
from pylot.core.util.utils import fnConstructor, full_range
|
||||||
|
from pylot.core.util.event import Event
|
||||||
|
|
||||||
class Data(object):
|
class Data(object):
|
||||||
"""
|
"""
|
||||||
@ -33,7 +34,7 @@ class Data(object):
|
|||||||
self.comp = 'Z'
|
self.comp = 'Z'
|
||||||
self.wfdata = Stream()
|
self.wfdata = Stream()
|
||||||
self._new = False
|
self._new = False
|
||||||
if isinstance(evtdata, Event):
|
if isinstance(evtdata, ObsPyEvent) or isinstance(evtdata, Event):
|
||||||
pass
|
pass
|
||||||
elif isinstance(evtdata, dict):
|
elif isinstance(evtdata, dict):
|
||||||
evt = readPILOTEvent(**evtdata)
|
evt = readPILOTEvent(**evtdata)
|
||||||
@ -49,7 +50,7 @@ class Data(object):
|
|||||||
if 'Unknown format for file' in e.message:
|
if 'Unknown format for file' in e.message:
|
||||||
if 'PHASES' in evtdata:
|
if 'PHASES' in evtdata:
|
||||||
picks = picksdict_from_pilot(evtdata)
|
picks = picksdict_from_pilot(evtdata)
|
||||||
evtdata = Event()
|
evtdata = ObsPyEvent()
|
||||||
evtdata.picks = picks_from_picksdict(picks)
|
evtdata.picks = picks_from_picksdict(picks)
|
||||||
elif 'LOC' in evtdata:
|
elif 'LOC' in evtdata:
|
||||||
raise NotImplementedError('PILOT location information '
|
raise NotImplementedError('PILOT location information '
|
||||||
@ -61,7 +62,7 @@ class Data(object):
|
|||||||
raise e
|
raise e
|
||||||
else: # create an empty Event object
|
else: # create an empty Event object
|
||||||
self.setNew()
|
self.setNew()
|
||||||
evtdata = Event()
|
evtdata = ObsPyEvent()
|
||||||
evtdata.picks = []
|
evtdata.picks = []
|
||||||
self.evtdata = evtdata
|
self.evtdata = evtdata
|
||||||
self.wforiginal = None
|
self.wforiginal = None
|
||||||
@ -73,6 +74,8 @@ class Data(object):
|
|||||||
|
|
||||||
def __add__(self, other):
|
def __add__(self, other):
|
||||||
assert isinstance(other, Data), "operands must be of same type 'Data'"
|
assert isinstance(other, Data), "operands must be of same type 'Data'"
|
||||||
|
rs_id = self.get_evt_data().get('resource_id')
|
||||||
|
rs_id_other = other.get_evt_data().get('resource_id')
|
||||||
if other.isNew() and not self.isNew():
|
if other.isNew() and not self.isNew():
|
||||||
picks_to_add = other.get_evt_data().picks
|
picks_to_add = other.get_evt_data().picks
|
||||||
old_picks = self.get_evt_data().picks
|
old_picks = self.get_evt_data().picks
|
||||||
@ -84,7 +87,7 @@ class Data(object):
|
|||||||
self.evtdata = new.get_evt_data()
|
self.evtdata = new.get_evt_data()
|
||||||
elif self.isNew() and other.isNew():
|
elif self.isNew() and other.isNew():
|
||||||
pass
|
pass
|
||||||
elif self.get_evt_data().get('id') == other.get_evt_data().get('id'):
|
elif rs_id == rs_id_other:
|
||||||
other.setNew()
|
other.setNew()
|
||||||
return self + other
|
return self + other
|
||||||
else:
|
else:
|
||||||
@ -95,7 +98,7 @@ class Data(object):
|
|||||||
def getPicksStr(self):
|
def getPicksStr(self):
|
||||||
picks_str = ''
|
picks_str = ''
|
||||||
for pick in self.get_evt_data().picks:
|
for pick in self.get_evt_data().picks:
|
||||||
picks_str += str(pick) + '\n'
|
picks_str += str(PyLoT) + '\n'
|
||||||
return picks_str
|
return picks_str
|
||||||
|
|
||||||
def getParent(self):
|
def getParent(self):
|
||||||
@ -144,12 +147,13 @@ class Data(object):
|
|||||||
# handle forbidden filenames especially on windows systems
|
# handle forbidden filenames especially on windows systems
|
||||||
return fnConstructor(str(ID))
|
return fnConstructor(str(ID))
|
||||||
|
|
||||||
def exportEvent(self, fnout, fnext='.xml'):
|
def exportEvent(self, fnout, fnext='.xml', fcheck='auto'):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
:param fnout:
|
:param fnout:
|
||||||
:param fnext:
|
:param fnext:
|
||||||
|
:param fcheck:
|
||||||
:raise KeyError:
|
:raise KeyError:
|
||||||
"""
|
"""
|
||||||
from pylot.core.util.defaults import OUTPUTFORMATS
|
from pylot.core.util.defaults import OUTPUTFORMATS
|
||||||
@ -161,12 +165,70 @@ class Data(object):
|
|||||||
'supported'.format(e, fnext)
|
'supported'.format(e, fnext)
|
||||||
raise FormatError(errmsg)
|
raise FormatError(errmsg)
|
||||||
|
|
||||||
|
# check for already existing xml-file
|
||||||
|
if fnext == '.xml':
|
||||||
|
if os.path.isfile(fnout + fnext):
|
||||||
|
print("xml-file already exists! Check content ...")
|
||||||
|
cat_old = read_events(fnout + fnext)
|
||||||
|
checkflag = 0
|
||||||
|
for j in range(len(cat_old.events[0].picks)):
|
||||||
|
if cat_old.events[0].picks[j].method_id.id.split('/')[1] == fcheck:
|
||||||
|
print("Found %s pick(s), append to new catalog." % fcheck)
|
||||||
|
checkflag = 1
|
||||||
|
break
|
||||||
|
if checkflag == 1:
|
||||||
|
self.get_evt_data().write(fnout + fnext, format=evtformat)
|
||||||
|
cat_new = read_events(fnout + fnext)
|
||||||
|
cat_new.append(cat_old.events[0])
|
||||||
|
cat_new.write(fnout + fnext, format=evtformat)
|
||||||
|
else:
|
||||||
|
self.get_evt_data().write(fnout + fnext, format=evtformat)
|
||||||
|
else:
|
||||||
|
self.get_evt_data().write(fnout + fnext, format=evtformat)
|
||||||
|
|
||||||
# try exporting event via ObsPy
|
# try exporting event via ObsPy
|
||||||
try:
|
else:
|
||||||
self.get_evt_data().write(fnout + fnext, format=evtformat)
|
# check for stations picked automatically as well as manually
|
||||||
except KeyError as e:
|
# Prefer manual picks!
|
||||||
raise KeyError('''{0} export format
|
evtdata_copy = self.get_evt_data().copy()
|
||||||
not implemented: {1}'''.format(evtformat, e))
|
evtdata_org = self.get_evt_data()
|
||||||
|
for i in range(len(evtdata_org.picks)):
|
||||||
|
if evtdata_org.picks[i].method_id == 'manual':
|
||||||
|
mstation = evtdata_org.picks[i].waveform_id.station_code
|
||||||
|
mstation_ext = mstation + '_'
|
||||||
|
for k in range(len(evtdata_copy.picks)):
|
||||||
|
if evtdata_copy.picks[k].waveform_id.station_code == mstation or \
|
||||||
|
evtdata_copy.picks[k].waveform_id.station_code == mstation_ext and \
|
||||||
|
evtdata_copy.picks[k].method_id == 'auto':
|
||||||
|
del evtdata_copy.picks[k]
|
||||||
|
break
|
||||||
|
lendiff = len(evtdata_org.picks) - len(evtdata_copy.picks)
|
||||||
|
if lendiff is not 0:
|
||||||
|
print("Manual as well as automatic picks available. Prefered the {} manual ones!".format(lendiff))
|
||||||
|
|
||||||
|
if fnext == '.obs':
|
||||||
|
try:
|
||||||
|
evtdata_copy.write(fnout + fnext, format=evtformat)
|
||||||
|
# write header afterwards
|
||||||
|
evid = str(evtdata_org.resource_id).split('/')[1]
|
||||||
|
header = '# EQEVENT: Label: EQ%s Loc: X 0.00 Y 0.00 Z 10.00 OT 0.00 \n' % evid
|
||||||
|
nllocfile = open(fnout + fnext)
|
||||||
|
l = nllocfile.readlines()
|
||||||
|
nllocfile.close()
|
||||||
|
l.insert(0, header)
|
||||||
|
nllocfile = open(fnout + fnext, 'w')
|
||||||
|
nllocfile.write("".join(l))
|
||||||
|
nllocfile.close()
|
||||||
|
except KeyError as e:
|
||||||
|
raise KeyError('''{0} export format
|
||||||
|
not implemented: {1}'''.format(evtformat, e))
|
||||||
|
if fnext == '.cnv':
|
||||||
|
try:
|
||||||
|
evtdata_org.write(fnout + fnext, format=evtformat)
|
||||||
|
except KeyError as e:
|
||||||
|
raise KeyError('''{0} export format
|
||||||
|
not implemented: {1}'''.format(evtformat, e))
|
||||||
|
|
||||||
|
|
||||||
def getComp(self):
|
def getComp(self):
|
||||||
"""
|
"""
|
||||||
@ -279,12 +341,12 @@ class Data(object):
|
|||||||
def setEvtData(self, event):
|
def setEvtData(self, event):
|
||||||
self.evtdata = event
|
self.evtdata = event
|
||||||
|
|
||||||
def applyEVTData(self, data, type='pick', authority_id='rub'):
|
def applyEVTData(self, data, typ='pick', authority_id='rub'):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
:param data:
|
:param data:
|
||||||
:param type:
|
:param typ:
|
||||||
:param authority_id:
|
:param authority_id:
|
||||||
:raise OverwriteError:
|
:raise OverwriteError:
|
||||||
"""
|
"""
|
||||||
@ -326,19 +388,27 @@ class Data(object):
|
|||||||
information on the event to the actual data
|
information on the event to the actual data
|
||||||
:param event:
|
:param event:
|
||||||
"""
|
"""
|
||||||
if not self.isNew():
|
if self.isNew():
|
||||||
self.setEvtData(event)
|
self.setEvtData(event)
|
||||||
else:
|
else:
|
||||||
# prevent overwriting original pick information
|
# prevent overwriting original pick information
|
||||||
picks = copy.deepcopy(self.get_evt_data().picks)
|
event_old = self.get_evt_data()
|
||||||
|
print(event_old.resource_id, event.resource_id)
|
||||||
|
if not event_old.resource_id == event.resource_id:
|
||||||
|
print("WARNING: Missmatch in event resource id's: {} and {}".format(
|
||||||
|
event_old.resource_id,
|
||||||
|
event.resource_id))
|
||||||
|
picks = copy.deepcopy(event_old.picks)
|
||||||
event = merge_picks(event, picks)
|
event = merge_picks(event, picks)
|
||||||
# apply event information from location
|
# apply event information from location
|
||||||
self.get_evt_data().update(event)
|
event_old.update(event)
|
||||||
|
|
||||||
applydata = {'pick': applyPicks,
|
applydata = {'pick': applyPicks,
|
||||||
'event': applyEvent}
|
'event': applyEvent}
|
||||||
|
|
||||||
applydata[type](data)
|
applydata[typ](data)
|
||||||
|
self._new = False
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class GenericDataStructure(object):
|
class GenericDataStructure(object):
|
||||||
|
@ -14,7 +14,7 @@ defaults = {'rootpath': {'type': str,
|
|||||||
'value': ''},
|
'value': ''},
|
||||||
|
|
||||||
'eventID': {'type': str,
|
'eventID': {'type': str,
|
||||||
'tooltip': 'event ID for single event processing',
|
'tooltip': 'event ID for single event processing (* for all events found in database)',
|
||||||
'value': ''},
|
'value': ''},
|
||||||
|
|
||||||
'extent': {'type': str,
|
'extent': {'type': str,
|
||||||
@ -278,12 +278,14 @@ defaults = {'rootpath': {'type': str,
|
|||||||
'value': 1.0},
|
'value': 1.0},
|
||||||
|
|
||||||
'WAscaling': {'type': (float, float, float),
|
'WAscaling': {'type': (float, float, float),
|
||||||
'tooltip': 'Scaling relation (log(Ao)+Alog(r)+Br+C) of Wood-Anderson amplitude Ao [nm]',
|
'tooltip': 'Scaling relation (log(Ao)+Alog(r)+Br+C) of Wood-Anderson amplitude Ao [nm] \
|
||||||
'value': (1.0, 1.0, 1.0)},
|
If zeros are set, original Richter magnitude is calculated!',
|
||||||
|
'value': (0., 0., 0.)},
|
||||||
|
|
||||||
'magscaling': {'type': (float, float),
|
'magscaling': {'type': (float, float),
|
||||||
'tooltip': 'Scaling relation for derived local magnitude [a*Ml+b]',
|
'tooltip': 'Scaling relation for derived local magnitude [a*Ml+b]. \
|
||||||
'value': (1.0, 1.0)},
|
If zeros are set, no scaling of network magnitude is applied!',
|
||||||
|
'value': (0., 0.)}
|
||||||
|
|
||||||
'minfreq': {'type': float,
|
'minfreq': {'type': float,
|
||||||
'tooltip': 'Lower filter frequency',
|
'tooltip': 'Lower filter frequency',
|
||||||
|
@ -222,26 +222,25 @@ class PylotParameter(object):
|
|||||||
# for key, value in self.iteritems():
|
# for key, value in self.iteritems():
|
||||||
# lines.append('{key}\t{value}\n'.format(key=key, value=value))
|
# lines.append('{key}\t{value}\n'.format(key=key, value=value))
|
||||||
# fid_out.writelines(lines)
|
# fid_out.writelines(lines)
|
||||||
|
|
||||||
header = ('%This is a parameter input file for PyLoT/autoPyLoT.\n'+
|
header = ('%This is a parameter input file for PyLoT/autoPyLoT.\n'+
|
||||||
'%All main and special settings regarding data handling\n'+
|
'%All main and special settings regarding data handling\n'+
|
||||||
'%and picking are to be set here!\n'+
|
'%and picking are to be set here!\n'+
|
||||||
'%Parameters are optimized for local data sets!\n')
|
'%Parameters are optimized for %{} data sets!\n'.format(self.get_main_para_names()['pick'][0]))
|
||||||
seperator = '%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n'
|
separator = '%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n'
|
||||||
|
|
||||||
fid_out.write(header)
|
fid_out.write(header)
|
||||||
self.write_section(fid_out, self.get_main_para_names()['dirs'],
|
self.write_section(fid_out, self.get_main_para_names()['dirs'],
|
||||||
'main settings', seperator)
|
'main settings', separator)
|
||||||
self.write_section(fid_out, self.get_main_para_names()['nlloc'],
|
self.write_section(fid_out, self.get_main_para_names()['nlloc'],
|
||||||
'NLLoc settings', seperator)
|
'NLLoc settings', separator)
|
||||||
self.write_section(fid_out, self.get_main_para_names()['smoment'],
|
self.write_section(fid_out, self.get_main_para_names()['smoment'],
|
||||||
'parameters for seismic moment estimation', seperator)
|
'parameters for seismic moment estimation', separator)
|
||||||
self.write_section(fid_out, self.get_main_para_names()['localmag'],
|
self.write_section(fid_out, self.get_main_para_names()['localmag'],
|
||||||
'settings local magnitude', seperator)
|
'settings local magnitude', separator)
|
||||||
self.write_section(fid_out, self.get_main_para_names()['filter'],
|
self.write_section(fid_out, self.get_main_para_names()['filter'],
|
||||||
'filter settings', seperator)
|
'filter settings', seperator)
|
||||||
self.write_section(fid_out, self.get_main_para_names()['pick'],
|
self.write_section(fid_out, self.get_main_para_names()['pick'],
|
||||||
'common settings picker', seperator)
|
'common settings picker', separator)
|
||||||
fid_out.write(('#special settings for calculating CF#\n'+
|
fid_out.write(('#special settings for calculating CF#\n'+
|
||||||
'%!!Edit the following only if you know what you are doing!!%\n'))
|
'%!!Edit the following only if you know what you are doing!!%\n'))
|
||||||
self.write_section(fid_out, self.get_special_para_names()['z'],
|
self.write_section(fid_out, self.get_special_para_names()['z'],
|
||||||
@ -253,9 +252,9 @@ class PylotParameter(object):
|
|||||||
self.write_section(fid_out, self.get_special_para_names()['quality'],
|
self.write_section(fid_out, self.get_special_para_names()['quality'],
|
||||||
'quality assessment', None)
|
'quality assessment', None)
|
||||||
|
|
||||||
def write_section(self, fid, names, title, seperator):
|
def write_section(self, fid, names, title, separator):
|
||||||
if seperator:
|
if separator:
|
||||||
fid.write(seperator)
|
fid.write(separator)
|
||||||
fid.write('#{}#\n'.format(title))
|
fid.write('#{}#\n'.format(title))
|
||||||
l_val = 50
|
l_val = 50
|
||||||
l_name = 15
|
l_name = 15
|
||||||
|
@ -7,6 +7,7 @@ import os
|
|||||||
import scipy.io as sio
|
import scipy.io as sio
|
||||||
import warnings
|
import warnings
|
||||||
from obspy.core import UTCDateTime
|
from obspy.core import UTCDateTime
|
||||||
|
from obspy.core.util import AttribDict
|
||||||
|
|
||||||
from pylot.core.io.inputs import PylotParameter
|
from pylot.core.io.inputs import PylotParameter
|
||||||
from pylot.core.io.location import create_arrival, create_event, \
|
from pylot.core.io.location import create_arrival, create_event, \
|
||||||
@ -195,6 +196,7 @@ def picksdict_from_picks(evt):
|
|||||||
phase = {}
|
phase = {}
|
||||||
station = pick.waveform_id.station_code
|
station = pick.waveform_id.station_code
|
||||||
channel = pick.waveform_id.channel_code
|
channel = pick.waveform_id.channel_code
|
||||||
|
network = pick.waveform_id.network_code
|
||||||
try:
|
try:
|
||||||
onsets = picks[station]
|
onsets = picks[station]
|
||||||
except KeyError as e:
|
except KeyError as e:
|
||||||
@ -215,6 +217,7 @@ def picksdict_from_picks(evt):
|
|||||||
phase['lpp'] = lpp
|
phase['lpp'] = lpp
|
||||||
phase['spe'] = spe
|
phase['spe'] = spe
|
||||||
phase['channel'] = channel
|
phase['channel'] = channel
|
||||||
|
phase['network'] = network
|
||||||
try:
|
try:
|
||||||
picker = str(pick.method_id)
|
picker = str(pick.method_id)
|
||||||
if picker.startswith('smi:local/'):
|
if picker.startswith('smi:local/'):
|
||||||
@ -231,7 +234,7 @@ def picks_from_picksdict(picks, creation_info=None):
|
|||||||
picks_list = list()
|
picks_list = list()
|
||||||
for station, onsets in picks.items():
|
for station, onsets in picks.items():
|
||||||
for label, phase in onsets.items():
|
for label, phase in onsets.items():
|
||||||
if not isinstance(phase, dict):
|
if not isinstance(phase, dict) and not isinstance(phase, AttribDict):
|
||||||
continue
|
continue
|
||||||
onset = phase['mpp']
|
onset = phase['mpp']
|
||||||
try:
|
try:
|
||||||
@ -382,12 +385,12 @@ def reassess_pilot_event(root_dir, db_dir, event_id, out_dir=None, fn_param=None
|
|||||||
evt.picks = picks_from_picksdict(picks_dict)
|
evt.picks = picks_from_picksdict(picks_dict)
|
||||||
# write phase information to file
|
# write phase information to file
|
||||||
if not out_dir:
|
if not out_dir:
|
||||||
fnout_prefix = os.path.join(root_dir, db_dir, event_id, '{0}.'.format(event_id))
|
fnout_prefix = os.path.join(root_dir, db_dir, event_id, 'PyLoT_{0}.'.format(event_id))
|
||||||
else:
|
else:
|
||||||
out_dir = os.path.join(out_dir, db_dir)
|
out_dir = os.path.join(out_dir, db_dir)
|
||||||
if not os.path.isdir(out_dir):
|
if not os.path.isdir(out_dir):
|
||||||
os.makedirs(out_dir)
|
os.makedirs(out_dir)
|
||||||
fnout_prefix = os.path.join(out_dir, '{0}.'.format(event_id))
|
fnout_prefix = os.path.join(out_dir, 'PyLoT_{0}.'.format(event_id))
|
||||||
evt.write(fnout_prefix + 'xml', format='QUAKEML')
|
evt.write(fnout_prefix + 'xml', format='QUAKEML')
|
||||||
#evt.write(fnout_prefix + 'cnv', format='VELEST')
|
#evt.write(fnout_prefix + 'cnv', format='VELEST')
|
||||||
|
|
||||||
@ -835,9 +838,10 @@ def merge_picks(event, picks):
|
|||||||
err = pick.time_errors
|
err = pick.time_errors
|
||||||
phase = pick.phase_hint
|
phase = pick.phase_hint
|
||||||
station = pick.waveform_id.station_code
|
station = pick.waveform_id.station_code
|
||||||
|
network = pick.waveform_id.network_code
|
||||||
method = pick.method_id
|
method = pick.method_id
|
||||||
for p in event.picks:
|
for p in event.picks:
|
||||||
if p.waveform_id.station_code == station and p.phase_hint == phase:
|
if p.waveform_id.station_code == station and p.phase_hint == phase:
|
||||||
p.time, p.time_errors, p.method_id = time, err, method
|
p.time, p.time_errors, p.waveform_id.network_code, p.method_id = time, err, network, method
|
||||||
del time, err, phase, station, method
|
del time, err, phase, station, network, method
|
||||||
return event
|
return event
|
||||||
|
@ -212,6 +212,14 @@ class AICPicker(AutoPicker):
|
|||||||
self.Data[0].data = self.Data[0].data * 1000000
|
self.Data[0].data = self.Data[0].data * 1000000
|
||||||
# get signal window
|
# get signal window
|
||||||
isignal = getsignalwin(self.Tcf, self.Pick, self.TSNR[2])
|
isignal = getsignalwin(self.Tcf, self.Pick, self.TSNR[2])
|
||||||
|
ii = min([isignal[len(isignal)-1], len(self.Tcf)])
|
||||||
|
isignal = isignal[0:ii]
|
||||||
|
try:
|
||||||
|
aic[isignal]
|
||||||
|
except IndexError as e:
|
||||||
|
msg = "Time series out of bounds! {}".format(e)
|
||||||
|
print(msg)
|
||||||
|
return
|
||||||
# calculate SNR from CF
|
# calculate SNR from CF
|
||||||
self.SNR = max(abs(aic[isignal] - np.mean(aic[isignal]))) / \
|
self.SNR = max(abs(aic[isignal] - np.mean(aic[isignal]))) / \
|
||||||
max(abs(aic[inoise] - np.mean(aic[inoise])))
|
max(abs(aic[inoise] - np.mean(aic[inoise])))
|
||||||
|
144
pylot/core/util/event.py
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
from obspy import UTCDateTime
|
||||||
|
from obspy.core.event import Event as ObsPyEvent
|
||||||
|
from obspy.core.event import Origin, Magnitude, ResourceIdentifier
|
||||||
|
|
||||||
|
from pylot.core.io.phases import picks_from_picksdict
|
||||||
|
|
||||||
|
|
||||||
|
class Event(ObsPyEvent):
|
||||||
|
'''
|
||||||
|
Pickable class derived from ~obspy.core.event.Event containing information on a single event.
|
||||||
|
'''
|
||||||
|
def __init__(self, path):
|
||||||
|
self.pylot_id = path.split('/')[-1]
|
||||||
|
# initialize super class
|
||||||
|
super(Event, self).__init__(resource_id=ResourceIdentifier('smi:local/'+self.pylot_id))
|
||||||
|
self.path = path
|
||||||
|
self.database = path.split('/')[-2]
|
||||||
|
self.datapath = path.split('/')[-3]
|
||||||
|
self.rootpath = '/' + os.path.join(*path.split('/')[:-3])
|
||||||
|
self.pylot_autopicks = {}
|
||||||
|
self.pylot_picks = {}
|
||||||
|
self.notes = ''
|
||||||
|
self._testEvent = False
|
||||||
|
self._refEvent = False
|
||||||
|
self.get_notes()
|
||||||
|
|
||||||
|
def get_notes_path(self):
|
||||||
|
notesfile = os.path.join(self.path, 'notes.txt')
|
||||||
|
return notesfile
|
||||||
|
|
||||||
|
def get_notes(self):
|
||||||
|
notesfile = self.get_notes_path()
|
||||||
|
if os.path.isfile(notesfile):
|
||||||
|
with open(notesfile) as infile:
|
||||||
|
path = str(infile.readlines()[0].split('\n')[0])
|
||||||
|
text = '[eventInfo: '+path+']'
|
||||||
|
self.addNotes(text)
|
||||||
|
try:
|
||||||
|
datetime = UTCDateTime(path.split('/')[-1])
|
||||||
|
origin = Origin(resource_id=self.resource_id, time=datetime, latitude=0, longitude=0, depth=0)
|
||||||
|
self.origins.append(origin)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def addNotes(self, notes):
|
||||||
|
self.notes = str(notes)
|
||||||
|
|
||||||
|
def clearNotes(self):
|
||||||
|
self.notes = None
|
||||||
|
|
||||||
|
def isRefEvent(self):
|
||||||
|
return self._refEvent
|
||||||
|
|
||||||
|
def isTestEvent(self):
|
||||||
|
return self._testEvent
|
||||||
|
|
||||||
|
def setRefEvent(self, bool):
|
||||||
|
self._refEvent = bool
|
||||||
|
if bool: self._testEvent = False
|
||||||
|
|
||||||
|
def setTestEvent(self, bool):
|
||||||
|
self._testEvent = bool
|
||||||
|
if bool: self._refEvent = False
|
||||||
|
|
||||||
|
def addPicks(self, picks):
|
||||||
|
'''
|
||||||
|
add pylot picks and overwrite existing
|
||||||
|
'''
|
||||||
|
for station in picks:
|
||||||
|
self.pylot_picks[station] = picks[station]
|
||||||
|
#add ObsPy picks
|
||||||
|
self.picks = picks_from_picksdict(self.pylot_picks)
|
||||||
|
|
||||||
|
def addAutopicks(self, autopicks):
|
||||||
|
for station in autopicks:
|
||||||
|
self.pylot_autopicks[station] = autopicks[station]
|
||||||
|
|
||||||
|
def setPick(self, station, pick):
|
||||||
|
if pick:
|
||||||
|
self.pylot_picks[station] = pick
|
||||||
|
self.picks = picks_from_picksdict(self.pylot_picks)
|
||||||
|
|
||||||
|
def setPicks(self, picks):
|
||||||
|
'''
|
||||||
|
set pylot picks and delete and overwrite all existing
|
||||||
|
'''
|
||||||
|
self.pylot_picks = picks
|
||||||
|
self.picks = picks_from_picksdict(self.pylot_picks)
|
||||||
|
|
||||||
|
def getPick(self, station):
|
||||||
|
if station in self.pylot_picks.keys():
|
||||||
|
return self.pylot_picks[station]
|
||||||
|
|
||||||
|
def getPicks(self):
|
||||||
|
return self.pylot_picks
|
||||||
|
|
||||||
|
def setAutopick(self, station, autopick):
|
||||||
|
if autopick:
|
||||||
|
self.pylot_autopicks[station] = autopick
|
||||||
|
|
||||||
|
def setAutopicks(self, autopicks):
|
||||||
|
self.pylot_autopicks = autopicks
|
||||||
|
|
||||||
|
def getAutopick(self, station):
|
||||||
|
if station in self.pylot_autopicks.keys():
|
||||||
|
return self.pylot_autopicks[station]
|
||||||
|
|
||||||
|
def getAutopicks(self):
|
||||||
|
return self.pylot_autopicks
|
||||||
|
|
||||||
|
def save(self, filename):
|
||||||
|
'''
|
||||||
|
Save PyLoT Event to a file.
|
||||||
|
Can be loaded by using event.load(filename).
|
||||||
|
'''
|
||||||
|
try:
|
||||||
|
import cPickle
|
||||||
|
except ImportError:
|
||||||
|
import _pickle as cPickle
|
||||||
|
|
||||||
|
try:
|
||||||
|
outfile = open(filename, 'wb')
|
||||||
|
cPickle.dump(self, outfile, -1)
|
||||||
|
except Exception as e:
|
||||||
|
print('Could not pickle PyLoT event. Reason: {}'.format(e))
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def load(filename):
|
||||||
|
'''
|
||||||
|
Load project from filename.
|
||||||
|
'''
|
||||||
|
try:
|
||||||
|
import cPickle
|
||||||
|
except ImportError:
|
||||||
|
import _pickle as cPickle
|
||||||
|
infile = open(filename, 'rb')
|
||||||
|
event = cPickle.load(infile)
|
||||||
|
print('Loaded %s' % filename)
|
||||||
|
return event
|
@ -22,6 +22,7 @@ class map_projection(QtGui.QWidget):
|
|||||||
self.parser = parent.metadata[1]
|
self.parser = parent.metadata[1]
|
||||||
self.picks = None
|
self.picks = None
|
||||||
self.picks_dict = None
|
self.picks_dict = None
|
||||||
|
self.eventLoc = None
|
||||||
self.figure = figure
|
self.figure = figure
|
||||||
self.init_graphics()
|
self.init_graphics()
|
||||||
self.init_stations()
|
self.init_stations()
|
||||||
@ -244,6 +245,10 @@ class map_projection(QtGui.QWidget):
|
|||||||
self.sc = self.basemap.scatter(self.lon, self.lat, s=50, facecolor='none', latlon=True,
|
self.sc = self.basemap.scatter(self.lon, self.lat, s=50, facecolor='none', latlon=True,
|
||||||
zorder=10, picker=True, edgecolor='m', label='Not Picked')
|
zorder=10, picker=True, edgecolor='m', label='Not Picked')
|
||||||
self.cid = self.canvas.mpl_connect('pick_event', self.onpick)
|
self.cid = self.canvas.mpl_connect('pick_event', self.onpick)
|
||||||
|
if self.eventLoc:
|
||||||
|
lat, lon = self.eventLoc
|
||||||
|
self.sc_event = self.basemap.scatter(lon, lat, s=100, facecolor='red',
|
||||||
|
latlon=True, zorder=11, label='Event (might be outside map region)')
|
||||||
|
|
||||||
def scatter_picked_stations(self):
|
def scatter_picked_stations(self):
|
||||||
lon = self.lon_no_nan
|
lon = self.lon_no_nan
|
||||||
@ -274,8 +279,7 @@ class map_projection(QtGui.QWidget):
|
|||||||
|
|
||||||
def refresh_drawings(self, picks=None):
|
def refresh_drawings(self, picks=None):
|
||||||
self.picks_dict = picks
|
self.picks_dict = picks
|
||||||
self.remove_drawings()
|
self._refresh_drawings()
|
||||||
self.draw_everything()
|
|
||||||
|
|
||||||
def _refresh_drawings(self):
|
def _refresh_drawings(self):
|
||||||
self.remove_drawings()
|
self.remove_drawings()
|
||||||
@ -303,6 +307,9 @@ class map_projection(QtGui.QWidget):
|
|||||||
if hasattr(self, 'sc_picked'):
|
if hasattr(self, 'sc_picked'):
|
||||||
self.sc_picked.remove()
|
self.sc_picked.remove()
|
||||||
del(self.sc_picked)
|
del(self.sc_picked)
|
||||||
|
if hasattr(self, 'sc_event'):
|
||||||
|
self.sc_event.remove()
|
||||||
|
del(self.sc_event)
|
||||||
if hasattr(self, 'cbar'):
|
if hasattr(self, 'cbar'):
|
||||||
self.cbar.remove()
|
self.cbar.remove()
|
||||||
del(self.cbar)
|
del(self.cbar)
|
||||||
|
@ -35,6 +35,7 @@ from PySide.QtGui import QAction, QApplication, QCheckBox, QComboBox, \
|
|||||||
from PySide.QtCore import QSettings, Qt, QUrl, Signal, Slot
|
from PySide.QtCore import QSettings, Qt, QUrl, Signal, Slot
|
||||||
from PySide.QtWebKit import QWebView
|
from PySide.QtWebKit import QWebView
|
||||||
from obspy import Stream, UTCDateTime
|
from obspy import Stream, UTCDateTime
|
||||||
|
from obspy.core.util import AttribDict
|
||||||
from pylot.core.io.data import Data
|
from pylot.core.io.data import Data
|
||||||
from pylot.core.io.inputs import FilterOptions, PylotParameter
|
from pylot.core.io.inputs import FilterOptions, PylotParameter
|
||||||
from pylot.core.pick.utils import getSNR, earllatepicker, getnoisewin, \
|
from pylot.core.pick.utils import getSNR, earllatepicker, getnoisewin, \
|
||||||
@ -707,7 +708,7 @@ class WaveformWidget(FigureCanvas):
|
|||||||
self.draw()
|
self.draw()
|
||||||
|
|
||||||
def updateTitle(self, text):
|
def updateTitle(self, text):
|
||||||
self.getAxes().set_title(text)
|
self.getAxes().set_title(text, verticalalignment='bottom')
|
||||||
self.draw()
|
self.draw()
|
||||||
|
|
||||||
def updateWidget(self, xlabel, ylabel, title):
|
def updateWidget(self, xlabel, ylabel, title):
|
||||||
@ -724,7 +725,7 @@ class WaveformWidget(FigureCanvas):
|
|||||||
|
|
||||||
class PickDlg(QDialog):
|
class PickDlg(QDialog):
|
||||||
update_picks = QtCore.Signal(dict)
|
update_picks = QtCore.Signal(dict)
|
||||||
def __init__(self, parent=None, data=None, station=None, picks=None,
|
def __init__(self, parent=None, data=None, station=None, network=None, picks=None,
|
||||||
autopicks=None, rotate=False, parameter=None, embedded=False):
|
autopicks=None, rotate=False, parameter=None, embedded=False):
|
||||||
super(PickDlg, self).__init__(parent)
|
super(PickDlg, self).__init__(parent)
|
||||||
|
|
||||||
@ -732,6 +733,7 @@ class PickDlg(QDialog):
|
|||||||
self.parameter = parameter
|
self.parameter = parameter
|
||||||
self._embedded = embedded
|
self._embedded = embedded
|
||||||
self.station = station
|
self.station = station
|
||||||
|
self.network = network
|
||||||
self.rotate = rotate
|
self.rotate = rotate
|
||||||
self.components = 'ZNE'
|
self.components = 'ZNE'
|
||||||
self.currentPhase = None
|
self.currentPhase = None
|
||||||
@ -806,6 +808,14 @@ class PickDlg(QDialog):
|
|||||||
self.cidscroll = self.connectScrollEvent(self.scrollZoom)
|
self.cidscroll = self.connectScrollEvent(self.scrollZoom)
|
||||||
|
|
||||||
def setupUi(self):
|
def setupUi(self):
|
||||||
|
menuBar = QtGui.QMenuBar(self)
|
||||||
|
if not self._embedded:
|
||||||
|
exitMenu = menuBar.addMenu('File')
|
||||||
|
exitAction = QtGui.QAction('Close', self)
|
||||||
|
exitAction.triggered.connect(self.close)
|
||||||
|
exitMenu.addAction(exitAction)
|
||||||
|
|
||||||
|
self.addPickPhases(menuBar)
|
||||||
|
|
||||||
# create matplotlib toolbar to inherit functionality
|
# create matplotlib toolbar to inherit functionality
|
||||||
self.figToolBar = NavigationToolbar2QT(self.getPlotWidget(), self)
|
self.figToolBar = NavigationToolbar2QT(self.getPlotWidget(), self)
|
||||||
@ -847,8 +857,8 @@ class PickDlg(QDialog):
|
|||||||
self.p_button.setCheckable(True)
|
self.p_button.setCheckable(True)
|
||||||
self.s_button.setCheckable(True)
|
self.s_button.setCheckable(True)
|
||||||
# set button tooltips
|
# set button tooltips
|
||||||
self.p_button.setToolTip('Hotkey: "1"')
|
# self.p_button.setToolTip('Hotkey: "1"')
|
||||||
self.s_button.setToolTip('Hotkey: "2"')
|
# self.s_button.setToolTip('Hotkey: "2"')
|
||||||
|
|
||||||
# create accept/reject button
|
# create accept/reject button
|
||||||
self.accept_button = QPushButton('&Accept Picks')
|
self.accept_button = QPushButton('&Accept Picks')
|
||||||
@ -859,8 +869,8 @@ class PickDlg(QDialog):
|
|||||||
self._shortcut_space = QtGui.QShortcut(QtGui.QKeySequence(' '), self)
|
self._shortcut_space = QtGui.QShortcut(QtGui.QKeySequence(' '), self)
|
||||||
self._shortcut_space.activated.connect(self.accept_button.clicked)
|
self._shortcut_space.activated.connect(self.accept_button.clicked)
|
||||||
# button shortcuts (1 for P-button, 2 for S-button)
|
# button shortcuts (1 for P-button, 2 for S-button)
|
||||||
self.p_button.setShortcut(QKeySequence('1'))
|
# self.p_button.setShortcut(QKeySequence('1'))
|
||||||
self.s_button.setShortcut(QKeySequence('2'))
|
# self.s_button.setShortcut(QKeySequence('2'))
|
||||||
|
|
||||||
# layout the outermost appearance of the Pick Dialog
|
# layout the outermost appearance of the Pick Dialog
|
||||||
_outerlayout = QVBoxLayout()
|
_outerlayout = QVBoxLayout()
|
||||||
@ -892,8 +902,12 @@ class PickDlg(QDialog):
|
|||||||
# merge widgets and layouts to establish the dialog
|
# merge widgets and layouts to establish the dialog
|
||||||
if not self._embedded:
|
if not self._embedded:
|
||||||
_innerlayout.addWidget(_buttonbox)
|
_innerlayout.addWidget(_buttonbox)
|
||||||
|
_outerlayout.addWidget(menuBar)
|
||||||
_outerlayout.addWidget(_dialtoolbar)
|
_outerlayout.addWidget(_dialtoolbar)
|
||||||
_outerlayout.addLayout(_innerlayout)
|
_outerlayout.addLayout(_innerlayout)
|
||||||
|
_outerlayout.setStretch(0, 0)
|
||||||
|
_outerlayout.setStretch(1, 0)
|
||||||
|
_outerlayout.setStretch(2, 1)
|
||||||
|
|
||||||
# connect widget element signals with slots (methods to the dialog
|
# connect widget element signals with slots (methods to the dialog
|
||||||
# object
|
# object
|
||||||
@ -910,6 +924,60 @@ class PickDlg(QDialog):
|
|||||||
self.setLayout(_outerlayout)
|
self.setLayout(_outerlayout)
|
||||||
self.resize(1280, 720)
|
self.resize(1280, 720)
|
||||||
|
|
||||||
|
def addPickPhases(self, menuBar):
|
||||||
|
settings = QtCore.QSettings()
|
||||||
|
p_phases = settings.value('p_phases')
|
||||||
|
s_phases = settings.value('s_phases')
|
||||||
|
|
||||||
|
if p_phases:
|
||||||
|
p_phases = p_phases.split(',')
|
||||||
|
else:
|
||||||
|
p_phases = []
|
||||||
|
if s_phases:
|
||||||
|
s_phases = s_phases.split(',')
|
||||||
|
else:
|
||||||
|
s_phases = []
|
||||||
|
|
||||||
|
phases = {'P': p_phases,
|
||||||
|
'S': s_phases}
|
||||||
|
if not 'P' in phases['P'] and not 'p' in phases['P']:
|
||||||
|
phases['P'] = ['P'] + phases['P']
|
||||||
|
if not 'S' in phases['S'] and not 's' in phases['S']:
|
||||||
|
phases['S'] = ['S'] + phases['S']
|
||||||
|
|
||||||
|
picksMenu = menuBar.addMenu('Picks')
|
||||||
|
self.picksActions = {}
|
||||||
|
|
||||||
|
# dictionary points on corresponding phase_select function
|
||||||
|
phaseSelect = {'P': self.p_phase_select,
|
||||||
|
'S': self.s_phase_select}
|
||||||
|
|
||||||
|
nHotkey = 4 # max hotkeys per phase
|
||||||
|
hotkey = 1 # start hotkey
|
||||||
|
|
||||||
|
# loop over P and S (use explicit list instead of iter over dict.keys to keep order)
|
||||||
|
for phaseIndex, phaseID in enumerate(['P', 'S']):
|
||||||
|
# loop through phases in list
|
||||||
|
for index, phase in enumerate(phases[phaseID]):
|
||||||
|
# remove zeros
|
||||||
|
phase = phase.strip()
|
||||||
|
# add hotkeys
|
||||||
|
if not index >= nHotkey:
|
||||||
|
shortcut = str(hotkey)
|
||||||
|
hotkey += 1
|
||||||
|
else:
|
||||||
|
shortcut = None
|
||||||
|
# create action and add to menu
|
||||||
|
# phase name transferred using lambda function
|
||||||
|
slot = lambda phase=phase, phaseID=phaseID: phaseSelect[phaseID](phase)
|
||||||
|
picksAction = createAction(parent=self, text=phase,
|
||||||
|
slot=slot,
|
||||||
|
shortcut=shortcut)
|
||||||
|
picksMenu.addAction(picksAction)
|
||||||
|
self.picksActions[str(phase)] = picksAction # save action in dictionary
|
||||||
|
if phaseIndex == 0:
|
||||||
|
picksMenu.addSeparator()
|
||||||
|
|
||||||
def disconnectPressEvent(self):
|
def disconnectPressEvent(self):
|
||||||
widget = self.getPlotWidget()
|
widget = self.getPlotWidget()
|
||||||
widget.mpl_disconnect(self.cidpress)
|
widget.mpl_disconnect(self.cidpress)
|
||||||
@ -953,8 +1021,31 @@ class PickDlg(QDialog):
|
|||||||
self.accept_button.setEnabled(bool)
|
self.accept_button.setEnabled(bool)
|
||||||
self.reject_button.setEnabled(bool)
|
self.reject_button.setEnabled(bool)
|
||||||
|
|
||||||
|
def p_phase_select(self, phase):
|
||||||
|
if not self.p_button.isChecked():
|
||||||
|
self.p_button.setChecked(True)
|
||||||
|
self.p_button.setText(phase)
|
||||||
|
else:
|
||||||
|
if str(phase) == str(self.p_button.text()):
|
||||||
|
self.reset_p_button()
|
||||||
|
else:
|
||||||
|
self.p_button.setText(phase)
|
||||||
|
self.p_clicked()
|
||||||
|
|
||||||
|
def s_phase_select(self, phase):
|
||||||
|
if not self.s_button.isChecked():
|
||||||
|
self.s_button.setChecked(True)
|
||||||
|
self.s_button.setText(phase)
|
||||||
|
else:
|
||||||
|
if str(phase) == str(self.s_button.text()):
|
||||||
|
self.reset_s_button()
|
||||||
|
else:
|
||||||
|
self.s_button.setText(phase)
|
||||||
|
self.s_clicked()
|
||||||
|
|
||||||
def p_clicked(self):
|
def p_clicked(self):
|
||||||
if self.p_button.isChecked():
|
if self.p_button.isChecked():
|
||||||
|
self.reset_s_button()
|
||||||
self.s_button.setEnabled(False)
|
self.s_button.setEnabled(False)
|
||||||
self.init_p_pick()
|
self.init_p_pick()
|
||||||
else:
|
else:
|
||||||
@ -962,6 +1053,7 @@ class PickDlg(QDialog):
|
|||||||
|
|
||||||
def s_clicked(self):
|
def s_clicked(self):
|
||||||
if self.s_button.isChecked():
|
if self.s_button.isChecked():
|
||||||
|
self.reset_p_button()
|
||||||
self.p_button.setEnabled(False)
|
self.p_button.setEnabled(False)
|
||||||
self.init_s_pick()
|
self.init_s_pick()
|
||||||
else:
|
else:
|
||||||
@ -971,13 +1063,13 @@ class PickDlg(QDialog):
|
|||||||
self.set_button_color(self.p_button, 'yellow')
|
self.set_button_color(self.p_button, 'yellow')
|
||||||
self.updateCurrentLimits()
|
self.updateCurrentLimits()
|
||||||
self.activatePicking()
|
self.activatePicking()
|
||||||
self.currentPhase = 'P'
|
self.currentPhase = str(self.p_button.text())
|
||||||
|
|
||||||
def init_s_pick(self):
|
def init_s_pick(self):
|
||||||
self.set_button_color(self.s_button, 'yellow')
|
self.set_button_color(self.s_button, 'yellow')
|
||||||
self.updateCurrentLimits()
|
self.updateCurrentLimits()
|
||||||
self.activatePicking()
|
self.activatePicking()
|
||||||
self.currentPhase = 'S'
|
self.currentPhase = str(self.s_button.text())
|
||||||
|
|
||||||
def set_button_color(self, button, color = None):
|
def set_button_color(self, button, color = None):
|
||||||
if type(color) == QtGui.QColor:
|
if type(color) == QtGui.QColor:
|
||||||
@ -989,14 +1081,22 @@ class PickDlg(QDialog):
|
|||||||
elif type(color) == str or not color:
|
elif type(color) == str or not color:
|
||||||
button.setStyleSheet("background-color: {}".format(color))
|
button.setStyleSheet("background-color: {}".format(color))
|
||||||
|
|
||||||
|
def reset_p_button(self):
|
||||||
|
self.set_button_color(self.p_button)
|
||||||
|
self.p_button.setEnabled(True)
|
||||||
|
self.p_button.setChecked(False)
|
||||||
|
self.p_button.setText('P')
|
||||||
|
|
||||||
|
def reset_s_button(self):
|
||||||
|
self.set_button_color(self.s_button)
|
||||||
|
self.s_button.setEnabled(True)
|
||||||
|
self.s_button.setChecked(False)
|
||||||
|
self.s_button.setText('S')
|
||||||
|
|
||||||
def leave_picking_mode(self):
|
def leave_picking_mode(self):
|
||||||
self.currentPhase = None
|
self.currentPhase = None
|
||||||
self.set_button_color(self.p_button)
|
self.reset_p_button()
|
||||||
self.set_button_color(self.s_button)
|
self.reset_s_button()
|
||||||
self.p_button.setEnabled(True)
|
|
||||||
self.s_button.setEnabled(True)
|
|
||||||
self.p_button.setChecked(False)
|
|
||||||
self.s_button.setChecked(False)
|
|
||||||
self.getPlotWidget().plotWFData(wfdata=self.getWFData(),
|
self.getPlotWidget().plotWFData(wfdata=self.getWFData(),
|
||||||
title=self.getStation())
|
title=self.getStation())
|
||||||
self.drawAllPicks()
|
self.drawAllPicks()
|
||||||
@ -1035,6 +1135,8 @@ class PickDlg(QDialog):
|
|||||||
return self.components
|
return self.components
|
||||||
|
|
||||||
def getStation(self):
|
def getStation(self):
|
||||||
|
if self.network and self.station:
|
||||||
|
return self.network+'.'+self.station
|
||||||
return self.station
|
return self.station
|
||||||
|
|
||||||
def getPlotWidget(self):
|
def getPlotWidget(self):
|
||||||
@ -1057,7 +1159,7 @@ class PickDlg(QDialog):
|
|||||||
return self._user
|
return self._user
|
||||||
|
|
||||||
def getFilterOptions(self, phase):
|
def getFilterOptions(self, phase):
|
||||||
options = self.filteroptions[phase]
|
options = self.filteroptions[phase[0]]
|
||||||
return FilterOptions(**options)
|
return FilterOptions(**options)
|
||||||
|
|
||||||
def getXLims(self):
|
def getXLims(self):
|
||||||
@ -1132,11 +1234,10 @@ class PickDlg(QDialog):
|
|||||||
self.disconnectMotionEvent()
|
self.disconnectMotionEvent()
|
||||||
self.cidpress = self.connectPressEvent(self.setPick)
|
self.cidpress = self.connectPressEvent(self.setPick)
|
||||||
|
|
||||||
print(self.currentPhase)
|
if self.currentPhase.startswith('P'):
|
||||||
if self.currentPhase == 'P':
|
|
||||||
self.set_button_color(self.p_button, 'green')
|
self.set_button_color(self.p_button, 'green')
|
||||||
self.setIniPickP(gui_event, wfdata, trace_number)
|
self.setIniPickP(gui_event, wfdata, trace_number)
|
||||||
elif self.currentPhase == 'S':
|
elif self.currentPhase.startswith('S'):
|
||||||
self.set_button_color(self.s_button, 'green')
|
self.set_button_color(self.s_button, 'green')
|
||||||
self.setIniPickS(gui_event, wfdata)
|
self.setIniPickS(gui_event, wfdata)
|
||||||
|
|
||||||
@ -1169,7 +1270,7 @@ class PickDlg(QDialog):
|
|||||||
|
|
||||||
# filter data and trace on which is picked prior to determination of SNR
|
# filter data and trace on which is picked prior to determination of SNR
|
||||||
phase = self.currentPhase
|
phase = self.currentPhase
|
||||||
filteroptions = self.getFilterOptions(phase).parseFilterOptions()
|
filteroptions = self.getFilterOptions(phase[0]).parseFilterOptions()
|
||||||
if filteroptions:
|
if filteroptions:
|
||||||
data.filter(**filteroptions)
|
data.filter(**filteroptions)
|
||||||
wfdata.filter(**filteroptions)
|
wfdata.filter(**filteroptions)
|
||||||
@ -1360,9 +1461,11 @@ class PickDlg(QDialog):
|
|||||||
'S': ('m', 'm--', 'r-', 'rv', 'r^', 'r', 'm:')
|
'S': ('m', 'm--', 'r-', 'rv', 'r^', 'r', 'm:')
|
||||||
}
|
}
|
||||||
if self.getPicks(picktype):
|
if self.getPicks(picktype):
|
||||||
if phase is not None and type(self.getPicks(picktype)[phase]) is dict:
|
if phase is not None:
|
||||||
picks = self.getPicks(picktype)[phase]
|
if (type(self.getPicks(picktype)[phase]) is dict
|
||||||
colors = phase_col[phase[0].upper()]
|
or type(self.getPicks(picktype)[phase]) is AttribDict):
|
||||||
|
picks = self.getPicks(picktype)[phase]
|
||||||
|
colors = phase_col[phase[0].upper()]
|
||||||
elif phase is None:
|
elif phase is None:
|
||||||
for phase in self.getPicks(picktype):
|
for phase in self.getPicks(picktype):
|
||||||
self.drawPicks(phase, picktype)
|
self.drawPicks(phase, picktype)
|
||||||
@ -1388,6 +1491,7 @@ class PickDlg(QDialog):
|
|||||||
ax.plot([mpp, mpp], ylims, colors[2], label='{}-Pick'.format(phase))
|
ax.plot([mpp, mpp], ylims, colors[2], label='{}-Pick'.format(phase))
|
||||||
else:
|
else:
|
||||||
ax.plot([mpp, mpp], ylims, colors[6], label='{}-Pick (NO PICKERROR)'.format(phase))
|
ax.plot([mpp, mpp], ylims, colors[6], label='{}-Pick (NO PICKERROR)'.format(phase))
|
||||||
|
ax.text(mpp, ylims[1], phase)
|
||||||
|
|
||||||
elif picktype == 'auto':
|
elif picktype == 'auto':
|
||||||
ax.plot(mpp, ylims[1], colors[3],
|
ax.plot(mpp, ylims[1], colors[3],
|
||||||
@ -1646,7 +1750,7 @@ class TuneAutopicker(QWidget):
|
|||||||
model = self.stationBox.model()
|
model = self.stationBox.model()
|
||||||
for network, station in stations:
|
for network, station in stations:
|
||||||
item = QtGui.QStandardItem(network+'.'+station)
|
item = QtGui.QStandardItem(network+'.'+station)
|
||||||
if station in self.get_current_event().picks:
|
if station in self.get_current_event().pylot_picks:
|
||||||
item.setBackground(self.parent._colors['ref'])
|
item.setBackground(self.parent._colors['ref'])
|
||||||
model.appendRow(item)
|
model.appendRow(item)
|
||||||
|
|
||||||
@ -1687,8 +1791,8 @@ class TuneAutopicker(QWidget):
|
|||||||
self.listWidget.scrollToBottom()
|
self.listWidget.scrollToBottom()
|
||||||
|
|
||||||
def get_current_event(self):
|
def get_current_event(self):
|
||||||
index = self.eventBox.currentIndex()
|
path = self.eventBox.currentText()
|
||||||
return self.eventBox.itemData(index)
|
return self.parent.project.getEventFromPath(path)
|
||||||
|
|
||||||
def get_current_event_name(self):
|
def get_current_event_name(self):
|
||||||
return self.eventBox.currentText().split('/')[-1]
|
return self.eventBox.currentText().split('/')[-1]
|
||||||
@ -1698,13 +1802,13 @@ class TuneAutopicker(QWidget):
|
|||||||
|
|
||||||
def get_current_event_picks(self, station):
|
def get_current_event_picks(self, station):
|
||||||
event = self.get_current_event()
|
event = self.get_current_event()
|
||||||
if station in event.picks.keys():
|
if station in event.pylot_picks.keys():
|
||||||
return event.picks[station]
|
return event.pylot_picks[station]
|
||||||
|
|
||||||
def get_current_event_autopicks(self, station):
|
def get_current_event_autopicks(self, station):
|
||||||
event = self.get_current_event()
|
event = self.get_current_event()
|
||||||
if event.autopicks:
|
if event.pylot_autopicks:
|
||||||
return event.autopicks[station]
|
return event.pylot_autopicks[station]
|
||||||
|
|
||||||
def get_current_station(self):
|
def get_current_station(self):
|
||||||
return str(self.stationBox.currentText()).split('.')[-1]
|
return str(self.stationBox.currentText()).split('.')[-1]
|
||||||
@ -1855,6 +1959,9 @@ class TuneAutopicker(QWidget):
|
|||||||
self.init_tab_names()
|
self.init_tab_names()
|
||||||
|
|
||||||
def fill_eventbox(self):
|
def fill_eventbox(self):
|
||||||
|
project = self.parent.project
|
||||||
|
if not project:
|
||||||
|
return
|
||||||
# update own list
|
# update own list
|
||||||
self.parent.fill_eventbox(eventBox=self.eventBox, select_events='ref')
|
self.parent.fill_eventbox(eventBox=self.eventBox, select_events='ref')
|
||||||
index_start = self.parent.eventBox.currentIndex()
|
index_start = self.parent.eventBox.currentIndex()
|
||||||
@ -1862,11 +1969,15 @@ class TuneAutopicker(QWidget):
|
|||||||
if index == -1:
|
if index == -1:
|
||||||
index += 1
|
index += 1
|
||||||
nevents = self.eventBox.model().rowCount()
|
nevents = self.eventBox.model().rowCount()
|
||||||
if self.eventBox.itemData(index).isTestEvent():
|
path = self.eventBox.itemText(index)
|
||||||
|
if project.getEventFromPath(path).isTestEvent():
|
||||||
for index in range(nevents):
|
for index in range(nevents):
|
||||||
if not self.eventBox.itemData(index).isTestEvent():
|
path = self.eventBox.itemText(index)
|
||||||
break
|
if project.getEventFromPath(index):
|
||||||
elif index == nevents - 1:
|
if not project.getEventFromPath(index).isTestEvent():
|
||||||
|
break
|
||||||
|
#in case all events are marked as test events and last event is reached
|
||||||
|
if index == nevents - 1:
|
||||||
index = -1
|
index = -1
|
||||||
self.eventBox.setCurrentIndex(index)
|
self.eventBox.setCurrentIndex(index)
|
||||||
if not index == index_start:
|
if not index == index_start:
|
||||||
@ -1911,8 +2022,8 @@ class TuneAutopicker(QWidget):
|
|||||||
self._warn('Could not execute picker:\n{}'.format(
|
self._warn('Could not execute picker:\n{}'.format(
|
||||||
self.ap_thread._executedError))
|
self.ap_thread._executedError))
|
||||||
return
|
return
|
||||||
self.picks = self.ap_thread.data
|
self.pylot_picks = self.ap_thread.data
|
||||||
if not self.picks:
|
if not self.pylot_picks:
|
||||||
self._warn('No picks found. See terminal output.')
|
self._warn('No picks found. See terminal output.')
|
||||||
return
|
return
|
||||||
#renew tabs
|
#renew tabs
|
||||||
@ -2456,6 +2567,7 @@ class PropertiesDlg(QDialog):
|
|||||||
elif setting.startswith('Channel N'):
|
elif setting.startswith('Channel N'):
|
||||||
component = 'N'
|
component = 'N'
|
||||||
compclass.setCompPosition(value, component, False)
|
compclass.setCompPosition(value, component, False)
|
||||||
|
|
||||||
settings.sync()
|
settings.sync()
|
||||||
|
|
||||||
|
|
||||||
@ -2547,7 +2659,7 @@ class OutputsTab(PropTab):
|
|||||||
settings = QSettings()
|
settings = QSettings()
|
||||||
curval = settings.value("output/Format", None)
|
curval = settings.value("output/Format", None)
|
||||||
|
|
||||||
eventOutputLabel = QLabel("event ouput format")
|
eventOutputLabel = QLabel("event/picks output format")
|
||||||
self.eventOutputComboBox = QComboBox()
|
self.eventOutputComboBox = QComboBox()
|
||||||
eventoutputformats = OUTPUTFORMATS.keys()
|
eventoutputformats = OUTPUTFORMATS.keys()
|
||||||
self.eventOutputComboBox.addItems(eventoutputformats)
|
self.eventOutputComboBox.addItems(eventoutputformats)
|
||||||
@ -2569,11 +2681,43 @@ class OutputsTab(PropTab):
|
|||||||
values = {"output/Format": self.eventOutputComboBox.setCurrentIndex(1)}
|
values = {"output/Format": self.eventOutputComboBox.setCurrentIndex(1)}
|
||||||
return values
|
return values
|
||||||
|
|
||||||
|
|
||||||
class PhasesTab(PropTab):
|
class PhasesTab(PropTab):
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
super(PhasesTab, self).__init__(parent)
|
super(PhasesTab, self).__init__(parent)
|
||||||
|
|
||||||
pass
|
self.PphasesEdit = QLineEdit()
|
||||||
|
self.SphasesEdit = QLineEdit()
|
||||||
|
|
||||||
|
PphasesLabel = QLabel("P Phases to pick")
|
||||||
|
SphasesLabel = QLabel("S Phases to pick")
|
||||||
|
|
||||||
|
settings = QSettings()
|
||||||
|
Pphases = settings.value('p_phases')
|
||||||
|
Sphases = settings.value('s_phases')
|
||||||
|
|
||||||
|
self.PphasesEdit.setText("%s" % Pphases)
|
||||||
|
self.SphasesEdit.setText("%s" % Sphases)
|
||||||
|
|
||||||
|
layout = QGridLayout()
|
||||||
|
layout.addWidget(PphasesLabel, 0, 0)
|
||||||
|
layout.addWidget(SphasesLabel, 1, 0)
|
||||||
|
|
||||||
|
layout.addWidget(self.PphasesEdit, 0, 1)
|
||||||
|
layout.addWidget(self.SphasesEdit, 1, 1)
|
||||||
|
self.setLayout(layout)
|
||||||
|
|
||||||
|
def getValues(self):
|
||||||
|
values = {'p_phases': self.PphasesEdit.text(),
|
||||||
|
's_phases': self.SphasesEdit.text()}
|
||||||
|
return values
|
||||||
|
|
||||||
|
def resetValues(self, infile=None):
|
||||||
|
Pphases = 'P, Pg, Pn, PmP, P1, P2, P3'
|
||||||
|
Sphases = 'S, Sg, Sn, SmS, S1, S2, S3'
|
||||||
|
values = {'p_phases': self.PphasesEdit.setText(Pphases),
|
||||||
|
's_phases': self.SphasesEdit.setText(Sphases)}
|
||||||
|
return values
|
||||||
|
|
||||||
|
|
||||||
class GraphicsTab(PropTab):
|
class GraphicsTab(PropTab):
|
||||||
@ -2619,6 +2763,11 @@ class GraphicsTab(PropTab):
|
|||||||
'pyqtgraphic': self.checkbox_pg.isChecked()}
|
'pyqtgraphic': self.checkbox_pg.isChecked()}
|
||||||
return values
|
return values
|
||||||
|
|
||||||
|
def resetValues(self, infile=None):
|
||||||
|
values = {'nth_sample': self.spinbox_nth_sample.setValue(1),
|
||||||
|
'pyqtgraphic': self.checkbox_pg.setChecked(True)}
|
||||||
|
return values
|
||||||
|
|
||||||
|
|
||||||
class ChannelOrderTab(PropTab):
|
class ChannelOrderTab(PropTab):
|
||||||
def __init__(self, parent=None, infile=None):
|
def __init__(self, parent=None, infile=None):
|
||||||
|