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