LINTUL3-Gym
LINTUL3-Gym is a transparent, reproducible Gymnasium
environment for nitrogen-management reinforcement learning, built on PCSE's LINTUL3 crop model.
Every transition returns a complete, inspectable record -- crop state, weather, and reward
components -- instead of an opaque feature vector, and the bundled winter-wheat example reproduces
a peer-reviewed paper's experiment end-to-end. It ships with a spring-wheat scenario for
gym.make(...) to work out of the box, plus two fuller worked examples -- spring wheat and winter
wheat -- with their own tutorial notebooks (see Examples).
Install
pip install lintul3-gym
Quick start
import gymnasium as gym
import lintul3_gym
env = gym.make("Lintul3Gym-v0", decision_interval=7)
observation, info = env.reset(seed=7)
while True:
observation, reward, terminated, truncated, info = env.step([0.0])
if terminated or truncated:
break
The action is one nitrogen dose in g N/m². The observation keeps crop, weather, and management fields separate. Each step's info includes the names and values consumed by the agent, weather metadata, reward components, and a serializable transition record. env.unwrapped.history is the complete episode audit trail.
Inputs and weather
By default the package loads its bundled spring-wheat .crop, .site, .soil, and nl1.xlsx inputs. Point data_dir at another directory to use your own inputs: Lintul3Env auto-discovers whichever single *.crop, *.site, and *.soil file it finds there by extension, not a fixed filename, so any directory shaped like the bundled example works. A sample .agro file may also be present for provenance/documentation, but it is never read as an environment input -- see Custom environments.
from lintul3_gym import Lintul3Env, WeatherConfig
excel_env = Lintul3Env(data_dir="/path/to/my/inputs")
nasa_env = Lintul3Env(
weather=WeatherConfig(
source="nasa",
locations=((51.97, 5.67), (52.0, 5.5)),
years=(2004, 2005, 2006),
random_weather_per_episode=True,
)
)
NASA POWER selections are seeded and cached locally under ~/.cache/lintul3_gym/nasa_power by default. Set cache_dir or refresh_cache in WeatherConfig to control this behavior.
Custom environments
Lintul3Env is flexible and works with any crop that has a LINTUL3
parameter set, via two pieces of configuration:
data_dir: a directory holding exactly one*.crop, one*.site, and one*.soilfile (any filename), and optionally annl1.xlsxforWeatherConfig(source="excel").SeasonConfig: the crop calendar (campaign_start,crop_start/crop_enddates and types,crop_name,max_duration) that would otherwise live in a PCSE.agrofile.Lintul3Envbuilds the equivalent calendar from this in code, so nitrogen application stays entirely under the RL agent's control.
from datetime import date
from lintul3_gym import Lintul3Env, SeasonConfig, WeatherConfig
season = SeasonConfig(
campaign_start=date(2007, 1, 1), crop_start=date(2007, 1, 1),
crop_end=date(2007, 9, 1), crop_name="winter-wheat",
crop_start_type="emergence", crop_end_type="earliest", max_duration=365,
)
env = Lintul3Env(data_dir="lintul3_gym/envs/data/winterwheat", season=season, decision_interval=7)
Two worked examples ship in this repo:
lintul3_gym/envs/data/springwheat/-- the bundled default (Netherlands, 2006).lintul3_gym/envs/data/winterwheat/-- winter wheat (Netherlands + France, 1990-2021), reproducing Kallenberg et al. (2023); see its ownREADME.mdfor full parameter provenance and a model-fidelity discussion.
For more LINTUL3-ready datasets, see PCSE's own documentation and WUR-AI/PCSE-Gym (the source of the winter-wheat set above) -- though most of PCSE-Gym's other crop configs are in WOFOST format (YAMLCropDataProvider/CABOFileReader), not this package's plain-text PCSEFileReader .crop/.site/.soil format, so they need translating rather than dropping in directly.
Reward and comparison
The default reward follows PCSE-Gym's LINTUL cost function:
storage-organ growth (g/m²) - 10.0 × applied nitrogen (g N/m²).
Use RewardConfig(nitrogen_cost=...) to change the cost, or relative_to_zero_nitrogen=True to score growth relative to a synchronized zero-nitrogen crop run.
Policies
lintul3_gym.policies provides a few simple, inspectable reference policies to evaluate a trained agent against, plus the evaluation helpers used throughout the examples:
ZeroNitrogenPolicy-- never applies nitrogen; a lower-bound baseline.ExpertPolicyandStandardPracticePolicy-- both are fixed calendar-dose baselines (apply a predetermined amount of nitrogen on predetermined calendar dates, regardless of crop state):ExpertPolicyreproduces the bundled spring-wheat.agroschedule (10 and 5 g N/m² on Apr 10 and May 5);StandardPracticePolicyreproduces the "Standard Practice" baseline from Kallenberg et al. (2023) for the winter-wheat use case (a configurable total split across three real fertilization dates). Both share the same underlying date-window matching logic.evaluate_policy(environment, policy, seed=...)-- runs one policy episode (works for either of the above, or a Stable-Baselines3 model) and returns a complete, transparentEvaluationResult.evaluate_policy_over_weather(environment, policy)-- runsevaluate_policyonce per(location, year)combination in aWeatherConfig, round-robin.evaluate_sb3_policy(vec_env, model, n_episodes=...)-- theVecNormalize-aware counterpart for trained Stable-Baselines3 models.
See examples/nitrogen-springwheat/Tutorial-Lintul3gym.ipynb and examples/nitrogen-winterwheat/PaperRep-Lintul3gym.ipynb for these in use.
Examples
| Example | What it shows |
|---|---|
examples/nitrogen-springwheat/Tutorial-Lintul3gym.ipynb |
Full tutorial -- what LINTUL3/PCSE need as input, how lintul3_gym supplies it, and both bundled experiments (train+eval on one fixed season; train+eval across disjoint years/locations via NASA POWER). Ends with a guide to adapting the environment to a different crop. |
examples/nitrogen-winterwheat/PaperRep-Lintul3gym.ipynb + lintul3_gym/envs/data/winterwheat/README.md |
Reproduces Kallenberg et al. (2023)'s winter-wheat nitrogen-management experiment: NASA POWER weather, the paper's train/test locations and years, a Standard Practice baseline, and out-of-distribution climate testing (Netherlands vs. France). |
How to cite
If you use lintul3-gym in your research, please cite it as:
Ohagwu, C. P. (2026). LINTUL3-Gym: A transparent, reproducible Gymnasium environment for LINTUL3 nitrogen management (Version 0.1.0) [Computer software]. https://github.com/cpohagwu/lintul3-gym
@software{ohagwu_lintul3gym,
author = {Ohagwu, Collins Patrick},
title = {{LINTUL3-Gym}: A transparent, reproducible {Gymnasium} environment for {LINTUL3} nitrogen management},
year = {2026},
url = {https://github.com/cpohagwu/lintul3-gym},
version = {0.1.0}
}
If you're using the winter-wheat example to reproduce Kallenberg et al. (2023)'s results, please
also cite that paper -- see lintul3_gym/envs/data/winterwheat/README.md
for its citation, which is separate from citing this software.
License
Apache-2.0 (see LICENSE). The design and economic convention of the default reward
are informed by the GPL-3.0 PCSE-Gym reference project.
The winter-wheat example's data files and patch
(lintul3_gym/envs/data/winterwheat/) are copied verbatim from PCSE-Gym and
remain under its GPL-3.0-or-later license rather than this repository's Apache-2.0 license -- see
that directory's README.md for details.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file lintul3_gym-0.1.0-py3-none-any.whl.
File metadata
- Download URL: lintul3_gym-0.1.0-py3-none-any.whl
- Upload date:
- Size: 152.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.0.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
754e4c88be19c39eb4ce89ae528534bba04352dad59c7b967387f405c4173da9
|
|
| MD5 |
ad6a628b14257c438c39d89c2ac0f799
|
|
| BLAKE2b-256 |
f9cfda8a2b6f6929d67bc243464247d965b7a454e776aa44cec818e1846510de
|