VDAPSEISUTILS is a set of (mostly) Python code that provides easy methods for common tasks in operational volcano seismology.
At the moment, core tasks include:
- VolcanoMap: Plot a basic map and cross section of earthquakes around a volcano.
- ObsPy Catalog & Inventory IO: Import/Export ObsPy Catalog & Inventory formats from Swarm, Earthworm, and NonLinLoc.
Sandbox tasks: (These routines are available, but I may change them significantly before they are stored in core. I am still working on them.)
- Velocity: Load, save, and plot velocity models.
- SwarmMPL: MatPlotLib routines for Swarm-like plots (Helicorders, waveform traces, spectrograms, spectra).
Pending tasks:
- CCMatrix: Create, save, load, and plot cross correlation matrices.
- Waveform statistics: E.g., compute Frequency Index for a list of Stream objects and compare results across events.
- DataSource: A wrapper for ObsPy Clients with a more universal usage (automatically determines Client type).
This package is not yet on PyPI. Clone the repo and use uv to create the environment and install the package (Python 3.11+).
One-time setup
This project uses a named environment vseis311. Set the env path, then sync:
git clone https://github.com/jwellik/vdapseisutils.git
cd vdapseisutils
export UV_PROJECT_ENVIRONMENT=vseis311
uv syncTo make that permanent in this repo (optional), use direnv: run direnv allow once; the project’s .envrc will set UV_PROJECT_ENVIRONMENT=vseis311 whenever you cd here.
Activate and run Python
source vseis311/bin/activate
pythonYou activate by sourcing the script inside the environment directory (vseis311/bin/activate). There is no global activate command that takes a name—that’s Conda’s interface. With Python’s venv (and uv), the environment is just a folder; you always run source <env-dir>/bin/activate (e.g. source vseis311/bin/activate or source .venv/bin/activate if you didn’t set a custom name).
Optional: run without activating: uv run python ..., uv run pytest, etc.
Optional: PyTables (HDF5)
The package does not require tables (PyTables) by default. If you need it, install the system HDF5 library first, then the extra:
- macOS (Homebrew):
brew install hdf5, thenexport HDF5_DIR=$(brew --prefix hdf5)andpip install ".[tables]"(oruv sync --extra tables). - Conda:
conda install hdf5thenpip install ".[tables]".
This package is still in development. If you have trouble with these codes, let me know.
source vseis311/bin/activate
cd gallery
python
>>> from vdapseisutils.gallery import Mapping_tutorial
>>> Mapping_tutorial.main() # graphics forwarding if remoteThis runs a script that reads .arc files from Wy'East/Mt Hood, Oregon and plots them on a map and cross sections. See the Gallery for more examples and usage.
Map classes are implemented under vdapseisutils.core.maps (e.g. map.py, volcano_figure.py). The module vdapseisutils.core.maps.maps is deprecated: importing it emits DeprecationWarning and re-exports the same symbols for now; it will be removed in a future release. Prefer from vdapseisutils.core.maps import Map (and from vdapseisutils.core.maps.utils import prep_catalog_data_mpl, etc.). Backend-neutral compute lives under vdapseisutils.compute (see the package docstring there).
Catalog points and origins: Use vdapseisutils.compute.catalog.prepare_catalog_points (or prepare_catalog_points_from_time_format for legacy time_format strings) for matplotlib-free tables of hypocenter data. vdapseisutils.utils.obspyutils.catalog.origin.get_primary_origin selects the QuakeML preferred origin when present, otherwise the first origin—the same rule used for VCatalog event-rate extraction, scatter maps, and catalog2txyzm by default. Pass origin_policy="last" to catalog2txyzm if you need the old “last origin in the list” behavior.
Maps matplotlib style (no import-time rc): Pure style dicts live in vdapseisutils.core.maps.defaults_constants. Importing that module does not load Matplotlib or change rcParams. To apply the maps theme globally, call vdapseisutils.core.maps.defaults.register_maps_mpl_style() once (e.g. at app startup). Map constructors (Map, CrossSection, VolcanoFigure, TimeSeries) call ensure_maps_mpl_style() so figures still get the intended defaults when those classes are used without a prior explicit registration.
Maps / volcano layout (narrative + examples, API v1 §11): See docs/maps_volcano_api_v1.md for how Map, VolcanoFigure, CrossSection, TimeSeries, and MagLegend fit together, import paths, register_pyplot() (plt.eqmap / plt.volcano), and catalog compute via vdapseisutils.compute.catalog.prepare_catalog_points. Runnable offline examples from the repo root: python examples/map_minimal.py, python examples/volcano_figure_layout.py, python examples/cross_section_standalone.py (or uv run python …).
Waveform and spectrogram compute: Shared, backend-neutral helpers live in vdapseisutils.compute.waveforms: prepare_waveform_series returns a WaveformSeriesResult (time axis and data); compute_spectrogram returns a SpectrogramResult (frequency, time offset, power) using the SciPy spectrogram path aligned with Swarm-style plots. vdapseisutils.core.swarmmpl (including the v3 time-axis stack) calls these helpers then draws; use the same APIs if you need arrays without Matplotlib.
If you still use older import paths (e.g. core.maps.maps), read CHANGELOG.md and the policy sections §8–§9 (and §13.4–§13.5) in .local/api-v1-coord/API_V1_CANONICAL.md if you keep a local copy of that doc.
You can attach VDAPSeisUtils figure constructors to Matplotlib’s pyplot module (API v1 section 3 in .local/api-v1-coord/API_V1_CANONICAL.md):
import matplotlib.pyplot as plt
import vdapseisutils.plot.mpl as vsmpl
vsmpl.register_pyplot()
fig = plt.helicorder(...) # or plt.clipboard / plt.eqmap / plt.volcano / plt.swarmAfter register_pyplot(), those names construct the corresponding project types (Helicorder, clipboard / SwarmFigure, Map, VolcanoFigure; plt.swarm matches plt.clipboard—see vdapseisutils.plot.mpl).
Swarm-style plotting (multi-trace clipboard, helicorder, time axes / panels) has one canonical import path: vdapseisutils.plot.swarm. Implementations live under vdapseisutils.core.swarmmpl (clipboard.py, panel.py, timeaxes.py, heli.py, …). Policy notes are in .local/api-v1-coord/API_V1_CANONICAL.md §8 (Swarm consolidation).
Canonical (new code):
from vdapseisutils.plot.swarm import (
Helicorder,
Clipboard, # legacy factory → ClipboardClass / SwarmFigure
ClipboardClass,
SwarmFigure, # alias of ClipboardClass (API v1 §3)
TimeAxes,
Panel,
SwarmClipboard, # v3 panel clipboard (distinct from the legacy Clipboard factory)
)Core module (same types as plot.swarm):
from vdapseisutils.core.swarmmpl.clipboard import Clipboard, ClipboardClass, SwarmClipboard
from vdapseisutils.core.swarmmpl import Panel, TimeAxesPrefer clipboard_figure if you want an explicit name for the legacy factory; it is the same callable as Clipboard.
Swarm runnable on-ramp (API v1 §11-style): For a short, offline script that constructs Helicorder and SwarmClipboard on synthetic waveforms (no FDSN), run from the repo root: python examples/swarm_clipboard_minimal.py (or uv run python …). That mirrors how map workflows point to examples/map_minimal.py and friends; deeper layout and naming notes remain under Pyplot helpers (register_pyplot) and vdapseisutils.plot.swarm / core/swarmmpl source.
Peak-value raster overlay API (waveform axes only):
Both ClipboardClass and SwarmClipboard support:
cb.plot_peak_value(
peak_stream,
window_s=0.05,
cmap="magma",
cmap_by_index={0: "RdPu", 1: "Blues"},
alpha=0.75,
interpolation="bilinear",
add_colorbar=True,
)plot_peak_value(...) intentionally overlays raster imagery behind existing waveform axes ("w" axes) without changing axis formatting; it raises when used on spectrogram-only (mode="g") figures.
Bokeh clipboard: For notebooks and standalone HTML, use SwarmClipboardBk from vdapseisutils.core.swarmmpl.bokeh. It mirrors SwarmClipboard semantics (modes w / g / wg, tick_type absolute vs relative, sync_waves, aligned waveform/spectrogram compute), plus overlays such as axvline, plot_trace / plot_horizontals, plot_peak_value, plot_catalog, scroll_traces, and save() for exported plots. Worked examples are in gallery/SwarmMPL/Clipboard_tutorial_bokeh.ipynb (Examples 1–3 align with gallery/SwarmMPL/Clipboard_Tutorial_A.ipynb).
Bokeh helicorder: For strip-style dayplots in Bokeh, import SwarmHelicorderBk from vdapseisutils.core.swarmmpl.bokeh:
from obspy import read, UTCDateTime
from vdapseisutils.core.swarmmpl.bokeh import SwarmHelicorderBk
st = read("data/waveforms/gareloi_test_data_20220710-010000.mseed")
st.trim(UTCDateTime("2022-07-10T01:00:00"), UTCDateTime("2022-07-10T02:00:00"))
heli = SwarmHelicorderBk(st, interval=30, color="swarm")
heli.show()
heli.save("heli_bokeh.html")To add an attached clipboard view around the decoded focus time:
cb = heli.attach_clipboard(mode="wg", window_s=600, sync_focus=True)See gallery/SwarmMPL/Helicorder_tutorial_bokeh.ipynb for three worked examples (basic strips, tick/style controls, and tags/catalog markers with HTML export). Current Bokeh parity deltas vs MPL are documented there: timezone footer rendering differs, focus-sync window is centered on focus_time, and catalog pick matching prefers full SEED ID with station fallback.
