[seiscomp, scanloc] Install, add .gitignore
This commit is contained in:
226
bin/sc2pa
Executable file
226
bin/sc2pa
Executable file
@ -0,0 +1,226 @@
|
||||
#!/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. #
|
||||
############################################################################
|
||||
|
||||
import time
|
||||
import sys
|
||||
import os
|
||||
import time
|
||||
import seiscomp.core, seiscomp.client, seiscomp.datamodel, seiscomp.logging
|
||||
from seiscomp.scbulletin import Bulletin, stationCount
|
||||
|
||||
|
||||
class ProcAlert(seiscomp.client.Application):
|
||||
def __init__(self, argc, argv):
|
||||
seiscomp.client.Application.__init__(self, argc, argv)
|
||||
|
||||
self.setMessagingEnabled(True)
|
||||
self.setDatabaseEnabled(True, True)
|
||||
|
||||
self.setAutoApplyNotifierEnabled(True)
|
||||
self.setInterpretNotifierEnabled(True)
|
||||
|
||||
self.setPrimaryMessagingGroup(seiscomp.client.Protocol.LISTENER_GROUP)
|
||||
self.addMessagingSubscription("EVENT")
|
||||
self.addMessagingSubscription("LOCATION")
|
||||
self.addMessagingSubscription("MAGNITUDE")
|
||||
|
||||
self.maxAgeDays = 1.0
|
||||
self.minPickCount = 25
|
||||
|
||||
self.procAlertScript = ""
|
||||
|
||||
ep = seiscomp.datamodel.EventParameters()
|
||||
|
||||
def createCommandLineDescription(self):
|
||||
try:
|
||||
self.commandline().addGroup("Publishing")
|
||||
self.commandline().addIntOption(
|
||||
"Publishing",
|
||||
"min-arr",
|
||||
"Minimum arrival count of a published origin",
|
||||
self.minPickCount,
|
||||
)
|
||||
self.commandline().addDoubleOption(
|
||||
"Publishing",
|
||||
"max-age",
|
||||
"Maximum age in days of published origins",
|
||||
self.maxAgeDays,
|
||||
)
|
||||
self.commandline().addStringOption(
|
||||
"Publishing",
|
||||
"procalert-script",
|
||||
"Specify the script to publish an event. The ProcAlert file and the event id are passed as parameter $1 and $2",
|
||||
)
|
||||
self.commandline().addOption(
|
||||
"Publishing", "test", "Test mode, no messages are sent"
|
||||
)
|
||||
except:
|
||||
seiscomp.logging.warning(f"caught unexpected error {sys.exc_info()}")
|
||||
|
||||
def initConfiguration(self):
|
||||
if not seiscomp.client.Application.initConfiguration(self):
|
||||
return False
|
||||
|
||||
try:
|
||||
self.procAlertScript = self.configGetString("scripts.procAlert")
|
||||
except:
|
||||
pass
|
||||
|
||||
try:
|
||||
self.minPickCount = self.configGetInt("minArrivals")
|
||||
except:
|
||||
pass
|
||||
|
||||
try:
|
||||
self.maxAgeDays = self.configGetDouble("maxAgeDays")
|
||||
except:
|
||||
pass
|
||||
|
||||
return True
|
||||
|
||||
def init(self):
|
||||
if not seiscomp.client.Application.init(self):
|
||||
return False
|
||||
|
||||
try:
|
||||
self.procAlertScript = self.commandline().optionString("procalert-script")
|
||||
except:
|
||||
pass
|
||||
|
||||
try:
|
||||
self.minPickCount = self.commandline().optionInt("min-arr")
|
||||
except:
|
||||
pass
|
||||
|
||||
try:
|
||||
self.maxAgeDays = self.commandline().optionDouble("max-age")
|
||||
except:
|
||||
pass
|
||||
|
||||
self.bulletin = Bulletin(self.query(), "autoloc1")
|
||||
self.cache = seiscomp.datamodel.PublicObjectRingBuffer(self.query(), 100)
|
||||
|
||||
if not self.procAlertScript:
|
||||
seiscomp.logging.warning("No procalert script given")
|
||||
else:
|
||||
seiscomp.logging.info(f"Using procalert script: {self.procAlertScript}")
|
||||
|
||||
return True
|
||||
|
||||
def addObject(self, parentID, obj):
|
||||
org = seiscomp.datamodel.Origin.Cast(obj)
|
||||
if org:
|
||||
self.cache.feed(org)
|
||||
seiscomp.logging.info(f"Received origin {org.publicID()}")
|
||||
return
|
||||
|
||||
self.updateObject(parentID, obj)
|
||||
|
||||
def updateObject(self, parentID, obj):
|
||||
try:
|
||||
evt = seiscomp.datamodel.Event.Cast(obj)
|
||||
if evt:
|
||||
orid = evt.preferredOriginID()
|
||||
|
||||
org = self.cache.get(seiscomp.datamodel.Origin, orid)
|
||||
if not org:
|
||||
seiscomp.logging.error(f"Unable to fetch origin {orid}")
|
||||
return
|
||||
|
||||
if org.arrivalCount() == 0:
|
||||
self.query().loadArrivals(org)
|
||||
if org.stationMagnitudeCount() == 0:
|
||||
self.query().loadStationMagnitudes(org)
|
||||
if org.magnitudeCount() == 0:
|
||||
self.query().loadMagnitudes(org)
|
||||
|
||||
if not self.originMeetsCriteria(org, evt):
|
||||
seiscomp.logging.warning(f"Origin {orid} not published")
|
||||
return
|
||||
|
||||
txt = self.bulletin.printEvent(evt)
|
||||
|
||||
for line in txt.split("\n"):
|
||||
line = line.rstrip()
|
||||
seiscomp.logging.info(line)
|
||||
seiscomp.logging.info("")
|
||||
|
||||
if not self.commandline().hasOption("test"):
|
||||
self.send_procalert(txt, evt.publicID())
|
||||
|
||||
return
|
||||
|
||||
except:
|
||||
sys.stderr.write(f"{sys.exc_info()}\n")
|
||||
|
||||
def hasValidNetworkMagnitude(self, org, evt):
|
||||
nmag = org.magnitudeCount()
|
||||
for imag in range(nmag):
|
||||
mag = org.magnitude(imag)
|
||||
if mag.publicID() == evt.preferredMagnitudeID():
|
||||
return True
|
||||
return False
|
||||
|
||||
def send_procalert(self, txt, evid):
|
||||
if self.procAlertScript:
|
||||
tmp = f"/tmp/yyy{evid.replace('/', '_').replace(':', '-')}"
|
||||
f = file(tmp, "w")
|
||||
f.write(f"{txt}")
|
||||
f.close()
|
||||
|
||||
os.system(self.procAlertScript + " " + tmp + " " + evid)
|
||||
|
||||
def coordinates(self, org):
|
||||
return org.latitude().value(), org.longitude().value(), org.depth().value()
|
||||
|
||||
def originMeetsCriteria(self, org, evt):
|
||||
publish = True
|
||||
|
||||
lat, lon, dep = self.coordinates(org)
|
||||
|
||||
if 43 < lat < 70 and -10 < lon < 60 and dep > 200:
|
||||
seiscomp.logging.error("suspicious region/depth - ignored")
|
||||
publish = False
|
||||
|
||||
if stationCount(org) < self.minPickCount:
|
||||
seiscomp.logging.error("too few picks - ignored")
|
||||
publish = False
|
||||
|
||||
now = seiscomp.core.Time.GMT()
|
||||
if (now - org.time().value()).seconds() / 86400.0 > self.maxAgeDays:
|
||||
seiscomp.logging.error("origin too old - ignored")
|
||||
publish = False
|
||||
|
||||
try:
|
||||
if org.evaluationMode() == seiscomp.datamodel.MANUAL:
|
||||
publish = True
|
||||
except:
|
||||
pass
|
||||
|
||||
try:
|
||||
if org.evaluationStatus() == seiscomp.datamodel.CONFIRMED:
|
||||
publish = True
|
||||
except:
|
||||
pass
|
||||
|
||||
if not self.hasValidNetworkMagnitude(org, evt):
|
||||
seiscomp.logging.error("no network magnitude - ignored")
|
||||
publish = False
|
||||
|
||||
return publish
|
||||
|
||||
|
||||
app = ProcAlert(len(sys.argv), sys.argv)
|
||||
sys.exit(app())
|
Reference in New Issue
Block a user