Skip to content

Commit 3265393

Browse files
committed
update landmarkreg.R
1 parent af6f604 commit 3265393

File tree

1 file changed

+67
-46
lines changed

1 file changed

+67
-46
lines changed

R/landmarkreg.R

+67-46
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,26 @@
1-
landmarkreg <- function(unregfd, ximarks, x0marks=xmeanmarks,
2-
WfdPar=NULL, ylambda=1e-10) {
1+
landmarkreg <- function(unregfd, ximarks, x0marks, x0lim=NULL,
2+
WfdPar=NULL, WfdPar0=NULL, ylambda=1e-10) {
3+
# This version of landmarkreg does not assume that the target marks
4+
# x0marks are within the same interval as that for the curves to be
5+
# registered. Consequently, it needs a required extra argument X0LIM
6+
# defining the target interval and optional fdPar argument for
7+
# representing the inverse warping function.
8+
39
# Arguments:
410
# UNREGFD ... functional data object for curves to be registered
511
# XIMARKS ... N by NL array of times of interior landmarks for
612
# each observed curve
713
# XOMARKS ... vector of length NL of times of interior landmarks for
814
# target curve
15+
# X0LIM ... vector of length 2 containing the lower and upper boundary
16+
# of the target interval containing x0marks.
917
# WFDPAR ... a functional parameter object defining a warping function
18+
# MONWRD ... If TRUE, warping functions are estimated by monotone smoothing,
19+
# otherwise by regular smoothing. The latter is faster, but
20+
# not guaranteed to produce a strictly monotone warping
21+
# function. If MONWRD is 0 and an error message results
22+
# indicating nonmonotonicity, rerun with MONWRD = 1.
23+
# Default: TRUE
1024
# YLAMBDA ... smoothing parameter to be used in computing the registered
1125
# functions. For high dimensional bases, local wiggles may be
1226
# found in the registered functions or its derivatives that are
@@ -24,16 +38,18 @@ landmarkreg <- function(unregfd, ximarks, x0marks=xmeanmarks,
2438
# smooth.basis too often violates this contraint. Function
2539
# smooth.morph ensures monotonicity.
2640

27-
# Last modified 29 March 2022 by Jim Ramsay
41+
# Last modified 2 June 2022 by Jim Ramsay
2842

29-
# check unregfd
43+
# check unregfd containing the curves to be registered
3044

3145
if (!(inherits(unregfd, "fd"))) stop(
3246
"Argument unregfd not a functional data object.")
3347

34-
basisobj <- unregfd$basis
35-
nbasis <- basisobj$nbasis
36-
rangeval <- basisobj$rangeval
48+
Ybasis <- unregfd$basis
49+
nbasis <- Ybasis$nbasis
50+
rangeval <- Ybasis$rangeval
51+
52+
if (is.null(x0lim)) x0lim = rangeval
3753

3854
# ---------------------------------------------------------------------
3955
# check ximarks and x0marks
@@ -51,11 +67,6 @@ landmarkreg <- function(unregfd, ximarks, x0marks=xmeanmarks,
5167
stop("Argument ximarks is not numeric.")
5268
}
5369

54-
# compute row-wise mean of ximarks to serve as x0marks if
55-
# needed
56-
57-
xmeanmarks <- apply(ximarks,2,mean)
58-
5970
# check x0marks and coerce it to be a one-row matrix
6071

6172
if (is.numeric(x0marks)) {
@@ -75,10 +86,10 @@ landmarkreg <- function(unregfd, ximarks, x0marks=xmeanmarks,
7586
if (any(ximarks <= rangeval[1]) || any(ximarks >= rangeval[2]))
7687
stop("Argument ximarks has values outside of range of unregfd.")
7788

78-
# check that x0marks are within range of unregfd
89+
# check that x0marks are within range of target interval
7990

80-
if (any(x0marks <= rangeval[1]) || any(x0marks >= rangeval[2]))
81-
stop("Argument x0marks has values outside of range of unregfd.")
91+
if (any(x0marks <= x0lim[1]) || any(x0marks >= x0lim[2]))
92+
stop("Argument x0marks has values outside of range of target interval.")
8293

8394
# determine the number of curves to be registered
8495

@@ -88,39 +99,47 @@ landmarkreg <- function(unregfd, ximarks, x0marks=xmeanmarks,
8899
# check WFDPAR
89100
# ---------------------------------------------------------------------
90101

91-
# set up default WfdPar
102+
# set up default WfdPar for warping function
92103

93104
if (is.null(WfdPar)) {
94105
Wnbasis <- length(x0marks) + 2
95-
Wbasis <- create.bspline.basis(rangeval, Wnbasis)
96-
Wfd <- fd(matrix(0,Wnbasis,ncurve), Wbasis)
106+
Ybasis <- create.bspline.basis(rangeval, Wnbasis)
107+
Wfd <- fd(matrix(0,Wnbasis,1), Wbasis)
97108
WfdPar <- fdPar(Wfd, 2, 1e-10)
109+
} else {
110+
WfdPar <- fdParcheck(WfdPar, 1)
111+
Wfd <- WfdPar$fd
112+
Wbasis <- Wfd$basis
113+
Wnbasis <- Wbasis$nbasis
114+
}
115+
116+
# set up default WfdPar0 for inverse warping function
117+
118+
if (is.null(WfdPar0)) {
119+
Wnbasis0 <- length(x0marks) + 2
120+
Wbasis0 <- create.bspline.basis(x0lim, Wnbasis0)
121+
Wfd0 <- fd(matrix(0,Wnbasis0,1), Wbasis0)
122+
WfdPar0 <- fdPar(Wfd0, 2, 1e-10)
123+
} else {
124+
WfdPar0 <- fdParcheck(WfdPar0, 1)
125+
Wfd0 <- WfdPar0$fd
126+
Wbasis0 <- Wfd0$basis
127+
Wnbasis0 <- Wbasis0$nbasis
98128
}
99-
100-
WfdPar <- fdParcheck(WfdPar, ncurve)
101-
102-
# set up WFD0 and WBASIS
103-
104-
Wfd0 <- WfdPar$fd
105-
WLfd <- WfdPar$Lfd
106-
Wbasis <- Wfd0$basis
107-
Wrange <- Wbasis$rangeval
108-
Wlambda <- WfdPar$lambda
109129

110130
# ---------------------------------------------------------------------
111131
# set up analysis
112132
# ---------------------------------------------------------------------
113133

114134
nfine <- min(c(101,10*nbasis))
115-
xfine <- seq(rangeval[1],rangeval[2],length=nfine)
135+
xfine <- seq(rangeval[1], rangeval[2], length=nfine)
136+
xfine0 <- seq( x0lim[1], x0lim[2], length=nfine)
116137
yfine <- eval.fd(xfine, unregfd)
117138
yregmat <- yfine
118139
hfunmat <- matrix(0,nfine,ncurve)
119140
hinvmat <- matrix(0,nfine,ncurve)
120-
Wlambda <- max(Wlambda,1e-10)
121141

122-
xval <- c(rangeval[1],x0marks,rangeval[2])
123-
Wnbasis <- Wbasis$nbasis
142+
xval <- matrix(c(x0lim[1],x0marks,x0lim[2]),nx0marks+2,1)
124143
Wcoef <- matrix(0,Wnbasis,ncurve)
125144
nval <- length(xval)
126145

@@ -133,10 +152,12 @@ landmarkreg <- function(unregfd, ximarks, x0marks=xmeanmarks,
133152
for (icurve in 1:ncurve) {
134153
if (ncurve > 1) cat(".")
135154
# set up landmark times for this curve
136-
yval <- c(rangeval[1],ximarks[icurve,],rangeval[2])
155+
yval <- matrix(c(rangeval[1],ximarks[icurve,],rangeval[2]),nx0marks+2,1)
137156
# smooth relation between this curve"s values and target"s values
138157
# use monotone smoother
139-
Wfd <- smooth.morph(xval, yval, Wrange, WfdPar)$Wfdobj
158+
159+
Wfd <- smooth.morph(xval, yval, rangeval, WfdPar)$Wfdobj
160+
140161
hfun <- monfn(xfine, Wfd)
141162
b <- (rangeval[2]-rangeval[1])/(hfun[nfine]-hfun[1])
142163
a <- rangeval[1] - b*hfun[1]
@@ -149,48 +170,48 @@ landmarkreg <- function(unregfd, ximarks, x0marks=xmeanmarks,
149170
# compute h-inverse in order to register curves
150171

151172
Wcoefi <- Wfd$coefs
152-
Wfdinv <- fd(-Wcoefi,Wbasis)
153-
WfdParinv <- fdPar(Wfdinv, WLfd, Wlambda)
154-
Wfdinv <- smooth.morph(hfun, xfine, Wrange, WfdParinv)$Wfdobj
173+
Wfdinv <- smooth.morph(hfun, xfine, x0lim, WfdPar0)$Wfdobj
155174
hinv <- monfn(xfine, Wfdinv)
156-
b <- (rangeval[2]-rangeval[1])/(hinv[nfine]-hinv[1])
157-
a <- rangeval[1] - b*hinv[1]
175+
b <- (x0lim[2]-x0lim[1])/(hinv[nfine]-hinv[1])
176+
a <- x0lim[1] - b*hinv[1]
158177
hinv <- a + b*hinv
159178
hinv[c(1,nfine)] <- rangeval
179+
hinvmat[,icurve] <- hinv
160180

161181
# compute registered curves
162182

163-
yregfd <- smooth.basis(hinv, yfine[,icurve], basisobj)$fd
183+
yregfd <- smooth.basis(hinv, yfine[,icurve], Ybasis)$fd
164184
yregmat[,icurve] <- eval.fd(xfine, yregfd, 0)
165185
}
166186

167187
if (ncurve > 1) cat("\n")
168188

169189
# create functional data objects for the registered curves
170190

171-
regfdPar <- fdPar(basisobj, 2, ylambda)
191+
regfdPar <- fdPar(Ybasis, 2, ylambda)
172192
regfd <- smooth.basis(xfine, yregmat, regfdPar)$fd
173193
regnames <- unregfd$fdnames
174194
names(regnames)[3] <- paste("Registered",names(regnames)[3])
175195
regfd$fdnames <- regnames
176196

177197
# create functional data objects for the warping functions
178198

179-
warpfd <- smooth.basis(xfine, hfunmat, basisobj)$fd
199+
warpfd <- smooth.basis(xfine, hfunmat, Ybasis)$fd
180200
warpfdnames <- unregfd$fdnames
181201
names(warpfdnames)[3] <- paste("Warped",names(regnames)[1])
182202
warpfd$fdnames <- warpfdnames
183-
203+
184204
# create functional data objects for the inverse warping functions
185205

186-
warpfdinv <- smooth.basis(xfine, hinvmat, basisobj)$fd
206+
Ybasis0 <- create.bspline.basis(x0lim, nbasis)
207+
warpinvfd <- smooth.basis(xfine0, hinvmat, Ybasis0)$fd
187208
warpfdnames <- unregfd$fdnames
188209
names(warpfdnames)[3] <- paste("Warped",names(regnames)[1])
189-
warpfdinv$fdnames <- warpfdnames
210+
warpinvfd$fdnames <- warpfdnames
190211

191212
# The core function defining the strictly monotone warping
192213

193214
Wfd <- fd(Wcoef, Wbasis)
194215

195-
return( list(regfd=regfd, warpfd=warpfd, warpfdinv=warpfdinv, Wfd = Wfd) )
216+
return( list(regfd=regfd, warpfd=warpfd, warpinvfd=warpinvfd, Wfd=Wfd) )
196217
}

0 commit comments

Comments
 (0)