bsplinesetup.fun <- function(y, n=min(50, dim(y)[2]))
{
#
#   Given a matrix y of data, find a B-spline basis based on at most (n-2)  internal knots. 
#   In this version, the number of knots is reduced if there are not at least n time points 
#     observed data
#
#  On input:  The rows of y represent observations and the columns time points.
#
#  Output:ycoef	Matrix of spline coefficients, columns represent observations
#	bmat	Matrix giving values of bsplines at observation points
#	jmat	Matrix of integrals of crossproducts of B-splines
#	kmat	Matrix of integrals of crossproducts of second derivatives of B-splines
#	meancoef  Mean B-spline coefficients
#	funmean	Average function values
#
#     First find the knots
#
	if(!is.matrix(y))  y <- t(as.matrix(y))
	m <-  dim(y)[2]
	nd <- dim(y)[1]
	n <- min(n, m)
	intkn <- seq(from = 0, to = 1, length = n)
	kn <- c(0, 0, 0, intkn, 1, 1, 1)	
#
#   Now find the crossintegral matrix jmat 
#
	bmat1 <- spline.des(knots = kn, x = seq(from = 0, to = 1, 
		length = 101))[[4]]
	jmat <- 0.01 * t(bmat1) %*% bmat1	
#
#  find the matrix kmat of integrals of products of second derivatives
#
	zs <- spline.des(kn, intkn, deriv = rep(2,n))[[4]]
	z1 <- zs[-1,  ]
	z2 <- zs[-n,  ]
	kmat <- 2*t(z1)%*%z1 + 2*t(z2)%*%z2 + t(z1)%*%z2 + t(z2)%*%z1
	kmat <- kmat/(6*(n-1))	

#
#   Now find the matrix of values at the evaluation points, 
#     and the coefficients of the data.  
#   If there are more bsplines than evaluation points, 
#     find the fit with the least roughness.
#
	bmat <- spline.des(knots=kn, x=seq(from=0, to=1, length=m))[[4]]
	if((n + 2) <= m) {
		ycoef <- solve(bmat, t(y))
	}
	else {
		bsvd <- svd(bmat, nv = n + 2)
		baug <- rbind(bmat, t(bsvd$v[, (m + 1):(n + 2)]) %*% kmat)
		zmat <- matrix(0, nrow = n + 2 - m, ncol = nd)
		yaug <- rbind(t(y), zmat)
		ycoef <- solve(baug, yaug)
	}
#
#  Now find the mean coefficients and the values of the mean of the original data
#
	meancoef <- apply(ycoef, 1, mean)
	funmean <- bmat %*% meancoef
	return(ycoef, bmat, jmat, kmat, meancoef, funmean)
}
bvals.fun <- function(yc, nvals = 101)
{
#
#   Given a vector of B-spline coefficients yc, 
#
	kn <- c(0,0,0, seq(from=0, to=1, length=length(yc)-2), 1,1,1)
	xx <- seq(from = 0, to = 1, length = nx)
	bmat1 <- spline.des(knots = kn, x = xx)[[4]]
	yfun <- bmat1 %*% yc
	return(x = xx, y = yfun)
}
funsmooth.fun <-  function(zs, spar)
{
#  	carry out roughness penalty smoothing of the mean curve, following preprocessing
#   	by the function bsplinesetup.fun.          On input 
#	zs is the output of bsplinesetup.fun
#    	spar is the smoothing parameter
#	On output
#     the values g of the smoothed mean function at the evaluation points
#    	and the coefficients gcoef of the smoothed mean function are returned
#    	
#
	jlk <- zs$jmat + spar * zs$kmat
	gcoef <- solve(jlk, zs$jmat %*% zs$meancoef)
	g <- zs$bmat %*% gcoef
	return(g, gcoef)
}
funsmoothcv.fun <- function(zs, spar)
{
#  	calculates crossvalidation score for roughness penalty smoothing of the mean curve
# 	following preprocessing by the function bsplinesetup.fun.  On input 
#		zs is the output of bsplinesetup.fun
#    		spar is a vector of smoothing parameters
#  	The vector of cross-validation scores is returned.
#
	nsp <- length(spar)
	n <- dim(zs$ycoef)[2]
	cvscores <- rep(NA, nsp)
	for(j in (1:nsp)) {
		jlk <- zs$jmat + spar[j] * zs$kmat
		gcoef <- solve(jlk, zs$jmat %*% zs$meancoef)
		smat <- solve(jlk, zs$jmat %*% zs$ycoef)
		delresmat <- n * sweep(zs$ycoef, 1, gcoef) + smat -zs$ycoef
		delresmatj <- t(delresmat) %*% chol(zs$jmat)
		cvscores[j] <- sum(delresmatj^2)
	}
	return(cvscores)
}
funpca.fun <-  function(zz, spar = 1, zmean = zz$meancoef)
{
#
#  Takes the output of bsplinesetup.fun and carries out a smoothed functional PCA
#    with smoothing parameter equal to spar. This is taken straight from page 118
#    of Ramsay and Silverman, 1997, but with a vital correction.  
#       If centered=T then it is assumed that the 
#    mean or estimated mean has been subtracted from the coefficients zz$ycoef
#
	zm <- zz$jmat + spar * zz$kmat
	zm <- 0.5 * (zm + t(zm))
	umat <- chol(zm)
	lmat <- t(umat)
	ycmat <- zz$jmat %*% sweep(zz$ycoef, 1, zmean)
	dmat <- solve(lmat, ycmat)
	cmat <- dmat %*% t(dmat)/dim(ycmat)[2]
	eig <- eigen(cmat)
	emat <- eig$vectors[, 1:10]
	pcasmat <- solve(umat, emat)
	pcabmat <- zz$bmat %*% pcasmat
	vn <- apply(pcabmat, 2, vecnorm)
	pcabmat <- sweep(pcabmat, 2, vn, "/")
	return(pcabmat)
}

