AOM Methods Gap Analysis

Date: 2026-06-05

This audit separates what already exists in nirs4all-methods from what still had to be added from the AOM / moment exploration.

Hard invariant: deployable methods must not route by dataset name, source name, database name, dataset id, or equivalent identity labels.

Already In nirs4all-methods

Native/catalogued primitives:

  • AOM preprocessing and AOM global PLS selection:

    • aom_pop.aom_preprocessing;

    • aom_pop.aom_pls;

    • aom_pop.pop_pls.

  • Model heads or neighboring model families:

    • PLS, CPPLS, Continuum Regression, ECR, Ridge / Ridge-PLS, robust and weighted PLS, PCR via the existing method set.

    • ABI-close Python helper functions now expose reusable moment-model heads: n4m.ridge, n4m.cppls, n4m.continuum_regression, and n4m.ecr.

  • Preprocessing families needed by the lab evidence:

    • Savitzky-Golay;

    • finite differences / derivatives;

    • Norris-Williams;

    • detrend;

    • Gaussian smoothing;

    • SNV, MSC, EMSC, local/weighted/piecewise variants;

    • baseline correction families;

    • FCK static transformer.

Python/reference Phase 7f objects already present before this pass:

  • AOMStructuralPolicy;

  • AOMStructuralPolicyWithPgt1200Admissions;

  • AOMStructuralPolicyWithP700ProtocolUnified;

  • AOMStructuralPolicyWithP700BlockLocalAdmission;

  • AOMControlSelector;

  • AOMTrueBankEndpointPortfolio;

  • AOMMidPEndpointStack;

  • AOMEndpointMarginStabilityGate;

  • AOMFallbackBlendGate.

  • AOMRidgeBlender;

  • AOMOperatorPLSStack.

Missing Before This Pass

The target repo had primitives and selector skeletons, but it did not yet have the product-facing method layer needed by an end user:

  • no built-in AOM preprocessing chain bank reproducing the useful diversity of the lab campaigns;

  • AOMControlSelector was Ridge-only;

  • no direct fit/predict robust-HPO estimator that builds the bank, screens Ridge/PLS heads, and reports the selected chain;

  • no compact end-user preset;

  • no wide/lab-style preset for controlled reproduction of larger preprocessing diversity.

Added In This Pass

Python/reference methods:

  • AOMPreprocessingChain:

    • fold-safe sequential preprocessing transformer;

    • deep-copies and fits each step inside CV;

    • used as the standard chain object for generated banks.

  • build_aom_control_chain_bank(profile=...):

    • compact: fast end-user bank;

    • robust: broader default bank;

    • wide / lab / moment_lab: larger lab-style bank;

    • includes the recurring families: raw, row center, SNV, MSC, EMSC, detrend, SavGol variants, Norris-Williams, derivatives, Gaussian, robust/area normalization, and selected short compositions.

  • AOMControlSelector now supports:

    • Ridge heads;

    • PLS1 heads;

    • fold-local chain fitting;

    • mean/median/quantile/max criteria;

    • rank-mean or simple ensembles over top candidates.

  • AOMRobustHPORegressor:

    • configurable end-user estimator;

    • builds or accepts a chain bank;

    • screens Ridge and/or PLS heads;

    • exposes selection_report_;

    • accepts metadata for audit only.

  • AOMRobustHPOCompact:

    • fast compact preset for users.

  • AOMRobustHPOWide:

    • larger lab-style preset for reproducing broad preprocessing diversity;

    • not recommended as the default until benchmarked from the integrated package.

  • NativeAOMRobustHPORegressor:

    • sklearn-style wrapper over the native strict-linear robust-HPO ABI;

    • uses input_coefficients folded into the original feature space;

    • predicts on new spectra without replaying the selected preprocessing chain in Python.

  • AOMRidgeBlender:

    • fold-safe OOF simplex blend ported from the AOM-Ridge headline family;

    • supports explicit estimator/factory candidates or a default chain+Ridge pool;

    • Python reference layer for explicit custom candidates; the strict-linear compact/wide Ridge pool is also available natively as n4m.aom_ridge_blender / n4m_aom_ridge_blender_fit.

  • AOMOperatorPLSStack:

    • guarded fixed-operator PLS score stack with Ridge head;

    • optional OOF baseline gate for false-positive control;

    • default operator bank is restricted to strict-linear fixed matrices;

    • Python reference layer for custom operators and baseline gates; the compact/wide strict-linear PLS1 score stack is also available natively as n4m.aom_operator_pls_stack / n4m_aom_operator_pls_stack_fit.

  • Native n4m.aom_sweep_run / n4m_aom_sweep_run:

    • configurable compact/wide strict-linear AOM chain sweep;

    • screens custom Ridge lambda grids and PLS component grids;

    • accepts explicit fold ids;

    • returns a candidate table with candidate_id, chain_id, head_id, param, cv_rmse, plus selected OOF/final predictions.

  • Native n4m.aom_chain_sweep_run / n4m_aom_chain_sweep_run:

    • accepts caller-provided strict-linear preprocessing chains through flat chain/operator/parameter offsets;

    • supports identity, detrend, Savitzky-Golay, Norris-Williams, finite difference, Whittaker and FCK in this fold-safe path;

    • rejects stateful or non-strict operators such as SNV/MSC/EMSC/OSC/EPO.

  • AOM route policy switch:

    • moment_policy="auto" uses guarded exact operator-moment routes;

    • moment_policy="materialized" or "legacy" forces the old materialized-chain screen for route timing comparisons and small-cell production guards;

    • moment_policy="force_moments" / "moments_only" rejects any candidate-screen route that would leave operator moments.

  • AOM score-only output mode:

    • score_only=True keeps candidate scores, selected ids, route counters and fold ids while skipping selected-model outputs for broad ranking passes;

    • it avoids selected-model output refits and OOF/model buffers in operator-moment and materialized candidate-screen routes, but does not yet fuse the fold-local materialized scoring fits.

  • ABI-close Python wrappers for the historical native AOM selectors:

    • n4m.aom_pls / n4m.aom_global_select call n4m_aom_global_select;

    • n4m.pop_pls / n4m.aom_per_component_select call n4m_aom_per_component_select;

    • both build the compact strict-linear operator bank by default, accept caller-provided strict operators, and build fold-safe validation plans from explicit fold_ids or contiguous CV folds.

  • Reusable native AOM/POP selected models:

    • both historical selectors now export input_coefficients and intercept;

    • n4m.sklearn.NativeAOMPLSRegressor and n4m.sklearn.NativePOPPLSRegressor predict on new X from those input-space linear states.

  • Native n4m.aom_ridge_blender / n4m_aom_ridge_blender_fit:

    • blends the native compact/wide strict-linear AOM Ridge candidate pool from fold-local OOF predictions;

    • returns candidate predictions and simplex weights for audit;

    • returns final input_coefficients and intercept for replay in original feature space;

    • is wrapped by NativeAOMRidgeBlenderRegressor for sklearn-style reuse;

    • requires strictly positive Ridge lambdas and does not cover custom Python estimator candidates.

  • Native n4m.aom_operator_pls_stack / n4m_aom_operator_pls_stack_fit:

    • fits fold-local PLS1 score projectors over compact/wide strict-linear AOM operator views;

    • selects (n_components, alpha) by train-only CV criterion;

    • returns final stack features and Ridge head for audit;

    • returns input_coefficients and input_intercept for direct replay in original feature space;

    • is wrapped by NativeAOMOperatorPLSStackRegressor for sklearn-style reuse.

Still Not In nirs4all-methods

Still intentionally absent or deferred:

  • broad GPU/moment grinder:

    • remains a lab capacity-audit tool, not an end-user product method;

  • source-route or dataset-name lookup:

    • explicitly forbidden;

  • test-tuned property routes:

    • require held-out validation before becoming a deployable selector;

  • native ABI endpoints for every historical AOM reference object:

    • the Python portfolio objects are now available for the main source-free route/policy/gate/blend/operator-stack patterns, but most are still pre-ABI and outside the strict native catalog; n4m.aom_ridge_blender is the native exception for the strict-linear AOM Ridge blend, and n4m.aom_operator_pls_stack is the native exception for the strict-linear PLS1 score stack.

  • custom batched GPU screen for hundreds of thousands of preprocessing chains:

    • not shipped; the current product method builds in CUDA-enabled libn4m and uses the existing native model path, but it is not a fused GPU grinder.

  • batched sweep engine ABI:

    • n4m_moments_* is now shipped as a raw/centered sufficient-statistics layer with exact row-subset subtraction and train-only recentering;

    • n4m_sweep_run now ships Ridge CV plus compatible single-target NIPALS/regression PLS1 component screening from train/held-out moments, with materialized prefix fallback for other PLS regimes;

    • n4m_aom_sweep_run now ships a configurable AOM strict-linear compact/wide sweep over those Ridge/PLS grids; Ridge candidate rows use exact operator-moment scoring when p <= n_train, including in mixed Ridge+PLS sweeps, compatible single-target NIPALS PLS1 rows score from moments, and identity/SavGol/Norris/finite/Gaussian/FCK chains now have a banded moment route outside the old dense p <= 48 guard; detrend_poly chains use an exact structured low-rank projection moment route and Whittaker chains use an exact structured pentadiagonal solve route; both can compose with those banded local operators; CPU auto routes Ridge p > n_train rows through the exact materialized dual-Ridge scorer and PLS min_train < 4p rows through the exact materialized prefix scorer while CUDA auto keeps the moment route;

    • n4m_aom_chain_sweep_run now ships strict-linear user-defined chain descriptors with the same hybrid Ridge/PLS1-moment behavior and materialized fallbacks, or fail-fast strict behavior with moment_policy="force_moments";

    • batched IKPLS and fused operator-moment updates are still design/backlog items, so the full 200k-chain AOM moment sweep remains outside the product ABI.

Current Product Recommendation

Expose three levels to users:

  • n4m.aom_robust_hpo(..., profile="compact") for the ABI-stable fast product screen; use NativeAOMRobustHPORegressor when a fitted sklearn-style predictor is needed from the same native result;

  • n4m.aom_sweep_run(...) when the user wants to control Ridge lambdas, PLS component grids or explicit CV folds over the same native strict-linear bank;

  • n4m.aom_chain_sweep_run(...) when the user wants to define the strict-linear preprocessing chains directly; use moment_policy to compare auto moment routes against the legacy materialized route, or force_moments to assert that the candidate screen did not leave moments; use score_only=True for first-pass chain ranking;

  • n4m.aom_pls(...) and n4m.pop_pls(...) when the user wants the older global/per-component AOM-PLS selectors over a compact strict operator bank; use NativeAOMPLSRegressor or NativePOPPLSRegressor for sklearn-style reuse on new spectra;

  • n4m.aom_ridge_blender(...) when the user wants a native Ridge-only OOF simplex blend over the compact/wide strict-linear AOM bank; use NativeAOMRidgeBlenderRegressor for fitted reuse;

  • n4m.aom_operator_pls_stack(...) when the user wants a native PLS1 operator-score stack with a Ridge head over the compact/wide strict-linear AOM bank; use NativeAOMOperatorPLSStackRegressor for fitted reuse;

  • n4m.aom_robust_hpo(..., profile="wide") for a broader native strict-linear screen;

  • AOMRobustHPORegressor(profile="wide") or AOMRobustHPOWide when fold-local stateful chains are required in Python/reference experiments.

The canonical catalog now contains aom_pop.robust_hpo, aom_pop.ridge_blender, and aom_pop.operator_pls_stack through public native ABI symbols and timing rows. The broader Python portfolio/gating objects remain reference-layer APIs until each gets a native ABI contract and timing row. aom_pop.robust_hpo also exposes input_coefficients, intercept, dimension diagnostics, and the native sklearn replay wrapper. aom_pop.ridge_blender now does the same for the weighted Ridge blend. aom_pop.operator_pls_stack exposes input_coefficients and input_intercept for the folded single-target stack.