Skip to content

Commit

Permalink
Edit user manual (#530)
Browse files Browse the repository at this point in the history
* Fix hyperlink errors caused by picking missing space character

* Fix a ton of improperly formatted py class/meth/func link lines
  • Loading branch information
pavlis authored May 15, 2024
1 parent b43ad79 commit cbe2cce
Show file tree
Hide file tree
Showing 11 changed files with 164 additions and 146 deletions.
6 changes: 3 additions & 3 deletions docs/source/user_manual/adapting_algorithms.rst
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ objects from their ancestors (TimeSeries and ThreeComponentSeismogram).
The current version of the implementations of these two algorithms can be
found `here <https://github.com/mspass-team/mspass/blob/master/cxx/src/lib/algorithms/slice_and_dice.cc>`__.

MsPASS uses the `pybind11 package<https://pybind11.readthedocs.io/en/stable/>`
MsPASS uses the `pybind11 package <https://pybind11.readthedocs.io/en/stable/>`
to bind C++ or C code for use by the python interpreter. For the present
all C/C++ code is bound to a single module we call mspasspy.ccore.
The details of the build system used in MsPASS are best discussed in a
Expand Down Expand Up @@ -183,11 +183,11 @@ We note a few details about this block of code:

1. The :code:`m` symbol is defined earlier in this file as a tag for the module to which we aim to bind this function.
It is defined earlier in the file with this construct:

.. code-block:: c
PYBIND11_MODULE(ccore,m)
That is, this construct defines the symbol :code:`m` as an abstraction for the
python module ccore.

Expand Down
42 changes: 22 additions & 20 deletions docs/source/user_manual/continuous_data.rst
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ data are:
two segments you need to merge have conflicting time stamps.
To make this clear it is helpful to review two MsPASS concepts in
the TimeSeries and Seismogram data objects. Let *d1* and *d2* be
two :code:`TimeSeries` objects that are successive segments we
two :py:class:`TimeSeries<mspasspy.ccore.seismic.TimeSeries>` objects that are successive segments we
expect to merge with *d2* being the segment following *d1* in time.
In MsPASS we use the attribute *t0* (alternatively the method
*starttime*) for the time of sample 0. We also use the method
Expand All @@ -64,10 +64,10 @@ covered by MsPASS.
Gap Processing
~~~~~~~~~~~~~~~~~~
Internally MsPASS handles data gaps with a subclass of the
:code:`TimeSeries` called :code:`TimeSeriesWGaps`. That extension of
:code:`TimeSeries` is written in C++ and is documented
:py:class:`TimeSeries<mspasspy.ccore.seismic.TimeSeries>` called :py:class:`TimeSeriesWGaps<mspasspy.ccore.seismic.TimeSeriesWGaps>``. That extension of
:py:class:`TimeSeries<mspasspy.ccore.seismic.TimeSeries>` is written in C++ and is documented
`here <https://www.mspass.org/cxx_api/mspass.html#mspass-namespace>`__.
Like :code:`TimeSeries` this class has python bindings created
Like :py:class:`TimeSeries<mspasspy.ccore.seismic.TimeSeries>` this class has python bindings created
with pybind11. All the methods described in the C++ documentation
page have python bindings. There are methods for defining gaps,
zeroing data in defined gaps, and deleting gaps.
Expand All @@ -81,12 +81,13 @@ Merging Data Segments
~~~~~~~~~~~~~~~~~~~~~~~~
There are currently two different methods in MsPASS to handle merging
continuous data segments: (1) a special, implicit option of the
:py:meth:`mspasspy.db.database.Database.read_data` method of the
:py:class:`mspasspy.db.database.Database` class, and (2) the
processing function :py:func:`mspasspy.algorithms.window.merge`.
:py:meth:`read_data<mspasspy.db.database.Database.read_data>` method of the
:py:class:`Database<mspasspy.db.database.Database>` class, and (2) the
processing function :py:func:`merge<mspasspy.algorithms.window.merge>`.
In addition, there is a special reader function called
:py:func:`mspasspy.db.ensembles.TimeIntervalReader` that can be used
to read fixed time windows of data. That function uses :code:`merge`
:py:func:`TimeIntervalReader<mspasspy.db.ensembles.TimeIntervalReader>` that can be used
to read fixed time windows of data. That function uses
:py:func:`merge<mspasspy.algorithms.window.merge>`
to do gap and overlap repair.

read_data merge algorithm
Expand All @@ -101,8 +102,8 @@ waveform. If the station codes ("net", "sta", "chan", and "loc" attributes
in all MsPASS schemas) change in a sequence of packets readers
universally assume that is the end of a given segment. How readers handle
a second issue is, however, variable. Each miniseed packet has a time
tag that is comparable to the `t0` attribute of a :class:`TimeSeries` object
and end time field equivalent to the output of the :class:`TimeSeries`
tag that is comparable to the `t0` attribute of a :py:class:`TimeSeries<mspasspy.ccore.seismic.TimeSeries>` object
and end time field equivalent to the output of the :py:class:`TimeSeries<mspasspy.ccore.seismic.TimeSeries>`
endtime method. If the `t0` value of a packet is greater than some
fractional tolerance of 1 sample more than the endtime of the previous
packet, a reader will invoke a gap handler. A reader's gap handler
Expand All @@ -112,7 +113,7 @@ handles this problem with their :class:`Stream` merge method described
`here <https://docs.obspy.org/packages/autogen/obspy.core.stream.Stream.merge.html>`__.
That particular algorithm is invoked when reading miniseed data
if and only if a block of data defined running the mspass
function :py:meth:`mspasspy.db.database.Database.index_mseed_file` is
function :py:meth:`index_mseed_file<mspasspy.db.database.Database.index_mseed_file>` is
run with the optional argument `segment_time_tears` is set False.
(Note the default is True.). If you need to use this approach, you will
need to also take care in defining the value of the following arguments
Expand All @@ -132,7 +133,7 @@ the obspy merge function noted above. The MsPASS function add some additional
features and, although not verified by formal testing,
is likely much faster than the obpsy version due to fundamental differences
in the implementation.
The docstring for :py:func:`mspasspy.algorithms.window.merge` describes more
The docstring for :py:func:`merge<mspasspy.algorithms.window.merge>` describes more
details but some key features of this function are:

- Like obspy's function of the same name its purpose is to glue/merge
Expand All @@ -148,7 +149,7 @@ details but some key features of this function are:
options for gap handling that are inseparable from the function.
Any detected gaps in the
MsPASS merge function are posted to the Metadata component of the
:class:`TimeSeries` it returns accessible with the key "gaps".
:py:class:`TimeSeries<mspasspy.ccore.seismic.TimeSeries>` it returns accessible with the key "gaps".
The content of the "gaps" attribute is a list of one or more
python dictionaries with the keyworks "starttime" and "endtime"
defining the epoch time range of all gaps in the returned datum.
Expand All @@ -167,29 +168,30 @@ details but some key features of this function are:
a data quality problem that invalidates the data when the samples
do not match. If you need
the obspy functionality use the
:py:func:`mspasspy.util.converter.TimeSeriesEnsemble2Stream` and the
inverse :py:func:`mspasspy.util.converter.Trace2TimeSeriesEnsemble`
:py:func:`TimeSeriesEnsemble2Stream<mspasspy.util.converter.TimeSeriesEnsemble2Stream>` and the
inverse :py:func:`Trace2TimeSeriesEnsemble<mspasspy.util.converter.Trace2TimeSeriesEnsemble>`
to create the obspy input and then restore the returned data to
the MsPASS internal data structures

TimeIntervalReader
-----------------------
A second MsPASS tool for working with continuous data is a function
with the descriptive name :py:func:`mspasspy.db.ensembles.TimeIntervalReader`.
with the descriptive name
:py:func:`TimeIntervalReader<mspasspy.db.ensembles.TimeIntervalReader>`.
It is designed to do the high-level task of cutting a fixed time
interval of data from one or more channels of a continuous data archive.
This function is built on top of the lower-level
:py:func:`mspasspy.algorithms.window.merge` but is best thought of as
:py:func:`merge<mspasspy.algorithms.window.merge>` but is best thought of as
an alternative reader to create ensembles cut from a continuous data archive.
For that reason the required arguments are a database handle and the
time interval of data to be extracted from the archive. Gap and overlap
handling is handled by :code:`merge`.
handling is handled by :py:func:`merge<mspasspy.algorithms.window.merge>`.

Examples
------------
*Example 1: Create a single waveform in a defined time window
from continuous data archive.*
This script will create a longer :class:`TimeSeries` object from a set day files
This script will create a longer :py:class:`TimeSeries<mspasspy.ccore.seismic.TimeSeries>` object from a set day files
for the BHZ channel of GSN station AAK. Ranges are constant for a simple
illustration:

Expand Down
30 changes: 15 additions & 15 deletions docs/source/user_manual/data_object_design_concepts.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Overview
atomic objects in seismology waveform processing:  scalar (i.e. single
channel) signals, and three-component signals.   The versions of these
you as a user should normally interact with are two objects defined in
MsPASS as :code:`TimeSeries` and :code:`Seismogram` respectively.  
MsPASS as :py:class:`TimeSeries<mspasspy.ccore.seismic.TimeSeries>` and :py:class:`Seismogram<mspasspy.ccore.seismic.Seismogram>` respectively.  
| These data objects were designed to simply interactions with MongoDB. 
MongoDB is completely flexible in attribute names handled by the
Expand All @@ -34,8 +34,9 @@ Overview
generic ensemble.   A limitation of the current capability to link C++
binary code with python is that templates do not translate directly.  
Consequently, the python interface uses two different names to define
Ensembles of TimeSeries and Seismogram objects:  :code:`TimeSeriesEnsemble`
and :code:`SeismogramEnsemble` respectively.
Ensembles of TimeSeries and Seismogram objects: 
:py:class:`TimeSeriesEnsemble<mspasspy.ccore.seismic.TimeSeriesEnsemble>`
and :py:class:`SeismogramEnsemble<mspasspy.ccore.seismic.SeismogramEnsemble>` respectively.
| The C++ objects have wrappers for python that hide implementation details from
the user.   All MongoDB operations implemented with the pymongo
Expand All @@ -52,8 +53,7 @@ History
developed by one of the authors (Pavlis) over a period of more than 15
years.   The original implementation was developed as a component of
Antelope.  It was distributed via the open source additions to
Antelope distributed through the `Antelope user's
group
Antelope distributed through the `Antelope user's group
<https://github.com/antelopeusersgroup/antelope_contrib>`__ and referred to as SEISPP.   The bulk of
the original code can be found
`here <https://github.com/antelopeusersgroup/antelope_contrib/tree/master/lib/seismic/libseispp>`__
Expand Down Expand Up @@ -105,15 +105,15 @@ History
:code:`Schema` object to reduce all Metadata to pure
name:value pairs. 
#. obspy does not handle three component data in a native way, but mixes
up the concepts we call :code:`Seismogram` and :code:`Ensemble` in to a common
up the concepts we call :py:class:`Seismogram<mspasspy.ccore.seismic.Seismogram>` and :code:`Ensemble` in to a common
python object they define as a
`Stream <http://docs.obspy.org/packages/autogen/obspy.core.stream.Stream.html#obspy.core.stream.Stream>`__.  
We would argue our model is a more logical encapsulation of the
concepts that define these ideas. For example, a collection of single
component data like a seismic reflection shot gather is a very different
thing than a set of three component channels that define the output of
three sensors at a common point in space. Hence, we carefully
separate :code:`TimeSeries` and :code:`Seismogram` (our name for Three-Component
separate :py:class:`TimeSeries<mspasspy.ccore.seismic.TimeSeries>` and :py:class:`Seismogram<mspasspy.ccore.seismic.Seismogram>` (our name for Three-Component
data). We further distinguish :code:`Ensembles` of each atomic type.

Core Concepts
Expand Down Expand Up @@ -141,7 +141,7 @@ Overview - Inheritance Relationships
inheritance from three base classes:  :code:`BasicTimeSeries`,
:code:`BasicMetadata`, and :code:`BasicProcessingHistory`.   Python supports multiple
inheritance and the wrappers make dynamic casting within the hierarchy
(mostly) automatic.  e.g. a :code:`Seismogram` object can be passed directly to a
(mostly) automatic.  e.g. a :py:class:`Seismogram<mspasspy.ccore.seismic.Seismogram>` object can be passed directly to a
python function that does only Metadata operations and it will be
handled seamlessly because python does not enforce type signatures on
functions.  CoreTimeSeries and CoreSeismogram should be thought of a
Expand All @@ -157,7 +157,7 @@ Overview - Inheritance Relationships
completely different framework. 
| We emphasize here that users should normally expect to only interact with
the :code:`TimeSeries` and :code:`Seismogram` objects. The lower levels sometimes
the :py:class:`TimeSeries<mspasspy.ccore.seismic.TimeSeries>` and :py:class:`Seismogram<mspasspy.ccore.seismic.Seismogram>` objects. The lower levels sometimes
but not always have python bindings.
| The remainder of this section discusses the individual components in
Expand Down Expand Up @@ -536,12 +536,12 @@ Scalar versus 3C data
container.  

| We handle three component data in MsPASS by using a matrix to store the data
for a given :code:`Seismogram`.   The data are directly accessible in C++ through a public
for a given :py:class:`Seismogram<mspasspy.ccore.seismic.Seismogram>`.   The data are directly accessible in C++ through a public
variable called u that is mnemonic for the standard symbol used in the
old testament of seismology by Aki and Richards. In python we use the
symbol :code:`data` for consistency with TimeSeries.
There are two choices of the order of indices for this matrix. 
The MsPASS implementation makes this choice: a :code:`Seismogram`
The MsPASS implementation makes this choice: a :py:class:`Seismogram<mspasspy.ccore.seismic.Seismogram>`
defines index 0(1) as the channel number and index 1(2) as the time
index.  The following python code section illustrates this more
clearly than any words:
Expand Down Expand Up @@ -645,7 +645,7 @@ Core versus Top-level Data Objects
focus on the data structure they impose. Other sections expand on
the details of both classes.
| Both :code:`TimeSeries` and :code:`Seismogram` objects extend their
| Both :py:class:`TimeSeries<mspasspy.ccore.seismic.TimeSeries>` and :py:class:`Seismogram<mspasspy.ccore.seismic.Seismogram>` objects extend their
"core" parents by adding two classes:
#. :code:`ProcessingHistory`, as the name implies, can (optionally) store the
Expand Down Expand Up @@ -678,9 +678,9 @@ Core versus Top-level Data Objects
for Seismogram and TimeSeries, but it does not satisfy the basic rule of
making a concept a base class if the child "is a" ErrorLogger.
It does, however, perfectly satisfy the idea that the object "has an"
ErrorLogger. Both :code:`TimeSeries` and :code:`Seismogram` use the
ErrorLogger. Both :py:class:`TimeSeries<mspasspy.ccore.seismic.TimeSeries>` and :py:class:`Seismogram<mspasspy.ccore.seismic.Seismogram>` use the
symbol :code:`elog` as the name for the ErrorLogger object
(e.g. If *d* is a :code:`Seismogram` object, *d.elog*, would refer to
(e.g. If *d* is a :py:class:`Seismogram<mspasspy.ccore.seismic.Seismogram>` object, *d.elog*, would refer to
the error logger component of *d*.)''

Object Level History Design Concepts
Expand Down Expand Up @@ -822,7 +822,7 @@ Error Logging Concepts
  d.elog.log_error(d.job_id(),alg,err)
  d.kill()  
| To understand the code above assume the symbol d is a :code:`Seismogram`
| To understand the code above assume the symbol d is a :py:class:`Seismogram<mspasspy.ccore.seismic.Seismogram>`
object with a singular transformation matrix created, for example, by
incorrectly building the object with two redundant east-west
components.   The rotate_to_standard method tries to compute a matrix
Expand Down
6 changes: 4 additions & 2 deletions docs/source/user_manual/database_concepts.rst
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,9 @@ With that background, there are two collections used to manage waveform data.
They are called :code:`wf_TimeSeries` and :code:`wf_Seismogram`.
These two collection are the primary work areas to assemble a working data set.
We elected to keep data describing each of the two atomic data types in MsPASS,
:code:`TimeSeries` and :code:`Seismogram`, in two different collections. The
:py:class:`TimeSeries<mspasspy.ccore.seismic.TimeSeries>`
and :py:class:`Seismogram<mspasspy.ccore.seismic.Seismogram>`,
in two different collections. The
main reason we made the decision to create two collections instead of one
is that there are some minor differences in the Metadata that would
create inefficiencies if we mixed the two data types in one place.
Expand Down Expand Up @@ -839,7 +841,7 @@ imports data through a two step procedure:
function builds only an index of the given file and writes the index to
a special collection called :code:`wf_miniseed`.

2. The same data can be loaded into memory as a MsPASS :code:`TimeSeriesEnsemble`
2. The same data can be loaded into memory as a MsPASS :py:class:`TimeSeriesEnsemble<mspasspy.ccore.seismic.TimeSeriesEnsemble>`
object using the related function with this signature:

.. code-block:: python
Expand Down
Loading

0 comments on commit cbe2cce

Please sign in to comment.