Writing Documentation¶
The documentation for QInfer is written using the Sphinx documentation engine, and is hosted by ReadTheDocs. This allows us to produce high-quality HTML- and LaTeX-formatted reference and tutorial material for QInfer. In particular, the documentation hosted by ReadTheDocs is integrated with the GitHub project for QInfer, simplifying the process of building and deploying documentation.
In this section, we will discuss how to use Sphinx and ReadTheDocs together to contribute to and improve QInfer documentation.
Building Documentation With Sphinx¶
In developing and writing documentation, it is helpful to be able to compile the current version of the documentation offline. To do so, first install Sphinx itself. If you are using Anaconda:
$ conda install sphinx
Otherwise, we suggest installing Sphinx using pip:
$ pip install sphinx
In either case, after installing Sphinx, you may need to install additional libraries that used by particular examples in the QInfer documentation. On Anaconda:
$ conda install scikit-learn ipython future matplotlib
$ conda install -c conda-forge qutip
$ pip install mpltools
Otherwise:
$ pip install -r doc/rtd-requirements.txt
With the dependencies installed, you can now build the documentation
using the Makefile
provided by Sphinx, or using the make.bat
script for Windows. Note that because the documentation includes several
computationally-intensive examples, the build process may take a significant
amount of time (a few minutes). On Linux and OS X:
$ cd doc/
$ make clean # Deletes all previously compiled outputs.
$ make html # Builds HTML-formatted docs.
$ make latexpdf # Builds PDF-formatted docs using LaTeX.
All of the compiled outputs will be saved to the doc/_build
folder. In particular, the HTML version can be found at
doc/_build/html/index.html
.
On Windows, we recommend using PowerShell to run make.bat
:
PS > cd doc/
PS > .\make.bat clean
PS > .\make.bat html
Note that on Windows, building PDF-formatted docs requires an additional step. First, make the LaTeX-formatted source:
PS > .\make latex
This will produce a folder called doc/_build/latex
containing
QInfer.tex
. Build this with your favorite LaTeX front-end to
produce the final PDF.
Formatting Documentation With reStructuredText¶
The documentation itself is written in the reStructuredText language,
an extensible and (largely) human-readable text format. We recommend
reading the primer provided with Sphinx to get a start. Largely, however,
documentation can be written as plain text, with emphasis indicated
by *asterisks*
, strong text indicated by **double asterisks**
,
and verbatim snippets indicated by ``double backticks``
.
Sections are denoted by different kinds of underlining,
using =
, -
, ~
and ^
to indicate sections, subsections,
paragraphs and subparagraphs, respectively.
Links are a bit more complicated, and take on a couple several different forms:
Inline links consist of backticks, with addresses denoted in angle-brackets,
`link text <link target>`_
. Note the final_
, which denotes that the backticks describe a link.Alternatively, the link target may be placed later on the page, as in the following snippet:
Lorem `ipsum`_ dolor sit amet... .. _ipsum: http://www.lipsum.com/
Links within the documentation are made using
:ref:
. For example,:ref:`apiref`:
formats as API Reference. The target of such a reference must be declared before a section header, as in the following example, which declares the targetfoobar
:.. _foobar: A Foo About Bar ---------------
Links to Python classes, modules and functions are formatted using
:class:
,:mod:
and:func:
, repsectively. For example,:class:`qinfer.SMCUpdater
formats asqinfer.SMCUpdater
. To suppress the path to a Python name, preface the name with a tilde (~
), as in:class:`~qinfer.SMCUpdater:`
. For a Python name to be a valid link target, it must be listed in the API Reference (see below), or must be documented in one of the external projects listed indoc/conf.py
. For instance, to link to NumPy documentation, use a link of the form:class:`~numpy.ndarray`
.Finally, QInfer provides special notation for linking to DOIs, Handles and arXiv postings:
:doi:`10.1088/1367-2630/18/3/033024`, :hdl:`10012/9217`, :arxiv:`1304.5828`
Typesetting Math¶
Math is formatted using the Sphinx markup :math:`...`
in place
of $
, and using the .. math::
directive in place of $$
.
When building HTML- or PDF-formatted documentation, this is automatically
converted to MathJax- or LaTeX-formatted math. The QInfer
documentation is configured with several macros available to each of
MathJax and LaTeX, specified in doc/_templates/page.html
and doc/conf.py
, respectively. For example, :math:`\expect`
is configured to produce the blackboard-bold expectation operator
\(\expect\).
Docstrings and API References¶
One of the most useful features of Sphinx is that it can import documentation
from Python code itself. In particular, the .. autofunction::
and
.. autoclass::
directives import documentation from functions and classes,
respectively. These directives typeset the docstrings for their targets as
reStructuredText, with the following notation used to indicate arguments,
return types, etc.:
:param name:
is used to declare that a class’ initializer or a function takes an argument namedname
, and is followed by a description of that parameter.:param type name:
can be used to indicate thatname
has the type typetype
. Iftype
is a recognized Python type, then Sphinx will automatically convert it into a link.:type name:
can be used to provide more detailed information about the type of the parametername
, and is followed by a longer description of that parameter’s type.:type:
on its own can be used to denote the type of a property accessor.:return:
is used to describe what a function returns.:rtype:
is used to describe the type of a return value.:raises exc_type:
denotes that the described function raises an exception of typeexc_type
, and describes the conditions under which that exception is raised.
In addition to the standard Sphinx fields described above, QInfer adds the following fields:
:modelparam name:
describes a model parameter namedname
, where the name is formatted as math (or should be, pending bugs in the documentation configuration).:expparam field_type field_name:
describes an experiment parameter field namedfield_name
withdtype
field_type
.:scalar-expparam scalar_type
describes that a class has exactly one experiment parameter of typescalar_type
.:column dtype name:
describes a column for data taken by Simple Estimation Functions functions.
Importantly, if math is included in a docstring, it is highly
recommended to format the docstring as a raw string; that is,
as a string starting with r'
or r"
for inline strings
or r'''
or r"""
for multi-line strings. This avoids having
to escape TeX markup that appears within a docstring. For instance,
consider the following hypothetical function:
def state(theta, phi):
r"""
Returns an array representing :math:`\cos(\theta)\ket{0} +
\sin(\theta) e^{i \phi} \ket{1}`.
"""
...
If the docstring were instead declared using """
, then
\t
everywhere inside the docstring would be interpreted by
Python as a tab character, and not as the start of a LaTeX command.
Showing Code Snippets¶
The documentation would be useless without code snippets, so Sphinx provides several ways to show snippets. Perhaps the most common is doctest-style:
Lorem ipsum dolor sit amet...
>>> print("Hello, world!")
Hello, world!
As described in _doctest_devguide, these snippets are run
automatically as tests to ensure that the documentation and code
are both correct. To mark a particular line in a snippet as not
testable, add # doctest: +SKIP
as a comment after.
For longer snippets, or for snippets that should not be run as
tests, use the .. code:: python
directive:
.. code:: python
print("Hello, world!")
This formats as:
print("Hello, world!")
Finally, a block can be formatted as code without any syntax highlighting
by using the ::
notation on the previous line, and then indenting
the block itself:
This is in fact how this section denotes reStructuredText code samples::
:foobar: is not a valid reStructuredText role.
Plotting Support¶
Sphinx can also run Python code and plot the resulting figures.
To do so, use the .. plot::
directive. Note that any such plots
should be relatively quick to generate, especially so as to not
overburden the build servers provided by ReadTheDocs.
The .. plot::
directive has been configured to automatically
import QInfer itself and to import matplotlib as plt
.
Thus, for example, the following demonstrates plotting functionality
provided by the qinfer.tomography
module:
.. plot::
basis = tomography.bases.pauli_basis(1)
prior = tomography.distributions.GinibreDistribution(basis)
tomography.plot_rebit_prior(prior, rebit_axes=[1, 3])
plt.show()
Note the plt.show()
call at the end; this is required to produce
the final figure!