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