Documentation Wiki

This page regroups information about the creation of this documentation.

Important

Please read this carefully if you want to participate in the documentation process.

Getting started

We all think we know what software documentation should look like… well guess what, most of us are wrong!

So read this and finally understand what software documentation is!

For a list of awesome Sphinx extension look here: https://github.com/yoloseem/awesome-sphinxdoc

Sphinx

Many tools allow generation and publication of technical documentation, but I chose to use sphinx as it is the only one (to my knowledge) oriented towards Python and offering solutions to automatically generate documentation from the docstrings.

Setup

To install the Sphinx package:

Usage

Initial documentation setup

In a terminal, at the root of the package (e.g. timagetk/), initialize your sphinx documentation with:

sphinx-quickstart

This will create a docs folder at the root of the package.

Build documentation

To generate the documentation HTML files, got to the documentation root folder, e.g. timegetk/docs/ and call make html:

cd timagetk/docs
make html

You should now have a build directory under timegetk/docs/ where you will find a index.html file.

MyST parser

As reStructuredText can be super tedious, we use the MyST parser to write the documentation in Markdown instead.

Setup

To install the MyST parser package:

In the docs/source/conf.py configuration file, add myst_parser to the extensions list:

extensions = [
    ...
    'myst_parser',  # Markdown parser
    ...
]

The chosen configuration is also specified in the docs/source/conf.py after activating the extension:

# Optional MyST syntax:
myst_enable_extensions = [
    "amsmath",
    "dollarmath",
    "colon_fence",
    "deflist"
]
# Activate auto-generated header anchors (for Hearders H1-3)
myst_heading_anchors = 3

Look here for a description of optional MyST syntaxes.

To be able to use a file named index.md instead of the default index.rst, you have to set these variables in the conf.py:

source_suffix = '.md'
master_doc = 'index'

Usage

You may now write files in Markdown to generate your documentation. Do not forget to read the official MyST syntax guide here.

MyST notebooks

We use jupyter notebooks for tutorials and how-to.

Setup

To install the MyST{NB} package:

In the docs/source/conf.py configuration file, add myst_nb to the extensions list:

extensions = [
    ...
    # 'myst_parser',  # MyST markdown parser, activated by 'myst_nb'
    'myst_nb',  # MyST jupyter notebooks parser
    ...
]

Warning

If you are using MyST-NB in your documentation, do not activate myst_parser in the extensions list. It will be automatically activated by myst_nb.

Usage

Configuration

In the docs/source/conf.py configuration file, we force the execution of notebooks with:

jupyter_execute_notebooks = "force"

Cleanup prior to documentation generation

Edit the Makefile to force documentation notebooks to have their output cells cleaned up prior to generating the documentation with sphinx.

Add these lines to top of the the html section of the Makefile:

	@echo "Cleaning documentation notebooks cell outputs..."
	find source -type f \( -name "*.ipynb" -not -wholename "*/.ipynb_checkpoints/*" \) -print -exec jupyter nbconvert --ClearOutputPreprocessor.enabled=True --inplace {} \;

This will search for all .ipynb files in the source documentation folder, excluding those in hidden .ipynb_checkpoints folders and clean them up.

Report notebook execution statistics

Create a notebooks_summary.md MarkDown file with the following content:

# Notebooks execution statistics
```{nb-exec-table}
```

This will generate a table summarizing the execution of the notebooks by MyST-NB. We do not reference it in the table of content has it is meant to be used by developers to check the correct execution of the notebooks.

Automatic API generation

To automatically generate the reference API we use the sphinx module autodoc. As we write our docstring in Numpy format (reference style guide here) we also use the napoleon extension.

Setup

In the docs/source/conf.py configuration file, add sphinx.ext.autodoc & sphinx.ext.napoleon to the extensions list:

extensions = [
    ...
    'sphinx.ext.autodoc',  # Include documentation from docstrings
    'sphinx.ext.napoleon',  # Support for NumPy and Google style docstrings
    ...
]

The chosen configuration for the napoleon extension is also specified in the docs/source/conf.py after activating the extension:

napoleon_google_docstring = False
napoleon_numpy_docstring = True
napoleon_include_init_with_doc = False
napoleon_include_private_with_doc = False
napoleon_include_special_with_doc = False
napoleon_use_admonition_for_examples = False
napoleon_use_admonition_for_notes = False
napoleon_use_admonition_for_references = False
napoleon_use_ivar = False
napoleon_use_keyword = True
napoleon_use_param = True
napoleon_use_rtype = False

Usage

The official documentation of MyST has a specific section in their “how-to” detailing this, look here

Now you can use the autodoc module to generate the reference API documentation using the .. automodule:: directive.

For example, to generate the reference API of the blockmatching algorithm:

Note

The :noindex: option here is to avoid duplicate object description of timagetk.algorithms.blockmatching.blockmatching as it is already called in the API documentation.

Automatic CLI documentation

To automatically add the documentation of CLI scripts built with the argparse Python module we use the sphinx-argparse extension.

Setup

Install the sphinx-argparse extension:

In the docs/source/conf.py configuration file, add sphinxarg.ext to the extensions list:

extensions = [
    ...
    'sphinxarg.ext'  # To include tables describing command-line arguments for executable scripts
    ...
]

Usage

To automatically document a script built with argparse:

Note

The :noindex: option here is to avoid duplicate object description of timagetk.algorithms.blockmatching.blockmatching as it is already called in the API documentation.

Simple inheritance diagram

In Sphinx, you can use the .. inheritance-diagram:: directive to generate simple inheritance diagrams.

Setup

In the docs/source/conf.py configuration file, add sphinx.ext.inheritance_diagram to the extensions list:

extensions = [
    ...
    'sphinx.ext.inheritance_diagram',  # Add inheritance diagram directive
    ...
]

Usage

To generate the inheritance diagram of the SpatialImage Class:

Don’t forget to add this inside the {eval-rst} block with MyST!

UML diagrams

We use pyreverse, a part of Pylint, to generate a full UML class diagram of our data structures.

Setup

Install pylint package:

Warning

This also require installing Graphviz system-wide as the python package only contains the bindings!

sudo apt install graphviz

Usage

Added these lines to the top of the html section of the Makefile to automatically re-generates the PNGs when using make html:

    @echo "Generating components UML diagram for classes & modules..."
    pyreverse ../src/timagetk/components/ -o png -d source/_static/image/

This export a files packages.png & classes.png to timagetk/docs/source/_static/image/.

Tabbed content

We use the sphinx-panels extension to produce tabbed content. Link to sphinx-panels documentation.

Setup

Install the sphinx-panels extension:

In the docs/source/conf.py configuration file, add sphinx_panels to the extensions list:

extensions = [
    ...
    'sphinx_panels',  # Enable panels, cards & tabs usage
    ...
]

Usage

The tabbed content in the Setup section where you can choose between conda & pip is made using:

````{tabbed} conda
```shell
conda install -c conda-forge sphinx-panels
```
````
````{tabbed} pip
```shell
python -m pip install sphinx-panels
```
````

Warning

Adding this extension changed the website layout by fixing a max width on the notebook cells. This was fixed by adding panels_add_bootstrap_css = False to the docs/source/conf.py configuration file.

CopyButton

To add the “copy button” in each code block we use the sphinx-copybutton extension. Link to sphinx-copybutton documentation.

Setup

Install the sphinx-copybutton extension:

In the docs/source/conf.py configuration file, add sphinx_copybutton to the extensions list:

extensions = [
    ...
    'sphinx_copybutton',  # Enable a copy button in each code-block
    ...
]

Usage

When you build your site, your code blocks should now have little copy buttons to their right. Clicking the button will copy the code inside!

Layout and styling

We modified the builtin theme Alabaster to improve it and chose to set:

Modified docs/source/conf.py configuration file:

html_theme = 'alabaster'

html_theme_options = {
    'body_min_width': '700px',
    'body_max_width': '1400px',
    'font_size': '17px',
    'code_font_size': '16px',
    'font_family': 'Lato,proxima-nova,Helvetica Neue,Arial,sans-serif',
    'page_width': '65%',
    'logo': 'image/logo_timagetk.png',
    'fixed_sidebar': True,
    'show_powered_by': True,
    'show_relbar_bottom': True,
    'pre_bg': '#272822'
}

pygments_style = 'monokai'
html_static_path = ['_static/']
html_css_files = ['css/custom.css']

panels_add_bootstrap_css = False

Added custom CSS style-sheet _static/css/custom.css:

dl {
    margin: 0 0 1.5em 0;
    padding: 0;
}

pre {
    padding: 7px 10px;

}
div.container.cell {
    font-size: 16px;
}