+ //set parsimony groups to left child
+ map<string,int> parsimony = tree[lc].pGroups;
+
+ int maxPars = 1;
+
+ //look at right child groups and update maxPars if right child has something higher for that group.
+ for(it=tree[rc].pGroups.begin();it!=tree[rc].pGroups.end();it++){
+ it2 = parsimony.find(it->first);
+ if (it2 != parsimony.end()) {
+ parsimony[it->first]++;
+ }else {
+ parsimony[it->first] = 1;
+ }
+
+ if(parsimony[it->first] > maxPars){
+ maxPars = parsimony[it->first];
+ }
+ }
+
+ // this is true if right child had a greater parsimony for a certain group
+ if(maxPars > 1){
+ //erase all the groups that are only 1 because you found something with 2.
+ for(it=parsimony.begin();it!=parsimony.end();){
+ if(it->second == 1){
+ parsimony.erase(it++);
+ }else { it++; }
+ }
+ //set one remaining groups to 1
+ //so with our above example p[white] = 2 would be left and it would become p[white] = 1
+ for(it=parsimony.begin();it!=parsimony.end();it++){
+ parsimony[it->first] = 1;
+ }
+
+ }
+
+ return parsimony;
+ }
+ catch(exception& e) {
+ m->errorOut(e, "Tree", "mergeGroups");
+ exit(1);
+ }
+}
+/*****************************************************************/
+//returns a map with a groupname and the number of times that group was seen in the children
+//for instance if your children are white and black then it would return a map with 2 entries
+// p[white] = 1 and p[black] = 1. Now go up a level and merge that with a node who has p[white] = 1
+//and you get p[white] = 2, p[black] = 1, but you erase the p[black] because you have a p value higher than 1.
+
+map<string, int> Tree::mergeUserGroups(int i, vector<string> g) {
+ try {
+
+ int lc = tree[i].getLChild();
+ int rc = tree[i].getRChild();
+
+ //loop through nodes groups removing the ones the user doesn't want
+ for(it=tree[lc].pGroups.begin();it!=tree[lc].pGroups.end();){
+ if (m->inUsersGroups(it->first, g) != true) {
+ tree[lc].pGroups.erase(it++);
+ }else { it++; }
+ }
+
+ //loop through nodes groups removing the ones the user doesn't want
+ for(it=tree[rc].pGroups.begin();it!=tree[rc].pGroups.end();){
+ if (m->inUsersGroups(it->first, g) != true) {
+ tree[rc].pGroups.erase(it++);
+ }else { it++; }
+ }
+
+ //set parsimony groups to left child
+ map<string,int> parsimony = tree[lc].pGroups;
+
+ int maxPars = 1;
+
+ //look at right child groups and update maxPars if right child has something higher for that group.
+ for(it=tree[rc].pGroups.begin();it!=tree[rc].pGroups.end();it++){
+ it2 = parsimony.find(it->first);
+ if (it2 != parsimony.end()) {
+ parsimony[it->first]++;
+ }else {
+ parsimony[it->first] = 1;
+ }
+
+ if(parsimony[it->first] > maxPars){
+ maxPars = parsimony[it->first];
+ }
+ }
+
+ // this is true if right child had a greater parsimony for a certain group
+ if(maxPars > 1){
+ //erase all the groups that are only 1 because you found something with 2.
+ for(it=parsimony.begin();it!=parsimony.end();){
+ if(it->second == 1){
+ parsimony.erase(it++);
+ }else { it++; }
+ }
+
+ for(it=parsimony.begin();it!=parsimony.end();it++){
+ parsimony[it->first] = 1;
+ }
+ }
+
+ return parsimony;
+ }
+ catch(exception& e) {
+ m->errorOut(e, "Tree", "mergeUserGroups");
+ exit(1);
+ }
+}
+
+
+/**************************************************************************************************/
+
+map<string,int> Tree::mergeGcounts(int position) {
+ try{
+ map<string,int>::iterator pos;
+
+ int lc = tree[position].getLChild();
+ int rc = tree[position].getRChild();
+
+ map<string,int> sum = tree[lc].pcount;
+
+ for(it=tree[rc].pcount.begin();it!=tree[rc].pcount.end();it++){
+ sum[it->first] += it->second;
+ }
+ return sum;
+ }
+ catch(exception& e) {
+ m->errorOut(e, "Tree", "mergeGcounts");
+ exit(1);
+ }
+}
+/**************************************************************************************************/
+void Tree::randomLabels(vector<string> g) {
+ try {
+
+ //initialize groupNodeInfo
+ for (int i = 0; i < (ct->getNamesOfGroups()).size(); i++) {
+ groupNodeInfo[(ct->getNamesOfGroups())[i]].resize(0);
+ }
+
+ for(int i = 0; i < numLeaves; i++){
+ int z;
+ //get random index to switch with
+ z = int((float)(i+1) * (float)(rand()) / ((float)RAND_MAX+1.0));
+
+ //you only want to randomize the nodes that are from a group the user wants analyzed, so
+ //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.
+ bool treez, treei;
+
+ treez = m->inUsersGroups(tree[z].getGroup(), g);
+ treei = m->inUsersGroups(tree[i].getGroup(), g);
+
+ if ((treez == true) && (treei == true)) {
+ //switches node i and node z's info.
+ map<string,int> lib_hold = tree[z].pGroups;
+ tree[z].pGroups = (tree[i].pGroups);
+ tree[i].pGroups = (lib_hold);
+
+ vector<string> zgroup = tree[z].getGroup();
+ tree[z].setGroup(tree[i].getGroup());
+ tree[i].setGroup(zgroup);
+
+ string zname = tree[z].getName();
+ tree[z].setName(tree[i].getName());
+ tree[i].setName(zname);
+
+ map<string,int> gcount_hold = tree[z].pcount;
+ tree[z].pcount = (tree[i].pcount);
+ tree[i].pcount = (gcount_hold);
+ }
+
+ for (int k = 0; k < (tree[i].getGroup()).size(); k++) { groupNodeInfo[(tree[i].getGroup())[k]].push_back(i); }
+ for (int k = 0; k < (tree[z].getGroup()).size(); k++) { groupNodeInfo[(tree[z].getGroup())[k]].push_back(z); }
+ }
+ }
+ catch(exception& e) {
+ m->errorOut(e, "Tree", "randomLabels");
+ exit(1);
+ }
+}
+/**************************************************************************************************/
+void Tree::randomBlengths() {
+ try {
+ for(int i=numNodes-1;i>=0;i--){
+ int z = int((float)(i+1) * (float)(rand()) / ((float)RAND_MAX+1.0));
+
+ float bl_hold = tree[z].getBranchLength();
+ tree[z].setBranchLength(tree[i].getBranchLength());
+ tree[i].setBranchLength(bl_hold);
+ }
+ }
+ catch(exception& e) {
+ m->errorOut(e, "Tree", "randomBlengths");
+ exit(1);
+ }
+}
+/*************************************************************************************************/
+void Tree::assembleRandomUnifracTree(vector<string> g) {
+ randomLabels(g);
+ assembleTree();
+}
+/*************************************************************************************************/
+void Tree::assembleRandomUnifracTree(string groupA, string groupB) {
+ vector<string> temp; temp.push_back(groupA); temp.push_back(groupB);
+ randomLabels(temp);
+ assembleTree();
+}
+
+/*************************************************************************************************/
+//for now it's just random topology but may become random labels as well later that why this is such a simple function now...
+void Tree::assembleRandomTree() {
+ randomTopology();
+ assembleTree();
+}
+/**************************************************************************************************/
+
+void Tree::randomTopology() {
+ try {
+ for(int i=0;i<numNodes;i++){
+ tree[i].setParent(-1);
+ }
+ for(int i=numLeaves;i<numNodes;i++){
+ tree[i].setChildren(-1, -1);
+ }
+
+ for(int i=numLeaves;i<numNodes;i++){
+ int escape =0;
+ int rnd_index1, rnd_index2;
+ while(escape == 0){
+ rnd_index1 = (int)(((double)rand() / (double) RAND_MAX)*i);
+ if(tree[rnd_index1].getParent() == -1){escape = 1;}
+ }
+
+ escape = 0;
+ while(escape == 0){
+ rnd_index2 = (int)(((double)rand() / (double) RAND_MAX)*i);
+ if(rnd_index2 != rnd_index1 && tree[rnd_index2].getParent() == -1){
+ escape = 1;
+ }
+ }
+
+ tree[i].setChildren(rnd_index1,rnd_index2);
+ tree[i].setParent(-1);
+ tree[rnd_index1].setParent(i);
+ tree[rnd_index2].setParent(i);
+ }
+ }
+ catch(exception& e) {
+ m->errorOut(e, "Tree", "randomTopology");
+ exit(1);
+ }
+}
+/*****************************************************************/
+void Tree::print(ostream& out) {
+ try {
+ int root = findRoot();
+ printBranch(root, out, "branch");
+ out << ";" << endl;
+ }
+ catch(exception& e) {
+ m->errorOut(e, "Tree", "print");
+ exit(1);
+ }
+}
+/*****************************************************************/
+void Tree::print(ostream& out, map<string, string> nameMap) {
+ try {
+ int root = findRoot();
+ printBranch(root, out, nameMap);
+ out << ";" << endl;
+ }
+ catch(exception& e) {
+ m->errorOut(e, "Tree", "print");
+ exit(1);
+ }
+}
+/*****************************************************************/
+void Tree::print(ostream& out, string mode) {
+ try {
+ int root = findRoot();
+ printBranch(root, out, mode);
+ out << ";" << endl;
+ }
+ catch(exception& e) {
+ m->errorOut(e, "Tree", "print");
+ exit(1);
+ }
+}