Documentation

DASCore uses comments for implementation intent, NumPy-style docstrings for API documentation, and .qmd pages for guides and examples.

Comments and docstrings

Comments should explain non-obvious intent, not restate code. Prefer clearer names or smaller functions when comments merely narrate operations.

Use NumPy-style docstrings and accurate type hints. Public objects need complete docstrings; private objects may use a short summary. Describe behavior and constraints, not types already expressed by annotations.

from __future__ import annotations

import dascore as dc
from dascore.constants import PatchType


@dc.patch_function()
def add_value(patch: PatchType, value: int | float = 0) -> PatchType:
    """
    Add a scalar to patch data.

    Parameters
    ----------
    patch
        Patch to update.
    value
        Value added to each sample.

    Examples
    --------
    >>> import dascore as dc
    >>> patch = dc.get_example_patch()
    >>> out = add_value(patch, 2)
    >>> assert out.shape == patch.shape
    """
    return patch.new(data=patch.data + value)

Docstring examples use doctest. Quarto options such as >>> #| code-fold: true and headings such as >>> ### Detail are preserved in generated API pages.

For IO contracts, document only the formatter’s responsibility. FiberIO.scan() returns patch-local attrs and a full CoordManager; the public scan pipeline adds source path, format, and version. Formats with stored per-sample coordinates return them exactly with snap=False.

Build and test

After the development install, install Quarto and run:

python scripts/build_api_docs.py
quarto render dascore/docs

Use quarto preview dascore/docs for live editing. Generated HTML is under dascore/docs/_site/.

Edit scripts/_templates/_quarto.yml for navigation; dascore/docs/_quarto.yml is generated and overwritten. The API sidebar intentionally lists top-level sections rather than every object; dascore/docs/api/_metadata.yml assigns unlisted API pages to it.

The docs build records timing, output size, and URL changes:

python scripts/_doc_report.py time build_api_docs -- python scripts/build_api_docs.py
python scripts/_doc_report.py index
python scripts/_doc_report.py time quarto_render -- quarto render dascore/docs
python scripts/_doc_report.py site
python scripts/_doc_report.py summary

Run these in order. scripts/_baselines/api_urls.tsv protects published API URLs; regenerate it with python scripts/_api_urls.py freeze only when intentional URL changes are explained in the PR.

A page that is also an agent skill holds only an include; its text, and its executable blocks, live in dascore/.agents/skills/<name>/SKILL.md, so edit that file.

Executable Python blocks in hand-written .qmd files, and in the skill files they include, are mirrored into pytest files; blocks with eval: false are not tested:

python scripts/generate_doc_code_tests.py
pytest tests/test_autogenerated_doccode

marimo tutorials

Runnable tutorials become marimo notebooks that run in the browser; CI builds them, and the .qmd files remain the source. Build them before rendering docs locally:

python -m build --wheel
python scripts/build_notebooks.py

This needs quarto, marimo and uv on the path and the generated _quarto.yml from scripts/build_api_docs.py. It exports the notebooks, with the newest wheel in dist/ and the example data, to dascore/docs/marimo/. The bundled wheel pins notebooks to the documented checkout and avoids WebAssembly-incompatible dependencies of released versions. Rendering without these steps omits the Open in marimo links. To try a notebook locally, serve the export (python -m http.server -d dascore/docs/marimo) and open a page.

marimo runs cells as a dependency graph, so a tutorial page must define each top-level name, imports included, in only one {python} block. Choose a new name rather than reassigning one from an earlier block; names starting with _ are local to their block and may be reused. The converter would otherwise rename later definitions (patch_1) or drop repeated imports, and the notebook would drift from the page, so tests/test_build_notebooks.py checks this.

Set DASCORE_DOC_SITE_URL for the deployment that notebook links should target. Add tutorial data to MIRRORED_DATA in scripts/build_notebooks.py to avoid browser downloads and shared-IP rate limits.

Links, citations, and equations

Link API objects by placing their import path in backticks:

[Patch](`dascore.core.Patch`)

From docstrings, link pages relative to dascore/docs/, for example [Documentation](dascore/docs/contributing/documentation.qmd). In .qmd pages, use ordinary relative paths.

Add publications to dascore/docs/references.bib and cite them with Pandoc syntax such as @lindsey2021fiber or [@lindsey2021fiber].

Use standard LaTeX: $E=mc^2$ inline or a labeled display for cross-references:

$$
y = mx + b
$$ {#eq-line}

See @eq-line.

See the Quarto documentation for layout and formatting options.