]> git.donarmstrong.com Git - mothur.git/blob - indicatorcommand.cpp
fixed bug with tree reading
[mothur.git] / indicatorcommand.cpp
1 /*
2  *  indicatorcommand.cpp
3  *  Mothur
4  *
5  *  Created by westcott on 11/12/10.
6  *  Copyright 2010 Schloss Lab. All rights reserved.
7  *
8  */
9
10 #include "indicatorcommand.h"
11 #include "sharedutilities.h"
12
13
14 //**********************************************************************************************************************
15 vector<string> IndicatorCommand::setParameters(){       
16         try {
17                 CommandParameter pdesign("design", "InputTypes", "", "", "none", "none", "none",false,false); parameters.push_back(pdesign);
18                 CommandParameter pshared("shared", "InputTypes", "", "", "SharedRel", "SharedRel", "none",false,false); parameters.push_back(pshared);  
19                 CommandParameter prelabund("relabund", "InputTypes", "", "", "SharedRel", "SharedRel", "none",false,false); parameters.push_back(prelabund);
20                 CommandParameter pgroups("groups", "String", "", "", "", "", "",false,false); parameters.push_back(pgroups);
21                 CommandParameter plabel("label", "String", "", "", "", "", "",false,false); parameters.push_back(plabel);
22                 CommandParameter ptree("tree", "InputTypes", "", "", "none", "none", "none",false,true); parameters.push_back(ptree);
23                 CommandParameter pinputdir("inputdir", "String", "", "", "", "", "",false,false); parameters.push_back(pinputdir);
24                 CommandParameter poutputdir("outputdir", "String", "", "", "", "", "",false,false); parameters.push_back(poutputdir);
25                 
26                 vector<string> myArray;
27                 for (int i = 0; i < parameters.size(); i++) {   myArray.push_back(parameters[i].name);          }
28                 return myArray;
29         }
30         catch(exception& e) {
31                 m->errorOut(e, "IndicatorCommand", "setParameters");
32                 exit(1);
33         }
34 }
35 //**********************************************************************************************************************
36 string IndicatorCommand::getHelpString(){       
37         try {
38                 string helpString = "";
39                 helpString += "The indicator command reads a shared or relabund file and a tree file, and outputs a .indicator.tre and .indicator.summary file. \n";
40                 helpString += "The new tree contains labels at each internal node.  The label is the node number so you can relate the tree to the summary file.\n";
41                 helpString += "The summary file lists the indicator value for each OTU for each node.\n";
42                 helpString += "The indicator command parameters are tree, groups, shared, relabund, design and label. The tree parameter is required as well as either shared or relabund.\n";
43                 helpString += "The design parameter allows you to provide a design file to relate the tree to the shared or relabund file.\n";          
44                 helpString += "The groups parameter allows you to specify which of the groups in your shared or relabund you would like analyzed, or if you provide a design file the groups in your design file.  The groups may be entered separated by dashes.\n";
45                 helpString += "The label parameter indicates at what distance your tree relates to the shared or relabund.\n";
46                 helpString += "The indicator command should be used in the following format: indicator(tree=test.tre, shared=test.shared, label=0.03)\n";
47                 helpString += "Note: No spaces between parameter labels (i.e. tree), '=' and parameters (i.e.yourTreefile).\n"; 
48                 return helpString;
49         }
50         catch(exception& e) {
51                 m->errorOut(e, "IndicatorCommand", "getHelpString");
52                 exit(1);
53         }
54 }
55
56 //**********************************************************************************************************************
57 IndicatorCommand::IndicatorCommand(){   
58         try {
59                 abort = true; calledHelp = true; 
60                 setParameters();
61                 vector<string> tempOutNames;
62                 outputTypes["tree"] = tempOutNames;
63                 outputTypes["summary"] = tempOutNames;
64         }
65         catch(exception& e) {
66                 m->errorOut(e, "IndicatorCommand", "IndicatorCommand");
67                 exit(1);
68         }
69 }
70 //**********************************************************************************************************************
71 IndicatorCommand::IndicatorCommand(string option)  {
72         try {
73                 abort = false; calledHelp = false;   
74                 
75                 //allow user to run help
76                 if(option == "help") { help(); abort = true; calledHelp = true; }
77                 
78                 else {
79                         vector<string> myArray = setParameters();
80                         
81                         OptionParser parser(option);
82                         map<string, string> parameters = parser.getParameters();
83                         
84                         ValidParameters validParameter;
85                         map<string, string>::iterator it;
86                         
87                         //check to make sure all parameters are valid for command
88                         for (it = parameters.begin(); it != parameters.end(); it++) { 
89                                 if (validParameter.isValidParameter(it->first, myArray, it->second) != true) {  abort = true;  }
90                         }
91                         
92                         m->runParse = true;
93                         m->Groups.clear();
94                         m->namesOfGroups.clear();
95                         m->Treenames.clear();
96                         m->names.clear();
97                         
98                         vector<string> tempOutNames;
99                         outputTypes["tree"] = tempOutNames;
100                         outputTypes["summary"] = tempOutNames;
101                         
102                         //if the user changes the input directory command factory will send this info to us in the output parameter 
103                         string inputDir = validParameter.validFile(parameters, "inputdir", false);              
104                         if (inputDir == "not found"){   inputDir = "";          }
105                         else {
106                                 string path;
107                                 it = parameters.find("tree");
108                                 //user has given a template file
109                                 if(it != parameters.end()){ 
110                                         path = m->hasPath(it->second);
111                                         //if the user has not given a path then, add inputdir. else leave path alone.
112                                         if (path == "") {       parameters["tree"] = inputDir + it->second;             }
113                                 }
114                                 
115                                 it = parameters.find("shared");
116                                 //user has given a template file
117                                 if(it != parameters.end()){ 
118                                         path = m->hasPath(it->second);
119                                         //if the user has not given a path then, add inputdir. else leave path alone.
120                                         if (path == "") {       parameters["shared"] = inputDir + it->second;           }
121                                 }
122                                 
123                                 it = parameters.find("relabund");
124                                 //user has given a template file
125                                 if(it != parameters.end()){ 
126                                         path = m->hasPath(it->second);
127                                         //if the user has not given a path then, add inputdir. else leave path alone.
128                                         if (path == "") {       parameters["relabund"] = inputDir + it->second;         }
129                                 }
130                                 
131                                 it = parameters.find("design");
132                                 //user has given a template file
133                                 if(it != parameters.end()){ 
134                                         path = m->hasPath(it->second);
135                                         //if the user has not given a path then, add inputdir. else leave path alone.
136                                         if (path == "") {       parameters["design"] = inputDir + it->second;           }
137                                 }
138                         }
139                         
140                         outputDir = validParameter.validFile(parameters, "outputdir", false);           if (outputDir == "not found"){  outputDir = ""; }
141
142                         //check for required parameters
143                         treefile = validParameter.validFile(parameters, "tree", true);
144                         if (treefile == "not open") { abort = true; }
145                         else if (treefile == "not found") {                             //if there is a current design file, use it
146                                 treefile = m->getTreeFile(); 
147                                 if (treefile != "") { m->mothurOut("Using " + treefile + " as input file for the tree parameter."); m->mothurOutEndLine(); }
148                                 else {  m->mothurOut("You have no current tree file and the tree parameter is required."); m->mothurOutEndLine(); abort = true; }                                                               
149                         }       
150                         
151                         sharedfile = validParameter.validFile(parameters, "shared", true);
152                         if (sharedfile == "not open") { abort = true; }
153                         else if (sharedfile == "not found") { sharedfile = ""; }
154                         else { inputFileName = sharedfile; }
155                         
156                         relabundfile = validParameter.validFile(parameters, "relabund", true);
157                         if (relabundfile == "not open") { abort = true; }
158                         else if (relabundfile == "not found") { relabundfile = ""; }
159                         else { inputFileName = relabundfile; }
160                         
161                         designfile = validParameter.validFile(parameters, "design", true);
162                         if (designfile == "not open") { abort = true; }
163                         else if (designfile == "not found") { designfile = ""; }
164                         
165                         groups = validParameter.validFile(parameters, "groups", false);                 
166                         if (groups == "not found") { groups = "";  Groups.push_back("all"); }
167                         else { m->splitAtDash(groups, Groups);  }                       
168                         m->Groups = Groups;
169                         
170                         label = validParameter.validFile(parameters, "label", false);                   
171                         if (label == "not found") { label = ""; m->mothurOut("You did not provide a label, I will use the first label in your inputfile."); m->mothurOutEndLine(); label=""; }  
172                         
173                         if ((relabundfile == "") && (sharedfile == "")) { 
174                                 //is there are current file available for either of these?
175                                 //give priority to shared, then relabund
176                                 sharedfile = m->getSharedFile(); 
177                                 if (sharedfile != "") {  inputFileName = sharedfile; m->mothurOut("Using " + sharedfile + " as input file for the shared parameter."); m->mothurOutEndLine(); }
178                                 else { 
179                                         relabundfile = m->getRelAbundFile(); 
180                                         if (relabundfile != "") {  inputFileName = relabundfile; m->mothurOut("Using " + relabundfile + " as input file for the relabund parameter."); m->mothurOutEndLine(); }
181                                         else { 
182                                                 m->mothurOut("No valid current files. You must provide a shared or relabund."); m->mothurOutEndLine(); 
183                                                 abort = true;
184                                         }
185                                 }
186                         }
187                         
188                         if ((relabundfile != "") && (sharedfile != "")) { m->mothurOut("You may not use both a shared and relabund file."); m->mothurOutEndLine(); abort = true;  }
189                         
190                 }
191         }
192         catch(exception& e) {
193                 m->errorOut(e, "IndicatorCommand", "IndicatorCommand");         
194                 exit(1);
195         }
196 }
197 //**********************************************************************************************************************
198
199 int IndicatorCommand::execute(){
200         try {
201                 
202                 if (abort == true) { if (calledHelp) { return 0; }  return 2;   }
203         
204                 //read designfile if given and set up globaldatas groups for read of sharedfiles
205                 if (designfile != "") {
206                         designMap = new GroupMap(designfile);
207                         designMap->readDesignMap();
208                         
209                         //fill Groups - checks for "all" and for any typo groups
210                         SharedUtil* util = new SharedUtil();
211                         util->setGroups(Groups, designMap->namesOfGroups);
212                         delete util;
213                         
214                         //loop through the Groups and fill Globaldata's Groups with the design file info
215                         m->Groups = designMap->getNamesSeqs(Groups);
216                 }
217         
218                 /***************************************************/
219                 // use smart distancing to get right sharedRabund  //
220                 /***************************************************/
221                 if (sharedfile != "") {  
222                         getShared(); 
223                         if (m->control_pressed) { if (designfile != "") { delete designMap; } for (int i = 0; i < lookup.size(); i++) {  delete lookup[i];  } return 0; }
224                         if (lookup[0] == NULL) { m->mothurOut("[ERROR] reading shared file."); m->mothurOutEndLine(); return 0; }
225                 }else { 
226                         getSharedFloat(); 
227                         if (m->control_pressed) {  if (designfile != "") { delete designMap; } for (int i = 0; i < lookupFloat.size(); i++) {  delete lookupFloat[i];  } return 0; }
228                         if (lookupFloat[0] == NULL) { m->mothurOut("[ERROR] reading relabund file."); m->mothurOutEndLine(); return 0; }
229                 }
230                 
231                 //reset Globaldatas groups if needed
232                 if (designfile != "") { m->Groups = Groups; }
233                         
234                 /***************************************************/
235                 //    reading tree info                                                    //
236                 /***************************************************/
237                 string groupfile = ""; 
238                 m->setTreeFile(treefile);
239                 Tree* tree = new Tree(treefile); delete tree;  //extracts names from tree to make faked out groupmap
240                 treeMap = new TreeMap();
241                 bool mismatch = false;
242                         
243                 for (int i = 0; i < m->Treenames.size(); i++) { 
244                         //sanity check - is this a group that is not in the sharedfile?
245                         if (designfile == "") {
246                                 if (!(m->inUsersGroups(m->Treenames[i], m->namesOfGroups))) {
247                                         m->mothurOut("[ERROR]: " + m->Treenames[i] + " is not a group in your shared or relabund file."); m->mothurOutEndLine();
248                                         mismatch = true;
249                                 }
250                                 treeMap->addSeq(m->Treenames[i], "Group1"); 
251                         }else{
252                                 vector<string> myGroups; myGroups.push_back(m->Treenames[i]);
253                                 vector<string> myNames = designMap->getNamesSeqs(myGroups);
254                                 
255                                 for(int k = 0; k < myNames.size(); k++) {
256                                         if (!(m->inUsersGroups(myNames[k], m->namesOfGroups))) {
257                                                 m->mothurOut("[ERROR]: " + myNames[k] + " is not a group in your shared or relabund file."); m->mothurOutEndLine();
258                                                 mismatch = true;
259                                         }
260                                 }
261                                 treeMap->addSeq(m->Treenames[i], "Group1");
262                         }
263                 }
264                 
265                 if ((designfile != "") && (m->Treenames.size() != Groups.size())) { m->mothurOut("[ERROR]: You design file does not match your tree, aborting."); m->mothurOutEndLine(); mismatch = true; }
266                                 
267                 if (mismatch) { //cleanup and exit
268                         if (designfile != "") { delete designMap; }
269                         if (sharedfile != "") {  for (int i = 0; i < lookup.size(); i++) {  delete lookup[i];  } }
270                         else { for (int i = 0; i < lookupFloat.size(); i++) {  delete lookupFloat[i];  } }
271                         delete treeMap;
272                         return 0;
273                 }
274          
275                 read = new ReadNewickTree(treefile);
276                 int readOk = read->read(treeMap); 
277                 
278                 if (readOk != 0) { m->mothurOut("Read Terminated."); m->mothurOutEndLine(); delete treeMap; delete read; return 0; }
279                 
280                 vector<Tree*> T = read->getTrees();
281                 
282                 delete read;
283                 
284                 if (m->control_pressed) { 
285                         if (designfile != "") { delete designMap; }
286                         if (sharedfile != "") {  for (int i = 0; i < lookup.size(); i++) {  delete lookup[i];  } }
287                         else { for (int i = 0; i < lookupFloat.size(); i++) {  delete lookupFloat[i];  } }
288                         for (int i = 0; i < T.size(); i++) {  delete T[i];  }  delete treeMap; return 0; 
289                 }
290                         
291                 T[0]->assembleTree();
292                                 
293                 /***************************************************/
294                 //    create ouptut tree - respecting pickedGroups //
295                 /***************************************************/
296                 Tree* outputTree = new Tree(m->Groups.size(), treeMap); 
297                 
298                 outputTree->getSubTree(T[0], m->Groups);
299                 outputTree->assembleTree();
300                         
301                 //no longer need original tree, we have output tree to use and label
302                 for (int i = 0; i < T.size(); i++) {  delete T[i];  } 
303                 
304                                 
305                 if (m->control_pressed) { 
306                         if (designfile != "") { delete designMap; }
307                         if (sharedfile != "") {  for (int i = 0; i < lookup.size(); i++) {  delete lookup[i];  } }
308                         else { for (int i = 0; i < lookupFloat.size(); i++) {  delete lookupFloat[i];  } }
309                         delete outputTree; delete treeMap;  return 0; 
310                 }
311                 
312                 /***************************************************/
313                 //              get indicator species values                       //
314                 /***************************************************/
315                 GetIndicatorSpecies(outputTree);
316                 
317                 if (designfile != "") { delete designMap; }
318                 if (sharedfile != "") {  for (int i = 0; i < lookup.size(); i++) {  delete lookup[i];  } }
319                 else { for (int i = 0; i < lookupFloat.size(); i++) {  delete lookupFloat[i];  } }
320                 delete outputTree; delete treeMap;
321                 
322                 
323                 if (m->control_pressed) { for (int i = 0; i < outputNames.size(); i++) {        remove(outputNames[i].c_str()); } return 0; }
324                 
325                 //set tree file as new current treefile
326                 string current = "";
327                 itTypes = outputTypes.find("tree");
328                 if (itTypes != outputTypes.end()) {
329                         if ((itTypes->second).size() != 0) { current = (itTypes->second)[0]; m->setTreeFile(current); }
330                 }
331                 
332                 m->mothurOutEndLine();
333                 m->mothurOut("Output File Names: "); m->mothurOutEndLine();
334                 for (int i = 0; i < outputNames.size(); i++) {  m->mothurOut(outputNames[i]); m->mothurOutEndLine();    }
335                 m->mothurOutEndLine();
336                                 
337                 return 0;
338         }
339         catch(exception& e) {
340                 m->errorOut(e, "IndicatorCommand", "execute");  
341                 exit(1);
342         }
343 }
344 //**********************************************************************************************************************
345 //traverse tree finding indicator species values for each otu at each node
346 //label node with otu number that has highest indicator value
347 //report all otu values to file
348 int IndicatorCommand::GetIndicatorSpecies(Tree*& T){
349         try {
350                 
351                 string thisOutputDir = outputDir;
352                 if (outputDir == "") {  thisOutputDir += m->hasPath(inputFileName);  }
353                 string outputFileName = thisOutputDir + m->getRootName(m->getSimpleName(inputFileName)) + "indicator.summary";
354                 outputNames.push_back(outputFileName); outputTypes["summary"].push_back(outputFileName);
355                 
356                 ofstream out;
357                 m->openOutputFile(outputFileName, out);
358                 out.setf(ios::fixed, ios::floatfield); out.setf(ios::showpoint);
359                 
360                 int numBins = 0;
361                 if (sharedfile != "") { numBins = lookup[0]->getNumBins(); }
362                 else { numBins = lookupFloat[0]->getNumBins(); }
363                 
364                 //print headings
365                 out << "TreeNode\t";
366                 for (int i = 0; i < numBins; i++) { out << "OTU-" << (i+1) << '\t'; }
367                 out << endl;
368                 
369                 string treeOutputDir = outputDir;
370                 if (outputDir == "") {  treeOutputDir += m->hasPath(treefile);  }
371                 string outputTreeFileName = treeOutputDir + m->getRootName(m->getSimpleName(treefile)) + "indicator.tre";
372                 
373                 
374                 //create a map from tree node index to names of descendants, save time later to know which sharedRabund you need
375                 map<int, set<string> > nodeToDescendants;
376                 map<int, set<int> > descendantNodes;
377                 for (int i = 0; i < T->getNumNodes(); i++) {
378                         if (m->control_pressed) { return 0; }
379                         
380                         nodeToDescendants[i] = getDescendantList(T, i, nodeToDescendants, descendantNodes);
381                 }
382                 
383                 //you need the distances to leaf to decide grouping below
384                 //this will also set branch lengths if the tree does not include them
385                 map<int, float> distToRoot = getDistToRoot(T);
386                         
387                 //for each node
388                 for (int i = T->getNumLeaves(); i < T->getNumNodes(); i++) {
389                                 
390                         if (m->control_pressed) { out.close(); return 0; }
391                         
392                         /*****************************************************/
393                         //create vectors containing rabund info                          //
394                         /*****************************************************/
395                         
396                         vector<float> indicatorValues; //size of numBins
397                         
398                         if (sharedfile != "") {
399                                 vector< vector<SharedRAbundVector*> > groupings;
400                                 
401                                 //get nodes that will be a valid grouping
402                                 //you are valid if you are not one of my descendants
403                                 //AND your distToRoot is >= mine
404                                 //AND you were not added as part of a larger grouping. Largest nodes are added first.
405                                 
406                                 set<string> groupsAlreadyAdded;
407                                 //create a grouping with my grouping
408                                 vector<SharedRAbundVector*> subset;
409                                 int count = 0;
410                                 int doneCount = nodeToDescendants[i].size();
411                                 for (int k = 0; k < lookup.size(); k++) {
412                                         //is this descendant of i
413                                         if ((nodeToDescendants[i].count(lookup[k]->getGroup()) != 0)) { 
414                                                 subset.push_back(lookup[k]);
415                                                 groupsAlreadyAdded.insert(lookup[k]->getGroup());
416                                                 count++;
417                                         }
418                                         if (count == doneCount) { break; } //quit once you get the rabunds for this grouping
419                                 }
420                                 if (subset.size() != 0) { groupings.push_back(subset); }
421                                 
422                                 
423                                 for (int j = (T->getNumNodes()-1); j >= 0; j--) {
424         
425                                         
426                                         if ((descendantNodes[i].count(j) == 0) && (distToRoot[j] >= distToRoot[i])) { 
427                                                 vector<SharedRAbundVector*> subset;
428                                                 int count = 0;
429                                                 int doneCount = nodeToDescendants[j].size();
430                                                 for (int k = 0; k < lookup.size(); k++) {
431                                                         //is this descendant of j, and we didn't already add this as part of a larger grouping
432                                                         if ((nodeToDescendants[j].count(lookup[k]->getGroup()) != 0) && (groupsAlreadyAdded.count(lookup[k]->getGroup()) == 0)) { 
433                                                                 subset.push_back(lookup[k]);
434                                                                 groupsAlreadyAdded.insert(lookup[k]->getGroup());
435                                                                 count++;
436                                                         }
437                                                         if (count == doneCount) { break; } //quit once you get the rabunds for this grouping
438                                                 }
439                                                 
440                                                 //if subset.size == 0 then the node was added as part of a larger grouping
441                                                 if (subset.size() != 0) { groupings.push_back(subset); }
442                                         }
443                                 }
444                                 
445                                 if (groupsAlreadyAdded.size() != lookup.size()) {  m->mothurOut("[ERROR]: could not make proper groupings."); m->mothurOutEndLine(); }
446                                                                 
447                                 indicatorValues = getValues(groupings);
448                                 
449                         }else {
450                                 vector< vector<SharedRAbundFloatVector*> > groupings;
451                                 
452                                 //get nodes that will be a valid grouping
453                                 //you are valid if you are not one of my descendants
454                                 //AND your distToRoot is >= mine
455                                 //AND you were not added as part of a larger grouping. Largest nodes are added first.
456                                 
457                                 set<string> groupsAlreadyAdded;
458                                 //create a grouping with my grouping
459                                 vector<SharedRAbundFloatVector*> subset;
460                                 int count = 0;
461                                 int doneCount = nodeToDescendants[i].size();
462                                 for (int k = 0; k < lookupFloat.size(); k++) {
463                                         //is this descendant of i
464                                         if ((nodeToDescendants[i].count(lookupFloat[k]->getGroup()) != 0)) { 
465                                                 subset.push_back(lookupFloat[k]);
466                                                 groupsAlreadyAdded.insert(lookupFloat[k]->getGroup());
467                                                 count++;
468                                         }
469                                         if (count == doneCount) { break; } //quit once you get the rabunds for this grouping
470                                 }
471                                 if (subset.size() != 0) { groupings.push_back(subset); }
472                                 
473                                 for (int j = (T->getNumNodes()-1); j >= 0; j--) {
474                                         if ((descendantNodes[i].count(j) == 0) && (distToRoot[j] >= distToRoot[i])) {
475                                                 vector<SharedRAbundFloatVector*> subset;
476                                                 int count = 0;
477                                                 int doneCount = nodeToDescendants[j].size();
478                                                 for (int k = 0; k < lookupFloat.size(); k++) {
479                                                         //is this descendant of j, and we didn't already add this as part of a larger grouping
480                                                         if ((nodeToDescendants[j].count(lookupFloat[k]->getGroup()) != 0) && (groupsAlreadyAdded.count(lookupFloat[k]->getGroup()) == 0)) { 
481                                                                 subset.push_back(lookupFloat[k]);
482                                                                 groupsAlreadyAdded.insert(lookupFloat[k]->getGroup());
483                                                                 count++;
484                                                         }
485                                                         if (count == doneCount) { break; } //quit once you get the rabunds for this grouping
486                                                 }
487                                                 
488                                                 //if subset.size == 0 then the node was added as part of a larger grouping
489                                                 if (subset.size() != 0) { groupings.push_back(subset); }
490                                         }
491                                 }
492                                 
493                                 if (groupsAlreadyAdded.size() != lookupFloat.size()) { m->mothurOut("[ERROR]: could not make proper groupings."); m->mothurOutEndLine(); }
494                                 
495                                 indicatorValues = getValues(groupings);
496                         }
497                         
498                         if (m->control_pressed) { out.close(); return 0; }
499                         
500                         
501                         /******************************************************/
502                         //output indicator values to table form + label tree  //
503                         /*****************************************************/
504                         out << (i+1) << '\t';
505                         for (int j = 0; j < indicatorValues.size(); j++) {
506                                 
507                                 if (m->control_pressed) { out.close(); return 0; }
508                                 
509                                 out << indicatorValues[j] << '\t';
510                         }
511                         out << endl;
512                         
513                         T->tree[i].setLabel((i+1));
514                         
515                 }
516                 out.close();
517         
518                 ofstream outTree;
519                 m->openOutputFile(outputTreeFileName, outTree);
520                 outputNames.push_back(outputTreeFileName); outputTypes["tree"].push_back(outputTreeFileName);
521                 
522                 T->print(outTree, "both");
523                 outTree.close();
524         
525                 return 0;
526         }
527         catch(exception& e) {
528                 m->errorOut(e, "IndicatorCommand", "GetIndicatorSpecies");      
529                 exit(1);
530         }
531 }
532 //**********************************************************************************************************************
533 vector<float> IndicatorCommand::getValues(vector< vector<SharedRAbundFloatVector*> >& groupings){
534         try {
535                 vector<float> values;
536                 
537                 //for each otu
538                 for (int i = 0; i < groupings[0][0]->getNumBins(); i++) {
539                         
540                         if (m->control_pressed) { return values; }
541                         
542                         vector<float> terms; 
543                         float AijDenominator = 0.0;
544                         vector<float> Bij;
545                         //get overall abundance of each grouping
546                         for (int j = 0; j < groupings.size(); j++) {
547                                 
548                                 float totalAbund = 0;
549                                 int numNotZero = 0;
550                                 for (int k = 0; k < groupings[j].size(); k++) { 
551                                         totalAbund += groupings[j][k]->getAbundance(i); 
552                                         if (groupings[j][k]->getAbundance(i) != 0) { numNotZero++; }
553                                 }
554                                 
555                                 float Aij = (totalAbund / (float) groupings[j].size());
556                                 terms.push_back(Aij);
557                                 
558                                 //percentage of sites represented
559                                 Bij.push_back(numNotZero / (float) groupings[j].size());
560                                 
561                                 AijDenominator += Aij;
562                         }
563                         
564                         float maxIndVal = 0.0;
565                         for (int j = 0; j < terms.size(); j++) { 
566                                 float thisAij = (terms[j] / AijDenominator); 
567                                 float thisValue = thisAij * Bij[j] * 100.0;
568                                 
569                                 //save largest
570                                 if (thisValue > maxIndVal) { maxIndVal = thisValue; }
571                         }
572                         
573                         values.push_back(maxIndVal);
574                 }
575                 
576                 return values;
577         }
578         catch(exception& e) {
579                 m->errorOut(e, "IndicatorCommand", "getValues");        
580                 exit(1);
581         }
582 }
583 //**********************************************************************************************************************
584 //same as above, just data type difference
585 vector<float> IndicatorCommand::getValues(vector< vector<SharedRAbundVector*> >& groupings){
586         try {
587                 vector<float> values;
588                 
589         /*for (int j = 0; j < groupings.size(); j++) {          
590                 cout << "grouping " << j << endl;
591                 for (int k = 0; k < groupings[j].size(); k++) { 
592                         cout << groupings[j][k]->getGroup() << endl;
593                 }
594         }*/
595                 //for each otu
596                 for (int i = 0; i < groupings[0][0]->getNumBins(); i++) {
597                         vector<float> terms; 
598                         float AijDenominator = 0.0;
599                         vector<float> Bij;
600                         //get overall abundance of each grouping
601                         for (int j = 0; j < groupings.size(); j++) {
602         
603                                 int totalAbund = 0.0;
604                                 int numNotZero = 0;
605                                 for (int k = 0; k < groupings[j].size(); k++) { 
606                                         totalAbund += groupings[j][k]->getAbundance(i); 
607                                         if (groupings[j][k]->getAbundance(i) != 0.0) { numNotZero++; }
608                                         
609                                 }
610                                         
611                                 float Aij = (totalAbund / (float) groupings[j].size());
612                                 terms.push_back(Aij);
613                                 
614                                 //percentage of sites represented
615                                 Bij.push_back(numNotZero / (float) groupings[j].size());
616                                 
617                                 AijDenominator += Aij;
618                         }
619                         
620                         float maxIndVal = 0.0;
621                         for (int j = 0; j < terms.size(); j++) { 
622                                 float thisAij = (terms[j] / AijDenominator); 
623                                 float thisValue = thisAij * Bij[j] * 100.0;
624                                         
625                                 //save largest
626                                 if (thisValue > maxIndVal) { maxIndVal = thisValue; }
627                         }
628                         
629                         values.push_back(maxIndVal);
630                 }
631                 
632                 return values;
633         }
634         catch(exception& e) {
635                 m->errorOut(e, "IndicatorCommand", "getValues");        
636                 exit(1);
637         }
638 }
639 //**********************************************************************************************************************
640 //you need the distances to root to decide groupings
641 //this will also set branch lengths if the tree does not include them
642 map<int, float> IndicatorCommand::getDistToRoot(Tree*& T){
643         try {
644                 map<int, float> dists;
645                 
646                 bool hasBranchLengths = false;
647                 for (int i = 0; i < T->getNumNodes(); i++) { 
648                         if (T->tree[i].getBranchLength() > 0.0) {  hasBranchLengths = true; break; }
649                 }
650                 
651                 //set branchlengths if needed
652                 if (!hasBranchLengths) { 
653                         for (int i = 0; i < T->getNumNodes(); i++) {
654                                 
655                                 int lc = T->tree[i].getLChild();
656                                 int rc = T->tree[i].getRChild();
657                                 
658                                 if (lc == -1) { // you are a leaf
659                                         //if you are a leaf set you priliminary length to 1.0, this may adjust later
660                                         T->tree[i].setBranchLength(1.0);
661                                         dists[i] = 1.0;
662                                 }else{ // you are an internal node
663                                         //look at your children's length to leaf
664                                         float ldist = dists[lc];
665                                         float rdist = dists[rc];
666                                         
667                                         float greater = ldist;
668                                         if (rdist > greater) { greater = rdist; dists[i] = ldist + 1.0;}
669                                         else { dists[i] = rdist + 1.0; }
670                                         
671                                         
672                                         //branch length = difference + 1
673                                         T->tree[lc].setBranchLength((abs(ldist-greater) + 1.0));
674                                         T->tree[rc].setBranchLength((abs(rdist-greater) + 1.0));
675                                 }
676                         }
677                 }
678                         
679                 dists.clear();
680                 
681                 for (int i = 0; i < T->getNumNodes(); i++) {
682                         
683                         double sum = 0.0;
684                         int index = i;
685                         
686                         while(T->tree[index].getParent() != -1){
687                                 if (T->tree[index].getBranchLength() != -1) {
688                                         sum += abs(T->tree[index].getBranchLength()); 
689                                 }
690                                 index = T->tree[index].getParent();
691                         }
692                         
693                         dists[i] = sum;
694                 }
695                 
696                 return dists;
697         }
698         catch(exception& e) {
699                 m->errorOut(e, "IndicatorCommand", "getLengthToLeaf");  
700                 exit(1);
701         }
702 }
703 //**********************************************************************************************************************
704 set<string> IndicatorCommand::getDescendantList(Tree*& T, int i, map<int, set<string> > descendants, map<int, set<int> >& nodes){
705         try {
706                 set<string> names;
707                 
708                 set<string>::iterator it;
709                 
710                 int lc = T->tree[i].getLChild();
711                 int rc = T->tree[i].getRChild();
712                 
713                 if (lc == -1) { //you are a leaf your only descendant is yourself
714                         set<int> temp; temp.insert(i);
715                         nodes[i] = temp;
716                         
717                         if (designfile == "") {
718                                 names.insert(T->tree[i].getName());
719                         }else {
720                                 vector<string> myGroup; myGroup.push_back(T->tree[i].getName());
721                                 vector<string> myReps = designMap->getNamesSeqs(myGroup);
722                                 for (int k = 0; k < myReps.size(); k++) {
723                                         names.insert(myReps[k]);
724                                 }
725                         }
726                         
727                 }else{ //your descedants are the combination of your childrens descendants
728                         names = descendants[lc];
729                         nodes[i] = nodes[lc];
730                         for (it = descendants[rc].begin(); it != descendants[rc].end(); it++) {
731                                 names.insert(*it);
732                         }
733                         for (set<int>::iterator itNum = nodes[rc].begin(); itNum != nodes[rc].end(); itNum++) {
734                                 nodes[i].insert(*itNum);
735                         }
736                         //you are your own descendant
737                         nodes[i].insert(i);
738                 }
739                 
740                 return names;
741         }
742         catch(exception& e) {
743                 m->errorOut(e, "IndicatorCommand", "getDescendantList");        
744                 exit(1);
745         }
746 }
747 //**********************************************************************************************************************
748 int IndicatorCommand::getShared(){
749         try {
750                 InputData* input = new InputData(sharedfile, "sharedfile");
751                 lookup = input->getSharedRAbundVectors();
752                 string lastLabel = lookup[0]->getLabel();
753                 
754                 if (label == "") { label = lastLabel; delete input; return 0; }
755                 
756                 //if the users enters label "0.06" and there is no "0.06" in their file use the next lowest label.
757                 set<string> labels; labels.insert(label);
758                 set<string> processedLabels;
759                 set<string> userLabels = labels;
760                 
761                 //as long as you are not at the end of the file or done wih the lines you want
762                 while((lookup[0] != NULL) && (userLabels.size() != 0)) {
763                         if (m->control_pressed) {  delete input; return 0;  }
764                         
765                         if(labels.count(lookup[0]->getLabel()) == 1){
766                                 processedLabels.insert(lookup[0]->getLabel());
767                                 userLabels.erase(lookup[0]->getLabel());
768                                 break;
769                         }
770                         
771                         if ((m->anyLabelsToProcess(lookup[0]->getLabel(), userLabels, "") == true) && (processedLabels.count(lastLabel) != 1)) {
772                                 string saveLabel = lookup[0]->getLabel();
773                                 
774                                 for (int i = 0; i < lookup.size(); i++) {  delete lookup[i];  } 
775                                 lookup = input->getSharedRAbundVectors(lastLabel);
776                                 
777                                 processedLabels.insert(lookup[0]->getLabel());
778                                 userLabels.erase(lookup[0]->getLabel());
779                                 
780                                 //restore real lastlabel to save below
781                                 lookup[0]->setLabel(saveLabel);
782                                 break;
783                         }
784                         
785                         lastLabel = lookup[0]->getLabel();                      
786                         
787                         //get next line to process
788                         //prevent memory leak
789                         for (int i = 0; i < lookup.size(); i++) {  delete lookup[i];  } 
790                         lookup = input->getSharedRAbundVectors();
791                 }
792                 
793                 
794                 if (m->control_pressed) { delete input; return 0;  }
795                 
796                 //output error messages about any remaining user labels
797                 set<string>::iterator it;
798                 bool needToRun = false;
799                 for (it = userLabels.begin(); it != userLabels.end(); it++) {  
800                         m->mothurOut("Your file does not include the label " + *it); 
801                         if (processedLabels.count(lastLabel) != 1) {
802                                 m->mothurOut(". I will use " + lastLabel + "."); m->mothurOutEndLine();
803                                 needToRun = true;
804                         }else {
805                                 m->mothurOut(". Please refer to " + lastLabel + "."); m->mothurOutEndLine();
806                         }
807                 }
808                 
809                 //run last label if you need to
810                 if (needToRun == true)  {
811                         for (int i = 0; i < lookup.size(); i++) {  if (lookup[i] != NULL) {     delete lookup[i];       } } 
812                         lookup = input->getSharedRAbundVectors(lastLabel);
813                 }       
814                 
815                 delete input;
816                 return 0;
817         }
818         catch(exception& e) {
819                 m->errorOut(e, "IndicatorCommand", "getShared");        
820                 exit(1);
821         }
822 }
823 //**********************************************************************************************************************
824 int IndicatorCommand::getSharedFloat(){
825         try {
826                 InputData* input = new InputData(relabundfile, "relabund");
827                 lookupFloat = input->getSharedRAbundFloatVectors();
828                 string lastLabel = lookupFloat[0]->getLabel();
829                 
830                 if (label == "") { label = lastLabel; delete input; return 0; }
831                 
832                 //if the users enters label "0.06" and there is no "0.06" in their file use the next lowest label.
833                 set<string> labels; labels.insert(label);
834                 set<string> processedLabels;
835                 set<string> userLabels = labels;
836                 
837                 //as long as you are not at the end of the file or done wih the lines you want
838                 while((lookupFloat[0] != NULL) && (userLabels.size() != 0)) {
839                         
840                         if (m->control_pressed) {  delete input; return 0;  }
841                         
842                         if(labels.count(lookupFloat[0]->getLabel()) == 1){
843                                 processedLabels.insert(lookupFloat[0]->getLabel());
844                                 userLabels.erase(lookupFloat[0]->getLabel());
845                                 break;
846                         }
847                         
848                         if ((m->anyLabelsToProcess(lookupFloat[0]->getLabel(), userLabels, "") == true) && (processedLabels.count(lastLabel) != 1)) {
849                                 string saveLabel = lookupFloat[0]->getLabel();
850                                 
851                                 for (int i = 0; i < lookupFloat.size(); i++) {  delete lookupFloat[i];  } 
852                                 lookupFloat = input->getSharedRAbundFloatVectors(lastLabel);
853                                 
854                                 processedLabels.insert(lookupFloat[0]->getLabel());
855                                 userLabels.erase(lookupFloat[0]->getLabel());
856                                 
857                                 //restore real lastlabel to save below
858                                 lookupFloat[0]->setLabel(saveLabel);
859                                 break;
860                         }
861                         
862                         lastLabel = lookupFloat[0]->getLabel();                 
863                         
864                         //get next line to process
865                         //prevent memory leak
866                         for (int i = 0; i < lookupFloat.size(); i++) {  delete lookupFloat[i];  } 
867                         lookupFloat = input->getSharedRAbundFloatVectors();
868                 }
869                 
870                 
871                 if (m->control_pressed) { delete input; return 0;  }
872                 
873                 //output error messages about any remaining user labels
874                 set<string>::iterator it;
875                 bool needToRun = false;
876                 for (it = userLabels.begin(); it != userLabels.end(); it++) {  
877                         m->mothurOut("Your file does not include the label " + *it); 
878                         if (processedLabels.count(lastLabel) != 1) {
879                                 m->mothurOut(". I will use " + lastLabel + "."); m->mothurOutEndLine();
880                                 needToRun = true;
881                         }else {
882                                 m->mothurOut(". Please refer to " + lastLabel + "."); m->mothurOutEndLine();
883                         }
884                 }
885                 
886                 //run last label if you need to
887                 if (needToRun == true)  {
888                         for (int i = 0; i < lookupFloat.size(); i++) {  if (lookupFloat[i] != NULL) {   delete lookupFloat[i];  } } 
889                         lookupFloat = input->getSharedRAbundFloatVectors(lastLabel);
890                 }       
891                 
892                 delete input;
893                 return 0;
894         }
895         catch(exception& e) {
896                 m->errorOut(e, "IndicatorCommand", "getShared");        
897         exit(1);
898         }
899 }               
900 /*****************************************************************/
901
902