%\VignetteEngine{knitr}
%\VignetteIndexEntry{prospectr: a R package for processing and calibration sampling of vis-NIR spectroscopic data}
%\VignettePackage{prospectr}
\documentclass[12pt]{article}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{lmodern}
\usepackage{amssymb,amsmath}
\usepackage{epstopdf} % include pdf graphics
\usepackage{graphicx} % include external graphics
\usepackage{rotating} % landscape fig and tables
\usepackage{hyperref} % for url's
\usepackage{marvosym} % for symbols
\usepackage{authblk} % manage authors and affiliations
\usepackage[cm, headings]{fullpage} % for larger margins

\newcommand{\R}{\texttt{R} }
\newcommand{\Rfunction}[1]{{\texttt{#1}}}
\newcommand{\Robject}[1]{{\texttt{#1}}}
\newcommand{\Rargument}[1]{{\texttt{#1}}}
\newcommand{\Rpackage}[1]{{\mbox{\normalfont\textsf{#1}}}}

\hypersetup{  
  pdftitle = {An Introduction to the \Rpackage{prospectr} package},
  pdfsubject = {Manuscript},
  pdfauthor = {Antoine Stevens},
  colorlinks = {true},
  linkcolor = {blue},
  citecolor = {blue},
  urlcolor = {red},
  linktocpage = {true}
}

\title{An introduction to the \Rpackage{prospectr} package}
\author[1]{Antoine Stevens}
\author[2]{Leonardo Ramirez--Lopez}

\affil[1]{\footnotesize Georges Lema\^{i}tre Centre for Earth and Climate Research, Earth and Life Institute, UCLouvain, Place Pasteur 3, 1348 Louvain--La--Neuve, Belgium. \Letter~\href{mailto:antoine.stevens@uclouvain.be}{antoine.stevens@uclouvain.be}}
\affil[2]{\footnotesize Swiss Federal Institute for Forest, Snow and Landscape Research WSL, Zürcherstrasse 111, 8903 Birmensdorf, Switzerland / Institute of Terrestrial Ecosystems, ETH Zurich, Universitätstrasse 16, 8092 Zurich, Switzerland. \Letter~\href{mailto:leonardo.ramirez@wsl.ch}{leonardo.ramirez@wsl.ch}}

\date{\today}

\begin{document}

\maketitle

\tableofcontents

\newpage

\section{Introduction}

Visible and Near Infrared diffuse reflectance (vis--NIR) spectroscopy is a high--troughput, non--destructive and cheap sensing method that has a range of applications in agricultural, medical, food and environmental science. A number of \R packages of interest for the spectroscopist is already available for processing and analysis of spectroscopic data (Table ~\ref{tab:pck}). The CRAN task views \href{http://cran.r-project.org/web/views/Multivariate.html}{Multivariate Statistics}, \href{http://cran.r-project.org/web/views/MachineLearning.html}{Machine Learning}, \href{http://cran.r-project.org/web/views/ChemPhys.html}{Chemometrics and Computational Physics}. The interested reader can also have a look at the special issue \href{http://ww.colin-baxter.com/academic/bib/downloads/mullen07.pdf}{"Spectroscopy and Chemometrics in R"} of the Journal of Statistical Software \cite{mullen2007}.

\begin{table}[h]
\caption{Non--exhaustive list of R package useful for vis--NIR spectroscopic analysis}
\centering
\begin{tabular}{l|l}
\hline
Package Name & Description  \\
\hline
\href{http://cran.r-project.org/web/packages/chemometrics/index.html}{\Rpackage{chemometrics}}  &  functions and scripts for chemometrics  \\
\href{http://cran.r-project.org/web/packages/ChemometricsWithR/index.html}{\Rpackage{ChemometricsWithR}} &  functions and scripts for chemometrics       \\
\href{http://cran.r-project.org/web/packages/ChemoSpec/index.html}{\Rpackage{ChemoSpec}}  &  misc functions for exploratory analysis in Spectroscopy \\
\href{http://cran.r-project.org/web/packages/hyperSpec/index.html}{\Rpackage{hyperSpec}} &  processing and visualisation of spectra   \\
\href{http://cran.r-project.org/web/packages/cluster/index.html}{\Rpackage{cluster}} & cluster analysis and visualisation    \\   
\href{http://cran.r-project.org/web/packages/mvoutlier/index.html}{\Rpackage{mvoutlier}} & outlier detection in the multivariate space \\ 
\href{http://cran.r-project.org/web/packages/pls/index.html}{\Rpackage{pls}} & partial least square regression \\         
\href{http://cran.r-project.org/web/packages/signal/index.html}{\Rpackage{signal}} & signal filtering \\
\href{http://cran.r-project.org/web/packages/soil.spec/index.html}{\Rpackage{soil.spec}} & some functions related to soil spectroscopy \\
\href{http://cran.r-project.org/web/packages/caret/index.html}{\Rpackage{caret}}  & training classification and regression models \\
\hline
\end{tabular}
\label{tab:pck}
\end{table}

The prospectr package gathers algorithms commonly--used in spectroscopy for pre--treating spectra and select calibration samples. Some of the algorithms are already available in other package, like the Savitzky--Golay algorithm \cite{savitzky1964} but our functions works indifferently on \Robject{vector}, \Robject{data.frame} or \Robject{matrix} input. 

\section{Signal Processing}

The aim of signal pre--treatment is to improve data quality before modeling and remove physical information from the spectra. Applying a pre--treatment can increase the repeatability/reproducibility of the method, model robustness and accuracy, although there are no guarantees this will actually work \dots. The pre--processing functions that are currently available in the package are listed in Table ~\ref{tab:fun}.

\begin{table}[h]
\caption{List of pre--processing functions}
\centering
\begin{tabular}{l|l}
\hline
Function Name & Description  \\
\hline  \Rfunction{movav} & simple moving (or running) average filter   \\  
\Rfunction{savitzkyGolay} & Savitzky--Golay smoothing and derivative  \\      
\Rfunction{gapDer} & gap--segment derivative  \\                       
\Rfunction{continuumRemoval} & compute continuum--removed values \\                               
\Rfunction{detrend} & detrend normalization \\
\Rfunction{standardNormalVariate} & Standard Normal Variate (SNV) transformation \\
\Rfunction{binning} & average a signal in column bins \\
\Rfunction{resample} & resample a signal to new band positions \\
\Rfunction{resample2} & resample a signal using FWHM values \\
\Rfunction{blockScale} & block scaling \\
\Rfunction{blockNorm}& sum of squares block weighting \\
\hline
\end{tabular}
\label{tab:fun}
\end{table}

We show below how they can be used, using the NIRsoil dataset included in the package \cite{fernandez2008}. Observations should be arranged row--wise.

<<NIRsoil, tidy=TRUE, message=FALSE>>=
library(prospectr)
data(NIRsoil)
# NIRsoil is a data.frame with 825 obs and 5 variables: 
# Nt (Total Nitrogen), Ciso (Carbon), CEC (Cation Exchange Capacity), 
# train (vector of 0,1 indicating training (1) and validation (0) samples),
# spc (spectral matrix)
str(NIRsoil)
@

\subsection{Noise removal}

Noise represents random fluctuations around the signal that can originate from the instrument or environmental laboratory conditions. The simplest solution to remove noise is to perform $n$ repetition of the measurements, and the average individual spectra. The noise will decrease with a factor $\sqrt{n}$. When this is not possible, or if residual noise is still present in the data, the noise can be removed mathematically. 
  
\subsubsection{Moving average or runnnig mean}

A moving average filter is a column--wise operation which average contiguous wavelengths within a given window size. 

<<movin, fig.cap="Effect of a moving average with window size of 10 bands on a raw spectrum",fig.height=6,fig.width=10, tidy=TRUE,dpi=300>>=
noisy <- NIRsoil$spc + rnorm(length(NIRsoil$spc),0,0.001) # adding some noise
# Plot the first spectrum
plot(as.numeric(colnames(NIRsoil$spc)),noisy[1, ],type="l",xlab="Wavelength",ylab="Absorbance") 
X <- movav(noisy,w=11) # window size of 11 bands
# Note that the 5 first and last bands are lost in the process
lines(as.numeric(colnames(X)),X[1,],col="red") 
legend("topleft",legend=c("raw","moving average"),lty=c(1,1),col=1:2)
@

\subsubsection{Binning}

<<binning,fig.cap="Average in bins",fig.height=6,fig.width=10, tidy=FALSE, dpi=300, fig.pos='t'>>=
# After averaging, the spectrum can be further resampled (binning)
# We keep here one 1 out every 10 data points
X.bin <- binning(X,bin.size=10) 
# We reduce the spectral matrix to 50 (equally-spaced) data points
X.bin2 <- binning(X,bins=50) 
# Plot the first spectrum
plot(as.numeric(colnames(X)),X[1,],type="l",
     xlab="Wavelength",ylab="Absorbance")
#  new data points
points(as.numeric(colnames(X.bin)),X.bin[1,],pch=2)
points(as.numeric(colnames(X.bin2)),X.bin2[1,],pch=1,col=2)
legend("topleft",legend=c("bin.size = 10","bins = 50"),pch = 2:1, col = 2:1)
@

\subsubsection{Savitzky-Golay filtering}

Savitzky-Golay filtering \cite{savitzky1964} is a very common preprocessing technique. It fits a local polynomial regression on the signal and requires \emph{equidistant} bandwidth. Mathematically, it operates simply as a weighted sum of neighbouring values:

$$ x_j\ast = \frac{1}{N}\sum_{h=-k}^{k}{c_hx_{j+h}}$$

where $x_j\ast$ is the new value, $N$ is a normalizing coefficient, $k$ is the number of neighbour values at each side of $j$ and $c_h$ are pre--computed coefficients, that depends on the chosen polynomial order and degree (smoothing, first and second derivative).

<<savits, tidy=TRUE>>=
# p = polynomial order
# w = window size (must be odd)
# m = m-th derivative (0 = smoothing)
# The function accepts vectors, data.frames or matrices.
# For a matrix input, observations should be arranged row-wise
sg.vec <- savitzkyGolay(NIRsoil$spc[1,],p=3,w=11,m=0) 
sg <- savitzkyGolay(NIRsoil$spc,p=3,w=11,m=0) 
# note that bands at the edges of the spectral matrix are lost !
dim(NIRsoil$spc);dim(sg)
@

\subsection{Derivatives}

Taking (numerical) derivatives of the spectra can remove both additive and multiplicative effects in the spectra and have other consequences as well (Table ~\ref{tab:der}).

\begin{table}[h]
\caption{Pro's and con's of using derivative spectra}
\centering
\begin{tabular}{l|l}
\hline
Advantage & Drawback  \\
\hline 
  Reduce of baseline offset & Risk of overfitting the calibration model \\
  Can resolve absorption overlapping & Increase noise, smoothing required \\
  Compensates for instrumental drift & Increase uncertainty in model coefficients  \\                                     
  Enhances small spectral absorptions & Complicate spectral interpretation \\
  Often increase predictive accuracy for complex datasets & Remove the baseline ! \\ 
\hline
\end{tabular}
\label{tab:der}
\end{table}

First and second derivatives of a spectrum can be computed with the finite difference method (difference between to subsequent data points), provided that the band width is constant: 

$$ x_i' = x_i - x_{i-1}$$

$$ x_i'' = x_{i-1} - 2 \cdot x_i + x_{i+1}$$

In \R, this can be simply achieved with the \Rfunction{diff} function in \Rpackage{base}: 

<<d1,fig.cap="Effect of first derivative and second derivative", fig.height=6,fig.width=10, tidy=TRUE, dpi=300, fig.pos='t'>>=
# X = wavelength
# Y = spectral matrix
# n = order
d1 <- t(diff(t(NIRsoil$spc), differences = 1)) # first derivative
d2 <- t(diff(t(NIRsoil$spc), differences = 2)) # second derivative
plot(as.numeric(colnames(d1)),d1[1,],type="l",xlab="Wavelength",ylab="")
lines(as.numeric(colnames(d2)),d2[1,],col="red")
legend("topleft",legend=c("1st der","2nd der"),lty=c(1,1),col=1:2)
@

One can see that derivatives tend to increase noise. One can use gap derivatives or the Savitzky-Golay algorithm to solve this. The gap derivative is computed simply as:

$$ x_i' = x_{i+k} - x_{i-k}$$

$$ x_i'' = x_{i-k} - 2 \cdot x_i + x_{i+k}$$

where $k$ is the gap size. Again, this can be easily achieved in R using the \Rargument{lag} argument of the \Rfunction{diff} function

<<gapder,fig.cap="Effect of 1st-order gap derivative ", fig.height=6,fig.width=10, tidy=TRUE, dpi=300, fig.pos='b'>>=
# first derivative with a gap of 10 bands
gd1 <- t(diff(t(NIRsoil$spc), differences = 1, lag = 10)) 
@

For more flexibility and control over the degree of smoothing, one could however use the Savitzky-Golay (\Rfunction{savitzkyGolay}) and Gap--segment derivative (\Rfunction{gapDer}) algorithms. The Gap-segment algorithms performs first a smoothing under a given segment size, followed by gap derivative. Here is an exemple of the use of the \Rfunction{gapDer} function.


<<gapseg,fig.cap="Effect of 1st-order gap-segment derivative ", fig.height=6,fig.width=10, tidy=TRUE, dpi=300>>=
# m = order of the derivative
# w = window size ( = {2 * gap size} + 1)
# s = segment size
# first derivative with a gap of 10 bands
gsd1 <- gapDer(X = NIRsoil$spc, m = 1, w = 11, s = 10) 
plot(as.numeric(colnames(d1)),d1[1,],type="l",xlab="Wavelength",ylab="")
lines(as.numeric(colnames(gsd1)),gsd1[1,],col="red")
legend("topleft",legend=c("1st der","gap-segment 1st der"),lty=c(1,1),col=1:2)
@

\subsection{Scatter corrections}

Undesired spectral variations due to light \emph{scatter} effects and variations in effective \emph{path length} can be removed using scatter corrections.

\subsubsection{Standard Normal Variate (SNV)}

Standard Normal Variate (SNV) is another simple way for normalizing spectra that intends to correct for light scatter. It operates row--wise:

$$ SNV_i = \frac{x_i - \bar{x_i}}{s_i}$$

<<snv, eval=TRUE, fig.cap="Effect of SNV on raw spectra", fig.height=6,fig.width=10, tidy=TRUE, dpi=300>>=
snv <- standardNormalVariate(X=NIRsoil$spc)
@

According to Fearn \cite{fearn2008}, it is better to perform SNV transformation after filtering (by e.g. Savitzky--Golay) than the reverse.

\subsubsection{SNV--Detrend}

The SNV--Detrend \cite{barnes1989} further accounts for wavelength-dependent scattering effects (variation in curvilinearity between the spectra). After a SNV transformation, a 2$^{nd}$--order polynomial is fit to the spectrum and subtracted from it.

<<detrend, fig.cap="Effect of SNV-Detrend on raw spectra",fig.height=6,fig.width=10, tidy=TRUE, dpi=300, fig.pos='t'>>=
# X = input spectral matrix
# wav = band centers
dt <- detrend(X=NIRsoil$spc,wav=as.numeric(colnames(NIRsoil$spc)))
plot(NIRsoil$spc[1,],type="l",xlab="Band number",ylab="")
par(new=T)
plot(dt[1,],xaxt = "n", yaxt = "n", xlab="", ylab="",col="red",type="l")
axis(4,col="red")
legend("topleft",legend=c("raw","detrend signal"),lty=c(1,1),col=1:2)
par(new=F)
@

\subsection{Centering and scaling}

Centering and scaling tranforms a given matrix to a matrix with columns with zero mean (centering), unit variance (scaling) or both (auto--scaling):

$$ Xc_{ij} = X_{ij}  - \bar{X}_{j} $$

$$ Xs_{ij} = \frac{X_{ij}  - \bar{X}_{j}}{s_{j}} $$

where $Xc$ and $Xs$ are the mean centered and auto-scaled matrices, $X$ is the input matrix, $\bar{X}_{j}$ and $s_{j}$ are the mean and standard deviation of variable $j$.

In \R, these operations are simply obtained with the \Rfunction{scale} function. Other types of scaling can be considered.  Spectroscopic models can often be improved by using ancillary data (e.g. temperature, \dots) \cite{fearn2010}. Due to the nature of spectral data (multivariate), other data would have great chance to be dominated by the spectral matrix and have no chance to contribute significantly to the model due to purely numerical reasons \cite{eriksson2006}. One can use \emph{block scaling} to overcome this limitation. It basically uses different weights for different block of variables. With \emph{soft block scaling}, each block is scaled (i.e. each column divided by a factor) such that the sum of their variance is equal to the square root of the number of variables in the block. With \emph{hard block scaling}, each block is scaled such that the sum of their variance is equal to 1.

<<bscale, tidy=FALSE>>=
# X = spectral matrix
# type = "soft" or "hard"
# The ouptut is a list with the scaled matrix (Xscaled) and the divisor (f)
bs <- blockScale(X=NIRsoil$spc,type="hard")$Xscaled
sum(apply(bs,2,var)) # this works!
@

The problem with \emph{block scaling} is that it down--scale all the block variables to the same variance. Since sometimes this is not advised, one can alternatively use \emph{sum of squares block weighting} . The spectral matrix is multiplied by a factor to achieve a pre--determined sum of square: 

<<bnorm, tidy=TRUE>>=
# X = spectral matrix
# targetnorm = desired norm for X
bn <- blockNorm(X=NIRsoil$spc,targetnorm=1)$Xscaled
sum(bn^2) # this works!
@

\subsection{Other transformations}

\subsubsection{Continuum removal}    

The continuum removal technique was introduced by \cite{clark1984} as an effective method to highlight absorption features of minerals. It can be viewed as an albedo normalization technique. This technique is based on the computation of the continuum (or envelope) of a given spectrum. The continuum-removed spectrum of a given spectrum is computed as follows:
\begin{enumerate}
  \item The local reflectance spectrum maxima points (in the case of absorbance, local minima points) are identified.  
  \item Then, these points are connected by linear interpolation to form the continuum $c$. 
  \item The continuum-removed spectrum is given by $\phi_{i} = \frac{x_{i}}{c_{i}};  i=\left \{ 1,..., p\right\}$, where $x_{i}$ and $c_{i}$ are the original and the continuum reflectance (or absorbance) values respectively at the $i^th$ wavelength of a set of $p$ wavelengths, and $\phi_{i}$ is the final reflectance (or absorbance) value after continuum removal.
\end{enumerate}

The \Rfunction{continuumRemoval} function allows to compute the continuum-removed values of either reflectance or absorbance spectra. 

<<cr, fig.cap="Absorbance and continuum-removed absorbance spectra",fig.height=6,fig.width=10, tidy=TRUE, dpi=300, fig.pos='t'>>=
# type of data: 'R' for reflectance (default), 'A' for absorbance
cr <- continuumRemoval(X= NIRsoil$spc,type="A")
# plot of the 10 first abs spectra
matplot(as.numeric(colnames(NIRsoil$spc)),t(NIRsoil$spc[1:10,]),type="l",
        ylim=c(0,.6),xlab="Wavelength /nm",ylab="Absorbance")
matlines(as.numeric(colnames(NIRsoil$spc)),t(cr[1:10,]))
@

\subsubsection{Resampling}

To match the response of one instrument with another, a signal can be resampled to new band positions by simple interpolation (\Rfunction{resample}) or using full width half maximum (FWHM) values (\Rfunction{resample2}). 

\section{Calibration sampling algorithms }

Calibration models are usually developed on a \emph{representative} portion of the data (training set) and validated on the remaining set of samples (test/validation set). There are several solutions for selecting samples, e.g.:   
\begin{itemize}
  \item random selection (see e.g. \Rfunction{sample} function in \Rpackage{base})
  \item stratified random sampling on percentiles of the response $y$ (see e.g. \Rfunction{createDataPartion} in the \Rpackage{caret} package)
  \item  use the spectral data. 
\end{itemize}

For selecting representative samples, the \Rpackage{prospectr} package provides functions that use the third solution. The following functions are available: \Rfunction{kenStone} \cite{kennard1969}, \Rfunction{duplex} \cite{snee1977}, \Rfunction{puchwein} \cite{puchwein1988}, \Rfunction{shenkWest} \cite{shenk1991}, \Rfunction{naes} \cite{naes2002}, \Rfunction{honigs} \cite{honigs1985}.

\subsection{Kennard-Stone sampling (\Rfunction{kenStone})}

To sample a subset of $n$  samples $X_{tr} = \left \{ {x_{tr}}_{j} \right \}_{j=1}^{n}$, from a given set of $N$ samples $X = \left \{ x_i \right \}_{i=1}^{N}$ (note that $N>n$) the Kennard-Stone (CADEX) sampling  algorithm consists in \cite{kennard1969}: 

\begin{enumerate}
  \item Find in $X$ the samples ${x_{tr}}_1$ and  ${x_{tr}}_2$ that are the farthest apart from each other, allocate them in $X_{tr}$  and remove them from $X$.   
  \item Find in $X$ the sample ${x_{tr}}_3$ with the maximum dissimilarity to $X_{tr}$. Allocate ${x_{tr}}_3$ in $X_{tr}$  and then remove it from $X$. The dissimilarity between $X_{tr}$  and each $x_i$  is given by the minimum distance of any sample allocated in $X_{tr}$  to each $x_i$. In other words, the selected sample is one of the nearest neighbours of the points already selected which is characterized by the maximum distance to the other points already selected.   
  \item Repeat the step 2 n-3 times in order to select the remaining samples (${x_{tr}}_4,..., {x_{tr}}_n$).   

\end{enumerate}

The Kennard--Stone algorithm allows to create a calibration set that has a flat distribution over the spectral space. The metric used to compute the distance between points can be either the Euclidean distance or the Mahalanobis distance. 
Let's see some examples \dots

<<ken, fig.cap="Selection of 40 calibration samples with the Kennard-Stone algorithm", tidy=FALSE, dpi=300, out.height='10cm', out.width='10cm',fig.align='center'>>=                          
# Create a dataset for illustrating how the calibration sampling 
# algorithms work
X <- data.frame(x1 = rnorm(1000), x2 = rnorm(1000))
plot(X) 
# kenStone produces a list with row index of the points selected for calibration
ken <- kenStone(X,k=40) 
points(X[ken$model,],col=2,pch=19,cex=1.4) # plot selected points
@

<<ken2, fig.cap="Kennard-Stone sampling on the NIRsoil dataset", tidy=FALSE, dpi=300, out.height='10cm', out.width='10cm',fig.align='center'>>=                          

# Test with the NIRsoil dataset
# one can use the mahalanobis distance (metric argument)
# computed in the pc space (pc argument)
ken_mahal <- kenStone(X = NIRsoil$spc, k = 20, metric = "mahal", pc = 2)
# The pc components in the output list stores the pc scores
plot(ken_mahal$pc[,1],ken_mahal$pc[,2],xlab="PC1",ylab="PC2") 
# This is the selected points in the pc space
points(ken_mahal$pc[ken_mahal$model,1],ken_mahal$pc[ken_mahal$model,2],pch=19,col=2) 
@

\subsection{DUPLEX (\Rfunction{duplex})}

The Kennard--Stone algorithm selects calibration samples. Often, we need also to select a validation subset. The DUPLEX algorithm \cite{snee1977} is a modification of the Kennard-Stone which allows to select a validation set that have similar properties to the calibration set. DUPLEX, similarly to Kennard--Stone, begins by selecting pairs of points that are the farthest apart from each other, and then assigns points alternatively to the calibration and validation sets.

<<duplex, fig.cap="Selection of 15 calibration and validation samples with the DUPLEX algorithm", tidy=TRUE, dpi=300, out.height='10cm', out.width='10cm', fig.align = 'center'>>=
dup <- duplex(X=X,k=15) # k is the number of selected samples
plot(X)
points(X[dup$model,1],X[dup$model,2],col="red",pch=19) # calibration samples
points(X[dup$test,1],X[dup$test,2],col="blue",pch=17) # validation samples
legend("topright",legend=c("calibration","validation"),pch=c(19,17),col=c("red","blue"))
@

\subsection{$k$-means sampling (\Rfunction{naes})}

The $k$-means sampling simply uses $k$-means clustering algorithm. To sample a subset of $n$  samples $X_{tr} = \left \{ {x_{tr}}_{j} \right \}_{j=1}^{n}$, from a given set of $N$ samples $X = \left \{ x_i \right \}_{i=1}^{N}$ (note that $N>n$) the algorithm works as follows:  

\begin{enumerate}
  \item Perform a $k$-means clustering of $X$ using $n$ clusters.   
  \item Extract the $n$ centroids ($c$, or prototypes). This can be also the sample that is the farthest away from the centre of the data, or a random selection. See the \Rargument{method} argument in \Rfunction{naes}.
  \item Calculate the distance of each sample to each $c$.  
  \item For each $c$ allocate in $X_{tr}$ its closest sample found in $X$.  
\end{enumerate}

<<naes, fig.cap="Selection of 5 samples by k-means sampling", tidy=FALSE, dpi=300, out.height='10cm', out.width='10cm', fig.align = 'center'>>=
# X = the input matrix
# k = number of calibration samples to be selected
# pc = if pc is specified, k-mean is performed in the pc space 
# (here we will use only the two 1st pcs)
# iter.max =  maximum number of iterations allowed for the k-means clustering.
kms <- naes(X = NIRsoil$spc, k = 5, pc = 2, iter.max = 100)
# Plot the pcs scores and clusters
plot(kms$pc,col=kms$cluster) 
# Add the selected points
points(kms$pc[kms$model,],col=6,pch=19)
@

\subsection{SELECT algorithm (\Rfunction{shenkWest})}

The SELECT algorithm \cite{shenk1991} is an iterative procedure which selects the sample having the maximum number of neighbour samples within a given distance (\Rargument{d.min} argument) and remove the neighbour samples of the selected sample from the list of points. The number of selected samples depends on the chosen treshold (default = 0.6). The distance metric is the Mahalanobis distance divided by the number of dimensions (number of pc components) used to compute the distance. Here is an example of how the \Rfunction{shenkWest} function might work:

<<shenk, fig.cap="Selection of samples with the SELECT algorithm", tidy=TRUE, dpi=300, out.height='10cm', out.width='10cm', fig.align = 'center', fig.align = 'center'>>=
shenk <- shenkWest(X = NIRsoil$spc,d.min = 0.6,pc=2)
plot(shenk$pc) 
points(shenk$pc[shenk$model,],col=2,pch=19)
@

\subsection{Puchwein algorithm (\Rfunction{puchwein})}

The Puchwein algorithm is yet another algorithm for calibration sampling \cite{puchwein1988} that creates a calibration set with a flat distribution. A nice feature of the algorithm is that it allows an objective selection of the number of required calibration samples with the help of plots. First the data is usually reduced through PCA and the most significant PCs are retained. Then the mahalanobis distance ($H$) to the center of the matrix is computed and samples are sorted decreasingly. The distances betwwen samples in the PC space are then computed.

Here is a \emph{pseudo-code} of the algorithm:

\begin{quote}
\begin{enumerate}
  \item Definition of a limiting distance
  \item Find the sample with $\max(H)$
  \item Remove all the samples which are within the limiting distance away from the sample selected in step 2.
  \item Go back in step 2 and find the sample with $\max(H)$ within the remaining samples
  \item When there is no sample anymore, go back to step 1 and increase the limiting distance.
\end{enumerate}
\end{quote}

<<puchwein, fig.cap="Samples selected by the Puchwein algorithm", tidy=TRUE, dpi=300, eval=TRUE, out.height='10cm', out.width='10cm', fig.align = 'center'>>=
pu <- puchwein(X=NIRsoil$spc,k=0.2,pc=2)
plot(pu$pc)
points(pu$pc[pu$model,],col=2,pch=19) # selected samples
@

The number of sample selected depends on the limiting distance. To help choosing the appropriate number of samples, two plots are used \cite{shetty2012}:
\begin{itemize}
  \item a plot showing the number of samples that are removed in each loop and the total number of samples left
  \item a plot showing the theoretical sum of leverages (each sample has the same leverage) together with the true sum of leverages. The optimal loop is the one for which the difference between the two measures of leverage is maximum
\end{itemize}


<<puchwein2, fig.cap="How to find the optimal loop", tidy=TRUE, dpi=300, eval=TRUE>>=
# Optimal loop
par(mfrow=c(2,1))
plot(pu$leverage$removed,pu$leverage$diff,type="l",
     xlab="# samples removed",ylab="Difference between th. and obs sum of leverages")
# This basically shows that the first loop is optimal
plot(pu$leverage$loop,nrow(NIRsoil)-pu$leverage$removed,xlab="# loops",
     ylab="# samples kept",type="l")
par(mfrow=c(1,1))
@

\subsection{Honigs (\Rfunction{honigs})}

The Honigs algorithm selects samples based on the size of their absorption features \cite{honigs1985}. It can works both on absorbance and continuum-removed spectra. The sample having the highest absorption feature is selected first. Then this absorption is substracted from other spectra and the algorithm iteratively select samples with the highest absorption (in absolute value) until the desired number of samples is reached.


<<honigs, fig.cap="Spectra selected with the Honigs algorithm and bands used", tidy=TRUE, dpi=300, fig.height=6,fig.width=10, fig.pos='h'>>=
ho <- honigs(X = NIRsoil$spc,k=10, type = "A") # type = "A" is for absorbance data
# plot calibration spectra
matplot(as.numeric(colnames(NIRsoil$spc)),t(NIRsoil$spc[ho$model,]),
        type="l",xlab="Wavelength",ylab="Absorbance")
# add bands used during the selection process
abline(v=as.numeric(colnames(NIRsoil$spc))[ho$bands],lty=2)
@
  
\bibliographystyle{plain}
\begin{thebibliography}{10}

\bibitem{barnes1989}
R.J. Barnes, M.S. Dhanoa, and S.J. Lister.
\newblock Standard normal variate transformation and de-trending of
  near-infrared diffuse reflectance spectra.
\newblock {\em Applied spectroscopy}, 43(5):772--777, 1989.

\bibitem{clark1984}
Roger~N. Clark and Ted~L. Roush.
\newblock Reflectance spectroscopy: Quantitative analysis techniques for remote
  sensing applications.
\newblock {\em Journal of Geophysical Research}, 89(B7):PP. 6329--6340, 1984.

\bibitem{eriksson2006}
Lennart Eriksson, Erik Johansson, Nouna Kettaneh, Johan Trygg, C.~Wikstrom, and
  Svante Wold.
\newblock {\em Multi- and Megavariate Data Analysis}.
\newblock {MKS} Umetrics {AB}, 2006.

\bibitem{fearn2008}
Tom Fearn.
\newblock The interaction between standard normal variate and derivatives.
\newblock {\em {NIR} news}, 19(7):16, 2008.

\bibitem{fearn2010}
Tom Fearn.
\newblock Combining other predictors with {NIR} spectra.
\newblock {\em {NIR} news}, 21(2):13, 2010.

\bibitem{fernandez2008}
J.~A. Fernandez~Pierna and P.~Dardenne.
\newblock Soil parameter quantification by {NIRS} as a chemometric challenge at
  chimiometrie 2006.
\newblock {\em Chemometrics and Intelligent Laboratory Systems}, 91(1):94--98,
  2008.

\bibitem{honigs1985}
D.~E. Honigs, Gary~M. Hieftje, H.~L. Mark, and T.~B. Hirschfeld.
\newblock Unique-sample selection via near-infrared spectral subtraction.
\newblock {\em Analytical Chemistry}, 57(12):2299--2303, October 1985.

\bibitem{kennard1969}
R.~W. Kennard and L.~A. Stone.
\newblock Computer aided design of experiments.
\newblock {\em Technometrics}, 11(1):137--148, February 1969.

\bibitem{mullen2007}
Katharine~M. Mullen and Ivo~{HM} van Stokkum.
\newblock An introduction to the special volume spectroscopy and chemometrics
  in r.
\newblock {\em Journal of Statistical Software}, 18(1):1--5, 2007.

\bibitem{naes2002}
T.~Naes, T.~Isaksson, T.~Fearn, and T.~Davies.
\newblock {\em A user friendly guide to multivariate calibration and
  classification}.
\newblock {NIR} Publications, Chichester, United Kingdom, 2002.

\bibitem{puchwein1988}
Gerd Puchwein.
\newblock Selection of calibration samples for near-infrared spectrometry by
  factor analysis of spectra.
\newblock {\em Analytical Chemistry}, 60(6):569--573, 1988.

\bibitem{savitzky1964}
Abraham. Savitzky and M.~J.~E. Golay.
\newblock Smoothing and differentiation of data by simplified least squares
  procedures.
\newblock {\em Anal. Chem.}, 36(8):1627--1639, 1964.

\bibitem{shenk1991}
J.~S. Shenk and M.~O. Westerhaus.
\newblock Population definition, sample selection, and calibration procedures
  for near infrared reflectance spectroscopy.
\newblock {\em Crop Science}, 31(2):469--474, 1991.

\bibitem{shetty2012}
Nisha Shetty, Asmund Rinnan, and Rene Gislum.
\newblock Selection of representative calibration sample sets for near-infrared
  reflectance spectroscopy to predict nitrogen concentration in grasses.
\newblock {\em Chemometrics and Intelligent Laboratory Systems}, 111(1):59--65,
  February 2012.

\bibitem{snee1977}
R.~D. Snee.
\newblock Validation of regression models: methods and examples.
\newblock {\em Technometrics}, 19(4):415--428, 1977.

\end{thebibliography}

\end{document}
