Merge branch 'develop' of ariadne.geophysik.rub.de:/data/git/pylot into develop

This commit is contained in:
Ludger Küperkoch
2015-08-31 09:02:16 +02:00
4 changed files with 301 additions and 84 deletions

View File

@@ -1 +1 @@
1abc-dirty
497c-dirty

View File

@@ -3,7 +3,6 @@
import os
import glob
import matplotlib.pyplot as plt
from obspy.xseed import Parser
from obspy.core import read, Stream, UTCDateTime
from obspy import readEvents, read_inventory
@@ -11,24 +10,21 @@ from obspy.core.event import Event, ResourceIdentifier, Pick, WaveformStreamID
from pylot.core.read.io import readPILOTEvent
from pylot.core.util.utils import fnConstructor, getGlobalTimes
from pylot.core.util.errors import FormatError
from pylot.core.util.errors import FormatError, OverwriteError
class Data(object):
'''
"""
Data container with attributes wfdata holding ~obspy.core.stream.
:type parent: PySide.QtGui.QWidget object, optional
:param parent: A PySide.QtGui.QWidget object utilized when
called by a GUI to display a PySide.QtGui.QMessageBox instead of printing
to standard out.
:type wfdata: ~obspy.core.stream.Stream object, optional
:param wfdata: ~obspy.core.stream.Stream object containing all available
waveform data for the actual event
:type evtdata: ~obspy.core.event.Event object, optional
:param evtdata ~obspy.core.event.Event object containing all derived or
loaded event. Container object holding, e.g. phase arrivals, etc.
'''
"""
def __init__(self, parent=None, evtdata=None):
self._parent = parent
@@ -56,32 +52,69 @@ class Data(object):
def __str__(self):
return str(self.wfdata)
def getPicksStr(self):
picks_str = ''
for pick in self.getEvtData().picks:
picks_str += str(pick) + '\n'
return picks_str
def getParent(self):
"""
:return:
"""
return self._parent
def isNew(self):
"""
:return:
"""
return self.newevent
def getCutTimes(self):
"""
:return:
"""
if self.cuttimes is None:
self.updateCutTimes()
return self.cuttimes
def updateCutTimes(self):
"""
"""
self.cuttimes = getGlobalTimes(self.getWFData())
def getEventFileName(self):
"""
:return:
"""
ID = self.getID()
# handle forbidden filenames especially on windows systems
return fnConstructor(str(ID))
def exportEvent(self, fnout, fnext='.xml'):
"""
:param fnout:
:param fnext:
:raise KeyError:
"""
from pylot.core.util.defaults import OUTPUTFORMATS
try:
evtformat = OUTPUTFORMATS[fnext]
except KeyError, e:
except KeyError as e:
errmsg = '{0}; selected file extension {1} not ' \
'supported'.format(e, fnext)
raise FormatError(errmsg)
@@ -89,24 +122,42 @@ class Data(object):
# try exporting event via ObsPy
try:
self.getEvtData().write(fnout + fnext, format=evtformat)
except KeyError, e:
except KeyError as e:
raise KeyError('''{0} export format
not implemented: {1}'''.format(evtformat, e))
def getComp(self):
"""
:return:
"""
return self.comp
def getID(self):
"""
:return:
"""
try:
return self.evtdata.get('resource_id').id
except:
return None
def filterWFData(self, kwargs):
"""
:param kwargs:
"""
self.getWFData().filter(**kwargs)
self.dirty = True
def setWFData(self, fnames):
"""
:param fnames:
"""
self.wfdata = Stream()
self.wforiginal = None
if fnames is not None:
@@ -115,10 +166,14 @@ class Data(object):
self.dirty = False
def appendWFData(self, fnames):
"""
:param fnames:
"""
assert isinstance(fnames, list), "input parameter 'fnames' is " \
"supposed to be of type 'list' " \
"but is actually {0}".format(type(
fnames))
"but is actually" \
" {0}".format(type(fnames))
if self.dirty:
self.resetWFData()
@@ -129,32 +184,59 @@ class Data(object):
except TypeError:
try:
self.wfdata += read(fname, format='GSE2')
except Exception, e:
except Exception as e:
warnmsg += '{0}\n{1}\n'.format(fname, e)
if warnmsg:
warnmsg = 'WARNING: unable to read\n' + warnmsg
print warnmsg
print(warnmsg)
def getWFData(self):
"""
:return:
"""
return self.wfdata
def getOriginalWFData(self):
"""
:return:
"""
return self.wforiginal
def resetWFData(self):
"""
"""
self.wfdata = self.getOriginalWFData().copy()
self.dirty = False
def resetPicks(self):
"""
"""
self.getEvtData().picks = []
def restituteWFData(self, invdlpath, streams=None):
if streams == None:
"""
:param invdlpath:
:param streams:
:return:
"""
if streams is None:
st = self.getWFData()
else:
st = streams
for tr in st:
# remove underscores
if tr.stats.station[3] == '_':
tr.stats.station = tr.stats.station[0:3]
if tr.stats.station[3] == '_':
tr.stats.station = tr.stats.station[0:3]
dlp = '%s/*.dless' % invdlpath
invp = '%s/*.xml' % invdlpath
respp = '%s/*.resp' % invdlpath
@@ -164,47 +246,53 @@ class Data(object):
# check for dataless-SEED file
if len(dlfile) >= 1:
print "Found dataless-SEED file(s)!"
print "Reading meta data information ..."
print("Found dataless-SEED file(s)!")
print("Reading meta data information ...")
for j in range(len(dlfile)):
print "Found dataless-SEED file %s" % dlfile[j]
parser = Parser('%s' % dlfile[j])
for i in range(len(st)):
print("Found dataless-SEED file %s" % dlfile[j])
parser = Parser('%s' % dlfile[j])
for i in range(len(st)):
# check, whether this trace has already been corrected
try:
st[i].stats.processing
except:
try:
print "Correcting %s, %s for instrument response ..." \
% (st[i].stats.station, st[i].stats.channel)
try:
print(
"Correcting %s, %s for instrument response "
"..." % (st[i].stats.station,
st[i].stats.channel))
# get corner frequencies for pre-filtering
fny = st[i].stats.sampling_rate / 2
fc21 = fny - (fny * 0.05)
fc22 = fny - (fny * 0.02)
prefilt = [0.5, 0.9, fc21, fc22]
# instrument correction
st[i].simulate(pre_filt=prefilt, seedresp={'filename': parser, \
'date': st[i].stats.starttime, 'units': "VEL"})
except ValueError, e:
vmsg = '{0}'.format(e)
print vmsg
st[i].simulate(pre_filt=prefilt,
seedresp={'filename': parser,
'date': st[
i].stats.starttime,
'units': "VEL"})
except ValueError as e:
vmsg = '{0}'.format(e)
print(vmsg)
else:
print "Trace has already been corrected!"
print("Trace has already been corrected!")
# check for inventory-xml file
if len(invfile) >= 1:
print "Found inventory-xml file(s)!"
print "Reading meta data information ..."
print("Found inventory-xml file(s)!")
print("Reading meta data information ...")
for j in range(len(invfile)):
print "Found inventory-xml file %s" % invfile[j]
print("Found inventory-xml file %s" % invfile[j])
inv = read_inventory(invfile[j], format="STATIONXML")
for i in range(len(st)):
for i in range(len(st)):
# check, whether this trace has already been corrected
try:
st[i].stats.processing
except:
try:
print "Correcting %s, %s for instrument response ..." \
% (st[i].stats.station, st[i].stats.channel)
try:
print("Correcting %s, %s for instrument response "
"..." % (st[i].stats.station,
st[i].stats.channel))
# get corner frequencies for pre-filtering
fny = st[i].stats.sampling_rate / 2
fc21 = fny - (fny * 0.05)
@@ -212,56 +300,84 @@ class Data(object):
prefilt = [0.5, 0.9, fc21, fc22]
# instrument correction
st[i].attach_response(inv)
st[i].remove_response(output='VEL', pre_filt=prefilt)
except ValueError, e:
vmsg = '{0}'.format(e)
print vmsg
else:
print "Trace has already been corrected!"
st[i].remove_response(output='VEL',
pre_filt=prefilt)
except ValueError as e:
vmsg = '{0}'.format(e)
print(vmsg)
else:
print("Trace has already been corrected!")
# check for RESP-file
if len(respfile) >= 1:
print "Found response file(s)!"
print "Reading meta data information ..."
print("Found response file(s)!")
print("Reading meta data information ...")
for j in range(len(respfile)):
print "Found RESP-file %s" % respfile[j]
for i in range(len(st)):
print("Found RESP-file %s" % respfile[j])
for i in range(len(st)):
# check, whether this trace has already been corrected
try:
st[i].stats.processing
except:
try:
print "Correcting %s, %s for instrument response ..." \
% (st[i].stats.station, st[i].stats.channel)
try:
print("Correcting %s, %s for instrument response "
"..." % (st[i].stats.station,
st[i].stats.channel))
# get corner frequencies for pre-filtering
fny = st[i].stats.sampling_rate / 2
fc21 = fny - (fny * 0.05)
fc22 = fny - (fny * 0.02)
prefilt = [0.5, 0.9, fc21, fc22]
# instrument correction
seedresp={'filename': respfile[0], 'date': st[0].stats.starttime, \
'units': "VEL"}
st[i].simulate(paz_remove=None, pre_filt=prefilt, seedresp=seedresp)
except ValueError, e:
vmsg = '{0}'.format(e)
print vmsg
seedresp = {'filename': respfile[0],
'date': st[0].stats.starttime,
'units': "VEL"}
st[i].simulate(paz_remove=None, pre_filt=prefilt,
seedresp=seedresp)
except ValueError as e:
vmsg = '{0}'.format(e)
print(vmsg)
else:
print "Trace has already been corrected!"
print("Trace has already been corrected!")
if len(respfile) < 1 and len(invfile) < 1 and len(dlfile) < 1:
print "No dataless-SEED file,inventory-xml file nor RESP-file found!"
print "Go on processing data without source parameter determination!"
print("No dataless-SEED file,inventory-xml file nor RESP-file "
"found!")
print("Go on processing data without source parameter "
"determination!")
return st
def getEvtData(self):
"""
:return:
"""
return self.evtdata
def applyEVTData(self, data, type='pick', authority_id='rub'):
"""
:param data:
:param type:
:param authority_id:
:raise OverwriteError:
"""
def applyPicks(picks):
"""
Creates ObsPy pick objects and append it to the picks list from the
PyLoT dictionary contain all picks.
:param picks:
:raise OverwriteError: raises an OverwriteError if the picks list is
not empty. The GUI will then ask for a decision.
"""
firstonset = None
if self.getEvtData().picks:
raise OverwriteError('Actual picks would be overwritten!')
for station, onsets in picks.items():
print 'Reading picks on station %s' % station
print('Reading picks on station %s' % station)
for label, phase in onsets.items():
onset = phase['mpp']
epp = phase['epp']
@@ -277,8 +393,8 @@ class Data(object):
self.getEvtData().picks.append(pick)
try:
polarity = phase['fm']
except KeyError, e:
print 'No polarity information found for %s' % phase
except KeyError as e:
print('No polarity information found for %s' % phase)
if firstonset is None or firstonset > onset:
firstonset = onset
@@ -289,9 +405,17 @@ class Data(object):
self.getEvtData().resource_id = ID
def applyArrivals(arrivals):
"""
:param arrivals:
"""
pass
def applyEvent(event):
"""
:param event:
"""
pass
applydata = {'pick': applyPicks,
@@ -302,10 +426,10 @@ class Data(object):
class GenericDataStructure(object):
'''
"""
GenericDataBase type holds all information about the current data-
base working on.
'''
"""
def __init__(self, **kwargs):
@@ -317,6 +441,10 @@ class GenericDataStructure(object):
def modifyFields(self, **kwargs):
"""
:param kwargs:
"""
assert isinstance(kwargs, dict), 'dictionary type object expected'
if not self.extraAllowed():
@@ -332,37 +460,67 @@ class GenericDataStructure(object):
value = str(value)
try:
self.setFieldValue(key, value)
except KeyError, e:
except KeyError as e:
errmsg = ''
errmsg += 'WARNING:\n'
errmsg += 'unable to set values for datastructure fields\n'
errmsg += '%s; desired value was: %s\n' % (e, value)
print errmsg
print(errmsg)
def isField(self, key):
"""
:param key:
:return:
"""
return key in self.getFields().keys()
def getFieldValue(self, key):
"""
:param key:
:return:
"""
if self.isField(key):
return self.getFields()[key]
else:
return
def setFieldValue(self, key, value):
"""
:param key:
:param value:
:raise KeyError:
"""
if not self.extraAllowed() and key not in self.getAllowed():
raise KeyError
else:
if not self.isField(key):
print 'creating new field "%s"' % key
print('creating new field "%s"' % key)
self.getFields()[key] = value
def getFields(self):
"""
:return:
"""
return self.dsFields
def getExpandFields(self):
"""
:return:
"""
return self.expandFields
def setExpandFields(self, keys):
"""
:param keys:
"""
expandFields = []
for key in keys:
if self.isField(key):
@@ -370,18 +528,38 @@ class GenericDataStructure(object):
self.expandFields = expandFields
def getAllowed(self):
"""
:return:
"""
return self.allowedFields
def extraAllowed(self):
"""
:return:
"""
return not self.allowedFields
def updateNotAllowed(self, kwargs):
"""
:param kwargs:
:return:
"""
for key in kwargs:
if key not in self.getAllowed():
kwargs.__delitem__(key)
return kwargs
def hasSuffix(self):
"""
:return:
"""
try:
self.getFieldValue('suffix')
except KeyError:
@@ -392,6 +570,11 @@ class GenericDataStructure(object):
return False
def expandDataPath(self):
"""
:return:
"""
expandList = []
for item in self.getExpandFields():
expandList.append(self.getFieldValue(item))
@@ -400,14 +583,19 @@ class GenericDataStructure(object):
return os.path.join(*expandList)
def getCatalogName(self):
"""
:return:
"""
return os.path.join(self.getFieldValue('root'), 'catalog.qml')
class PilotDataStructure(GenericDataStructure):
'''
"""
Object containing the data access information for the old PILOT data
structure.
'''
"""
def __init__(self, **fields):
if not fields:
@@ -420,14 +608,14 @@ class PilotDataStructure(GenericDataStructure):
class SeiscompDataStructure(GenericDataStructure):
'''
"""
Dictionary containing the data access information for an SDS data archive:
:param str dataType: Desired data type. Default: ``'waveform'``
:param sdate, edate: Either date string or an instance of
:class:`obspy.core.utcdatetime.UTCDateTime. Default: ``None``
:type sdate, edate: str or UTCDateTime or None
'''
"""
def __init__(self, rootpath='/data/SDS', dataformat='MSEED',
filesuffix=None, **kwargs):
@@ -458,6 +646,10 @@ class SeiscompDataStructure(GenericDataStructure):
self.modifiyFields(**kwargs)
def modifiyFields(self, **kwargs):
"""
:param kwargs:
"""
if kwargs and isinstance(kwargs, dict):
for key, value in kwargs.iteritems():
key = str(key)
@@ -467,28 +659,32 @@ class SeiscompDataStructure(GenericDataStructure):
else:
value = str(value)
try:
self.setField(key, value)
except KeyError, e:
self.setFieldValue(key, value)
except KeyError as e:
errmsg = ''
errmsg += 'WARNING:\n'
errmsg += 'unable to set values for SDS fields\n'
errmsg += '%s; desired value was: %s\n' % (e, value)
print errmsg
print(errmsg)
def setFieldValue(self, key, value):
"""
:param key:
:param value:
"""
if self.isField(key):
self.getFields()[key] = value
else:
print('Warning: trying to set value of non-existent field '
'{field}'.format(field=key))
def getFields(self):
return self.__sdsFields
def getName(self):
return self.__name
def expandDataPath(self):
"""
:return:
"""
fullChan = '{0}.{1}'.format(self.getFields()['CHAN'], self.getType())
dataPath = os.path.join(self.getFields()['SDSdir'],
self.getFields()['YEAR'],

View File

@@ -16,3 +16,7 @@ class FormatError(Exception):
class DatastructureError(Exception):
pass
class OverwriteError(IOError):
pass