################################################################
## matrix-clustering.R
##
## This script takes as input a matrix comparison file (that can be
## generated by compare-matrices), performs hierarchical
## clustering.
##
## It returns the resulting tree in json format, which can be loaded
## by the d3 library for display purposes.

## Define the local directory for R librairies
dir.rsat <- Sys.getenv("RSAT")
if (dir.rsat == "") {
  stop(paste("The environment variable RSAT is not defined. Command: ", commandArgs()))
}

dir.rsat.rscripts <- file.path(dir.rsat, "R-scripts")
dir.rsat.rlib <- file.path(dir.rsat.rscripts, "Rpackages")


## Load required libraries
## List of packages to install
required.packages = c("Rcpp",
                      "RcppEigen",
                      "Rclusterpp",
                      "gplots")


## List of RSAT-specific packages to be compiled on the server
required.packages.rsat <- c("TFBMclust")
for (pkg in c(required.packages, required.packages.rsat)) {
  suppressPackageStartupMessages(library(pkg, warn.conflicts=FALSE, character.only = TRUE, lib.loc=c(dir.rsat.rlib, .libPaths())))
}


## Install the TFBM library if required
# dir.create(dir.rsat.rlib, recursive=TRUE,showWarnings=FALSE)
if(!require("TFBMclust", lib.loc=dir.rsat.rlib)){
  stop("The TFBM R library is not properly installed.")
}


## Load some libraries
source(file.path(dir.rsat, 'R-scripts/config.R'))
source(file.path(dir.rsat, 'R-scripts/cluster_motifs_lib.R'))

## Options
thresholds <<- list()

###########################################
## Read arguments from the command line.
##
## Arguments passed on the command line
## will over-write the default arguments
## specified above.
args <- commandArgs(trailingOnly=TRUE);
if (length(args >= 1)) {
  for(i in 1:length(args)){
    eval(parse(text=args[[i]]))
  }
  verbose(args, 3)
}

######################
## Check parameters
check.param()


#####################################
## Example for Debugging ############
#
# infile <- "/home/jcastro/Documents/JaimeCastro/PhD/matrix_clustering/results/matrix-clustering_results/peak-motifs_Oct4_testing_metrics/average_linkage/cor_0.5/peak-motifs_Oct4_hclust-average_cor_0.5_tables/pairwise_compa.tab"
# description.file <- "/home/jcastro/Documents/JaimeCastro/PhD/matrix_clustering/results/matrix-clustering_results/peak-motifs_Oct4_testing_metrics/average_linkage/cor_0.5/peak-motifs_Oct4_hclust-average_cor_0.5_tables/pairwise_compa_matrix_descriptions.tab"
# metric <- "Ncor"
# hclust.method <- "average"
# thresholds <- list(Ncor = 0.4, cor = 0.6, w = 5)


##############################################
## Read matrix comparison table + treatment
global.compare.matrices.table <<- read.csv(infile, sep="\t", comment.char=";")
names(global.compare.matrices.table)[1] <- sub("^X.", "", names(global.compare.matrices.table)[1])

#######################################
## Read description table +treatment
global.description.table <<- read.csv(description.file, sep="\t", comment.char=";")

## In reference to the names, order alphabetically the description table
global.description.table <- global.description.table[order(global.description.table$id),]
global.description.table$n <- 1:length(global.description.table$id)

matrix.labels <-  as.vector(global.description.table$label)
names(matrix.labels) <- as.vector(global.description.table$id)

## Substitute the "_" for "." in the column names
names(global.description.table) <- gsub("X.n", "n", names(global.description.table))
names(global.description.table) <- gsub("_", ".", names(global.description.table))

## Check that the compare-matrices table contains the required metric column
if (length(grep(pattern=metric, names(global.compare.matrices.table))) < 1) {
  stop(paste(sep="", "Input file (", infile, ") does not contain the metric column (", metric, ")."))
}

## Convert distance table into a distance matrix, required by hclust
distances.objects <- build.distance.matrix(global.compare.matrices.table, metric = metric)
dist.table <- distances.objects$table
dist.matrix <- distances.objects$matrix

## Export the distance table
write.table(dist.table, file=distance.table, quote=FALSE, row.names=TRUE, col.names=NA, sep="\t")

## Read the range table

ranges <<- read.csv(range.table, sep="\t", comment.char=";", header = FALSE)
ranges <<- ranges[1:2,]

tree <<- hclust.motifs(dist.matrix, hclust.method=hclust.method)

metric.1.values <- seq(ranges[1,2], ranges[1,3], by = ranges[1,4])
metric.2.values <- seq(ranges[2,2], ranges[2,3], by = ranges[2,4])

nb.clusters.matrix <- lapply(metric.1.values, function(m1){
  sapply(metric.2.values, function(m2){
    th <- list(Ncor =  m1, cor = m2)
    names(th) <- c(as.character(ranges[1,1]), as.character(ranges[2,1]))

    ###########################################################
    ## Initially align all the motifs and search the cluster
    ## After each cluster will be aligned separately
    alignment <- align.motifs(tree,
                              global.description.table,
                              global.compare.matrices.table,
                              thresholds = th,
                              method = hclust.method,
                              metric = metric,
                              nodes.attributes=TRUE,
                              intermediate.alignments=FALSE)
    alignment.list <- alignment$motifs.alignment
    alignment.attributes <- alignment$node.attributes

    ## Reset the labels
    tree$labels <- sapply(tree$labels, function(x){
      paste(alignment.list[[x]][["consensus_d"]], alignment.list[[x]][["name"]], sep="   " )
    })

    #############################################
    ## Define the clusters: Bottom-up approach
    ## and get their motif IDs
    clusters <<- find.clusters(alignment.attributes, tree)
    length(clusters)
  })
})


nb.clusters.matrix <- t(as.data.frame(nb.clusters.matrix))
rownames(nb.clusters.matrix) <- as.character(metric.1.values)
colnames(nb.clusters.matrix) <- as.character(metric.2.values)

grad <- colorRampPalette(c("#66CCFF","blue"))(100)


for (plot.format in c("pdf", "jpg")) {
  heatmap.file <- paste(sep="", out.prefix, "_figures/heatmap_nb_clusters.", plot.format)
  w <- 6
  h <- w + 0.75
  resol <- 72 ## Screen resolution
  verbose(paste("drawing heatmap", heatmap.file), 2)
  if (plot.format == "pdf") {
    pdf(file=heatmap.file, width=w, height=h)
  } else if (plot.format == "jpg") {
    jpeg(filename=heatmap.file, width=w, height=h, units="in", res=500)
  }

  heatmap.2(nb.clusters.matrix,
            dendrogram = "none",
            Rowv = FALSE,
            Colv = FALSE,
            trace = "none",
            symm=TRUE,
            col = grad,

            main = "Nb of clusters",
            xlab = as.character(ranges[1,1]),
            ylab = as.character(ranges[2,1]),

            cellnote=nb.clusters.matrix,
            notecol="black",

            key = TRUE,
            keysize = 1.5,
            key.xlab = "Nb clusters",
            key.ylab = "",
            key.title = "Color key",
            density.info = "none"
  )
  dev.off()
}