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