]> git.donarmstrong.com Git - mothur.git/blobdiff - decalc.cpp
fixed bug in cluster.split with classify method
[mothur.git] / decalc.cpp
index 61de7c832dfbc7a16f8984b6bff127ebc68ba63f..74cd8652909d17f0cd0e4e899b1472c6eea2ef93 100644 (file)
 #include "chimera.h"
 #include "dist.h"
 #include "eachgapdist.h"
+#include "ignoregaps.h"
 
 
 //***************************************************************************************************************
-void DeCalculator::setMask(string m) { 
+void DeCalculator::setMask(string ms) { 
        try {
-               seqMask = m; 
+               seqMask = ms
                int count = 0;
                maskMap.clear();
                
@@ -39,7 +40,7 @@ void DeCalculator::setMask(string m) {
                }
        }
        catch(exception& e) {
-               errorOut(e, "DeCalculator", "setMask");
+               m->errorOut(e, "DeCalculator", "setMask");
                exit(1);
        } 
 }
@@ -61,7 +62,7 @@ void DeCalculator::runMask(Sequence* seq) {
                seq->setUnaligned(tempQuery);
        }
        catch(exception& e) {
-               errorOut(e, "DeCalculator", "runMask");
+               m->errorOut(e, "DeCalculator", "runMask");
                exit(1);
        }
 }
@@ -89,7 +90,7 @@ void DeCalculator::trimSeqs(Sequence* query, Sequence* subject, map<int, int>& t
                
        }
        catch(exception& e) {
-               errorOut(e, "DeCalculator", "trimSeqs");
+               m->errorOut(e, "DeCalculator", "trimSeqs");
                exit(1);
        }
 }
@@ -105,7 +106,7 @@ vector<int>  DeCalculator::findWindows(Sequence* query, int front, int back, int
                if (size == 0) {  if (cutoff > 1200) {  size = 300; }
                                                        else{  size = (cutoff / 4); }  } 
                else if (size > (cutoff / 4)) { 
-                               mothurOut("You have selected too large a window size for sequence " + query->getName() + ".  I will choose an appropriate window size."); mothurOutEndLine();
+                               m->mothurOut("You have selected too large a window size for sequence " + query->getName() + ".  I will choose an appropriate window size."); m->mothurOutEndLine();
                                size = (cutoff / 4); 
                }
        
@@ -157,7 +158,7 @@ vector<int>  DeCalculator::findWindows(Sequence* query, int front, int back, int
        
        }
        catch(exception& e) {
-               errorOut(e, "DeCalculator", "findWindows");
+               m->errorOut(e, "DeCalculator", "findWindows");
                exit(1);
        }
 }
@@ -199,7 +200,7 @@ vector<float> DeCalculator::calcObserved(Sequence* query, Sequence* subject, vec
                return temp;
        }
        catch(exception& e) {
-               errorOut(e, "DeCalculator", "calcObserved");
+               m->errorOut(e, "DeCalculator", "calcObserved");
                exit(1);
        }
 }
@@ -231,7 +232,7 @@ float DeCalculator::calcDist(Sequence* query, Sequence* subject, int front, int
                return dist;
        }
        catch(exception& e) {
-               errorOut(e, "DeCalculator", "calcDist");
+               m->errorOut(e, "DeCalculator", "calcDist");
                exit(1);
        }
 }
@@ -254,7 +255,7 @@ vector<float> DeCalculator::calcExpected(vector<float> qav, float coef) {
                                
        }
        catch(exception& e) {
-               errorOut(e, "DeCalculator", "calcExpected");
+               m->errorOut(e, "DeCalculator", "calcExpected");
                exit(1);
        }
 }
@@ -278,7 +279,7 @@ float DeCalculator::calcDE(vector<float> obs, vector<float> exp) {
                return de;
        }
        catch(exception& e) {
-               errorOut(e, "DeCalculator", "calcDE");
+               m->errorOut(e, "DeCalculator", "calcDE");
                exit(1);
        }
 }
@@ -344,7 +345,7 @@ vector<float> DeCalculator::calcFreq(vector<Sequence*> seqs, string filename) {
                                
        }
        catch(exception& e) {
-               errorOut(e, "DeCalculator", "calcFreq");
+               m->errorOut(e, "DeCalculator", "calcFreq");
                exit(1);
        }
 }
@@ -374,7 +375,7 @@ vector<float>  DeCalculator::findQav(vector<int> window, int size, vector<float>
                return averages;
        }
        catch(exception& e) {
-               errorOut(e, "DeCalculator", "findQav");
+               m->errorOut(e, "DeCalculator", "findQav");
                exit(1);
        }
 }
@@ -393,7 +394,7 @@ vector< vector<quanMember> > DeCalculator::getQuantiles(vector<Sequence*> seqs,
                //for each sequence
                for(int i = start; i < end; i++){
                
-                       mothurOut("Processing sequence " + toString(i)); mothurOutEndLine();
+                       m->mothurOut("Processing sequence " + toString(i)); m->mothurOutEndLine();
                        Sequence* query = new Sequence(seqs[i]->getName(), seqs[i]->getAligned());
                        
                        //compare to every other sequence in template
@@ -401,6 +402,8 @@ vector< vector<quanMember> > DeCalculator::getQuantiles(vector<Sequence*> seqs,
                                
                                Sequence* subject = new Sequence(seqs[j]->getName(), seqs[j]->getAligned());
                                
+                               if (m->control_pressed) { delete query; delete subject; return quan; }
+                               
                                map<int, int> trim;
                                map<int, int>::iterator it;
                                
@@ -425,7 +428,7 @@ vector< vector<quanMember> > DeCalculator::getQuantiles(vector<Sequence*> seqs,
                                float de = calcDE(obsi, exp);
                                                                
                                float dist = calcDist(query, subject, front, back); 
-       //o << i << '\t' <<  j << '\t' << dist << '\t' << de << endl;                   
+       //cout << i << '\t' <<  j << '\t' << dist << '\t' << de << endl;                        
                                dist = ceil(dist);
                                
                                quanMember newScore(de, i, j);
@@ -442,7 +445,7 @@ vector< vector<quanMember> > DeCalculator::getQuantiles(vector<Sequence*> seqs,
                                                
        }
        catch(exception& e) {
-               errorOut(e, "DeCalculator", "getQuantiles");
+               m->errorOut(e, "DeCalculator", "getQuantiles");
                exit(1);
        }
 }
@@ -484,7 +487,7 @@ void DeCalculator::removeObviousOutliers(vector< vector<quanMember> >& quantiles
                //while you still have guys to eliminate
                while (contributions.size() > 0) {
                
-                       mothurOut("Removing scores contributed by sequence " + toString(largestContrib) + " in your template file."); mothurOutEndLine();
+                       m->mothurOut("Removing scores contributed by sequence " + toString(largestContrib) + " in your template file."); m->mothurOutEndLine();
                        
                        //remove from quantiles all scores that were made using this largestContrib
                        for (int i = 0; i < quantiles.size(); i++) {
@@ -515,7 +518,7 @@ cout << "high = " << high << endl;
                
                for(int i = 0; i < marked.size(); i++) {
                        if (marked[i] > high) { 
-                               mothurOut("Removing scores contributed by sequence " + toString(marked[i]) + " in your template file."); mothurOutEndLine();
+                               m->mothurOut("Removing scores contributed by sequence " + toString(marked[i]) + " in your template file."); m->mothurOutEndLine();
                                for (int i = 0; i < quantiles.size(); i++) {
                                        removeContrib(marked[i], quantiles[i]);
                                }
@@ -559,7 +562,7 @@ cout << "high = " << high << endl;
                
        }
        catch(exception& e) {
-               errorOut(e, "DeCalculator", "removeObviousOutliers");
+               m->errorOut(e, "DeCalculator", "removeObviousOutliers");
                exit(1);
        }
 }
@@ -591,7 +594,7 @@ cout << largest->second << '\t' << largest->first->score << '\t' << largest->fir
                
        }
        catch(exception& e) {
-               errorOut(e, "DeCalculator", "sortContrib");
+               m->errorOut(e, "DeCalculator", "sortContrib");
                exit(1);
        }
 }
@@ -617,7 +620,7 @@ int DeCalculator::findLargestContrib(vector<int> seen) {
                
        }
        catch(exception& e) {
-               errorOut(e, "DeCalculator", "findLargestContribs");
+               m->errorOut(e, "DeCalculator", "findLargestContribs");
                exit(1);
        }
 }
@@ -636,7 +639,7 @@ void DeCalculator::removeContrib(int bad, vector<quanMember>& quan) {
                
        }
        catch(exception& e) {
-               errorOut(e, "DeCalculator", "removeContrib");
+               m->errorOut(e, "DeCalculator", "removeContrib");
                exit(1);
        }
 }
@@ -654,7 +657,7 @@ float DeCalculator::findAverage(vector<float> myVector) {
                
        }
        catch(exception& e) {
-               errorOut(e, "DeCalculator", "findAverage");
+               m->errorOut(e, "DeCalculator", "findAverage");
                exit(1);
        }
 }
@@ -674,17 +677,19 @@ float DeCalculator::getCoef(vector<float> obs, vector<float> qav) {
                return coef;
        }
        catch(exception& e) {
-               errorOut(e, "DeCalculator", "getCoef");
+               m->errorOut(e, "DeCalculator", "getCoef");
                exit(1);
        }
 }
 //***************************************************************************************************************
 //gets closest matches to each end, since chimeras will most likely have different parents on each end
-vector<Sequence*> DeCalculator::findClosest(Sequence* querySeq, vector<Sequence*> db, int numWanted) {
+vector<Sequence*> DeCalculator::findClosest(Sequence* querySeq, vector<Sequence*> db, int& numWanted, vector<int>& indexes) {
        try {
+               indexes.clear();
                
                vector<Sequence*> seqsMatches;  
-               vector<SeqDist> dists;
+               vector<SeqDist> distsLeft;
+               vector<SeqDist> distsRight;
                
                Dist* distcalculator = new eachGapDist();
                
@@ -696,12 +701,19 @@ vector<Sequence*> DeCalculator::findClosest(Sequence* querySeq, vector<Sequence*
                string queryAligned = querySeq->getAligned();
                
                //left side
+               bool foundFirstBase = false;
                int baseCount = 0;
                int leftSpot = 0;
+               int firstBaseSpot = 0;
                for (int i = 0; i < queryAligned.length(); i++) {
-                       leftQuery += queryAligned[i];
                        //if you are a base
-                       if ((queryAligned[i] != '.') && (queryAligned[i] != '-')) {             baseCount++;    }
+                       if (isalpha(queryAligned[i])) {         
+                               baseCount++; 
+                               if (!foundFirstBase) {   foundFirstBase = true;  firstBaseSpot = i;  }
+                       }
+                       
+                       //eliminate opening .'s
+                       if (foundFirstBase) {   leftQuery += queryAligned[i];  }
                        //if you have 1/3
                        if (baseCount >= numBases) {  leftSpot = i; break; } //first 1/3
                }
@@ -711,21 +723,31 @@ vector<Sequence*> DeCalculator::findClosest(Sequence* querySeq, vector<Sequence*
                int rightSpot = 0;
                for (int i = leftSpot; i < queryAligned.length(); i++) {
                        //if you are a base
-                       if ((queryAligned[i] != '.') && (queryAligned[i] != '-')) {             baseCount++;    }
+                       if (isalpha(queryAligned[i])) {         baseCount++;    }
                        //if you have 1/3
                        if (baseCount >= numBases) { rightSpot = i;  break; } //last 1/3
                }
-               rightQuery = queryAligned.substr(rightSpot); //sequence from pos spot to end
+               
+               //trim end
+               //find last position in query that is a non gap character
+               int lastBaseSpot = queryAligned.length()-1;
+               for (int j = queryAligned.length()-1; j >= 0; j--) {
+                       if (isalpha(queryAligned[j])) {
+                               lastBaseSpot = j;
+                               break;
+                       }
+               }
+               rightQuery = queryAligned.substr(rightSpot, (lastBaseSpot-rightSpot)); //sequence from pos spot to end
                
                Sequence queryLeft(querySeq->getName(), leftQuery);
                Sequence queryRight(querySeq->getName(), rightQuery);
-//cout << querySeq->getName() << '\t' << leftSpot << '\t' << rightSpot << endl;
+//cout << querySeq->getName() << '\t' << leftSpot << '\t' << rightSpot << '\t' << firstBaseSpot << '\t' << lastBaseSpot << endl;
 //cout << queryUnAligned.length() << '\t' << queryLeft.getUnaligned().length() << '\t' << queryRight.getUnaligned().length() << endl;
                for(int j = 0; j < db.size(); j++){
                        
                        string dbAligned = db[j]->getAligned();
-                       string leftDB = dbAligned.substr(0, leftSpot+1); //first 1/3 of the sequence
-                       string rightDB = dbAligned.substr(rightSpot); //last 1/3 of the sequence
+                       string leftDB = dbAligned.substr(firstBaseSpot, (leftSpot-firstBaseSpot+1)); //first 1/3 of the sequence
+                       string rightDB = dbAligned.substr(rightSpot, (lastBaseSpot-rightSpot)); //last 1/3 of the sequence
                        
                        Sequence dbLeft(db[j]->getName(), leftDB);
                        Sequence dbRight(db[j]->getName(), rightDB);
@@ -736,28 +758,118 @@ vector<Sequence*> DeCalculator::findClosest(Sequence* querySeq, vector<Sequence*
                        distcalculator->calcDist(queryRight, dbRight);
                        float distRight = distcalculator->getDist();
                        
-                       float dist = min(distLeft, distRight); //keep smallest distance
+                       SeqDist subjectLeft;
+                       subjectLeft.seq = db[j];
+                       subjectLeft.dist = distLeft;
+                       subjectLeft.index = j;
                        
-                       SeqDist subject;
-                       subject.seq = db[j];
-                       subject.dist = dist;
+                       distsLeft.push_back(subjectLeft);
                        
-                       dists.push_back(subject);
+                       SeqDist subjectRight;
+                       subjectRight.seq = db[j];
+                       subjectRight.dist = distRight;
+                       subjectRight.index = j;
+                       
+                       distsRight.push_back(subjectRight);
+
                }
                
                delete distcalculator;
                
-               sort(dists.begin(), dists.end(), compareSeqDist);
+               //sort by smallest distance
+               sort(distsRight.begin(), distsRight.end(), compareSeqDist);
+               sort(distsLeft.begin(), distsLeft.end(), compareSeqDist);
                
+               //merge results         
+               map<string, string> seen;
+               map<string, string>::iterator it;
+               
+               vector<SeqDist> dists;
+               float lastRight = distsRight[0].dist;
+               float lastLeft = distsLeft[0].dist;
+               int lasti = 0;
+               for (int i = 0; i < distsLeft.size(); i++) {
+                       //add left if you havent already
+                       it = seen.find(distsLeft[i].seq->getName());
+                       if (it == seen.end()) {  
+                               dists.push_back(distsLeft[i]);
+                               seen[distsLeft[i].seq->getName()] = distsLeft[i].seq->getName();
+                               lastLeft =  distsLeft[i].dist;
+                       }
+
+                       //add right if you havent already
+                       it = seen.find(distsRight[i].seq->getName());
+                       if (it == seen.end()) {  
+                               dists.push_back(distsRight[i]);
+                               seen[distsRight[i].seq->getName()] = distsRight[i].seq->getName();
+                               lastRight =  distsRight[i].dist;
+                       }
+                       
+                       if (dists.size() > numWanted) { lasti = i; break; } //you have enough results
+               }
+               
+               //add in dups
+               lasti++;
+               int i = lasti;
+               while (i < distsLeft.size()) {  
+                       if (distsLeft[i].dist == lastLeft) {  dists.push_back(distsLeft[i]);  numWanted++; }
+                       else { break; }
+                       i++;
+               }
+               
+               i = lasti;
+               while (i < distsRight.size()) {  
+                       if (distsRight[i].dist == lastRight) {  dists.push_back(distsRight[i]);  numWanted++; }
+                       else { break; }
+                       i++;
+               }
+
+               if (numWanted > dists.size()) { m->mothurOut("numwanted is larger than the number of template sequences, adjusting numwanted."); m->mothurOutEndLine(); numWanted = dists.size(); }
+
+//cout << numWanted << endl;
                for (int i = 0; i < numWanted; i++) {
+//cout << dists[i].seq->getName() << '\t' << dists[i].dist << endl;
                        Sequence* temp = new Sequence(dists[i].seq->getName(), dists[i].seq->getAligned()); //have to make a copy so you can trim and filter without stepping on eachother.
                        seqsMatches.push_back(temp);
+                       indexes.push_back(dists[i].index);
                }
                
                return seqsMatches;
        }
        catch(exception& e) {
-               errorOut(e, "DeCalculator", "findClosest");
+               m->errorOut(e, "DeCalculator", "findClosest");
+               exit(1);
+       }
+}
+//***************************************************************************************************************
+Sequence* DeCalculator::findClosest(Sequence* querySeq, vector<Sequence*> db) {
+       try {
+               
+               Sequence* seqsMatch;  
+               
+               Dist* distcalculator = new eachGapDist();
+               int index = 0;
+               int smallest = 1000000;
+               
+               for(int j = 0; j < db.size(); j++){
+                       
+                       distcalculator->calcDist(*querySeq, *db[j]);
+                       float dist = distcalculator->getDist();
+                       
+                       if (dist < smallest) { 
+                               smallest = dist;
+                               index = j;
+                       }
+               }
+               
+               delete distcalculator;
+               
+               seqsMatch = new Sequence(db[index]->getName(), db[index]->getAligned()); //have to make a copy so you can trim and filter without stepping on eachother.
+                       
+               return seqsMatch;
+       }
+       catch(exception& e) {
+               m->errorOut(e, "DeCalculator", "findClosest");
                exit(1);
        }
 }
@@ -837,11 +949,11 @@ map<int, int> DeCalculator::trimSeqs(Sequence* query, vector<Sequence*> topMatch
                if (pos < rearPos) { rearPos = pos; }
 
                //check to make sure that is not whole seq
-               if ((rearPos - frontPos - 1) <= 0) {  mothurOut("Error, when I trim your sequences, the entire sequence is trimmed."); mothurOutEndLine(); exit(1);  }
-//cout << "front = " << frontPos << " rear = " << rearPos << endl;             
+               if ((rearPos - frontPos - 1) <= 0) {  m->mothurOut("Error, when I trim your sequences, the entire sequence is trimmed."); m->mothurOutEndLine(); exit(1);  }
+//cout << query->getName() << " front = " << frontPos << " rear = " << rearPos << endl;                
                //trim query
                string newAligned = query->getAligned();
-               newAligned = newAligned.substr(frontPos, (rearPos-frontPos));
+               newAligned = newAligned.substr(frontPos, (rearPos-frontPos+1));
                query->setAligned(newAligned);
                
                //trim topMatches
@@ -860,7 +972,7 @@ map<int, int> DeCalculator::trimSeqs(Sequence* query, vector<Sequence*> topMatch
                return trimmedPos;
        }
        catch(exception& e) {
-               errorOut(e, "DeCalculator", "trimSequences");
+               m->errorOut(e, "DeCalculator", "trimSequences");
                exit(1);
        }