Conventions — axes, depth sign, angles, units, array ordering, regularization: see
conventions.md.
All plot functions follow a consistent pattern:
- Accept optional
ax=None; create a new figure ifNone - Return the
matplotlib.axes.Axesused - Never call
plt.show() - Pass
**kwargsthrough to the underlying matplotlib artist
A good inversion figure should show observations, predictions, residuals, fault geometry, units, and the color scale. Use identical limits when comparing models, and prefer a diverging colormap centered on zero for signed slip or residuals. Smooth-looking interpolation is not additional resolution: always inspect the underlying patch values and resolution/uncertainty alongside an interpolated map.
Slip distribution as colored patches (rectangular or triangular).
geodef.plot.slip(fault, result.slip_magnitude)
geodef.plot.slip(fault, result.slip_vector,
ax=ax,
components='dip', # 'strike', 'dip', 'magnitude' (default)
coords='fault', # 'fault' (default) or 'geographic'
updip_edge=True, # black line along the up-dip edge (default)
cmap='RdBu_r',
vmin=-2, vmax=2,
edgecolor='gray', linewidth=0.5, # → PatchCollection/**kwargs
colorbar=True,
colorbar_label='Dip slip (m)',
title='Coseismic slip',
)By default the slip is drawn in fault coordinates — along-strike (x) and
along-dip (y) kilometers, with the up-dip (shallowest) edge at the top of the
axes — which is the natural frame for reading a slip distribution. A black line
marks the up-dip edge (disable with updip_edge=False). Pass
coords='geographic' to plot in local East/North kilometers instead; use this
when overlaying the slip on a map together with plot.vectors, plot.insar, or
station locations (the up-dip edge is then drawn as the surface trace). The
coords and updip_edge arguments are also available on plot.patches,
plot.resolution, and plot.uncertainty (defaulting to 'geographic' and
False there).
Pass the named result array you want to plot, such as result.strike_slip,
result.dip_slip, result.slip_magnitude, result.rake_parallel, or
result.rake_perpendicular. Raw N/2N vectors remain accepted; a raw
one-component vector is plotted directly.
A smoothly interpolated slip field in map view, as an alternative to the
discrete patches of plot.slip. Rectangular faults are drawn with a
Gouraud-shaded pcolormesh over the structured grid; triangular (or
unstructured) faults use tricontourf over the patch centroids.
geodef.plot.slip_interpolated(fault, result.slip_magnitude,
cmap='viridis',
levels=20, # filled contour levels (tricontourf path)
colorbar=True,
title='Interpolated slip',
)The tricontourf path needs at least three patches to triangulate.
Generic per-patch scalar plot. plot.slip, plot.resolution, and plot.uncertainty are thin wrappers around this.
geodef.plot.patches(fault, some_array, cmap='viridis', vmin=0, vmax=1)Model resolution diagonal on fault patches (same interface as plot.slip).
geodef.plot.resolution(fault, np.diag(R), cmap='viridis', vmin=0, vmax=1)diag(R) measures how strongly each parameter is reproduced by the linearized
inverse operator, but it ignores off-diagonal smearing. Values near one are not
equivalent to small uncertainty; inspect rows of R, covariance, and synthetic
recovery tests for a fuller resolution assessment.
Per-parameter 1-sigma uncertainty on fault patches.
geodef.plot.uncertainty(fault, sigma, cmap='magma_r')These are standard deviations under the assumed linear model, covariance, and regularization. They do not automatically include fault-geometry uncertainty or systematic model error.
GNSS displacement/velocity vectors as quiver arrows.
predictions = geodef.invert.prediction(result)
geodef.plot.vectors(gnss, fault,
predicted=predictions[gnss.dataset_name], # optional overlay
scale=10,
obs_color='black', pred_color='red',
components='both', # 'horizontal', 'vertical', 'both'
legend=True,
scale_arrow=0.5, scale_arrow_label="50 cm",
scale_arrow_loc='lower right',
vertical_colorbar=True, # colorbar for the vertical dots
vertical_size=40, # constant dot area (points^2)
)For components='vertical' (and the vertical part of 'both'), the vertical
component is shown as color-coded circles (symmetric RdBu_r) with a colorbar;
set vertical_colorbar=False to suppress it. The dots are a constant size
(vertical_size) — the vertical value is encoded by color only, not marker
area. In 'both' mode the horizontal arrows are drawn above the vertical dots
so they cannot be hidden.
InSAR LOS data as colored scatter points.
geodef.plot.insar(insar, fault,
predicted=predictions[insar.dataset_name],
layout='obs_pred_res', # 'obs', 'pred', 'residual', 'obs_pred_res'
cmap='RdBu_r',
vmin=-0.1, vmax=0.1,
scatter_kwargs={'s': 2},
)layout='obs_pred_res' returns a figure with 3 axes.
Observed vs. predicted scatter or residual histogram.
geodef.plot.fit(gnss.obs, predictions[gnss.dataset_name])
geodef.plot.fit(gnss.obs, predictions[gnss.dataset_name],
style='residual_histogram')For an inversion result, the named assessment plots avoid manual slicing and do not require the original fault or dataset objects:
geodef.plot.prediction(result) # observed vs predicted
geodef.plot.residual(result) # residual histograms
geodef.plot.diagnostics(result) # reduced chi-squared bars
geodef.plot.diagnostics(result, metric="rms")
geodef.plot.summary(result) # assumptions and fit text3-D visualization of fault geometry.
geodef.plot.fault3d(fault,
color_by='depth', # 'depth', 'area', 1-D array, or None
cmap='viridis',
show_edges=True,
view=(30, -60), # (elevation, azimuth) in degrees; None = matplotlib default
aspect='equal', # 'equal', 'auto', or a vertical-exaggeration factor
station_locations=gnss, # optional: overlay station positions
)aspect controls the data aspect ratio. The default 'equal' scales all
three axes in proportion to their data ranges so the geometry is undistorted.
Shallow faults have a small depth extent relative to their horizontal
footprint, so 'equal' can render them as a thin slab; pass a positive number
(e.g. aspect=3) to apply a vertical exaggeration to the depth axis, or
'auto' for matplotlib's default cubic box. New figures use constrained
layout and a padded colorbar so depth labels and the colorbar do not collide.
2-D map view of fault patches with optional station overlay.
geodef.plot.map_view(fault,
datasets=[gnss, insar],
slip_vector=result.slip_vector,
components='magnitude',
cmap='YlOrRd',
colorbar_label='Slip (m)',
show_trace=True,
trace_kwargs={'color': 'red', 'linewidth': 2},
patch_kwargs={},
)As with plot.slip(), a length-N one-parameter slip vector is plotted as
an amplitude directly; components only selects from blocked length-2N
strike/dip slip vectors.
Since every function accepts ax, plots can be layered freely:
fig, ax = plt.subplots()
geodef.plot.slip(fault, result.slip_vector, ax=ax, cmap='YlOrRd')
geodef.plot.vectors(gnss, fault, ax=ax, scale=10)LCurveResult and ABICCurveResult have .plot() methods that follow the same pattern:
lc = geodef.invert.lcurve(fault, data, regularization='laplacian', regularization_range=(1e-2, 1e6))
ax = lc.plot() # optimal λ annotated automatically
ax = lc.plot(ax=ax, color='navy')