Skip to content

Read binary output

Use OutputReader for report-period series, not for live solver observations. It owns an independent worker and can read output after the simulation has closed. Pass file contents, not a host path; in Node, use bytes from fs.readFile(). See Load files and download output for file handling.

Query selected columns

This example assumes the output contains node J1:

import { OutputReader, type FileContents } from "@swmmrs/swmmrs";

export async function readHead(input: FileContents) {
    const reader = await OutputReader.open(input);
    try {
        console.log(reader.metadata.runStatus, reader.metadata.flowUnits);
        return await reader.readBulkSeries([
            { elementType: "node", element: "J1", attribute: "hydraulic_head" },
            { elementType: "system", element: null, attribute: "volume_stored" },
        ], { lowMemory: true });
    } finally {
        await reader.close();
    }
}

The columns share a nominal report-date axis. Keep their selection labels with the values rather than relying on column positions alone. Returned arrays and metadata are immutable and remain usable after closing the reader.

Inspect before selecting

Check metadata.runStatus when processing interrupted runs: a readable file can contain complete periods without a finalized trailer, and finalized output can record an unsuccessful solver status. Inspect metadata.resultSchema to learn which attributes are actually present.

Use metadata indices or exact stored names. Output-name matching is case-sensitive, unlike simulation collection lookup. For names that are not valid UTF-8, retain OutputName or its raw bytes instead of replacing invalid characters. Unknown categorical codes are retained so applications can inspect newer output formats.

Pollutant columns use { selector: pollutant } rather than a built-in attribute name. The selector can be a pollutant index, exact name, raw bytes, or metadata name. System results do not have pollutant columns.

Choose a range and memory strategy

Use start and end to select a half-open report-period range. Integer bounds are period offsets; calendar bounds locate nominal report dates, not simulation routing steps. Omitted bounds select all available complete periods.

For large files, select only the columns and periods needed. lowMemory: true changes the read strategy without changing values. Duplicate selections remain separate columns, so de-duplicate them yourself when repetition is unintended.

The normal time axis is rounded and follows the nominal reporting schedule. Use readStoredDates() when you need the exact SWMM serial-day values stored in the file. Neither axis changes the observation cadence of Simulation.steps().

See the Binary output reference for selectors, units, bounds, errors, and every metadata and result field.