SphericalHarmonicRegistration#

class ktch.harmonic.SphericalHarmonicRegistration(n_dim=3, method='auto', scale=True, scale_method=None, align_parameter=True, reflect=False, return_transform=False, n_jobs=None, verbose=0)[source]#

Registration of precomputed real SPHARM coefficient vectors.

Registers coefficient arrays produced elsewhere (e.g. by SphericalHarmonicAnalysis.transform(), or by external tools such as SlicerSALT / SPHARM-PDM) without recomputing. Input and output share the axis-major flat layout of SphericalHarmonicAnalysis.transform() ([cx_0_0, cx_1_-1, ..., cy_..., cz_...]); l_max is inferred from the input width.

Registration removes the codomain nuisances (translation, rotation, scale) and, for first_order, the orientation of the parameter sphere, which fixes the correspondence between parameter values and surface points. It is a per-sample canonicalization, so fit is a no-op for the implemented methods and transform() maps each coefficient vector independently.

Parameters:
n_dimint, default=3

Codomain dimension. first_order requires 3 (the l=1 ellipsoid spans a full 3D frame).

method{“auto”, None, “first_order”, “moment”}, default=”auto”

Registration method. "auto" resolves to "first_order" for n_dim=3 and inferred l_max >= 1, and None otherwise. None passes coefficients through unchanged. "first_order" uses the l=1 ellipsoid (first-order ellipsoid canonicalization, Brechbühler et al. 1995) to align both the codomain orientation and the parameter sphere (SO(3)). "moment" aligns the codomain to the second-moment principal axes and scales by centroid size. "landmark" and "rotational_match" are reserved (raise NotImplementedError).

scalebool, default=True

Whether registration removes size (shape space) or keeps it (form space). Ignored when the resolved method is None.

scale_method{None, “semi_major_axis”, “ellipsoid_volume”}, default=None

Size measure when scale=True. None resolves to the method default ("first_order": "semi_major_axis").

align_parameterbool, default=True

Whether "first_order" rotates the parameter sphere as well as the codomain. False rotates the codomain only and keeps the parameterization as given, for input whose parameter sphere is already aligned or already carries a correspondence, such as SPHARM-PDM .coef files (with scale=False this reproduces their _ellalign output up to a half turn about z, see Notes). It warns when the degree-1 columns are not orthogonal. Ignored by "moment".

reflectbool, default=False

Whether to also remove reflection (chirality). False enforces a proper codomain rotation (det=+1).

return_transformbool, default=False

Append the estimated transform (planned: first-order ellipsoid orientation angles and scale) as extra output columns. Reserved; True raises NotImplementedError.

n_jobsint, default=None

Number of parallel jobs over samples.

verboseint, default=0

Verbosity level.

Notes

first_order writes the l=1 ellipsoid as M1 = U Σ Vᵀ, applies Uᵀ to the codomain, rotates the parameter sphere by V via Wigner-D, drops the l=0 mode (translation), and divides by a length derived from the ellipsoid: the semi-major axis, or the cube root of the ellipsoid volume. The ellipsoid’s Klein-four sign ambiguity is broken by a rotation- and reparameterization-invariant third moment, which is ill-conditioned for near-symmetric shapes.

With align_parameter=False the codomain is rotated so that the images of the parameter axes fall on x, y, and z (the nearest rotation to the normalized degree-1 columns) and the parameter sphere is left as it is. The input’s frame is kept; the registered degree-1 block is diagonal in the input’s axis order. SPHARM-PDM’s _ellalign frame is this output turned by a half turn about z, diag(-1, -1, 1) on the codomain, because its degree-1 basis functions follow the Condon-Shortley sign. The turn is the same for every specimen.

Examples

>>> import numpy as np
>>> from ktch.harmonic import (
...     SphericalHarmonicAnalysis,
...     SphericalHarmonicRegistration,
... )
>>> coeffs = np.random.default_rng(0).standard_normal((4, 3 * (3 + 1) ** 2))
>>> reg = SphericalHarmonicRegistration(method="first_order", scale=False)
>>> registered = reg.fit_transform(coeffs)
>>> registered.shape
(4, 48)
fit(X, y=None)#

Validate settings and record the input shape.

Parameters:
Xarray-like of shape (n_samples, n_features)

Flat shape descriptors to register.

yignored
Returns:
selfobject
fit_transform(X, y=None, **fit_params)#

Fit to data, then transform it.

Fits transformer to X and y with optional parameters fit_params and returns a transformed version of X.

Parameters:
Xarray-like of shape (n_samples, n_features)

Input samples.

yarray-like of shape (n_samples,) or (n_samples, n_outputs), default=None

Target values (None for unsupervised transformations).

**fit_paramsdict

Additional fit parameters. Pass only if the estimator accepts additional params in its fit method.

Returns:
X_newndarray array of shape (n_samples, n_features_new)

Transformed array.

get_feature_names_out(input_features=None)#

Get output feature names for transformation.

Parameters:
input_featuresarray-like of str or None, default=None

Input features.

  • If input_features is None, then feature_names_in_ is used as feature names in. If feature_names_in_ is not defined, then the following input feature names are generated: [“x0”, “x1”, …, “x(n_features_in_ - 1)”].

  • If input_features is an array-like, then input_features must match feature_names_in_ if feature_names_in_ is defined.

Returns:
feature_names_outndarray of str objects

Same as input features.

get_metadata_routing()#

Get metadata routing of this object.

Please check User Guide on how the routing mechanism works.

Returns:
routingMetadataRequest

A MetadataRequest encapsulating routing information.

get_params(deep=True)#

Get parameters for this estimator.

Parameters:
deepbool, default=True

If True, will return the parameters for this estimator and contained subobjects that are estimators.

Returns:
paramsdict

Parameter names mapped to their values.

set_output(*, transform=None)#

Set output container.

Refer to the user guide for more details and Introducing the set_output API for an example on how to use the API.

Parameters:
transform{“default”, “pandas”, “polars”}, default=None

Configure output of transform and fit_transform.

  • “default”: Default output format of a transformer

  • “pandas”: DataFrame output

  • “polars”: Polars output

  • None: Transform configuration is unchanged

Added in version 1.4: “polars” option was added.

Returns:
selfestimator instance

Estimator instance.

set_params(**params)#

Set the parameters of this estimator.

The method works on simple estimators as well as on nested objects (such as Pipeline). The latter have parameters of the form <component>__<parameter> so that it’s possible to update each component of a nested object.

Parameters:
**paramsdict

Estimator parameters.

Returns:
selfestimator instance

Estimator instance.

transform(X)#

Register each sample.

Parameters:
Xarray-like of shape (n_samples, n_features)

Flat shape descriptors, same width as seen in fit.

Returns:
X_registeredndarray of shape (n_samples, n_features)

Registered descriptors in the same layout as the input.