]> git.donarmstrong.com Git - mothur.git/blob - counttable.cpp
added name, group and count files to chop.seqs. added intelligent warnings for when...
[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) {
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) { 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 group info, then read it
250             vector<int> groupCounts; groupCounts.resize(numGroups, 0);
251             for (int i = 0; i < numGroups; i++) {  int thisIndex = indexGroupMap[originalGroupIndexes[i]]; in >> groupCounts[thisIndex]; m->gobble(in); totalGroups[thisIndex] += groupCounts[thisIndex];  }
252             
253             map<string, int>::iterator it = indexNameMap.find(name);
254             if (it == indexNameMap.end()) {
255                 if (hasGroups) {  counts.push_back(groupCounts);  }
256                 indexNameMap[name] = uniques;
257                 totals.push_back(thisTotal);
258                 total += thisTotal;
259                 uniques++;
260             }else {
261                 error = true;
262                 m->mothurOut("[ERROR]: Your count table contains more than 1 sequence named " + name + ", sequence names must be unique. Please correct."); m->mothurOutEndLine(); 
263             }
264         }
265         in.close();
266         
267         if (error) { m->control_pressed = true; }
268         else { //check for zero groups
269             if (hasGroups) {
270                 for (int i = 0; i < totalGroups.size(); i++) {
271                     if (totalGroups[i] == 0) { m->mothurOut("\nRemoving group: " + groups[i] + " because all sequences have been removed.\n"); removeGroup(groups[i]); i--; }
272                 }
273             }
274         }
275         
276         return 0;
277     }
278         catch(exception& e) {
279                 m->errorOut(e, "CountTable", "readTable");
280                 exit(1);
281         }
282 }
283 /************************************************************/
284 int CountTable::printTable(string file) {
285     try {
286         ofstream out;
287         m->openOutputFile(file, out); 
288                 out << "Representative_Sequence\ttotal\t";
289         for (int i = 0; i < groups.size(); i++) { out << groups[i] << '\t'; }
290         out << endl;
291         
292         map<int, string> reverse; //use this to preserve order
293         for (map<string, int>::iterator it = indexNameMap.begin(); it !=indexNameMap.end(); it++) { reverse[it->second] = it->first;  }
294         
295         for (int i = 0; i < totals.size(); i++) {
296             map<int, string>::iterator itR = reverse.find(i);
297             
298             if (itR != reverse.end()) { //will equal end if seqs were removed because remove just removes from indexNameMap
299                 out << itR->second << '\t' << totals[i] << '\t';
300                 if (hasGroups) {
301                     for (int j = 0; j < groups.size(); j++) {
302                         out << counts[i][j] << '\t';
303                     }
304                 }
305                 out << endl;
306             }
307         }
308         /*for (map<string, int>::iterator itNames = indexNameMap.begin(); itNames != indexNameMap.end(); itNames++) {
309             out << itNames->first << '\t' << totals[itNames->second] << '\t';
310             if (hasGroups) {
311                 
312                 for (int i = 0; i < groups.size(); i++) {
313                     out << counts[itNames->second][i] << '\t';
314                 }
315             }
316             out << endl;
317         }*/
318         out.close();
319         return 0;
320     }
321         catch(exception& e) {
322                 m->errorOut(e, "CountTable", "printTable");
323                 exit(1);
324         }
325 }
326 /************************************************************/
327 int CountTable::printHeaders(ofstream& out) {
328     try {
329                 out << "Representative_Sequence\ttotal\t";
330         for (int i = 0; i < groups.size(); i++) { out << groups[i] << '\t'; }
331         out << endl;
332         return 0;
333     }
334         catch(exception& e) {
335                 m->errorOut(e, "CountTable", "printHeaders");
336                 exit(1);
337         }
338 }
339 /************************************************************/
340 int CountTable::printSeq(ofstream& out, string seqName) {
341     try {
342                 map<string, int>::iterator it = indexNameMap.find(seqName);
343         if (it == indexNameMap.end()) {
344             m->mothurOut("[ERROR]: " + seqName + " is not in your count table. Please correct.\n"); m->control_pressed = true;
345         }else { 
346             out << it->first << '\t' << totals[it->second] << '\t';
347             if (hasGroups) {
348                 for (int i = 0; i < groups.size(); i++) {
349                     out << counts[it->second][i] << '\t';
350                 }
351             }
352             out << endl;
353         }
354         return 0;
355     }
356         catch(exception& e) {
357                 m->errorOut(e, "CountTable", "printSeq");
358                 exit(1);
359         }
360 }
361 /************************************************************/
362 //group counts for a seq
363 vector<int> CountTable::getGroupCounts(string seqName) {
364     try {
365         vector<int> temp;
366         if (hasGroups) {
367             map<string, int>::iterator it = indexNameMap.find(seqName);
368             if (it == indexNameMap.end()) {
369                 //look for it in names of groups to see if the user accidently used the wrong file
370                 if (m->inUsersGroups(seqName, groups)) {
371                     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();
372                 }
373                 m->mothurOut("[ERROR]: " + seqName + " is not in your count table. Please correct.\n"); m->control_pressed = true;
374             }else { 
375                 temp = counts[it->second];
376             }
377         }else{  m->mothurOut("[ERROR]: Your count table does not have group info. Please correct.\n"); m->control_pressed = true; }
378         
379         return temp;
380     }
381         catch(exception& e) {
382                 m->errorOut(e, "CountTable", "getGroupCounts");
383                 exit(1);
384         }
385 }
386 /************************************************************/
387 //total number of sequences for the group
388 int CountTable::getGroupCount(string groupName) {
389     try {
390         if (hasGroups) {
391             map<string, int>::iterator it = indexGroupMap.find(groupName);
392             if (it == indexGroupMap.end()) {
393                 m->mothurOut("[ERROR]: group " + groupName + " is not in your count table. Please correct.\n"); m->control_pressed = true;
394             }else { 
395                 return totalGroups[it->second];
396             }
397         }else{  m->mothurOut("[ERROR]: Your count table does not have group info. Please correct.\n");  m->control_pressed = true; }
398
399         return 0;
400     }
401         catch(exception& e) {
402                 m->errorOut(e, "CountTable", "getGroupCount");
403                 exit(1);
404         }
405 }
406 /************************************************************/
407 //total number of sequences for the seq for the group
408 int CountTable::getGroupCount(string seqName, string groupName) {
409     try {
410         if (hasGroups) {
411             map<string, int>::iterator it = indexGroupMap.find(groupName);
412             if (it == indexGroupMap.end()) {
413                 m->mothurOut("[ERROR]: group " + groupName + " is not in your count table. Please correct.\n"); m->control_pressed = true;
414             }else { 
415                 map<string, int>::iterator it2 = indexNameMap.find(seqName);
416                 if (it2 == indexNameMap.end()) {
417                     //look for it in names of groups to see if the user accidently used the wrong file
418                     if (m->inUsersGroups(seqName, groups)) {
419                         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();
420                     }
421                     m->mothurOut("[ERROR]: seq " + seqName + " is not in your count table. Please correct.\n"); m->control_pressed = true;
422                 }else { 
423                     return counts[it2->second][it->second];
424                 }
425             }
426         }else{  m->mothurOut("[ERROR]: Your count table does not have group info. Please correct.\n");  m->control_pressed = true; }
427         
428         return 0;
429     }
430         catch(exception& e) {
431                 m->errorOut(e, "CountTable", "getGroupCount");
432                 exit(1);
433         }
434 }
435 /************************************************************/
436 //set the number of sequences for the seq for the group
437 int CountTable::setAbund(string seqName, string groupName, int num) {
438     try {
439         if (hasGroups) {
440             map<string, int>::iterator it = indexGroupMap.find(groupName);
441             if (it == indexGroupMap.end()) {
442                 m->mothurOut("[ERROR]: " + groupName + " is not in your count table. Please correct.\n"); m->control_pressed = true;
443             }else { 
444                 map<string, int>::iterator it2 = indexNameMap.find(seqName);
445                 if (it2 == indexNameMap.end()) {
446                     //look for it in names of groups to see if the user accidently used the wrong file
447                     if (m->inUsersGroups(seqName, groups)) {
448                         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();
449                     }
450                     m->mothurOut("[ERROR]: " + seqName + " is not in your count table. Please correct.\n"); m->control_pressed = true;
451                 }else { 
452                     int oldCount = counts[it2->second][it->second];
453                     counts[it2->second][it->second] = num;
454                     totalGroups[it->second] += (num - oldCount);
455                     total += (num - oldCount);
456                     totals[it2->second] += (num - oldCount);
457                 }
458             }
459         }else{  m->mothurOut("[ERROR]: Your count table does not have group info. Please correct.\n");  m->control_pressed = true; }
460         
461         return 0;
462     }
463         catch(exception& e) {
464                 m->errorOut(e, "CountTable", "set");
465                 exit(1);
466         }
467 }
468 /************************************************************/
469 //add group
470 int CountTable::addGroup(string groupName) {
471     try {        
472         bool sanity = m->inUsersGroups(groupName, groups);
473         if (sanity) { m->mothurOut("[ERROR]: " + groupName + " is already in the count table, cannot add again.\n"); m->control_pressed = true;  return 0; }
474         
475         groups.push_back(groupName);
476         if (!hasGroups) { counts.resize(uniques);  }
477         
478         for (int i = 0; i < counts.size(); i++) { counts[i].push_back(0); }
479         totalGroups.push_back(0);
480         indexGroupMap[groupName] = groups.size()-1;
481         map<string, int> originalGroupMap = indexGroupMap;
482         
483         //important to play well with others, :)
484         sort(groups.begin(), groups.end());
485         
486         //fix indexGroupMap && totalGroups
487         vector<int> newTotals; newTotals.resize(groups.size(), 0);
488         for (int i = 0; i < groups.size(); i++) {  
489             indexGroupMap[groups[i]] = i;  
490             //find original spot of group[i]
491             int index = originalGroupMap[groups[i]];
492             newTotals[i] = totalGroups[index];
493         }
494         totalGroups = newTotals;
495         
496         //fix counts vectors
497         for (int i = 0; i < counts.size(); i++) {
498             vector<int> newCounts; newCounts.resize(groups.size(), 0);
499             for (int j = 0; j < groups.size(); j++) {  
500                 //find original spot of group[i]
501                 int index = originalGroupMap[groups[j]];
502                 newCounts[j] = counts[i][index];
503             }
504             counts[i] = newCounts;
505         }
506         hasGroups = true;
507         m->setAllGroups(groups);
508         
509         return 0;
510     }
511         catch(exception& e) {
512                 m->errorOut(e, "CountTable", "addGroup");
513                 exit(1);
514         }
515 }
516 /************************************************************/
517 //remove group
518 int CountTable::removeGroup(string groupName) {
519     try {        
520         if (hasGroups) {
521             //save for later in case removing a group means we need to remove a seq.
522             map<int, string> reverse;
523             for (map<string, int>::iterator it = indexNameMap.begin(); it !=indexNameMap.end(); it++) { reverse[it->second] = it->first;  }
524             
525             map<string, int>::iterator it = indexGroupMap.find(groupName);
526             if (it == indexGroupMap.end()) {
527                 m->mothurOut("[ERROR]: " + groupName + " is not in your count table. Please correct.\n"); m->control_pressed = true;
528             }else { 
529                 int indexOfGroupToRemove = it->second;
530                 map<string, int> currentGroupIndex = indexGroupMap;
531                 vector<string> newGroups;
532                 for (int i = 0; i < groups.size(); i++) {
533                     if (groups[i] != groupName) { 
534                         newGroups.push_back(groups[i]);
535                         indexGroupMap[groups[i]] = newGroups.size()-1;
536                     }
537                 }
538                 indexGroupMap.erase(groupName);
539                 groups = newGroups;
540                 totalGroups.erase(totalGroups.begin()+indexOfGroupToRemove);
541                 
542                 int thisIndex = 0;
543                 map<string, int> newIndexNameMap;
544                 for (int i = 0; i < counts.size(); i++) {
545                     int num = counts[i][indexOfGroupToRemove];
546                     counts[i].erase(counts[i].begin()+indexOfGroupToRemove);
547                     totals[i] -= num;
548                     total -= num;
549                     if (totals[i] == 0) { //your sequences are only from the group we want to remove, then remove you.
550                         counts.erase(counts.begin()+i);
551                         totals.erase(totals.begin()+i);
552                         uniques--;
553                         i--;
554                     }
555                     newIndexNameMap[reverse[thisIndex]] = i;
556                     thisIndex++;
557                 }
558                 indexNameMap = newIndexNameMap;
559                 
560                 if (groups.size() == 0) { hasGroups = false; }
561             }
562         }else { m->mothurOut("[ERROR]: your count table does not contain group information, can not remove group " + groupName + ".\n"); m->control_pressed = true; }
563     
564         return 0;
565     }
566         catch(exception& e) {
567                 m->errorOut(e, "CountTable", "removeGroup");
568                 exit(1);
569         }
570 }
571 /************************************************************/
572 //vector of groups for the seq
573 vector<string> CountTable::getGroups(string seqName) {
574     try {
575         vector<string> thisGroups;
576         if (hasGroups) {
577             vector<int> thisCounts = getGroupCounts(seqName);
578             for (int i = 0; i < thisCounts.size(); i++) {  
579                 if (thisCounts[i] != 0) {  thisGroups.push_back(groups[i]); }
580             } 
581         }else{  m->mothurOut("[ERROR]: Your count table does not have group info. Please correct.\n");  m->control_pressed = true; }
582         
583         return thisGroups;
584     }
585         catch(exception& e) {
586                 m->errorOut(e, "CountTable", "getGroups");
587                 exit(1);
588         }
589 }
590 /************************************************************/
591 //total number of seqs represented by seq
592 int CountTable::renameSeq(string oldSeqName, string newSeqName) {
593     try {
594         
595         map<string, int>::iterator it = indexNameMap.find(oldSeqName);
596         if (it == indexNameMap.end()) {
597             if (hasGroupInfo()) {
598                 //look for it in names of groups to see if the user accidently used the wrong file
599                 if (m->inUsersGroups(oldSeqName, groups)) {
600                     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();
601                 }
602             }
603             m->mothurOut("[ERROR]: " + oldSeqName + " is not in your count table. Please correct.\n"); m->control_pressed = true;
604         }else {  
605             int index = it->second;
606             indexNameMap.erase(it);
607             indexNameMap[newSeqName] = index;
608         }
609         
610         return 0;
611     }
612         catch(exception& e) {
613                 m->errorOut(e, "CountTable", "renameSeq");
614                 exit(1);
615         }
616 }
617
618 /************************************************************/
619 //total number of seqs represented by seq
620 int CountTable::getNumSeqs(string seqName) {
621     try {
622                 
623         map<string, int>::iterator it = indexNameMap.find(seqName);
624         if (it == indexNameMap.end()) {
625             if (hasGroupInfo()) {
626                 //look for it in names of groups to see if the user accidently used the wrong file
627                 if (m->inUsersGroups(seqName, groups)) {
628                     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();
629                 }
630             }
631             m->mothurOut("[ERROR]: " + seqName + " is not in your count table. Please correct.\n"); m->control_pressed = true;
632         }else { 
633             return totals[it->second];
634         }
635
636         return 0;
637     }
638         catch(exception& e) {
639                 m->errorOut(e, "CountTable", "getNumSeqs");
640                 exit(1);
641         }
642 }
643 /************************************************************/
644 //returns unique index for sequence like get in NameAssignment
645 int CountTable::get(string seqName) {
646     try {
647         
648         map<string, int>::iterator it = indexNameMap.find(seqName);
649         if (it == indexNameMap.end()) {
650             if (hasGroupInfo()) {
651                 //look for it in names of groups to see if the user accidently used the wrong file
652                 if (m->inUsersGroups(seqName, groups)) {
653                     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();
654                 }
655             }
656             m->mothurOut("[ERROR]: " + seqName + " is not in your count table. Please correct.\n"); m->control_pressed = true;
657         }else { return it->second; }
658         
659         return -1;
660     }
661         catch(exception& e) {
662                 m->errorOut(e, "CountTable", "get");
663                 exit(1);
664         }
665 }
666 /************************************************************/
667 //add seqeunce without group info
668 int CountTable::push_back(string seqName) {
669     try {
670         map<string, int>::iterator it = indexNameMap.find(seqName);
671         if (it == indexNameMap.end()) {
672             if (hasGroups) {  m->mothurOut("[ERROR]: Your count table has groups and I have no group information for " + seqName + "."); m->mothurOutEndLine(); m->control_pressed = true;  }
673             indexNameMap[seqName] = uniques;
674             totals.push_back(1);
675             total++;
676             uniques++;
677         }else {
678             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;
679         }
680         
681         return 0;
682     }
683         catch(exception& e) {
684                 m->errorOut(e, "CountTable", "push_back");
685                 exit(1);
686         }
687 }
688 /************************************************************/
689 //remove sequence
690 int CountTable::remove(string seqName) {
691     try {
692         map<string, int>::iterator it = indexNameMap.find(seqName);
693         if (it != indexNameMap.end()) {
694             uniques--;
695             if (hasGroups){ //remove this sequences counts from group totals
696                 for (int i = 0; i < totalGroups.size(); i++) {  totalGroups[i] -= counts[it->second][i];  counts[it->second][i] = 0; }
697             }
698             int thisTotal = totals[it->second]; totals[it->second] = 0;
699             total -= thisTotal;
700             indexNameMap.erase(it);
701         }else {
702             if (hasGroupInfo()) {
703                 //look for it in names of groups to see if the user accidently used the wrong file
704                 if (m->inUsersGroups(seqName, groups)) {
705                     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();
706                 }
707             }
708             m->mothurOut("[ERROR]: Your count table contains does not include " + seqName + ", cannot remove."); m->mothurOutEndLine(); m->control_pressed = true;
709         }
710         
711         return 0;
712     }
713         catch(exception& e) {
714                 m->errorOut(e, "CountTable", "push_back");
715                 exit(1);
716         }
717 }
718 /************************************************************/
719 //add seqeunce without group info
720 int CountTable::push_back(string seqName, int thisTotal) {
721     try {
722         map<string, int>::iterator it = indexNameMap.find(seqName);
723         if (it == indexNameMap.end()) {
724             if (hasGroups) {  m->mothurOut("[ERROR]: Your count table has groups and I have no group information for " + seqName + "."); m->mothurOutEndLine(); m->control_pressed = true;  }
725             indexNameMap[seqName] = uniques;
726             totals.push_back(thisTotal);
727             total+=thisTotal;
728             uniques++;
729         }else {
730             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;
731         }
732         
733         return 0;
734     }
735         catch(exception& e) {
736                 m->errorOut(e, "CountTable", "push_back");
737                 exit(1);
738         }
739 }
740 /************************************************************/
741 //add sequence with group info
742 int CountTable::push_back(string seqName, vector<int> groupCounts) {
743     try {
744         map<string, int>::iterator it = indexNameMap.find(seqName);
745         if (it == indexNameMap.end()) {
746             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;  }
747             int thisTotal = 0;
748             for (int i = 0; i < getNumGroups(); i++) {   totalGroups[i] += groupCounts[i];  thisTotal += groupCounts[i]; }
749             if (hasGroups) {  counts.push_back(groupCounts);  }
750             indexNameMap[seqName] = uniques;
751             totals.push_back(thisTotal);
752             total+= thisTotal;
753             uniques++;
754         }else {
755             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;
756         }
757         
758         return 0;
759     }
760         catch(exception& e) {
761                 m->errorOut(e, "CountTable", "push_back");
762                 exit(1);
763         }
764 }
765
766 /************************************************************/
767 //create ListVector from uniques
768 ListVector CountTable::getListVector() {
769     try {
770         ListVector list(indexNameMap.size());
771         for (map<string, int>::iterator it = indexNameMap.begin(); it != indexNameMap.end(); it++) { 
772             if (m->control_pressed) { break; }
773             list.set(it->second, it->first); 
774         }
775         return list;
776     }
777         catch(exception& e) {
778                 m->errorOut(e, "CountTable", "getListVector");
779                 exit(1);
780         }
781 }
782
783 /************************************************************/
784 //returns the names of all unique sequences in file
785 vector<string> CountTable::getNamesOfSeqs() {
786     try {
787         vector<string> names;
788         for (map<string, int>::iterator it = indexNameMap.begin(); it != indexNameMap.end(); it++) {
789             names.push_back(it->first);
790         }
791                 
792         return names;
793     }
794         catch(exception& e) {
795                 m->errorOut(e, "CountTable", "getNamesOfSeqs");
796                 exit(1);
797         }
798 }
799 /************************************************************/
800 //returns the names of all unique sequences in file mapped to their seqCounts
801 map<string, int> CountTable::getNameMap() {
802     try {
803         map<string, int> names;
804         for (map<string, int>::iterator it = indexNameMap.begin(); it != indexNameMap.end(); it++) {
805             names[it->first] = totals[it->second];
806         }
807         
808         return names;
809     }
810         catch(exception& e) {
811                 m->errorOut(e, "CountTable", "getNameMap");
812                 exit(1);
813         }
814 }
815 /************************************************************/
816 //returns the names of all unique sequences in file
817 vector<string> CountTable::getNamesOfSeqs(string group) {
818     try {
819         vector<string> names;
820         if (hasGroups) {
821             map<string, int>::iterator it = indexGroupMap.find(group);
822             if (it == indexGroupMap.end()) {
823                 m->mothurOut("[ERROR]: " + group + " is not in your count table. Please correct.\n"); m->control_pressed = true;
824             }else { 
825                 for (map<string, int>::iterator it2 = indexNameMap.begin(); it2 != indexNameMap.end(); it2++) {
826                     if (counts[it2->second][it->second] != 0) {  names.push_back(it2->first); }
827                 }
828             }
829         }else{  m->mothurOut("[ERROR]: Your count table does not have group info. Please correct.\n");  m->control_pressed = true; }
830         
831         return names;
832     }
833         catch(exception& e) {
834                 m->errorOut(e, "CountTable", "getNamesOfSeqs");
835                 exit(1);
836         }
837 }
838 /************************************************************/
839 //merges counts of seq1 and seq2, saving in seq1
840 int CountTable::mergeCounts(string seq1, string seq2) {
841     try {
842         map<string, int>::iterator it = indexNameMap.find(seq1);
843         if (it == indexNameMap.end()) {
844             if (hasGroupInfo()) {
845                 //look for it in names of groups to see if the user accidently used the wrong file
846                 if (m->inUsersGroups(seq1, groups)) {
847                     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();
848                 }
849             }
850             m->mothurOut("[ERROR]: " + seq1 + " is not in your count table. Please correct.\n"); m->control_pressed = true;
851         }else { 
852             map<string, int>::iterator it2 = indexNameMap.find(seq2);
853             if (it2 == indexNameMap.end()) {
854                 if (hasGroupInfo()) {
855                     //look for it in names of groups to see if the user accidently used the wrong file
856                     if (m->inUsersGroups(seq2, groups)) {
857                         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();
858                     }
859                 }
860                 m->mothurOut("[ERROR]: " + seq2 + " is not in your count table. Please correct.\n"); m->control_pressed = true;
861             }else { 
862                 //merge data
863                 for (int i = 0; i < groups.size(); i++) { counts[it->second][i] += counts[it2->second][i]; }
864                 totals[it->second] += totals[it2->second];
865                 uniques--;
866                 indexNameMap.erase(it2); 
867             }
868         }
869         return 0;
870     }
871         catch(exception& e) {
872                 m->errorOut(e, "CountTable", "getNamesOfSeqs");
873                 exit(1);
874         }
875 }
876 /************************************************************/
877 int CountTable::copy(CountTable* ct) {
878     try {
879         vector<string> thisGroups = ct->getNamesOfGroups();
880         for (int i = 0; i < thisGroups.size(); i++) { addGroup(thisGroups[i]); }
881         vector<string> names = ct->getNamesOfSeqs();
882                                                                
883         for (int i = 0; i < names.size(); i++) {
884             vector<int> thisCounts = ct->getGroupCounts(names[i]);
885             push_back(names[i], thisCounts);
886         }
887                                                                
888         return 0;
889     }
890         catch(exception& e) {
891                 m->errorOut(e, "CountTable", "copy");
892                 exit(1);
893         }
894 }
895
896 /************************************************************/
897
898