Basic Usage
Overview
epanetparser provides a command-line utility for validating EPANET models,
and a Python library which may be used to parse and validate EPANET networks.
This section covers the command-line utility. Use of the library is described in the The epanetparser Library section, and the rule set mechanism in Rules, Warnings, and Rule Sets.
Installation
epanetparser requires Python 3.10 or later, and can be installed with either
Poetry or pip:
$ git clone git@github.com:tomjanus/epanetparser.git
$ cd epanetparser
$ poetry install
Or using pip:
$ git clone git@github.com:tomjanus/epanetparser.git
$ cd epanetparser
$ pip install .
To display the usage guide:
$ epanetparser -h
Usage: epanetparser [-h] [--version] ...
Parser and validator of EPANET water distribution network models.
Options:
-h, --help show this help message and exit
--version Display the version of epanetparser
Available Commands:
download-extra
Download additional networks from GitHub release for testing
and benchmarking
validate Validate an EPANET model and display results
convert Convert between EPANET's native INP format and WNTR JSON
format
info Display information about the EPANET parser
For further information, please visit https://tomjanus.github.io/epanetparser
Validation
The basic operation of the epanetparser validate command validates an EPANET
model and returns either:
A report describing a valid model, along with any warnings raised during validation
A report detailing the errors that made the model invalid
An exception, if the input could not be parsed at all
$ epanetparser validate --help
Usage: epanetparser validate [-h] -f <filename> [--ruleset <ruleset>]
[--list-rulesets] [--raise-on-warning]
[--ignore-warnings] [--raise-on-error]
[--json-output] [--pretty-output] [--no-emoji]
[--no-colour] [--terse-report] [--no-digest]
Options:
-h, --help show this help message and exit
-f, --filename <filename>
File containing an EPANET model in INP or WNTR JSON
format
Validation Options:
--ruleset <ruleset> Add a custom ruleset to the core ruleset. May be given
more than once to apply several, e.g. --ruleset milp
--ruleset project
--list-rulesets List the available rulesets and exit
--raise-on-warning Treat warnings as failures, so the exit status is
non-zero
--ignore-warnings Omit warnings from the report
--raise-on-error Raise a structural parsing problem as an exception
instead of reporting it
Display Options:
--json-output Display parsing report in JSON format for machine
reading
--pretty-output Display parsing report on the console with colour
(default)
--no-emoji Omit emoji in console parsing reports
--no-colour Omit colour output in console parsing reports. Implies
--no-emoji
--terse-report Display only a terse report for valid networks
--no-digest Omit sha256 digest in JSON and dict parsing reports
Both INP and WNTR JSON files are accepted. An .inp file is converted to
WNTR’s JSON representation with WNTR before being parsed.
An invalid model produces a report categorised by component, with each finding carrying a stable code:
$ epanetparser validate -f invalid_network.json --no-digest
─────────────────────────────────────── 1 ───────────────────────────────────────
🔴 1 'E_CURVE_TYPE_UNSUPPORTED' -> Unsupported curve type None
─────────────────────────────────────────────────────────────────────────────────
File: invalid_network.json
Nodes: 785
Links: 909
Curves: 1
Patterns: 3
Controls: 2
The code, rather than the message text, is the stable identifier, so downstream tooling can match on it without depending on wording.
This report may be customised with the various configuration options described
in the Display Options section of the output from epanetparser validate -h.
A valid model is one for which no error is raised. Warnings inform without blocking. Validating a valid model results in a brief summary of the model, and nothing more:
$ epanetparser validate -f valid_network.json --no-digest
File: valid_network.json
Nodes: 785
Links: 909
Curves: 1
Patterns: 3
Controls: 2
The --no-digest option causes the report to omit calculation and display of
the SHA256 digest, which may improve performance for large files on slow systems.
The --terse-report option causes only a summary of the numbers of each
component defined in the model to be displayed:
$ epanetparser validate -f valid_network.json --terse-report
{'nodes': 785, 'links': 909, 'curves': 1, 'patterns': 3, 'controls': 2}
This is useful where the output is intended to be consumed by an automated process.
The --json-output option provides the full report as JSON, for machine
reading. The top level carries validity, per-severity counts, and the issues
themselves:
$ epanetparser validate -f invalid_network.json --json-output --no-digest
{
"is_valid": false,
"counts": {
"ERROR": 2,
"WARNING": 1,
"INFO": 0
},
"issues": [
{
"code": "E_NETWORK_NAME_MISSING",
"message": "Network missing a name",
"severity": "ERROR",
"rule_id": "rule_network_has_name",
"ruleset_key": "epanet_core",
"component_type": "WNTREPANETNetworkInfo",
"component_name": null,
"attribute": "name",
"context": {
"ruleset": "epanet_core",
"component_subtype": "network_info"
}
},
...
]
}
Exit status
The exit status says whether the model is usable, so the command composes with a build or a test:
0 the model parsed and validated with no errors
1 bad usage: an unknown ruleset, or an unreadable file with --raise-on-error
2 the model parsed but is invalid, or warned and --raise-on-warning was given
$ epanetparser validate -f invalid_network.json --no-digest
$ echo $?
2
Selecting a rule set
Exactly one core rule set is applied to every run. Custom rule sets are added
with --ruleset, which may be given more than once:
$ epanetparser validate -f model.json --ruleset milp --ruleset project
To see what is available:
$ epanetparser info --list-rulesets
Available rule sets:
epanet_core (core) - EPANET core rules v1.0.0
module: epanetparser.core_rules.epanet_core
rules: 35 component, 9 network
Simulator-agnostic checks that a model is a well-formed EPANET model:
required component fields, valid component types, well-formed curves,
unique component names, and resolvable references between components.
milp (custom) - Mixed Integer Linear Programming ruleset v0.2.0
module: epanetparser.custom_rules.milp
rules: 17 component, 0 network
Constraints imposed by an example MILP optimal pump scheduling tool.
Adding a custom rule set is how an application imposes its own restrictions on a model. See Rules, Warnings, and Rule Sets for the mechanism.
Converting between formats
The convert subcommand translates between EPANET’s native INP format and
WNTR’s JSON format. The direction is inferred from the input extension:
$ epanetparser convert Net1.inp Net1.json
✓ Converted INP to JSON: Net1.json
$ epanetparser convert Net1.json roundtrip.inp
✓ Converted JSON to INP: roundtrip.inp
The output filename is optional. Omitted, the input name is reused with the extension swapped:
$ epanetparser convert Net1.inp
✓ Converted INP to JSON: Net1.json
Two options control the output. --indent sets JSON indentation, defaulting
to 2 spaces. --epanet-version selects the EPANET version targeted when
writing INP, defaulting to 2.2:
$ epanetparser convert Net1.inp Net1.json --indent 4
$ epanetparser convert Net1.json Net1.inp --epanet-version 2.0
Downloading additional networks
Additional benchmark networks are published as GitHub releases and can be fetched for testing:
$ epanetparser download-extra --progress
Inspecting rule sets
The epanetparser-plugins command inspects the discovered rule sets in more
detail than info --list-rulesets provides:
$ epanetparser-plugins list
$ epanetparser-plugins show --ruleset milp
$ epanetparser-plugins show --ruleset epanet_core --component WNTREPANETNode
Discovery is cached. After installing a new rule set package, discard the cache so it is rescanned:
$ epanetparser-plugins refresh
Configuration
On first import, epanetparser writes a configuration file to a
platform-specific location:
Linux:
~/.config/epanetparser/default_config.yamlmacOS:
~/Library/Application Support/epanetparser/default_config.yamlWindows:
%APPDATA%\\epanetparser\\default_config.yaml
Your settings are merged with the package defaults, with yours taking
precedence, and the merge is recursive: a file need only set the keys it wants
to change. The rule set search paths live under rule_set_discovery, and this
file, not pyproject.toml, is the single source of truth for them:
rule_set_discovery:
packages:
- epanetparser.core_rules
- epanetparser.custom_rules
extra_packages: []
Add your own package under extra_packages. The merge substitutes lists
rather than extending them, so packages replaces the list above while
extra_packages appends to it. The built-in packages are always searched
first, so a shorter packages cannot drop the core rule set.
rule_set_discovery:
extra_packages:
- my_project.rulesets
A malformed file is reported with its path and line rather than ignored, so a typo fails loudly instead of silently reverting you to the defaults.