TABLE OF CONTENTS


00main/splinesurv.agdata [ Functions ]

NAME

    splinesurv.agdata --- main estimation function

FUNCTION

This is the main fitting function for the splinesurv routine. It accepts a data frame in a specified format, conducts the initialization procedure, then either starts the MCMC loop within R or calls compiled C code that does the same thing.

See also the call graph linked from 00main.

This function should not be called directly, instead the interface provided by splinesurv.formula should be used.

SYNOPSIS

4246 splinesurv.agdata <- function(x, hazard = NULL, frailty = NULL, regression = NULL,
4247     control = NULL, coda = FALSE, initial = NULL, verbose = 3, usec = TRUE, ...)

INPUTS

    x      a data frame with the following columns:
           i       cluster index
           j       subject index
           time    event time
           delta   event indicator
           ...     covariates
    See the package documentation for detail on the remaining options

OUTPUTS

    an object of class splinesurv, see package documentation.

SOURCE

4250 {
4251         
4252     if(verbose >= 1) cat("Initializing...\n")
4253     
4254     agdata <- x
4255     rm(x)
4256     call <- match.call()
4257     m <- length(unique(agdata$i))
4258     if(m == 1) warning("Single cluster: frailty density estimate is meaningless")
4259     Ji <- table(agdata$i)
4260     
4261     if(verbose >= 2) cat("\tSetting initial parameters...\n")
4262     
4263     # Parse input (control)
4264     control.in <- control
4265     # default control options
4266     control.default <- list(
4267         burnin = 500, # Length of the burn - in period
4268         maxiter = 1000, # Max number of iterations
4269         thin = 1, # Degree of thinning
4270         tun.auto = TRUE, # Auto - calibrate tuning parameters
4271         tun.int = 100 # Interval for calibration of the acceptance rate
4272     )
4273     control <- control.default
4274     controlnames <- names(control)
4275     innames <- names(control.in)
4276     if(!is.null(control.in)){
4277         # replace default control settings by any specified in input
4278         for(n in innames) eval(parse(text = paste("control$",
4279             match.arg(n, controlnames), " <- control.in$", n, sep = "")))
4280     }
4281     if(control$burnin > control$maxiter) stop("Burnin cannot be greater than maxiter")
4282      
4283      # Parse input (frailty)   
4284     frailty.in <- frailty
4285     # default settings for frailty RCurve options
4286     frailty.default <- list(
4287         type = "spline",
4288         spline.ord = 4,
4289         spline.adaptive = TRUE,
4290         spline.knots = NULL,
4291         spline.knotspacing = "equal",
4292         spline.nknots = NULL,
4293         spline.nknots.prior = NULL,
4294         spline.nknots.hyper = NULL,
4295         spline.ncandknots = 100,
4296         spline.bdmconst=.4,
4297         spline.maxoccknots = 35,
4298         spline.maxknot = 5,
4299         spline.par = NULL,
4300         spline.min=-100,
4301         spline.penalty = "none",
4302         spline.penaltyfactor = 1,
4303         spline.meanpenalty = 1e10,
4304         spline.priorvar = 0.1,
4305         spline.hyper = c(0.01, 0.01),
4306         spline.tun = 1,
4307         spline.accept = 0,       
4308         param.dist = "none",
4309         param.par = NULL,
4310         param.priorvar = 0.1,
4311         param.hyper = c(0.01, 0.01),
4312         param.tun = 1,
4313         param.accept = 0,
4314         weight = 0.5,
4315         weight.priorvar = 0.1,
4316         weight.hyper = c(1, 2),
4317         weight.tun = 0.01,
4318         weight.accept = 0,
4319         accept = 0
4320     )
4321     frailty <- frailty.default
4322     frailtynames <- names(frailty)
4323     if(!is.null(frailty.in)){
4324         # replace default frailty options by input
4325         for(n in names(frailty.in)) eval(parse(text = paste("frailty$",
4326             match.arg(n, frailtynames), " <- frailty.in$", n, sep = "")))
4327     }
4328     # set additional RCurve settings
4329     frailty$type <- match.arg(frailty$type, c("spline", "parametric", "both"))
4330     frailty$hasspline <- frailty$type == "spline" | frailty$type == "both"
4331     frailty$haspar <- frailty$type == "parametric" | frailty$type == "both"
4332     frailty$spline.knotspacing <- match.arg(frailty$spline.knotspacing, c("equal"))
4333     frailty$spline.penalty <- match.arg(frailty$spline.penalty,
4334         c("2diff", "2deriv", "log2deriv", "none"))
4335     frailty$param.dist <- match.arg(frailty$param.dist, c("none", "gamma", "lognormal"))
4336     if(m == 1 & frailty$haspar) stop("parametric component not allowed for single cluster")
4337     if(frailty$haspar & frailty$param.dist == "none") {
4338         warning(paste("no distribution specified for frailty parametric component",
4339             "-- setting to gamma"))
4340         frailty$param.dist <- "gamma"
4341     }
4342     # match prior settings and set default hyperparameters
4343     frailty$spline.nknots.prior <- match.arg(frailty$spline.nknots.prior,
4344         c("poisson", "geometric", "poissonmix", "negbin", "power"))
4345     if(frailty$spline.nknots.prior == "poisson" & is.null(frailty$spline.nknots.hyper))
4346         frailty$spline.nknots.hyper <- 10
4347     if(frailty$spline.nknots.prior == "geometric" & is.null(frailty$spline.nknots.hyper))
4348         frailty$spline.nknots.hyper <- 0.1
4349     if(frailty$spline.nknots.prior == "poissonmix" & is.null(frailty$spline.nknots.hyper))
4350         frailty$spline.nknots.hyper <- c(10, 30)
4351     if(frailty$spline.nknots.prior == "negbin" & is.null(frailty$spline.nknots.hyper))
4352         frailty$spline.nknots.hyper <- c(2, .1)
4353     if(frailty$spline.nknots.prior == "power" & is.null(frailty$spline.nknots.hyper))
4354         frailty$spline.nknots.hyper <- -1 / 2
4355 
4356     frailty$spline.norm <- TRUE
4357     frailty$name <- "frailty"
4358     
4359      # Parse input (hazard)   
4360     hazard.in <- hazard
4361     # default hazard RCurve
4362     hazard.default <- list(
4363         type = "spline",
4364         spline.ord = 4,
4365         spline.adaptive = TRUE,
4366         spline.knotspacing = "mixed",
4367         spline.nknots = NULL,
4368         spline.nknots.prior = NULL,
4369         spline.nknots.hyper = NULL,
4370         spline.ncandknots = 100,
4371         spline.maxoccknots = 35,
4372         spline.bdmconst=.4,
4373         spline.knots = NULL,
4374         spline.par = NULL,
4375         spline.min=-100,
4376         spline.penalty = "none",
4377         spline.penaltyfactor = 1,
4378         spline.priorvar = 0.1,
4379         spline.hyper = c(0.01, 0.01),
4380         spline.tun = 1,      
4381         spline.accept = 0, 
4382         param.dist = "none",
4383         param.par = NULL,
4384         param.priorvar = 0.1,
4385         param.hyper = c(0.01, 0.01),
4386         param.tun = 1,
4387         param.accept = 0,
4388         weight = 0.5,
4389         weight.priorvar = 0.1,
4390         weight.hyper = c(1, 2),
4391         weight.tun = 0.01,
4392         weight.accept = 0
4393     )
4394     hazard <- hazard.default
4395     haznames <- names(hazard)
4396     if(!is.null(hazard.in)){
4397         for(n in names(hazard.in)) eval(parse(text = paste("hazard$",
4398             match.arg(n, haznames), " <- hazard.in$", n, sep = "")))
4399     }
4400     # other hazard settings
4401     hazard$type <- match.arg(hazard$type, c("spline", "parametric", "both"))
4402     hazard$hasspline <- hazard$type == "spline" | hazard$type == "both"
4403     hazard$haspar <- hazard$type == "parametric" | hazard$type == "both"
4404     hazard$spline.knotspacing <- match.arg(hazard$spline.knotspacing,
4405         c("quantile", "equal", "mixed"))
4406     hazard$spline.penalty <- match.arg(hazard$spline.penalty,
4407         c("2diff", "2deriv", "log2deriv", "none"))
4408     hazard$param.dist <- match.arg(hazard$param.dist,
4409         c("none", "exponential", "weibull", "lognormal")) 
4410     if(hazard$haspar & hazard$param.dist == "none") {
4411         warning(paste("no distribution specified for hazard parametric component",
4412             "-- setting to weibull"))
4413         hazard$param.dist <- "weibull"
4414     }
4415     # priors and hyperparameters for the number of knots
4416     hazard$spline.nknots.prior <- match.arg(hazard$spline.nknots.prior,
4417         c("poisson", "geometric", "poissonmix", "negbin", "power"))
4418     if(hazard$spline.nknots.prior == "poisson" & is.null(hazard$spline.nknots.hyper))
4419         hazard$spline.nknots.hyper <- 10
4420     if(hazard$spline.nknots.prior == "geometric" & is.null(hazard$spline.nknots.hyper))
4421         hazard$spline.nknots.hyper <- 0.1
4422     if(hazard$spline.nknots.prior == "poissonmix" & is.null(hazard$spline.nknots.hyper))
4423         hazard$spline.nknots.hyper <- c(10, 30)
4424     if(hazard$spline.nknots.prior == "negbin" & is.null(hazard$spline.nknots.hyper))
4425         hazard$spline.nknots.hyper <- c(2, .1)
4426     if(hazard$spline.nknots.prior == "power" & is.null(hazard$spline.nknots.hyper))
4427         hazard$spline.nknots.hyper <- -1 / 2
4428 
4429     # default weight settings
4430     if(!hazard$haspar) hazard$weight <- 1
4431     if(!hazard$hasspline) hazard$weight <- 0
4432     if(!frailty$haspar) frailty$weight <- 1
4433     if(!frailty$hasspline) frailty$weight <- 0
4434     
4435     hazard$spline.norm <- FALSE
4436     hazard$name <- "hazard"
4437     hazard$x <- agdata$time
4438      
4439     # Parse input (regression)
4440     reg.in <- regression
4441     reg.default <- list(
4442         priorvar = 0.1,
4443         hyper = c(0.01, 0.01),
4444         tun = 1,
4445         accept = 0
4446     )
4447     regression <- reg.default
4448     regnames <- names(regression)
4449     if(!is.null(reg.in)) for(n in names(reg.in))
4450         eval(parse(text = paste("regression$", match.arg(n, regnames),
4451             " <- reg.in$", n, sep = "")))
4452 
4453      # Default settings for the initial number of knots
4454     if(is.null(hazard$spline.nknots)) hazard$spline.nknots <- if(hazard$spline.adaptive) 
4455         min(nknotsPriorMean(hazard), hazard$spline.maxoccknots) else 
4456         max(min(round(sum(Ji) / 4), 35), 1)
4457     if(is.null(frailty$spline.nknots)) frailty$spline.nknots <- if(frailty$spline.adaptive)
4458         min(nknotsPriorMean(frailty), frailty$spline.maxoccknots) else 
4459         max(1, min(round(m / 4), 35), 1)
4460     
4461     
4462     if(verbose >= 2) cat("\tFitting Cox survival models...\n")
4463     
4464     # Cox fit with gamma frailties for initial values of Ui and beta
4465     varnames <- colnames(agdata)[ - (1:4)]
4466     qvarnames <- paste("`", varnames, "`", sep = "")
4467     if(m > 1){
4468         coxfit <- coxph(as.formula(paste("Surv(time, delta)~",
4469             paste(qvarnames, collapse = " + "), " + frailty(i)")), data = agdata)
4470         Ui <- exp(coxfit$frail)
4471         if(var(Ui) < 1e-5) {
4472             Ui <- 2 * runif(length(Ui))
4473             Ui <- 1 + (Ui - mean(Ui))
4474             Ui[Ui < 0] <- 1
4475         }
4476     }else{
4477         coxfit <- coxph(as.formula(paste("Surv(time, delta)~",
4478             paste(qvarnames, collapse = " + "))), data = agdata)
4479         Ui <- 1
4480     } 
4481     # set initial frailies and regression structure
4482     frailty$x <- Ui   
4483     beta <- coxfit$coef
4484     regression$m <- m
4485     regression$Ji <- Ji
4486     regression$covariates <- as.matrix(agdata[, -(1:4)], sum(Ji), length(beta))
4487     regression$time <- agdata$time
4488     regression$status <- agdata$delta
4489     regression$cluster <- as.integer(agdata$i)
4490     regression <- updateregression(regression, beta)
4491         
4492     rm(coxfit)
4493     
4494     # Parametric fits
4495     if(verbose >= 2 & (frailty$haspar | hazard$haspar)) 
4496         cat("\tFitting parametric components...\n")
4497     
4498     hazard <- fitparametric(hazard, agdata)
4499     frailty <- fitparametric(frailty, Ui)
4500 
4501     # Spline knots
4502     if(verbose >= 2 & (frailty$hasspline | hazard$hasspline))
4503         cat("\tComputing spline knots...\n")
4504     
4505     hazbounds <- range(agdata$time) + c(-.1, .1) * diff(range(agdata$time))
4506     hazbounds[hazbounds < 0] <- 0
4507     hazard <- makeknots(hazard, agdata$time[agdata$delta == 1], bounds = hazbounds)
4508     frailty <- makeknots(frailty, Ui, bounds = c(0, max(max(Ui), min(2 * max(Ui),
4509         frailty$spline.maxknot))))
4510         
4511     # Evaluate the splines and integrals
4512     if(verbose >= 2 & (frailty$hasspline | hazard$hasspline))
4513         cat("\tConstructing spline basis functions...\n")
4514     
4515     hazard <- makesplinebasis(hazard, usec = usec)
4516     frailty <- makesplinebasis(frailty, usec = usec)
4517        
4518     # Penalty matrices
4519     if(verbose >= 2 & (frailty$hasspline | hazard$hasspline))
4520         cat("\tInitializing penalty matrices...\n")
4521 
4522     hazard <- makepenalty(hazard, usec = usec)
4523     frailty <- makepenalty(frailty, usec = usec)    
4524         
4525 
4526     if(verbose >= 2 & (frailty$hasspline | hazard$hasspline))
4527         cat("\tObtaining initial values for spline parameters...\n")
4528 
4529     {{{# Initial values for the theta vectors
4530     
4531     if(hazard$haspar & hazard$hasspline){
4532         oldhazweight <- hazard$weight
4533         hazard$weight <- 1;
4534         hazard <- weightcurve(hazard)
4535     }
4536     if(frailty$haspar & frailty$hasspline){
4537         oldfrailweight <- frailty$weight
4538         frailty$weight <- 1;
4539         frailty <- weightcurve(frailty)
4540     }
4541 
4542     # Initial values for hazard parameters 
4543     if(hazard$hasspline){
4544             theta.haz <- rep(0, hazard$spline.nknots + hazard$spline.ord)
4545         if(usec){ # use fast C code to compute likelihoods
4546             par <- as.double(theta.haz); status <- as.double(regression$status);
4547             lp <- as.double(regression$lp); frailrep <- as.double(rep(frailty$x, Ji));
4548             hazParY <- as.double(if(hazard$haspar) hazard$param.y else rep(0, length(lp))); 
4549             hazParYcum <- as.double(if(hazard$haspar) hazard$param.ycum else
4550                 rep(0, length(lp))); 
4551             weight <- hazard$weight; B <- as.double(hazard$spline.basis);
4552             C <- as.double(hazard$spline.basiscum);
4553             P <- as.double(hazard$spline.penaltyfactor * hazard$spline.penaltymatrix);
4554             penaltyType <- as.integer(pmatch(hazard$spline.penalty,
4555                 c("none", "2diff", "2deriv", "log2deriv")) - 1);
4556             splinemin <- as.double(hazard$spline.min)
4557             sigma2 <- hazard$spline.priorvar
4558             sigma2 <- 100; sigma2target <- hazard$spline.priorvar
4559              #compute initial values by slowly decreasing the prior variance for stability
4560             while(sigma2 > sigma2target){
4561                 sigma2 <- as.double(sigma2 / 10)
4562                 opt.theta.haz <- optim(par, fn = cmklik.spline.haz, gr = cmkgr.spline.haz,
4563                     status = status, lp = lp, frailrep = frailrep, hazParY = hazParY, 
4564                     hazParYcum = hazParYcum, weight = weight, B = B, C = C, P = P,
4565                     penaltyType = penaltyType, sigma2 = sigma2, min = splinemin,
4566                     method = "BFGS", control = list(fnscale=-1))
4567                 par <- as.double(opt.theta.haz$par)
4568             }
4569             opt.theta.haz <- optim(par, fn = cmklik.spline.haz, gr = cmkgr.spline.haz,
4570                 status = status, lp = lp, frailrep = frailrep, hazParY = hazParY,
4571                 hazParYcum = hazParYcum, weight = weight, B = B, C = C, P = P,
4572                 penaltyType = penaltyType, sigma2 = sigma2, min = splinemin,
4573                 method = "BFGS", control = list(fnscale=-1, maxit = 1), hessian = TRUE)
4574             rm(par, status, lp, hazParY, hazParYcum, weight, B, C, P, penaltyType,
4575                 splinemin, sigma2)
4576             gcout <- gc()
4577         }else{ # usec=FALSE
4578             hazard <- updatespline(hazard, theta.haz)
4579             gcout <- gc()
4580             sigma2 <- 100; sigma2target <- hazard$spline.priorvar
4581              #compute initial values by slowly decreasing the prior variance
4582             while(sigma2 > sigma2target){
4583                 sigma2 <- sigma2 / 10;
4584                 hazard$spline.priorvar <- sigma2
4585                 opt.theta.haz <- optim(hazard$spline.par,
4586                         fn = mklik.spline.haz,
4587                         gr = mkgr.spline.haz,
4588                         method = "BFGS",
4589                         control = list(fnscale=-1),
4590                         hazard = hazard,
4591                         frailty = frailty,
4592                         regression = regression,
4593                         hessian = FALSE)
4594                 hazard <- updatespline(hazard, opt.theta.haz$par)
4595             }
4596             opt.theta.haz <- optim(hazard$spline.par,
4597                     fn = mklik.spline.haz,
4598                     gr = mkgr.spline.haz,
4599                     method = "BFGS",
4600                     control = list(fnscale=-1),
4601                     hazard = hazard,
4602                     frailty = frailty,
4603                     regression = regression,
4604                     hessian = TRUE)
4605         }
4606         gcout <- gc()
4607         hazard <- updatespline(hazard, opt.theta.haz$par)
4608 
4609     }
4610 
4611         # Initial values for frailty parameters
4612     if(frailty$hasspline){
4613         frailty$spline.fixedind <- 1
4614         # parameter vector not including the fixed index
4615             theta.frail <- rep(0, frailty$spline.nknots + frailty$spline.ord - 1)
4616         {
4617             opt.theta.frail <- optim(theta.frail,
4618                     fn = mklik.spline.frail.init,
4619                     method = "BFGS",
4620                     control = list(fnscale=-1),
4621                     hazard = hazard,
4622                     frailty = frailty,
4623                     regression = regression,
4624                     hessian = TRUE)    
4625         }
4626         gcout <- gc()
4627         # add the fixed index back in
4628         theta.frail <- repairfrailtypar(opt.theta.frail$par, frailty$spline.fixedind)
4629         badtheta <- TRUE; j <- 0;
4630         # set the mean of the estimated frailty density to be exactly 1
4631         while(badtheta){
4632            j <- j + 1
4633            thetaj <- suppressWarnings(log(-sum(frailty$spline.basisexp[ - j] * exp(theta.frail[ - j])) / frailty$spline.basisexp[j]))
4634            if(!is.nan(thetaj)) badtheta <- FALSE
4635         }
4636         theta.frail[j] <- thetaj; 
4637         frailty <- updatespline(frailty, theta.frail)
4638     }
4639 
4640     gcout <- gc()
4641     # reweight the inital curves
4642     if(hazard$hasspline & hazard$haspar){
4643         hazard$weight <- oldhazweight
4644         hazard <- weightcurve(hazard);
4645     }
4646     if(frailty$hasspline & frailty$haspar){
4647         frailty$weight <- oldfrailweight
4648         frailty <- weightcurve(frailty)
4649     }
4650 
4651     gcout <- gc() 
4652     # Evaluate variances and hessians for candidate generation
4653     frailty$tun <- diff(range(Ui))^2 / 6
4654     hess.coef <- mkhess.coef(regression$coefficients, hazard, frailty, regression)
4655     Sigma.coef <- solve(-hess.coef)
4656     regression$candcov <- Sigma.coef
4657     regression$cholcandcov <- chol(Sigma.coef, pivot = TRUE)
4658     if(hazard$hasspline){
4659         hess.haz <- opt.theta.haz$hess
4660         Sigma.haz <- inverthessian(hess.haz)
4661         hazard$spline.candcov <- Sigma.haz
4662         hazard$spline.candsd <- rep(1, hazard$spline.maxoccknots + hazard$spline.ord)
4663         hazard$spline.cholcandcov <- chol(Sigma.haz, pivot = TRUE)
4664         rm(hess.haz, Sigma.haz)
4665     }
4666     if(frailty$hasspline){
4667         hess.frail <- opt.theta.frail$hess
4668         Sigma.frail <- inverthessian(hess.frail)
4669         frailty$spline.candcov <- Sigma.frail
4670         frailty$spline.candsd <- rep(1, frailty$spline.maxoccknots + frailty$spline.ord)
4671         frailty$spline.cholcandcov <- chol(Sigma.frail, pivot = TRUE)
4672         rm(hess.frail, Sigma.frail)
4673     }
4674     # construct a numeric hessian for the parametric parameters
4675     if(hazard$haspar){ 
4676         # (I don't remember why it doesn't just use numHess.par like for the frailty, but
4677         #   there must be a reason for this inelegant setup)
4678         temphaz <- list(haspar = hazard$haspar, hasspline = hazard$hasspline,
4679         weight = hazard$weight, spline.y = hazard$spline.y, spline.ycum = hazard$spline.ycum,
4680         name = hazard$name, param.dist = hazard$param.dist, x = hazard$x, y = hazard$y,
4681         ycum = hazard$ycum, param.y = hazard$param.y, param.ycum = hazard$param.ycum,
4682         param.par = hazard$param.par, param.priorvar = hazard$param.priorvar)
4683         eps <- 1e-5
4684         par <- temphaz$param.par
4685         hess <- matrix(0, length(par), length(par))
4686         for(i in 1:length(par)){
4687             # this constructs numerical gradients by finite differences
4688             for(j in 1:length(par)){
4689             par1 <- par;par2 <- par;par3 <- par;
4690             if(i == j) {par1[i] <- par[i] + eps;par2 <- par1;par3[i] <- par[i] + 2 * eps}
4691             else {par1[i] <- par[i] + eps; par2[j] <- par[j] + eps; par3 <- par1;
4692                 par3[j] <- par[j] + eps}
4693             g1 <- (mklik.param.haz(par1, temphaz, frailty, regression) -
4694                 mklik.param.haz(par, temphaz, frailty, regression)) / eps
4695             g2 <- (mklik.param.haz(par3, temphaz, frailty, regression) -
4696                 mklik.param.haz(par2, temphaz, frailty, regression)) / eps
4697             hess[i, j] <- (g2 - g1) / eps
4698             }
4699         }
4700         Sigma.par.haz <- inverthessian(hess)
4701         hazard$param.candcov <- Sigma.par.haz
4702         hazard$param.cholcandcov <- chol(Sigma.par.haz, pivot = TRUE)
4703         rm(Sigma.par.haz, hess, temphaz)
4704     }
4705     if(frailty$haspar){
4706         Sigma.par.frail <- inverthessian(numHess.par(frailty$param.par, mklik.param.frail,
4707             hazard = hazard, frailty = frailty, regression = regression))
4708         frailty$param.candcov <- Sigma.par.frail
4709         frailty$param.cholcandcov <- chol(Sigma.par.frail, pivot = TRUE)
4710         rm(Sigma.par.frail)
4711     }
4712     
4713     
4714     }}}
4715 
4716     if(frailty$hasspline) frailty$spline.fvar <- frailtysplinefvar(frailty)
4717     #browser()
4718     gcout <- gc()
4719     # Store initial values in parameter history
4720     history <- inithistory(hazard, frailty, regression, control)
4721     avg.tunhist <- NULL
4722     avg.accepthist <- NULL
4723     
4724 
4725     # an internal function to prepare the curve structures for calling the C code
4726     prepforCall <- function(curve){
4727         if(curve$type == "parametric") return(curve)
4728         if(curve$spline.nknots < curve$spline.maxoccknots){
4729             addcols <- curve$spline.maxoccknots - curve$spline.nknots
4730             curve$spline.knots <- c(curve$spline.knots, rep(-Inf, addcols))
4731             curve$spline.par <- c(curve$spline.par, rep(-Inf, addcols))
4732             curve$spline.candsd <- c(curve$spline.candsd, rep(-Inf, addcols))
4733             curve$spline.basis <- cbind(curve$spline.basis, matrix(-Inf, 
4734                 dim(curve$spline.basis)[1], addcols))
4735             curve$spline.basisint <- c(curve$spline.basisint, rep(-Inf, addcols))
4736             if(curve$name == "hazard") curve$spline.basiscum <- cbind(curve$spline.basiscum,
4737                 matrix(-Inf, dim(curve$spline.basiscum)[1], addcols))
4738             if(curve$name == "frailty") curve$spline.basisexp <- c(curve$spline.basisexp,
4739                 rep(-Inf, addcols))
4740         }
4741         curve$spline.candocc <- attr(curve$spline.candknots, "occupied")
4742         return(curve)
4743     }
4744     if(usec){
4745         hazard <- prepforCall(hazard)
4746         frailty <- prepforCall(frailty)
4747     }
4748 
4749      # this does nothing, it just creates a useful marker
4750      main <- function() {}
4751         
4752     if(verbose >= 1) cat("Starting MCMC...\n")
4753     
4754     iter <- 1 # Counts the recorded iterations
4755     iter.el <- 0 # Counts elapsed iterations in each thinning cycle
4756     
4757     if(verbose >= 3) cat(iter, " ")
4758 
4759     
4760     while(iter < control$maxiter)
4761     {
4762         if(usec){
4763             # C version of the main loop
4764             gcout <- gc()
4765             nexttunint <- iter - iter%%control$tun.int + control$tun.int
4766             enditer <- min(nexttunint, control$maxiter)
4767             out <- .Call("SplineSurvMainLoop", hazard, frailty, regression, history, iter,
4768                 enditer, control$thin, verbose) 
4769             iter <- enditer
4770         }else{
4771 
4772             # R version of the main loop
4773 
4774             iter.el <- iter.el + 1
4775 
4776             if(verbose >= 4) cat(iter.el)
4777                 
4778             # MH update of frailties
4779             frailty <- mh.frail(hazard, frailty, regression)
4780             
4781             # MH update of regression parameters
4782             regression <- mh.coef(hazard, frailty, regression)
4783 
4784             # MH update of baseline parameters
4785             hazard <- mh.hazard.spline(hazard, frailty, regression)
4786             
4787             # MH update of frailty density parameters
4788             frailty <- mh.frailty.spline(hazard, frailty, regression)
4789                     
4790             # MH update of parametric baseline parameters
4791             hazard <- mh.hazard.param(hazard, frailty, regression)
4792             
4793             # MH update of parametric frailty parameters
4794             frailty <- mh.frailty.param(hazard, frailty, regression)
4795 
4796             # MH update of weights
4797             hazard <- mh.weight("hazard", hazard, frailty, regression)
4798             frailty <- mh.weight("frailty", hazard, frailty, regression)
4799 
4800             # Update of the sigmas / taus
4801             hazard <- updatepostvar.curve(hazard)
4802             frailty <- updatepostvar.curve(frailty)
4803             regression <- updatepostvar.coef(regression)
4804 
4805             # Birth - death - move
4806             if(hazard$spline.adaptive)
4807                 hazard <- mh.bdm("hazard", hazard, frailty, regression)
4808             if(frailty$spline.adaptive)
4809                 frailty <- mh.bdm("frailty", hazard, frailty, regression)
4810 
4811             # record history
4812             if(iter.el == control$thin){        
4813                 iter <- iter + 1
4814                 history <- updatehistory(history, iter, hazard, frailty, regression)
4815                 iter.el <- 0
4816                 if(verbose >= 3) cat(" ", iter, " ", sep = "")
4817             }
4818         }
4819 
4820         {{{  # Periodic calibration check
4821         if(iter%%control$tun.int == 0 & iter < control$maxiter){
4822   
4823             if(verbose == 1 | verbose == 2) cat(iter, " ")
4824             
4825             calinds <- (iter - control$tun.int + 1):iter   
4826 
4827             # Calibration of the tuning parameters for acceptance rate
4828             if(control$tun.auto & iter <= control$burnin){
4829                if(verbose >= 3) cat("\n Calibration ...\n")
4830                       
4831                           
4832                 tunnames <- c("regression$tun",
4833                     "hazard$spline.tun",
4834                     "frailty$spline.tun",
4835                     "hazard$param.tun",
4836                     "frailty$param.tun",
4837                     "hazard$weight.tun",
4838                     "frailty$weight.tun",
4839                     "frailty$tun")             
4840                 alltun <- rep(0, length(tunnames))
4841                 for(i in 1:length(alltun)) eval(parse(text = paste("alltun[", i, "] <- ",
4842                     tunnames[i])))
4843                 avg.tunhist <- rbind(avg.tunhist, alltun)
4844                 avg.accepthist <- rbind(avg.accepthist,
4845                                       apply(history$accept[calinds, ], 2, mean))
4846                 for(g in 1:length(alltun)){
4847                     if(all(avg.accepthist[, g]>.25)) alltun[g] <- alltun[g] * 2
4848                     if(all(avg.accepthist[, g]<.25)) alltun[g] <- alltun[g] / 2
4849                     if(any(avg.accepthist[, g]>.25) & any(avg.accepthist[, g]<.25)){
4850                         # build linear regression model for tuning parameters
4851                         fit <- lm(y~x, data.frame(x = avg.tunhist[, g], 
4852                             y = avg.accepthist[, g]))
4853                         out <- try(max(1e-3, nlm(accrate.predict.lm, alltun[g], m = fit)$est))
4854                         if(inherits(out, "try-error"))
4855                             alltun[g] <- avg.tunhist[which.min((avg.accepthist-.25)^2)]
4856                         else
4857                             alltun[g] <- out
4858                     }
4859                 }
4860                 for(i in 1:length(alltun)) eval(parse(text = paste(tunnames[i],
4861                     " <- alltun[", i, "]")))
4862 
4863                 if(verbose >= 4){
4864                     outmat <- cbind(avg.accepthist, alltun);
4865                     rownames(outmat) <- tunnames;
4866                     colnames(outmat) <- c("acceptance", "tuning")
4867                     print(outmat)
4868                 }
4869             }
4870             # Print full iteration info
4871             if(verbose >= 5){
4872                 cat("Frailties: ", submean(history$frailty, calinds), "\n")
4873                 cat("Coefficients: ", submean(history$coefficients, calinds), "\n")
4874                 cat("Hazard.spline: ", submean(history$hazard.spline.par, calinds), "\n")
4875                 cat("Frailty.spline: ", submean(history$frailty.spline.par, calinds), "\n")
4876                 cat("Hazard.param: ", submean(history$hazard.param.par, calinds), "\n")
4877                 cat("Frailty.param: ", submean(history$frailty.param.par, calinds), "\n")
4878                 cat("Prior variances: ", submean(history$priorvar, calinds), "\n")
4879             }
4880             
4881             #browser()
4882             
4883         }
4884         }}}
4885         
4886     }   # end main loop
4887 
4888     gcout <- gc()
4889     if(verbose > 0) cat("Done!\n")
4890     hazard <- makeoutputcurve(hazard)
4891     frailty <- makeoutputcurve(frailty)
4892    
4893     gcout <- gc()
4894    {{{ # Construct output
4895     if(control$burnin < iter){
4896         if(hasspline(frailty)){
4897         frail.par.rs <- rowSums(exp(history$frailty.spline.par))
4898         history$frailty.spline.par <- exp(history$frailty.spline.par) / frail.par.rs
4899         }
4900         sub <- (1:(iter)) > (control$burnin)
4901         posterior.mean <- list(coefficients = submean(history$coefficients, sub),
4902                             frailty = submean(history$frailty, sub),
4903                             hazard.spline.par = submean(history$hazard.spline.par, sub),
4904                             hazard.param.par = submean(history$hazard.param.par, sub),
4905                             hazard.weight = submean(history$hazard.weight, sub),
4906                             frailty.spline.par = submean(history$frailty.spline.par, sub),
4907                             frailty.param.par = submean(history$frailty.param.par, sub),
4908                             frailty.weight = submean(history$frailty.weight, sub)
4909                         )
4910         # save mean number of knots in spline.nknots for output
4911         if(hasspline(hazard)) 
4912             hazard$spline.nknots <- mean(apply(history$hazard.spline.knots[sub, ], 1,
4913                 function(x) sum(x>-Inf))) - 2 * hazard$spline.ord
4914         if(hasspline(frailty)) {
4915             frailty$spline.nknots <- mean(apply(history$frailty.spline.knots[sub, ], 1,
4916                 function(x) sum(x>-Inf))) - 2 * frailty$spline.ord
4917             history$frailty.spline.par <- log(history$frailty.spline.par)
4918             posterior.mean$frailty.spline.par <- log(posterior.mean$frailty.spline.par)
4919         }
4920         colnames(history$coefficients) <- varnames
4921         names(posterior.mean$coefficients) <- varnames
4922     }else{
4923         postmean = NULL
4924     }
4925     if(coda){
4926         # convert history to mcmc objects
4927         library(coda)
4928         for(i in 1:length(history)) history[[i]] <- as.mcmc(history[[i]])
4929     }
4930     # clear history rownames
4931     rownames(history$frailty) <- rownames(history$coefficients) <-
4932         rownames(history$splinepar.haz) <- rownames(history$splinepar.frail) <- NULL
4933     control$iter <- iter
4934     }}}
4935 
4936     gcout <- gc()
4937     # output object
4938     out <- list(call = call, history = history, posterior.mean = posterior.mean,
4939         hazard = hazard, frailty = frailty, control = control, data = agdata)
4940     class(out) <- "splinesurv"
4941     return(out)
4942 }