Merge branch 'export-and-save-picks' into develop
This commit is contained in:
commit
0b02e8c213
35
QtPyLoT.py
35
QtPyLoT.py
@ -23,7 +23,7 @@ https://www.iconfinder.com/iconsets/flavour
|
|||||||
(http://www.gnu.org/copyleft/lesser.html)
|
(http://www.gnu.org/copyleft/lesser.html)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import sys
|
import os, sys
|
||||||
import matplotlib
|
import matplotlib
|
||||||
|
|
||||||
matplotlib.use('Qt4Agg')
|
matplotlib.use('Qt4Agg')
|
||||||
@ -64,7 +64,6 @@ class MainWindow(QMainWindow):
|
|||||||
super(MainWindow, self).__init__(parent)
|
super(MainWindow, self).__init__(parent)
|
||||||
|
|
||||||
self.createAction = createAction
|
self.createAction = createAction
|
||||||
self.dirty = False
|
|
||||||
settings = QSettings()
|
settings = QSettings()
|
||||||
if settings.value("user/FullName", None) is None:
|
if settings.value("user/FullName", None) is None:
|
||||||
fulluser = QInputDialog.getText(self, "Enter Name:", "Full name")
|
fulluser = QInputDialog.getText(self, "Enter Name:", "Full name")
|
||||||
@ -102,8 +101,8 @@ class MainWindow(QMainWindow):
|
|||||||
self.data = Data(self)
|
self.data = Data(self)
|
||||||
|
|
||||||
# load and display waveform data
|
# load and display waveform data
|
||||||
self.loadWaveformData()
|
|
||||||
self.dirty = False
|
self.dirty = False
|
||||||
|
self.loadWaveformData()
|
||||||
self.loadData()
|
self.loadData()
|
||||||
self.updateFilterOptions()
|
self.updateFilterOptions()
|
||||||
|
|
||||||
@ -333,6 +332,10 @@ class MainWindow(QMainWindow):
|
|||||||
self.fileMenu.addSeparator()
|
self.fileMenu.addSeparator()
|
||||||
self.fileMenu.addAction(self.fileMenuActions[-1])
|
self.fileMenu.addAction(self.fileMenuActions[-1])
|
||||||
|
|
||||||
|
def getRoot(self):
|
||||||
|
settings = QSettings()
|
||||||
|
return settings.value("data/dataRoot")
|
||||||
|
|
||||||
def loadData(self, fname=None):
|
def loadData(self, fname=None):
|
||||||
if fname is None:
|
if fname is None:
|
||||||
try:
|
try:
|
||||||
@ -390,18 +393,27 @@ class MainWindow(QMainWindow):
|
|||||||
else:
|
else:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
def getEventFileName(self):
|
||||||
|
return self.getData().getEventFileName()
|
||||||
|
|
||||||
def saveData(self):
|
def saveData(self):
|
||||||
settings = QSettings()
|
settings = QSettings()
|
||||||
exform = settings.value('data/exportFormat', 'QUAKEML')
|
exform = settings.value('data/exportFormat', 'QUAKEML')
|
||||||
|
self.getData().applyEVTData(self.getPicks())
|
||||||
try:
|
try:
|
||||||
self.data.exportEvent(self.fname, exform)
|
self.getData().exportEvent(self.fname, exform)
|
||||||
except FormatError:
|
except FormatError:
|
||||||
return False
|
return False
|
||||||
except AttributeError, e:
|
except AttributeError, e:
|
||||||
print 'warning: {0}'.format(e)
|
print 'warning: {0}'.format(e)
|
||||||
fname = QFileDialog.getSaveFileName(self, 'Save event')
|
directory = os.path.join(self.getRoot(), self.getEventFileName())
|
||||||
fname = fname[0]
|
file_filter = "Seismic observation files (*.cnv *.obs *.xml)"
|
||||||
self.getData().exportEvent(fname, exform)
|
fname = QFileDialog.getSaveFileName(self, 'Save event data ...',
|
||||||
|
directory, file_filter)
|
||||||
|
fbasename, exform = os.path.splitext(fname[0])
|
||||||
|
if not fbasename:
|
||||||
|
return False
|
||||||
|
self.getData().exportEvent(fbasename, exform)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def getComponent(self):
|
def getComponent(self):
|
||||||
@ -455,7 +467,7 @@ class MainWindow(QMainWindow):
|
|||||||
|
|
||||||
def loadWaveformData(self):
|
def loadWaveformData(self):
|
||||||
if self.fnames and self.okToContinue():
|
if self.fnames and self.okToContinue():
|
||||||
self.dirty = True
|
self.setDirty(True)
|
||||||
self.data.setWFData(self.fnames)
|
self.data.setWFData(self.fnames)
|
||||||
elif self.fnames is None and self.okToContinue():
|
elif self.fnames is None and self.okToContinue():
|
||||||
self.data.setWFData(self.getWFFnames())
|
self.data.setWFData(self.getWFFnames())
|
||||||
@ -585,6 +597,7 @@ class MainWindow(QMainWindow):
|
|||||||
station=station,
|
station=station,
|
||||||
picks=self.getPicksOnStation(station))
|
picks=self.getPicksOnStation(station))
|
||||||
if pickDlg.exec_():
|
if pickDlg.exec_():
|
||||||
|
self.setDirty(True)
|
||||||
self.updateStatus('picks accepted ({0})'.format(station))
|
self.updateStatus('picks accepted ({0})'.format(station))
|
||||||
self.addPicks(station, pickDlg.getPicks())
|
self.addPicks(station, pickDlg.getPicks())
|
||||||
self.drawPicks(station)
|
self.drawPicks(station)
|
||||||
@ -593,6 +606,7 @@ class MainWindow(QMainWindow):
|
|||||||
|
|
||||||
def autoPick(self):
|
def autoPick(self):
|
||||||
list = QListWidget()
|
list = QListWidget()
|
||||||
|
self.setDirty(True)
|
||||||
logDockWidget = QDockWidget("AutoPickLog", self)
|
logDockWidget = QDockWidget("AutoPickLog", self)
|
||||||
logDockWidget.setObjectName("LogDockWidget")
|
logDockWidget.setObjectName("LogDockWidget")
|
||||||
logDockWidget.setAllowedAreas(Qt.LeftDockWidgetArea)
|
logDockWidget.setAllowedAreas(Qt.LeftDockWidgetArea)
|
||||||
@ -700,11 +714,14 @@ class MainWindow(QMainWindow):
|
|||||||
cinfo = createCreationInfo(agency_id=self.agency)
|
cinfo = createCreationInfo(agency_id=self.agency)
|
||||||
event = createEvent(evtpar['origintime'], cinfo)
|
event = createEvent(evtpar['origintime'], cinfo)
|
||||||
self.data = Data(self, evtdata=event)
|
self.data = Data(self, evtdata=event)
|
||||||
self.dirty = True
|
self.setDirty(True)
|
||||||
|
|
||||||
def draw(self):
|
def draw(self):
|
||||||
self.getPlotWidget().draw()
|
self.getPlotWidget().draw()
|
||||||
|
|
||||||
|
def setDirty(self, value):
|
||||||
|
self.dirty = value
|
||||||
|
|
||||||
def closeEvent(self, event):
|
def closeEvent(self, event):
|
||||||
if self.okToContinue():
|
if self.okToContinue():
|
||||||
self.closing.emit()
|
self.closing.emit()
|
||||||
|
@ -3,9 +3,9 @@
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from obspy.core import (read, Stream, UTCDateTime)
|
from obspy.core import read, Stream, UTCDateTime
|
||||||
from obspy import readEvents, read_inventory
|
from obspy import readEvents, read_inventory
|
||||||
from obspy.core.event import (Event, Catalog)
|
from obspy.core.event import Event, ResourceIdentifier, Pick, WaveformStreamID
|
||||||
|
|
||||||
from pylot.core.read.io import readPILOTEvent
|
from pylot.core.read.io import readPILOTEvent
|
||||||
from pylot.core.util.utils import fnConstructor, getGlobalTimes
|
from pylot.core.util.utils import fnConstructor, getGlobalTimes
|
||||||
@ -46,6 +46,7 @@ class Data(object):
|
|||||||
else: # create an empty Event object
|
else: # create an empty Event object
|
||||||
self.newevent = True
|
self.newevent = True
|
||||||
self.evtdata = Event()
|
self.evtdata = Event()
|
||||||
|
self.getEvtData().picks = []
|
||||||
self.wforiginal = None
|
self.wforiginal = None
|
||||||
self.cuttimes = None
|
self.cuttimes = None
|
||||||
self.dirty = False
|
self.dirty = False
|
||||||
@ -67,29 +68,25 @@ class Data(object):
|
|||||||
def updateCutTimes(self):
|
def updateCutTimes(self):
|
||||||
self.cuttimes = getGlobalTimes(self.getWFData())
|
self.cuttimes = getGlobalTimes(self.getWFData())
|
||||||
|
|
||||||
def exportEvent(self, fnout=None, evtformat='QUAKEML'):
|
def getEventFileName(self):
|
||||||
|
ID = self.getID()
|
||||||
|
# handle forbidden filenames especially on windows systems
|
||||||
|
return fnConstructor(str(ID))
|
||||||
|
|
||||||
|
def exportEvent(self, fnout, fnext='.xml'):
|
||||||
|
|
||||||
from pylot.core.util.defaults import OUTPUTFORMATS
|
from pylot.core.util.defaults import OUTPUTFORMATS
|
||||||
|
|
||||||
if evtformat.strip() not in OUTPUTFORMATS.values():
|
try:
|
||||||
errmsg = 'selected format {0} not available'.format(evtformat)
|
evtformat = OUTPUTFORMATS[fnext]
|
||||||
|
except KeyError, e:
|
||||||
|
errmsg = '{0}; selected file extension {1} not ' \
|
||||||
|
'supported'.format(e, fnext)
|
||||||
raise FormatError(errmsg)
|
raise FormatError(errmsg)
|
||||||
|
|
||||||
if fnout is None:
|
|
||||||
ID = self.getID()
|
|
||||||
# handle forbidden filenames especially on windows systems
|
|
||||||
fnout = fnConstructor(str(ID))
|
|
||||||
else:
|
|
||||||
fnout = fnConstructor(str(fnout))
|
|
||||||
|
|
||||||
evtformat = evtformat.upper().strip()
|
|
||||||
|
|
||||||
# establish catalog object (event object has no write method)
|
|
||||||
cat = Catalog()
|
|
||||||
cat.append(self.getEvtData())
|
|
||||||
# try exporting event via ObsPy
|
# try exporting event via ObsPy
|
||||||
try:
|
try:
|
||||||
cat.write(fnout + evtformat.lower(), format=evtformat)
|
self.getEvtData().write(fnout + fnext, format=evtformat)
|
||||||
except KeyError, e:
|
except KeyError, e:
|
||||||
raise KeyError('''{0} export format
|
raise KeyError('''{0} export format
|
||||||
not implemented: {1}'''.format(evtformat, e))
|
not implemented: {1}'''.format(evtformat, e))
|
||||||
@ -156,12 +153,41 @@ class Data(object):
|
|||||||
def getEvtData(self):
|
def getEvtData(self):
|
||||||
return self.evtdata
|
return self.evtdata
|
||||||
|
|
||||||
def applyEVTData(self, data, type='pick'):
|
def applyEVTData(self, data, type='pick', authority_id='rub'):
|
||||||
|
|
||||||
def applyPicks(picks):
|
def applyPicks(picks):
|
||||||
pass
|
firstonset = None
|
||||||
|
for station, onsets in picks.items():
|
||||||
|
print 'Reading picks on station %s' % station
|
||||||
|
for label, phase in onsets.items():
|
||||||
|
onset = phase['mpp']
|
||||||
|
epp = phase['epp']
|
||||||
|
lpp = phase['lpp']
|
||||||
|
error = phase['spe']
|
||||||
|
pick = Pick()
|
||||||
|
pick.time = onset
|
||||||
|
pick.time_errors.lower_uncertainty = onset - epp
|
||||||
|
pick.time_errors.upper_uncertainty = lpp - onset
|
||||||
|
pick.time_errors.uncertainty = error
|
||||||
|
pick.phase_hint = label
|
||||||
|
pick.waveform_id = WaveformStreamID(station_code=station)
|
||||||
|
self.getEvtData().picks.append(pick)
|
||||||
|
try:
|
||||||
|
polarity = phase['fm']
|
||||||
|
except KeyError, e:
|
||||||
|
print 'No polarity information found for %s' % phase
|
||||||
|
if firstonset is None or firstonset > onset:
|
||||||
|
firstonset = onset
|
||||||
|
|
||||||
|
if 'smi:local' in self.getID():
|
||||||
|
fonset_str = firstonset.strftime('%Y_%m_%d_%H_%M_%S')
|
||||||
|
ID = ResourceIdentifier('event/' + fonset_str)
|
||||||
|
ID.convertIDToQuakeMLURI(authority_id=authority_id)
|
||||||
|
self.getEvtData().resource_id = ID
|
||||||
|
|
||||||
def applyArrivals(arrivals):
|
def applyArrivals(arrivals):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def applyEvent(event):
|
def applyEvent(event):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@ -171,6 +197,7 @@ class Data(object):
|
|||||||
|
|
||||||
applydata[type](data)
|
applydata[type](data)
|
||||||
|
|
||||||
|
|
||||||
class GenericDataStructure(object):
|
class GenericDataStructure(object):
|
||||||
'''
|
'''
|
||||||
GenericDataBase type holds all information about the current data-
|
GenericDataBase type holds all information about the current data-
|
||||||
@ -280,7 +307,6 @@ class PilotDataStructure(GenericDataStructure):
|
|||||||
'''
|
'''
|
||||||
|
|
||||||
def __init__(self, **fields):
|
def __init__(self, **fields):
|
||||||
|
|
||||||
if not fields:
|
if not fields:
|
||||||
fields = {'database': '2006.01',
|
fields = {'database': '2006.01',
|
||||||
'root': '/data/Egelados/EVENT_DATA/LOCAL'}
|
'root': '/data/Egelados/EVENT_DATA/LOCAL'}
|
||||||
@ -304,7 +330,6 @@ class SeiscompDataStructure(GenericDataStructure):
|
|||||||
filesuffix=None, **kwargs):
|
filesuffix=None, **kwargs):
|
||||||
super(GenericDataStructure, self).__init__()
|
super(GenericDataStructure, self).__init__()
|
||||||
|
|
||||||
|
|
||||||
edate = UTCDateTime()
|
edate = UTCDateTime()
|
||||||
halfyear = UTCDateTime('1970-07-01')
|
halfyear = UTCDateTime('1970-07-01')
|
||||||
sdate = UTCDateTime(edate - halfyear)
|
sdate = UTCDateTime(edate - halfyear)
|
||||||
|
@ -13,6 +13,6 @@ FILTERDEFAULTS = {'P': {'filtertype': None,
|
|||||||
'order': 4,
|
'order': 4,
|
||||||
'freq': [.5, 5]}}
|
'freq': [.5, 5]}}
|
||||||
|
|
||||||
OUTPUTFORMATS = {'QuakeML':'QUAKEML',
|
OUTPUTFORMATS = {'.xml':'QUAKEML',
|
||||||
'VelEst':'CNV',
|
'.cnv':'CNV',
|
||||||
'NonLinLoc':'NLLOC_OBS'}
|
'.obs':'NLLOC_OBS'}
|
||||||
|
Loading…
Reference in New Issue
Block a user