[seiscomp, scanloc] Install, add .gitignore
This commit is contained in:
332
bin/scevtls
Executable file
332
bin/scevtls
Executable file
@ -0,0 +1,332 @@
|
||||
#!/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 os
|
||||
import sys
|
||||
|
||||
import seiscomp.core
|
||||
import seiscomp.client
|
||||
import seiscomp.datamodel
|
||||
import seiscomp.logging
|
||||
|
||||
|
||||
def readXML(self):
|
||||
ar = seiscomp.io.XMLArchive()
|
||||
if not ar.open(self._inputFile):
|
||||
print(f"Unable to open input file {self._inputFile}")
|
||||
return []
|
||||
|
||||
obj = ar.readObject()
|
||||
if obj is None:
|
||||
raise TypeError("invalid input file format")
|
||||
|
||||
ep = seiscomp.datamodel.EventParameters.Cast(obj)
|
||||
if ep is None:
|
||||
raise ValueError("no event parameters found in input file")
|
||||
|
||||
eventIDs = []
|
||||
for i in range(ep.eventCount()):
|
||||
evt = ep.event(i)
|
||||
|
||||
if self._modifiedAfterTime is not None:
|
||||
try:
|
||||
if evt.creationInfo().modificationTime() < self._modifiedAfterTime:
|
||||
continue
|
||||
except ValueError:
|
||||
try:
|
||||
if evt.creationInfo().creationTime() < self._modifiedAfterTime:
|
||||
continue
|
||||
except ValueError:
|
||||
continue
|
||||
|
||||
if self._eventType:
|
||||
try:
|
||||
eventType = seiscomp.datamodel.EEventTypeNames_name(evt.type())
|
||||
if eventType != self._eventType:
|
||||
continue
|
||||
except ValueError:
|
||||
continue
|
||||
|
||||
prefOrgID = evt.preferredOriginID()
|
||||
|
||||
# filter by origin time
|
||||
org = ep.findOrigin(prefOrgID)
|
||||
orgTime = org.time().value()
|
||||
if orgTime < self._startTime:
|
||||
continue
|
||||
if orgTime > self._endTime:
|
||||
continue
|
||||
|
||||
outputString = evt.publicID()
|
||||
if self._preferredOrigin:
|
||||
try:
|
||||
outputString += " " + evt.preferredOriginID()
|
||||
except ValueError:
|
||||
outputString += " none"
|
||||
|
||||
eventIDs.append(outputString)
|
||||
|
||||
return eventIDs
|
||||
|
||||
|
||||
class EventList(seiscomp.client.Application):
|
||||
def __init__(self, argc, argv):
|
||||
seiscomp.client.Application.__init__(self, argc, argv)
|
||||
|
||||
self.setMessagingEnabled(False)
|
||||
self.setDatabaseEnabled(True, False)
|
||||
self.setDaemonEnabled(False)
|
||||
|
||||
self._startTime = None
|
||||
self._endTime = None
|
||||
self.hours = None
|
||||
self._delimiter = None
|
||||
self._modifiedAfterTime = None
|
||||
self._preferredOrigin = False
|
||||
self._inputFile = None
|
||||
self._eventType = None
|
||||
|
||||
def createCommandLineDescription(self):
|
||||
self.commandline().addGroup("Input")
|
||||
self.commandline().addStringOption(
|
||||
"Input",
|
||||
"input,i",
|
||||
"Name of input XML file. Read from stdin if '-' is given. Deactivates "
|
||||
"reading events from database",
|
||||
)
|
||||
self.commandline().addGroup("Events")
|
||||
self.commandline().addStringOption(
|
||||
"Events", "begin", "Specify the lower bound of the time interval."
|
||||
)
|
||||
self.commandline().addStringOption(
|
||||
"Events", "end", "Specify the upper bound of the time interval."
|
||||
)
|
||||
self.commandline().addStringOption(
|
||||
"Events",
|
||||
"hours",
|
||||
"Start searching given hours before"
|
||||
" now. If set, --begin and --end "
|
||||
"are ignored.",
|
||||
)
|
||||
self.commandline().addStringOption(
|
||||
"Events",
|
||||
"modified-after",
|
||||
"Select events modified after the specified time.",
|
||||
)
|
||||
|
||||
self.commandline().addStringOption(
|
||||
"Events",
|
||||
"event-type",
|
||||
"Select events whith specified " "event type.",
|
||||
)
|
||||
|
||||
self.commandline().addGroup("Output")
|
||||
self.commandline().addStringOption(
|
||||
"Output",
|
||||
"delimiter,D",
|
||||
"Specify the delimiter of the resulting event IDs. Default: '\\n')",
|
||||
)
|
||||
self.commandline().addOption(
|
||||
"Output",
|
||||
"preferred-origin,p",
|
||||
"Print the ID of the preferred origin along with the event ID.",
|
||||
)
|
||||
return True
|
||||
|
||||
def validateParameters(self):
|
||||
if not seiscomp.client.Application.validateParameters(self):
|
||||
return False
|
||||
|
||||
try:
|
||||
self._inputFile = self.commandline().optionString("input")
|
||||
except RuntimeError:
|
||||
pass
|
||||
|
||||
if self._inputFile:
|
||||
self.setDatabaseEnabled(False, False)
|
||||
|
||||
return True
|
||||
|
||||
def init(self):
|
||||
if not seiscomp.client.Application.init(self):
|
||||
return False
|
||||
|
||||
try:
|
||||
self.hours = float(self.commandline().optionString("hours"))
|
||||
except RuntimeError:
|
||||
pass
|
||||
|
||||
end = "2500-01-01T00:00:00Z"
|
||||
if self.hours is None:
|
||||
try:
|
||||
start = self.commandline().optionString("begin")
|
||||
except RuntimeError:
|
||||
start = "1900-01-01T00:00:00Z"
|
||||
|
||||
self._startTime = seiscomp.core.Time.FromString(start)
|
||||
if self._startTime is None:
|
||||
seiscomp.logging.error(f"Wrong 'begin' format '{start}'")
|
||||
return False
|
||||
seiscomp.logging.debug(
|
||||
f"Setting start to {self._startTime.toString('%FT%TZ')}"
|
||||
)
|
||||
|
||||
try:
|
||||
end = self.commandline().optionString("end")
|
||||
except RuntimeError:
|
||||
pass
|
||||
|
||||
self._endTime = seiscomp.core.Time.FromString(end)
|
||||
if self._endTime is None:
|
||||
seiscomp.logging.error(f"Wrong 'end' format '{end}'")
|
||||
return False
|
||||
seiscomp.logging.debug(f"Setting end to {self._endTime.toString('%FT%TZ')}")
|
||||
else:
|
||||
seiscomp.logging.debug(
|
||||
"Time window set by hours option: ignoring all other time parameters"
|
||||
)
|
||||
secs = self.hours * 3600
|
||||
maxSecs = 596523 * 3600
|
||||
if secs > maxSecs:
|
||||
seiscomp.logging.error(
|
||||
f"Maximum hours exceeeded. Maximum is {int(maxSecs / 3600)}"
|
||||
)
|
||||
return False
|
||||
|
||||
self._startTime = seiscomp.core.Time.UTC() - seiscomp.core.TimeSpan(secs)
|
||||
self._endTime = seiscomp.core.Time.FromString(end)
|
||||
|
||||
try:
|
||||
self._delimiter = self.commandline().optionString("delimiter")
|
||||
except RuntimeError:
|
||||
self._delimiter = "\n"
|
||||
|
||||
try:
|
||||
modifiedAfter = self.commandline().optionString("modified-after")
|
||||
self._modifiedAfterTime = seiscomp.core.Time.FromString(modifiedAfter)
|
||||
if self._modifiedAfterTime is None:
|
||||
seiscomp.logging.error(
|
||||
f"Wrong 'modified-after' format '{modifiedAfter}'"
|
||||
)
|
||||
return False
|
||||
seiscomp.logging.debug(
|
||||
f"Setting 'modified-after' time to {self._modifiedAfterTime.toString('%FT%TZ')}"
|
||||
)
|
||||
except RuntimeError:
|
||||
pass
|
||||
|
||||
try:
|
||||
self._preferredOrigin = self.commandline().hasOption("preferred-origin")
|
||||
except RuntimeError:
|
||||
pass
|
||||
|
||||
try:
|
||||
self._eventType = self.commandline().optionString("event-type")
|
||||
except RuntimeError:
|
||||
pass
|
||||
|
||||
if self._eventType:
|
||||
flagEvent = False
|
||||
for i in range(seiscomp.datamodel.EEventTypeQuantity):
|
||||
if self._eventType == seiscomp.datamodel.EEventTypeNames.name(i):
|
||||
flagEvent = True
|
||||
break
|
||||
|
||||
if not flagEvent:
|
||||
seiscomp.logging.error(
|
||||
f"'{self._eventType}' is not a valid SeisComP event type"
|
||||
)
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def printUsage(self):
|
||||
print(
|
||||
f"""Usage:
|
||||
{os.path.basename(__file__)} [options]
|
||||
|
||||
List event IDs available in a given time range and print to stdout."""
|
||||
)
|
||||
|
||||
seiscomp.client.Application.printUsage(self)
|
||||
|
||||
print(
|
||||
f"""Examples:
|
||||
Print all event IDs from year 2022 and thereafter
|
||||
{os.path.basename(__file__)} -d mysql://sysop:sysop@localhost/seiscomp \
|
||||
--begin "2022-01-01 00:00:00"
|
||||
|
||||
Print all event IDs with event type 'quarry blast'
|
||||
{os.path.basename(__file__)} -d mysql://sysop:sysop@localhost/seiscomp --event-type 'quarry blast'
|
||||
|
||||
Print IDs of all events in XML file
|
||||
{os.path.basename(__file__)} -i events.xml
|
||||
"""
|
||||
)
|
||||
|
||||
def run(self):
|
||||
out = []
|
||||
seiscomp.logging.debug(f"Search interval: {self._startTime} - {self._endTime}")
|
||||
|
||||
if self._inputFile:
|
||||
out = readXML(self)
|
||||
sys.stdout.write(f"{self._delimiter.join(out)}\n")
|
||||
return True
|
||||
|
||||
for obj in self.query().getEvents(self._startTime, self._endTime):
|
||||
evt = seiscomp.datamodel.Event.Cast(obj)
|
||||
if not evt:
|
||||
continue
|
||||
|
||||
if self._modifiedAfterTime is not None:
|
||||
try:
|
||||
if evt.creationInfo().modificationTime() < self._modifiedAfterTime:
|
||||
continue
|
||||
except ValueError:
|
||||
try:
|
||||
if evt.creationInfo().creationTime() < self._modifiedAfterTime:
|
||||
continue
|
||||
except ValueError:
|
||||
continue
|
||||
|
||||
if self._eventType:
|
||||
try:
|
||||
eventType = seiscomp.datamodel.EEventTypeNames_name(evt.type())
|
||||
if eventType != self._eventType:
|
||||
continue
|
||||
except ValueError:
|
||||
continue
|
||||
|
||||
outputString = evt.publicID()
|
||||
if self._preferredOrigin:
|
||||
try:
|
||||
outputString += " " + evt.preferredOriginID()
|
||||
except ValueError:
|
||||
outputString += " none"
|
||||
|
||||
out.append(outputString)
|
||||
|
||||
sys.stdout.write(f"{self._delimiter.join(out)}\n")
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def main():
|
||||
app = EventList(len(sys.argv), sys.argv)
|
||||
app()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
Reference in New Issue
Block a user