\HeaderA{smooth.construct}{Constructor functions for smooth terms in a GAM}{smooth.construct}
\aliasA{smooth.construct.tensor.smooth.spec}{smooth.construct}{smooth.construct.tensor.smooth.spec}
\aliasA{smooth.construct2}{smooth.construct}{smooth.construct2}
\aliasA{user.defined.smooth}{smooth.construct}{user.defined.smooth}
\keyword{models}{smooth.construct}
\keyword{smooth}{smooth.construct}
\keyword{regression}{smooth.construct}
\begin{Description}\relax
Smooth terms in a GAM formula are turned into smooth specification objects of 
class \code{xx.smooth.spec} during processing of the formula. Each of these objects is
converted to a smooth object using an appropriate \code{smooth.construct} function. New smooth classes 
can be added by writing a new \code{smooth.construct} method function and a corresponding 
\code{\LinkA{Predict.matrix}{Predict.matrix}} method function (see example code below).

In practice, \code{smooth.construct} is usually called via \code{smooth.construct2} and the wrapper
function \code{\LinkA{smoothCon}{smoothCon}}, in order to handle \code{by} variables and
centering constraints (see the \code{\LinkA{smoothCon}{smoothCon}} documentation if 
you need to handle these things directly, for a user defined smooth class).
\end{Description}
\begin{Usage}
\begin{verbatim}
smooth.construct(object,data,knots)
smooth.construct2(object,data,knots)
\end{verbatim}
\end{Usage}
\begin{Arguments}
\begin{ldescription}
\item[\code{object}] is a smooth specification object, generated by an \code{\LinkA{s}{s}} or \code{\LinkA{te}{te}} term in a GAM 
formula. Objects generated by \code{s} terms have class \code{xx.smooth.spec} where \code{xx} is given by the 
\code{bs} argument of \code{s} (this convention allows the user to add their own smoothers). 
If \code{object} is not class \code{tensor.smooth.spec} it will have the following elements:

\Itemize{
\item[term] The names of the covariates for this smooth, in an array.
\item[bs.dim] Argument \code{k} of the \code{s} term generating the object. This is the dimension of the basis 
used to represent the term (or, arguably, 1 greater than the basis dimension for \code{cc} terms). 
\code{bs.dim<0} indicates that the constructor should set this to the default value.
\item[fixed] \code{TRUE} if the term is to be unpenalized, otherwise \code{FALSE}.
\item[dim] the number covariates of which this smooth is a function.
\item[p.order] the order of the smoothness penalty or \code{NA} for autoselection of this. This is argument 
\code{m} of the \code{s} term that generated \code{object}.
\item[by] the name of any \code{by} variable to multiply this term as supplied as an argument to \code{s}. 
\code{"NA"} if there is no such term.
\item[label] A suitable label for use with this term.
\item[xt] An object containing information that may be needed for basis setup
(used, e.g. by \code{"tp"} smooths to pass optional information on big dataset
handling).
\item[id] Any identity associated with this term --- used for linking bases
and smoothing parameters. \code{NULL} by default, indicating no linkage.
\item[sp] Smoothing parameters for the term. Any negative are estimated,
otherwise they are fixed at the supplied value. Unless \code{NULL} (default),
over-rides \code{sp} argument to \code{\LinkA{gam}{gam}}.
}

If \code{object} is of class \code{tensor.smooth.spec} then it was generated by a \code{te} term in the GAM formula, 
and specifies a smooth of several variables with a basis generated as a tensor product of lower dimensional bases. 
In this case the object will be different and will have the following elements:
\Itemize{
\item[margin] is a list of smooth specification objects of the type listed above, defining the bases which have 
their tensor product formed in order to construct this term.
\item[term] is the array of names of the covariates that are arguments of the smooth.
\item[by] is the name of any \code{by} variable, or \code{"NA"}.
\item[fx] is an array, the elements of which indicate whether (\code{TRUE}) any of the margins in the 
tensor product should be unpenalized.
\item[label] A suitable label for use with this term.
\item[dim] is the number of covariates of which this smooth is a function.
\item[mp] \code{TRUE} if multiple penalties are to be used.
\item[np] \code{TRUE} if 1-D marginal smooths are to be re-parameterized in terms of
function values.
\item[id] Any identity associated with this term --- used for linking bases
and smoothing parameters. \code{NULL} by default, indicating no linkage.
\item[sp] Smoothing parameters for the term. Any negative are estimated,
otherwise they are fixed at the supplied value. Unless \code{NULL} (default),
over-rides \code{sp} argument to \code{\LinkA{gam}{gam}}.
}
\item[\code{data}] For \code{smooth.construct} a data frame or list containing the evaluation of the elements of \code{object\$term},
with names given by \code{object\$term}. The last entry will be the \code{by} variable, if \code{object\$by}
is not \code{"NA"}. For \code{smooth.construct2} \code{data} need only be an object within which \code{object\$term} 
can be evaluated, the variables can be in any order, and there can be irrelevant variables present as well. 
\item[\code{knots}] an optional data frame or list containing the knots relating to \code{object\$term}. 
If it is \code{NULL} then the knot locations are generated automatically. The structure of \code{knots} should
be as for \code{data}, depending on whether \code{smooth.construct} or \code{smooth.construct2} is used.
\end{ldescription}
\end{Arguments}
\begin{Details}\relax
There are built in methods for objects with the following classes:
\code{tp.smooth.spec} (thin plate regression splines: see \code{\LinkA{tprs}{tprs}}); 
\code{ts.smooth.spec} (thin plate regression splines with shrinkage-to-zero);
\code{cr.smooth.spec} (cubic regression splines: see \code{\LinkA{cubic.regression.spline}{cubic.regression.spline}};
\code{cs.smooth.spec} (cubic regression splines with shrinkage-to-zero);
\code{cc.smooth.spec} (cyclic cubic regression splines);
\code{ps.smooth.spec} (Eilers and Marx (1986) style P-splines: see \code{\LinkA{p.spline}{p.spline}});
\code{cp.smooth.spec} (cyclic P-splines)
\code{ad.smooth.spec} (adaptive smooths of 1 or 2 variables: see \code{\LinkA{adaptive.smooth}{adaptive.smooth}});
\code{tensor.smooth.spec} (tensor product smooths).

There is an implicit assumption that the basis only depends on the knots and/or the set of unique 
covariate combinations; i.e. that the basis is the same whether generated from
the full set of covariates, or just the unique combinations of covariates.
\end{Details}
\begin{Value}
The input argument \code{object}, assigned a new class to indicate what type of smooth it is and with at least the 
following items added:
\begin{ldescription}
\item[\code{X}] The model matrix from this term. This may have an \code{"offset"}
attribute:  a vector of length \code{nrow(X)} containing any contribution of
the smooth to the model offset term. \code{by} variables do not need to be
dealt with here, but if they are then an item \code{by.done} must be added to
the \code{object}.
\item[\code{S}] A list of positive semi-definite penalty matrices that apply to this term. The list will be empty 
if the term is to be left un-penalized.
\item[\code{rank}] an array giving the ranks of the penalties.
\item[\code{C}] The matrix defining any constraints on the term. If this is \code{NULL} then
\code{smoothCon} will add an identifiability constraint that each term should
sum to zero over the covariate values. Set to a zero row matrix if no
constraints are required. Note that a supplied \code{C} is never ignored, even if any
\code{by} variables of a smooth imply that no constraint is actually needed. 
\item[\code{df}] the degrees of freedom associated with this term (when
unpenalized and unconstrained). If this is null then \code{smoothCon} will set it to the basis 
dimension. \code{smoothCon} will reduce this by the number of constraints.
\item[\code{L}] smooths may depend on fewer `underlying' smoothing parameters than there are elements of
\code{S}. In this case \code{L} is the matrix mapping the vector of underlying log smoothing 
parameters to the vector of logs of the smoothing parameters actually multiplying the \code{S[[i]]}. 
\code{L=NULL} signifies that there is one smoothing parameter per \code{S[[i]]}. 
\end{ldescription}


Usually the returned object will also include extra information required to define the basis, and used by 
\code{\LinkA{Predict.matrix}{Predict.matrix}} methods to make predictions using the basis. See
the \code{Details} section for links to the information included for the built in smooth classes. 

\code{tensor.smooth} returned objects will additionally have each element of
the \code{margin} list updated in the same way. \code{tensor.smooths} also
have a list, \code{XP}, containing re-parameterization matrices for any 1-D marginal terms
re-parameterized in terms of function values. This list will have \code{NULL}
entries for marginal smooths that are not re-parameterized, and is only long
enough to reach the last re-parameterized marginal in the list.
\end{Value}
\begin{Section}{WARNING}
User defined smooth objects should avoid having attributes names
\code{"qrc"} or \code{"nCons"} as these are used internally to provide
constraint free parameterizations.
\end{Section}
\begin{Author}\relax
Simon N. Wood \email{simon.wood@r-project.org}
\end{Author}
\begin{References}\relax
Wood, S.N. (2003) Thin plate regression splines. J.R.Statist.Soc.B 65(1):95-114

Wood, S.N. (2006) Low rank scale invariant tensor product smooths for
generalized additive mixed models. Biometrics 62(4):1025-1036

The P-spline code given in the example is based on those advocated in:

Ruppert, D., M.P. Wand and R.J. Carroll (2003) Semiparametric Regression. Cambridge 
University Press.

However if you want p-splines, rather than splines with derivative based penalties,
then the built in "ps" class is probably a better bet. It's based on

Eilers, P.H.C. and B.D. Marx (1996) Flexible Smoothing with B-splines and Penalties. 
Statistical Science, 11(2):89-121

\url{http://www.maths.bath.ac.uk/~sw283/}
\end{References}
\begin{SeeAlso}\relax
\code{\LinkA{s}{s}},\code{\LinkA{get.var}{get.var}}, \code{\LinkA{gamm}{gamm}}, \code{\LinkA{gam}{gam}},
\code{\LinkA{Predict.matrix}{Predict.matrix}},
\code{\LinkA{smoothCon}{smoothCon}}, \code{\LinkA{PredictMat}{PredictMat}}
\end{SeeAlso}
\begin{Examples}
\begin{ExampleCode}# adding "p-spline" classes and methods

smooth.construct.tr.smooth.spec<-function(object,data,knots)
## a truncated power spline constructor method function
## object$p.order = null space dimension
{ m <- object$p.order[1]
  if (is.na(m)) m <- 2 ## default 
  if (m<1) stop("silly m supplied")
  if (object$bs.dim<0) object$bs.dim <- 10 ## default
  nk<-object$bs.dim-m-1 ## number of knots
  if (nk<=0) stop("k too small for m")
  x <- data[[object$term]]  ## the data
  x.shift <- mean(x) # shift used to enhance stability
  k <- knots[[object$term]] ## will be NULL if none supplied
  if (is.null(k)) # space knots through data
  { n<-length(x)
    k<-quantile(x[2:(n-1)],seq(0,1,length=nk+2))[2:(nk+1)]
  }
  if (length(k)!=nk) # right number of knots?
  stop(paste("there should be ",nk," supplied knots"))
  x <- x - x.shift # basis stabilizing shift
  k <- k - x.shift # knots treated the same!
  X<-matrix(0,length(x),object$bs.dim)
  for (i in 1:(m+1)) X[,i] <- x^(i-1)
  for (i in 1:nk) X[,i+m+1]<-(x-k[i])^m*as.numeric(x>k[i])
  object$X<-X # the finished model matrix
  if (!object$fixed) # create the penalty matrix
  { object$S[[1]]<-diag(c(rep(0,m+1),rep(1,nk)))
  }
  object$rank<-nk  # penalty rank
  object$null.space.dim <- m+1  # dim. of unpenalized space
  ## store "tr" specific stuff ...
  object$knots<-k;object$m<-m;object$x.shift <- x.shift
  ## get the centering constraint ...
 
  object$df<-ncol(object$X)     # maximum DoF (if unconstrained)
 
  class(object)<-"tr.smooth"  # Give object a class
  object
}

Predict.matrix.tr.smooth<-function(object,data)
## prediction method function for the `tr' smooth class
{ x <- data[[object$term]]
  x <- x - object$x.shift # stabilizing shift
  m <- object$m;     # spline order (3=cubic)
  k<-object$knots    # knot locations
  nk<-length(k)      # number of knots
  X<-matrix(0,length(x),object$bs.dim)
  for (i in 1:(m+1)) X[,i] <- x^(i-1)
  for (i in 1:nk) X[,i+m+1] <- (x-k[i])^m*as.numeric(x>k[i])
  X # return the prediction matrix
}


# an example, using the new class....
set.seed(100)
dat <- gamSim(1,n=400,scale=2)
b<-gam(y~s(x0,bs="tr",m=2)+s(x1,bs="ps",m=c(1,3))+
         s(x2,bs="tr",m=3)+s(x3,bs="tr",m=2),data=dat)
plot(b,pages=1)
b<-gamm(y~s(x0,bs="tr",m=2)+s(x1,bs="ps",m=c(1,3))+
         s(x2,bs="tr",m=3)+s(x3,bs="tr",m=2),data=dat)
plot(b$gam,pages=1)
# another example using tensor products of the new class
dat <- gamSim(2,n=400,scale=.1)$data
b <- gam(y~te(x,z,bs=c("tr","tr"),m=c(2,2)),data=dat)
vis.gam(b)
\end{ExampleCode}
\end{Examples}

