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