From bb194586fcd1082bfc6773adbb20d10cac51d47b Mon Sep 17 00:00:00 2001 From: SarahAlidoost Date: Wed, 15 Oct 2025 14:05:34 +0200 Subject: [PATCH 01/32] update intro --- docs/intro.md | 17 +++++++++++++++++ mkdocs.yml | 27 +++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/docs/intro.md b/docs/intro.md index e69de29..a9e2ce9 100644 --- a/docs/intro.md +++ b/docs/intro.md @@ -0,0 +1,17 @@ +# Differentiable WOFOST + +The package diffwofost contains a differentiable implementation of the WOFOST +crop growth models using [`pytorch`](https://pytorch.org/) and +[`PCSE`](https://pcse.readthedocs.io/en/stable/index.html). The implementation +allows for automatic differentiation, enabling gradient-based optimization and +sensitivity analysis. + +In PCSE, WOFOST models are categorized based on +`___` and ech model +contains a set of submodels, see [Models available in +PCSE](https://pcse.readthedocs.io/en/stable/available_models.html#models-available-in-pcse) +and [PCSE +Engine](https://pcse.readthedocs.io/en/stable/reference_guide.html#the-engine). +in diffwofost, each submodel is implemented as a differentiable pytorch module, +allowing for end-to-end differentiation of the entire WOFOST model, see +[torch.nn](https://docs.pytorch.org/docs/stable/nn.html). diff --git a/mkdocs.yml b/mkdocs.yml index 4a26e08..131dc82 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -4,7 +4,9 @@ repo_name: diffWOFOST nav: - Introduction: intro.md + - Example notebooks: - Contributing guide: CONTRIBUTING.md + - API Reference: api_reference.md theme: name: material @@ -35,6 +37,31 @@ theme: plugins: - include-markdown - search +- mkdocs-jupyter: + include_source: True +- mkdocstrings: + handlers: + python: + options: + docstring_style: numpy + docstring_options: + ignore_init_summary: true + merge_init_into_class: true + docstring_section_style: list + show_submodules: true + show_root_heading: true + show_source: true + heading_level: 3 + relative_crossrefs: true + parameter_headings: false + separate_signature: true + show_bases: true + show_signature_annotations: true + show_symbol_type_heading: true + signature_crossrefs: true + summary: true + backlinks: tree + scoped_crossrefs: true markdown_extensions: - pymdownx.highlight: From a5b19bb25c233b28f7c19f1c24e09a78ea8aed47 Mon Sep 17 00:00:00 2001 From: SarahAlidoost Date: Mon, 20 Oct 2025 09:49:49 +0200 Subject: [PATCH 02/32] update docs --- docs/intro.md | 116 ++++++++++++++++++++++++++++++++++++++++++++++---- mkdocs.yml | 15 +++++-- 2 files changed, 119 insertions(+), 12 deletions(-) diff --git a/docs/intro.md b/docs/intro.md index a9e2ce9..9e17e7b 100644 --- a/docs/intro.md +++ b/docs/intro.md @@ -1,17 +1,115 @@ -# Differentiable WOFOST +# -The package diffwofost contains a differentiable implementation of the WOFOST +## diffWOFOST: Differentiable WOFOST + +The package diffWOFOST contains a differentiable implementation of the WOFOST crop growth models using [`pytorch`](https://pytorch.org/) and [`PCSE`](https://pcse.readthedocs.io/en/stable/index.html). The implementation -allows for automatic differentiation, enabling gradient-based optimization and -sensitivity analysis. +allows for automatic differentiation, enabling gradient-based optimization, +sensitivity analysis and data assimilation. In PCSE, WOFOST models are categorized based on -`___` and ech model -contains a set of submodels, see [Models available in +`version, productionlevel, waterbalance, nitrogenbalance` and each model +contains a set of elements e.g. crop and soil models, see [models available in PCSE](https://pcse.readthedocs.io/en/stable/available_models.html#models-available-in-pcse) and [PCSE Engine](https://pcse.readthedocs.io/en/stable/reference_guide.html#the-engine). -in diffwofost, each submodel is implemented as a differentiable pytorch module, -allowing for end-to-end differentiation of the entire WOFOST model, see -[torch.nn](https://docs.pytorch.org/docs/stable/nn.html). + +In diffWOFOST, each element is implemented as a differentiable module, using +[torch.Tensor](https://docs.pytorch.org/docs/stable/tensors.html), allowing for +end-to-end differentiation of the entire WOFOST model. To develop a +differentiable module, we check for look-up tables, hard thresholds, and +mathematical operations, and replace them with differentiable alternatives. + +In addition to differentiability, the implementation also focuses on efficiency, +by leveraging vectorized operations. This is particularly important for +large-scale simulations and training workflows, where the computational cost +can be significant. + +## Hybrid modelling with diffWOFOST + +Hybrid modelling, referring to a combination of process-based and +machine-learning modelling, has recently emerged as a promising line of research +to harness the strengths of both approaches while mitigating their respective +weaknesses, see [Integrating Scientific Knowledge with Machine Learning for +Engineering and Environmental Systems]( +https://doi.org/10.48550/arXiv.2003.04919 ) and [Deep learning and process +understanding for data-driven Earth system +science](https://doi.org/10.1038/s41586-019-0912-1). + +The approach where an machine learning (ML) model predicts physical parameters, which +are then used in a physics-based model, and combines both in a hybrid +architecture, is a state-of-the-art approach and is known under various names, +see [Scientific Machine +Learning](https://sciml.wur.nl/reviews/sciml/sciml.html). The mathematics would +be: + +$$ +\frac{\partial \text{loss}}{\partial \text{(ML model weights)}} = \frac{\partial \text{loss}}{\partial \text{(physics-based model output)}} \cdot \frac{\partial \text{(physics-based model output)}}{\partial \text{(physics-based model parameters)}} \cdot \frac{\partial \text{(physics-based model parameters)}}{\partial \text{(ML model weights)}} +$$ + +And code wise, this would look like: + +```python +import torch.nn as nn + +# Step 1: ML model that outputs physical parameters e.g. LSTM +class MLModel(nn.Module): + def __init__(self, input_size, hidden_size, num_physical_params): + super().__init__() + self.lstm = nn.LSTM(input_size=input_size, hidden_size=hidden_size, batch_first=True) + self.linear = nn.Linear(hidden_size, num_physical_params) + + def forward(self, x): + lstm_out, _ = self.lstm(x) + physical_params = self.linear(lstm_out[:, -1, :]) + return physical_params + +# Step 2: Physical model i.e. a differentiable WOFOST model e.g. Wofost72_PP +class PhysicalModel(nn.Module): + def __init__(self, dt): + super().__init__() + + def forward(self, params): + model = Wofost72_PP(params, ...) # this is differentiable version + model.run_till_terminate() # finish the simulation + output = model.get_output() + return output + +# Step 3: Hybrid model integrating ML and physical model +class HybridModel(nn.Module): + def __init__(self, input_size, hidden_size, num_physical_params): + super().__init__() + self.ml_model = MLModel(input_size, hidden_size, num_physical_params) + self.physical_model = PhysicalModel() + + def forward(self, x): + physical_params = self.ml_model(x) + output = self.physical_model(physical_params) + return output, physical_params +``` + +## Code structure (under development) + +The package is structured as follows: + +```bash +├── physical_models/ + ├── crop/ # differentiable implementation of each crop model + │ ├── leaf_dynamics.py + │ ├── root_dynamics.py + ├── soil/ + ├── utils.py # helpers +``` + +## Citation + +to be added. + +## Acknowledgements + +to be added. + +## License + +to be added. diff --git a/mkdocs.yml b/mkdocs.yml index 131dc82..f6e250f 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -4,16 +4,19 @@ repo_name: diffWOFOST nav: - Introduction: intro.md - - Example notebooks: + - Getting started: getting_started.md - Contributing guide: CONTRIBUTING.md - API Reference: api_reference.md theme: name: material + custom_dir: docs/download_button + logo: logo/diffwofost.png features: - navigation.instant - navigation.tabs - navigation.tabs.sticky + - content.code.copy icon: repo: fontawesome/brands/github-alt @@ -23,7 +26,7 @@ theme: toggle: icon: material/weather-sunny name: Switch to dark mode - primary: light blue + primary: green accent: blue # Palette toggle for dark mode @@ -31,7 +34,7 @@ theme: toggle: icon: material/weather-night name: Switch to light mode - primary: blue grey + primary: green accent: teal plugins: @@ -66,6 +69,8 @@ plugins: markdown_extensions: - pymdownx.highlight: anchor_linenums: true + - pymdownx.arithmatex: + generic: true - pymdownx.superfences - pymdownx.details - admonition @@ -75,3 +80,7 @@ markdown_extensions: extra: generator: false + math: mathjax + +extra_javascript: + - https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js From db1474a7c27c398a2f610faaff5f6e23671a5781 Mon Sep 17 00:00:00 2001 From: SarahAlidoost Date: Tue, 21 Oct 2025 11:24:33 +0200 Subject: [PATCH 03/32] update docs --- LICENSE | 30 ++++--- docs/CONTRIBUTING.md | 79 ++++++++--------- docs/README.dev.md | 172 ------------------------------------ docs/acknowledgements.md | 0 docs/api_reference.md | 15 ++++ docs/citation.md | 0 docs/developer_guide.md | 100 +++++++++++++++++++++ docs/examples.md | 26 ++++++ docs/{intro.md => index.md} | 12 --- docs/installation.md | 25 ++++++ docs/license.md | 3 + docs/project_setup.md | 87 +++++------------- docs/run_model.md | 32 +++++++ mkdocs.yml | 21 ++++- 14 files changed, 293 insertions(+), 309 deletions(-) delete mode 100644 docs/README.dev.md create mode 100644 docs/acknowledgements.md create mode 100644 docs/api_reference.md create mode 100644 docs/citation.md create mode 100644 docs/developer_guide.md create mode 100644 docs/examples.md rename docs/{intro.md => index.md} (98%) create mode 100644 docs/installation.md create mode 100644 docs/license.md create mode 100644 docs/run_model.md diff --git a/LICENSE b/LICENSE index bbafe88..1c51bed 100644 --- a/LICENSE +++ b/LICENSE @@ -1,16 +1,18 @@ -# Licensed under the EUPL, Version 1.1 or – as soon they -# will be approved by the European Commission - subsequent -# versions of the EUPL (the "Licence"); -# You may not use this work except in compliance with the -# Licence. -# You may obtain a copy of the Licence at: +**EUPL, Version 1.1** -# http://ec.europa.eu/idabc/eupl +Licensed under the EUPL, Version 1.1 or as soon they +will be approved by the European Commission - subsequent +versions of the EUPL (the "Licence") -# Unless required by applicable law or agreed to in -# writing, software distributed under the Licence is -# distributed on an "AS IS" basis, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -# express or implied. -# See the Licence for the specific language governing -# permissions and limitations under the Licence. +You may not use this work except in compliance with the +Licence. +You may obtain a copy of the Licence at +http://ec.europa.eu/idabc/eup +Unless required by applicable law or agreed to in +writing, software distributed under the Licence is +distributed on an "AS IS" basis, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either +express or implied. + +See the Licence for the specific language governing +permissions and limitations under the Licence. diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md index b4f7281..b74efe8 100644 --- a/docs/CONTRIBUTING.md +++ b/docs/CONTRIBUTING.md @@ -1,6 +1,9 @@ -# Contributing guidelines +# -We welcome any kind of contribution to our software, from simple comment or question to a full fledged [pull request](https://help.github.com/articles/about-pull-requests/). Please read and follow our [Code of Conduct](CODE_OF_CONDUCT.md). +We welcome any kind of contribution to our software, from simple comment or +question to a full fledged [pull +request](https://help.github.com/articles/about-pull-requests/). Please read and +follow our [Code of Conduct](CODE_OF_CONDUCT.md). A contribution can be one of the following cases: @@ -13,56 +16,50 @@ The sections below outline the steps in each case. ## You have a question -1. use the search functionality [here](https://github.com/WUR-AI/diffwofost/issues) to see if someone already filed the same issue; +1. use the search functionality [in + issues](https://github.com/WUR-AI/diffwofost/issues) to see if someone + already filed the same issue; 2. if your issue search did not yield any relevant results, make a new issue; 3. apply the "Question" label; apply other labels when relevant. ## You think you may have found a bug -1. use the search functionality [here](https://github.com/WUR-AI/diffwofost/issues) to see if someone already filed the same issue; -1. if your issue search did not yield any relevant results, make a new issue, making sure to provide enough information to the rest of the community to understand the cause and context of the problem. Depending on the issue, you may want to include: - - the [SHA hashcode](https://help.github.com/articles/autolinked-references-and-urls/#commit-shas) of the commit that is causing your problem; - - some identifying information (name and version number) for dependencies you're using; - - information about the operating system; -1. apply relevant labels to the newly created issue. +1. use the search functionality [in + issues](https://github.com/WUR-AI/diffwofost/issues) to see if someone + already filed the same issue; +2. if your issue search did not yield any relevant results, make a new issue, + making sure to provide enough information to the rest of the community to + understand the cause and context of the problem. ## You want to make some kind of change to the code base -1. (**important**) announce your plan to the rest of the community *before you start working*. This announcement should be in the form of a (new) issue; -1. (**important**) wait until some kind of consensus is reached about your idea being a good idea; -1. if needed, fork the repository to your own Github profile and create your own feature branch off of the latest main commit. While working on your feature branch, make sure to stay up to date with the main branch by pulling in changes, possibly from the 'upstream' repository (follow the instructions [here](https://help.github.com/articles/configuring-a-remote-for-a-fork/) and [here](https://help.github.com/articles/syncing-a-fork/)); -1. install dependencies (see the [development documentation](README.dev.md#development_install)); -1. make sure the existing tests still work by running ``pytest``; -1. add your own tests (if necessary); -1. update or expand the documentation; +1. (**important**) announce your plan to the rest of the community *before you + start working*. This announcement should be in the form of a (new) issue; +2. (**important**) wait until some kind of consensus is reached about your idea being a good idea; +3. follow the instruction in [developer_guide.md](developer_guide.md). -1. [push](http://rogerdudler.github.io/git-guide/) your feature branch to (your fork of) the diffwofost repository on GitHub; -1. create the pull request, e.g. following the instructions [here](https://help.github.com/articles/creating-a-pull-request/). - -In case you feel like you've made a valuable contribution, but you don't know how to write or run tests for it, or how to generate the documentation: don't let this discourage you from making the pull request; we can help you! Just go ahead and submit the pull request, but keep in mind that you might be asked to append additional commits to your pull request. +In case you feel like you've made a valuable contribution, but you don't know +how to write or run tests for it, or how to generate the documentation: don't +let this discourage you from making the pull request; we can help you! Just go +ahead and submit an issue and ask your questions. ## You want to make a new release of the code base To create a release you need write permission on the repository. -1. Check the author list in [`CITATION.cff`](CITATION.cff) -1. Bump the version using `bump-my-version bump `. For example, `bump-my-version bump major` will increase major version numbers everywhere it's needed (code, meta, etc.) in the repo. Alternatively the version can be manually changed in diffwofost/__init__.py, pyproject.toml, CITATION.cffand docs/conf.py (and other places it was possibly added). - -1. Go to the [GitHub release page](https://github.com/WUR-AI/diffwofost/releases) -1. Press draft a new release button -1. Fill version, title and description field -1. Press the Publish Release button - - - -Also a Zenodo entry will be made for the release with its own DOI. +1. Check the author list in `CITATION.cff`in + the root of the repository. +2. Bump the version. The version can be manually changed in `pyproject.toml` in + the root of the repository. Follow [Semantic Versioning](https://semver.org/) + principles. + +3. Go to the [GitHub release + page](https://github.com/WUR-AI/diffwofost/releases). Press draft a new + release button. Fill version, title and description field. Press the Publish + Release button + +4. This software automatically publish to PyPI using a release or publish + workflow. Wait until [PyPi publish + workflow](https://github.com/WUR-AI/diffwofost/actions/workflows/python-publish.yml) + has completed and verify new release is on + [PyPi](https://pypi.org/project/matchms/#history) diff --git a/docs/README.dev.md b/docs/README.dev.md deleted file mode 100644 index b365d11..0000000 --- a/docs/README.dev.md +++ /dev/null @@ -1,172 +0,0 @@ -# `diffwofost` developer documentation - -If you're looking for user documentation, go [here](README.md). - -## Development install - -```shell -# Create a virtual environment, e.g. with -python -m venv env - -# activate virtual environment -source env/bin/activate - -# make sure to have a recent version of pip and setuptools -python -m pip install --upgrade pip setuptools - -# (from the project root directory) -# install diffwofost as an editable package -python -m pip install --no-cache-dir --editable . -# install development dependencies -python -m pip install --no-cache-dir --editable .[dev] -# install documentation dependencies only -python -m pip install --no-cache-dir --editable .[docs] -``` - -Afterwards check that the install directory is present in the `PATH` environment variable. - -## Running the tests - -There are two ways to run tests. - -The first way requires an activated virtual environment with the development tools installed: - -```shell -pytest -v -``` - -### Test coverage - -In addition to just running the tests to see if they pass, they can be used for coverage statistics, i.e. to determine how much of the package's code is actually executed during tests. -In an activated virtual environment with the development tools installed, inside the package directory, run: - -```shell -coverage run -``` - -This runs tests and stores the result in a `.coverage` file. -To see the results on the command line, run - -```shell -coverage report -``` - -`coverage` can also generate output in HTML and other formats; see `coverage help` for more information.## Running linters locally - -For linting and sorting imports we will use [ruff](https://beta.ruff.rs/docs/). Running the linters requires an -activated virtual environment with the development tools installed. - -```shell -# linter -ruff check . - -# linter with automatic fixing -ruff check . --fix -``` - -To fix readability of your code style you can use [yapf](https://github.com/google/yapf) - -## Generating documentation page - -- Install the required dependencies as: - - ```bash - cd FOWT-ML - pip install -e .[docs] - ``` - -- Build the documentation as: - - ```bash - mkdocs build - ``` - -- Preview the documentation as: - - ```bash - mkdocs serve - ``` - -Click on the link provided in the terminal to view the documentation page. - -## Versioning - -Bumping the version across all files is done with [bump-my-version](https://github.com/callowayproject/bump-my-version), e.g. - -```shell -bump-my-version bump major # bumps from e.g. 0.3.2 to 1.0.0 -bump-my-version bump minor # bumps from e.g. 0.3.2 to 0.4.0 -bump-my-version bump patch # bumps from e.g. 0.3.2 to 0.3.3 -``` - -## Making a release - -This section describes how to make a release in 3 parts: - -1. preparation -1. making a release on PyPI -1. making a release on GitHub - -### (1/3) Preparation - - -1. Verify that the information in [`CITATION.cff`](CITATION.cff) is correct. -1. Make sure the [version has been updated](#versioning). -1. Run the unit tests with `pytest -v` - -### (2/3) PyPI - -In a new terminal: - -```shell -# OPTIONAL: prepare a new directory with fresh git clone to ensure the release -# has the state of origin/main branch -cd $(mktemp -d diffwofost.XXXXXX) -git clone git@github.com:WUR-AI/diffwofost . - -# make sure to have a recent version of pip and the publishing dependencies -python -m pip install --upgrade pip -python -m pip install .[publishing] - -# create the source distribution and the wheel -python -m build - -# upload to test pypi instance (requires credentials) -python -m twine upload --repository testpypi dist/* -``` - -Visit -[https://test.pypi.org/project/diffwofost](https://test.pypi.org/project/diffwofost) -and verify that your package was uploaded successfully. Keep the terminal open, we'll need it later. - -In a new terminal, without an activated virtual environment or an env directory: - -```shell -cd $(mktemp -d diffwofost-test.XXXXXX) - -# prepare a clean virtual environment and activate it -python -m venv env -source env/bin/activate - -# make sure to have a recent version of pip and setuptools -python -m pip install --upgrade pip - -# install from test pypi instance: -python -m pip -v install --no-cache-dir \ ---index-url https://test.pypi.org/simple/ \ ---extra-index-url https://pypi.org/simple diffwofost -``` - -Check that the package works as it should when installed from pypitest. - -Then upload to pypi.org with: - -```shell -# Back to the first terminal, -# FINAL STEP: upload to PyPI (requires credentials) -python -m twine upload dist/* -``` - -### (3/3) GitHub - -Don't forget to also make a [release on GitHub](https://github.com/WUR-AI/diffwofost/releases/new).GitHub-Zenodo integration will also trigger Zenodo into making a snapshot of your repository and sticking a DOI on it. \ No newline at end of file diff --git a/docs/acknowledgements.md b/docs/acknowledgements.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/api_reference.md b/docs/api_reference.md new file mode 100644 index 0000000..5674925 --- /dev/null +++ b/docs/api_reference.md @@ -0,0 +1,15 @@ +--- +hide: +- navigation +--- +# + +## **Crop modules** + +::: diffwofost.physical_models.crop.leaf_dynamics.WOFOST_Leaf_Dynamics + +::: diffwofost.physical_models.crop.root_dynamics.WOFOST_Root_Dynamics + +## **Utility** + +::: diffwofost.physical_models.utils.EngineTestHelper diff --git a/docs/citation.md b/docs/citation.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/developer_guide.md b/docs/developer_guide.md new file mode 100644 index 0000000..6868c6c --- /dev/null +++ b/docs/developer_guide.md @@ -0,0 +1,100 @@ +# + +If you are a developer wanting to contribute to the diffwofost package, this +guide will help you get started. First check out the contribution guidelines in +[Contributing guide](CONTRIBUTING.md) and the [project setup](project_setup.md) +to get familiar with the package structure and development practices. + +## Installation in development mode + +To install the package in development mode, you need to clone the source code +and install the package in development mode: + +```bash +git clone https://github.com/WUR-AI/diffWOFOST.git +cd diffWOFOST +pip install -e .[dev] ## install with development dependencies +pip install -e .[docs] ## install with documentation dependencies +``` + +## GitHub collaboration workflow + +We use a GitHub collaboration workflow based on feature branches and pull +requests. When starting adding a new feature or fixing a bug, create a new +branch from `main` branch. When your changes are ready, create a pull request to +merge your changes back into `main` branch. Make sure to ask for at least one +review from another team member before merging your pull request. + +## Running the tests + +- Tests should be put in the `tests` folder. +- The testing framework used is [PyTest](https://pytest.org) +- The project uses [GitHub action workflows](https://docs.github.com/en/actions) + to automatically run tests on GitHub infrastructure against multiple Python + versions. Workflows can be found in [`.github/workflows`](.github/workflows/) +- [Relevant section in the + guide](https://guide.esciencecenter.nl/#/best_practices/language_guides/python?id=testing) +- To run the tests locally, you need to make sure that you have installed the +development dependencies as described in the [Installation in development +mode](#installation-in-development-mode) section. +Then, inside the package directory, run: + +```bash +pytest -v +``` + +to run all tests with verbose output. To run an individual test file, run: + +```bash +pytest -v tests/test_my_module.py +``` + +### Linters + +For linting and sorting imports we will use [ruff](https://beta.ruff.rs/docs/). +Running the linters requires an activated virtual environment with the +development tools installed. + +```shell +# linter +ruff check . + +# linter with automatic fixing +ruff check . --fix + +# check formatting only +ruff format --check . --diff +``` + +## Documentation page + +- Documentation should be put in the [`docs/`](docs/) directory. +- We recommend writing the documentation using Google style docstrings. +- The documentation is set up with the [MkDocs](https://www.mkdocs.org/). + - `.mkdocs.yml` is the [MkDocs](https://www.mkdocs.org/) configuration file. When MkDocs is building the documentation this package and its development dependencies are installed so the API reference can be rendered. +- Make sure you have installed the documentation dependencies as described in the +[Installation in development mode](#installation-in-development-mode) section. +Then, inside the package directory, run: + +```bash + +# Build the documentation +mkdocs build + +# Preview the documentation +mkdocs serve + +``` + +Click on the link provided in the terminal to view the documentation page. + +## Coding style conventions and code quality + +- [Relevant section in the NLeSC guide](https://guide.esciencecenter.nl/#/best_practices/language_guides/python?id=coding-style-conventions). + +## Continuous code quality + +[Sonarcloud](https://sonarcloud.io/) is used to perform quality analysis and code coverage report + +- `sonar-project.properties` is the SonarCloud [configuration](https://docs.sonarqube.org/latest/analysis/analysis-parameters/) file +- `.github/workflows/sonarcloud.yml` is the GitHub action workflow which performs the SonarCloud analysis \ No newline at end of file diff --git a/docs/examples.md b/docs/examples.md new file mode 100644 index 0000000..8580013 --- /dev/null +++ b/docs/examples.md @@ -0,0 +1,26 @@ +# + +## Hybrid modelling + +We provide an example notebook showing hybrid modelling with `diffWOFOST`. + +=== "Open the notebook in Colab" + + You can open and run the notebook directly in Google Colab by clicking the badge below: + + [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)][colab_link] + +=== "Access the source notebook" + + You can access the source code of the notebook on GitHub by clicking the badge below: + + [![Access the source code](https://img.shields.io/badge/github-repo-000.svg?logo=github&labelColor=gray&color=blue)][source_link] + +=== "View the notebook" + + You can view the full notebook [here](./notebooks/optimization.ipynb). + + +[colab_link]: https://colab.research.google.com/github/WUR-AI/diffWOFOST/blob/main/docs/notebooks/optimization.ipynb + +[source_link]: https://github.com/WUR-AI/diffWOFOST/blob/main/docs/notebooks/optimization.ipynb diff --git a/docs/intro.md b/docs/index.md similarity index 98% rename from docs/intro.md rename to docs/index.md index 9e17e7b..dd78cfd 100644 --- a/docs/intro.md +++ b/docs/index.md @@ -101,15 +101,3 @@ The package is structured as follows: ├── soil/ ├── utils.py # helpers ``` - -## Citation - -to be added. - -## Acknowledgements - -to be added. - -## License - -to be added. diff --git a/docs/installation.md b/docs/installation.md new file mode 100644 index 0000000..fb31fdc --- /dev/null +++ b/docs/installation.md @@ -0,0 +1,25 @@ +# Installation + +To install the package, use pip: + +```bash +pip install diffwofost +``` + +if you want to run notebooks locally, you need to install `jupyterlab`: + +```bash +pip install jupyterlab +``` + +If you are a contributer, clone the source code and install the package in +development mode: + +```bash +git clone https://github.com/WUR-AI/diffWOFOST.git +cd diffWOFOST +pip install -e .[dev] +``` + +If you are a contributer, please follwo the instructions in the `contribution +guide` in the documentation. diff --git a/docs/license.md b/docs/license.md new file mode 100644 index 0000000..8f249ec --- /dev/null +++ b/docs/license.md @@ -0,0 +1,3 @@ +# + +{% include-markdown "https://raw.githubusercontent.com/WUR-AI/diffWOFOST/refs/heads/main/LICENSE" %} diff --git a/docs/project_setup.md b/docs/project_setup.md index 4830b60..a172504 100644 --- a/docs/project_setup.md +++ b/docs/project_setup.md @@ -1,32 +1,33 @@ -# Project Setup Here we provide some details about the project setup. Most of the choices are -explained in the [guide](https://guide.esciencecenter.nl). Links to the relevant -sections are included below. Feel free to remove this text when the development -of the software package takes off. +explained in the [guide](https://guide.esciencecenter.nl). For a quick reference on software development, we refer to [the software guide checklist](https://guide.esciencecenter.nl/#/best_practices/checklist). -## Python versions +## Repository structure -This repository is set up with Python versions: +The repository has the following structure: -- 3.10 -- 3.11 -- 3.12 +```bash -Add or remove Python versions based on project requirements. See [the -guide](https://guide.esciencecenter.nl/#/best_practices/language_guides/python) -for more information about Python versions. +├── .github/ # GitHub specific files such as workflows +├── docs/ # Documentation source files +├── my_package/ # Main package code +├── tests/ # Test code +├── .gitignore # Git ignore file +├── CITATION.cff # Citation file +├── LICENSE # License file +├── README.md # User documentation +├── pyproject.toml # Project configuration file and dependencies +├── mkdocs.yml # MkDocs configuration file + +``` ## Package management and dependencies -You can use either pip or conda for installing dependencies and package -management. This repository does not force you to use one or the other, as -project requirements differ. For advice on what to use, please check [the -relevant section of the -guide](https://guide.esciencecenter.nl/#/best_practices/language_guides/python?id=dependencies-and-package-management). +You can use pip for installing dependencies and package +management. - Runtime dependencies should be added to `pyproject.toml` in the `dependencies` list under `[project]`. @@ -36,55 +37,15 @@ guide](https://guide.esciencecenter.nl/#/best_practices/language_guides/python?i ## Packaging/One command install -You can distribute your code using PyPI. [The -guide](https://guide.esciencecenter.nl/#/best_practices/language_guides/python?id=building-and-packaging-code) -can help you decide which tool to use for packaging. - -## Testing and code coverage - -- Tests should be put in the `tests` folder. -- The `tests` folder contains: - - Example tests that you should replace with your own meaningful tests (file: `test_my_module.py`) -- The testing framework used is [PyTest](https://pytest.org) - - [PyTest introduction](https://pythontest.com/pytest-book/) - - PyTest is listed as a development dependency - - This is configured in `pyproject.toml` -- The project uses [GitHub action workflows](https://docs.github.com/en/actions) to automatically run tests on GitHub infrastructure against multiple Python versions - - Workflows can be found in [`.github/workflows`](.github/workflows/) -- [Relevant section in the guide](https://guide.esciencecenter.nl/#/best_practices/language_guides/python?id=testing) - -## Documentation - -- Documentation should be put in the [`docs/`](docs/) directory. -- We recommend writing the documentation using Google style docstrings. -- The documentation is set up with the [MkDocs](https://www.mkdocs.org/). - - `.mkdocs.yml` is the [MkDocs](https://www.mkdocs.org/) configuration file. When MkDocs is building the documentation this package and its development dependencies are installed so the API reference can be rendered. - -## Coding style conventions and code quality - -- [Relevant section in the NLeSC guide](https://guide.esciencecenter.nl/#/best_practices/language_guides/python?id=coding-style-conventions) and [README.dev.md](README.dev.md). - -## Continuous code quality - -[Sonarcloud](https://sonarcloud.io/) is used to perform quality analysis and code coverage report - -- `sonar-project.properties` is the SonarCloud [configuration](https://docs.sonarqube.org/latest/analysis/analysis-parameters/) file -- `.github/workflows/sonarcloud.yml` is the GitHub action workflow which performs the SonarCloud analysis +You can distribute your code using PyPI. This can be done automatically using +GitHub workflows, see `.github/`. ## Package version number - We recommend using [semantic versioning](https://guide.esciencecenter.nl/#/best_practices/releases?id=semantic-versioning). -- For convenience, the package version is stored in a single place: `pyproject.toml` under the `tool.bumpversion` header. +- For convenience, the package version is stored in a single place: `pyproject.toml`. - Don't forget to update the version number before [making a release](https://guide.esciencecenter.nl/#/best_practices/releases)! -## Logging - -- We recommend using the logging module for getting useful information from your module (instead of using print). -- The project is set up with a logging example. -- [Relevant section in the guide](https://guide.esciencecenter.nl/#/best_practices/language_guides/python?id=logging) - - - ## CITATION.cff - To allow others to cite your software, add a `CITATION.cff` file @@ -100,9 +61,3 @@ can help you decide which tool to use for packaging. - Information about how to contribute to this software package - [Relevant section in the guide](https://guide.esciencecenter.nl/#/best_practices/documentation?id=contribution-guidelines) - - -## NOTICE - -- List of attributions of this project and Apache-license dependencies -- [Relevant section in the guide](https://guide.esciencecenter.nl/#/best_practices/licensing?id=notice) diff --git a/docs/run_model.md b/docs/run_model.md new file mode 100644 index 0000000..b9458b5 --- /dev/null +++ b/docs/run_model.md @@ -0,0 +1,32 @@ +# + +# How to run a model with PCSE + +To get familiar with WOFOST models and how to run the models, we recommend to +first check out the [PCSE +documentation](https://pcse.readthedocs.io/en/stable/index.html) and explore the +notebooks [01 Getting Started with +PCSE.ipynb](https://github.com/ajwdewit/pcse_notebooks/blob/master/01%20Getting%20Started%20with%20PCSE.ipynb) +and [02 Running with custom input data.ipynb +](https://github.com/ajwdewit/pcse_notebooks/blob/master/02%20Running%20with%20custom%20input%20data.ipynb). + +in a nutshell, we can run a model for example `leaf_dynamics` using PCSE as: + +```python +from diffwofost.physical_models.utils import EngineTestHelper + +# create the model +model = EngineTestHelper( + crop_parameters_provider, # this provides the crop parameters + weather_data_provider, + agromanagement_provider, + leaf_dynamics_config_file, # this where the differentiable model is specified + external_states, # any external states if needed +) + +# run the simulation with a fixed time step of one day +model.run_till_terminate() + +# get the output +results = model.get_output() +``` diff --git a/mkdocs.yml b/mkdocs.yml index f6e250f..f011e7d 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -3,9 +3,18 @@ repo_url: https://github.com/WUR-AI/diffwofost repo_name: diffWOFOST nav: - - Introduction: intro.md - - Getting started: getting_started.md - - Contributing guide: CONTRIBUTING.md + - Introduction: + - diffWOFOST: index.md + - Citation: citation.md + - License: license.md + - Acknowledgements: acknowledgements.md + - Getting started: + - Installation: installation.md + - How to run a model: run_model.md + - Example notebooks: examples.md + - Geeting involved in development: + - Contributing guide: CONTRIBUTING.md + - Developer guide: developer_guide.md - API Reference: api_reference.md theme: @@ -17,6 +26,7 @@ theme: - navigation.tabs - navigation.tabs.sticky - content.code.copy + - content.tabs icon: repo: fontawesome/brands/github-alt @@ -45,8 +55,9 @@ plugins: - mkdocstrings: handlers: python: + paths: [src] options: - docstring_style: numpy + docstring_style: google docstring_options: ignore_init_summary: true merge_init_into_class: true @@ -65,6 +76,7 @@ plugins: summary: true backlinks: tree scoped_crossrefs: true + members_order: source markdown_extensions: - pymdownx.highlight: @@ -73,6 +85,7 @@ markdown_extensions: generic: true - pymdownx.superfences - pymdownx.details + - pymdownx.emoji - admonition - pymdownx.tabbed: alternate_style: true From 547bf20469a13566092414c8a4cfbd35f7fbfa68 Mon Sep 17 00:00:00 2001 From: SarahAlidoost Date: Tue, 21 Oct 2025 11:25:10 +0200 Subject: [PATCH 04/32] add version to a dependency in pyproject --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index c82fa27..38a539c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -44,7 +44,7 @@ docs = [ "mkdocs", "mkdocs-material", "mkdocs-jupyter", - "mkdocstrings[python]", + "mkdocstrings[python]>=0.18", "mkdocs-gen-files", "mkdocs-include-markdown-plugin", "jupyterlab", From a4bd4bf2ed6f83a298d62e09bcf26e29d8354ec9 Mon Sep 17 00:00:00 2001 From: SarahAlidoost Date: Tue, 21 Oct 2025 11:25:30 +0200 Subject: [PATCH 05/32] fix init --- src/diffwofost/__init__.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/diffwofost/__init__.py b/src/diffwofost/__init__.py index d4bb9a5..6fa945e 100644 --- a/src/diffwofost/__init__.py +++ b/src/diffwofost/__init__.py @@ -1,9 +1,18 @@ """Documentation about diffwofost.""" import logging +from diffwofost.physical_models.crop import leaf_dynamics +from diffwofost.physical_models.crop import root_dynamics +from diffwofost.physical_models import utils logging.getLogger(__name__).addHandler(logging.NullHandler()) __author__ = "" __email__ = "" -__version__ = "0.1.0" +__version__ = "0.1.1" + +__all__ = [ + "leaf_dynamics", + "root_dynamics", + "utils", +] \ No newline at end of file From b917e83a79a4ebe8e97550de8546706a63c9726d Mon Sep 17 00:00:00 2001 From: SarahAlidoost Date: Tue, 21 Oct 2025 11:25:50 +0200 Subject: [PATCH 06/32] add init files --- src/diffwofost/physical_models/__init__.py | 0 src/diffwofost/physical_models/crop/__init__.py | 0 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 src/diffwofost/physical_models/__init__.py create mode 100644 src/diffwofost/physical_models/crop/__init__.py diff --git a/src/diffwofost/physical_models/__init__.py b/src/diffwofost/physical_models/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/diffwofost/physical_models/crop/__init__.py b/src/diffwofost/physical_models/crop/__init__.py new file mode 100644 index 0000000..e69de29 From 10751e9675d875142a03a436d08d1dbaf11e33f9 Mon Sep 17 00:00:00 2001 From: SarahAlidoost Date: Tue, 21 Oct 2025 11:26:31 +0200 Subject: [PATCH 07/32] add download_button --- docs/download_button/main.html | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 docs/download_button/main.html diff --git a/docs/download_button/main.html b/docs/download_button/main.html new file mode 100644 index 0000000..f223d92 --- /dev/null +++ b/docs/download_button/main.html @@ -0,0 +1,11 @@ +{% extends "base.html" %} + +{% block content %} +{% if page.nb_url %} + + {% include ".icons/material/download.svg" %} + +{% endif %} + +{{ super() }} +{% endblock content %} \ No newline at end of file From 20c435ac5f684534b7e38dc00d8fb536a631d858 Mon Sep 17 00:00:00 2001 From: SarahAlidoost Date: Tue, 21 Oct 2025 17:07:42 +0200 Subject: [PATCH 08/32] fix citation file --- CITATION.cff | 38 +++++++++++++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/CITATION.cff b/CITATION.cff index f39a3a4..c45f27a 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -2,12 +2,40 @@ --- cff-version: "1.2.0" title: "diffwofost" +type: software authors: - - family-names: - given-names: - orcid: "" -date-released: 2025-07-11 -version: "0.1.0" + - given-names: Fakhereh + family-names: Alidoost + email: f.alidoost@esciencecenter.nl + affiliation: Netherlands eScience Center + orcid: 'https://orcid.org/0000-0001-8407-6472' + - given-names: Ioannis + family-names: Athanasiadis + email: ioannis.athanasiadis@wur.nl + affiliation: Wageningen University & Research + orcid: 'https://orcid.org/0000-0003-2764-0078' + - given-names: Michiel + family-names: Kallenberg + email: michiel.kallenberg@wur.nl + affiliation: Wageningen University & Research + orcid: 'https://orcid.org/0000-0002-4661-6674' + - given-names: Ron + family-names: van Bree + email: ron.vanbree@wur.nl + affiliation: Wageningen University & Research + orcid: 'https://orcid.org/0009-0000-6365-6996' + - given-names: Francesco + family-names: Nattino + email: f.nattino@esciencecenter.nl + affiliation: Netherlands eScience Center + orcid: 'https://orcid.org/0000-0003-3286-0139' + - given-names: Allard + family-names: de Wit + email: allard.dewit@wur.nl + affiliation: Wageningen University & Research + orcid: 'https://orcid.org/0000-0002-5517-6404' +date-released: 2025-09-23 +version: "0.1.1" repository-code: "https://github.com/WUR-AI/diffwofost" keywords: - "pytorch" From 2a4ce15041926573b5cc87b863e8937bbbdab107 Mon Sep 17 00:00:00 2001 From: SarahAlidoost Date: Tue, 21 Oct 2025 17:07:59 +0200 Subject: [PATCH 09/32] update readme, add badges --- README.md | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index ca94816..34cf9d5 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,15 @@ + + +[![github repo badge](https://img.shields.io/badge/github-repo-000.svg?logo=github&labelColor=gray&color=blue)](https://github.com/WUR-AI/diffWOFOST) +[![PyPI - Version](https://badge.fury.io/py/diffwofost.svg)](https://img.shields.io/pypi/v/diffwofost) +[![Python package built](https://github.com/WUR-AI/diffWOFOST/actions/workflows/build.yml/badge.svg)](https://github.com/WUR-AI/diffWOFOST/actions/workflows/build.yml) +[![Documentation built](https://github.com/WUR-AI/diffWOFOST/actions/workflows/deploy-documentation.yml/badge.svg)](https://github.com/WUR-AI/diffWOFOST/actions/workflows/deploy-documentation.yml) +[![Code quality](https://github.com/WUR-AI/diffWOFOST/actions/workflows/sonarcloud.yml/badge.svg)](https://github.com/WUR-AI/diffWOFOST/actions/workflows/sonarcloud.yml) + # diffWOFOST +Logo + The python package `diffWOFOST` is a differentiable implementation of WOFOST models using [`torch`](https://pytorch.org/), allowing gradients to flow through the simulations for optimization and data assimilation. @@ -24,20 +34,14 @@ To work with notebooks, you need to install `jupyterlab`: pip install jupyterlab ``` -## Usage - -An example notebooks are provided in the `docs/notebooks` folder. +## Documentation -## PCSE +The documentation for `diffWOFOST` is available at +[https://WUR-AI.github.io/diffWOFOST](https://WUR-AI.github.io/diffWOFOST). -The python implementation of WOFOST is available at -[`PCSE`](https://pcse.readthedocs.io/en/stable/). For more information about the -models, the functional components of PCSE, and documentation have a look at the -following links: +## Acknowledgements -- [Models available in PCSE](https://pcse.readthedocs.io/en/stable/available_models.html#models-available-in-pcse) -- [The Engine](https://pcse.readthedocs.io/en/stable/reference_guide.html#the-engine) -- [PCSE source code](https://github.com/ajwdewit/pcse) -- [PCSE test data](https://github.com/ajwdewit/pcse/tree/master/tests/test_data) -- [PCSE example notebooks](https://github.com/ajwdewit/pcse_notebooks). -- [WOFOST_crop_parameters](https://github.com/ajwdewit/WOFOST_crop_parameters): each branch contains the crop parameters for a specific crop model version +The package `diffWOFOST` is developed in the project +[deltaCrop](https://research-software-directory.org/projects/deltacrop), a +collaboration between Wageningen University & Research and Netherlands eScience +Center. From d1060cfd40241fb22c09e04a3e3a80d5486bf8e5 Mon Sep 17 00:00:00 2001 From: SarahAlidoost Date: Tue, 21 Oct 2025 17:08:24 +0200 Subject: [PATCH 10/32] update doc --- docs/acknowledgements.md | 1 + docs/api_reference.md | 2 +- docs/citation.md | 1 + docs/developer_guide.md | 4 ++-- docs/examples.md | 27 +++++++++------------------ docs/index.md | 2 ++ docs/installation.md | 4 ++-- docs/license.md | 2 +- mkdocs.yml | 2 +- 9 files changed, 20 insertions(+), 25 deletions(-) diff --git a/docs/acknowledgements.md b/docs/acknowledgements.md index e69de29..a232d62 100644 --- a/docs/acknowledgements.md +++ b/docs/acknowledgements.md @@ -0,0 +1 @@ +{% include-markdown "../README.md" start="## Acknowledgements" heading-offset=1%} \ No newline at end of file diff --git a/docs/api_reference.md b/docs/api_reference.md index 5674925..5058a64 100644 --- a/docs/api_reference.md +++ b/docs/api_reference.md @@ -10,6 +10,6 @@ hide: ::: diffwofost.physical_models.crop.root_dynamics.WOFOST_Root_Dynamics -## **Utility** +## **Utility (under development)** ::: diffwofost.physical_models.utils.EngineTestHelper diff --git a/docs/citation.md b/docs/citation.md index e69de29..610e7f1 100644 --- a/docs/citation.md +++ b/docs/citation.md @@ -0,0 +1 @@ +zenodo doi will be added. \ No newline at end of file diff --git a/docs/developer_guide.md b/docs/developer_guide.md index 6868c6c..d231f84 100644 --- a/docs/developer_guide.md +++ b/docs/developer_guide.md @@ -31,7 +31,7 @@ review from another team member before merging your pull request. - The testing framework used is [PyTest](https://pytest.org) - The project uses [GitHub action workflows](https://docs.github.com/en/actions) to automatically run tests on GitHub infrastructure against multiple Python - versions. Workflows can be found in [`.github/workflows`](.github/workflows/) + versions. Workflows can be found in `.github/workflows` directory. - [Relevant section in the guide](https://guide.esciencecenter.nl/#/best_practices/language_guides/python?id=testing) - To run the tests locally, you need to make sure that you have installed the @@ -68,7 +68,7 @@ ruff format --check . --diff ## Documentation page -- Documentation should be put in the [`docs/`](docs/) directory. +- Documentation should be put in the `docs/` directory. - We recommend writing the documentation using Google style docstrings. - The documentation is set up with the [MkDocs](https://www.mkdocs.org/). - `.mkdocs.yml` is the [MkDocs](https://www.mkdocs.org/) configuration file. When MkDocs is building the documentation this package and its development dependencies are installed so the API reference can be rendered. diff --git a/docs/examples.md b/docs/examples.md index 8580013..8e7a83a 100644 --- a/docs/examples.md +++ b/docs/examples.md @@ -2,24 +2,15 @@ ## Hybrid modelling -We provide an example notebook showing hybrid modelling with `diffWOFOST`. - -=== "Open the notebook in Colab" - - You can open and run the notebook directly in Google Colab by clicking the badge below: - - [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)][colab_link] - -=== "Access the source notebook" - - You can access the source code of the notebook on GitHub by clicking the badge below: - - [![Access the source code](https://img.shields.io/badge/github-repo-000.svg?logo=github&labelColor=gray&color=blue)][source_link] - -=== "View the notebook" - - You can view the full notebook [here](./notebooks/optimization.ipynb). - +We provide an example notebook showing hybrid modelling with `diffWOFOST`. To +get familiar with the concepts and implementation, check out `Introduction` in +the documentation. + +| | | +|--------|-----------------------------------------------------| +| Open the notebook in Colab | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)][colab_link] | +| Access the source code | [![Access the source code](https://img.shields.io/badge/GitHub_Repository-000.svg?logo=github&labelColor=gray&color=blue)][source_link] | +| View the notebook | [![here](https://img.shields.io/badge/View_Notebook-orange.svg?logo=jupyter&labelColor=gray)](./notebooks/optimization.ipynb) | [colab_link]: https://colab.research.google.com/github/WUR-AI/diffWOFOST/blob/main/docs/notebooks/optimization.ipynb diff --git a/docs/index.md b/docs/index.md index dd78cfd..071398c 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,5 +1,7 @@ # +{% include-markdown "../README.md" end="# diffWOFOST" %} + ## diffWOFOST: Differentiable WOFOST The package diffWOFOST contains a differentiable implementation of the WOFOST diff --git a/docs/installation.md b/docs/installation.md index fb31fdc..b797100 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -21,5 +21,5 @@ cd diffWOFOST pip install -e .[dev] ``` -If you are a contributer, please follwo the instructions in the `contribution -guide` in the documentation. +If you are a contributer, follow the instructions in the `How to Contribute` in +the documentation. diff --git a/docs/license.md b/docs/license.md index 8f249ec..92414a9 100644 --- a/docs/license.md +++ b/docs/license.md @@ -1,3 +1,3 @@ # -{% include-markdown "https://raw.githubusercontent.com/WUR-AI/diffWOFOST/refs/heads/main/LICENSE" %} +{% include-markdown "../LICENSE" %} diff --git a/mkdocs.yml b/mkdocs.yml index f011e7d..8af90da 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -12,7 +12,7 @@ nav: - Installation: installation.md - How to run a model: run_model.md - Example notebooks: examples.md - - Geeting involved in development: + - How to Contribute: - Contributing guide: CONTRIBUTING.md - Developer guide: developer_guide.md - API Reference: api_reference.md From 90cd9b24ae6342b98a9d0d85d1e91d2bd0e3be84 Mon Sep 17 00:00:00 2001 From: SarahAlidoost Date: Tue, 21 Oct 2025 17:08:42 +0200 Subject: [PATCH 11/32] fix init file --- src/diffwofost/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/diffwofost/__init__.py b/src/diffwofost/__init__.py index 6fa945e..6b62816 100644 --- a/src/diffwofost/__init__.py +++ b/src/diffwofost/__init__.py @@ -1,9 +1,9 @@ """Documentation about diffwofost.""" import logging +from diffwofost.physical_models import utils from diffwofost.physical_models.crop import leaf_dynamics from diffwofost.physical_models.crop import root_dynamics -from diffwofost.physical_models import utils logging.getLogger(__name__).addHandler(logging.NullHandler()) From ef11e2d417c657cb32260e7b42ae5a5902cdd0da Mon Sep 17 00:00:00 2001 From: SarahAlidoost Date: Tue, 21 Oct 2025 17:09:01 +0200 Subject: [PATCH 12/32] fix docstring in root_dynamics --- .../physical_models/crop/root_dynamics.py | 152 +++++++++--------- 1 file changed, 78 insertions(+), 74 deletions(-) diff --git a/src/diffwofost/physical_models/crop/root_dynamics.py b/src/diffwofost/physical_models/crop/root_dynamics.py index 81af040..811684b 100644 --- a/src/diffwofost/physical_models/crop/root_dynamics.py +++ b/src/diffwofost/physical_models/crop/root_dynamics.py @@ -1,8 +1,12 @@ +from datetime import datetime import torch from pcse.base import ParamTemplate from pcse.base import RatesTemplate from pcse.base import SimulationObject from pcse.base import StatesTemplate +from pcse.base.parameter_providers import ParameterProvider +from pcse.base.variablekiosk import VariableKiosk +from pcse.base.weather import WeatherDataContainer from pcse.decorators import prepare_rates from pcse.decorators import prepare_states from pcse.traitlets import Any @@ -28,44 +32,34 @@ class WOFOST_Root_Dynamics(SimulationObject): **Simulation parameters** - ======= ============================================= ======= ============ - Name Description Type Unit - ======= ============================================= ======= ============ - RDI Initial rooting depth SCr cm - RRI Daily increase in rooting depth SCr |cm day-1| - RDMCR Maximum rooting depth of the crop SCR cm - RDMSOL Maximum rooting depth of the soil SSo cm - TDWI Initial total crop dry weight SCr |kg ha-1| - IAIRDU Presence of air ducts in the root (1) or SCr - - not (0) - RDRRTB Relative death rate of roots as a function TCr - - of development stage - ======= ============================================= ======= ============ - + | Name | Description | Type | Unit | + |--------|-----------------------------------------------------|------|-----------| + | RDI | Initial rooting depth | SCr | cm | + | RRI | Daily increase in rooting depth | SCr | cm day⁻¹ | + | RDMCR | Maximum rooting depth of the crop | SCR | cm | + | RDMSOL | Maximum rooting depth of the soil | SSo | cm | + | TDWI | Initial total crop dry weight | SCr | kg ha⁻¹ | + | IAIRDU | Presence of air ducts in the root (1) or not (0) | SCr | - | + | RDRRTB | Relative death rate of roots as a function of development stage | TCr | - | **State variables** - ======= ================================================= ==== ============ - Name Description Pbl Unit - ======= ================================================= ==== ============ - RD Current rooting depth Y cm - RDM Maximum attainable rooting depth at the minimum N cm - of the soil and crop maximum rooting depth - WRT Weight of living roots Y |kg ha-1| - DWRT Weight of dead roots N |kg ha-1| - TWRT Total weight of roots Y |kg ha-1| - ======= ================================================= ==== ============ + | Name | Description | Pbl | Unit | + |------|------------------------------------------------------------------------------|-----|----------| + | RD | Current rooting depth | Y | cm | + | RDM | Maximum attainable rooting depth at the minimum of the soil and crop maximum rooting depth | N | cm | + | WRT | Weight of living roots | Y | kg ha⁻¹ | + | DWRT | Weight of dead roots | N | kg ha⁻¹ | + | TWRT | Total weight of roots | Y | kg ha⁻¹ | **Rate variables** - ======= ================================================= ==== ============ - Name Description Pbl Unit - ======= ================================================= ==== ============ - RR Growth rate root depth N cm - GRRT Growth rate root biomass N |kg ha-1 d-1| - DRRT Death rate root biomass N |kg ha-1 d-1| - GWRT Net change in root biomass N |kg ha-1 d-1| - ======= ================================================= ==== ============ + | Name | Description | Pbl | Unit | + |------|-----------------------------|-----|--------------| + | RR | Growth rate root depth | N | cm | + | GRRT | Growth rate root biomass | N | kg ha⁻¹ d⁻¹ | + | DRRT | Death rate root biomass | N | kg ha⁻¹ d⁻¹ | + | GWRT | Net change in root biomass | N | kg ha⁻¹ d⁻¹ | **Signals send or handled** @@ -73,22 +67,21 @@ class WOFOST_Root_Dynamics(SimulationObject): **External dependencies:** - ======= =================================== ================= ============ - Name Description Provided by Unit - ======= =================================== ================= ============ - DVS Crop development stage DVS_Phenology - - DMI Total dry matter CropSimulation |kg ha-1 d-1| - increase - FR Fraction biomass to roots DVS_Partitioning - - ======= =================================== ================= ============ + | Name | Description | Provided by | Unit | + |------|---------------------------|------------------|--------------| + | DVS | Crop development stage | DVS_Phenology | - | + | DMI | Total dry matter increase | CropSimulation | kg ha⁻¹ d⁻¹ | + | FR | Fraction biomass to roots | DVS_Partitioning | - | **Outputs:** - - RD, TWRT - """ + | Name | Description | Provided by | Unit | + |------|-------------------------|------------------|--------------| + | RD | Current rooting depth | Y | cm | + | TWRT | Total weight of roots | Y | kg ha⁻¹ | + + **IMPORTANT NOTICE** - """ - IMPORTANT NOTICE Currently root development is linear and depends only on the fraction of assimilates send to the roots (FR) and not on the amount of assimilates itself. This means that roots also grow through the winter when there is no assimilation due to low @@ -110,7 +103,7 @@ class WOFOST_Root_Dynamics(SimulationObject): We conclude that our current knowledge on root development is insufficient to propose a better and more biophysical approach to root development in WOFOST. - """ + """ # noqa: E501 class Parameters(ParamTemplate): RDI = Any(default_value=[torch.tensor(-99.0, dtype=DTYPE)]) @@ -134,13 +127,24 @@ class StateVariables(StatesTemplate): DWRT = Any(default_value=[torch.tensor(-99.0, dtype=DTYPE)]) TWRT = Any(default_value=[torch.tensor(-99.0, dtype=DTYPE)]) - def initialize(self, day, kiosk, parvalues): + def initialize(self, + day: datetime.date, + kiosk: VariableKiosk, + parvalues: ParameterProvider + ) -> None: """Initialize the model. - :param day: start date of the simulation - :param kiosk: variable kiosk of this PCSE instance - :param parvalues: `ParameterProvider` object providing parameters as - key/value pairs + Args: + day (datetime.date): The starting date of the simulation. + kiosk (VariableKiosk): A container for registering and publishing + (internal and external) state variables. See PCSE documentation for + details. + parvalues (ParameterProvider): A dictionary-like container holding + all parameter sets (crop, soil, site) as key/value. The values are + arrays or scalars. See PCSE documentation for details. + + Returns: + None: This method initializes the model and does not return anything. """ self.params = self.Parameters(parvalues) self.rates = self.RateVariables(kiosk, publish=["DRRT", "GRRT"]) @@ -164,8 +168,19 @@ def initialize(self, day, kiosk, parvalues): ) @prepare_rates - def calc_rates(self, day, drv): - """Calculate the rates of change of the state variables.""" + def calc_rates(self, day: datetime.date, drv: WeatherDataContainer) -> None: + """Calculate the rates of change of the state variables. + + Args: + day (datetime.date): The current date of the simulation. + drv (WeatherDataContainer): A dictionary-like container holding + weather data elements as key/value. The values are + arrays or scalars. See PCSE documentation for details. + + Returns: + None: This method calculates the rates and does not return anything. + + """ p = self.params r = self.rates s = self.states @@ -191,8 +206,17 @@ def calc_rates(self, day, drv): r.RR = r.RR * mask @prepare_states - def integrate(self, day, delt=1.0): - """Integrate the state variables using the rates of change.""" + def integrate(self, day: datetime.date, delt=1.0): + """Integrate the state variables using the rates of change. + + Args: + day (datetime.date): The current date of the simulation. + delt (float, optional): The time step for integration. Defaults to 1.0. + + Returns: + None: This method integrates the states and does not return anything. + + """ rates = self.rates states = self.states @@ -207,23 +231,3 @@ def integrate(self, day, delt=1.0): # New root depth states.RD = states.RD + rates.RR - - @prepare_states - def _set_variable_WRT(self, nWRT): # FIXEME - """Updates the value of WRT to to the new value provided as input. - - Related state variables will be updated as well and the increments - to all adjusted state variables will be returned as a dict. - """ - states = self.states - - # Store old values of states - oWRT = states.WRT - oTWRT = states.TWRT - - # Apply new root weight and adjust total (dead + live) root weight - states.WRT = nWRT - states.TWRT = states.WRT + states.DWRT - - increments = {"WRT": states.WRT - oWRT, "TWLRT": states.TWRT - oTWRT} - return increments From 93aa7a10b2801454a21d08bfce5b4a7ff779aa8e Mon Sep 17 00:00:00 2001 From: SarahAlidoost Date: Tue, 21 Oct 2025 17:16:14 +0200 Subject: [PATCH 13/32] fix ruff formatting --- src/diffwofost/__init__.py | 2 +- src/diffwofost/physical_models/crop/root_dynamics.py | 10 ++++------ 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/diffwofost/__init__.py b/src/diffwofost/__init__.py index 6b62816..52f9e0c 100644 --- a/src/diffwofost/__init__.py +++ b/src/diffwofost/__init__.py @@ -15,4 +15,4 @@ "leaf_dynamics", "root_dynamics", "utils", -] \ No newline at end of file +] diff --git a/src/diffwofost/physical_models/crop/root_dynamics.py b/src/diffwofost/physical_models/crop/root_dynamics.py index 811684b..6eae1f9 100644 --- a/src/diffwofost/physical_models/crop/root_dynamics.py +++ b/src/diffwofost/physical_models/crop/root_dynamics.py @@ -103,7 +103,7 @@ class WOFOST_Root_Dynamics(SimulationObject): We conclude that our current knowledge on root development is insufficient to propose a better and more biophysical approach to root development in WOFOST. - """ # noqa: E501 + """ # noqa: E501 class Parameters(ParamTemplate): RDI = Any(default_value=[torch.tensor(-99.0, dtype=DTYPE)]) @@ -127,11 +127,9 @@ class StateVariables(StatesTemplate): DWRT = Any(default_value=[torch.tensor(-99.0, dtype=DTYPE)]) TWRT = Any(default_value=[torch.tensor(-99.0, dtype=DTYPE)]) - def initialize(self, - day: datetime.date, - kiosk: VariableKiosk, - parvalues: ParameterProvider - ) -> None: + def initialize( + self, day: datetime.date, kiosk: VariableKiosk, parvalues: ParameterProvider + ) -> None: """Initialize the model. Args: From 12a948d2c16de8f0dea5cf6d6650c19b3ddb8d88 Mon Sep 17 00:00:00 2001 From: SarahAlidoost Date: Wed, 22 Oct 2025 10:50:40 +0200 Subject: [PATCH 14/32] fix docsting --- src/diffwofost/physical_models/crop/root_dynamics.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/diffwofost/physical_models/crop/root_dynamics.py b/src/diffwofost/physical_models/crop/root_dynamics.py index 6eae1f9..2c0f03a 100644 --- a/src/diffwofost/physical_models/crop/root_dynamics.py +++ b/src/diffwofost/physical_models/crop/root_dynamics.py @@ -166,12 +166,12 @@ def initialize( ) @prepare_rates - def calc_rates(self, day: datetime.date, drv: WeatherDataContainer) -> None: + def calc_rates(self, day: datetime.date = None, drv: WeatherDataContainer = None) -> None: """Calculate the rates of change of the state variables. Args: - day (datetime.date): The current date of the simulation. - drv (WeatherDataContainer): A dictionary-like container holding + day (datetime.date, optional): The current date of the simulation. + drv (WeatherDataContainer, optional): A dictionary-like container holding weather data elements as key/value. The values are arrays or scalars. See PCSE documentation for details. @@ -204,11 +204,11 @@ def calc_rates(self, day: datetime.date, drv: WeatherDataContainer) -> None: r.RR = r.RR * mask @prepare_states - def integrate(self, day: datetime.date, delt=1.0): + def integrate(self, day: datetime.date = None, delt=1.0): """Integrate the state variables using the rates of change. Args: - day (datetime.date): The current date of the simulation. + day (datetime.date, optional): The current date of the simulation. delt (float, optional): The time step for integration. Defaults to 1.0. Returns: From 9450f372e6ca6f67bf9799eb0fe407f5bc019460 Mon Sep 17 00:00:00 2001 From: SarahAlidoost Date: Wed, 22 Oct 2025 10:59:27 +0200 Subject: [PATCH 15/32] update docs, add reference section, fix link in license --- CITATION.cff | 24 ++++++++++++------------ LICENSE | 5 +++-- docs/examples.md | 8 ++++---- mkdocs.yml | 1 + 4 files changed, 20 insertions(+), 18 deletions(-) diff --git a/CITATION.cff b/CITATION.cff index c45f27a..9b8d87e 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -1,19 +1,19 @@ # YAML 1.2 --- cff-version: "1.2.0" -title: "diffwofost" +title: "diffwofost: A differentiable implementation of the WOFOST crop growth model" type: software authors: - - given-names: Fakhereh + - given-names: Fakhereh (Sarah) family-names: Alidoost email: f.alidoost@esciencecenter.nl affiliation: Netherlands eScience Center orcid: 'https://orcid.org/0000-0001-8407-6472' - - given-names: Ioannis - family-names: Athanasiadis - email: ioannis.athanasiadis@wur.nl - affiliation: Wageningen University & Research - orcid: 'https://orcid.org/0000-0003-2764-0078' + - given-names: Francesco + family-names: Nattino + email: f.nattino@esciencecenter.nl + affiliation: Netherlands eScience Center + orcid: 'https://orcid.org/0000-0003-3286-0139' - given-names: Michiel family-names: Kallenberg email: michiel.kallenberg@wur.nl @@ -24,11 +24,11 @@ authors: email: ron.vanbree@wur.nl affiliation: Wageningen University & Research orcid: 'https://orcid.org/0009-0000-6365-6996' - - given-names: Francesco - family-names: Nattino - email: f.nattino@esciencecenter.nl - affiliation: Netherlands eScience Center - orcid: 'https://orcid.org/0000-0003-3286-0139' + - given-names: Ioannis + family-names: Athanasiadis + email: ioannis.athanasiadis@wur.nl + affiliation: Wageningen University & Research + orcid: 'https://orcid.org/0000-0003-2764-0078' - given-names: Allard family-names: de Wit email: allard.dewit@wur.nl diff --git a/LICENSE b/LICENSE index 1c51bed..dd3326a 100644 --- a/LICENSE +++ b/LICENSE @@ -2,12 +2,13 @@ Licensed under the EUPL, Version 1.1 or as soon they will be approved by the European Commission - subsequent -versions of the EUPL (the "Licence") +versions of the EUPL (the "Licence"). You may not use this work except in compliance with the Licence. You may obtain a copy of the Licence at -http://ec.europa.eu/idabc/eup +[https://interoperable-europe.ec.europa.eu/licence/european-union-public-licence-version-11-eupl](https://interoperable-europe.ec.europa.eu/licence/european-union-public-licence-version-11-eupl). + Unless required by applicable law or agreed to in writing, software distributed under the Licence is distributed on an "AS IS" basis, diff --git a/docs/examples.md b/docs/examples.md index 8e7a83a..13ac79e 100644 --- a/docs/examples.md +++ b/docs/examples.md @@ -1,10 +1,10 @@ # -## Hybrid modelling +## Optimization with diffWOFOST -We provide an example notebook showing hybrid modelling with `diffWOFOST`. To -get familiar with the concepts and implementation, check out `Introduction` in -the documentation. +We provide an example notebook showing optimization of models' parameters with +`diffWOFOST`. To get familiar with the concepts and implementation, check out +`Introduction` in the documentation. | | | |--------|-----------------------------------------------------| diff --git a/mkdocs.yml b/mkdocs.yml index 8af90da..1ef6461 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -8,6 +8,7 @@ nav: - Citation: citation.md - License: license.md - Acknowledgements: acknowledgements.md + - References: references.md - Getting started: - Installation: installation.md - How to run a model: run_model.md From cbb819310539d67b228a95c5bcf1d3127e929f0a Mon Sep 17 00:00:00 2001 From: SarahAlidoost Date: Wed, 22 Oct 2025 14:59:13 +0200 Subject: [PATCH 16/32] add reference file --- docs/references.md | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 docs/references.md diff --git a/docs/references.md b/docs/references.md new file mode 100644 index 0000000..5464fdb --- /dev/null +++ b/docs/references.md @@ -0,0 +1,11 @@ +# + +Here are some useful references related to `WOFOST` and `PCSE`. If you want to +cite the `diffWOFOST` package in your research, please use the software doi. + +- [WOFOST (WOrld FOod STudies)](https://www.wur.nl/en/research-results/research-institutes/environmental-research/facilities-tools/software-models-and-databases/wofost.htm) +- [A gentle introduction to WOFOST](https://www.wur.nl/en/show/a-gentle-introduction-to-wofost.htm) +- [PCSE/ WOFOST documentation](http://pcse.readthedocs.io/) +- [Jupyter notebooks demonstrating the use of PCSE/WOFOST](https://github.com/ajwdewit/pcse_notebooks) +- [PCSE GitHub repository](https://github.com/ajwdewit/pcse) +- [DeltaCrop project](https://research-software-directory.org/projects/deltacrop) From eb3f404142797b392d202976c337a317d50cd843 Mon Sep 17 00:00:00 2001 From: SarahAlidoost Date: Wed, 22 Oct 2025 15:46:26 +0200 Subject: [PATCH 17/32] update docs --- docs/api_reference.md | 5 +++++ docs/developer_guide.md | 2 +- docs/examples.md | 19 ++++++++++++++----- docs/index.md | 6 ++++++ docs/run_model.md | 2 +- 5 files changed, 27 insertions(+), 7 deletions(-) diff --git a/docs/api_reference.md b/docs/api_reference.md index 5058a64..ebb4a1b 100644 --- a/docs/api_reference.md +++ b/docs/api_reference.md @@ -6,6 +6,11 @@ hide: ## **Crop modules** +!!! note + At the moment only two modules of `leaf_dynamics` and `root_dynamics` are + differentiable w.r.t two parameters of `SPAN` and `TDWI`. But the package is under + continuous development. So make sure that you install the latest version. + ::: diffwofost.physical_models.crop.leaf_dynamics.WOFOST_Leaf_Dynamics ::: diffwofost.physical_models.crop.root_dynamics.WOFOST_Root_Dynamics diff --git a/docs/developer_guide.md b/docs/developer_guide.md index d231f84..400da8f 100644 --- a/docs/developer_guide.md +++ b/docs/developer_guide.md @@ -2,7 +2,7 @@ If you are a developer wanting to contribute to the diffwofost package, this guide will help you get started. First check out the contribution guidelines in -[Contributing guide](CONTRIBUTING.md) and the [project setup](project_setup.md) +[Contributing guide](CONTRIBUTING.md) and the [Project setup](project_setup.md) to get familiar with the package structure and development practices. ## Installation in development mode diff --git a/docs/examples.md b/docs/examples.md index 13ac79e..34e9f00 100644 --- a/docs/examples.md +++ b/docs/examples.md @@ -6,11 +6,20 @@ We provide an example notebook showing optimization of models' parameters with `diffWOFOST`. To get familiar with the concepts and implementation, check out `Introduction` in the documentation. -| | | -|--------|-----------------------------------------------------| -| Open the notebook in Colab | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)][colab_link] | -| Access the source code | [![Access the source code](https://img.shields.io/badge/GitHub_Repository-000.svg?logo=github&labelColor=gray&color=blue)][source_link] | -| View the notebook | [![here](https://img.shields.io/badge/View_Notebook-orange.svg?logo=jupyter&labelColor=gray)](./notebooks/optimization.ipynb) | +| Open the notebook | Access the source | View the notebook | +|-------|------------|---------------| +| [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)][colab_link] | [![Access the source code](https://img.shields.io/badge/GitHub_Repository-000.svg?logo=github&labelColor=gray&color=blue)][source_link] | [![here](https://img.shields.io/badge/View_Notebook-orange.svg?logo=jupyter&labelColor=gray)](./notebooks/optimization.ipynb) | + +!!! note + When calculating gradients, it is important to ensure that the predicted + physical parameters are within realistic bounds regarding the crop and + environmental conditions. + + Also, when calculating gradients of an output w.r.t. parameters, it would be + good to know in advance how the parameters in a model influence the outputs. + If a parameter has little to no influence on an output, the gradient of the + output w.r.t the parameter will be close to zero, which may not provide + useful information for optimization. [colab_link]: https://colab.research.google.com/github/WUR-AI/diffWOFOST/blob/main/docs/notebooks/optimization.ipynb diff --git a/docs/index.md b/docs/index.md index 071398c..11e5a0f 100644 --- a/docs/index.md +++ b/docs/index.md @@ -100,6 +100,12 @@ The package is structured as follows: ├── crop/ # differentiable implementation of each crop model │ ├── leaf_dynamics.py │ ├── root_dynamics.py + │ ├── ... ├── soil/ ├── utils.py # helpers ``` + +!!! note + At the moment only two modules of `leaf_dynamics` and `root_dynamics` are + differentiable w.r.t two parameters of `SPAN` and `TDWI`. But the package is under + continuous development. So make sure that you install the latest version. diff --git a/docs/run_model.md b/docs/run_model.md index b9458b5..be8a2ca 100644 --- a/docs/run_model.md +++ b/docs/run_model.md @@ -10,7 +10,7 @@ PCSE.ipynb](https://github.com/ajwdewit/pcse_notebooks/blob/master/01%20Getting% and [02 Running with custom input data.ipynb ](https://github.com/ajwdewit/pcse_notebooks/blob/master/02%20Running%20with%20custom%20input%20data.ipynb). -in a nutshell, we can run a model for example `leaf_dynamics` using PCSE as: +In a nutshell, we can run a model, for example, `leaf_dynamics` using PCSE as: ```python from diffwofost.physical_models.utils import EngineTestHelper From 552be22694bd3fceb546a3bee5ac665c9c6a1338 Mon Sep 17 00:00:00 2001 From: SarahAlidoost Date: Wed, 22 Oct 2025 15:46:40 +0200 Subject: [PATCH 18/32] fix sonar badge --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 34cf9d5..0f8f89d 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ [![PyPI - Version](https://badge.fury.io/py/diffwofost.svg)](https://img.shields.io/pypi/v/diffwofost) [![Python package built](https://github.com/WUR-AI/diffWOFOST/actions/workflows/build.yml/badge.svg)](https://github.com/WUR-AI/diffWOFOST/actions/workflows/build.yml) [![Documentation built](https://github.com/WUR-AI/diffWOFOST/actions/workflows/deploy-documentation.yml/badge.svg)](https://github.com/WUR-AI/diffWOFOST/actions/workflows/deploy-documentation.yml) -[![Code quality](https://github.com/WUR-AI/diffWOFOST/actions/workflows/sonarcloud.yml/badge.svg)](https://github.com/WUR-AI/diffWOFOST/actions/workflows/sonarcloud.yml) +[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=WUR-AI_diffWOFOST&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=WUR-AI_diffWOFOST) # diffWOFOST From c355bd7c2d956f50f3e2125bb3347cef9a644b2c Mon Sep 17 00:00:00 2001 From: SarahAlidoost Date: Mon, 27 Oct 2025 10:37:50 +0100 Subject: [PATCH 19/32] fix docstring of leaf_dynamics --- .../physical_models/crop/leaf_dynamics.py | 215 ++++++++++-------- .../physical_models/crop/root_dynamics.py | 2 +- 2 files changed, 123 insertions(+), 94 deletions(-) diff --git a/src/diffwofost/physical_models/crop/leaf_dynamics.py b/src/diffwofost/physical_models/crop/leaf_dynamics.py index 8e24d1a..207054b 100644 --- a/src/diffwofost/physical_models/crop/leaf_dynamics.py +++ b/src/diffwofost/physical_models/crop/leaf_dynamics.py @@ -1,10 +1,14 @@ """Leaf dynamics for the WOFOST crop model.""" +import datetime import torch from pcse.base import ParamTemplate from pcse.base import RatesTemplate from pcse.base import SimulationObject from pcse.base import StatesTemplate +from pcse.base.parameter_providers import ParameterProvider +from pcse.base.variablekiosk import VariableKiosk +from pcse.base.weather import WeatherDataContainer from pcse.decorators import prepare_rates from pcse.decorators import prepare_states from pcse.traitlets import Any @@ -29,89 +33,73 @@ class WOFOST_Leaf_Dynamics(SimulationObject): Senescense of the leaves can occur as a result of physiological age, drought stress or self-shading. - *Simulation parameters* (provide in cropdata dictionary) - - ======= ============================================= ======= ============ - Name Description Type Unit - ======= ============================================= ======= ============ - RGRLAI Maximum relative increase in LAI. SCr ha ha-1 d-1 - SPAN Life span of leaves growing at 35 Celsius SCr |d| - TBASE Lower threshold temp. for ageing of leaves SCr |C| - PERDL Max. relative death rate of leaves due to SCr - water stress - TDWI Initial total crop dry weight SCr |kg ha-1| - KDIFTB Extinction coefficient for diffuse visible TCr - light as function of DVS - SLATB Specific leaf area as a function of DVS TCr |ha kg-1| - ======= ============================================= ======= ============ - - *State variables* - - ======= ================================================= ==== ============ - Name Description Pbl Unit - ======= ================================================= ==== ============ - LV Leaf biomass per leaf class N |kg ha-1| - SLA Specific leaf area per leaf class N |ha kg-1| - LVAGE Leaf age per leaf class N |d| - LVSUM Sum of LV N |kg ha-1| - LAIEM LAI at emergence N - - LASUM Total leaf area as sum of LV*SLA, N - - not including stem and pod area N - LAIEXP LAI value under theoretical exponential growth N - - LAIMAX Maximum LAI reached during growth cycle N - - LAI Leaf area index, including stem and pod area Y - - WLV Dry weight of living leaves Y |kg ha-1| - DWLV Dry weight of dead leaves N |kg ha-1| - TWLV Dry weight of total leaves (living + dead) Y |kg ha-1| - ======= ================================================= ==== ============ - - - *Rate variables* - - ======= ================================================= ==== ============ - Name Description Pbl Unit - ======= ================================================= ==== ============ - GRLV Growth rate leaves N |kg ha-1 d-1| - DSLV1 Death rate leaves due to water stress N |kg ha-1 d-1| - DSLV2 Death rate leaves due to self-shading N |kg ha-1 d-1| - DSLV3 Death rate leaves due to frost kill N |kg ha-1 d-1| - DSLV Maximum of DLSV1, DSLV2, DSLV3 N |kg ha-1 d-1| - DALV Death rate leaves due to aging. N |kg ha-1 d-1| - DRLV Death rate leaves as a combination of DSLV and N |kg ha-1 d-1| - DALV - SLAT Specific leaf area for current time step, N |ha kg-1| - adjusted for source/sink limited leaf expansion - rate. - FYSAGE Increase in physiological leaf age N - - GLAIEX Sink-limited leaf expansion rate (exponential N |ha ha-1 d-1| - curve) - GLASOL Source-limited leaf expansion rate (biomass N |ha ha-1 d-1| - increase) - ======= ================================================= ==== ============ - - - *External dependencies:* - - ======== ============================== =============================== =========== - Name Description Provided by Unit - ======== ============================== =============================== =========== - DVS Crop development stage DVS_Phenology - - FL Fraction biomass to leaves DVS_Partitioning - - FR Fraction biomass to roots DVS_Partitioning - - SAI Stem area index WOFOST_Stem_Dynamics - - PAI Pod area index WOFOST_Storage_Organ_Dynamics - - TRA Transpiration rate Evapotranspiration |cm day-1| ? - TRAMX Maximum transpiration rate Evapotranspiration |cm day-1| ? - ADMI Above-ground dry matter CropSimulation |kg ha-1 d-1| - increase - RFTRA Reduction factor for Y - - transpiration (wat & ox) - RF_FROST Reduction factor frost kill FROSTOL(optional) - - ======== ============================== =============================== =========== - - *Outputs:* - LAI, TWLV - """ + **Simulation parameters** (provide in cropdata dictionary) + + | Name | Description | Type | Unit | + |--------|------------------------------------------------------------------ |------|------------| + | RGRLAI | Maximum relative increase in LAI. |SCr | ha ha⁻¹ d⁻¹| + | SPAN | Life span of leaves growing at 35 Celsius |SCr | d | + | TBASE | Lower threshold temp. for ageing of leaves |SCr | C | + | PERDL | Max. relative death rate of leaves due to water stress |SCr | | + | TDWI | Initial total crop dry weight |SCr | kg ha⁻¹ | + | KDIFTB | Extinction coefficient for diffuse visible light as function of DVS|TCr | | + | SLATB | Specific leaf area as a function of DVS |TCr | ha kg⁻¹ | + + **State variables** + + | Name | Description | Pbl | Unit | + |--------|-------------------------------------------------------|------|-------------| + | LV | Leaf biomass per leaf class | N | kg ha⁻¹ | + | SLA | Specific leaf area per leaf class | N | ha kg⁻¹ | + | LVAGE | Leaf age per leaf class | N | d | + | LVSUM | Sum of LV | N | kg ha⁻¹ | + | LAIEM | LAI at emergence | N | - | + | LASUM | Total leaf area as sum of LV*SLA, not including stem and pod area | N | - | + | LAIEXP | LAI value under theoretical exponential growth | N | - | + | LAIMAX | Maximum LAI reached during growth cycle | N | - | + | LAI | Leaf area index, including stem and pod area | Y | - | + | WLV | Dry weight of living leaves | Y | kg ha⁻¹ | + | DWLV | Dry weight of dead leaves | N | kg ha⁻¹ | + | TWLV | Dry weight of total leaves (living + dead) | Y | kg ha⁻¹ | + + **Rate variables** + + | Name | Description | Pbl | Unit | + |--------|-------------------------------------------------------|------|---------------| + | GRLV | Growth rate leaves | N | kg ha⁻¹ d⁻¹ | + | DSLV1 | Death rate leaves due to water stress | N | kg ha⁻¹ d⁻¹ | + | DSLV2 | Death rate leaves due to self-shading | N | kg ha⁻¹ d⁻¹ | + | DSLV3 | Death rate leaves due to frost kill | N | kg ha⁻¹ d⁻¹ | + | DSLV | Maximum of DSLV1, DSLV2, DSLV3 | N | kg ha⁻¹ d⁻¹ | + | DALV | Death rate leaves due to aging | N | kg ha⁻¹ d⁻¹ | + | DRLV | Death rate leaves as a combination of DSLV and DALV | N | kg ha⁻¹ d⁻¹ | + | SLAT | Specific leaf area for current time step, adjusted for source/sink limited leaf expansion rate | N | ha kg⁻¹ | + | FYSAGE | Increase in physiological leaf age | N | - | + | GLAIEX | Sink-limited leaf expansion rate (exponential curve) | N | ha ha⁻¹ d⁻¹ | + | GLASOL | Source-limited leaf expansion rate (biomass increase) | N | ha ha⁻¹ d⁻¹ | + + **External dependencies** + + | Name | Description | Provided by | Unit | + |-----------|-----------------------------------|--------------------------------|----------------| + | DVS | Crop development stage | DVS_Phenology | - | + | FL | Fraction biomass to leaves | DVS_Partitioning | - | + | FR | Fraction biomass to roots | DVS_Partitioning | - | + | SAI | Stem area index | WOFOST_Stem_Dynamics | - | + | PAI | Pod area index | WOFOST_Storage_Organ_Dynamics | - | + | TRA | Transpiration rate | Evapotranspiration | cm day⁻¹ ? | + | TRAMX | Maximum transpiration rate | Evapotranspiration | cm day⁻¹ ? | + | ADMI | Above-ground dry matter increase | CropSimulation | kg ha⁻¹ d⁻¹ | + | RFTRA | Reduction factor for transpiration (water & oxygen) | Y | - | + | RF_FROST | Reduction factor frost kill | FROSTOL (optional) | - | + + **Outputs** + + | Name | Description | Pbl | Unit | + |--------|-------------------------------------------------------|------|-------------| + | LAI | Leaf area index, including stem and pod area | Y | - | + | TWLV | Dry weight of total leaves (living + dead) | Y | kg ha⁻¹ | + """ # noqa: E501 # The following parameters are used to initialize and control the arrays that store information # on the leaf classes during the time integration: leaf area, age, and biomass. @@ -153,13 +141,23 @@ class RateVariables(RatesTemplate): GLAIEX = Any(default_value=torch.tensor(0.0, dtype=DTYPE)) GLASOL = Any(default_value=torch.tensor(0.0, dtype=DTYPE)) - def initialize(self, day, kiosk, parvalues): + def initialize( + self, day: datetime.date, kiosk: VariableKiosk, parvalues: ParameterProvider + ) -> None: """Initialize the WOFOST_Leaf_Dynamics simulation object. - :param day: start date of the simulation - :param kiosk: variable kiosk of this PCSE instance - :param parvalues: `ParameterProvider` object providing parameters as - key/value pairs + Args: + day (datetime.date): The starting date of the simulation. + kiosk (VariableKiosk): A container for registering and publishing + (internal and external) state variables. See PCSE documentation for + details. + parvalues (ParameterProvider): A dictionary-like container holding + all parameter sets (crop, soil, site) as key/value. The values are + arrays or scalars. See PCSE documentation for details. + + Returns: + None: This method initializes the model and does not return anything. + """ self.START_DATE = day self.kiosk = kiosk @@ -223,8 +221,19 @@ def _calc_LAI(self): return total_LAI @prepare_rates - def calc_rates(self, day, drv): - """Calculate the rates of change for the leaf dynamics.""" + def calc_rates(self, day: datetime.date, drv: WeatherDataContainer) -> None: + """Calculate the rates of change for the leaf dynamics. + + Args: + day (datetime.date, optional): The current date of the simulation. + drv (WeatherDataContainer, optional): A dictionary-like container holding + weather data elements as key/value. The values are + arrays or scalars. See PCSE documentation for details. + + Returns: + None: This method calculates the rates and does not return anything. + + """ r = self.rates s = self.states p = self.params @@ -295,8 +304,17 @@ def calc_rates(self, day, drv): r.SLAT = torch.where(is_lai_exp & (r.GRLV > 0.0), GLA / r.GRLV, r.SLAT) @prepare_states - def integrate(self, day, delt=1.0): - """Integrate the leaf dynamics state variables.""" + def integrate(self, day: datetime.date, delt=1.0) -> None: + """Integrate the leaf dynamics state variables. + + Args: + day (datetime.date, optional): The current date of the simulation. + delt (float, optional): The time step for integration. Defaults to 1.0. + + Returns: + None: This method integrates the states and does not return anything. + + """ # TODO check if DVS < 0 and skip integration needed rates = self.rates states = self.states @@ -312,17 +330,20 @@ def integrate(self, day, delt=1.0): # find out which leaf classes are dead (negative weights) weight_cumsum = tLV.cumsum(dim=-1) - tDRLV is_alive = weight_cumsum >= 0 + # Adjust value of oldest leaf class, i.e. the first non-zero # weight along the time axis (the last dimension). # Cast argument to int because torch.argmax requires it to be numeric idx_oldest = torch.argmax(is_alive.type(torch.int), dim=-1, keepdim=True) new_biomass = torch.take_along_dim(weight_cumsum, indices=idx_oldest, dim=-1) tLV = torch.scatter(tLV, dim=-1, index=idx_oldest, src=new_biomass) + # Zero out all dead leaf classes # NOTE: conditional statements do not allow for the gradient to be # tracked through the condition. Thus, the gradient with respect to # parameters that contribute to `is_alive` are expected to be incorrect. tLV = torch.where(is_alive, tLV, 0.0) + # Integration of physiological age tLVAGE = tLVAGE + rates.FYSAGE tLVAGE = torch.where(is_alive, tLVAGE, 0.0) @@ -354,7 +375,15 @@ def integrate(self, day, delt=1.0): def _exist_required_external_variables(kiosk): - """Check if all required external variables are available in the kiosk.""" + """Check if all required external variables are available in the kiosk. + + Args: + kiosk (VariableKiosk): The variable kiosk to check. + + Raises: + ValueError: If any required external variable is missing. + + """ required_external_vars_at_init = ["DVS", "FL", "FR", "SAI", "PAI"] for var in required_external_vars_at_init: if var not in kiosk: diff --git a/src/diffwofost/physical_models/crop/root_dynamics.py b/src/diffwofost/physical_models/crop/root_dynamics.py index 2c0f03a..20f3da4 100644 --- a/src/diffwofost/physical_models/crop/root_dynamics.py +++ b/src/diffwofost/physical_models/crop/root_dynamics.py @@ -204,7 +204,7 @@ def calc_rates(self, day: datetime.date = None, drv: WeatherDataContainer = None r.RR = r.RR * mask @prepare_states - def integrate(self, day: datetime.date = None, delt=1.0): + def integrate(self, day: datetime.date = None, delt=1.0) -> None: """Integrate the state variables using the rates of change. Args: From 2a209f0b7d3f49475faba42fa1b45e24ee0b0d02 Mon Sep 17 00:00:00 2001 From: SarahAlidoost <55081872+SarahAlidoost@users.noreply.github.com> Date: Tue, 28 Oct 2025 17:20:48 +0100 Subject: [PATCH 20/32] Update README.md Co-authored-by: Francesco Nattino <49899980+fnattino@users.noreply.github.com> --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 0f8f89d..c8dbc90 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ The documentation for `diffWOFOST` is available at ## Acknowledgements -The package `diffWOFOST` is developed in the project -[deltaCrop](https://research-software-directory.org/projects/deltacrop), a +The package `diffWOFOST` is developed in the +[DeltaCrop](https://research-software-directory.org/projects/deltacrop) project, a collaboration between Wageningen University & Research and Netherlands eScience Center. From 75077b29e73b4478763a30755a2390c191ea8bc4 Mon Sep 17 00:00:00 2001 From: SarahAlidoost <55081872+SarahAlidoost@users.noreply.github.com> Date: Tue, 28 Oct 2025 17:21:16 +0100 Subject: [PATCH 21/32] Update LICENSE Co-authored-by: Francesco Nattino <49899980+fnattino@users.noreply.github.com> --- LICENSE | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/LICENSE b/LICENSE index dd3326a..5f2183a 100644 --- a/LICENSE +++ b/LICENSE @@ -6,9 +6,9 @@ versions of the EUPL (the "Licence"). You may not use this work except in compliance with the Licence. -You may obtain a copy of the Licence at -[https://interoperable-europe.ec.europa.eu/licence/european-union-public-licence-version-11-eupl](https://interoperable-europe.ec.europa.eu/licence/european-union-public-licence-version-11-eupl). +You may obtain a copy of the Licence at: +https://interoperable-europe.ec.europa.eu/licence/european-union-public-licence-version-11-eupl Unless required by applicable law or agreed to in writing, software distributed under the Licence is distributed on an "AS IS" basis, From 44c91f4a02c4b7376f106764742fac62304d60a4 Mon Sep 17 00:00:00 2001 From: SarahAlidoost <55081872+SarahAlidoost@users.noreply.github.com> Date: Tue, 28 Oct 2025 17:21:35 +0100 Subject: [PATCH 22/32] Update docs/examples.md Co-authored-by: Francesco Nattino <49899980+fnattino@users.noreply.github.com> --- docs/examples.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/examples.md b/docs/examples.md index 34e9f00..57b0c8b 100644 --- a/docs/examples.md +++ b/docs/examples.md @@ -4,7 +4,7 @@ We provide an example notebook showing optimization of models' parameters with `diffWOFOST`. To get familiar with the concepts and implementation, check out -`Introduction` in the documentation. +[`Introduction`](./index.md) in the documentation. | Open the notebook | Access the source | View the notebook | |-------|------------|---------------| From f686a2def12e3b9107f4e319b2b0858401765b06 Mon Sep 17 00:00:00 2001 From: SarahAlidoost <55081872+SarahAlidoost@users.noreply.github.com> Date: Tue, 28 Oct 2025 17:21:52 +0100 Subject: [PATCH 23/32] Update docs/run_model.md Co-authored-by: Francesco Nattino <49899980+fnattino@users.noreply.github.com> --- docs/run_model.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/run_model.md b/docs/run_model.md index be8a2ca..79fe7df 100644 --- a/docs/run_model.md +++ b/docs/run_model.md @@ -10,7 +10,7 @@ PCSE.ipynb](https://github.com/ajwdewit/pcse_notebooks/blob/master/01%20Getting% and [02 Running with custom input data.ipynb ](https://github.com/ajwdewit/pcse_notebooks/blob/master/02%20Running%20with%20custom%20input%20data.ipynb). -In a nutshell, we can run a model, for example, `leaf_dynamics` using PCSE as: +In a nutshell, we can run a model, for example, `leaf_dynamics` using diffWOFOST as: ```python from diffwofost.physical_models.utils import EngineTestHelper From d2760eeb51b703f236900441b171f5dd19c15225 Mon Sep 17 00:00:00 2001 From: SarahAlidoost <55081872+SarahAlidoost@users.noreply.github.com> Date: Tue, 28 Oct 2025 17:22:20 +0100 Subject: [PATCH 24/32] Update docs/installation.md Co-authored-by: Francesco Nattino <49899980+fnattino@users.noreply.github.com> --- docs/installation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/installation.md b/docs/installation.md index b797100..afa722a 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -12,7 +12,7 @@ if you want to run notebooks locally, you need to install `jupyterlab`: pip install jupyterlab ``` -If you are a contributer, clone the source code and install the package in +If you are a contributor, clone the source code and install the package in development mode: ```bash From 88b0c68cbe6756408b06c5133b5ccede481fcc6e Mon Sep 17 00:00:00 2001 From: SarahAlidoost <55081872+SarahAlidoost@users.noreply.github.com> Date: Tue, 28 Oct 2025 17:22:36 +0100 Subject: [PATCH 25/32] Update docs/installation.md Co-authored-by: Francesco Nattino <49899980+fnattino@users.noreply.github.com> --- docs/installation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/installation.md b/docs/installation.md index afa722a..47598ef 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -21,5 +21,5 @@ cd diffWOFOST pip install -e .[dev] ``` -If you are a contributer, follow the instructions in the `How to Contribute` in +If you are a contributor, follow the instructions in the `How to Contribute` in the documentation. From d99ea88dc96c8c7446f601ccffb8d5a73638ba0b Mon Sep 17 00:00:00 2001 From: SarahAlidoost <55081872+SarahAlidoost@users.noreply.github.com> Date: Wed, 29 Oct 2025 09:06:44 +0100 Subject: [PATCH 26/32] remove return none from docstring Co-authored-by: Francesco Nattino <49899980+fnattino@users.noreply.github.com> --- src/diffwofost/physical_models/crop/leaf_dynamics.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/diffwofost/physical_models/crop/leaf_dynamics.py b/src/diffwofost/physical_models/crop/leaf_dynamics.py index 207054b..0d6d81f 100644 --- a/src/diffwofost/physical_models/crop/leaf_dynamics.py +++ b/src/diffwofost/physical_models/crop/leaf_dynamics.py @@ -155,9 +155,6 @@ def initialize( all parameter sets (crop, soil, site) as key/value. The values are arrays or scalars. See PCSE documentation for details. - Returns: - None: This method initializes the model and does not return anything. - """ self.START_DATE = day self.kiosk = kiosk From 1891eda94017c1a0043cb93dff0c4b08149c3ce4 Mon Sep 17 00:00:00 2001 From: SarahAlidoost <55081872+SarahAlidoost@users.noreply.github.com> Date: Wed, 29 Oct 2025 09:07:08 +0100 Subject: [PATCH 27/32] remove return none from docstring Co-authored-by: Francesco Nattino <49899980+fnattino@users.noreply.github.com> --- src/diffwofost/physical_models/crop/root_dynamics.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/diffwofost/physical_models/crop/root_dynamics.py b/src/diffwofost/physical_models/crop/root_dynamics.py index 20f3da4..b700b79 100644 --- a/src/diffwofost/physical_models/crop/root_dynamics.py +++ b/src/diffwofost/physical_models/crop/root_dynamics.py @@ -140,9 +140,6 @@ def initialize( parvalues (ParameterProvider): A dictionary-like container holding all parameter sets (crop, soil, site) as key/value. The values are arrays or scalars. See PCSE documentation for details. - - Returns: - None: This method initializes the model and does not return anything. """ self.params = self.Parameters(parvalues) self.rates = self.RateVariables(kiosk, publish=["DRRT", "GRRT"]) From 2b48d9ca3fb1dce3b4d8e8ee8010201bc4da773d Mon Sep 17 00:00:00 2001 From: SarahAlidoost Date: Wed, 29 Oct 2025 09:10:48 +0100 Subject: [PATCH 28/32] remove returns none from docstring --- src/diffwofost/physical_models/crop/leaf_dynamics.py | 9 --------- src/diffwofost/physical_models/crop/root_dynamics.py | 8 -------- 2 files changed, 17 deletions(-) diff --git a/src/diffwofost/physical_models/crop/leaf_dynamics.py b/src/diffwofost/physical_models/crop/leaf_dynamics.py index 0d6d81f..219da47 100644 --- a/src/diffwofost/physical_models/crop/leaf_dynamics.py +++ b/src/diffwofost/physical_models/crop/leaf_dynamics.py @@ -154,7 +154,6 @@ def initialize( parvalues (ParameterProvider): A dictionary-like container holding all parameter sets (crop, soil, site) as key/value. The values are arrays or scalars. See PCSE documentation for details. - """ self.START_DATE = day self.kiosk = kiosk @@ -226,10 +225,6 @@ def calc_rates(self, day: datetime.date, drv: WeatherDataContainer) -> None: drv (WeatherDataContainer, optional): A dictionary-like container holding weather data elements as key/value. The values are arrays or scalars. See PCSE documentation for details. - - Returns: - None: This method calculates the rates and does not return anything. - """ r = self.rates s = self.states @@ -307,10 +302,6 @@ def integrate(self, day: datetime.date, delt=1.0) -> None: Args: day (datetime.date, optional): The current date of the simulation. delt (float, optional): The time step for integration. Defaults to 1.0. - - Returns: - None: This method integrates the states and does not return anything. - """ # TODO check if DVS < 0 and skip integration needed rates = self.rates diff --git a/src/diffwofost/physical_models/crop/root_dynamics.py b/src/diffwofost/physical_models/crop/root_dynamics.py index b700b79..61ba60d 100644 --- a/src/diffwofost/physical_models/crop/root_dynamics.py +++ b/src/diffwofost/physical_models/crop/root_dynamics.py @@ -171,10 +171,6 @@ def calc_rates(self, day: datetime.date = None, drv: WeatherDataContainer = None drv (WeatherDataContainer, optional): A dictionary-like container holding weather data elements as key/value. The values are arrays or scalars. See PCSE documentation for details. - - Returns: - None: This method calculates the rates and does not return anything. - """ p = self.params r = self.rates @@ -207,10 +203,6 @@ def integrate(self, day: datetime.date = None, delt=1.0) -> None: Args: day (datetime.date, optional): The current date of the simulation. delt (float, optional): The time step for integration. Defaults to 1.0. - - Returns: - None: This method integrates the states and does not return anything. - """ rates = self.rates states = self.states From fc9ad446a5fa1644adb389e8604feba0fef6e794 Mon Sep 17 00:00:00 2001 From: SarahAlidoost Date: Wed, 29 Oct 2025 09:14:37 +0100 Subject: [PATCH 29/32] add about zenodo integration to docs --- docs/CONTRIBUTING.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md index b74efe8..0e43498 100644 --- a/docs/CONTRIBUTING.md +++ b/docs/CONTRIBUTING.md @@ -52,12 +52,11 @@ To create a release you need write permission on the repository. 2. Bump the version. The version can be manually changed in `pyproject.toml` in the root of the repository. Follow [Semantic Versioning](https://semver.org/) principles. - 3. Go to the [GitHub release page](https://github.com/WUR-AI/diffwofost/releases). Press draft a new release button. Fill version, title and description field. Press the Publish - Release button - + Release button. For this package, the zenodo integration is enabled, so a new + DOI will be created automatically. 4. This software automatically publish to PyPI using a release or publish workflow. Wait until [PyPi publish workflow](https://github.com/WUR-AI/diffwofost/actions/workflows/python-publish.yml) From 6966deae259b7fa310f6ca27abaadf98fb831c65 Mon Sep 17 00:00:00 2001 From: SarahAlidoost Date: Wed, 29 Oct 2025 09:15:41 +0100 Subject: [PATCH 30/32] add version to release docs --- docs/CONTRIBUTING.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md index 0e43498..42f1732 100644 --- a/docs/CONTRIBUTING.md +++ b/docs/CONTRIBUTING.md @@ -51,7 +51,8 @@ To create a release you need write permission on the repository. the root of the repository. 2. Bump the version. The version can be manually changed in `pyproject.toml` in the root of the repository. Follow [Semantic Versioning](https://semver.org/) - principles. + principles. Also, update `__version__` variable in `diffwofost/__init__.py` to the + same version. 3. Go to the [GitHub release page](https://github.com/WUR-AI/diffwofost/releases). Press draft a new release button. Fill version, title and description field. Press the Publish From 2d6900c7f852ad27a57d715e185ec353febb3f0e Mon Sep 17 00:00:00 2001 From: SarahAlidoost Date: Wed, 29 Oct 2025 09:16:58 +0100 Subject: [PATCH 31/32] add version to project_setup docs --- docs/project_setup.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/project_setup.md b/docs/project_setup.md index a172504..c07118f 100644 --- a/docs/project_setup.md +++ b/docs/project_setup.md @@ -44,7 +44,8 @@ GitHub workflows, see `.github/`. - We recommend using [semantic versioning](https://guide.esciencecenter.nl/#/best_practices/releases?id=semantic-versioning). - For convenience, the package version is stored in a single place: `pyproject.toml`. -- Don't forget to update the version number before [making a release](https://guide.esciencecenter.nl/#/best_practices/releases)! +- Don't forget to update the version number before [making a release](https://guide.esciencecenter.nl/#/best_practices/releases)! Also, update `__version__` variable in `diffwofost/__init__.py` to the + same version. ## CITATION.cff From a90b11f5d494f9c0d7fcae44111dcfb07834f789 Mon Sep 17 00:00:00 2001 From: SarahAlidoost Date: Wed, 29 Oct 2025 09:31:22 +0100 Subject: [PATCH 32/32] fix links --- docs/project_setup.md | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/docs/project_setup.md b/docs/project_setup.md index c07118f..bbe1d9a 100644 --- a/docs/project_setup.md +++ b/docs/project_setup.md @@ -1,9 +1,8 @@ Here we provide some details about the project setup. Most of the choices are -explained in the [guide](https://guide.esciencecenter.nl). +explained in the [Turing Way: Guide for Reproducible +Research](https://book.the-turing-way.org/reproducible-research/reproducible-research/). -For a quick reference on software development, we refer to [the software guide -checklist](https://guide.esciencecenter.nl/#/best_practices/checklist). ## Repository structure @@ -42,23 +41,23 @@ GitHub workflows, see `.github/`. ## Package version number -- We recommend using [semantic versioning](https://guide.esciencecenter.nl/#/best_practices/releases?id=semantic-versioning). +- We recommend using [semantic versioning](https://semver.org/). - For convenience, the package version is stored in a single place: `pyproject.toml`. -- Don't forget to update the version number before [making a release](https://guide.esciencecenter.nl/#/best_practices/releases)! Also, update `__version__` variable in `diffwofost/__init__.py` to the +- Don't forget to update the version number before [making a release](./CONTRIBUTING.md)! Also, update `__version__` variable in `diffwofost/__init__.py` to the same version. ## CITATION.cff - To allow others to cite your software, add a `CITATION.cff` file - It only makes sense to do this once there is something to cite (e.g., a software release with a DOI). -- Follow the [making software citable](https://guide.esciencecenter.nl/#/citable_software/making_software_citable) section in the guide. +- Follow the [Software Citation with CITATION.cff](https://book.the-turing-way.org/communication/citable/citable-cff/) section in the Turing Way guide. ## CODE_OF_CONDUCT.md - Information about how to behave professionally -- [Relevant section in the guide](https://guide.esciencecenter.nl/#/best_practices/documentation?id=code-of-conduct) +- To know more, read [Turing Way guide on Code of Conduct](https://book.the-turing-way.org/community-handbook/coc/) ## CONTRIBUTING.md - Information about how to contribute to this software package -- [Relevant section in the guide](https://guide.esciencecenter.nl/#/best_practices/documentation?id=contribution-guidelines) +- To know more, read [Turing Way guide on Contributing](https://book.the-turing-way.org/reproducible-research/code-documentation/code-documentation-project/#contributing-guidelines)