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"
12 //**********************************************************************************************************************
13 vector<string> NewCommand::setParameters(){
15 //eaxamples of each type of parameter. more info on the types of parameters can be found in commandparameter.h
16 CommandParameter pprocessors("processors", "Number", "", "1", "", "", "",false,false); parameters.push_back(pprocessors);
18 //files that have dependancies
19 CommandParameter pphylip("phylip", "InputTypes", "", "", "PhylipColumn", "PhylipColumn", "none",false,false); parameters.push_back(pphylip);
20 CommandParameter pname("name", "InputTypes", "", "", "none", "none", "ColumnName",false,false); parameters.push_back(pname);
21 CommandParameter pcolumn("column", "InputTypes", "", "", "PhylipColumn", "PhylipColumn", "ColumnName",false,false); parameters.push_back(pcolumn);
22 //files that do not have dependancies - fasta is set to not be required whereas shared is set to be required
23 CommandParameter pfasta("fasta", "InputTypes", "", "", "none", "none", "none",false,false); parameters.push_back(pfasta);
24 CommandParameter pshared("shared", "InputTypes", "", "", "none", "none", "none",false,true); parameters.push_back(pshared);
27 CommandParameter pgroups("groups", "String", "", "", "", "", "",false,false); parameters.push_back(pgroups);
28 CommandParameter plabel("label", "String", "", "", "", "", "",false,false); parameters.push_back(plabel);
30 //choose more than one multiple options
31 CommandParameter pcalc("calc", "Multiple", "jabund-sorabund-jclass-sorclass-jest-sorest-thetayc-thetan-morisitahorn-braycurtis", "jest-thetayc", "", "", "",true,false); parameters.push_back(pcalc);
32 //choose only one multiple options
33 CommandParameter pdistance("distance", "Multiple", "column-lt-square", "column", "", "", "",false,false); parameters.push_back(pdistance);
35 CommandParameter ptiming("timing", "Boolean", "", "F", "", "", "",false,false); parameters.push_back(ptiming);
37 //every command must have inputdir and outputdir. This allows mothur users to redirect input and output files.
38 CommandParameter pinputdir("inputdir", "String", "", "", "", "", "",false,false); parameters.push_back(pinputdir);
39 CommandParameter poutputdir("outputdir", "String", "", "", "", "", "",false,false); parameters.push_back(poutputdir);
41 vector<string> myArray;
42 for (int i = 0; i < parameters.size(); i++) { myArray.push_back(parameters[i].name); }
46 m->errorOut(e, "NewCommand", "setParameters");
50 //**********************************************************************************************************************
51 string NewCommand::getHelpString(){
53 string helpString = "";
54 helpString += "The new command allows you to ....\n";
55 helpString += "The new command parameters are: ....\n";
56 helpString += "The whatever parameter is used to ....\n";
57 helpString += "The new command should be in the following format: \n";
58 helpString += "new(...)\n";
62 m->errorOut(e, "NewCommand", "getHelpString");
66 //**********************************************************************************************************************
67 string NewCommand::getOutputFileNameTag(string type, string inputName=""){
70 map<string, vector<string> >::iterator it;
72 //is this a type this command creates
73 it = outputTypes.find(type);
74 if (it == outputTypes.end()) { m->mothurOut("[ERROR]: this command doesn't create a " + type + " output file.\n"); }
76 if (type == "fileType1") { tag = "tag1"; }
77 else if (type == "fileType2") { tag = "tag2"; }
78 else if (type == "fileType3") { tag = "tag3"; }
79 else { m->mothurOut("[ERROR]: No definition for type " + type + " output file tag.\n"); m->control_pressed = true; }
84 m->errorOut(e, "NewCommand", "getOutputFileName");
88 //**********************************************************************************************************************
89 NewCommand::NewCommand(){
91 abort = true; calledHelp = true;
93 vector<string> tempOutNames;
94 outputTypes["fileType1"] = tempOutNames; //filetypes should be things like: shared, fasta, accnos...
95 outputTypes["fileType2"] = tempOutNames;
96 outputTypes["FileType3"] = tempOutNames;
99 m->errorOut(e, "NewCommand", "NewCommand");
103 //**********************************************************************************************************************
104 NewCommand::NewCommand(string option) {
106 ////////////////////////////////////////////////////////
107 /////////////////// start leave alone block ////////////
108 ////////////////////////////////////////////////////////
109 abort = false; calledHelp = false;
111 //allow user to run help
112 if(option == "help") { help(); abort = true; calledHelp = true; }
113 else if(option == "citation") { citation(); abort = true; calledHelp = true;}
116 //valid paramters for this command
117 vector<string> myArray = setParameters();
119 OptionParser parser(option);
120 map<string,string> parameters = parser.getParameters();
122 ValidParameters validParameter;
123 map<string,string>::iterator it;
124 //check to make sure all parameters are valid for command
125 for (it = parameters.begin(); it != parameters.end(); it++) {
126 if (validParameter.isValidParameter(it->first, myArray, it->second) != true) { abort = true; }
130 //if the user changes the input directory command factory will send this info to us in the output parameter
131 string inputDir = validParameter.validFile(parameters, "inputdir", false);
132 if (inputDir == "not found"){ inputDir = ""; }
135 ///////////////////////////////////////////////////////////////
136 //////////////// stop leave alone block ///////////////////////
137 ///////////////////////////////////////////////////////////////
139 //edit file types below to include only the types you added as parameters
142 it = parameters.find("phylip");
143 //user has given a template file
144 if(it != parameters.end()){
145 path = m->hasPath(it->second);
146 //if the user has not given a path then, add inputdir. else leave path alone.
147 if (path == "") { parameters["phylip"] = inputDir + it->second; }
150 it = parameters.find("column");
151 //user has given a template file
152 if(it != parameters.end()){
153 path = m->hasPath(it->second);
154 //if the user has not given a path then, add inputdir. else leave path alone.
155 if (path == "") { parameters["column"] = inputDir + it->second; }
158 it = parameters.find("fasta");
159 //user has given a template file
160 if(it != parameters.end()){
161 path = m->hasPath(it->second);
162 //if the user has not given a path then, add inputdir. else leave path alone.
163 if (path == "") { parameters["fasta"] = inputDir + it->second; }
166 it = parameters.find("name");
167 //user has given a template file
168 if(it != parameters.end()){
169 path = m->hasPath(it->second);
170 //if the user has not given a path then, add inputdir. else leave path alone.
171 if (path == "") { parameters["name"] = inputDir + it->second; }
174 it = parameters.find("shared");
175 //user has given a template file
176 if(it != parameters.end()){
177 path = m->hasPath(it->second);
178 //if the user has not given a path then, add inputdir. else leave path alone.
179 if (path == "") { parameters["shared"] = inputDir + it->second; }
182 ///////////////////////////////////////////////////////////////////////////////
183 /////////// example of getting filenames and checking dependancies ////////////
184 // the validParameter class will make sure file exists, fill with correct //
185 // and name is current is given ///////////////////////////////////////////////
186 ///////////////////////////////////////////////////////////////////////////////
189 ///variables for examples below that you will most likely want to put in the header for
190 //use by the other class functions.
191 string phylipfile, columnfile, namefile, fastafile, sharedfile, method;
193 bool useTiming, allLines;
194 vector<string> Estimators, Groups;
196 //if allLines is used it should be initialized to 1 above.
199 //check for parameters
200 phylipfile = validParameter.validFile(parameters, "phylip", true);
201 if (phylipfile == "not open") { phylipfile = ""; abort = true; }
202 else if (phylipfile == "not found") { phylipfile = ""; }
203 else { m->setPhylipFile(phylipfile); }
205 columnfile = validParameter.validFile(parameters, "column", true);
206 if (columnfile == "not open") { columnfile = ""; abort = true; }
207 else if (columnfile == "not found") { columnfile = ""; }
208 else { m->setColumnFile(columnfile); }
210 namefile = validParameter.validFile(parameters, "name", true);
211 if (namefile == "not open") { abort = true; }
212 else if (namefile == "not found") { namefile = ""; }
213 else { m->setNameFile(namefile); }
215 //get fastafile - it is not required
216 fastafile = validParameter.validFile(parameters, "fasta", true);
217 if (fastafile == "not open") { fastafile = ""; abort=true; }
218 else if (fastafile == "not found") { fastafile = ""; }
219 if (fastafile != "") { m->setFastaFile(fastafile); }
222 if ((phylipfile == "") && (columnfile == "")) {
223 //is there are current file available for either of these?
224 //give priority to column, then phylip
225 columnfile = m->getColumnFile();
226 if (columnfile != "") { m->mothurOut("Using " + columnfile + " as input file for the column parameter."); m->mothurOutEndLine(); }
228 phylipfile = m->getPhylipFile();
229 if (phylipfile != "") { m->mothurOut("Using " + phylipfile + " as input file for the phylip parameter."); m->mothurOutEndLine(); }
231 m->mothurOut("No valid current files. You must provide a phylip or column file before you can use the cluster command."); m->mothurOutEndLine();
236 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; }
238 if (columnfile != "") {
239 if (namefile == "") {
240 namefile = m->getNameFile();
241 if (namefile != "") { m->mothurOut("Using " + namefile + " as input file for the name parameter."); m->mothurOutEndLine(); }
243 m->mothurOut("You need to provide a namefile if you are going to use the column format."); m->mothurOutEndLine();
249 //get shared file, it is required
250 sharedfile = validParameter.validFile(parameters, "shared", true);
251 if (sharedfile == "not open") { sharedfile = ""; abort = true; }
252 else if (sharedfile == "not found") {
253 //if there is a current shared file, use it
254 sharedfile = m->getSharedFile();
255 if (sharedfile != "") { m->mothurOut("Using " + sharedfile + " as input file for the shared parameter."); m->mothurOutEndLine(); }
256 else { m->mothurOut("You have no current sharedfile and the shared parameter is required."); m->mothurOutEndLine(); abort = true; }
257 }else { m->setSharedFile(sharedfile); }
259 //if the user changes the output directory command factory will send this info to us in the output parameter
260 outputDir = validParameter.validFile(parameters, "outputdir", false); if (outputDir == "not found"){
261 outputDir = m->hasPath(sharedfile); //if user entered a file with a path then preserve it
265 //////////////////////////////////////////////////////////////////////
266 ////////// example of getting other types of parameters //////////////
267 //////////////////////////////////////////////////////////////////////
269 //use only one Mutliple type
270 method = validParameter.validFile(parameters, "method", false);
271 if (method == "not found") { method = "average"; }
273 if ((method == "furthest") || (method == "nearest") || (method == "average") || (method == "weighted")) { }
274 else { m->mothurOut("Not a valid clustering method. Valid clustering algorithms are furthest, nearest, average, and weighted."); m->mothurOutEndLine(); abort = true; }
276 //use more than one multiple type. do not check to make sure the entry is valid.
277 string calc = validParameter.validFile(parameters, "calc", false);
278 if (calc == "not found") { calc = "sobs-chao-ace-jack-shannon-npshannon-simpson"; }
280 if (calc == "default") { calc = "sobs-chao-ace-jack-shannon-npshannon-simpson"; }
282 m->splitAtDash(calc, Estimators);
284 //Boolean type - m->isTrue looks for t, true, f or false and is case insensitive
285 string timing = validParameter.validFile(parameters, "timing", false);
286 if (timing == "not found") { timing = "F"; }
287 useTiming = m->isTrue(timing);
289 //Number type - mothurConvert makes sure the convert can happen to avoid a crash.
290 string temp = validParameter.validFile(parameters, "processors", false); if (temp == "not found"){ temp = m->getProcessors(); }
291 m->setProcessors(temp);
292 m->mothurConvert(temp, processors);
294 //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?
295 string groups = validParameter.validFile(parameters, "groups", false);
296 if (groups == "not found") { groups = ""; }
297 else { m->splitAtDash(groups, Groups); }
298 m->setGroups(Groups);
300 //Commonly used to process list, rabund, sabund, shared and relabund files. Look at "smart distancing" examples below in the execute function.
301 string label = validParameter.validFile(parameters, "label", false);
302 if (label == "not found") { label = ""; }
304 if(label != "all") { m->splitAtDash(label, labels); allLines = 0; }
305 else { allLines = 1; }
308 //if your command has a namefile as an option, you may want ot check to see if there is a current namefile
309 //saved by mothur that is associated with the other files you are using as inputs.
310 //You can do so by adding the files associated with the namefile to the files vector and then asking parser to check.
311 //This saves our users headaches over file mismatches because they forgot to include the namefile, :)
312 if (namefile == "") {
313 vector<string> files; files.push_back(fastafile);
314 parser.getNameFile(files);
320 catch(exception& e) {
321 m->errorOut(e, "NewCommand", "NewCommand");
325 //**********************************************************************************************************************
327 int NewCommand::execute(){
330 if (abort == true) { if (calledHelp) { return 0; } return 2; }
332 // reading and processing a shared file code example
333 // 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.
334 // 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.
336 //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.
339 InputData input(sharedfile, "sharedfile");
340 vector<SharedRAbundVector*> lookup = input.getSharedRAbundVectors();
341 string lastLabel = lookup[0]->getLabel();
343 //if the users enters label "0.06" and there is no "0.06" in their file use the next lowest label.
344 set<string> processedLabels;
345 set<string> userLabels = labels;
348 //as long as you are not at the end of the file or done wih the lines you want
349 while((lookup[0] != NULL) && ((allLines == 1) || (userLabels.size() != 0))) {
351 if (m->control_pressed) { for (int i = 0; i < lookup.size(); i++) { delete lookup[i]; } return 0; }
353 if(allLines == 1 || labels.count(lookup[0]->getLabel()) == 1){
355 m->mothurOut(lookup[0]->getLabel()); m->mothurOutEndLine();
357 ///////////////////////////////////////////////////////////////////////////////////
358 //// Call your function to process specific distance in sharedfile, ie lookup /////
359 ///////////////////////////////////////////////////////////////////////////////////
361 processedLabels.insert(lookup[0]->getLabel());
362 userLabels.erase(lookup[0]->getLabel());
365 if ((m->anyLabelsToProcess(lookup[0]->getLabel(), userLabels, "") == true) && (processedLabels.count(lastLabel) != 1)) {
366 string saveLabel = lookup[0]->getLabel();
368 for (int i = 0; i < lookup.size(); i++) { delete lookup[i]; }
369 lookup = input.getSharedRAbundVectors(lastLabel);
370 m->mothurOut(lookup[0]->getLabel()); m->mothurOutEndLine();
372 ///////////////////////////////////////////////////////////////////////////////////
373 //// Call your function to process specific distance in sharedfile, ie lookup /////
374 ///////////////////////////////////////////////////////////////////////////////////
377 processedLabels.insert(lookup[0]->getLabel());
378 userLabels.erase(lookup[0]->getLabel());
380 //restore real lastlabel to save below
381 lookup[0]->setLabel(saveLabel);
384 lastLabel = lookup[0]->getLabel();
385 //prevent memory leak
386 for (int i = 0; i < lookup.size(); i++) { delete lookup[i]; lookup[i] = NULL; }
388 if (m->control_pressed) { return 0; }
390 //get next line to process
391 lookup = input.getSharedRAbundVectors();
394 if (m->control_pressed) { return 0; }
396 //output error messages about any remaining user labels
397 set<string>::iterator it;
398 bool needToRun = false;
399 for (it = userLabels.begin(); it != userLabels.end(); it++) {
400 m->mothurOut("Your file does not include the label " + *it);
401 if (processedLabels.count(lastLabel) != 1) {
402 m->mothurOut(". I will use " + lastLabel + "."); m->mothurOutEndLine();
405 m->mothurOut(". Please refer to " + lastLabel + "."); m->mothurOutEndLine();
409 //run last label if you need to
410 if (needToRun == true) {
411 for (int i = 0; i < lookup.size(); i++) { if (lookup[i] != NULL) { delete lookup[i]; } }
412 lookup = input.getSharedRAbundVectors(lastLabel);
414 m->mothurOut(lookup[0]->getLabel()); m->mothurOutEndLine();
416 ///////////////////////////////////////////////////////////////////////////////////
417 //// Call your function to process specific distance in sharedfile, ie lookup /////
418 ///////////////////////////////////////////////////////////////////////////////////
421 for (int i = 0; i < lookup.size(); i++) { delete lookup[i]; }
427 //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.
428 string currentFasta = "";
429 itTypes = outputTypes.find("fasta");
430 if (itTypes != outputTypes.end()) {
431 if ((itTypes->second).size() != 0) { currentFasta = (itTypes->second)[0]; m->setFastaFile(currentFasta); }
434 //output files created by command
435 m->mothurOutEndLine();
436 m->mothurOut("Output File Names: "); m->mothurOutEndLine();
437 for (int i = 0; i < outputNames.size(); i++) { m->mothurOut(outputNames[i]); m->mothurOutEndLine(); }
438 m->mothurOutEndLine();
442 catch(exception& e) {
443 m->errorOut(e, "NewCommand", "NewCommand");
447 //**********************************************************************************************************************