.packageName <- "LBE"
`LBE` <-
function (pval, a = NA, l = 0.05, ci.level = 0.95, qvalues = TRUE,
    plot.type = "main", FDR.level = 0.05, n.significant = NA)
{
    if (min(pval) < 0 | max(pval) > 1) {
        print("ERROR: p-values not in valid range.")
        return(0)
    }
    else {
        m <- length(pval)
        FDR <- NA
        if (is.na(a) == FALSE & a < 1) {
            a <- NA
            sdbound <- sqrt(1/(3 * m))
            pi0 <- min(1, mean(pval) * 2)
            icpi0 <- c(0, pi0 - qnorm((1 - ci.level), 0, sdbound))
        }
        else {
            if (is.na(a)) {
                a <- LBEa(m,l,fig=FALSE)
            }
            sdbound <- sqrt((1/(gamma(a + 1))^2) * ((gamma(2 *
                a + 1) - (gamma(a + 1))^2)/m))
            pi0 <- min(1, mean((-log(1 - pval))^a)/gamma(a +
                1))
            icpi0 <- c(0, min(1, pi0 - qnorm((1 - ci.level),
                0, sdbound)))
        }
        mat <- NA
        if (qvalues == TRUE) {
            qval <- rep(NA, m)
            sort.pval <- sort(pval)
            order.pval <- order(pval)
            rank.pval <- rank(pval)
            qval[m] <- (pi0 * m * sort.pval[m])/m
            for (i in 1:(m - 1)) {
                qval[m - i] <- min((pi0 * m * sort.pval[m - i])/(m -
                  i), qval[m - i + 1])
            }
            mat <- cbind(rank.pval, qval, sort.pval)
           
            if (is.na(n.significant) == FALSE) {
                FDR.level <- mat[n.significant, 2]
                FDR <- FDR.level
            }
            else {
                n.significant <- length(mat[mat[, 2] <= FDR.level,
                  2])
                FDR <- max(mat[mat[, 2] <= FDR.level, 2],0)
            }
        }
    
        if (sdbound>0.5){
            print(paste("WARNING: l = ",sdbound,". A smaller value is recommended for a (or l).",sep=""))
        }
        
        if (qvalues == TRUE) {
          significant<-(qval[rank.pval] <= FDR.level)
          r <- list(call = match.call(), FDR = FDR, pi0 = pi0, pi0.ci = icpi0, ci.level = ci.level, a = a, l = sdbound, qvalues = qval[rank.pval], pvalues = pval, significant = significant, n.significant = length(significant[significant==TRUE]))
          class(r) <- "LBE"
          if(plot.type!="none"&qvalues==TRUE){
            LBEplot(r,plot.type=plot.type)
          }
          invisible(r)
        }
        else {
          r <- list(call = match.call(), FDR = NA, pi0 = pi0, pi0.ci = icpi0, ci.level = ci.level, a = a, l = sdbound, qvalues = NA, pvalues = pvalues, significant = NA, n.significant = NA)
          class(r) <- "LBE"
          invisible(r)
        }
    }
}

`LBEa` <-
function(m,l=0.05,fig=TRUE,a.rng=NA){
  asearch <- function(a) {
    abs(sqrt(1/(gamma(a + 1))^2 * ((gamma(2 * a + 1) - (gamma(a + 1))^2)/m)) - l)
  }
  aopt <- max(1, optimize(asearch, c(0.3, 25))$minimum)
  if (fig){
    par(mfrow=c(1,1))
    if (is.na(a.rng[1])){
      asearch2 <- function(a) {
        abs(sqrt(1/(gamma(a + 1))^2 * ((gamma(2 * a + 1) - (gamma(a + 1))^2)/m)) - 0.5)
      }
      a.rng=c(1,max(1, optimize(asearch2, c(0.3, 30))$minimum))
    }
    a2<-seq(a.rng[1],a.rng[2],0.01)
    sd <- sqrt(1/(gamma(a2 + 1))^2 * ((gamma(2 * a2 + 1) - (gamma(a2 + 1))^2)/m))
    plot(a2,sd,type="l",lwd=3,col=4,ylab="standard deviation",xlab="a")
    abline(h=l,col="orange",lwd=3)
    abline(v=aopt,lty=2,lwd=2)
    legend(aopt,l,paste("a =",round(aopt,5)),bty="n",xjust=0,yjust=1,cex=1,col="white")
  }
  return(aopt)
}

`LBEplot` <-
function (LBEobj, rng = c(0, 0.1), plot.type = c("multiple","main"),legend=TRUE){
    if (class(LBEobj)=="LBE" ){    
      if (is.na(LBEobj$qvalues[1])) {
        print("ERROR: Estimated q-values not found. Apply the function LBE with the option: qvalues=TRUE.")
      }     
      else {
        q2 <- LBEobj$qval[order(LBEobj$pval)]
        if (min(q2) > rng[2]) {
            rng <- c(min(q2), quantile(q2, 0.1))
        }
        p2 <- LBEobj$pval[order(LBEobj$pval)]
        m <- length(q2)
        if (plot.type[1] == "main"){
          nf <- layout(cbind(rep(0, 12), matrix(c(rep(1,81), rep(2, 27)), ncol = 9, byrow = TRUE),rep(0, 12)), respect = FALSE)
          plot(p2, q2, xlab = "p-values", ylab = "q-values",xlim = c(0, 1), ylim = c(0, 1), col = "blue",pch = 16)
          par(new = TRUE)
          plot(p2[q2 <= LBEobj$FDR], q2[q2 <= LBEobj$FDR], xlab = "p-values", ylab = "q-values",xlim = c(0, 1), ylim = c(0, 1), col = "orange", pch = 16)
          if (legend == TRUE) {
            n.select<-length(LBEobj$significant[LBEobj$significant==TRUE])
            legend(1, 0, c(paste("FDR =", round(LBEobj$FDR, digits = 5)), paste(m - n.select, "non rejected null hypotheses"), paste(n.select, "rejected null hypotheses")), pch = rep(16, 3), col = c("white", "blue", "orange"), xjust = 1, yjust = 0, cex = 1.5, bty = "n")
          }
          hist(p2, xlim = c(0, 1), nclass = 100, ann = FALSE, xlab = "p-values", xaxt = "n", yaxt = "n", main = "")
        }
        if (plot.type[1] == "multiple"){
          par(mfrow=c(2,2))
          hist(p2,xlab = "p-value", ylab = "frequency",main="",col="blue")
          plot(p2[q2 >= rng[1] & q2 <= rng[2]], q2[q2 >= rng[1] & q2 <=
           rng[2]], type = "l", xlab = "p-value", ylab = "q-value",col="blue",lwd=2)
          plot(q2[q2 >= rng[1] & q2 <= rng[2]], (1 + sum(q2 < rng[1])):sum(q2 <=
            rng[2]), type = "l", xlab = "q-value cut-off", ylab = "significant tests",col="blue",lwd=2)
          plot((1 + sum(q2 < rng[1])):sum(q2 <= rng[2]), q2[q2 >= rng[1] &
            q2 <= rng[2]] * (1 + sum(q2 < rng[1])):sum(q2 <= rng[2]),
            type = "l", xlab = "significant tests", ylab = "expected false positives",col="blue",lwd=2)
        } 
      }
    }
    else {
            print("ERROR: An LBE object is required as input.")
    }            
}

`LBEsummary` <-
function (LBEobj, cuts = c(1e-04, 0.001, 0.01, 0.025, 0.05, 0.1,1), digits = getOption("digits"), ...){
    cat("\nCall:\n", deparse(LBEobj$call), "\n\n", sep = "")
    cat("pi0:", format(LBEobj$pi0, digits = digits), "\n", sep = "\t")
    cat(paste("Confidence Interval (level=",LBEobj$ci.level,"): [",format(LBEobj$pi0.ci[1], digits = digits),",",format(LBEobj$pi0.ci[2],digits=digits),"]",sep=""),"\n")
    cat("\n")
    cat("Cumulative number of significant calls:\n")
    cat("\n")
    counts<-sapply(cuts, function(x) c("p-value" = sum(LBEobj$pvalues<x), "q-value" = sum(LBEobj$qvalues < x)))
    colnames(counts)<-paste("<", cuts, sep = "")
    print(counts)
    cat("\n")
    invisible(LBEobj)
}

`LBEwrite` <-
function (LBEobj, filename = "LBE-results.txt"){
    cat(c("pi0:", LBEobj$pi0, "\n\n"), file = filename, append = FALSE)
    cat(c("ic.pi0:", LBEobj$ci.pi0, "\n\n"), file = filename, append = FALSE)   
    cat(c("FDR:", LBEobj$FDR, "\n\n"), file = filename, append = TRUE)
    cat(c("p-value q-value significant", "\n"), file = filename, append = TRUE)
    write(t(cbind(LBEobj$pval, LBEobj$qval, LBEobj$significant)), file = filename, ncolumns=3, sep="\t", append = TRUE)
}

