ashdisperse.core package

Submodules

ashdisperse.core.core module

ashdisperse.core.core.LowerODE(kx, ky, fxy_ij, grain_i, cheby, parameters, velocities)
ashdisperse.core.core.UpperODE(kx, ky, grain_i, cheby, parameters, velocities)

ashdisperse.core.getters module

ashdisperse.core.getters.Source_z(z, profile, Suzuki_k, lower, upper)
ashdisperse.core.getters.Source_z_dimless(z, profile, Suzuki_k, lower, upper, H)
ashdisperse.core.getters.Source_z_dimless_value(z, profile, Suzuki_k, lower, upper, H)
ashdisperse.core.getters.Source_z_value(z, profile, Suzuki_k, lower, upper)
ashdisperse.core.getters.Ws_surface(velocities, k)
ashdisperse.core.getters.lower_U(velocities, k)
ashdisperse.core.getters.lower_V(velocities, k)
ashdisperse.core.getters.lower_Ws(velocities, k)
ashdisperse.core.getters.lower_dWsdz(velocities, k)
ashdisperse.core.getters.lower_z(velocities, k)
ashdisperse.core.getters.upper_U(velocities, k)
ashdisperse.core.getters.upper_V(velocities, k)
ashdisperse.core.getters.upper_Ws(velocities, k)
ashdisperse.core.getters.upper_dWsdz(velocities, k)
ashdisperse.core.getters.upper_z(velocities, k)

ashdisperse.core.results module

class ashdisperse.core.results.AshDisperseResult(params: Parameters, C0_FT: ndarray[tuple[Any, ...], dtype[complex128]], Cz_FT: ndarray[tuple[Any, ...], dtype[complex128]])

Bases: object

Results of an AshDisperse simulation

C0: ndarray[tuple[Any, ...], dtype[float64]]
C0_FT: ndarray[tuple[Any, ...], dtype[complex128]]
C0_dimless: ndarray[tuple[Any, ...], dtype[float64]]
Cz: ndarray[tuple[Any, ...], dtype[float64]]
Cz_FT: ndarray[tuple[Any, ...], dtype[complex128]]
Cz_dimless: ndarray[tuple[Any, ...], dtype[float64]]
POI_ashload(latlon: tuple[float, float] | list[tuple[float, float]], vmin: float = 1e-05) tuple[float | ndarray[tuple[Any, ...], dtype[float64]], list[dict[str, float | ndarray[tuple[Any, ...], dtype[float64]] | None]]]

Retrieve the ground-level ash load at a points-of-interest, aggregated over all grain classes.

Ash load represents the total deposited mass per unit area (kg/m²) summed over all grain class, computed as:

ashload = sum (settling_flux_igrain) * eruption_duration

Parameters

latlontuple[float, float] | list[tuple[float, float]]

Point- or points-of-interest. A single point is passed as a tuple as (latitude, longitude). Multiple points-of-interest are passed as a list of single points.

vminfloat, optional

Minimum ash load threshold (kg/m²). Values below this threshold are treated as absent. Default is 1e-5.

Returns

tuple[float | NDArray[np.float64], list[dict[str, float | NDArray[np.float64] | None]]]

If valid data exists, returns a tuple (total_load, load_by_grain): - total_load: the cummulative ash load, returned as either:

  • float if latlon is a single point

  • list[float] if latlon is a list of points

If no valid data is found, the total load is zero.

  • load_by_grain: the loads for each grain class, returned as dict containing:
    • diameter: the grain diameter

    • density: the grain density

    • proportion: the grain proportion

    • load: the grain load, returned as
      • float if latlon is a single point

      • list[float] if latlon is a list of points

      • None if no valid data is found

POI_ashload_for_grain_class(grain_i: int, latlon: tuple[float, float] | list[tuple[float, float]], vmin: float = 1e-05) float | ndarray[tuple[Any, ...], dtype[float64]] | None

Retrieve the ground-level ash load at a points-of-interest for a specific grain class

Ash load represents the total deposited mass per unit area (kg/m²) for the specified grain class, computed as:

ashload = settling_flux * eruption_duration

Parameters

grain_iint

Zero-based index of the grain size class to extract.

latlontuple[float, float] | list[tuple[float, float]]

Point- or points-of-interest. A single point is passed as a tuple as (latitude, longitude). Multiple points-of-interest are passed as a list of single points.

vminfloat, optional

Minimum ash load threshold (kg/m²). Values below this threshold are treated as absent. Default is 1e-5.

Returns

float | NDArray[np.float64] | None

If valid data exists, returns: - a float if latlon is a single point - a 1D ndarray of floats if latlon is a list of points If no valid data exists (e.g., all values below vmin), returns None.

POI_groundconc(latlon: tuple[float, float] | list[tuple[float, float]], vmin: float = 0.001) tuple[float | ndarray[tuple[Any, ...], dtype[float64]], list[dict[str, float | ndarray[tuple[Any, ...], dtype[float64]]]]]
POI_groundconc_for_grain_class(grain_i: int, latlon: tuple[float, float] | list[tuple[float, float]], vmin: float = 0.001) float | ndarray[tuple[Any, ...], dtype[float64]] | None
POI_settlingflux(latlon: tuple[float, float] | list[tuple[float, float]], vmin: float = 0.001) tuple[float | ndarray[tuple[Any, ...], dtype[float64]], list[dict[str, float | ndarray[tuple[Any, ...], dtype[float64]]]]]
POI_settlingflux_for_grain_class(grain_i: int, latlon: tuple[float, float] | list[tuple[float, float]], vmin: float = 0.001) float | ndarray[tuple[Any, ...], dtype[float64]] | None
SettlingFlux: ndarray[tuple[Any, ...], dtype[float64]]
change_MER(MER: float) AshDisperseResult

Create a new AshDisperseResult with updated mass eruption rate (MER).

This method does not modify the original object; instead, it returns a new instance with the specified MER applied.

Parameters

MERfloat

A float representing the new MER. The MER must be positive.

Returns

AshDisperseResult

A new AshDisperseResult instance with updated MER.

Raises

ValueError

If MER is not positive.

Examples

Change original_result with new MER of 1e7
>>> result = original_result.change_duration(1e6)
>>> result.params.source.MER
1000000.0
change_duration(duration: float) AshDisperseResult

Create a new AshDisperseResult with updated duration.

This method does not modify the original object; instead, it returns a new instance with the specified duration applied.

Parameters

durationfloat

A float representing the new duration. The duration must be positive.

Returns

AshDisperseResult

A new AshDisperseResult instance with updated duration.

Raises

ValueError

If duration is not positive.

Examples

Change original_result with new duration of one hour
>>> result = original_result.change_duration(3600)
>>> result.params.source.duration
3600.0
change_grain_proportions(props: list[float]) AshDisperseResult

Create a new AshDisperseResult with updated grain size proportions.

This method does not modify the original object; instead, it returns a new instance with the specified grain size proportions applied.

Parameters

propslist of float

A list of floats representing the new proportions for each grain size class. The length of this list must equal the number of grain size classes defined in self.params.grains.bins. Each value must be in the range [0, 1].

Returns

AshDisperseResult

A new AshDisperseResult instance with updated grain proportions.

Raises

RuntimeError

If the length of props does not match the number of grain size classes (self.params.grains.bins).

ValueError

If any element in props is outside the valid range [0, 1]. Each proportion must be a float between 0 and 1 inclusive, representing the fraction of material in that grain size class.

Examples

Change original_result with three grain classes
>>> result = original_result.change_grain_proportions([0.2, 0.3, 0.5])
>>> result.params.grains.proportion
array([0.2, 0.3, 0.5])
contour_ashload_for_grain_class(grain_i, cntrs_levels='log', vmin=0.01)
contour_settling_flux(grain_i, logscale=True, vmin=1e-06)
classmethod create(params, C0_FT, Cz_FT) Self
folium_ashloads(savename, vmin=0.001)
classmethod from_netcdf(filename: str) AshDisperseResult

Create an AshDisperseResult from a NetCDF file.

This classmethod loads a NetCDF dataset, reconstructs the full set of model parameters (solver, grains, source, emission, physical, meteorology, output, and model parameters), and returns a new result object populated with the spectral fields C0_FT and Cz_FT.

The method attempts to handle both scalar and array encodings for several parameter groups (e.g., grains, emission, model), choosing between from_values and from_lists depending on the underlying type.

Parameters

filenamestr

Path to the NetCDF file containing AshDisperse output. This file is expected to include fields such as version, solver domain and grid settings, grain properties (diameter, density, proportion), source parameters, emission profile parameters, physical constants, meteorology, output scheduling, model scaling parameters, and the real/imaginary parts of the spectral fields: C0_FT_r, C0_FT_i, Cz_FT_r, and Cz_FT_i.

Returns

Self

A new instance of AshDisperseResult initialized from the contents of the NetCDF file.

Raises

FileNotFoundError

If filename does not exist.

OSError

If the file cannot be opened or read as a NetCDF dataset.

KeyError

If required variables are missing from the dataset (e.g., grid settings, grain properties, spectral components).

ValueError

If variable shapes or dtypes are incompatible with the expected parameter constructors (e.g., mismatched array lengths across diameter/density/ proportion or emission profiles).

Warnings

UserWarning

If the dataset version (da.version) differs from the current library version (__version__). The method continues but warns about possible incompatibilities.

Notes

  • Grain parameters:

Switches between GrainParameters.from_values and GrainParameters.from_lists depending on whether da.diameter is loaded as a scalar (np.float64) or an array-like. - Emission parameters: Similarly selects EmissionParameters.from_values vs from_lists based on the type of da.emission_lower. - Model parameters: Chooses ModelParameters.from_values vs from_lists using the type of da.SettlingScale. - Spectral fields: The complex arrays are reconstructed from their real and imaginary parts as C0_FT = C0_FT_r + 1j * C0_FT_i and Cz_FT = Cz_FT_r + 1j * Cz_FT_i.

Examples

>>> result = AshDisperseResult.from_netcdf("outputs/ashdisperse_run.nc")
>>> result.params.solver.Nx_log2, result.params.solver.Ny_log2
(10, 10)
>>> result.C0_FT.shape, result.Cz_FT.shape
((256, 256), (256, 256))
get_ashload(resolution: float = 300.0, vmin: float = 0.001, nodata: float = -1.0) tuple[ndarray[tuple[Any, ...], dtype[float64]], ndarray[tuple[Any, ...], dtype[float64]], ndarray[tuple[Any, ...], dtype[float64]]]
get_ashload_for_grain_class(grain_i: int, vmin: float = 1e-05, masked: bool = False, clipped: bool = True) tuple[ndarray[tuple[Any, ...], dtype[float64]], ndarray[tuple[Any, ...], dtype[float64]], ndarray[tuple[Any, ...], dtype[float64]]] | None

Retrieve the ground-level ash load grid for a specific grain size class.

Ash load represents the total deposited mass per unit area (kg/m²) for the specified grain class, computed as:

ashload = settling_flux * eruption_duration

Parameters

grain_iint

Zero-based index of the grain size class to extract.

vminfloat, optional

Minimum ash load threshold (kg/m²). Values below this threshold are treated as absent. Default is 1e-5.

maskedbool, optional

If True, return a masked array where values below vmin are masked. Default is False.

clippedbool, optional

If True, clip the returned grid to the smallest bounding box that contains all values above vmin. If False, return the full model grid for the grain class. Default is True.

Returns

tuple of ndarray or None

If valid data exists, returns a tuple (x, y, ashload): - x : 1D ndarray of x-coordinates (model units) - y : 1D ndarray of y-coordinates (model units) - ashload : 2D ndarray or MaskedArray of ash load values (kg/m²) with shape (ny, nx) If no valid data exists (e.g., all values below vmin or clipped region is empty), returns None.

Raises

IndexError

If grain_i is out of range for the available grain size classes.

ValueError

If grain_i is negative.

Notes

  • Ash load is derived from the precomputed settling flux multiplied by the

eruption duration. - Use masked=True to obtain a masked array suitable for plotting or further filtering. - When clipped=True, the returned coordinates and grid are cropped to the minimal region containing ash load values above vmin. - If all ash load values are below vmin, the method returns None.

See Also

get_settlingflux_for_grain_class : Retrieve settling flux (kg/m²/s) for a grain class. raster_ashload_for_grain_class : Export ash load as an xarray.Dataset with geospatial metadata.

Examples

>>> x, y, ashload = result.get_ashload_for_grain_class(2, vmin=1e-4, masked=True)
get_groundconc_for_grain_class(grain_i: int, vmin: float = 1e-09, masked: bool = False, clipped: bool = True) tuple[ndarray[tuple[Any, ...], dtype[float64]], ndarray[tuple[Any, ...], dtype[float64]], ndarray[tuple[Any, ...], dtype[float64]]] | None

Retrieve the ground-level concentration grid for a specific grain size class.

This method extracts the concentration field for the given grain class at ground level, optionally masking low values and/or clipping the grid to the minimal bounding region containing valid data.

Parameters

grain_iint

Zero-based index of the grain size class to extract.

vminfloat, optional

Minimum concentration threshold. Values below this threshold are treated as absent. Default is 1e-9.

maskedbool, optional

If True, return a masked array where values below vmin are masked. Default is False.

clippedbool, optional

If True, clip the returned grid to the smallest bounding box that contains all values above vmin. If False, return the full model grid for the grain class. Default is True.

Returns

tuple of ndarray or None

If valid data exists, returns a tuple (x, y, conc): - x : 1D ndarray of x-coordinates (model units) - y : 1D ndarray of y-coordinates (model units) - conc : 2D ndarray or MaskedArray of concentrations with shape (ny, nx) If no valid data exists (e.g., all values below vmin or clipped region is empty), returns None.

Raises

IndexError

If grain_i is out of range for the available grain size classes.

ValueError

If grain_i is negative.

Notes

  • Use masked=True to obtain a masked array suitable for plotting or

further filtering. - When clipped=True, the returned coordinates and grid are cropped to the minimal region containing concentrations above vmin. - If all concentrations are below vmin, the method returns None.

Examples

>>> x, y, conc = result.get_groundconc_for_grain_class(0, vmin=1e-8, masked=True)
get_settlingflux_for_grain_class(grain_i: int, vmin: float = 1e-07, masked: bool = False, clipped: bool = True) tuple[ndarray[tuple[Any, ...], dtype[float64]], ndarray[tuple[Any, ...], dtype[float64]], ndarray[tuple[Any, ...], dtype[float64]]] | None

Retrieve the ground-level settling flux (mass flux to surface) for a specific grain size class.

This method extracts the settling flux field for the given grain class at ground level, optionally masking low values and/or clipping the grid to the minimal bounding region containing valid flux data.

Parameters

grain_iint

Zero-based index of the grain size class to extract.

vminfloat, optional

Minimum flux threshold (kg/m²/s). Values below this threshold are treated as absent. Default is 1e-7.

maskedbool, optional

If True, return a masked array where values below vmin are masked. Default is False.

clippedbool, optional

If True, clip the returned grid to the smallest bounding box that contains all values above vmin. If False, return the full model grid for the grain class. Default is True.

Returns

tuple of ndarray or None

If valid data exists, returns a tuple (x, y, flux): - x : 1D ndarray of x-coordinates (model units) - y : 1D ndarray of y-coordinates (model units) - flux : 2D ndarray or MaskedArray of settling flux values with shape (ny, nx) If no valid data exists (e.g., all values below vmin or clipped region is empty), returns None.

Raises

IndexError

If grain_i is out of range for the available grain size classes.

ValueError

If grain_i is negative.

Notes

  • Settling flux represents the mass flux to the ground surface for the specified grain class.

  • Use masked=True to obtain a masked array suitable for plotting or further filtering.

  • When clipped=True, the returned coordinates and grid are cropped to the minimal region

containing flux values above vmin. - If all flux values are below vmin, the method returns None.

Examples

>>> x, y, flux = result.get_settlingflux_for_grain_class(1, vmin=1e-6, masked=True)
get_total_ashload(resolution: float = 300.0, vmin: float = 0.001, nodata: float = -1.0) tuple[ndarray[tuple[Any, ...], dtype[float64]], ndarray[tuple[Any, ...], dtype[float64]], ndarray[tuple[Any, ...], dtype[float64]]]

Compute aggregated total ash load raster from all grain-class settling fluxes.

Parameters

resolutionfloat, optional

Output grid resolution in model units (default: 300.0).

vminfloat, optional

Minimum value to keep (values below are masked/nodata, default: 1e-3).

nodatafloat, optional

Value to use for nodata in output arrays (default: -1).

Returns

(x, y, totalAshLoad)tuple of arrays,

x, y are 1D arrays of coordinates; totalAshLoad is a masked 2D array.

property grain_classes: int

Number of grain classes

Returns

int

Number of grain classes

property interpolated: bool

Check if this AshDisperseResult is produced by interpolation

Returns

bool

True if this AshDisperseResult is produced by zero-padding interpolation from a computed AshDisperseResult, False otherwise

kx: ndarray[tuple[Any, ...], dtype[float64]]
ky: ndarray[tuple[Any, ...], dtype[float64]]
linear_interp(Nx_log2: int, Ny_log2: int) AshDisperseResult

Return a new AshDisperseResult with bilinear interpolation by zero-padding the FFTs.

Parameters

Nx_log2int

log2 of the number of Fourier modes in x

Ny_log2int

log2 of the number of Fourier modes in y

Returns

AshDisperseResult

A new AshDisperseResult. The original object is unchanged.

Notes

The internal stored parameters are updated for the new sizes. A class private variable _interpolated is set to True to indicate this AshDisperseResult is generated by zero-padding interpolation.

max_ashload_for_grain_class(grain_i: int) float
params: Parameters
plot_ashload(resolution=300.0, logscale=True, cmap='viridis', vmin=0.001, nodata=-1, alpha=0.5, basemap=False, export_gtiff=False, export_name='AshLoad.tif', show=True, ds=None)

Plot total ash load as filled contours.

Parameters

resolutionfloat, optional

Output grid resolution (default: 300.0). Ignored if ds is provided.

logscalebool, optional

Use logarithmic color scale (default: True).

cmapmatplotlib colormap, optional

Colormap to use (default: viridis).

vminfloat, optional

Minimum value to plot (default: 1e-3).

nodatafloat, optional

Value to use for nodata (default: -1).

alphafloat, optional

Alpha blending for filled contours (default: 0.5).

basemapbool, optional

If True, add a basemap (default: False).

export_gtiffbool, optional

If True, write a GeoTIFF (default: False).

export_namestr, optional

Filename for GeoTIFF (default: ‘AshLoad.tif’).

showbool, optional

If True, show the plot (default: True).

dsxarray.Dataset, optional

If provided, use this dataset (must have ‘ash_load’). Otherwise, compute from model.

Returns

fig, ax, cbartuple

Matplotlib Figure, Axes, and Colorbar objects.

Notes

If ds is not provided, the function computes the total ash load using current model parameters.

plot_ashload_for_grain_class(grain_i: int, logscale: bool = True, vmin: float = 1e-06, vmax: float | None = None, cmap: str | Colormap = 'plasma', basemap: bool = True, alpha: float = 0.5, max_zoom: int | None = None, show: bool = True, save: bool = False, save_name: str = 'ashdisperse_result.png', min_ax_width: float | None = None, min_ax_height: float | None = None) tuple[Figure, Axes, Colorbar]
plot_conc_for_grain_class(grain_i, logscale=True, vmin=1e-06, cmap='bone', basemap=False)
plot_iso_conc_for_grain_class(grain_i, conc)
plot_settling_flux_for_grain_class(grain_i: int, logscale: bool = True, vmin: float = 1e-06, vmax: float | None = None, cmap: str | Colormap = 'Purples', basemap: bool = True, alpha: float = 0.5, max_zoom: int | None = None, show: bool = True, save: bool = False, save_name: str = 'ashdisperse_result.png', min_ax_width: float | None = None, min_ax_height: float | None = None) tuple[Figure, Axes, Colorbar]
plot_spectrum_for_grainsize(grain_i, vmin=None, vmax=None)
raster_ashload_for_grain_class(grain_i: int, vmin: float = 0.01, nodata: float = nan, masked: bool = False, clipped: bool = True, crs: str | None = None) Dataset | None
raster_groundconc_for_grain_class(grain_i: int, vmin: float = 1e-09, nodata: float = nan, masked: bool = False, clipped: bool = True, crs: str | None = None) Dataset | None
raster_settlingflux_for_grain_class(grain_i: int, vmin: float = 1e-06, nodata: float = nan, masked: bool = False, clipped: bool = True, crs: str | None = None) Dataset | None
raster_total_ashload(resolution: float = 300.0, vmin: float = 0.001, nodata: float = -1.0, crs: str | None = None) Dataset | None

Compute aggregated total ash load raster from all grain-class settling fluxes

Parameters

resolutionfloat, optional

Output grid resolution in model units (default: 300.0).

vminfloat, optional

Minimum value to keep (values below are masked/nodata, default: 1e-3).

nodatafloat, optional

Value to use for nodata in output arrays (default: -1).

Returns

property source_marker: GeoDataFrame

GeoDataFrame containing the source location

Returns

gpd.GeoDataFrame

GeoDataFrame containing the source location in WGS84 coordinates

to_netcdf(filename: str = 'AshDisperse.nc', compress: bool = True, complevel: int = 5) None

Save the current AshDisperseResult to a NetCDF file.

This method writes the complex spectral fields and all associated model parameters to a NetCDF file using the h5netcdf engine. Complex arrays are stored as separate real and imaginary components.

Parameters

filenamestr, optional

Output file path. If the file exists, it will be overwritten. Default is "AshDisperse.nc".

compressbool, optional

Whether to apply zlib compression to data variables. Default is True.

complevelint, optional

Compression level passed to zlib (typically in the range 0-9). Ignored if compress=False. Default is 5.

Returns

None

Raises

PermissionError

If the file cannot be created or overwritten due to insufficient permissions or the path is not writable.

OSError

If there is a low-level I/O or HDF5/NetCDF issue while writing.

ValueError

If an invalid complevel is provided (e.g., out of the supported range for the underlying zlib implementation) or if array shapes are inconsistent with the declared dimensions.

Notes

Data variables (stored as float arrays): - C0_FT_r: Real part of C0_FT with dims ("ky", "kx", "grains") - C0_FT_i: Imag part of C0_FT with dims ("ky", "kx", "grains") - Cz_FT_r: Real part of Cz_FT with dims ("ky", "kx", "z", "grains") - Cz_FT_i: Imag part of Cz_FT with dims ("ky", "kx", "z", "grains")

Coordinates: - grains: range(self.params.grains.bins) - kx: self.kx[: Nx // 2 + 1] (positive and zero wavenumbers) - ky: self.ky - z: self.params.output.altitudes

Global attributes include solver/domain configuration, grain parameters (diameter, density, proportion), source parameters (location, plume, MER, duration), emission profile, physical constants, meteorology, model scaling, and output schedule. The current package version is also recorded.

Compression and encoding: If compress=True, all data variables are written with zlib=True and complevel=complevel. If compress=False, the dataset is written without compression.

File format and engine: The file is written with format="NETCDF4" using the engine="h5netcdf" backend.

Examples

>>> result.to_netcdf("outputs/ashdisperse_run.nc")
>>> result.to_netcdf("outputs/run_compressed.nc", compress=True, complevel=9)
>>> result.to_netcdf("outputs/run_uncompressed.nc    >>> result.to_netcdf("outputs/run_uncompressed.nc", compress=False)
utm: tuple[Any | float, Any | float, Any | int, Any | LiteralString | None]
utmepsg: int
write_ashload_for_grain_class(grain_i: int, vmin: float = 0.001, resolution: float | None = None, outname: str | None = None, compress: str = 'LZW') None
write_gtiff(raster: ndarray[tuple[Any, ...], dtype[float64]], x: ndarray[tuple[Any, ...], dtype[float64]], y: ndarray[tuple[Any, ...], dtype[float64]], outname: str, nodata: float = -1, vmin: float = 1e-06, resolution: float | None = None) None
write_settling_flux_for_grain_class(grain_i: int, nodata: float = -1.0, vmin: float = 1e-06, resolution: float | None = None) None
x: ndarray[tuple[Any, ...], dtype[float64]]
x_dimless: ndarray[tuple[Any, ...], dtype[float64]]
y: ndarray[tuple[Any, ...], dtype[float64]]
y_dimless: ndarray[tuple[Any, ...], dtype[float64]]
ashdisperse.core.results.compat_warning(message: str, category: type[Warning], filename: str, lineno, file=None, line=None) str

Module contents