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
+
3
9
# Arguments:
4
10
# UNREGFD ... functional data object for curves to be registered
5
11
# XIMARKS ... N by NL array of times of interior landmarks for
6
12
# each observed curve
7
13
# XOMARKS ... vector of length NL of times of interior landmarks for
8
14
# target curve
15
+ # X0LIM ... vector of length 2 containing the lower and upper boundary
16
+ # of the target interval containing x0marks.
9
17
# 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
10
24
# YLAMBDA ... smoothing parameter to be used in computing the registered
11
25
# functions. For high dimensional bases, local wiggles may be
12
26
# found in the registered functions or its derivatives that are
@@ -24,16 +38,18 @@ landmarkreg <- function(unregfd, ximarks, x0marks=xmeanmarks,
24
38
# smooth.basis too often violates this contraint. Function
25
39
# smooth.morph ensures monotonicity.
26
40
27
- # Last modified 29 March 2022 by Jim Ramsay
41
+ # Last modified 2 June 2022 by Jim Ramsay
28
42
29
- # check unregfd
43
+ # check unregfd containing the curves to be registered
30
44
31
45
if (! (inherits(unregfd , " fd" ))) stop(
32
46
" Argument unregfd not a functional data object." )
33
47
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
37
53
38
54
# ---------------------------------------------------------------------
39
55
# check ximarks and x0marks
@@ -51,11 +67,6 @@ landmarkreg <- function(unregfd, ximarks, x0marks=xmeanmarks,
51
67
stop(" Argument ximarks is not numeric." )
52
68
}
53
69
54
- # compute row-wise mean of ximarks to serve as x0marks if
55
- # needed
56
-
57
- xmeanmarks <- apply(ximarks ,2 ,mean )
58
-
59
70
# check x0marks and coerce it to be a one-row matrix
60
71
61
72
if (is.numeric(x0marks )) {
@@ -75,10 +86,10 @@ landmarkreg <- function(unregfd, ximarks, x0marks=xmeanmarks,
75
86
if (any(ximarks < = rangeval [1 ]) || any(ximarks > = rangeval [2 ]))
76
87
stop(" Argument ximarks has values outside of range of unregfd." )
77
88
78
- # check that x0marks are within range of unregfd
89
+ # check that x0marks are within range of target interval
79
90
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 ." )
82
93
83
94
# determine the number of curves to be registered
84
95
@@ -88,39 +99,47 @@ landmarkreg <- function(unregfd, ximarks, x0marks=xmeanmarks,
88
99
# check WFDPAR
89
100
# ---------------------------------------------------------------------
90
101
91
- # set up default WfdPar
102
+ # set up default WfdPar for warping function
92
103
93
104
if (is.null(WfdPar )) {
94
105
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 )
97
108
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
98
128
}
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
109
129
110
130
# ---------------------------------------------------------------------
111
131
# set up analysis
112
132
# ---------------------------------------------------------------------
113
133
114
134
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 )
116
137
yfine <- eval.fd(xfine , unregfd )
117
138
yregmat <- yfine
118
139
hfunmat <- matrix (0 ,nfine ,ncurve )
119
140
hinvmat <- matrix (0 ,nfine ,ncurve )
120
- Wlambda <- max(Wlambda ,1e-10 )
121
141
122
- xval <- c(rangeval [1 ],x0marks ,rangeval [2 ])
123
- Wnbasis <- Wbasis $ nbasis
142
+ xval <- matrix (c(x0lim [1 ],x0marks ,x0lim [2 ]),nx0marks + 2 ,1 )
124
143
Wcoef <- matrix (0 ,Wnbasis ,ncurve )
125
144
nval <- length(xval )
126
145
@@ -133,10 +152,12 @@ landmarkreg <- function(unregfd, ximarks, x0marks=xmeanmarks,
133
152
for (icurve in 1 : ncurve ) {
134
153
if (ncurve > 1 ) cat(" ." )
135
154
# 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 )
137
156
# smooth relation between this curve"s values and target"s values
138
157
# use monotone smoother
139
- Wfd <- smooth.morph(xval , yval , Wrange , WfdPar )$ Wfdobj
158
+
159
+ Wfd <- smooth.morph(xval , yval , rangeval , WfdPar )$ Wfdobj
160
+
140
161
hfun <- monfn(xfine , Wfd )
141
162
b <- (rangeval [2 ]- rangeval [1 ])/ (hfun [nfine ]- hfun [1 ])
142
163
a <- rangeval [1 ] - b * hfun [1 ]
@@ -149,48 +170,48 @@ landmarkreg <- function(unregfd, ximarks, x0marks=xmeanmarks,
149
170
# compute h-inverse in order to register curves
150
171
151
172
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
155
174
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 ]
158
177
hinv <- a + b * hinv
159
178
hinv [c(1 ,nfine )] <- rangeval
179
+ hinvmat [,icurve ] <- hinv
160
180
161
181
# compute registered curves
162
182
163
- yregfd <- smooth.basis(hinv , yfine [,icurve ], basisobj )$ fd
183
+ yregfd <- smooth.basis(hinv , yfine [,icurve ], Ybasis )$ fd
164
184
yregmat [,icurve ] <- eval.fd(xfine , yregfd , 0 )
165
185
}
166
186
167
187
if (ncurve > 1 ) cat(" \n " )
168
188
169
189
# create functional data objects for the registered curves
170
190
171
- regfdPar <- fdPar(basisobj , 2 , ylambda )
191
+ regfdPar <- fdPar(Ybasis , 2 , ylambda )
172
192
regfd <- smooth.basis(xfine , yregmat , regfdPar )$ fd
173
193
regnames <- unregfd $ fdnames
174
194
names(regnames )[3 ] <- paste(" Registered" ,names(regnames )[3 ])
175
195
regfd $ fdnames <- regnames
176
196
177
197
# create functional data objects for the warping functions
178
198
179
- warpfd <- smooth.basis(xfine , hfunmat , basisobj )$ fd
199
+ warpfd <- smooth.basis(xfine , hfunmat , Ybasis )$ fd
180
200
warpfdnames <- unregfd $ fdnames
181
201
names(warpfdnames )[3 ] <- paste(" Warped" ,names(regnames )[1 ])
182
202
warpfd $ fdnames <- warpfdnames
183
-
203
+
184
204
# create functional data objects for the inverse warping functions
185
205
186
- warpfdinv <- smooth.basis(xfine , hinvmat , basisobj )$ fd
206
+ Ybasis0 <- create.bspline.basis(x0lim , nbasis )
207
+ warpinvfd <- smooth.basis(xfine0 , hinvmat , Ybasis0 )$ fd
187
208
warpfdnames <- unregfd $ fdnames
188
209
names(warpfdnames )[3 ] <- paste(" Warped" ,names(regnames )[1 ])
189
- warpfdinv $ fdnames <- warpfdnames
210
+ warpinvfd $ fdnames <- warpfdnames
190
211
191
212
# The core function defining the strictly monotone warping
192
213
193
214
Wfd <- fd(Wcoef , Wbasis )
194
215
195
- return ( list (regfd = regfd , warpfd = warpfd , warpfdinv = warpfdinv , Wfd = Wfd ) )
216
+ return ( list (regfd = regfd , warpfd = warpfd , warpinvfd = warpinvfd , Wfd = Wfd ) )
196
217
}
0 commit comments