[task] further steps to implement pick comparison from QtPyLoT

This commit is contained in:
Sebastian Wehling-Benatelli 2016-05-27 11:25:47 +02:00
parent a1d29a45cb
commit 618dd10c23
4 changed files with 167 additions and 79 deletions

View File

@ -23,11 +23,10 @@ https://www.iconfinder.com/iconsets/flavour
(http://www.gnu.org/copyleft/lesser.html) (http://www.gnu.org/copyleft/lesser.html)
""" """
import matplotlib
import os import os
import sys import sys
import matplotlib
matplotlib.use('Qt4Agg') matplotlib.use('Qt4Agg')
matplotlib.rcParams['backend.qt4'] = 'PySide' matplotlib.rcParams['backend.qt4'] = 'PySide'
@ -50,7 +49,7 @@ from pylot.core.util.defaults import FILTERDEFAULTS, COMPNAME_MAP,\
from pylot.core.util.errors import FormatError, DatastructureError, \ from pylot.core.util.errors import FormatError, DatastructureError, \
OverwriteError OverwriteError
from pylot.core.util.connection import checkurl from pylot.core.util.connection import checkurl
from pylot.core.util.utils import fnConstructor, createEvent, getLogin, \ from pylot.core.util.utils import fnConstructor, getLogin, \
getGlobalTimes getGlobalTimes
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, \
@ -81,8 +80,8 @@ class MainWindow(QMainWindow):
"Enter authority name (e.g. BUG):", "Enter authority name (e.g. BUG):",
"Authority") "Authority")
settings.setValue("agency_id", agency) settings.setValue("agency_id", agency)
self.recentEvents = settings.value("data/recentEvents", []) self.recentfiles = settings.value("data/recentEvents", [])
self.fname = None self.fname = dict(manual=None, auto=None, loc=None)
self.fnames = None self.fnames = None
structure_setting = settings.value("data/Structure", "PILOT") structure_setting = settings.value("data/Structure", "PILOT")
self.dataStructure = DATASTRUCTURE[structure_setting]() self.dataStructure = DATASTRUCTURE[structure_setting]()
@ -104,7 +103,7 @@ class MainWindow(QMainWindow):
self.setupUi() self.setupUi()
# initialize event data # initialize event data
if self.recentEvents: if self.recentfiles:
lastEvent = self.getLastEvent() lastEvent = self.getLastEvent()
self.data = Data(self, lastEvent) self.data = Data(self, lastEvent)
else: else:
@ -112,7 +111,7 @@ class MainWindow(QMainWindow):
# load and display waveform data # load and display waveform data
self.dirty = False self.dirty = False
self.loadData() self.load_data()
if self.loadWaveformData(): if self.loadWaveformData():
self.updateFilterOptions() self.updateFilterOptions()
else: else:
@ -149,7 +148,10 @@ class MainWindow(QMainWindow):
lambda event: self.tutorUser()) lambda event: self.tutorUser())
_layout.addWidget(self.DataPlot) _layout.addWidget(self.DataPlot)
openIcon = self.style().standardIcon(QStyle.SP_DirOpenIcon) manupicksicon = self.style().standardIcon(QStyle.SP_DialogYesButton)
autopicksicon = self.style().standardIcon(QStyle.SP_DialogNoButton)
locactionicon = self.style().standardIcon(QStyle.SP_DirOpenIcon)
loadpiloticon = self.style().standardIcon(QStyle.SP_ComputerIcon)
quitIcon = self.style().standardIcon(QStyle.SP_MediaStop) quitIcon = self.style().standardIcon(QStyle.SP_MediaStop)
saveIcon = self.style().standardIcon(QStyle.SP_DriveHDIcon) saveIcon = self.style().standardIcon(QStyle.SP_DriveHDIcon)
helpIcon = self.style().standardIcon(QStyle.SP_DialogHelpButton) helpIcon = self.style().standardIcon(QStyle.SP_DialogHelpButton)
@ -179,18 +181,40 @@ class MainWindow(QMainWindow):
self.createNewEvent, self.createNewEvent,
QKeySequence.New, newIcon, QKeySequence.New, newIcon,
"Create a new event.") "Create a new event.")
openEventAction = self.createAction(self, "&Open event ...", openmanualpicksaction = self.createAction(self, "Load &picks ...",
self.loadData, QKeySequence.Open, self.load_data,
openIcon, "Open an event.") QKeySequence.Open,
openEventAction.setData(None) manupicksicon,
"Load pick data for "
"the actual event.")
openmanualpicksaction.setData(None)
openautopicksaction = self.createAction(self, "Load &automatic picks "
"...",
self.load_autopicks,
"Ctrl+A",
autopicksicon,
"Load automatic pick data "
"for the actual event.")
openautopicksaction.setData(None)
loadlocationaction = self.createAction(self, "Load &location ...",
self.load_loc, "Ctrl+L",
locactionicon,
"Load location information on "
"the actual event.")
loadpilotevent = self.createAction(self, "Load PILOT &event ...",
self.load_pilot, "Ctrl+E",
loadpiloticon,
"Load PILOT event from information "
"Matlab binary collections.")
saveEventAction = self.createAction(self, "&Save event ...", saveEventAction = self.createAction(self, "&Save event ...",
self.saveData, QKeySequence.Save, self.saveData, QKeySequence.Save,
saveIcon, "Save actual event data.") saveIcon, "Save actual event data.")
openWFDataAction = self.createAction(self, "Open &waveforms ...", openWFDataAction = self.createAction(self, "Open &waveforms ...",
self.loadWaveformData, self.loadWaveformData,
"Ctrl+W", QIcon(":/wfIcon.png"), "Ctrl+W", QIcon(":/wfIcon.png"),
"""Open waveform data (event will "Open waveform data (event will "
be closed).""") "be closed)")
prefsEventAction = self.createAction(self, "Preferences", prefsEventAction = self.createAction(self, "Preferences",
self.PyLoTprefs, self.PyLoTprefs,
QKeySequence.Preferences, QKeySequence.Preferences,
@ -228,7 +252,7 @@ class MainWindow(QMainWindow):
homepage (internet connection available), homepage (internet connection available),
or shipped documentation files.""") or shipped documentation files.""")
self.fileMenu = self.menuBar().addMenu('&File') self.fileMenu = self.menuBar().addMenu('&File')
self.fileMenuActions = (newEventAction, openEventAction, self.fileMenuActions = (newEventAction, openmanualpicksaction,
saveEventAction, openWFDataAction, None, saveEventAction, openWFDataAction, None,
prefsEventAction, quitAction) prefsEventAction, quitAction)
self.fileMenu.aboutToShow.connect(self.updateFileMenu) self.fileMenu.aboutToShow.connect(self.updateFileMenu)
@ -245,7 +269,9 @@ class MainWindow(QMainWindow):
self.addActions(self.helpMenu, helpActions) self.addActions(self.helpMenu, helpActions)
fileToolBar = self.addToolBar("FileTools") fileToolBar = self.addToolBar("FileTools")
fileToolActions = (newEventAction, openEventAction, saveEventAction) fileToolActions = (newEventAction, openmanualpicksaction,
openautopicksaction, loadlocationaction,
loadpilotevent, saveEventAction)
fileToolBar.setObjectName("FileTools") fileToolBar.setObjectName("FileTools")
self.addActions(fileToolBar, fileToolActions) self.addActions(fileToolBar, fileToolActions)
@ -299,8 +325,10 @@ class MainWindow(QMainWindow):
# self.addActions(pickToolBar, pickToolActions) # self.addActions(pickToolBar, pickToolActions)
locateEvent = self.createAction(parent=self, text='locateEvent', locateEvent = self.createAction(parent=self, text='locateEvent',
slot=self.locateEvent, shortcut='Alt+Ctrl+L', slot=self.locateEvent,
icon=locate_icon, tip='Locate the event using ' shortcut='Alt+Ctrl+L',
icon=locate_icon,
tip='Locate the event using '
'the picked arrivals.') 'the picked arrivals.')
locationToolBar = self.addToolBar("LocationTools") locationToolBar = self.addToolBar("LocationTools")
@ -333,12 +361,12 @@ class MainWindow(QMainWindow):
except AttributeError: except AttributeError:
current = None current = None
recentEvents = [] recentEvents = []
for eventID in self.recentEvents: for eventID in self.recentfiles:
fname = fnConstructor(eventID) fname = fnConstructor(eventID)
if eventID != current and QFile.exists(fname): if eventID != current and QFile.exists(fname):
recentEvents.append(eventID) recentEvents.append(eventID)
recentEvents.reverse() recentEvents.reverse()
self.recentEvents = recentEvents[0:5] self.recentfiles = recentEvents[0:5]
settings = QSettings() settings = QSettings()
settings.setValue() settings.setValue()
if recentEvents: if recentEvents:
@ -350,7 +378,7 @@ class MainWindow(QMainWindow):
self) self)
action.setData(fname) action.setData(fname)
self.connect(action, Signal("triggered()"), self.connect(action, Signal("triggered()"),
self.loadData) self.load_data)
self.fileMenu.addAction(action) self.fileMenu.addAction(action)
self.fileMenu.addSeparator() self.fileMenu.addSeparator()
self.fileMenu.addAction(self.fileMenuActions[-1]) self.fileMenu.addAction(self.fileMenuActions[-1])
@ -359,34 +387,49 @@ class MainWindow(QMainWindow):
settings = QSettings() settings = QSettings()
return settings.value("data/dataRoot") return settings.value("data/dataRoot")
def loadAutoPicks(self): def load_autopicks(self, fname=None):
self.loadData(type='auto') self.load_data(fname, type='auto')
def loadData(self, fname=None, type='manual'): def load_loc(self, fname=None):
self.load_data(fname, type='loc')
def load_pilotevent(self):
filt = "PILOT location files (*.mat)"
caption = "Select PILOT loaction file"
fn_loc = QFileDialog().getOpenFileName(self, caption=caption,
filter=filt)
filt = "PILOT phases files (*.mat)"
caption = "Select PILOT phases file"
fn_phases = QFileDialog().getOpenFileName(self, caption=caption,
filter=filt)
type = QInputDialog().getItem(self, self.tr("Select phases type"),
self.tr("Type:"), [self.tr("manual"),
self.tr("automatic")])
if type.startswith('auto'):
type = 'auto'
fname_dict = dict(phasfn=fn_phases, locfn=fn_loc)
self.load_data(fname_dict, type=type)
def load_data(self, fname=None, type='manual'):
if not self.okToContinue(): if not self.okToContinue():
return return
if fname is None: if fname is None:
action = self.sender() action = self.sender()
if isinstance(action, QAction): if isinstance(action, QAction):
if action.data() is None: fname = self.filename_from_action(action)
filt = "Supported event formats (*.mat *.qml *.xml *.kor *.evt)" self.set_fname(fname, type)
caption = "Open an event file" self.data += Data(self, evtdata=fname)
fname = QFileDialog().getOpenFileName(self, if 'loc' not in type:
caption=caption,
filter=filt)
fname = fname[0]
else:
fname = str(action.data().toString())
self.setFileName(fname)
self.data += Data(self, evtdata=self.getFileName())
self.updatePicks(type=type) self.updatePicks(type=type)
self.drawPicks() self.drawPicks()
def getLastEvent(self): def getLastEvent(self):
return self.recentEvents[0] return self.recentfiles[0]
def addRecentEvent(self, event): def add_recentfile(self, event):
self.recentEvents.insert(0, event) self.recentfiles.insert(0, event)
def getWFFnames(self): def getWFFnames(self):
try: try:
@ -422,27 +465,44 @@ class MainWindow(QMainWindow):
else: else:
return return
def getFileName(self): def filename_from_action(self, action):
if action.data() is None:
filt = "Supported file formats" \
" (*.mat *.qml *.xml *.kor *.evt)"
caption = "Open an event file"
fname = QFileDialog().getOpenFileName(self,
caption=caption,
filter=filt)
fname = fname[0]
else:
fname = str(action.data().toString())
return fname
def get_fnames(self):
return self.fname return self.fname
def setFileName(self, fname): def set_fname(self, fname, type):
if self.getFileName() is not None: if self.get_fnames()[type] is not None:
self.addRecentEvent(self.getFileName()) self.add_recentfile(self.get_fnames())
self.fname = fname self.fname[type] = fname
def getEventFileName(self): def getEventFileName(self):
if self.getFileName() is None: if self.get_fnames() is None:
self.setFileName(self.getData().getEventFileName()) self.set_fname(self.getData().getEventFileName())
return self.getFileName() return self.get_fnames()
def saveData(self): def saveData(self):
def getSavePath(e): def getSavePath(e):
print('warning: {0}'.format(e)) print('warning: {0}'.format(e))
directory = os.path.join(self.getRoot(), self.getEventFileName()) directory = os.path.join(self.getRoot(), self.getEventFileName())
file_filter = "QuakeML file (*.xml);;VELEST observation file format (*.cnv);;NonLinLoc observation file (*.obs)" file_filter = "QuakeML file (*.xml);;VELEST observation file " \
fname, selected_filter = QFileDialog.getSaveFileName(self, 'Save event data ...', "format (*.cnv);;NonLinLoc observation file (*.obs)"
directory, file_filter) title = 'Save event data ...'
fname, selected_filter = QFileDialog.getSaveFileName(self,
title,
directory,
file_filter)
fbasename, exform = os.path.splitext(fname) fbasename, exform = os.path.splitext(fname)
@ -459,7 +519,8 @@ class MainWindow(QMainWindow):
except OverwriteError: except OverwriteError:
msgBox = QMessageBox() msgBox = QMessageBox()
msgBox.setText("Picks have been modified!") msgBox.setText("Picks have been modified!")
msgBox.setInformativeText("Do you want to save the changes and overwrite the picks?") msgBox.setInformativeText(
"Do you want to save the changes and overwrite the picks?")
msgBox.setDetailedText(self.getData().getPicksStr()) msgBox.setDetailedText(self.getData().getPicksStr())
msgBox.setStandardButtons(QMessageBox.Save | QMessageBox.Cancel) msgBox.setStandardButtons(QMessageBox.Save | QMessageBox.Cancel)
msgBox.setDefaultButton(QMessageBox.Save) msgBox.setDefaultButton(QMessageBox.Save)
@ -689,7 +750,8 @@ class MainWindow(QMainWindow):
self.setDirty(True) self.setDirty(True)
self.logDockWidget = QDockWidget("AutoPickLog", self) self.logDockWidget = QDockWidget("AutoPickLog", self)
self.logDockWidget.setObjectName("LogDockWidget") self.logDockWidget.setObjectName("LogDockWidget")
self.logDockWidget.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea) self.logDockWidget.setAllowedAreas(
Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea)
self.logDockWidget.setWidget(self.listWidget) self.logDockWidget.setWidget(self.listWidget)
self.addDockWidget(Qt.LeftDockWidgetArea, self.logDockWidget) self.addDockWidget(Qt.LeftDockWidgetArea, self.logDockWidget)
self.addListItem('loading default values for local data ...') self.addListItem('loading default values for local data ...')
@ -754,8 +816,10 @@ class MainWindow(QMainWindow):
plotID = self.getStationID(station) plotID = self.getStationID(station)
ax = self.getPlotWidget().axes ax = self.getPlotWidget().axes
ylims = np.array([-.5, +.5]) + plotID ylims = np.array([-.5, +.5]) + plotID
phase_col = {'P': ('c', 'c--', 'b-', 'bv', 'b^'), phase_col = {
'S': ('m', 'm--', 'r-', 'rv', 'r^')} 'P': ('c', 'c--', 'b-', 'bv', 'b^'),
'S': ('m', 'm--', 'r-', 'rv', 'r^')
}
stat_picks = self.getPicks(type=picktype)[station] stat_picks = self.getPicks(type=picktype)[station]

View File

@ -1,17 +1,17 @@
#!/usr/bin/env python #!/usr/bin/env python
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import os
import glob import glob
import os
from obspy.io.xseed import Parser
from obspy.core import read, Stream, UTCDateTime
from obspy import read_events, read_inventory from obspy import read_events, read_inventory
from obspy.core.event import Event, ResourceIdentifier, Pick, WaveformStreamID from obspy.core import read, Stream, UTCDateTime
from obspy.core.event import Event
from obspy.io.xseed import Parser
from pylot.core.io.phases import readPILOTEvent, picks_from_picksdict from pylot.core.io.phases import readPILOTEvent, picks_from_picksdict, \
from pylot.core.util.utils import fnConstructor, getGlobalTimes picks_from_pilot
from pylot.core.util.errors import FormatError, OverwriteError from pylot.core.util.errors import FormatError, OverwriteError
from pylot.core.util.utils import fnConstructor, getGlobalTimes
class Data(object): class Data(object):
@ -36,17 +36,36 @@ class Data(object):
self.wfdata = Stream() self.wfdata = Stream()
self._new = False self._new = False
if isinstance(evtdata, Event): if isinstance(evtdata, Event):
self.evtdata = evtdata pass
elif isinstance(evtdata, dict): elif isinstance(evtdata, dict):
evt = readPILOTEvent(**evtdata) evt = readPILOTEvent(**evtdata)
self.evtdata = evt evtdata = evt
elif evtdata: elif isinstance(evtdata, str):
try:
cat = read_events(evtdata) cat = read_events(evtdata)
self.evtdata = cat[0] if len(cat) is not 1:
raise ValueError('ambiguous event information for file: '
'{file}'.format(file=evtdata))
evtdata = cat[0]
except TypeError as e:
if 'Unknown format for file' in e.message:
if 'PHASES' in evtdata:
picks = picks_from_pilot(evtdata)
evtdata = Event()
evtdata.picks = picks_from_picksdict(picks)
elif 'LOC' in evtdata:
raise NotImplementedError('PILOT location information '
'read support not yet '
'implemeted.')
else:
raise e
else:
raise e
else: # create an empty Event object else: # create an empty Event object
self.setNew() self.setNew()
self.evtdata = Event() evtdata = Event()
self.getEvtData().picks = [] evtdata.picks = []
self.evtdata = evtdata
self.wforiginal = None self.wforiginal = None
self.cuttimes = None self.cuttimes = None
self.dirty = False self.dirty = False

View File

@ -11,10 +11,10 @@ from obspy.core import UTCDateTime
from pylot.core.io.location import create_arrival, create_event, \ from pylot.core.io.location import create_arrival, create_event, \
create_magnitude, create_origin, create_pick create_magnitude, create_origin, create_pick
from pylot.core.pick.utils import select_for_phase from pylot.core.pick.utils import select_for_phase
from pylot.core.util.utils import getOwner, getGlobalTimes from pylot.core.util.utils import getOwner, getGlobalTimes, four_digits
def readPILOTEvent(phasfn=None, locfn=None, authority_id=None, **kwargs): def readPILOTEvent(phasfn=None, locfn=None, authority_id='RUB', **kwargs):
""" """
readPILOTEvent - function readPILOTEvent - function
@ -67,18 +67,15 @@ def readPILOTEvent(phasfn=None, locfn=None, authority_id=None, **kwargs):
minute = int(loc['mm']) minute = int(loc['mm'])
second = int(loc['ss']) second = int(loc['ss'])
if year + 2000 < UTCDateTime.utcnow().year: year = four_digits(year)
year += 2000
else:
year += 1900
eventDate = UTCDateTime(year=year, julday=julday, hour=hour, eventDate = UTCDateTime(year=year, julday=julday, hour=hour,
minute=minute, second=second) minute=minute, second=second)
stations = [stat for stat in phases['stat'][0:-1:3]] stations = [stat for stat in phases['stat'][0:-1:3]]
event = create_event(eventDate, loccinfo, etype='earthquake', resID=eventNum, event = create_event(eventDate, loccinfo, etype='earthquake',
authority_id=authority_id) resID=eventNum, authority_id=authority_id)
lat = float(loc['LAT']) lat = float(loc['LAT'])
lon = float(loc['LON']) lon = float(loc['LON'])
@ -123,13 +120,13 @@ def readPILOTEvent(phasfn=None, locfn=None, authority_id=None, **kwargs):
pickID = pick.get('id') pickID = pick.get('id')
arrival = create_arrival(pickID, pickcinfo, phase) arrival = create_arrival(pickID, pickcinfo, phase)
origin.arrivals.append(arrival) origin.arrivals.append(arrival)
event.picks.append(pick)
np += 1 np += 1
magnitude = create_magnitude(origin.get('id'), loccinfo) magnitude = create_magnitude(origin.get('id'), loccinfo)
magnitude.mag = float(loc['Mnet']) magnitude.mag = float(loc['Mnet'])
magnitude.magnitude_type = 'Ml' magnitude.magnitude_type = 'Ml'
event.picks.append(pick)
event.origins.append(origin) event.origins.append(origin)
event.magnitudes.append(magnitude) event.magnitudes.append(magnitude)
return event return event

View File

@ -93,6 +93,14 @@ def fnConstructor(s):
return fn return fn
def four_digits(year):
if year + 2000 < UTCDateTime.utcnow().year:
year += 2000
else:
year += 1900
return year
def getGlobalTimes(stream): def getGlobalTimes(stream):
''' '''