Coverage for /usr/local/lib/python3.11/dist-packages/pyrocko/gui/snuffler/snuffler.py: 62%
130 statements
« prev ^ index » next coverage.py v6.5.0, created at 2023-10-06 15:01 +0000
« prev ^ index » next coverage.py v6.5.0, created at 2023-10-06 15:01 +0000
1# https://pyrocko.org - GPLv3
2#
3# The Pyrocko Developers, 21st Century
4# ---|P------/S----------~Lg----------
6'''
7Effective seismological trace viewer.
8'''
10import os
11import sys
12import logging
13import gc
14import tempfile
15import shutil
16import glob
18from os.path import join as pjoin
19from optparse import OptionParser
22from pyrocko import deps
23from pyrocko import pile as pile_mod
24from pyrocko import util
25from pyrocko import model
26from pyrocko import config
27from pyrocko import io
28from pyrocko.io import stationxml
30from . import marker
33logger = logging.getLogger('pyrocko.gui.snuffler.snuffler')
36def extend_paths(paths):
37 paths_r = []
38 for p in paths:
39 paths_r.extend(glob.glob(p))
40 return paths_r
43def snuffle(pile=None, **kwargs):
44 '''
45 View pile in a snuffler window.
47 :param pile: :py:class:`~pyrocko.pile.Pile` object to be visualized
48 :param stations: list of `pyrocko.model.Station` objects or ``None``
49 :param events: list of `pyrocko.model.Event` objects or ``None``
50 :param markers: list of `pyrocko.gui.snuffler.util.Marker` objects or
51 ``None``
52 :param ntracks: float, number of tracks to be shown initially (default: 12)
53 :param marker_editor_sortable: bool, whether to allow sorting in marker
54 table (default True). Disabling this will give better performance
55 when working with many markers.
56 :param follow: time interval (in seconds) for real time follow mode or
57 ``None``
58 :param controls: bool, whether to show the main controls (default:
59 ``True``)
60 :param opengl: bool, whether to use opengl (default: ``None`` - automatic
61 choice).
62 :param paths: list of files and directories to search for trace files
63 :param pattern: regex which filenames must match
64 :param format: format of input files
65 :param cache_dir: cache directory with trace meta information
66 :param force_cache: bool, whether to use the cache when attribute spoofing
67 is active
68 :param store_path: filename template, where to store trace data from input
69 streams
70 :param store_interval: float, time interval (in seconds) between stream
71 buffer dumps
72 :param want_markers: bool, whether markers should be returned
73 :param launch_hook: callback function called before snuffler window is
74 shown
75 :param instant_close: bool, whether to bypass close window confirmation
76 dialog
77 '''
78 from .snuffler_app import SnufflerWindow, \
79 setup_acquisition_sources, PollInjector
81 if pile is None:
82 pile = pile_mod.make_pile()
84 from pyrocko.gui import util as gui_util
85 app = gui_util.get_app()
87 kwargs_load = {}
88 for k in ('paths', 'regex', 'format', 'cache_dir', 'force_cache'):
89 try:
90 kwargs_load[k] = kwargs.pop(k)
91 except KeyError:
92 pass
94 store_path = kwargs.pop('store_path', None)
95 store_interval = kwargs.pop('store_interval', 600)
96 want_markers = kwargs.pop('want_markers', False)
97 launch_hook = kwargs.pop('launch_hook', None)
99 win = SnufflerWindow(pile, **kwargs)
100 app.set_main_window(win)
102 if launch_hook:
103 if not isinstance(launch_hook, list):
104 launch_hook = [launch_hook]
105 for hook in launch_hook:
106 hook(win)
108 sources = []
109 pollinjector = None
110 tempdir = None
111 if 'paths' in kwargs_load:
112 sources.extend(setup_acquisition_sources(kwargs_load['paths']))
113 if sources:
114 if store_path is None:
115 tempdir = tempfile.mkdtemp('', 'snuffler-tmp-')
116 store_path = pjoin(
117 tempdir,
118 'trace-%(network)s.%(station)s.%(location)s.%(channel)s.'
119 '%(tmin_ms)s.mseed')
120 elif os.path.isdir(store_path):
121 store_path = pjoin(
122 store_path,
123 'trace-%(network)s.%(station)s.%(location)s.%(channel)s.'
124 '%(tmin_ms)s.mseed')
126 interval = min(
127 source.get_wanted_poll_interval() for source in sources)
129 pollinjector = PollInjector(
130 pile,
131 fixation_length=store_interval,
132 path=store_path,
133 interval=interval)
135 for source in sources:
136 source.start()
137 pollinjector.add_source(source)
139 win.get_view().load(**kwargs_load)
141 if not win.is_closing():
142 app.install_sigint_handler()
143 try:
144 app.exec_()
146 finally:
147 app.uninstall_sigint_handler()
148 app.set_main_window(None)
150 for source in sources:
151 source.stop()
153 if pollinjector:
154 pollinjector.fixate_all()
156 ret = win.return_tag()
158 if want_markers:
159 markers = win.get_view().get_markers()
161 del win
162 gc.collect()
164 if tempdir:
165 shutil.rmtree(tempdir)
167 if want_markers:
168 return ret, markers
169 else:
170 return ret
173def snuffler_from_commandline(args=None):
174 if args is None:
175 args = sys.argv[1:]
177 usage = '''usage: %prog [options] waveforms ...'''
178 parser = OptionParser(usage=usage)
180 parser.add_option(
181 '--format',
182 dest='format',
183 default='detect',
184 choices=io.allowed_formats('load'),
185 help='assume input files are of given FORMAT. Choices: %s'
186 % io.allowed_formats('load', 'cli_help', 'detect'))
188 parser.add_option(
189 '--pattern',
190 dest='regex',
191 metavar='REGEX',
192 help='only include files whose paths match REGEX')
194 parser.add_option(
195 '--stations',
196 dest='station_fns',
197 action='append',
198 default=[],
199 metavar='STATIONS',
200 help='read station information from file STATIONS')
202 parser.add_option(
203 '--stationxml',
204 dest='stationxml_fns',
205 action='append',
206 default=[],
207 metavar='STATIONSXML',
208 help='read station information from XML file STATIONSXML')
210 parser.add_option(
211 '--event', '--events',
212 dest='event_fns',
213 action='append',
214 default=[],
215 metavar='EVENT',
216 help='read event information from file EVENT')
218 parser.add_option(
219 '--markers',
220 dest='marker_fns',
221 action='append',
222 default=[],
223 metavar='MARKERS',
224 help='read marker information file MARKERS')
226 parser.add_option(
227 '--follow',
228 type='float',
229 dest='follow',
230 metavar='N',
231 help='follow real time with a window of N seconds')
233 parser.add_option(
234 '--cache',
235 dest='cache_dir',
236 default=config.config().cache_dir,
237 metavar='DIR',
238 help='use directory DIR to cache trace metadata '
239 "(default='%default')")
241 parser.add_option(
242 '--force-cache',
243 dest='force_cache',
244 action='store_true',
245 default=False,
246 help='use the cache even when trace attribute spoofing is active '
247 '(may have silly consequences)')
249 parser.add_option(
250 '--store-path',
251 dest='store_path',
252 metavar='PATH_TEMPLATE',
253 help='store data received through streams to PATH_TEMPLATE')
255 parser.add_option(
256 '--store-interval',
257 type='float',
258 dest='store_interval',
259 default=600,
260 metavar='N',
261 help='dump stream data to file every N seconds [default: %default]')
263 parser.add_option(
264 '--ntracks',
265 type='int',
266 dest='ntracks',
267 default=24,
268 metavar='N',
269 help='initially use N waveform tracks in viewer [default: %default]')
271 parser.add_option(
272 '--disable-marker-sorting',
273 action='store_false',
274 dest='marker_editor_sortable',
275 default=True,
276 help='disable sorting in marker table for improved performance with '
277 '100000+ markers')
279 parser.add_option(
280 '--hptime',
281 choices=('on', 'off', 'config'),
282 dest='hp_time',
283 default='config',
284 metavar='on|off|config',
285 help='set high precision time mode [default: %default]')
287 parser.add_option(
288 '--opengl',
289 dest='opengl',
290 action='store_true',
291 default=None,
292 help='use OpenGL for drawing')
294 parser.add_option(
295 '--no-opengl',
296 dest='opengl',
297 action='store_false',
298 default=None,
299 help='do not use OpenGL for drawing')
301 parser.add_option(
302 '--debug',
303 dest='debug',
304 action='store_true',
305 default=False,
306 help='print debugging information to stderr')
308 options, args = parser.parse_args(list(args))
310 if options.debug:
311 util.setup_logging('snuffler', 'debug')
312 else:
313 util.setup_logging('snuffler', 'info')
315 if options.hp_time in ('on', 'off'):
316 util.use_high_precision_time(options.hp_time == 'on')
318 this_pile = pile_mod.Pile()
319 stations = []
320 for stations_fn in extend_paths(options.station_fns):
321 stations.extend(model.station.load_stations(stations_fn))
323 for stationxml_fn in extend_paths(options.stationxml_fns):
324 stations.extend(
325 stationxml.load_xml(
326 filename=stationxml_fn).get_pyrocko_stations())
328 events = []
329 for event_fn in extend_paths(options.event_fns):
330 events.extend(model.load_events(event_fn))
332 markers = []
333 for marker_fn in extend_paths(options.marker_fns):
334 markers.extend(marker.load_markers(marker_fn))
336 import pyrocko
338 try:
339 return pyrocko.snuffle(
340 this_pile,
341 stations=stations,
342 events=events,
343 markers=markers,
344 ntracks=options.ntracks,
345 marker_editor_sortable=options.marker_editor_sortable,
346 follow=options.follow,
347 controls=True,
348 opengl=options.opengl,
349 paths=args,
350 cache_dir=options.cache_dir,
351 regex=options.regex,
352 format=options.format,
353 force_cache=options.force_cache,
354 store_path=options.store_path,
355 store_interval=options.store_interval)
357 except deps.MissingPyrockoDependency as e:
358 logger.fatal(str(e))
359 sys.exit(1)
362if __name__ == '__main__':
363 snuffler_from_commandline()