asp_plot.utils#

Attributes#

Classes#

ColorBar

Utility class for managing colorbar limits and normalization.

Plotter

Base class for plotting array and vector data.

Raster

Utility class for raster data handling and processing.

Functions#

add_copyright_overlay(ax)

Add Vantor copyright text overlay to the bottom-right of a matplotlib axes.

detect_planetary_body(dem_fn)

Detect planetary body from DEM CRS WKT.

detect_vantor_satellite(directory)

Check if XML files in directory indicate a Vantor (WorldView) satellite.

get_acquisition_dates(directory[, extra_dirs])

Extract scene acquisition date(s) from metadata in a processing directory.

get_planetary_bounds(dem_fn[, body])

Get DEM bounds in planetocentric lon/lat with 0-360 east-positive longitude.

get_utm_epsg(lon, lat)

Get the UTM EPSG code for a given longitude and latitude.

get_xml_tag(xml, tag[, all])

Extract value(s) from XML tag(s).

glob_file(directory, *patterns[, all_files])

Find files matching pattern(s) in a directory.

run_subprocess_command(command)

Run a subprocess command and stream output.

save_figure(fig[, save_dir, fig_fn, dpi])

Save a matplotlib figure to a file.

show_existing_figure(filename)

Display an existing figure from a file.

Module Contents#

class asp_plot.utils.ColorBar(perc_range=(2, 98), symm=False)#

Utility class for managing colorbar limits and normalization.

This class handles color scaling for data visualization, including percentile-based limits, symmetric color mapping, and logarithmic normalization.

perc_range#

Percentile range (min, max) for color limits, default is (2, 98)

Type:

tuple

symm#

Whether to use symmetric color limits, default is False

Type:

bool

clim#

Current color limits (min, max), None until calculated

Type:

tuple or None

Examples

>>> cb = ColorBar(perc_range=(5, 95), symm=True)
>>> clim = cb.get_clim(data)
>>> norm = cb.get_norm(lognorm=False)
>>> im = ax.imshow(data, norm=norm)
>>> plt.colorbar(im, extend=cb.get_cbar_extend(data))
find_common_clim(inputs)#

Find common color limits across multiple inputs.

Parameters:

inputs (list) – List of input data arrays

Returns:

Common color limits (min, max)

Return type:

tuple

get_cbar_extend(input, clim=None)#

Determine colorbar extension mode based on data and limits.

Parameters:
  • input (array_like) – Input data array

  • clim (tuple, optional) – Color limits (min, max), if None uses current or calculated limits

Returns:

Colorbar extension mode: ‘neither’, ‘min’, ‘max’, or ‘both’

Return type:

str

get_clim(input)#

Calculate color limits based on data percentiles.

Parameters:

input (array_like) – Input data array (can be masked)

Returns:

Color limits (min, max)

Return type:

tuple

get_norm(lognorm=False)#

Get normalization for colormap.

Parameters:

lognorm (bool, optional) – Whether to use logarithmic normalization, default is False

Returns:

Normalization object for matplotlib colormaps

Return type:

matplotlib.colors.Normalize

Notes

Requires the clim attribute to be set (by calling get_clim or find_common_clim)

symm_clim()#

Make color limits symmetric around zero.

Returns:

Symmetric color limits (-max, max)

Return type:

tuple

clim = None#
perc_range = (2, 98)#
symm = False#
class asp_plot.utils.Plotter(clim_perc=(2, 98), lognorm=False, title=None)#

Base class for plotting array and vector data.

This class provides common plotting functionality, including color management, colorbar customization, and basemap addition.

clim_perc#

Percentile range for color limits, default is (2, 98)

Type:

tuple

lognorm#

Whether to use logarithmic color normalization, default is False

Type:

bool

title#

Plot title, default is None

Type:

str or None

cb#

ColorBar instance for managing color scaling

Type:

ColorBar

Examples

>>> plotter = Plotter(clim_perc=(5, 95), title="My Plot")
>>> fig, ax = plt.subplots()
>>> plotter.plot_array(ax, data, cmap="viridis", cbar_label="Elevation (m)")
plot_array(ax, array, clim=None, cmap='inferno', add_cbar=True, cbar_label=None, alpha=1)#

Plot a 2D array on the given axes.

Parameters:
  • ax (matplotlib.axes.Axes) – Axes to plot on

  • array (array_like) – 2D array to plot

  • clim (tuple, optional) – Color limits (min, max), default is None (auto-calculated)

  • cmap (str or matplotlib.colors.Colormap, optional) – Colormap to use, default is “inferno”

  • add_cbar (bool, optional) – Whether to add a colorbar, default is True

  • cbar_label (str, optional) – Label for the colorbar, default is None

  • alpha (float, optional) – Transparency (0-1), default is 1

Returns:

The plotted image

Return type:

matplotlib.image.AxesImage

Notes

If clim is None, color limits are calculated using the ColorBar instance.

plot_geodataframe(ax, gdf, column_name, clim=None, cmap='inferno', cbar_label=None, **ctx_kwargs)#

Plot a GeoDataFrame with color mapping and optional basemap.

Parameters:
  • ax (matplotlib.axes.Axes) – Axes to plot on

  • gdf (geopandas.GeoDataFrame) – GeoDataFrame to plot

  • column_name (str) – Column name to use for color mapping

  • clim (tuple, optional) – Color limits (min, max), default is None (auto-calculated)

  • cmap (str or matplotlib.colors.Colormap, optional) – Colormap to use, default is “inferno”

  • cbar_label (str, optional) – Label for the colorbar, default is None

  • **ctx_kwargs – Additional keyword arguments for contextily.add_basemap

Returns:

The axes with the plot

Return type:

matplotlib.axes.Axes

Notes

If ctx_kwargs are provided, adds a basemap using contextily.

cb#
clim_perc = (2, 98)#
lognorm = False#
title = None#
class asp_plot.utils.Raster(fn, downsample=1)#

Utility class for raster data handling and processing.

This class provides convenient methods for reading, processing, and analyzing raster data using rasterio and GDAL.

fn#

Path to the raster file

Type:

str

ds#

Open rasterio dataset

Type:

rasterio.DatasetReader

downsample#

Downsampling factor for reading data

Type:

int or float

data#

Cached raster data (loaded on demand)

Type:

numpy.ma.MaskedArray or None

transform#

Affine transform for the raster (adjusted if downsampled)

Type:

affine.Affine

Examples

>>> raster = Raster("path/to/dem.tif")
>>> data = raster.read_array()
>>> hillshade = raster.hillshade()
>>> epsg = raster.get_epsg_code()
>>> gsd = raster.get_gsd()
>>> # Downsample for faster plotting
>>> raster_ds = Raster("path/to/dem.tif", downsample=10)
>>> raster_ds.plot(ax=ax, cmap="viridis")
compute_difference(second_fn, save=False)#

Compute the difference between this raster and another.

Parameters:
  • second_fn (str) – Path to the second raster file

  • save (bool, optional) – Whether to save the difference raster to disk, default is False

Returns:

Difference array (second_raster - this_raster)

Return type:

numpy.ndarray

Notes

Aligns rasters to the grid of the second raster before differencing. If save=True, saves the difference raster with “_diff.tif” suffix.

get_bounds(latlon=True, json_format=True)#

Get the geographic bounds of the raster.

Parameters:
  • latlon (bool, optional) – Whether to return bounds in latitude/longitude, default is True

  • json_format (bool, optional) – Whether to return bounds in GeoJSON-like format, default is True

Returns:

If json_format=True: list of corner coordinates as dictionaries If json_format=False: tuple of (min_x, min_y, max_x, max_y)

Return type:

list or tuple

get_epsg_code()#

Get the EPSG code for the raster’s coordinate reference system.

Returns:

EPSG code

Return type:

int

Notes

If the CRS has no exact EPSG match (e.g. a compound or 3D-promoted CRS such as “EPSG:32610+EPSG:4979”), falls back to the EPSG code of the horizontal (2D) component.

get_gsd()#

Get the ground sample distance (resolution) of the raster.

Returns:

Ground sample distance (pixel size) in raster units

Return type:

float

get_ndv()#

Get the no-data value for the raster.

Returns:

No-data value

Return type:

float or int

Notes

If no-data value is not defined in the raster metadata, tries to infer it from the first pixel value.

get_utm_epsg_code()#

Estimate the appropriate UTM EPSG code for this raster’s location.

Uses the raster’s center coordinates to determine the correct UTM zone via the PROJ database. Works regardless of the raster’s current CRS (geographic or projected).

Returns:

UTM EPSG code (e.g., 32616 for UTM Zone 16N)

Return type:

int

hillshade()#

Generate a hillshade from the raster.

Returns:

Hillshade array

Return type:

numpy.ma.MaskedArray

Notes

First checks if a hillshade file already exists with “_hs.tif” suffix. If not, generates the hillshade using GDAL.

static load_and_diff_rasters(first_fn, second_fn)#

Load two rasters, align them, and compute their difference.

Parameters:
  • first_fn (str) – Path to the first raster file

  • second_fn (str) – Path to the second raster file (used as reference grid)

Returns:

(difference array (second_raster - first_raster), transform, CRS, nodata)

Return type:

tuple

Notes

The first raster is reprojected and resampled to match the second raster’s grid before differencing. Both rasters are cropped to their intersection first (matching geoutils behavior). Uses rioxarray for efficient reprojection.

read_array(b=1, extent=False)#

Read raster data as a numpy masked array.

Parameters:
  • b (int, optional) – Band number to read, default is 1

  • extent (bool, optional) – Whether to return extent information for plotting, default is False

Returns:

If extent=False: masked array of raster data If extent=True: tuple of (masked array, extent)

Return type:

numpy.ma.MaskedArray or tuple

Notes

No-data values are properly masked, and invalid values are fixed. If downsample > 1, reads a downsampled version of the raster.

read_raster_subset(bbox, b=1)#

Read a subset of raster data defined by a bounding box.

Parameters:
  • bbox (tuple) – Bounding box in the format (ul_x, lr_y, lr_x, ul_y) (upper-left x, lower-right y, lower-right x, upper-left y)

  • b (int, optional) – Band number to read, default is 1

Returns:

Masked array of subset raster data with nodata values masked

Return type:

numpy.ma.MaskedArray

Notes

No-data values are properly masked, similar to read_array()

static save_raster(data, output_fn, reference_fn, dtype=None, nodata=None)#

Save a numpy array as a GeoTIFF using a reference raster’s profile.

Parameters:
  • data (numpy.ndarray) – Data array to save

  • output_fn (str) – Output file path

  • reference_fn (str) – Reference raster file to copy metadata from

  • dtype (numpy.dtype or str, optional) – Data type for output raster, default is None (uses float32)

  • nodata (int or float, optional) – No-data value for output raster, default is None (uses reference nodata)

Return type:

None

Notes

Copies CRS, transform, and other metadata from the reference raster. Useful for saving processed data that should align with an existing raster.

Examples

>>> diff = raster1.data - raster2.data
>>> Raster.save_raster(diff, "difference.tif", reference_fn="raster2.tif")
property data#

Lazy-loaded raster data.

Returns:

Raster data (loaded on first access)

Return type:

numpy.ma.MaskedArray

downsample = 1#
fn#
property transform#

Get the affine transform for the raster.

Returns:

Affine transform (adjusted for downsampling if applicable) or None if the transform is identity (not georeferenced)

Return type:

affine.Affine

Add Vantor copyright text overlay to the bottom-right of a matplotlib axes.

Parameters:

ax (matplotlib.axes.Axes) – The axes to add the copyright overlay to.

asp_plot.utils.detect_planetary_body(dem_fn)#

Detect planetary body from DEM CRS WKT.

Inspects the DATUM/ELLIPSOID fields of the DEM’s CRS WKT string to determine the planetary body. ASP’s point2dem consistently encodes the body name in these fields regardless of projection type.

Parameters:

dem_fn (str) – Path to the DEM file.

Returns:

One of "earth", "moon", or "mars".

Return type:

str

asp_plot.utils.detect_vantor_satellite(directory)#

Check if XML files in directory indicate a Vantor (WorldView) satellite.

Parameters:

directory (str) – Path to directory containing XML camera model files.

Returns:

True if any XML file contains a WorldView SATID (WV01, WV02, WV03, etc.).

Return type:

bool

asp_plot.utils.get_acquisition_dates(directory, extra_dirs=None)#

Extract scene acquisition date(s) from metadata in a processing directory.

Looks for WorldView/Maxar-style XML camera files (using the FIRSTLINETIME tag) and ASTER L1A file or directory names (which encode the capture date in the filename: AST_L1A_<prodcode><MMDDYYYY><HHMMSS>_...). Returns a sorted, deduplicated list of date strings. An empty list is returned if nothing is found.

Parameters:
  • directory (str) – Top-level ASP processing directory to search (non-recursive for XMLs, recursive for ASTER L1A filenames).

  • extra_dirs (list of str, optional) – Additional directories to search non-recursively for XML files (e.g. a stereo or bundle-adjust subdirectory).

Returns:

Acquisition datetime strings formatted as YYYY-MM-DD HH:MM:SS UTC.

Return type:

list of str

asp_plot.utils.get_planetary_bounds(dem_fn, body=None)#

Get DEM bounds in planetocentric lon/lat with 0-360 east-positive longitude.

Reprojects the DEM’s native-CRS bounding box into the body’s geographic coordinate system, which is the format required by the ODE GDS REST API.

Parameters:
  • dem_fn (str) – Path to the DEM file.

  • body (str or None, optional) – Planetary body ("earth", "moon", "mars"). If None, auto-detected from the DEM CRS via detect_planetary_body().

Returns:

Dictionary with keys westernlon, easternlon, minlat, maxlat in planetocentric coordinates with east-positive 0-360 longitude.

Return type:

dict

asp_plot.utils.get_utm_epsg(lon, lat)#

Get the UTM EPSG code for a given longitude and latitude.

Uses the PROJ database to determine the correct UTM zone.

Parameters:
  • lon (float) – Longitude in degrees

  • lat (float) – Latitude in degrees

Returns:

UTM EPSG code (e.g., 32616 for UTM Zone 16N)

Return type:

int

asp_plot.utils.get_xml_tag(xml, tag, all=False)#

Extract value(s) from XML tag(s).

Parses an XML file and extracts the content of specified tag(s).

Parameters:
  • xml (str) – Path to XML file

  • tag (str) – XML tag to extract

  • all (bool, optional) – If True, find all occurrences of the tag; if False, find first occurrence Default is False

Returns:

If all=False: string content of the first matching tag If all=True: list of string contents for all matching tags

Return type:

str or list

Raises:

ValueError – If the tag is not found in the XML file

Examples

>>> satid = get_xml_tag("path/to/file.xml", "SATID")
>>> ephemeris = get_xml_tag("path/to/file.xml", "EPHEMLIST", all=True)
asp_plot.utils.glob_file(directory, *patterns, all_files=False)#

Find files matching pattern(s) in a directory.

Searches a directory for files matching one or more glob patterns. By default, returns the first matching file found. If all_files is True, returns all matching files.

Parameters:
  • directory (str) – Directory to search in

  • *patterns (str) – One or more glob patterns (e.g., “*.tif”, “*DEM.tif”)

  • all_files (bool, optional) – If True, return all matching files; if False, return only the first match. Default is False.

Returns:

If all_files is False, returns the first matching file path or None if no matches If all_files is True, returns a list of matching file paths or None if no matches

Return type:

str or list or None

Examples

>>> first_tif = glob_file("/path/to/dir", "*.tif")
>>> all_tifs = glob_file("/path/to/dir", "*.tif", all_files=True)
>>> dem_file = glob_file("/path/to/dir", "*-DEM.tif", "*_dem.tif")
asp_plot.utils.run_subprocess_command(command)#

Run a subprocess command and stream output.

Executes a shell command using subprocess, streaming its output in real time to the console.

Parameters:

command (list or str) – Command to execute as a list of arguments or a single string

Returns:

Return code from the command (0 for success)

Return type:

int

Notes

This function prints command output in real time and indicates whether command execution was successful.

Examples

>>> run_subprocess_command(["ls", "-la"])
>>> run_subprocess_command("dg_mosaic --skip-tif-gen --output-prefix output_file input_files")
asp_plot.utils.save_figure(fig, save_dir=None, fig_fn=None, dpi=None)#

Save a matplotlib figure to a file.

Saves a figure to the specified directory with the given filename. Creates the directory if it doesn’t exist.

Parameters:
  • fig (matplotlib.figure.Figure) – Figure object to save

  • save_dir (str, optional) – Directory to save the figure in

  • fig_fn (str, optional) – Filename for the saved figure

  • dpi (int or None, optional) – Resolution in dots per inch. Default is None, which uses the figure’s own DPI setting.

Return type:

None

Raises:

ValueError – If save_dir or fig_fn is not provided

Examples

>>> fig, ax = plt.subplots()
>>> ax.plot([1, 2, 3], [1, 2, 3])
>>> save_figure(fig, save_dir='plots', fig_fn='line_plot.png')
asp_plot.utils.show_existing_figure(filename)#

Display an existing figure from a file.

Loads and displays an image file using matplotlib.

Parameters:

filename (str) – Path to the image file

Returns:

Displays the figure in the current matplotlib figure

Return type:

None

Notes

If the file does not exist, a message is printed and no figure is displayed.

asp_plot.utils.logger#