.packageName <- "SemSim"
`.getOnt` <-
function(gene, ontology, dropCodes) {
    allGO<-.id2go[[gene]]
	
    if(!is.null(dropCodes)) {
        evidence<-sapply(allGO, function(x) x$Evidence)
        drop<-evidence %in% dropCodes
        allGO<-allGO[!drop]
    }

    category<-sapply(allGO, function(x) x$Ontology)
    unlist(unique(names(allGO[category %in% ontology])))
}

`geneSim` <-
function(gene1, gene2, ont="MF", measure="Resnik", drop=NULL, db="all", multiple="max") { 
    wh_ont<-match.arg(ont, c("MF", "BP", "CC"))
    wh_measure<-match.arg(measure, c("Resnik", "Lin", "Jiang", "Rel"))
    wh_db<-match.arg(db, c("all", "human", "mouse", "rat", "yeast", "plant", "microbe"))
    wh_multiple<-match.arg(multiple, c("max", "avg", "rcmax"))
	
    GO1<-.getOnt(gene1, wh_ont, drop)
    GO2<-.getOnt(gene2, wh_ont, drop)

    sim<-mtermSim(GO1, GO2, wh_ont, wh_measure, wh_db, wh_multiple)
    return(list(Sim=sim, GO1=GO1, GO2=GO2))
}

`mgeneSim` <-
function(genes, ont="MF", measure="Resnik", drop=NULL, db="all", multiple="max") {
    wh_ont<-match.arg(ont, c("MF", "BP", "CC"))
    wh_measure<-match.arg(measure, c("Resnik", "Lin", "Jiang", "Rel"))
    wh_db<-match.arg(db, c("all", "human", "mouse", "rat", "yeast", "plant", "microbe"))
    wh_multiple<-match.arg(multiple, c("max", "avg", "rcmax"))

    geneNumber<-length(genes)
    simMatrix<-matrix(NA, nrow=geneNumber, ncol=geneNumber)
    colnames(simMatrix)<-genes
    rownames(simMatrix)<-genes 
    for(i in 1:geneNumber) {
        for(j in 1:i) {
            simMatrix[i, j]<-geneSim(genes[i], genes[j], wh_ont, wh_measure, drop, wh_db, wh_multiple)$Sim
	    if(i != j) simMatrix[j, i]<-simMatrix[i, j]
	}
    }

    removeNA<-apply(!is.na(simMatrix), 1, sum) > 0
    return(simMatrix[removeNA, removeNA])
}

`mtermSim` <-
function(GO1, GO2, ont, measure="Resnik", db="all", multiple="max") {
    wh_ont<-match.arg(ont, c("MF", "BP", "CC"))
    wh_measure<-match.arg(measure, c("Resnik", "Lin", "Jiang", "Rel"))
    wh_db<-match.arg(db, c("all", "human", "mouse", "rat", "yeast", "plant", "microbe"))
    wh_multiple<-match.arg(multiple, c("max", "avg", "rcmax"))

    size1<-length(GO1)
    size2<-length(GO2)
    if(size1 == 0 || size2 == 0) return(NA)

    allSim<-matrix(data=NA, nrow=size1, ncol=size2)
    for( i in 1:size1 ) 
        for(j in 1:size2)
		if( Ontology(get(GO1[i], GOTERM)) == wh_ont && Ontology(get(GO2[j], GOTERM)) == wh_ont )  
 	           allSim[i, j]<-termSim(GO1[i], GO2[j], wh_measure, wh_db)

    if(!sum(!is.na(allSim))) return(NA)

    if(wh_multiple == "rcmax") { 
        rowNN<-matrix(allSim[apply(!is.na(allSim), 1, sum) > 0, ], ncol=size2)
        colNN<-matrix(allSim[, apply(!is.na(allSim), 2, sum) > 0], nrow=size1)

        rowScore<-switch(wh_measure, 
            Jiang=mean(apply(rowNN, 1, min, na.rm=T)), mean(apply(rowNN, 1, max, na.rm=TRUE)) )
        colScore<-switch(wh_measure,
	    Jiang=mean(apply(colNN, 2, min, na.rm=TRUE)), mean(apply(colNN, 2, max, na.rm=TRUE)) )

 	result<-switch(wh_measure, Jiang=min(rowScore, colScore), max(rowScore, colScore))
    } else if(wh_multiple == "max") {
	result<-switch(wh_measure, Jiang=min(allSim, na.rm=TRUE), max(allSim, na.rm=TRUE))
    } else if(wh_multiple == "avg") {
	result<-mean(allSim, na.rm=TRUE)
    } 
		
    return(round(result, digits=3))
}

`termSim` <-
function(GOID1, GOID2, measure="Resnik", db="all") {
    go1<-get(GOID1, GOTERM)
    go2<-get(GOID2, GOTERM)
    wh_ont<-Ontology(go1)
    if(wh_ont != Ontology(go2)) 
        stop("GO terms should be in the same sub-ontology (BP, MF, or CC)!")	

    rootCount<-switch(wh_ont, 
        MF=.gocount["GO:0003674", db],
	BP=.gocount["GO:0008150", db],		
	CC=.gocount["GO:0005575", db] )

    p1<-.gocount[GOID1, db]/rootCount
    p2<-.gocount[GOID2, db]/rootCount
    if(is.na(p1) || is.na(p2)) return(NA)
    if((p1 == 0 || p2 == 0) && measure != 'Resnik') return(NA)

    dataenv<-get(paste("GO", wh_ont, "ANCESTOR", sep=""), mode="environment")
    ancestor1<-c(GOID1, get(GOID1, dataenv))
    ancestor2<-c(GOID2, get(GOID2, dataenv))
    commonAncestor<-intersect(ancestor1, ancestor2)

    pms<-min(.gocount[commonAncestor, db], na.rm=TRUE)/rootCount

    sim<-switch(measure,
        Resnik=-log(pms),
	Lin=2*log(pms)/(log(p1)+log(p2)),
	Jiang=2*log(pms)-log(p1)-log(p2), 
	Rel=(2*log(pms)/(log(p1)+log(p2)))*(1-pms) )	

    return(round(sim, digits=3))
}

.First.lib<-function(lib, pkg) {
    fullname<-paste("package", pkg, sep=":")
    myEnv<-as.environment(match(fullname, search()))

    data(GOCount, envir=myEnv)
    assign(".gocount", GOCount, envir=myEnv)
    assign(".id2go", as.list(GOENTREZID2GO), envir=myEnv)
}


