Welcome to TorchCrop
Introduction
torchcrop is a fully differentiable reimplementation of the
LINTUL-5 crop growth model (Wolf, 2012).
Every step of the simulation — from sowing to harvest — produces valid
torch.autograd gradients, so mechanistic crop processes can be combined
seamlessly with learnable components (neural residuals, learned stress
responses, parameter networks) and calibrated end-to-end with standard
torch.optim optimizers.
Features
- Differentiable Lintul5 — daily forward-Euler simulation of phenology,
radiation interception, photosynthesis, partitioning, leaf/stem/root
dynamics, water balance, and NPK demand, uptake, and soil availability,
all as
torch.nn.Modules. Supports potential (IOPT=1), water-limited (IOPT=2), and water-and-NPK-limited (IOPT=3/4) production modes, with optional automatic irrigation. - Batch-first — every state, parameter and driver carries a leading
batch dimension
[B, ...]so that many sites, years, or parameter sets can be simulated in parallel on GPU. - 23 bundled crop presets —
torchcrop.available_crops()lists species (wheat, maize, rice, soybean, potato, sugar beet, …); load one viaCropParameters(crop_name="wheat"). - Gradient-based calibration —
torchcrop.calibrationprovides a constraint-aware (bounds, dtype, table-ordinate, ordering), transform-basedCalibrationManagerfor fitting crop parameters to observations. - Hybrid modeling hooks — a
HybridManagerwiring layer accepts declarativeResidualSpecs (seedefault_slots()) to injectNeuralResidualcorrections at named points in the pipeline, plus drop-inLearnedStressFactorandParameterNetmodules. - External irrigation/fertiliser — pass explicit
irrigation: [B, T]andfertilizer: [B, T, 3]schedules tomodel(...), overriding the internal table-driven application on a per-day basis. - Smooth options — stage-based branching (
DVS < 1, maturity, etc.) can be switched between hardtorch.whereand sigmoid blends for second-order smoothness. - Gradient-checked primitives — differentiable AFGEN-style interpolation
and soft FST helpers (
LIMIT,INSW,NOTNUL) passtorch.autograd.gradcheck.
Installation
pip install torchcrop
Quickstart
import torch
import torchcrop
from torchcrop.utils.io import make_constant_weather
weather = make_constant_weather(batch_size=2, n_days=150)
model = torchcrop.Lintul5Model()
output = model(weather, start_doy=60)
print(output.yield_) # [B] final storage-organ biomass (g m-2)
print(output.lai.shape) # [B, T+1] LAI trajectory
print(output.dvs.shape) # [B, T+1] development stage trajectory
Gradient-based parameter calibration
torchcrop.calibration turns bounded crop/soil/site parameters into
optimizable latents, keeping them inside their physical range by
construction:
import torch
from torchcrop import CalibrationManager, Lintul5Model, ParameterSpec
model = Lintul5Model(crop_params=torchcrop.CropParameters().to(dtype=torch.float64)).double()
manager = CalibrationManager(
model, specs=[ParameterSpec(name="crop.scale_factor_rue", bounds=(0.5, 1.5))]
)
optimizer = torch.optim.Adam(manager.parameters(), lr=1e-2)
for _ in range(50):
optimizer.zero_grad()
manager.materialize() # write the current latents into model.crop_params
out = model(weather.to(torch.float64), start_doy=60)
loss = ((out.yield_ - observed_yield) ** 2).mean()
loss.backward()
optimizer.step()
See docs/examples/04_calibration/ for a full worked example.
Hybrid modeling
Inject a neural residual on top of a named point in the mechanistic pipeline
via a declarative ResidualSpec:
from torchcrop.nn import ResidualSpec
model = torchcrop.Lintul5Model(
residual_specs=[
ResidualSpec(
"photosynthesis.gtotal",
"rate_factor",
context=("lai", "dvs", "davtmp", "tranrf", "nstress"),
scale=0.15,
),
],
)
torchcrop.nn.default_slots() returns the recommended catalogue of
observable-tied slots (photosynthesis, water stress, partitioning, leaf
senescence); pass a hand-picked subset rather than the whole list unless
every pathway is observable. All parameters — mechanistic and neural — are
surfaced by model.parameters() and can be optimized jointly.
Package layout
torchcrop/
├── model.py # Lintul5Model(nn.Module)
├── engine.py # SimulationEngine time-stepping loop
├── config.py # RunConfig
├── parameters/ # CropParameters / SoilParameters / SiteParameters
│ # + 23 bundled crop presets (crop_data/*.yaml)
├── drivers/weather.py # WeatherDriver [B, T, C]
├── states/model_state.py # ModelState / DiagnosticState tensor containers
├── processes/ # Biophysical processes (astro, phenology,
│ # irradiation, evapotranspiration,
│ # co2_transpiration, water_balance,
│ # photosynthesis, partitioning, leaf_dynamics,
│ # stem_dynamics, root_dynamics, nutrient_demand,
│ # soil_nutrients, heat_stress, stress)
├── functions/ # Differentiable primitives (AFGEN, FST, smoothing)
├── nn/ # NeuralResidual, LearnedStressFactor, ParameterNet,
│ # HybridManager / ResidualSpec wiring layer
├── calibration/ # CalibrationManager, ParameterSpec,
│ # ConstraintGroup, transforms
└── utils/ # I/O, visualisation, validation helpers
Examples
Worked notebooks under docs/examples/ (rendered into the docs site):
01_potential/— potential production (winter wheat)02_water_limited/— water-limited production (winter wheat)03_water_and_nutrient_limited/— water + N and water + NPK limited production04_calibration/— gradient-based parameter calibration05_hybrid/— hybrid ML residual corrections (reserved, notebook in progress)06_daily_timestep/— low-level, day-by-day API usageothers/data_prep.ipynb— preparing the Brandenburg example dataset
Development
pytest # run the test suite
flake8 torchcrop tests # lint
black torchcrop tests # format
pre-commit run --all-files
References
- Wolf, J. (2012). User guide for LINTUL5. Wageningen UR. https://models.pps.wur.nl/lintul-5-crop-growth-simulation-model-potential-water-limited-n-limited-and-npk-limited-conditions
- WUR-AI. diffWOFOST — Differentiable WOFOST crop model. https://github.com/WUR-AI/diffWOFOST
Metadata
Release files for torchcrop 1.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| torchcrop-1.1.1.tar.gz | 2.2 MB | Without provenance | Details for torchcrop-1.1.1.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| torchcrop-1.1.1-py2.py3-none-any.whl | Python 3, Python 2 | none | any | Details for torchcrop-1.1.1-py2.py3-none-any.whl |
Total release size: 2.4 MB
Release files / torchcrop-1.1.1.tar.gz
| Download URL | torchcrop-1.1.1.tar.gz |
|---|---|
| Size | 2.2 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
aa91def48433e765976d05223b3227cd43d91a0b2feb8a45827de006e546dbee
|
|
BLAKE2b-256 checksum How to use checksums |
f24e9de80f04adacfc848b5e45c49df5c7a02e7114caa73f6281d87f6bafa0ef
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.6
|
Release files / torchcrop-1.1.1-py2.py3-none-any.whl
| Download URL | torchcrop-1.1.1-py2.py3-none-any.whl |
|---|---|
| Size | 158.4 kB |
| Tags | Python 2 Python 3 |
|
SHA-256 checksum How to use checksums |
baa4af6a0b8e3135a1d97328e621f07f0a6dcb3895c0634c410bb4e8e60799f8
|
|
BLAKE2b-256 checksum How to use checksums |
216da853b57b20bdab553f1bc25b5c96060462c2365af18aa10c2f5b0c19dac3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.6
|
Security for torchcrop 1.1.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.