Tables (time series, curves, patterns)#
Note
Engine: OpenSWMM 6 — refactored.
Three families of tabular objects live in the engine:
Time series —
(time, value)pairs wheretimeis adatetime.Curves — generic
(x, y)pairs.Patterns — periodic multiplier sequences keyed by
PatternType.
The first two share the C API’s tables namespace and live on
solver.tables; patterns live on solver.patterns.
Reference: openswmm_tables.h.
Quickstart#
Important
Creating a time series, curve, or pattern is only valid while the
engine is in BUILDING or OPENED state — i.e. on a Solver
after open() but before
initialize() / start(). The
with Solver(...) as s: context manager auto-runs
open() → initialize() → start(), so by the time the block body runs
the engine is already STARTED and add_timeseries / add_curve
/ patterns.add will raise LifecycleError. Use an explicit
open() instead, as shown below. (Adding points to an
existing table, by contrast, is allowed in any state.)
from datetime import datetime
from openswmm.engine import Solver, PatternType
s = Solver("model.inp")
s.open() # -> OPENED (creation window)
# Add a new time series and populate it.
ts = s.tables.add_timeseries("rain1")
ts.add(datetime(2024, 6, 15, 0, 0), 0.0)
ts.add(datetime(2024, 6, 15, 1, 0), 0.5)
# Add a curve.
curve = s.tables.add_curve("storage1")
curve.add_point(0.0, 0.0)
curve.add_point(1.0, 100.0)
print(curve.lookup(0.5)) # interpolation
# Patterns.
s.patterns.add("DLY1", PatternType.DAILY)
s.patterns[0].set_factors([1.0] * 7)
# Finish arming and run.
s.initialize()
s.start()
for _ in s.steps():
pass
s.end()
s.report()
s.close()
Once the model is opened you can still inspect and edit points of existing tables at any point in the lifecycle:
# Inspect existing tables — generic helper returns ._PointTable;
# use as_timeseries / as_curve for typed views.
ts = s.tables.as_timeseries("rain1")
pts = ts.points # structured numpy array
print(pts["time"], pts["value"])
Tables collection#
len(s.tables)/for t in s.tables:/s.tables[key]— standard.s.tables.add_timeseries(id)— returns aTimeSeries. Creation is valid only inBUILDINGorOPENEDstate.s.tables.add_curve(id, curve_type=0)— returns aCurve. Creation is valid only inBUILDINGorOPENEDstate.s.tables.as_timeseries(key)/as_curve(key)— typed view of an existing entry.
The C API does not currently expose a per-entry type discriminator, so
iteration yields a generic _PointTable. Use the as_* helpers
when you need TimeSeries or Curve specifically.
TimeSeries#
.pointsreturns a numpy structured array with fieldstime: datetime64[s]andvalue: float64..add(when, value)acceptswhenasdatetimeor a SWMM DateTime float..lookup(x)runs the engine’s interpolation (x can be any SWMM DateTime float)..add_point(x, y)/.clear()/len(ts)— common point-table operations.
Curve#
.pointsreturns afloat64(n_points, 2)numpy array..add_point(x, y)/.lookup(x)/.clear()— common point-table operations.
Patterns and Pattern#
solver.patterns is indexable by integer only (the C API has no
id→index lookup for patterns):
p = s.patterns.add("DLY1", PatternType.DAILY)
p.set_factors([1.0, 1.1, 1.2, 1.0, 0.9, 1.0, 1.0])
For monthly/daily/hourly/weekend factor counts, follow the SWMM 5 conventions (12 / 7 / 24 / 24).
See also#
Rain gages —
Gage.set_timeseries()binds a gage to aTimeSeries.External inflows — DWF uses pattern ids; external inflows use time series ids.
SWMM DateTime and Python datetime interop — how the time axis works.