Domain Plotter
Domain_plotter provides matplotlib-based plotting of domain quantities
during a simulation, making it suitable for interactive use in a Jupyter
notebook or for saving a sequence of frame images alongside the evolve loop.
For post-processing a completed simulation from a saved SWW file, use SWW Plotter instead.
Feature |
|
|
|---|---|---|
Data source |
Live domain centroid values |
SWW file (NetCDF) |
When to use |
During or just after evolve loop |
Post-processing |
Seeks to frame |
Current time only |
Any stored time step |
Typical context |
Jupyter notebook |
Script or notebook |
Setup
Create a Domain_plotter from any Domain object, or call
domain.set_plotter() which creates one and attaches its methods
directly to the domain for convenience.
Direct construction
import anuga
domain = anuga.rectangular_cross_domain(40, 40, len1=10.0, len2=10.0)
# ... set quantities, boundaries ...
dplotter = anuga.Domain_plotter(domain, plot_dir='_plot', min_depth=0.01)
Via ``set_plotter`` (attaches methods to the domain object)
domain.set_plotter(plot_dir='_plot', min_depth=0.01)
# Now domain.plot_depth_frame(), domain.save_depth_frame(), etc. are available
Argument |
Default |
Description |
|---|---|---|
|
— |
The |
|
|
Directory for saved frame images. Created automatically if it does
not exist. Pass |
|
|
Water depth threshold (m) below which cells are treated as dry and shown using the elevation colour map instead of the quantity colour map. |
|
|
If |
Data attributes
After construction the following NumPy arrays are available. All centroid-based arrays update in place as the simulation progresses (they are views into the domain’s quantity arrays, not copies).
Attribute |
Description |
|---|---|
|
|
|
Node coordinates (1-D arrays) |
|
Centroid coordinates (1-D arrays) |
|
Elevation at centroids (m) |
|
Water surface elevation at centroids (m) |
|
Water depth at centroids: |
|
x- and y-momentum at centroids (m²/s) |
|
x- and y-velocity at centroids (m/s), zero where dry |
|
Flow speed at centroids (m/s) |
|
Manning friction coefficient at centroids |
Plotting methods
Each quantity has three methods: plot_* (display), save_* (write
PNG to plot_dir), and make_*_animation (assemble saved PNGs into
a FuncAnimation).
Method |
Description |
|---|---|
|
Plot the triangular mesh |
|
Plot water depth at the current simulation time. Dry cells shown in greyscale elevation (or via basemap). |
|
Save depth frame as PNG named |
|
Assemble all saved depth PNGs into a |
|
Plot water surface stage |
|
Save stage frame as PNG |
|
Assemble all saved stage PNGs into a |
|
Plot flow speed |
|
Save speed frame as PNG |
|
Assemble all saved speed PNGs into a |
All plot_* methods return (fig, ax) so the caller can add titles,
annotations, or further customisation before displaying.
Visualisation options
All plot_* and save_* frame methods share these optional keyword
arguments in addition to figsize, dpi, vmin, and vmax:
Argument |
Default |
Description |
|---|---|---|
|
|
Any matplotlib colormap
name, e.g. |
|
|
If |
|
|
Dot-notation provider string. Any key from
|
|
|
Opacity of the wet-area colour layer (0 = fully transparent,
1 = fully opaque). Values around |
Optional dependency: basemap=True requires contextily:
conda install contextily
# or
pip install contextily
If contextily is not installed a warning is issued and the basemap is
skipped — all other plot options continue to work normally.
Example: interactive notebook
The typical pattern in a Jupyter notebook is to call set_plotter once
before the evolve loop, then call save_*_frame at each yield step to
accumulate frames, and finally assemble them into an animation.
import anuga
import matplotlib.pyplot as plt
domain = anuga.rectangular_cross_domain(40, 40, len1=10.0, len2=10.0)
domain.set_quantity('elevation', lambda x, y: -1.0 - 0.1 * x)
domain.set_quantity('friction', 0.03)
domain.set_quantity('stage', 0.0)
Br = anuga.Reflective_boundary(domain)
Bd = anuga.Dirichlet_boundary([0.5, 0.0, 0.0])
domain.set_boundary({'left': Bd, 'right': Br, 'top': Br, 'bottom': Br})
# Set up the plotter once before the evolve loop.
domain.set_plotter(plot_dir='_plot', min_depth=0.01)
# Determine colour scale limits from the initial state.
vmax = domain.dplotter.depth.max() + 0.5
for t in domain.evolve(yieldstep=10.0, finaltime=100.0):
domain.print_timestepping_statistics()
domain.save_depth_frame(vmin=0.0, vmax=vmax)
# Assemble saved frames into an animation (displays inline in a notebook).
anim = domain.make_depth_animation()
anim # display in Jupyter
Example: custom colormap and transparency
domain.set_plotter()
for t in domain.evolve(yieldstep=10.0, finaltime=100.0):
domain.save_depth_frame(vmin=0.0, vmax=2.0, cmap='plasma')
Example: quick single-frame plot
To inspect the state at a single point during or after the evolve loop:
domain.set_plotter()
# Run a few steps
for t in domain.evolve(yieldstep=10.0, finaltime=30.0):
pass
fig, ax = domain.plot_depth_frame(vmin=0.0, vmax=2.0)
ax.set_title('Depth at t = 30 s')
plt.show()
Example: OSM basemap (requires contextily and a georeferenced domain)
When the domain carries a valid EPSG code in its geo_reference, an
OpenStreetMap basemap can be added automatically. Dry cells become
transparent, and the wet-area layer can be made semi-transparent with
alpha so the street map shows through:
domain.set_plotter()
for t in domain.evolve(yieldstep=10.0, finaltime=100.0):
domain.save_depth_frame(vmin=0.0, vmax=2.0,
basemap=True, alpha=0.6)
Example: plot the mesh
domain.set_plotter()
fig, ax = domain.plot_mesh()
plt.show()
Note
Domain_plotter holds live references to the domain’s centroid
arrays. Plots produced during the evolve loop always reflect the current
simulation time — there is no need to re-create the plotter at each step.
Note
make_*_animation assembles images that were previously saved with
save_*_frame. Call save_*_frame at every yield step you want
to appear in the animation before calling make_*_animation.