Monday, December 30, 2024

SWMMIO swmm_graphics.py Summary

 Below is an extended summary of this code, detailing how it generates both static images and interactive web maps for SWMM model elements (nodes, conduits, parcels) and what each function contributes to that workflow.


Overview

This code comprises two primary functionalities:

  1. draw_model – Generates a static image (PNG) of a SWMM model’s geometry (nodes, links, optional parcels) with optional basemap integration.
  2. create_map – Produces an interactive web map (HTML/GeoJSON) reflecting the model’s network, centering on the model’s bounding box or centroid.

By combining methods for coordinate transformation, PIL-based drawing, and HTML/JavaScript templating, the module allows users to visualize SWMM models in a flexible way—either as a static, annotated image or an interactive map in a browser.


1. draw_model Function

Purpose

draw_model orchestrates the creation of a PNG image representing SWMM model data, optionally including:

  • Nodes: Drawn as circles using a separate draw_node utility.
  • Conduits (Links): Drawn as lines with draw_conduit.
  • Parcels: (Optional) drawn as polygons (e.g., for flood-risk areas).
  • Basemap layers: If configured, it calls _draw_basemap to overlay additional shapefile-based features (streets, polygons).

Key Arguments

  • model: A swmmio.Model object (optional). If provided, the code automatically retrieves model.nodes() and model.links().
  • nodes, conduits: Pandas DataFrames containing geometry columns (e.g., coords). These can be passed directly if a model object is not used.
  • parcels: An optional DataFrame for polygon data. Each row needs a draw_coords or coordinate info.
  • title and annotation: Strings to annotate the final image with a title (top-left) and extra details (bottom-left).
  • file_path: If provided, the final PNG is saved to disk; if omitted, the PIL Image object is returned.
  • bbox: Custom bounding box for clipping. If omitted, the bounding box is derived from the data extents.
  • px_width: Desired output image width in pixels (default 2048). Internally, the function doubles this for anti-aliasing.

Workflow

  1. Data Gathering:

    • If model is provided, calls model.nodes() and model.links() for geometry.
    • Otherwise, uses the nodes and conduits DataFrames directly.
  2. Coordinate Transform:

    • Calls px_to_irl_coords to convert real-world or model coordinates into pixel coordinates.
    • Yields a bounding box and scale ratio for consistent rendering.
  3. Creating the Image:

    • Makes a PIL Image of the appropriate dimension and background color (white).
    • Obtains a Draw handle (draw = ImageDraw.Draw(img)).
  4. Basemap Layers (optional):

    • If config.include_basemap is True, calls _draw_basemap to load shapefiles from config.basemap_options and draw them in the background (e.g., roads, property boundaries).
  5. Drawing:

    • Parcels: If provided, draws each polygon using the draw_coords plus a fill color from r.draw_color.
    • Conduits: Each row is passed to draw_conduit(row, draw).
    • Nodes: Each row is passed to draw_node(row, draw).
  6. Annotation:

    • If title is given, calls annotate_title.
    • If annotation is given, calls annotate_details.
    • Always calls annotate_timestamp to add a timestamp in the top-right corner.
  7. Saving or Returning the Image:

    • If file_path is specified, calls save_image(img, file_path) (which can do an antialias thumbnail and optionally open the file).
    • Otherwise, returns the img object directly—useful in Jupyter notebooks or for further processing in memory.

Typical Use

my_image = draw_model(
    model=my_swmm_model,
    title="Example Model",
    annotation="Beta version",
    file_path="example_model.png",
    bbox=((2691647, 221073), (2702592, 227171)),
    px_width=2048
)

2. create_map Function

Purpose

Creates an interactive web-based map (HTML + GeoJSON) displaying the SWMM model’s geometry. This approach uses a map template (e.g., from BETTER_BASEMAP_PATH) where placeholders are replaced with:

  • The model’s centroid and bounding box, to position and bound the map.
  • The model’s links.geojson and nodes.geojson data (assuming model has .geojson properties).

Arguments

  • model: A swmmio.Model object that presumably includes .nodes.geojson and .links.geojson.
  • filename: Destination HTML file path. If not provided, the function returns the generated HTML as a string.
  • basemap: A path to an HTML template with placeholders.

Workflow

  1. CRS Check: If model.crs is known, tries to transform the model coordinates to EPSG:4326 for web mapping.
  2. Compute centroid and bounding box from the model’s inp.coordinates (via centroid_and_bbox_from_coords).
  3. Read the basemap template file line by line.
  4. Insert relevant data:
    • conduits = <geojson dumps of model.links.geojson>
    • nodes = <geojson dumps of model.nodes.geojson>
    • map center from the centroid [lng, lat].
    • fitBounds calls from the bounding box.
  5. Write the final HTML to the filename.
    • If filename is None, the result is returned as a string.

Typical Use

html_content = create_map(model=my_swmm_model, filename=None)

# This returns the HTML as a string, which can be displayed in a Jupyter notebook via IFrame or written to file manually

Supporting Elements

_draw_basemap(draw, img, bbox, px_width, shift_ratio)

  • Called internally by draw_model if config.include_basemap is True.
  • Iterates over features in config.basemap_options['features'], reads shapefiles, transforms them to pixel coords, and draws lines or polygons.
  • If columns like ST_NAME exist, it calls annotate_streets to place text.

import statements

  • PIL (Image, ImageDraw) for static image creation.
  • swmmio.graphics.config and swmmio.defs.constants for color definitions and user preferences (like white background).
  • px_to_irl_coords, save_image from swmmio.graphics.utils: handle geometry transformations and final image saving.
  • draw_node, draw_conduit from swmmio.graphics.drawing: actual shape-drawing functions for SWMM nodes/links.
  • spatial modules for shapefile reading (spatial.read_shapefile) and coordinate conversions.
  • centroid_and_bbox_from_coords for bounding box logic.

Why These Functions Are Useful

  1. Versatile Visualization:

    • draw_model suits quick static diagrams for reports, screenshots, or docs.
    • create_map suits interactive exploration—useful for large networks or checking node/link attributes in detail.
  2. Easy Integration:

    • Because the code references typical SWMM data structures (from model.nodes(), model.links()), it plugs directly into swmmio’s data pipeline.
  3. Customizable:

    • By adjusting parameters like px_width, bbox, or passing in your own DataFrames, you can refine your map’s resolution and coverage.
    • The code can also incorporate external shapefiles for background context (streets, administrative boundaries) via _draw_basemap.

Example End-to-End Usage

  1. Create/Load a SWMM Model:
    from swmmio import Model
    my_model = Model("example_model.inp")
    
  2. Generate a Static PNG:
    draw_model(
        model=my_model,
        title="My SWMM Model Visualization",
        annotation="Preliminary results",
        file_path="my_model_viz.png",
        px_width=2048
    )
    
  3. Generate an Interactive Map:
    map_html = create_map(my_model, filename="my_model_map.html", auto_open=True)
    # This writes an HTML file that references the model's geojson data.
    # If auto_open=True is implemented, it might automatically open in a web browser (depending on OS).
    

Conclusion

Through draw_model and create_map, this code seamlessly visualizes SWMM networks in static or interactive formats:

  • draw_model: Renders a color-coded, labeled 2D PNG from a SWMM model or user-supplied DataFrames.
  • create_map: Creates a Leaflet-style HTML page embedding the model as geojson for dynamic panning/zooming.

These functionalities enhance the analysis workflow by allowing engineers, researchers, and stakeholders to quickly see how a model’s nodes, links, or external shapefile-based layers align, and to share results in either a simple image or an interactive, browsable map.

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...