]> git.donarmstrong.com Git - mothur.git/blob - makebiomcommand.cpp
added make.biom command
[mothur.git] / makebiomcommand.cpp
1 //
2 //  makebiomcommand.cpp
3 //  Mothur
4 //
5 //  Created by Sarah Westcott on 4/16/12.
6 //  Copyright (c) 2012 Schloss Lab. All rights reserved.
7 //
8
9 #include "makebiomcommand.h"
10 #include "sharedrabundvector.h"
11 #include "inputdata.h"
12
13 //taken from http://biom-format.org/documentation/biom_format.html
14 /* Minimal Sparse 
15  {
16  "id":null,
17  "format": "Biological Observation Matrix 0.9.1",
18  "format_url": "http://biom-format.org",
19  "type": "OTU table",
20  "generated_by": "QIIME revision 1.4.0-dev",
21  "date": "2011-12-19T19:00:00",
22  "rows":[
23  {"id":"GG_OTU_1", "metadata":null},
24  {"id":"GG_OTU_2", "metadata":null},
25  {"id":"GG_OTU_3", "metadata":null},
26  {"id":"GG_OTU_4", "metadata":null},
27  {"id":"GG_OTU_5", "metadata":null}
28  ],
29  "columns": [
30  {"id":"Sample1", "metadata":null},
31  {"id":"Sample2", "metadata":null},
32  {"id":"Sample3", "metadata":null},
33  {"id":"Sample4", "metadata":null},
34  {"id":"Sample5", "metadata":null},
35  {"id":"Sample6", "metadata":null}
36  ],
37  "matrix_type": "sparse",
38  "matrix_element_type": "int",
39  "shape": [5, 6],
40  "data":[[0,2,1],
41  [1,0,5],
42  [1,1,1],
43  [1,3,2],
44  [1,4,3],
45  [1,5,1],
46  [2,2,1],
47  [2,3,4],
48  [2,4,2],
49  [3,0,2],
50  [3,1,1],
51  [3,2,1],
52  [3,5,1],
53  [4,1,1],
54  [4,2,1]
55  ]
56  }
57  */
58 /* Minimal dense
59  {
60  "id":null,
61  "format": "Biological Observation Matrix 0.9.1",
62  "format_url": "http://biom-format.org",
63  "type": "OTU table",
64  "generated_by": "QIIME revision 1.4.0-dev",
65  "date": "2011-12-19T19:00:00",
66  "rows":[
67  {"id":"GG_OTU_1", "metadata":null},
68  {"id":"GG_OTU_2", "metadata":null},
69  {"id":"GG_OTU_3", "metadata":null},
70  {"id":"GG_OTU_4", "metadata":null},
71  {"id":"GG_OTU_5", "metadata":null}
72  ],
73  "columns": [
74  {"id":"Sample1", "metadata":null},
75  {"id":"Sample2", "metadata":null},
76  {"id":"Sample3", "metadata":null},
77  {"id":"Sample4", "metadata":null},
78  {"id":"Sample5", "metadata":null},
79  {"id":"Sample6", "metadata":null}
80  ],
81  "matrix_type": "dense",
82  "matrix_element_type": "int",
83  "shape": [5,6],
84  "data":  [[0,0,1,0,0,0],
85  [5,1,0,2,3,1],
86  [0,0,1,4,2,0],
87  [2,1,1,0,0,1],
88  [0,1,1,0,0,0]]
89  }
90  */
91 //**********************************************************************************************************************
92 vector<string> MakeBiomCommand::setParameters(){        
93         try {
94                 CommandParameter pshared("shared", "InputTypes", "", "", "none", "none", "none",false,true); parameters.push_back(pshared);
95         CommandParameter pcontaxonomy("contaxonomy", "InputTypes", "", "", "none", "none", "none",false,false); parameters.push_back(pcontaxonomy);
96                 CommandParameter pgroups("groups", "String", "", "", "", "", "",false,false); parameters.push_back(pgroups);
97                 CommandParameter plabel("label", "String", "", "", "", "", "",false,false); parameters.push_back(plabel);
98                 CommandParameter pinputdir("inputdir", "String", "", "", "", "", "",false,false); parameters.push_back(pinputdir);
99                 CommandParameter poutputdir("outputdir", "String", "", "", "", "", "",false,false); parameters.push_back(poutputdir);
100         CommandParameter pmatrixtype("matrixtype", "Multiple", "sparse-dense", "sparse", "", "", "",false,false); parameters.push_back(pmatrixtype);
101
102                 vector<string> myArray;
103                 for (int i = 0; i < parameters.size(); i++) {   myArray.push_back(parameters[i].name);          }
104                 return myArray;
105         }
106         catch(exception& e) {
107                 m->errorOut(e, "MakeBiomCommand", "setParameters");
108                 exit(1);
109         }
110 }
111 //**********************************************************************************************************************
112 string MakeBiomCommand::getHelpString(){        
113         try {
114                 string helpString = "";
115                 helpString += "The make.biom command parameters are shared, groups, matrixtype and label.  shared is required, unless you have a valid current file.\n";
116                 helpString += "The groups parameter allows you to specify which of the groups in your groupfile you would like included. The group names are separated by dashes.\n";
117                 helpString += "The label parameter allows you to select what distance levels you would like, and are also separated by dashes.\n";
118                 helpString += "The matrixtype parameter allows you to select what type you would like to make. Choices are sparse and dense, default is sparse.\n";
119                 helpString += "The make.biom command should be in the following format: make.biom(shared=yourShared, groups=yourGroups, label=yourLabels).\n";
120         helpString += "The contaxonomy file is the taxonomy file outputted by classify.otu(list=yourListfile, taxonomy=yourTaxonomyFile). Be SURE that the you are the constaxonomy file distance matches the shared file distance.  ie, for *.0.03.cons.taxonomy set label=0.03. Mothur is smart enough to handle shared files that have been subsampled after the classify.otu command was run on the list and taxonomy file.\n";
121                 helpString += "Example make.biom(shared=abrecovery.an.shared, groups=A-B-C).\n";
122                 helpString += "The default value for groups is all the groups in your groupfile, and all labels in your inputfile will be used.\n";
123                 helpString += "The make.biom command outputs a .biom file.\n";
124                 helpString += "Note: No spaces between parameter labels (i.e. groups), '=' and parameters (i.e.yourGroups).\n";
125                 return helpString;
126         }
127         catch(exception& e) {
128                 m->errorOut(e, "MakeBiomCommand", "getHelpString");
129                 exit(1);
130         }
131 }
132 //**********************************************************************************************************************
133 MakeBiomCommand::MakeBiomCommand(){     
134         try {
135                 abort = true; calledHelp = true; 
136                 setParameters();
137                 vector<string> tempOutNames;
138                 outputTypes["biom"] = tempOutNames;
139         }
140         catch(exception& e) {
141                 m->errorOut(e, "MakeBiomCommand", "MakeBiomCommand");
142                 exit(1);
143         }
144 }
145 //**********************************************************************************************************************
146 MakeBiomCommand::MakeBiomCommand(string option) {
147         try {
148                 abort = false; calledHelp = false;   
149                 allLines = 1;
150         
151                 //allow user to run help
152                 if(option == "help") { help(); abort = true; calledHelp = true; }
153                 else if(option == "citation") { citation(); abort = true; calledHelp = true;}
154                 
155                 else {
156                         vector<string> myArray = setParameters();
157                         
158                         OptionParser parser(option);
159                         map<string,string> parameters = parser.getParameters();
160                         map<string,string>::iterator it;
161                         
162                         ValidParameters validParameter;
163                         
164                         //check to make sure all parameters are valid for command
165                         for (it = parameters.begin(); it != parameters.end(); it++) { 
166                                 if (validParameter.isValidParameter(it->first, myArray, it->second) != true) {  abort = true;  }
167                         }
168                         
169                         //initialize outputTypes
170                         vector<string> tempOutNames;
171                         outputTypes["relabund"] = tempOutNames;
172                         
173                         //if the user changes the input directory command factory will send this info to us in the output parameter 
174                         string inputDir = validParameter.validFile(parameters, "inputdir", false);              
175                         if (inputDir == "not found"){   inputDir = "";          }
176                         else {
177                                 string path;
178                                 it = parameters.find("shared");
179                                 //user has given a template file
180                                 if(it != parameters.end()){ 
181                                         path = m->hasPath(it->second);
182                                         //if the user has not given a path then, add inputdir. else leave path alone.
183                                         if (path == "") {       parameters["shared"] = inputDir + it->second;           }
184                                 }
185                 
186                 it = parameters.find("contaxonomy");
187                                 //user has given a template file
188                                 if(it != parameters.end()){ 
189                                         path = m->hasPath(it->second);
190                                         //if the user has not given a path then, add inputdir. else leave path alone.
191                                         if (path == "") {       parameters["contaxonomy"] = inputDir + it->second;              }
192                                 }
193                         }
194             
195                         //get shared file
196                         sharedfile = validParameter.validFile(parameters, "shared", true);
197                         if (sharedfile == "not open") { sharedfile = ""; abort = true; }        
198                         else if (sharedfile == "not found") { 
199                                 //if there is a current shared file, use it
200                                 sharedfile = m->getSharedFile(); 
201                                 if (sharedfile != "") { m->mothurOut("Using " + sharedfile + " as input file for the shared parameter."); m->mothurOutEndLine(); }
202                                 else {  m->mothurOut("You have no current sharedfile and the shared parameter is required."); m->mothurOutEndLine(); abort = true; }
203                         }else { m->setSharedFile(sharedfile); }
204                         
205                         
206                         //if the user changes the output directory command factory will send this info to us in the output parameter 
207                         outputDir = validParameter.validFile(parameters, "outputdir", false);           if (outputDir == "not found"){  outputDir = m->hasPath(sharedfile);             }
208             
209             contaxonomyfile = validParameter.validFile(parameters, "contaxonomy", true);
210                         if (contaxonomyfile == "not found") {  contaxonomyfile = "";  }
211                         else if (contaxonomyfile == "not open") { contaxonomyfile = ""; abort = true; }
212
213             
214                         //check for optional parameter and set defaults
215                         // ...at some point should added some additional type checking...
216                         label = validParameter.validFile(parameters, "label", false);                   
217                         if (label == "not found") { label = ""; }
218                         else { 
219                                 if(label != "all") {  m->splitAtDash(label, labels);  allLines = 0;  }
220                                 else { allLines = 1;  }
221                         }
222                         
223                         groups = validParameter.validFile(parameters, "groups", false);                 
224                         if (groups == "not found") { groups = ""; }
225                         else { 
226                                 m->splitAtDash(groups, Groups);
227                                 m->setGroups(Groups);
228                         }
229                         
230             if ((contaxonomyfile != "") && (labels.size() > 1)) { m->mothurOut("[ERROR]: the contaxonomy parameter cannot be used with multiple labels."); m->mothurOutEndLine(); abort = true; }
231             
232                         format = validParameter.validFile(parameters, "matrixtype", false);                             if (format == "not found") { format = "sparse"; }
233                         
234                         if ((format != "sparse") && (format != "dense")) {
235                                 m->mothurOut(format + " is not a valid option for the matrixtype parameter. Options are sparse and dense."); m->mothurOutEndLine(); abort = true; 
236                         }
237                 }
238         
239         }
240         catch(exception& e) {
241                 m->errorOut(e, "MakeBiomCommand", "MakeBiomCommand");
242                 exit(1);
243         }
244 }
245 //**********************************************************************************************************************
246
247 int MakeBiomCommand::execute(){
248         try {
249         
250                 if (abort == true) { if (calledHelp) { return 0; }  return 2;   }
251             
252                 InputData input(sharedfile, "sharedfile");
253                 vector<SharedRAbundVector*> lookup = input.getSharedRAbundVectors();
254                 string lastLabel = lookup[0]->getLabel();
255         
256         //if user did not specify a label, then use first one
257         if ((contaxonomyfile != "") && (labels.size() == 0)) {
258             allLines = 0;
259             labels.insert(lastLabel);
260         }
261                 
262                 //if the users enters label "0.06" and there is no "0.06" in their file use the next lowest label.
263                 set<string> processedLabels;
264                 set<string> userLabels = labels;
265         
266                 //as long as you are not at the end of the file or done wih the lines you want
267                 while((lookup[0] != NULL) && ((allLines == 1) || (userLabels.size() != 0))) {
268                         
269                         if (m->control_pressed) { for (int i = 0; i < outputNames.size(); i++) {        m->mothurRemove(outputNames[i]); } for (int i = 0; i < lookup.size(); i++) {  delete lookup[i];  }  return 0; }
270             
271                         if(allLines == 1 || labels.count(lookup[0]->getLabel()) == 1){                  
272                 
273                                 m->mothurOut(lookup[0]->getLabel()); m->mothurOutEndLine();
274                                 getBiom(lookup);
275                                 
276                                 processedLabels.insert(lookup[0]->getLabel());
277                                 userLabels.erase(lookup[0]->getLabel());
278                         }
279                         
280                         if ((m->anyLabelsToProcess(lookup[0]->getLabel(), userLabels, "") == true) && (processedLabels.count(lastLabel) != 1)) {
281                                 string saveLabel = lookup[0]->getLabel();
282                 
283                                 for (int i = 0; i < lookup.size(); i++) {  delete lookup[i];  }  
284                                 lookup = input.getSharedRAbundVectors(lastLabel);
285                                 m->mothurOut(lookup[0]->getLabel()); m->mothurOutEndLine();
286                                 
287                                 getBiom(lookup);
288                                 
289                                 processedLabels.insert(lookup[0]->getLabel());
290                                 userLabels.erase(lookup[0]->getLabel());
291                                 
292                                 //restore real lastlabel to save below
293                                 lookup[0]->setLabel(saveLabel);
294                         }
295                         
296                         lastLabel = lookup[0]->getLabel();
297             
298                         //prevent memory leak and get next set
299                         for (int i = 0; i < lookup.size(); i++) {  delete lookup[i]; lookup[i] = NULL; }
300                         lookup = input.getSharedRAbundVectors();                                
301                 }
302                 
303         if (m->control_pressed) { for (int i = 0; i < outputNames.size(); i++) {        m->mothurRemove(outputNames[i]); }  return 0; }     
304         
305                 //output error messages about any remaining user labels
306                 set<string>::iterator it;
307                 bool needToRun = false;
308                 for (it = userLabels.begin(); it != userLabels.end(); it++) {  
309                         m->mothurOut("Your file does not include the label " + *it); 
310                         if (processedLabels.count(lastLabel) != 1) {
311                                 m->mothurOut(". I will use " + lastLabel + "."); m->mothurOutEndLine();
312                                 needToRun = true;
313                         }else {
314                                 m->mothurOut(". Please refer to " + lastLabel + "."); m->mothurOutEndLine();
315                         }
316                 }
317         
318                 //run last label if you need to
319                 if (needToRun == true)  {
320                         for (int i = 0; i < lookup.size(); i++) { if (lookup[i] != NULL) { delete lookup[i]; } }  
321                         lookup = input.getSharedRAbundVectors(lastLabel);
322                         
323                         m->mothurOut(lookup[0]->getLabel()); m->mothurOutEndLine();
324             getBiom(lookup);
325                         
326                         for (int i = 0; i < lookup.size(); i++) {  delete lookup[i];  }
327                 }
328                 
329         if (m->control_pressed) { for (int i = 0; i < outputNames.size(); i++) {        m->mothurRemove(outputNames[i]); }  return 0; }     
330                 
331                 m->mothurOutEndLine();
332                 m->mothurOut("Output File Names: "); m->mothurOutEndLine();
333                 for (int i = 0; i < outputNames.size(); i++) {  m->mothurOut(outputNames[i]); m->mothurOutEndLine();    }
334                 m->mothurOutEndLine();
335                 
336                 return 0;
337         }
338         catch(exception& e) {
339                 m->errorOut(e, "MakeBiomCommand", "execute");
340                 exit(1);
341         }
342 }
343 //**********************************************************************************************************************
344 int MakeBiomCommand::getBiom(vector<SharedRAbundVector*>& lookup){
345         try {
346         
347         string outputFileName = outputDir + m->getRootName(m->getSimpleName(sharedfile)) + lookup[0]->getLabel() + ".biom";
348                 ofstream out;
349                 m->openOutputFile(outputFileName, out);
350                 outputNames.push_back(outputFileName); outputTypes["biom"].push_back(outputFileName);
351
352         string mothurString = "mothur" + toString(m->getVersion());
353         time_t rawtime;
354         struct tm * timeinfo;
355         time ( &rawtime );
356         timeinfo = localtime ( &rawtime );
357         string dateString = asctime (timeinfo);
358         int pos = dateString.find('\n');
359         if (pos != string::npos) { dateString = dateString.substr(0, pos);}
360         string spaces = "      ";
361         
362         //standard 
363         out << "{\n" + spaces + "\"id\":\"" + sharedfile + "-" + lookup[0]->getLabel() + "\",\n" + spaces + "\"format\": \"Biological Observation Matrix 0.9.1\",\n" + spaces + "\"format_url\": \"http://biom-format.org\",\n";
364         out << spaces + "\"type\": \"OTU table\",\n" + spaces + "\"generated_by\": \"" << mothurString << "\",\n" + spaces + "\"date\": \"" << dateString << "\",\n";
365         
366         vector<string> metadata = getMetaData(lookup);  
367         
368         if (m->control_pressed) {  out.close(); return 0; }
369         
370         //get row info
371         /*"rows":[
372                 {"id":"GG_OTU_1", "metadata":null},
373                 {"id":"GG_OTU_2", "metadata":null},
374                 {"id":"GG_OTU_3", "metadata":null},
375                 {"id":"GG_OTU_4", "metadata":null},
376                 {"id":"GG_OTU_5", "metadata":null}
377                 ],*/
378         out << spaces + "\"rows\":[\n";
379         string rowFront = spaces + spaces + "{\"id\":\"";
380         string rowBack = "\", \"metadata\":";
381         for (int i = 0; i < m->currentBinLabels.size()-1; i++) {
382             if (m->control_pressed) {  out.close(); return 0; }
383             out << rowFront << m->currentBinLabels[i] << rowBack << metadata[i] << "},\n";
384         }
385         out << rowFront << m->currentBinLabels[(m->currentBinLabels.size()-1)] << rowBack << metadata[(m->currentBinLabels.size()-1)] << "}\n" + spaces + "],\n";
386         
387         //get column info
388         /*"columns": [
389                     {"id":"Sample1", "metadata":null},
390                     {"id":"Sample2", "metadata":null},
391                     {"id":"Sample3", "metadata":null},
392                     {"id":"Sample4", "metadata":null},
393                     {"id":"Sample5", "metadata":null},
394                     {"id":"Sample6", "metadata":null}
395                     ],*/
396         
397         string colBack = "\", \"metadata\":null}";
398         out << spaces + "\"columns\":[\n";
399         for (int i = 0; i < lookup.size()-1; i++) {
400             if (m->control_pressed) {  out.close(); return 0; }
401             out << rowFront << lookup[i]->getGroup() << colBack << ",\n";
402         }
403         out << rowFront << lookup[(lookup.size()-1)]->getGroup() << colBack << "\n" + spaces + "],\n";
404         
405         out << spaces + "\"matrix_type\": \"" << format << "\",\n" + spaces + "\"matrix_element_type\": \"int\",\n";
406         out <<  spaces + "\"shape\": [" << m->currentBinLabels.size() << "," << lookup.size() << "],\n";
407         out << spaces + "\"data\":  [";
408         
409         vector<string> dataRows;
410         if (format == "sparse") {
411             /*"data":[[0,2,1],
412              [1,0,5],
413              [1,1,1],
414              [1,3,2],
415              [1,4,3],
416              [1,5,1],
417              [2,2,1],
418              [2,3,4],
419              [2,4,2],
420              [3,0,2],
421              [3,1,1],
422              [3,2,1],
423              [3,5,1],
424              [4,1,1],
425              [4,2,1]
426              ]*/
427             string output = "";
428             for (int i = 0; i < lookup[0]->getNumBins(); i++) {
429                 
430                 if (m->control_pressed) { out.close(); return 0; }
431                 
432                 for (int j = 0; j < lookup.size(); j++) {
433                     string binInfo = "[" + toString(i) + "," + toString(j) + "," + toString(lookup[j]->getAbundance(i)) + "]";
434                     //only print non zero values
435                     if (lookup[j]->getAbundance(i) != 0) { dataRows.push_back(binInfo); }
436                 }
437             }
438         }else {
439             
440             /* "matrix_type": "dense",
441              "matrix_element_type": "int",
442              "shape": [5,6],
443              "data":  [[0,0,1,0,0,0],
444              [5,1,0,2,3,1],
445              [0,0,1,4,2,0],
446              [2,1,1,0,0,1],
447              [0,1,1,0,0,0]]*/
448             
449             for (int i = 0; i < lookup[0]->getNumBins(); i++) {
450                 
451                 if (m->control_pressed) { out.close(); return 0; }
452                 
453                 string binInfo = "[";
454                 for (int j = 0; j < lookup.size()-1; j++) {
455                     binInfo += toString(lookup[j]->getAbundance(i)) + ",";
456                 }
457                 binInfo += toString(lookup[lookup.size()-1]->getAbundance(i)) + "]";
458                 dataRows.push_back(binInfo);
459             }
460         }
461         
462         for (int i = 0; i < dataRows.size()-1; i++) {
463             out << dataRows[i] << ",\n" + spaces  + spaces;
464         }
465         out << dataRows[dataRows.size()-1] << "]\n";
466         
467         out << "}\n";
468         out.close();
469         
470         return 0;
471     }
472         catch(exception& e) {
473                 m->errorOut(e, "MakeBiomCommand", "getBiom");
474                 exit(1);
475         }
476 }
477 //**********************************************************************************************************************
478 vector<string> MakeBiomCommand::getMetaData(vector<SharedRAbundVector*>& lookup){
479         try {
480         vector<string> metadata;
481         
482         if (contaxonomyfile == "") { for (int i = 0; i < lookup[0]->getNumBins(); i++) {  metadata.push_back("null");  } }
483         else {
484             
485             //read constaxonomy file storing in a map, otulabel -> taxonomy
486             //constaxonomy file will most likely contain more labels than the shared file, because sharedfile could have been subsampled.
487             ifstream in;
488             m->openInputFile(contaxonomyfile, in);
489             
490             //grab headers
491             m->getline(in); m->gobble(in);
492             
493             string otuLabel, tax;
494             int size;
495             vector<string> otuLabels;
496             vector<string> taxs;
497             while (!in.eof()) {
498                 
499                 if (m->control_pressed) { in.close(); return metadata; }
500                 
501                 in >> otuLabel >> size >> tax; m->gobble(in);
502                 
503                 otuLabels.push_back(otuLabel);
504                 taxs.push_back(tax);
505             }
506             in.close();
507             
508             //should the labels be Otu001 or PhyloType001
509             string firstBin = m->currentBinLabels[0];
510             string binTag = "Otu";
511             if ((firstBin.find("Otu")) == string::npos) { binTag = "PhyloType";  }
512             
513             //convert list file bin labels to shared file bin labels
514             //parse tax strings
515             //save in map
516             map<string, vector<string> > labelTaxMap;
517             string snumBins = toString(otuLabels.size());
518             for (int i = 0; i < otuLabels.size(); i++) {  
519                 
520                 if (m->control_pressed) { return metadata; }
521                 
522                 //if there is a bin label use it otherwise make one
523                 string binLabel = binTag;
524                 string sbinNumber = otuLabels[i];
525                 if (sbinNumber.length() < snumBins.length()) { 
526                     int diff = snumBins.length() - sbinNumber.length();
527                     for (int h = 0; h < diff; h++) { binLabel += "0"; }
528                 }
529                 binLabel += sbinNumber;
530                 
531                 vector<string> taxString;
532                 m->splitAtChar(taxs[i], taxString, ';');
533                 taxString.pop_back(); //adds blank string because taxonomies end in ;
534                 
535                 labelTaxMap[binLabel] = taxString;
536             }
537             
538             
539             //{"taxonomy":["k__Bacteria", "p__Proteobacteria", "c__Gammaproteobacteria", "o__Enterobacteriales", "f__Enterobacteriaceae", "g__Escherichia", "s__"]}
540             
541             //traverse the binLabels forming the metadata strings and saving them
542             //make sure to sanity check
543             map<string, vector<string> >::iterator it;
544             for (int i = 0; i < m->currentBinLabels.size(); i++) {
545                 
546                 if (m->control_pressed) { return metadata; }
547                 
548                 it = labelTaxMap.find(m->currentBinLabels[i]);
549                 
550                 if (it == labelTaxMap.end()) { m->mothurOut("[ERROR]: can't find taxonomy information for " + m->currentBinLabels[i] + ".\n"); m->control_pressed = true; }
551                 else {
552                     string data = "{\"taxonomy\":[";
553                     for (int j = 0; j < (it->second).size()-1; j ++) {
554                         
555                         string taxon = (it->second)[j];
556                         
557                         //strip "" if they are there
558                         int pos = taxon.find("\"");
559                         if (pos != string::npos) {
560                             string newTax = "";
561                             for (int k = 0; k < taxon.length(); k++) {
562                                 if (taxon[k] != '\"') { newTax += taxon[k]; }
563                             }
564                             taxon = newTax;
565                         }
566                         
567                         data += "\"" + taxon + "\", ";
568                     }
569                     
570                     string taxon = (it->second)[(it->second).size()-1];
571                     
572                     //strip "" if they are there
573                     int pos = taxon.find("\"");
574                     if (pos != string::npos) {
575                         string newTax = "";
576                         for (int k = 0; k < taxon.length(); k++) {
577                             if (taxon[k] != '\"') { newTax += taxon[k]; }
578                         }
579                         taxon = newTax;
580                     }
581                     
582                     data += "\"" + taxon + "\"]} ";
583                     
584                     metadata.push_back(data);
585                 }
586             }
587         }
588         
589         return metadata;
590         
591     }
592         catch(exception& e) {
593                 m->errorOut(e, "MakeBiomCommand", "getMetadata");
594                 exit(1);
595         }
596
597 }        
598 //**********************************************************************************************************************
599
600
601