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