{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# WaveBank\n",
"`WaveBank` is an in-process database for accessing seismic time-series data. Any directory structure containing ObsPy-readable waveforms can be used as the data source. `WaveBank` uses a simple indexing scheme and the [Hierarchical Data Format](https://en.wikipedia.org/wiki/Hierarchical_Data_Format) to keep track of each `Trace` in the directory. Without `WaveBank` (or another similar program) applications have implement their own data organization/access logic which is tedious and clutters up application code. `WaveBank` provides a better way. \n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Load Example Data\n",
"This tutorial will demonstrate the use of `WaveBank` on two different [obsplus datasets](../datasets/datasets.ipynb). \n",
"\n",
"The first dataset, [crandall canyon](https://en.wikipedia.org/wiki/Crandall_Canyon_Mine), only has event waveform files. The second only has continuous data from two TA stations. We start by loading these datasets, making a temporary copy, and getting a path to their waveform directories."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"execution": {
"iopub.execute_input": "2026-03-20T08:39:01.147867Z",
"iopub.status.busy": "2026-03-20T08:39:01.147686Z",
"iopub.status.idle": "2026-03-20T08:39:02.429120Z",
"shell.execute_reply": "2026-03-20T08:39:02.428263Z"
}
},
"outputs": [],
"source": [
"%%capture\n",
"import obsplus\n",
"\n",
"# make sure datasets are downloaded and copy them to temporary\n",
"# directories to make sure no accidental changes are made\n",
"crandall_dataset = obsplus.load_dataset(\"crandall_test\").copy_to()\n",
"ta_dataset = obsplus.load_dataset(\"ta_test\").copy_to()\n",
"\n",
"# get path to waveform directories\n",
"crandall_path = crandall_dataset.waveform_path\n",
"ta_path = ta_dataset.waveform_path"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"execution": {
"iopub.execute_input": "2026-03-20T08:39:02.431271Z",
"iopub.status.busy": "2026-03-20T08:39:02.430811Z",
"iopub.status.idle": "2026-03-20T08:39:02.436576Z",
"shell.execute_reply": "2026-03-20T08:39:02.435759Z"
}
},
"outputs": [
{
"data": {
"text/plain": [
"PosixPath('/tmp/tmp_bwmr699/crandall_test/waveforms')"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"crandall_path"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Create a WaveBank object\n",
"To create a `WaveBank` instance simply pass the class a path to the waveform directory."
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"execution": {
"iopub.execute_input": "2026-03-20T08:39:02.466743Z",
"iopub.status.busy": "2026-03-20T08:39:02.466524Z",
"iopub.status.idle": "2026-03-20T08:39:02.486670Z",
"shell.execute_reply": "2026-03-20T08:39:02.485828Z"
}
},
"outputs": [],
"source": [
"bank = obsplus.WaveBank(crandall_path)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Utilizing the `udpate_index` method on the bank ensures the index is up-to-date. This will iterate through all files that are timestamped later than the last time `update_index` was run.\n",
"\n",
"Note: If the index has not yet been created or new files have been added, `update_index` needs to be called."
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"execution": {
"iopub.execute_input": "2026-03-20T08:39:02.488728Z",
"iopub.status.busy": "2026-03-20T08:39:02.488527Z",
"iopub.status.idle": "2026-03-20T08:39:02.633062Z",
"shell.execute_reply": "2026-03-20T08:39:02.632221Z"
}
},
"outputs": [
{
"data": {
"text/plain": [
"WaveBank(base_path=/tmp/tmp_bwmr699/crandall_test/waveforms, index_path=/tmp/tmp_bwmr699/crandall_test/waveforms/.index.h5)"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"bank.update_index()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Using a custom index path\n",
"\n",
"If you are working from a data directory that doesn't have write access, you can specify a custom location for the index path:"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"execution": {
"iopub.execute_input": "2026-03-20T08:39:02.634903Z",
"iopub.status.busy": "2026-03-20T08:39:02.634696Z",
"iopub.status.idle": "2026-03-20T08:39:02.730656Z",
"shell.execute_reply": "2026-03-20T08:39:02.729865Z"
}
},
"outputs": [
{
"data": {
"text/plain": [
"WaveBank(base_path=/tmp/tmp_bwmr699/crandall_test/waveforms, index_path=/tmp/tmpae0579kf/index.h5)"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"import tempfile\n",
"from pathlib import Path\n",
"\n",
"index_path = Path(tempfile.mkdtemp()) / \"index.h5\"\n",
"cust_ind_bank = obsplus.WaveBank(crandall_path, index_path=index_path)\n",
"cust_ind_bank.update_index()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Get waveforms\n",
"\n",
"The files can be retrieved from the directory with the `get_waveforms` method. This method has the same signature as the ObsPy client `get_waveform` methods so they can be used interchangeably:"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"execution": {
"iopub.execute_input": "2026-03-20T08:39:02.732854Z",
"iopub.status.busy": "2026-03-20T08:39:02.732648Z",
"iopub.status.idle": "2026-03-20T08:39:02.802359Z",
"shell.execute_reply": "2026-03-20T08:39:02.801423Z"
}
},
"outputs": [],
"source": [
"import obspy\n",
"\n",
"t1 = obspy.UTCDateTime(\"2007-08-06T01-44-48\")\n",
"t2 = t1 + 60\n",
"st = bank.get_waveforms(starttime=t1, endtime=t2)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"`WaveBank` can filter on channels, locations, stations, networks, etc. using linux style search strings or regex. "
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"execution": {
"iopub.execute_input": "2026-03-20T08:39:02.804335Z",
"iopub.status.busy": "2026-03-20T08:39:02.804011Z",
"iopub.status.idle": "2026-03-20T08:39:02.820053Z",
"shell.execute_reply": "2026-03-20T08:39:02.819086Z"
}
},
"outputs": [],
"source": [
"st2 = bank.get_waveforms(network=\"UU\", starttime=t1, endtime=t2)\n",
"\n",
"# ensure only UU traces were returned\n",
"for tr in st2:\n",
" assert tr.stats.network == \"UU\"\n"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {
"execution": {
"iopub.execute_input": "2026-03-20T08:39:02.821824Z",
"iopub.status.busy": "2026-03-20T08:39:02.821646Z",
"iopub.status.idle": "2026-03-20T08:39:02.834381Z",
"shell.execute_reply": "2026-03-20T08:39:02.833460Z"
}
},
"outputs": [],
"source": [
"st = bank.get_waveforms(starttime=t1, endtime=t2, station=\"O1??\", channel=\"BH[NE]\")\n",
"\n",
"# test returned traces\n",
"for tr in st:\n",
" assert tr.stats.starttime >= t1 - 0.00001\n",
" assert tr.stats.endtime <= t2 + 0.00001\n",
" assert tr.stats.station.startswith(\"O1\")\n",
" assert tr.stats.channel.startswith(\"BH\")\n",
" assert tr.stats.channel[-1] in {\"N\", \"E\"}\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"WaveBank also has a `get_waveforms_bulk` method for efficiently retrieving a large number of streams. "
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {
"execution": {
"iopub.execute_input": "2026-03-20T08:39:02.836207Z",
"iopub.status.busy": "2026-03-20T08:39:02.835991Z",
"iopub.status.idle": "2026-03-20T08:39:02.904096Z",
"shell.execute_reply": "2026-03-20T08:39:02.903267Z"
}
},
"outputs": [],
"source": [
"args = [ # in practice this list may contain hundreds or thousands of requests\n",
" (\n",
" \"TA\",\n",
" \"O15A\",\n",
" \"\",\n",
" \"BHZ\",\n",
" t1 - 5,\n",
" t2 - 5,\n",
" ),\n",
" (\n",
" \"UU\",\n",
" \"SRU\",\n",
" \"\",\n",
" \"HHZ\",\n",
" t1,\n",
" t2,\n",
" ),\n",
"]\n",
"st = bank.get_waveforms_bulk(args)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Yield waveforms\n",
"The Bank class also provides a generator for iterating large amounts of continuous waveforms. The following example shows how to get streams of one hour duration with a minute of overlap between the slices. \n",
"\n",
"The first step is to create a bank on a dataset which has continuous data. The example below will use the TA dataset."
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {
"execution": {
"iopub.execute_input": "2026-03-20T08:39:02.906385Z",
"iopub.status.busy": "2026-03-20T08:39:02.906197Z",
"iopub.status.idle": "2026-03-20T08:39:02.923616Z",
"shell.execute_reply": "2026-03-20T08:39:02.922846Z"
}
},
"outputs": [],
"source": [
"ta_bank = obsplus.WaveBank(ta_path)"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {
"execution": {
"iopub.execute_input": "2026-03-20T08:39:02.925572Z",
"iopub.status.busy": "2026-03-20T08:39:02.925362Z",
"iopub.status.idle": "2026-03-20T08:39:03.383160Z",
"shell.execute_reply": "2026-03-20T08:39:03.382279Z"
}
},
"outputs": [],
"source": [
"# get a few hours of kemmerer data\n",
"ta_t1 = obspy.UTCDateTime(\"2007-02-15\")\n",
"ta_t2 = obspy.UTCDateTime(\"2007-02-16\")\n",
"\n",
"for st in ta_bank.yield_waveforms(\n",
" starttime=ta_t1, endtime=ta_t2, duration=3600, overlap=60\n",
"):\n",
" pass"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Put waveforms\n",
"Files can be added to the bank by passing a stream or trace to the `bank.put_waveforms` method. `WaveBank` does not merge files so overlap in data may occur if care is not taken."
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {
"execution": {
"iopub.execute_input": "2026-03-20T08:39:03.385394Z",
"iopub.status.busy": "2026-03-20T08:39:03.385207Z",
"iopub.status.idle": "2026-03-20T08:39:03.431839Z",
"shell.execute_reply": "2026-03-20T08:39:03.430924Z"
}
},
"outputs": [],
"source": [
"# show that no data for RJOB is in the bank\n",
"st = bank.get_waveforms(station=\"RJOB\")\n",
"\n",
"assert len(st) == 0\n"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {
"execution": {
"iopub.execute_input": "2026-03-20T08:39:03.433740Z",
"iopub.status.busy": "2026-03-20T08:39:03.433387Z",
"iopub.status.idle": "2026-03-20T08:39:03.639247Z",
"shell.execute_reply": "2026-03-20T08:39:03.638405Z"
}
},
"outputs": [],
"source": [
"# add the default stream to the archive (which contains data for RJOB)\n",
"bank.put_waveforms(obspy.read())\n",
"st_out = bank.get_waveforms(station=\"RJOB\")\n",
"\n",
"# test output\n",
"assert len(st_out)\n",
"for tr in st_out:\n",
" assert tr.stats.station == \"RJOB\"\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Availability\n",
"`WaveBank` can be used to get the availability of data. The outputs can either be a dataframe or as a list of tuples in the form of [(network, station, location, channel, min_starttime, max_endtime)]. "
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {
"execution": {
"iopub.execute_input": "2026-03-20T08:39:03.641531Z",
"iopub.status.busy": "2026-03-20T08:39:03.641330Z",
"iopub.status.idle": "2026-03-20T08:39:03.698086Z",
"shell.execute_reply": "2026-03-20T08:39:03.697238Z"
}
},
"outputs": [
{
"data": {
"text/html": [
"
\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" network | \n",
" station | \n",
" location | \n",
" channel | \n",
" starttime | \n",
" endtime | \n",
"
\n",
" \n",
" \n",
" \n",
" | 0 | \n",
" TA | \n",
" O15A | \n",
" | \n",
" BHE | \n",
" 2007-08-06 01:44:38.825000 | \n",
" 2007-08-07 21:43:51.124998 | \n",
"
\n",
" \n",
" | 1 | \n",
" TA | \n",
" O16A | \n",
" | \n",
" BHE | \n",
" 2007-08-06 01:44:38.825000 | \n",
" 2007-08-07 21:43:51.125000 | \n",
"
\n",
" \n",
" | 2 | \n",
" TA | \n",
" O18A | \n",
" | \n",
" BHE | \n",
" 2007-08-06 01:44:38.824998 | \n",
" 2007-08-07 21:43:51.125000 | \n",
"
\n",
" \n",
" | 3 | \n",
" TA | \n",
" R16A | \n",
" | \n",
" BHE | \n",
" 2007-08-07 02:04:54.500000 | \n",
" 2007-08-07 21:43:51.125000 | \n",
"
\n",
" \n",
" | 4 | \n",
" TA | \n",
" R17A | \n",
" | \n",
" BHE | \n",
" 2007-08-06 01:44:38.825000 | \n",
" 2007-08-07 21:43:51.125000 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" network station location channel starttime \\\n",
"0 TA O15A BHE 2007-08-06 01:44:38.825000 \n",
"1 TA O16A BHE 2007-08-06 01:44:38.825000 \n",
"2 TA O18A BHE 2007-08-06 01:44:38.824998 \n",
"3 TA R16A BHE 2007-08-07 02:04:54.500000 \n",
"4 TA R17A BHE 2007-08-06 01:44:38.825000 \n",
"\n",
" endtime \n",
"0 2007-08-07 21:43:51.124998 \n",
"1 2007-08-07 21:43:51.125000 \n",
"2 2007-08-07 21:43:51.125000 \n",
"3 2007-08-07 21:43:51.125000 \n",
"4 2007-08-07 21:43:51.125000 "
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# get a dataframe of availability by seed ids and timestamps\n",
"bank.get_availability_df(channel=\"BHE\", station=\"[OR]*\")"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {
"execution": {
"iopub.execute_input": "2026-03-20T08:39:03.699824Z",
"iopub.status.busy": "2026-03-20T08:39:03.699632Z",
"iopub.status.idle": "2026-03-20T08:39:03.714575Z",
"shell.execute_reply": "2026-03-20T08:39:03.713737Z"
}
},
"outputs": [
{
"data": {
"text/plain": [
"[('TA',\n",
" 'O15A',\n",
" '',\n",
" 'BHE',\n",
" 2007-08-06T01:44:38.825000Z,\n",
" 2007-08-07T21:43:51.124998Z),\n",
" ('TA',\n",
" 'O16A',\n",
" '',\n",
" 'BHE',\n",
" 2007-08-06T01:44:38.825000Z,\n",
" 2007-08-07T21:43:51.125000Z),\n",
" ('TA',\n",
" 'O18A',\n",
" '',\n",
" 'BHE',\n",
" 2007-08-06T01:44:38.824998Z,\n",
" 2007-08-07T21:43:51.125000Z),\n",
" ('TA',\n",
" 'R16A',\n",
" '',\n",
" 'BHE',\n",
" 2007-08-07T02:04:54.500000Z,\n",
" 2007-08-07T21:43:51.125000Z),\n",
" ('TA',\n",
" 'R17A',\n",
" '',\n",
" 'BHE',\n",
" 2007-08-06T01:44:38.825000Z,\n",
" 2007-08-07T21:43:51.125000Z)]"
]
},
"execution_count": 15,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# get list of tuples of availability\n",
"bank.availability(channel=\"BHE\", station=\"[OR]*\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Get Gaps and uptime\n",
"`WaveBank` can return a dataframe of missing data with the `get_gaps_df` method, and a dataframe of reliability statistics with the `get_uptime_df` method. These are useful for assessing the completeness of an archive of contiguous data."
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {
"execution": {
"iopub.execute_input": "2026-03-20T08:39:03.716335Z",
"iopub.status.busy": "2026-03-20T08:39:03.716106Z",
"iopub.status.idle": "2026-03-20T08:39:03.740996Z",
"shell.execute_reply": "2026-03-20T08:39:03.740035Z"
}
},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" network | \n",
" station | \n",
" location | \n",
" channel | \n",
" starttime | \n",
" endtime | \n",
" sampling_period | \n",
" path | \n",
" gap_duration | \n",
"
\n",
" \n",
" \n",
" \n",
" | 0 | \n",
" TA | \n",
" O16A | \n",
" | \n",
" BHE | \n",
" 2007-08-06 01:45:48.800000 | \n",
" 2007-08-06 08:48:30.025 | \n",
" 0 days 00:00:00.025000 | \n",
" TA.O16A..BHE__20070806T014438Z__20070806T01454... | \n",
" 0 days 07:02:41.225000 | \n",
"
\n",
" \n",
" | 1 | \n",
" TA | \n",
" O16A | \n",
" | \n",
" BHE | \n",
" 2007-08-06 08:49:40.000001 | \n",
" 2007-08-06 10:47:15.600 | \n",
" 0 days 00:00:00.025000 | \n",
" TA.O16A..BHE__20070806T084830Z__20070806T08494... | \n",
" 0 days 01:57:35.599999 | \n",
"
\n",
" \n",
" | 2 | \n",
" TA | \n",
" O16A | \n",
" | \n",
" BHE | \n",
" 2007-08-06 10:48:25.600000 | \n",
" 2007-08-07 02:04:54.500 | \n",
" 0 days 00:00:00.025000 | \n",
" TA.O16A..BHE__20070806T104715Z__20070806T10482... | \n",
" 0 days 15:16:28.900000 | \n",
"
\n",
" \n",
" | 3 | \n",
" TA | \n",
" O16A | \n",
" | \n",
" BHE | \n",
" 2007-08-07 02:06:04.475000 | \n",
" 2007-08-07 02:14:14.100 | \n",
" 0 days 00:00:00.025000 | \n",
" TA.O16A..BHE__20070807T020454Z__20070807T02060... | \n",
" 0 days 00:08:09.625000 | \n",
"
\n",
" \n",
" | 4 | \n",
" TA | \n",
" O16A | \n",
" | \n",
" BHE | \n",
" 2007-08-07 02:15:24.075000 | \n",
" 2007-08-07 03:44:08.475 | \n",
" 0 days 00:00:00.025000 | \n",
" TA.O16A..BHE__20070807T021414Z__20070807T02152... | \n",
" 0 days 01:28:44.400000 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" network station location channel starttime \\\n",
"0 TA O16A BHE 2007-08-06 01:45:48.800000 \n",
"1 TA O16A BHE 2007-08-06 08:49:40.000001 \n",
"2 TA O16A BHE 2007-08-06 10:48:25.600000 \n",
"3 TA O16A BHE 2007-08-07 02:06:04.475000 \n",
"4 TA O16A BHE 2007-08-07 02:15:24.075000 \n",
"\n",
" endtime sampling_period \\\n",
"0 2007-08-06 08:48:30.025 0 days 00:00:00.025000 \n",
"1 2007-08-06 10:47:15.600 0 days 00:00:00.025000 \n",
"2 2007-08-07 02:04:54.500 0 days 00:00:00.025000 \n",
"3 2007-08-07 02:14:14.100 0 days 00:00:00.025000 \n",
"4 2007-08-07 03:44:08.475 0 days 00:00:00.025000 \n",
"\n",
" path gap_duration \n",
"0 TA.O16A..BHE__20070806T014438Z__20070806T01454... 0 days 07:02:41.225000 \n",
"1 TA.O16A..BHE__20070806T084830Z__20070806T08494... 0 days 01:57:35.599999 \n",
"2 TA.O16A..BHE__20070806T104715Z__20070806T10482... 0 days 15:16:28.900000 \n",
"3 TA.O16A..BHE__20070807T020454Z__20070807T02060... 0 days 00:08:09.625000 \n",
"4 TA.O16A..BHE__20070807T021414Z__20070807T02152... 0 days 01:28:44.400000 "
]
},
"execution_count": 16,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"bank.get_gaps_df(channel=\"BHE\", station=\"O*\").head()"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {
"execution": {
"iopub.execute_input": "2026-03-20T08:39:03.742761Z",
"iopub.status.busy": "2026-03-20T08:39:03.742583Z",
"iopub.status.idle": "2026-03-20T08:39:03.868020Z",
"shell.execute_reply": "2026-03-20T08:39:03.866982Z"
}
},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" network | \n",
" station | \n",
" location | \n",
" channel | \n",
" starttime | \n",
" endtime | \n",
" duration | \n",
" gap_duration | \n",
" uptime | \n",
" availability | \n",
"
\n",
" \n",
" \n",
" \n",
" | 0 | \n",
" TA | \n",
" M11A | \n",
" | \n",
" VHE | \n",
" 2007-02-15 00:00:09.999998 | \n",
" 2007-02-24 23:59:59.999998 | \n",
" 9 days 23:59:50 | \n",
" 0 days | \n",
" 9 days 23:59:50 | \n",
" 1.0 | \n",
"
\n",
" \n",
" | 1 | \n",
" TA | \n",
" M11A | \n",
" | \n",
" VHN | \n",
" 2007-02-15 00:00:09.999998 | \n",
" 2007-02-24 23:59:59.999998 | \n",
" 9 days 23:59:50 | \n",
" 0 days | \n",
" 9 days 23:59:50 | \n",
" 1.0 | \n",
"
\n",
" \n",
" | 2 | \n",
" TA | \n",
" M11A | \n",
" | \n",
" VHZ | \n",
" 2007-02-15 00:00:09.999998 | \n",
" 2007-02-24 23:59:59.999998 | \n",
" 9 days 23:59:50 | \n",
" 0 days | \n",
" 9 days 23:59:50 | \n",
" 1.0 | \n",
"
\n",
" \n",
" | 3 | \n",
" TA | \n",
" M14A | \n",
" | \n",
" VHE | \n",
" 2007-02-15 00:00:00.000003 | \n",
" 2007-02-25 00:00:00.000003 | \n",
" 10 days 00:00:00 | \n",
" 0 days | \n",
" 10 days 00:00:00 | \n",
" 1.0 | \n",
"
\n",
" \n",
" | 4 | \n",
" TA | \n",
" M14A | \n",
" | \n",
" VHN | \n",
" 2007-02-15 00:00:00.000003 | \n",
" 2007-02-25 00:00:00.000003 | \n",
" 10 days 00:00:00 | \n",
" 0 days | \n",
" 10 days 00:00:00 | \n",
" 1.0 | \n",
"
\n",
" \n",
" | 5 | \n",
" TA | \n",
" M14A | \n",
" | \n",
" VHZ | \n",
" 2007-02-15 00:00:00.000004 | \n",
" 2007-02-25 00:00:00.000004 | \n",
" 10 days 00:00:00 | \n",
" 0 days | \n",
" 10 days 00:00:00 | \n",
" 1.0 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" network station location channel starttime \\\n",
"0 TA M11A VHE 2007-02-15 00:00:09.999998 \n",
"1 TA M11A VHN 2007-02-15 00:00:09.999998 \n",
"2 TA M11A VHZ 2007-02-15 00:00:09.999998 \n",
"3 TA M14A VHE 2007-02-15 00:00:00.000003 \n",
"4 TA M14A VHN 2007-02-15 00:00:00.000003 \n",
"5 TA M14A VHZ 2007-02-15 00:00:00.000004 \n",
"\n",
" endtime duration gap_duration uptime \\\n",
"0 2007-02-24 23:59:59.999998 9 days 23:59:50 0 days 9 days 23:59:50 \n",
"1 2007-02-24 23:59:59.999998 9 days 23:59:50 0 days 9 days 23:59:50 \n",
"2 2007-02-24 23:59:59.999998 9 days 23:59:50 0 days 9 days 23:59:50 \n",
"3 2007-02-25 00:00:00.000003 10 days 00:00:00 0 days 10 days 00:00:00 \n",
"4 2007-02-25 00:00:00.000003 10 days 00:00:00 0 days 10 days 00:00:00 \n",
"5 2007-02-25 00:00:00.000004 10 days 00:00:00 0 days 10 days 00:00:00 \n",
"\n",
" availability \n",
"0 1.0 \n",
"1 1.0 \n",
"2 1.0 \n",
"3 1.0 \n",
"4 1.0 \n",
"5 1.0 "
]
},
"execution_count": 17,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"ta_bank.get_uptime_df()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Read index\n",
"`WaveBank` can return a dataframe of the the index with the `read_index` method, although in most cases this shouldn't be needed."
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {
"execution": {
"iopub.execute_input": "2026-03-20T08:39:03.869861Z",
"iopub.status.busy": "2026-03-20T08:39:03.869614Z",
"iopub.status.idle": "2026-03-20T08:39:03.880471Z",
"shell.execute_reply": "2026-03-20T08:39:03.879674Z"
}
},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" network | \n",
" station | \n",
" location | \n",
" channel | \n",
" starttime | \n",
" endtime | \n",
" sampling_period | \n",
" path | \n",
"
\n",
" \n",
" \n",
" \n",
" | 0 | \n",
" TA | \n",
" M11A | \n",
" | \n",
" VHE | \n",
" 2007-02-21 11:59:59.999998 | \n",
" 2007-02-21 12:59:59.999998 | \n",
" 0 days 00:00:10 | \n",
" TA/M11A/VHE/2007-02-21T12-00-00.mseed | \n",
"
\n",
" \n",
" | 1 | \n",
" TA | \n",
" M14A | \n",
" | \n",
" VHE | \n",
" 2007-02-21 12:00:00.000003 | \n",
" 2007-02-21 13:00:00.000003 | \n",
" 0 days 00:00:10 | \n",
" TA/M11A/VHE/2007-02-21T12-00-00.mseed | \n",
"
\n",
" \n",
" | 2 | \n",
" TA | \n",
" M11A | \n",
" | \n",
" VHE | \n",
" 2007-02-19 02:59:59.999998 | \n",
" 2007-02-19 03:59:59.999998 | \n",
" 0 days 00:00:10 | \n",
" TA/M11A/VHE/2007-02-19T03-00-00.mseed | \n",
"
\n",
" \n",
" | 3 | \n",
" TA | \n",
" M14A | \n",
" | \n",
" VHE | \n",
" 2007-02-19 03:00:00.000003 | \n",
" 2007-02-19 04:00:00.000003 | \n",
" 0 days 00:00:10 | \n",
" TA/M11A/VHE/2007-02-19T03-00-00.mseed | \n",
"
\n",
" \n",
" | 4 | \n",
" TA | \n",
" M11A | \n",
" | \n",
" VHE | \n",
" 2007-02-22 08:59:59.999998 | \n",
" 2007-02-22 09:59:59.999998 | \n",
" 0 days 00:00:10 | \n",
" TA/M11A/VHE/2007-02-22T09-00-00.mseed | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" network station location channel starttime \\\n",
"0 TA M11A VHE 2007-02-21 11:59:59.999998 \n",
"1 TA M14A VHE 2007-02-21 12:00:00.000003 \n",
"2 TA M11A VHE 2007-02-19 02:59:59.999998 \n",
"3 TA M14A VHE 2007-02-19 03:00:00.000003 \n",
"4 TA M11A VHE 2007-02-22 08:59:59.999998 \n",
"\n",
" endtime sampling_period \\\n",
"0 2007-02-21 12:59:59.999998 0 days 00:00:10 \n",
"1 2007-02-21 13:00:00.000003 0 days 00:00:10 \n",
"2 2007-02-19 03:59:59.999998 0 days 00:00:10 \n",
"3 2007-02-19 04:00:00.000003 0 days 00:00:10 \n",
"4 2007-02-22 09:59:59.999998 0 days 00:00:10 \n",
"\n",
" path \n",
"0 TA/M11A/VHE/2007-02-21T12-00-00.mseed \n",
"1 TA/M11A/VHE/2007-02-21T12-00-00.mseed \n",
"2 TA/M11A/VHE/2007-02-19T03-00-00.mseed \n",
"3 TA/M11A/VHE/2007-02-19T03-00-00.mseed \n",
"4 TA/M11A/VHE/2007-02-22T09-00-00.mseed "
]
},
"execution_count": 18,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"ta_bank.read_index().head()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Similar Projects\n",
"`WaveBank` is a useful tool, but it may not be a good fit for every application. Check out the following items as well:\n",
"\n",
"Obspy has a way to visualize availability of waveform data in a directory using [obspy-scan](https://docs.obspy.org/tutorial/code_snippets/visualize_data_availability_of_local_waveform_archive.html). If you prefer a graphical option to working with `DataFrame`s this might be for you.\n",
"\n",
"Obspy also has [filesystem client](https://docs.obspy.org/master/packages/autogen/obspy.clients.filesystem.sds.Client.html#obspy.clients.filesystem.sds.Client) for working with SeisComP structured archives.\n",
"\n",
"[IRIS](https://www.iris.edu/hq/) released a mini-seed indexing program called [mseedindex](https://github.com/iris-edu/mseedindex) which has an [ObsPy API](https://github.com/obspy/obspy/pull/2206)."
]
}
],
"metadata": {
"anaconda-cloud": {},
"kernelspec": {
"display_name": "Python 3",
"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.12"
}
},
"nbformat": 4,
"nbformat_minor": 4
}