#!/usr/bin/env Rscript

library(lattice)  # for levelplot

cleardiag = TRUE  # remove diagnoal?
printnum = FALSE  # print cell values?
scale = 3.5       # font scale
printtid = TRUE   # print thread IDs?

comm_het = function(frame) {
	nt = ncol(frame)
	if (nt<4)
		return(0)
	frame = frame / max(frame, na.rm=T) * 100

	for (i in 1:ncol(frame))
		frame[i,i] = NA

	v = 0
	for (i in 1:(nt-2)) v = v + var(frame[i:nt,i], na.rm=T)
	val1 = v / nt

	v = 0
	for (i in 3:nt) v = v + var(frame[1:i,i], na.rm=T)
	val2 = v / nt

	return(min(val1,val2))
}

comm_avg = function(frame)
	return(sum(as.numeric(unlist(frame)))/length(frame)/length(frame))

lambda = function(l) {return((max(l)/mean(l)-1)*100)}

myPanel = function(x, y, z, ...) {
	panel.levelplot(x,y,z,...)
	if (printnum) {
		panel.abline(h=c(1:(nt-1))+0.5, v=c(1:(nt-1))+0.5)
		panel.text(x, y, round(z,1),cex=scale)
	}
}

rsig = function(x, dig=3) {formatC(as.character(ifelse(x<1, round(x, dig), signif(x,dig+1))), width=-(dig+2), format="s")}

args = commandArgs(trailingOnly=TRUE)

if (length(args) < 1)
	stop("Usage: mkCommMatrix.R <CommPattern.csv>...\n")

maxlen = max(nchar(args))

for (filename in args) {

	if (grepl(".csv", filename)) {
		outfilename = gsub(".csv", ".pdf", filename)
		if (filename == outfilename)
			outfilename = paste(filename, ".pdf", sep="")

		csv = as.data.frame(read.csv(filename, header=FALSE))
	} else if (grepl(".dat", filename)) { # .dat files generated by eztrace
		outfilename = gsub(".dat", ".pdf", filename)
		outcsvname = gsub(".dat", ".csv", filename)
		if (filename == outfilename)
			outfilename = paste(filename, ".pdf", sep="")

		csv = data.matrix(read.table(filename, header=FALSE))
		csv = csv + t(csv) # make csv symmetric
		csv = apply(csv, 2, rev) # reverse csv
		csv = data.frame(csv)
		write.table(csv, file=outcsvname, sep=",", col.names=F, row.names=F)
	}

	nt = ncol(csv)
	if (ncol(csv) != nrow(csv)) {
		cat(filename, "- input matrix is not square, skipping\n")
		next
	}

	mat = data.matrix(csv)
	mat = mat[nrow(mat):1,] # reverse matrix

	private = 0
	comm = 0

	for (i in 1:nt)
		for (j in 1:nt)
			if (i!=j) comm = comm + mat[i,j]
			else private = private + mat[i,j]


	if (cleardiag)
		for (i in 1:nt)
			mat[i,i] = 0

	het = comm_het(mat)
	cavg = comm_avg(mat)

	if (nt<=8)
		every=1
	else if (nt<=32)
		every=5
	else if (nt<=64)
		every=10
	else if (nt<=128)
		every=25
	else if (nt<=256)
		every=50
	else if (nt<1000)
		every=100
	else {
		every=200
		scale=3
	}

	if (printtid)
		optlist=list(cex=scale,limits=range(-0.5:nt+1),labels=seq(0,nt-1,every),tck=c(1,0),at=seq(1,nt,every))
	else
		optlist=list(cex=scale,limits=range(-0.5:nt+1),labels=NULL,tck=c(0,0),at=seq(1,nt,every))


	# generate comm matrix
	pdf(outfilename, family="NimbusSan")
	print(levelplot(mat, panel=myPanel, col.regions=grey(seq(1,0,-0.01)), colorkey=F, xlab=NULL, ylab=NULL, scales=list(x=optlist, y=optlist)))
	garbage = dev.off()

	embedFonts(outfilename)
	system(paste("pdfcrop ", outfilename, outfilename, "> /dev/null"))


	# remove lower part of the matrix
	for (i in 1:nt) {
		if (i<nt/2)
			for (j in 1:i)
				mat[i,j] = 0
		else
			for (j in i:nt)
				mat[i,j] = 0
	}

	mat = matrix(rowSums(mat))
	mat = mat/max(mat) * 100
	l = lambda(mat)
	# outfilename = gsub(".pdf", ".load.pdf", outfilename)

	# # generate comm balance
	# pdf(outfilename, family="NimbusSan")
	# print(levelplot(mat, panel=myPanel, col.regions=grey(seq(1,0,-0.01)), colorkey=F, xlab=NULL, ylab=NULL, scales=list(x=optlist,y=list(labels=NULL,tck=c(0,0)))))
	# garbage = dev.off()

	# embedFonts(outfilename)

	# system(paste("pdfcrop ", outfilename, outfilename, "> /dev/null"))

	cat(formatC(outfilename, width=-maxlen), "het:", rsig(het), "avg:", rsig(cavg), "ratio:", (comm/private *100), "%", "imbal:", rsig(l), "\n")
}
