LocalCovarianceFeatures#

class LocalCovarianceFeatures(k=16, include_self=False, gaussian_weight=False, gaussian_sigma=None, out_keys=('local_eigvals', 'local_shape'))[source]#

Bases: object

Per-point local-neighborhood covariance eigen-features.

Reads data_dict["coord"], builds a kd-tree, and for each point computes the covariance of its k nearest neighbors (optionally Gaussian-weighted), then its sorted (descending) eigenvalues. Writes out_keys[0] = local_eigvals (N, 3) and out_keys[1] = local_shape (N, 4) holding the anisotropy ratios l2/l1, l3/l2, l3/l1 and the surface variation/curvature l3 / (l1 + l2 + l3). Both keys are appended to data_dict["index_valid_keys"] so they are carried through index-based cropping. A no-op when coord is missing or empty. Registered as LocalCovarianceFeatures — use this string as the type in a transform=[...] config list.

Parameters:
  • k (int) – Number of neighbors used per point. Defaults to 16.

  • include_self (bool) – If True, include the point itself among its neighbors; otherwise the nearest (self) neighbor is dropped. Defaults to False.

  • gaussian_weight (bool) – If True, weight neighbors by a Gaussian of their distance rather than uniformly. Defaults to False.

  • gaussian_sigma (float, optional) – Fixed Gaussian bandwidth; if None a per-point median-distance bandwidth is used. Defaults to None.

  • out_keys (tuple) – Output keys (eigvals_key, shape_key). Defaults to ("local_eigvals", "local_shape").

Note

Requires data_dict["index_valid_keys"] to already exist (it is appended to, not created).

Example

>>> import numpy as np
>>> rng = np.random.default_rng(0)
>>> data = {"coord": rng.random((20, 3), dtype="f4"), "index_valid_keys": []}
>>> out = LocalCovarianceFeatures(k=5)(data)
>>> out["local_eigvals"].shape, out["local_shape"].shape
((20, 3), (20, 4))  # per-point sorted eigvals + (l2/l1, l3/l2, l3/l1, curvature)
>>> out["index_valid_keys"]
['local_eigvals', 'local_shape']  # registered for index-based cropping