{ "cells": [ { "attachments": {}, "cell_type": "markdown", "id": "e0929444", "metadata": {}, "source": [ "# 1. Introduction\n", "\n", "This series of notebooks show how to use the [scatseisnet](https://scatseisnet.readthedocs.io/en/latest/) package for exploring continuous seismograms with a scattering network. \n", "\n", "Depending on the task at hand, different preprocessing steps might be necessary to prepare the data for the scattering transformation, and use the results for your application. We here present a tutorial workflow that you can adapt to your own data and research questions. The scattering coefficients are well-adapted to data exploration methods such as dimensionality reduction and clustering methods, which we will also explore. \n", "\n", "We investigate different exploration methods which have been presented in Seydoux et al. ([2020](https://www.nature.com/articles/s41467-020-17841-x)), and Steinmann et al. ([2021](https://agupubs.onlinelibrary.wiley.com/doi/full/10.1029/2021JB022455), [2022](https://agupubs.onlinelibrary.wiley.com/doi/full/10.1029/2022GL098854), and [2023](https://essopenarchive.org/doi/full/10.22541/essoar.168614505.54607219)), and we hope that these notebooks will inspire your research!\n", "\n", "— René Steinmann and Léonard Seydoux, last updated in November 2025.\n", "\n", "## Contents\n", "\n", "1. [Introduction](1_intro.ipynb) \n", "1. [Scattering network design](2_design.ipynb)\n", "1. [Scattering transformation](3_transformation.ipynb)\n", "1. [Independent component analysis](4_reduction.ipynb)\n", "1. [Scattering coefficient reconstruction](5_reconstruction.ipynb)\n", "1. [Clustering](6_clustering.ipynb)\n", "1. [Seismogram atlas](7_atlas.ipynb)\n", "\n", "\n", "## Prerequisites\n", "\n", "This tutorial requires the installation of several libraries specified in the pyproject.toml file under the [project.optional-dependencies] tutorials section. To enable the installation of these dependencies, you can use the following command when installing scatseisnet:\n", "\n", "```bash\n", "pip install scatseisnet[tutorials]\n", "```\n", "\n", "You can also install the required libraries individually using your package manager of choice. The list of required libraries includes:\n", "- [matplotlib](https://matplotlib.org/stable/users/installing.html)\n", "- [obspy](https://obspy.org/)\n", "- [scikit-learn](https://scikit-learn.org/stable/install.html)\n", "- [umap-learn](https://umap-learn.readthedocs.io/en/latest/installation.html)\n", "- [numpy](https://numpy.org/install/)\n", "- [scipy](https://scipy.org/install/)" ] }, { "cell_type": "code", "execution_count": 24, "id": "8db7a2e3", "metadata": {}, "outputs": [], "source": [ "from obspy.clients.fdsn import Client\n", "from obspy.core import UTCDateTime" ] }, { "cell_type": "code", "execution_count": 28, "id": "c5f2518b", "metadata": {}, "outputs": [], "source": [ "%config InlineBackend.figure_format = \"svg\"" ] }, { "cell_type": "markdown", "id": "07f2c06b", "metadata": {}, "source": [ "## Load seismograms\n", "\n", "We choose a one-day-long three-component seismogram from station `SV13` from the temporary _Klyuchevskoy Investigation_ network KISS (code `X9`) that was installed in the Klyuchevskoy volcano group from 2015 to 2016. In our study Steinmann et al. ([2023](https://essopenarchive.org/doi/full/10.22541/essoar.168614505.54607219)), we analyzed the whole recording period from the station SV13. For this tutorial, we narrow down the focus to a single day for demonstration purposes.\n", "\n", "We select focus on December 4 in 2015, which marks the onset of tremor activity due to the reactivation of the Klyuchevskoy volcano. We download the data from the [GFZ data center](https://geofon.gfz-potsdam.de/) using ObsPy." ] }, { "cell_type": "code", "execution_count": null, "id": "e9cb5edc", "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", " \n", " \n", " \n", " \n", " 2025-10-31T13:53:42.077246\n", " image/svg+xml\n", " \n", " \n", " Matplotlib v3.10.7, https://matplotlib.org/\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ], "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "3 Trace(s) in Stream:\n", "X9.SV13..HHZ | 2015-12-04T00:00:00.000000Z - 2015-12-05T00:00:00.000000Z | 50.0 Hz, 4320001 samples\n", "X9.SV13..HHN | 2015-12-04T00:00:00.000000Z - 2015-12-05T00:00:00.000000Z | 50.0 Hz, 4320001 samples\n", "X9.SV13..HHE | 2015-12-04T00:00:00.000000Z - 2015-12-05T00:00:00.000000Z | 50.0 Hz, 4320001 samples\n" ] } ], "source": [ "# Query dictionary\n", "query = {\n", " \"network\": \"X9\",\n", " \"station\": \"SV13\",\n", " \"location\": \"*\",\n", " \"channel\": \"*\",\n", " \"starttime\": UTCDateTime(\"2015-12-04T00:00\"),\n", " \"endtime\": UTCDateTime(\"2015-12-05T00:00\"),\n", "}\n", "\n", "# Collect waveforms and station information from the datacenter\n", "client = Client(\"GFZ\")\n", "stream = client.get_waveforms(**query)\n", "inventory = client.get_stations(**query)\n", "\n", "# Show the station loaction map\n", "inventory.plot(projection=\"ortho\")\n", "\n", "# Print stream information\n", "print(stream)" ] }, { "cell_type": "markdown", "id": "87afabae", "metadata": {}, "source": [ "## Preprocess seismograms\n", "\n", "Before exploring the data, it is helpful to clean and standardize the seismograms. In the next code cell, we apply a minimal yet practical pipeline:\n", "\n", "- Merge: combine partially overlapping or gappy segments into continuous traces per channel.\n", "- Detrend (linear): remove linear trends to reduce DC bias and avoid filter edge effects.\n", "- High-pass filter at 1 Hz: suppress long-period drift and microseisms while emphasizing tremor and transient events.\n", "\n", "After processing, we quickly inspect the result with a plot and save the stream to MiniSEED for reuse in later notebooks.\n", "\n", "Tips for adaptation:\n", "- Tune the corner frequency and filter type to your task and the station’s noise characteristics.\n", "- Consider adding a taper, resampling, or instrument response removal if needed.\n", "- Always visualize after each major step to verify that processing behaves as expected.\n", "- For more options, see ObsPy’s signal processing routines: https://docs.obspy.org/packages/obspy.signal.html" ] }, { "cell_type": "code", "execution_count": 32, "id": "db6e731c", "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", " \n", " \n", " \n", " \n", " 2025-10-31T13:54:29.518399\n", " image/svg+xml\n", " \n", " \n", " Matplotlib v3.10.7, https://matplotlib.org/\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ], "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Preprocess the data: merge, detrend, filter\n", "stream.merge(method=1)\n", "stream.detrend(\"linear\")\n", "stream.filter(type=\"highpass\", freq=1.0)\n", "\n", "# Plot one of the seismograms component\n", "stream[0].plot(linewidth=0.5, rasterized=True, method=\"full\", equal_scale=True)\n", "\n", "# Save the seismograms to a MiniSEED file\n", "stream.write(\"../example/stream.mseed\", format=\"MSEED\", encoding=\"FLOAT64\")" ] }, { "cell_type": "markdown", "id": "338b869f", "metadata": {}, "source": [ "## Define task\n", "\n", "We observe in these seismograms that there is an increase in volcanic tremor activity throughout the day, starting from low levels in the morning and intensifying towards the evening. Additionally, there are several transient seismic events scattered throughout the day.\n", "\n", "With scatseisnet we want to **explore this one-day long three-component seismogram and identify clusters related to the tremor and non-tremor activity**. Note that this is only a toy example. The power of scatseisnet and data exploration lies in exploring large continuous time series when manual investigation is not feasible." ] } ], "metadata": { "kernelspec": { "display_name": ".venv", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.13.7" } }, "nbformat": 4, "nbformat_minor": 5 }