diff --git a/.dist/fluxie-docs/.readthedocs.yaml b/.dist/fluxie-docs/.readthedocs.yaml new file mode 100644 index 00000000..8cc9fd88 --- /dev/null +++ b/.dist/fluxie-docs/.readthedocs.yaml @@ -0,0 +1,25 @@ +# .readthedocs.yaml +# +# Read the Docs build configuration. +# Reference: https://docs.readthedocs.io/en/stable/config-file/v2.html + +version: 2 + +build: + os: ubuntu-22.04 + tools: + python: "3.11" + +sphinx: + configuration: docs/conf.py + +python: + install: + # Install fluxie itself so autodoc can import the package during the build. + - method: pip + path: . + extra_requirements: + - docs + # Install the pinned documentation dependencies separately to ensure + # reproducible builds regardless of what gets released on PyPI. + - requirements: docs/requirements.txt diff --git a/.dist/fluxie-docs/DOCS_README.md b/.dist/fluxie-docs/DOCS_README.md new file mode 100644 index 00000000..73299f02 --- /dev/null +++ b/.dist/fluxie-docs/DOCS_README.md @@ -0,0 +1,69 @@ +# fluxie — Sphinx documentation + +This directory contains the source files for the fluxie Sphinx documentation, +hosted at https://fluxie.readthedocs.io. + +## Directory layout + +``` +docs/ +├── conf.py Sphinx configuration +├── index.rst Root table of contents +├── getting_started.rst Installation and quick-start guide +├── data_format.rst Input file formats and naming conventions +├── requirements.txt Pinned build dependencies for Read the Docs +├── api/ +│ └── index.rst Auto-generated API reference entry point +├── developer/ +│ └── index.rst Developer guide (setup, tests, contributing) +├── tutorials/ +│ ├── index.rst Tutorial listing +│ └── example_basics.nblink Links to scripts/example_basics.ipynb +└── _static/ Custom CSS / images (add as needed) + +.readthedocs.yaml Read the Docs build configuration (repo root) +pyproject_docs_addition.toml Snippet to add to pyproject.toml +``` + +## Building locally + +1. Install the documentation dependencies: + + ```bash + pip install -e ".[docs]" + ``` + +2. Build the HTML output: + + ```bash + cd docs + make html + ``` + +3. Open `docs/_build/html/index.html` in a browser. + +To rebuild from scratch: + +```bash +make clean html +``` + +## Connecting to Read the Docs + +1. Sign in to https://readthedocs.org with the openghg GitHub account. +2. Click **Import a project** and select `openghg/fluxie`. +3. Read the Docs detects `.readthedocs.yaml` automatically and uses it for all + subsequent builds. +4. Every push to `devel` triggers a new build. Git tags (e.g. `v2.1`) appear + as versioned documentation snapshots. + +## Adding content + +- **New page:** Create a `.rst` (or `.md`) file in the appropriate + subdirectory and add its name to the nearest `toctree` directive. +- **New tutorial notebook:** Add the notebook to `scripts/`, create a + matching `.nblink` stub in `docs/tutorials/`, and add the name to the + `toctree` in `docs/tutorials/index.rst`. +- **API coverage:** The API reference is built from docstrings. Any public + function or class that lacks a docstring will appear as an empty entry. + Write NumPy-style docstrings to populate it. diff --git a/.dist/fluxie-docs/docs/_static/.gitkeep b/.dist/fluxie-docs/docs/_static/.gitkeep new file mode 100644 index 00000000..0d5557c5 --- /dev/null +++ b/.dist/fluxie-docs/docs/_static/.gitkeep @@ -0,0 +1,2 @@ +# This file exists only to ensure the _static/ directory is tracked by git. +# Place any custom CSS, images, or JavaScript files here. diff --git a/.dist/fluxie-docs/docs/api/index.rst b/.dist/fluxie-docs/docs/api/index.rst new file mode 100644 index 00000000..70c0e02b --- /dev/null +++ b/.dist/fluxie-docs/docs/api/index.rst @@ -0,0 +1,14 @@ +API reference +============= + +This section is generated automatically from the source code. +All public symbols in the ``fluxie`` package are listed here together with +their docstrings and type signatures. + +Click the ``[source]`` link next to any symbol to view its implementation. + +.. autosummary:: + :toctree: generated + :recursive: + + fluxie diff --git a/.dist/fluxie-docs/docs/conf.py b/.dist/fluxie-docs/docs/conf.py new file mode 100644 index 00000000..63e13ec6 --- /dev/null +++ b/.dist/fluxie-docs/docs/conf.py @@ -0,0 +1,81 @@ +# docs/conf.py +# +# Sphinx configuration for the fluxie documentation. +# Build locally: cd docs && make html +# Hosted on: https://fluxie.readthedocs.io + +import os +import sys + +# Make the fluxie package importable during the build so autodoc can inspect it. +sys.path.insert(0, os.path.abspath("..")) + +# --------------------------------------------------------------------------- +# Project information +# --------------------------------------------------------------------------- + +project = "fluxie" +copyright = "2024, OpenGHG contributors" +author = "OpenGHG contributors" + +# Pull the version from the installed package so it stays in sync automatically. +try: + from importlib.metadata import version as _pkg_version + release = _pkg_version("fluxie") +except Exception: + release = "unknown" + +version = ".".join(release.split(".")[:2]) + +# General configuration + + +extensions = [ + "sphinx.ext.autodoc", # Extract docstrings from source code + "sphinx.ext.autosummary", # Generate summary tables for modules/classes + "sphinx.ext.napoleon", # Parse NumPy- and Google-style docstrings + "sphinx.ext.viewcode", # Add [source] links next to each symbol + "sphinx.ext.intersphinx", # Cross-link to NumPy, xarray, pandas, etc. + "sphinx_autodoc_typehints", # Render type hints in the signature line + "myst_parser", # Allow Markdown (.md) source files + "nbsphinx", # Render Jupyter notebooks +] + +autosummary_generate = True + +autodoc_default_options = { + "members": True, + "undoc-members": False, + "show-inheritance": True, + "member-order": "bysource", +} + +napoleon_google_docstring = False +napoleon_numpy_docstring = True +napoleon_use_param = True +napoleon_use_rtype = True + +intersphinx_mapping = { + "python": ("https://docs.python.org/3", None), + "numpy": ("https://numpy.org/doc/stable", None), + "xarray": ("https://docs.xarray.dev/en/stable", None), + "pandas": ("https://pandas.pydata.org/docs", None), +} + +templates_path = ["_templates"] +exclude_patterns = ["_build", "Thumbs.db", ".DS_Store", "**.ipynb_checkpoints"] + + + +html_theme = "sphinx_rtd_theme" + +html_theme_options = { + "navigation_depth": 4, + "collapse_navigation": False, + "sticky_navigation": True, + "titles_only": False, +} + +html_static_path = ["_static"] + +nbsphinx_execute = "never" diff --git a/.dist/fluxie-docs/docs/data_format.rst b/.dist/fluxie-docs/docs/data_format.rst new file mode 100644 index 00000000..3db30bdf --- /dev/null +++ b/.dist/fluxie-docs/docs/data_format.rst @@ -0,0 +1,231 @@ +Data formatting +=============== + +This page describes every input file that fluxie can consume, the required +directory layout, and the naming conventions that allow filenames to be +resolved automatically. + +All NetCDF templates referenced below are stored in the repository under +``data/templates/``. + +.. contents:: On this page + :local: + :depth: 2 + +Required files +-------------- + +Flux and concentration NetCDF files +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +These files carry the inversion model output and are the primary input to +fluxie. They must conform to the **PARIS-AVENGERS-EYECLIMA** template: + +- ``data/templates/PAR-AVE-EYE_inversion_flux_output.cdl`` +- ``data/templates/PAR-AVE-EYE_inversion_concentration_output.cdl`` + +A human-readable summary of the most important variables in each template is +provided in ``data/templates/README_templates.md``. + +Naming convention +^^^^^^^^^^^^^^^^^ + +Both files share a common naming scheme based on ``_``-separated tags: + +.. code-block:: text + + Flux file: + ___.nc + + Concentration file: + ____concentration.nc + +```` must be exactly ``yearly`` or ``monthly``. + +For clear traceability and automatic plot labelling, use the following +pattern for ````:: + + __ + +**Example** — InTEM inversion of HFC-134a using NAME transport over Europe +with EDGAR prior: + +.. code-block:: text + + InTEM_NAME_EUROPE_EDGAR_hfc134a_yearly.nc + InTEM_NAME_EUROPE_EDGAR_hfc134a_yearly_concentration.nc + +Directory layout +^^^^^^^^^^^^^^^^ + +Files must be placed under:: + + /path/to/data/// + +For example:: + + /path/to/data/InTEM/hfc134a/ + InTEM_NAME_EUROPE_EDGAR_hfc134a_yearly.nc + InTEM_NAME_EUROPE_EDGAR_hfc134a_yearly_concentration.nc + +The path ``/path/to/data/`` is specified in the notebook when you initialise +the analysis. + +Optional configuration files +----------------------------- + +All configuration files use JSON format. Working examples for each file are +provided in the ``configs/`` directory of the repository. + +Regions information +~~~~~~~~~~~~~~~~~~~ + +**File:** ``configs/regions_info.json`` + +Controls how countries are aggregated into named regions and specifies +point-source locations to overlay on maps. + +.. list-table:: + :header-rows: 1 + :widths: 25 20 55 + + * - Key + - Type + - Description + * - ``country_codes`` + - ``dict[str, str]`` + - Country names mapped to their ISO 3166-1 alpha-3 codes. + * - ``regions`` + - ``dict[str, list[str]]`` + - Named regions mapped to lists of country names they contain. + * - ``point_source`` + - ``dict[str, list[float]]`` + - Named locations mapped to ``[latitude, longitude]`` coordinates. + +Models information +~~~~~~~~~~~~~~~~~~ + +**File:** ``configs/models_info.json`` + +Controls filename resolution, plot labels, and multi-species aggregation. + +.. list-table:: + :header-rows: 1 + :widths: 25 20 55 + + * - Key + - Type + - Description + * - ``filename_tags`` + - ``dict[str, str]`` + - Short alias mapped to a full tag string embedded in filenames. + For example ``{"std": "4sites_baseline_optimized"}`` means the + model run ``InTEM_NAME_EDGAR_std`` resolves to + ``InTEM_NAME_EDGAR_4sites_baseline_optimized``. + Use ```` as a placeholder that is replaced by the + inversion model name in lower case. + * - ``model_labels`` + - ``dict[str, str]`` + - Model run names mapped to the labels shown on plots. + If a run is absent from this dictionary the label is constructed + automatically from the run name. + * - ``species_name`` + - ``dict[str, dict]`` + - Per-model overrides for the species identifier used in filenames. + Keys correspond to ````. + * - ``standard_run`` + - ``dict[str, dict]`` + - Identifies the standard run for each model when aggregating over + all HFCs or PFCs. Use the ``"default"`` sub-key for the default + set of name tags; add additional sub-keys (e.g. ``"longrun"``) for + alternative configurations. + +Species information +~~~~~~~~~~~~~~~~~~~ + +**File:** ``configs/species_info.json`` + +A dictionary of species identifiers (or group names) mapped to their physical +properties and display settings. + +.. list-table:: + :header-rows: 1 + :widths: 25 20 55 + + * - Key + - Type + - Description + * - ``species_print`` + - ``str`` + - Species name for plot axis labels, in LaTeX notation + (e.g. ``"HFC-134a"``). + * - ``gwp`` + - ``float`` + - GWP-100 value from IPCC AR5, used to convert country fluxes to + CO\ :sub:`2`-equivalent mass. + * - ``molar_mass`` + - ``float`` + - Molar mass in g mol\ :sup:`-1`, used for mol–g conversions. + * - ``list_species`` + - ``list[str]`` + - List of species identifiers that make up a group. + Used when plotting the sum of country fluxes across multiple species. + +Sites information +~~~~~~~~~~~~~~~~~ + +**File:** ``configs/site_info.json`` + +A dictionary of station codes mapped to per-network observation metadata. + +.. list-table:: + :header-rows: 1 + :widths: 25 20 55 + + * - Key + - Type + - Description + * - ``latitude`` + - ``float`` + - Latitude of the station in degrees North. + * - ``longitude`` + - ``float`` + - Longitude of the station in degrees East. + * - ``height_station_masl`` + - ``float`` + - Station elevation in metres above sea level. + * - ``long_name`` + - ``str`` + - Full descriptive name of the station. + * - ``height`` + - ``list[str]`` + - Inlet heights in metres above ground level. + * - ``height_name`` + - ``list[str]`` + - Human-readable labels for each inlet height. + +Optional input files +-------------------- + +Bottom-up inventory NetCDF +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Used to overlay gridded inventory estimates on flux maps. + +- **Template:** ``data/templates/PAR-AVE-EYE_inventory.cdl`` +- **Location:** ``/path/to/data/inventory/`` +- **Naming:** ``__.nc`` + + Example: ``UNFCCC_inventory_hfc134a_2024.nc`` + +Baseline timestamp NetCDF +~~~~~~~~~~~~~~~~~~~~~~~~~ + +Contains timestamps that flag background (baseline) periods at each +measurement station. + +- **Template:** ``data/templates/PAR-AVE-EYE_baseline_timestamps.cdl`` +- **Location:** ``/path/to/data/baseline_timestamps/`` +- **Naming:** ``__baseline_timestamps.nc`` + + Example: ``JFJ_InTEM_baseline_timestamps.nc`` diff --git a/.dist/fluxie-docs/docs/developer/index.rst b/.dist/fluxie-docs/docs/developer/index.rst new file mode 100644 index 00000000..18ef53a7 --- /dev/null +++ b/.dist/fluxie-docs/docs/developer/index.rst @@ -0,0 +1,135 @@ +Developer guide +=============== + +This page describes how to set up a development environment, run the test +suite, build the documentation locally, and submit contributions. + +.. contents:: On this page + :local: + :depth: 2 + +Setting up a development environment +------------------------------------- + +Clone the repository and install fluxie together with all development and +documentation dependencies:: + + git clone https://github.com/openghg/fluxie.git + cd fluxie + pip install -e ".[docs]" + +The ``.[docs]`` extra installs Sphinx, the Read the Docs theme, and all other +packages needed to build the documentation. + +Running the tests +----------------- + +The test suite uses `pytest `_:: + + pip install pytest + pytest tests/ + +To run a single test file:: + + pytest tests/test_.py -v + +Building the documentation locally +------------------------------------ + +:: + + cd docs + make html + +Open ``docs/_build/html/index.html`` in a browser to review the result. + +To rebuild from scratch (clears cached output):: + + make clean html + +Coding conventions +------------------ + +- Follow `PEP 8 `_ for all Python code. +- Write **NumPy-style docstrings** for every public function, class, and + module. The API reference is generated directly from these docstrings, so + accuracy and completeness matter. + + Minimal example:: + + def load_flux(path: str, species: str) -> xr.Dataset: + """Load a flux NetCDF file into an xarray Dataset. + + Parameters + ---------- + path : str + Path to the NetCDF file. + species : str + Species identifier used in the filename (e.g. ``"hfc134a"``). + + Returns + ------- + xr.Dataset + Dataset containing the flux variables defined in the + PARIS-AVENGERS-EYECLIMA template. + + Raises + ------ + FileNotFoundError + If no file matching ``path`` exists on disk. + """ + +- Add or update tests for every new function or bug fix. +- Keep pull requests focused: one logical change per PR makes review faster. + +Adding a new tutorial notebook +-------------------------------- + +1. Create the notebook under ``scripts/``. +2. Add a corresponding ``.nblink`` file in ``docs/tutorials/``:: + + { + "path": "../../scripts/.ipynb" + } + +3. Add the notebook name (without extension) to the ``toctree`` in + ``docs/tutorials/index.rst``. +4. Set ``nbsphinx_execute = "never"`` in ``docs/conf.py`` (already the + default) so the notebook is not re-executed during the documentation build. + +Making a release +---------------- + +1. Update the version string in ``pyproject.toml``. +2. Update ``CHANGELOG.md`` (if present) with a summary of changes. +3. Commit the version bump and push to ``devel``:: + + git add pyproject.toml + git commit -m "Bump version to X.Y" + git push origin devel + +4. Create and push a git tag matching the version:: + + git tag vX.Y + git push origin vX.Y + + Read the Docs will automatically build a versioned documentation snapshot + for the new tag. + +Contributing +------------ + +Contributions are welcome. The recommended workflow is: + +1. Open an issue on the `GitHub repository `_ + to describe the proposed change and discuss the approach with the maintainers + before writing code. +2. Fork the repository and create a feature branch:: + + git checkout -b feature/short-description + +3. Make your changes, add tests, and ensure the test suite passes. +4. Open a pull request against the ``devel`` branch and link it to the + relevant issue. + +For questions or discussion, use the issue tracker rather than direct contact. diff --git a/.dist/fluxie-docs/docs/getting_started.rst b/.dist/fluxie-docs/docs/getting_started.rst new file mode 100644 index 00000000..8adce1c7 --- /dev/null +++ b/.dist/fluxie-docs/docs/getting_started.rst @@ -0,0 +1,75 @@ +Getting started +=============== + +Requirements +------------ + +Fluxie requires Python 3.9 or later. All other dependencies are declared in +``pyproject.toml`` and are installed automatically. + +Installation +------------ + +Local machine +~~~~~~~~~~~~~ + +Clone the repository and install fluxie in editable mode so that any local +changes are immediately reflected without reinstalling:: + + git clone https://github.com/openghg/fluxie.git + cd fluxie + pip install -e . + +ICOS Jupyter Hub +~~~~~~~~~~~~~~~~ + +On the ICOS Jupyter Hub you must first create and activate a dedicated virtual +environment before installing the package. + +Create and activate the environment:: + + python -m venv fluxie-env + source fluxie-env/bin/activate + +Register the environment as a Jupyter kernel so you can select it in the +notebook interface:: + + pip install --upgrade pip + pip install ipykernel + python -m ipykernel install --user --name fluxie-env --display-name "fluxie-env" + +Install fluxie:: + + git clone https://github.com/openghg/fluxie.git + cd fluxie + pip install -e . + +.. note:: + + After installation, select ``fluxie-env`` from the kernel drop-down in the + upper-right corner of the Jupyter interface. If the kernel does not appear, + restart your Jupyter instance following the + `ICOS instructions `_. + +Quick start +----------- + +The fastest way to explore fluxie is to open and run the bundled example +notebook:: + + scripts/example_basics.ipynb + +It uses test data shipped with the repository and demonstrates the core +workflow: loading model output, selecting date ranges, and producing the +standard set of comparison plots. + +See :doc:`tutorials/index` for a rendered version of this notebook and +additional examples. + +Next steps +---------- + +- Read the :doc:`data_format` guide to learn how to structure your own model + output files so fluxie can read them. +- Browse the :doc:`api/index` for the complete function and class reference. +- See the :doc:`developer/index` if you want to contribute to the project. diff --git a/.dist/fluxie-docs/docs/index.rst b/.dist/fluxie-docs/docs/index.rst new file mode 100644 index 00000000..1452d09e --- /dev/null +++ b/.dist/fluxie-docs/docs/index.rst @@ -0,0 +1,46 @@ +.. fluxie documentation master file + +Fluxie documentation +==================== + +**Flux Intercomparison Environment (FLUXIE)** is a Python package developed +under the `PARIS project `_ for comparing and +visualising results from atmospheric inverse modelling systems. + +It provides: + +- Functions for loading, aligning, and aggregating model output. +- Standardised plots for flux maps, country totals, and concentration comparisons. +- Support for multi-model, multi-species, and multi-year analyses. + +.. toctree:: + :maxdepth: 2 + :caption: User guide + + getting_started + data_format + +.. toctree:: + :maxdepth: 2 + :caption: Tutorials + + tutorials/index + +.. toctree:: + :maxdepth: 2 + :caption: Reference + + api/index + +.. toctree:: + :maxdepth: 2 + :caption: Development + + developer/index + +Indices and tables +------------------ + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` diff --git a/.dist/fluxie-docs/docs/requirements.txt b/.dist/fluxie-docs/docs/requirements.txt new file mode 100644 index 00000000..c53694ad --- /dev/null +++ b/.dist/fluxie-docs/docs/requirements.txt @@ -0,0 +1,11 @@ +# docs/requirements.txt +# +# Pinned build dependencies for Read the Docs. +# These versions are tested together; bumping one may require checking +# compatibility with the others. +sphinx==7.3.7 +sphinx-rtd-theme==2.0.0 +sphinx-autodoc-typehints==1.25.3 +myst-parser==2.0.0 +nbsphinx==0.9.3 +nbsphinx-link==1.3.0 diff --git a/.dist/fluxie-docs/docs/tutorials/example_basics.nblink b/.dist/fluxie-docs/docs/tutorials/example_basics.nblink new file mode 100644 index 00000000..d959824e --- /dev/null +++ b/.dist/fluxie-docs/docs/tutorials/example_basics.nblink @@ -0,0 +1,3 @@ +{ + "path": "../../scripts/example_basics.ipynb" +} diff --git a/.dist/fluxie-docs/docs/tutorials/index.rst b/.dist/fluxie-docs/docs/tutorials/index.rst new file mode 100644 index 00000000..a0cfc67a --- /dev/null +++ b/.dist/fluxie-docs/docs/tutorials/index.rst @@ -0,0 +1,15 @@ +Tutorials +========= + +The notebooks below walk through concrete workflows using fluxie. +They are executed against real test data shipped with the repository, +so every output shown is reproducible. + +To run a notebook interactively, open it from the ``scripts/`` directory +in your Jupyter environment after completing the :doc:`../getting_started` +installation steps. + +.. toctree:: + :maxdepth: 1 + + example_basics diff --git a/.dist/fluxie-docs/pyproject_docs_addition.toml b/.dist/fluxie-docs/pyproject_docs_addition.toml new file mode 100644 index 00000000..3817e605 --- /dev/null +++ b/.dist/fluxie-docs/pyproject_docs_addition.toml @@ -0,0 +1,25 @@ +# ----------------------------------------------------------------------- +# ADD THIS BLOCK to the [project.optional-dependencies] section of your +# existing pyproject.toml. +# +# Example of what the section looks like after the addition: +# +# [project.optional-dependencies] +# docs = [ +# "sphinx>=7.0", +# ... +# ] +# +# Install locally with: +# pip install -e ".[docs]" +# ----------------------------------------------------------------------- + +[project.optional-dependencies] +docs = [ + "sphinx>=7.0", + "sphinx-rtd-theme>=2.0", + "sphinx-autodoc-typehints>=1.25", + "myst-parser>=2.0", + "nbsphinx>=0.9", + "nbsphinx-link>=1.3", +] diff --git a/fluxie-docs/.readthedocs.yaml b/fluxie-docs/.readthedocs.yaml new file mode 100644 index 00000000..8cc9fd88 --- /dev/null +++ b/fluxie-docs/.readthedocs.yaml @@ -0,0 +1,25 @@ +# .readthedocs.yaml +# +# Read the Docs build configuration. +# Reference: https://docs.readthedocs.io/en/stable/config-file/v2.html + +version: 2 + +build: + os: ubuntu-22.04 + tools: + python: "3.11" + +sphinx: + configuration: docs/conf.py + +python: + install: + # Install fluxie itself so autodoc can import the package during the build. + - method: pip + path: . + extra_requirements: + - docs + # Install the pinned documentation dependencies separately to ensure + # reproducible builds regardless of what gets released on PyPI. + - requirements: docs/requirements.txt diff --git a/fluxie-docs/DOCS_README.md b/fluxie-docs/DOCS_README.md new file mode 100644 index 00000000..73299f02 --- /dev/null +++ b/fluxie-docs/DOCS_README.md @@ -0,0 +1,69 @@ +# fluxie — Sphinx documentation + +This directory contains the source files for the fluxie Sphinx documentation, +hosted at https://fluxie.readthedocs.io. + +## Directory layout + +``` +docs/ +├── conf.py Sphinx configuration +├── index.rst Root table of contents +├── getting_started.rst Installation and quick-start guide +├── data_format.rst Input file formats and naming conventions +├── requirements.txt Pinned build dependencies for Read the Docs +├── api/ +│ └── index.rst Auto-generated API reference entry point +├── developer/ +│ └── index.rst Developer guide (setup, tests, contributing) +├── tutorials/ +│ ├── index.rst Tutorial listing +│ └── example_basics.nblink Links to scripts/example_basics.ipynb +└── _static/ Custom CSS / images (add as needed) + +.readthedocs.yaml Read the Docs build configuration (repo root) +pyproject_docs_addition.toml Snippet to add to pyproject.toml +``` + +## Building locally + +1. Install the documentation dependencies: + + ```bash + pip install -e ".[docs]" + ``` + +2. Build the HTML output: + + ```bash + cd docs + make html + ``` + +3. Open `docs/_build/html/index.html` in a browser. + +To rebuild from scratch: + +```bash +make clean html +``` + +## Connecting to Read the Docs + +1. Sign in to https://readthedocs.org with the openghg GitHub account. +2. Click **Import a project** and select `openghg/fluxie`. +3. Read the Docs detects `.readthedocs.yaml` automatically and uses it for all + subsequent builds. +4. Every push to `devel` triggers a new build. Git tags (e.g. `v2.1`) appear + as versioned documentation snapshots. + +## Adding content + +- **New page:** Create a `.rst` (or `.md`) file in the appropriate + subdirectory and add its name to the nearest `toctree` directive. +- **New tutorial notebook:** Add the notebook to `scripts/`, create a + matching `.nblink` stub in `docs/tutorials/`, and add the name to the + `toctree` in `docs/tutorials/index.rst`. +- **API coverage:** The API reference is built from docstrings. Any public + function or class that lacks a docstring will appear as an empty entry. + Write NumPy-style docstrings to populate it. diff --git a/fluxie-docs/docs/_static/.gitkeep b/fluxie-docs/docs/_static/.gitkeep new file mode 100644 index 00000000..0d5557c5 --- /dev/null +++ b/fluxie-docs/docs/_static/.gitkeep @@ -0,0 +1,2 @@ +# This file exists only to ensure the _static/ directory is tracked by git. +# Place any custom CSS, images, or JavaScript files here. diff --git a/fluxie-docs/docs/api/index.rst b/fluxie-docs/docs/api/index.rst new file mode 100644 index 00000000..70c0e02b --- /dev/null +++ b/fluxie-docs/docs/api/index.rst @@ -0,0 +1,14 @@ +API reference +============= + +This section is generated automatically from the source code. +All public symbols in the ``fluxie`` package are listed here together with +their docstrings and type signatures. + +Click the ``[source]`` link next to any symbol to view its implementation. + +.. autosummary:: + :toctree: generated + :recursive: + + fluxie diff --git a/fluxie-docs/docs/conf.py b/fluxie-docs/docs/conf.py new file mode 100644 index 00000000..63e13ec6 --- /dev/null +++ b/fluxie-docs/docs/conf.py @@ -0,0 +1,81 @@ +# docs/conf.py +# +# Sphinx configuration for the fluxie documentation. +# Build locally: cd docs && make html +# Hosted on: https://fluxie.readthedocs.io + +import os +import sys + +# Make the fluxie package importable during the build so autodoc can inspect it. +sys.path.insert(0, os.path.abspath("..")) + +# --------------------------------------------------------------------------- +# Project information +# --------------------------------------------------------------------------- + +project = "fluxie" +copyright = "2024, OpenGHG contributors" +author = "OpenGHG contributors" + +# Pull the version from the installed package so it stays in sync automatically. +try: + from importlib.metadata import version as _pkg_version + release = _pkg_version("fluxie") +except Exception: + release = "unknown" + +version = ".".join(release.split(".")[:2]) + +# General configuration + + +extensions = [ + "sphinx.ext.autodoc", # Extract docstrings from source code + "sphinx.ext.autosummary", # Generate summary tables for modules/classes + "sphinx.ext.napoleon", # Parse NumPy- and Google-style docstrings + "sphinx.ext.viewcode", # Add [source] links next to each symbol + "sphinx.ext.intersphinx", # Cross-link to NumPy, xarray, pandas, etc. + "sphinx_autodoc_typehints", # Render type hints in the signature line + "myst_parser", # Allow Markdown (.md) source files + "nbsphinx", # Render Jupyter notebooks +] + +autosummary_generate = True + +autodoc_default_options = { + "members": True, + "undoc-members": False, + "show-inheritance": True, + "member-order": "bysource", +} + +napoleon_google_docstring = False +napoleon_numpy_docstring = True +napoleon_use_param = True +napoleon_use_rtype = True + +intersphinx_mapping = { + "python": ("https://docs.python.org/3", None), + "numpy": ("https://numpy.org/doc/stable", None), + "xarray": ("https://docs.xarray.dev/en/stable", None), + "pandas": ("https://pandas.pydata.org/docs", None), +} + +templates_path = ["_templates"] +exclude_patterns = ["_build", "Thumbs.db", ".DS_Store", "**.ipynb_checkpoints"] + + + +html_theme = "sphinx_rtd_theme" + +html_theme_options = { + "navigation_depth": 4, + "collapse_navigation": False, + "sticky_navigation": True, + "titles_only": False, +} + +html_static_path = ["_static"] + +nbsphinx_execute = "never" diff --git a/fluxie-docs/docs/data_format.rst b/fluxie-docs/docs/data_format.rst new file mode 100644 index 00000000..3db30bdf --- /dev/null +++ b/fluxie-docs/docs/data_format.rst @@ -0,0 +1,231 @@ +Data formatting +=============== + +This page describes every input file that fluxie can consume, the required +directory layout, and the naming conventions that allow filenames to be +resolved automatically. + +All NetCDF templates referenced below are stored in the repository under +``data/templates/``. + +.. contents:: On this page + :local: + :depth: 2 + +Required files +-------------- + +Flux and concentration NetCDF files +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +These files carry the inversion model output and are the primary input to +fluxie. They must conform to the **PARIS-AVENGERS-EYECLIMA** template: + +- ``data/templates/PAR-AVE-EYE_inversion_flux_output.cdl`` +- ``data/templates/PAR-AVE-EYE_inversion_concentration_output.cdl`` + +A human-readable summary of the most important variables in each template is +provided in ``data/templates/README_templates.md``. + +Naming convention +^^^^^^^^^^^^^^^^^ + +Both files share a common naming scheme based on ``_``-separated tags: + +.. code-block:: text + + Flux file: + ___.nc + + Concentration file: + ____concentration.nc + +```` must be exactly ``yearly`` or ``monthly``. + +For clear traceability and automatic plot labelling, use the following +pattern for ````:: + + __ + +**Example** — InTEM inversion of HFC-134a using NAME transport over Europe +with EDGAR prior: + +.. code-block:: text + + InTEM_NAME_EUROPE_EDGAR_hfc134a_yearly.nc + InTEM_NAME_EUROPE_EDGAR_hfc134a_yearly_concentration.nc + +Directory layout +^^^^^^^^^^^^^^^^ + +Files must be placed under:: + + /path/to/data/// + +For example:: + + /path/to/data/InTEM/hfc134a/ + InTEM_NAME_EUROPE_EDGAR_hfc134a_yearly.nc + InTEM_NAME_EUROPE_EDGAR_hfc134a_yearly_concentration.nc + +The path ``/path/to/data/`` is specified in the notebook when you initialise +the analysis. + +Optional configuration files +----------------------------- + +All configuration files use JSON format. Working examples for each file are +provided in the ``configs/`` directory of the repository. + +Regions information +~~~~~~~~~~~~~~~~~~~ + +**File:** ``configs/regions_info.json`` + +Controls how countries are aggregated into named regions and specifies +point-source locations to overlay on maps. + +.. list-table:: + :header-rows: 1 + :widths: 25 20 55 + + * - Key + - Type + - Description + * - ``country_codes`` + - ``dict[str, str]`` + - Country names mapped to their ISO 3166-1 alpha-3 codes. + * - ``regions`` + - ``dict[str, list[str]]`` + - Named regions mapped to lists of country names they contain. + * - ``point_source`` + - ``dict[str, list[float]]`` + - Named locations mapped to ``[latitude, longitude]`` coordinates. + +Models information +~~~~~~~~~~~~~~~~~~ + +**File:** ``configs/models_info.json`` + +Controls filename resolution, plot labels, and multi-species aggregation. + +.. list-table:: + :header-rows: 1 + :widths: 25 20 55 + + * - Key + - Type + - Description + * - ``filename_tags`` + - ``dict[str, str]`` + - Short alias mapped to a full tag string embedded in filenames. + For example ``{"std": "4sites_baseline_optimized"}`` means the + model run ``InTEM_NAME_EDGAR_std`` resolves to + ``InTEM_NAME_EDGAR_4sites_baseline_optimized``. + Use ```` as a placeholder that is replaced by the + inversion model name in lower case. + * - ``model_labels`` + - ``dict[str, str]`` + - Model run names mapped to the labels shown on plots. + If a run is absent from this dictionary the label is constructed + automatically from the run name. + * - ``species_name`` + - ``dict[str, dict]`` + - Per-model overrides for the species identifier used in filenames. + Keys correspond to ````. + * - ``standard_run`` + - ``dict[str, dict]`` + - Identifies the standard run for each model when aggregating over + all HFCs or PFCs. Use the ``"default"`` sub-key for the default + set of name tags; add additional sub-keys (e.g. ``"longrun"``) for + alternative configurations. + +Species information +~~~~~~~~~~~~~~~~~~~ + +**File:** ``configs/species_info.json`` + +A dictionary of species identifiers (or group names) mapped to their physical +properties and display settings. + +.. list-table:: + :header-rows: 1 + :widths: 25 20 55 + + * - Key + - Type + - Description + * - ``species_print`` + - ``str`` + - Species name for plot axis labels, in LaTeX notation + (e.g. ``"HFC-134a"``). + * - ``gwp`` + - ``float`` + - GWP-100 value from IPCC AR5, used to convert country fluxes to + CO\ :sub:`2`-equivalent mass. + * - ``molar_mass`` + - ``float`` + - Molar mass in g mol\ :sup:`-1`, used for mol–g conversions. + * - ``list_species`` + - ``list[str]`` + - List of species identifiers that make up a group. + Used when plotting the sum of country fluxes across multiple species. + +Sites information +~~~~~~~~~~~~~~~~~ + +**File:** ``configs/site_info.json`` + +A dictionary of station codes mapped to per-network observation metadata. + +.. list-table:: + :header-rows: 1 + :widths: 25 20 55 + + * - Key + - Type + - Description + * - ``latitude`` + - ``float`` + - Latitude of the station in degrees North. + * - ``longitude`` + - ``float`` + - Longitude of the station in degrees East. + * - ``height_station_masl`` + - ``float`` + - Station elevation in metres above sea level. + * - ``long_name`` + - ``str`` + - Full descriptive name of the station. + * - ``height`` + - ``list[str]`` + - Inlet heights in metres above ground level. + * - ``height_name`` + - ``list[str]`` + - Human-readable labels for each inlet height. + +Optional input files +-------------------- + +Bottom-up inventory NetCDF +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Used to overlay gridded inventory estimates on flux maps. + +- **Template:** ``data/templates/PAR-AVE-EYE_inventory.cdl`` +- **Location:** ``/path/to/data/inventory/`` +- **Naming:** ``__.nc`` + + Example: ``UNFCCC_inventory_hfc134a_2024.nc`` + +Baseline timestamp NetCDF +~~~~~~~~~~~~~~~~~~~~~~~~~ + +Contains timestamps that flag background (baseline) periods at each +measurement station. + +- **Template:** ``data/templates/PAR-AVE-EYE_baseline_timestamps.cdl`` +- **Location:** ``/path/to/data/baseline_timestamps/`` +- **Naming:** ``__baseline_timestamps.nc`` + + Example: ``JFJ_InTEM_baseline_timestamps.nc`` diff --git a/fluxie-docs/docs/developer/index.rst b/fluxie-docs/docs/developer/index.rst new file mode 100644 index 00000000..18ef53a7 --- /dev/null +++ b/fluxie-docs/docs/developer/index.rst @@ -0,0 +1,135 @@ +Developer guide +=============== + +This page describes how to set up a development environment, run the test +suite, build the documentation locally, and submit contributions. + +.. contents:: On this page + :local: + :depth: 2 + +Setting up a development environment +------------------------------------- + +Clone the repository and install fluxie together with all development and +documentation dependencies:: + + git clone https://github.com/openghg/fluxie.git + cd fluxie + pip install -e ".[docs]" + +The ``.[docs]`` extra installs Sphinx, the Read the Docs theme, and all other +packages needed to build the documentation. + +Running the tests +----------------- + +The test suite uses `pytest `_:: + + pip install pytest + pytest tests/ + +To run a single test file:: + + pytest tests/test_.py -v + +Building the documentation locally +------------------------------------ + +:: + + cd docs + make html + +Open ``docs/_build/html/index.html`` in a browser to review the result. + +To rebuild from scratch (clears cached output):: + + make clean html + +Coding conventions +------------------ + +- Follow `PEP 8 `_ for all Python code. +- Write **NumPy-style docstrings** for every public function, class, and + module. The API reference is generated directly from these docstrings, so + accuracy and completeness matter. + + Minimal example:: + + def load_flux(path: str, species: str) -> xr.Dataset: + """Load a flux NetCDF file into an xarray Dataset. + + Parameters + ---------- + path : str + Path to the NetCDF file. + species : str + Species identifier used in the filename (e.g. ``"hfc134a"``). + + Returns + ------- + xr.Dataset + Dataset containing the flux variables defined in the + PARIS-AVENGERS-EYECLIMA template. + + Raises + ------ + FileNotFoundError + If no file matching ``path`` exists on disk. + """ + +- Add or update tests for every new function or bug fix. +- Keep pull requests focused: one logical change per PR makes review faster. + +Adding a new tutorial notebook +-------------------------------- + +1. Create the notebook under ``scripts/``. +2. Add a corresponding ``.nblink`` file in ``docs/tutorials/``:: + + { + "path": "../../scripts/.ipynb" + } + +3. Add the notebook name (without extension) to the ``toctree`` in + ``docs/tutorials/index.rst``. +4. Set ``nbsphinx_execute = "never"`` in ``docs/conf.py`` (already the + default) so the notebook is not re-executed during the documentation build. + +Making a release +---------------- + +1. Update the version string in ``pyproject.toml``. +2. Update ``CHANGELOG.md`` (if present) with a summary of changes. +3. Commit the version bump and push to ``devel``:: + + git add pyproject.toml + git commit -m "Bump version to X.Y" + git push origin devel + +4. Create and push a git tag matching the version:: + + git tag vX.Y + git push origin vX.Y + + Read the Docs will automatically build a versioned documentation snapshot + for the new tag. + +Contributing +------------ + +Contributions are welcome. The recommended workflow is: + +1. Open an issue on the `GitHub repository `_ + to describe the proposed change and discuss the approach with the maintainers + before writing code. +2. Fork the repository and create a feature branch:: + + git checkout -b feature/short-description + +3. Make your changes, add tests, and ensure the test suite passes. +4. Open a pull request against the ``devel`` branch and link it to the + relevant issue. + +For questions or discussion, use the issue tracker rather than direct contact. diff --git a/fluxie-docs/docs/getting_started.rst b/fluxie-docs/docs/getting_started.rst new file mode 100644 index 00000000..8adce1c7 --- /dev/null +++ b/fluxie-docs/docs/getting_started.rst @@ -0,0 +1,75 @@ +Getting started +=============== + +Requirements +------------ + +Fluxie requires Python 3.9 or later. All other dependencies are declared in +``pyproject.toml`` and are installed automatically. + +Installation +------------ + +Local machine +~~~~~~~~~~~~~ + +Clone the repository and install fluxie in editable mode so that any local +changes are immediately reflected without reinstalling:: + + git clone https://github.com/openghg/fluxie.git + cd fluxie + pip install -e . + +ICOS Jupyter Hub +~~~~~~~~~~~~~~~~ + +On the ICOS Jupyter Hub you must first create and activate a dedicated virtual +environment before installing the package. + +Create and activate the environment:: + + python -m venv fluxie-env + source fluxie-env/bin/activate + +Register the environment as a Jupyter kernel so you can select it in the +notebook interface:: + + pip install --upgrade pip + pip install ipykernel + python -m ipykernel install --user --name fluxie-env --display-name "fluxie-env" + +Install fluxie:: + + git clone https://github.com/openghg/fluxie.git + cd fluxie + pip install -e . + +.. note:: + + After installation, select ``fluxie-env`` from the kernel drop-down in the + upper-right corner of the Jupyter interface. If the kernel does not appear, + restart your Jupyter instance following the + `ICOS instructions `_. + +Quick start +----------- + +The fastest way to explore fluxie is to open and run the bundled example +notebook:: + + scripts/example_basics.ipynb + +It uses test data shipped with the repository and demonstrates the core +workflow: loading model output, selecting date ranges, and producing the +standard set of comparison plots. + +See :doc:`tutorials/index` for a rendered version of this notebook and +additional examples. + +Next steps +---------- + +- Read the :doc:`data_format` guide to learn how to structure your own model + output files so fluxie can read them. +- Browse the :doc:`api/index` for the complete function and class reference. +- See the :doc:`developer/index` if you want to contribute to the project. diff --git a/fluxie-docs/docs/index.rst b/fluxie-docs/docs/index.rst new file mode 100644 index 00000000..1452d09e --- /dev/null +++ b/fluxie-docs/docs/index.rst @@ -0,0 +1,46 @@ +.. fluxie documentation master file + +Fluxie documentation +==================== + +**Flux Intercomparison Environment (FLUXIE)** is a Python package developed +under the `PARIS project `_ for comparing and +visualising results from atmospheric inverse modelling systems. + +It provides: + +- Functions for loading, aligning, and aggregating model output. +- Standardised plots for flux maps, country totals, and concentration comparisons. +- Support for multi-model, multi-species, and multi-year analyses. + +.. toctree:: + :maxdepth: 2 + :caption: User guide + + getting_started + data_format + +.. toctree:: + :maxdepth: 2 + :caption: Tutorials + + tutorials/index + +.. toctree:: + :maxdepth: 2 + :caption: Reference + + api/index + +.. toctree:: + :maxdepth: 2 + :caption: Development + + developer/index + +Indices and tables +------------------ + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` diff --git a/fluxie-docs/docs/requirements.txt b/fluxie-docs/docs/requirements.txt new file mode 100644 index 00000000..c53694ad --- /dev/null +++ b/fluxie-docs/docs/requirements.txt @@ -0,0 +1,11 @@ +# docs/requirements.txt +# +# Pinned build dependencies for Read the Docs. +# These versions are tested together; bumping one may require checking +# compatibility with the others. +sphinx==7.3.7 +sphinx-rtd-theme==2.0.0 +sphinx-autodoc-typehints==1.25.3 +myst-parser==2.0.0 +nbsphinx==0.9.3 +nbsphinx-link==1.3.0 diff --git a/fluxie-docs/docs/tutorials/example_basics.nblink b/fluxie-docs/docs/tutorials/example_basics.nblink new file mode 100644 index 00000000..d959824e --- /dev/null +++ b/fluxie-docs/docs/tutorials/example_basics.nblink @@ -0,0 +1,3 @@ +{ + "path": "../../scripts/example_basics.ipynb" +} diff --git a/fluxie-docs/docs/tutorials/index.rst b/fluxie-docs/docs/tutorials/index.rst new file mode 100644 index 00000000..a0cfc67a --- /dev/null +++ b/fluxie-docs/docs/tutorials/index.rst @@ -0,0 +1,15 @@ +Tutorials +========= + +The notebooks below walk through concrete workflows using fluxie. +They are executed against real test data shipped with the repository, +so every output shown is reproducible. + +To run a notebook interactively, open it from the ``scripts/`` directory +in your Jupyter environment after completing the :doc:`../getting_started` +installation steps. + +.. toctree:: + :maxdepth: 1 + + example_basics diff --git a/fluxie-docs/pyproject_docs_addition.toml b/fluxie-docs/pyproject_docs_addition.toml new file mode 100644 index 00000000..3817e605 --- /dev/null +++ b/fluxie-docs/pyproject_docs_addition.toml @@ -0,0 +1,25 @@ +# ----------------------------------------------------------------------- +# ADD THIS BLOCK to the [project.optional-dependencies] section of your +# existing pyproject.toml. +# +# Example of what the section looks like after the addition: +# +# [project.optional-dependencies] +# docs = [ +# "sphinx>=7.0", +# ... +# ] +# +# Install locally with: +# pip install -e ".[docs]" +# ----------------------------------------------------------------------- + +[project.optional-dependencies] +docs = [ + "sphinx>=7.0", + "sphinx-rtd-theme>=2.0", + "sphinx-autodoc-typehints>=1.25", + "myst-parser>=2.0", + "nbsphinx>=0.9", + "nbsphinx-link>=1.3", +] diff --git a/scripts/fluxie-docs/.readthedocs.yaml b/scripts/fluxie-docs/.readthedocs.yaml new file mode 100644 index 00000000..8cc9fd88 --- /dev/null +++ b/scripts/fluxie-docs/.readthedocs.yaml @@ -0,0 +1,25 @@ +# .readthedocs.yaml +# +# Read the Docs build configuration. +# Reference: https://docs.readthedocs.io/en/stable/config-file/v2.html + +version: 2 + +build: + os: ubuntu-22.04 + tools: + python: "3.11" + +sphinx: + configuration: docs/conf.py + +python: + install: + # Install fluxie itself so autodoc can import the package during the build. + - method: pip + path: . + extra_requirements: + - docs + # Install the pinned documentation dependencies separately to ensure + # reproducible builds regardless of what gets released on PyPI. + - requirements: docs/requirements.txt diff --git a/scripts/fluxie-docs/DOCS_README.md b/scripts/fluxie-docs/DOCS_README.md new file mode 100644 index 00000000..73299f02 --- /dev/null +++ b/scripts/fluxie-docs/DOCS_README.md @@ -0,0 +1,69 @@ +# fluxie — Sphinx documentation + +This directory contains the source files for the fluxie Sphinx documentation, +hosted at https://fluxie.readthedocs.io. + +## Directory layout + +``` +docs/ +├── conf.py Sphinx configuration +├── index.rst Root table of contents +├── getting_started.rst Installation and quick-start guide +├── data_format.rst Input file formats and naming conventions +├── requirements.txt Pinned build dependencies for Read the Docs +├── api/ +│ └── index.rst Auto-generated API reference entry point +├── developer/ +│ └── index.rst Developer guide (setup, tests, contributing) +├── tutorials/ +│ ├── index.rst Tutorial listing +│ └── example_basics.nblink Links to scripts/example_basics.ipynb +└── _static/ Custom CSS / images (add as needed) + +.readthedocs.yaml Read the Docs build configuration (repo root) +pyproject_docs_addition.toml Snippet to add to pyproject.toml +``` + +## Building locally + +1. Install the documentation dependencies: + + ```bash + pip install -e ".[docs]" + ``` + +2. Build the HTML output: + + ```bash + cd docs + make html + ``` + +3. Open `docs/_build/html/index.html` in a browser. + +To rebuild from scratch: + +```bash +make clean html +``` + +## Connecting to Read the Docs + +1. Sign in to https://readthedocs.org with the openghg GitHub account. +2. Click **Import a project** and select `openghg/fluxie`. +3. Read the Docs detects `.readthedocs.yaml` automatically and uses it for all + subsequent builds. +4. Every push to `devel` triggers a new build. Git tags (e.g. `v2.1`) appear + as versioned documentation snapshots. + +## Adding content + +- **New page:** Create a `.rst` (or `.md`) file in the appropriate + subdirectory and add its name to the nearest `toctree` directive. +- **New tutorial notebook:** Add the notebook to `scripts/`, create a + matching `.nblink` stub in `docs/tutorials/`, and add the name to the + `toctree` in `docs/tutorials/index.rst`. +- **API coverage:** The API reference is built from docstrings. Any public + function or class that lacks a docstring will appear as an empty entry. + Write NumPy-style docstrings to populate it. diff --git a/scripts/fluxie-docs/docs/_static/.gitkeep b/scripts/fluxie-docs/docs/_static/.gitkeep new file mode 100644 index 00000000..0d5557c5 --- /dev/null +++ b/scripts/fluxie-docs/docs/_static/.gitkeep @@ -0,0 +1,2 @@ +# This file exists only to ensure the _static/ directory is tracked by git. +# Place any custom CSS, images, or JavaScript files here. diff --git a/scripts/fluxie-docs/docs/api/index.rst b/scripts/fluxie-docs/docs/api/index.rst new file mode 100644 index 00000000..70c0e02b --- /dev/null +++ b/scripts/fluxie-docs/docs/api/index.rst @@ -0,0 +1,14 @@ +API reference +============= + +This section is generated automatically from the source code. +All public symbols in the ``fluxie`` package are listed here together with +their docstrings and type signatures. + +Click the ``[source]`` link next to any symbol to view its implementation. + +.. autosummary:: + :toctree: generated + :recursive: + + fluxie diff --git a/scripts/fluxie-docs/docs/conf.py b/scripts/fluxie-docs/docs/conf.py new file mode 100644 index 00000000..63e13ec6 --- /dev/null +++ b/scripts/fluxie-docs/docs/conf.py @@ -0,0 +1,81 @@ +# docs/conf.py +# +# Sphinx configuration for the fluxie documentation. +# Build locally: cd docs && make html +# Hosted on: https://fluxie.readthedocs.io + +import os +import sys + +# Make the fluxie package importable during the build so autodoc can inspect it. +sys.path.insert(0, os.path.abspath("..")) + +# --------------------------------------------------------------------------- +# Project information +# --------------------------------------------------------------------------- + +project = "fluxie" +copyright = "2024, OpenGHG contributors" +author = "OpenGHG contributors" + +# Pull the version from the installed package so it stays in sync automatically. +try: + from importlib.metadata import version as _pkg_version + release = _pkg_version("fluxie") +except Exception: + release = "unknown" + +version = ".".join(release.split(".")[:2]) + +# General configuration + + +extensions = [ + "sphinx.ext.autodoc", # Extract docstrings from source code + "sphinx.ext.autosummary", # Generate summary tables for modules/classes + "sphinx.ext.napoleon", # Parse NumPy- and Google-style docstrings + "sphinx.ext.viewcode", # Add [source] links next to each symbol + "sphinx.ext.intersphinx", # Cross-link to NumPy, xarray, pandas, etc. + "sphinx_autodoc_typehints", # Render type hints in the signature line + "myst_parser", # Allow Markdown (.md) source files + "nbsphinx", # Render Jupyter notebooks +] + +autosummary_generate = True + +autodoc_default_options = { + "members": True, + "undoc-members": False, + "show-inheritance": True, + "member-order": "bysource", +} + +napoleon_google_docstring = False +napoleon_numpy_docstring = True +napoleon_use_param = True +napoleon_use_rtype = True + +intersphinx_mapping = { + "python": ("https://docs.python.org/3", None), + "numpy": ("https://numpy.org/doc/stable", None), + "xarray": ("https://docs.xarray.dev/en/stable", None), + "pandas": ("https://pandas.pydata.org/docs", None), +} + +templates_path = ["_templates"] +exclude_patterns = ["_build", "Thumbs.db", ".DS_Store", "**.ipynb_checkpoints"] + + + +html_theme = "sphinx_rtd_theme" + +html_theme_options = { + "navigation_depth": 4, + "collapse_navigation": False, + "sticky_navigation": True, + "titles_only": False, +} + +html_static_path = ["_static"] + +nbsphinx_execute = "never" diff --git a/scripts/fluxie-docs/docs/data_format.rst b/scripts/fluxie-docs/docs/data_format.rst new file mode 100644 index 00000000..3db30bdf --- /dev/null +++ b/scripts/fluxie-docs/docs/data_format.rst @@ -0,0 +1,231 @@ +Data formatting +=============== + +This page describes every input file that fluxie can consume, the required +directory layout, and the naming conventions that allow filenames to be +resolved automatically. + +All NetCDF templates referenced below are stored in the repository under +``data/templates/``. + +.. contents:: On this page + :local: + :depth: 2 + +Required files +-------------- + +Flux and concentration NetCDF files +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +These files carry the inversion model output and are the primary input to +fluxie. They must conform to the **PARIS-AVENGERS-EYECLIMA** template: + +- ``data/templates/PAR-AVE-EYE_inversion_flux_output.cdl`` +- ``data/templates/PAR-AVE-EYE_inversion_concentration_output.cdl`` + +A human-readable summary of the most important variables in each template is +provided in ``data/templates/README_templates.md``. + +Naming convention +^^^^^^^^^^^^^^^^^ + +Both files share a common naming scheme based on ``_``-separated tags: + +.. code-block:: text + + Flux file: + ___.nc + + Concentration file: + ____concentration.nc + +```` must be exactly ``yearly`` or ``monthly``. + +For clear traceability and automatic plot labelling, use the following +pattern for ````:: + + __ + +**Example** — InTEM inversion of HFC-134a using NAME transport over Europe +with EDGAR prior: + +.. code-block:: text + + InTEM_NAME_EUROPE_EDGAR_hfc134a_yearly.nc + InTEM_NAME_EUROPE_EDGAR_hfc134a_yearly_concentration.nc + +Directory layout +^^^^^^^^^^^^^^^^ + +Files must be placed under:: + + /path/to/data/// + +For example:: + + /path/to/data/InTEM/hfc134a/ + InTEM_NAME_EUROPE_EDGAR_hfc134a_yearly.nc + InTEM_NAME_EUROPE_EDGAR_hfc134a_yearly_concentration.nc + +The path ``/path/to/data/`` is specified in the notebook when you initialise +the analysis. + +Optional configuration files +----------------------------- + +All configuration files use JSON format. Working examples for each file are +provided in the ``configs/`` directory of the repository. + +Regions information +~~~~~~~~~~~~~~~~~~~ + +**File:** ``configs/regions_info.json`` + +Controls how countries are aggregated into named regions and specifies +point-source locations to overlay on maps. + +.. list-table:: + :header-rows: 1 + :widths: 25 20 55 + + * - Key + - Type + - Description + * - ``country_codes`` + - ``dict[str, str]`` + - Country names mapped to their ISO 3166-1 alpha-3 codes. + * - ``regions`` + - ``dict[str, list[str]]`` + - Named regions mapped to lists of country names they contain. + * - ``point_source`` + - ``dict[str, list[float]]`` + - Named locations mapped to ``[latitude, longitude]`` coordinates. + +Models information +~~~~~~~~~~~~~~~~~~ + +**File:** ``configs/models_info.json`` + +Controls filename resolution, plot labels, and multi-species aggregation. + +.. list-table:: + :header-rows: 1 + :widths: 25 20 55 + + * - Key + - Type + - Description + * - ``filename_tags`` + - ``dict[str, str]`` + - Short alias mapped to a full tag string embedded in filenames. + For example ``{"std": "4sites_baseline_optimized"}`` means the + model run ``InTEM_NAME_EDGAR_std`` resolves to + ``InTEM_NAME_EDGAR_4sites_baseline_optimized``. + Use ```` as a placeholder that is replaced by the + inversion model name in lower case. + * - ``model_labels`` + - ``dict[str, str]`` + - Model run names mapped to the labels shown on plots. + If a run is absent from this dictionary the label is constructed + automatically from the run name. + * - ``species_name`` + - ``dict[str, dict]`` + - Per-model overrides for the species identifier used in filenames. + Keys correspond to ````. + * - ``standard_run`` + - ``dict[str, dict]`` + - Identifies the standard run for each model when aggregating over + all HFCs or PFCs. Use the ``"default"`` sub-key for the default + set of name tags; add additional sub-keys (e.g. ``"longrun"``) for + alternative configurations. + +Species information +~~~~~~~~~~~~~~~~~~~ + +**File:** ``configs/species_info.json`` + +A dictionary of species identifiers (or group names) mapped to their physical +properties and display settings. + +.. list-table:: + :header-rows: 1 + :widths: 25 20 55 + + * - Key + - Type + - Description + * - ``species_print`` + - ``str`` + - Species name for plot axis labels, in LaTeX notation + (e.g. ``"HFC-134a"``). + * - ``gwp`` + - ``float`` + - GWP-100 value from IPCC AR5, used to convert country fluxes to + CO\ :sub:`2`-equivalent mass. + * - ``molar_mass`` + - ``float`` + - Molar mass in g mol\ :sup:`-1`, used for mol–g conversions. + * - ``list_species`` + - ``list[str]`` + - List of species identifiers that make up a group. + Used when plotting the sum of country fluxes across multiple species. + +Sites information +~~~~~~~~~~~~~~~~~ + +**File:** ``configs/site_info.json`` + +A dictionary of station codes mapped to per-network observation metadata. + +.. list-table:: + :header-rows: 1 + :widths: 25 20 55 + + * - Key + - Type + - Description + * - ``latitude`` + - ``float`` + - Latitude of the station in degrees North. + * - ``longitude`` + - ``float`` + - Longitude of the station in degrees East. + * - ``height_station_masl`` + - ``float`` + - Station elevation in metres above sea level. + * - ``long_name`` + - ``str`` + - Full descriptive name of the station. + * - ``height`` + - ``list[str]`` + - Inlet heights in metres above ground level. + * - ``height_name`` + - ``list[str]`` + - Human-readable labels for each inlet height. + +Optional input files +-------------------- + +Bottom-up inventory NetCDF +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Used to overlay gridded inventory estimates on flux maps. + +- **Template:** ``data/templates/PAR-AVE-EYE_inventory.cdl`` +- **Location:** ``/path/to/data/inventory/`` +- **Naming:** ``__.nc`` + + Example: ``UNFCCC_inventory_hfc134a_2024.nc`` + +Baseline timestamp NetCDF +~~~~~~~~~~~~~~~~~~~~~~~~~ + +Contains timestamps that flag background (baseline) periods at each +measurement station. + +- **Template:** ``data/templates/PAR-AVE-EYE_baseline_timestamps.cdl`` +- **Location:** ``/path/to/data/baseline_timestamps/`` +- **Naming:** ``__baseline_timestamps.nc`` + + Example: ``JFJ_InTEM_baseline_timestamps.nc`` diff --git a/scripts/fluxie-docs/docs/developer/index.rst b/scripts/fluxie-docs/docs/developer/index.rst new file mode 100644 index 00000000..18ef53a7 --- /dev/null +++ b/scripts/fluxie-docs/docs/developer/index.rst @@ -0,0 +1,135 @@ +Developer guide +=============== + +This page describes how to set up a development environment, run the test +suite, build the documentation locally, and submit contributions. + +.. contents:: On this page + :local: + :depth: 2 + +Setting up a development environment +------------------------------------- + +Clone the repository and install fluxie together with all development and +documentation dependencies:: + + git clone https://github.com/openghg/fluxie.git + cd fluxie + pip install -e ".[docs]" + +The ``.[docs]`` extra installs Sphinx, the Read the Docs theme, and all other +packages needed to build the documentation. + +Running the tests +----------------- + +The test suite uses `pytest `_:: + + pip install pytest + pytest tests/ + +To run a single test file:: + + pytest tests/test_.py -v + +Building the documentation locally +------------------------------------ + +:: + + cd docs + make html + +Open ``docs/_build/html/index.html`` in a browser to review the result. + +To rebuild from scratch (clears cached output):: + + make clean html + +Coding conventions +------------------ + +- Follow `PEP 8 `_ for all Python code. +- Write **NumPy-style docstrings** for every public function, class, and + module. The API reference is generated directly from these docstrings, so + accuracy and completeness matter. + + Minimal example:: + + def load_flux(path: str, species: str) -> xr.Dataset: + """Load a flux NetCDF file into an xarray Dataset. + + Parameters + ---------- + path : str + Path to the NetCDF file. + species : str + Species identifier used in the filename (e.g. ``"hfc134a"``). + + Returns + ------- + xr.Dataset + Dataset containing the flux variables defined in the + PARIS-AVENGERS-EYECLIMA template. + + Raises + ------ + FileNotFoundError + If no file matching ``path`` exists on disk. + """ + +- Add or update tests for every new function or bug fix. +- Keep pull requests focused: one logical change per PR makes review faster. + +Adding a new tutorial notebook +-------------------------------- + +1. Create the notebook under ``scripts/``. +2. Add a corresponding ``.nblink`` file in ``docs/tutorials/``:: + + { + "path": "../../scripts/.ipynb" + } + +3. Add the notebook name (without extension) to the ``toctree`` in + ``docs/tutorials/index.rst``. +4. Set ``nbsphinx_execute = "never"`` in ``docs/conf.py`` (already the + default) so the notebook is not re-executed during the documentation build. + +Making a release +---------------- + +1. Update the version string in ``pyproject.toml``. +2. Update ``CHANGELOG.md`` (if present) with a summary of changes. +3. Commit the version bump and push to ``devel``:: + + git add pyproject.toml + git commit -m "Bump version to X.Y" + git push origin devel + +4. Create and push a git tag matching the version:: + + git tag vX.Y + git push origin vX.Y + + Read the Docs will automatically build a versioned documentation snapshot + for the new tag. + +Contributing +------------ + +Contributions are welcome. The recommended workflow is: + +1. Open an issue on the `GitHub repository `_ + to describe the proposed change and discuss the approach with the maintainers + before writing code. +2. Fork the repository and create a feature branch:: + + git checkout -b feature/short-description + +3. Make your changes, add tests, and ensure the test suite passes. +4. Open a pull request against the ``devel`` branch and link it to the + relevant issue. + +For questions or discussion, use the issue tracker rather than direct contact. diff --git a/scripts/fluxie-docs/docs/getting_started.rst b/scripts/fluxie-docs/docs/getting_started.rst new file mode 100644 index 00000000..8adce1c7 --- /dev/null +++ b/scripts/fluxie-docs/docs/getting_started.rst @@ -0,0 +1,75 @@ +Getting started +=============== + +Requirements +------------ + +Fluxie requires Python 3.9 or later. All other dependencies are declared in +``pyproject.toml`` and are installed automatically. + +Installation +------------ + +Local machine +~~~~~~~~~~~~~ + +Clone the repository and install fluxie in editable mode so that any local +changes are immediately reflected without reinstalling:: + + git clone https://github.com/openghg/fluxie.git + cd fluxie + pip install -e . + +ICOS Jupyter Hub +~~~~~~~~~~~~~~~~ + +On the ICOS Jupyter Hub you must first create and activate a dedicated virtual +environment before installing the package. + +Create and activate the environment:: + + python -m venv fluxie-env + source fluxie-env/bin/activate + +Register the environment as a Jupyter kernel so you can select it in the +notebook interface:: + + pip install --upgrade pip + pip install ipykernel + python -m ipykernel install --user --name fluxie-env --display-name "fluxie-env" + +Install fluxie:: + + git clone https://github.com/openghg/fluxie.git + cd fluxie + pip install -e . + +.. note:: + + After installation, select ``fluxie-env`` from the kernel drop-down in the + upper-right corner of the Jupyter interface. If the kernel does not appear, + restart your Jupyter instance following the + `ICOS instructions `_. + +Quick start +----------- + +The fastest way to explore fluxie is to open and run the bundled example +notebook:: + + scripts/example_basics.ipynb + +It uses test data shipped with the repository and demonstrates the core +workflow: loading model output, selecting date ranges, and producing the +standard set of comparison plots. + +See :doc:`tutorials/index` for a rendered version of this notebook and +additional examples. + +Next steps +---------- + +- Read the :doc:`data_format` guide to learn how to structure your own model + output files so fluxie can read them. +- Browse the :doc:`api/index` for the complete function and class reference. +- See the :doc:`developer/index` if you want to contribute to the project. diff --git a/scripts/fluxie-docs/docs/index.rst b/scripts/fluxie-docs/docs/index.rst new file mode 100644 index 00000000..1452d09e --- /dev/null +++ b/scripts/fluxie-docs/docs/index.rst @@ -0,0 +1,46 @@ +.. fluxie documentation master file + +Fluxie documentation +==================== + +**Flux Intercomparison Environment (FLUXIE)** is a Python package developed +under the `PARIS project `_ for comparing and +visualising results from atmospheric inverse modelling systems. + +It provides: + +- Functions for loading, aligning, and aggregating model output. +- Standardised plots for flux maps, country totals, and concentration comparisons. +- Support for multi-model, multi-species, and multi-year analyses. + +.. toctree:: + :maxdepth: 2 + :caption: User guide + + getting_started + data_format + +.. toctree:: + :maxdepth: 2 + :caption: Tutorials + + tutorials/index + +.. toctree:: + :maxdepth: 2 + :caption: Reference + + api/index + +.. toctree:: + :maxdepth: 2 + :caption: Development + + developer/index + +Indices and tables +------------------ + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` diff --git a/scripts/fluxie-docs/docs/requirements.txt b/scripts/fluxie-docs/docs/requirements.txt new file mode 100644 index 00000000..c53694ad --- /dev/null +++ b/scripts/fluxie-docs/docs/requirements.txt @@ -0,0 +1,11 @@ +# docs/requirements.txt +# +# Pinned build dependencies for Read the Docs. +# These versions are tested together; bumping one may require checking +# compatibility with the others. +sphinx==7.3.7 +sphinx-rtd-theme==2.0.0 +sphinx-autodoc-typehints==1.25.3 +myst-parser==2.0.0 +nbsphinx==0.9.3 +nbsphinx-link==1.3.0 diff --git a/scripts/fluxie-docs/docs/tutorials/example_basics.nblink b/scripts/fluxie-docs/docs/tutorials/example_basics.nblink new file mode 100644 index 00000000..d959824e --- /dev/null +++ b/scripts/fluxie-docs/docs/tutorials/example_basics.nblink @@ -0,0 +1,3 @@ +{ + "path": "../../scripts/example_basics.ipynb" +} diff --git a/scripts/fluxie-docs/docs/tutorials/index.rst b/scripts/fluxie-docs/docs/tutorials/index.rst new file mode 100644 index 00000000..a0cfc67a --- /dev/null +++ b/scripts/fluxie-docs/docs/tutorials/index.rst @@ -0,0 +1,15 @@ +Tutorials +========= + +The notebooks below walk through concrete workflows using fluxie. +They are executed against real test data shipped with the repository, +so every output shown is reproducible. + +To run a notebook interactively, open it from the ``scripts/`` directory +in your Jupyter environment after completing the :doc:`../getting_started` +installation steps. + +.. toctree:: + :maxdepth: 1 + + example_basics diff --git a/scripts/fluxie-docs/pyproject_docs_addition.toml b/scripts/fluxie-docs/pyproject_docs_addition.toml new file mode 100644 index 00000000..3817e605 --- /dev/null +++ b/scripts/fluxie-docs/pyproject_docs_addition.toml @@ -0,0 +1,25 @@ +# ----------------------------------------------------------------------- +# ADD THIS BLOCK to the [project.optional-dependencies] section of your +# existing pyproject.toml. +# +# Example of what the section looks like after the addition: +# +# [project.optional-dependencies] +# docs = [ +# "sphinx>=7.0", +# ... +# ] +# +# Install locally with: +# pip install -e ".[docs]" +# ----------------------------------------------------------------------- + +[project.optional-dependencies] +docs = [ + "sphinx>=7.0", + "sphinx-rtd-theme>=2.0", + "sphinx-autodoc-typehints>=1.25", + "myst-parser>=2.0", + "nbsphinx>=0.9", + "nbsphinx-link>=1.3", +]