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:
draw_model– Generates a static image (PNG) of a SWMM model’s geometry (nodes, links, optional parcels) with optional basemap integration.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_nodeutility. - 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_basemapto overlay additional shapefile-based features (streets, polygons).
Key Arguments
model: Aswmmio.Modelobject (optional). If provided, the code automatically retrievesmodel.nodes()andmodel.links().nodes,conduits: Pandas DataFrames containing geometry columns (e.g.,coords). These can be passed directly if amodelobject is not used.parcels: An optional DataFrame for polygon data. Each row needs adraw_coordsor coordinate info.titleandannotation: 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 PILImageobject 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
-
Data Gathering:
- If
modelis provided, callsmodel.nodes()andmodel.links()for geometry. - Otherwise, uses the
nodesandconduitsDataFrames directly.
- If
-
Coordinate Transform:
- Calls
px_to_irl_coordsto convert real-world or model coordinates into pixel coordinates. - Yields a bounding box and scale ratio for consistent rendering.
- Calls
-
Creating the Image:
- Makes a PIL
Imageof the appropriate dimension and background color (white). - Obtains a
Drawhandle (draw = ImageDraw.Draw(img)).
- Makes a PIL
-
Basemap Layers (optional):
- If
config.include_basemapisTrue, calls_draw_basemapto load shapefiles fromconfig.basemap_optionsand draw them in the background (e.g., roads, property boundaries).
- If
-
Drawing:
- Parcels: If provided, draws each polygon using the
draw_coordsplus afillcolor fromr.draw_color. - Conduits: Each row is passed to
draw_conduit(row, draw). - Nodes: Each row is passed to
draw_node(row, draw).
- Parcels: If provided, draws each polygon using the
-
Annotation:
- If
titleis given, callsannotate_title. - If
annotationis given, callsannotate_details. - Always calls
annotate_timestampto add a timestamp in the top-right corner.
- If
-
Saving or Returning the Image:
- If
file_pathis specified, callssave_image(img, file_path)(which can do an antialias thumbnail and optionally open the file). - Otherwise, returns the
imgobject directly—useful in Jupyter notebooks or for further processing in memory.
- If
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
modelhas.geojsonproperties).
Arguments
model: Aswmmio.Modelobject that presumably includes.nodes.geojsonand.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
- CRS Check: If
model.crsis known, tries to transform the model coordinates toEPSG:4326for web mapping. - Compute centroid and bounding box from the model’s
inp.coordinates(viacentroid_and_bbox_from_coords). - Read the basemap template file line by line.
- Insert relevant data:
conduits = <geojson dumps of model.links.geojson>nodes = <geojson dumps of model.nodes.geojson>map centerfrom the centroid[lng, lat].fitBoundscalls from the bounding box.
- Write the final HTML to the
filename.- If
filenameisNone, the result is returned as a string.
- If
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_modelifconfig.include_basemapisTrue. - Iterates over features in
config.basemap_options['features'], reads shapefiles, transforms them to pixel coords, and draws lines or polygons. - If columns like
ST_NAMEexist, it callsannotate_streetsto 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
whitebackground). px_to_irl_coords,save_imagefromswmmio.graphics.utils: handle geometry transformations and final image saving.draw_node,draw_conduitfromswmmio.graphics.drawing: actual shape-drawing functions for SWMM nodes/links.spatialmodules for shapefile reading (spatial.read_shapefile) and coordinate conversions.centroid_and_bbox_from_coordsfor bounding box logic.
Why These Functions Are Useful
-
Versatile Visualization:
draw_modelsuits quick static diagrams for reports, screenshots, or docs.create_mapsuits interactive exploration—useful for large networks or checking node/link attributes in detail.
-
Easy Integration:
- Because the code references typical SWMM data structures (from
model.nodes(),model.links()), it plugs directly into swmmio’s data pipeline.
- Because the code references typical SWMM data structures (from
-
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.
- By adjusting parameters like
Example End-to-End Usage
- Create/Load a SWMM Model:
from swmmio import Model my_model = Model("example_model.inp") - 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 ) - 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.