Roundtrip and CLI Modules#
The roundtrip modules provide read-write-read verification pipelines, run script generation, model packaging, and CLI subcommands for IWFM models.
Roundtrip Pipeline#
The pipeline module orchestrates a full read-write-read verification cycle: load a model, write it to a new directory, optionally run both versions, and compare results.
Main roundtrip testing pipeline orchestrator.
- class pyiwfm.roundtrip.pipeline.StepResult(name='', success=False, message='', data=None, error='')[source]#
Bases:
objectResult of a single pipeline step.
- Variables:
- __init__(name='', success=False, message='', data=None, error='')#
- class pyiwfm.roundtrip.pipeline.RunPairResult(preprocessor=None, simulation=None)[source]#
Bases:
objectResult of running preprocessor + simulation.
- Variables:
preprocessor (
PreprocessorResult | None) – Result from preprocessing.simulation (
SimulationResult | None) – Result from simulation.
- preprocessor: PreprocessorResult | None = None#
- simulation: SimulationResult | None = None#
- __init__(preprocessor=None, simulation=None)#
- class pyiwfm.roundtrip.pipeline.RoundtripResult(steps=<factory>, baseline_run=None, written_run=None, input_diff=None, results_comparison=None)[source]#
Bases:
objectAggregate result of the full roundtrip pipeline.
- Variables:
steps (
dict[str,StepResult]) – Results for each pipeline step.baseline_run (
RunPairResult | None) – Result of running the original model.written_run (
RunPairResult | None) – Result of running the written model.input_diff (
InputDiffResult | None) – Input file comparison result.results_comparison (
Any) – Simulation output comparison result.
- steps: dict[str, StepResult]#
- baseline_run: RunPairResult | None = None#
- written_run: RunPairResult | None = None#
- __init__(steps=<factory>, baseline_run=None, written_run=None, input_diff=None, results_comparison=None)#
- class pyiwfm.roundtrip.pipeline.RoundtripPipeline(config)[source]#
Bases:
objectOrchestrates the full roundtrip test: load -> write -> run -> verify.
- Parameters:
config (
RoundtripConfig) – Pipeline configuration.
Roundtrip Configuration#
Configuration dataclass for the roundtrip pipeline.
Configuration for the roundtrip testing pipeline.
- class pyiwfm.roundtrip.config.RoundtripConfig(source_model_dir=<factory>, simulation_main_file='', preprocessor_main_file='', output_dir=<factory>, executable_manager=None, run_baseline=True, run_written=True, compare_results=True, preprocessor_timeout=300, simulation_timeout=3600, head_atol=0.01, budget_rtol=0.001)[source]#
Bases:
objectConfiguration for a roundtrip test run.
- Parameters:
source_model_dir (
Path) – Root directory of the source IWFM model.simulation_main_file (
str) – Relative path to the Simulation main file within the model dir.preprocessor_main_file (
str) – Relative path to the PreProcessor main file within the model dir.output_dir (
Path) – Directory for written model and test outputs.executable_manager (
IWFMExecutableManager | None) – Manager for finding/downloading executables. Created automatically if not provided.run_baseline (
bool) – Whether to run the original model for comparison.run_written (
bool) – Whether to run the written (roundtripped) model.compare_results (
bool) – Whether to compare simulation results between baseline and written.preprocessor_timeout (
float) – Timeout in seconds for preprocessor runs.simulation_timeout (
float) – Timeout in seconds for simulation runs.head_atol (
float) – Absolute tolerance for head comparisons (ft).budget_rtol (
float) – Relative tolerance for budget comparisons.
- executable_manager: IWFMExecutableManager | None = None#
- classmethod from_env()[source]#
Create config from environment variables.
Reads: - IWFM_MODEL_DIR: source model directory - IWFM_ROUNDTRIP_OUTPUT: output directory - IWFM_BIN: path to executables
- Returns:
Configuration populated from environment.
- Return type:
- classmethod for_sample_model(iwfm_dir)[source]#
Create config for the IWFM Sample Model.
- Parameters:
iwfm_dir (
Path | str) – Root directory containing the sample model.- Returns:
Configuration for sample model roundtrip test.
- Return type:
- classmethod for_c2vsimfg(c2vsimfg_dir)[source]#
Create config for the C2VSimFG model.
- Parameters:
c2vsimfg_dir (
Path | str) – Root directory of the C2VSimFG model.- Returns:
Configuration for C2VSimFG roundtrip test.
- Return type:
- classmethod for_c2vsimcg(c2vsimcg_dir)[source]#
Create config for the C2VSimCG (Coarse Grid) model.
- Parameters:
c2vsimcg_dir (
Path | str) – Root directory of the C2VSimCG model.- Returns:
Configuration for C2VSimCG roundtrip test.
- Return type:
- __init__(source_model_dir=<factory>, simulation_main_file='', preprocessor_main_file='', output_dir=<factory>, executable_manager=None, run_baseline=True, run_written=True, compare_results=True, preprocessor_timeout=300, simulation_timeout=3600, head_atol=0.01, budget_rtol=0.001)#
Run Script Generator#
Generates platform-appropriate run scripts (.bat, .ps1, .sh)
for IWFM preprocessor, simulation, and optional Budget/ZBudget
post-processors.
Generate platform-appropriate run scripts for IWFM models.
- pyiwfm.roundtrip.script_generator.generate_run_scripts(model_dir, preprocessor_main, simulation_main, preprocessor_exe='PreProcessor_x64.exe', simulation_exe='Simulation_x64.exe', budget_exe=None, zbudget_exe=None, formats=None)[source]#
Generate run scripts for an IWFM model.
Creates scripts in the model directory for each requested format: - run_preprocessor (.bat/.ps1/.sh) - run_simulation (.bat/.ps1/.sh) - run_all (.bat/.ps1/.sh) - run_budget (.bat/.ps1/.sh) — if budget_exe is provided - run_zbudget (.bat/.ps1/.sh) — if zbudget_exe is provided
- Parameters:
model_dir (
Path) – Root directory of the model.preprocessor_main (
str) – Relative path from model_dir to the preprocessor main file.simulation_main (
str) – Relative path from model_dir to the simulation main file.preprocessor_exe (
str) – Name of the preprocessor executable.simulation_exe (
str) – Name of the simulation executable.budget_exe (
str | None) – Name of the Budget post-processor executable. WhenNone(default), no budget run script is generated.zbudget_exe (
str | None) – Name of the ZBudget post-processor executable. WhenNone(default), no zbudget run script is generated.formats (
list[str] | None) – Script formats to generate. Accepted values:"bat","ps1","sh".Noneselects the platform-appropriate default (["bat", "ps1"]on Windows,["sh"]elsewhere).
- Returns:
Paths to the generated scripts.
- Return type:
list[Path]
Model Packager#
Packages an IWFM model directory into a distributable ZIP archive with
an embedded manifest.json.
Package IWFM model directories into distributable ZIP archives.
- class pyiwfm.io.model_packager.ModelPackageResult(archive_path, files_included=<factory>, total_size_bytes=0, manifest=<factory>)[source]
Bases:
objectResult of a model packaging operation.
- Variables:
archive_path (
Path) – Path to the created ZIP archive.files_included (
list[Path]) – Absolute paths of all files that were added to the archive.total_size_bytes (
int) – Total uncompressed size of included files in bytes.manifest (
dict[str,str]) – Mapping of relative path (inside ZIP) to the file-type category.
- archive_path: Path
- total_size_bytes: int = 0
- __init__(archive_path, files_included=<factory>, total_size_bytes=0, manifest=<factory>)
- pyiwfm.io.model_packager.collect_model_files(model_dir, *, include_executables=False, include_results=False)[source]
Collect all model files from a directory tree.
Walks model_dir recursively and returns files relevant to an IWFM model, excluding output/cache directories by default.
- Parameters:
- Returns:
Sorted list of absolute paths to included files.
- Return type:
list[Path]
- pyiwfm.io.model_packager.package_model(model_dir, output_path=None, *, include_executables=False, include_results=False, compression=8, compresslevel=6)[source]
Package an IWFM model directory into a ZIP archive.
Creates a ZIP file preserving the directory structure (
Preprocessor/,Simulation/, etc.) with amanifest.jsonembedded in the archive.- Parameters:
model_dir (
Path) – Root directory of the IWFM model.output_path (
Path | None) – Path for the output ZIP file. IfNone, defaults to<model_dir_name>.zipin the parent of model_dir.include_executables (
bool) – IfTrue, include.exe,.dll, and.sofiles.include_results (
bool) – IfTrue, include theResults/directory and HDF5 output files.compression (
int) – ZIP compression method (defaultZIP_DEFLATED).compresslevel (
int) – Compression level (0-9, default 6).
- Returns:
Result with archive path, file list, size, and manifest.
- Return type:
- Raises:
FileNotFoundError – If model_dir does not exist or is not a directory.
Executable Manager#
Downloads, locates, and places IWFM executables (PreProcessor, Simulation, Budget, ZBudget) for model execution.
IWFM executable manager for finding, downloading, and placing executables.
- class pyiwfm.runner.executables.IWFMExecutableManager(github_repo='', version='', config='Release', search_paths=<factory>)[source]#
Bases:
objectManage IWFM executable discovery and download.
Handles finding local executables, downloading from GitHub releases, placing executables into model directories, and verification.
- Parameters:
Examples
>>> mgr = IWFMExecutableManager() >>> exes = mgr.find_or_download() >>> print(exes.available) ['preprocessor', 'simulation', 'budget', 'zbudget']
- find_or_download()[source]#
Try to find local executables, download if not found.
- Returns:
Discovered or downloaded executables.
- Return type:
IWFMExecutables
- download_from_github(dest=None)[source]#
Download IWFM executables from a GitHub release.
- Parameters:
dest (
Path | None) – Destination directory. Defaults to ~/.pyiwfm/bin/{version}/.- Returns:
Downloaded executables.
- Return type:
IWFMExecutables- Raises:
RuntimeError – If the download or extraction fails.
- place_executables(exes, model_dir)[source]#
Copy executables into a model directory.
- Parameters:
exes (
IWFMExecutables) – Source executables.model_dir (
Path) – Target model directory.
- Returns:
Mapping of executable name to placed path.
- Return type:
dict[str,Path]
- verify_executables(exes)[source]#
Verify that executables can run.
Attempts to run each executable with a quick invocation to check that it is a valid binary. On Windows, passing an empty stdin typically causes IWFM exes to print usage and exit.
- Parameters:
exes (
IWFMExecutables) – Executables to verify.- Returns:
Mapping of executable name to verification status.
- Return type:
dict[str,bool]
- __init__(github_repo='', version='', config='Release', search_paths=<factory>)#
Results Differ#
Compares simulation results between baseline and written model runs.
Compare simulation results between two IWFM model runs.
Provides the critical verification step for roundtrip testing: compares heads, budgets, and hydrographs between a baseline model run and a roundtripped (written) model run.
- class pyiwfm.comparison.results_differ.HeadComparison(n_timesteps=0, n_nodes=0, max_abs_diff=0.0, mean_abs_diff=0.0, n_mismatched_timesteps=0, within_tolerance=False)[source]#
Bases:
objectResult of comparing groundwater head outputs.
- Variables:
n_timesteps (
int) – Number of timesteps compared.n_nodes (
int) – Number of nodes compared.max_abs_diff (
float) – Maximum absolute difference across all nodes and timesteps.mean_abs_diff (
float) – Mean absolute difference.n_mismatched_timesteps (
int) – Number of timesteps that exceed tolerance.within_tolerance (
bool) – True if all timesteps are within the specified tolerance.
- __init__(n_timesteps=0, n_nodes=0, max_abs_diff=0.0, mean_abs_diff=0.0, n_mismatched_timesteps=0, within_tolerance=False)#
- class pyiwfm.comparison.results_differ.BudgetComparison(name='', n_datasets=0, max_rel_diff=0.0, within_tolerance=False, details=<factory>)[source]#
Bases:
objectResult of comparing a single budget file.
- Variables:
- __init__(name='', n_datasets=0, max_rel_diff=0.0, within_tolerance=False, details=<factory>)#
- class pyiwfm.comparison.results_differ.HydrographComparison(name='', n_locations=0, min_nse=0.0, mean_nse=0.0, n_poor_matches=0, within_tolerance=False)[source]#
Bases:
objectResult of comparing hydrograph outputs.
- Variables:
name (
str) – Hydrograph file identifier.n_locations (
int) – Number of hydrograph locations compared.min_nse (
float) – Minimum Nash-Sutcliffe Efficiency across locations.mean_nse (
float) – Mean NSE across locations.n_poor_matches (
int) – Number of locations with NSE below threshold.within_tolerance (
bool) – True if all locations meet the NSE threshold.
- __init__(name='', n_locations=0, min_nse=0.0, mean_nse=0.0, n_poor_matches=0, within_tolerance=False)#
- class pyiwfm.comparison.results_differ.ResultsComparison(head_comparison=None, budget_comparisons=<factory>, hydrograph_comparisons=<factory>, final_heads_match=None, errors=<factory>)[source]#
Bases:
objectAggregate comparison of all simulation outputs.
- Variables:
head_comparison (
HeadComparison | None) – Head comparison results.budget_comparisons (
list[BudgetComparison]) – Per-budget file comparisons.hydrograph_comparisons (
list[HydrographComparison]) – Per-hydrograph file comparisons.final_heads_match (
bool | None) – Whether final heads files match.errors (
list[str]) – Any errors encountered during comparison.
- head_comparison: HeadComparison | None = None#
- budget_comparisons: list[BudgetComparison]#
- hydrograph_comparisons: list[HydrographComparison]#
- __init__(head_comparison=None, budget_comparisons=<factory>, hydrograph_comparisons=<factory>, final_heads_match=None, errors=<factory>)#
- class pyiwfm.comparison.results_differ.ResultsDiffer(baseline_dir, written_dir, head_atol=0.01, budget_rtol=0.001, nse_threshold=0.9999)[source]#
Bases:
objectCompare simulation outputs between two model runs.
- Parameters:
baseline_dir (
Path) – Directory containing baseline model outputs.written_dir (
Path) – Directory containing written (roundtripped) model outputs.head_atol (
float) – Absolute tolerance for head comparisons (ft).budget_rtol (
float) – Relative tolerance for budget comparisons.nse_threshold (
float) – Minimum NSE for hydrograph comparisons.
- __init__(baseline_dir, written_dir, head_atol=0.01, budget_rtol=0.001, nse_threshold=0.9999)[source]#
- compare_heads_hdf5()[source]#
Compare GW head outputs from HDF5 files.
Loads timesteps one-at-a-time for memory efficiency.
- Returns:
Comparison result, or None if no HDF5 head files found.
- Return type:
HeadComparison | None
- compare_heads_text()[source]#
Compare GW head outputs from text .out files.
- Returns:
Comparison result, or None if no text head files found.
- Return type:
HeadComparison | None
- compare_final_heads()[source]#
Compare FinalGWHeads.dat files with float tolerance.
- Returns:
True if they match, False if not, None if files not found.
- Return type:
bool | None
CLI Subcommands#
Package Command#
The pyiwfm package subcommand packages a model directory into a ZIP archive.
CLI subcommand for packaging an IWFM model into a ZIP archive.
Usage:
pyiwfm package --model-dir ./model [--output model.zip]
[--include-executables] [--include-results]
Run Command#
The pyiwfm run subcommand generates run scripts and optionally downloads
executables.
CLI subcommand for generating run scripts and optionally downloading executables.
Usage:
pyiwfm run --model-dir ./model [--download-executables] [--scripts-only]
[--format bat] [--format ps1] [--format sh]