Browse Source

docs: add squirrel cli tutorial

Co-authored-by: m.r.d <dwars@uni-potsdam.de>
release
Sebastian Heimann 2 months ago
parent
commit
7434624de5
  1. 2
      .gitignore
  2. 2
      doc/Makefile
  3. 58
      doc/source/apps/squirrel/index.rst
  4. 63
      doc/source/apps/squirrel/manual.rst
  5. 592
      doc/source/apps/squirrel/tutorial.rst
  6. 2
      doc/source/library/examples/squirrel/cli_tool.rst
  7. 19
      doc/source/library/reference/squirrel/index.rst
  8. 703
      doc/source/static/squirrel-cli-summon.svg
  9. 688
      doc/source/static/squirrel-cli-update-promises.svg
  10. 672
      doc/source/static/squirrel-cli-update-responses.svg
  11. 638
      doc/source/static/squirrel-cli-update.svg
  12. 98
      doc/source/static/squirrel.svg
  13. BIN
      doc/source/static/squirrel_tutorial1.png
  14. BIN
      doc/source/static/squirrel_tutorial2.png
  15. 2
      maintenance/argparse_help_to_rst.py
  16. 9
      src/squirrel/tool/commands/template.py

2
.gitignore vendored

@ -1,7 +1,7 @@
/build/
/dist/
/doc/build/
/doc/source/apps/squirrel/manual/
/doc/source/apps/squirrel/reference/
/pyrocko.egg-info/
/src/info.py

2
doc/Makefile

@ -16,7 +16,7 @@ help:
squirrel_cli:
python3 ../maintenance/argparse_help_to_rst.py \
pyrocko.squirrel.main \
source/apps/squirrel/manual/
source/apps/squirrel/reference/
.PHONY: help Makefile squirrel_cli

58
doc/source/apps/squirrel/index.rst

@ -1,54 +1,20 @@
Squirrel Tool - *dataset inspection and management*
===================================================
.. image:: /static/squirrel.svg
:align: left
The :program:`squirrel` command line tool is a front-end to the :ref:`Squirrel
data access infrastructure <squirrel>`. It offers functionality to
* inspect various aspects of a data collection.
* pre-scan / index file collections.
* download data from online sources (FDSN web services, earthquake catalogs).
* manage separate (isolated, local) environments for different projects.
* manage persistent selections to speed up access to very large datasets.
Command reference
-----------------
.. toctree::
:maxdepth: 3
manual/squirrel
Help
----
The :app:`squirrel` tool and its subcommands are self-documenting with the
``--help`` option. Run ``squirrel`` without any options to get the list of
available subcommands. Run ``squirrel SUBCOMMAND --help`` to get details about
a specific subcommand.
Squirrel - *dataset inspection and management*
==============================================
The :program:`squirrel` command line tool is a front-end to the :ref:`Squirrel
data access infrastructure <squirrel>`.
Common options
--------------
.. raw:: html
Options shared between subcommands are grouped into three categories:
<div style="clear:both"></div>
* **General options** include ``--loglevel`` to select the
program's verbosity and ``--progress`` to control how progress status is
indicated. These are provided by all of Squirrel's subcommands.
* **Data collection options** control which files and other data sources should
be aggregated to form a dataset. The ``--add`` option to add files and
directories. Further options are available to include/exclude files by
regular expression patterns, to restrict to use selected content kinds only
(waveform, station, channel, response, event), to create persistent data
selections and more. Finally, the ``--dataset`` option is provided to
configure the dataset conveniently in a YAML file rather than repeatedly with
the many command line options. Using ``--dataset`` includes the possibility
to add online data sources.
.. toctree::
:maxdepth: 2
* **Data query options** are used to restrict processing/presentation to a
subset of a data collection. They have no influence on the data collection
itself, only on what is shown. It is possible to query by time interval
(``--tmin``, ``--tmax``, ``--time``), channel/station code pattern
(``--codes``), and content kinds (``--kinds``).
Manual <manual>
Tutorial <tutorial>

63
doc/source/apps/squirrel/manual.rst

@ -0,0 +1,63 @@
.. image:: /static/squirrel.svg
:align: left
Squirrel command line tool manual
=================================
The :program:`squirrel` command line tool is a front-end to the :ref:`Squirrel
data access infrastructure <squirrel>`.
.. raw:: html
<div style="clear:both"></div>
It offers functionality to
* inspect various aspects of a data collection.
* pre-scan / index file collections.
* download data from online sources (FDSN web services, earthquake catalogs).
* convert large data collections (file format and directory layout)
* manage separate (isolated, local) environments for different projects.
* manage persistent selections to speed up access to very large datasets.
Command reference
-----------------
The :app:`squirrel` tool and its subcommands are self-documenting with the
``--help`` option. Run ``squirrel`` without any options to get the list of
available subcommands. Run ``squirrel SUBCOMMAND --help`` to get details about
a specific subcommand, e.g. ``squirrel scan --help``.
.. toctree::
:maxdepth: 3
squirrel <reference/squirrel>
.. _squirrel_common_options:
Common options
--------------
Options shared between subcommands are grouped into three categories:
* **General options** include ``--loglevel`` to select the
program's verbosity and ``--progress`` to control how progress status is
indicated. These are provided by all of Squirrel's subcommands.
* **Data collection options** control which files and other data sources should
be aggregated to form a dataset. Use the ``--add`` option to add files and
directories. Further options are available to include/exclude files by
regular expression patterns, to restrict to use selected content kinds only
(waveform, station, channel, response, event), to create persistent data
selections and more. Finally, the ``--dataset`` option is provided to
configure the dataset conveniently in a YAML file rather than repeatedly with
the many command line options. Using ``--dataset`` includes the possibility
to add online data sources.
* **Data query options** are used to restrict processing/presentation to a
subset of a data collection. They have no influence on the data collection
itself, only on what is shown. It is possible to query by time interval
(``--tmin``, ``--tmax``, ``--time``), channel/station code pattern
(``--codes``), and content kinds (``--kinds``).

592
doc/source/apps/squirrel/tutorial.rst

@ -0,0 +1,592 @@
.. image:: /static/squirrel.svg
:align: left
Squirrel command line tool tutorial
-----------------------------------
This tutorial introduces seismological data handling with the
:program:`squirrel` command line tool.
.. raw:: html
<div style="clear:both"></div>
The :app:`squirrel` command line tool is a front-end to the :doc:`Squirrel data
access infrastructure </library/reference/squirrel/index>`. In this tutorial,
we will download seismic waveforms organize them into a local file structure
and investigate various properties of the assembled dataset.
For an introduction on how to use the Squirrel framework in your own code,
head on over to :ref:`squirrel_api_cli_example`.
.. contents :: Content
:depth: 4
Downloading data
................
The Squirrel framework contains functionality to download seismic waveforms and
station metadata from FDSN web services. With an appropriate dataset
configuration this can happen in a just-in-time fashion during processing.
However, sometimes we may prefer to completely download a dataset in advance.
This is one of the tasks for which the :app:`squirrel`
command line tool has been created.
In this part of the tutorial we will download a few days of long period seismic
waveforms from the BGR's FDSN web service. We have selected a time window
including the ground motions of the 2021 Mw 8.2 Alaska Earthquake and some of
its aftershocks as they were recorded on German broad-band seismometers. Of
course, you may choose a different time window, set of stations or FDSN web
service, but please be responsible and do not download huge amounts of data
just for testing.
Our first step is to create a local Squirrel environment with
:app:`squirrel init`, so that all the downloaded files
as well as the database are stored in the current directory (our project
directory) under :file:`.squirrel/`. This will make it easier to clean up when
we are done (``rm -rf .squirrel/``). If we omit this step, the user's globally
shared Squirrel environment (:file:`~/.pyrocko/cache/squirrel/`) is used.
Create local environment (optional):
.. code-block:: shell-session
$ squirrel init
To use a remote data source we can create a dataset description file and pass
this to the ``--dataset`` option of the various
:app:`squirrel` subcommands. Examples of such dataset
description files are provided by the
:app:`squirrel template` command. Running this command
without any further arguments will output a brief list of the available
examples. By chance there is one for accessing all LH channels from BGR's FDSN
web service: ``bgr-gr-lh.dataset``. We can save the dataset description file
with:
.. code-block:: shell-session
$ squirrel template bgr-gr-lh.dataset -w
squirrel:psq.cli.template - INFO - File written: bgr-gr-lh.dataset.yaml
The dataset description is a nicely commented YAML file and we could modify it
to our liking:
.. code-block:: yaml
:caption: bgr-gr-lh.dataset.yaml
--- !squirrel.Dataset
# All file paths given below are treated relative to the location of this
# configuration file. Here we may give a common prefix. For example, if the
# configuration file is in the sub-directory 'PROJECT/config/', set it to '..'
# so that all paths are relative to 'PROJECT/'.
path_prefix: '.'
# Data sources to be added (LocalData, FDSNSource, CatalogSource, ...)
sources:
- !squirrel.FDSNSource
# URL or alias of FDSN site.
site: bgr
# Uncomment to let metadata expire in 10 days:
#expires: 10d
# Waveforms can be optionally shared with other FDSN client configurations,
# so that data is not downloaded multiple times. The downside may be that in
# some cases more data than expected is available (if data was previously
# downloaded for a different application).
#shared_waveforms: true
# FDSN query arguments to make metadata queries.
# See http://www.fdsn.org/webservices/fdsnws-station-1.1.pdf
# Time span arguments should not be added here, because they are handled
# automatically by Squirrel.
query_args:
network: 'GR'
channel: 'LH?'
Expert users can get a non-commented version of the file by adding ``--format
brief`` to the :app:`squirrel template` command.
Next, we must update the station meta-information for the time interval of
interest. This is done with the
:app:`squirrel update` command. Channel information
intersecting with the given time interval will be downloaded (Fig. 1):
.. code-block:: shell-session
$ squirrel update --dataset bgr-gr-lh.dataset.yaml --tmin 2021-07-28 --tmax 2021-08-01
[...]
squirrel update:psq.client.fdsn - INFO - FDSN "bgr" metadata: querying...
squirrel update:psq.client.fdsn - INFO - FDSN "bgr" metadata: new (expires: never)
[...]
squirrel update:psq.cli.update - INFO - Squirrel stats:
Number of files: 2
Total size of known files: 87 kB
Number of index nuts: 160
Available content kinds:
channel: 120 1991-09-01 00:00:00.000 - <none>
station: 40 <none> - <none>
Available codes:
GR.AHRW..LHE GR.AHRW..LHN GR.AHRW..LHZ GR.AHRW.* GR.ASSE..LHE GR.ASSE..LHN
GR.ASSE..LHZ GR.ASSE.* GR.BFO..LHE GR.BFO..LHN
[140 more]
GR.UBR..LHZ GR.UBR.* GR.WET..LHE GR.WET..LHN GR.WET..LHZ GR.WET.*
GR.ZARR..LHE GR.ZARR..LHN GR.ZARR..LHZ GR.ZARR.*
Sources:
client:fdsn:b3ad21f2a866c178889cfdf4f493eba588a59543
Operators: <none>
.. figure :: /static/squirrel-cli-update.svg
:align: center
:alt: squirrel update
:figwidth: 80%
Figure 1: The :app:`squirrel update` command
ensures that the local channel metatadata is up to date. Channels epochs
intersecting with the time span specified with ``--tmin`` and
``--tmax`` is downloaded or updated.
After fetching the meta information from the FDSN web service, it prints a
brief overview of the contents currently available in our data collection.
If we run the update command a second time, Squirrel informs us that cached
metadata has been used:
.. code-block:: shell-session
$ squirrel update --dataset bgr-gr-lh.dataset.yaml --tmin 2021-07-28 --tmax 2021-08-01
[...]
squirrel update:psq.client.fdsn - INFO - FDSN "bgr" metadata: using cached (expires: never)
[...]
Only if we call the update command with a yet unknown time span, it will make
new queries. It is also possible to set an expiration date for metadata from
this data-source in the dataset configuration
(:py:class:`~pyrocko.squirrel.client.fdsn.FDSNSource.expires`).
If we later need the instrument response information of the seismic stations of
the data selection, we can add the ``--responses`` option to
:app:`squirrel update` (Fig. 2):
.. code-block:: shell-session
$ squirrel update --responses --dataset bgr-gr-lh.dataset.yaml --tmin 2021-07-28 --tmax 2021-08-01
[...]
Available content kinds:
channel: 120 1991-09-01 00:00:00.000 - <none>
response: 150 1991-01-01 00:00:00.000 - <none>
station: 40 <none> - <none>
[...]
.. figure :: /static/squirrel-cli-update-responses.svg
:align: center
:alt: squirrel update --responses
:figwidth: 80%
Figure 2: With the ``--responses`` option also instrument response
information is downloaded with
:app:`squirrel update`.
So now we also have response information containing details about how the
seismometers convert physical ground motion into measurement records.
Next we must give permission to Squirrel to download data given certain
constraints. Squirrel will only download waveform data when it has a so-called
*promise* for a given time span and channel. These promises must be explicitly
created with the ``--promises`` option of
:app:`squirrel update`. We are only interested in
vertical component seismograms at this point, so we restrict promise creation
to channels ending in 'Z' (Fig. 3):
.. code-block:: shell-session
$ squirrel update --promises --dataset bgr-gr-lh.dataset.yaml --tmin 2021-07-28 --tmax 2021-08-01 --codes '*.*.*.??Z'
[...]
Available content kinds:
channel: 120 1991-09-01 00:00:00.000 - <none>
station: 40 <none> - <none>
waveform_promise: 40 2021-07-28 00:00:00.000 - 2021-08-01 00:00:00.000
[...]
.. figure :: /static/squirrel-cli-update-promises.svg
:align: center
:alt: squirrel update --promises
:figwidth: 80%
Figure 3: With the ``--promises`` option of
:app:`squirrel update` selected time intervals on
selected channels are marked as downloadable. The promises act as
placeholders for the real waveforms which are not yet available.
Why do we need a concept involving "promises" you may ask. Well, besides giving
us a tight leash on what Squirrel will eventually download, it solves a
bookkeeping problem: normally, when resolving a promise and if the download
succeeds, the promise is simply removed. When it fails because of a temporary
problem (e.g. connectivity), it is kept so that the download can be tried again
later. If it however fails permanently, maybe because the waveform is not
available on the server, the promise is deleted, so that we do not repeatedly
query the server for non-existent data. Finally, if we want to freeze the
dataset, we can just remove all remaining promises and no further download
attempts will be made. We think that these benefits outweigh the conceptual
complexity added with the promises.
After setting up the promises, to actually download the waveforms, we can now
use the :app:`squirrel summon` command (Fig. 4):
.. code-block:: shell-session
$ squirrel summon --dataset bgr-gr-lh.dataset.yaml --tmin 2021-07-28 --tmax 2021-08-01
.. figure :: /static/squirrel-cli-summon.svg
:align: center
:figwidth: 80%
:alt: squirrel summon
Figure 4: The with the :app:`squirrel summon`
command, matching promises are resolved by downloading the actual waveforms
if possible. On success, the placeholder promises are removed.
Finally, let's have a look at the waveforms. We can use an experimental
Squirrel-powered version of the :doc:`Snuffler application
</apps/snuffler/index>` to interactively explore the dataset (Fig. 5):
.. code-block:: shell-session
$ squirrel snuffler --dataset bgr-gr-lh.dataset.yaml
.. figure :: /static/squirrel_tutorial1.png
:align: center
:width: 90%
:figwidth: 80%
:alt: output of squirrel_tutorial1.png
Figure 5: Screenshot from :app:`squirrel snuffler`
showing the available waveforms after successfully summoning the dataset.
The downloaded waveforms include the signals from an Mw 8.2 earthquake which
occurred on 2021-07-29 at 06:15 UTC (Fig. 6).
.. figure :: /static/squirrel_tutorial2.png
:align: center
:width: 90%
:figwidth: 80%
:alt: output of squirrel_tutorial2.png
Figure 6: Screenshot from :app:`squirrel snuffler`
after zooming in on the waveforms from the Mw 8.2 Alaska earthquake. The
earthquake was located at a depth of 28 km and 104 km SE of Perryville,
Alaska in the Aleutian megathrust. It was followed by some smaller
aftershocks. The authorities issued a Tsunami warning but only a small
Tsunami of 30 cm was observed and the warning was lifted shortly after.
Waveforms are always downloaded in blocks of reasonable size, therefore the
downloaded time frame may be slightly larger than the requested time span. The
downloaded dataset can be incrementally extended by running
:app:`squirrel update` and
:app:`squirrel summon` multiple times. Only missing
data blocks are downloaded when running
:app:`squirrel summon`. Other waveforms available
through the current Squirrel data collection are also considered to avoid
unnecessary downloads.
Dataset conversion
..................
So far the waveforms have been downloaded into a special cache directory
maintained by Squirrel. Using the data from there is useful if we will later
want to extend the dataset. However, sometimes we want to have full control and
so want to create our own waveform archive in a portable form.
To copy the data downloaded in the previous section into a handy directory
structure, we can use the :app:`squirrel jackseis`
command. With its ``--out-sds-path`` a standard `SDS data directory
<https://www.seiscomp.de/seiscomp3/doc/applications/slarchive/SDS.html>`_ with
day-files in MSEED format is created:
.. code-block:: shell-session
$ squirrel jackseis --dataset bgr-gr-lh.dataset.yaml --out-sds-path data/sds
$ tree data/ # Use `ls`, if `tree` is not installed.
data/
└── sds
└── 2021
└── GR
├── BFO
   └── LHZ.D
   ├── GR.BFO..LHZ.D.2021.208
   ├── GR.BFO..LHZ.D.2021.209
   ├── GR.BFO..LHZ.D.2021.210
   ├── GR.BFO..LHZ.D.2021.211
   ├── GR.BFO..LHZ.D.2021.212
   └── GR.BFO..LHZ.D.2021.213
├── ...
Station metadata is exported when adding the ``--out-meta-path`` option to
:app:`squirrel jackseis`. By default, this exports the
metadata in StationXML format to the given file path:
.. code-block:: shell-session
$ squirrel jackseis --dataset bgr-gr-lh.dataset.yaml --out-meta-path meta/stations.xml
We will use the dataset consisting of the waveforms in ``data/sds`` and the
station meta-data in ``meta/stations.xml`` as a "local dataset" in the
following sections.
Local datasets
..............
To inspect some local data holdings, we can use the :doc:`Snuffler application
</apps/snuffler/index>` by calling
:app:`squirrel snuffler`. Files and directories given
to the ``--add`` option are made available. File formats are usually
autodetected and directories are recursively scanned for any readable files.
To look at the dataset that we have created in the previous section of the
tutorial, use:
.. code-block:: shell-session
$ squirrel snuffler --add data/sds meta/stations.xml
The ``--add`` option is part of a :ref:`group of standardized options
<squirrel_common_options>` to configure the run-time data collection of
Squirrel based programs. If we find ourselves repeatedly specifying the same
file paths over and over again, it may be a good idea to tie them together in a
dataset description file. An example of such a file for local datasets can be
obtained with ``squirrel template local.dataset``. For a nicely organized
project directory, we may want to place the dataset description file into a
subdirectory ``config``:
.. code-block:: shell-session
$ mkdir config
$ squirrel template local.dataset > config/alaska.dataset.yaml
$ nano config/alaska.dataset.yaml # or use your favourite text editor
Let's modify the file so that our precious waveforms and metadata are found:
.. code-block:: yaml
--- !squirrel.Dataset
# All file paths given below are treated relative to the location of this
# configuration file. Here we may give a common prefix. For example, if the
# configuration file is in the sub-directory 'PROJECT/config/', set it to '..'
# so that all paths are relative to 'PROJECT/'.
path_prefix: '..'
# Data sources to be added (LocalData, FDSNSource, CatalogSource, ...)
sources:
- !squirrel.LocalData # This data source is for local files.
# These paths are scanned for waveforms, stations, events.
paths:
- 'data/sds'
- 'meta/stations.xml'
# Select file format or 'detect' for autodetection.
format: 'detect'
The paths in the dataset description file are relative to the location of this
file itself. The value of ``path_prefix`` is prepended to all paths. Because
``alaska.dataset.yaml`` is in the projects subdirectory ``config``, we have set
``path_prefix`` to ``'..'``. With this, the rest of the paths can be given
relative to the project directory root.
Now we can look at our waveforms by just passing the dataset description file
to :app:`squirrel snuffler`:
.. code-block:: shell-session
$ squirrel snuffler --dataset config/alaska.dataset.yaml
With an appropriate configuration of the dataset, local and remote data sources
can be combined. It is also possible to add multiple datasets to a Squirrel
program or to combine ``--dataset`` and ``--add``. Like this, the runtime data
collection can be flexibly composed at program startup. Squirrel maintains
indexes of known files, so that repeated program startups are extremely
efficient. This approach works well with datasets of up to about 100k - 1M
files. For larger data archives, it is possible to create persistent
selections, which we will cover later.
Dataset inspection and querying
...............................
In this part of the tutorial, we will explore some more
:app:`squirrel` subcommands useful when checking data
availability or to hunt down data problems.
Commands like :app:`squirrel snuffler` will always
first index any unknown files. For large data archives, this can take quite
some time. To perform the indexing in advance use the
:app:`squirrel scan` subcommand:
.. code-block:: shell-session
$ squirrel scan --dataset config/alaska.dataset.yaml
To obtain a visual representation of the data availability over time on the
terminal use :app:`squirrel coverage`:
.. code-block:: shell-session
$ squirrel coverage --dataset config/alaska.dataset.yaml
Use ``--tmin`` and ``--tmax`` to narrow down the displayed time span.
To get all data codes identifying the various stations/channels available in a
data collection, run:
.. code-block:: shell-session
$ squirrel codes --dataset config/alaska.dataset.yaml
The returned codes (aka channel IDs / stream IDs / NSLC codes) have the form
``NET.STA.LOC.CHA.EXTRA``, where the first four follow the FDSN conventions and
the optional ``EXTRA`` code is for derived data streams within the Squirrel
framework.
Several :app:`squirrel` subcommands allow querying
for channels using patterns given to the ``--codes`` option. For example
:app:`squirrel nuts` lists index entries. Nuts are the
smallest units of information in the Squirrel framework. To obtain an inventory
listing of everything related to the vertical component of station BFO, we may
run:
.. code-block:: shell-session
$ squirrel nuts --dataset config/alaska.dataset.yaml --codes '*.BFO.*.??Z'
Or, to find out what files in our collection contain information about station
BFO, run:
.. code-block:: shell-session
$ squirrel files --dataset config/alaska.dataset.yaml --codes '*.BFO.*.*'
Similarly, it is possible to query by time span (``--tmin``, ``--tmax``) or
content kind (``--kind``), ie. waveform, channel, response, etc.
Conceptually, we should remember that the collection options build up a data
collection and the query options are used to query information from that
collection. The query options never change the collection itself.
Earthquake catalogs
...................
Squirrel can also be used to retrieve and incrementally update earthquake
catalog information from a few selected online catalogs.
Online catalogs can be added to the
:py:gattr:`~pyrocko.squirrel.dataset.Dataset.sources` in a dataset description.
In this example we will use events with a magnitude above 7.0 from the `GEOFON
earthquake catalog <https://geofon.gfz-potsdam.de/eqinfo/list.php>`_:
.. code-block:: yaml
--- !squirrel.Dataset
path_prefix: '..'
sources:
- !squirrel.LocalData # This data source is for local files.
paths:
- 'data/sds'
- 'meta/stations.xml'
- !squirrel.CatalogSource
catalog: geofon
query_args:
magmin: 7.0
To make sure that the local excerpt of the catalog is up to date for a given
time span, we must call :app:`squirrel update` with
the dataset description and the desired time span:
.. code-block:: shell-session
$ squirrel update --dataset config/alaska.dataset.yaml --tmin 2021-07-28 --tmax 2021-08-01
Again, as we have seen with waveforms and station metadata, Squirrel is lazy
and tries to avoid duplicate downloads of event information. It uses the
locally cached information when possible. To make our dataset aware of updates
in the upstream catalog, we can to set an expiration time for the cached
information
(:py:class:`~pyrocko.squirrel.client.catalog.CatalogSource.expires`) or a time
period for which new data is considered unreliable
(:py:class:`~pyrocko.squirrel.client.catalog.CatalogSource.anxious`).
Large datasets and persistent selections
........................................
So far, the runtime data selection used in each squirrel command has been
composed at each startup. For example when running ``squirrel snuffler --add
data/sds meta/stations.xml``, a temporary database is created with all the
content given to ``--add``. This temporary database is deleted again when
``squirrel snuffler`` exits. The advantage of this approach is that we can very
flexibly combine what data should be available in each processing step. The
disadvantage is that the creation of the temporary database takes some time and
leads to slow program startup for large datasets. To use a persistent instead
of a temporary database, use the ``--persistent`` option. This option takes the
name of the persistent selection which will be created or used as an argument.
For example, to create a persistent selection named ``alaska``, and add all
files in ``data/sds``, run:
.. code-block:: shell-session
$ squirrel snuffler --persistent alaska --add data/sds
To look at the newly created selection:
.. code-block:: shell-session
$ squirrel snuffler --persistent alaska
We can also add further data to the selection:
.. code-block:: shell-session
$ squirrel snuffler --persistent alaska --add meta/stations.xml
It is possible to create multiple persistent selections but each one adds some
internal bookkeeping overhead which can impact the overall performance of the
database.
Existing persistent selections can be listed:
.. code-block:: shell-session
$ squirrel persistent list
To remove again the persistent selection ``alaska``:
.. code-block:: shell-session
$ squirrel persistent remove alaska
Persistent selections trade flexibility against program startup time.
Summary
.......
The :doc:`Squirrel framework </library/reference/squirrel/index>` provides a
unified interface to query and access seismic waveforms, station meta-data and
event information from local file collections and remote data sources. For
prompt responses, a database setup is used under the hood. To speed up
assemblage of ad-hoc data selections, files are indexed on first use and the
extracted meta-data is remembered for subsequent accesses.
The :app:`squirrel` tool provides some of the features of the Squirrel
framework on the command line. In this tutorial, we have seen how we can use it
to perform some every day seismological tasks such as downloading data from
FDSN web services, dataset conversion and inspection.
For an introduction on how to use the Squirrel framework in your own code,
see :ref:`squirrel_api_cli_example`.

2
doc/source/library/examples/squirrel/cli_tool.rst

@ -14,7 +14,7 @@ writing such a script/app, each useful in slightly different situations. If you
use the provided building blocks and follow the conventions laid out below,
your app will immediately feel familiar to other Squirrel users. And it will
ship with a bunch of nice features, like support for extra large datasets. And
it will be pleasure to maintain.
it will be a pleasure to maintain.
**Specs for the tutorial app:**

19
doc/source/library/reference/squirrel/index.rst

@ -1,4 +1,7 @@
.. image:: /static/squirrel.svg
:align: left
.. _squirrel:
``squirrel``
@ -6,15 +9,17 @@
Prompt seismological data access with a fluffy tail.
The :program:`squirrel` command line tool is a front-end to the :doc:`Squirrel
data access infrastructure </library/reference/squirrel/index>`.
The Squirrel framework provides a unified interface to query and access seismic
waveforms, station meta-data and event information from local file collections
and remote data sources. For prompt responses, a profound database setup is
used under the hood. To speed up assemblage of ad-hoc data selections, files
are indexed on first use and the extracted meta-data is remembered for
subsequent accesses. Bulk data is lazily loaded from disk and remote sources,
just when requested. Once loaded, data is cached in memory to expedite typical
access patterns. Files and data sources can be dynamically added and removed at
runtime.
and remote data sources. For prompt responses, a database setup is used under
the hood. To speed up assemblage of ad-hoc data selections, files are indexed
on first use and the extracted meta-data is remembered for subsequent accesses.
Bulk data is lazily loaded from disk and remote sources, just when requested.
Once loaded, data is cached in memory to expedite typical access patterns.
Files and data sources can be dynamically added and removed at runtime.
**Features**

703
doc/source/static/squirrel-cli-summon.svg

@ -0,0 +1,703 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="180mm"
height="60.081089mm"
viewBox="0 0 180 60.081089"
version="1.1"
id="svg5"
inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)"
sodipodi:docname="squirrel-cli-summon.svg"
inkscape:export-filename="/home/heimann/Temp/pyrocko/doc/source/static/squirrel-cli-update.png"
inkscape:export-xdpi="96"
inkscape:export-ydpi="96"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview7"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="mm"
showgrid="true"
inkscape:zoom="1.4786147"
inkscape:cx="354.38576"
inkscape:cy="107.53308"
inkscape:window-width="1918"
inkscape:window-height="1169"
inkscape:window-x="1921"
inkscape:window-y="17"
inkscape:window-maximized="0"
inkscape:current-layer="layer1"
inkscape:pageshadow="2"
inkscape:snap-others="true"
inkscape:snap-text-baseline="false"
inkscape:snap-midpoints="false"
inkscape:object-nodes="true"
inkscape:snap-grids="true"
lock-margins="true"
fit-margin-top="2"
fit-margin-left="2"
fit-margin-right="2"
fit-margin-bottom="2"
inkscape:snap-to-guides="false">
<inkscape:grid
type="xygrid"
id="grid9"
originx="-35.499699"
originy="-8.0965022" />
</sodipodi:namedview>
<defs
id="defs2">
<marker
style="overflow:visible"
id="marker145579"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow2Lend"
inkscape:isstock="true">
<path
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
style="fill:context-stroke;fill-rule:evenodd;stroke:context-stroke;stroke-width:0.625;stroke-linejoin:round"
id="path145577" />
</marker>
<marker
style="overflow:visible"
id="Arrow2Lend"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow2Lend"
inkscape:isstock="true">
<path
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
style="fill:context-stroke;fill-rule:evenodd;stroke:context-stroke;stroke-width:0.625;stroke-linejoin:round"
id="path82326" />
</marker>
<marker
style="overflow:visible"
id="Arrow1Lend"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow1Lend"
inkscape:isstock="true">
<path
transform="matrix(-0.8,0,0,-0.8,-10,0)"
style="fill:context-stroke;fill-rule:evenodd;stroke:context-stroke;stroke-width:1pt"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
id="path82308" />
</marker>
</defs>
<g
inkscape:label="Ebene 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-35.499698,-8.096502)">
<g
id="g98365"
transform="translate(83.343751)">
<path
id="path98359"
style="fill:#eeeeec"
d="m 76.729179,18.520832 h 7.937488 v 43.65625 h -7.937488 z" />
<path
style="fill:none;stroke:#000000;stroke-width:0.264583;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:0.793749, 0.264583;stroke-dashoffset:0;stroke-opacity:1"
d="m 76.729166,18.520833 v 43.65625"
id="path98361" />
<path
style="fill:none;stroke:#000000;stroke-width:0.264583;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:0.793749, 0.264583;stroke-dashoffset:0;stroke-opacity:1"
d="m 84.666667,18.520833 v 43.65625"
id="path98363" />
</g>
<rect
style="fill:#e9b96e;stroke:#000000;stroke-width:0.264583;stroke-opacity:1"
id="rect967"
width="26.458334"
height="1.3229173"
x="144.19792"
y="21.166666" />
<rect
style="fill:#f57900;stroke:#000000;stroke-width:0.264583;stroke-opacity:1"
id="rect967-0"
width="26.458334"
height="1.322916"
x="144.19792"
y="22.489584" />
<rect
style="fill:#e9b96e;stroke:#000000;stroke-width:0.264583;stroke-opacity:1"
id="rect967-1"
width="30.427094"
height="1.3229173"
x="174.62498"
y="21.166666" />
<rect
style="fill:#f57900;stroke:#000000;stroke-width:0.264583;stroke-opacity:1"
id="rect967-0-8"
width="30.427094"
height="1.322916"
x="174.62498"
y="22.489584" />
<rect
style="fill:#8f5902;stroke:#000000;stroke-width:0.264583;stroke-opacity:1"
id="rect967-0-93-3"
width="13.22917"
height="1.322916"
x="157.42708"
y="23.8125" />
<rect
style="fill:#8f5902;stroke:#000000;stroke-width:0.264583;stroke-opacity:1"
id="rect967-0-93-3-83"
width="6.6145797"
height="1.322916"
x="148.16667"
y="23.8125" />
<rect
style="fill:#8f5902;stroke:#000000;stroke-width:0.264583;stroke-opacity:1"
id="rect967-0-93-3-4"
width="13.22917"
height="1.322916"
x="157.42708"
y="30.427084" />
<rect
style="fill:#8f5902;stroke:#000000;stroke-width:0.264583;stroke-opacity:1"
id="rect967-0-93-3-83-3"
width="6.6145797"
height="1.322916"
x="148.16667"
y="30.427084" />
<rect
style="fill:#8f5902;stroke:#000000;stroke-width:0.264583;stroke-opacity:1"
id="rect967-0-93-3-8"
width="17.197924"
height="1.322916"
x="174.62498"
y="23.8125" />
<rect
style="fill:#e9b96e;stroke:#000000;stroke-width:0.264583;stroke-opacity:1"
id="rect967-5"
width="26.458326"
height="1.3229173"
x="144.19792"
y="27.78125" />
<rect
style="fill:#f57900;stroke:#000000;stroke-width:0.264583;stroke-opacity:1"
id="rect967-0-7"
width="26.458326"
height="1.322916"
x="144.19792"
y="29.104168" />
<rect
style="fill:#e9b96e;stroke:#000000;stroke-width:0.264583;stroke-opacity:1"
id="rect967-1-1"
width="30.427094"
height="1.3229173"
x="174.62498"
y="27.78125" />
<rect
style="fill:#f57900;stroke:#000000;stroke-width:0.264583;stroke-opacity:1"
id="rect967-0-8-0"
width="30.427094"
height="1.322916"
x="174.62498"
y="29.104168" />
<rect
style="fill:#8f5902;stroke:#000000;stroke-width:0.264583;stroke-opacity:1"
id="rect967-0-93-3-8-3"
width="17.197924"
height="1.322916"
x="174.62498"
y="30.427084" />
<rect
style="fill:#e9b96e;stroke:#000000;stroke-width:0.264583;stroke-opacity:1"
id="rect967-02"
width="26.458334"
height="1.3229173"
x="144.19792"
y="34.395836" />
<rect
style="fill:#f57900;stroke:#000000;stroke-width:0.264583;stroke-opacity:1"
id="rect967-0-3"
width="26.458334"
height="1.322916"
x="144.19792"
y="35.718754" />
<rect
style="fill:#e9b96e;stroke:#000000;stroke-width:0.264583;stroke-opacity:1"
id="rect967-1-2"
width="30.427094"
height="1.3229173"
x="174.62498"
y="34.395836" />
<rect
style="fill:#f57900;stroke:#000000;stroke-width:0.264583;stroke-opacity:1"
id="rect967-0-8-7"
width="30.427094"
height="1.322916"
x="174.62498"
y="35.718754" />
<rect
style="fill:#8f5902;stroke:#000000;stroke-width:0.264583;stroke-opacity:1"
id="rect967-0-93-3-8-9"
width="17.197924"
height="1.322916"
x="174.62498"
y="37.041668" />
<rect
style="fill:#e9b96e;stroke:#000000;stroke-width:0.264583;stroke-opacity:1"
id="rect967-2"
width="30.427074"
height="1.3229173"
x="153.45833"
y="42.333332" />
<rect
style="fill:#f57900;stroke:#000000;stroke-width:0.264583;stroke-opacity:1"
id="rect967-0-5"
width="30.427086"
height="1.322916"
x="153.45833"
y="43.656246" />
<rect
style="fill:#8f5902;stroke:#000000;stroke-width:0.264583;stroke-opacity:1"
id="rect967-0-93-3-1"
width="27.781246"
height="1.322916"
x="156.10417"
y="44.979164" />
<rect
style="fill:#e9b96e;stroke:#000000;stroke-width:0.264583;stroke-opacity:1"
id="rect967-5-3"
width="30.427086"
height="1.3229173"
x="153.45833"
y="48.947914" />
<rect
style="fill:#f57900;stroke:#000000;stroke-width:0.264583;stroke-opacity:1"
id="rect967-0-7-9"
width="30.427086"
height="1.322916"
x="153.45833"
y="50.270832" />
<rect
style="fill:#8f5902;stroke:#000000;stroke-width:0.264583;stroke-opacity:1"
id="rect967-0-93-3-0-0"
width="27.781248"
height="1.322916"
x="156.10417"
y="51.59375" />
<rect
style="fill:#e9b96e;stroke:#000000;stroke-width:0.264583;stroke-opacity:1"
id="rect967-02-6"
width="30.427074"
height="1.3229173"
x="153.45833"
y="55.5625" />
<rect
style="fill:#f57900;stroke:#000000;stroke-width:0.264583;stroke-opacity:1"
id="rect967-0-3-0"
width="30.427074"
height="1.322916"
x="153.45833"
y="56.885418" />
<rect
style="fill:#8f5902;stroke:#000000;stroke-width:0.264583;stroke-opacity:1"
id="rect967-0-93-3-00-8"
width="27.781248"
height="1.322916"
x="156.10417"
y="58.208332" />
<rect
style="fill:#8f5902;stroke:#000000;stroke-width:0.264583;stroke-opacity:1"
id="rect967-0-93-3-7"
width="13.22917"
height="1.322916"
x="157.42708"
y="37.041664" />
<rect
style="fill:#8f5902;stroke:#000000;stroke-width:0.264583;stroke-opacity:1"
id="rect967-0-93-3-83-7"
width="6.6145797"
height="1.322916"
x="148.16667"
y="37.041664" />
<g
id="g98357">
<path
id="rect21616"
style="fill:#eeeeec"
d="m 76.729179,18.520832 h 7.937488 v 43.65625 h -7.937488 z" />
<path
style="fill:none;stroke:#000000;stroke-width:0.264583;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:0.793749, 0.264583;stroke-dashoffset:0;stroke-opacity:1"
d="m 76.729166,18.520833 v 43.65625"
id="path98108" />
<path
style="fill:none;stroke:#000000;stroke-width:0.264583;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:0.793749, 0.264583;stroke-dashoffset:0;stroke-opacity:1"
d="m 84.666667,18.520833 v 43.65625"
id="path98192" />
</g>
<rect
style="fill:#e9b96e;stroke:#000000;stroke-width:0.264583;stroke-opacity:1"
id="rect21503"
width="26.458334"
height="1.3229173"
x="60.854187"
y="21.166664" />
<rect
style="fill:#e9b96e;stroke:#000000;stroke-width:0.264583;stroke-opacity:1"
id="rect21505"
width="26.458326"
height="1.3229173"
x="60.854187"
y="27.781248" />
<rect
style="fill:#e9b96e;stroke:#000000;stroke-width:0.264583;stroke-opacity:1"
id="rect21507"
width="26.458334"
height="1.3229173"
x="60.854187"
y="34.395836" />
<rect
style="fill:#e9b96e;stroke:#000000;stroke-width:0.264583;stroke-opacity:1"
id="rect21509"
width="30.427074"
height="1.3229173"
x="70.114594"
y="42.333332" />
<rect
style="fill:#e9b96e;stroke:#000000;stroke-width:0.264583;stroke-opacity:1"
id="rect21511"
width="30.427086"
height="1.3229173"
x="70.114594"
y="48.947914" />
<rect
style="fill:#e9b96e;stroke:#000000;stroke-width:0.264583;stroke-opacity:1"
id="rect21513"
width="30.427074"
height="1.3229173"
x="70.114594"
y="55.5625" />
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.175px;font-family:Quicksand;-inkscape-font-specification:'Quicksand, @wght=400';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;font-variation-settings:'wght' 400;fill:#000000;stroke:none"
x="37.347305"
y="24.365416"
id="text21594"><tspan
sodipodi:role="line"
id="tspan21592"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.175px;font-family:Quicksand;-inkscape-font-specification:'Quicksand, @wght=400';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;font-variation-settings:'wght' 400;fill:#000000;stroke:none"
x="37.347305"
y="24.365416">GR.<tspan
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.175px;font-family:Quicksand;-inkscape-font-specification:'Quicksand, @wght=400';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;font-variation-settings:'wght' 400"
id="tspan48099">BFO</tspan>..LHE</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.175px;font-family:Quicksand;-inkscape-font-specification:'Quicksand, @wght=400';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;font-variation-settings:'wght' 400;fill:#000000;stroke:none;stroke-width:0.264583;stroke-opacity:1"
x="37.347313"
y="30.98"
id="text21598"><tspan
sodipodi:role="line"
id="tspan21596"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.175px;font-family:Quicksand;-inkscape-font-specification:'Quicksand, @wght=400';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;font-variation-settings:'wght' 400;fill:#000000;stroke:none;stroke-width:0.264583"
x="37.347313"
y="30.98">GR.BFO..LHN</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.175px;font-family:Quicksand;-inkscape-font-specification:'Quicksand, @wght=400';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;font-variation-settings:'wght' 400;fill:#000000;stroke:none;stroke-width:0.264583;stroke-opacity:1"
x="37.347305"
y="37.594585"
id="text21602"><tspan
sodipodi:role="line"
id="tspan21600"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.175px;font-family:Quicksand;-inkscape-font-specification:'Quicksand, @wght=400';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;font-variation-settings:'wght' 400;fill:#000000;stroke:none;stroke-width:0.264583"
x="37.347305"
y="37.594585">GR.BFO..LHZ</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.175px;font-family:Quicksand;-inkscape-font-specification:'Quicksand, @wght=400';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;font-variation-settings:'wght' 400;fill:#000000;stroke:none;stroke-width:0.264583;stroke-opacity:1"
x="37.347298"
y="45.532082"
id="text21606"><tspan
sodipodi:role="line"
id="tspan21604"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.175px;font-family:Quicksand;-inkscape-font-specification:'Quicksand, @wght=400';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;font-variation-settings:'wght' 400;fill:#000000;stroke:none;stroke-width:0.264583"
x="37.347298"
y="45.532082">GR.ASSE..LHE</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.175px;font-family:Quicksand;-inkscape-font-specification:'Quicksand, @wght=400';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;font-variation-settings:'wght' 400;fill:#000000;stroke:none;stroke-width:0.264583;stroke-opacity:1"
x="37.347305"
y="52.146667"
id="text21610"><tspan
sodipodi:role="line"
id="tspan21608"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.175px;font-family:Quicksand;-inkscape-font-specification:'Quicksand, @wght=400';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;font-variation-settings:'wght' 400;fill:#000000;stroke:none;stroke-width:0.264583"
x="37.347305"
y="52.146667">GR.ASSE..LHN</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.175px;font-family:Quicksand;-inkscape-font-specification:'Quicksand, @wght=400';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;font-variation-settings:'wght' 400;fill:#000000;stroke:none;stroke-width:0.264583;stroke-opacity:1"
x="37.347298"
y="58.76125"
id="text21614"><tspan
sodipodi:role="line"
id="tspan21612"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.175px;font-family:Quicksand;-inkscape-font-specification:'Quicksand, @wght=400';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;font-variation-settings:'wght' 400;fill:#000000;stroke:none;stroke-width:0.264583"
x="37.347298"
y="58.76125">GR.ASSE..LHZ</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.23333px;line-height:1.25;font-family:Quicksand;-inkscape-font-specification:'Quicksand, @wght=700';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;font-variation-settings:'wght' 700;letter-spacing:0px;word-spacing:0px;stroke-width:0.264583"
x="145.56747"
y="13.229167"
id="text60133"><tspan
sodipodi:role="line"
id="tspan60131"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.23333px;font-family:Quicksand;-inkscape-font-specification:'Quicksand, @wght=700';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;font-variation-settings:'wght' 700;stroke-width:0.264583"
x="145.56747"
y="13.229167">Remote FDSN site</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.23333px;line-height:1.25;font-family:Quicksand;-inkscape-font-specification:'Quicksand, @wght=700';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;font-variation-settings:'wght' 700;letter-spacing:0px;word-spacing:0px;stroke-width:0.264583"
x="66.139542"
y="13.229166"
id="text60133-6"><tspan
sodipodi:role="line"
id="tspan60131-6"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.23333px;font-family:Quicksand;-inkscape-font-specification:'Quicksand, @wght=700';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;font-variation-settings:'wght' 700;stroke-width:0.264583"
x="66.139542"
y="13.229166">Squirrel cache</tspan></text>
<text
xml:space="preserve"
style="font-size:3.175px;line-height:1.25;font-family:Quicksand;-inkscape-font-specification:'Quicksand, @wght=400';font-variation-settings:'wght' 400;text-align:end;letter-spacing:0px;word-spacing:0px;text-anchor:end;stroke-width:0.264583"
x="76.729164"
y="66.145836"
id="text90336"><tspan
sodipodi:role="line"
id="tspan90334"
style="text-align:end;text-anchor:end;stroke-width:0.264583"
x="76.729164"
y="66.145836">tmin</tspan></text>
<text
xml:space="preserve"
style="font-size:3.175px;line-height:1.25;font-family:Quicksand;-inkscape-font-specification:'Quicksand, @wght=400';font-variation-settings:'wght' 400;letter-spacing:0px;word-spacing:0px;stroke-width:0.264583"
x="84.666664"
y="66.145836"
id="text92144"><tspan
sodipodi:role="line"
id="tspan92142"
style="stroke-width:0.264583"
x="84.666664"
y="66.145836">tmax</tspan></text>
<text
xml:space="preserve"
style="font-size:3.175px;line-height:1.25;font-family:Quicksand;-inkscape-font-specification:'Quicksand, @wght=400';font-variation-settings:'wght' 400;text-align:end;letter-spacing:0px;word-spacing:0px;text-anchor:end;stroke-width:0.264583"
x="160.07291"
y="66.145836"
id="text90336-2"><tspan
sodipodi:role="line"
id="tspan90334-2"
style="text-align:end;text-anchor:end;stroke-width:0.264583"
x="160.07291"
y="66.145836">tmin</tspan></text>
<text
xml:space="preserve"
style="font-size:3.175px;line-height:1.25;font-family:Quicksand;-inkscape-font-specification:'Quicksand, @wght=400';font-variation-settings:'wght' 400;letter-spacing:0px;word-spacing:0px;stroke-width:0.264583"
x="168.01042"
y="66.145836"
id="text92144-4"><tspan
sodipodi:role="line"
id="tspan92142-6"
style="stroke-width:0.264583"
x="168.01042"
y="66.145836">tmax</tspan></text>
<rect
style="fill:#f57900;stroke:#000000;stroke-width:0.264583;stroke-opacity:1"
id="rect133393"
width="26.458334"
height="1.322916"
x="60.854164"
y="22.489584" />
<rect
style="fill:#f57900;stroke:#000000;stroke-width:0.264583;stroke-opacity:1"
id="rect133395"
width="26.458326"
height="1.322916"
x="60.854164"
y="29.104168" />
<rect
style="fill:#f57900;stroke:#000000;stroke-width:0.264583;stroke-opacity:1"
id="rect133397"
width="26.458334"
height="1.322916"
x="60.854164"
y="35.718754" />
<rect
style="fill:#f57900;stroke:#000000;stroke-width:0.264583;stroke-opacity:1"
id="rect133399"
width="30.427086"
height="1.322916"
x="70.114571"
y="43.656246" />
<rect
style="fill:#f57900;stroke:#000000;stroke-width:0.264583;stroke-opacity:1"
id="rect133401"
width="30.427086"
height="1.322916"
x="70.114571"
y="50.270832" />
<rect
style="fill:#f57900;stroke:#000000;stroke-width:0.264583;stroke-opacity:1"
id="rect133403"
width="30.427074"
height="1.322916"
x="70.114571"
y="56.885418" />
<g
id="path145134" />
<rect
style="fill:#8f5902;stroke:#000000;stroke-width:0.264583;stroke-opacity:1"
id="rect156382"
width="10.583332"
height="1.3229152"
x="75.40625"
y="37.041668" />
<rect
style="fill:#8f5902;stroke:#000000;stroke-width:0.264583;stroke-opacity:1"
id="rect156384"
width="10.583329"
height="1.3229169"
x="75.40625"
y="58.208332" />
<g
id="path83431"
transform="translate(-0.39137633,15.48249)">
<path
style="color:#000000;fill:#000000;-inkscape-stroke:none"
d="m 116.83594,17.068359 c -8.15385,-0.06625 -16.66806,1.19181 -26.912112,3.970703 l 0.06836,0.25586 c 20.455582,-5.548967 33.942742,-5.02217 51.523432,-0.002 l 0.0723,-0.253907 c -8.8052,-2.51435 -16.5981,-3.904449 -24.75195,-3.970703 z"
id="path144175" />
<g
id="g144165">
<g
id="path144167">
<path
style="color:#000000;fill:#000000;fill-rule:evenodd;stroke-width:0.181901;stroke-linejoin:round;-inkscape-stroke:none"
d="m 92.995542,21.559176 -3.375105,-0.296021 2.76283,-1.961053 c -0.309549,0.799289 -0.05944,1.71012 0.612275,2.257074 z"
id="path144171" />
<path
style="color:#000000;fill:#000000;fill-rule:evenodd;stroke-linejoin:round;-inkscape-stroke:none"
d="m 92.404297,19.212891 a 0.09095959,0.09095959 0 0 0 -0.07422,0.01563 l -2.761719,1.960937 a 0.09095959,0.09095959 0 0 0 0.04492,0.164063 l 3.375,0.296875 a 0.09095959,0.09095959 0 0 0 0.06445,-0.16211 C 92.410785,20.965564 92.173563,20.096189 92.46875,19.333984 A 0.09095959,0.09095959 0 0 0 92.4043,19.212891 Z m -0.115235,0.269531 c -0.189964,0.711907 0.0079,1.444378 0.533204,1.970703 l -2.945313,-0.259766 z"
id="path144173" />
</g>
</g>
</g>
<text
xml:space="preserve"
style="font-size:3.175px;line-height:1.25;font-family:Quicksand;-inkscape-font-specification:'Quicksand, @wght=400';font-variation-settings:'wght' 400;text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;stroke-width:0.264583"
x="116.16208"
y="19.320101"
id="text159441"><tspan
sodipodi:role="line"
id="tspan159439"
style="text-align:center;text-anchor:middle;stroke-width:0.264583"
x="116.16208"
y="19.320101">waveform promises</tspan><tspan
sodipodi:role="line"
style="text-align:center;text-anchor:middle;stroke-width:0.264583"
x="116.16208"
y="23.288851"
id="tspan159443">are resolved</tspan><tspan
sodipodi:role="line"
style="text-align:center;text-anchor:middle;stroke-width:0.264583"
x="116.16208"
y="27.257601"
id="tspan159445">by downloading the</tspan><tspan
sodipodi:role="line"
style="text-align:center;text-anchor:middle;stroke-width:0.264583"
x="116.16208"
y="31.226351"
id="tspan159447">waveforms</tspan></text>
<rect
style="fill:#e9b96e;stroke:#000000;stroke-width:0.264583;stroke-opacity:1"
id="rect967-2-5"
width="5.2916613"
height="1.3229173"
x="190.50003"
y="48.947906" />
<rect
style="fill:#8f5902;stroke:#000000;stroke-width:0.264583;stroke-opacity:1"
id="rect967-0-93-3-1-7"
width="5.2916641"
height="1.322916"
x="190.50002"
y="56.885414" />
<rect
style="fill:#f57900;stroke:#000000;stroke-width:0.264583;stroke-opacity:1"
id="rect133399-3"
width="5.2916632"
height="1.322916"
x="190.50003"
y="52.916656" />
<text
xml:space="preserve"
style="font-size:3.175px;line-height:1.25;font-family:Quicksand;-inkscape-font-specification:'Quicksand, @wght=400';font-variation-settings:'wght' 400;letter-spacing:0px;word-spacing:0px;stroke-width:0.264583"
x="198.4375"
y="50.270821"
id="text173348"><tspan
sodipodi:role="line"
id="tspan173346"
style="stroke-width:0.264583"
x="198.4375"
y="50.270821">channel</tspan></text>
<text
xml:space="preserve"
style="font-size:3.175px;line-height:1.25;font-family:Quicksand;-inkscape-font-specification:'Quicksand, @wght=400';font-variation-settings:'wght' 400;letter-spacing:0px;word-spacing:0px;stroke-width:0.264583"
x="198.4375"
y="54.239571"
id="text175144"><tspan
sodipodi:role="line"
id="tspan175142"
style="stroke-width:0.264583"
x="198.4375"
y="54.239571">response</tspan></text>
<text
xml:space="preserve"
style="font-size:3.175px;line-height:1.25;font-family:Quicksand;-inkscape-font-specification:'Quicksand, @wght=400';font-variation-settings:'wght' 400;letter-spacing:0px;word-spacing:0px;stroke-width:0.264583"
x="198.4375"
y="58.208324"
id="text176864"><tspan
sodipodi:role="line"
id="tspan176862"
style="stroke-width:0.264583"
x="198.4375"
y="58.208324">waveform</tspan></text>
<rect
style="fill:#729fcf;stroke:#000000;stroke-width:0.264583;stroke-opacity:1"
id="rect179711"
width="5.2916641"
height="1.322916"
x="190.5"
y="60.854168" />
<text
xml:space="preserve"
style="font-size:3.175px;line-height:1.25;font-family:Quicksand;-inkscape-font-specification:'Quicksand, @wght=400';font-variation-settings:'wght' 400;letter-spacing:0px;word-spacing:0px;stroke-width:0.264583"
x="198.43748"
y="62.177082"
id="text181837"><tspan
sodipodi:role="line"
id="tspan181835"
style="stroke-width:0.264583"
x="198.43748"
y="62.177082">promise</tspan></text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 30 KiB

688
doc/source/static/squirrel-cli-update-promises.svg

@ -0,0 +1,688 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="180mm"
height="60.081089mm"
viewBox="0 0 180 60.081089"
version="1.1"
id="svg5"
inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)"
sodipodi:docname="squirrel-cli-update-promises.svg"
inkscape:export-filename="/home/heimann/Temp/pyrocko/doc/source/static/squirrel-cli-update.png"
inkscape:export-xdpi="96"
inkscape:export-ydpi="96"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview7"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="mm"
showgrid="true"
inkscape:zoom="0.73930735"
inkscape:cx="212.36093"
inkscape:cy="231.29758"
inkscape:window-width="1918"
inkscape:window-height="1169"
inkscape:window-x="1921"
inkscape:window-y="17"
inkscape:window-maximized="0"
inkscape:current-layer="path145134"
inkscape:pageshadow="2"
inkscape:snap-others="true"
inkscape:snap-text-baseline="true"
inkscape:snap-midpoints="false"
inkscape:object-nodes="true"
inkscape:snap-grids="false"
lock-margins="true"
fit-margin-top="2"
fit-margin-left="2"
fit-margin-right="2"
fit-margin-bottom="2"
width="180mm">
<inkscape:grid
type="xygrid"
id="grid9"
originx="-35.499699"
originy="-8.0965022" />
</sodipodi:namedview>
<defs
id="defs2">
<marker
style="overflow:visible"
id="marker145579"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow2Lend"
inkscape:isstock="true">
<path
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
style="fill:context-stroke;fill-rule:evenodd;stroke:context-stroke;stroke-width:0.625;stroke-linejoin:round"
id="path145577" />
</marker>
<marker
style="overflow:visible"
id="Arrow2Lend"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow2Lend"
inkscape:isstock="true">
<path
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
style="fill:context-stroke;fill-rule:evenodd;stroke:context-stroke;stroke-width:0.625;stroke-linejoin:round"
id="path82326" />
</marker>
<marker
style="overflow:visible"
id="Arrow1Lend"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow1Lend"
inkscape:isstock="true">
<path
transform="matrix(-0.8,0,0,-0.8,-10,0)"
style="fill:context-stroke;fill-rule:evenodd;stroke:context-stroke;stroke-width:1pt"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
id="path82308" />
</marker>
</defs>
<g
inkscape:label="Ebene 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-35.499698,-8.096502)">
<g
id="g98365"
transform="translate(83.343751)">
<path
id="path98359"
style="fill:#eeeeec"
d="m 76.729179,18.520832 h 7.937488 v 43.65625 h -7.937488 z" />
<path