]> git.donarmstrong.com Git - mothur.git/blob - classifyotucommand.cpp
added summary file to classify.otu
[mothur.git] / classifyotucommand.cpp
1 /*
2  *  classifyotucommand.cpp
3  *  Mothur
4  *
5  *  Created by westcott on 6/1/10.
6  *  Copyright 2010 Schloss Lab. All rights reserved.
7  *
8  */
9
10 #include "classifyotucommand.h"
11 #include "phylotree.h"
12 #include "phylosummary.h"
13
14 //**********************************************************************************************************************
15 vector<string> ClassifyOtuCommand::getValidParameters(){        
16         try {
17                 string AlignArray[] =  {"list","label","name","taxonomy","basis","cutoff","probs","group","reftaxonomy","outputdir","inputdir"};
18                 vector<string> myArray (AlignArray, AlignArray+(sizeof(AlignArray)/sizeof(string)));
19                 return myArray;
20         }
21         catch(exception& e) {
22                 m->errorOut(e, "ClassifyOtuCommand", "getValidParameters");
23                 exit(1);
24         }
25 }
26 //**********************************************************************************************************************
27 ClassifyOtuCommand::ClassifyOtuCommand(){       
28         try {
29                 abort = true;
30                 //initialize outputTypes
31                 vector<string> tempOutNames;
32                 outputTypes["constaxonomy"] = tempOutNames;
33                 outputTypes["taxsummary"] = tempOutNames;
34         }
35         catch(exception& e) {
36                 m->errorOut(e, "ClassifyOtuCommand", "ClassifyOtuCommand");
37                 exit(1);
38         }
39 }
40 //**********************************************************************************************************************
41 vector<string> ClassifyOtuCommand::getRequiredParameters(){     
42         try {
43                 string Array[] =  {"list","taxonomy"};
44                 vector<string> myArray (Array, Array+(sizeof(Array)/sizeof(string)));
45                 return myArray;
46         }
47         catch(exception& e) {
48                 m->errorOut(e, "ClassifyOtuCommand", "getRequiredParameters");
49                 exit(1);
50         }
51 }
52 //**********************************************************************************************************************
53 vector<string> ClassifyOtuCommand::getRequiredFiles(){  
54         try {
55                 vector<string> myArray;
56                 return myArray;
57         }
58         catch(exception& e) {
59                 m->errorOut(e, "ClassifyOtuCommand", "getRequiredFiles");
60                 exit(1);
61         }
62 }
63 //**********************************************************************************************************************
64 ClassifyOtuCommand::ClassifyOtuCommand(string option)  {
65         try{
66                 abort = false;
67                 allLines = 1;
68                 labels.clear();
69                                 
70                 //allow user to run help
71                 if (option == "help") { 
72                         help(); abort = true;
73                 } else {
74                         //valid paramters for this command
75                         string Array[] =  {"list","label","name","taxonomy","cutoff","probs","basis","reftaxonomy","group","outputdir","inputdir"};
76                         vector<string> myArray (Array, Array+(sizeof(Array)/sizeof(string)));
77                         
78                         OptionParser parser(option);
79                         map<string, string> parameters = parser.getParameters();
80                         
81                         ValidParameters validParameter;
82                         map<string, string>::iterator it;
83                 
84                         //check to make sure all parameters are valid for command
85                         for (it = parameters.begin(); it != parameters.end(); it++) { 
86                                 if (validParameter.isValidParameter(it->first, myArray, it->second) != true) {  abort = true;  }
87                         }
88                         
89                         //initialize outputTypes
90                         vector<string> tempOutNames;
91                         outputTypes["constaxonomy"] = tempOutNames;
92                         outputTypes["taxsummary"] = 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("list");
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["list"] = inputDir + it->second;             }
105                                 }
106                                 
107                                 it = parameters.find("name");
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["name"] = inputDir + it->second;             }
113                                 }
114                                 
115                                 it = parameters.find("taxonomy");
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["taxonomy"] = inputDir + it->second;         }
121                                 }
122                                 
123                                 it = parameters.find("reftaxonomy");
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["reftaxonomy"] = inputDir + it->second;              }
129                                 }
130                                 
131                                 it = parameters.find("group");
132                                 //user has given a template file
133                                 if(it != parameters.end()){ 
134                                         path = m->hasPath(it->second);
135                                         //if the user has not given a path then, add inputdir. else leave path alone.
136                                         if (path == "") {       parameters["group"] = inputDir + it->second;            }
137                                 }
138                         }
139
140                         
141                         //if the user changes the output directory command factory will send this info to us in the output parameter 
142                         outputDir = validParameter.validFile(parameters, "outputdir", false);           if (outputDir == "not found"){  outputDir = "";         }
143                         
144                         //check for required parameters
145                         listfile = validParameter.validFile(parameters, "list", true);
146                         if (listfile == "not found") { m->mothurOut("list is a required parameter for the classify.otu command."); m->mothurOutEndLine(); abort = true; }
147                         else if (listfile == "not open") { abort = true; }      
148                         
149                         taxfile = validParameter.validFile(parameters, "taxonomy", true);
150                         if (taxfile == "not found") {  m->mothurOut("taxonomy is a required parameter for the classify.otu command."); m->mothurOutEndLine(); abort = true; }
151                         else if (taxfile == "not open") { abort = true; }
152                         
153                         refTaxonomy = validParameter.validFile(parameters, "reftaxonomy", true);
154                         if (refTaxonomy == "not found") { refTaxonomy = ""; m->mothurOut("reftaxonomy is not required, but if given will keep the rankIDs in the summary file static."); m->mothurOutEndLine(); }
155                         else if (refTaxonomy == "not open") { abort = true; }
156         
157                         namefile = validParameter.validFile(parameters, "name", true);
158                         if (namefile == "not open") { abort = true; }   
159                         else if (namefile == "not found") { namefile = ""; }
160                         
161                         groupfile = validParameter.validFile(parameters, "group", true);
162                         if (groupfile == "not open") { abort = true; }  
163                         else if (groupfile == "not found") { groupfile = ""; }
164                         
165                         //check for optional parameter and set defaults
166                         // ...at some point should added some additional type checking...
167                         label = validParameter.validFile(parameters, "label", false);                   
168                         if (label == "not found") { label = ""; allLines = 1;  }
169                         else { 
170                                 if(label != "all") {  m->splitAtDash(label, labels);  allLines = 0;  }
171                                 else { allLines = 1;  }
172                         }
173                         
174                         basis = validParameter.validFile(parameters, "basis", false);
175                         if (basis == "not found") { basis = "otu"; }    
176                         
177                         if ((basis != "otu") && (basis != "sequence")) { m->mothurOut("Invalid option for basis. basis options are otu and sequence, using otu."); m->mothurOutEndLine(); }
178                         
179                         string temp = validParameter.validFile(parameters, "cutoff", false);                    if (temp == "not found") { temp = "51"; }
180                         convert(temp, cutoff); 
181                         
182                         temp = validParameter.validFile(parameters, "probs", false);                                    if (temp == "not found"){       temp = "true";                  }
183                         probs = m->isTrue(temp);
184                         
185                         
186                         if ((cutoff < 51) || (cutoff > 100)) { m->mothurOut("cutoff must be above 50, and no greater than 100."); m->mothurOutEndLine(); abort = true;  }
187                         
188                 }
189         }
190         catch(exception& e) {
191                 m->errorOut(e, "ClassifyOtuCommand", "ClassifyOtuCommand");
192                 exit(1);
193         }
194 }
195
196 //**********************************************************************************************************************
197
198 void ClassifyOtuCommand::help(){
199         try {
200                 m->mothurOut("The classify.otu command parameters are list, taxonomy, reftaxonomy, name, group, cutoff, label, basis and probs.  The taxonomy and list parameters are required.\n");
201                 m->mothurOut("The reftaxonomy parameter allows you give the name of the reference taxonomy file used when you classified your sequences. Providing it will keep the rankIDs in the summary file static.\n");
202                 m->mothurOut("The name parameter allows you add a names file with your taxonomy file.\n");
203                 m->mothurOut("The group parameter allows you provide a group file to use in creating the summary file breakdown.\n");
204                 m->mothurOut("The basis parameter allows you indicate what you want the summary file to represent, options are otu and sequence. Default is otu.\n");
205                 m->mothurOut("For example consider the following basis=sequence could give Clostridiales        3       105     16      43      46, where 105 is the total number of sequences whose otu classified to Clostridiales.\n");
206                 m->mothurOut("16 is the number of sequences in the otus from groupA, 43 is the number of sequences in the otus from groupB, and 46 is the number of sequences in the otus from groupC.\n");
207                 m->mothurOut("Now for basis=otu could give Clostridiales        3       7       6       1       2, where 7 is the number of otus that classified to Clostridiales.\n");
208                 m->mothurOut("6 is the number of otus containing sequences from groupA, 1 is the number of otus containing sequences from groupB, and 2 is the number of otus containing sequences from groupC.\n");
209                 m->mothurOut("The label parameter allows you to select what distance levels you would like a output files created for, and is separated by dashes.\n");
210                 m->mothurOut("The default value for label is all labels in your inputfile.\n");
211                 m->mothurOut("The cutoff parameter allows you to specify a consensus confidence threshold for your taxonomy.  The default is 51, meaning 51%. Cutoff cannot be below 51.\n");
212                 m->mothurOut("The probs parameter shuts off the outputting of the consensus confidence results. The default is true, meaning you want the confidence to be shown.\n");
213                 m->mothurOut("The classify.otu command should be in the following format: classify.otu(taxonomy=yourTaxonomyFile, list=yourListFile, name=yourNamesFile, label=yourLabels).\n");
214                 m->mothurOut("Example classify.otu(taxonomy=abrecovery.silva.full.taxonomy, list=abrecovery.fn.list, label=0.10).\n");
215                 m->mothurOut("Note: No spaces between parameter labels (i.e. list), '=' and parameters (i.e.yourListFile).\n\n");
216         }
217         catch(exception& e) {
218                 m->errorOut(e, "ClassifyOtuCommand", "help");
219                 exit(1);
220         }
221 }
222
223 //**********************************************************************************************************************
224
225 ClassifyOtuCommand::~ClassifyOtuCommand(){}
226
227 //**********************************************************************************************************************
228
229 int ClassifyOtuCommand::execute(){
230         try {
231         
232                 if (abort == true) { return 0; }
233                 
234                 //if user gave a namesfile then use it
235                 if (namefile != "") {   readNamesFile();        }
236                 
237                 //read taxonomy file and save in map for easy access in building bin trees
238                 readTaxonomyFile();
239                 
240                 if (m->control_pressed) { return 0; }
241                 
242                 input = new InputData(listfile, "list");
243                 list = input->getListVector();
244                 string lastLabel = list->getLabel();
245
246                 //if the users enters label "0.06" and there is no "0.06" in their file use the next lowest label.
247                 set<string> processedLabels;
248                 set<string> userLabels = labels;
249                 
250                 if (m->control_pressed) { outputTypes.clear(); delete input; delete list; for (int i = 0; i < outputNames.size(); i++) {        remove(outputNames[i].c_str());  }  return 0; }
251         
252                 while((list != NULL) && ((allLines == 1) || (userLabels.size() != 0))) {
253                         
254                         if (allLines == 1 || labels.count(list->getLabel()) == 1){
255                         
256                                         m->mothurOut(list->getLabel() + "\t" + toString(list->size())); m->mothurOutEndLine();
257                                         process(list);
258                                         if (m->control_pressed) { outputTypes.clear(); for (int i = 0; i < outputNames.size(); i++) {   remove(outputNames[i].c_str());  } delete input; delete list; return 0; }
259                                                                                 
260                                         processedLabels.insert(list->getLabel());
261                                         userLabels.erase(list->getLabel());
262                         }
263                         
264                         if ((m->anyLabelsToProcess(list->getLabel(), userLabels, "") == true) && (processedLabels.count(lastLabel) != 1)) {
265                                         string saveLabel = list->getLabel();
266                                         
267                                         delete list;
268                                         list = input->getListVector(lastLabel);
269                                         m->mothurOut(list->getLabel() + "\t" + toString(list->size())); m->mothurOutEndLine();
270                                         process(list);
271                                 
272                                         
273                                         if (m->control_pressed) { outputTypes.clear();  for (int i = 0; i < outputNames.size(); i++) {  remove(outputNames[i].c_str());  } delete input; delete list; return 0; }
274                                                                                 
275                                         processedLabels.insert(list->getLabel());
276                                         userLabels.erase(list->getLabel());
277                                         
278                                         //restore real lastlabel to save below
279                                         list->setLabel(saveLabel);
280                         }
281                         
282                         lastLabel = list->getLabel();
283         
284                         delete list;
285                         list = input->getListVector();
286                 }
287                 
288                 //output error messages about any remaining user labels
289                 bool needToRun = false;
290                 for (set<string>::iterator it = userLabels.begin(); it != userLabels.end(); it++) {  
291                         m->mothurOut("Your file does not include the label " + (*it)); 
292                         if (processedLabels.count(lastLabel) != 1) {
293                                 m->mothurOut(". I will use " + lastLabel + "."); m->mothurOutEndLine();
294                                 needToRun = true;
295                         }else {
296                                 m->mothurOut(". Please refer to " + lastLabel + "."); m->mothurOutEndLine();
297                         }
298                 }
299                 
300                 //run last label if you need to
301                 if (needToRun == true)  {
302                         if (list != NULL) {     delete list;    }
303                         list = input->getListVector(lastLabel);
304                         m->mothurOut(list->getLabel() + "\t" + toString(list->size())); m->mothurOutEndLine();
305                         
306                         process(list);
307                         delete list;
308                         
309                         if (m->control_pressed) { outputTypes.clear();  for (int i = 0; i < outputNames.size(); i++) {  remove(outputNames[i].c_str());  } delete input; delete list; return 0; }
310                 }
311                 
312                 delete input;  
313                                 
314                 if (m->control_pressed) { outputTypes.clear(); for (int i = 0; i < outputNames.size(); i++) {   remove(outputNames[i].c_str());  } return 0; }
315                 
316                 m->mothurOutEndLine();
317                 m->mothurOut("Output File Names: "); m->mothurOutEndLine();
318                 for (int i = 0; i < outputNames.size(); i++) {  m->mothurOut(outputNames[i]); m->mothurOutEndLine();    }
319                 m->mothurOutEndLine();
320                 
321                 return 0;
322         }
323         catch(exception& e) {
324                 m->errorOut(e, "ClassifyOtuCommand", "execute");
325                 exit(1);
326         }
327 }
328
329 //**********************************************************************************************************************
330 int ClassifyOtuCommand::readNamesFile() {
331         try {
332                 
333                 ifstream inNames;
334                 m->openInputFile(namefile, inNames);
335                 
336                 string name, names;
337         
338                 while(!inNames.eof()){
339                         inNames >> name;                        //read from first column  A
340                         inNames >> names;               //read from second column  A,B,C,D
341                         m->gobble(inNames);
342                         
343                         //parse names into vector
344                         vector<string> theseNames;
345                         m->splitAtComma(names, theseNames);
346
347                         for (int i = 0; i < theseNames.size(); i++) {  nameMap[theseNames[i]] = name;  }
348                         
349                         if (m->control_pressed) { inNames.close(); nameMap.clear(); return 0; }
350                 }
351                 inNames.close();
352                 
353                 return 0;
354         }
355         catch(exception& e) {
356                 m->errorOut(e, "ClassifyOtuCommand", "readNamesFile");
357                 exit(1);
358         }
359 }
360 //**********************************************************************************************************************
361 int ClassifyOtuCommand::readTaxonomyFile() {
362         try {
363                 
364                 ifstream in;
365                 m->openInputFile(taxfile, in);
366                 
367                 string name, tax;
368         
369                 while(!in.eof()){
370                         in >> name >> tax;              
371                         m->gobble(in);
372                         
373                         //are there confidence scores, if so remove them
374                         if (tax.find_first_of('(') != -1) {  removeConfidences(tax);    }
375                         
376                         taxMap[name] = tax;
377                         
378                         if (m->control_pressed) { in.close(); taxMap.clear(); return 0; }
379                 }
380                 in.close();
381                 
382                 return 0;
383         }
384         catch(exception& e) {
385                 m->errorOut(e, "ClassifyOtuCommand", "readTaxonomyFile");
386                 exit(1);
387         }
388 }
389 //**********************************************************************************************************************
390 vector<string> ClassifyOtuCommand::findConsensusTaxonomy(int bin, ListVector* thisList, int& size, string& conTax) {
391         try{
392                 conTax = "";
393                 vector<string> names;
394                 vector<string> allNames;
395                 map<string, string>::iterator it;
396                 map<string, string>::iterator it2;
397
398                 //parse names into vector
399                 string binnames = thisList->get(bin);
400                 m->splitAtComma(binnames, names);
401
402                 //create a tree containing sequences from this bin
403                 PhyloTree* phylo = new PhyloTree();
404                 
405                 size = 0;
406                 for (int i = 0; i < names.size(); i++) {
407         
408                         //if namesfile include the names
409                         if (namefile != "") {
410         
411                                 //is this sequence in the name file - namemap maps seqName -> repSeqName
412                                 it2 = nameMap.find(names[i]);
413                                 
414                                 if (it2 == nameMap.end()) { //this name is not in name file, skip it
415                                         m->mothurOut(names[i] + " is not in your name file.  I will not include it in the consensus."); m->mothurOutEndLine();
416                                 }else{
417                                         
418                                         //is this sequence in the taxonomy file - look for repSeqName since we are assuming the taxonomy file is unique
419                                         it = taxMap.find(it2->second);
420                         
421                                         if (it == taxMap.end()) { //this name is not in taxonomy file, skip it
422                                         
423                                                 if (names[i] != it2->second) { m->mothurOut(names[i] + " is represented by " +  it2->second + " and is not in your taxonomy file.  I will not include it in the consensus."); m->mothurOutEndLine(); }
424                                                 else {  m->mothurOut(names[i] + " is not in your taxonomy file.  I will not include it in the consensus."); m->mothurOutEndLine(); }
425                                         }else{
426                                 
427                                                 //add seq to tree
428                                                 phylo->addSeqToTree(names[i], it->second);
429                                                 size++;
430                                                 allNames.push_back(names[i]);
431                                         }
432                                 }
433                                 
434                         }else{
435                                 //is this sequence in the taxonomy file - look for repSeqName since we are assuming the taxonomy file is unique
436                                 it = taxMap.find(names[i]);
437                 
438                                 if (it == taxMap.end()) { //this name is not in taxonomy file, skip it
439                                         m->mothurOut(names[i] + " is not in your taxonomy file.  I will not include it in the consensus."); m->mothurOutEndLine();
440                                 }else{
441                                         //add seq to tree
442                                         phylo->addSeqToTree(names[i], it->second);
443                                         size++;
444                                         allNames.push_back(names[i]);
445                                 }
446                         }
447
448                         
449                         if (m->control_pressed) { delete phylo; return allNames; }
450                         
451                 }
452                 
453                 //build tree
454                 phylo->assignHeirarchyIDs(0);
455                 
456                 TaxNode currentNode = phylo->get(0);
457                 
458                 //at each level
459                 while (currentNode.children.size() != 0) { //you still have more to explore
460                 
461                         TaxNode bestChild;
462                         int bestChildSize = 0;
463                         
464                         //go through children
465                         for (map<string, int>::iterator itChild = currentNode.children.begin(); itChild != currentNode.children.end(); itChild++) {
466                                 
467                                 TaxNode temp = phylo->get(itChild->second);
468                                 
469                                 //select child with largest accesions - most seqs assigned to it
470                                 if (temp.accessions.size() > bestChildSize) {
471                                         bestChild = phylo->get(itChild->second);
472                                         bestChildSize = temp.accessions.size();
473                                 }
474                                 
475                         }
476                                 
477                         //is this taxonomy above cutoff
478                         int consensusConfidence = ceil((bestChildSize / (float) size) * 100);
479                         
480                         if (consensusConfidence >= cutoff) { //if yes, add it
481                                 if (probs) {
482                                         conTax += bestChild.name + "(" + toString(consensusConfidence) + ");";
483                                 }else{
484                                         conTax += bestChild.name + ";";
485                                 }
486                         }else{ //if no, quit
487                                 break;
488                         }
489                         
490                         //move down a level
491                         currentNode = bestChild;
492                 }
493                 
494                                 
495                 if (conTax == "") {  conTax = "no_consensus;";  }
496                 
497                 delete phylo;   
498                 
499                 return allNames;
500                         
501         }
502         catch(exception& e) {
503                 m->errorOut(e, "ClassifyOtuCommand", "findConsensusTaxonomy");
504                 exit(1);
505         }
506 }
507
508 //**********************************************************************************************************************
509 int ClassifyOtuCommand::process(ListVector* processList) {
510         try{
511                 string conTax;
512                 int size;
513                 
514                 //create output file
515                 if (outputDir == "") { outputDir += m->hasPath(listfile); }
516                                 
517                 ofstream out;
518                 string outputFile = outputDir + m->getRootName(m->getSimpleName(listfile)) + processList->getLabel() + ".cons.taxonomy";
519                 m->openOutputFile(outputFile, out);
520                 outputNames.push_back(outputFile); outputTypes["constaxonomy"].push_back(outputFile);
521                 
522                 ofstream outSum;
523                 string outputSumFile = outputDir + m->getRootName(m->getSimpleName(listfile)) + processList->getLabel() + ".cons.tax.summary";
524                 m->openOutputFile(outputSumFile, outSum);
525                 outputNames.push_back(outputSumFile); outputTypes["taxsummary"].push_back(outputSumFile);
526                 
527                 out << "OTU\tSize\tTaxonomy" << endl;
528                 
529                 PhyloSummary* taxaSum;
530                 if (refTaxonomy != "") {
531                         taxaSum = new PhyloSummary(refTaxonomy, groupfile);
532                 }else {
533                         taxaSum = new PhyloSummary(groupfile);
534                 }
535                 
536                 //for each bin in the list vector
537                 for (int i = 0; i < processList->getNumBins(); i++) {
538                         
539                         if (m->control_pressed) { break; }
540                         
541                         vector<string> names;
542                         names = findConsensusTaxonomy(i, processList, size, conTax);
543                 
544                         if (m->control_pressed) { out.close();  return 0; }
545                         
546                         //output to new names file
547                         out << (i+1) << '\t' << size << '\t' << conTax << endl;
548                         
549                         string noConfidenceConTax = conTax;
550                         removeConfidences(noConfidenceConTax);
551                         
552                         //add this bins taxonomy to summary
553                         if (basis == "sequence") {
554                                 for(int j = 0; j < names.size(); j++) {  taxaSum->addSeqToTree(names[j], noConfidenceConTax);  }
555                         }else { //otu
556                                 taxaSum->addSeqToTree(noConfidenceConTax, names);
557                         }
558                 }
559
560                 out.close();
561                 
562                 //print summary file
563                 taxaSum->print(outSum);
564                 outSum.close();
565                 
566                 delete taxaSum;
567                 
568                 return 0;
569
570         }
571         catch(exception& e) {
572                 m->errorOut(e, "ClassifyOtuCommand", "process");
573                 exit(1);
574         }
575 }
576 /**************************************************************************************************/
577 void ClassifyOtuCommand::removeConfidences(string& tax) {
578         try {
579                 
580                 string taxon;
581                 string newTax = "";
582                 
583                 while (tax.find_first_of(';') != -1) {
584                         //get taxon
585                         taxon = tax.substr(0,tax.find_first_of(';'));
586                         
587                         int pos = taxon.find_first_of('(');
588                         if (pos != -1) {
589                                 taxon = taxon.substr(0, pos); //rip off confidence 
590                         }
591                         
592                         taxon += ";";
593                         
594                         tax = tax.substr(tax.find_first_of(';')+1, tax.length());
595                         newTax += taxon;
596                 }
597                 
598                 tax = newTax;
599         }
600         catch(exception& e) {
601                 m->errorOut(e, "ClassifyOtuCommand", "removeConfidences");
602                 exit(1);
603         }
604 }
605 //**********************************************************************************************************************
606
607