.packageName <- "SemSim"
`.getOnt` <-
function(gene, ontology, dropCodes) {
    allGO<-GOENTREZID2GO[[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])))
}

`.getSim` <-
function(GOID1, GOID2, ont, measure, db) { 
    rootCount<-switch(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(p1 == 0 || p2 == 0) return(NA)

    dataenv<-get(paste("GO", 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))
}






`geneSim` <-
function(gene1, gene2, ont="MF", measure="Resnik", drop="IEA", db="UniProt", 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("UniProt", "mouse", "rat", "plant", "yeast", "worm", "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="IEA", db="UniProt", 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("UniProt", "mouse", "rat", "plant", "yeast", "worm", "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="UniProt", 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("UniProt", "human", "mouse", "rat", "plant", "yeast", "worm", "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) {
        ont1<-.gocount[GO1[i], "Ont"]
	if(!is.na(ont1) && ont1 == wh_ont) { 
	    for(j in 1:size2) {
	        ont2<-.gocount[GO2[j], "Ont"]
	        if(!is.na(ont2) && ont2 == wh_ont ) {  
 	            allSim[i, j]<-.getSim(GO1[i], GO2[j], wh_ont, 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="UniProt") {
    if(is.na(.gocount[GOID1, db]) || is.na(.gocount[GOID2, db]))
	stop("GO term does not exist in the current package!")
  
    wh_ont<-as.character(.gocount[GOID1, "Ont"])
    if(wh_ont != as.character(.gocount[GOID2, "Ont"])) 
        stop("GO terms should be in the same sub-ontology (BP, MF, or CC)!")	
    .getSim(GOID1, GOID2, wh_ont, measure, db)
}



.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)
}


