]> git.donarmstrong.com Git - mothur.git/blob - counttable.cpp
working on pam
[mothur.git] / counttable.cpp
1 //
2 //  counttable.cpp
3 //  Mothur
4 //
5 //  Created by Sarah Westcott on 6/26/12.
6 //  Copyright (c) 2012 Schloss Lab. All rights reserved.
7 //
8
9 #include "counttable.h"
10
11 /************************************************************/
12 int CountTable::createTable(set<string>& n, map<string, string>& g, set<string>& gs) {
13     try {
14         int numGroups = 0;
15         groups.clear();
16         totalGroups.clear();
17         indexGroupMap.clear();
18         indexNameMap.clear();
19         counts.clear();
20         for (set<string>::iterator it = gs.begin(); it != gs.end(); it++) { groups.push_back(*it);  hasGroups = true; }
21         numGroups = groups.size();
22         totalGroups.resize(numGroups, 0);
23         
24                 //sort groups to keep consistent with how we store the groups in groupmap
25         sort(groups.begin(), groups.end());
26         for (int i = 0; i < groups.size(); i++) {  indexGroupMap[groups[i]] = i; }
27         m->setAllGroups(groups);
28         
29         uniques = 0;
30         total = 0;
31         for (set<string>::iterator it = n.begin(); it != n.end(); it++) {
32             
33             if (m->control_pressed) { break; }
34             
35             string seqName = *it;
36             
37             vector<int> groupCounts; groupCounts.resize(numGroups, 0);
38             map<string, string>::iterator itGroup = g.find(seqName);
39             
40             if (itGroup != g.end()) {   
41                 groupCounts[indexGroupMap[itGroup->second]] = 1; 
42                 totalGroups[indexGroupMap[itGroup->second]]++;
43             }else {
44                 //look for it in names of groups to see if the user accidently used the wrong file
45                 if (m->inUsersGroups(seqName, groups)) {
46                     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();
47                 }
48                 m->mothurOut("[ERROR]: Your group file does not contain " + seqName + ". Please correct."); m->mothurOutEndLine();
49             }
50             
51             map<string, int>::iterator it2 = indexNameMap.find(seqName);
52             if (it2 == indexNameMap.end()) {
53                 if (hasGroups) {  counts.push_back(groupCounts);  }
54                 indexNameMap[seqName] = uniques;
55                 totals.push_back(1);
56                 total++;
57                 uniques++;
58             }
59         }
60         
61         if (hasGroups) {
62             for (int i = 0; i < totalGroups.size(); i++) {
63                 if (totalGroups[i] == 0) { m->mothurOut("\nRemoving group: " + groups[i] + " because all sequences have been removed.\n"); removeGroup(groups[i]); i--; }
64             }
65         }
66
67         return 0;
68     }
69         catch(exception& e) {
70                 m->errorOut(e, "CountTable", "createTable");
71                 exit(1);
72         }
73 }
74 /************************************************************/
75 bool CountTable::testGroups(string file) {
76     try {
77         m = MothurOut::getInstance(); hasGroups = false; total = 0;
78         ifstream in;
79         m->openInputFile(file, in);
80     
81         string headers = m->getline(in); m->gobble(in);
82         vector<string> columnHeaders = m->splitWhiteSpace(headers);
83         if (columnHeaders.size() > 2) { hasGroups = true;   }
84         return hasGroups;
85     }
86         catch(exception& e) {
87                 m->errorOut(e, "CountTable", "readTable");
88                 exit(1);
89         }
90 }
91 /************************************************************/
92 int CountTable::createTable(string namefile, string groupfile, bool createGroup) {
93     try {
94         
95         if (namefile == "") { m->mothurOut("[ERROR]: namefile cannot be blank when creating a count table.\n"); m->control_pressed = true; }
96                                            
97         GroupMap* groupMap;
98         int numGroups = 0;
99         groups.clear();
100         totalGroups.clear();
101         indexGroupMap.clear();
102         indexNameMap.clear();
103         counts.clear();
104         map<int, string> originalGroupIndexes;
105         
106         if (groupfile != "") { 
107             hasGroups = true;
108             groupMap = new GroupMap(groupfile); groupMap->readMap();
109             numGroups = groupMap->getNumGroups();
110             groups = groupMap->getNamesOfGroups();
111             totalGroups.resize(numGroups, 0);
112         }else if(createGroup) {
113             hasGroups = true;
114             numGroups = 1;
115             groups.push_back("Group1");
116             totalGroups.resize(numGroups, 0);
117         }
118                 //sort groups to keep consistent with how we store the groups in groupmap
119         sort(groups.begin(), groups.end());
120         for (int i = 0; i < groups.size(); i++) {  indexGroupMap[groups[i]] = i; }
121         m->setAllGroups(groups);
122         
123         bool error = false;
124         string name;
125         uniques = 0;
126         total = 0;
127         
128         
129         //open input file
130         ifstream in;
131         m->openInputFile(namefile, in);
132         
133         int total = 0;
134         while (!in.eof()) {
135             if (m->control_pressed) { break; }
136             
137             string firstCol, secondCol;
138             in >> firstCol; m->gobble(in); in >> secondCol; m->gobble(in);
139             
140             m->checkName(firstCol);
141             m->checkName(secondCol);
142             
143             vector<string> names;
144             m->splitAtChar(secondCol, names, ',');
145             
146             map<string, int> groupCounts;
147             int thisTotal = 0;
148             if (groupfile != "") {
149                 //set to 0
150                 for (int i = 0; i < groups.size(); i++) { groupCounts[groups[i]] = 0; }
151                 
152                 //get counts for each of the users groups
153                 for (int i = 0; i < names.size(); i++) {
154                     string group = groupMap->getGroup(names[i]);
155                     
156                     if (group == "not found") { m->mothurOut("[ERROR]: " + names[i] + " is not in your groupfile, please correct."); m->mothurOutEndLine(); error=true; }
157                     else {
158                         map<string, int>::iterator it = groupCounts.find(group);
159                         
160                         //if not found, then this sequence is not from a group we care about
161                         if (it != groupCounts.end()) {
162                             it->second++;
163                             thisTotal++;
164                         }
165                     }
166                 }
167             }else if (createGroup) {
168                 groupCounts["Group1"]=0;
169                 for (int i = 0; i < names.size(); i++) {
170                     string group = "Group1";
171                     groupCounts["Group1"]++; thisTotal++;
172                 }
173             }else { thisTotal = names.size();  }
174             
175             //if group info, then read it
176             vector<int> thisGroupsCount; thisGroupsCount.resize(numGroups, 0);
177             for (int i = 0; i < numGroups; i++) {  
178                 thisGroupsCount[i] = groupCounts[groups[i]]; 
179                 totalGroups[i] += thisGroupsCount[i]; 
180             }
181             
182             map<string, int>::iterator it = indexNameMap.find(firstCol);
183             if (it == indexNameMap.end()) {
184                 if (hasGroups) {  counts.push_back(thisGroupsCount);  }
185                 indexNameMap[firstCol] = uniques;
186                 totals.push_back(thisTotal);
187                 total += thisTotal;
188                 uniques++;
189             }else {
190                 error = true;
191                 m->mothurOut("[ERROR]: Your count table contains more than 1 sequence named " + firstCol + ", sequence names must be unique. Please correct."); m->mothurOutEndLine(); 
192             }
193         }
194         in.close();
195                 
196         if (error) { m->control_pressed = true; }
197         else { //check for zero groups
198             if (hasGroups) {
199                 for (int i = 0; i < totalGroups.size(); i++) {
200                     if (totalGroups[i] == 0) { m->mothurOut("\nRemoving group: " + groups[i] + " because all sequences have been removed.\n"); removeGroup(groups[i]); i--; }
201                 }
202             }
203         }
204         if (groupfile != "") { delete groupMap; }
205         
206         return 0;
207     }
208         catch(exception& e) {
209                 m->errorOut(e, "CountTable", "createTable");
210                 exit(1);
211         }
212 }
213 /************************************************************/
214 int CountTable::readTable(string file, bool readGroups, bool mothurRunning) {
215     try {
216         filename = file;
217         ifstream in;
218         m->openInputFile(filename, in);
219         
220         string headers = m->getline(in); m->gobble(in);
221         vector<string> columnHeaders = m->splitWhiteSpace(headers);
222         
223         int numGroups = 0;
224         groups.clear();
225         totalGroups.clear();
226         indexGroupMap.clear();
227         indexNameMap.clear();
228         counts.clear();
229         map<int, string> originalGroupIndexes;
230         if ((columnHeaders.size() > 2) && readGroups) { hasGroups = true; numGroups = columnHeaders.size() - 2;  }
231         for (int i = 2; i < columnHeaders.size(); i++) {  groups.push_back(columnHeaders[i]);  originalGroupIndexes[i-2] = columnHeaders[i]; totalGroups.push_back(0); }
232         //sort groups to keep consistent with how we store the groups in groupmap
233         sort(groups.begin(), groups.end());
234         for (int i = 0; i < groups.size(); i++) {  indexGroupMap[groups[i]] = i; }
235         m->setAllGroups(groups);
236         
237         bool error = false;
238         string name;
239         int thisTotal;
240         uniques = 0;
241         total = 0;
242         while (!in.eof()) {
243             
244             if (m->control_pressed) { break; }
245             
246             in >> name; m->gobble(in); in >> thisTotal; m->gobble(in);
247             if (m->debug) { m->mothurOut("[DEBUG]: " + name + '\t' + toString(thisTotal) + "\n"); }
248             
249             if ((thisTotal == 0) && !mothurRunning) { error=true; m->mothurOut("[ERROR]: Your count table contains a sequence named " + name + " with a total=0. Please correct."); m->mothurOutEndLine();
250             }
251             
252             //if group info, then read it
253             vector<int> groupCounts; groupCounts.resize(numGroups, 0);
254             if (columnHeaders.size() > 2) { //file contains groups
255                 if (readGroups) { //user wants to save them
256                     for (int i = 0; i < numGroups; i++) {  int thisIndex = indexGroupMap[originalGroupIndexes[i]]; in >> groupCounts[thisIndex]; m->gobble(in); totalGroups[thisIndex] += groupCounts[thisIndex];  }
257                 }else { //read and discard
258                     m->getline(in); m->gobble(in);
259                 }
260             }
261             
262             map<string, int>::iterator it = indexNameMap.find(name);
263             if (it == indexNameMap.end()) {
264                 if (hasGroups) {  counts.push_back(groupCounts);  }
265                 indexNameMap[name] = uniques;
266                 totals.push_back(thisTotal);
267                 total += thisTotal;
268                 uniques++;
269             }else {
270                 error = true;
271                 m->mothurOut("[ERROR]: Your count table contains more than 1 sequence named " + name + ", sequence names must be unique. Please correct."); m->mothurOutEndLine(); 
272             }
273         }
274         in.close();
275         
276         if (error) { m->control_pressed = true; }
277         else { //check for zero groups
278             if (hasGroups) {
279                 for (int i = 0; i < totalGroups.size(); i++) {
280                     if (totalGroups[i] == 0) { m->mothurOut("\nRemoving group: " + groups[i] + " because all sequences have been removed.\n"); removeGroup(groups[i]); i--; }
281                 }
282             }
283         }
284         
285         return 0;
286     }
287         catch(exception& e) {
288                 m->errorOut(e, "CountTable", "readTable");
289                 exit(1);
290         }
291 }
292 /************************************************************/
293 int CountTable::printTable(string file) {
294     try {
295         ofstream out;
296         m->openOutputFile(file, out); 
297                 out << "Representative_Sequence\ttotal\t";
298         for (int i = 0; i < groups.size(); i++) { out << groups[i] << '\t'; }
299         out << endl;
300         
301         map<int, string> reverse; //use this to preserve order
302         for (map<string, int>::iterator it = indexNameMap.begin(); it !=indexNameMap.end(); it++) { reverse[it->second] = it->first;  }
303         
304         for (int i = 0; i < totals.size(); i++) {
305             map<int, string>::iterator itR = reverse.find(i);
306             
307             if (itR != reverse.end()) { //will equal end if seqs were removed because remove just removes from indexNameMap
308                 out << itR->second << '\t' << totals[i] << '\t';
309                 if (hasGroups) {
310                     for (int j = 0; j < groups.size(); j++) {
311                         out << counts[i][j] << '\t';
312                     }
313                 }
314                 out << endl;
315             }
316         }
317         /*for (map<string, int>::iterator itNames = indexNameMap.begin(); itNames != indexNameMap.end(); itNames++) {
318             out << itNames->first << '\t' << totals[itNames->second] << '\t';
319             if (hasGroups) {
320                 
321                 for (int i = 0; i < groups.size(); i++) {
322                     out << counts[itNames->second][i] << '\t';
323                 }
324             }
325             out << endl;
326         }*/
327         out.close();
328         return 0;
329     }
330         catch(exception& e) {
331                 m->errorOut(e, "CountTable", "printTable");
332                 exit(1);
333         }
334 }
335 /************************************************************/
336 int CountTable::printHeaders(ofstream& out) {
337     try {
338                 out << "Representative_Sequence\ttotal\t";
339         for (int i = 0; i < groups.size(); i++) { out << groups[i] << '\t'; }
340         out << endl;
341         return 0;
342     }
343         catch(exception& e) {
344                 m->errorOut(e, "CountTable", "printHeaders");
345                 exit(1);
346         }
347 }
348 /************************************************************/
349 int CountTable::printSeq(ofstream& out, string seqName) {
350     try {
351                 map<string, int>::iterator it = indexNameMap.find(seqName);
352         if (it == indexNameMap.end()) {
353             m->mothurOut("[ERROR]: " + seqName + " is not in your count table. Please correct.\n"); m->control_pressed = true;
354         }else { 
355             out << it->first << '\t' << totals[it->second] << '\t';
356             if (hasGroups) {
357                 for (int i = 0; i < groups.size(); i++) {
358                     out << counts[it->second][i] << '\t';
359                 }
360             }
361             out << endl;
362         }
363         return 0;
364     }
365         catch(exception& e) {
366                 m->errorOut(e, "CountTable", "printSeq");
367                 exit(1);
368         }
369 }
370 /************************************************************/
371 //group counts for a seq
372 vector<int> CountTable::getGroupCounts(string seqName) {
373     try {
374         vector<int> temp;
375         if (hasGroups) {
376             map<string, int>::iterator it = indexNameMap.find(seqName);
377             if (it == indexNameMap.end()) {
378                 //look for it in names of groups to see if the user accidently used the wrong file
379                 if (m->inUsersGroups(seqName, groups)) {
380                     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();
381                 }
382                 m->mothurOut("[ERROR]: " + seqName + " is not in your count table. Please correct.\n"); m->control_pressed = true;
383             }else { 
384                 temp = counts[it->second];
385             }
386         }else{  m->mothurOut("[ERROR]: Your count table does not have group info. Please correct.\n"); m->control_pressed = true; }
387         
388         return temp;
389     }
390         catch(exception& e) {
391                 m->errorOut(e, "CountTable", "getGroupCounts");
392                 exit(1);
393         }
394 }
395 /************************************************************/
396 //total number of sequences for the group
397 int CountTable::getGroupCount(string groupName) {
398     try {
399         if (hasGroups) {
400             map<string, int>::iterator it = indexGroupMap.find(groupName);
401             if (it == indexGroupMap.end()) {
402                 m->mothurOut("[ERROR]: group " + groupName + " is not in your count table. Please correct.\n"); m->control_pressed = true;
403             }else { 
404                 return totalGroups[it->second];
405             }
406         }else{  m->mothurOut("[ERROR]: Your count table does not have group info. Please correct.\n");  m->control_pressed = true; }
407
408         return 0;
409     }
410         catch(exception& e) {
411                 m->errorOut(e, "CountTable", "getGroupCount");
412                 exit(1);
413         }
414 }
415 /************************************************************/
416 //total number of sequences for the seq for the group
417 int CountTable::getGroupCount(string seqName, string groupName) {
418     try {
419         if (hasGroups) {
420             map<string, int>::iterator it = indexGroupMap.find(groupName);
421             if (it == indexGroupMap.end()) {
422                 m->mothurOut("[ERROR]: group " + groupName + " is not in your count table. Please correct.\n"); m->control_pressed = true;
423             }else { 
424                 map<string, int>::iterator it2 = indexNameMap.find(seqName);
425                 if (it2 == indexNameMap.end()) {
426                     //look for it in names of groups to see if the user accidently used the wrong file
427                     if (m->inUsersGroups(seqName, groups)) {
428                         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();
429                     }
430                     m->mothurOut("[ERROR]: seq " + seqName + " is not in your count table. Please correct.\n"); m->control_pressed = true;
431                 }else { 
432                     return counts[it2->second][it->second];
433                 }
434             }
435         }else{  m->mothurOut("[ERROR]: Your count table does not have group info. Please correct.\n");  m->control_pressed = true; }
436         
437         return 0;
438     }
439         catch(exception& e) {
440                 m->errorOut(e, "CountTable", "getGroupCount");
441                 exit(1);
442         }
443 }
444 /************************************************************/
445 //set the number of sequences for the seq for the group
446 int CountTable::setAbund(string seqName, string groupName, int num) {
447     try {
448         if (hasGroups) {
449             map<string, int>::iterator it = indexGroupMap.find(groupName);
450             if (it == indexGroupMap.end()) {
451                 m->mothurOut("[ERROR]: " + groupName + " is not in your count table. Please correct.\n"); m->control_pressed = true;
452             }else { 
453                 map<string, int>::iterator it2 = indexNameMap.find(seqName);
454                 if (it2 == indexNameMap.end()) {
455                     //look for it in names of groups to see if the user accidently used the wrong file
456                     if (m->inUsersGroups(seqName, groups)) {
457                         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();
458                     }
459                     m->mothurOut("[ERROR]: " + seqName + " is not in your count table. Please correct.\n"); m->control_pressed = true;
460                 }else { 
461                     int oldCount = counts[it2->second][it->second];
462                     counts[it2->second][it->second] = num;
463                     totalGroups[it->second] += (num - oldCount);
464                     total += (num - oldCount);
465                     totals[it2->second] += (num - oldCount);
466                 }
467             }
468         }else{  m->mothurOut("[ERROR]: Your count table does not have group info. Please correct.\n");  m->control_pressed = true; }
469         
470         return 0;
471     }
472         catch(exception& e) {
473                 m->errorOut(e, "CountTable", "set");
474                 exit(1);
475         }
476 }
477 /************************************************************/
478 //add group
479 int CountTable::addGroup(string groupName) {
480     try {        
481         bool sanity = m->inUsersGroups(groupName, groups);
482         if (sanity) { m->mothurOut("[ERROR]: " + groupName + " is already in the count table, cannot add again.\n"); m->control_pressed = true;  return 0; }
483         
484         groups.push_back(groupName);
485         if (!hasGroups) { counts.resize(uniques);  }
486         
487         for (int i = 0; i < counts.size(); i++) { counts[i].push_back(0); }
488         totalGroups.push_back(0);
489         indexGroupMap[groupName] = groups.size()-1;
490         map<string, int> originalGroupMap = indexGroupMap;
491         
492         //important to play well with others, :)
493         sort(groups.begin(), groups.end());
494         
495         //fix indexGroupMap && totalGroups
496         vector<int> newTotals; newTotals.resize(groups.size(), 0);
497         for (int i = 0; i < groups.size(); i++) {  
498             indexGroupMap[groups[i]] = i;  
499             //find original spot of group[i]
500             int index = originalGroupMap[groups[i]];
501             newTotals[i] = totalGroups[index];
502         }
503         totalGroups = newTotals;
504         
505         //fix counts vectors
506         for (int i = 0; i < counts.size(); i++) {
507             vector<int> newCounts; newCounts.resize(groups.size(), 0);
508             for (int j = 0; j < groups.size(); j++) {  
509                 //find original spot of group[i]
510                 int index = originalGroupMap[groups[j]];
511                 newCounts[j] = counts[i][index];
512             }
513             counts[i] = newCounts;
514         }
515         hasGroups = true;
516         m->setAllGroups(groups);
517         
518         return 0;
519     }
520         catch(exception& e) {
521                 m->errorOut(e, "CountTable", "addGroup");
522                 exit(1);
523         }
524 }
525 /************************************************************/
526 //remove group
527 int CountTable::removeGroup(string groupName) {
528     try {        
529         if (hasGroups) {
530             //save for later in case removing a group means we need to remove a seq.
531             map<int, string> reverse;
532             for (map<string, int>::iterator it = indexNameMap.begin(); it !=indexNameMap.end(); it++) { reverse[it->second] = it->first;  }
533             
534             map<string, int>::iterator it = indexGroupMap.find(groupName);
535             if (it == indexGroupMap.end()) {
536                 m->mothurOut("[ERROR]: " + groupName + " is not in your count table. Please correct.\n"); m->control_pressed = true;
537             }else { 
538                 int indexOfGroupToRemove = it->second;
539                 map<string, int> currentGroupIndex = indexGroupMap;
540                 vector<string> newGroups;
541                 for (int i = 0; i < groups.size(); i++) {
542                     if (groups[i] != groupName) { 
543                         newGroups.push_back(groups[i]);
544                         indexGroupMap[groups[i]] = newGroups.size()-1;
545                     }
546                 }
547                 indexGroupMap.erase(groupName);
548                 groups = newGroups;
549                 totalGroups.erase(totalGroups.begin()+indexOfGroupToRemove);
550                 
551                 int thisIndex = 0;
552                 map<string, int> newIndexNameMap;
553                 for (int i = 0; i < counts.size(); i++) {
554                     int num = counts[i][indexOfGroupToRemove];
555                     counts[i].erase(counts[i].begin()+indexOfGroupToRemove);
556                     totals[i] -= num;
557                     total -= num;
558                     if (totals[i] == 0) { //your sequences are only from the group we want to remove, then remove you.
559                         counts.erase(counts.begin()+i);
560                         totals.erase(totals.begin()+i);
561                         uniques--;
562                         i--;
563                     }
564                     newIndexNameMap[reverse[thisIndex]] = i;
565                     thisIndex++;
566                 }
567                 indexNameMap = newIndexNameMap;
568                 
569                 if (groups.size() == 0) { hasGroups = false; }
570             }
571         }else { m->mothurOut("[ERROR]: your count table does not contain group information, can not remove group " + groupName + ".\n"); m->control_pressed = true; }
572     
573         return 0;
574     }
575         catch(exception& e) {
576                 m->errorOut(e, "CountTable", "removeGroup");
577                 exit(1);
578         }
579 }
580 /************************************************************/
581 //vector of groups for the seq
582 vector<string> CountTable::getGroups(string seqName) {
583     try {
584         vector<string> thisGroups;
585         if (hasGroups) {
586             vector<int> thisCounts = getGroupCounts(seqName);
587             for (int i = 0; i < thisCounts.size(); i++) {  
588                 if (thisCounts[i] != 0) {  thisGroups.push_back(groups[i]); }
589             } 
590         }else{  m->mothurOut("[ERROR]: Your count table does not have group info. Please correct.\n");  m->control_pressed = true; }
591         
592         return thisGroups;
593     }
594         catch(exception& e) {
595                 m->errorOut(e, "CountTable", "getGroups");
596                 exit(1);
597         }
598 }
599 /************************************************************/
600 //total number of seqs represented by seq
601 int CountTable::renameSeq(string oldSeqName, string newSeqName) {
602     try {
603         
604         map<string, int>::iterator it = indexNameMap.find(oldSeqName);
605         if (it == indexNameMap.end()) {
606             if (hasGroupInfo()) {
607                 //look for it in names of groups to see if the user accidently used the wrong file
608                 if (m->inUsersGroups(oldSeqName, groups)) {
609                     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();
610                 }
611             }
612             m->mothurOut("[ERROR]: " + oldSeqName + " is not in your count table. Please correct.\n"); m->control_pressed = true;
613         }else {  
614             int index = it->second;
615             indexNameMap.erase(it);
616             indexNameMap[newSeqName] = index;
617         }
618         
619         return 0;
620     }
621         catch(exception& e) {
622                 m->errorOut(e, "CountTable", "renameSeq");
623                 exit(1);
624         }
625 }
626
627 /************************************************************/
628 //total number of seqs represented by seq
629 int CountTable::getNumSeqs(string seqName) {
630     try {
631                 
632         map<string, int>::iterator it = indexNameMap.find(seqName);
633         if (it == indexNameMap.end()) {
634             if (hasGroupInfo()) {
635                 //look for it in names of groups to see if the user accidently used the wrong file
636                 if (m->inUsersGroups(seqName, groups)) {
637                     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();
638                 }
639             }
640             m->mothurOut("[ERROR]: " + seqName + " is not in your count table. Please correct.\n"); m->control_pressed = true;
641         }else { 
642             return totals[it->second];
643         }
644
645         return 0;
646     }
647         catch(exception& e) {
648                 m->errorOut(e, "CountTable", "getNumSeqs");
649                 exit(1);
650         }
651 }
652 /************************************************************/
653 //returns unique index for sequence like get in NameAssignment
654 int CountTable::get(string seqName) {
655     try {
656         
657         map<string, int>::iterator it = indexNameMap.find(seqName);
658         if (it == indexNameMap.end()) {
659             if (hasGroupInfo()) {
660                 //look for it in names of groups to see if the user accidently used the wrong file
661                 if (m->inUsersGroups(seqName, groups)) {
662                     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();
663                 }
664             }
665             m->mothurOut("[ERROR]: " + seqName + " is not in your count table. Please correct.\n"); m->control_pressed = true;
666         }else { return it->second; }
667         
668         return -1;
669     }
670         catch(exception& e) {
671                 m->errorOut(e, "CountTable", "get");
672                 exit(1);
673         }
674 }
675 /************************************************************/
676 //add seqeunce without group info
677 int CountTable::push_back(string seqName) {
678     try {
679         map<string, int>::iterator it = indexNameMap.find(seqName);
680         if (it == indexNameMap.end()) {
681             if (hasGroups) {  m->mothurOut("[ERROR]: Your count table has groups and I have no group information for " + seqName + "."); m->mothurOutEndLine(); m->control_pressed = true;  }
682             indexNameMap[seqName] = uniques;
683             totals.push_back(1);
684             total++;
685             uniques++;
686         }else {
687             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;
688         }
689         
690         return 0;
691     }
692         catch(exception& e) {
693                 m->errorOut(e, "CountTable", "push_back");
694                 exit(1);
695         }
696 }
697 /************************************************************/
698 //remove sequence
699 int CountTable::remove(string seqName) {
700     try {
701         map<string, int>::iterator it = indexNameMap.find(seqName);
702         if (it != indexNameMap.end()) {
703             uniques--;
704             if (hasGroups){ //remove this sequences counts from group totals
705                 for (int i = 0; i < totalGroups.size(); i++) {  totalGroups[i] -= counts[it->second][i];  counts[it->second][i] = 0; }
706             }
707             int thisTotal = totals[it->second]; totals[it->second] = 0;
708             total -= thisTotal;
709             indexNameMap.erase(it);
710         }else {
711             if (hasGroupInfo()) {
712                 //look for it in names of groups to see if the user accidently used the wrong file
713                 if (m->inUsersGroups(seqName, groups)) {
714                     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();
715                 }
716             }
717             m->mothurOut("[ERROR]: Your count table contains does not include " + seqName + ", cannot remove."); m->mothurOutEndLine(); m->control_pressed = true;
718         }
719         
720         return 0;
721     }
722         catch(exception& e) {
723                 m->errorOut(e, "CountTable", "push_back");
724                 exit(1);
725         }
726 }
727 /************************************************************/
728 //add seqeunce without group info
729 int CountTable::push_back(string seqName, int thisTotal) {
730     try {
731         map<string, int>::iterator it = indexNameMap.find(seqName);
732         if (it == indexNameMap.end()) {
733             if (hasGroups) {  m->mothurOut("[ERROR]: Your count table has groups and I have no group information for " + seqName + "."); m->mothurOutEndLine(); m->control_pressed = true;  }
734             indexNameMap[seqName] = uniques;
735             totals.push_back(thisTotal);
736             total+=thisTotal;
737             uniques++;
738         }else {
739             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;
740         }
741         
742         return 0;
743     }
744         catch(exception& e) {
745                 m->errorOut(e, "CountTable", "push_back");
746                 exit(1);
747         }
748 }
749 /************************************************************/
750 //add sequence with group info
751 int CountTable::push_back(string seqName, vector<int> groupCounts) {
752     try {
753         map<string, int>::iterator it = indexNameMap.find(seqName);
754         if (it == indexNameMap.end()) {
755             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;  }
756             int thisTotal = 0;
757             for (int i = 0; i < getNumGroups(); i++) {   totalGroups[i] += groupCounts[i];  thisTotal += groupCounts[i]; }
758             if (hasGroups) {  counts.push_back(groupCounts);  }
759             indexNameMap[seqName] = uniques;
760             totals.push_back(thisTotal);
761             total+= thisTotal;
762             uniques++;
763         }else {
764             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;
765         }
766         
767         return 0;
768     }
769         catch(exception& e) {
770                 m->errorOut(e, "CountTable", "push_back");
771                 exit(1);
772         }
773 }
774
775 /************************************************************/
776 //create ListVector from uniques
777 ListVector CountTable::getListVector() {
778     try {
779         ListVector list(indexNameMap.size());
780         for (map<string, int>::iterator it = indexNameMap.begin(); it != indexNameMap.end(); it++) { 
781             if (m->control_pressed) { break; }
782             list.set(it->second, it->first); 
783         }
784         return list;
785     }
786         catch(exception& e) {
787                 m->errorOut(e, "CountTable", "getListVector");
788                 exit(1);
789         }
790 }
791
792 /************************************************************/
793 //returns the names of all unique sequences in file
794 vector<string> CountTable::getNamesOfSeqs() {
795     try {
796         vector<string> names;
797         for (map<string, int>::iterator it = indexNameMap.begin(); it != indexNameMap.end(); it++) {
798             names.push_back(it->first);
799         }
800                 
801         return names;
802     }
803         catch(exception& e) {
804                 m->errorOut(e, "CountTable", "getNamesOfSeqs");
805                 exit(1);
806         }
807 }
808 /************************************************************/
809 //returns the names of all unique sequences in file mapped to their seqCounts
810 map<string, int> CountTable::getNameMap() {
811     try {
812         map<string, int> names;
813         for (map<string, int>::iterator it = indexNameMap.begin(); it != indexNameMap.end(); it++) {
814             names[it->first] = totals[it->second];
815         }
816         
817         return names;
818     }
819         catch(exception& e) {
820                 m->errorOut(e, "CountTable", "getNameMap");
821                 exit(1);
822         }
823 }
824 /************************************************************/
825 //returns the names of all unique sequences in file
826 vector<string> CountTable::getNamesOfSeqs(string group) {
827     try {
828         vector<string> names;
829         if (hasGroups) {
830             map<string, int>::iterator it = indexGroupMap.find(group);
831             if (it == indexGroupMap.end()) {
832                 m->mothurOut("[ERROR]: " + group + " is not in your count table. Please correct.\n"); m->control_pressed = true;
833             }else { 
834                 for (map<string, int>::iterator it2 = indexNameMap.begin(); it2 != indexNameMap.end(); it2++) {
835                     if (counts[it2->second][it->second] != 0) {  names.push_back(it2->first); }
836                 }
837             }
838         }else{  m->mothurOut("[ERROR]: Your count table does not have group info. Please correct.\n");  m->control_pressed = true; }
839         
840         return names;
841     }
842         catch(exception& e) {
843                 m->errorOut(e, "CountTable", "getNamesOfSeqs");
844                 exit(1);
845         }
846 }
847 /************************************************************/
848 //merges counts of seq1 and seq2, saving in seq1
849 int CountTable::mergeCounts(string seq1, string seq2) {
850     try {
851         map<string, int>::iterator it = indexNameMap.find(seq1);
852         if (it == indexNameMap.end()) {
853             if (hasGroupInfo()) {
854                 //look for it in names of groups to see if the user accidently used the wrong file
855                 if (m->inUsersGroups(seq1, groups)) {
856                     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();
857                 }
858             }
859             m->mothurOut("[ERROR]: " + seq1 + " is not in your count table. Please correct.\n"); m->control_pressed = true;
860         }else { 
861             map<string, int>::iterator it2 = indexNameMap.find(seq2);
862             if (it2 == indexNameMap.end()) {
863                 if (hasGroupInfo()) {
864                     //look for it in names of groups to see if the user accidently used the wrong file
865                     if (m->inUsersGroups(seq2, groups)) {
866                         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();
867                     }
868                 }
869                 m->mothurOut("[ERROR]: " + seq2 + " is not in your count table. Please correct.\n"); m->control_pressed = true;
870             }else { 
871                 //merge data
872                 for (int i = 0; i < groups.size(); i++) { counts[it->second][i] += counts[it2->second][i]; }
873                 totals[it->second] += totals[it2->second];
874                 uniques--;
875                 indexNameMap.erase(it2); 
876             }
877         }
878         return 0;
879     }
880         catch(exception& e) {
881                 m->errorOut(e, "CountTable", "getNamesOfSeqs");
882                 exit(1);
883         }
884 }
885 /************************************************************/
886 int CountTable::copy(CountTable* ct) {
887     try {
888         vector<string> thisGroups = ct->getNamesOfGroups();
889         for (int i = 0; i < thisGroups.size(); i++) { addGroup(thisGroups[i]); }
890         vector<string> names = ct->getNamesOfSeqs();
891                                                                
892         for (int i = 0; i < names.size(); i++) {
893             vector<int> thisCounts = ct->getGroupCounts(names[i]);
894             push_back(names[i], thisCounts);
895         }
896                                                                
897         return 0;
898     }
899         catch(exception& e) {
900                 m->errorOut(e, "CountTable", "copy");
901                 exit(1);
902         }
903 }
904
905 /************************************************************/
906
907