PyHydroGeophysX.visualization package#

Submodules#

PyHydroGeophysX.visualization.animation module#

Time-lapse animation utilities for geophysical models.

PyHydroGeophysX.visualization.animation.create_combined_timelapse_gif(mesh, filename: str, *, wc_models: Sequence[ndarray] | None = None, res_models: Sequence[ndarray] | None = None, app_res_data: Sequence | None = None, precipitation: ndarray | None = None, n_frames: int | None = None, wc_cmap=None, res_cmap=None, app_res_cmap=None, wc_cmin: float = 0.0, wc_cmax: float = 0.32, res_cmin: float = 100, res_cmax: float = 2000, app_res_cmin: float = 100, app_res_cmax: float = 1000, app_res_plot_type: str = 'scatter', app_res_scatter_size: float = 10, mesh_ylim: Tuple[float, float] | None = None, figsize: Tuple[float, float] = (14, 10), dpi: int = 100, duration: int = 100, first_frame_duration: int = 500, loop: int = 0, day_labels: Sequence[str] | None = None) str[source]#

Create a combined GIF with water content, resistivity, apparent resistivity pseudosection, and precipitation panels.

The water content and resistivity model panels are placed side-by-side on the same row.

Parameters:
  • mesh (pygimli.Mesh) – Mesh shared by WC and resistivity models.

  • filename (str) – Output GIF path.

  • wc_models (sequence of array-like, optional) – Water content model per frame.

  • res_models (sequence of array-like, optional) – Resistivity model per frame.

  • app_res_data (sequence, optional) – PyGimli DataContainers (or file paths) of apparent resistivity per frame. Converted to SimPEG internally for pseudosection plotting.

  • precipitation (array-like, optional) – 1-D precipitation array (length = n_frames).

  • n_frames (int, optional) – Number of frames. Inferred from whichever data list is provided.

  • wc_cmap – Colormaps for each panel.

  • res_cmap – Colormaps for each panel.

  • app_res_cmap – Colormaps for each panel.

  • wc_cmin (float) – Water content color limits.

  • wc_cmax (float) – Water content color limits.

  • res_cmin (float) – Resistivity color limits.

  • res_cmax (float) – Resistivity color limits.

  • app_res_cmin (float) – Apparent resistivity color limits.

  • app_res_cmax (float) – Apparent resistivity color limits.

  • app_res_plot_type (str) – 'scatter', 'pcolor', or 'contourf'.

  • mesh_ylim (tuple of (ymin, ymax), optional) – Y-axis limits for the mesh model panels (WC and resistivity). E.g. (1600, 1720) to crop the vertical range.

  • figsize (tuple) – Figure size per frame.

  • dpi (int) – Resolution.

  • duration (int) – Milliseconds per frame.

  • first_frame_duration (int) – Duration of first frame in ms.

  • loop (int) – 0 = infinite loop.

  • day_labels (sequence of str, optional) – Label for each frame (e.g. 'Day 0', 'Day 1', …).

Returns:

Path to the saved GIF file.

Return type:

str

PyHydroGeophysX.visualization.animation.create_difference_gif(mesh, models: Sequence[ndarray], reference: ndarray, filename: str, *, mode: str = 'difference', titles: Sequence[str] | None = None, cmap: str = 'RdBu_r', symmetric: bool = True, label: str = '', figsize: Tuple[float, float] = (8, 2.5), dpi: int = 150, duration: int = 100, coverage: ndarray | Sequence[ndarray] | None = None) str[source]#

Create a GIF animation showing model changes relative to a reference.

Parameters:
  • mesh (pygimli.Mesh) –

  • models (sequence of array-like) – Model snapshots for each frame.

  • reference (array-like) – Baseline model to subtract / divide.

  • mode ('difference' | 'ratio' | 'percent_change') –

  • symmetric (bool) – Center colorbar at zero / one.

:param (other parameters same as create_timelapse_gif()):

Returns:

Path to the saved GIF file.

Return type:

str

PyHydroGeophysX.visualization.animation.create_timelapse_gif(mesh, models: Sequence[ndarray], filename: str, *, titles: Sequence[str] | None = None, cmap=None, cmin: float | None = None, cmax: float | None = None, log_scale: bool = False, label: str = '', xlabel: str = 'Distance (m)', ylabel: str = 'Elevation (m)', coverage: ndarray | Sequence[ndarray] | None = None, figsize: Tuple[float, float] = (8, 2.5), dpi: int = 150, duration: int = 100, first_frame_duration: int = 500, loop: int = 0) str[source]#

Create a GIF animation of time-lapse model snapshots.

Each frame renders the model on the given mesh using pg.show and captures it as a PIL image. Requires Pillow.

Parameters:
  • mesh (pygimli.Mesh) – Mesh shared by all models.

  • models (sequence of array-like) – Model values for each frame.

  • filename (str) – Output GIF path.

  • titles (sequence of str, optional) – Title per frame.

  • cmap (str or Colormap, optional) – Colormap. Defaults to BlueDarkRed18_18_r if available.

  • cmin (float, optional) – Fixed color limits.

  • cmax (float, optional) – Fixed color limits.

  • log_scale (bool) – Logarithmic color scale.

  • label (str) – Colorbar label.

  • coverage (array or list of arrays, optional) – Coverage mask(s).

  • figsize (tuple) – Figure size per frame.

  • dpi (int) – Resolution.

  • duration (int) – Milliseconds per frame.

  • first_frame_duration (int) – Duration of the first frame in ms (longer for visual pause).

  • loop (int) – Number of loops (0 = infinite).

Returns:

Path to the saved GIF file.

Return type:

str

PyHydroGeophysX.visualization.animation.create_timelapse_mp4(mesh, models: Sequence[ndarray], filename: str, *, titles: Sequence[str] | None = None, cmap=None, cmin: float | None = None, cmax: float | None = None, log_scale: bool = False, label: str = '', xlabel: str = 'Distance (m)', ylabel: str = 'Elevation (m)', coverage: ndarray | Sequence[ndarray] | None = None, figsize: Tuple[float, float] = (8, 2.5), dpi: int = 150, fps: int = 10) str[source]#

Create an MP4 video of time-lapse model snapshots using matplotlib.

Requires ffmpeg to be available on the system path.

Parameters:
  • mesh (pygimli.Mesh) –

  • models (sequence of array-like) –

  • filename (str) – Output .mp4 path.

  • fps (int) – Frames per second.

:param (other parameters same as create_timelapse_gif()):

Returns:

Path to the saved MP4 file.

Return type:

str

PyHydroGeophysX.visualization.multi_method module#

Visualization helpers for multi-method geophysical workflows.

PyHydroGeophysX.visualization.multi_method.plot_cross_section_with_wells(result, mesh, well_data: Dict[str, ndarray] | None = None)[source]#

Plot a model cross-section and overlay optional well picks.

PyHydroGeophysX.visualization.multi_method.plot_em_data_fit(times, observed, predicted, uncertainties=None, true_data=None, chi2: float | None = None, time_scale: float = 1000.0, time_label: str = 'Time (ms)', data_label: str = '|Response|', ax=None)[source]#

Plot log-log EM data fit similar to TDEM workflow examples.

PyHydroGeophysX.visualization.multi_method.plot_em_fit_and_residuals(times, observed, predicted, uncertainties, true_data=None, chi2: float | None = None, time_scale: float = 1000.0)[source]#

Create side-by-side EM data fit and residual plots.

PyHydroGeophysX.visualization.multi_method.plot_em_residuals(times, observed, predicted, uncertainties, sigma_bound: float = 2.0, time_scale: float = 1000.0, time_label: str = 'Time (ms)', ax=None)[source]#

Plot normalized residuals with +/-sigma bounds.

PyHydroGeophysX.visualization.multi_method.plot_hydro_vs_geophys(hydro_wc, inverted_wc, mesh=None)[source]#

Compare hydrological water content to geophysics-derived water content.

PyHydroGeophysX.visualization.multi_method.plot_layered_profiles(depth_edges, profiles: Dict[str, Sequence[float]], colors: Sequence[str] | None = None, xscale: str = 'linear')[source]#

Plot one or more layered profiles as step-like vertical columns.

PyHydroGeophysX.visualization.multi_method.plot_multi_method_panel(ert_result, srt_result, em_result, mesh=None)[source]#

Plot side-by-side ERT/SRT/EM model panels.

PyHydroGeophysX.visualization.multi_method.plot_petrophysical_scatter(x, y, color=None, xlabel: str = 'Porosity (-)', ylabel: str = 'Property', color_label: str = 'Saturation (-)', cmap: str = 'Blues', fit_line: bool = True, ax=None)[source]#

Plot petrophysical scatter diagnostics with optional trend line.

PyHydroGeophysX.visualization.multi_method.plot_time_lapse_panel(models: Sequence[Any], mesh=None, titles: Sequence[str] | None = None, ncols: int = 4, cmap: str = 'viridis')[source]#

Plot a grid of time-lapse model snapshots.

PyHydroGeophysX.visualization.plotting module#

2D plotting utilities for geophysical models and data.

PyHydroGeophysX.visualization.plotting.plot_apparent_resistivity_pseudosection(data_obj, *, ax=None, plot_type: str = 'scatter', cmap=None, cmin: float | None = None, cmax: float | None = None, scale: str = 'linear', label: str = 'Apparent resistivity ($\\Omega\\cdot$m)', title: str = '', scatter_marker: str = 's', scatter_size: float = 10, mask_topography: bool = True, show_colorbar: bool = True, cbar_opts: Dict | None = None, figsize: Tuple[float, float] = (12, 5), data_locations: bool = False, clean_axes: bool = False, xlabel: str = 'x (m)', ylabel: str = 'Elevation (m)') Tuple[source]#

Plot apparent resistivity pseudosection with topography using SimPEG.

Converts PyGimli ERT data to SimPEG format and uses SimPEG’s plot_pseudosection to render a pseudosection that honours surface topography.

Parameters:
  • data_obj (pygimli.DataContainer, str, or SimPEG Data) – PyGimli ERT data (or file path to a .dat), or a pre-converted SimPEG Data object. When a PyGimli object or path is passed the conversion is done automatically.

  • ax (matplotlib.axes.Axes, optional) – Axes to draw on. Created if None.

  • plot_type ('scatter' | 'pcolor' | 'contourf') – Pseudosection rendering style.

  • cmap (str or Colormap, optional) – Colormap. Defaults to BlueDarkRed18_18 (warm-to-cool).

  • cmin (float, optional) – Color limits.

  • cmax (float, optional) – Color limits.

  • scale ('linear' | 'log') – Color scale.

  • label (str) – Colorbar label.

  • title (str) – Axes title.

  • scatter_marker (str) – Marker style when plot_type=’scatter’.

  • scatter_size (float) – Marker size when plot_type=’scatter’.

  • mask_topography (bool) – If True, mask the region above topography.

  • show_colorbar (bool) – Show the colorbar.

  • cbar_opts (dict, optional) – Extra keyword arguments forwarded to the colorbar.

  • figsize (tuple) – Figure size (only used when ax is None).

  • data_locations (bool) – Show electrode locations on the plot.

  • clean_axes (bool) – If True, remove spines and ticks for a clean look.

  • xlabel (str) – Axis labels.

  • ylabel (str) – Axis labels.

Return type:

fig, ax, cbar_or_mappable

PyHydroGeophysX.visualization.plotting.plot_apparent_resistivity_timelapse(data_objs, *, titles: Sequence[str] | None = None, ncols: int = 4, plot_type: str = 'scatter', cmap=None, cmin: float | None = None, cmax: float | None = None, scale: str = 'linear', label: str = 'Apparent resistivity ($\\Omega\\cdot$m)', scatter_marker: str = 's', scatter_size: float = 10, mask_topography: bool = True, figsize_per_panel: Tuple[float, float] = (4.0, 2.5), clean_axes: bool = True, save_path: str | None = None, dpi: int = 100) Tuple[source]#

Plot a multi-panel time-lapse apparent resistivity pseudosection.

Parameters:
  • data_objs (sequence) – List of PyGimli DataContainers, file paths, or SimPEG Data objects.

  • titles (sequence of str, optional) – Panel titles.

  • ncols (int) – Number of columns.

  • plot_type (str) – 'scatter', 'pcolor', or 'contourf'.

  • cmap – Colormap and scale parameters.

  • cmin – Colormap and scale parameters.

  • cmax – Colormap and scale parameters.

  • scale – Colormap and scale parameters.

  • label – Colormap and scale parameters.

  • figsize_per_panel (tuple) – (width, height) per subplot.

  • clean_axes (bool) – Remove spines and ticks.

  • save_path (str, optional) – If given, save the figure to this path.

  • dpi (int) – Resolution for saving.

Return type:

fig, axes

PyHydroGeophysX.visualization.plotting.plot_convergence(chi2_history: Sequence[float], *, ax=None, target_chi2: float = 1.0, ylabel: str = '$\\chi^2$', title: str = 'Inversion Convergence') Tuple[source]#

Plot chi-squared convergence curve.

Parameters:
  • chi2_history (sequence of float) – Chi-squared value per iteration.

  • target_chi2 (float) – Target misfit (plotted as a dashed line).

Return type:

fig, ax

PyHydroGeophysX.visualization.plotting.plot_coverage(mesh, coverage: ndarray, *, ax=None, cmap: str = 'YlGn', threshold: float | None = None, title: str = 'Data Coverage') Tuple[source]#

Plot a coverage / sensitivity map.

Parameters:
  • mesh (pygimli.Mesh) –

  • coverage (array-like) – Coverage values per cell.

  • threshold (float, optional) – If given, overlay a contour at this level.

Return type:

fig, ax, cbar

PyHydroGeophysX.visualization.plotting.plot_difference_map(mesh, model_a: ndarray, model_b: ndarray, *, mode: str = 'difference', ax=None, cmap: str = 'RdBu_r', symmetric: bool = True, label: str = '', title: str = '', coverage: ndarray | None = None) Tuple[source]#

Plot the difference or ratio between two models.

Parameters:
  • mesh (pygimli.Mesh) –

  • model_a (array-like) – Two model arrays. result = model_b - model_a (difference) or model_b / model_a (ratio).

  • model_b (array-like) – Two model arrays. result = model_b - model_a (difference) or model_b / model_a (ratio).

  • mode ('difference' | 'ratio' | 'percent_change') –

  • symmetric (bool) – If True, center the colorbar at zero (difference) or one (ratio).

  • coverage (array-like, optional) – Coverage mask.

Return type:

fig, ax, cbar

PyHydroGeophysX.visualization.plotting.plot_electrode_layout(positions: Dict[str, ndarray], *, ax=None, color_by: str = 'z', cmap: str = 'terrain', title: str = 'Electrode Layout') Tuple[source]#

Scatter-plot electrode positions colored by elevation.

Parameters:

positions (dict) – Must contain 'x' and 'y' keys; optionally 'z'.

Return type:

fig, ax

PyHydroGeophysX.visualization.plotting.plot_model_section(mesh, values: ndarray, *, ax=None, cmap=None, cmin: float | None = None, cmax: float | None = None, log_scale: bool = False, label: str = '', xlabel: str = 'Distance (m)', ylabel: str = 'Elevation (m)', title: str = '', coverage: ndarray | None = None, orientation: str = 'vertical') Tuple[source]#

Plot a 2D model cross-section on a PyGIMLi mesh.

Parameters:
  • mesh (pygimli.Mesh) – The mesh to plot on.

  • values (array-like) – Cell values (resistivity, velocity, water content, etc.).

  • ax (matplotlib.axes.Axes, optional) – Axes to draw on. Created if None.

  • cmap (str or Colormap, optional) – Colormap. Defaults to BlueDarkRed18_18_r if available.

  • cmin (float, optional) – Color limits.

  • cmax (float, optional) – Color limits.

  • log_scale (bool) – Use logarithmic color scaling.

  • label (str) – Colorbar label.

  • coverage (array-like, optional) – Coverage array for masking low-sensitivity cells.

  • orientation (str) – Colorbar orientation ('vertical' or 'horizontal').

Return type:

fig, ax, cbar

PyHydroGeophysX.visualization.plotting.plot_monitoring_timeseries(times: ndarray, series: Dict[str, ndarray], *, true_series: Dict[str, ndarray] | None = None, uncertainties: Dict[str, Tuple[ndarray, ndarray]] | None = None, ax=None, ylabel: str = 'Value', title: str = 'Monitoring Point Time Series') Tuple[source]#

Plot estimated (and optionally true) time-series at monitoring points.

Parameters:
  • times (array-like) – Time axis.

  • series (dict of str -> array) – Estimated values keyed by point name.

  • true_series (dict of str -> array, optional) – True / reference values for comparison (dashed lines).

  • uncertainties (dict of str -> (lower, upper), optional) – Uncertainty bounds per point for shading.

Return type:

fig, ax

PyHydroGeophysX.visualization.plotting.plot_pseudosection_matrix(data_matrix: ndarray, *, ax=None, cmap=None, vmin: float | None = None, vmax: float | None = None, xlabel: str = 'Time', ylabel: str = 'Measurement #', label: str = 'Apparent resistivity ($\\Omega\\cdot$m)', title: str = '') Tuple[source]#

Plot a time-lapse apparent resistivity matrix as a heatmap.

Parameters:

data_matrix (2-D array) – Shape (n_times, n_measurements) or similar.

Return type:

fig, ax, im

PyHydroGeophysX.visualization.plotting.plot_timelapse_snapshots(mesh, models: Sequence[ndarray], *, titles: Sequence[str] | None = None, ncols: int = 4, cmap=None, cmin: float | None = None, cmax: float | None = None, log_scale: bool = False, label: str = '', coverage: ndarray | Sequence[ndarray] | None = None, figsize_per_panel: Tuple[float, float] = (4.0, 2.5)) Tuple[source]#

Plot a grid of time-lapse model snapshots.

Parameters:
  • mesh (pygimli.Mesh) – Mesh shared by all snapshots.

  • models (sequence of array-like) – Model arrays for each timestep.

  • titles (sequence of str, optional) – Panel titles. Defaults to 'Timestep 1', 'Timestep 2', …

  • ncols (int) – Number of columns.

  • cmap – Passed to pg.show.

  • cmin – Passed to pg.show.

  • cmax – Passed to pg.show.

  • log_scale – Passed to pg.show.

  • label – Passed to pg.show.

  • coverage (array or sequence of arrays, optional) – Coverage mask(s). If a single 1-D array it is reused for all panels. If 2-D, coverage[i] is used for panel i.

  • figsize_per_panel (tuple) – (width, height) per subplot panel.

Return type:

fig, axes

PyHydroGeophysX.visualization.plotting.plot_topography(topo_grid: ndarray, *, profile_endpoints: List[Tuple[float, float]] | None = None, ax=None, cmap: str = 'terrain', title: str = 'Surface Topography') Tuple[source]#

Plot a 2-D topography grid with optional profile line overlay.

Parameters:
  • topo_grid (2-D array) – Elevation raster.

  • profile_endpoints (list of (row, col) tuples, optional) – If two points are given, draw the profile line.

Return type:

fig, ax

PyHydroGeophysX.visualization.vtk_export module#

VTK export utilities for ParaView visualization.

PyHydroGeophysX.visualization.vtk_export.export_mesh_to_vtk(mesh, filename: str, cell_data: Dict[str, ndarray] | None = None) str[source]#

Export a PyGIMLi mesh to VTK unstructured grid format.

This uses PyGIMLi’s built-in mesh.exportVTK when available and then optionally injects extra cell data fields.

Parameters:
  • mesh (pygimli.Mesh) – The mesh to export.

  • filename (str) – Output .vtk path.

  • cell_data (dict of str -> array, optional) – Additional named cell-data arrays to write.

Returns:

Path to the written file.

Return type:

str

PyHydroGeophysX.visualization.vtk_export.export_points_to_vtk(points: ndarray, scalars: Dict[str, ndarray], filename: str) str[source]#

Export point-cloud data (e.g. cell centers) to VTK PolyData.

Parameters:
  • points (array of shape (N, 3)) – XYZ coordinates.

  • scalars (dict of str -> array) – Named scalar values at each point.

  • filename (str) – Output .vtk path.

Returns:

Path to the written file.

Return type:

str

PyHydroGeophysX.visualization.vtk_export.export_structured_vtk(values: ndarray, filename: str, *, dx: float = 1.0, dy: float = 1.0, dz: float = 1.0, origin: tuple = (0.0, 0.0, 0.0), scalar_name: str = 'model') str[source]#

Export a 3-D numpy array to VTK structured-points format.

Useful for MODFLOW/ParFlow grids that map directly to a regular grid.

Parameters:
  • values (3-D array) – Shape (nz, ny, nx) — layer, row, column ordering.

  • filename (str) – Output .vtk path.

  • dx (float) – Cell spacing in each direction.

  • dy (float) – Cell spacing in each direction.

  • dz (float) – Cell spacing in each direction.

  • origin (tuple of float) – (x0, y0, z0) origin of the grid.

  • scalar_name (str) – Name for the scalar dataset.

Returns:

Path to the written file.

Return type:

str

PyHydroGeophysX.visualization.vtk_export.export_structured_vtk_multi(scalars: Dict[str, ndarray], filename: str, *, dx: float = 1.0, dy: float = 1.0, dz: float = 1.0, origin: tuple = (0.0, 0.0, 0.0)) str[source]#

Export multiple 3-D arrays as named scalars in a single VTK file.

All arrays must have the same shape (nz, ny, nx).

Parameters:
  • scalars (dict of str -> 3-D array) – Named scalar datasets (e.g. {"resistivity": res, "water_content": wc}).

  • filename (str) – Output .vtk path.

Returns:

Path to the written file.

Return type:

str

PyHydroGeophysX.visualization.vtk_export.export_timelapse_structured_vtk(models: Sequence[ndarray], output_dir: str, prefix: str = 'timelapse', *, dx: float = 1.0, dy: float = 1.0, dz: float = 1.0, origin: tuple = (0.0, 0.0, 0.0), scalar_name: str = 'model') List[str][source]#

Export time-lapse 3-D arrays as a numbered VTK series.

Parameters:
  • models (sequence of 3-D arrays) – Each entry has shape (nz, ny, nx).

  • output_dir (str) – Output directory.

  • prefix (str) – File prefix.

  • dx (float) – Grid spacing.

  • dy (float) – Grid spacing.

  • dz (float) – Grid spacing.

  • origin (tuple) – Grid origin.

  • scalar_name (str) – Scalar field name.

Returns:

Paths to generated VTK files.

Return type:

list of str

PyHydroGeophysX.visualization.vtk_export.export_timelapse_vtk(mesh, models: Sequence[ndarray], output_dir: str, prefix: str = 'timelapse', *, scalar_name: str = 'model', extra_data: Dict[str, Sequence[ndarray]] | None = None) List[str][source]#

Export time-lapse models as a numbered VTK series for ParaView.

Creates files prefix_0000.vtk, prefix_0001.vtk, … and a .pvd collection file that ParaView can load as a time series.

Parameters:
  • mesh (pygimli.Mesh) – Mesh shared by all timesteps.

  • models (sequence of array-like) – Model values per timestep.

  • output_dir (str) – Directory for output files.

  • prefix (str) – Filename prefix.

  • scalar_name (str) – Name for the primary scalar field.

  • extra_data (dict of str -> sequence of arrays, optional) – Additional scalar fields per timestep.

Returns:

Paths to all generated VTK files.

Return type:

list of str

Module contents#

Visualization utilities for PyHydroGeophysX.

PyHydroGeophysX.visualization.create_combined_timelapse_gif(mesh, filename: str, *, wc_models: Sequence[ndarray] | None = None, res_models: Sequence[ndarray] | None = None, app_res_data: Sequence | None = None, precipitation: ndarray | None = None, n_frames: int | None = None, wc_cmap=None, res_cmap=None, app_res_cmap=None, wc_cmin: float = 0.0, wc_cmax: float = 0.32, res_cmin: float = 100, res_cmax: float = 2000, app_res_cmin: float = 100, app_res_cmax: float = 1000, app_res_plot_type: str = 'scatter', app_res_scatter_size: float = 10, mesh_ylim: Tuple[float, float] | None = None, figsize: Tuple[float, float] = (14, 10), dpi: int = 100, duration: int = 100, first_frame_duration: int = 500, loop: int = 0, day_labels: Sequence[str] | None = None) str[source]#

Create a combined GIF with water content, resistivity, apparent resistivity pseudosection, and precipitation panels.

The water content and resistivity model panels are placed side-by-side on the same row.

Parameters:
  • mesh (pygimli.Mesh) – Mesh shared by WC and resistivity models.

  • filename (str) – Output GIF path.

  • wc_models (sequence of array-like, optional) – Water content model per frame.

  • res_models (sequence of array-like, optional) – Resistivity model per frame.

  • app_res_data (sequence, optional) – PyGimli DataContainers (or file paths) of apparent resistivity per frame. Converted to SimPEG internally for pseudosection plotting.

  • precipitation (array-like, optional) – 1-D precipitation array (length = n_frames).

  • n_frames (int, optional) – Number of frames. Inferred from whichever data list is provided.

  • wc_cmap – Colormaps for each panel.

  • res_cmap – Colormaps for each panel.

  • app_res_cmap – Colormaps for each panel.

  • wc_cmin (float) – Water content color limits.

  • wc_cmax (float) – Water content color limits.

  • res_cmin (float) – Resistivity color limits.

  • res_cmax (float) – Resistivity color limits.

  • app_res_cmin (float) – Apparent resistivity color limits.

  • app_res_cmax (float) – Apparent resistivity color limits.

  • app_res_plot_type (str) – 'scatter', 'pcolor', or 'contourf'.

  • mesh_ylim (tuple of (ymin, ymax), optional) – Y-axis limits for the mesh model panels (WC and resistivity). E.g. (1600, 1720) to crop the vertical range.

  • figsize (tuple) – Figure size per frame.

  • dpi (int) – Resolution.

  • duration (int) – Milliseconds per frame.

  • first_frame_duration (int) – Duration of first frame in ms.

  • loop (int) – 0 = infinite loop.

  • day_labels (sequence of str, optional) – Label for each frame (e.g. 'Day 0', 'Day 1', …).

Returns:

Path to the saved GIF file.

Return type:

str

PyHydroGeophysX.visualization.create_difference_gif(mesh, models: Sequence[ndarray], reference: ndarray, filename: str, *, mode: str = 'difference', titles: Sequence[str] | None = None, cmap: str = 'RdBu_r', symmetric: bool = True, label: str = '', figsize: Tuple[float, float] = (8, 2.5), dpi: int = 150, duration: int = 100, coverage: ndarray | Sequence[ndarray] | None = None) str[source]#

Create a GIF animation showing model changes relative to a reference.

Parameters:
  • mesh (pygimli.Mesh) –

  • models (sequence of array-like) – Model snapshots for each frame.

  • reference (array-like) – Baseline model to subtract / divide.

  • mode ('difference' | 'ratio' | 'percent_change') –

  • symmetric (bool) – Center colorbar at zero / one.

:param (other parameters same as create_timelapse_gif()):

Returns:

Path to the saved GIF file.

Return type:

str

PyHydroGeophysX.visualization.create_timelapse_gif(mesh, models: Sequence[ndarray], filename: str, *, titles: Sequence[str] | None = None, cmap=None, cmin: float | None = None, cmax: float | None = None, log_scale: bool = False, label: str = '', xlabel: str = 'Distance (m)', ylabel: str = 'Elevation (m)', coverage: ndarray | Sequence[ndarray] | None = None, figsize: Tuple[float, float] = (8, 2.5), dpi: int = 150, duration: int = 100, first_frame_duration: int = 500, loop: int = 0) str[source]#

Create a GIF animation of time-lapse model snapshots.

Each frame renders the model on the given mesh using pg.show and captures it as a PIL image. Requires Pillow.

Parameters:
  • mesh (pygimli.Mesh) – Mesh shared by all models.

  • models (sequence of array-like) – Model values for each frame.

  • filename (str) – Output GIF path.

  • titles (sequence of str, optional) – Title per frame.

  • cmap (str or Colormap, optional) – Colormap. Defaults to BlueDarkRed18_18_r if available.

  • cmin (float, optional) – Fixed color limits.

  • cmax (float, optional) – Fixed color limits.

  • log_scale (bool) – Logarithmic color scale.

  • label (str) – Colorbar label.

  • coverage (array or list of arrays, optional) – Coverage mask(s).

  • figsize (tuple) – Figure size per frame.

  • dpi (int) – Resolution.

  • duration (int) – Milliseconds per frame.

  • first_frame_duration (int) – Duration of the first frame in ms (longer for visual pause).

  • loop (int) – Number of loops (0 = infinite).

Returns:

Path to the saved GIF file.

Return type:

str

PyHydroGeophysX.visualization.create_timelapse_mp4(mesh, models: Sequence[ndarray], filename: str, *, titles: Sequence[str] | None = None, cmap=None, cmin: float | None = None, cmax: float | None = None, log_scale: bool = False, label: str = '', xlabel: str = 'Distance (m)', ylabel: str = 'Elevation (m)', coverage: ndarray | Sequence[ndarray] | None = None, figsize: Tuple[float, float] = (8, 2.5), dpi: int = 150, fps: int = 10) str[source]#

Create an MP4 video of time-lapse model snapshots using matplotlib.

Requires ffmpeg to be available on the system path.

Parameters:
  • mesh (pygimli.Mesh) –

  • models (sequence of array-like) –

  • filename (str) – Output .mp4 path.

  • fps (int) – Frames per second.

:param (other parameters same as create_timelapse_gif()):

Returns:

Path to the saved MP4 file.

Return type:

str

PyHydroGeophysX.visualization.export_mesh_to_vtk(mesh, filename: str, cell_data: Dict[str, ndarray] | None = None) str[source]#

Export a PyGIMLi mesh to VTK unstructured grid format.

This uses PyGIMLi’s built-in mesh.exportVTK when available and then optionally injects extra cell data fields.

Parameters:
  • mesh (pygimli.Mesh) – The mesh to export.

  • filename (str) – Output .vtk path.

  • cell_data (dict of str -> array, optional) – Additional named cell-data arrays to write.

Returns:

Path to the written file.

Return type:

str

PyHydroGeophysX.visualization.export_points_to_vtk(points: ndarray, scalars: Dict[str, ndarray], filename: str) str[source]#

Export point-cloud data (e.g. cell centers) to VTK PolyData.

Parameters:
  • points (array of shape (N, 3)) – XYZ coordinates.

  • scalars (dict of str -> array) – Named scalar values at each point.

  • filename (str) – Output .vtk path.

Returns:

Path to the written file.

Return type:

str

PyHydroGeophysX.visualization.export_structured_vtk(values: ndarray, filename: str, *, dx: float = 1.0, dy: float = 1.0, dz: float = 1.0, origin: tuple = (0.0, 0.0, 0.0), scalar_name: str = 'model') str[source]#

Export a 3-D numpy array to VTK structured-points format.

Useful for MODFLOW/ParFlow grids that map directly to a regular grid.

Parameters:
  • values (3-D array) – Shape (nz, ny, nx) — layer, row, column ordering.

  • filename (str) – Output .vtk path.

  • dx (float) – Cell spacing in each direction.

  • dy (float) – Cell spacing in each direction.

  • dz (float) – Cell spacing in each direction.

  • origin (tuple of float) – (x0, y0, z0) origin of the grid.

  • scalar_name (str) – Name for the scalar dataset.

Returns:

Path to the written file.

Return type:

str

PyHydroGeophysX.visualization.export_structured_vtk_multi(scalars: Dict[str, ndarray], filename: str, *, dx: float = 1.0, dy: float = 1.0, dz: float = 1.0, origin: tuple = (0.0, 0.0, 0.0)) str[source]#

Export multiple 3-D arrays as named scalars in a single VTK file.

All arrays must have the same shape (nz, ny, nx).

Parameters:
  • scalars (dict of str -> 3-D array) – Named scalar datasets (e.g. {"resistivity": res, "water_content": wc}).

  • filename (str) – Output .vtk path.

Returns:

Path to the written file.

Return type:

str

PyHydroGeophysX.visualization.export_timelapse_structured_vtk(models: Sequence[ndarray], output_dir: str, prefix: str = 'timelapse', *, dx: float = 1.0, dy: float = 1.0, dz: float = 1.0, origin: tuple = (0.0, 0.0, 0.0), scalar_name: str = 'model') List[str][source]#

Export time-lapse 3-D arrays as a numbered VTK series.

Parameters:
  • models (sequence of 3-D arrays) – Each entry has shape (nz, ny, nx).

  • output_dir (str) – Output directory.

  • prefix (str) – File prefix.

  • dx (float) – Grid spacing.

  • dy (float) – Grid spacing.

  • dz (float) – Grid spacing.

  • origin (tuple) – Grid origin.

  • scalar_name (str) – Scalar field name.

Returns:

Paths to generated VTK files.

Return type:

list of str

PyHydroGeophysX.visualization.export_timelapse_vtk(mesh, models: Sequence[ndarray], output_dir: str, prefix: str = 'timelapse', *, scalar_name: str = 'model', extra_data: Dict[str, Sequence[ndarray]] | None = None) List[str][source]#

Export time-lapse models as a numbered VTK series for ParaView.

Creates files prefix_0000.vtk, prefix_0001.vtk, … and a .pvd collection file that ParaView can load as a time series.

Parameters:
  • mesh (pygimli.Mesh) – Mesh shared by all timesteps.

  • models (sequence of array-like) – Model values per timestep.

  • output_dir (str) – Directory for output files.

  • prefix (str) – Filename prefix.

  • scalar_name (str) – Name for the primary scalar field.

  • extra_data (dict of str -> sequence of arrays, optional) – Additional scalar fields per timestep.

Returns:

Paths to all generated VTK files.

Return type:

list of str

PyHydroGeophysX.visualization.plot_apparent_resistivity_pseudosection(data_obj, *, ax=None, plot_type: str = 'scatter', cmap=None, cmin: float | None = None, cmax: float | None = None, scale: str = 'linear', label: str = 'Apparent resistivity ($\\Omega\\cdot$m)', title: str = '', scatter_marker: str = 's', scatter_size: float = 10, mask_topography: bool = True, show_colorbar: bool = True, cbar_opts: Dict | None = None, figsize: Tuple[float, float] = (12, 5), data_locations: bool = False, clean_axes: bool = False, xlabel: str = 'x (m)', ylabel: str = 'Elevation (m)') Tuple[source]#

Plot apparent resistivity pseudosection with topography using SimPEG.

Converts PyGimli ERT data to SimPEG format and uses SimPEG’s plot_pseudosection to render a pseudosection that honours surface topography.

Parameters:
  • data_obj (pygimli.DataContainer, str, or SimPEG Data) – PyGimli ERT data (or file path to a .dat), or a pre-converted SimPEG Data object. When a PyGimli object or path is passed the conversion is done automatically.

  • ax (matplotlib.axes.Axes, optional) – Axes to draw on. Created if None.

  • plot_type ('scatter' | 'pcolor' | 'contourf') – Pseudosection rendering style.

  • cmap (str or Colormap, optional) – Colormap. Defaults to BlueDarkRed18_18 (warm-to-cool).

  • cmin (float, optional) – Color limits.

  • cmax (float, optional) – Color limits.

  • scale ('linear' | 'log') – Color scale.

  • label (str) – Colorbar label.

  • title (str) – Axes title.

  • scatter_marker (str) – Marker style when plot_type=’scatter’.

  • scatter_size (float) – Marker size when plot_type=’scatter’.

  • mask_topography (bool) – If True, mask the region above topography.

  • show_colorbar (bool) – Show the colorbar.

  • cbar_opts (dict, optional) – Extra keyword arguments forwarded to the colorbar.

  • figsize (tuple) – Figure size (only used when ax is None).

  • data_locations (bool) – Show electrode locations on the plot.

  • clean_axes (bool) – If True, remove spines and ticks for a clean look.

  • xlabel (str) – Axis labels.

  • ylabel (str) – Axis labels.

Return type:

fig, ax, cbar_or_mappable

PyHydroGeophysX.visualization.plot_apparent_resistivity_timelapse(data_objs, *, titles: Sequence[str] | None = None, ncols: int = 4, plot_type: str = 'scatter', cmap=None, cmin: float | None = None, cmax: float | None = None, scale: str = 'linear', label: str = 'Apparent resistivity ($\\Omega\\cdot$m)', scatter_marker: str = 's', scatter_size: float = 10, mask_topography: bool = True, figsize_per_panel: Tuple[float, float] = (4.0, 2.5), clean_axes: bool = True, save_path: str | None = None, dpi: int = 100) Tuple[source]#

Plot a multi-panel time-lapse apparent resistivity pseudosection.

Parameters:
  • data_objs (sequence) – List of PyGimli DataContainers, file paths, or SimPEG Data objects.

  • titles (sequence of str, optional) – Panel titles.

  • ncols (int) – Number of columns.

  • plot_type (str) – 'scatter', 'pcolor', or 'contourf'.

  • cmap – Colormap and scale parameters.

  • cmin – Colormap and scale parameters.

  • cmax – Colormap and scale parameters.

  • scale – Colormap and scale parameters.

  • label – Colormap and scale parameters.

  • figsize_per_panel (tuple) – (width, height) per subplot.

  • clean_axes (bool) – Remove spines and ticks.

  • save_path (str, optional) – If given, save the figure to this path.

  • dpi (int) – Resolution for saving.

Return type:

fig, axes

PyHydroGeophysX.visualization.plot_convergence(chi2_history: Sequence[float], *, ax=None, target_chi2: float = 1.0, ylabel: str = '$\\chi^2$', title: str = 'Inversion Convergence') Tuple[source]#

Plot chi-squared convergence curve.

Parameters:
  • chi2_history (sequence of float) – Chi-squared value per iteration.

  • target_chi2 (float) – Target misfit (plotted as a dashed line).

Return type:

fig, ax

PyHydroGeophysX.visualization.plot_coverage(mesh, coverage: ndarray, *, ax=None, cmap: str = 'YlGn', threshold: float | None = None, title: str = 'Data Coverage') Tuple[source]#

Plot a coverage / sensitivity map.

Parameters:
  • mesh (pygimli.Mesh) –

  • coverage (array-like) – Coverage values per cell.

  • threshold (float, optional) – If given, overlay a contour at this level.

Return type:

fig, ax, cbar

PyHydroGeophysX.visualization.plot_cross_section_with_wells(result, mesh, well_data: Dict[str, ndarray] | None = None)[source]#

Plot a model cross-section and overlay optional well picks.

PyHydroGeophysX.visualization.plot_difference_map(mesh, model_a: ndarray, model_b: ndarray, *, mode: str = 'difference', ax=None, cmap: str = 'RdBu_r', symmetric: bool = True, label: str = '', title: str = '', coverage: ndarray | None = None) Tuple[source]#

Plot the difference or ratio between two models.

Parameters:
  • mesh (pygimli.Mesh) –

  • model_a (array-like) – Two model arrays. result = model_b - model_a (difference) or model_b / model_a (ratio).

  • model_b (array-like) – Two model arrays. result = model_b - model_a (difference) or model_b / model_a (ratio).

  • mode ('difference' | 'ratio' | 'percent_change') –

  • symmetric (bool) – If True, center the colorbar at zero (difference) or one (ratio).

  • coverage (array-like, optional) – Coverage mask.

Return type:

fig, ax, cbar

PyHydroGeophysX.visualization.plot_electrode_layout(positions: Dict[str, ndarray], *, ax=None, color_by: str = 'z', cmap: str = 'terrain', title: str = 'Electrode Layout') Tuple[source]#

Scatter-plot electrode positions colored by elevation.

Parameters:

positions (dict) – Must contain 'x' and 'y' keys; optionally 'z'.

Return type:

fig, ax

PyHydroGeophysX.visualization.plot_em_data_fit(times, observed, predicted, uncertainties=None, true_data=None, chi2: float | None = None, time_scale: float = 1000.0, time_label: str = 'Time (ms)', data_label: str = '|Response|', ax=None)[source]#

Plot log-log EM data fit similar to TDEM workflow examples.

PyHydroGeophysX.visualization.plot_em_fit_and_residuals(times, observed, predicted, uncertainties, true_data=None, chi2: float | None = None, time_scale: float = 1000.0)[source]#

Create side-by-side EM data fit and residual plots.

PyHydroGeophysX.visualization.plot_em_residuals(times, observed, predicted, uncertainties, sigma_bound: float = 2.0, time_scale: float = 1000.0, time_label: str = 'Time (ms)', ax=None)[source]#

Plot normalized residuals with +/-sigma bounds.

PyHydroGeophysX.visualization.plot_hydro_vs_geophys(hydro_wc, inverted_wc, mesh=None)[source]#

Compare hydrological water content to geophysics-derived water content.

PyHydroGeophysX.visualization.plot_layered_profiles(depth_edges, profiles: Dict[str, Sequence[float]], colors: Sequence[str] | None = None, xscale: str = 'linear')[source]#

Plot one or more layered profiles as step-like vertical columns.

PyHydroGeophysX.visualization.plot_model_section(mesh, values: ndarray, *, ax=None, cmap=None, cmin: float | None = None, cmax: float | None = None, log_scale: bool = False, label: str = '', xlabel: str = 'Distance (m)', ylabel: str = 'Elevation (m)', title: str = '', coverage: ndarray | None = None, orientation: str = 'vertical') Tuple[source]#

Plot a 2D model cross-section on a PyGIMLi mesh.

Parameters:
  • mesh (pygimli.Mesh) – The mesh to plot on.

  • values (array-like) – Cell values (resistivity, velocity, water content, etc.).

  • ax (matplotlib.axes.Axes, optional) – Axes to draw on. Created if None.

  • cmap (str or Colormap, optional) – Colormap. Defaults to BlueDarkRed18_18_r if available.

  • cmin (float, optional) – Color limits.

  • cmax (float, optional) – Color limits.

  • log_scale (bool) – Use logarithmic color scaling.

  • label (str) – Colorbar label.

  • coverage (array-like, optional) – Coverage array for masking low-sensitivity cells.

  • orientation (str) – Colorbar orientation ('vertical' or 'horizontal').

Return type:

fig, ax, cbar

PyHydroGeophysX.visualization.plot_monitoring_timeseries(times: ndarray, series: Dict[str, ndarray], *, true_series: Dict[str, ndarray] | None = None, uncertainties: Dict[str, Tuple[ndarray, ndarray]] | None = None, ax=None, ylabel: str = 'Value', title: str = 'Monitoring Point Time Series') Tuple[source]#

Plot estimated (and optionally true) time-series at monitoring points.

Parameters:
  • times (array-like) – Time axis.

  • series (dict of str -> array) – Estimated values keyed by point name.

  • true_series (dict of str -> array, optional) – True / reference values for comparison (dashed lines).

  • uncertainties (dict of str -> (lower, upper), optional) – Uncertainty bounds per point for shading.

Return type:

fig, ax

PyHydroGeophysX.visualization.plot_multi_method_panel(ert_result, srt_result, em_result, mesh=None)[source]#

Plot side-by-side ERT/SRT/EM model panels.

PyHydroGeophysX.visualization.plot_petrophysical_scatter(x, y, color=None, xlabel: str = 'Porosity (-)', ylabel: str = 'Property', color_label: str = 'Saturation (-)', cmap: str = 'Blues', fit_line: bool = True, ax=None)[source]#

Plot petrophysical scatter diagnostics with optional trend line.

PyHydroGeophysX.visualization.plot_pseudosection_matrix(data_matrix: ndarray, *, ax=None, cmap=None, vmin: float | None = None, vmax: float | None = None, xlabel: str = 'Time', ylabel: str = 'Measurement #', label: str = 'Apparent resistivity ($\\Omega\\cdot$m)', title: str = '') Tuple[source]#

Plot a time-lapse apparent resistivity matrix as a heatmap.

Parameters:

data_matrix (2-D array) – Shape (n_times, n_measurements) or similar.

Return type:

fig, ax, im

PyHydroGeophysX.visualization.plot_time_lapse_panel(models: Sequence[Any], mesh=None, titles: Sequence[str] | None = None, ncols: int = 4, cmap: str = 'viridis')[source]#

Plot a grid of time-lapse model snapshots.

PyHydroGeophysX.visualization.plot_timelapse_snapshots(mesh, models: Sequence[ndarray], *, titles: Sequence[str] | None = None, ncols: int = 4, cmap=None, cmin: float | None = None, cmax: float | None = None, log_scale: bool = False, label: str = '', coverage: ndarray | Sequence[ndarray] | None = None, figsize_per_panel: Tuple[float, float] = (4.0, 2.5)) Tuple[source]#

Plot a grid of time-lapse model snapshots.

Parameters:
  • mesh (pygimli.Mesh) – Mesh shared by all snapshots.

  • models (sequence of array-like) – Model arrays for each timestep.

  • titles (sequence of str, optional) – Panel titles. Defaults to 'Timestep 1', 'Timestep 2', …

  • ncols (int) – Number of columns.

  • cmap – Passed to pg.show.

  • cmin – Passed to pg.show.

  • cmax – Passed to pg.show.

  • log_scale – Passed to pg.show.

  • label – Passed to pg.show.

  • coverage (array or sequence of arrays, optional) – Coverage mask(s). If a single 1-D array it is reused for all panels. If 2-D, coverage[i] is used for panel i.

  • figsize_per_panel (tuple) – (width, height) per subplot panel.

Return type:

fig, axes

PyHydroGeophysX.visualization.plot_topography(topo_grid: ndarray, *, profile_endpoints: List[Tuple[float, float]] | None = None, ax=None, cmap: str = 'terrain', title: str = 'Surface Topography') Tuple[source]#

Plot a 2-D topography grid with optional profile line overlay.

Parameters:
  • topo_grid (2-D array) – Elevation raster.

  • profile_endpoints (list of (row, col) tuples, optional) – If two points are given, draw the profile line.

Return type:

fig, ax