visualization package#

Submodules#

PyHydroGeophysX.visualization.plotting module#

2D plotting utilities for geophysical models and data.

PyHydroGeophysX.visualization.plotting.plot_apparent_resistivity_pseudosection(data_obj: Any, *, ax: Any = None, plot_type: str = 'scatter', cmap: Any = 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: Any, *, titles: Sequence[str] | None = None, ncols: int = 4, plot_type: str = 'scatter', cmap: Any = 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: Any = 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: Any, coverage: ndarray, *, ax: Any = 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: Any, model_a: ndarray, model_b: ndarray, *, mode: str = 'difference', ax: Any = 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: Any = 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: Any, values: ndarray, *, ax: Any = None, cmap: Any = 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: Any = 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: Any = None, cmap: Any = 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: Any, models: Sequence[ndarray], *, titles: Sequence[str] | None = None, ncols: int = 4, cmap: Any = 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: Any = 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.multi_method module#

Visualization helpers for multi-method geophysical workflows.

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

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

PyHydroGeophysX.visualization.multi_method.plot_depth_slices(cells: Any, depths: Any = (5.0, 15.0, 30.0, 50.0), basemap: Any = None, extent: Any = None, max_distance: float | None = None, drop_below_doi: bool = True, grid: int = 400, vmin: float | None = None, vmax: float | None = None, ncols: int = 2, cmap: str = 'turbo', show_stations: bool = False) Any[source]#

Map the recovered resistivity at fixed depths, over a basemap.

cells is the per-cell table a line inversion writes, needing x, y, depth_center_m and resistivity_ohm_m, and using below_doi when it carries one. A pandas frame or any mapping of columns will do.

Each requested depth is snapped to the nearest layer the model actually has, and the panel is titled with the depth used rather than the depth asked for. Interpolating between layer centres would invent a resolution the layering does not have.

max_distance is what keeps the picture honest. A survey of a few lines leaves most of the map with no station anywhere near it, and a triangulated interpolation will happily fill that space from stations hundreds of metres away. Anything further than this from a station is left blank, so the ground that was measured is the ground that is coloured.

One width serves every panel, so that a ribbon growing or shrinking between them means the coverage changed rather than the rule did. The mask is about where a station is, and a survey traces the same track at every depth; how far a sounding sees sideways is a question about resolution, which belongs in how the answer is read rather than in which ground gets coloured.

Left unset it is half the deepest slice requested, floored at three times the station spacing, and the figure states the number it used.

drop_below_doi removes cells the run marked as unresolved before interpolating, so a depth below the investigation depth over part of the survey shows a gap there instead of a colour.

Colour is log10 resistivity, with the range taken from the slices drawn so that the panels are comparable to each other.

show_stations marks each sounding. It is off because a shallow slice is a ribbon a few metres wide and a marker per station hides the colour it is there to mark; the ribbon already traces the survey.

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

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

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

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

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

Plot normalized residuals with +/-sigma bounds.

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

Compare hydrological water content to geophysics-derived water content.

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

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

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

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

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

Plot petrophysical scatter diagnostics with optional trend line.

PyHydroGeophysX.visualization.multi_method.plot_signal_and_noise(summary: Any, line: int | None = None, moments: Any = ('LM', 'HM'), smooth: int = 21, axes: Any = None) Any[source]#

Draw the measured signal and the absolute noise along a survey line.

Takes what PyHydroGeophysX.data_processing.em1d.survey_summary() returns. One panel per moment, both on a log axis, plotted against distance along the line.

The pair is the point. A station returns fewer usable gates for two reasons that call for opposite readings, and the relative error the file records is the one divided by the other, so it rises either way and cannot separate them. Drawn apart they can be read directly: a signal that falls while the noise holds is evidence about the ground, because a resistive half-space returns dB/dt going as rho**(-3/2) and is genuinely quieter. A noise floor that rises under a steady signal is an instrument or an environment and says nothing about the ground.

smooth is the width of a running mean over stations, which is cosmetic: station-to-station scatter obscures the trend the figure is drawn to show. Set it to 1 to plot the values themselves.

line selects one survey line, and defaults to the first the summary holds. Distance runs from that line’s own first station.

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

Plot a grid of time-lapse model snapshots.

PyHydroGeophysX.visualization.animation module#

Time-lapse animation utilities for geophysical models.

PyHydroGeophysX.visualization.animation.create_combined_timelapse_gif(mesh: Any, 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: Any = None, res_cmap: Any = None, app_res_cmap: Any = 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: Any, 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: Any, models: Sequence[ndarray], filename: str, *, titles: Sequence[str] | None = None, cmap: Any = 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: Any, models: Sequence[ndarray], filename: str, *, titles: Sequence[str] | None = None, cmap: Any = 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.vtk_export module#

VTK export utilities for ParaView visualization.

PyHydroGeophysX.visualization.vtk_export.export_mesh_to_vtk(mesh: Any, 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: Any, 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: Any, 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: Any = None, res_cmap: Any = None, app_res_cmap: Any = 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: Any, 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: Any, models: Sequence[ndarray], filename: str, *, titles: Sequence[str] | None = None, cmap: Any = 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: Any, models: Sequence[ndarray], filename: str, *, titles: Sequence[str] | None = None, cmap: Any = 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: Any, 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: Any, 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: Any, *, ax: Any = None, plot_type: str = 'scatter', cmap: Any = 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: Any, *, titles: Sequence[str] | None = None, ncols: int = 4, plot_type: str = 'scatter', cmap: Any = 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: Any = 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: Any, coverage: ndarray, *, ax: Any = 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: Any, mesh: Any, well_data: Dict[str, ndarray] | None = None) Any[source]#

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

PyHydroGeophysX.visualization.plot_depth_slices(cells: Any, depths: Any = (5.0, 15.0, 30.0, 50.0), basemap: Any = None, extent: Any = None, max_distance: float | None = None, drop_below_doi: bool = True, grid: int = 400, vmin: float | None = None, vmax: float | None = None, ncols: int = 2, cmap: str = 'turbo', show_stations: bool = False) Any[source]#

Map the recovered resistivity at fixed depths, over a basemap.

cells is the per-cell table a line inversion writes, needing x, y, depth_center_m and resistivity_ohm_m, and using below_doi when it carries one. A pandas frame or any mapping of columns will do.

Each requested depth is snapped to the nearest layer the model actually has, and the panel is titled with the depth used rather than the depth asked for. Interpolating between layer centres would invent a resolution the layering does not have.

max_distance is what keeps the picture honest. A survey of a few lines leaves most of the map with no station anywhere near it, and a triangulated interpolation will happily fill that space from stations hundreds of metres away. Anything further than this from a station is left blank, so the ground that was measured is the ground that is coloured.

One width serves every panel, so that a ribbon growing or shrinking between them means the coverage changed rather than the rule did. The mask is about where a station is, and a survey traces the same track at every depth; how far a sounding sees sideways is a question about resolution, which belongs in how the answer is read rather than in which ground gets coloured.

Left unset it is half the deepest slice requested, floored at three times the station spacing, and the figure states the number it used.

drop_below_doi removes cells the run marked as unresolved before interpolating, so a depth below the investigation depth over part of the survey shows a gap there instead of a colour.

Colour is log10 resistivity, with the range taken from the slices drawn so that the panels are comparable to each other.

show_stations marks each sounding. It is off because a shallow slice is a ribbon a few metres wide and a marker per station hides the colour it is there to mark; the ribbon already traces the survey.

PyHydroGeophysX.visualization.plot_difference_map(mesh: Any, model_a: ndarray, model_b: ndarray, *, mode: str = 'difference', ax: Any = 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: Any = 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: Any, observed: Any, predicted: Any, uncertainties: Any = None, true_data: Any = None, chi2: float | None = None, time_scale: float = 1000.0, time_label: str = 'Time (ms)', data_label: str = '|Response|', ax: Any = None) Any[source]#

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

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

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

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

Plot normalized residuals with +/-sigma bounds.

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

Compare hydrological water content to geophysics-derived water content.

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

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

PyHydroGeophysX.visualization.plot_model_section(mesh: Any, values: ndarray, *, ax: Any = None, cmap: Any = 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: Any = 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: Any, srt_result: Any, em_result: Any, mesh: Any = None) Any[source]#

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

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

Plot petrophysical scatter diagnostics with optional trend line.

PyHydroGeophysX.visualization.plot_pseudosection_matrix(data_matrix: ndarray, *, ax: Any = None, cmap: Any = 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_signal_and_noise(summary: Any, line: int | None = None, moments: Any = ('LM', 'HM'), smooth: int = 21, axes: Any = None) Any[source]#

Draw the measured signal and the absolute noise along a survey line.

Takes what PyHydroGeophysX.data_processing.em1d.survey_summary() returns. One panel per moment, both on a log axis, plotted against distance along the line.

The pair is the point. A station returns fewer usable gates for two reasons that call for opposite readings, and the relative error the file records is the one divided by the other, so it rises either way and cannot separate them. Drawn apart they can be read directly: a signal that falls while the noise holds is evidence about the ground, because a resistive half-space returns dB/dt going as rho**(-3/2) and is genuinely quieter. A noise floor that rises under a steady signal is an instrument or an environment and says nothing about the ground.

smooth is the width of a running mean over stations, which is cosmetic: station-to-station scatter obscures the trend the figure is drawn to show. Set it to 1 to plot the values themselves.

line selects one survey line, and defaults to the first the summary holds. Distance runs from that line’s own first station.

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

Plot a grid of time-lapse model snapshots.

PyHydroGeophysX.visualization.plot_timelapse_snapshots(mesh: Any, models: Sequence[ndarray], *, titles: Sequence[str] | None = None, ncols: int = 4, cmap: Any = 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: Any = 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