]> git.donarmstrong.com Git - mothur.git/blobdiff - counttable.cpp
changes while testing
[mothur.git] / counttable.cpp
index c4e2732e8554cd81a934af7f2ee3bfcff7705db6..6eca8ee2a4b5354da54412b9eb6986b6ba244657 100644 (file)
@@ -8,9 +8,210 @@
 
 #include "counttable.h"
 
+/************************************************************/
+int CountTable::createTable(set<string>& n, map<string, string>& g, set<string>& gs) {
+    try {
+        int numGroups = 0;
+        groups.clear();
+        totalGroups.clear();
+        indexGroupMap.clear();
+        indexNameMap.clear();
+        counts.clear();
+        for (set<string>::iterator it = gs.begin(); it != gs.end(); it++) { groups.push_back(*it);  hasGroups = true; }
+        numGroups = groups.size();
+        totalGroups.resize(numGroups, 0);
+        
+               //sort groups to keep consistent with how we store the groups in groupmap
+        sort(groups.begin(), groups.end());
+        for (int i = 0; i < groups.size(); i++) {  indexGroupMap[groups[i]] = i; }
+        m->setAllGroups(groups);
+        
+        uniques = 0;
+        total = 0;
+        for (set<string>::iterator it = n.begin(); it != n.end(); it++) {
+            
+            if (m->control_pressed) { break; }
+            
+            string seqName = *it;
+            
+            vector<int> groupCounts; groupCounts.resize(numGroups, 0);
+            map<string, string>::iterator itGroup = g.find(seqName);
+            
+            if (itGroup != g.end()) {   
+                groupCounts[indexGroupMap[itGroup->second]] = 1; 
+                totalGroups[indexGroupMap[itGroup->second]]++;
+            }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()) {
+                if (hasGroups) {  counts.push_back(groupCounts);  }
+                indexNameMap[seqName] = uniques;
+                totals.push_back(1);
+                total++;
+                uniques++;
+            }
+        }
+        
+        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) {
+               m->errorOut(e, "CountTable", "createTable");
+               exit(1);
+       }
+}
 /************************************************************/
-int CountTable::readTable(string file) {
+bool CountTable::testGroups(string file) {
+    try {
+        m = MothurOut::getInstance(); hasGroups = false; total = 0;
+        ifstream in;
+        m->openInputFile(file, in);
+    
+        string headers = m->getline(in); m->gobble(in);
+        vector<string> columnHeaders = m->splitWhiteSpace(headers);
+        if (columnHeaders.size() > 2) { hasGroups = true;   }
+        return hasGroups;
+    }
+       catch(exception& e) {
+               m->errorOut(e, "CountTable", "readTable");
+               exit(1);
+       }
+}
+/************************************************************/
+int CountTable::createTable(string namefile, string groupfile, bool createGroup) {
+    try {
+        
+        if (namefile == "") { m->mothurOut("[ERROR]: namefile cannot be blank when creating a count table.\n"); m->control_pressed = true; }
+                                           
+        GroupMap* groupMap;
+        int numGroups = 0;
+        groups.clear();
+        totalGroups.clear();
+        indexGroupMap.clear();
+        indexNameMap.clear();
+        counts.clear();
+        map<int, string> originalGroupIndexes;
+        
+        if (groupfile != "") { 
+            hasGroups = true;
+            groupMap = new GroupMap(groupfile); groupMap->readMap();
+            numGroups = groupMap->getNumGroups();
+            groups = groupMap->getNamesOfGroups();
+            totalGroups.resize(numGroups, 0);
+        }else if(createGroup) {
+            hasGroups = true;
+            numGroups = 1;
+            groups.push_back("Group1");
+            totalGroups.resize(numGroups, 0);
+        }
+               //sort groups to keep consistent with how we store the groups in groupmap
+        sort(groups.begin(), groups.end());
+        for (int i = 0; i < groups.size(); i++) {  indexGroupMap[groups[i]] = i; }
+        m->setAllGroups(groups);
+        
+        bool error = false;
+        string name;
+        uniques = 0;
+        total = 0;
+        
+        
+        //open input file
+        ifstream in;
+        m->openInputFile(namefile, in);
+        
+        int total = 0;
+        while (!in.eof()) {
+            if (m->control_pressed) { break; }
+            
+            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, ',');
+            
+            map<string, int> groupCounts;
+            int thisTotal = 0;
+            if (groupfile != "") {
+                //set to 0
+                for (int i = 0; i < groups.size(); i++) { groupCounts[groups[i]] = 0; }
+                
+                //get counts for each of the users groups
+                for (int i = 0; i < names.size(); i++) {
+                    string group = groupMap->getGroup(names[i]);
+                    
+                    if (group == "not found") { m->mothurOut("[ERROR]: " + names[i] + " is not in your groupfile, please correct."); m->mothurOutEndLine(); error=true; }
+                    else {
+                        map<string, int>::iterator it = groupCounts.find(group);
+                        
+                        //if not found, then this sequence is not from a group we care about
+                        if (it != groupCounts.end()) {
+                            it->second++;
+                            thisTotal++;
+                        }
+                    }
+                }
+            }else if (createGroup) {
+                groupCounts["Group1"]=0;
+                for (int i = 0; i < names.size(); i++) {
+                    string group = "Group1";
+                    groupCounts["Group1"]++; thisTotal++;
+                }
+            }else { thisTotal = names.size();  }
+            
+            //if group info, then read it
+            vector<int> thisGroupsCount; thisGroupsCount.resize(numGroups, 0);
+            for (int i = 0; i < numGroups; i++) {  
+                thisGroupsCount[i] = groupCounts[groups[i]]; 
+                totalGroups[i] += thisGroupsCount[i]; 
+            }
+            
+            map<string, int>::iterator it = indexNameMap.find(firstCol);
+            if (it == indexNameMap.end()) {
+                if (hasGroups) {  counts.push_back(thisGroupsCount);  }
+                indexNameMap[firstCol] = uniques;
+                totals.push_back(thisTotal);
+                total += thisTotal;
+                uniques++;
+            }else {
+                error = true;
+                m->mothurOut("[ERROR]: Your count table contains more than 1 sequence named " + firstCol + ", sequence names must be unique. Please correct."); m->mothurOutEndLine(); 
+            }
+        }
+        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--; }
+                }
+            }
+        }
+        if (groupfile != "") { delete groupMap; }
+        
+        return 0;
+    }
+       catch(exception& e) {
+               m->errorOut(e, "CountTable", "createTable");
+               exit(1);
+       }
+}
+/************************************************************/
+int CountTable::readTable(string file, bool readGroups) {
     try {
         filename = file;
         ifstream in;
@@ -26,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());
@@ -42,11 +243,18 @@ int CountTable::readTable(string file) {
             
             if (m->control_pressed) { break; }
             
-            in >> name >> thisTotal; m->gobble(in);
+            in >> name; m->gobble(in); in >> thisTotal; m->gobble(in);
+            if (m->debug) { m->mothurOut("[DEBUG]: " + name + '\t' + toString(thisTotal) + "\n"); }
             
             //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()) {
@@ -63,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;
     }
@@ -72,6 +287,84 @@ int CountTable::readTable(string file) {
        }
 }
 /************************************************************/
+int CountTable::printTable(string file) {
+    try {
+        ofstream out;
+        m->openOutputFile(file, out); 
+               out << "Representative_Sequence\ttotal\t";
+        for (int i = 0; i < groups.size(); i++) { out << groups[i] << '\t'; }
+        out << endl;
+        
+        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) {
+                
+                for (int i = 0; i < groups.size(); i++) {
+                    out << counts[itNames->second][i] << '\t';
+                }
+            }
+            out << endl;
+        }*/
+        out.close();
+        return 0;
+    }
+       catch(exception& e) {
+               m->errorOut(e, "CountTable", "printTable");
+               exit(1);
+       }
+}
+/************************************************************/
+int CountTable::printHeaders(ofstream& out) {
+    try {
+               out << "Representative_Sequence\ttotal\t";
+        for (int i = 0; i < groups.size(); i++) { out << groups[i] << '\t'; }
+        out << endl;
+        return 0;
+    }
+       catch(exception& e) {
+               m->errorOut(e, "CountTable", "printHeaders");
+               exit(1);
+       }
+}
+/************************************************************/
+int CountTable::printSeq(ofstream& out, string seqName) {
+    try {
+               map<string, int>::iterator it = indexNameMap.find(seqName);
+        if (it == indexNameMap.end()) {
+            m->mothurOut("[ERROR]: " + seqName + " is not in your count table. Please correct.\n"); m->control_pressed = true;
+        }else { 
+            out << it->first << '\t' << totals[it->second] << '\t';
+            if (hasGroups) {
+                for (int i = 0; i < groups.size(); i++) {
+                    out << counts[it->second][i] << '\t';
+                }
+            }
+            out << endl;
+        }
+        return 0;
+    }
+       catch(exception& e) {
+               m->errorOut(e, "CountTable", "printSeq");
+               exit(1);
+       }
+}
+/************************************************************/
 //group counts for a seq
 vector<int> CountTable::getGroupCounts(string seqName) {
     try {
@@ -79,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];
@@ -99,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];
             }
@@ -119,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];
                 }
@@ -137,6 +438,189 @@ int CountTable::getGroupCount(string seqName, string groupName) {
                exit(1);
        }
 }
+/************************************************************/
+//set the number of sequences for the seq for the group
+int CountTable::setAbund(string seqName, string groupName, int num) {
+    try {
+        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;
+            }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];
+                    counts[it2->second][it->second] = num;
+                    totalGroups[it->second] += (num - oldCount);
+                    total += (num - oldCount);
+                    totals[it2->second] += (num - oldCount);
+                }
+            }
+        }else{  m->mothurOut("[ERROR]: Your count table does not have group info. Please correct.\n");  m->control_pressed = true; }
+        
+        return 0;
+    }
+       catch(exception& e) {
+               m->errorOut(e, "CountTable", "set");
+               exit(1);
+       }
+}
+/************************************************************/
+//add group
+int CountTable::addGroup(string groupName) {
+    try {        
+        bool sanity = m->inUsersGroups(groupName, groups);
+        if (sanity) { m->mothurOut("[ERROR]: " + groupName + " is already in the count table, cannot add again.\n"); m->control_pressed = true;  return 0; }
+        
+        groups.push_back(groupName);
+        if (!hasGroups) { counts.resize(uniques);  }
+        
+        for (int i = 0; i < counts.size(); i++) { counts[i].push_back(0); }
+        totalGroups.push_back(0);
+        indexGroupMap[groupName] = groups.size()-1;
+        map<string, int> originalGroupMap = indexGroupMap;
+        
+        //important to play well with others, :)
+        sort(groups.begin(), groups.end());
+        
+        //fix indexGroupMap && totalGroups
+        vector<int> newTotals; newTotals.resize(groups.size(), 0);
+        for (int i = 0; i < groups.size(); i++) {  
+            indexGroupMap[groups[i]] = i;  
+            //find original spot of group[i]
+            int index = originalGroupMap[groups[i]];
+            newTotals[i] = totalGroups[index];
+        }
+        totalGroups = newTotals;
+        
+        //fix counts vectors
+        for (int i = 0; i < counts.size(); i++) {
+            vector<int> newCounts; newCounts.resize(groups.size(), 0);
+            for (int j = 0; j < groups.size(); j++) {  
+                //find original spot of group[i]
+                int index = originalGroupMap[groups[j]];
+                newCounts[j] = counts[i][index];
+            }
+            counts[i] = newCounts;
+        }
+        hasGroups = true;
+        m->setAllGroups(groups);
+        
+        return 0;
+    }
+       catch(exception& e) {
+               m->errorOut(e, "CountTable", "addGroup");
+               exit(1);
+       }
+}
+/************************************************************/
+//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 {
+        vector<string> thisGroups;
+        if (hasGroups) {
+            vector<int> thisCounts = getGroupCounts(seqName);
+            for (int i = 0; i < thisCounts.size(); i++) {  
+                if (thisCounts[i] != 0) {  thisGroups.push_back(groups[i]); }
+            } 
+        }else{  m->mothurOut("[ERROR]: Your count table does not have group info. Please correct.\n");  m->control_pressed = true; }
+        
+        return thisGroups;
+    }
+       catch(exception& e) {
+               m->errorOut(e, "CountTable", "getGroups");
+               exit(1);
+       }
+}
+/************************************************************/
+//total number of seqs represented by seq
+int CountTable::renameSeq(string oldSeqName, string newSeqName) {
+    try {
+        
+        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;
+            indexNameMap.erase(it);
+            indexNameMap[newSeqName] = index;
+        }
+        
+        return 0;
+    }
+       catch(exception& e) {
+               m->errorOut(e, "CountTable", "renameSeq");
+               exit(1);
+       }
+}
+
 /************************************************************/
 //total number of seqs represented by seq
 int CountTable::getNumSeqs(string seqName) {
@@ -144,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];
@@ -157,7 +647,147 @@ int CountTable::getNumSeqs(string seqName) {
        }
 }
 /************************************************************/
-//returns names of seqs
+//returns unique index for sequence like get in NameAssignment
+int CountTable::get(string seqName) {
+    try {
+        
+        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; }
+        
+        return -1;
+    }
+       catch(exception& e) {
+               m->errorOut(e, "CountTable", "get");
+               exit(1);
+       }
+}
+/************************************************************/
+//add seqeunce without group info
+int CountTable::push_back(string seqName) {
+    try {
+        map<string, int>::iterator it = indexNameMap.find(seqName);
+        if (it == indexNameMap.end()) {
+            if (hasGroups) {  m->mothurOut("[ERROR]: Your count table has groups and I have no group information for " + seqName + "."); m->mothurOutEndLine(); m->control_pressed = true;  }
+            indexNameMap[seqName] = uniques;
+            totals.push_back(1);
+            total++;
+            uniques++;
+        }else {
+            m->mothurOut("[ERROR]: Your count table contains more than 1 sequence named " + seqName + ", sequence names must be unique. Please correct."); m->mothurOutEndLine(); m->control_pressed = true;
+        }
+        
+        return 0;
+    }
+       catch(exception& e) {
+               m->errorOut(e, "CountTable", "push_back");
+               exit(1);
+       }
+}
+/************************************************************/
+//remove sequence
+int CountTable::remove(string seqName) {
+    try {
+        map<string, int>::iterator it = indexNameMap.find(seqName);
+        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; }
+            }
+            int thisTotal = totals[it->second]; totals[it->second] = 0;
+            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;
+        }
+        
+        return 0;
+    }
+       catch(exception& e) {
+               m->errorOut(e, "CountTable", "push_back");
+               exit(1);
+       }
+}
+/************************************************************/
+//add seqeunce without group info
+int CountTable::push_back(string seqName, int thisTotal) {
+    try {
+        map<string, int>::iterator it = indexNameMap.find(seqName);
+        if (it == indexNameMap.end()) {
+            if (hasGroups) {  m->mothurOut("[ERROR]: Your count table has groups and I have no group information for " + seqName + "."); m->mothurOutEndLine(); m->control_pressed = true;  }
+            indexNameMap[seqName] = uniques;
+            totals.push_back(thisTotal);
+            total+=thisTotal;
+            uniques++;
+        }else {
+            m->mothurOut("[ERROR]: Your count table contains more than 1 sequence named " + seqName + ", sequence names must be unique. Please correct."); m->mothurOutEndLine(); m->control_pressed = true;
+        }
+        
+        return 0;
+    }
+       catch(exception& e) {
+               m->errorOut(e, "CountTable", "push_back");
+               exit(1);
+       }
+}
+/************************************************************/
+//add sequence with group info
+int CountTable::push_back(string seqName, vector<int> groupCounts) {
+    try {
+        map<string, int>::iterator it = indexNameMap.find(seqName);
+        if (it == indexNameMap.end()) {
+            if ((hasGroups) && (groupCounts.size() != getNumGroups())) {  m->mothurOut("[ERROR]: Your count table has a " + toString(getNumGroups()) + " groups and " + seqName + " has " + toString(groupCounts.size()) + ", please correct."); m->mothurOutEndLine(); m->control_pressed = true;  }
+            int thisTotal = 0;
+            for (int i = 0; i < getNumGroups(); i++) {   totalGroups[i] += groupCounts[i];  thisTotal += groupCounts[i]; }
+            if (hasGroups) {  counts.push_back(groupCounts);  }
+            indexNameMap[seqName] = uniques;
+            totals.push_back(thisTotal);
+            total+= thisTotal;
+            uniques++;
+        }else {
+            m->mothurOut("[ERROR]: Your count table contains more than 1 sequence named " + seqName + ", sequence names must be unique. Please correct."); m->mothurOutEndLine(); m->control_pressed = true;
+        }
+        
+        return 0;
+    }
+       catch(exception& e) {
+               m->errorOut(e, "CountTable", "push_back");
+               exit(1);
+       }
+}
+
+/************************************************************/
+//create ListVector from uniques
+ListVector CountTable::getListVector() {
+    try {
+        ListVector list(indexNameMap.size());
+        for (map<string, int>::iterator it = indexNameMap.begin(); it != indexNameMap.end(); it++) { 
+            if (m->control_pressed) { break; }
+            list.set(it->second, it->first); 
+        }
+        return list;
+    }
+       catch(exception& e) {
+               m->errorOut(e, "CountTable", "getListVector");
+               exit(1);
+       }
+}
+
+/************************************************************/
+//returns the names of all unique sequences in file
 vector<string> CountTable::getNamesOfSeqs() {
     try {
         vector<string> names;
@@ -173,5 +803,102 @@ 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 {
+        vector<string> names;
+        if (hasGroups) {
+            map<string, int>::iterator it = indexGroupMap.find(group);
+            if (it == indexGroupMap.end()) {
+                m->mothurOut("[ERROR]: " + group + " is not in your count table. Please correct.\n"); m->control_pressed = true;
+            }else { 
+                for (map<string, int>::iterator it2 = indexNameMap.begin(); it2 != indexNameMap.end(); it2++) {
+                    if (counts[it2->second][it->second] != 0) {  names.push_back(it2->first); }
+                }
+            }
+        }else{  m->mothurOut("[ERROR]: Your count table does not have group info. Please correct.\n");  m->control_pressed = true; }
+        
+        return names;
+    }
+       catch(exception& e) {
+               m->errorOut(e, "CountTable", "getNamesOfSeqs");
+               exit(1);
+       }
+}
+/************************************************************/
+//merges counts of seq1 and seq2, saving in seq1
+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
+                for (int i = 0; i < groups.size(); i++) { counts[it->second][i] += counts[it2->second][i]; }
+                totals[it->second] += totals[it2->second];
+                uniques--;
+                indexNameMap.erase(it2); 
+            }
+        }
+        return 0;
+    }
+       catch(exception& e) {
+               m->errorOut(e, "CountTable", "getNamesOfSeqs");
+               exit(1);
+       }
+}
+/************************************************************/
+int CountTable::copy(CountTable* ct) {
+    try {
+        vector<string> thisGroups = ct->getNamesOfGroups();
+        for (int i = 0; i < thisGroups.size(); i++) { addGroup(thisGroups[i]); }
+        vector<string> names = ct->getNamesOfSeqs();
+                                                               
+        for (int i = 0; i < names.size(); i++) {
+            vector<int> thisCounts = ct->getGroupCounts(names[i]);
+            push_back(names[i], thisCounts);
+        }
+                                                               
+        return 0;
+    }
+       catch(exception& e) {
+               m->errorOut(e, "CountTable", "copy");
+               exit(1);
+       }
+}
+
+/************************************************************/