Skip to content

sylva.geo.interpolate

sylva.geo.interpolate

Interpolation between point clouds and rasters.

Three directions are covered:

  • transfer_attributes carries attributes from one cloud to another (for example labels computed on a thinned cloud back to the full cloud);
  • grid interpolates points onto a ~sylva.raster.Raster by inverse distance weighting, a triangulated irregular network or natural-neighbour interpolation;
  • sample_raster and sample_rasters read rasters at the points of a cloud.

transfer_attributes

transfer_attributes(source: PointCloud, target: PointCloud, names: str | Iterable[str] | None = None, method: str = 'nearest', k: int = 8, power: float = 2.0, max_distance: float | None = None, fill=None) -> PointCloud

Interpolate attributes of one cloud onto the points of another.

A k-d tree is built on source and every target point is processed independently and in parallel, so the target can hold hundreds of millions of points; the source is typically a thinned copy of it. Distances are 3D.

Parameters:

Name Type Description Default
source PointCloud

Cloud carrying the attributes. Points with a non-finite coordinate are ignored.

required
target PointCloud

Cloud that receives them.

required
names str | Iterable[str] | None

Attribute name or names to transfer; every attribute of source if None.

None
method ('nearest', 'idw', 'majority')

"nearest" copies the value of the nearest source point and works for any dtype. "idw" takes the inverse-distance weighted mean over the k nearest source points (weights 1 / d**power; a target that coincides with source points takes the mean of their values; non-finite source values are skipped); numeric attributes only. "majority" takes the most common value among the k nearest source points, ties going to the value of the nearest one; use it for labels such as tree_id, classification or a wood mask, which must not be averaged.

"nearest"
k int

Neighbours considered by "idw" and "majority".

8
power float

Inverse-distance exponent for "idw" (0 gives the plain mean).

2.0
max_distance float | None

Only source points within this distance (m) of a target point are used. Target points with none keep no value and get fill. None means no limit.

None
fill

Value for target points left without one (beyond max_distance, non-finite coordinates, or an empty source). By default NaN for floating-point results (including every "idw" result) and -1 for integer and boolean attributes.

None

Returns:

Type Description
PointCloud

target with the transferred attributes added (replacing attributes of the same name); coordinates and other attributes are shared with target. "nearest" and "majority" keep the source dtype, except that an unsigned or boolean attribute whose fill it cannot represent (for example -1 in uint8) is widened to the smallest signed type holding both, whenever max_distance is given or some point is left unfilled; pass a representable fill (fill=0) to keep the dtype. "idw" returns float32 for float32 attributes and float64 otherwise.

Raises:

Type Description
ValueError

For an unknown method or attribute name, "idw" on a non-numeric attribute, k < 1, a negative power or a negative max_distance.

Examples:

Segment a thinned copy of a cloud, then label every original point:

>>> thin = sylva.filters.voxel_downsample(cloud, 0.05)
>>> thin = thin.with_attrs(tree_id=labels)
>>> full = interpolate.transfer_attributes(thin, cloud, "tree_id",
...                                        method="majority", k=5,
...                                        max_distance=0.1)

grid

grid(cloud: PointCloud, resolution: float, value: str = 'z', method: str = 'idw', bounds=None, power: float = 2.0, k: int = 12, max_distance: float | None = None) -> Raster

Interpolate point values onto a regular grid.

Each cell takes the value interpolated at its centre from the points' x, y positions. Grid geometry follows sylva.ground.make_dtm: row 0 is at ymin; without bounds the south-west corner is the points' minimum snapped down to a multiple of resolution and the grid extends past their maximum.

Parameters:

Name Type Description Default
cloud PointCloud

Points to interpolate, e.g. the ground points of a classified cloud. Points with a non-finite x, y or value are ignored, and points that share an x, y are merged into one carrying their mean value.

required
resolution float

Cell size (m).

required
value str

"z" or the name of a numeric attribute to interpolate.

'z'
method ('idw', 'tin', 'natural')

"idw": inverse distance weighting over the k nearest points in x, y (weights 1 / d**power); every cell gets a value unless max_distance is set, and values stay within the range of the data. "tin": linear interpolation on the Delaunay triangulation of the points, exact for planar data. "natural": natural- neighbour (Sibson) interpolation, smooth away from the data points and exact for linear functions. Both "tin" and "natural" leave cells outside the convex hull of the points NaN.

"idw"
bounds

(xmin, ymin, xmax, ymax) of the grid; the extent of the points if None.

None
power float

Inverse-distance exponent ("idw" only).

2.0
k int

Neighbours per cell ("idw" only).

12
max_distance float | None

Cells whose centre is farther than this (m, in x, y) from every point are NaN, for every method; None means no limit.

None

Returns:

Type Description
Raster

Interpolated values, NaN where there is none. crs is taken from the cloud when it has one.

Raises:

Type Description
ValueError

For an unknown method or attribute, a non-positive resolution, invalid bounds, k < 1, a negative power or max_distance, or an empty cloud without bounds.

See Also

sylva.ground.make_dtm : a DTM with these methods (method="tin").

Examples:

>>> ground = cloud[sylva.ground.ground_mask(cloud)]
>>> dtm = interpolate.grid(ground, 0.25, method="tin")
>>> intensity = interpolate.grid(cloud, 0.5, value="intensity")

sample_raster

sample_raster(cloud: PointCloud, raster: Raster, name: str, method: str = 'bilinear') -> PointCloud

Add the value of a raster at each point as an attribute.

Parameters:

Name Type Description Default
cloud PointCloud

Points in the raster's frame.

required
raster Raster

Grid to read, e.g. a DTM, CHM or canopy cover map.

required
name str

Name of the new attribute.

required
method ('bilinear', 'nearest')

"bilinear" interpolates between the four surrounding cell centres (as sylva.raster.Raster.sample), holding the edge value in the outer half of the border cells; a NaN among the four cells gives NaN. "nearest" takes the value of the cell containing the point.

"bilinear"

Returns:

Type Description
PointCloud

The cloud with name added as float64. Points outside the raster's extent (xmin <= x < xmax, ymin <= y < ymax) get NaN.

Raises:

Type Description
ValueError

For an unknown method.

See Also

sylva.ground.normalize_height : height above a DTM, which extends the DTM's edge values beyond it instead of returning NaN.

sample_rasters

sample_rasters(cloud: PointCloud, rasters: Mapping[str, Raster], method: str = 'bilinear') -> PointCloud

Add the values of several rasters at each point as attributes.

Parameters:

Name Type Description Default
cloud PointCloud

Points in the rasters' frame.

required
rasters Mapping[str, Raster]

Attribute name to raster, e.g. {"ground": dtm, "canopy": chm}. The rasters need not share a grid.

required
method ('bilinear', 'nearest')

As for sample_raster, applied to every raster.

"bilinear"

Returns:

Type Description
PointCloud

The cloud with one float64 attribute per raster, NaN outside it.

Raises:

Type Description
ValueError

For an unknown method.