Contributions (bug reports, fixes, documentation, enhancements, ideas, …) are welcome and appreciated.

To get started, find the best path for your contribution:

  • Ask questions, discuss models, and present ideas in Discussions.

  • Report bugs or suggest changes as Issues.

  • Contribute fixes or improvements as Pull Requests.

Please follow the Github Community Guidelines when participating in any of these forums.

The following emulates the xarray contributing guidelines.

Contributing to documentation#

Documentation is written in reStructuredText and synthesized with Sphinx.

For small changes, fork and edit files directly in the Github interface.

For larger changes:

$ pip install -e ".[docs]"
  • Edit documents and notebooks following existing conventions.

  • Build and review the documentation locally:

# docs build to directory docs/_build/html
$ make docs-build

# automatically build docs on changes
# docs will be served at
$ make docs-serve

Contributing to the code base#

If you are new to development, see xarray’s Working with the code. This reference provides an introduction to version control, git, Github, Forking, and creating branches.

For more involved changes, create a Github Issue describing the intended changes first.

Once you’re ready to develop:

# set up dev install automatically
$ make dev-install

# install dependencies and pre-commit hooks manually
$ pip install -e ".[dev]"
$ pre-commit install
  • Implement updates. Make sure code is documented using existing conventions.

  • Ensure tests pass locally:

$ make test



pycontrails aims to implement clear, consistent, performant data structures and models.

The project uses mypy for static type checking. All code should have specific, clear type annotations.

The project uses Black, ruff and doc8 to standardize code-formatting. These tools are run automatically in a pre-commit hook.

The project uses pytest to run unit tests. New code should include clear unit tests for implementation and output values. New test files should be included in the /tests/unit/ directory.

The project uses Github Actions to run code quality and unit tests on each pull request. Test locally before pushing using:

$ make test


Sphinx uses reStructuredText to synthesize documentation. The quick reStructuredText reference provides a basic overview.

Sphinx includes many additional roles, directives, and extensions to enhance documentation.

Sphinx configuration is stored in The full list of Sphinx configuration options is in the Sphinx configuration docs.


Tutorials should be written as isolated executable Jupyter Notebooks. The nbsphinx extension includes notebooks in the static documentation.

Notebooks will be automatically evaluated during tests. To exclude a notebook cell from evaluation during testing or documentation generation, add the tags nbval-skip and skip-execution to cell metadata. See *Avoiding output comparison in the nbval documentation for more information.

Literature References#

The documentation uses sphinxcontrib-bibtex to include citations and a bibliography.

All references should be cited through documentation and docstrings using the :cite: directive.

Bibliography references are managed in the Zotero pycontrails library. The Zotero Better Bibtex extension automatically syncs this library to the docs/_static/pycontrails.bib Bibtex file.

See the References section of the docs for setup.


Wherever possible, we adhere to the NumPy docstring conventions.

The following links are good references for writing numpy docstrings:

General guidelines:

Use *italics*, **bold** and ``monospace`` if needed in any explanations
(but not for variable names and doctest code or multi-line code).
Variable, module, function, and class names
should be written between single back-ticks (`numpy`).

When you specify a type in Parameters or See Also, Sphinx will automatically replace the text with the napolean_type_aliases specified in, e.g.

x : np.ndarray
    Sphinx will automatically replace
    "np.ndarray" with the napolean type alias "numpy.ndarray"

The See Also section is not a list. All of the following work:

See Also

When you specify a type outside of Parameters, you have to use the sphinx cross-referencing syntax:

This is a :func:`pd.to_datetime`    # NO
and :func:`pandas.to_datetime`      # YES

This is a :class:`np.datetime64`    # NO
and :class:`numpy.datetime64`       # YES