CIplot_uni <- function(data, group=NA, group.order=NA, cols=rainbow(ncol(data)), names=colnames(data), main="", ylab="", 
                       ylim=c(NA,NA), cex=1, pch=rep(21, ncol(data)), fg=rainbow(ncol(data)), bg="white", 
                       shade=F, alpha=0.2, horizon=F, nperm=1000, conf=0.5, CONF=0.95, thin=1, end=1, add=FALSE) {

# function to plot confidence plots for univariate data, multiple samples

# data: matrix with data in columns (if not a matrix, then assumed to have grouping variable group)
# group: grouping variable if data not a matrix
# group.order: group names in order preferred in plot
# cols: colours of plots for respective samples
# names: labels for variables, by default the column names of data
# main: title for figure
# ylab: y-axis label
# ylim: user-defined y limits, otherwise computed by function
# cex: expansion factor for symbols
# pch: alternative set of symbols for samples, otherwise small filled circles (pch=21)
# fg and bg: colours for symbols and (possible) fill colour
# shade: set to TRUE if you want shading
# alpha: shading factor, by default=0.2 (should be between 0 and 1)
# horizon: T if horizontal gray dashed lines required at "nice" y-values, not implemented yet
# nperm: number of bootstrap replicates
# conf: confidence level for box, default 50% (0.5)
# CONF: confidence level for whiskers, default 95% (0.95)
# thin: by default=1, adjust for fatter or thinner boxes
# end: by default=1, adjust for wider or narrower ends of whiskers
# add: if bars to be added to existing plot, default=FALSE

  if(!is.matrix(data)) {
    foo <- data
    if(is.na(group[1])) stop("data is vector but no grouping variable")
    ngp <- length(table(group))
    data <- matrix(NA, nrow=max(table(group)), ncol=ngp)
    gps <- sort(unique(group))
    if(!is.na(group.order[1])) gps <- group.order
    for(igp in 1:ngp) {
      n <- sum(group==gps[igp]) 
      data[1:n,igp] <- foo[group==gps[igp]] 
    }
    colnames(data) <- gps
    names <- colnames(data)
  }

  xrange <- c(0, ncol(data)+1)
  if(is.na(ylim[1])) {
    yrange <- max(data, na.rm=T)-min(data, na.rm=T)
    ylim <- c(min(data, na.rm=T), max(data, na.rm=T)+0.05*yrange)
  }

# dummy mean function for boot function

  mean.fun <- function(dat, idx) mean(dat[idx], na.rm = TRUE)

# plot area

if(!add)  plot(0, 0, type="n", xlim=xrange, ylim=ylim, xaxt="n", yaxt="n", bty="n", xlab="", 
       main=main, ylab=ylab)
if(!add)  axis(2)
if(!add)  axis(1, at=c(1:ncol(data)), labels=names, tick=F, font=2, col=cols)
  
# bootstrapping, mean and CI for each sample
  set.seed(1234567)
  for(j in 1:ncol(data)) {
    foo.boot  <- boot(data[,j], statistic=mean.fun, R=nperm)
    foo.mean  <- mean(data[,j], na.rm=T)
    foo.CI    <- boot.ci(foo.boot, type="bca", conf=CONF)$bca[4:5]
    foo.CI50  <- boot.ci(foo.boot, type="bca", conf=conf)$bca[4:5]
    foo.lower <- foo.mean - foo.CI[1]
    foo.upper <- foo.CI[2] - foo.mean
    foo.box   <- foo.CI50
    width <- 0.15*thin
    segments(j, foo.CI[1], j, foo.CI[2], col=cols[j])
    width <- 0.07*end
    segments(j-width, foo.CI[1], j+width, foo.CI[1], col=cols[j], lwd=1.5, lend=2)
    segments(j-width, foo.CI[2], j+width, foo.CI[2], col=cols[j], lwd=1.5, lend=2)
    width <- 0.15*thin
    if (!shade) rect(j-width, foo.box[1], j+width, foo.box[2], col="white", lwd=1.5)
    if(shade) {
      cols.shade <- adjustcolor(cols, alpha.f=alpha)
      rect(j-width, foo.box[1], j+width, foo.box[2], col="white", lwd=1.5, border="white")
      rect(j-width, foo.box[1], j+width, foo.box[2], col=cols.shade[j], lwd=1.5, border=cols[j])
    }
    points(j, foo.mean, pch=pch, bg=bg, fg=fg[j], cex=cex, col=cols[j])    
  }
}
