2 * otuassociationcommand.cpp
5 * Created by westcott on 1/19/12.
6 * Copyright 2012 Schloss Lab. All rights reserved.
10 #include "otuassociationcommand.h"
11 #include "linearalgebra.h"
13 //**********************************************************************************************************************
14 vector<string> OTUAssociationCommand::setParameters(){
16 CommandParameter pshared("shared", "InputTypes", "", "", "SharedRelMeta", "SharedRelMeta", "none","otucorr",false,false,true); parameters.push_back(pshared);
17 CommandParameter prelabund("relabund", "InputTypes", "", "", "SharedRelMeta", "SharedRelMeta", "none","otucorr",false,false); parameters.push_back(prelabund);
18 CommandParameter pmetadata("metadata", "InputTypes", "", "", "none", "none", "none","",false,false); parameters.push_back(pmetadata);
19 CommandParameter pcutoff("cutoff", "Number", "", "10", "", "", "","",false,false,true); parameters.push_back(pcutoff);
20 CommandParameter plabel("label", "String", "", "", "", "", "","",false,false); parameters.push_back(plabel);
21 CommandParameter pgroups("groups", "String", "", "", "", "", "","",false,false); parameters.push_back(pgroups);
22 CommandParameter pmethod("method", "Multiple", "pearson-spearman-kendall", "pearson", "", "", "","",false,false,true); parameters.push_back(pmethod);
23 CommandParameter pinputdir("inputdir", "String", "", "", "", "", "","",false,false); parameters.push_back(pinputdir);
24 CommandParameter poutputdir("outputdir", "String", "", "", "", "", "","",false,false); parameters.push_back(poutputdir);
26 vector<string> myArray;
27 for (int i = 0; i < parameters.size(); i++) { myArray.push_back(parameters[i].name); }
31 m->errorOut(e, "OTUAssociationCommand", "setParameters");
35 //**********************************************************************************************************************
36 string OTUAssociationCommand::getHelpString(){
38 string helpString = "";
39 helpString += "The otu.association command reads a shared or relabund file and calculates the correlation coefficients between otus.\n";
40 helpString += "If you provide a metadata file, mothur will calculate te correlation bewteen the metadata and the otus.\n";
41 helpString += "The otu.association command parameters are shared, relabund, metadata, groups, method, cutoff and label. The shared or relabund parameter is required.\n";
42 helpString += "The groups parameter allows you to specify which of the groups you would like included. The group names are separated by dashes.\n";
43 helpString += "The label parameter allows you to select what distances level you would like used, and are also separated by dashes.\n";
44 helpString += "The cutoff parameter allows you to set a pvalue at which the otu will be reported.\n";
45 helpString += "The method parameter allows you to select what method you would like to use. Options are pearson, spearman and kendall. Default=pearson.\n";
46 helpString += "The otu.association command should be in the following format: otu.association(shared=yourSharedFile, method=yourMethod).\n";
47 helpString += "Example otu.association(shared=genus.pool.shared, method=kendall).\n";
48 helpString += "The otu.association command outputs a .otu.corr file.\n";
49 helpString += "Note: No spaces between parameter labels (i.e. groups), '=' and parameters (i.e.yourGroups).\n";
53 m->errorOut(e, "OTUAssociationCommand", "getHelpString");
57 //**********************************************************************************************************************
58 string OTUAssociationCommand::getOutputPattern(string type) {
62 if (type == "otucorr") { pattern = "[filename],[distance],[tag],otu.corr"; }
63 else { m->mothurOut("[ERROR]: No definition for type " + type + " output pattern.\n"); m->control_pressed = true; }
68 m->errorOut(e, "OTUAssociationCommand", "getOutputPattern");
72 //**********************************************************************************************************************
73 OTUAssociationCommand::OTUAssociationCommand(){
75 abort = true; calledHelp = true;
77 vector<string> tempOutNames;
78 outputTypes["otucorr"] = tempOutNames;
81 m->errorOut(e, "OTUAssociationCommand", "OTUAssociationCommand");
85 //**********************************************************************************************************************
86 OTUAssociationCommand::OTUAssociationCommand(string option) {
88 abort = false; calledHelp = false;
91 //allow user to run help
92 if(option == "help") { help(); abort = true; calledHelp = true; }
93 else if(option == "citation") { citation(); abort = true; calledHelp = true;}
96 vector<string> myArray = setParameters();
98 OptionParser parser(option);
99 map<string, string> parameters = parser.getParameters();
101 ValidParameters validParameter;
102 map<string, string>::iterator it;
104 //check to make sure all parameters are valid for command
105 for (it = parameters.begin(); it != parameters.end(); it++) {
106 if (validParameter.isValidParameter(it->first, myArray, it->second) != true) { abort = true; }
109 vector<string> tempOutNames;
110 outputTypes["otucorr"] = tempOutNames;
112 //if the user changes the input directory command factory will send this info to us in the output parameter
113 string inputDir = validParameter.validFile(parameters, "inputdir", false);
114 if (inputDir == "not found"){ inputDir = ""; }
117 it = parameters.find("shared");
118 //user has given a template file
119 if(it != parameters.end()){
120 path = m->hasPath(it->second);
121 //if the user has not given a path then, add inputdir. else leave path alone.
122 if (path == "") { parameters["shared"] = inputDir + it->second; }
125 it = parameters.find("relabund");
126 //user has given a template file
127 if(it != parameters.end()){
128 path = m->hasPath(it->second);
129 //if the user has not given a path then, add inputdir. else leave path alone.
130 if (path == "") { parameters["relabund"] = inputDir + it->second; }
133 it = parameters.find("metadata");
134 //user has given a template file
135 if(it != parameters.end()){
136 path = m->hasPath(it->second);
137 //if the user has not given a path then, add inputdir. else leave path alone.
138 if (path == "") { parameters["metadata"] = inputDir + it->second; }
143 //check for required parameters
144 sharedfile = validParameter.validFile(parameters, "shared", true);
145 if (sharedfile == "not open") { abort = true; }
146 else if (sharedfile == "not found") { sharedfile = ""; }
147 else { inputFileName = sharedfile; m->setSharedFile(sharedfile); }
149 relabundfile = validParameter.validFile(parameters, "relabund", true);
150 if (relabundfile == "not open") { abort = true; }
151 else if (relabundfile == "not found") { relabundfile = ""; }
152 else { inputFileName = relabundfile; m->setRelAbundFile(relabundfile); }
154 metadatafile = validParameter.validFile(parameters, "metadata", true);
155 if (metadatafile == "not open") { abort = true; metadatafile = ""; }
156 else if (metadatafile == "not found") { metadatafile = ""; }
158 groups = validParameter.validFile(parameters, "groups", false);
159 if (groups == "not found") { groups = ""; pickedGroups = false; }
162 m->splitAtDash(groups, Groups);
164 m->setGroups(Groups);
166 outputDir = validParameter.validFile(parameters, "outputdir", false); if (outputDir == "not found"){ outputDir = m->hasPath(inputFileName); }
168 label = validParameter.validFile(parameters, "label", false);
169 if (label == "not found") { label = ""; }
171 if(label != "all") { m->splitAtDash(label, labels); allLines = 0; }
172 else { allLines = 1; }
175 if ((relabundfile == "") && (sharedfile == "")) {
176 //is there are current file available for any of these?
177 //give priority to shared, then relabund
178 //if there is a current shared file, use it
179 sharedfile = m->getSharedFile();
180 if (sharedfile != "") { inputFileName = sharedfile; m->mothurOut("Using " + sharedfile + " as input file for the shared parameter."); m->mothurOutEndLine(); }
182 relabundfile = m->getRelAbundFile();
183 if (relabundfile != "") { inputFileName = relabundfile; m->mothurOut("Using " + relabundfile + " as input file for the relabund parameter."); m->mothurOutEndLine(); }
185 m->mothurOut("You must provide either a shared or relabund file."); m->mothurOutEndLine(); abort = true;
191 if ((relabundfile != "") && (sharedfile != "")) { m->mothurOut("You may only use one of the following : shared or relabund file."); m->mothurOutEndLine(); abort = true; }
193 method = validParameter.validFile(parameters, "method", false); if (method == "not found"){ method = "pearson"; }
195 string temp = validParameter.validFile(parameters, "cutoff", false);
196 if (temp == "not found") { temp = "10"; }
197 m->mothurConvert(temp, cutoff);
199 if ((method != "pearson") && (method != "spearman") && (method != "kendall")) { m->mothurOut(method + " is not a valid method. Valid methods are pearson, spearman, and kendall."); m->mothurOutEndLine(); abort = true; }
203 catch(exception& e) {
204 m->errorOut(e, "OTUAssociationCommand", "OTUAssociationCommand");
208 //**********************************************************************************************************************
210 int OTUAssociationCommand::execute(){
213 if (abort == true) { if (calledHelp) { return 0; } return 2; }
215 if (metadatafile != "") { readMetadata(); }
217 //function are identical just different datatypes
218 if (sharedfile != "") { processShared(); }
219 else if (relabundfile != "") { processRelabund(); }
221 if (m->control_pressed) { for (int i = 0; i < outputNames.size(); i++) { m->mothurRemove(outputNames[i]); } return 0; }
223 m->mothurOutEndLine();
224 m->mothurOut("Output File Names: "); m->mothurOutEndLine();
225 for (int i = 0; i < outputNames.size(); i++) { m->mothurOut(outputNames[i]); m->mothurOutEndLine(); }
226 m->mothurOutEndLine();
230 catch(exception& e) {
231 m->errorOut(e, "OTUAssociationCommand", "execute");
235 //**********************************************************************************************************************
236 int OTUAssociationCommand::processShared(){
238 InputData* input = new InputData(sharedfile, "sharedfile");
239 vector<SharedRAbundVector*> lookup = input->getSharedRAbundVectors();
240 string lastLabel = lookup[0]->getLabel();
242 if (metadatafile != "") {
245 if (metadata[0].size() != lookup.size()) { m->mothurOut("[ERROR]: You have selected to use " + toString(metadata[0].size()) + " data rows from the metadata file, but " + toString(lookup.size()) + " from the shared file.\n"); m->control_pressed = true; error=true;}
247 //maybe add extra info here?? compare groups in each file??
251 //if the users enters label "0.06" and there is no "0.06" in their file use the next lowest label.
252 set<string> processedLabels;
253 set<string> userLabels = labels;
255 //as long as you are not at the end of the file or done wih the lines you want
256 while((lookup[0] != NULL) && ((allLines == 1) || (userLabels.size() != 0))) {
258 if (m->control_pressed) { delete input; return 0; }
260 if(allLines == 1 || labels.count(lookup[0]->getLabel()) == 1){
261 processedLabels.insert(lookup[0]->getLabel());
262 userLabels.erase(lookup[0]->getLabel());
264 m->mothurOut(lookup[0]->getLabel()); m->mothurOutEndLine();
268 if ((m->anyLabelsToProcess(lookup[0]->getLabel(), userLabels, "") == true) && (processedLabels.count(lastLabel) != 1)) {
269 string saveLabel = lookup[0]->getLabel();
271 for (int i = 0; i < lookup.size(); i++) { delete lookup[i]; }
272 lookup = input->getSharedRAbundVectors(lastLabel);
274 processedLabels.insert(lookup[0]->getLabel());
275 userLabels.erase(lookup[0]->getLabel());
277 //restore real lastlabel to save below
278 lookup[0]->setLabel(saveLabel);
280 m->mothurOut(lookup[0]->getLabel()); m->mothurOutEndLine();
284 lastLabel = lookup[0]->getLabel();
286 //get next line to process
287 //prevent memory leak
288 for (int i = 0; i < lookup.size(); i++) { delete lookup[i]; }
289 lookup = input->getSharedRAbundVectors();
293 if (m->control_pressed) { delete input; return 0; }
295 //output error messages about any remaining user labels
296 set<string>::iterator it;
297 bool needToRun = false;
298 for (it = userLabels.begin(); it != userLabels.end(); it++) {
299 m->mothurOut("Your file does not include the label " + *it);
300 if (processedLabels.count(lastLabel) != 1) {
301 m->mothurOut(". I will use " + lastLabel + "."); m->mothurOutEndLine();
304 m->mothurOut(". Please refer to " + lastLabel + "."); m->mothurOutEndLine();
308 //run last label if you need to
309 if (needToRun == true) {
310 for (int i = 0; i < lookup.size(); i++) { if (lookup[i] != NULL) { delete lookup[i]; } }
311 lookup = input->getSharedRAbundVectors(lastLabel);
313 m->mothurOut(lookup[0]->getLabel()); m->mothurOutEndLine();
321 catch(exception& e) {
322 m->errorOut(e, "OTUAssociationCommand", "processShared");
326 //**********************************************************************************************************************
327 int OTUAssociationCommand::process(vector<SharedRAbundVector*>& lookup){
329 map<string, string> variables;
330 variables["[filename]"] = outputDir + m->getRootName(m->getSimpleName(inputFileName));
331 variables["[distance]"] = lookup[0]->getLabel();
332 variables["[tag]"] = method;
333 string outputFileName = getOutputFileName("otucorr",variables);
334 outputNames.push_back(outputFileName); outputTypes["otucorr"].push_back(outputFileName);
337 m->openOutputFile(outputFileName, out);
338 out.setf(ios::fixed, ios::floatfield); out.setf(ios::showpoint);
341 if (metadatafile == "") { out << "OTUA\tOTUB\t" << method << "Coef\tSignificance\n"; }
342 else { out << "OTUA\tMetadata\t" << method << "Coef\tSignificance\n"; }
345 vector< vector<double> > xy; xy.resize(lookup[0]->getNumBins());
346 for (int i = 0; i < lookup[0]->getNumBins(); i++) { for (int j = 0; j < lookup.size(); j++) { xy[i].push_back(lookup[j]->getAbundance(i)); } }
348 LinearAlgebra linear;
349 if (metadatafile == "") {//compare otus
350 for (int i = 0; i < xy.size(); i++) {
352 for (int k = 0; k < i; k++) {
354 if (m->control_pressed) { out.close(); return 0; }
358 if (method == "spearman") { coef = linear.calcSpearman(xy[i], xy[k], sig); }
359 else if (method == "pearson") { coef = linear.calcPearson(xy[i], xy[k], sig); }
360 else if (method == "kendall") { coef = linear.calcKendall(xy[i], xy[k], sig); }
361 else { m->mothurOut("[ERROR]: invalid method, choices are spearman, pearson or kendall."); m->mothurOutEndLine(); m->control_pressed = true; }
363 if (sig < cutoff) { out << m->binLabelsInFile[i] << '\t' << m->binLabelsInFile[k] << '\t' << coef << '\t' << sig << endl; }
366 }else { //compare otus to metadata
367 for (int i = 0; i < xy.size(); i++) {
369 for (int k = 0; k < metadata.size(); k++) {
371 if (m->control_pressed) { out.close(); return 0; }
375 if (method == "spearman") { coef = linear.calcSpearman(xy[i], metadata[k], sig); }
376 else if (method == "pearson") { coef = linear.calcPearson(xy[i], metadata[k], sig); }
377 else if (method == "kendall") { coef = linear.calcKendall(xy[i], metadata[k], sig); }
378 else { m->mothurOut("[ERROR]: invalid method, choices are spearman, pearson or kendall."); m->mothurOutEndLine(); m->control_pressed = true; }
380 if (sig < cutoff) { out << m->binLabelsInFile[i] << '\t' << metadataLabels[k] << '\t' << coef << '\t' << sig << endl; }
391 catch(exception& e) {
392 m->errorOut(e, "OTUAssociationCommand", "process");
396 //**********************************************************************************************************************
397 int OTUAssociationCommand::processRelabund(){
399 InputData* input = new InputData(relabundfile, "relabund");
400 vector<SharedRAbundFloatVector*> lookup = input->getSharedRAbundFloatVectors();
401 string lastLabel = lookup[0]->getLabel();
403 if (metadatafile != "") {
406 if (metadata[0].size() != lookup.size()) { m->mothurOut("[ERROR]: You have selected to use " + toString(metadata[0].size()) + " data rows from the metadata file, but " + toString(lookup.size()) + " from the relabund file.\n"); m->control_pressed = true; error=true;}
408 //maybe add extra info here?? compare groups in each file??
414 //if the users enters label "0.06" and there is no "0.06" in their file use the next lowest label.
415 set<string> processedLabels;
416 set<string> userLabels = labels;
418 //as long as you are not at the end of the file or done wih the lines you want
419 while((lookup[0] != NULL) && ((allLines == 1) || (userLabels.size() != 0))) {
421 if (m->control_pressed) { delete input; return 0; }
423 if(allLines == 1 || labels.count(lookup[0]->getLabel()) == 1){
424 processedLabels.insert(lookup[0]->getLabel());
425 userLabels.erase(lookup[0]->getLabel());
427 m->mothurOut(lookup[0]->getLabel()); m->mothurOutEndLine();
431 if ((m->anyLabelsToProcess(lookup[0]->getLabel(), userLabels, "") == true) && (processedLabels.count(lastLabel) != 1)) {
432 string saveLabel = lookup[0]->getLabel();
434 for (int i = 0; i < lookup.size(); i++) { delete lookup[i]; }
435 lookup = input->getSharedRAbundFloatVectors(lastLabel);
437 processedLabels.insert(lookup[0]->getLabel());
438 userLabels.erase(lookup[0]->getLabel());
440 //restore real lastlabel to save below
441 lookup[0]->setLabel(saveLabel);
443 m->mothurOut(lookup[0]->getLabel()); m->mothurOutEndLine();
447 lastLabel = lookup[0]->getLabel();
449 //get next line to process
450 //prevent memory leak
451 for (int i = 0; i < lookup.size(); i++) { delete lookup[i]; }
452 lookup = input->getSharedRAbundFloatVectors();
456 if (m->control_pressed) { delete input; return 0; }
458 //output error messages about any remaining user labels
459 set<string>::iterator it;
460 bool needToRun = false;
461 for (it = userLabels.begin(); it != userLabels.end(); it++) {
462 m->mothurOut("Your file does not include the label " + *it);
463 if (processedLabels.count(lastLabel) != 1) {
464 m->mothurOut(". I will use " + lastLabel + "."); m->mothurOutEndLine();
467 m->mothurOut(". Please refer to " + lastLabel + "."); m->mothurOutEndLine();
471 //run last label if you need to
472 if (needToRun == true) {
473 for (int i = 0; i < lookup.size(); i++) { if (lookup[i] != NULL) { delete lookup[i]; } }
474 lookup = input->getSharedRAbundFloatVectors(lastLabel);
476 m->mothurOut(lookup[0]->getLabel()); m->mothurOutEndLine();
484 catch(exception& e) {
485 m->errorOut(e, "OTUAssociationCommand", "processRelabund");
489 //**********************************************************************************************************************
490 int OTUAssociationCommand::process(vector<SharedRAbundFloatVector*>& lookup){
493 map<string, string> variables;
494 variables["[filename]"] = outputDir + m->getRootName(m->getSimpleName(inputFileName));
495 variables["[distance]"] = lookup[0]->getLabel();
496 variables["[tag]"] = method;
497 string outputFileName = getOutputFileName("otucorr",variables);
498 outputNames.push_back(outputFileName); outputTypes["otucorr"].push_back(outputFileName);
501 m->openOutputFile(outputFileName, out);
502 out.setf(ios::fixed, ios::floatfield); out.setf(ios::showpoint);
505 if (metadatafile == "") { out << "OTUA\tOTUB\t" << method << "Coef\tSignificance\n"; }
506 else { out << "OTUA\tMetadata\t" << method << "Coef\tSignificance\n"; }
508 vector< vector<double> > xy; xy.resize(lookup[0]->getNumBins());
509 for (int i = 0; i < lookup[0]->getNumBins(); i++) { for (int j = 0; j < lookup.size(); j++) { xy[i].push_back(lookup[j]->getAbundance(i)); } }
511 LinearAlgebra linear;
512 if (metadatafile == "") {//compare otus
513 for (int i = 0; i < xy.size(); i++) {
515 for (int k = 0; k < i; k++) {
517 if (m->control_pressed) { out.close(); return 0; }
521 if (method == "spearman") { coef = linear.calcSpearman(xy[i], xy[k], sig); }
522 else if (method == "pearson") { coef = linear.calcPearson(xy[i], xy[k], sig); }
523 else if (method == "kendall") { coef = linear.calcKendall(xy[i], xy[k], sig); }
524 else { m->mothurOut("[ERROR]: invalid method, choices are spearman, pearson or kendall."); m->mothurOutEndLine(); m->control_pressed = true; }
526 if (sig < cutoff) { out << m->binLabelsInFile[i] << '\t' << m->binLabelsInFile[k] << '\t' << coef << '\t' << sig << endl; }
529 }else { //compare otus to metadata
530 for (int i = 0; i < xy.size(); i++) {
532 for (int k = 0; k < metadata.size(); k++) {
534 if (m->control_pressed) { out.close(); return 0; }
538 if (method == "spearman") { coef = linear.calcSpearman(xy[i], metadata[k], sig); }
539 else if (method == "pearson") { coef = linear.calcPearson(xy[i], metadata[k], sig); }
540 else if (method == "kendall") { coef = linear.calcKendall(xy[i], metadata[k], sig); }
541 else { m->mothurOut("[ERROR]: invalid method, choices are spearman, pearson or kendall."); m->mothurOutEndLine(); m->control_pressed = true; }
543 if (sig < cutoff) { out << m->binLabelsInFile[i] << '\t' << metadataLabels[k] << '\t' << coef << '\t' << sig << endl; }
554 catch(exception& e) {
555 m->errorOut(e, "OTUAssociationCommand", "process");
559 /*****************************************************************/
560 int OTUAssociationCommand::readMetadata(){
563 m->openInputFile(metadatafile, in);
565 string headerLine = m->getline(in); m->gobble(in);
566 istringstream iss (headerLine,istringstream::in);
568 //read the first label, because it refers to the groups
570 iss >> columnLabel; m->gobble(iss);
572 //save names of columns you are reading
574 iss >> columnLabel; m->gobble(iss);
575 if (m->debug) { m->mothurOut("[DEBUG]: metadata column Label = " + columnLabel + "\n"); }
576 metadataLabels.push_back(columnLabel);
578 int count = metadataLabels.size();
583 if (m->control_pressed) { in.close(); return 0; }
586 in >> group; m->gobble(in);
587 if (m->debug) { m->mothurOut("[DEBUG]: metadata group = " + group + "\n"); }
589 SharedRAbundFloatVector* tempLookup = new SharedRAbundFloatVector();
590 tempLookup->setGroup(group);
591 tempLookup->setLabel("1");
593 for (int i = 0; i < count; i++) {
596 if (m->debug) { m->mothurOut("[DEBUG]: metadata value = " + toString(temp) + "\n"); }
597 tempLookup->push_back(temp, group);
600 metadataLookup.push_back(tempLookup);
608 catch(exception& e) {
609 m->errorOut(e, "OTUAssociationCommand", "readMetadata");
613 /*****************************************************************/
614 //eliminate groups user did not pick, remove zeroed out otus, fill metadata vector.
615 int OTUAssociationCommand::getMetadata(){
618 vector<string> mGroups = m->getGroups();
621 for (int i = 0; i < metadataLookup.size(); i++) {
622 //if this sharedrabund is not from a group the user wants then delete it.
623 if (!(m->inUsersGroups(metadataLookup[i]->getGroup(), mGroups))) {
624 delete metadataLookup[i]; metadataLookup[i] = NULL;
625 metadataLookup.erase(metadataLookup.begin()+i);
631 vector<SharedRAbundFloatVector*> newLookup;
632 for (int i = 0; i < metadataLookup.size(); i++) {
633 SharedRAbundFloatVector* temp = new SharedRAbundFloatVector();
634 temp->setLabel(metadataLookup[i]->getLabel());
635 temp->setGroup(metadataLookup[i]->getGroup());
636 newLookup.push_back(temp);
640 vector<string> newBinLabels;
641 for (int i = 0; i < metadataLookup[0]->getNumBins(); i++) {
642 if (m->control_pressed) { for (int j = 0; j < newLookup.size(); j++) { delete newLookup[j]; } return 0; }
644 //look at each sharedRabund and make sure they are not all zero
646 for (int j = 0; j < metadataLookup.size(); j++) {
647 if (metadataLookup[j]->getAbundance(i) != 0) { allZero = false; break; }
650 //if they are not all zero add this bin
652 for (int j = 0; j < metadataLookup.size(); j++) {
653 newLookup[j]->push_back(metadataLookup[j]->getAbundance(i), metadataLookup[j]->getGroup());
655 newBinLabels.push_back(metadataLabels[i]);
659 metadataLabels = newBinLabels;
661 for (int j = 0; j < metadataLookup.size(); j++) { delete metadataLookup[j]; }
662 metadataLookup.clear();
664 metadata.resize(newLookup[0]->getNumBins());
665 for (int i = 0; i < newLookup[0]->getNumBins(); i++) { for (int j = 0; j < newLookup.size(); j++) { metadata[i].push_back(newLookup[j]->getAbundance(i)); } }
667 for (int j = 0; j < newLookup.size(); j++) { delete newLookup[j]; }
671 catch(exception& e) {
672 m->errorOut(e, "OTUAssociationCommand", "getMetadata");
676 /*****************************************************************/