% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/spectra-neighbours.R
\name{classify_by_spectral_neighbours}
\alias{classify_by_spectral_neighbours}
\title{Classify a soil by spectral similarity to OSSL reference profiles}
\usage{
classify_by_spectral_neighbours(
  spectrum,
  ossl_library,
  system = c("wrb2022", "sibcs", "usda"),
  k = 25L,
  preprocess = "snv+sg1",
  region = NULL,
  verbose = TRUE
)
}
\arguments{
\item{spectrum}{Numeric vector or 1-row matrix (the query
spectrum). Must align (after preprocessing) with the
column space of \code{ossl_library$Xr}.}

\item{ossl_library}{A list with \code{Xr} (numeric matrix, rows
= OSSL training profiles, cols = wavelengths) and \code{Yr}
(data frame keyed by property; \emph{must include} a
column named \code{wrb_rsg} and / or \code{sibcs_ordem} /
\code{usda_order} for the labels to aggregate over).
\code{ossl_library} may also carry \code{lat} and
\code{lon} columns in \code{Yr} for the regional filter.}

\item{system}{One of \code{"wrb2022"} (default), \code{"sibcs"},
\code{"usda"}. Controls which label column of \code{Yr}
is aggregated.}

\item{k}{Number of nearest neighbours (default 25).}

\item{preprocess}{Pre-processing pipeline; passed to
\code{\link{preprocess_spectra}}. Default \code{"snv+sg1"}.}

\item{region}{Optional \code{list(lat, lon, radius_km)} for a
regional filter on \code{ossl_library$Yr$lat / lon}.}

\item{verbose}{Emit a \code{cli} summary.}
}
\value{
A list with three elements:
  \describe{
    \item{\code{distribution}}{A \code{data.table} with columns
          \code{class}, \code{n_neighbours}, \code{probability}
          (= \code{n_neighbours / k}), sorted by probability.}
    \item{\code{neighbours}}{A \code{data.table} with one row per
          neighbour (top K), columns \code{rank}, \code{distance},
          \code{class}, plus any other columns present in
          \code{ossl_library$Yr}.}
    \item{\code{query}}{The query metadata (system, k,
          region filter, n_library_rows, n_filtered).}
  }
}
\description{
Given a Vis-NIR (or MIR) spectrum and an OSSL reference library
enriched with WRB / SiBCS / USDA labels, returns the K most
spectrally similar profiles plus a probabilistic class prediction
aggregated from their labels.
}
\details{
This is the **spectral analogy** classifier. It does not replace
the deterministic key in
\code{\link{classify_wrb2022}} / \code{\link{classify_sibcs}} /
\code{\link{classify_usda}}; instead it provides a high-prior
"expected class" before the user has lab data, reducing the
search space when collecting confirming attributes.
}
\section{Distance metric}{

By default we compute distances on PLS scores (matching the
resemble / OSSL recipe), with PLS components fit on the OSSL
reference Yr matrix. When \code{resemble} is unavailable, we fall
back to PCA scores from \code{stats::prcomp} on the preprocessed
Xr -- a defensible-but-simpler heuristic.
}

\section{Region filter}{

Optional \code{lat / lon / radius_km} arguments filter the OSSL
library to profiles within \code{radius_km} (great-circle) of the
query location before computing distances. This implements the
"biome-aware" use case the architecture document calls for: a
Cerrado profile shouldn't have its class inferred from spectral
neighbours in the Boreal taiga.
}

\examples{
\donttest{
# Toy run against the bundled demo library (synthetic):
data(ossl_demo_sa)
# Inject a fake label column for the demo (real OSSL has it):
ossl_demo_sa$Yr$wrb_rsg <- sample(c("FR", "AC", "LX", "AL"),
                                    nrow(ossl_demo_sa$Yr),
                                    replace = TRUE)
query <- ossl_demo_sa$Xr[1, ]
res <- classify_by_spectral_neighbours(query, ossl_demo_sa,
                                        k = 10)
res$distribution    # ranked classes
res$neighbours      # the 10 most similar profiles
}
}
\seealso{
\code{\link{predict_ossl_mbl}} (predicts attributes),
         \code{\link{classify_wrb2022}} (the deterministic key).
}
