Contributing to the documentation¶
Here we describe the procedure through which to contribute to these Finesse documentation pages and guidelines for conventions and styles to use. The documentation is built with Sphinx and uses reStructured Text (reST) for formatting and markdown support.
The authoritative reStructuredText User Documentation.
Structure of the project¶
The directory structure of the project is shown in the figure below. Each directory
finesse/docs/source/ contains the documentation files which these pages are
built from. The sub-directories of the documentation each contain an
which links the relevant pages to that section of the documentation.
In order to expand a section of the documentation with another page, you must link your
new reST file in the
index.rst file of that section. Below is an example showing the
index file for the An Introduction to Finesse section of the
.. _intro: ========================== An introduction to Finesse ========================== This section contains information regarding the key concepts of |Finesse| and how to use them to produce accurate frequency-domain models of any interferometer configuration you are considering. .. toctree:: :maxdepth: 1 installation key_concepts simple_example changes
The starting line (.. _intro:) defines a cross-reference label for the file so that
other reST files within the documentation can link to the introduction index page using
:ref:`intro` (see note below). Within the snippet above a
toctree is defined
which links the listed reST files to the index page for the introduction. As described
earlier, if you wanted to link a new reST file for a different topic within the
introduction then you would simply add the name of this file to the toctree directive
Titles of sections should not use any styling such as the |Finesse| or backtick for code blocks “``”, because such styling does not always carry over correctly or as intended in cross-references.
References to labels can be written in the form :ref:`intro` only if the intro label is defined directly before a section or figure directive. If a label is defined somewhere else then references can only be made to this label with an explicit title, e.g. :ref:`Some label <mylabel>`.
A common pitfall is to define a label before an .. include: directive at the top
.rst file. In this case Sphinx cannot work out which label to use for the
reference and so emits a warning during the build. The fix is to either move the
label to be before a section title or add an explicit title to its references.
See the Sphinx referencing documentation for more information.
Writing Sphinx compatible docstrings¶
To produce well formatted API documentation for Finesse, all module, class and function docstrings will be written in the numpydoc style (follow the link for the style guide).
In contrast to PEP-257, numpydoc
asks for class
__init__ methods to be documented in the class docstring, not
__init__ method itself.
There is currently no directly supported method for documenting properties in
numpydoc, instead you should use reST syntax in the docstrings for a class property.
This involves using docstrings only for the “getter” and passing the tags :getter:
and :setter: to document both. An example is shown below for the nr property of
@property def nr(self): """The refractive index associated with the `BeamParam`. :getter: Returns the index of refraction. :setter: Sets the index of refraction. """ return self.__nr @nr.setter def nr(self, value): self.__nr = value
The above docstrings result in the
Linking to internal and external module objects¶
Sphinx enables you to cross-reference modules, classes, functions and attributes both internal to the project and external to it. To cross-reference an internal object (or attribute, method etc.) simply use the following directives:
:mod:`.internal_module_name` to create a link to an internal module,
:class:`.internal_class_name` to create a link to an internal class,
:func:`.internal_function_name` to create a link to an internal function or :meth:`.internal_class_name.internal_function_name` to create a link to an internal class method,
:attr:`.internal_class_name.internal_attribute_name` to create a link to an internal class attribute.
The Finesse documentation tooling provides additional cross-reference support for KatScript instructions:
:kat:command:`command_name` to create a link to a kat-script command,
:kat:element:`element_name` to create a link to a kat-script element,
:kat:analysis:`analysis_name` to create a link to a kat-script analysis.
An example of cross-referencing is shown below for the
def path(self, from_node, to_node): """Retrieves an ordered list of the path trace betwwen the specified nodes, including any spaces. The list is formatted as `[(node, to_comp)]` where `to_comp` can be any sub-class instance of :class:`.Connector` (including :class:`.Space`) and `node` is an input to `to_comp`. Parameters ---------- from_node : :class:`.Node` Node to trace from. to_node : :class:`.Node` Node to trace to. Returns ------- out : list A list of the nodes and components (including spaces) between `from_node` and `to_node` in order. Raises ------ e : :class:`.NodeException` If either of `from_node`, `to_node` are not contained within the model. """ from .components import Nothing nc_between = self.path(from_node, to_node) nodes_comps_spaces =  trace_end = Nothing('end') for node, comp in nc_between: if node.is_input: nodes_comps_spaces.append((node, comp)) else: space = node.space if space is None: nodes_comps_spaces.append((node, trace_end)) else: nodes_comps_spaces.append((node, space)) return nodes_comps_spaces
Linking to objects in external modules is just as simple but requires a change to the
conf.py file in the
finesse/docs/source directory if you want to have links to a
module not already defined in the
intersphinx_mapping variable in this file. For
details on how to specify new targets in this variable see the intersphinx
Once the necessary target is included in
intersphinx_mapping, then you can create
links to external modules’ documentation as before using the directive syntax shown in
the bulleted list above. An example follows for the
which creates a link to the
@property def network(self): """The directed graph object containing the optical configuration as a :class:`networkx.DiGraph` instance. The `network` stores :class:`.Node` instances as nodes and :class:`.Space` instances as edges, where the former has access to its associated component via :attr:`.Node.component`. :getter: Returns the directed graph object containing the configuration (read-only). """ return self.__network
Documenting Cython extensions¶
Showing output from inline scripts¶
Code is executed in the environment used to build the documentation, so the
package is available to import and run.
Simple code blocks can be executed with
.. jupyter-execute:: directives. More
advanced usage is possible, such as running scripts within different kernels (using the
:id: directive option), showing line numbers, importing and showing the contents of
scripts on the file system, etc. See the jupyter-sphinx documentation for more information.
Finesse is developed by many people and maintaining consistency across the documentation is essential. The following subsections describe some style aspects to be conformed to when writing documentation.
Where style guidance is undefined, conform first to the rules enforced by doc8 then the Python documentation style guide.
Try to stick to a maximum of 88 characters. This is consistent with the rules for Python code, set by Black. This limit isn’t just for aesthetics in your IDE: code blocks in documentation pages with longer lines will overflow the visible page and create irritating horizontal scroll bars.
You may wish to create a ruler in your IDE to give a visual cue for this limit.
In some editors you can highlight a block of text and press Alt + Q to
automatically wrap the text at the configured line length. In Visual Studio Code you
might wish to install the Rewrap extension to enable this shortcut, and set a
.vscode/settings.json using e.g.
Try not to write documentation with many nested subsections; documentation should be mostly prose. Only the first four section levels are displayed in the sidebar of the HTML documentation, and each level beyond the top level is hidden until its parent is navigated to. If a section makes sense to appear in the sidebar then it should be within the top four levels; use common sense.
Section titles should use sentence case, e.g. Showing output from inline scripts, not Showing Output from Inline Scripts.
Do not use backtick-style formatting in titles as these do not render nicely in the sidebar. Instead you can consider using single quotes, e.g. “Logging via the Python ‘logging’ module”.
There are particular characters assigned to heading levels in reST; the structure is
determined from the succession of headings as defined in each
.rst file. Finesse
documentation should nevertheless ideally follow this convention:
=with overline, for page titles
=, for sections
-, for subsections
^, for subsubsections
", for paragraphs
Use an affirmative, succinct tone. Concise is better than verbose. Users typically don’t read whole pages of documentation but rather arrive at particular sections via links or search results.
Use of US English is preferred, for consistency with the Python documentation; however, refactoring existing text just for the sake of changing English forms is discouraged - focus your efforts on something more fruitful. As with the Python documentation, consistency within a page or section is more important than global consistency.
Finesse 3 should be referred to in the documentation simply as Finesse. Explicit inclusion of version numbers should only be made when referring to or comparing differences in behaviour.
Core documentation should focus on explaining how Finesse 3 works, not how it’s different to other tools or previous versions. Discussions of differences between Finesse 2 and 3 should be kept in relevant sections. It’s fine however to include brief “see also” directives in Finesse 3 documentation pointing to such discussions.
Various Finesse-related terms have particular capitalisation conventions. Some are also defined as macros which format the text appropriately:
|Finesse|, not e.g. FINESSE
Pykat, not e.g. PyKat
KatScript, not e.g. kat script, katscript, or kat-script
Write code examples using the same formatting rules as Finesse source code.
Building the documentation¶
The documentation can be built using the Makefile provided within the
make with no arguments to print a list of available output formats.
The most common output format is HTML, which can be produced with the command
html. Note that in order to compile the documentation certain extra dependencies are
required. These are automatically installed when the project is installed in
mode, e.g. using
pip install -e .[dev].
In order to build the PDF docs (using
make latexpdf), you must ensure that a
comprehensive LaTeX package (such as
texlive) and a program that provides the
rsvg-convert tool are available on the system path.
There are some alternatives to
rsvg-convert if this tool is not available,
through they involve making some manual edits to the documentation’s settings in
conf.py - see the documentation for sphinxcontrib-svg2pdfconverter for more information.
The doc8 package provides a command line tool to
check documentation. Running
doc8 from the project root directory will have it
automatically pick up the line length setting defined in
setup.cfg. For instance,
you can lint the whole documentation source with:
$ cd /path/to/finesse/git/project/ # The directory that contains setup.cfg. $ doc8 docs/source
This will print a list of files and their corresponding issues, if any.
Comments and todo items¶
The .. todo:: directive will add a highlighted todo item in the manual, these should be used only as placeholders for larger sections, such as .. todo:: This section is missing for a missing section. For internal todo items such as ‘fix this later’ a simple comment can be used, for example: .. Todo: fix this later.