2 // newcommandtemplate.cpp
5 // Created by Sarah Westcott on 5/3/12.
6 // Copyright (c) 2012 Schloss Lab. All rights reserved.
10 #include "newcommandtemplate.h"
13 //**********************************************************************************************************************
14 vector<string> NewCommand::setParameters(){
16 //eaxamples of each type of parameter. more info on the types of parameters can be found in commandparameter.h
17 CommandParameter pprocessors("processors", "Number", "", "1", "", "", "","",false,false); parameters.push_back(pprocessors);
19 //files that have dependancies
20 CommandParameter pphylip("phylip", "InputTypes", "", "", "PhylipColumn", "PhylipColumn", "none","outputType",false,false); parameters.push_back(pphylip);
21 CommandParameter pname("name", "InputTypes", "", "", "none", "none", "ColumnName","outputType",false,false); parameters.push_back(pname);
22 CommandParameter pcolumn("column", "InputTypes", "", "", "PhylipColumn", "PhylipColumn", "ColumnName","outputType",false,false); parameters.push_back(pcolumn);
23 //files that do not have dependancies - fasta is set to not be required whereas shared is set to be required
24 CommandParameter pfasta("fasta", "InputTypes", "", "", "none", "none", "none","outputType",false,false); parameters.push_back(pfasta);
25 CommandParameter pshared("shared", "InputTypes", "", "", "none", "none", "none","outputType",false,true); parameters.push_back(pshared);
28 CommandParameter pgroups("groups", "String", "", "", "", "", "","",false,false); parameters.push_back(pgroups);
29 CommandParameter plabel("label", "String", "", "", "", "", "","",false,false); parameters.push_back(plabel);
31 //choose more than one multiple options
32 CommandParameter pcalc("calc", "Multiple", "jabund-sorabund-jclass-sorclass-jest-sorest-thetayc-thetan-morisitahorn-braycurtis", "jest-thetayc", "", "", "","",true,false); parameters.push_back(pcalc);
33 //choose only one multiple options
34 CommandParameter pdistance("distance", "Multiple", "column-lt-square", "column", "", "", "","",false,false); parameters.push_back(pdistance);
36 CommandParameter ptiming("timing", "Boolean", "", "F", "", "", "","",false,false); parameters.push_back(ptiming);
38 //every command must have inputdir and outputdir. This allows mothur users to redirect input and output files.
39 CommandParameter pinputdir("inputdir", "String", "", "", "", "", "","",false,false); parameters.push_back(pinputdir);
40 CommandParameter poutputdir("outputdir", "String", "", "", "", "", "","",false,false); parameters.push_back(poutputdir);
42 vector<string> myArray;
43 for (int i = 0; i < parameters.size(); i++) { myArray.push_back(parameters[i].name); }
47 m->errorOut(e, "NewCommand", "setParameters");
51 //**********************************************************************************************************************
52 string NewCommand::getHelpString(){
54 string helpString = "";
55 helpString += "The new command allows you to ....\n";
56 helpString += "The new command parameters are: ....\n";
57 helpString += "The whatever parameter is used to ....\n";
58 helpString += "The new command should be in the following format: \n";
59 helpString += "new(...)\n";
63 m->errorOut(e, "NewCommand", "getHelpString");
67 //**********************************************************************************************************************
68 string NewCommand::getOutputPattern(string type) {
72 if (type == "fileType1") { pattern = "[filename],tag1"; }
73 else if (type == "fileType2") { pattern = "[filename],tag2"; }
74 else if (type == "fileType3") { pattern = "[filename],tag3"; }
75 else { m->mothurOut("[ERROR]: No definition for type " + type + " output pattern.\n"); m->control_pressed = true; }
80 m->errorOut(e, "NewCommand", "getOutputPattern");
84 //**********************************************************************************************************************
85 NewCommand::NewCommand(){
87 abort = true; calledHelp = true;
89 vector<string> tempOutNames;
90 outputTypes["fileType1"] = tempOutNames; //filetypes should be things like: shared, fasta, accnos...
91 outputTypes["fileType2"] = tempOutNames;
92 outputTypes["FileType3"] = tempOutNames;
95 m->errorOut(e, "NewCommand", "NewCommand");
99 //**********************************************************************************************************************
100 NewCommand::NewCommand(string option) {
102 ////////////////////////////////////////////////////////
103 /////////////////// start leave alone block ////////////
104 ////////////////////////////////////////////////////////
105 abort = false; calledHelp = false;
107 //allow user to run help
108 if(option == "help") { help(); abort = true; calledHelp = true; }
109 else if(option == "citation") { citation(); abort = true; calledHelp = true;}
112 //valid paramters for this command
113 vector<string> myArray = setParameters();
115 OptionParser parser(option);
116 map<string,string> parameters = parser.getParameters();
118 ValidParameters validParameter;
119 map<string,string>::iterator it;
120 //check to make sure all parameters are valid for command
121 for (it = parameters.begin(); it != parameters.end(); it++) {
122 if (validParameter.isValidParameter(it->first, myArray, it->second) != true) { abort = true; }
126 //if the user changes the input directory command factory will send this info to us in the output parameter
127 string inputDir = validParameter.validFile(parameters, "inputdir", false);
128 if (inputDir == "not found"){ inputDir = ""; }
131 ///////////////////////////////////////////////////////////////
132 //////////////// stop leave alone block ///////////////////////
133 ///////////////////////////////////////////////////////////////
135 //edit file types below to include only the types you added as parameters
138 it = parameters.find("phylip");
139 //user has given a template file
140 if(it != parameters.end()){
141 path = m->hasPath(it->second);
142 //if the user has not given a path then, add inputdir. else leave path alone.
143 if (path == "") { parameters["phylip"] = inputDir + it->second; }
146 it = parameters.find("column");
147 //user has given a template file
148 if(it != parameters.end()){
149 path = m->hasPath(it->second);
150 //if the user has not given a path then, add inputdir. else leave path alone.
151 if (path == "") { parameters["column"] = inputDir + it->second; }
154 it = parameters.find("fasta");
155 //user has given a template file
156 if(it != parameters.end()){
157 path = m->hasPath(it->second);
158 //if the user has not given a path then, add inputdir. else leave path alone.
159 if (path == "") { parameters["fasta"] = inputDir + it->second; }
162 it = parameters.find("name");
163 //user has given a template file
164 if(it != parameters.end()){
165 path = m->hasPath(it->second);
166 //if the user has not given a path then, add inputdir. else leave path alone.
167 if (path == "") { parameters["name"] = inputDir + it->second; }
170 it = parameters.find("shared");
171 //user has given a template file
172 if(it != parameters.end()){
173 path = m->hasPath(it->second);
174 //if the user has not given a path then, add inputdir. else leave path alone.
175 if (path == "") { parameters["shared"] = inputDir + it->second; }
178 ///////////////////////////////////////////////////////////////////////////////
179 /////////// example of getting filenames and checking dependancies ////////////
180 // the validParameter class will make sure file exists, fill with correct //
181 // and name is current is given ///////////////////////////////////////////////
182 ///////////////////////////////////////////////////////////////////////////////
185 ///variables for examples below that you will most likely want to put in the header for
186 //use by the other class functions.
187 string phylipfile, columnfile, namefile, fastafile, sharedfile, method, countfile;
189 bool useTiming, allLines;
190 vector<string> Estimators, Groups;
192 //if allLines is used it should be initialized to 1 above.
195 //check for parameters
196 phylipfile = validParameter.validFile(parameters, "phylip", true);
197 if (phylipfile == "not open") { phylipfile = ""; abort = true; }
198 else if (phylipfile == "not found") { phylipfile = ""; }
199 else { m->setPhylipFile(phylipfile); }
201 columnfile = validParameter.validFile(parameters, "column", true);
202 if (columnfile == "not open") { columnfile = ""; abort = true; }
203 else if (columnfile == "not found") { columnfile = ""; }
204 else { m->setColumnFile(columnfile); }
206 namefile = validParameter.validFile(parameters, "name", true);
207 if (namefile == "not open") { abort = true; }
208 else if (namefile == "not found") { namefile = ""; }
209 else { m->setNameFile(namefile); }
211 //get fastafile - it is not required
212 fastafile = validParameter.validFile(parameters, "fasta", true);
213 if (fastafile == "not open") { fastafile = ""; abort=true; }
214 else if (fastafile == "not found") { fastafile = ""; }
215 if (fastafile != "") { m->setFastaFile(fastafile); }
218 if ((phylipfile == "") && (columnfile == "")) {
219 //is there are current file available for either of these?
220 //give priority to column, then phylip
221 columnfile = m->getColumnFile();
222 if (columnfile != "") { m->mothurOut("Using " + columnfile + " as input file for the column parameter."); m->mothurOutEndLine(); }
224 phylipfile = m->getPhylipFile();
225 if (phylipfile != "") { m->mothurOut("Using " + phylipfile + " as input file for the phylip parameter."); m->mothurOutEndLine(); }
227 m->mothurOut("No valid current files. You must provide a phylip or column file before you can use the cluster command."); m->mothurOutEndLine();
232 else if ((phylipfile != "") && (columnfile != "")) { m->mothurOut("When executing a cluster command you must enter ONLY ONE of the following: phylip or column."); m->mothurOutEndLine(); abort = true; }
234 if (columnfile != "") {
235 if (namefile == "") {
236 namefile = m->getNameFile();
237 if (namefile != "") { m->mothurOut("Using " + namefile + " as input file for the name parameter."); m->mothurOutEndLine(); }
239 m->mothurOut("You need to provide a namefile if you are going to use the column format."); m->mothurOutEndLine();
245 //get shared file, it is required
246 sharedfile = validParameter.validFile(parameters, "shared", true);
247 if (sharedfile == "not open") { sharedfile = ""; abort = true; }
248 else if (sharedfile == "not found") {
249 //if there is a current shared file, use it
250 sharedfile = m->getSharedFile();
251 if (sharedfile != "") { m->mothurOut("Using " + sharedfile + " as input file for the shared parameter."); m->mothurOutEndLine(); }
252 else { m->mothurOut("You have no current sharedfile and the shared parameter is required."); m->mothurOutEndLine(); abort = true; }
253 }else { m->setSharedFile(sharedfile); }
255 //if the user changes the output directory command factory will send this info to us in the output parameter
256 outputDir = validParameter.validFile(parameters, "outputdir", false); if (outputDir == "not found"){
257 outputDir = m->hasPath(sharedfile); //if user entered a file with a path then preserve it
261 //////////////////////////////////////////////////////////////////////
262 ////////// example of getting other types of parameters //////////////
263 //////////////////////////////////////////////////////////////////////
265 //use only one Mutliple type
266 method = validParameter.validFile(parameters, "method", false);
267 if (method == "not found") { method = "average"; }
269 if ((method == "furthest") || (method == "nearest") || (method == "average") || (method == "weighted")) { }
270 else { m->mothurOut("Not a valid clustering method. Valid clustering algorithms are furthest, nearest, average, and weighted."); m->mothurOutEndLine(); abort = true; }
272 //use more than one multiple type. do not check to make sure the entry is valid.
273 string calc = validParameter.validFile(parameters, "calc", false);
274 if (calc == "not found") { calc = "sobs-chao-ace-jack-shannon-npshannon-simpson"; }
276 if (calc == "default") { calc = "sobs-chao-ace-jack-shannon-npshannon-simpson"; }
278 m->splitAtDash(calc, Estimators);
280 //Boolean type - m->isTrue looks for t, true, f or false and is case insensitive
281 string timing = validParameter.validFile(parameters, "timing", false);
282 if (timing == "not found") { timing = "F"; }
283 useTiming = m->isTrue(timing);
285 //Number type - mothurConvert makes sure the convert can happen to avoid a crash.
286 string temp = validParameter.validFile(parameters, "processors", false); if (temp == "not found"){ temp = m->getProcessors(); }
287 m->setProcessors(temp);
288 m->mothurConvert(temp, processors);
290 //Groups must be checked later to make sure they are valid. SharedUtilities has functions of check the validity, just make to so m->setGroups() after the checks. If you are using these with a shared file no need to check the SharedRAbundVector class will call SharedUtilites for you, kinda nice, huh?
291 string groups = validParameter.validFile(parameters, "groups", false);
292 if (groups == "not found") { groups = ""; }
293 else { m->splitAtDash(groups, Groups); }
294 m->setGroups(Groups);
296 //Commonly used to process list, rabund, sabund, shared and relabund files. Look at "smart distancing" examples below in the execute function.
297 string label = validParameter.validFile(parameters, "label", false);
298 if (label == "not found") { label = ""; }
300 if(label != "all") { m->splitAtDash(label, labels); allLines = 0; }
301 else { allLines = 1; }
304 //if your command has a namefile as an option, you may want ot check to see if there is a current namefile
305 //saved by mothur that is associated with the other files you are using as inputs.
306 //You can do so by adding the files associated with the namefile to the files vector and then asking parser to check.
307 //This saves our users headaches over file mismatches because they forgot to include the namefile, :)
308 if (countfile == "") {
309 if (namefile == "") {
310 vector<string> files; files.push_back(fastafile);
311 parser.getNameFile(files);
319 catch(exception& e) {
320 m->errorOut(e, "NewCommand", "NewCommand");
324 //**********************************************************************************************************************
326 int NewCommand::execute(){
329 if (abort == true) { if (calledHelp) { return 0; } return 2; }
331 // reading and processing a shared file code example
332 // Note: As long as you set groups and labels as shown in the constructor, you can use this code without modification other than adding your function call which is passed the lookup vector.
333 // The classes used below will handle the checking of groups to make sure they are valid and returning only the groups you selected. The while loop implements mothur "smart distancing" so as long as you filled label as shown above in the constructor the code below will handle bad labels or labels not included in the sharedfile.
335 //Reads sharefile, binLabels are stored in m->currentBinLabels, lookup will be filled with groups in m->getGroups() or all groups in file if m->getGroups is empty. If groups are selected, some bins maybe eliminated if they only contained seqs from groups not included. No need to worry about the details of this, SharedRAbundVector takes care of it. Just make sure to use m->currentBinLabels if you are outputting OTU labels so that if otus are eliminated you still have the correct names.
338 InputData input(sharedfile, "sharedfile");
339 vector<SharedRAbundVector*> lookup = input.getSharedRAbundVectors();
340 string lastLabel = lookup[0]->getLabel();
342 //if the users enters label "0.06" and there is no "0.06" in their file use the next lowest label.
343 set<string> processedLabels;
344 set<string> userLabels = labels;
347 //as long as you are not at the end of the file or done wih the lines you want
348 while((lookup[0] != NULL) && ((allLines == 1) || (userLabels.size() != 0))) {
350 if (m->control_pressed) { for (int i = 0; i < lookup.size(); i++) { delete lookup[i]; } return 0; }
352 if(allLines == 1 || labels.count(lookup[0]->getLabel()) == 1){
354 m->mothurOut(lookup[0]->getLabel()); m->mothurOutEndLine();
356 ///////////////////////////////////////////////////////////////////////////////////
357 //// Call your function to process specific distance in sharedfile, ie lookup /////
358 ///////////////////////////////////////////////////////////////////////////////////
360 processedLabels.insert(lookup[0]->getLabel());
361 userLabels.erase(lookup[0]->getLabel());
364 if ((m->anyLabelsToProcess(lookup[0]->getLabel(), userLabels, "") == true) && (processedLabels.count(lastLabel) != 1)) {
365 string saveLabel = lookup[0]->getLabel();
367 for (int i = 0; i < lookup.size(); i++) { delete lookup[i]; }
368 lookup = input.getSharedRAbundVectors(lastLabel);
369 m->mothurOut(lookup[0]->getLabel()); m->mothurOutEndLine();
371 ///////////////////////////////////////////////////////////////////////////////////
372 //// Call your function to process specific distance in sharedfile, ie lookup /////
373 ///////////////////////////////////////////////////////////////////////////////////
376 processedLabels.insert(lookup[0]->getLabel());
377 userLabels.erase(lookup[0]->getLabel());
379 //restore real lastlabel to save below
380 lookup[0]->setLabel(saveLabel);
383 lastLabel = lookup[0]->getLabel();
384 //prevent memory leak
385 for (int i = 0; i < lookup.size(); i++) { delete lookup[i]; lookup[i] = NULL; }
387 if (m->control_pressed) { return 0; }
389 //get next line to process
390 lookup = input.getSharedRAbundVectors();
393 if (m->control_pressed) { return 0; }
395 //output error messages about any remaining user labels
396 set<string>::iterator it;
397 bool needToRun = false;
398 for (it = userLabels.begin(); it != userLabels.end(); it++) {
399 m->mothurOut("Your file does not include the label " + *it);
400 if (processedLabels.count(lastLabel) != 1) {
401 m->mothurOut(". I will use " + lastLabel + "."); m->mothurOutEndLine();
404 m->mothurOut(". Please refer to " + lastLabel + "."); m->mothurOutEndLine();
408 //run last label if you need to
409 if (needToRun == true) {
410 for (int i = 0; i < lookup.size(); i++) { if (lookup[i] != NULL) { delete lookup[i]; } }
411 lookup = input.getSharedRAbundVectors(lastLabel);
413 m->mothurOut(lookup[0]->getLabel()); m->mothurOutEndLine();
415 ///////////////////////////////////////////////////////////////////////////////////
416 //// Call your function to process specific distance in sharedfile, ie lookup /////
417 ///////////////////////////////////////////////////////////////////////////////////
420 for (int i = 0; i < lookup.size(); i++) { delete lookup[i]; }
426 //if you make a new file or a type that mothur keeps track of the current version, you can update it with something like the following.
427 string currentFasta = "";
428 itTypes = outputTypes.find("fasta");
429 if (itTypes != outputTypes.end()) {
430 if ((itTypes->second).size() != 0) { currentFasta = (itTypes->second)[0]; m->setFastaFile(currentFasta); }
433 //output files created by command
434 m->mothurOutEndLine();
435 m->mothurOut("Output File Names: "); m->mothurOutEndLine();
436 for (int i = 0; i < outputNames.size(); i++) { m->mothurOut(outputNames[i]); m->mothurOutEndLine(); }
437 m->mothurOutEndLine();
441 catch(exception& e) {
442 m->errorOut(e, "NewCommand", "NewCommand");
446 //**********************************************************************************************************************