# https://pyrocko.org - GPLv3
#
# The Pyrocko Developers, 21st Century
# ---|P------/S----------~Lg----------
'''
Effective seismological trace viewer.
'''
import os
import sys
import logging
import gc
import tempfile
import shutil
import glob
from os.path import join as pjoin
from optparse import OptionParser
from pyrocko import deps
from pyrocko import pile as pile_mod
from pyrocko import util
from pyrocko import model
from pyrocko import config
from pyrocko import io
from pyrocko.io import stationxml
from . import marker
logger = logging.getLogger('pyrocko.gui.snuffler.snuffler')
def extend_paths(paths):
paths_r = []
for p in paths:
paths_r.extend(glob.glob(p))
return paths_r
[docs]def snuffle(pile=None, **kwargs):
'''
View pile in a snuffler window.
:param pile: :py:class:`~pyrocko.pile.Pile` object to be visualized
:param stations: list of `pyrocko.model.Station` objects or ``None``
:param events: list of `pyrocko.model.Event` objects or ``None``
:param markers: list of `pyrocko.gui.snuffler.util.Marker` objects or
``None``
:param ntracks: float, number of tracks to be shown initially (default: 12)
:param marker_editor_sortable: bool, whether to allow sorting in marker
table (default True). Disabling this will give better performance
when working with many markers.
:param follow: time interval (in seconds) for real time follow mode or
``None``
:param controls: bool, whether to show the main controls (default:
``True``)
:param opengl: bool, whether to use opengl (default: ``None`` - automatic
choice).
:param paths: list of files and directories to search for trace files
:param pattern: regex which filenames must match
:param format: format of input files
:param cache_dir: cache directory with trace meta information
:param force_cache: bool, whether to use the cache when attribute spoofing
is active
:param store_path: filename template, where to store trace data from input
streams
:param store_interval: float, time interval (in seconds) between stream
buffer dumps
:param want_markers: bool, whether markers should be returned
:param launch_hook: callback function called before snuffler window is
shown
:param instant_close: bool, whether to bypass close window confirmation
dialog
'''
from .snuffler_app import SnufflerWindow, \
setup_acquisition_sources, PollInjector
if pile is None:
pile = pile_mod.make_pile()
from pyrocko.gui import util as gui_util
app = gui_util.get_app()
kwargs_load = {}
for k in ('paths', 'regex', 'format', 'cache_dir', 'force_cache'):
try:
kwargs_load[k] = kwargs.pop(k)
except KeyError:
pass
store_path = kwargs.pop('store_path', None)
store_interval = kwargs.pop('store_interval', 600)
want_markers = kwargs.pop('want_markers', False)
launch_hook = kwargs.pop('launch_hook', None)
win = SnufflerWindow(pile, **kwargs)
app.set_main_window(win)
if launch_hook:
if not isinstance(launch_hook, list):
launch_hook = [launch_hook]
for hook in launch_hook:
hook(win)
sources = []
pollinjector = None
tempdir = None
if 'paths' in kwargs_load:
sources.extend(setup_acquisition_sources(kwargs_load['paths']))
if sources:
if store_path is None:
tempdir = tempfile.mkdtemp('', 'snuffler-tmp-')
store_path = pjoin(
tempdir,
'trace-%(network)s.%(station)s.%(location)s.%(channel)s.'
'%(tmin_ms)s.mseed')
elif os.path.isdir(store_path):
store_path = pjoin(
store_path,
'trace-%(network)s.%(station)s.%(location)s.%(channel)s.'
'%(tmin_ms)s.mseed')
interval = min(
source.get_wanted_poll_interval() for source in sources)
pollinjector = PollInjector(
pile,
fixation_length=store_interval,
path=store_path,
interval=interval)
for source in sources:
source.start()
pollinjector.add_source(source)
win.get_view().load(**kwargs_load)
if not win.is_closing():
app.install_sigint_handler()
try:
app.exec_()
finally:
app.uninstall_sigint_handler()
app.set_main_window(None)
for source in sources:
source.stop()
if pollinjector:
pollinjector.fixate_all()
ret = win.return_tag()
if want_markers:
markers = win.get_view().get_markers()
del win
gc.collect()
if tempdir:
shutil.rmtree(tempdir)
if want_markers:
return ret, markers
else:
return ret
def snuffler_from_commandline(args=None):
if args is None:
args = sys.argv[1:]
usage = '''usage: %prog [options] waveforms ...'''
parser = OptionParser(usage=usage)
parser.add_option(
'--format',
dest='format',
default='detect',
choices=io.allowed_formats('load'),
help='assume input files are of given FORMAT. Choices: %s'
% io.allowed_formats('load', 'cli_help', 'detect'))
parser.add_option(
'--pattern',
dest='regex',
metavar='REGEX',
help='only include files whose paths match REGEX')
parser.add_option(
'--stations',
dest='station_fns',
action='append',
default=[],
metavar='STATIONS',
help='read station information from file STATIONS')
parser.add_option(
'--stationxml',
dest='stationxml_fns',
action='append',
default=[],
metavar='STATIONSXML',
help='read station information from XML file STATIONSXML')
parser.add_option(
'--event', '--events',
dest='event_fns',
action='append',
default=[],
metavar='EVENT',
help='read event information from file EVENT')
parser.add_option(
'--markers',
dest='marker_fns',
action='append',
default=[],
metavar='MARKERS',
help='read marker information file MARKERS')
parser.add_option(
'--follow',
type='float',
dest='follow',
metavar='N',
help='follow real time with a window of N seconds')
parser.add_option(
'--cache',
dest='cache_dir',
default=config.config().cache_dir,
metavar='DIR',
help='use directory DIR to cache trace metadata '
"(default='%default')")
parser.add_option(
'--force-cache',
dest='force_cache',
action='store_true',
default=False,
help='use the cache even when trace attribute spoofing is active '
'(may have silly consequences)')
parser.add_option(
'--store-path',
dest='store_path',
metavar='PATH_TEMPLATE',
help='store data received through streams to PATH_TEMPLATE')
parser.add_option(
'--store-interval',
type='float',
dest='store_interval',
default=600,
metavar='N',
help='dump stream data to file every N seconds [default: %default]')
parser.add_option(
'--ntracks',
type='int',
dest='ntracks',
default=24,
metavar='N',
help='initially use N waveform tracks in viewer [default: %default]')
parser.add_option(
'--disable-marker-sorting',
action='store_false',
dest='marker_editor_sortable',
default=True,
help='disable sorting in marker table for improved performance with '
'100000+ markers')
parser.add_option(
'--hptime',
choices=('on', 'off', 'config'),
dest='hp_time',
default='config',
metavar='on|off|config',
help='set high precision time mode [default: %default]')
parser.add_option(
'--opengl',
dest='opengl',
action='store_true',
default=None,
help='use OpenGL for drawing')
parser.add_option(
'--no-opengl',
dest='opengl',
action='store_false',
default=None,
help='do not use OpenGL for drawing')
parser.add_option(
'--debug',
dest='debug',
action='store_true',
default=False,
help='print debugging information to stderr')
options, args = parser.parse_args(list(args))
if options.debug:
util.setup_logging('snuffler', 'debug')
else:
util.setup_logging('snuffler', 'info')
if options.hp_time in ('on', 'off'):
util.use_high_precision_time(options.hp_time == 'on')
this_pile = pile_mod.Pile()
stations = []
for stations_fn in extend_paths(options.station_fns):
stations.extend(model.station.load_stations(stations_fn))
for stationxml_fn in extend_paths(options.stationxml_fns):
stations.extend(
stationxml.load_xml(
filename=stationxml_fn).get_pyrocko_stations())
events = []
for event_fn in extend_paths(options.event_fns):
events.extend(model.load_events(event_fn))
markers = []
for marker_fn in extend_paths(options.marker_fns):
markers.extend(marker.load_markers(marker_fn))
import pyrocko
try:
return pyrocko.snuffle(
this_pile,
stations=stations,
events=events,
markers=markers,
ntracks=options.ntracks,
marker_editor_sortable=options.marker_editor_sortable,
follow=options.follow,
controls=True,
opengl=options.opengl,
paths=args,
cache_dir=options.cache_dir,
regex=options.regex,
format=options.format,
force_cache=options.force_cache,
store_path=options.store_path,
store_interval=options.store_interval)
except deps.MissingPyrockoDependency as e:
logger.fatal(str(e))
sys.exit(1)
if __name__ == '__main__':
snuffler_from_commandline()