]> git.donarmstrong.com Git - mothur.git/blobdiff - counttable.cpp
changes while testing
[mothur.git] / counttable.cpp
index bc9d4da05966b6b3fc3ec5fe0e751c21be7f180f..6eca8ee2a4b5354da54412b9eb6986b6ba244657 100644 (file)
@@ -40,7 +40,13 @@ int CountTable::createTable(set<string>& n, map<string, string>& g, set<string>&
             if (itGroup != g.end()) {   
                 groupCounts[indexGroupMap[itGroup->second]] = 1; 
                 totalGroups[indexGroupMap[itGroup->second]]++;
-            }else { m->mothurOut("[ERROR]: Your group file does not contain " + seqName + ". Please correct."); m->mothurOutEndLine(); }
+            }else {
+                //look for it in names of groups to see if the user accidently used the wrong file
+                if (m->inUsersGroups(seqName, groups)) {
+                    m->mothurOut("[WARNING]: Your group or design file contains a group named " + seqName + ".  Perhaps you are used a group file instead of a design file? A common cause of this is using a tree file that relates your groups (created by the tree.shared command) with a group file that assigns sequences to a group."); m->mothurOutEndLine();
+                }
+                m->mothurOut("[ERROR]: Your group file does not contain " + seqName + ". Please correct."); m->mothurOutEndLine();
+            }
             
             map<string, int>::iterator it2 = indexNameMap.find(seqName);
             if (it2 == indexNameMap.end()) {
@@ -52,6 +58,12 @@ int CountTable::createTable(set<string>& n, map<string, string>& g, set<string>&
             }
         }
         
+        if (hasGroups) {
+            for (int i = 0; i < totalGroups.size(); i++) {
+                if (totalGroups[i] == 0) { m->mothurOut("\nRemoving group: " + groups[i] + " because all sequences have been removed.\n"); removeGroup(groups[i]); i--; }
+            }
+        }
+
         return 0;
     }
        catch(exception& e) {
@@ -125,6 +137,9 @@ int CountTable::createTable(string namefile, string groupfile, bool createGroup)
             string firstCol, secondCol;
             in >> firstCol; m->gobble(in); in >> secondCol; m->gobble(in);
             
+            m->checkName(firstCol);
+            m->checkName(secondCol);
+            
             vector<string> names;
             m->splitAtChar(secondCol, names, ',');
             
@@ -179,7 +194,14 @@ int CountTable::createTable(string namefile, string groupfile, bool createGroup)
         in.close();
                
         if (error) { m->control_pressed = true; }
-               if (groupfile != "") { delete groupMap; }
+        else { //check for zero groups
+            if (hasGroups) {
+                for (int i = 0; i < totalGroups.size(); i++) {
+                    if (totalGroups[i] == 0) { m->mothurOut("\nRemoving group: " + groups[i] + " because all sequences have been removed.\n"); removeGroup(groups[i]); i--; }
+                }
+            }
+        }
+        if (groupfile != "") { delete groupMap; }
         
         return 0;
     }
@@ -189,7 +211,7 @@ int CountTable::createTable(string namefile, string groupfile, bool createGroup)
        }
 }
 /************************************************************/
-int CountTable::readTable(string file) {
+int CountTable::readTable(string file, bool readGroups) {
     try {
         filename = file;
         ifstream in;
@@ -205,7 +227,7 @@ int CountTable::readTable(string file) {
         indexNameMap.clear();
         counts.clear();
         map<int, string> originalGroupIndexes;
-        if (columnHeaders.size() > 2) { hasGroups = true; numGroups = columnHeaders.size() - 2;  }
+        if ((columnHeaders.size() > 2) && readGroups) { hasGroups = true; numGroups = columnHeaders.size() - 2;  }
         for (int i = 2; i < columnHeaders.size(); i++) {  groups.push_back(columnHeaders[i]);  originalGroupIndexes[i-2] = columnHeaders[i]; totalGroups.push_back(0); }
         //sort groups to keep consistent with how we store the groups in groupmap
         sort(groups.begin(), groups.end());
@@ -226,7 +248,13 @@ int CountTable::readTable(string file) {
             
             //if group info, then read it
             vector<int> groupCounts; groupCounts.resize(numGroups, 0);
-            for (int i = 0; i < numGroups; i++) {  int thisIndex = indexGroupMap[originalGroupIndexes[i]]; in >> groupCounts[thisIndex]; m->gobble(in); totalGroups[thisIndex] += groupCounts[thisIndex];  }
+            if (columnHeaders.size() > 2) { //file contains groups
+                if (readGroups) { //user wants to save them
+                    for (int i = 0; i < numGroups; i++) {  int thisIndex = indexGroupMap[originalGroupIndexes[i]]; in >> groupCounts[thisIndex]; m->gobble(in); totalGroups[thisIndex] += groupCounts[thisIndex];  }
+                }else { //read and discard
+                    m->getline(in); m->gobble(in);
+                }
+            }
             
             map<string, int>::iterator it = indexNameMap.find(name);
             if (it == indexNameMap.end()) {
@@ -243,6 +271,13 @@ int CountTable::readTable(string file) {
         in.close();
         
         if (error) { m->control_pressed = true; }
+        else { //check for zero groups
+            if (hasGroups) {
+                for (int i = 0; i < totalGroups.size(); i++) {
+                    if (totalGroups[i] == 0) { m->mothurOut("\nRemoving group: " + groups[i] + " because all sequences have been removed.\n"); removeGroup(groups[i]); i--; }
+                }
+            }
+        }
         
         return 0;
     }
@@ -260,7 +295,23 @@ int CountTable::printTable(string file) {
         for (int i = 0; i < groups.size(); i++) { out << groups[i] << '\t'; }
         out << endl;
         
-        for (map<string, int>::iterator itNames = indexNameMap.begin(); itNames != indexNameMap.end(); itNames++) {
+        map<int, string> reverse; //use this to preserve order
+        for (map<string, int>::iterator it = indexNameMap.begin(); it !=indexNameMap.end(); it++) { reverse[it->second] = it->first;  }
+        
+        for (int i = 0; i < totals.size(); i++) {
+            map<int, string>::iterator itR = reverse.find(i);
+            
+            if (itR != reverse.end()) { //will equal end if seqs were removed because remove just removes from indexNameMap
+                out << itR->second << '\t' << totals[i] << '\t';
+                if (hasGroups) {
+                    for (int j = 0; j < groups.size(); j++) {
+                        out << counts[i][j] << '\t';
+                    }
+                }
+                out << endl;
+            }
+        }
+        /*for (map<string, int>::iterator itNames = indexNameMap.begin(); itNames != indexNameMap.end(); itNames++) {
             out << itNames->first << '\t' << totals[itNames->second] << '\t';
             if (hasGroups) {
                 
@@ -269,7 +320,7 @@ int CountTable::printTable(string file) {
                 }
             }
             out << endl;
-        }
+        }*/
         out.close();
         return 0;
     }
@@ -321,6 +372,10 @@ vector<int> CountTable::getGroupCounts(string seqName) {
         if (hasGroups) {
             map<string, int>::iterator it = indexNameMap.find(seqName);
             if (it == indexNameMap.end()) {
+                //look for it in names of groups to see if the user accidently used the wrong file
+                if (m->inUsersGroups(seqName, groups)) {
+                    m->mothurOut("[WARNING]: Your group or design file contains a group named " + seqName + ".  Perhaps you are used a group file instead of a design file? A common cause of this is using a tree file that relates your groups (created by the tree.shared command) with a group file that assigns sequences to a group."); m->mothurOutEndLine();
+                }
                 m->mothurOut("[ERROR]: " + seqName + " is not in your count table. Please correct.\n"); m->control_pressed = true;
             }else { 
                 temp = counts[it->second];
@@ -341,7 +396,7 @@ int CountTable::getGroupCount(string groupName) {
         if (hasGroups) {
             map<string, int>::iterator it = indexGroupMap.find(groupName);
             if (it == indexGroupMap.end()) {
-                m->mothurOut("[ERROR]: " + groupName + " is not in your count table. Please correct.\n"); m->control_pressed = true;
+                m->mothurOut("[ERROR]: group " + groupName + " is not in your count table. Please correct.\n"); m->control_pressed = true;
             }else { 
                 return totalGroups[it->second];
             }
@@ -361,11 +416,15 @@ int CountTable::getGroupCount(string seqName, string groupName) {
         if (hasGroups) {
             map<string, int>::iterator it = indexGroupMap.find(groupName);
             if (it == indexGroupMap.end()) {
-                m->mothurOut("[ERROR]: " + groupName + " is not in your count table. Please correct.\n"); m->control_pressed = true;
+                m->mothurOut("[ERROR]: group " + groupName + " is not in your count table. Please correct.\n"); m->control_pressed = true;
             }else { 
                 map<string, int>::iterator it2 = indexNameMap.find(seqName);
                 if (it2 == indexNameMap.end()) {
-                    m->mothurOut("[ERROR]: " + seqName + " is not in your count table. Please correct.\n"); m->control_pressed = true;
+                    //look for it in names of groups to see if the user accidently used the wrong file
+                    if (m->inUsersGroups(seqName, groups)) {
+                        m->mothurOut("[WARNING]: Your group or design file contains a group named " + seqName + ".  Perhaps you are used a group file instead of a design file? A common cause of this is using a tree file that relates your groups (created by the tree.shared command) with a group file that assigns sequences to a group."); m->mothurOutEndLine();
+                    }
+                    m->mothurOut("[ERROR]: seq " + seqName + " is not in your count table. Please correct.\n"); m->control_pressed = true;
                 }else { 
                     return counts[it2->second][it->second];
                 }
@@ -390,6 +449,10 @@ int CountTable::setAbund(string seqName, string groupName, int num) {
             }else { 
                 map<string, int>::iterator it2 = indexNameMap.find(seqName);
                 if (it2 == indexNameMap.end()) {
+                    //look for it in names of groups to see if the user accidently used the wrong file
+                    if (m->inUsersGroups(seqName, groups)) {
+                        m->mothurOut("[WARNING]: Your group or design file contains a group named " + seqName + ".  Perhaps you are used a group file instead of a design file? A common cause of this is using a tree file that relates your groups (created by the tree.shared command) with a group file that assigns sequences to a group."); m->mothurOutEndLine();
+                    }
                     m->mothurOut("[ERROR]: " + seqName + " is not in your count table. Please correct.\n"); m->control_pressed = true;
                 }else { 
                     int oldCount = counts[it2->second][it->second];
@@ -457,6 +520,61 @@ int CountTable::addGroup(string groupName) {
        }
 }
 /************************************************************/
+//remove group
+int CountTable::removeGroup(string groupName) {
+    try {        
+        if (hasGroups) {
+            //save for later in case removing a group means we need to remove a seq.
+            map<int, string> reverse;
+            for (map<string, int>::iterator it = indexNameMap.begin(); it !=indexNameMap.end(); it++) { reverse[it->second] = it->first;  }
+            
+            map<string, int>::iterator it = indexGroupMap.find(groupName);
+            if (it == indexGroupMap.end()) {
+                m->mothurOut("[ERROR]: " + groupName + " is not in your count table. Please correct.\n"); m->control_pressed = true;
+            }else { 
+                int indexOfGroupToRemove = it->second;
+                map<string, int> currentGroupIndex = indexGroupMap;
+                vector<string> newGroups;
+                for (int i = 0; i < groups.size(); i++) {
+                    if (groups[i] != groupName) { 
+                        newGroups.push_back(groups[i]);
+                        indexGroupMap[groups[i]] = newGroups.size()-1;
+                    }
+                }
+                indexGroupMap.erase(groupName);
+                groups = newGroups;
+                totalGroups.erase(totalGroups.begin()+indexOfGroupToRemove);
+                
+                int thisIndex = 0;
+                map<string, int> newIndexNameMap;
+                for (int i = 0; i < counts.size(); i++) {
+                    int num = counts[i][indexOfGroupToRemove];
+                    counts[i].erase(counts[i].begin()+indexOfGroupToRemove);
+                    totals[i] -= num;
+                    total -= num;
+                    if (totals[i] == 0) { //your sequences are only from the group we want to remove, then remove you.
+                        counts.erase(counts.begin()+i);
+                        totals.erase(totals.begin()+i);
+                        uniques--;
+                        i--;
+                    }
+                    newIndexNameMap[reverse[thisIndex]] = i;
+                    thisIndex++;
+                }
+                indexNameMap = newIndexNameMap;
+                
+                if (groups.size() == 0) { hasGroups = false; }
+            }
+        }else { m->mothurOut("[ERROR]: your count table does not contain group information, can not remove group " + groupName + ".\n"); m->control_pressed = true; }
+    
+        return 0;
+    }
+       catch(exception& e) {
+               m->errorOut(e, "CountTable", "removeGroup");
+               exit(1);
+       }
+}
+/************************************************************/
 //vector of groups for the seq
 vector<string> CountTable::getGroups(string seqName) {
     try {
@@ -482,6 +600,12 @@ int CountTable::renameSeq(string oldSeqName, string newSeqName) {
         
         map<string, int>::iterator it = indexNameMap.find(oldSeqName);
         if (it == indexNameMap.end()) {
+            if (hasGroupInfo()) {
+                //look for it in names of groups to see if the user accidently used the wrong file
+                if (m->inUsersGroups(oldSeqName, groups)) {
+                    m->mothurOut("[WARNING]: Your group or design file contains a group named " + oldSeqName + ".  Perhaps you are used a group file instead of a design file? A common cause of this is using a tree file that relates your groups (created by the tree.shared command) with a group file that assigns sequences to a group."); m->mothurOutEndLine();
+                }
+            }
             m->mothurOut("[ERROR]: " + oldSeqName + " is not in your count table. Please correct.\n"); m->control_pressed = true;
         }else {  
             int index = it->second;
@@ -504,6 +628,12 @@ int CountTable::getNumSeqs(string seqName) {
                 
         map<string, int>::iterator it = indexNameMap.find(seqName);
         if (it == indexNameMap.end()) {
+            if (hasGroupInfo()) {
+                //look for it in names of groups to see if the user accidently used the wrong file
+                if (m->inUsersGroups(seqName, groups)) {
+                    m->mothurOut("[WARNING]: Your group or design file contains a group named " + seqName + ".  Perhaps you are used a group file instead of a design file? A common cause of this is using a tree file that relates your groups (created by the tree.shared command) with a group file that assigns sequences to a group."); m->mothurOutEndLine();
+                }
+            }
             m->mothurOut("[ERROR]: " + seqName + " is not in your count table. Please correct.\n"); m->control_pressed = true;
         }else { 
             return totals[it->second];
@@ -523,6 +653,12 @@ int CountTable::get(string seqName) {
         
         map<string, int>::iterator it = indexNameMap.find(seqName);
         if (it == indexNameMap.end()) {
+            if (hasGroupInfo()) {
+                //look for it in names of groups to see if the user accidently used the wrong file
+                if (m->inUsersGroups(seqName, groups)) {
+                    m->mothurOut("[WARNING]: Your group or design file contains a group named " + seqName + ".  Perhaps you are used a group file instead of a design file? A common cause of this is using a tree file that relates your groups (created by the tree.shared command) with a group file that assigns sequences to a group."); m->mothurOutEndLine();
+                }
+            }
             m->mothurOut("[ERROR]: " + seqName + " is not in your count table. Please correct.\n"); m->control_pressed = true;
         }else { return it->second; }
         
@@ -560,7 +696,7 @@ int CountTable::push_back(string seqName) {
 int CountTable::remove(string seqName) {
     try {
         map<string, int>::iterator it = indexNameMap.find(seqName);
-        if (it == indexNameMap.end()) {
+        if (it != indexNameMap.end()) {
             uniques--;
             if (hasGroups){ //remove this sequences counts from group totals
                 for (int i = 0; i < totalGroups.size(); i++) {  totalGroups[i] -= counts[it->second][i];  counts[it->second][i] = 0; }
@@ -569,6 +705,12 @@ int CountTable::remove(string seqName) {
             total -= thisTotal;
             indexNameMap.erase(it);
         }else {
+            if (hasGroupInfo()) {
+                //look for it in names of groups to see if the user accidently used the wrong file
+                if (m->inUsersGroups(seqName, groups)) {
+                    m->mothurOut("[WARNING]: Your group or design file contains a group named " + seqName + ".  Perhaps you are used a group file instead of a design file? A common cause of this is using a tree file that relates your groups (created by the tree.shared command) with a group file that assigns sequences to a group."); m->mothurOutEndLine();
+                }
+            }
             m->mothurOut("[ERROR]: Your count table contains does not include " + seqName + ", cannot remove."); m->mothurOutEndLine(); m->control_pressed = true;
         }
         
@@ -661,6 +803,22 @@ vector<string> CountTable::getNamesOfSeqs() {
        }
 }
 /************************************************************/
+//returns the names of all unique sequences in file mapped to their seqCounts
+map<string, int> CountTable::getNameMap() {
+    try {
+        map<string, int> names;
+        for (map<string, int>::iterator it = indexNameMap.begin(); it != indexNameMap.end(); it++) {
+            names[it->first] = totals[it->second];
+        }
+        
+        return names;
+    }
+       catch(exception& e) {
+               m->errorOut(e, "CountTable", "getNameMap");
+               exit(1);
+       }
+}
+/************************************************************/
 //returns the names of all unique sequences in file
 vector<string> CountTable::getNamesOfSeqs(string group) {
     try {
@@ -689,10 +847,22 @@ int CountTable::mergeCounts(string seq1, string seq2) {
     try {
         map<string, int>::iterator it = indexNameMap.find(seq1);
         if (it == indexNameMap.end()) {
+            if (hasGroupInfo()) {
+                //look for it in names of groups to see if the user accidently used the wrong file
+                if (m->inUsersGroups(seq1, groups)) {
+                    m->mothurOut("[WARNING]: Your group or design file contains a group named " + seq1 + ".  Perhaps you are used a group file instead of a design file? A common cause of this is using a tree file that relates your groups (created by the tree.shared command) with a group file that assigns sequences to a group."); m->mothurOutEndLine();
+                }
+            }
             m->mothurOut("[ERROR]: " + seq1 + " is not in your count table. Please correct.\n"); m->control_pressed = true;
         }else { 
             map<string, int>::iterator it2 = indexNameMap.find(seq2);
             if (it2 == indexNameMap.end()) {
+                if (hasGroupInfo()) {
+                    //look for it in names of groups to see if the user accidently used the wrong file
+                    if (m->inUsersGroups(seq2, groups)) {
+                        m->mothurOut("[WARNING]: Your group or design file contains a group named " + seq2 + ".  Perhaps you are used a group file instead of a design file? A common cause of this is using a tree file that relates your groups (created by the tree.shared command) with a group file that assigns sequences to a group."); m->mothurOutEndLine();
+                    }
+                }
                 m->mothurOut("[ERROR]: " + seq2 + " is not in your count table. Please correct.\n"); m->control_pressed = true;
             }else { 
                 //merge data