Skip to content

Latest commit

 

History

10 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

InfoDrainage Python Package (iddx_core)

A pure-Python toolkit for programmatically reading, writing, and manipulating Autodesk InfoDrainage .iddx project files and their SWMM simulation results. Zero required dependencies.

Installation

Option 1: Install with pip

pip install .

This installs the iddx-core package and the iddx command-line tool. The core library has zero external dependencies — it uses only Python's built-in xml.etree.ElementTree and struct.

Optional dependencies

Install extras for additional features:

pip install ".[plotting]"     # matplotlib for charts and graphs
pip install ".[simulation]"   # pyswmm for running SWMM simulations
pip install ".[network]"      # networkx for graph-based network analysis
pip install ".[all]"          # everything

Option 2: Clone from GitHub

git clone https://github.com/jcholly/InfoDrainage-Python-Package.git
cd InfoDrainage-Python-Package
pip install -e .

Option 3: Copy into an existing project

Copy the iddx_core/ folder into your project directory. That's the entire package — zero dependencies.

Requirements

  • Python 3.10+
  • No pip install needed for the core library — it uses only Python built-ins

Verify it works

python -c "from iddx_core import IddxModel; print('iddx_core is ready')"

Or with the CLI:

iddx --version

Security considerations

iddx_core is designed for parsing .iddx and .out files from trusted sources (your own InfoDrainage projects, files from collaborators, files generated by simulation runs you control).

The library hardens the binary .out parser against malformed and adversarial inputs (file-size caps, count/offset validation, string-length bounds), so a corrupt or malicious result file will raise ResultsError rather than hang or exhaust memory. CSV exports are also escaped against formula injection.

The XML parser uses Python's standard xml.etree.ElementTree, which since Python 3.7.1 disables external entity resolution (no XXE / file-disclosure / SSRF). Entity-expansion DoS (the "billion laughs" pattern) is still theoretically possible from a hostile .iddx — if you parse .iddx files from untrusted sources, install defusedxml and replace ET.parse calls in the library, or sandbox the process.


Command-Line Interface

After installing with pip install ., the iddx command is available system-wide.

iddx summary — Model inventory

Print a full inventory of any .iddx file, including phases, rainfall sources, and available SWMM result files.

iddx summary project.iddx

iddx pipes — Pipe schedule

Export a pipe schedule for a phase, either to the console or to CSV.

iddx pipes project.iddx                          # print to console (first phase)
iddx pipes project.iddx --phase "Proposed"        # specific phase
iddx pipes project.iddx --csv pipe_schedule.csv   # export to CSV

iddx compare — Compare SWMM results

Compare peak flows, flooding, and velocities across all scenarios and return periods. Reads the SWMM .out binary files generated by InfoDrainage analysis.

iddx compare project.iddx                    # print comparison table
iddx compare project.iddx --csv results.csv  # export to CSV

iddx validate — Design validation

Run automated design checks against the model definition and SWMM simulation results.

Model checks (no results needed):

  • Cover depth violations (invert above cover, cover less than pipe diameter)
  • Adverse or zero slopes
  • Invalid or unusual Manning's n values
  • Junction depth errors
  • Broken connectivity (GUIDs referencing missing nodes)
  • Missing outfalls
  • Zero-area catchments

SWMM results checks (requires analysis to have been run):

  • Node flooding detected in simulation output
  • Link surcharging (capacity ratio > 1.0)
  • Low velocity — self-cleansing risk (< 0.6 m/s)
  • High velocity — erosion risk (> 6.0 m/s)
iddx validate project.iddx                    # validate first phase
iddx validate project.iddx --phase "Proposed" # specific phase

Exit code 1 if any errors are found, 0 if only warnings or clean.

Global options

iddx --version        # print version
iddx -v summary ...   # verbose/debug logging

Quick Start (Python API)

1. Open a model and print a summary

from iddx_core import IddxModel

model = IddxModel.open(r"C:\path\to\project.iddx")

for label, phase in model.phases.items():
    s = phase.summary()
    print(f"{label}: {s['catchments']} catchments, {s['junctions']} junctions, {s['connections']} pipes")

2. Change all catchment runoff coefficients and save

from iddx_core import IddxModel

model = IddxModel.open(r"C:\path\to\project.iddx")
phase = model.phases["Proposed"]

for catchment in phase.catchments:
    catchment.cv = 0.85

model.save(r"C:\path\to\updated.iddx")

Open updated.iddx in InfoDrainage — every catchment now shows CV = 0.85.

3. Create scenario variations

from iddx_core import IddxModel

model = IddxModel.open(r"C:\path\to\project.iddx")

for pimp in [40, 60, 80, 95]:
    new_phase = model.clone_phase("Proposed", f"PIMP {pimp}%")
    for c in new_phase.catchments:
        c.pimp = pimp

model.save(r"C:\path\to\scenarios.iddx")

This creates 4 new phases, each with a different percent impervious. Open in InfoDrainage and run all scenarios at once.


Example Scripts

The examples/ folder contains ready-to-run scripts. Each one accepts a file path as an argument, or uses a built-in default.

Script What it does
01_model_summary.py Print a full inventory of any .iddx file
02_pipe_schedule_csv.py Export a pipe schedule to CSV
03_bulk_update_cv.py Change the runoff coefficient on every catchment
04_sensitivity_study.py Generate 10 scenario phases varying CV, PIMP, and area
05_cover_depth_check.py QA check: flag pipes with less than X feet of cover
06_create_model.py Build a complete model from scratch
07_compare_phases.py Side-by-side comparison of catchment data across phases
08_read_results.py Read SWMM simulation results: peak flows, depths, flooding
09_demo4_scenarios.py Generate 30 scenarios varying orifice and runoff parameters
10_pond_depth_graph.py Pond depth time series graph
10_compare_scenario_results.py Compare SWMM results across scenarios and export CSV

Run an example:

cd InfoDrainage-Python-Package
python examples/01_model_summary.py "C:\path\to\project.iddx"

What can you do with this?

Use case How
Batch modify catchments Loop over phase.catchments, change .cv, .pimp, .area, save
Generate sensitivity studies model.clone_phase() with different parameters per scenario
Export pipe schedules iddx pipes project.iddx --csv or loop over phase.connections
QA / design validation iddx validate project.iddx or custom checks in Python
Build models programmatically IddxModel.new() + add catchments, junctions, pipes from data
Compare design iterations Read multiple .iddx files and compare element counts/properties
Read SWMM results ResultsReader parses .out files for peak flows, depths, flooding
Compare storms iddx compare or load_results() to compare peaks across return periods
Read inlet HEC-22 config Access inlet.hec22_config.gutter, .combo, .grate for full sizing params
Edit inlet sizing Modify gutter slope, grate dimensions, clogging, depression and save back
Audit bypass connections Filter phase.connections with .is_bypass, inspect cross-sections
Automate bypass routing Create CustomCon bypass connections between inlets programmatically

API Reference

Core Classes

Class Description
IddxModel Top-level model. IddxModel.open() to read, .save() to write, .new() to create from scratch. Supports with for context-manager use.
Phase A design scenario containing all network elements. Access via model.phases["name"]. find_*(label) returns None if missing; get_*(label) raises ElementNotFoundError.
Catchment Inflow area. Key properties: .label, .area, .cv (alias .runoff_coefficient), .pimp (alias .percent_impervious), .runoff_method
Junction Manhole, inlet, or outfall. Key properties: .label, .cover_level, .invert_level, .is_outfall
DrainageSystem Stormwater control (pond, tank, swale, etc.). Key properties: .label, .system_type, .depth
Connection Pipe, channel, or bypass. Key properties: .label, .diameter, .length, .mannings_n, .is_bypass
Hec22InletConfig HEC-22 inlet sizing inputs. Key properties: .hec22_inlet_type, .gutter, .grate, .combo, .curb, .slotted
CrossSectionDetails Custom cross-section for bypass connections. Key properties: .points, .con_covered
RationalResults Rational-method design results on a connection (read-only). Key properties: .flow, .velocity, .capacity
UpstreamTotals Accumulated upstream area/flow totals on a connection (read-only). Key properties: .area, .contributing_area
RainfallSource Rainfall data (NOAA, FEH, etc.). Key properties: .label, .return_periods
ResultsReader Read SWMM simulation results from .out files. Key methods: .node_summary(), .link_summary(), .node_time_series(), .link_time_series()

Exceptions

Exception When raised
IddxError Base exception for all iddx_core errors
IddxParseError .iddx file cannot be parsed (missing, corrupt, invalid XML)
IddxValidationError Model data fails a validation check
ResultsError SWMM .out file cannot be read (missing, corrupt, wrong format)
ElementNotFoundError Requested element (junction, catchment, link, phase) not found
from iddx_core import IddxModel, IddxParseError, ResultsError

try:
    model = IddxModel.open("project.iddx")
except IddxParseError as e:
    print(f"Cannot open model: {e}")

try:
    results = ResultsReader("missing.out")
except ResultsError as e:
    print(f"Cannot read results: {e}")

Key Enumerations

Enum Values
RunoffMethod RATIONAL, SCS_CURVE_NUMBER, SWMM, STATIC, FOUL, and others
DrainageSystemType POND, SWALE, BIORETENTION, POROUS_PAVEMENT, CHAMBER, TANK
ConnectionType CIRCULAR_PIPE, BOX_CULVERT, TRAPEZOIDAL_CHANNEL, TRIANGULAR_CHANNEL, CUSTOM_BYPASS
Hec22InletType GRATE, CURB, COMBINATION, SLOTTED
InletCapacityType NONE, LOW_HIGH_FLOW, RATED_BY_FLOW, HEC_22
InletLocation ON_GRADE, IN_SAG
OutletType FLOW_CONTROL, ORIFICE, WEIR, COMPLEX, PUMP, FREE_OUTLET

Common Operations

from iddx_core import IddxModel, Catchment, Junction, Connection

# Open
model = IddxModel.open("project.iddx")

# Access phases
phase = model.phases["Proposed"]
print(phase.summary())

# Find elements by label
j = phase.find_junction("MH-1")
c = phase.find_catchment("Site-A")

# Modify
c.cv = 0.90
c.pimp = 80

# Clone a phase
new_phase = model.clone_phase("Proposed", "High Density")

# Add new elements
phase.add_junction(Junction(label="MH-NEW", x=100, y=200, cover_level=250, invert_level=247))

# Access rainfall
for rs in model.rainfall_sources:
    storm = rs.get_storm(100.0)  # 100-year storm
    if storm:
        print(f"100-yr depth: {storm.total_depth:.2f}")

# Save
model.save("updated.iddx")

Reading SWMM Simulation Results

After running analysis in InfoDrainage, results are saved as SWMM .out binary files in a subfolder next to the .iddx file.

from iddx_core import IddxModel, ResultsReader, find_results, load_results, build_label_map

# Find all SWMM result files for a project
result_files = find_results(r"C:\path\to\project.iddx")
for phase, files in result_files.items():
    print(f"{phase}: {len(files)} storms analyzed")

# Load a single SWMM result file
results = ResultsReader(r"C:\path\to\project\Proposed_100.000_1440.00.out")
print(f"Nodes: {len(results.node_ids)}, Links: {len(results.link_ids)}")
print(f"Periods: {results.num_periods}, Interval: {results.report_interval_seconds}s")

# Get peak results for all links (cross-reference with model for labels)
model = IddxModel.open(r"C:\path\to\project.iddx")
label_map = build_label_map(model)

for ls in results.all_link_summaries(label_map):
    if ls.peak_flow > 0.001:
        print(f"{ls.label}: peak flow = {ls.peak_flow:.4f}")

# Get a full time series from SWMM output
ts = results.link_time_series(results.link_ids[0], variable="flow_rate")
print(f"Peak flow: {ts.peak:.4f} at {ts.peak_time}")

# Compare peak flows across return periods
all_results = load_results(r"C:\path\to\project.iddx")
for rp, r in sorted(all_results["Proposed"].items()):
    ls = r.link_summary(results.link_ids[0])
    print(f"{rp:.0f}-yr: {ls.peak_flow:.4f}")

Package Structure

InfoDrainage-Python-Package/
├── pyproject.toml               <- Package metadata, dependencies, CLI entry point
├── README.md                    <- This file
├── iddx_core/                   <- The Python package
│   ├── __init__.py              <- Public API exports (v0.4.2)
│   ├── model.py                 <- IddxModel (open/save/create)
│   ├── phase.py                 <- Phase (scenario container)
│   ├── nodes.py                 <- Catchment, Junction, DrainageSystem, HEC-22 inlet classes
│   ├── connections.py           <- Connection (pipes, channels, bypass), CrossSection, RatRes
│   ├── rainfall.py              <- RainfallSource, StormEvent
│   ├── results.py               <- ResultsReader (read SWMM .out binary files)
│   ├── enums.py                 <- RunoffMethod, OutletType, Hec22InletType, etc.
│   ├── utils.py                 <- XML helpers, GUID generation
│   ├── exceptions.py            <- Typed exceptions (IddxParseError, ResultsError, etc.)
│   └── cli.py                   <- Command-line interface (iddx command)
└── examples/                    <- Ready-to-run example scripts

Changelog

0.4.2

  • Fixed: Bypass connections (CustomCon) were silently dropped during model parsing — added CUSTOM_BYPASS to ConnectionType and CustomCon to ALL_CONNECTION_TAGS
  • Added full HEC-22 inlet configuration parsing: Hec22InletConfig, GutterDetail, GrateInletParams, CurbInletParams, ComboInletParams, SlottedInletParams
  • InletDetail now reads and writes the complete HEC22InCapDet XML block (gutter geometry, grate/curb/combo/slotted sizing params, clogging, depression, location)
  • Added CrossSectionDetails — parses custom cross-section geometry on bypass connections (CrsSctDetails)
  • Added RationalResults — parses rational-method design output (RatRes) on connections
  • Added UpstreamTotals — parses accumulated upstream totals (USTot) on connections
  • Added Connection.is_bypass property and Connection.conduit_height_user field
  • New enums: Hec22InletType, InletCapacityType, InletLocation
  • Round-trip verified: 32 bypass connections and 43 HEC-22 inlets preserved through save/reload

0.4.1

  • Fixed: Inlet edits now persist on save — Junction.to_xml() and DrainageSystem.to_xml() re-serialize inlets from Python objects instead of keeping stale raw XML
  • Fixed: InletDetail now reads and writes all XML fields: Type, ICapType, Dest, BCGUID (bypass destination)
  • Added InletDetail.from_xml() / .to_xml() methods for proper round-trip serialization
  • Added Hec22Results dataclass — reads HEC-22 inlet capacity results (approach flow, bypass flow, captured flow, spread, depth) from the XML
  • Added InletDetail.capacity_type, .inlet_type, .bypass_dest_guid, .bypass_dest_label properties
  • Exported InletDetail, InletSource, and Hec22Results from iddx_core

0.4.0

  • Added pyproject.toml — installable via pip install . with optional dependency groups
  • Added iddx CLI with summary, pipes, compare, and validate commands
  • Added typed exceptions: IddxError, IddxParseError, IddxValidationError, ResultsError, ElementNotFoundError
  • Added structured logging via Python logging module
  • Design validation checks model data and cross-references SWMM simulation results
  • SWMM results checks: flooding, surcharging, velocity (self-cleansing and erosion limits)

0.3.0

  • Initial public release
  • Read/write .iddx project files
  • Parse SWMM .out binary result files
  • Phase cloning, scenario comparison, CSV export

About

No description, website, or topics provided.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages