Legacy SWMM 5 Output Reader#

Note

Engine: SWMM 5.x — legacy. This page documents openswmm.legacy.output.Output — the binary .out file reader that ships with the legacy compatibility layer. For the OpenSWMM 6 reader see Output reader (binary .out file).

The Output class reads the binary results file produced by:

  • The legacy SWMM 5.x solver (openswmm.legacy.engine.Solver).

  • The new OpenSWMM 6 engine (openswmm.engine.Solver) — both engines write the same on-disk format.

You can therefore use this reader with results from either engine. In new code, however, the ergonomics of openswmm.engine.OutputReader (typed enums, simpler element addressing, bulk-array methods) are usually preferable.


Class signature#

from openswmm.legacy.output import Output

class Output:
    def __init__(self, output_file: str) -> None: ...
    def __enter__(self): ...
    def __exit__(self, exc_type, exc_value, traceback): ...
  • output_file — path to a SWMM .out binary results file.

The class supports the context-manager protocol — using with is strongly recommended so the file handle closes on error.


Key methods#

File-level metadata#

Method

Returns

version()

Output-file format version.

output_size()

{element_type: count} mapping.

units()

(unit_system, flow_units, [pollutant_units]).

flow_units()

FlowUnits.

pollutant_units()

ConcentrationUnits per pollutant.

start_date()

datetime of the first reporting period.

times()

List[datetime] of every reporting time.

Element / variable enumeration#

Method

Returns

get_num_variables(element_type)()

Number of variables for that kind.

get_variable_codes(element_type)()

Variable codes for that kind.

get_num_properties(element_type)()

Number of element properties.

get_property_codes(element_type)()

Property codes for that kind.

get_property_value(et, idx, code)()

Property value for one element.

get_element_name(et, idx)()

Name of element idx.

get_element_names(element_type)()

All element names of that kind.

The ElementType enum identifies what’s being queried — ElementType.SUBCATCH, NODE, LINK, SYSTEM, POLLUTANT.

Time-series queries (one element, all times)#

Method

Returns

get_subcatchment_timeseries()

Dict[datetime, float] for one subcatch attribute.

get_node_timeseries()

Dict[datetime, float] for one node attribute.

get_link_timeseries()

Dict[datetime, float] for one link attribute.

get_system_timeseries()

Dict[datetime, float] for one system-level attribute.

Snapshot queries (all elements, one time)#

Method

Returns

get_subcatchment_values_by_time_and_attribute()

Dict[name, value]

get_node_values_by_time_and_attribute()

Dict[name, value]

get_link_values_by_time_and_attribute()

Dict[name, value]

The corresponding attribute enums are:

  • SubcatchAttribute

  • NodeAttribute

  • LinkAttribute

  • SystemAttribute

  • TimeAttribute


End-to-end example#

from openswmm.legacy.output import Output, NodeAttribute, ElementType

with Output("model.out") as out:
    print("Format version:", out.version())
    print("Flow units:    ", out.flow_units().name)
    print("Reporting times:", len(out.times()))
    print("Element counts: ", out.output_size())

    # Time series for one node:
    depth_series = out.get_node_timeseries("J1", NodeAttribute.DEPTH)
    peak_t, peak_d = max(depth_series.items(), key=lambda kv: kv[1])
    print(f"J1 peak depth: {peak_d:.3f} at {peak_t}")

    # Snapshot for every node at the final reporting time:
    last_t = len(out.times()) - 1
    depths_at_end = out.get_node_values_by_time_and_attribute(
        last_t, NodeAttribute.DEPTH,
    )
    for name, d in sorted(depths_at_end.items()):
        print(f"  {name:<12}  {d:.3f}")

Common recipes#

Plot one node’s depth time-series with matplotlib#

import matplotlib.pyplot as plt
from openswmm.legacy.output import Output, NodeAttribute

with Output("model.out") as out:
    series = out.get_node_timeseries("J1", NodeAttribute.DEPTH)
    plt.plot(list(series.keys()), list(series.values()))
    plt.title("J1 depth")
    plt.xlabel("time")
    plt.ylabel("depth")
    plt.show()

Convert a snapshot to a pandas DataFrame#

import pandas as pd
from openswmm.legacy.output import Output, LinkAttribute

with Output("model.out") as out:
    rows = []
    for t_idx, t in enumerate(out.times()):
        row = out.get_link_values_by_time_and_attribute(
            t_idx, LinkAttribute.FLOW_RATE,
        )
        row["time"] = t
        rows.append(row)
    df = pd.DataFrame(rows).set_index("time")

System-wide cumulative continuity#

from openswmm.legacy.output import Output, SystemAttribute

with Output("model.out") as out:
    ts = out.get_system_timeseries(SystemAttribute.RUNOFF_FLOW)
    total_runoff = sum(ts.values()) * (
        (out.times()[1] - out.times()[0]).total_seconds()
    )
    print(f"Total runoff volume ≈ {total_runoff:.0f}")

Exceptions#

The reader raises SWMMOutputException on file-format errors (corrupt header, mismatched version, missing pollutant section, etc.). A common cause is opening a partial file written by an aborted simulation — only files whose last write was through close() are guaranteed consistent.

from openswmm.legacy.output import Output, SWMMOutputException

try:
    with Output("aborted.out") as out:
        ...
except SWMMOutputException as e:
    print("output file unreadable:", e)

See also#