Nothing
######################################################################
#
# abc.R
#
# copyright (c) 2011-05-30, Katalin Csillery, Olivier Francois and
# Michael GB Blum with some initial code from Mark Beaumont
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License,
# version 3, as published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but without any warranty; without even the implied warranty of
# merchantability or fitness for a particular purpose. See the GNU
# General Public License, version 3, for more details.
#
# A copy of the GNU General Public License, version 3, is available
# at http://www.r-project.org/Licenses/GPL-3
#
# Part of the R/abc package
# Contains: abc, return.abc, print.abc, is.abc, summary.abc, hist.abc, plot.abc
#
######################################################################
abc <- function(target, param, sumstat, tol, method, hcorr = TRUE,
transf = "none", logit.bounds = c(0,0), subset = NULL,
kernel = "epanechnikov", numnet = 10, sizenet = 5,
lambda = c(0.0001,0.001,0.01), trace = FALSE, maxit =
500, ...){
call <- match.call()
## general checks that the function is used correctly
## ###################################################
if(missing(target)) stop("'target' is missing")
if(missing(param)) stop("'param' is missing")
if(missing(sumstat)) stop("'sumstat' is missing")
if(!is.matrix(param) && !is.data.frame(param) && !is.vector(param)) stop("'param' has to be a matrix, data.frame or vector.")
if(!is.matrix(sumstat) && !is.data.frame(sumstat) && !is.vector(sumstat)) stop("'sumstat' has to be a matrix, data.frame or vector.")
if(missing(tol)) stop("'tol' is missing")
if(missing(method)) stop("'method' is missing with no default")
if(!any(method == c("rejection", "loclinear", "neuralnet","ridge"))){
stop("Method must be rejection, loclinear, or neuralnet or ridge")
}
if(method == "rejection") rejmethod <- TRUE
else rejmethod <- FALSE
if(!any(kernel == c("gaussian", "epanechnikov", "rectangular", "triangular", "biweight", "cosine"))){
kernel <- "epanechnikov"
warning("Kernel is incorrectly defined. Setting to default (Epanechnikov)")
}
if(is.data.frame(param)) param <- as.matrix(param)
if(is.data.frame(sumstat)) sumstat <- as.matrix(sumstat)
if(is.list(target)) target <- unlist(target)
if(is.vector(sumstat)) sumstat <- matrix(sumstat, ncol=1)
if(length(target)!=dim(sumstat)[2]) stop("Number of summary statistics in 'target' has to be the same as in 'sumstat'.")
## stop if zero var in sumstat
## #########################
nss <- length(sumstat[1,])
cond1 <- !any(as.logical(apply(sumstat, 2, function(x) length(unique(x))-1)))
if(cond1) stop("Zero variance in the summary statistics.")
## transformations
## ################
ltransf <- length(transf)
if(is.vector(param)){
numparam <- 1
param <- matrix(param, ncol=1)
}
else numparam <- dim(param)[2]
for (i in 1:ltransf){
if(sum(transf[i] == c("none","log","logit")) == 0){
stop("Transformations must be none, log, or logit.")
}
if(transf[i]=="logit"){
if(logit.bounds[i,1] >= logit.bounds[i,2]){
stop("Logit bounds are incorrect.")
}
}
}
## if no logit change logit.bounds to NULL
## if(any(transf) == "logit") logit.bounds <- NULL
## no transformation should be applied when rejmethod is true
if(rejmethod){
if(!all(transf == "none")){
warning("No transformation is applied when the simple rejection is used.", call.=F)
}
transf[1:numparam] <- "none"
}
else{
if(numparam != ltransf){
if(length(transf) == 1){
transf <- rep(transf[1], numparam)
warning("All parameters are \"", transf[1], "\" transformed.", sep="", call.=F)
}
else stop("Number of parameters is not the same as number of transformations.", sep="", call.=F)
}
}
## parameter and/or sumstat values that are to be excluded
## #######################################################
gwt <- rep(TRUE,length(sumstat[,1]))
gwt[attributes(na.omit(sumstat))$na.action] <- FALSE
if(missing(subset)) subset <- rep(TRUE,length(sumstat[,1]))
gwt <- as.logical(gwt*subset)
## extract names of parameters and statistics if given
## ###################################################
if(!length(colnames(param))){
warning("No parameter names are given, using P1, P2, ...")
paramnames <- paste("P", 1:numparam, sep="")
}
else paramnames <- colnames(param)
if(!length(colnames(sumstat))){
warning("No summary statistics names are given, using S1, S2, ...")
statnames <- paste("S", 1:nss, sep="")
}
else statnames <- colnames(sumstat)
## scale everything
## #################
scaled.sumstat <- sumstat
for(j in 1:nss){
scaled.sumstat[,j] <- normalise(sumstat[,j],sumstat[,j][gwt])
}
for(j in 1:nss){
target[j] <- normalise(target[j],sumstat[,j][gwt])
}
## calculate euclidean distance
## ############################
sum1 <- 0
for(j in 1:nss){
sum1 <- sum1 + (scaled.sumstat[,j]-target[j])^2
}
dist <- sqrt(sum1)
## includes the effect of gwt in the tolerance
dist[!gwt] <- floor(max(dist[gwt])+10)
## wt1 defines the region we're interested in
ceiling(length(dist)*tol)->nacc
sort(dist)[nacc]->ds
wt1 <- (dist <= ds)
aux<-cumsum(wt1)
wt1 <- wt1 & (aux<=nacc)
if(kernel == "gaussian")
{
wt1 <- rep(TRUE, length(dist))
}
## transform parameters
## ######################
for (i in 1:numparam){
if(transf[i] == "log"){
if(min(param[,i]) <= 0){
cat("log transform: values out of bounds - correcting...")
x.tmp <- ifelse(param[,i] <= 0,max(param[,i]),param[,i])
x.tmp.min <- min(x.tmp)
param[,i] <- ifelse(param[,i] <= 0, x.tmp.min,param[,i])
}
param[,i] <- log(param[,i])
}
else if(transf[i] == "logit"){
if(min(param[,i]) <= logit.bounds[i,1]){
x.tmp <- ifelse(param[,i] <= logit.bounds[i,1],max(param[,i]),param[,i])
x.tmp.min <- min(x.tmp)
param[,i] <- ifelse(param[,i] <= logit.bounds[i,1], x.tmp.min,param[,i])
}
if(max(param[,i]) >= logit.bounds[i,2]){
x.tmp <- ifelse(param[,i] >= logit.bounds[i,2],min(param[,i]),param[,i])
x.tmp.max <- max(x.tmp)
param[,i] <- ifelse(param[,i] >= logit.bounds[i,2], x.tmp.max,param[,i])
}
param[,i] <- (param[,i]-logit.bounds[i,1])/(logit.bounds[i,2]-logit.bounds[i,1])
param[,i] <- log(param[,i]/(1-param[,i]))
}
} # end of parameter transformations
## select summary statistics in region
## ###################################
ss <- sumstat[wt1,]
unadj.values <- param[wt1,]
## if simple rejection or in the selected region there is no var in sumstat
## ########################################################################
statvar <- as.logical(apply(cbind(sumstat[wt1,]), 2, function(x) length(unique(x))-1))
cond2 <- !any(statvar)
if(cond2 && !rejmethod)
stop("Zero variance in the summary statistics in the selected region. Try: checking summary statistics, choosing larger tolerance, or rejection method.")
if(rejmethod){
if(cond2) warning("Zero variance in the summary statistics in the selected region. Check summary statistics, consider larger tolerance.")
weights <- rep(1,length=sum(wt1))
adj.values <- NULL
residuals <- NULL
lambda <- NULL
}
else{
if(cond2) cat("Warning messages:\nStatistic(s)", statnames[!statvar], "has/have zero variance in the selected region.\nConsider using larger tolerance or the rejection method or discard this/these statistics, which might solve the collinearity problem in 'lsfit'.\n", sep=", ")
## weights
if(kernel == "epanechnikov") weights <- 1 - (dist[wt1]/ds)^2
if(kernel == "rectangular") weights <- dist[wt1]/ds
if(kernel == "gaussian") weights <- 1/sqrt(2*pi)*exp(-0.5*(dist/(ds/2))^2)
if(kernel == "triangular") weights <- 1 - abs(dist[wt1]/ds)
if(kernel == "biweight") weights <- (1 - (dist[wt1]/ds)^2)^2
if(kernel == "cosine") weights <- cos(pi/2*dist[wt1]/ds)
## regression correction
## ######################
if(method == "loclinear"){
fit1 <- lsfit(scaled.sumstat[wt1,],param[wt1,],wt=weights)
#pred <- t(fit1$coeff) %*% c(1,target)
pred <- t(structure(cbind(fit1$coefficients)[fit1$qr$pivot,], names=names(fit1$coefficients))) %*% c(1,target)
pred <- matrix(pred, ncol=numparam, nrow=sum(wt1), byrow=TRUE)
#residuals <- fit1$residuals
residuals<-param[wt1,]-t(t(structure(cbind(fit1$coefficients)[fit1$qr$pivot,], names=names(fit1$coefficients))) %*%t(cbind(1,scaled.sumstat[wt1,])))
residuals<-cbind(residuals)
#rrr<<-residuals
the_m<-apply(residuals,FUN=mean,2)
residuals<-sapply(1:numparam,FUN=function(x){residuals[,x]-the_m[x]})
pred <- sapply(1:numparam,FUN=function(x){pred[,x]+the_m[x]})
sigma2<-apply(as.matrix(residuals),FUN=function(x){sum((x)^2 *weights)/sum(weights)},MARGIN=2)
aic<-sum(wt1)*sum(log(sigma2))+2*(nss+1)*numparam
bic<-sum(wt1)*sum(log(sigma2))+log(sum(wt1))*(nss+1)*numparam
if(hcorr == TRUE){
fit2 <- lsfit(scaled.sumstat[wt1,],log(residuals^2),wt=weights)
auxaux<-t(structure(cbind(fit2$coefficients)[fit2$qr$pivot,], names=names(fit2$coefficients))) %*% c(1,target)
pred.sd <- sqrt(exp(auxaux))
pred.sd <- matrix(pred.sd, nrow=sum(wt1), ncol=numparam, byrow=T)
pred.si<-t(t(structure(cbind(fit2$coefficients)[fit2$qr$pivot,], names=names(fit2$coefficients))) %*%t(cbind(1,scaled.sumstat[wt1,])))
pred.si<-sqrt(exp(pred.si))
#residuals2<-log(residuals^2)-t(t(structure(cbind(fit2$coefficients)[fit2$qr$pivot,], names=names(fit2$coefficients))) %*%t(cbind(1,scaled.sumstat[wt1,])))
#fv <- sqrt(exp(log(fit1$residuals^2) - fit2$residuals))
#fv <- sqrt(exp(residuals2))
# adj.values <- pred + (pred.sd*residuals) / fv # correction heteroscedasticity
adj.values <- pred + (pred.sd*residuals) / pred.si
residuals<-(pred.sd*residuals) / pred.si
}
else{
adj.values <- pred + residuals
}
colnames(adj.values) <- colnames(unadj.values)
lambda <- NULL
}
## neural network regression
## ##########################
if(method == "neuralnet"){
linout <- TRUE
## normalise parameters
param.mad <- c()
for(i in 1:numparam){
param.mad[i] <- mad(param[,i][gwt]) # save for renormalisation
param[,i] <- normalise(param[,i],param[,i][gwt])
}
lambda <- sample(lambda, numnet, replace=T)
fv <- array(dim=c(sum(wt1), numparam, numnet))
pred <- matrix(nrow=numparam, ncol=numnet)
for (i in 1:numnet){
fit1 <- nnet(scaled.sumstat[wt1,], param[wt1,], weights = weights, decay = lambda[i],
size = sizenet, trace = trace, linout = linout, maxit = maxit, ...)
cat(i)
fv[,,i] <- fit1$fitted.values
pred[,i] <- predict(fit1, data.frame(rbind(target)))
}
cat("\n")
pred.med <- apply(pred, 1, median)
pred.med <- matrix(pred.med, nrow=sum(wt1), ncol=numparam, byrow=T)
fitted.values <- apply(fv, c(1,2), median)
residuals <- param[wt1,] - fitted.values # median of fitted values par nnets for each accepted point and parameter
if(hcorr == TRUE){
pred2 <- matrix(nrow=numparam, ncol=numnet)
fv2 <- array(dim=c(sum(wt1), numparam, numnet))
for (i in 1:numnet){
fit2 <- nnet(scaled.sumstat[wt1,], log(residuals^2), weights = weights, decay = lambda[i], size = sizenet, trace = trace, linout = linout, ...)
cat(i)
fv2[,,i] <- fit2$fitted.values
pred2[,i] <- predict(fit2, data.frame(rbind(target)))
}
cat("\n")
pred.sd <- sqrt(exp(apply(pred2, 1, median)))
pred.sd <- matrix(pred.sd, nrow=sum(wt1), ncol=numparam, byrow=T)
fv.sd <- sqrt(exp(apply(fv2, c(1,2), median)))
adj.values <- pred.med + (pred.sd*residuals)/fv.sd # correction heteroscedasticity
residuals<-(pred.sd*residuals)/fv.sd
}
else{
adj.values <- pred.med + residuals
}
colnames(adj.values) <- colnames(unadj.values)
## renormalise
for(i in 1:numparam){
## residuals[,i] <- residuals[,i]*param.mad[i] not much sense...
adj.values[,i] <- adj.values[,i]*param.mad[i]
}
} # end of neuralnet
if(method == "ridge"){
#print("la")
## normalise parameters
param.mad <- c()
for(i in 1:numparam){
param.mad[i] <- mad(param[,i][gwt]) # save for renormalisation
param[,i] <- normalise(param[,i],param[,i][gwt])
}
# print("ici")
numnet<-length(lambda)
#lambda <- sample(lambda, numnet, replace=T)
fv <- array(dim=c(sum(wt1), numparam, numnet))
pred <- matrix(nrow=numparam, ncol=numnet)
mataux<-sqrt(diag(weights))
paramaux<-as.matrix(mataux%*%param[wt1,])
#print(dim(paramaux))
scaledaux<-mataux%*%scaled.sumstat[wt1,]
#targetaux<-drop(mataux%*%target
for(parcur in (1:numparam))
{
#cat(parcur)
fit1<-lm.ridge(paramaux[,parcur]~scaledaux,lambda=lambda)
for (i in 1:numnet){
# fit1 <- nnet(scaled.sumstat[wt1,], param[wt1,], weights = weights, decay = lambda[i],
# size = sizenet, trace = trace, linout = linout, maxit = maxit, ...)
# cat(i)
fv[,parcur,i] <- drop(cbind(1,scaled.sumstat[wt1,])%*%(rbind(coef(fit1))[i,]))
pred[parcur,i] <- drop(c(1, target) %*%(rbind(coef(fit1))[i,]))
}
}
# cat("\n")
pred.med <- apply(pred, 1, median)
pred.med <- matrix(pred.med, nrow=sum(wt1), ncol=numparam, byrow=T)
fitted.values <- apply(fv, c(1,2), median)
residuals <- param[wt1,] - fitted.values # median of fitted values par nnets for each accepted point and parameter
if(hcorr == TRUE){
pred2 <- matrix(nrow=numparam, ncol=numnet)
fv2 <- array(dim=c(sum(wt1), numparam, numnet))
for(parcur in (1:numparam))
{
lresidaux<-(mataux%*%(log(residuals[,parcur]^2)))
fit2<-lm.ridge(lresidaux~scaledaux,lambda=lambda)
for (i in 1:numnet){
#cat(i)
fv2[,parcur,i] <- drop(cbind(1,scaled.sumstat[wt1,])%*%(rbind(coef(fit2))[i,]))
pred2[parcur,i] <- drop(c(1, target) %*%(rbind(coef(fit2))[i,]))
}
}
cat("\n")
pred.sd <- sqrt(exp(apply(pred2, 1, median)))
pred.sd <- matrix(pred.sd, nrow=sum(wt1), ncol=numparam, byrow=T)
fv.sd <- sqrt(exp(apply(fv2, c(1,2), median)))
adj.values <- pred.med + (pred.sd*residuals)/fv.sd # correction heteroscedasticity
residuals<- (pred.sd*residuals)/fv.sd
}
else{
adj.values <- pred.med + residuals
}
colnames(adj.values) <- colnames(unadj.values)
## renormalise
for(i in 1:numparam){
## residuals[,i] <- residuals[,i]*param.mad[i] not much sense...
adj.values[,i] <- adj.values[,i]*param.mad[i]
}
} # end of ridge
} # end of else than rejmethod
## back transform parameter values
## ################################
if(numparam == 1){
unadj.values <- matrix(unadj.values, ncol=1)
if(method!="rejection")
{adj.values <- matrix(adj.values, ncol=1)
residuals <- matrix(residuals, ncol=1)}
}
for (i in 1:numparam){
if(transf[i] == "log"){
unadj.values[,i] <- exp(unadj.values[,i])
adj.values[,i] <- exp(adj.values[,i])
}
else if(transf[i] == "logit"){
unadj.values[,i] <- exp(unadj.values[,i])/(1+exp(unadj.values[,i]))
unadj.values[,i] <- unadj.values[,i]*(logit.bounds[i,2]-logit.bounds[i,1])+logit.bounds[i,1]
adj.values[,i] <- exp(adj.values[,i])/(1+exp(adj.values[,i]))
adj.values[,i] <- adj.values[,i]*(logit.bounds[i,2]-logit.bounds[i,1])+logit.bounds[i,1]
}
}
abc.return(transf, logit.bounds, method, call, numparam, nss, paramnames, statnames,
unadj.values, adj.values, ss, weights, residuals, dist, wt1, gwt, lambda, hcorr,aic,bic)
}
abc.return <- function(transf, logit.bounds, method, call, numparam, nss, paramnames, statnames,
unadj.values, adj.values, ss, weights, residuals, dist, wt1, gwt, lambda, hcorr,aic,bic){
if(method == "rejection"){
out <- list(unadj.values=unadj.values, ss=ss, dist=dist,
call=call, na.action=gwt, region=wt1, transf=transf, logit.bounds = logit.bounds,
method="rejection", numparam=numparam, numstat=nss, names=list(parameter.names=paramnames, statistics.names=statnames))
}
else if(method == "loclinear"){
out <- list(adj.values=adj.values, unadj.values=unadj.values,
ss=ss, weights=weights, residuals=residuals, dist=dist,
call=call, na.action=gwt, region=wt1, transf=transf, logit.bounds = logit.bounds,
method="loclinear", hcorr = hcorr, numparam=numparam, numstat=nss,aic=aic,bic=bic,
names=list(parameter.names=paramnames, statistics.names=statnames))
}
else if(method == "ridge"){
out <- list(adj.values=adj.values, unadj.values=unadj.values,
ss=ss, weights=weights, residuals=residuals, dist=dist,
call=call, na.action=gwt, region=wt1, transf=transf, logit.bounds = logit.bounds,
method="ridge", hcorr = hcorr, numparam=numparam, numstat=nss,
names=list(parameter.names=paramnames, statistics.names=statnames))
}
else if(method == "neuralnet"){
out <- list(adj.values=adj.values, unadj.values=unadj.values,
ss=ss, weights=weights, residuals=residuals, dist=dist,
call=call, na.action=gwt, region=wt1, transf=transf, logit.bounds = logit.bounds,
method="neuralnet", hcorr = hcorr, lambda=lambda, numparam=numparam, numstat=nss,
names=list(parameter.names=paramnames, statistics.names=statnames))
}
class(out) <- "abc"
out
}
is.abc <- function(x){
if (inherits(x, "abc")) TRUE
else FALSE
}
print.abc <- function(x, ...){
if (!inherits(x, "abc"))
stop("Use only with objects of class \"abc\".", call.=F)
abc.out <- x
cl <- abc.out$call
cat("Call:\n")
dput(cl, control=NULL)
cat("Method:\n")
## rejection
if (abc.out$method == "rejection")
cat("Rejection\n\n")
## loclinear
else if (abc.out$method == "loclinear"){
if(abc.out$hcorr == T){
cat("Local linear regression\n")
cat("with correction for heteroscedasticity\n\n")
}
else cat("Local linear regression\n\n")
}
## ridge
else if (abc.out$method == "ridge"){
if(abc.out$hcorr == T){
cat("Ridge regression\n")
cat("with correction for heteroscedasticity\n\n")
}
else cat("Ridge regression\n\n")
}
## nnet
else if (abc.out$method == "neuralnet"){
if(abc.out$hcorr == T){
cat("Non-linear regression via neural networks\n")
cat("with correction for heteroscedasticity\n\n")
}
else cat("Non-linear regression via neural networks\n\n")
}
cat("Parameters:\n")
cat(abc.out$names$parameter.names, sep=", ")
cat("\n\n")
cat("Statistics:\n")
cat(abc.out$names$statistics.names, sep=", ")
cat("\n\n")
cat("Total number of simulations", length(abc.out$na.action), "\n\n")
cat("Number of accepted simulations: ", dim(abc.out$unadj.values)[1], "\n\n")
invisible(abc.out)
}
summary.abc <- function(object, unadj = FALSE, intvl = .95, print = TRUE, digits = max(3, getOption("digits")-3), ...){
if (!inherits(object, "abc"))
stop("Use only with objects of class \"abc\".", call.=F)
abc.out <- object
np <- abc.out$numparam
cl <- abc.out$call
parnames <- abc.out$names[[1]]
npri <- dim(abc.out$unadj.values)[1]
npost <- dim(abc.out$unadj.values)[1]
myprobs <- c((1-intvl)/2, 0.5, 1-(1-intvl)/2)
if(print){
cat("Call: \n")
dput(cl, control=NULL)
}
if(abc.out$method == "rejection" || unadj){
if(print) cat(paste("Data:\n abc.out$unadj.values (",npost," posterior samples)\n\n", sep=""))
res <- matrix(abc.out$unadj.values, ncol=np)
mymin <- apply(res, 2, min)
mymax <- apply(res, 2, max)
mymean <- apply(res, 2, mean)
mymode <- apply(res, 2, getmode, ...)
quants <- apply(res, 2, quantile, probs = myprobs)
sums <- rbind(mymin, quants[1,], quants[2,], mymean, mymode, quants[3,], mymax)
dimnames(sums) <- list(c("Min.:", paste(c(myprobs[1])*100, "% Perc.:", sep=""),
"Median:", "Mean:", "Mode:",
paste(c(myprobs[3])*100, "% Perc.:", sep=""), "Max.:"),
parnames)
}
else{
if(print){
cat(paste("Data:\n abc.out$adj.values (",npost," posterior samples)\n", sep=""))
cat(paste("Weights:\n abc.out$weights\n\n", sep=""))
}
res <- matrix(abc.out$adj.values, ncol=np)
wt <- abc.out$weights
mymin <- apply(res, 2, min)
mymax <- apply(res, 2, max)
mymean <- apply(res, 2, weighted.mean, w = wt)
mymode <- apply(res, 2, getmode, wt/sum(wt), ...)
quants <- apply(res, 2, function(x) rq(x~1, tau = myprobs, weights = wt)$coef)
sums <- rbind(mymin, quants[1,], quants[2,], mymean, mymode, quants[3,], mymax)
dimnames(sums) <- list(c("Min.:", paste("Weighted ", c(myprobs[1])*100, " % Perc.:", sep=""),
"Weighted Median:", "Weighted Mean:", "Weighted Mode:",
paste("Weighted ", c(myprobs[3])*100, " % Perc.:", sep=""), "Max.:"),
parnames)
}
class(sums) <- "table"
if(print){
if(length(digits) == 1)
print(round(sums, digits = digits), quote=FALSE)
else
print(apply(rbind(digits, sums), 2, function(a) round(a[-1], digits = a[1])), quote=FALSE)
invisible(sums)
}
else sums
}
getmode <- function(x, weights = NULL, ...){
## if(missing(bw) | missing(kernel) | missing(window) | missing(n)) warning("density.default() was used to calculate the posterior mode")
d <- density(x, weights = weights)
d$x[which(d$y == max(d$y))][1]
}
hist.abc <- function(x, unadj = FALSE, true = NULL,
file = NULL, postscript = FALSE, onefile = TRUE, ask = !is.null(deviceIsInteractive()),
col.hist = "grey", col.true = "red", caption = NULL, ...){
if (!inherits(x, "abc"))
stop("Use only with objects of class \"abc\".", call.=F)
abc.out <- x
np <- abc.out$numparam
parnames <- abc.out$names[[1]]
if(is.null(caption)) mycaption <- as.graphicsAnnot(parnames)
else mycaption <- caption
## checks if true is given
if(!is.null(true)){
if(!is.vector(true)){
stop("Supply true parameter value(s) as a vector.", call.=F)
}
if (length(true) != np){
stop("Number of true values has to be the same as number of parameters in 'x'.", call.=F)
}
cond <- isTRUE(c(match(names(true), parnames), match(names(true), parnames)))
if(cond) stop("Names do not match in 'x' and 'true'.", call.=F)
}
if(abc.out$method == "rejection") res <- abc.out$unadj.values
else if (unadj){
res <- abc.out$unadj.values
}
else res <- abc.out$adj.values
## Devices
## ##########
save.devAskNewPage <- devAskNewPage()
if(!is.null(file)){
file <- substitute(file)
if(!postscript) pdf(file = paste(file, "pdf", sep="."), onefile=onefile)
if(postscript) postscript(file = paste(file, "ps", sep="."), onefile=onefile)
}
else{
if (ask && prod(par("mfcol")) < np) {
devAskNewPage(TRUE)
}
}
myhist <- list()
for(i in 1:np){
myxlim <- range(res[,i], true[i])
myhist[[i]] <- hist(res[,i], xlab = parnames[i], main = paste("Posterior histogram of ", mycaption[i], sep=""),
col = col.hist, xlim = myxlim, ...)
myhist[[i]]$xname <- parnames[i]
if(!is.null(true)){
abline(v = true[i], lwd = 2, col = col.true)
}
}
if(!is.null(file)){
dev.off()
}
else devAskNewPage(save.devAskNewPage)
names(myhist) <- parnames
invisible(myhist)
} # end of hist.abc
##########################################################################################
## plots: for each parameter
## 1. prior density
## 2. posterior + prior density
## 3. distances vs parameters
## 4. histogram of the residuals
##########################################################################################
plot.abc <- function(x, param, subsample = 1000, true = NULL,
file = NULL, postscript = FALSE, onefile = TRUE, ask = !is.null(deviceIsInteractive()), ...){
if (!inherits(x, "abc"))
stop("Use only with objects of class \"abc\".", call.=F)
abc.out <- x
mymethod <- abc.out$method
if(mymethod == "rejection")
stop("Diagnostic plots can be displayed only when method is \"loclinear\", \"neuralnet\" or \"ridge\".", cal.=F)
if(!is.matrix(param) && !is.data.frame(param) && !is.vector(param)) stop("'param' has to be a matrix, data.frame or vector.", call.=F)
if(is.null(dim(param))) param <- matrix(param, ncol=1)
if(is.data.frame(param)) param <- as.matrix(param)
np <- abc.out$numparam
numsim <- length(param)/np
alldist <- log(abc.out$dist)
myregion <- abc.out$region
residuals <- abc.out$residuals
parnames <- abc.out$names$parameter.names
transf <- abc.out$transf
logit.bounds <- abc.out$logit.bounds
##check if param is compatible with x
cond <- isTRUE(c(match(colnames(param), parnames), match(parnames, colnames(param))))
if(cond) stop("'abc.out' and 'param' are not compatible; paramater names are different.", call.=F)
## checks if true is given
if(!is.null(true)){
if(!is.vector(true)){
stop("Supply true parameter value(s) as a vector.", call.=F)
}
if (length(true) != np){
stop("Number of true values has to be the same as number of parameters in 'x'.", call.=F)
}
cond <- isTRUE(c(match(names(true), parnames), match(names(true), parnames)))
if(cond) stop("Names do not match in 'x' and 'true'.", call.=F)
}
rej <- abc.out$unadj.values
res <- abc.out$adj.values
if(np == 1) rej <- matrix(rej, ncol=1)
if(is.vector(param)){
np.orig <- 1
nsim <- length(param)
}
else if(is.matrix(param)){
np.orig <- dim(param)[2]
nsim <- dim(param)[1]
myorder <- match(parnames, colnames(param))
if(isTRUE(myorder-1:np)){
param <- param[, myorder]
warning("'param' is being re-ordered according to 'abc.out'...", call.=F, immediate.=T)
}
}
## check if param has the right dimensions
if(np.orig != np){
stop("The number parameters supplied in \"param\" is different from that in \"x\".", call.=F)
}
## for (i in 1:np){
## if(transf[i] == "log"){
## if(min(param[,i]) <= 0){
## warning("Correcting out of bounds values for \"log\" transformed parameters.", call.=F, immediate.=T)
## x.tmp <- ifelse(param[,i] <= 0,max(param[,i]),param[,i])
## x.tmp.min <- min(x.tmp)
## param[,i] <- ifelse(param[,i] <= 0, x.tmp.min,param[,i])
## }
## param[,i] <- log(param[,i])
## if(min(rej[,i]) <= 0){
## warning("Correcting out of bounds values for \"log\" transformed parameters.", call.=F, immediate.=T)
## x.tmp <- ifelse(rej[,i] <= 0,max(rej[,i]),rej[,i])
## x.tmp.min <- min(x.tmp)
## rej[,i] <- ifelse(rej[,i] <= 0, x.tmp.min,rej[,i])
## }
## rej[,i] <- log(rej[,i])
## if(min(res[,i]) <= 0){
## warning("Correcting out of bounds values for \"log\" transformed parameters.", call.=F, immediate.=T)
## x.tmp <- ifelse(res[,i] <= 0,max(res[,i]),res[,i])
## x.tmp.min <- min(x.tmp)
## res[,i] <- ifelse(res[,i] <= 0, x.tmp.min,res[,i])
## }
## res[,i] <- log(res[,i])
## if(!is.null(true)){
## if(min(true[i]) <= 0){
## x.tmp <- ifelse(true[i] <= 0,max(true[i]),true[i])
## x.tmp.min <- min(x.tmp)
## true[,i] <- ifelse(true[i] <= 0, x.tmp.min,true[i])
## }
## true[i] <- log(true[i])
## }
## }
## else if(transf[i] == "logit"){
## if(min(param[,i]) <= logit.bounds[i,1]){
## x.tmp <- ifelse(param[,i] <= logit.bounds[i,1],max(param[,i]),param[,i])
## x.tmp.min <- min(x.tmp)
## param[,i] <- ifelse(param[,i] <= logit.bounds[i,1], x.tmp.min,param[,i])
## }
## if(max(param[,i]) >= logit.bounds[i,2]){
## x.tmp <- ifelse(param[,i] >= logit.bounds[i,2],min(param[,i]),param[,i])
## x.tmp.max <- max(x.tmp)
## param[,i] <- ifelse(param[,i] >= logit.bounds[i,2], x.tmp.max,param[,i])
## }
## param[,i] <- (param[,i]-logit.bounds[i,1])/(logit.bounds[i,2]-logit.bounds[i,1])
## param[,i] <- log(param[,i]/(1-param[,i]))
## if(min(rej[,i]) <= logit.bounds[i,1]){
## x.tmp <- ifelse(rej[,i] <= logit.bounds[i,1],max(rej[,i]),rej[,i])
## x.tmp.min <- min(x.tmp)
## rej[,i] <- ifelse(rej[,i] <= logit.bounds[i,1], x.tmp.min,rej[,i])
## }
## if(max(rej[,i]) >= logit.bounds[i,2]){
## x.tmp <- ifelse(rej[,i] >= logit.bounds[i,2],min(rej[,i]),rej[,i])
## x.tmp.max <- max(x.tmp)
## rej[,i] <- ifelse(rej[,i] >= logit.bounds[i,2], x.tmp.max,rej[,i])
## }
## rej[,i] <- (rej[,i]-logit.bounds[i,1])/(logit.bounds[i,2]-logit.bounds[i,1])
## rej[,i] <- log(rej[,i]/(1-rej[,i]))
## if(min(res[,i]) <= logit.bounds[i,1]){
## x.tmp <- ifelse(res[,i] <= logit.bounds[i,1],max(res[,i]),res[,i])
## x.tmp.min <- min(x.tmp)
## res[,i] <- ifelse(res[,i] <= logit.bounds[i,1], x.tmp.min,res[,i])
## }
## if(max(res[,i]) >= logit.bounds[i,2]){
## x.tmp <- ifelse(res[,i] >= logit.bounds[i,2],min(res[,i]),res[,i])
## x.tmp.max <- max(x.tmp)
## res[,i] <- ifelse(res[,i] >= logit.bounds[i,2], x.tmp.max,res[,i])
## }
## res[,i] <- (res[,i]-logit.bounds[i,1])/(logit.bounds[i,2]-logit.bounds[i,1])
## res[,i] <- log(res[,i]/(1-res[,i]))
## if(!is.null(true)){
## if(min(true[i]) <= logit.bounds[i,1]){
## x.tmp <- ifelse(true[i] <= logit.bounds[i,1],max(true[i]),true[i])
## x.tmp.min <- min(x.tmp)
## true[i] <- ifelse(true[i] <= logit.bounds[i,1], x.tmp.min,true[i])
## }
## if(max(true[i]) >= logit.bounds[i,2]){
## x.tmp <- ifelse(true[i] >= logit.bounds[i,2],min(true[i]),true[i])
## x.tmp.max <- max(x.tmp)
## true[i] <- ifelse(true[i] >= logit.bounds[i,2], x.tmp.max,true[i])
## }
## true[i] <- (true[i]-logit.bounds[i,1])/(logit.bounds[i,2]-logit.bounds[i,1])
## true[i] <- log(true[i]/(1-true[i]))
## }
## }
## } # end of parameter transformations
## devices
## ########
save.devAskNewPage <- devAskNewPage()
if(!is.null(file)){
file <- substitute(file)
if(!postscript) pdf(file = paste(file, "pdf", sep="."), onefile=onefile)
if(postscript) postscript(file = paste(file, "ps", sep="."), onefile=onefile)
}
else{
if (ask && 1 < np) {
devAskNewPage(TRUE)
}
}
## if param is too large, draw a random sample from it the size of
## which can be set by the user
mysample <- sample(1:nsim, subsample)
## plots
## #####
# prior, reg, rej, true
ltys <- c(3, 1, 1, 3)
lwds <- c(1, 2, 1, 2)
cols <- c("black", "red", "black", "black")
unadj <- TRUE
for(i in 1:np){
par(mfcol=c(2,2))
prior.d <- density(param[mysample,i])
post.d <- density(res[,i])
rej.d <- density(rej[,i])
myxlim <- range(c(post.d$x, rej.d$x, true))
myylim <- range(c(post.d$y, rej.d$y, prior.d$y))
par(cex = 1, cex.main = 1.2, cex.lab = 1.1, lwd = 2)
##if(transf[i] == "none")
myxlab <- parnames[i]
##else if(transf[i] == "log") myxlab <- paste("log(", parnames[i], ")", sep="")
##else if(transf[i] == "logit") myxlab <- paste("log(", parnames[i], "/(1-",parnames[i],"))", sep="")
## 1. prior
## ########
plot(prior.d, main = "", col=cols[1], lty = ltys[1], lwd=lwds[1], xlab=myxlab, ...)
title("Prior", sub = paste("N =", prior.d$n, " Bandwidth =", formatC(prior.d$bw)))
## 2. posterior
## ############
plot(post.d, col=cols[2], lty = ltys[2], lwd=lwds[2], xlim = myxlim, ylim = myylim, main = "", xlab=myxlab, ...)
lines(prior.d, col=cols[1], lty = ltys[1], lwd=lwds[1], ...)
lines(rej.d, col = cols[3], lty = ltys[3], lwd=lwds[3], ...)
if(!is.null(true)){
segments(x0 = true[i], x1 = true[i], y0 = myylim[1], y1 = myylim[2], col=cols[4], lty = ltys[4], lwd=lwds[4])
mtext(text="True value", side = 1, line=2, at=true[i])
}
title(paste("Posterior with \"", mymethod, "\"", sep=""), sub=paste("N =", post.d$n, " Bandwidth =", formatC(post.d$bw)))
mtext("\"rejection\" and prior as reference", side=3, line = 0.5)
## 3. distances
## ############
mypch <- 19
myylim <- range(alldist[mysample])#*c(1,1.2)
plot(param[mysample,i], alldist[mysample], col=cols[1],
xlab=myxlab, ylab="log Euclidean distance", ylim=myylim, pch=mypch, ...)
title("Euclidean distances")
mtext(paste("N(All / plotted) = ", numsim, "/", subsample, sep=" "), side = 3, line = .5)
points(param[myregion,i], alldist[myregion], col=cols[2], pch=mypch, ...)
mypar <- par()
if(!is.null(true)){
segments(x0 = true[i], x1 = true[i], y0 = myylim[1], y1 = myylim[2], col=cols[4], lty = ltys[4], lwd=lwds[4])
mtext(text="True value", side = 1, line=2, at=true[i])
}
## 4. residuals
## ############
if(mymethod=="loclinear") mymain <- "Residuals from lsfit()"
if(mymethod=="neuralnet") mymain <- "Residuals from nnet()"
if(mymethod=="ridge") mymain <- "Residuals from lm.ridge()"
qqnorm(residuals, pch=mypch, main=mymain, sub="Normal Q-Q plot", xlab="Theoretical quantiles", ylab="Residuals",...)
qqline(residuals)
} # np
par(mfcol=c(1,1))
if(!is.null(file)){
dev.off()
}
else devAskNewPage(save.devAskNewPage)
invisible()
} # end of plot.abc
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.