isotope.search <-
function(ftlist, mz.tol = 3e-3, min_samples = 5, max_ratio = 0.8, n_std = 5, fplot = TRUE){

cat("ISOTOPE ANALYSIS:\n", sep = "")
cat("\t- M/Z tolerance:\t",mz.tol,"u\n", sep = "")
Iso <- c(13.00335 - 12, 2*(13.00335 - 12))
Lab <- c("13C#1/12C-isotope","13C#2/12C-isotope")
pl  <- c("(a) ","(b) ")
cat("\t- C12-isotope m/z:\t",12,"u\n", sep = "")
cat("\t- C13#1-isotope m/z:\t",12+Iso[1],"u\n", sep = "")
cat("\t- C13#2-isotope m/z:\t",12+Iso[2],"u\n", sep = "")

isotopes <- matrix(0,dim(ftlist$feature.set)[1],2*(length(Iso)+1))
annot_isotopes <- matrix(NA,dim(ftlist$feature.set)[1],2)
for (n in 1:length(Iso)){
	index  <- which( abs(ftlist$feature.set[,6]-Iso[n]) < mz.tol )
	cat("\t- ",Lab[n],":\t",length(index)," feature pair candidates\n",sep="")
	if(length(index)>1){
		C13C12 <- apply(ftlist$data[ftlist$feature.set[index,2],],1,mean)/apply(ftlist$data[ftlist$feature.set[index,1],],1,mean)
	} else {
		if (length(index)==1) C13C12 <- mean(ftlist$data[ftlist$feature.set[index,2],])/mean(ftlist$data[ftlist$feature.set[index,1],])
	}
  excl   <- which(C13C12>=max_ratio)
  incl   <- which(C13C12<max_ratio)
	cat("\t    ",length(incl)," feature pair candidates after excluding pairs with Ir>=",max_ratio,"\n",sep="")
  isotopes[index[incl],1]   <- ftlist$feature.set[index[incl],1]
  isotopes[index[incl],n+1] <- ftlist$feature.set[index[incl],2]
	if (length(index)>1){
		isotopes[index[incl],2+length(Iso)]   <- apply(ftlist$data[ftlist$feature.set[index[incl],1],],1,mean)
		isotopes[index[incl],n+2+length(Iso)] <- apply(ftlist$data[ftlist$feature.set[index[incl],2],],1,mean)
	} else {
		isotopes[index[incl],2+length(Iso)]   <- mean(ftlist$data[ftlist$feature.set[index[incl],1],])
		isotopes[index[incl],n+2+length(Iso)] <- mean(ftlist$data[ftlist$feature.set[index[incl],2],])
	}
	mz1    <- ftlist$mz[ftlist$feature.set[index[incl],1]]
  mz2    <- ftlist$mz[ftlist$feature.set[index[excl],1]]
	if (length(mz1)>(min_samples-1)){
	  cat("\t    LR model fitted\n",sep="")
    model <- lm( as.vector(C13C12[incl]) ~ as.vector(mz1))
    incl2 <- incl
    imz   <- 1:length(incl)
    j <- which(abs(model$residuals)>3*sqrt(var(model$residuals)))
    while(length(j)>0){
      incl2 <- setdiff(incl2,incl2[j])
      imz   <- setdiff(imz,j)
      if (length(incl2)<2) break
      model <- lm( as.vector(C13C12[incl2]) ~ as.vector(mz1[imz]))
      j <- which(abs(model$residuals)>n_std*sqrt(var(model$residuals)))
    }
    cat("\t    ",length(incl2)," feature pair candidates after excluding pairs with high model residuals\n",sep="")
    if (length(incl2)>1){
      annot_isotopes[index[incl2],n]   <- (model$residuals)/sqrt(var(model$residuals))
      annot_isotopes[index[setdiff(incl,incl2)],n]   <- NA
    } 
  } else {
    cat("\t    LR model not fitted\n",sep="")
	}
  if (fplot){
    if (n==1) ge <- split.screen(c(2,1))
    screen(n)
    plot(ftlist$mz[ftlist$feature.set[index,1]],C13C12,cex=1,col="red",xlab="M/Z",ylab="Intensity Ratio",main=paste(pl[n],Lab[n]," ratios (N=",length(incl)," included)",sep=""))
    grid()
    if (length(mz1)>(min_samples-1)){
      x  <- seq(min(mz1),max(mz1),length=100)        
      lines(x,model$coefficients[2]*x+model$coefficients[1],col="black",lwd=2)    
	    if (n==1) lab <- sprintf("I(C13#1)/I(C12) = m/z * %1.2e + %1.2e",model$coefficients[2],model$coefficients[1])
	    if (n==2) lab <- sprintf("I(C13#2)/I(C12) = m/z * %1.2e + %1.2e",model$coefficients[2],model$coefficients[1])
      legend("topright",legend=c("EXCLUDED (r>1)","EXCLUDED (std)","INCLUDED","L.R."),col = c("red","magenta","blue","black"),lty = c(0,0,0,1), cex = .7, pch = c(1,1,1,-1))
    } else {
	    legend("topright",legend=c("EXCLUDED (r>1)","INCLUDED"),col = c(2,4),lty = c(0,0), cex = .7, pch = c(1,1))
	    lab <- ""
    }
    if (lab!="") legend(x=min(mz1),y=max(C13C12)*0.95,legend=lab,bg="aliceblue",pch=-1,cex=0.8)
    points(ftlist$mz[ftlist$feature.set[index,1]],C13C12,cex=1,col="red")
    points(mz1,C13C12[incl],cex=1,col="magenta")
    points(mz1[imz],C13C12[incl2],cex=1,col="blue")
    if (n==length(Iso)) close.screen(all.screens=TRUE)
  }
}
ftlist$isotopes <- isotopes[which(isotopes[,1]>0),]
ftlist$isotopes <- cbind(ftlist$isotopes,annot_isotopes[which(isotopes[,1]>0),])
colnames(ftlist$isotopes)<-c("Index-12C","Index-13C1","Index-13C2","Intensity-12C","Intensity-13C1","Intensity-13C2","Model.Residuals-13C1","Model.Residuals-13C2")
## CHECK FOR REDUNDANT ISOTOPES
i1 <- which(ftlist$isotopes[,2]!=0)
model <- lm( ftlist$isotopes[i1,5]/ftlist$isotopes[i1,4] ~ ftlist$mz[ftlist$isotopes[i1,1]])
U <- unique(ftlist$isotopes[i1,1])
kk1 <- rep(0,length(i1))
for (j in 1:length(U)){
  k <- which(ftlist$isotopes[i1,1]==U[j])
  if (length(k)>1){
    kk1[k[which.min(abs(model$residuals[k]))]]<-1
  } else {
    kk1[k] <- 1
  }
}
i1 <- i1[kk1==1]
i2 <- which(ftlist$isotopes[,3]!=0)
model <- lm( ftlist$isotopes[i2,6]/ftlist$isotopes[i2,4] ~ ftlist$mz[ftlist$isotopes[i2,1]])
U <- unique(ftlist$isotopes[i2,1])
kk1 <- rep(0,length(i2))
for (j in 1:length(U)){
  k <- which(ftlist$isotopes[i2,1]==U[j])
  if (length(k)>1){
    kk1[k[which.min(abs(model$residuals[k]))[1]]]<-1
  } else {
    kk1[k] <- 1
  }
}
i2 <- i2[kk1==1]
ftlist$isotopes <- ftlist$isotopes[sort(c(i1,i2)),]
cat("\t- Total number:\t",dim(ftlist$isotopes)[1]," isotope patterns\n",sep="")
return(ftlist)
}
