-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathgetbasismatrix.R
182 lines (157 loc) · 5.88 KB
/
getbasismatrix.R
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
getbasismatrix <- function(evalarg, basisobj, nderiv=0, returnMatrix=FALSE) {
# Computes the basis matrix evaluated at arguments in EVALARG associated
# with basis.fd object BASISOBJ. The basis matrix contains the values
# at argument value vector EVALARG of applying the nonhomogeneous
# linear differential operator LFD to the basis functions. By default
# LFD is 0, and the basis functions are simply evaluated at argument
# values in EVALARG.
#
# If LFD is a functional data object with m + 1 functions c_1, ... c_{m+1},
# then it is assumed to define the order m HOMOGENEOUS linear
# differential operator
# Lx(t) = c_1(t) + c_2(t)x(t) + c_3(t)Dx(t) + ... +
# c_{m+1}D^{m-1}x(t) + D^m x(t).
#
# If the basis type is either polygonal or constant, LFD is ignored.
#
# Arguments:
# EVALARG...Either a vector of values at which all functions are to evaluated,
# or a matrix of values, with number of columns corresponding to
# number of functions in argument FD. If the number of evaluation
# values varies from curve to curve, pad out unwanted positions in
# each column with NA. The number of rows is equal to the maximum
# of number of evaluation points.
# BASISOBJ...A basis object
# NDERIV ... A nonnegative integer indicating a derivative to be evaluated.
#
# Note that the first two arguments may be interchanged.
#
# Last modified 6 January 2020
##
## Exchange the first two arguments if the first is an BASIS.FD object
## and the second numeric
##
if (is.numeric(basisobj) && inherits(evalarg, "basisfd")) {
temp <- basisobj
basisobj <- evalarg
evalarg <- temp
}
##
## check EVALARG
##
# if (!(is.numeric(evalarg))) stop("Argument EVALARG is not numeric.")
if(is.null(evalarg)) stop('evalarg required; is NULL.')
Evalarg <- evalarg
# turn off warnings in checking if argvals can be converted to numeric
op <- options(warn=-1)
evalarg <- as.numeric(Evalarg)
options(op)
nNA <- sum(is.na(evalarg))
if(nNA>0)
stop('as.numeric(evalarg) contains ', nNA,
' NA', c('', 's')[1+(nNA>1)],
'; class(evalarg) = ', class(Evalarg))
##
## check BASISOBJ
##
if (!(inherits(basisobj, "basisfd")))
stop("Second argument is not a basis object.")
##
## search for stored basis matrix and return it if found
##
if (!(length(basisobj$basisvalues) == 0 || is.null(basisobj$basisvalues))) {
# one or more stored basis matrices found,
# check that requested derivative is available
if (!is.vector(basisobj$basisvalues)) stop("BASISVALUES is not a vector.")
basisvalues <- basisobj$basisvalues
nvalues <- length(basisvalues)
# search for argvals match
N <- length(evalarg)
OK <- FALSE
for (ivalues in 1:nvalues) {
basisvaluesi <- basisvalues[ivalues]
if (!is.list(basisvaluesi)) stop("BASISVALUES does not contain lists.")
argvals <- basisvaluesi[[1]]
if (!length(basisvaluesi) < nderiv+2) {
if (N == length(argvals)) {
if (all(argvals == evalarg)) {
basismat <- basisvaluesi[[nderiv+2]]
OK <- TRUE
}
}
}
}
# dimnames
dimnames(basismat) <- list(NULL, basisobj$names)
if (OK){
if(length(dim(basismat)) == 2){
return(as.matrix(basismat))
}
return(basismat)
}
}
##
## compute the basis matrix and return it
##
# Extract information about the basis
type <- basisobj$type
nbasis <- basisobj$nbasis
params <- basisobj$params
rangeval <- basisobj$rangeval
dropind <- basisobj$dropind
##
## Select basis and evaluate it at EVALARG values
##
# ----------------------------- B-spline basis -------------------
if (type == "bspline") {
if (length(params) == 0) {
breaks <- c(rangeval[1], rangeval[2])
} else {
breaks <- c(rangeval[1], params, rangeval[2])
}
norder <- nbasis - length(breaks) + 2
basismat <- bsplineS(evalarg, breaks, norder, nderiv)
# The following lines call spline.des in the base R system.
# This is slightly slower than the above call to bsplineS
# nbreaks <- length(breaks)
# knots <- c(rep(rangeval[1],norder), breaks(2:(nbreaks-1)),
# rep(rangeval[2],norder))
# basismat <- spline.des(knots, evalarg, norder, nderiv, sparse=TRUE)
# ----------------------------- Constant basis --------------------
} else if (type == "const") {
basismat <- matrix(1,length(evalarg),1)
# ----------------------------- Exponential basis -------------------
} else if (type == "expon") {
basismat <- expon(evalarg, params, nderiv)
# ------------------------------- Fourier basis -------------------
} else if (type == "fourier") {
period <- params[1]
basismat <- fourier(evalarg, nbasis, period, nderiv)
# ----------------------------- Monomial basis -------------------
} else if (type == "monom") {
basismat <- monomial(evalarg, params, nderiv)
# ----------------------------- Polygonal basis -------------------
} else if (type == "polygonal") {
basismat <- polyg(evalarg, params)
# ----------------------------- Power basis -------------------
} else if (type == "power") {
basismat <- powerbasis(evalarg, params, nderiv)
# ----------------------- Unrecognizable basis --------------------
} else {
stop("Basis type not recognizable")
}
# dimnames
dimnames(basismat) <- list(NULL, basisobj$names)
# remove columns for bases to be dropped
if (length(dropind) > 0) basismat <- basismat[,-dropind]
if (length(evalarg) == 1) {
basismat = matrix(basismat,1,length(basismat))
}
if (length(dim(basismat)) == 2){
# coerce basismat to be nonsparse
return(as.matrix(basismat))
} else {
# allow basismat to be sparse if it already is
return(as.matrix(basismat))
}
}