]> git.donarmstrong.com Git - mothur.git/blob - tree.cpp
added indicator command
[mothur.git] / tree.cpp
1 /*
2  *  tree.cpp
3  *  Mothur
4  *
5  *  Created by Sarah Westcott on 1/22/09.
6  *  Copyright 2009 Schloss Lab UMASS Amherst. All rights reserved.
7  *
8  */
9
10 #include "tree.h"
11
12 /*****************************************************************/
13 Tree::Tree(int num) {
14         try {
15                 globaldata = GlobalData::getInstance();
16                 m = MothurOut::getInstance();
17                 
18                 numLeaves = num;  
19                 numNodes = 2*numLeaves - 1;
20                 
21                 tree.resize(numNodes);
22         }
23         catch(exception& e) {
24                 m->errorOut(e, "Tree", "Tree - numNodes");
25                 exit(1);
26         }
27 }
28 /*****************************************************************/
29 Tree::Tree(string g) {
30         try {
31                 globaldata = GlobalData::getInstance();
32                 m = MothurOut::getInstance();
33                 
34                 parseTreeFile();  globaldata->runParse = false;  
35         }
36         catch(exception& e) {
37                 m->errorOut(e, "Tree", "Tree - just parse");
38                 exit(1);
39         }
40 }
41 /*****************************************************************/
42 Tree::Tree() {
43         try {
44                 globaldata = GlobalData::getInstance();
45                 m = MothurOut::getInstance();
46                 
47                 if (globaldata->runParse == true) {  parseTreeFile();  globaldata->runParse = false;  }
48 //for(int i = 0; i <    globaldata->Treenames.size(); i++) { cout << i << '\t' << globaldata->Treenames[i] << endl;  }  
49                 numLeaves = globaldata->Treenames.size();
50                 numNodes = 2*numLeaves - 1;
51                 
52                 tree.resize(numNodes);
53                 
54                 //initialize groupNodeInfo
55                 for (int i = 0; i < globaldata->gTreemap->namesOfGroups.size(); i++) {
56                         groupNodeInfo[globaldata->gTreemap->namesOfGroups[i]].resize(0);
57                 }
58
59                 //initialize tree with correct number of nodes, name and group info.
60                 for (int i = 0; i < numNodes; i++) {
61                         //initialize leaf nodes
62                         if (i <= (numLeaves-1)) {
63                                 tree[i].setName(globaldata->Treenames[i]);
64                                 
65                                 //save group info
66                                 string group = globaldata->gTreemap->getGroup(globaldata->Treenames[i]);
67                                 vector<string> tempGroups; tempGroups.push_back(group);
68                                 tree[i].setGroup(tempGroups);
69                                 groupNodeInfo[group].push_back(i); 
70                                 
71                                 //set pcount and pGroup for groupname to 1.
72                                 tree[i].pcount[group] = 1;
73                                 tree[i].pGroups[group] = 1;
74                                 
75                                 //Treemap knows name, group and index to speed up search
76                                 globaldata->gTreemap->setIndex(globaldata->Treenames[i], i);
77         
78                         //intialize non leaf nodes
79                         }else if (i > (numLeaves-1)) {
80                                 tree[i].setName("");
81                                 vector<string> tempGroups;
82                                 tree[i].setGroup(tempGroups);
83                         }
84                 }
85         }
86         catch(exception& e) {
87                 m->errorOut(e, "Tree", "Tree");
88                 exit(1);
89         }
90 }
91
92 /*****************************************************************/
93 Tree::~Tree() {}
94 /*****************************************************************/
95 void Tree::addNamesToCounts() {
96         try {
97                 //ex. seq1      seq2,seq3,se4
98                 //              seq1 = pasture
99                 //              seq2 = forest
100                 //              seq4 = pasture
101                 //              seq3 = ocean
102                 
103                 //before this function seq1.pcount = pasture -> 1
104                 //after                            seq1.pcount = pasture -> 2, forest -> 1, ocean -> 1
105                 
106                 //before this function seq1.pgroups = pasture -> 1
107                 //after                            seq1.pgroups = pasture -> 1 since that is the dominant group
108
109                                 
110                 //go through each leaf and update its pcounts and pgroups
111                 
112                 //float A = clock();
113
114                 for (int i = 0; i < numLeaves; i++) {
115
116                         string name = tree[i].getName();
117                 
118                         map<string, string>::iterator itNames = globaldata->names.find(name);
119                 
120                         if (itNames == globaldata->names.end()) { m->mothurOut(name + " is not in your name file, please correct."); m->mothurOutEndLine(); exit(1);  }
121                         else {
122                                 vector<string> dupNames;
123                                 m->splitAtComma(globaldata->names[name], dupNames);
124                                 
125                                 map<string, int>::iterator itCounts;
126                                 int maxPars = 1;
127                                 set<string> groupsAddedForThisNode;
128                                 for (int j = 0; j < dupNames.size(); j++) {
129                                         
130                                         string group = globaldata->gTreemap->getGroup(dupNames[j]);
131                                         
132                                         if (dupNames[j] != name) {//you already added yourself in the constructor
133                                 
134                                                 if (groupsAddedForThisNode.count(group) == 0)  {  groupNodeInfo[group].push_back(i);  groupsAddedForThisNode.insert(group);  } //if you have not already added this node for this group, then add it
135                                                 
136                                                 //update pcounts
137                                                 itCounts = tree[i].pcount.find(group);
138                                                 if (itCounts == tree[i].pcount.end()) { //new group, add it
139                                                         tree[i].pcount[group] = 1;
140                                                 }else {
141                                                         tree[i].pcount[group]++;
142                                                 }
143                                                         
144                                                 //update pgroups
145                                                 itCounts = tree[i].pGroups.find(group);
146                                                 if (itCounts == tree[i].pGroups.end()) { //new group, add it
147                                                         tree[i].pGroups[group] = 1;
148                                                 }else{
149                                                         tree[i].pGroups[group]++;
150                                                 }
151                                                 
152                                                 //keep highest group
153                                                 if(tree[i].pGroups[group] > maxPars){
154                                                         maxPars = tree[i].pGroups[group];
155                                                 }
156                                         }else {  groupsAddedForThisNode.insert(group);  } //add it so you don't add it to groupNodeInfo again
157                                 }//end for
158                                 
159                                 if (maxPars > 1) { //then we have some more dominant groups
160                                         //erase all the groups that are less than maxPars because you found a more dominant group.
161                                         for(it=tree[i].pGroups.begin();it!=tree[i].pGroups.end();){
162                                                 if(it->second < maxPars){
163                                                         tree[i].pGroups.erase(it++);
164                                                 }else { it++; }
165                                         }
166                                         //set one remaining groups to 1
167                                         for(it=tree[i].pGroups.begin();it!=tree[i].pGroups.end();it++){
168                                                 tree[i].pGroups[it->first] = 1;
169                                         }
170                                 }//end if
171                                 
172                                 //update groups to reflect all the groups this node represents
173                                 vector<string> nodeGroups;
174                                 map<string, int>::iterator itGroups;
175                                 for (itGroups = tree[i].pcount.begin(); itGroups != tree[i].pcount.end(); itGroups++) {
176                                         nodeGroups.push_back(itGroups->first);
177                                 }
178                                 tree[i].setGroup(nodeGroups);
179                                 
180                         }//end else
181                 }//end for              
182                 
183                 //float B = clock();
184                 //cout << "addNamesToCounts\t" << (B - A) / CLOCKS_PER_SEC << endl;     
185
186         }
187         catch(exception& e) {
188                 m->errorOut(e, "Tree", "addNamesToCounts");
189                 exit(1);
190         }
191 }
192 /*****************************************************************/
193 int Tree::getIndex(string searchName) {
194         try {
195                 //Treemap knows name, group and index to speed up search
196                 // getIndex function will return the vector index or -1 if seq is not found.
197                 int index = globaldata->gTreemap->getIndex(searchName);
198                 return index;
199                 
200         }
201         catch(exception& e) {
202                 m->errorOut(e, "Tree", "getIndex");
203                 exit(1);
204         }
205 }
206 /*****************************************************************/
207
208 void Tree::setIndex(string searchName, int index) {
209         try {
210                 //set index in treemap
211                 globaldata->gTreemap->setIndex(searchName, index);
212         }
213         catch(exception& e) {
214                 m->errorOut(e, "Tree", "setIndex");
215                 exit(1);
216         }
217 }
218 /*****************************************************************/
219 int Tree::assembleTree() {
220         try {
221                 //float A = clock();
222
223                 //if user has given a names file we want to include that info in the pgroups and pcount info.
224                 if(globaldata->names.size() != 0) {  addNamesToCounts();  }
225                 
226                 //build the pGroups in non leaf nodes to be used in the parsimony calcs.
227                 for (int i = numLeaves; i < numNodes; i++) {
228                         if (m->control_pressed) { return 1; }
229
230                         tree[i].pGroups = (mergeGroups(i));
231                         tree[i].pcount = (mergeGcounts(i));
232                 }
233                 //float B = clock();
234                 //cout << "assembleTree\t" << (B-A) / CLOCKS_PER_SEC << endl;
235                 return 0;
236         }
237         catch(exception& e) {
238                 m->errorOut(e, "Tree", "assembleTree");
239                 exit(1);
240         }
241 }
242 /*****************************************************************/
243 int Tree::assembleTree(string n) {
244         try {
245                 
246                 //build the pGroups in non leaf nodes to be used in the parsimony calcs.
247                 for (int i = numLeaves; i < numNodes; i++) {
248                         if (m->control_pressed) { return 1; }
249
250                         tree[i].pGroups = (mergeGroups(i));
251                         tree[i].pcount = (mergeGcounts(i));
252                 }
253                 //float B = clock();
254                 //cout << "assembleTree\t" << (B-A) / CLOCKS_PER_SEC << endl;
255                 return 0;
256         }
257         catch(exception& e) {
258                 m->errorOut(e, "Tree", "assembleTree");
259                 exit(1);
260         }
261 }
262 /*****************************************************************/
263 void Tree::getSubTree(Tree* copy, vector<string> Groups) {
264         try {
265                         
266                 //we want to select some of the leaf nodes to create the output tree
267                 //go through the input Tree starting at parents of leaves
268                 for (int i = 0; i < numNodes; i++) {
269                         
270                         //initialize leaf nodes
271                         if (i <= (numLeaves-1)) {
272                                 tree[i].setName(Groups[i]);
273                                         
274                                 //save group info
275                                 string group = globaldata->gTreemap->getGroup(Groups[i]);
276                                 vector<string> tempGroups; tempGroups.push_back(group);
277                                 tree[i].setGroup(tempGroups);
278                                 groupNodeInfo[group].push_back(i); 
279                                 
280                                 //set pcount and pGroup for groupname to 1.
281                                 tree[i].pcount[group] = 1;
282                                 tree[i].pGroups[group] = 1;
283                                 
284                                 //Treemap knows name, group and index to speed up search
285                                 globaldata->gTreemap->setIndex(Groups[i], i);
286                                 
287                                 //intialize non leaf nodes
288                         }else if (i > (numLeaves-1)) {
289                                 tree[i].setName("");
290                                 vector<string> tempGroups;
291                                 tree[i].setGroup(tempGroups);
292                         }
293                 }
294                 
295                 set<int> removedLeaves;
296                 for (int i = 0; i < copy->getNumLeaves(); i++) {
297                         
298                         if (removedLeaves.count(i) == 0) {
299                         
300                         //am I in the group
301                         int parent = copy->tree[i].getParent();
302                         
303                         if (parent != -1) {
304                                 if (m->inUsersGroups(copy->tree[i].getName(), Groups)) {
305                                         //find my siblings name
306                                         int parentRC = copy->tree[parent].getRChild();
307                                         int parentLC = copy->tree[parent].getLChild();
308                                         
309                                         //if I am the right child, then my sib is the left child
310                                         int sibIndex = parentRC;
311                                         if (parentRC == i) { sibIndex = parentLC; }
312                                         
313                                         string sibsName = copy->tree[sibIndex].getName();
314                                         
315                                         //if yes, is my sibling
316                                         if ((m->inUsersGroups(sibsName, Groups)) || (sibsName == "")) {
317                                                 //we both are okay no trimming required
318                                         }else{
319                                                 //i am, my sib is not, so remove sib by setting my parent to my grandparent
320                                                 int grandparent = copy->tree[parent].getParent();
321                                                 int grandparentLC = copy->tree[grandparent].getLChild();
322                                                 int grandparentRC = copy->tree[grandparent].getRChild();
323                                                 
324                                                 //whichever of my granparents children was my parent now equals me
325                                                 if (grandparentLC == parent) { grandparentLC = i; }
326                                                 else { grandparentRC = i; }
327                                                 
328                                                 copy->tree[i].setParent(grandparent);
329                                                 copy->tree[i].setBranchLength((copy->tree[i].getBranchLength()+copy->tree[parent].getBranchLength()));
330                                                 copy->tree[grandparent].setChildren(grandparentLC, grandparentRC);
331                                                 removedLeaves.insert(sibIndex);
332                                         }
333                                 }else{
334                                         //find my siblings name
335                                         int parentRC = copy->tree[parent].getRChild();
336                                         int parentLC = copy->tree[parent].getLChild();
337                                         
338                                         //if I am the right child, then my sib is the left child
339                                         int sibIndex = parentRC;
340                                         if (parentRC == i) { sibIndex = parentLC; }
341                                         
342                                         string sibsName = copy->tree[sibIndex].getName();
343                                         
344                                         //if no is my sibling
345                                         if ((m->inUsersGroups(sibsName, Groups)) || (sibsName == "")) {
346                                                 //i am not, but my sib is
347                                                 int grandparent = copy->tree[parent].getParent();
348                                                 int grandparentLC = copy->tree[grandparent].getLChild();
349                                                 int grandparentRC = copy->tree[grandparent].getRChild();
350                                                 
351                                                 //whichever of my granparents children was my parent now equals my sib
352                                                 if (grandparentLC == parent) { grandparentLC = sibIndex; }
353                                                 else { grandparentRC = sibIndex; }
354                                                 
355                                                 copy->tree[sibIndex].setParent(grandparent);
356                                                 copy->tree[sibIndex].setBranchLength((copy->tree[sibIndex].getBranchLength()+copy->tree[parent].getBranchLength()));
357                                                 copy->tree[grandparent].setChildren(grandparentLC, grandparentRC);
358                                                 removedLeaves.insert(i);
359                                         }else{
360                                                 //neither of us are, so we want to eliminate ourselves and our parent
361                                                 //so set our parents sib to our great-grandparent
362                                                 int parent = copy->tree[i].getParent();
363                                                 int grandparent = copy->tree[parent].getParent();
364                                                 
365                                                 if (grandparent != -1) {
366                                                         int greatgrandparent = copy->tree[grandparent].getParent();
367                                                         int greatgrandparentLC = copy->tree[greatgrandparent].getLChild();
368                                                         int greatgrandparentRC = copy->tree[greatgrandparent].getRChild();
369                                                         
370                                                         int grandparentLC = copy->tree[grandparent].getLChild();
371                                                         int grandparentRC = copy->tree[grandparent].getRChild();
372                                                         
373                                                         int parentsSibIndex = grandparentLC;
374                                                         if (grandparentRC == parent) { parentsSibIndex = grandparentLC; }
375
376                                                         //whichever of my greatgrandparents children was my grandparent
377                                                         if (greatgrandparentLC == grandparent) { greatgrandparentLC = parentsSibIndex; }
378                                                         else { greatgrandparentRC = parentsSibIndex; }
379                                                         
380                                                         copy->tree[parentsSibIndex].setParent(greatgrandparent);
381                                                         copy->tree[parentsSibIndex].setBranchLength((copy->tree[parentsSibIndex].getBranchLength()+copy->tree[grandparent].getBranchLength()));
382                                                         copy->tree[greatgrandparent].setChildren(greatgrandparentLC, greatgrandparentRC);
383                                                 }else{
384                                                         copy->tree[parent].setChildren(-1, -1);
385                                                         cout << "issues with making subtree" << endl;
386                                                 }
387                                                 removedLeaves.insert(sibIndex);
388                                                 removedLeaves.insert(i);
389                                         }
390                                 }
391                         }
392                         }
393                 }
394                 
395                 int root = 0;
396                 for (int i = 0; i < copy->getNumNodes(); i++) {
397                         //you found the root
398                         if (copy->tree[i].getParent() == -1) { root = i; break; }
399                 }
400                 
401                 int nextSpot = numLeaves;
402                 populateNewTree(copy->tree, root, nextSpot);
403                 
404                 
405         }
406         catch(exception& e) {
407                 m->errorOut(e, "Tree", "getCopy");
408                 exit(1);
409         }
410 }
411 /*****************************************************************/
412 int Tree::populateNewTree(vector<Node>& oldtree, int node, int& index) {
413         try {
414                 
415                 if (oldtree[node].getLChild() != -1) {
416                         int rc = populateNewTree(oldtree, oldtree[node].getLChild(), index);
417                         int lc = populateNewTree(oldtree, oldtree[node].getRChild(), index);
418                         
419                         tree[index].setChildren(lc, rc);
420                         index++;
421                         
422                         return (index-1);
423                 }else { //you are a leaf
424                         int indexInNewTree = globaldata->gTreemap->getIndex(oldtree[node].getName());
425                         
426                         tree[indexInNewTree].setParent(index);
427                         return indexInNewTree;
428                         
429                 }
430         }
431         catch(exception& e) {
432                 m->errorOut(e, "Tree", "populateNewTree");
433                 exit(1);
434         }
435 }
436 /*****************************************************************/
437 void Tree::getCopy(Tree* copy) {
438         try {
439         
440                 //for each node in the tree copy its info
441                 for (int i = 0; i < numNodes; i++) {
442                         //copy name
443                         tree[i].setName(copy->tree[i].getName());
444                 
445                         //copy group
446                         tree[i].setGroup(copy->tree[i].getGroup());
447                         
448                         //copy branch length
449                         tree[i].setBranchLength(copy->tree[i].getBranchLength());
450                 
451                         //copy parent
452                         tree[i].setParent(copy->tree[i].getParent());
453                 
454                         //copy children
455                         tree[i].setChildren(copy->tree[i].getLChild(), copy->tree[i].getRChild());
456                 
457                         //copy index in node and tmap
458                         tree[i].setIndex(copy->tree[i].getIndex());
459                         setIndex(copy->tree[i].getName(), getIndex(copy->tree[i].getName()));
460                         
461                         //copy pGroups
462                         tree[i].pGroups = copy->tree[i].pGroups;
463                 
464                         //copy pcount
465                         tree[i].pcount = copy->tree[i].pcount;
466                 }
467                 
468                 groupNodeInfo = copy->groupNodeInfo;
469                 
470         }
471         catch(exception& e) {
472                 m->errorOut(e, "Tree", "getCopy");
473                 exit(1);
474         }
475 }
476 /*****************************************************************/
477 //returns a map with a groupname and the number of times that group was seen in the children
478 //for instance if your children are white and black then it would return a map with 2 entries
479 // p[white] = 1 and p[black] = 1.  Now go up a level and merge that with a node who has p[white] = 1
480 //and you get p[white] = 2, p[black] = 1, but you erase the p[black] because you have a p value higher than 1.
481
482 map<string, int> Tree::mergeGroups(int i) {
483         try {
484                 int lc = tree[i].getLChild();
485                 int rc = tree[i].getRChild();
486
487                 //set parsimony groups to left child
488                 map<string,int> parsimony = tree[lc].pGroups;
489                 
490                 int maxPars = 1;
491
492                 //look at right child groups and update maxPars if right child has something higher for that group.
493                 for(it=tree[rc].pGroups.begin();it!=tree[rc].pGroups.end();it++){
494                         it2 = parsimony.find(it->first);
495                         if (it2 != parsimony.end()) {
496                                 parsimony[it->first]++;
497                         }else {
498                                 parsimony[it->first] = 1;
499                         }
500                         
501                         if(parsimony[it->first] > maxPars){
502                                 maxPars = parsimony[it->first];
503                         }
504                 }
505         
506                 // this is true if right child had a greater parsimony for a certain group
507                 if(maxPars > 1){
508                         //erase all the groups that are only 1 because you found something with 2.
509                         for(it=parsimony.begin();it!=parsimony.end();){
510                                 if(it->second == 1){
511                                         parsimony.erase(it++);
512                                 }else { it++; }
513                         }
514                         //set one remaining groups to 1
515                         //so with our above example p[white] = 2 would be left and it would become p[white] = 1
516                         for(it=parsimony.begin();it!=parsimony.end();it++){
517                                 parsimony[it->first] = 1;
518                         }
519                 
520                 }
521         
522                 return parsimony;
523         }
524         catch(exception& e) {
525                 m->errorOut(e, "Tree", "mergeGroups");
526                 exit(1);
527         }
528 }
529 /*****************************************************************/
530 //returns a map with a groupname and the number of times that group was seen in the children
531 //for instance if your children are white and black then it would return a map with 2 entries
532 // p[white] = 1 and p[black] = 1.  Now go up a level and merge that with a node who has p[white] = 1
533 //and you get p[white] = 2, p[black] = 1, but you erase the p[black] because you have a p value higher than 1.
534
535 map<string, int> Tree::mergeUserGroups(int i, vector<string> g) {
536         try {
537         
538                 int lc = tree[i].getLChild();
539                 int rc = tree[i].getRChild();
540                 
541                 //loop through nodes groups removing the ones the user doesn't want
542                 for(it=tree[lc].pGroups.begin();it!=tree[lc].pGroups.end();){
543                                 if (m->inUsersGroups(it->first, g) != true) {
544                                         tree[lc].pGroups.erase(it++);
545                                 }else { it++; }
546                 }
547
548                 //loop through nodes groups removing the ones the user doesn't want
549                 for(it=tree[rc].pGroups.begin();it!=tree[rc].pGroups.end();){
550                                 if (m->inUsersGroups(it->first, g) != true) {
551                                         tree[rc].pGroups.erase(it++);
552                                 }else { it++; }
553                 }
554
555                 //set parsimony groups to left child
556                 map<string,int> parsimony = tree[lc].pGroups;
557                 
558                 int maxPars = 1;
559
560                 //look at right child groups and update maxPars if right child has something higher for that group.
561                 for(it=tree[rc].pGroups.begin();it!=tree[rc].pGroups.end();it++){
562                         it2 = parsimony.find(it->first);
563                         if (it2 != parsimony.end()) {
564                                 parsimony[it->first]++;
565                         }else {
566                                 parsimony[it->first] = 1;
567                         }
568                         
569                         if(parsimony[it->first] > maxPars){
570                                 maxPars = parsimony[it->first];
571                         }
572                 }
573                         
574                 // this is true if right child had a greater parsimony for a certain group
575                 if(maxPars > 1){
576                         //erase all the groups that are only 1 because you found something with 2.
577                         for(it=parsimony.begin();it!=parsimony.end();){
578                                 if(it->second == 1){
579                                         parsimony.erase(it++);
580                                 }else { it++; }
581                         }
582
583                         for(it=parsimony.begin();it!=parsimony.end();it++){
584                                 parsimony[it->first] = 1;
585                         }
586                 }               
587                 
588                 return parsimony;
589         }
590         catch(exception& e) {
591                 m->errorOut(e, "Tree", "mergeUserGroups");
592                 exit(1);
593         }
594 }
595
596
597 /**************************************************************************************************/
598
599 map<string,int> Tree::mergeGcounts(int position) {
600         try{
601                 map<string,int>::iterator pos;
602         
603                 int lc = tree[position].getLChild();
604                 int rc = tree[position].getRChild();
605         
606                 map<string,int> sum = tree[lc].pcount;
607     
608                 for(it=tree[rc].pcount.begin();it!=tree[rc].pcount.end();it++){
609                         sum[it->first] += it->second;
610                 }
611                 return sum;
612         }
613         catch(exception& e) {
614                 m->errorOut(e, "Tree", "mergeGcounts");
615                 exit(1);
616         }
617 }
618 /**************************************************************************************************/
619
620 void Tree::randomLabels(vector<string> g) {
621         try {
622         
623                 //initialize groupNodeInfo
624                 for (int i = 0; i < globaldata->gTreemap->namesOfGroups.size(); i++) {
625                         groupNodeInfo[globaldata->gTreemap->namesOfGroups[i]].resize(0);
626                 }
627                 
628                 for(int i = 0; i < numLeaves; i++){
629                         int z;
630                         //get random index to switch with
631                         z = int((float)(i+1) * (float)(rand()) / ((float)RAND_MAX+1.0));        
632                         
633                         //you only want to randomize the nodes that are from a group the user wants analyzed, so
634                         //if either of the leaf nodes you are about to switch are not in the users groups then you don't want to switch them.
635                         bool treez, treei;
636                 
637                         treez = m->inUsersGroups(tree[z].getGroup(), g);
638                         treei = m->inUsersGroups(tree[i].getGroup(), g);
639                         
640                         if ((treez == true) && (treei == true)) {
641                                 //switches node i and node z's info.
642                                 map<string,int> lib_hold = tree[z].pGroups;
643                                 tree[z].pGroups = (tree[i].pGroups);
644                                 tree[i].pGroups = (lib_hold);
645                                 
646                                 vector<string> zgroup = tree[z].getGroup();
647                                 tree[z].setGroup(tree[i].getGroup());
648                                 tree[i].setGroup(zgroup);
649                                 
650                                 string zname = tree[z].getName();
651                                 tree[z].setName(tree[i].getName());
652                                 tree[i].setName(zname);
653                                 
654                                 map<string,int> gcount_hold = tree[z].pcount;
655                                 tree[z].pcount = (tree[i].pcount);
656                                 tree[i].pcount = (gcount_hold);
657                         }
658                         
659                         for (int k = 0; k < (tree[i].getGroup()).size(); k++) {  groupNodeInfo[(tree[i].getGroup())[k]].push_back(i); }
660                         for (int k = 0; k < (tree[z].getGroup()).size(); k++) {  groupNodeInfo[(tree[z].getGroup())[k]].push_back(z); }
661                 }
662         }
663         catch(exception& e) {
664                 m->errorOut(e, "Tree", "randomLabels");
665                 exit(1);
666         }
667 }
668 /**************************************************************************************************
669
670 void Tree::randomLabels(string groupA, string groupB) {
671         try {
672                 int numSeqsA = globaldata->gTreemap->seqsPerGroup[groupA];
673                 int numSeqsB = globaldata->gTreemap->seqsPerGroup[groupB];
674
675                 vector<string> randomGroups(numSeqsA+numSeqsB, groupA);
676                 for(int i=numSeqsA;i<randomGroups.size();i++){
677                         randomGroups[i] = groupB;
678                 }
679                 random_shuffle(randomGroups.begin(), randomGroups.end());
680                                 
681                 int randomCounter = 0;                          
682                 for(int i=0;i<numLeaves;i++){
683                         if(tree[i].getGroup() == groupA || tree[i].getGroup() == groupB){
684                                 tree[i].setGroup(randomGroups[randomCounter]);
685                                 tree[i].pcount.clear();
686                                 tree[i].pcount[randomGroups[randomCounter]] = 1;
687                                 tree[i].pGroups.clear();
688                                 tree[i].pGroups[randomGroups[randomCounter]] = 1;
689                                 randomCounter++;
690                         }
691                 }
692         }               
693         catch(exception& e) {
694                 m->errorOut(e, "Tree", "randomLabels");
695                 exit(1);
696         }
697 }
698 /**************************************************************************************************/
699 void Tree::randomBlengths()  {
700         try {
701                 for(int i=numNodes-1;i>=0;i--){
702                         int z = int((float)(i+1) * (float)(rand()) / ((float)RAND_MAX+1.0));    
703                 
704                         float bl_hold = tree[z].getBranchLength();
705                         tree[z].setBranchLength(tree[i].getBranchLength());
706                         tree[i].setBranchLength(bl_hold);
707                 }
708         }
709         catch(exception& e) {
710                 m->errorOut(e, "Tree", "randomBlengths");
711                 exit(1);
712         }
713 }
714 /*************************************************************************************************/
715 void Tree::assembleRandomUnifracTree(vector<string> g) {
716         randomLabels(g);
717         assembleTree("noNameCounts");
718 }
719 /*************************************************************************************************/
720 void Tree::assembleRandomUnifracTree(string groupA, string groupB) {
721
722         vector<string> temp; temp.push_back(groupA); temp.push_back(groupB);
723         randomLabels(temp);
724         assembleTree("noNameCounts");
725 }
726
727 /*************************************************************************************************/
728 //for now it's just random topology but may become random labels as well later that why this is such a simple function now...
729 void Tree::assembleRandomTree() {
730         randomTopology();
731         assembleTree();
732 }
733 /**************************************************************************************************/
734
735 void Tree::randomTopology() {
736         try {
737                 for(int i=0;i<numNodes;i++){
738                         tree[i].setParent(-1);
739                 }
740                 for(int i=numLeaves;i<numNodes;i++){
741                         tree[i].setChildren(-1, -1); 
742                 }
743     
744                 for(int i=numLeaves;i<numNodes;i++){
745                         int escape =0;
746                         int rnd_index1, rnd_index2;
747                         while(escape == 0){
748                                 rnd_index1 = (int)(((double)rand() / (double) RAND_MAX)*i);
749                                 if(tree[rnd_index1].getParent() == -1){escape = 1;}
750                         }
751                 
752                         escape = 0;
753                         while(escape == 0){
754                                 rnd_index2 = (int)(((double)rand() / (double) RAND_MAX)*i);
755                                 if(rnd_index2 != rnd_index1 && tree[rnd_index2].getParent() == -1){
756                                         escape = 1;
757                                 }               
758                         }
759         
760                         tree[i].setChildren(rnd_index1,rnd_index2);
761                         tree[i].setParent(-1);
762                         tree[rnd_index1].setParent(i);
763                         tree[rnd_index2].setParent(i);
764                 }
765         }
766         catch(exception& e) {
767                 m->errorOut(e, "Tree", "randomTopology");
768                 exit(1);
769         }
770 }
771 /*****************************************************************/
772 void Tree::print(ostream& out) {
773         try {
774                 int root = findRoot();
775                 printBranch(root, out, "branch");
776                 out << ";" << endl;
777         }
778         catch(exception& e) {
779                 m->errorOut(e, "Tree", "print");
780                 exit(1);
781         }
782 }
783 /*****************************************************************/
784 void Tree::print(ostream& out, string mode) {
785         try {
786                 int root = findRoot();
787                 printBranch(root, out, mode);
788                 out << ";" << endl;
789         }
790         catch(exception& e) {
791                 m->errorOut(e, "Tree", "print");
792                 exit(1);
793         }
794 }
795 /*****************************************************************/
796 // This prints out the tree in Newick form.
797 void Tree::createNewickFile(string f) {
798         try {
799                 int root = findRoot();
800                 //filename = m->getRootName(globaldata->getTreeFile()) + "newick";
801                 filename = f;
802
803                 m->openOutputFile(filename, out);
804                 
805                 printBranch(root, out, "branch");
806                 
807                 // you are at the end of the tree
808                 out << ";" << endl;
809                 out.close();
810         }
811         catch(exception& e) {
812                 m->errorOut(e, "Tree", "createNewickFile");
813                 exit(1);
814         }
815 }
816
817 /*****************************************************************/
818 //This function finds the index of the root node.
819
820 int Tree::findRoot() {
821         try {
822                 for (int i = 0; i < numNodes; i++) {
823                         //you found the root
824                         if (tree[i].getParent() == -1) { return i; }
825                         //cout << "i = " << i << endl;
826                         //cout << "i's parent = " << tree[i].getParent() << endl;  
827                 }
828                 return -1;
829         }
830         catch(exception& e) {
831                 m->errorOut(e, "Tree", "findRoot");
832                 exit(1);
833         }
834 }
835 /*****************************************************************/
836 void Tree::printBranch(int node, ostream& out, string mode) {
837 try {
838
839 // you are not a leaf
840                 if (tree[node].getLChild() != -1) {
841                         out << "(";
842                         printBranch(tree[node].getLChild(), out, mode);
843                         out << ",";
844                         printBranch(tree[node].getRChild(), out, mode);
845                         out << ")";
846                         if (mode == "branch") {
847                                 //if there is a branch length then print it
848                                 if (tree[node].getBranchLength() != -1) {
849                                         out << ":" << tree[node].getBranchLength();
850                                 }
851                         }else if (mode == "boot") {
852                                 //if there is a label then print it
853                                 if (tree[node].getLabel() != -1) {
854                                         out << tree[node].getLabel();
855                                 }
856                         }else if (mode == "both") {
857                                 if (tree[node].getLabel() != -1) {
858                                         out << tree[node].getLabel();
859                                 }
860                                 //if there is a branch length then print it
861                                 if (tree[node].getBranchLength() != -1) {
862                                         out << ":" << tree[node].getBranchLength();
863                                 }
864                         }
865                 }else { //you are a leaf
866                         string leafGroup = globaldata->gTreemap->getGroup(tree[node].getName());
867                         
868                         if (mode == "branch") {
869                                 out << leafGroup; 
870                                 //if there is a branch length then print it
871                                 if (tree[node].getBranchLength() != -1) {
872                                         out << ":" << tree[node].getBranchLength();
873                                 }
874                         }else if (mode == "boot") {
875                                 out << leafGroup; 
876                                 //if there is a label then print it
877                                 if (tree[node].getLabel() != -1) {
878                                         out << tree[node].getLabel();
879                                 }
880                         }else if (mode == "both") {
881                                 out << tree[node].getName();
882                                 if (tree[node].getLabel() != -1) {
883                                         out << tree[node].getLabel();
884                                 }
885                                 //if there is a branch length then print it
886                                 if (tree[node].getBranchLength() != -1) {
887                                         out << ":" << tree[node].getBranchLength();
888                                 }
889                         }
890                 }
891                 
892         }
893         catch(exception& e) {
894                 m->errorOut(e, "Tree", "printBranch");
895                 exit(1);
896         }
897 }
898                                                                           
899 /*****************************************************************/
900
901 void Tree::printTree() {
902         
903         for(int i=0;i<numNodes;i++){
904                 cout << i << '\t';
905                 tree[i].printNode();
906         }
907         
908 }
909
910 /*****************************************************************/
911 //this code is a mess and should be rethought...-slw
912 void Tree::parseTreeFile() {
913         
914         //only takes names from the first tree and assumes that all trees use the same names.
915         try {
916                 string filename = globaldata->getTreeFile();
917                 ifstream filehandle;
918                 m->openInputFile(filename, filehandle);
919                 int c, comment;
920                 comment = 0;
921                 int done = 1;
922                 
923                 //ifyou are not a nexus file 
924                 if((c = filehandle.peek()) != '#') {  
925                         while((c = filehandle.peek()) != ';') { 
926                                 while ((c = filehandle.peek()) != ';') {
927                                         // get past comments
928                                         if(c == '[') {
929                                                 comment = 1;
930                                         }
931                                         if(c == ']'){
932                                                 comment = 0;
933                                         }
934                                         if((c == '(') && (comment != 1)){ break; }
935                                         filehandle.get();
936                                 }
937
938                                 done = readTreeString(filehandle); 
939                                 if (done == 0) { break; }
940                         }
941                 //ifyou are a nexus file
942                 }else if((c = filehandle.peek()) == '#') {
943                         string holder = "";
944                                         
945                         // get past comments
946                         while(holder != "translate" && holder != "Translate"){  
947                                 if(holder == "[" || holder == "[!"){
948                                         comment = 1;
949                                 }
950                                 if(holder == "]"){
951                                         comment = 0;
952                                 }
953                                 filehandle >> holder; 
954
955                                 //if there is no translate then you must read tree string otherwise use translate to get names
956                                 if((holder == "tree") && (comment != 1)){       
957                                         //pass over the "tree rep.6878900 = "
958                                         while (((c = filehandle.get()) != '(') && ((c = filehandle.peek()) != EOF)) {;}
959
960                                         if(c == EOF) { break; }
961                                         filehandle.putback(c);  //put back first ( of tree.
962                                         done = readTreeString(filehandle);
963         
964                                         break;
965                                 }
966                         
967                                 if (done == 0) { break;  }
968                         }
969                         
970                         //use nexus translation rather than parsing tree to save time
971                         if((holder == "translate") || (holder == "Translate")) {
972
973                                 string number, name, h;
974                                 h = ""; // so it enters the loop the first time
975                                 while((h != ";") && (number != ";")) { 
976                                         filehandle >> number;
977                                         filehandle >> name;
978         
979                                         //c = , until done with translation then c = ;
980                                         h = name.substr(name.length()-1, name.length()); 
981                                         name.erase(name.end()-1);  //erase the comma
982                                         globaldata->Treenames.push_back(number);
983                                 }
984                                 if(number == ";") { globaldata->Treenames.pop_back(); }  //in case ';' from translation is on next line instead of next to last name
985                         }
986                 }
987                 filehandle.close();
988                 
989                 //for (int i = 0; i < globaldata->Treenames.size(); i++) {
990 //cout << globaldata->Treenames[i] << endl; }
991 //cout << globaldata->Treenames.size() << endl;
992         }
993         catch(exception& e) {
994                 m->errorOut(e, "Tree", "parseTreeFile");
995                 exit(1);
996         }
997 }
998 /*******************************************************/
999
1000 /*******************************************************/
1001 int Tree::readTreeString(ifstream& filehandle)  {
1002         try {
1003                 int c;
1004                 string name;  //, k
1005                 
1006                 while((c = filehandle.peek()) != ';') { 
1007 //k = c;
1008 //cout << " at beginning of while " <<  k << endl;                      
1009                         if(c == ')')  {    
1010                                 //to pass over labels in trees
1011                                 c=filehandle.get();
1012                                 while((c!=',') && (c != -1) && (c!= ':') && (c!=';')){ c=filehandle.get(); }
1013                                 filehandle.putback(c);
1014                         }
1015                         if(c == ';') { return 0; }
1016                         if(c == -1) { return 0; }
1017                         //if you are a name
1018                         if((c != '(') && (c != ')') && (c != ',') && (c != ':') && (c != '\n') && (c != '\t') && (c != 32)) { //32 is space
1019                                 name = "";
1020                                 c = filehandle.get();
1021                         //k = c;
1022 //cout << k << endl;
1023                                 while ((c != '(') && (c != ')') && (c != ',') && (c != ':') && (c != '\n') && (c != 32) && (c != '\t')) {                       
1024                                         name += c;
1025                                         c = filehandle.get();
1026                         //k = c;
1027 //cout << " in name while " << k << endl;
1028                                 }
1029                                 
1030 //cout << "name = " << name << endl;
1031                                 globaldata->Treenames.push_back(name);
1032                                 filehandle.putback(c);
1033 //k = c;
1034 //cout << " after putback" <<  k << endl;
1035                         } 
1036                         
1037                         if(c  == ':') { //read until you reach the end of the branch length
1038                                 while ((c != '(') && (c != ')') && (c != ',') && (c != ';') && (c != '\n') && (c != '\t') && (c != 32)) {
1039                                         c = filehandle.get();
1040         //k = c;
1041         //cout << " in branch while " << k << endl;
1042                                 }
1043                                 filehandle.putback(c);
1044                         }
1045                 
1046                         c = filehandle.get();
1047 //k = c;
1048         //cout << " here after get " << k << endl;
1049                         if(c == ';') { return 0; }
1050                         if(c == ')') { filehandle.putback(c); }
1051         //k = c;
1052 //cout << k << endl;
1053
1054                 }
1055                 return 0;
1056         }
1057         catch(exception& e) {
1058                 m->errorOut(e, "Tree", "readTreeString");
1059                 exit(1);
1060         }
1061 }       
1062
1063 /*******************************************************/
1064
1065 /*******************************************************/
1066