API reference interactive example#

This page demonstrates jupyterlite-sphinx’s integration with NumPy-style docstrings using the numpydoc extension. jupyterlite-sphinx supports both numpydoc and sphinx.ext.napoleon, though the latter is not added in this website.

Here, we showcase the automatic insertion of the ..try_examples:: directive/TryExamples buttons in “Examples” sections when using numpydoc for documenting public methods and functions, and common aspects around using them, such as disabling the buttons on a per-docstring and per-page basis.

Please refer to the TryExamples directive documentation for an extended overview of the functionalities offered beyond this demo.

Features at a glance#

  1. Configuring where to display the buttons – We’ve set the global_enable_try_examples configuration option to True in conf.py, through which the extension automatically detects Examples sections in docstrings and inserts the .. try_examples:: directive, which automatically adds the buttons. This works with either numpydoc or sphinx.ext.napoleon for docstring parsing.

  2. Mathematical equations – The solve_pendulum_ode() function below shows how mathematical equations inside the “Examples” section are rendered with MathJax.

  3. Disabling the buttons – The image_processing() function’s docstring below contains the .. disable_try_examples comment, which disables the automatic insertion of the directive/buttons. This is useful for methods that are not intended to be executed interactively or for those that may not work well in a notebook environment.

  4. The try_examples.json configuration file – this file has been provided in the source directory, where we’ve set:

    • a minimum global height for the examples to ensure that the notebooks for examples use a minimum amount of space if the examples sections are small in length.

    • an ignore pattern for the Disabled examples page, so that the buttons are not displayed for any of the examples on that page.

Please refer to the conf.py file for the configuration options used in this demo.

Implementation notes#

The examples are displayed as mini-notebooks when users click the TryExamples button, with:

  • text blocks becoming Markdown cells

  • code blocks becoming executable code cells

  • LaTeX math being rendered using MathJax

  • links, if any, being converted from reST to Markdown format

Module source#

Here’s the example module that we’ll document:

Source code for example.py
example.py#
"""Here are some utility functions for ``jupyterlite-sphinx-demo``.

This module contains example functions with NumPy-style docstrings,
whose Examples sections include code snippets that can be executed
interactively with a button to open a JupyterLite session.

The examples below are designed to be simple and self-contained.
"""

import numpy as np
from scipy.integrate import solve_ivp
import pandas as pd


def fibonacci_sequence(n):
    """Generate a Fibonacci sequence up to the nth term.

    This function demonstrates basic NumPy docstrings with a simple
    mathematical function and an interactive example.

    Parameters
    ----------
    n : int
        Number of terms to generate.

    Returns
    -------
    list
        List containing the Fibonacci sequence up to the nth term.

    Examples
    --------
    Use NumPy to create and analyze a sequence:

    >>> import numpy as np
    >>> import matplotlib.pyplot as plt
    >>> # Create a sequence
    >>> x = np.arange(1, 11)
    >>> y = np.power(x, 2)
    >>> print(y)
    [  1   4   9  16  25  36  49  64  81 100]

    Plot the sequence:

    >>> plt.figure(figsize=(8, 4))
    >>> plt.plot(x, y, 'o-', linewidth=2)
    >>> plt.title('Square Numbers')
    >>> plt.xlabel('n')
    >>> plt.ylabel('n²')
    >>> plt.grid(True)
    >>> plt.show()
    """
    if not isinstance(n, int) or n <= 0:
        raise ValueError("n must be a positive integer")

    fibonacci = [0, 1]
    if n <= 2:
        return fibonacci[:n]

    for i in range(2, n):
        fibonacci.append(fibonacci[i - 1] + fibonacci[i - 2])

    return fibonacci


def analyze_data(data, column=None, bins=10):
    """Analyze numerical data with descriptive statistics and visualization.

    This function demonstrates more complex docstrings with various
    visualization options in the examples section.

    Parameters
    ----------
    data : array_like or pandas.DataFrame
        The numerical data to analyze.
    column : str, optional
        If data is a DataFrame, specify the column to analyze.
    bins : int, default 10
        Number of bins for the histogram.

    Returns
    -------
    dict
        Dictionary containing descriptive statistics:
        - 'mean': The mean of the data
        - 'median': The median of the data
        - 'std': The standard deviation of the data
        - 'min': The minimum value
        - 'max': The maximum value

    Examples
    --------
    Generate and analyze random data:

    >>> import numpy as np
    >>> import pandas as pd
    >>> np.random.seed(42)
    >>> data = np.random.normal(loc=5, scale=2, size=1000)
    >>>
    >>> # Calculate statistics using NumPy
    >>> mean = np.mean(data)
    >>> median = np.median(data)
    >>> std = np.std(data)
    >>> min_val = np.min(data)
    >>> max_val = np.max(data)
    >>>
    >>> print(f"Mean: {mean:.2f}, Median: {median:.2f}")
    Mean: 5.04, Median: 5.04

    Create and explore a DataFrame:

    >>> df = pd.DataFrame({
    ...     'temperature': np.random.normal(25, 5, 100),
    ...     'humidity': np.random.normal(60, 10, 100)
    ... })
    >>> print(df.describe())
           temperature     humidity
    count  100.000000  100.000000
    mean    25.227...   59.935...
    std      4.916...    9.076...
    min     15.090...   36.670...
    25%     21.421...   53.133...
    50%     25.354...   60.585...
    75%     28.752...   65.789...
    max     37.937...   82.882...

    Visualize the data with a histogram and KDE:

    >>> import matplotlib.pyplot as plt
    >>> from scipy import stats
    >>> plt.figure(figsize=(10, 6))
    >>> plt.hist(data, bins=20, alpha=0.7, density=True)
    >>> x = np.linspace(data.min(), data.max(), 100)
    >>> kde = stats.gaussian_kde(data)
    >>> plt.plot(x, kde(x), 'r-', linewidth=2)
    >>> plt.title('Data Distribution')
    >>> plt.xlabel('Value')
    >>> plt.ylabel('Density')
    >>> plt.grid(True, alpha=0.3)
    >>> plt.show()
    """
    # Convert to numpy array if necessary
    if isinstance(data, pd.DataFrame):
        if column is None:
            raise ValueError("Column must be specified when data is a DataFrame")
        values = data[column].values
    else:
        values = np.asarray(data)

    # Calculate statistics
    stats = {
        "mean": np.mean(values),
        "median": np.median(values),
        "std": np.std(values),
        "min": np.min(values),
        "max": np.max(values),
    }

    return stats


def solve_pendulum_ode(theta0=np.pi / 4, omega0=0, t_span=(0, 10), g=9.8, L=1.0):
    """Solve the differential equation for a simple pendulum.

    This function uses of mathematical equations in docstrings. ``jupyterlite-sphinx``
    is able to convert LaTeX syntax for use with MathJax for rendering in the documentation.

    Parameters
    ----------
    theta0 : float, default π/4
        Initial angle in radians.
    omega0 : float, default 0
        Initial angular velocity in radians/second.
    t_span : tuple of (float, float), default (0, 10)
        Time interval (start, end) for the simulation.
    g : float, default 9.8
        Acceleration due to gravity in m/s².
    L : float, default 1.0
        Length of the pendulum in meters.

    Returns
    -------
    tuple
        (t, y) where t is the time points and y is the solution array with
        columns [theta, omega].

    Examples
    --------
    Simulate a damped harmonic oscillator, governed by the second-order
    differential equation:

    .. math::
        \\frac{d^2\\theta}{dt^2} + \\frac{g}{L}\\sin(\\theta) = 0

    where

    1. :math:`\\theta` is the angle from the vertical position
    2. :math:`g` is the acceleration due to gravity
    3. :math:`L` is the length of the pendulum

    >>> import numpy as np
    >>> from scipy.integrate import solve_ivp
    >>> import matplotlib.pyplot as plt
    >>>
    >>> def harmonic_oscillator(t, y, k=1.0, m=1.0, c=0.1):
    ...     # Simple harmonic oscillator with damping
    ...     # y[0] is position, y[1] is velocity
    ...     return [y[1], -k/m * y[0] - c/m * y[1]]
    >>>
    >>> # Initial conditions: position = 1, velocity = 0
    >>> y0 = [1.0, 0.0]
    >>>
    >>> ### Solving the ODE
    >>> t_span = (0, 20)
    >>> t_eval = np.linspace(t_span[0], t_span[1], 500)
    >>> sol = solve_ivp(harmonic_oscillator, t_span, y0, method='RK45', t_eval=t_eval)
    >>>
    >>> ### Plotting the results
    >>> plt.figure(figsize=(10, 6))
    >>> plt.subplot(2, 1, 1)
    >>> plt.plot(sol.t, sol.y[0])
    >>> plt.title('Damped Harmonic Oscillator')
    >>> plt.ylabel('Position')
    >>> plt.grid(True)
    >>>
    >>> plt.subplot(2, 1, 2)
    >>> plt.plot(sol.t, sol.y[1])
    >>> plt.xlabel('Time (s)')
    >>> plt.ylabel('Velocity')
    >>> plt.grid(True)
    >>> plt.tight_layout()
    >>> plt.show()
    >>>
    >>> # A phase space plot
    >>> plt.figure(figsize=(8, 8))
    >>> plt.plot(sol.y[0], sol.y[1])
    >>> plt.title('Phase Space')
    >>> plt.xlabel('Position')
    >>> plt.ylabel('Velocity')
    >>> plt.grid(True)
    >>> plt.axis('equal')
    >>> plt.show()
    """

    def pendulum_system(t, y):
        theta, omega = y
        dydt = [omega, -(g / L) * np.sin(theta)]
        return dydt

    y0 = [theta0, omega0]
    t_eval = np.linspace(t_span[0], t_span[1], 500)

    sol = solve_ivp(pendulum_system, t_span, y0, method="RK45", t_eval=t_eval)

    return sol.t, sol.y.T


def image_processing(image):
    """Process an image with various transformations.

    This function has the TryExamples button explicitly disabled using
    the `.. disable_try_examples` comment at the beginning of the
    Examples section.

    Parameters
    ----------
    image : ndarray
        Input image as a numpy array.

    Returns
    -------
    dict
        Dictionary containing various processed versions of the image.

    Examples
    --------

    .. disable_try_examples

    Generate and process synthetic images:

    >>> import numpy as np
    >>> import matplotlib.pyplot as plt
    >>> from matplotlib.colors import LinearSegmentedColormap
    >>>
    >>> # Create a simple synthetic image
    >>> x = np.linspace(-3, 3, 100)
    >>> y = np.linspace(-3, 3, 100)
    >>> X, Y = np.meshgrid(x, y)
    >>> Z = np.sin(X) * np.cos(Y)
    >>>
    >>> # Display the image
    >>> plt.figure(figsize=(12, 10))
    >>> plt.subplot(2, 2, 1)
    >>> plt.imshow(Z, cmap='viridis')
    >>> plt.title('Original')
    >>> plt.colorbar()
    >>>
    >>> ### Apply some transformations
    >>> # 1. Add some noise
    >>> Z_noisy = Z + np.random.normal(0, 0.2, Z.shape)
    >>> plt.subplot(2, 2, 2)
    >>> plt.imshow(Z_noisy, cmap='viridis')
    >>> plt.title('With Noise')
    >>> plt.colorbar()
    >>>
    >>> # 2. Apply a filter (for smoothing)
    >>> from scipy.ndimage import gaussian_filter
    >>> Z_smooth = gaussian_filter(Z, sigma=1)
    >>> plt.subplot(2, 2, 3)
    >>> plt.imshow(Z_smooth, cmap='viridis')
    >>> plt.title('Smoothed')
    >>> plt.colorbar()
    >>>
    >>> # 3. Perform edge detection
    >>> from scipy.ndimage import sobel
    >>> Z_edges = sobel(Z)
    >>> plt.subplot(2, 2, 4)
    >>> plt.imshow(Z_edges, cmap='gray')
    >>> plt.title('Edges')
    >>> plt.colorbar()
    >>>
    >>> plt.tight_layout()
    >>> plt.show()
    """
    from skimage import color, filters

    grayscale = color.rgb2gray(image)
    blurred = filters.gaussian(image, sigma=2, multichannel=True)
    edges = filters.sobel(grayscale)

    return {"grayscale": grayscale, "blurred": blurred, "edges": edges}

Rendered documentation#

Now, here’s how the documentation for this module is rendered with automatic TryExamples buttons, using numpydoc:

Here are some utility functions for jupyterlite-sphinx-demo.

This module contains example functions with NumPy-style docstrings, whose Examples sections include code snippets that can be executed interactively with a button to open a JupyterLite session.

The examples below are designed to be simple and self-contained.

example.analyze_data(data, column=None, bins=10)#

Analyze numerical data with descriptive statistics and visualization.

This function demonstrates more complex docstrings with various visualization options in the examples section.

Parameters:
dataarray_like or pandas.DataFrame

The numerical data to analyze.

columnstr, optional

If data is a DataFrame, specify the column to analyze.

binsint, default 10

Number of bins for the histogram.

Returns:
dict

Dictionary containing descriptive statistics: - ‘mean’: The mean of the data - ‘median’: The median of the data - ‘std’: The standard deviation of the data - ‘min’: The minimum value - ‘max’: The maximum value

Examples

Generate and analyze random data:

>>> import numpy as np
>>> import pandas as pd
>>> np.random.seed(42)
>>> data = np.random.normal(loc=5, scale=2, size=1000)
>>>
>>> # Calculate statistics using NumPy
>>> mean = np.mean(data)
>>> median = np.median(data)
>>> std = np.std(data)
>>> min_val = np.min(data)
>>> max_val = np.max(data)
>>>
>>> print(f"Mean: {mean:.2f}, Median: {median:.2f}")
Mean: 5.04, Median: 5.04

Create and explore a DataFrame:

>>> df = pd.DataFrame({
...     'temperature': np.random.normal(25, 5, 100),
...     'humidity': np.random.normal(60, 10, 100)
... })
>>> print(df.describe())
       temperature     humidity
count  100.000000  100.000000
mean    25.227...   59.935...
std      4.916...    9.076...
min     15.090...   36.670...
25%     21.421...   53.133...
50%     25.354...   60.585...
75%     28.752...   65.789...
max     37.937...   82.882...

Visualize the data with a histogram and KDE:

>>> import matplotlib.pyplot as plt
>>> from scipy import stats
>>> plt.figure(figsize=(10, 6))
>>> plt.hist(data, bins=20, alpha=0.7, density=True)
>>> x = np.linspace(data.min(), data.max(), 100)
>>> kde = stats.gaussian_kde(data)
>>> plt.plot(x, kde(x), 'r-', linewidth=2)
>>> plt.title('Data Distribution')
>>> plt.xlabel('Value')
>>> plt.ylabel('Density')
>>> plt.grid(True, alpha=0.3)
>>> plt.show()
example.fibonacci_sequence(n)#

Generate a Fibonacci sequence up to the nth term.

This function demonstrates basic NumPy docstrings with a simple mathematical function and an interactive example.

Parameters:
nint

Number of terms to generate.

Returns:
list

List containing the Fibonacci sequence up to the nth term.

Examples

Use NumPy to create and analyze a sequence:

>>> import numpy as np
>>> import matplotlib.pyplot as plt
>>> # Create a sequence
>>> x = np.arange(1, 11)
>>> y = np.power(x, 2)
>>> print(y)
[  1   4   9  16  25  36  49  64  81 100]

Plot the sequence:

>>> plt.figure(figsize=(8, 4))
>>> plt.plot(x, y, 'o-', linewidth=2)
>>> plt.title('Square Numbers')
>>> plt.xlabel('n')
>>> plt.ylabel('n²')
>>> plt.grid(True)
>>> plt.show()
example.image_processing(image)#

Process an image with various transformations.

This function has the TryExamples button explicitly disabled using the .. disable_try_examples comment at the beginning of the Examples section.

Parameters:
imagendarray

Input image as a numpy array.

Returns:
dict

Dictionary containing various processed versions of the image.

Examples

Generate and process synthetic images:

>>> import numpy as np
>>> import matplotlib.pyplot as plt
>>> from matplotlib.colors import LinearSegmentedColormap
>>>
>>> # Create a simple synthetic image
>>> x = np.linspace(-3, 3, 100)
>>> y = np.linspace(-3, 3, 100)
>>> X, Y = np.meshgrid(x, y)
>>> Z = np.sin(X) * np.cos(Y)
>>>
>>> # Display the image
>>> plt.figure(figsize=(12, 10))
>>> plt.subplot(2, 2, 1)
>>> plt.imshow(Z, cmap='viridis')
>>> plt.title('Original')
>>> plt.colorbar()
>>>
>>> ### Apply some transformations
>>> # 1. Add some noise
>>> Z_noisy = Z + np.random.normal(0, 0.2, Z.shape)
>>> plt.subplot(2, 2, 2)
>>> plt.imshow(Z_noisy, cmap='viridis')
>>> plt.title('With Noise')
>>> plt.colorbar()
>>>
>>> # 2. Apply a filter (for smoothing)
>>> from scipy.ndimage import gaussian_filter
>>> Z_smooth = gaussian_filter(Z, sigma=1)
>>> plt.subplot(2, 2, 3)
>>> plt.imshow(Z_smooth, cmap='viridis')
>>> plt.title('Smoothed')
>>> plt.colorbar()
>>>
>>> # 3. Perform edge detection
>>> from scipy.ndimage import sobel
>>> Z_edges = sobel(Z)
>>> plt.subplot(2, 2, 4)
>>> plt.imshow(Z_edges, cmap='gray')
>>> plt.title('Edges')
>>> plt.colorbar()
>>>
>>> plt.tight_layout()
>>> plt.show()
example.solve_pendulum_ode(theta0=0.7853981633974483, omega0=0, t_span=(0, 10), g=9.8, L=1.0)#

Solve the differential equation for a simple pendulum.

This function uses of mathematical equations in docstrings. jupyterlite-sphinx is able to convert LaTeX syntax for use with MathJax for rendering in the documentation.

Parameters:
theta0float, default π/4

Initial angle in radians.

omega0float, default 0

Initial angular velocity in radians/second.

t_spantuple of (float, float), default (0, 10)

Time interval (start, end) for the simulation.

gfloat, default 9.8

Acceleration due to gravity in m/s².

Lfloat, default 1.0

Length of the pendulum in meters.

Returns:
tuple

(t, y) where t is the time points and y is the solution array with columns [theta, omega].

Examples

Simulate a damped harmonic oscillator, governed by the second-order differential equation:

\[\frac{d^2\theta}{dt^2} + \frac{g}{L}\sin(\theta) = 0\]

where

  1. \(\theta\) is the angle from the vertical position

  2. \(g\) is the acceleration due to gravity

  3. \(L\) is the length of the pendulum

>>> import numpy as np
>>> from scipy.integrate import solve_ivp
>>> import matplotlib.pyplot as plt
>>>
>>> def harmonic_oscillator(t, y, k=1.0, m=1.0, c=0.1):
...     # Simple harmonic oscillator with damping
...     # y[0] is position, y[1] is velocity
...     return [y[1], -k/m * y[0] - c/m * y[1]]
>>>
>>> # Initial conditions: position = 1, velocity = 0
>>> y0 = [1.0, 0.0]
>>>
>>> ### Solving the ODE
>>> t_span = (0, 20)
>>> t_eval = np.linspace(t_span[0], t_span[1], 500)
>>> sol = solve_ivp(harmonic_oscillator, t_span, y0, method='RK45', t_eval=t_eval)
>>>
>>> ### Plotting the results
>>> plt.figure(figsize=(10, 6))
>>> plt.subplot(2, 1, 1)
>>> plt.plot(sol.t, sol.y[0])
>>> plt.title('Damped Harmonic Oscillator')
>>> plt.ylabel('Position')
>>> plt.grid(True)
>>>
>>> plt.subplot(2, 1, 2)
>>> plt.plot(sol.t, sol.y[1])
>>> plt.xlabel('Time (s)')
>>> plt.ylabel('Velocity')
>>> plt.grid(True)
>>> plt.tight_layout()
>>> plt.show()
>>>
>>> # A phase space plot
>>> plt.figure(figsize=(8, 8))
>>> plt.plot(sol.y[0], sol.y[1])
>>> plt.title('Phase Space')
>>> plt.xlabel('Position')
>>> plt.ylabel('Velocity')
>>> plt.grid(True)
>>> plt.axis('equal')
>>> plt.show()