]> git.donarmstrong.com Git - mothur.git/blob - bootstrapsharedcommand.cpp
de9657420aabb0f8dd817a7bfe1fb4339bc3144e
[mothur.git] / bootstrapsharedcommand.cpp
1 /*
2  *  bootstrapsharedcommand.cpp
3  *  Mothur
4  *
5  *  Created by Sarah Westcott on 4/16/09.
6  *  Copyright 2009 Schloss Lab UMASS Amherst. All rights reserved.
7  *
8  */
9
10 #include "bootstrapsharedcommand.h"
11 #include "sharedjabund.h"
12 #include "sharedsorabund.h"
13 #include "sharedjclass.h"
14 #include "sharedsorclass.h"
15 #include "sharedjest.h"
16 #include "sharedsorest.h"
17 #include "sharedthetayc.h"
18 #include "sharedthetan.h"
19 #include "sharedmorisitahorn.h"
20 #include "sharedbraycurtis.h"
21
22
23 //**********************************************************************************************************************
24 vector<string> BootSharedCommand::setParameters(){      
25         try {
26                 CommandParameter pshared("shared", "InputTypes", "", "", "none", "none", "none",false,true); parameters.push_back(pshared);
27                 CommandParameter plabel("label", "String", "", "", "", "", "",false,false); parameters.push_back(plabel);
28                 CommandParameter pgroups("groups", "String", "", "", "", "", "",false,false); parameters.push_back(pgroups);
29                 CommandParameter piters("iters", "Number", "", "1000", "", "", "",false,false); parameters.push_back(piters);
30                 CommandParameter pcalc("calc", "Multiple", "jabund-sorabund-jclass-sorclass-jest-sorest-thetayc-thetan-morisitahorn-braycurtis", "jclass-thetayc", "", "", "",true,false); parameters.push_back(pcalc);
31                 CommandParameter pinputdir("inputdir", "String", "", "", "", "", "",false,false); parameters.push_back(pinputdir);
32                 CommandParameter poutputdir("outputdir", "String", "", "", "", "", "",false,false); parameters.push_back(poutputdir);
33
34                 vector<string> myArray;
35                 for (int i = 0; i < parameters.size(); i++) {   myArray.push_back(parameters[i].name);          }
36                 return myArray;
37         }
38         catch(exception& e) {
39                 m->errorOut(e, "BootSharedCommand", "setParameters");
40                 exit(1);
41         }
42 }
43 //**********************************************************************************************************************
44 string BootSharedCommand::getHelpString(){      
45         try {
46                 string helpString = "";
47                 helpString += "The bootstrap.shared command parameters are shared, groups, calc, iters and label. shared is required.\n";
48                 helpString += "The groups parameter allows you to specify which of the groups in your groupfile you would like included used.\n";
49                 helpString += "The group names are separated by dashes. The label parameter allows you to select what distance levels you would like trees created for, and is also separated by dashes.\n";
50                 helpString += "The bootstrap.shared command should be in the following format: bootstrap.shared(groups=yourGroups, calc=yourCalcs, label=yourLabels, iters=yourIters).\n";
51                 helpString += "Example bootstrap.shared(groups=A-B-C, calc=jabund-sorabund, iters=100).\n";
52                 helpString += "The default value for groups is all the groups in your groupfile.\n";
53                 helpString += "The default value for calc is jclass-thetayc. The default for iters is 1000.\n";
54                 return helpString;
55         }
56         catch(exception& e) {
57                 m->errorOut(e, "BootSharedCommand", "getHelpString");
58                 exit(1);
59         }
60 }
61 //**********************************************************************************************************************
62 BootSharedCommand::BootSharedCommand(){ 
63         try {
64                 abort = true; calledHelp = true; 
65                 setParameters();
66                 vector<string> tempOutNames;
67                 outputTypes["tree"] = tempOutNames;
68         }
69         catch(exception& e) {
70                 m->errorOut(e, "BootSharedCommand", "BootSharedCommand");
71                 exit(1);
72         }
73 }
74 //**********************************************************************************************************************
75 BootSharedCommand::BootSharedCommand(string option) {
76         try {
77                 abort = false; calledHelp = false;   
78                 
79                 //allow user to run help
80                 if(option == "help") { help(); abort = true; calledHelp = true; }
81                 else if(option == "citation") { citation(); abort = true; calledHelp = true;}
82                 
83                 else {
84                         vector<string> myArray = setParameters();
85                         
86                         OptionParser parser(option);
87                         map<string,string> parameters = parser.getParameters();
88                         map<string,string>::iterator it;
89                         
90                         ValidParameters validParameter;
91                 
92                         //check to make sure all parameters are valid for command
93                         for (it = parameters.begin(); it != parameters.end(); it++) { 
94                                 if (validParameter.isValidParameter(it->first, myArray, it->second) != true) {  abort = true;  }
95                         }
96                         
97                         //initialize outputTypes
98                         vector<string> tempOutNames;
99                         outputTypes["tree"] = tempOutNames;
100                         
101                         //if the user changes the input directory command factory will send this info to us in the output parameter 
102                         string inputDir = validParameter.validFile(parameters, "inputdir", false);              
103                         if (inputDir == "not found"){   inputDir = "";          }
104                         else {
105                                 string path;
106                                 it = parameters.find("shared");
107                                 //user has given a template file
108                                 if(it != parameters.end()){ 
109                                         path = m->hasPath(it->second);
110                                         //if the user has not given a path then, add inputdir. else leave path alone.
111                                         if (path == "") {       parameters["shared"] = inputDir + it->second;           }
112                                 }
113                         }
114                         
115                         sharedfile = validParameter.validFile(parameters, "shared", true);
116                         if (sharedfile == "not found") { 
117                                 sharedfile = m->getSharedFile(); 
118                                 if (sharedfile != "") { m->mothurOut("Using " + sharedfile + " as input file for the shared parameter."); m->mothurOutEndLine(); }
119                                 else {  m->mothurOut("You have no current shared file and the shared parameter is required."); m->mothurOutEndLine(); abort = true; }
120                         }       
121                         else if (sharedfile == "not open") { sharedfile = ""; abort = true; }
122                         else { m->setSharedFile(sharedfile); }
123                 
124                         //if the user changes the output directory command factory will send this info to us in the output parameter 
125                         outputDir = validParameter.validFile(parameters, "outputdir", false);           if (outputDir == "not found"){  
126                                 outputDir = ""; 
127                                 outputDir += m->hasPath(sharedfile); //if user entered a file with a path then preserve it      
128                         }
129                         
130                         //check for optional parameter and set defaults
131                         // ...at some point should added some additional type checking...
132                         label = validParameter.validFile(parameters, "label", false);                   
133                         if (label == "not found") { label = ""; }
134                         else { 
135                                 if(label != "all") {  m->splitAtDash(label, labels);  allLines = 0;  }
136                                 else { allLines = 1;  }
137                         }
138                                                         
139                         groups = validParameter.validFile(parameters, "groups", false);                 
140                         if (groups == "not found") { groups = ""; }
141                         else { 
142                                 m->splitAtDash(groups, Groups);
143                                 m->setGroups(Groups);
144                         }
145                                 
146                         calc = validParameter.validFile(parameters, "calc", false);                     
147                         if (calc == "not found") { calc = "jclass-thetayc";  }
148                         else { 
149                                  if (calc == "default")  {  calc = "jclass-thetayc";  }
150                         }
151                         m->splitAtDash(calc, Estimators);
152                         if (m->inUsersGroups("citation", Estimators)) { 
153                                 ValidCalculators validCalc; validCalc.printCitations(Estimators); 
154                                 //remove citation from list of calcs
155                                 for (int i = 0; i < Estimators.size(); i++) { if (Estimators[i] == "citation") {  Estimators.erase(Estimators.begin()+i); break; } }
156                         }
157
158                         string temp;
159                         temp = validParameter.validFile(parameters, "iters", false);  if (temp == "not found") { temp = "1000"; }
160                         m->mothurConvert(temp, iters); 
161                                 
162                         if (abort == false) {
163                         
164                                 //used in tree constructor 
165                                 m->runParse = false;
166                         
167                                 validCalculator = new ValidCalculators();
168                                 
169                                 
170                                 //NOTE: if you add a calc to this if statement you must add it to the setParameters function
171                                 //or it will not be visible in the gui
172                                 int i;
173                                 for (i=0; i<Estimators.size(); i++) {
174                                         if (validCalculator->isValidCalculator("boot", Estimators[i]) == true) { 
175                                                 if (Estimators[i] == "jabund") {        
176                                                         treeCalculators.push_back(new JAbund());
177                                                 }else if (Estimators[i] == "sorabund") { 
178                                                         treeCalculators.push_back(new SorAbund());
179                                                 }else if (Estimators[i] == "jclass") { 
180                                                         treeCalculators.push_back(new Jclass());
181                                                 }else if (Estimators[i] == "sorclass") { 
182                                                         treeCalculators.push_back(new SorClass());
183                                                 }else if (Estimators[i] == "jest") { 
184                                                         treeCalculators.push_back(new Jest());
185                                                 }else if (Estimators[i] == "sorest") { 
186                                                         treeCalculators.push_back(new SorEst());
187                                                 }else if (Estimators[i] == "thetayc") { 
188                                                         treeCalculators.push_back(new ThetaYC());
189                                                 }else if (Estimators[i] == "thetan") { 
190                                                         treeCalculators.push_back(new ThetaN());
191                                                 }else if (Estimators[i] == "morisitahorn") { 
192                                                         treeCalculators.push_back(new MorHorn());
193                                                 }else if (Estimators[i] == "braycurtis") { 
194                                                         treeCalculators.push_back(new BrayCurtis());
195                                                 }
196                                         }
197                                 }
198                                 
199                                 delete validCalculator;
200                                 
201                                 ofstream* tempo;
202                                 for (int i=0; i < treeCalculators.size(); i++) {
203                                         tempo = new ofstream;
204                                         out.push_back(tempo);
205                                 }
206                                 
207                                 //make a vector of tree* for each calculator
208                                 trees.resize(treeCalculators.size());
209                         }
210                 }
211
212         }
213         catch(exception& e) {
214                 m->errorOut(e, "BootSharedCommand", "BootSharedCommand");
215                 exit(1);
216         }
217 }
218 //**********************************************************************************************************************
219 BootSharedCommand::~BootSharedCommand(){}
220 //**********************************************************************************************************************
221
222 int BootSharedCommand::execute(){
223         try {
224         
225                 if (abort == true) { if (calledHelp) { return 0; }  return 2;   }
226                 
227                 m->mothurOut("bootstrap.shared command is no longer available."); m->mothurOutEndLine();
228         /*
229                 //read first line
230                 input = new InputData(sharedfile, "sharedfile");
231                 order = input->getSharedOrderVector();
232                 string lastLabel = order->getLabel();
233                 
234                 //if the users entered no valid calculators don't execute command
235                 if (treeCalculators.size() == 0) { return 0; }
236
237                 //if the users enters label "0.06" and there is no "0.06" in their file use the next lowest label.
238                 set<string> processedLabels;
239                 set<string> userLabels = labels;
240                                 
241                 //set users groups
242                 util = new SharedUtil();
243                 util->setGroups(m->Groups, m->namesOfGroups, "treegroup");
244                 
245                 numGroups = m->Groups.size();
246                 
247                 //clear globaldatas old tree names if any
248                 globaldata->Treenames.clear();
249                 
250                 //fills globaldatas tree names
251                 globaldata->Treenames = m->Groups;
252                 
253                 //create treemap class from groupmap for tree class to use
254                 tmap = new TreeMap();
255                 tmap->makeSim(globaldata->gGroupmap);
256                 globaldata->gTreemap = tmap;
257                         
258                 while((order != NULL) && ((allLines == 1) || (userLabels.size() != 0))) {
259                         if (m->control_pressed) {  for (int i = 0; i < outputNames.size(); i++) {       m->mothurRemove(outputNames[i]);  } globaldata->Groups.clear(); delete input;delete util; return 0;     } 
260         
261                         if(allLines == 1 || labels.count(order->getLabel()) == 1){                      
262                                 
263                                 m->mothurOut(order->getLabel()); m->mothurOutEndLine();
264                                 int error = process(order);
265                                 if (error == 1) {  for (int i = 0; i < outputNames.size(); i++) {       m->mothurRemove(outputNames[i]);  } globaldata->Groups.clear(); delete input;delete util; return 0;     } 
266                                 
267                                 processedLabels.insert(order->getLabel());
268                                 userLabels.erase(order->getLabel());
269                         }
270                         
271                         //you have a label the user want that is smaller than this label and the last label has not already been processed
272                         if ((m->anyLabelsToProcess(order->getLabel(), userLabels, "") == true) && (processedLabels.count(lastLabel) != 1)) {
273                                 string saveLabel = order->getLabel();
274                                 
275                                 delete order;
276                                 order = input->getSharedOrderVector(lastLabel);                                                                                                 
277                                 m->mothurOut(order->getLabel()); m->mothurOutEndLine();
278                                 int error = process(order);
279                                 if (error == 1) {  for (int i = 0; i < outputNames.size(); i++) {       m->mothurRemove(outputNames[i]);  } globaldata->Groups.clear(); delete input;delete util; return 0;     } 
280
281                                 processedLabels.insert(order->getLabel());
282                                 userLabels.erase(order->getLabel());
283                                 
284                                 //restore real lastlabel to save below
285                                 order->setLabel(saveLabel);
286                         }
287                         
288                         
289                         lastLabel = order->getLabel();                  
290
291                         //get next line to process
292                         delete order;
293                         order = input->getSharedOrderVector();
294                 }
295                 
296                 
297                 if (m->control_pressed) {  for (int i = 0; i < outputNames.size(); i++) {       m->mothurRemove(outputNames[i]);  } globaldata->Groups.clear(); delete input; delete util;  return 0;   } 
298
299                 //output error messages about any remaining user labels
300                 set<string>::iterator it;
301                 bool needToRun = false;
302                 for (it = userLabels.begin(); it != userLabels.end(); it++) {  
303                         m->mothurOut("Your file does not include the label " + *it); 
304                         if (processedLabels.count(lastLabel) != 1) {
305                                 m->mothurOut(". I will use " + lastLabel + "."); m->mothurOutEndLine();
306                                 needToRun = true;
307                         }else {
308                                 m->mothurOut(". Please refer to " + lastLabel + ".");  m->mothurOutEndLine();
309                         }
310                 }
311                 
312                 if (m->control_pressed) {  for (int i = 0; i < outputNames.size(); i++) {       m->mothurRemove(outputNames[i]);  } globaldata->Groups.clear(); delete input; delete util; return 0;    } 
313
314                 //run last line if you need to
315                 if (needToRun == true)  {
316                                 if (order != NULL) {    delete order;   }
317                                 order = input->getSharedOrderVector(lastLabel);                                                                                                 
318                                 m->mothurOut(order->getLabel()); m->mothurOutEndLine();
319                                 int error = process(order);
320                                 if (error == 1) {  for (int i = 0; i < outputNames.size(); i++) {       m->mothurRemove(outputNames[i]);  } globaldata->Groups.clear(); delete input; delete util; return 0;    } 
321                                 
322                                 delete order;
323
324                 }
325                 
326                 if (m->control_pressed) {  for (int i = 0; i < outputNames.size(); i++) {       m->mothurRemove(outputNames[i]);  } globaldata->Groups.clear();delete input; delete util; return 0;     } 
327
328                 //reset groups parameter
329                 globaldata->Groups.clear();  
330                 
331                 //set first tree file as new current treefile
332                 string currentTree = "";
333                 itTypes = outputTypes.find("tree");
334                 if (itTypes != outputTypes.end()) {
335                         if ((itTypes->second).size() != 0) { currentTree = (itTypes->second)[0]; m->setTreeFile(currentTree); }
336                 }
337                 
338                 delete input;
339                 delete util;
340                 
341                 m->mothurOutEndLine();
342                 m->mothurOut("Output File Names: "); m->mothurOutEndLine();
343                 for (int i = 0; i < outputNames.size(); i++) {  m->mothurOut(outputNames[i]); m->mothurOutEndLine();    }
344                 m->mothurOutEndLine();
345 */
346
347                 return 0;
348         }
349         catch(exception& e) {
350                 m->errorOut(e, "BootSharedCommand", "execute");
351                 exit(1);
352         }
353 }
354 //**********************************************************************************************************************
355
356 int BootSharedCommand::createTree(ostream* out, Tree* t){
357         try {
358                 /*
359                 //do merges and create tree structure by setting parents and children
360                 //there are numGroups - 1 merges to do
361                 for (int i = 0; i < (numGroups - 1); i++) {
362                 
363                         if (m->control_pressed) {  return 1; }
364                 
365                         float largest = -1000.0;
366                         int row, column;
367                         //find largest value in sims matrix by searching lower triangle
368                         for (int j = 1; j < simMatrix.size(); j++) {
369                                 for (int k = 0; k < j; k++) {
370                                         if (simMatrix[j][k] > largest) {  largest = simMatrix[j][k]; row = j; column = k;  }
371                                 }
372                         }
373
374                         //set non-leaf node info and update leaves to know their parents
375                         //non-leaf
376                         t->tree[numGroups + i].setChildren(index[row], index[column]);
377                 
378                         //parents
379                         t->tree[index[row]].setParent(numGroups + i);
380                         t->tree[index[column]].setParent(numGroups + i);
381                         
382                         //blength = distance / 2;
383                         float blength = ((1.0 - largest) / 2);
384                         
385                         //branchlengths
386                         t->tree[index[row]].setBranchLength(blength - t->tree[index[row]].getLengthToLeaves());
387                         t->tree[index[column]].setBranchLength(blength - t->tree[index[column]].getLengthToLeaves());
388                 
389                         //set your length to leaves to your childs length plus branchlength
390                         t->tree[numGroups + i].setLengthToLeaves(t->tree[index[row]].getLengthToLeaves() + t->tree[index[row]].getBranchLength());
391                         
392                 
393                         //update index 
394                         index[row] = numGroups+i;
395                         index[column] = numGroups+i;
396                         
397                         //zero out highest value that caused the merge.
398                         simMatrix[row][column] = -1000.0;
399                         simMatrix[column][row] = -1000.0;
400                 
401                         //merge values in simsMatrix
402                         for (int n = 0; n < simMatrix.size(); n++)      {
403                                 //row becomes merge of 2 groups
404                                 simMatrix[row][n] = (simMatrix[row][n] + simMatrix[column][n]) / 2;
405                                 simMatrix[n][row] = simMatrix[row][n];
406                                 //delete column
407                                 simMatrix[column][n] = -1000.0;
408                                 simMatrix[n][column] = -1000.0;
409                         }
410                 }
411                 
412                 //adjust tree to make sure root to tip length is .5
413                 int root = t->findRoot();
414                 t->tree[root].setBranchLength((0.5 - t->tree[root].getLengthToLeaves()));
415
416                 //assemble tree
417                 t->assembleTree();
418                 
419                 if (m->control_pressed) { return 1; }
420         
421                 //print newick file
422                 t->print(*out);*/
423                 
424                 return 0;
425         
426         }
427         catch(exception& e) {
428                 m->errorOut(e, "BootSharedCommand", "createTree");
429                 exit(1);
430         }
431 }
432 /***********************************************************/
433 void BootSharedCommand::printSims() {
434         try {
435                 m->mothurOut("simsMatrix"); m->mothurOutEndLine(); 
436                 for (int k = 0; k < simMatrix.size(); k++)      {
437                         for (int n = 0; n < simMatrix.size(); n++)      {
438                                 m->mothurOut(toString(simMatrix[k][n]));  m->mothurOut("\t"); 
439                         }
440                         m->mothurOutEndLine(); 
441                 }
442
443         }
444         catch(exception& e) {
445                 m->errorOut(e, "BootSharedCommand", "printSims");
446                 exit(1);
447         }
448 }
449 /***********************************************************/
450 int BootSharedCommand::process(SharedOrderVector* order) {
451         try{
452                         /*      EstOutput data;
453                                 vector<SharedRAbundVector*> subset;
454                                                                 
455                                 //open an ostream for each calc to print to
456                                 for (int z = 0; z < treeCalculators.size(); z++) {
457                                         //create a new filename
458                                         outputFile = outputDir + m->getRootName(m->getSimpleName(sharedfile)) + treeCalculators[z]->getName() + ".boot" + order->getLabel() + ".tre";
459                                         m->openOutputFile(outputFile, *(out[z]));
460                                         outputNames.push_back(outputFile); outputTypes["tree"].push_back(outputFile);
461                                 }
462                                 
463                                 m->mothurOut("Generating bootstrap trees..."); cout.flush();
464                                 
465                                 //create a file for each calculator with the 1000 trees in it.
466                                 for (int p = 0; p < iters; p++) {
467                                         
468                                         if (m->control_pressed) {  return 1; }
469                                         
470                                         util->getSharedVectorswithReplacement(m->Groups, lookup, order);  //fills group vectors from order vector.
471
472                                 
473                                         //for each calculator                                                                                           
474                                         for(int i = 0 ; i < treeCalculators.size(); i++) {
475                                                 
476                                                 if (m->control_pressed) {  return 1; }
477                                                 
478                                                 //initialize simMatrix
479                                                 simMatrix.clear();
480                                                 simMatrix.resize(numGroups);
481                                                 for (int o = 0; o < simMatrix.size(); o++)      {
482                                                         for (int j = 0; j < simMatrix.size(); j++)      {
483                                                                 simMatrix[o].push_back(0.0);
484                                                         }
485                                                 }
486                                 
487                                                 //initialize index
488                                                 index.clear();
489                                                 for (int g = 0; g < numGroups; g++) {   index[g] = g;   }
490                                                         
491                                                 for (int k = 0; k < lookup.size(); k++) { // pass cdd each set of groups to commpare
492                                                         for (int l = k; l < lookup.size(); l++) {
493                                                                 if (k != l) { //we dont need to similiarity of a groups to itself
494                                                                         subset.clear(); //clear out old pair of sharedrabunds
495                                                                         //add new pair of sharedrabunds
496                                                                         subset.push_back(lookup[k]); subset.push_back(lookup[l]); 
497                                                                         
498                                                                         //get estimated similarity between 2 groups
499                                                                         data = treeCalculators[i]->getValues(subset); //saves the calculator outputs
500                                                                         //save values in similarity matrix
501                                                                         simMatrix[k][l] = data[0];
502                                                                         simMatrix[l][k] = data[0];
503                                                                 }
504                                                         }
505                                                 }
506                                                 
507                                                 tempTree = new Tree();
508                                                 
509                                                 if (m->control_pressed) {   delete tempTree; return 1; }
510                                                 
511                                                 //creates tree from similarity matrix and write out file
512                                                 createTree(out[i], tempTree);
513                                                 
514                                                 if (m->control_pressed) {   delete tempTree; return 1; }
515                                                 
516                                                 //save trees for consensus command.
517                                                 trees[i].push_back(tempTree);
518                                         }
519                                 }
520                                 
521                                 m->mothurOut("\tDone."); m->mothurOutEndLine();
522                                                                 
523                                 
524                                 //create consensus trees for each bootstrapped tree set
525                                 for (int k = 0; k < trees.size(); k++) {
526                                         
527                                         m->mothurOut("Generating consensus tree for " + treeCalculators[k]->getName()); m->mothurOutEndLine();
528                                         
529                                         if (m->control_pressed) {  return 1; }
530                                         
531                                         //set global data to calc trees
532                                         globaldata->gTree = trees[k];
533                                         
534                                         string filename = outputDir + m->getRootName(m->getSimpleName(sharedfile)) + treeCalculators[k]->getName() + ".boot" + order->getLabel();
535                                         consensus = new ConcensusCommand(filename);
536                                         consensus->execute();
537                                         delete consensus;
538                                         
539                                         outputNames.push_back(filename + ".cons.pairs");
540                                         outputNames.push_back(filename + ".cons.tre");
541                                         
542                                 }
543                                 
544                                 
545                                         
546                                 //close ostream for each calc
547                                 for (int z = 0; z < treeCalculators.size(); z++) { out[z]->close(); }
548                                 */
549                                 return 0;
550         
551         }
552         catch(exception& e) {
553                 m->errorOut(e, "BootSharedCommand", "process");
554                 exit(1);
555         }
556 }
557 /***********************************************************/
558
559
560