astream.annotate <-
function(ftlist, results, range = 1e-2, mode="+", location = c(), nfg_min = 0, output = ""){

cat("FORMATTING AND EXPORTING RESULTS:\n")
cat(" - Positive mode selected\n")
info_ad <- adduct.list(mode)
if (mode=="+") ref <- info_ad$masses[info_ad$labels=="[M+H]"]
if (mode=="-") ref <- info_ad$masses[info_ad$labels=="[M-H]"]
if (!is.factor(ftlist$class$class)) ftlist$class$class <- factor(ftlist$class$class)
cat(" - Computing P-Values for intensity differences between groups\n")
pvals <- compute.count.stats(ftlist)
data(hmdb,package="AStream")
cat(" - HMDB metabolites loaded (n=",nrow(hmdb),")\n",sep="")
if (length(location)>0){
  index <- c()
  for (i in location) index <- c(index,grep(i,hmdb$biofluid,ignore.case=T))
  for (i in location) index <- c(index,grep(i,hmdb$tissue,ignore.case=T))
  index <- sort(unique(index))
  hmdb <- hmdb[index,]
  cat(" - Filtering metabolites by biofluid/tissue location: n=",nrow(hmdb)," after filtering\n")
}
cn    <- c("id","MZ","MassSubmitted","RT","FoldChange","N1","N2","P-value","Metlin","REF.NFG","REF.13C#1-isotope","REF.13C#2-isotope","REF.Adducts","NOTREF.NFG","NOTREF.LABELS")
data  <- matrix(NA,nrow=0,ncol=length(cn))
colnames(data) <- cn
ij  <- setdiff(1:length(ftlist$class$class),ftlist$outliers) #not ouliers
a1 <- which(ftlist$class$class[ij] == levels(ftlist$class$class)[1]) #group 1
a2 <- which(ftlist$class$class[ij] == levels(ftlist$class$class)[2]) #group 2
ftlist$labels <- colnames(results)[6:length(colnames(results))] #adduct labels
nn <- c()
cat(" - Populating results data matrix...\n")
for (i in 1:nrow(ftlist$data)){
  # OTHERS
  Metlin <- paste("http://metlin.scripps.edu/metabo_list.php?mass_min=",
                  round(ftlist$mz[i] - range - ref, 4), "&mass_max=",
                  round(ftlist$mz[i] + range - ref, 4), sep="")
  fc <- round(mean(ftlist$data[i,a1])/mean(ftlist$data[i,a2]),2)
  N1 <- length(which(ftlist$data[i,a1]!=0))
  N2 <- length(which(ftlist$data[i,a2]!=0))
  nfg <- 0
  # [M+H] label (isotopes)
  j   <- which((ftlist$isotopes[,1]==i)&(ftlist$isotopes[,2]>0))
  label13C1 <- "NA"
  label13C2 <- "NA"
  if (length(j)>0){
    if (ftlist$isotopes[j,2]>0){
      nfg <- nfg + 1
      rtdiff <- ftlist$rt[ftlist$isotopes[j,2]]-ftlist$rt[i]
      mzdev  <- abs(abs(ftlist$mz[ftlist$isotopes[j,2]]-ftlist$mz[i])-1.00335)
      k <- which(((ftlist$feature.set[,1]==i)&(ftlist$feature.set[,2]==ftlist$isotopes[j,2]))|((ftlist$feature.set[,2]==i)&(ftlist$feature.set[,1]==ftlist$isotopes[j,2])))
      corr   <- ftlist$feature.set[k,3]
      label13C1 <- sprintf("id=%d;rtdiff=%1.2e;mzdev=%1.2e;C=%1.2f",ftlist$isotopes[j,2],rtdiff,mzdev,corr)
    }  
  }
  j   <- which((ftlist$isotopes[,1]==i)&(ftlist$isotopes[,3]>0))
  if (length(j)>0){
    if (ftlist$isotopes[j,3]>0){
      nfg <- nfg + 1
      rtdiff <- ftlist$rt[ftlist$isotopes[j,3]]-ftlist$rt[i]
      mzdev  <- abs(abs(ftlist$mz[ftlist$isotopes[j,3]]-ftlist$mz[i])-2.00670)
      k <- which(((ftlist$feature.set[,1]==i)&(ftlist$feature.set[,2]==ftlist$isotopes[j,3]))|((ftlist$feature.set[,2]==i)&(ftlist$feature.set[,1]==ftlist$isotopes[j,3])))
      corr   <- ftlist$feature.set[k,3]
      label13C2 <- sprintf("id=%d;rtdiff=%1.1e;mzdev=%1.1e;C=%1.2f",ftlist$isotopes[j,3],rtdiff,mzdev,corr)
    }  
  } 
  # [M+H] label (adducts)
  j   <- which(results[,1]==i)
  if (length(j)>0){
    temp<- results[j,6:ncol(results)]
    if (any(temp>0)){
      k <- which(temp>0)
      for (ik in 1:length(k)){
        nfg    <- nfg + 1
        adduct <- names(temp[k[ik]])
        rtdiff <- ftlist$rt[temp[k[ik]]]-ftlist$rt[i]
        mzdev  <- abs(abs(ftlist$mz[temp[k[ik]]]-ftlist$mz[i]-(info_ad$masses[which(info_ad$labels==adduct)]-ref)))
        kk <- which(((ftlist$feature.set[,1]==i)&(ftlist$feature.set[,2]==temp[k[ik]]))|((ftlist$feature.set[,2]==i)&(ftlist$feature.set[,1]==temp[k[ik]])))
        corr   <- ftlist$feature.set[kk,3]
        if (ik==1) labeladduct <- sprintf("%s:id=%d;rtdiff=%1.1e;mzdev=%1.1e;C=%1.2f",adduct,temp[k[ik]],rtdiff,mzdev,corr)
        if (ik> 1) labeladduct <- sprintf("%s %s:id=%d;rtdiff=%1.1e;mzdev=%1.1e;C=%1.2f",labeladduct,adduct,temp[k[ik]],rtdiff,mzdev,corr)
      }
    } else {
      labeladduct <- "NA"
    }
  } else {
    labeladduct <- "NA"
  }
  t1 <- c(i,round(ftlist$mz[i],5),round(ftlist$mz[i]-ref,5),round(ftlist$rt[i],2),fc,N1,N2,sprintf("%1.2e",pvals[i]),Metlin,nfg,label13C1,label13C2,labeladduct)
  nfg <- 0
  # other labels
  j   <- which(ftlist$isotopes[,2]==i)
  labelothers <- ""
  if (length(j)>0){
    for (k in 1:length(j)){
      nfg <- nfg + 1
      rtdiff <- abs(ftlist$rt[ftlist$isotopes[j[k],1]]-ftlist$rt[i])
      mzdev  <- abs(abs(ftlist$mz[ftlist$isotopes[j[k],1]]-ftlist$mz[i])-1.00335)
      kk <- which(((ftlist$feature.set[,1]==i)&(ftlist$feature.set[,2]==ftlist$isotopes[j[k],1]))|((ftlist$feature.set[,2]==i)&(ftlist$feature.set[,1]==ftlist$isotopes[j[k],1])))
      corr   <- ftlist$feature.set[kk,3]
      labelothers <- sprintf("%s [13C#1]id=%d;rtdiff=%1.2e;mzdev=%1.2e;C=%1.2f",labelothers,ftlist$isotopes[j[k],1],rtdiff,mzdev,corr)
    }
  }
  j   <- which(ftlist$isotopes[,3]==i)
  if (length(j)>0){
    for (k in 1:length(j)){
      nfg <- nfg + 1
      rtdiff <- abs(ftlist$rt[ftlist$isotopes[j[k],1]]-ftlist$rt[i])
      mzdev  <- abs(abs(ftlist$mz[ftlist$isotopes[j[k],1]]-ftlist$mz[i])-1.00335)
      kk <- which(((ftlist$feature.set[,1]==i)&(ftlist$feature.set[,2]==ftlist$isotopes[j[k],1]))|((ftlist$feature.set[,2]==i)&(ftlist$feature.set[,1]==ftlist$isotopes[j[k],1])))
      corr   <- ftlist$feature.set[kk,3]
      labelothers <- sprintf("%s [13C#2]id=%d;rtdiff=%1.2e;mzdev=%1.2e;C=%1.2f",labelothers,ftlist$isotopes[j[k],1],rtdiff,mzdev,corr)
    }
  }
  for (iadduct in 6:ncol(results)){
    j   <- which(results[,iadduct]==i)
    if (length(j)>0){
      temp<- results[j,1]
      for (icand in 1:length(temp)){
        nfg    <- nfg + 1
        adduct <- colnames(results)[iadduct]
        rtdiff <- abs(ftlist$rt[temp[icand]]-ftlist$rt[i])
        mzdev  <- abs(abs(ftlist$mz[i]-ftlist$mz[temp[icand]]-(info_ad$masses[which(info_ad$labels==adduct)]-ref)))
        kk <- which(((ftlist$feature.set[,1]==i)&(ftlist$feature.set[,2]==temp[icand]))|((ftlist$feature.set[,2]==i)&(ftlist$feature.set[,1]==temp[icand])))
        corr   <- ftlist$feature.set[kk,3]
        labelothers <- sprintf("%s %sid=%d;rtdiff=%1.2e;mzdev=%1.2e;C=%1.2f",labelothers,adduct,temp[icand],rtdiff,mzdev,corr)
      }
    }
  }
  t1 <- c(t1,nfg,labelothers)
  nn <- c(nn,length(t1))
  data <- rbind(data,t1)
}
id <- matrix(NA,nrow=nrow(data),ncol=2)
for (i in 1:nrow(data)){
  j       <- which(abs(ftlist$mz[i]  - ref - hmdb[,2]) < range)
  id[i,1] <- length(j)
  if (length(j)>0){
    mzdiff  <- (ftlist$mz[i]  - ref - hmdb[j,2])
    jj <- sort(abs(mzdiff),index.return=T)
    id[i,2] <- paste(hmdb[j[jj$ix],1],rep(":",length(j)),sprintf("%1.1e",jj$x),rep("/",length(j)),hmdb[j[jj$ix],3],collapse=" ",sep="")
  }
}
colnames(id) <- c("HMDB.N","HMDB.MATCHS")
cat(" - Resulting number of features: ",nrow(data),"\n",sep="")
data <- cbind(data,id)
if (nfg_min>0){
  cat(" - Filtering features with less than ",nfg_min," related (isotope/adduct) features\n",sep="")
  data <- data[as.numeric(as.character(data[,10]))>=nfg_min,]
  cat(" - Final number of features: ",nrow(data),"\n",sep="")
}
if (nchar(output)>0){
  cat(" - Exporting results to: ",output,"\n",sep="")
  write.table(data,output,quote=F,sep="\t",row.names=F)
}
return(data)
}
