You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

885 lines
36 KiB
Plaintext

#!/usr/bin/env seiscomp-python
# -*- coding: utf-8 -*-
############################################################################
# Copyright (C) GFZ Potsdam #
# All rights reserved. #
# #
# GNU Affero General Public License Usage #
# This file may be used under the terms of the GNU Affero #
# Public License version 3.0 as published by the Free Software Foundation #
# and appearing in the file LICENSE included in the packaging of this #
# file. Please review the following information to ensure the GNU Affero #
# Public License version 3.0 requirements will be met: #
# https://www.gnu.org/licenses/agpl-3.0.html. #
# #
# Author: Alexander Jaeger, Stephan Herrnkind, #
# Lukas Lehmann, Dirk Roessler# #
# Email: herrnkind@gempa.de #
############################################################################
import seiscomp.client, seiscomp.core, seiscomp.datamodel, seiscomp.io, seiscomp.logging, seiscomp.math
from time import strptime
import sys
import traceback
TimeFormats = [
'%d-%b-%Y_%H:%M:%S.%f',
'%d-%b-%Y_%H:%M:%S'
]
# SC3 has more event types available in the datamodel
EventTypes = {
'teleseismic quake': seiscomp.datamodel.EARTHQUAKE,
'local quake': seiscomp.datamodel.EARTHQUAKE,
'regional quake': seiscomp.datamodel.EARTHQUAKE,
'quarry blast': seiscomp.datamodel.QUARRY_BLAST,
'nuclear explosion': seiscomp.datamodel.NUCLEAR_EXPLOSION,
'mining event': seiscomp.datamodel.MINING_EXPLOSION
}
def wfs2Str(wfsID):
return '%s.%s.%s.%s' % (wfsID.networkCode(), wfsID.stationCode(),
wfsID.locationCode(), wfsID.channelCode())
###############################################################################
class SH2Proc(seiscomp.client.Application):
###########################################################################
def __init__(self):
seiscomp.client.Application.__init__(self, len(sys.argv), sys.argv)
self.setMessagingEnabled(True)
self.setDatabaseEnabled(True, True)
self.setLoadInventoryEnabled(True)
self.setLoadConfigModuleEnabled(True)
self.setDaemonEnabled(False)
self.inputFile = '-'
###########################################################################
def initConfiguration(self):
if not seiscomp.client.Application.initConfiguration(self):
return False
# If the database connection is passed via command line or configuration
# file then messaging is disabled. Messaging is only used to get
# the configured database connection URI.
if self.databaseURI() != '':
self.setMessagingEnabled(False)
else:
# A database connection is not required if the inventory is loaded
# from file
if not self.isInventoryDatabaseEnabled():
self.setMessagingEnabled(False)
self.setDatabaseEnabled(False, False)
return True
##########################################################################
def printUsage(self):
print('''Usage:
sh2proc [options]
Convert Seismic Handler event data to SeisComP XML format''')
seiscomp.client.Application.printUsage(self)
print('''Examples:
Convert the Seismic Handler file shm.evt to SCML. Receive the database
connection to read inventory and configuration information from messaging
sh2proc shm.evt
Read Seismic Handler data from stdin. Provide inventory and configuration in XML
cat shm.evt | sh2proc --inventory-db=inventory.xml --config-db=config.xml
''')
##########################################################################
def validateParameters(self):
if not seiscomp.client.Application.validateParameters(self):
return False
for opt in self.commandline().unrecognizedOptions():
if len(opt) > 1 and opt.startswith('-'):
continue
self.inputFile = opt
break
return True
###########################################################################
def loadStreams(self):
now = seiscomp.core.Time.GMT()
inv = seiscomp.client.Inventory.Instance()
self.streams = {}
# try to load streams by detecLocid and detecStream
mod = self.configModule()
if mod is not None and mod.configStationCount() > 0:
seiscomp.logging.info('loading streams using detecLocid and detecStream')
for i in range(mod.configStationCount()):
cfg = mod.configStation(i)
net = cfg.networkCode()
sta = cfg.stationCode()
if sta in self.streams:
seiscomp.logging.warning(
'ambiguous stream id found for station %s.%s' % (net, sta))
continue
setup = seiscomp.datamodel.findSetup(cfg, self.name(), True)
if not setup:
seiscomp.logging.warning(
'could not find station setup for %s.%s' % (net, sta))
continue
params = seiscomp.datamodel.ParameterSet.Find(setup.parameterSetID())
if not params:
seiscomp.logging.warning(
'could not find station parameters for %s.%s' % (net, sta))
continue
detecLocid = ''
detecStream = None
for j in range(params.parameterCount()):
param = params.parameter(j)
if param.name() == 'detecStream':
detecStream = param.value()
elif param.name() == 'detecLocid':
detecLocid = param.value()
if detecStream is None:
seiscomp.logging.warning(
'could not find detecStream for %s.%s' % (net, sta))
continue
loc = inv.getSensorLocation(net, sta, detecLocid, now)
if loc is None:
seiscomp.logging.warning(
'could not find preferred location for %s.%s' % (net, sta))
continue
components = {}
tc = seiscomp.datamodel.ThreeComponents()
seiscomp.datamodel.getThreeComponents(tc, loc, detecStream[:2], now)
if tc.vertical():
cha = tc.vertical()
wfsID = seiscomp.datamodel.WaveformStreamID(net, sta, loc.code(),
cha.code(), '')
components[cha.code()[-1]] = wfsID
seiscomp.logging.debug('add stream %s (vertical)' % wfs2Str(wfsID))
if tc.firstHorizontal():
cha = tc.firstHorizontal()
wfsID = seiscomp.datamodel.WaveformStreamID(net, sta, loc.code(),
cha.code(), '')
components[cha.code()[-1]] = wfsID
seiscomp.logging.debug('add stream %s (first horizontal)' % wfs2Str(wfsID))
if tc.secondHorizontal():
cha = tc.secondHorizontal()
wfsID = seiscomp.datamodel.WaveformStreamID(net, sta, loc.code(),
cha.code(), '')
components[cha.code()[-1]] = wfsID
seiscomp.logging.debug('add stream %s (second horizontal)' % wfs2Str(wfsID))
if len(components) > 0:
self.streams[sta] = components
return
# fallback loading streams from inventory
seiscomp.logging.warning(
'no configuration module available, loading streams '
'from inventory and selecting first available stream '
'matching epoch')
for iNet in range(inv.inventory().networkCount()):
net = inv.inventory().network(iNet)
seiscomp.logging.debug('network %s: loaded %i stations' % (net.code(), net.stationCount()))
for iSta in range(net.stationCount()):
sta = net.station(iSta)
try:
start = sta.start()
if not start <= now:
continue
except:
continue
try:
end = sta.end()
if not now <= end:
continue
except:
pass
for iLoc in range(sta.sensorLocationCount()):
loc = sta.sensorLocation(iLoc)
for iCha in range(loc.streamCount()):
cha = loc.stream(iCha)
wfsID = seiscomp.datamodel.WaveformStreamID(net.code(),
sta.code(), loc.code(), cha.code(), '')
comp = cha.code()[2]
if sta.code() not in self.streams:
components = {}
components[comp] = wfsID
self.streams[sta.code()] = components
else:
# Seismic Handler does not support network,
# location and channel code: make sure network and
# location codes match first item in station
# specific steam list
oldWfsID = list(self.streams[sta.code()].values())[0]
if net.code() != oldWfsID.networkCode() or \
loc.code() != oldWfsID.locationCode() or \
cha.code()[:2] != oldWfsID.channelCode()[:2]:
seiscomp.logging.warning(
'ambiguous stream id found for station %s, ignoring %s'
% (sta.code(), wfs2Str(wfsID)))
continue
self.streams[sta.code()][comp] = wfsID
seiscomp.logging.debug('add stream %s' % wfs2Str(wfsID))
###########################################################################
def parseTime(self, timeStr):
time = seiscomp.core.Time()
for fmt in TimeFormats:
if time.fromString(timeStr, fmt):
break
return time
###########################################################################
def parseMagType(self, value):
if value == 'm':
return 'M'
elif value == 'ml':
return 'ML'
elif value == 'mb':
return 'mb'
elif value == 'ms':
return 'Ms(BB)'
elif value == 'mw':
return 'Mw'
elif value == 'bb':
return 'mB'
return ''
###########################################################################
def sh2proc(self, file):
ep = seiscomp.datamodel.EventParameters()
origin = seiscomp.datamodel.Origin.Create()
event = seiscomp.datamodel.Event.Create()
origin.setCreationInfo(seiscomp.datamodel.CreationInfo())
origin.creationInfo().setCreationTime(seiscomp.core.Time.GMT())
originQuality = None
originCE = None
latFound = False
lonFound = False
depthError = None
originComments = {}
# variables, reset after 'end of phase'
pick = None
stationMag = None
staCode = None
compCode = None
stationMagBB = None
amplitudeDisp = None
amplitudeVel = None
amplitudeSNR = None
amplitudeBB = None
magnitudeMB = None
magnitudeML = None
magnitudeMS = None
magnitudeBB = None
km2degFac = 1.0 / seiscomp.math.deg2km(1.0)
# read file line by line, split key and value at colon
iLine = 0
for line in file:
iLine += 1
a = line.split(':', 1)
key = a[0].strip()
keyLower = key.lower()
value = None
# empty line
if len(keyLower) == 0:
continue
# end of phase
elif keyLower == '--- end of phase ---':
if pick is None:
seiscomp.logging.warning(
'Line %i: found empty phase block' % iLine)
continue
if staCode is None or compCode is None:
seiscomp.logging.warning(
'Line %i: end of phase, stream code incomplete' % iLine)
continue
if not staCode in self.streams:
seiscomp.logging.warning(
'Line %i: end of phase, station code %s not found in inventory' % (iLine, staCode))
continue
if not compCode in self.streams[staCode]:
seiscomp.logging.warning(
'Line %i: end of phase, component %s of station %s not found in inventory' % (iLine, compCode, staCode))
continue
streamID = self.streams[staCode][compCode]
pick.setWaveformID(streamID)
ep.add(pick)
arrival.setPickID(pick.publicID())
arrival.setPhase(phase)
origin.add(arrival)
if amplitudeSNR is not None:
amplitudeSNR.setPickID(pick.publicID())
amplitudeSNR.setWaveformID(streamID)
ep.add(amplitudeSNR)
if amplitudeBB is not None:
amplitudeBB.setPickID(pick.publicID())
amplitudeBB.setWaveformID(streamID)
ep.add(amplitudeBB)
if stationMagBB is not None:
stationMagBB.setWaveformID(streamID)
origin.add(stationMagBB)
stationMagContrib = seiscomp.datamodel.StationMagnitudeContribution()
stationMagContrib.setStationMagnitudeID(
stationMagBB.publicID())
if magnitudeBB is None:
magnitudeBB = seiscomp.datamodel.Magnitude.Create()
magnitudeBB.add(stationMagContrib)
if stationMag is not None:
if stationMag.type() in ['mb', 'ML'] and amplitudeDisp is not None:
amplitudeDisp.setPickID(pick.publicID())
amplitudeDisp.setWaveformID(streamID)
amplitudeDisp.setPeriod(
seiscomp.datamodel.RealQuantity(ampPeriod))
amplitudeDisp.setType(stationMag.type())
ep.add(amplitudeDisp)
if stationMag.type() in ['Ms(BB)'] and amplitudeVel is not None:
amplitudeVel.setPickID(pick.publicID())
amplitudeVel.setWaveformID(streamID)
amplitudeVel.setPeriod(
seiscomp.datamodel.RealQuantity(ampPeriod))
amplitudeVel.setType(stationMag.type())
ep.add(amplitudeVel)
stationMag.setWaveformID(streamID)
origin.add(stationMag)
stationMagContrib = seiscomp.datamodel.StationMagnitudeContribution()
stationMagContrib.setStationMagnitudeID(
stationMag.publicID())
magType = stationMag.type()
if magType == 'ML':
if magnitudeML is None:
magnitudeML = seiscomp.datamodel.Magnitude.Create()
magnitudeML.add(stationMagContrib)
elif magType == 'Ms(BB)':
if magnitudeMS is None:
magnitudeMS = seiscomp.datamodel.Magnitude.Create()
magnitudeMS.add(stationMagContrib)
elif magType == 'mb':
if magnitudeMB is None:
magnitudeMB = seiscomp.datamodel.Magnitude.Create()
magnitudeMB.add(stationMagContrib)
pick = None
staCode = None
compCode = None
stationMag = None
stationMagBB = None
amplitudeDisp = None
amplitudeVel = None
amplitudeSNR = None
amplitudeBB = None
continue
# empty key
elif len(a) == 1:
seiscomp.logging.warning('Line %i: key without value' % iLine)
continue
value = a[1].strip()
if pick is None:
pick = seiscomp.datamodel.Pick.Create()
arrival = seiscomp.datamodel.Arrival()
try:
##############################################################
# station parameters
# station code
if keyLower == 'station code':
staCode = value
# pick time
elif keyLower == 'onset time':
pick.setTime(seiscomp.datamodel.TimeQuantity(self.parseTime(value)))
# pick onset type
elif keyLower == 'onset type':
found = False
for onset in [seiscomp.datamodel.EMERGENT, seiscomp.datamodel.IMPULSIVE,
seiscomp.datamodel.QUESTIONABLE]:
if value == seiscomp.datamodel.EPickOnsetNames_name(onset):
pick.setOnset(onset)
found = True
break
if not found:
raise Exception('Unsupported onset value')
# phase code
elif keyLower == 'phase name':
phase = seiscomp.datamodel.Phase()
phase.setCode(value)
pick.setPhaseHint(phase)
# event type
elif keyLower == 'event type':
evttype = EventTypes[value]
event.setType(evttype)
originComments[key] = value
# filter ID
elif keyLower == 'applied filter':
pick.setFilterID(value)
# channel code, prepended by configured Channel prefix if only
# one character is found
elif keyLower == 'component':
compCode = value
# pick evaluation mode
elif keyLower == 'pick type':
found = False
for mode in [seiscomp.datamodel.AUTOMATIC, seiscomp.datamodel.MANUAL]:
if value == seiscomp.datamodel.EEvaluationModeNames_name(mode):
pick.setEvaluationMode(mode)
found = True
break
if not found:
raise Exception('Unsupported evaluation mode value')
# pick author
elif keyLower == 'analyst':
creationInfo = seiscomp.datamodel.CreationInfo()
creationInfo.setAuthor(value)
pick.setCreationInfo(creationInfo)
# pick polarity
# isn't tested
elif keyLower == 'sign':
if value == 'positive':
sign = '0' # positive
elif value == 'negative':
sign = '1' # negative
else:
sign = '2' # unknown
pick.setPolarity(float(sign))
# arrival weight
elif keyLower == 'weight':
arrival.setWeight(float(value))
# arrival azimuth
elif keyLower == 'theo. azimuth (deg)':
arrival.setAzimuth(float(value))
# pick theo backazimuth
elif keyLower == 'theo. backazimuth (deg)':
if pick.slownessMethodID() == 'corrected':
seiscomp.logging.debug('Line %i: ignoring parameter: %s' % (iLine, key))
else:
pick.setBackazimuth(
seiscomp.datamodel.RealQuantity(float(value)))
pick.setSlownessMethodID('theoretical')
# pick beam slowness
elif keyLower == 'beam-slowness (sec/deg)':
if pick.slownessMethodID() == 'corrected':
seiscomp.logging.debug('Line %i: ignoring parameter: %s' % (iLine, key))
else:
pick.setHorizontalSlowness(
seiscomp.datamodel.RealQuantity(float(value)))
pick.setSlownessMethodID('Array Beam')
# pick beam backazimuth
elif keyLower == 'beam-azimuth (deg)':
if pick.slownessMethodID() == 'corrected':
seiscomp.logging.debug('Line %i: ignoring parameter: %s' % (iLine, key))
else:
pick.setBackazimuth(
seiscomp.datamodel.RealQuantity(float(value)))
# pick epi slowness
elif keyLower == 'epi-slowness (sec/deg)':
pick.setHorizontalSlowness(
seiscomp.datamodel.RealQuantity(float(value)))
pick.setSlownessMethodID('corrected')
# pick epi backazimuth
elif keyLower == 'epi-azimuth (deg)':
pick.setBackazimuth(seiscomp.datamodel.RealQuantity(float(value)))
# arrival distance degree
elif keyLower == 'distance (deg)':
arrival.setDistance(float(value))
# arrival distance km, recalculates for degree
elif keyLower == 'distance (km)':
if isinstance(arrival.distance(), float):
seiscomp.logging.debug('Line %i: ignoring parameter: %s' % (iLine-1, 'distance (deg)'))
arrival.setDistance(float(value) * km2degFac)
# arrival time residual
elif keyLower == 'residual time':
arrival.setTimeResidual(float(value))
# amplitude snr
elif keyLower == 'signal/noise':
amplitudeSNR = seiscomp.datamodel.Amplitude.Create()
amplitudeSNR.setType('SNR')
amplitudeSNR.setAmplitude(
seiscomp.datamodel.RealQuantity(float(value)))
# amplitude period
elif keyLower.startswith('period'):
ampPeriod = float(value)
# amplitude value for displacement
elif keyLower == 'amplitude (nm)':
amplitudeDisp = seiscomp.datamodel.Amplitude.Create()
amplitudeDisp.setAmplitude(
seiscomp.datamodel.RealQuantity(float(value)))
amplitudeDisp.setUnit('nm')
# amplitude value for velocity
elif keyLower.startswith('vel. amplitude'):
amplitudeVel = seiscomp.datamodel.Amplitude.Create()
amplitudeVel.setAmplitude(
seiscomp.datamodel.RealQuantity(float(value)))
amplitudeVel.setUnit('nm/s')
elif keyLower == 'bb amplitude (nm/sec)':
amplitudeBB = seiscomp.datamodel.Amplitude.Create()
amplitudeBB.setAmplitude(
seiscomp.datamodel.RealQuantity(float(value)))
amplitudeBB.setType('mB')
amplitudeBB.setUnit('nm/s')
amplitudeBB.setPeriod(seiscomp.datamodel.RealQuantity(ampBBPeriod))
elif keyLower == 'bb period (sec)':
ampBBPeriod = float(value)
elif keyLower == 'broadband magnitude':
magType = self.parseMagType('bb')
stationMagBB = seiscomp.datamodel.StationMagnitude.Create()
stationMagBB.setMagnitude(
seiscomp.datamodel.RealQuantity(float(value)))
stationMagBB.setType(magType)
stationMagBB.setAmplitudeID(amplitudeBB.publicID())
# ignored
elif keyLower == 'quality number':
seiscomp.logging.debug('Line %i: ignoring parameter: %s' % (iLine, key))
# station magnitude value and type
elif keyLower.startswith('magnitude '):
magType = self.parseMagType(key[10:])
stationMag = seiscomp.datamodel.StationMagnitude.Create()
stationMag.setMagnitude(
seiscomp.datamodel.RealQuantity(float(value)))
if len(magType) > 0:
stationMag.setType(magType)
if magType == 'mb':
stationMag.setAmplitudeID(amplitudeDisp.publicID())
elif magType == 'MS(BB)':
stationMag.setAmplitudeID(amplitudeVel.publicID())
else:
seiscomp.logging.debug('Line %i: Magnitude Type not known %s.' % (iLine, magType))
###############################################################
# origin parameters
# event ID, added as origin comment later on
elif keyLower == 'event id':
originComments[key] = value
# magnitude value and type
elif keyLower == 'mean bb magnitude':
magType = self.parseMagType('bb')
if magnitudeBB is None:
magnitudeBB = seiscomp.datamodel.Magnitude.Create()
magnitudeBB.setMagnitude(
seiscomp.datamodel.RealQuantity(float(value)))
magnitudeBB.setType(magType)
elif keyLower.startswith('mean magnitude '):
magType = self.parseMagType(key[15:])
if magType == 'ML':
if magnitudeML is None:
magnitudeML = seiscomp.datamodel.Magnitude.Create()
magnitudeML.setMagnitude(
seiscomp.datamodel.RealQuantity(float(value)))
magnitudeML.setType(magType)
elif magType == 'Ms(BB)':
if magnitudeMS is None:
magnitudeMS = seiscomp.datamodel.Magnitude.Create()
magnitudeMS.setMagnitude(
seiscomp.datamodel.RealQuantity(float(value)))
magnitudeMS.setType(magType)
elif magType == 'mb':
if magnitudeMB is None:
magnitudeMB = seiscomp.datamodel.Magnitude.Create()
magnitudeMB.setMagnitude(
seiscomp.datamodel.RealQuantity(float(value)))
magnitudeMB.setType(magType)
else:
seiscomp.logging.warning('Line %i: Magnitude type %s not defined yet.' % (iLine, magType))
# latitude
elif keyLower == 'latitude':
origin.latitude().setValue(float(value))
latFound = True
elif keyLower == 'error in latitude (km)':
origin.latitude().setUncertainty(float(value))
# longitude
elif keyLower == 'longitude':
origin.longitude().setValue(float(value))
lonFound = True
elif keyLower == 'error in longitude (km)':
origin.longitude().setUncertainty(float(value))
# depth
elif keyLower == 'depth (km)':
origin.setDepth(seiscomp.datamodel.RealQuantity(float(value)))
if depthError is not None:
origin.depth().setUncertainty(depthError)
elif keyLower == 'depth type':
seiscomp.logging.debug('Line %i: ignoring parameter: %s' % (iLine, key))
elif keyLower == 'error in depth (km)':
depthError = float(value)
try:
origin.depth().setUncertainty(depthError)
except seiscomp.core.ValueException:
pass
# time
elif keyLower == 'origin time':
origin.time().setValue(self.parseTime(value))
elif keyLower == 'error in origin time':
origin.time().setUncertainty(float(value))
# location method
elif keyLower == 'location method':
origin.setMethodID(str(value))
# region table, added as origin comment later on
elif keyLower == 'region table':
originComments[key] = value
# region table, added as origin comment later on
elif keyLower == 'region id':
originComments[key] = value
# source region, added as origin comment later on
elif keyLower == 'source region':
originComments[key] = value
# used station count
elif keyLower == 'no. of stations used':
if originQuality is None:
originQuality = seiscomp.datamodel.OriginQuality()
originQuality.setUsedStationCount(int(value))
# ignored
elif keyLower == 'reference location name':
seiscomp.logging.debug('Line %i: ignoring parameter: %s' % (iLine, key))
# confidence ellipsoid major axis
elif keyLower == 'error ellipse major':
if originCE is None:
originCE = seiscomp.datamodel.ConfidenceEllipsoid()
originCE.setSemiMajorAxisLength(float(value))
# confidence ellipsoid minor axis
elif keyLower == 'error ellipse minor':
if originCE is None:
originCE = seiscomp.datamodel.ConfidenceEllipsoid()
originCE.setSemiMinorAxisLength(float(value))
# confidence ellipsoid rotation
elif keyLower == 'error ellipse strike':
if originCE is None:
originCE = seiscomp.datamodel.ConfidenceEllipsoid()
originCE.setMajorAxisRotation(float(value))
# azimuthal gap
elif keyLower == 'max azimuthal gap (deg)':
if originQuality is None:
originQuality = seiscomp.datamodel.OriginQuality()
originQuality.setAzimuthalGap(float(value))
# creation info author
elif keyLower == 'author':
origin.creationInfo().setAuthor(value)
# creation info agency
elif keyLower == 'source of information':
origin.creationInfo().setAgencyID(value)
# earth model id
elif keyLower == 'velocity model':
origin.setEarthModelID(value)
# standard error
elif keyLower == 'rms of residuals (sec)':
if originQuality is None:
originQuality = seiscomp.datamodel.OriginQuality()
originQuality.setStandardError(float(value))
# ignored
elif keyLower == 'phase flags':
seiscomp.logging.debug('Line %i: ignoring parameter: %s' % (iLine, key))
# ignored
elif keyLower == 'location input params':
seiscomp.logging.debug('Line %i: ignoring parameter: %s' % (iLine, key))
# missing keys
elif keyLower == 'ampl&period source':
seiscomp.logging.debug('Line %i: ignoring parameter: %s' % (iLine, key))
elif keyLower == 'location quality':
seiscomp.logging.debug('Line %i: ignoring parameter: %s' % (iLine, key))
elif keyLower == 'reference latitude':
seiscomp.logging.debug('Line %i: ignoring parameter: %s' % (iLine, key))
elif keyLower == 'reference longitude':
seiscomp.logging.debug('Line %i: ignoring parameter: %s' % (iLine, key))
elif keyLower.startswith('amplitude time'):
seiscomp.logging.debug('Line %i: ignoring parameter: %s' % (iLine, key))
# unknown key
else:
seiscomp.logging.warning('Line %i: ignoring unknown parameter: %s' % (iLine, key))
except ValueError as ve:
seiscomp.logging.warning('Line %i: can not parse %s value' % (iLine, key))
except Exception:
seiscomp.logging.error('Line %i: %s' % (iLine, str(traceback.format_exc())))
return None
# check
if not latFound:
seiscomp.logging.warning('could not add origin, missing latitude parameter')
elif not lonFound:
seiscomp.logging.warning('could not add origin, missing longitude parameter')
elif not origin.time().value().valid():
seiscomp.logging.warning('could not add origin, missing origin time parameter')
else:
if magnitudeMB is not None:
origin.add(magnitudeMB)
if magnitudeML is not None:
origin.add(magnitudeML)
if magnitudeMS is not None:
origin.add(magnitudeMS)
if magnitudeBB is not None:
origin.add(magnitudeBB)
ep.add(event)
ep.add(origin)
if originQuality is not None:
origin.setQuality(originQuality)
if originCE is not None:
uncertainty = seiscomp.datamodel.OriginUncertainty()
uncertainty.setConfidenceEllipsoid(originCE)
origin.setUncertainty(uncertainty)
for k, v in originComments.items():
comment = seiscomp.datamodel.Comment()
comment.setId(k)
comment.setText(v)
origin.add(comment)
return ep
###########################################################################
def run(self):
self.loadStreams()
try:
if self.inputFile == '-':
f = sys.stdin
else:
f = open(self.inputFile)
except IOError as e:
seiscomp.logging.error(str(e))
return False
ep = self.sh2proc(f)
if ep is None:
return False
ar = seiscomp.io.XMLArchive()
ar.create('-')
ar.setFormattedOutput(True)
ar.writeObject(ep)
ar.close()
return True
###############################################################################
def main():
try:
app = SH2Proc()
return app()
except:
sys.stderr.write(str(traceback.format_exc()))
return 1
if __name__ == '__main__':
sys.exit(main())
# vim: ts=4 et