5 * Created by westcott on 5/11/10.
6 * Copyright 2010 Schloss Lab. All rights reserved.
10 #include "catchallcommand.h"
12 //**********************************************************************************************************************
13 vector<string> CatchAllCommand::setParameters(){
15 CommandParameter plabel("label", "String", "", "", "", "", "",false,false); parameters.push_back(plabel);
16 //can choose shared or sabund not both, so put them in the same chooseOnlyOneGroup
17 CommandParameter pshared("shared", "InputTypes", "", "", "catchallInputs", "catchallInputs", "none",false,false); parameters.push_back(pshared);
18 CommandParameter psabund("sabund", "InputTypes", "", "", "catchallInputs", "catchallInputs", "none",false,false); parameters.push_back(psabund);
19 CommandParameter pinputdir("inputdir", "String", "", "", "", "", "",false,false); parameters.push_back(pinputdir);
20 CommandParameter poutputdir("outputdir", "String", "", "", "", "", "",false,false); parameters.push_back(poutputdir);
22 vector<string> myArray;
23 for (int i = 0; i < parameters.size(); i++) { myArray.push_back(parameters[i].name); }
27 m->errorOut(e, "CatchAllCommand", "setParameters");
31 //**********************************************************************************************************************
32 string CatchAllCommand::getHelpString(){
34 string helpString = "";
35 helpString += "The catchall command interfaces mothur with the catchall program written by Linda Woodard, Sean Connolly and John Bunge.\n";
36 helpString += "For more information about catchall refer to http://www.northeastern.edu/catchall/index.html \n";
37 helpString += "The catchall executable must be in the same folder as your mothur executable. \n";
38 helpString += "If you are a MAC or Linux user you must also have installed mono, a link to mono is on the webpage. \n";
39 helpString += "The catchall command parameters are shared, sabund and label. shared or sabund is required. \n";
40 helpString += "The label parameter is used to analyze specific labels in your input.\n";
41 helpString += "The catchall command should be in the following format: \n";
42 helpString += "catchall(sabund=yourSabundFile) \n";
43 helpString += "Example: catchall(sabund=abrecovery.fn.sabund) \n";
47 m->errorOut(e, "CatchAllCommand", "getHelpString");
51 //**********************************************************************************************************************
52 CatchAllCommand::CatchAllCommand(){
54 abort = true; calledHelp = true;
56 //initialize outputTypes
57 vector<string> tempOutNames;
58 outputTypes["csv"] = tempOutNames;
59 outputTypes["summary"] = tempOutNames;
62 m->errorOut(e, "CatchAllCommand", "CatchAllCommand");
66 /**************************************************************************************/
67 CatchAllCommand::CatchAllCommand(string option) {
70 abort = false; calledHelp = false;
73 //allow user to run help
74 if(option == "help") { help(); abort = true; calledHelp = true; }
75 else if(option == "citation") { citation(); abort = true; calledHelp = true;}
78 vector<string> myArray = setParameters();
80 OptionParser parser(option);
81 map<string,string> parameters = parser.getParameters();
83 ValidParameters validParameter;
84 map<string, string>::iterator it;
86 //check to make sure all parameters are valid for command
87 for (it = parameters.begin(); it != parameters.end(); it++) {
88 if (validParameter.isValidParameter(it->first, myArray, it->second) != true) { abort = true; }
91 //initialize outputTypes
92 vector<string> tempOutNames;
93 outputTypes["csv"] = tempOutNames;
94 outputTypes["summary"] = tempOutNames;
96 //if the user changes the input directory command factory will send this info to us in the output parameter
97 string inputDir = validParameter.validFile(parameters, "inputdir", false);
98 if (inputDir == "not found"){ inputDir = ""; }
101 it = parameters.find("sabund");
102 //user has given a template file
103 if(it != parameters.end()){
104 path = m->hasPath(it->second);
105 //if the user has not given a path then, add inputdir. else leave path alone.
106 if (path == "") { parameters["sabund"] = inputDir + it->second; }
109 it = parameters.find("shared");
110 //user has given a template file
111 if(it != parameters.end()){
112 path = m->hasPath(it->second);
113 //if the user has not given a path then, add inputdir. else leave path alone.
114 if (path == "") { parameters["shared"] = inputDir + it->second; }
118 //check for required parameters
119 sabundfile = validParameter.validFile(parameters, "sabund", true);
120 if (sabundfile == "not open") { sabundfile = ""; abort = true; }
121 else if (sabundfile == "not found") { sabundfile = ""; }
122 else { m->setSabundFile(sabundfile); }
124 sharedfile = validParameter.validFile(parameters, "shared", true);
125 if (sharedfile == "not open") { sharedfile = ""; abort = true; }
126 else if (sharedfile == "not found") { sharedfile = ""; }
127 else { m->setSharedFile(sharedfile); }
129 string label = validParameter.validFile(parameters, "label", false);
130 if (label == "not found") { label = ""; }
132 if(label != "all") { m->splitAtDash(label, labels); allLines = 0; }
133 else { allLines = 1; }
136 if ((sharedfile == "") && (sabundfile == "")) {
137 //is there are current file available for either of these?
138 //give priority to shared, then sabund
139 //if there is a current shared file, use it
140 sharedfile = m->getSharedFile();
141 if (sharedfile != "") { m->mothurOut("Using " + sharedfile + " as input file for the shared parameter."); m->mothurOutEndLine(); }
143 sabundfile = m->getSabundFile();
144 if (sabundfile != "") { m->mothurOut("Using " + sabundfile + " as input file for the sabund parameter."); m->mothurOutEndLine(); }
146 m->mothurOut("No valid current files. You must provide a sabund or shared file before you can use the catchall command."); m->mothurOutEndLine();
152 //if the user changes the output directory command factory will send this info to us in the output parameter
153 outputDir = validParameter.validFile(parameters, "outputdir", false);
154 if (outputDir == "not found"){
155 if (sabundfile != "") { outputDir = m->hasPath(sabundfile); }
156 else { outputDir = m->hasPath(sharedfile); }
161 catch(exception& e) {
162 m->errorOut(e, "CatchAllCommand", "CatchAllCommand");
166 /**************************************************************************************/
167 int CatchAllCommand::execute() {
170 if (abort == true) { if (calledHelp) { return 0; } return 2; }
172 //get location of catchall
174 path = path.substr(0, (path.find_last_of("othur")-5));
175 path = m->getFullPathName(path);
177 if (m->debug) { m->mothurOut("[DEBUG]: mothur's path = " + path + "\n"); }
179 savedOutputDir = outputDir;
180 string catchAllCommandExe = "";
181 string catchAllTest = "";
182 #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix)
183 catchAllCommandExe += "mono " + path + "CatchAllcmdL.exe ";
184 if (outputDir == "") { outputDir = "./"; } //force full pathname to be created for catchall, this is necessary because if catchall is in the path it will look for input file whereever the exe is and not the cwd.
185 catchAllTest = path + "CatchAllcmdL.exe";
187 catchAllCommandExe += "\"" + path + "CatchAllcmdW.exe\"" + " ";
188 if (outputDir == "") { outputDir = ".\\"; } //force full pathname to be created for catchall, this is necessary because if catchall is in the path it will look for input file whereever the exe is and not the cwd.
189 catchAllTest = path + "CatchAllcmdW.exe";
192 //test to make sure formatdb exists
194 catchAllTest = m->getFullPathName(catchAllTest);
195 int ableToOpen = m->openInputFile(catchAllTest, in, "no error"); in.close();
196 if(ableToOpen == 1) { m->mothurOut("[ERROR]: " + catchAllTest + " file does not exist. mothur requires the catchall executable to run the catchall command."); m->mothurOutEndLine(); m->control_pressed = true; return 0; }
198 //prepare full output directory
199 outputDir = m->getFullPathName(outputDir);
201 if (m->debug) { m->mothurOut("[DEBUG]: catchall location = " + catchAllCommandExe + ".\n [DEBUG]: outputDir = " + outputDir + ".\n"); }
203 vector<string> inputFileNames;
204 if (sharedfile != "") { inputFileNames = parseSharedFile(sharedfile); }
205 else { inputFileNames.push_back(sabundfile); }
207 for (int p = 0; p < inputFileNames.size(); p++) {
208 if (inputFileNames.size() > 1) {
209 m->mothurOutEndLine(); m->mothurOut("Processing group " + groups[p]); m->mothurOutEndLine(); m->mothurOutEndLine();
212 InputData input(inputFileNames[p], "sabund");
213 SAbundVector* sabund = input.getSAbundVector();
214 string lastLabel = sabund->getLabel();
216 set<string> processedLabels;
217 set<string> userLabels = labels;
219 string summaryfilename = outputDir + m->getRootName(m->getSimpleName(inputFileNames[p])) + "catchall.summary";
220 summaryfilename = m->getFullPathName(summaryfilename);
222 if (m->debug) { m->mothurOut("[DEBUG]: Input File = " + inputFileNames[p] + ".\n [DEBUG]: inputdata address = " + toString(&input) + ".\n [DEBUG]: sabund address = " + toString(&sabund) + ".\n"); }
225 m->openOutputFile(summaryfilename, out);
227 out << "label\tmodel\testimate\tlci\tuci" << endl;
229 if (m->debug) { string open = "no"; if (out.is_open()) { open = "yes"; } m->mothurOut("[DEBUG]: output stream is open = " + open + ".\n"); }
231 //for each label the user selected
232 while((sabund != NULL) && ((allLines == 1) || (userLabels.size() != 0))) {
235 if(allLines == 1 || labels.count(sabund->getLabel()) == 1){
236 m->mothurOut(sabund->getLabel()); m->mothurOutEndLine();
238 //create catchall input file from mothur's inputfile
239 string filename = process(sabund, inputFileNames[p]);
240 string outputPath = m->getPathName(filename);
242 //create system command
243 string catchAllCommand = "";
244 #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix)
245 catchAllCommand += catchAllCommandExe + filename + " " + outputPath + " 1";
247 if (outputPath.length() > 0) { outputPath = outputPath.substr(0, outputPath.length()-1); }
248 catchAllCommand += catchAllCommandExe + "\"" + filename + "\" \"" + outputPath + "\" 1";
249 //wrap entire string in ""
250 catchAllCommand = "\"" + catchAllCommand + "\"";
253 if (m->debug) { m->mothurOut("[DEBUG]: catchall command = " + catchAllCommand + ". About to call system.\n"); }
256 system(catchAllCommand.c_str());
258 if (m->debug) { m->mothurOut("[DEBUG]: back from system call. Keeping file: " + filename + ".\n"); }
260 if (!m->debug) { m->mothurRemove(filename); }
263 filename = m->getRootName(filename); filename = filename.substr(0, filename.length()-1); //rip off extra .
264 if (savedOutputDir == "") { filename = m->getSimpleName(filename); }
266 outputNames.push_back(filename + "_Analysis.csv"); outputTypes["csv"].push_back(filename + "_Analysis.csv");
267 outputNames.push_back(filename + "_BestModelsAnalysis.csv"); outputTypes["csv"].push_back(filename + "_BestModelsAnalysis.csv");
268 outputNames.push_back(filename + "_BestModelsFits.csv"); outputTypes["csv"].push_back(filename + "_BestModelsFits.csv");
269 outputNames.push_back(filename + "_BubblePlot.csv"); outputTypes["csv"].push_back(filename + "_BubblePlot.csv");
271 if (m->debug) { m->mothurOut("[DEBUG]: About to create summary file for: " + filename + ".\n[DEBUG]: sabund label = " + sabund->getLabel() + ".\n"); }
273 createSummaryFile(filename + "_BestModelsAnalysis.csv", sabund->getLabel(), out);
275 if (m->debug) { m->mothurOut("[DEBUG]: Done creating summary file.\n"); }
277 if (m->control_pressed) { out.close(); for (int i = 0; i < outputNames.size(); i++) {m->mothurRemove(outputNames[i]); } delete sabund; return 0; }
279 processedLabels.insert(sabund->getLabel());
280 userLabels.erase(sabund->getLabel());
283 if ((m->anyLabelsToProcess(sabund->getLabel(), userLabels, "") == true) && (processedLabels.count(lastLabel) != 1)) {
284 string saveLabel = sabund->getLabel();
287 sabund = (input.getSAbundVector(lastLabel));
289 m->mothurOut(sabund->getLabel()); m->mothurOutEndLine();
292 //create catchall input file from mothur's inputfile
293 string filename = process(sabund, inputFileNames[p]);
294 string outputPath = m->getPathName(filename);
296 //create system command
297 string catchAllCommand = "";
298 #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix)
299 catchAllCommand += catchAllCommandExe + filename + " " + outputPath + " 1";
301 if (outputPath.length() > 0) { outputPath = outputPath.substr(0, outputPath.length()-1); }
302 catchAllCommand += catchAllCommandExe + "\"" + filename + "\" \"" + outputPath + "\" 1";
303 catchAllCommand = "\"" + catchAllCommand + "\"";
306 if (m->debug) { m->mothurOut("[DEBUG]: catchall command = " + catchAllCommand + ". About to call system.\n"); }
309 system(catchAllCommand.c_str());
311 if (m->debug) { m->mothurOut("[DEBUG]: back from system call. Keeping file: " + filename + ".\n"); }
313 if (!m->debug) { m->mothurRemove(filename); }
316 filename = m->getRootName(filename); filename = filename.substr(0, filename.length()-1); //rip off extra .
317 if (savedOutputDir == "") { filename = m->getSimpleName(filename); }
319 outputNames.push_back(filename + "_Analysis.csv"); outputTypes["csv"].push_back(filename + "_Analysis.csv");
320 outputNames.push_back(filename + "_BestModelsAnalysis.csv"); outputTypes["csv"].push_back(filename + "_BestModelsAnalysis.csv");
321 outputNames.push_back(filename + "_BestModelsFits.csv"); outputTypes["csv"].push_back(filename + "_BestModelsFits.csv");
322 outputNames.push_back(filename + "_BubblePlot.csv"); outputTypes["csv"].push_back(filename + "_BubblePlot.csv");
325 if (m->debug) { m->mothurOut("[DEBUG]: About to create summary file for: " + filename + ".\n[DEBUG]: sabund label = " + sabund->getLabel() + ".\n"); }
327 createSummaryFile(filename + "_BestModelsAnalysis.csv", sabund->getLabel(), out);
329 if (m->debug) { m->mothurOut("[DEBUG]: Done creating summary file.\n"); }
331 if (m->control_pressed) { out.close(); for (int i = 0; i < outputNames.size(); i++) {m->mothurRemove(outputNames[i]); } delete sabund; return 0; }
333 processedLabels.insert(sabund->getLabel());
334 userLabels.erase(sabund->getLabel());
336 //restore real lastlabel to save below
337 sabund->setLabel(saveLabel);
341 lastLabel = sabund->getLabel();
344 sabund = (input.getSAbundVector());
347 //output error messages about any remaining user labels
348 set<string>::iterator it;
349 bool needToRun = false;
350 for (it = userLabels.begin(); it != userLabels.end(); it++) {
351 m->mothurOut("Your file does not include the label " + *it);
352 if (processedLabels.count(lastLabel) != 1) {
353 m->mothurOut(". I will use " + lastLabel + "."); m->mothurOutEndLine();
356 m->mothurOut(". Please refer to " + lastLabel + "."); m->mothurOutEndLine();
360 //run last label if you need to
361 if (needToRun == true) {
362 if (sabund != NULL) { delete sabund; }
363 sabund = (input.getSAbundVector(lastLabel));
365 m->mothurOut(sabund->getLabel()); m->mothurOutEndLine();
367 //create catchall input file from mothur's inputfile
368 string filename = process(sabund, inputFileNames[p]);
369 string outputPath = m->getPathName(filename);
371 //create system command
372 string catchAllCommand = "";
373 #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix)
374 catchAllCommand += catchAllCommandExe + filename + " " + outputPath + " 1";
376 if (outputPath.length() > 0) { outputPath = outputPath.substr(0, outputPath.length()-1); }
377 catchAllCommand += catchAllCommandExe + "\"" + filename + "\" \"" + outputPath + "\" 1";
378 catchAllCommand = "\"" + catchAllCommand + "\"";
381 if (m->debug) { m->mothurOut("[DEBUG]: catchall command = " + catchAllCommand + ". About to call system.\n"); }
384 system(catchAllCommand.c_str());
386 if (m->debug) { m->mothurOut("[DEBUG]: back from system call. Keeping file: " + filename + ".\n"); }
388 if (!m->debug) { m->mothurRemove(filename); }
390 filename = m->getRootName(filename); filename = filename.substr(0, filename.length()-1); //rip off extra .
391 if (savedOutputDir == "") { filename = m->getSimpleName(filename); }
393 outputNames.push_back(filename + "_Analysis.csv"); outputTypes["csv"].push_back(filename + "_Analysis.csv");
394 outputNames.push_back(filename + "_BestModelsAnalysis.csv"); outputTypes["csv"].push_back(filename + "_BestModelsAnalysis.csv");
395 outputNames.push_back(filename + "_BestModelsFits.csv"); outputTypes["csv"].push_back(filename + "_BestModelsFits.csv");
396 outputNames.push_back(filename + "_BubblePlot.csv"); outputTypes["csv"].push_back(filename + "_BubblePlot.csv");
397 if (m->debug) { m->mothurOut("[DEBUG]: About to create summary file for: " + filename + ".\n[DEBUG]: sabund label = " + sabund->getLabel() + ".\n"); }
399 createSummaryFile(filename + "_BestModelsAnalysis.csv", sabund->getLabel(), out);
401 if (m->debug) { m->mothurOut("[DEBUG]: Done creating summary file.\n"); }
408 if (m->control_pressed) { for (int i = 0; i < outputNames.size(); i++) {m->mothurRemove(outputNames[i]); } return 0; }
412 if (sharedfile == "") {
413 string summaryfilename = savedOutputDir + m->getRootName(m->getSimpleName(inputFileNames[0])) + "catchall.summary";
414 summaryfilename = m->getFullPathName(summaryfilename);
415 outputNames.push_back(summaryfilename); outputTypes["summary"].push_back(summaryfilename);
416 }else { //combine summaries
417 vector<string> sumNames;
418 for (int i = 0; i < inputFileNames.size(); i++) {
419 sumNames.push_back(m->getFullPathName(outputDir + m->getRootName(m->getSimpleName(inputFileNames[i])) + "catchall.summary"));
421 string summaryfilename = combineSummmary(sumNames);
422 outputNames.push_back(summaryfilename); outputTypes["summary"].push_back(summaryfilename);
425 m->mothurOutEndLine();
426 m->mothurOut("Output File Names: "); m->mothurOutEndLine();
427 for (int i = 0; i < outputNames.size(); i++) { m->mothurOut(outputNames[i]); m->mothurOutEndLine(); }
428 m->mothurOutEndLine();
433 catch(exception& e) {
434 m->errorOut(e, "CatchAllCommand", "execute");
438 //**********************************************************************************************************************
439 string CatchAllCommand::process(SAbundVector* sabund, string file1) {
441 string filename = outputDir + m->getRootName(m->getSimpleName(file1)) + sabund->getLabel() + ".csv";
442 filename = m->getFullPathName(filename);
445 m->openOutputFile(filename, out);
447 if (m->debug) { m->mothurOut("[DEBUG]: Creating " + filename + " file for catchall, shown below.\n\n"); }
449 for (int i = 1; i <= sabund->getMaxRank(); i++) {
450 int temp = sabund->get(i);
453 out << i << "," << temp << endl;
454 if (m->debug) { m->mothurOut(toString(i) + "," + toString(temp) + "\n"); }
459 if (m->debug) { m->mothurOut("[DEBUG]: Done creating " + filename + " file for catchall, shown above.\n\n"); }
464 catch(exception& e) {
465 m->errorOut(e, "CatchAllCommand", "process");
469 //*********************************************************************************************************************
470 string CatchAllCommand::combineSummmary(vector<string>& outputNames) {
474 string combineFileName = savedOutputDir + m->getRootName(m->getSimpleName(sharedfile)) + "catchall.summary";
477 m->openOutputFile(combineFileName, out);
479 out << "label\tgroup\tmodel\testimate\tlci\tuci" << endl;
481 //open each groups summary file
482 string newLabel = "";
484 map<string, vector<string> > files;
485 for (int i=0; i<outputNames.size(); i++) {
486 vector<string> thisFilesLines;
489 m->openInputFile(outputNames[i], temp);
491 //read through first line - labels
496 while (!temp.eof()) {
498 string thisLine = "";
501 for (int j = 0; j < 5; j++) {
505 if (j == 1) { thisLine += groups[i] + "\t" + tempLabel + "\t"; }
506 else{ thisLine += tempLabel + "\t"; }
511 thisFilesLines.push_back(thisLine);
516 files[outputNames[i]] = thisFilesLines;
518 numLines = thisFilesLines.size();
521 m->mothurRemove(outputNames[i]);
525 for (int k = 0; k < numLines; k++) {
527 //grab summary data for each group
528 for (int i=0; i<outputNames.size(); i++) {
529 out << files[outputNames[i]][k];
536 //return combine file name
537 return combineFileName;
540 catch(exception& e) {
541 m->errorOut(e, "CatchAllCommand", "combineSummmary");
545 //**********************************************************************************************************************
546 int CatchAllCommand::createSummaryFile(string file1, string label, ofstream& out) {
550 int able = m->openInputFile(file1, in, "noerror");
552 if (able == 1) { m->mothurOut("[ERROR]: the catchall program did not run properly. Please check to make sure it is located in the same folder as your mothur executable.");m->mothurOutEndLine(); m->control_pressed = true; return 0; }
556 string header = m->getline(in); m->gobble(in);
558 int pos = header.find("Total Number of Observed Species =");
559 string numString = "";
562 if (pos == string::npos) { m->mothurOut("[ERROR]: cannot parse " + file1); m->mothurOutEndLine(); }
564 //pos will be the position of the T in total, so we want to count to the position of =
575 if (pos > header.length()) { m->mothurOut("Cannot find number of OTUs in " + file1); m->mothurOutEndLine(); in.close(); return 0; }
579 string firstline = m->getline(in); m->gobble(in);
580 vector<string> values;
581 m->splitAtComma(firstline, values);
583 values.pop_back(); //last value is always a blank string since the last character in the line is always a ','
585 if (values.size() == 1) { //grab next line if firstline didn't have what you wanted
586 string secondline = m->getline(in); m->gobble(in);
588 m->splitAtComma(secondline, values);
590 values.pop_back(); //last value is always a blank string since the last character in the line is always a ','
593 if (values.size() == 1) { //still not what we wanted fill values with numOTUs
594 values.resize(8, "");
596 values[4] = numString;
597 values[6] = numString;
598 values[7] = numString;
601 if (values.size() < 8) { values.resize(8, ""); }
603 out << label << '\t' << values[1] << '\t' << values[4] << '\t' << values[6] << '\t' << values[7] << endl;
611 catch(exception& e) {
612 m->errorOut(e, "CatchAllCommand", "createSummaryFile");
616 //**********************************************************************************************************************
617 vector<string> CatchAllCommand::parseSharedFile(string filename) {
619 vector<string> filenames;
622 InputData input(filename, "sharedfile");
623 vector<SharedRAbundVector*> lookup = input.getSharedRAbundVectors();
625 string sharedFileRoot = outputDir + m->getRootName(m->getSimpleName(filename));
627 //clears file before we start to write to it below
628 for (int i=0; i<lookup.size(); i++) {
629 m->mothurRemove((sharedFileRoot + lookup[i]->getGroup() + ".sabund"));
630 filenames.push_back((sharedFileRoot + lookup[i]->getGroup() + ".sabund"));
631 groups.push_back(lookup[i]->getGroup());
634 while(lookup[0] != NULL) {
636 for (int i = 0; i < lookup.size(); i++) {
637 SAbundVector sav = lookup[i]->getSAbundVector();
639 m->openOutputFileAppend(sharedFileRoot + lookup[i]->getGroup() + ".sabund", out);
644 for (int i = 0; i < lookup.size(); i++) { delete lookup[i]; }
645 lookup = input.getSharedRAbundVectors();
650 catch(exception& e) {
651 m->errorOut(e, "CatchAllCommand", "parseSharedFile");
655 /**************************************************************************************/