[seiscomp, scanloc] Install, add .gitignore
This commit is contained in:
938
bin/playback_picks
Executable file
938
bin/playback_picks
Executable file
@ -0,0 +1,938 @@
|
||||
#!/usr/bin/env seiscomp-python
|
||||
|
||||
############################################################################
|
||||
# Copyright (C) 2016 by gempa GmbH #
|
||||
# #
|
||||
# All Rights Reserved. #
|
||||
# #
|
||||
# NOTICE: All information contained herein is, and remains #
|
||||
# the property of gempa GmbH and its suppliers, if any. The intellectual #
|
||||
# and technical concepts contained herein are proprietary to gempa GmbH #
|
||||
# and its suppliers. #
|
||||
# Dissemination of this information or reproduction of this material #
|
||||
# is strictly forbidden unless prior written permission is obtained #
|
||||
# from gempa GmbH. #
|
||||
# #
|
||||
# Author: Enrico Ellguth, Dirk Roessler #
|
||||
# Email: enrico.ellguth@gempa.de, roessler@gempa.de #
|
||||
############################################################################
|
||||
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import seiscomp.client
|
||||
import seiscomp.core
|
||||
import seiscomp.io
|
||||
import seiscomp.datamodel
|
||||
|
||||
|
||||
def timing_pickTime(obj):
|
||||
"""
|
||||
Sort picks, origins by their time values
|
||||
Sort amplitudes by their reference time
|
||||
"""
|
||||
|
||||
po = seiscomp.datamodel.Pick.Cast(obj[0])
|
||||
oo = seiscomp.datamodel.Origin.Cast(obj[0])
|
||||
if po or oo:
|
||||
t = obj[0].time().value()
|
||||
else:
|
||||
t = obj[0].timeWindow().reference()
|
||||
|
||||
return t
|
||||
|
||||
|
||||
def timing_creationTime(obj):
|
||||
"""
|
||||
Sort all objects by their creation time
|
||||
"""
|
||||
|
||||
ct = obj[0].creationInfo().creationTime()
|
||||
return ct
|
||||
|
||||
|
||||
def listPicks(self, objects):
|
||||
print(
|
||||
"\n#phase, time , streamID , author, to previous pick "
|
||||
"[s], delay [s]",
|
||||
file=sys.stdout,
|
||||
)
|
||||
|
||||
t0 = None
|
||||
for obj, _ in objects:
|
||||
p = seiscomp.datamodel.Pick.Cast(obj)
|
||||
if not p:
|
||||
continue
|
||||
|
||||
time = p.time().value()
|
||||
try:
|
||||
phase = p.phaseHint().code()
|
||||
except ValueError:
|
||||
phase = "None"
|
||||
wfID = p.waveformID()
|
||||
net = wfID.networkCode()
|
||||
sta = wfID.stationCode()
|
||||
loc = wfID.locationCode()
|
||||
cha = wfID.channelCode()
|
||||
try:
|
||||
author = p.creationInfo().author()
|
||||
except ValueError:
|
||||
author = "None"
|
||||
try:
|
||||
delay = f"{(p.creationInfo().creationTime() - time).toDouble():.3f}"
|
||||
except ValueError:
|
||||
delay = "None"
|
||||
|
||||
if t0 is not None:
|
||||
deltaT = f"{(time - t0).toDouble():.3f}"
|
||||
else:
|
||||
deltaT = "None"
|
||||
|
||||
streamID = f"{net}.{sta}.{loc}.{cha}"
|
||||
print(
|
||||
f"{phase: <6}, {time.toString('%FT%T')}.{int(time.microseconds()/1000):03d}"
|
||||
f", {streamID: <15}, {author}, {deltaT}, {delay}",
|
||||
file=sys.stdout,
|
||||
)
|
||||
|
||||
t0 = time
|
||||
return True
|
||||
|
||||
|
||||
def printStatistics(ep):
|
||||
minPickTime = None
|
||||
maxPickTime = None
|
||||
minPickCTime = None
|
||||
maxPickCTime = None
|
||||
minAmplitudeTime = None
|
||||
maxAmplitudeTime = None
|
||||
minOriginTime = None
|
||||
maxOriginTime = None
|
||||
minOriginCTime = None
|
||||
maxOriginCTime = None
|
||||
|
||||
# read picks
|
||||
nslc = set()
|
||||
authorPick = set()
|
||||
authorAmplitude = set()
|
||||
authorOrigin = set()
|
||||
detectionStreams = set()
|
||||
cntPick = ep.pickCount()
|
||||
for i in range(cntPick):
|
||||
pick = ep.pick(i)
|
||||
|
||||
try:
|
||||
authorPick.add(pick.creationInfo().author())
|
||||
except ValueError:
|
||||
print(
|
||||
f"Author information not found in pick {pick.publicID()}: NSLC list may"
|
||||
" be incomplete",
|
||||
file=sys.stderr,
|
||||
)
|
||||
|
||||
try:
|
||||
net = pick.waveformID().networkCode()
|
||||
sta = pick.waveformID().stationCode()
|
||||
loc = pick.waveformID().locationCode()
|
||||
cha = pick.waveformID().channelCode()
|
||||
nslc.add(f"{net}.{sta}.{loc}.{cha}")
|
||||
detectionStreams.add(f".{loc}.{cha}")
|
||||
except ValueError:
|
||||
print(
|
||||
f"Stream information not found in pick {pick.publicID()}: NSLC list "
|
||||
"may be incomplete",
|
||||
file=sys.stderr,
|
||||
)
|
||||
|
||||
if not minPickTime:
|
||||
minPickTime = pick.time().value()
|
||||
elif pick.time().value() < minPickTime:
|
||||
minPickTime = pick.time().value()
|
||||
|
||||
if not maxPickTime:
|
||||
maxPickTime = pick.time().value()
|
||||
elif pick.time().value() > maxPickTime:
|
||||
maxPickTime = pick.time().value()
|
||||
|
||||
try:
|
||||
pick.creationInfo().creationTime()
|
||||
except ValueError:
|
||||
print(
|
||||
f"Creation time not found in pick {pick.publicID()}: Statistics may "
|
||||
"be incomplete",
|
||||
file=sys.stderr,
|
||||
)
|
||||
continue
|
||||
|
||||
if not minPickCTime:
|
||||
minPickCTime = pick.creationInfo().creationTime()
|
||||
elif pick.creationInfo().creationTime() < minPickCTime:
|
||||
minPickCTime = pick.creationInfo().creationTime()
|
||||
|
||||
if not maxPickCTime:
|
||||
maxPickCTime = pick.creationInfo().creationTime()
|
||||
elif pick.creationInfo().creationTime() > maxPickCTime:
|
||||
maxPickCTime = pick.creationInfo().creationTime()
|
||||
|
||||
# read amplitudes
|
||||
cntAmp = ep.amplitudeCount()
|
||||
for i in range(cntAmp):
|
||||
amp = ep.amplitude(i)
|
||||
try:
|
||||
authorAmplitude.add(amp.creationInfo().author())
|
||||
except ValueError:
|
||||
print(
|
||||
f"Author information not found in amplitude {amp.publicID()}: NSLC "
|
||||
"list may be incomplete",
|
||||
file=sys.stderr,
|
||||
)
|
||||
try:
|
||||
net = amp.waveformID().networkCode()
|
||||
sta = amp.waveformID().stationCode()
|
||||
loc = amp.waveformID().locationCode()
|
||||
cha = amp.waveformID().channelCode()
|
||||
nslc.add(f"{net}.{sta}.{loc}.{cha}")
|
||||
detectionStreams.add(f".{loc}.{cha}")
|
||||
except ValueError:
|
||||
print(
|
||||
f"Stream information not found in amplitude {amp.publicID()}: NSLC "
|
||||
"list may be incomplete",
|
||||
file=sys.stderr,
|
||||
)
|
||||
|
||||
if not minAmplitudeTime:
|
||||
minAmplitudeTime = amp.timeWindow().reference()
|
||||
elif amp.timeWindow().reference() < minAmplitudeTime:
|
||||
minAmplitudeTime = amp.timeWindow().reference()
|
||||
|
||||
if not maxAmplitudeTime:
|
||||
maxAmplitudeTime = amp.timeWindow().reference()
|
||||
elif amp.timeWindow().reference() > maxAmplitudeTime:
|
||||
maxAmplitudeTime = amp.timeWindow().reference()
|
||||
|
||||
# read origins
|
||||
cntOrg = ep.originCount()
|
||||
for i in range(cntOrg):
|
||||
oo = ep.origin(i)
|
||||
|
||||
try:
|
||||
authorOrigin.add(oo.creationInfo().author())
|
||||
except ValueError:
|
||||
print(
|
||||
f"Author information not found in origin {oo.publicID()}:",
|
||||
file=sys.stderr,
|
||||
)
|
||||
|
||||
if not minOriginTime:
|
||||
minOriginTime = oo.time().value()
|
||||
elif oo.time().value() < minOriginTime:
|
||||
minOriginTime = oo.time().value()
|
||||
|
||||
if not maxOriginTime:
|
||||
maxOriginTime = oo.time().value()
|
||||
elif oo.time().value() > maxOriginTime:
|
||||
maxOriginTime = oo.time().value()
|
||||
|
||||
try:
|
||||
oo.creationInfo().creationTime()
|
||||
except ValueError:
|
||||
print(
|
||||
f"Creation time not found in oo {oo.publicID()}: Statistics may "
|
||||
"be incomplete",
|
||||
file=sys.stderr,
|
||||
)
|
||||
continue
|
||||
|
||||
if not minOriginCTime:
|
||||
minOriginCTime = oo.creationInfo().creationTime()
|
||||
elif oo.creationInfo().creationTime() < minOriginCTime:
|
||||
minOriginCTime = oo.creationInfo().creationTime()
|
||||
|
||||
if not maxOriginCTime:
|
||||
maxOriginCTime = oo.creationInfo().creationTime()
|
||||
elif oo.creationInfo().creationTime() > maxOriginCTime:
|
||||
maxOriginCTime = oo.creationInfo().creationTime()
|
||||
|
||||
print(
|
||||
f"""
|
||||
Picks
|
||||
+ number: {cntPick}
|
||||
+ first pick: {minPickTime}
|
||||
+ last pick: {maxPickTime}""",
|
||||
file=sys.stdout,
|
||||
)
|
||||
if cntPick > 0:
|
||||
print(
|
||||
f""" + interval: {(maxPickTime - minPickTime).toDouble():.3f} s""",
|
||||
file=sys.stdout,
|
||||
)
|
||||
try:
|
||||
print(
|
||||
f""" + first created: {minPickCTime}
|
||||
+ last created: {maxPickCTime}
|
||||
+ interval: {(maxPickCTime - minPickCTime).toDouble():.3f} s""",
|
||||
file=sys.stdout,
|
||||
)
|
||||
except TypeError:
|
||||
print(
|
||||
""" + first created: no creation information
|
||||
+ last created: no creation information
|
||||
+ interval: no creation information""",
|
||||
file=sys.stdout,
|
||||
)
|
||||
pass
|
||||
|
||||
print(f" + found {len(authorPick)} pick author(s):", file=sys.stdout)
|
||||
for i in authorPick:
|
||||
print(f" + {i}", file=sys.stdout)
|
||||
|
||||
print(
|
||||
f"""
|
||||
Amplitudes
|
||||
+ number: {cntAmp}""",
|
||||
file=sys.stdout,
|
||||
)
|
||||
if cntAmp > 0:
|
||||
print(
|
||||
f""" + first amplitude: {minAmplitudeTime}
|
||||
+ last amplitude: {maxAmplitudeTime}
|
||||
+ interval: {(maxAmplitudeTime - minAmplitudeTime).toDouble():.3f} s""",
|
||||
file=sys.stdout,
|
||||
)
|
||||
print(f" + found {len(authorAmplitude)} amplitude author(s):", file=sys.stdout)
|
||||
for i in authorAmplitude:
|
||||
print(f" + {i}", file=sys.stdout)
|
||||
|
||||
print(
|
||||
f"""
|
||||
Origins
|
||||
+ number: {cntOrg}""",
|
||||
file=sys.stdout,
|
||||
)
|
||||
if cntOrg > 0:
|
||||
print(
|
||||
f""" + first origin: {minOriginTime}
|
||||
+ last origin: {maxOriginTime}
|
||||
+ interval: {(maxOriginTime - minOriginTime).toDouble():.3f} s""",
|
||||
file=sys.stdout,
|
||||
)
|
||||
try:
|
||||
print(
|
||||
f""" + first created: {minOriginCTime}
|
||||
+ last created: {maxOriginCTime}
|
||||
+ interval: {(maxOriginCTime - minOriginCTime).toDouble():.3f} s""",
|
||||
file=sys.stdout,
|
||||
)
|
||||
except TypeError:
|
||||
print(
|
||||
""" + first created: no creation information
|
||||
+ last created: no creation information
|
||||
+ interval: no creation information""",
|
||||
file=sys.stdout,
|
||||
)
|
||||
pass
|
||||
|
||||
print(f" + found {len(authorOrigin)} origin author(s):", file=sys.stdout)
|
||||
for i in authorOrigin:
|
||||
print(f" + {i}", file=sys.stdout)
|
||||
|
||||
# stream information
|
||||
print(f"\nFound {len(detectionStreams)} SensorLocation.Channel:", file=sys.stdout)
|
||||
for i in detectionStreams:
|
||||
print(f" + {i}", file=sys.stdout)
|
||||
|
||||
print(f"\nFound {len(nslc)} streams:", file=sys.stdout)
|
||||
for i in sorted(nslc):
|
||||
print(f" + {i}", file=sys.stdout)
|
||||
|
||||
return True
|
||||
|
||||
|
||||
class PickPlayback(seiscomp.client.Application):
|
||||
def __init__(self, argc, argv):
|
||||
super().__init__(argc, argv)
|
||||
|
||||
self.speed = 1.0
|
||||
self.timing = "creationTime"
|
||||
self.jump = 0.0
|
||||
self.print = False
|
||||
self.printList = False
|
||||
self.group = "PICK"
|
||||
self.ampGroup = "AMPLITUDE"
|
||||
self.orgGroup = "LOCATION"
|
||||
self.fileNames = None
|
||||
self.mode = "historic"
|
||||
self.authors = None
|
||||
self.objects = None
|
||||
|
||||
self.setMessagingUsername("pbpick")
|
||||
self.setMessagingEnabled(True)
|
||||
self.setPrimaryMessagingGroup("PICK")
|
||||
self.setDatabaseEnabled(False, False)
|
||||
|
||||
def createCommandLineDescription(self):
|
||||
self.commandline().addGroup("Playback")
|
||||
self.commandline().addStringOption(
|
||||
"Playback",
|
||||
"authors",
|
||||
"Author of objects to filter before playing back. Objects from all other "
|
||||
"authors are ignored. Separate multiple authors by comma.",
|
||||
)
|
||||
self.commandline().addDoubleOption(
|
||||
"Playback", "jump,j", "Minutes to skip objects in the beginning."
|
||||
)
|
||||
self.commandline().addOption(
|
||||
"Playback",
|
||||
"list",
|
||||
"Just list important pick information from the read XML file and then "
|
||||
"exit without playing back. The sorting of the list depends on '--timing'."
|
||||
"Information include: phase hint, pick time, stream ID, author, time to "
|
||||
"previous pick, delay.",
|
||||
)
|
||||
self.commandline().addStringOption(
|
||||
"Playback",
|
||||
"mode",
|
||||
"Playback mode: 'historic' or 'realTime'. "
|
||||
"'realTime' mimics current situation. Default: 'historic'.",
|
||||
)
|
||||
self.commandline().addStringOption(
|
||||
"Playback",
|
||||
"object,o",
|
||||
"Limit the playback to the given list of objects. Supported values are: \n"
|
||||
"pick, amplitude, origin.",
|
||||
)
|
||||
self.commandline().addOption(
|
||||
"Playback",
|
||||
"print",
|
||||
"Just print some statistics of the read XML file and then "
|
||||
"exit without playing back. The list of stream codes (NSLC) is printed to "
|
||||
"stdout. All other information is printed to stderr. The information can "
|
||||
"be used for filtering waveforms (scart) or inventory (invextr), for "
|
||||
"creating global bindings or applying author filtering, e.g., in "
|
||||
"dump_picks.",
|
||||
)
|
||||
self.commandline().addDoubleOption(
|
||||
"Playback", "speed", "Speed of playback.\n1: true speed."
|
||||
)
|
||||
self.commandline().addStringOption(
|
||||
"Playback",
|
||||
"timing",
|
||||
"Timing reference: pickTime or creationTime. Default: creationTime. "
|
||||
"'pickTime' plays back in order of actual times of objects, "
|
||||
"'creationTime' considers their creation times instead. Use 'pickTime' if "
|
||||
"creation times are not representative of the order of objects, e.g., when "
|
||||
"created in playbacks. 'creationTime' should be considered for playing "
|
||||
"back origins since their actual origin time values are always before "
|
||||
"picks and amplitudes.",
|
||||
)
|
||||
|
||||
def printUsage(self):
|
||||
print(
|
||||
f"""Usage:
|
||||
{os.path.basename(__file__)} [options] [XML file][:PICK:AMPLITUDE:LOCATION]
|
||||
|
||||
Play back pick, amplitude and origin objects from one or more XML files in SCML format
|
||||
sending them to the SeisComP messaging in timely order. Default message groups:
|
||||
* PICK for picks,
|
||||
* AMPLITUDE for amplitudes.
|
||||
* LOCATION for origins,"""
|
||||
)
|
||||
|
||||
super().printUsage()
|
||||
|
||||
print(
|
||||
f"""Examples:
|
||||
Play back picks and other objects in file 'pick.xml' at true speed jumping the
|
||||
first 2 minutes
|
||||
{os.path.basename(__file__)} -j 2 picks.xml
|
||||
|
||||
Play back picks and other objects from 2 XML files sending the picks, amplitudes
|
||||
and origins ordered by creation time to different message groups but amplitudes
|
||||
to the same default group (AMPLITUDE).
|
||||
{os.path.basename(__file__)} origins.xml l1origins.xml:L1PICK:AMPLITUDE:L1LOCATION
|
||||
|
||||
Just print statistics and stream information
|
||||
{os.path.basename(__file__)} --print picks.xml
|
||||
"""
|
||||
)
|
||||
|
||||
def init(self):
|
||||
if not super().init():
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def validateParameters(self):
|
||||
if not super().validateParameters():
|
||||
return False
|
||||
|
||||
try:
|
||||
self.authors = self.commandline().optionString("authors").split(",")
|
||||
except RuntimeError:
|
||||
pass
|
||||
|
||||
try:
|
||||
self.mode = self.commandline().optionString("mode")
|
||||
except RuntimeError:
|
||||
pass
|
||||
|
||||
try:
|
||||
self.objects = self.commandline().optionString("object")
|
||||
except RuntimeError:
|
||||
pass
|
||||
|
||||
if self.mode not in ("historic", "realTime"):
|
||||
print(f"Unknown mode: {self.mode}", file=sys.stderr)
|
||||
return False
|
||||
|
||||
try:
|
||||
self.print = self.commandline().hasOption("print")
|
||||
except RuntimeError:
|
||||
pass
|
||||
|
||||
try:
|
||||
self.printList = self.commandline().hasOption("list")
|
||||
except RuntimeError:
|
||||
pass
|
||||
|
||||
try:
|
||||
self.speed = self.commandline().optionDouble("speed")
|
||||
except RuntimeError:
|
||||
pass
|
||||
|
||||
try:
|
||||
self.timing = self.commandline().optionString("timing")
|
||||
except RuntimeError:
|
||||
pass
|
||||
|
||||
try:
|
||||
self.jump = self.commandline().optionDouble("jump")
|
||||
except RuntimeError:
|
||||
pass
|
||||
|
||||
if self.timing not in ("pickTime", "creationTime"):
|
||||
print(f"Unknown timing: {self.timing}", file=sys.stderr)
|
||||
return False
|
||||
|
||||
try:
|
||||
self.group = self.commandline().optionString("primary-group")
|
||||
except RuntimeError:
|
||||
pass
|
||||
|
||||
files = self.commandline().unrecognizedOptions()
|
||||
if not files:
|
||||
print("At least one XML file must be given!", file=sys.stderr)
|
||||
return False
|
||||
|
||||
print(files, file=sys.stderr)
|
||||
self.fileNames = list(files)
|
||||
|
||||
if self.print or self.printList:
|
||||
self.setMessagingEnabled(False)
|
||||
|
||||
return True
|
||||
|
||||
def run(self):
|
||||
seiscomp.datamodel.PublicObject.SetRegistrationEnabled(False)
|
||||
|
||||
objects = []
|
||||
eps = []
|
||||
|
||||
minTime = None
|
||||
maxTime = None
|
||||
|
||||
print("Input:", file=sys.stdout)
|
||||
for fileName in self.fileNames:
|
||||
group = self.group
|
||||
ampGroup = self.ampGroup
|
||||
orgGroup = self.orgGroup
|
||||
|
||||
toks = fileName.split(":")
|
||||
if len(toks) == 2:
|
||||
fileName = toks[0]
|
||||
group = toks[1]
|
||||
|
||||
elif len(toks) == 3:
|
||||
fileName = toks[0]
|
||||
group = toks[1]
|
||||
ampGroup = toks[2]
|
||||
|
||||
elif len(toks) == 4:
|
||||
fileName = toks[0]
|
||||
group = toks[1]
|
||||
ampGroup = toks[2]
|
||||
orgGroup = toks[3]
|
||||
|
||||
print(
|
||||
f" + file: {fileName}",
|
||||
file=sys.stdout,
|
||||
)
|
||||
|
||||
ar = seiscomp.io.XMLArchive()
|
||||
if not ar.open(fileName):
|
||||
print(f"Could not open {fileName}", file=sys.stderr)
|
||||
return False
|
||||
|
||||
obj = ar.readObject()
|
||||
ar.close()
|
||||
|
||||
if obj is None:
|
||||
print("Empty document", file=sys.stderr)
|
||||
return False
|
||||
|
||||
ep = seiscomp.datamodel.EventParameters.Cast(obj)
|
||||
|
||||
if self.print:
|
||||
printStatistics(ep)
|
||||
if not self.printList:
|
||||
return True
|
||||
|
||||
eps.append(ep)
|
||||
|
||||
if ep is None:
|
||||
print(
|
||||
f"Expected event parameters, got {obj.className()}", file=sys.stderr
|
||||
)
|
||||
return False
|
||||
|
||||
# read picks
|
||||
cntPick = ep.pickCount()
|
||||
if cntPick == 0:
|
||||
print(f"No picks found in file {fileName}", file=sys.stderr)
|
||||
|
||||
if self.objects is not None and "pick" not in self.objects:
|
||||
print(
|
||||
f"Skipping picks. Supported objects: {self.objects}",
|
||||
file=sys.stderr,
|
||||
)
|
||||
cntPick = 0
|
||||
|
||||
for i in range(cntPick):
|
||||
pick = ep.pick(i)
|
||||
if self.authors is not None:
|
||||
try:
|
||||
if (
|
||||
pick.creationInfo().author() not in self.authors
|
||||
and not self.printList
|
||||
):
|
||||
print(
|
||||
f"Skipping pick {pick.publicID()}: "
|
||||
f"{pick.creationInfo().author()} not in author list",
|
||||
file=sys.stderr,
|
||||
)
|
||||
continue
|
||||
except ValueError:
|
||||
if not self.printList:
|
||||
print(
|
||||
f"Skipping pick {pick.publicID()}: "
|
||||
f"author is not available",
|
||||
file=sys.stderr,
|
||||
)
|
||||
continue
|
||||
|
||||
if self.timing == "creationTime":
|
||||
try:
|
||||
pick.creationInfo().creationTime()
|
||||
except Exception:
|
||||
if not self.printList:
|
||||
print(
|
||||
f"Skipping pick {pick.publicID()}: no creation time",
|
||||
file=sys.stderr,
|
||||
)
|
||||
continue
|
||||
|
||||
# filter by time
|
||||
if minTime and pick.time().value() < minTime:
|
||||
continue
|
||||
if maxTime and pick.time().value() >= maxTime:
|
||||
continue
|
||||
objects.append((pick, group))
|
||||
|
||||
# read amplitudes and add to objects
|
||||
cntAmp = ep.amplitudeCount()
|
||||
if cntAmp == 0:
|
||||
print("No Amplitudes found", file=sys.stderr)
|
||||
|
||||
if self.objects is not None and "amplitude" not in self.objects:
|
||||
print(
|
||||
f"Skipping amplitudes. Supported objects: {self.objects}",
|
||||
file=sys.stderr,
|
||||
)
|
||||
cntAmp = 0
|
||||
|
||||
for i in range(cntAmp):
|
||||
amp = ep.amplitude(i)
|
||||
if self.authors is not None:
|
||||
try:
|
||||
if (
|
||||
amp.creationInfo().author() not in self.authors
|
||||
and not self.printList
|
||||
):
|
||||
print(
|
||||
f"Skipping amplitude {amp.publicID()}: "
|
||||
f"{amp.creationInfo().author()} not in author list",
|
||||
file=sys.stderr,
|
||||
)
|
||||
continue
|
||||
except ValueError:
|
||||
if not self.printList:
|
||||
print(
|
||||
f"Skipping amplitude {amp.publicID()}: "
|
||||
f"author is not available",
|
||||
file=sys.stderr,
|
||||
)
|
||||
continue
|
||||
|
||||
if self.timing == "creationTime":
|
||||
try:
|
||||
amp.creationInfo().creationTime()
|
||||
except Exception:
|
||||
print(
|
||||
f"Skipping amplitude {amp.publicID()}: no creation time",
|
||||
file=sys.stderr,
|
||||
)
|
||||
continue
|
||||
|
||||
objects.append((amp, ampGroup))
|
||||
|
||||
# read origins and add to objects
|
||||
cntOrgs = ep.originCount()
|
||||
if cntOrgs == 0:
|
||||
print("No Origins found", file=sys.stderr)
|
||||
|
||||
if self.objects is not None and "origin" not in self.objects:
|
||||
print(
|
||||
f"Skipping origins. Supported objects: {self.objects}",
|
||||
file=sys.stderr,
|
||||
)
|
||||
cntOrgs = 0
|
||||
|
||||
for i in range(cntOrgs):
|
||||
oo = ep.origin(i)
|
||||
|
||||
if self.authors is not None:
|
||||
try:
|
||||
if (
|
||||
oo.creationInfo().author() not in self.authors
|
||||
and not self.printList
|
||||
):
|
||||
print(
|
||||
f"Skipping origin {oo.publicID()}: "
|
||||
f"{oo.creationInfo().author()} not in author list",
|
||||
file=sys.stderr,
|
||||
)
|
||||
continue
|
||||
except ValueError:
|
||||
if not self.printList:
|
||||
print(
|
||||
f"Skipping origin {oo.publicID()}: "
|
||||
f"author is not available",
|
||||
file=sys.stderr,
|
||||
)
|
||||
continue
|
||||
|
||||
if self.timing == "creationTime":
|
||||
try:
|
||||
oo.creationInfo().creationTime()
|
||||
except Exception:
|
||||
try:
|
||||
string = oo.publicID().split("/")[1].split(".")[:2]
|
||||
timeString = string[0] + "." + string[1]
|
||||
timeFormat = "%Y%m%d%H%M%S.%f"
|
||||
t = seiscomp.core.Time()
|
||||
t.fromString(str(timeString), timeFormat)
|
||||
ci = seiscomp.datamodel.CreationInfo()
|
||||
ci.setCreationTime(t)
|
||||
oo.setCreationInfo(ci)
|
||||
print(
|
||||
f"creation time not found in origin {oo.publicID()}: "
|
||||
f"assuming {oo.creationInfo().creationTime()} from "
|
||||
"originID ",
|
||||
file=sys.stderr,
|
||||
)
|
||||
except Exception:
|
||||
if not self.printList:
|
||||
print(
|
||||
f"Skipping origin {oo.publicID()}: no creation time",
|
||||
file=sys.stderr,
|
||||
)
|
||||
continue
|
||||
|
||||
objects.append((oo, orgGroup))
|
||||
|
||||
print(
|
||||
f" + considering {cntPick} picks, {cntAmp} amplitudes, {cntOrgs} origins",
|
||||
file=sys.stdout,
|
||||
)
|
||||
if self.print or self.printList:
|
||||
print(" + do not send objects to messaging")
|
||||
else:
|
||||
print(
|
||||
f""" + sending objects to groups
|
||||
+ picks: {group}
|
||||
+ amplitudes: {ampGroup}
|
||||
+ origins: {orgGroup}""",
|
||||
file=sys.stdout,
|
||||
)
|
||||
|
||||
if self.timing == "pickTime":
|
||||
try:
|
||||
objects.sort(key=timing_pickTime)
|
||||
except ValueError:
|
||||
print("Time value not set in at least 1 object", file=sys.stderr)
|
||||
if not self.printList:
|
||||
return False
|
||||
elif self.timing == "creationTime":
|
||||
try:
|
||||
objects.sort(key=timing_creationTime)
|
||||
except ValueError:
|
||||
print("Creation time not set in at least 1 object", file=sys.stderr)
|
||||
if not self.printList:
|
||||
return False
|
||||
else:
|
||||
print(f"Unknown timing: {self.timing}", file=sys.stderr)
|
||||
return False
|
||||
|
||||
print("Setup:", file=sys.stdout)
|
||||
print(f" + author filter: {self.authors}", file=sys.stdout)
|
||||
print(f" + timing/sorting: {self.timing}", file=sys.stdout)
|
||||
|
||||
if self.printList:
|
||||
listPicks(self, objects)
|
||||
return True
|
||||
|
||||
seiscomp.datamodel.Notifier.Enable()
|
||||
|
||||
firstTime = None
|
||||
lastTime = None
|
||||
refTime = None
|
||||
addSeconds = 0.0
|
||||
|
||||
sys.stdout.flush()
|
||||
|
||||
for obj, group in objects:
|
||||
po = seiscomp.datamodel.Pick.Cast(obj)
|
||||
ao = seiscomp.datamodel.Amplitude.Cast(obj)
|
||||
oo = seiscomp.datamodel.Origin.Cast(obj)
|
||||
|
||||
if self.isExitRequested():
|
||||
break
|
||||
|
||||
if self.timing == "pickTime":
|
||||
if ao:
|
||||
refTime = obj.timeWindow().reference()
|
||||
elif po:
|
||||
refTime = obj.time().value()
|
||||
elif oo:
|
||||
refTime = obj.time().value()
|
||||
else:
|
||||
print(
|
||||
"Object neither pick nor amplitude or origin- ignoring",
|
||||
file=sys.stderr,
|
||||
)
|
||||
return False
|
||||
else:
|
||||
refTime = obj.creationInfo().creationTime()
|
||||
|
||||
if not firstTime:
|
||||
firstTime = refTime
|
||||
|
||||
print(f" + first time: {firstTime}", file=sys.stderr)
|
||||
print(f" + playback mode: {self.mode}", file=sys.stderr)
|
||||
print(f" + speed factor: {self.speed}", file=sys.stderr)
|
||||
|
||||
if self.mode == "realTime":
|
||||
now = seiscomp.core.Time.GMT()
|
||||
addSeconds = (now - firstTime).toDouble()
|
||||
print(
|
||||
f" + adding {addSeconds: .3f} s to: pick time, amplitude "
|
||||
"reference time, origin time, creation time",
|
||||
file=sys.stderr,
|
||||
)
|
||||
|
||||
print("Playback progress:", file=sys.stderr)
|
||||
|
||||
objectType = "pick"
|
||||
if ao:
|
||||
objectType = "amplitude"
|
||||
if oo:
|
||||
objectType = "origin"
|
||||
|
||||
print(
|
||||
f" + {obj.publicID()} {objectType}: {group} - reference time: {refTime}",
|
||||
end="",
|
||||
file=sys.stderr,
|
||||
)
|
||||
|
||||
# add addSeconds to all times in real-time mode
|
||||
if self.mode == "realTime":
|
||||
objectInfo = obj.creationInfo()
|
||||
creationTime = objectInfo.creationTime() + seiscomp.core.TimeSpan(
|
||||
addSeconds
|
||||
)
|
||||
obj.creationInfo().setCreationTime(creationTime)
|
||||
|
||||
if ao:
|
||||
objectInfo = obj.timeWindow()
|
||||
amplitudeTime = objectInfo.reference() + seiscomp.core.TimeSpan(
|
||||
addSeconds
|
||||
)
|
||||
obj.timeWindow().setReference(amplitudeTime)
|
||||
print(
|
||||
"\n + real-time mode - using modified reference time: "
|
||||
f"{obj.timeWindow().reference()}, creation time: {creationTime}",
|
||||
end="",
|
||||
file=sys.stderr,
|
||||
)
|
||||
elif po or oo:
|
||||
objectTime = obj.time()
|
||||
objectTime.setValue(
|
||||
objectTime.value() + seiscomp.core.TimeSpan(addSeconds)
|
||||
)
|
||||
obj.setTime(objectTime)
|
||||
print(
|
||||
f"\n + real-time mode - using modified {objectType} time: "
|
||||
f"{obj.time().value()}, creation time: {creationTime}",
|
||||
end="",
|
||||
file=sys.stderr,
|
||||
)
|
||||
else:
|
||||
print(
|
||||
"\n + object not pick, amplitude or origin - ignoring",
|
||||
file=sys.stderr,
|
||||
)
|
||||
return False
|
||||
|
||||
delay = 0
|
||||
if lastTime:
|
||||
delay = (refTime - lastTime).toDouble() / self.speed
|
||||
|
||||
if (refTime - firstTime).toDouble() / 60.0 >= self.jump:
|
||||
delay = max(delay, 0)
|
||||
|
||||
print(f" - time to sending: {delay:.4f} s", file=sys.stderr)
|
||||
time.sleep(delay)
|
||||
|
||||
lastTime = refTime
|
||||
|
||||
nc = seiscomp.datamodel.NotifierCreator(seiscomp.datamodel.OP_ADD)
|
||||
obj.accept(nc)
|
||||
msg = seiscomp.datamodel.Notifier.GetMessage()
|
||||
self.connection().send(group, msg)
|
||||
else:
|
||||
print(" - skipping", file=sys.stderr)
|
||||
|
||||
sys.stdout.flush()
|
||||
|
||||
print("")
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def main(argv):
|
||||
app = PickPlayback(len(argv), argv)
|
||||
return app()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main(sys.argv))
|
Reference in New Issue
Block a user