<jupyter_start><jupyter_text>Documenting your code **Code documentation is an integral part of the programming process**. In this chapter I give some recommendations about how to write a useful documentation and how dedicated tools can be used to generate an html documentation for your project. Table of Contents22&nbsp;&nbsp;Documenting your code22.1&nbsp;&nbsp;Introduction22.2&nbsp;&nbsp;Inline comments22.2.1&nbsp;&nbsp;How to write inline comments22.2.2&nbsp;&nbsp;How NOT to write inline comments22.3&nbsp;&nbsp;API documentation22.4&nbsp;&nbsp;Documentation generators22.4.1&nbsp;&nbsp;Sphinx22.4.2&nbsp;&nbsp;ReadTheDocs22.5&nbsp;&nbsp;Interactive tutorials22.6&nbsp;&nbsp;Take home points22.7&nbsp;&nbsp;What's next?22.8&nbsp;&nbsp;License  Introduction There are three major components of code documentation:- **inline comments**: they explain the algorithm and single blocks of code as they are written. They are meant to be read by yourself and other programmers trying to debug and/or understand your code- **API documentation** (or function / method documentation): explains the purpose of functions or methods, their output, their input variables and their expected types, as well as implementation details if necessary. API stands for [Application Programming Interface](https://en.wikipedia.org/wiki/Application_programming_interface):  API documentation is written for *users* of the function and should be understandable without looking at the code.- **project documentation**: this encompasses all materials around a project: introductory material, tutorials, online classes, workshops, etc. Without such a project documentation, complex libraries like numpy or pandas would be very difficult to learn. Writing documentation is like writing tests: it is hard, and represents a lot of work with little immediate visible reward. **At the very least**, your own code should have inline comments.  Inline comments  Inline comments are plain text explanations of your code. As written in [cs.utah.edu](https://www.cs.utah.edu/~germain/PPS/Topics/commenting.html): All programs should be commented in such a manner as to easily describe the purpose of the code and any algorithms used to accomplish the purpose. A user should be able to utilize a previously written program (or function) without ever having to look at the code, simply by reading the comments.  How to write inline comments They are often placed at the top of a file (header comments) or before a thematic code block:<jupyter_code># 1D interpolation example from scipy
# see: https://docs.scipy.org/doc/scipy/reference/tutorial/interpolate.html
# We compare two ways to interpolate data (linear and cubic) on a synthetic example
# Inline comments are my own (<NAME>)
import numpy as np
import matplotlib.pyplot as plt
from scipy.interpolate import interp1d
%matplotlib inline

# Create synthetic data for the plot
x = np.linspace(0, 10, num=11, endpoint=True)
y = np.cos(-x**2/9.0)

# Define two different interpolation functions to compare:
# linear (default) and cubic
fl = interp1d(x, y)
fc = interp1d(x, y, kind='cubic')

# Location at which we want to interpolate
xnew = np.linspace(0, 10, num=41, endpoint=True)

# Compute the interpolated points and plot
plt.plot(x, y, 'o', xnew, fl(xnew), '-', xnew, fc(xnew), '--')
plt.legend(['data', 'linear', 'cubic'], loc='best');<jupyter_output><empty_output><jupyter_text>As you can see, the comments help to organize the code. The same example without comments is much less engaging:<jupyter_code>import numpy as np
import matplotlib.pyplot as plt
from scipy.interpolate import interp1d
%matplotlib inline
x = np.linspace(0, 10, num=11, endpoint=True)
y = np.cos(-x**2/9.0)
fl = interp1d(x, y)
fc = interp1d(x, y, kind='cubic')
xnew = np.linspace(0, 10, num=41, endpoint=True)
plt.plot(x, y, 'o', xnew, fl(xnew), '-', xnew, fc(xnew), '--')
plt.legend(['data', 'linear', 'cubic'], loc='best');<jupyter_output><empty_output><jupyter_text>Comments can include references to algorithms or indications about who wrote these lines. They should become an automatism when you write code: organize your code in blocks, and comment the purpose of each block. For places which require a bit more explanation, don't hesitate to write several lines of comments.  How NOT to write inline comments  Inline comments can be more harmfull than helping. See the following example:<jupyter_code># Numpy tutorial on matrix multiplication
# Author: mowglie
import numpy as np
import matplotlib.pyplot as plt
from scipy.interpolate import interp1d
%matplotlib inline

# linspace between 0 and 10
x = np.linspace(0, 10, num=11, endpoint=True)
y = np.cos(-x**2/9.0)  # apply cosinus

# from documentation: 
# https://docs.numpy.org/doc/numpy/reference/generated/scipy.interpolate.interp1d.html#scipy.interpolate.interp1d
fl = interp1d(x, y)
fc = interp1d(x, y, kind='cubic')

# linspace between 0 and 10
xnew = np.linspace(0, 10, num=41, endpoint=True)

# Plot
plt.plot(x, y, 'o', xnew, fl(xnew), '-', xnew, fc(xnew), '--')
plt.legend(['data', 'linear', 'cubic'], loc='best');<jupyter_output><empty_output><jupyter_text>What are the problems here?1. **Wrong/outdated documentation**: the header inline comments are from a previous file and the documentation link does not work2. **Commenting the obvious**: paraphrasing the name of the function or its arguments is not helping at all! It is not plain English, and assumes that the reader knows the function and what it does. Regarding obvious comments, I really like this comic by [Abstruse Goose](https://abstrusegoose.com/432) which I find brings it quite to the point:![abstruse goose 432](https://abstrusegoose.com/strips/you_down_wit_OPC-yeah_you_know_me.png) Basically: **think about future readers when writing both code and comments**! And don't forget: this future reader might be *you*, and you'll be thanking yourself.  API documentation A [function signature](https://developer.mozilla.org/en-US/docs/Glossary/Signature/Function) (or type signature, or method signature) defines input and output of functions or methods. When writing a function, you expect users (including yourself) to use it more than once, possibly for a longer period of time. Ideally, you would like to understand what a function does *long* after writing it. This is what [docstrings](https://www.python.org/dev/peps/pep-0257/what-is-a-docstring) are for:<jupyter_code>def repeat(phrase, n_times=2, sep=', '):
    """Repeat a phrase a given number of times.
    
    This uses the well known algorithm of string multiplication
    by GvR et al.
    
    Parameters
    ----------
    phrase : str
        The phrase to repat
    n_times : int, optional
        The number of times the phrase should be repeated
    sep : str, optional
        The separator between each repetition
        
    Returns
    -------
    str
        The repeated phrase
        
    Raises
    ------
    ValueError
        When ``phrase`` is not a string
    """
    
    if not isinstance(phrase, str):
        raise ValueError('phrase should be a string!')
    return sep.join([phrase] * n_times)<jupyter_output><empty_output><jupyter_text>**Docstrings** have a special meaning in python. They are not used by the language itself, but python offers a way to access them:<jupyter_code>print(repeat.__doc__)<jupyter_output>Repeat a phrase a given number of times.
    
    This uses the well known algorithm of string multiplication
    by GvR et al.
    
    Parameters
    ----------
    phrase : str
        The phrase to repat
    n_times : int, optional
        The number of times the phrase should be repeated
    sep : str, optional
        The separator between each repetition
        
    Returns
    -------
    str
        The repeated phrase
        
    Raises
    ------
    ValueError
        When ``phrase`` is not a string
{'fraction_non_alphanumeric': 0.09320956256358087, 'fraction_numerical': 0.014242115971515769, 'mean_word_length': 4.299865229110512, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 21, 'https://': 8, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '5', 'dir': 'jupyter-structured-clean-dedup', 'id': '104534', 'license': 'CC-BY-4.0', 'n_tokens_mistral': 2300, 'n_tokens_neox': 2211, 'n_words': 932, 'path': 'notebooks/22-Documentation.ipynb', 'repo_name': 'fmaussion/scipro_ws2019', 'size': '7869'}