Custom data demo¶
Note - this script can also be opened in interactive Python if you wanted to
play around. On the GitHub it is in docs/notebooks.
To run this on your local machine, you will need to install the optional dependencies
for doc:
pip install swmmanywhere[doc]
Introduction¶
This script demonstrates how to use swmmanywhere when you have custom data.
Since this is a notebook, we will define config
as a dictionary rather than a yaml file, but the same principles apply.
Initial setup¶
We will use the same example as the extended demo, but with a custom elevation dataset. Let's start by rerunning it.
In [1]:
Copied!
# Imports
from __future__ import annotations
import tempfile
from pathlib import Path
import folium
import geopandas as gpd
from swmmanywhere.logging import set_verbose
from swmmanywhere.swmmanywhere import swmmanywhere
from swmmanywhere.utilities import plot_map
# Create temporary directory
temp_dir = tempfile.TemporaryDirectory(dir=".")
base_dir = Path(temp_dir.name)
# Define minimum viable config
bbox = (1.52740, 42.50524, 1.54273, 42.51259)
config = {
"base_dir": base_dir,
"project": "my_first_swmm",
"bbox": bbox,
"run_settings": {"duration": 3600},
"parameter_overrides": {
"topology_derivation": {
"allowable_networks": ["drive"],
"omit_edges": ["bridge"],
},
"outfall_derivation": {
"outfall_length": 5,
"river_buffer_distance": 30,
},
},
}
set_verbose(True) # Set verbosity
# Run SWMManywhere
outputs = swmmanywhere(config)
model_dir = outputs[0].parent
# Imports
from __future__ import annotations
import tempfile
from pathlib import Path
import folium
import geopandas as gpd
from swmmanywhere.logging import set_verbose
from swmmanywhere.swmmanywhere import swmmanywhere
from swmmanywhere.utilities import plot_map
# Create temporary directory
temp_dir = tempfile.TemporaryDirectory(dir=".")
base_dir = Path(temp_dir.name)
# Define minimum viable config
bbox = (1.52740, 42.50524, 1.54273, 42.51259)
config = {
"base_dir": base_dir,
"project": "my_first_swmm",
"bbox": bbox,
"run_settings": {"duration": 3600},
"parameter_overrides": {
"topology_derivation": {
"allowable_networks": ["drive"],
"omit_edges": ["bridge"],
},
"outfall_derivation": {
"outfall_length": 5,
"river_buffer_distance": 30,
},
},
}
set_verbose(True) # Set verbosity
# Run SWMManywhere
outputs = swmmanywhere(config)
model_dir = outputs[0].parent
/opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html from .autonotebook import tqdm as notebook_tqdm
2026/05/08 09:13:45 | Creating project structure.
2026/05/08 09:13:45 | Project structure created at tmpy2xk9c2h
2026/05/08 09:13:45 | Project name: my_first_swmm
2026/05/08 09:13:45 | Bounding box: (1.5274, 42.50524, 1.54273, 42.51259),
number: 1
2026/05/08 09:13:45 | Model number: 1
2026/05/08 09:13:45 | Loading and setting parameters.
2026/05/08 09:13:45 | Setting topology_derivation allowable_networks to ['drive']
2026/05/08 09:13:45 | Setting topology_derivation omit_edges to ['bridge']
2026/05/08 09:13:45 | Setting outfall_derivation outfall_length to 5
2026/05/08 09:13:45 | Setting outfall_derivation river_buffer_distance to 30
2026/05/08 09:13:45 | Allowable networks have been changed, removing old street graph.
2026/05/08 09:13:45 | Running downloads.
2026/05/08 09:13:45 | downloading elevation to tmpy2xk9c2h/my_first_swmm/bbox_1/download/elevation.tif
2026/05/08 09:13:49 | downloading buildings to tmpy2xk9c2h/my_first_swmm/bbox_1/download/building.geoparquet
2026/05/08 09:14:28 | downloading network to tmpy2xk9c2h/my_first_swmm/bbox_1/download/street.json
2026/05/08 09:14:30 | downloading river network to tmpy2xk9c2h/my_first_swmm/bbox_1/download/river.json
2026/05/08 09:14:31 | Iterating graphs.
2026/05/08 09:14:31 | Iterating graph functions.
2026/05/08 09:14:31 | graphfcn: assign_id completed.
2026/05/08 09:14:31 | graphfcn: fix_geometries completed.
2026/05/08 09:14:31 | graphfcn: remove_non_pipe_allowable_links completed.
2026/05/08 09:14:31 | graphfcn: calculate_streetcover completed.
2026/05/08 09:14:31 | graphfcn: remove_parallel_edges completed.
2026/05/08 09:14:32 | graphfcn: to_undirected completed.
2026/05/08 09:14:32 | graphfcn: split_long_edges completed.
2026/05/08 09:14:32 | graphfcn: merge_street_nodes completed.
2026/05/08 09:14:32 | graphfcn: assign_id completed.
2026/05/08 09:14:37 | graphfcn: clip_to_catchments completed.
2026/05/08 09:14:38 | graphfcn: calculate_contributing_area completed.
2026/05/08 09:14:39 | graphfcn: set_elevation completed.
2026/05/08 09:14:39 | graphfcn: double_directed completed.
2026/05/08 09:14:39 | graphfcn: fix_geometries completed.
2026/05/08 09:14:39 | graphfcn: set_surface_slope completed.
2026/05/08 09:14:39 | graphfcn: set_chahinian_slope completed.
2026/05/08 09:14:39 | graphfcn: set_chahinian_angle completed.
2026/05/08 09:14:40 | graphfcn: calculate_weights completed.
2026/05/08 09:14:40 | No outfalls found for subgraph containing
913, using this node as outfall.
2026/05/08 09:14:40 | No outfalls found for subgraph containing
855, using this node as outfall.
2026/05/08 09:14:40 | No outfalls found for subgraph containing
703, using this node as outfall.
2026/05/08 09:14:40 | No outfalls found for subgraph containing
786, using this node as outfall.
2026/05/08 09:14:40 | No outfalls found for subgraph containing
811, using this node as outfall.
2026/05/08 09:14:40 | No outfalls found for subgraph containing
1310, using this node as outfall.
2026/05/08 09:14:40 | No outfalls found for subgraph containing
1612, using this node as outfall.
2026/05/08 09:14:40 | graphfcn: identify_outfalls completed.
2026/05/08 09:14:40 | Total graph weight 262.64488134057075.
2026/05/08 09:14:40 | graphfcn: derive_topology completed.
0%| | 0/393 [00:00<?, ?it/s]
10%|█ | 40/393 [00:00<00:00, 383.13it/s]
21%|██ | 81/393 [00:00<00:00, 397.70it/s]
31%|███ | 121/393 [00:00<00:00, 378.58it/s]
40%|████ | 159/393 [00:00<00:00, 304.86it/s]
49%|████▉ | 192/393 [00:00<00:00, 300.45it/s]
57%|█████▋ | 224/393 [00:00<00:00, 279.53it/s]
64%|██████▍ | 253/393 [00:00<00:00, 254.18it/s]
71%|███████ | 280/393 [00:00<00:00, 250.87it/s]
79%|███████▊ | 309/393 [00:01<00:00, 259.85it/s]
86%|████████▌ | 337/393 [00:01<00:00, 263.13it/s]
93%|█████████▎| 364/393 [00:01<00:00, 247.49it/s]
99%|█████████▉| 390/393 [00:01<00:00, 241.17it/s]
100%|██████████| 393/393 [00:01<00:00, 274.58it/s]
2026/05/08 09:14:42 | graphfcn: pipe_by_pipe completed.
2026/05/08 09:14:42 | graphfcn: fix_geometries completed.
2026/05/08 09:14:42 | graphfcn: assign_id completed.
2026/05/08 09:14:42 | Saving final graph and writing inp file.
2026/05/08 09:14:43 | Running the synthetic model.
2026/05/08 09:14:43 | tmpy2xk9c2h/my_first_swmm/bbox_1/model_1/model_1.inp initialised in pyswmm
2026/05/08 09:14:43 | Starting simulation for: tmpy2xk9c2h/my_first_swmm/bbox_1/model_1/model_1.inp
0%| | 0/3600 [00:00<?, ?it/s]
14%|█▎ | 494.0/3600 [00:00<00:00, 4930.55it/s]
27%|██▋ | 988.0/3600 [00:00<00:01, 2406.05it/s]
36%|███▌ | 1296.0/3600 [00:00<00:01, 2153.93it/s]
43%|████▎ | 1545.0/3600 [00:00<00:00, 2131.01it/s]
49%|████▉ | 1780.0/3600 [00:00<00:00, 2187.48it/s]
66%|██████▌ | 2375.0/3600 [00:00<00:00, 3197.84it/s]
92%|█████████▏| 3325.0/3600 [00:00<00:00, 4943.45it/s]
2026/05/08 09:14:44 | Model run complete.
3605.0it [00:01, 3511.10it/s]
2026/05/08 09:14:44 | Writing synthetic results.
2026/05/08 09:14:44 | No real network provided, returning SWMM .inp file.
Plotting output¶
Now we can plot the output. To highlight the differences in the supplied data that we are about to demonstrate, we also plot the subbasins.
In [2]:
Copied!
m = plot_map(model_dir)
subbasins = gpd.read_parquet(model_dir / "subbasins.geoparquet")
folium.GeoJson(subbasins, fill_opacity=0, color="blue", weight=2).add_to(m)
m
m = plot_map(model_dir)
subbasins = gpd.read_parquet(model_dir / "subbasins.geoparquet")
folium.GeoJson(subbasins, fill_opacity=0, color="blue", weight=2).add_to(m)
m
Out[2]:
Make this Notebook Trusted to load map: File -> Trust Notebook