pycsamt.ai.geology.fields#
Regular geological grids and anisotropic correlated Gaussian fields.
The canonical array order is (z, x) in 2-D and (z, y, x) in 3-D.
Coordinates represent cell centres in metres, with depth z increasing
downward. Field generation uses spectral synthesis and never invokes an EM
forward solver.
Functions
|
Calculate an unbinned empirical directional semivariogram. |
|
Generate a deterministic anisotropic Gaussian random field. |
Classes
|
Immutable generated scalar field with complete generation provenance. |
|
Empirical semivariance along one canonical geological axis. |
|
Anisotropic Gaussian spatial-correlation model. |
|
Immutable regular cell-centre grid for 2-D or 3-D geological priors. |
- class pycsamt.ai.geology.fields.GeologyGrid(x_m, z_m, y_m=None, crs=None)[source]
Bases:
objectImmutable regular cell-centre grid for 2-D or 3-D geological priors.
- Parameters:
x_m (array-like) – Strictly increasing horizontal and depth cell centres in metres.
z_m (array-like) – Strictly increasing horizontal and depth cell centres in metres.
y_m (array-like or None, optional) – Strictly increasing second horizontal axis. Omit it for a 2-D profile.
crs (str or None, optional) – Coordinate reference system identifier for horizontal coordinates.
Examples
Construct a 2-D grid directly:
>>> grid = GeologyGrid(x_m=[50, 150, 250], z_m=[25, 75]) >>> grid.shape (2, 3) >>> grid.dimension 2
Use
regular_3d()for a volume:>>> volume = GeologyGrid.regular_3d( ... nx=4, ny=3, nz=2, dx_m=100, dy_m=200, dz_m=50 ... ) >>> volume.shape (2, 3, 4)
- x_m: ndarray
- z_m: ndarray
- classmethod regular_2d(*, nx, nz, dx_m, dz_m, x_origin_m=0.0, z_origin_m=0.0, crs=None)[source]
Construct a uniform 2-D cell-centre grid.
- Parameters:
nx (int) – At least two cells in the horizontal and depth directions.
nz (int) – At least two cells in the horizontal and depth directions.
dx_m (float) – Positive cell widths in metres.
dz_m (float) – Positive cell widths in metres.
x_origin_m (float, default=0.0) – Coordinate of the outer edge before the first cell centre.
z_origin_m (float, default=0.0) – Coordinate of the outer edge before the first cell centre.
crs (str or None, optional) – Coordinate reference system identifier.
- Returns:
Grid whose centres begin one half-cell from each origin.
- Return type:
Examples
>>> grid = GeologyGrid.regular_2d(nx=3, nz=2, dx_m=100, dz_m=50) >>> grid.x_m.tolist(), grid.z_m.tolist() ([50.0, 150.0, 250.0], [25.0, 75.0])
- classmethod regular_3d(*, nx, ny, nz, dx_m, dy_m, dz_m, x_origin_m=0.0, y_origin_m=0.0, z_origin_m=0.0, crs=None)[source]
Construct a uniform 3-D cell-centre grid.
- Parameters:
nx (int) – At least two cells along each axis.
ny (int) – At least two cells along each axis.
nz (int) – At least two cells along each axis.
dx_m (float) – Positive cell widths in metres.
dy_m (float) – Positive cell widths in metres.
dz_m (float) – Positive cell widths in metres.
x_origin_m (float, default=0.0) – Outer-edge coordinate before the first centre on each axis.
y_origin_m (float, default=0.0) – Outer-edge coordinate before the first centre on each axis.
z_origin_m (float, default=0.0) – Outer-edge coordinate before the first centre on each axis.
crs (str or None, optional) – Coordinate reference system identifier.
- Returns:
Uniform grid with canonical shape
(nz, ny, nx).- Return type:
Examples
>>> grid = GeologyGrid.regular_3d( ... nx=2, ny=3, nz=4, dx_m=10, dy_m=20, dz_m=5 ... ) >>> grid.shape (4, 3, 2)
- property dimension: int[source]
Return whether the grid is two- or three-dimensional.
- Returns:
Spatial dimension.
- Return type:
{2, 3}
Examples
>>> GeologyGrid.regular_2d(nx=2, nz=2, dx_m=1, dz_m=1).dimension 2
- property shape: tuple[int, ...][source]
Return the canonical geological array shape.
Examples
>>> GeologyGrid.regular_2d(nx=5, nz=3, dx_m=1, dz_m=1).shape (3, 5)
- property spacing_m: tuple[float, ...][source]
Return regular spacing in canonical array-axis order.
- Returns:
(dz, dx)in 2-D or(dz, dy, dx)in 3-D.- Return type:
- Raises:
ValueError – If any coordinate axis is not regularly spaced.
Examples
>>> GeologyGrid.regular_2d(nx=2, nz=2, dx_m=100, dz_m=25).spacing_m (25.0, 100.0)
- property extent_m: dict[str, tuple[float, float]][source]
Return outer cell-edge extents along all available axes.
- Returns:
Axis names mapped to
(minimum_edge, maximum_edge)in metres.- Return type:
Examples
>>> grid = GeologyGrid.regular_2d(nx=2, nz=2, dx_m=100, dz_m=50) >>> grid.extent_m["x"] (0.0, 200.0)
- to_dict()[source]
Return a JSON-serializable grid definition.
- Returns:
Schema version, coordinates, and CRS.
- Return type:
Examples
>>> GeologyGrid.regular_2d(nx=2, nz=2, dx_m=1, dz_m=1).to_dict()[ ... "dimension" ... ] 2
- classmethod from_dict(data)[source]
Restore a validated serialized grid.
- Parameters:
data (mapping) – State returned by
to_dict().- Returns:
Immutable grid.
- Return type:
Examples
>>> grid = GeologyGrid.regular_2d(nx=2, nz=2, dx_m=1, dz_m=1) >>> GeologyGrid.from_dict(grid.to_dict()).shape == grid.shape True
- class pycsamt.ai.geology.fields.GaussianCorrelation(length_x_m, length_z_m, length_y_m=None, azimuth_deg=0.0)[source]
Bases:
objectAnisotropic Gaussian spatial-correlation model.
- Parameters:
length_x_m (float) – Positive horizontal and vertical correlation lengths in metres for
C(h) = exp(-0.5 * (h / length)**2).length_z_m (float) – Positive horizontal and vertical correlation lengths in metres for
C(h) = exp(-0.5 * (h / length)**2).length_y_m (float or None, optional) – Second horizontal length required for 3-D generation.
azimuth_deg (float, default=0.0) – Clockwise rotation of horizontal principal axes. It affects 3-D fields and is normalized to
[0, 180)because Gaussian axes are bidirectional.
Examples
>>> model = GaussianCorrelation(1000, 100, length_y_m=500, azimuth_deg=210) >>> model.azimuth_deg 30.0 >>> model.anisotropy_xz 10.0
- length_x_m: float
- length_z_m: float
- azimuth_deg: float = 0.0
- property anisotropy_xz: float[source]
Return horizontal-to-vertical correlation-length ratio.
- Returns:
length_x_m / length_z_m.- Return type:
Examples
>>> GaussianCorrelation(500, 100).anisotropy_xz 5.0
- validate_grid(grid)[source]
Validate dimensional compatibility with a geological grid.
- Parameters:
grid (GeologyGrid) – Grid on which the model will be sampled.
- Returns:
Successful return means all required correlation lengths exist.
- Return type:
None
- Raises:
TypeError – If
gridis notGeologyGrid.ValueError – If a 3-D grid has no
length_y_m.
Examples
>>> grid = GeologyGrid.regular_2d(nx=2, nz=2, dx_m=1, dz_m=1) >>> GaussianCorrelation(2, 1).validate_grid(grid) is None True
- to_dict()[source]
Return a JSON-serializable correlation model.
- Returns:
Versioned Gaussian lengths and azimuth.
- Return type:
Examples
>>> GaussianCorrelation(10, 2).to_dict()["kind"] 'gaussian'
- classmethod from_dict(data)[source]
Restore a validated Gaussian correlation model.
- Parameters:
data (mapping) – State returned by
to_dict().- Returns:
Immutable model.
- Return type:
Examples
>>> model = GaussianCorrelation(10, 2) >>> GaussianCorrelation.from_dict(model.to_dict()) == model True
- class pycsamt.ai.geology.fields.CorrelatedField(values, grid, correlation, seed, boundary='reflect', standardized=True)[source]
Bases:
objectImmutable generated scalar field with complete generation provenance.
- Parameters:
values (ndarray) – Finite values shaped exactly like
grid.shape.grid (GeologyGrid) – Spatial cell-centre grid.
correlation (GaussianCorrelation) – Requested correlation model.
seed (int) – Recorded random seed.
boundary ({"periodic", "reflect"}, default="reflect") – Spectral boundary policy used during generation.
standardized (bool, default=True) – Whether the stored sample was standardized to zero sample mean and unit sample standard deviation.
Examples
>>> grid = GeologyGrid.regular_2d(nx=8, nz=6, dx_m=100, dz_m=50) >>> field = generate_gaussian_field( ... grid, GaussianCorrelation(300, 100), seed=4 ... ) >>> field.values.shape (6, 8) >>> field.seed 4
- values: ndarray
- grid: GeologyGrid
- correlation: GaussianCorrelation
- seed: int
- boundary: str = 'reflect'
- standardized: bool = True
- property field_hash: str[source]
Return a digest covering values and generation configuration.
- Returns:
Lowercase SHA-256 digest. Values are hashed as contiguous little- endian float64 bytes for platform-stable identity.
- Return type:
Examples
>>> grid = GeologyGrid.regular_2d(nx=4, nz=4, dx_m=1, dz_m=1) >>> field = generate_gaussian_field( ... grid, GaussianCorrelation(2, 1), seed=0 ... ) >>> len(field.field_hash) 64
- provenance()[source]
Return JSON-compatible generation provenance without field values.
- Returns:
Grid, correlation, seed, boundary, and standardization state.
- Return type:
Examples
>>> grid = GeologyGrid.regular_2d(nx=4, nz=4, dx_m=1, dz_m=1) >>> field = generate_gaussian_field( ... grid, GaussianCorrelation(2, 1), seed=0 ... ) >>> field.provenance()["seed"] 0
- rescale(*, mean=0.0, standard_deviation=1.0)[source]
Return a copy with a requested sample mean and standard deviation.
- Parameters:
- Returns:
New field with unchanged spatial pattern and
standardized=Falseunless the requested values are exactly zero and one.- Return type:
Examples
>>> grid = GeologyGrid.regular_2d(nx=8, nz=8, dx_m=1, dz_m=1) >>> field = generate_gaussian_field( ... grid, GaussianCorrelation(2, 1), seed=1 ... ).rescale(mean=2, standard_deviation=3) >>> ( ... round(float(np.mean(field.values)), 12), ... round(float(np.std(field.values)), 12), ... ) (2.0, 3.0)
- to_npz(path)[source]
Persist values and provenance in a pickle-free NPZ archive.
- Parameters:
path (str or pathlib.Path) – Destination archive.
- Returns:
Requested destination path.
- Return type:
Examples
>>> from tempfile import TemporaryDirectory >>> grid = GeologyGrid.regular_2d(nx=4, nz=4, dx_m=1, dz_m=1) >>> field = generate_gaussian_field( ... grid, GaussianCorrelation(2, 1), seed=0 ... ) >>> with TemporaryDirectory() as directory: ... path = field.to_npz(Path(directory) / "field.npz") ... restored = CorrelatedField.from_npz(path) >>> restored.field_hash == field.field_hash True
- classmethod from_npz(path)[source]
Load and validate a field archive without enabling pickle.
- Parameters:
path (str or pathlib.Path) – Archive written by
to_npz().- Returns:
Immutable restored field.
- Return type:
Examples
>>> from tempfile import TemporaryDirectory >>> field = generate_gaussian_field( ... GeologyGrid.regular_2d(nx=3, nz=3, dx_m=1, dz_m=1), ... GaussianCorrelation(2, 1), ... seed=3, ... ) >>> with TemporaryDirectory() as directory: ... path = field.to_npz(Path(directory) / "f.npz") ... restored = CorrelatedField.from_npz(path) >>> np.array_equal(restored.values, field.values) True
- class pycsamt.ai.geology.fields.DirectionalVariogram(axis, lag_m, semivariance, pair_count)[source]
Bases:
objectEmpirical semivariance along one canonical geological axis.
- Parameters:
axis ({"x", "y", "z"}) – Direction along which cell pairs were compared.
lag_m (ndarray) – Positive lag distances and corresponding finite semivariances.
semivariance (ndarray) – Positive lag distances and corresponding finite semivariances.
pair_count (ndarray of int) – Number of finite cell pairs supporting each lag.
Examples
>>> result = DirectionalVariogram("x", [1, 2], [0.2, 0.5], [10, 8]) >>> result.n_lags 2
- axis: str
- lag_m: ndarray
- semivariance: ndarray
- pair_count: ndarray
- pycsamt.ai.geology.fields.generate_gaussian_field(grid, correlation, *, seed, boundary='reflect', standardize=True)[source]
Generate a deterministic anisotropic Gaussian random field.
- Parameters:
grid (GeologyGrid) – Regular 2-D or 3-D cell-centre grid.
correlation (GaussianCorrelation) – Requested Gaussian covariance lengths and horizontal azimuth.
seed (int) – Explicit seed recorded in the returned field.
boundary ({"reflect", "periodic"}, default="reflect") –
periodicsynthesizes directly on the requested grid.reflectsynthesizes on a grid doubled along each axis and crops the centre, reducing wrap-around correlation at opposite model edges.standardize (bool, default=True) – Shift and scale the realized sample to zero mean and unit population standard deviation.
- Returns:
Immutable field with complete generation provenance.
- Return type:
- Raises:
ValueError – If the grid is irregular, correlation model is incompatible, or the filtered realization is numerically constant.
Examples
>>> grid = GeologyGrid.regular_2d(nx=32, nz=16, dx_m=100, dz_m=50) >>> model = GaussianCorrelation(length_x_m=500, length_z_m=100) >>> first = generate_gaussian_field(grid, model, seed=12) >>> second = generate_gaussian_field(grid, model, seed=12) >>> np.array_equal(first.values, second.values) True >>> ( ... abs(round(float(np.mean(first.values)), 12)), ... round(float(np.std(first.values)), 12), ... ) (0.0, 1.0)
- pycsamt.ai.geology.fields.directional_variogram(field, axis, *, max_lag_cells=None)[source]
Calculate an unbinned empirical directional semivariogram.
- Parameters:
field (CorrelatedField) – Finite scalar field.
axis ({"x", "y", "z"}) – Geological direction.
"y"is unavailable for 2-D fields.max_lag_cells (int or None, optional) – Maximum positive integer cell offset. The default is half the selected axis length, with at least one lag.
- Returns:
Lag distance, mean half-squared difference, and pair count.
- Return type:
Examples
>>> grid = GeologyGrid.regular_2d(nx=16, nz=8, dx_m=100, dz_m=50) >>> field = generate_gaussian_field( ... grid, GaussianCorrelation(300, 100), seed=1 ... ) >>> variogram = directional_variogram(field, "x", max_lag_cells=3) >>> variogram.n_lags 3 >>> variogram.pair_count[0] > variogram.pair_count[-1] True