Monday, December 30, 2024

PYSWMM output.py Summary

 Below is an extended summary of this code, which focuses on reading and accessing data from a SWMM output (.out) file via a Python interface. It describes the purpose, structure, and usage of each class, along with relevant methods and decorators.


Overview

This module provides a robust way to interact with SWMM’s output binary files in Python. It allows users to:

  1. Open or close SWMM output binary files.
  2. Query time-series data for subcatchments, nodes, links, and the overall system.
  3. Retrieve, filter, and present simulation results as Python dictionaries keyed by timestamps.
  4. Easily integrate with pandas or other data-processing tools, thanks to dictionary-based outputs.

Key elements include:

  • Output class: Core functionality for opening and querying the binary file.
  • output_open_handler decorator: Ensures an output file is opened before any function runs.
  • Classes like SubcatchSeries, NodeSeries, LinkSeries, and SystemSeries: High-level objects that map SWMM attributes (rainfall, flow rate, infiltration, etc.) into time-indexed Python dictionaries.

Core Functionality

1. Output Class

Purpose: Manages a SWMM output (.out) file, including opening/closing it, reading metadata (like start time, end time, number of periods), and fetching results in various formats.

Key Methods and Properties:

  1. File Handling

    • open(): Initializes an internal handle to the output file. Loads critical info such as start date/time, reporting interval, total periods, etc.
    • close(): Closes the file and cleans up the internal handle.
    • __enter__ / __exit__: Implements Python’s context-manager protocol (with statement), ensuring that the file automatically opens and closes.
  2. Project/Simulation Metadata

    • project_size: Returns counts for subcatchments, nodes, links, system objects, and pollutants.
    • start, end, report, period: Start date/time, end date/time, reporting interval (in seconds), and number of reporting periods.
    • version: Returns the SWMM engine version used to produce this output file.
    • units: Shows the user’s unit system (US or SI), flow units (CFS, CMS, etc.), and pollutant units.
  3. Model Element Dictionaries

    • subcatchments, nodes, links, pollutants: Each returns a dict mapping element IDs (e.g., “J1”, “C2”, “S1”) to integer indices. These indices are needed to make calls into the underlying SWMM output toolkit.
  4. Time Management

    • times: A list of datetime objects for each reporting period in the simulation.
    • Internally, times are generated by starting at self.start and incrementing in steps of self.report seconds.
  5. Retrieving Data

    • subcatch_series, node_series, link_series, system_series: Time-series retrieval for a single object (subcatch/node/link) or the entire system.
      • Returns a dictionary of { datetime: value }.
    • subcatch_attribute, node_attribute, link_attribute: Snapshots of a single attribute for all subcatchments/nodes/links at a single time index.
    • subcatch_result, node_result, link_result: Returns all attributes for a single subcatchment/node/link at a single time index.
    • system_result: Returns a dictionary of system-wide attributes (e.g., total runoff, infiltration) at a single time index.
  6. Validation Helpers

    • verify_index(...): Ensures a user-provided ID or index is valid for a given subcatchment/node/link dictionary.
    • verify_time(...): Converts a user-supplied datetime or integer index into a valid time-step index. Raises exceptions if the time/index is out of range.

2. output_open_handler Decorator

  • Ensures that before any method runs (e.g., subcatch_series, node_attribute), the output file is open.
  • If self.loaded is False, it calls self.open() to establish a handle.
  • This decorator simplifies code by allowing users to call methods directly without worrying about manually opening the output file first.

3. High-Level Series Classes

  1. SubcatchSeries

    • Usage: SubcatchSeries(out_handle)[‘S1’].rainfall
    • Each property (e.g., .rainfall, .snow_depth) yields a time-series dictionary for the specified subcatchment.
    • Internally calls Output.subcatch_series(...).
  2. NodeSeries

    • Usage: NodeSeries(out_handle)[‘J1’].invert_depth
    • Maps node attributes like INVERT_DEPTH, HYDRAULIC_HEAD, etc. to time-series dictionaries.
  3. LinkSeries

    • Usage: LinkSeries(out_handle)[‘C1:C2’].flow_rate
    • Provides link attributes such as FLOW_RATE, FLOW_DEPTH, FLOW_VELOCITY.
  4. SystemSeries

    • Usage: SystemSeries(out_handle).runoff_flow
    • No element ID needed (the entire system is a single entity).
    • Returns time-series data for system-level attributes (e.g., total rainfall, total inflow, outflow).

Common Patterns:

  • Each of these series classes inherits from OutAttributeBase, which implements:
    • A dynamic __getattr__ that interprets attribute names (e.g., .flow_rate) and calls the underlying PySWMM methods.
    • A _series_type(...) helper method that routes to Output methods like .subcatch_series, .node_series, etc.

4. Example Usage

from pyswmm import Output, NodeSeries

# 1) Open a SWMM output file via the context manager
with Output("my_model.out") as out:
    # 2) Access metadata
    print("Start Time:", out.start)
    print("End Time:", out.end)
    print("Number of Nodes:", len(out.nodes))

    # 3) Retrieve time-series data for a specific node
    node_data = NodeSeries(out)["J1"].total_inflow
    for time, inflow_value in node_data.items():
        print(time, inflow_value)

    # 4) Retrieve a single time snapshot for all nodes
    snapshot_16h = out.node_attribute(
        attribute=shared_enum.NodeAttribute.INVERT_DEPTH,
        time_index=datetime(2020, 1, 1, 16, 0)
    )
    print(snapshot_16h)  # {"J1": 10.2, "J2": 12.3, ...}

Benefits and Applications

  1. Simplicity: Users can retrieve SWMM results using Python dictionaries keyed by datetime, making integration with other data libraries (like pandas or matplotlib) straightforward.

  2. Flexibility:

    • Retrieve results by time (snapshot across many objects) or by object (time-series for a single subcatchment/node/link).
    • Retrieve single attributes or all attributes at once.
  3. Error Handling:

    • Clear exceptions (OutputException) if an ID or time-step is invalid.
    • Decorators ensuring the file is open before data retrieval.
  4. Separation of Concerns:

    • Output handles low-level file reading and indexing.
    • SubcatchSeries, NodeSeries, LinkSeries, and SystemSeries provide higher-level, user-friendly interfaces to time-series data.

Conclusion

This code presents a comprehensive Python interface for processing SWMM output files. By abstracting the SWMM toolkit’s C-based calls into intuitive classes and decorators, it gives modelers and data scientists convenient access to simulation results at different levels (subcatchment, node, link, or entire system). Thanks to dictionary-based returns keyed by timestamps, it integrates naturally with Python’s ecosystem for data analysis and visualization, ultimately streamlining the post-processing workflow for stormwater and hydrological modeling projects.

No comments:

A comprehensive explanation of how minimum travel distance relates to link length in InfoSewer

In hydraulic modeling of sewer networks, the minimum travel distance is a fundamental parameter that affects how accurately the model can si...