Releases: MAGALA-RICHARD/apsimNGpy
API enhancement
Version 1.5.3
API improvements
- Added
append_simulationmethod
append_simulation method can be used to append simulations to the current ApsimModel instance. Unlike
clone_simulation, this method supports transferring simulations from external ApsimModel objects in addition to duplicating
simulations already present within the current model instance.
Advantages:
- Reuse simulations across APSIM models without manual copying.
- Build complex scenario collections from multiple source models with minimal effort.
- Quickly create simulation variants by duplicating existing simulations.
- Avoid naming conflicts through optional simulation renaming.
- By allowing multiple simulations to be managed within a single APSIM model instance, the overhead associated with repeatedly loading and initializing
Models.exeis reduced. - Rapidly generate multiple simulation scenarios using the
payloadargument, enabling efficient exploration of management, soil, weather, or cultivar variations and their impacts on model outputs. - Simplify what-if analysis by automatically creating simulation variants from different input configurations, reducing the effort required to evaluate alternative strategies and outcomes.
Basic example:
Append a simulation from another APSIM model
from apsimNGpy import ApsimModel
base_model = ApsimModel("Maize")
# Get the first simulation from another model
other_simulation = ApsimModel("Soybean")[0]
base_model.append_simulation(
simulation=other_simulation,
rename="Simulation2",
)Duplicate an existing simulation
from apsimNGpy import ApsimModel
model = ApsimModel("Maize")
model.append_simulation(
simulation=model[0],
rename="Simulation_copy",
)Edit the appended simulation on the fly
The payload argument allows simulations to be modified during the append operation, making it easy to generate multiple scenario variants without additional editing steps.
from apsimNGpy import ApsimModel
with ApsimModel("Maize") as model:
model.append_simulation(
simulation=model[0],
rename="pop12",
payload=dict(
model_type="Models.Manager",
model_name="Sow using a variable rule",
Population=12,
),
)This feature is particularly useful for rapidly generating scenario ensembles, sensitivity analysis experiments, and optimization studies where multiple simulations differ only in a small number of parameter values.
Note
append_simulation()should not be used withExperimentManagerobjects, even thoughExperimentManagerinherits fromApsimModel. Experiment managers are designed around a single base simulation and appending simulations directly may result in unexpected behavior.In many cases, appended simulations should be modified to distinguish them from their source simulations. The
payloadargument provides a convenient way to apply edits during the append operation.payloadmay be either a dictionary or a list of dictionaries containing arguments accepted byedit_model().
model.append_simulation(
simulation=model[0],
rename="clone1",
payload=dict(
model_type="Models.Manager",
model_name="Sow using a variable rule",
Population=12,
),
)For more examples and implementation details:
help(model.append_simulation)Added add_node_from()
A new add_node_from() method has been introduced to simplify transferring APSIM nodes between models and simulations while providing greater control over node placement and replacement behavior.
Advantages
- Transfer nodes from external or internal APSIM models into a specified target location.
- Improve workflow automation for model customization, scenario generation, and programmatic model construction.
- Reduce errors by enforcing keyword-only arguments, improving readability and preventing parameter mis-ordering.
- Support safe replacement of existing nodes through the
del_if_existsoption. - Allow inserted nodes to be renamed during transfer to avoid naming conflicts.
- Identify source nodes using either node names or full APSIM paths.
- Improve handling of multiple nodes of the same type, such as Manager scripts serving different roles within a simulation.
Example
target_model.add_node_from(
source=source_model,
source_node="Fertiliser",
target="Simulation.Field",
rename="HighN",
del_if_exists=True,
)This addition provides a more robust and flexible approach for building, modifying, and extending APSIM models programmatically, particularly in workflows involving large-scale scenario generation, experimentation, and model templating.
Added clone_simulation()
A new clone_simulation() method has been introduced to simplify the creation of simulation variants within the same APSIM model.
Advantages
- Rapidly generate alternative management, cultivar, or environmental scenarios while preserving the original simulation.
- Simplify comparative analysis by maintaining multiple simulation variants within a single APSIM model.
- Reduce the effort required to create and manage large scenario ensembles.
- Enable efficient sensitivity analysis, optimization, and what-if experimentation workflows.
Example
from apsimNGpy import ApsimModel
model = ApsimModel("Maize")
population = 10
simulation_name = f"sim_{population}"
model.clone_simulation(
rename=simulation_name,
base_simulation=0,
)
model.edit_model(
model_type="Models.Manager",
model_name="Sow using a variable rule",
simulations=simulation_name,
Population=population,
)Added has_node()
A new has_node() method has been added to simplify node discovery and validation within APSIM models.
Advantages
- Verify the existence of nodes before performing modifications.
- Support node lookup using either node names or full APSIM paths.
- Improve robustness of automation workflows by reducing node-resolution errors.
- Facilitate model inspection, validation, and dynamic editing operations.
Example
from apsimNGpy import ApsimModel
with ApsimModel("Maize") as model:
model.has_node(
"Sow using a variable rule",
"Models.Manager",
)
model.has_node(
".Simulations.Simulation.Field.Sow using a variable rule",
"Models.Manager",
)Added switch_wm_to_swim3()
A new switch_wm_to_swim3() method has been introduced to simplify the replacement of APSIM's default soil water model with the physically based SWIM3 module.
Advantages
- Accelerate conversion of existing models to SWIM3.
- Automatically configure subsurface tile drainage systems.
- Support custom SWIM3 parameter overrides.
- Validate drainage configuration inputs before model execution.
- Simplify hydrological scenario analysis and drainage-management studies.
Examples
Automatic drainage configuration:
model.switch_wm_to_swim3(
ss_tile_drainage="auto"
)Custom drainage configuration:
model.switch_wm_to_swim3(
ss_tile_drainage={
"DrainDepth": 1200,
"DrainSpacing": 30000,
"ImpermDepth": 2500,
}
)Cultivar Editing Interface
Introduced a dedicated CultivarEditor implementation based on a composition-oriented design.
Advantages
- Provides a clearer and more maintainable API for cultivar editing.
- Simplifies the creation and management of derived cultivars.
- Improves compatibility with APSIM cultivar editing limitations.
- Enables cultivar modifications without directly altering replacement nodes.
Added add_new_model()
A new add_new_model() method has been introduced for dynamically constructing and inserting APSIM model nodes directly from Python dictionaries.
Advantages
- Build APSIM models programmatically without manual JSON manipulation.
- Create APSIM nodes directly from Python-native data structures.
- Support both APSIM-standard
"$type"and Python-friendly"type"declarations. - Automatically resolve and instantiate APSIM CLR model types.
- Insert nodes into arbitrary locations within an APSIM model.
- Support replacement and renaming during insertion.
- Automatically parse APSIM date fields and manager parameter definitions.
- Simplify automated model generation, templating, and scenario construction workflows.
Example
from apsimNGpy import ApsimModel
model = ApsimModel("Maize")
model.add_new_model(
parent_identifier="Simulation",
parent_type="Simulation",
source={
"$type": "Models.Clock, Models",
"Start": "2000-01-01",
"End": "2020-12-31",
},
)Bug Fixes and Improvements
Fixed add_replacement() Duplication Issue
Resolved an issue where repeated calls to add_replacement() could create duplicate replacement nodes. The method now detects existing replacements and prevents unintended duplication, improving model consistency and reducing replacement management errors.
Improved inspect_model_parameters()
inspect_model_parameters() now returns a dictionary consistently across supported APSIM model types.
Advantages
- Provides a uniform and predictable API across APSIM model types.
- Simplifies programmatic inspection, calibration, and model-editing workflows.
- Preserves both scalar and layered parameter values in a single structure.
- Eliminates model-type-specific return handling.
- Improves compatibili...
Improved public API access
Version 1.5.2
Improvements
- Added lazy-loading support for APSIM runtime modules to prevent early CLR initialization.
- Consolidates all apsimNGpy public API into a single access point to enable easier discovery and support lazy importing. For example,
ApsimModelif the APSIM binary path has been set, can now be imported directly from the top-level package:
from apsimNGpy import ApsimModel
Bug Fixes
- Fixed issues with APSIM binary path configuration when importing
apsimNGpy. - Improved compatibility with Ruff static analysis for
TYPE_CHECKINGimports. - fixed f strings errors in early versions of python
- Fixed the add_crop_replacements method and removed the deprecated _crop argument. Future releases will allow this method to be called without arguments, automatically detecting available plant modules and adding them to the replacements folder.
Tests
- Added tests verifying lazy attribute resolution and caching behavior.
- Added tests ensuring unittest modules are correctly exposed.
Automatic file deletion made easy
### apsimNGpy 0.39.11.20 – Release Notes
This release introduces a dedicated simulation file context manager that automatically removes transient .apsimx files and all associated output database files (.db, .db-wal, .db-sha, etc.) at the end of a with block.
This allows users to run temporary simulations with confidence that intermediate files will not accumulate on disk — especially important for large workflows, such as optimization loops, Monte Carlo runs, or multi-site batch simulations.
To achieve this, the context manager now coordinates more carefully with APSIM-NG’s I/O locking behavior. In particular, it triggers the underlying C# garbage collector (when necessary) to ensure that the write locks on the result database are fully released before deletion.
As a result, there is a small (but practically negligible) performance overhead; future versions may introduce a switch to disable this behavior for users who do not require automatic cleanup.
This release also introduces a second context manager for managing temporary APSIM bin paths.
It allows users to specify a local APSIM-NG installation path for a given script/module while preserving the global default in memory — enabling cleaner multi-version testing or workflow portability without rewriting environment variables.
### 1) Temporally simulations using a context manager
from apsimNGpy.core.apsim import ApsimModel
with Apsim_model("template.apsimx") as temp_model:
temp_model.run() # temporary .apsimx + .db files created
df= temp_model.results
print(df)
Immediately after exiting the with block, the temporary .apsimx file (and its associated .db files) are deleted,
since only clones of the original model file are used inside the context.
2) Temporary APSIM-bin path
from apsimNGpy.core.config import apsim_bin_context
with apsim_bin_context("C:/APSIM/2025.05.1234/bin"):
from Models.Core import Simulations # uses this bin path for loading
from apsimNGpy.core.apsim import ApsimModel
Immediately after exiting the with block, the path is restored back to the global APSIM path — meaning that other projects and modules can continue to access their own settings normally. The importance of this pattern lies in its reproducibility, as it allows your project to be “locked” to a specific APSIM binary path.
APSIM versions change frequently, and a future run of your current project may fail or yield different results if a newer APSIM version is installed without your knowledge. By scoping a local APSIM bin path for this project, you ensure that reruns in the future use exactly the same APSIM version that generated the original results.
This makes the workflow both reproducible and stable.
The bin path can also be substituted with just the project .env path as follows
with apsim_bin_context( dotenv_path = './config/.env', bin_key ='APSIM_BIN_PATH'):
from Models.Core import Simulations # uses this bin path for loading
from apsimNGpy.core.apsim import ApsimModel # uses this bin path for loading
Note
Since the model assemblies are already loaded into memory inside the apsim_bin_context, you do not need to remain inside the
with block to keep using them. Once loaded, those modules (and their namespaces) are global within the process, and they retain
their reference to the APSIM bin path that was supplied during loading.
v0.39.8.14
v0.39.8.14 – APSIM file structure patches
Fixes
- Additional patches to handle recent APSIM NG file-structure changes.
- Improved detection and fallback logic in readers/writers.
Compatibility
- Works with recent APSIM NG builds that modified file layout.
- If you hit issues, please open an issue with your APSIM build number and a minimal .apsimx.
Notes
- No API changes; backward-compatible.
v0.35
apsimNGpy version: v0.35 – April 2025
APSIMNGpy is a Python interface for APSIM Next Generation (.apsimx) models. It enables seamless model inspection, execution, batch simulation, optimization, and diagnostic reporting—directly from Python. Designed for reproducible research and integration with scientific workflows. Please take a look at the new improvements below.
✨ New Features
Model Introspection: inspect_model_inputs() enables inspection of internal parameters (Weather, Clock, Soil, Report, etc.).
Model Actions: Support for get, delete, and check operations on models within simulations via get_or_check_model().
Flexible Model Lookup: Added _eval_model() and find_model() utilities for robust model resolution by name or namespace.
Batch Simulation Support: Functions for handling multiple simulations and reports concurrently.
Model editing: Model editing has been streamlined by introducing a unified method, edit_model, which allows users to specify the model type, name, and target simulation in a single call.
Model inspection: Model inspection has been enhanced with the inspect_model_parameters method, enabling users to retrieve parameter values by specifying the model type, name, and simulation. Additionally, the inspect_model method can be used to explore available model names and their paths within simulations.
Cultivar Modification: Access and manipulation of PMF.Cultivar parameters, including dynamic cultivar switching.
More CLI model edits and interactions
🛠 Improvements
Refactored internal utilities for better maintainability and reuse.
Improved error handling and descriptive exceptions.
Memory-safe operations with explicit use of garbage collection to clear memory after expensive recursions.
Logging minimization inside event loops for improved performance.
🐛 Bug Fixes
Fixed incorrect type handling in soil model inspection.
Resolved missing models from deeply nested namespaces like Models.Factorial.
📚 Documentation
Enhanced docstrings and type hints across all public APIs.
Added inline usage instructions for key functions.