]> git.donarmstrong.com Git - mothur.git/blob - newcommandtemplate.cpp
added debug flag to mothurOut. added debug parameter to set.dir. added debug code...
[mothur.git] / newcommandtemplate.cpp
1 //
2 //  newcommandtemplate.cpp
3 //  Mothur
4 //
5 //  Created by Sarah Westcott on 5/3/12.
6 //  Copyright (c) 2012 Schloss Lab. All rights reserved.
7 //
8
9
10 #include "newcommandtemplate.h"
11
12 //**********************************************************************************************************************
13 vector<string> NewCommand::setParameters(){     
14         try {
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);
17         
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);             
25
26         
27         CommandParameter pgroups("groups", "String", "", "", "", "", "",false,false); parameters.push_back(pgroups);
28                 CommandParameter plabel("label", "String", "", "", "", "", "",false,false); parameters.push_back(plabel);
29                 
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);
34         
35         CommandParameter ptiming("timing", "Boolean", "", "F", "", "", "",false,false); parameters.push_back(ptiming);
36         
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);
40                 
41                 vector<string> myArray;
42                 for (int i = 0; i < parameters.size(); i++) {   myArray.push_back(parameters[i].name);          }
43                 return myArray;
44         }
45         catch(exception& e) {
46                 m->errorOut(e, "NewCommand", "setParameters");
47                 exit(1);
48         }
49 }
50 //**********************************************************************************************************************
51 string NewCommand::getHelpString(){     
52         try {
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";
59                 return helpString;
60         }
61         catch(exception& e) {
62                 m->errorOut(e, "NewCommand", "getHelpString");
63                 exit(1);
64         }
65 }
66 //**********************************************************************************************************************
67 NewCommand::NewCommand(){       
68         try {
69                 abort = true; calledHelp = true;
70                 setParameters();
71         vector<string> tempOutNames;
72                 outputTypes["fileType1"] = tempOutNames; //filetypes should be things like: shared, fasta, accnos...
73                 outputTypes["fileType2"] = tempOutNames;
74                 outputTypes["FileType2"] = tempOutNames;
75         }
76         catch(exception& e) {
77                 m->errorOut(e, "NewCommand", "NewCommand");
78                 exit(1);
79         }
80 }
81 //**********************************************************************************************************************
82 NewCommand::NewCommand(string option)  {
83         try {
84 ////////////////////////////////////////////////////////
85 /////////////////// start leave alone block ////////////
86 ////////////////////////////////////////////////////////
87                 abort = false; calledHelp = false;   
88                 
89                 //allow user to run help
90                 if(option == "help") { help(); abort = true; calledHelp = true; }
91                 else if(option == "citation") { citation(); abort = true; calledHelp = true;}
92                 
93                 else {
94                         //valid paramters for this command
95                         vector<string> myArray = setParameters();
96                         
97                         OptionParser parser(option);
98                         map<string,string> parameters = parser.getParameters();
99                         
100                         ValidParameters validParameter;
101                         map<string,string>::iterator it;
102                         //check to make sure all parameters are valid for command
103                         for (it = parameters.begin(); it != parameters.end(); it++) { 
104                                 if (validParameter.isValidParameter(it->first, myArray, it->second) != true) {  abort = true;  }
105                         }
106                         
107                         
108                         //if the user changes the input directory command factory will send this info to us in the output parameter 
109                         string inputDir = validParameter.validFile(parameters, "inputdir", false);              
110                         if (inputDir == "not found"){   inputDir = "";          }
111                         else {
112                 
113 ///////////////////////////////////////////////////////////////
114 //////////////// stop leave alone block ///////////////////////
115 ///////////////////////////////////////////////////////////////
116                 
117 //edit file types below to include only the types you added as parameters
118                 
119                                 string path;
120                                 it = parameters.find("phylip");
121                                 //user has given a template file
122                                 if(it != parameters.end()){ 
123                                         path = m->hasPath(it->second);
124                                         //if the user has not given a path then, add inputdir. else leave path alone.
125                                         if (path == "") {       parameters["phylip"] = inputDir + it->second;           }
126                                 }
127                                 
128                                 it = parameters.find("column");
129                                 //user has given a template file
130                                 if(it != parameters.end()){ 
131                                         path = m->hasPath(it->second);
132                                         //if the user has not given a path then, add inputdir. else leave path alone.
133                                         if (path == "") {       parameters["column"] = inputDir + it->second;           }
134                                 }
135                                 
136                                 it = parameters.find("fasta");
137                                 //user has given a template file
138                                 if(it != parameters.end()){ 
139                                         path = m->hasPath(it->second);
140                                         //if the user has not given a path then, add inputdir. else leave path alone.
141                                         if (path == "") {       parameters["fasta"] = inputDir + it->second;            }
142                                 }
143                                                                 
144                                 it = parameters.find("name");
145                                 //user has given a template file
146                                 if(it != parameters.end()){ 
147                                         path = m->hasPath(it->second);
148                                         //if the user has not given a path then, add inputdir. else leave path alone.
149                                         if (path == "") {       parameters["name"] = inputDir + it->second;             }
150                                 }
151                 
152                 it = parameters.find("shared");
153                                 //user has given a template file
154                                 if(it != parameters.end()){ 
155                                         path = m->hasPath(it->second);
156                                         //if the user has not given a path then, add inputdir. else leave path alone.
157                                         if (path == "") {       parameters["shared"] = inputDir + it->second;           }
158                                 }
159             }
160 ///////////////////////////////////////////////////////////////////////////////
161 /////////// example of getting filenames and checking dependancies ////////////
162 // the validParameter class will make sure file exists, fill with correct    //
163 // and name is current is given ///////////////////////////////////////////////
164 ///////////////////////////////////////////////////////////////////////////////
165             
166             
167             ///variables for examples below that you will most likely want to put in the header for 
168             //use by the other class functions.
169             string phylipfile, columnfile, namefile, fastafile, sharedfile, method;
170             int processors;
171             bool useTiming, allLines;
172             vector<string> Estimators, Groups;
173             set<string> labels;
174             //if allLines is used it should be initialized to 1 above.
175             
176             
177                         //check for parameters
178             phylipfile = validParameter.validFile(parameters, "phylip", true);
179                         if (phylipfile == "not open") { phylipfile = ""; abort = true; }
180                         else if (phylipfile == "not found") { phylipfile = ""; }        
181                         else {  m->setPhylipFile(phylipfile); }
182                         
183                         columnfile = validParameter.validFile(parameters, "column", true);
184                         if (columnfile == "not open") { columnfile = ""; abort = true; }        
185                         else if (columnfile == "not found") { columnfile = ""; }
186                         else {   m->setColumnFile(columnfile);  }
187                         
188                         namefile = validParameter.validFile(parameters, "name", true);
189                         if (namefile == "not open") { abort = true; }   
190                         else if (namefile == "not found") { namefile = ""; }
191                         else { m->setNameFile(namefile); }
192             
193             //get fastafile - it is not required
194             fastafile = validParameter.validFile(parameters, "fasta", true);
195                         if (fastafile == "not open") { fastafile = ""; abort=true;  }
196                         else if (fastafile == "not found") {  fastafile = "";  }
197                         if (fastafile != "") { m->setFastaFile(fastafile); }
198
199                         
200                         if ((phylipfile == "") && (columnfile == "")) { 
201                                 //is there are current file available for either of these?
202                                 //give priority to column, then phylip
203                                 columnfile = m->getColumnFile(); 
204                                 if (columnfile != "") {   m->mothurOut("Using " + columnfile + " as input file for the column parameter."); m->mothurOutEndLine(); }
205                                 else { 
206                                         phylipfile = m->getPhylipFile(); 
207                                         if (phylipfile != "") {  m->mothurOut("Using " + phylipfile + " as input file for the phylip parameter."); m->mothurOutEndLine(); }
208                                         else { 
209                                                 m->mothurOut("No valid current files. You must provide a phylip or column file before you can use the cluster command."); m->mothurOutEndLine(); 
210                                                 abort = true;
211                                         }
212                                 }
213                         }
214                         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; }
215                         
216                         if (columnfile != "") {
217                                 if (namefile == "") { 
218                                         namefile = m->getNameFile(); 
219                                         if (namefile != "") {  m->mothurOut("Using " + namefile + " as input file for the name parameter."); m->mothurOutEndLine(); }
220                                         else { 
221                                                 m->mothurOut("You need to provide a namefile if you are going to use the column format."); m->mothurOutEndLine(); 
222                                                 abort = true; 
223                                         }       
224                                 }
225                         }
226             
227             //get shared file, it is required
228                         sharedfile = validParameter.validFile(parameters, "shared", true);
229                         if (sharedfile == "not open") { sharedfile = ""; abort = true; }        
230                         else if (sharedfile == "not found") { 
231                                 //if there is a current shared file, use it
232                                 sharedfile = m->getSharedFile(); 
233                                 if (sharedfile != "") { m->mothurOut("Using " + sharedfile + " as input file for the shared parameter."); m->mothurOutEndLine(); }
234                                 else {  m->mothurOut("You have no current sharedfile and the shared parameter is required."); m->mothurOutEndLine(); abort = true; }
235                         }else { m->setSharedFile(sharedfile); }
236             
237             //if the user changes the output directory command factory will send this info to us in the output parameter 
238                         outputDir = validParameter.validFile(parameters, "outputdir", false);           if (outputDir == "not found"){  
239                                 outputDir = m->hasPath(sharedfile); //if user entered a file with a path then preserve it       
240                         }
241
242                         
243 //////////////////////////////////////////////////////////////////////
244 ////////// example of getting other types of parameters //////////////
245 //////////////////////////////////////////////////////////////////////
246             
247                         //use only one Mutliple type
248                         method = validParameter.validFile(parameters, "method", false);
249                         if (method == "not found") { method = "average"; }
250                         
251                         if ((method == "furthest") || (method == "nearest") || (method == "average") || (method == "weighted")) { }
252                         else { m->mothurOut("Not a valid clustering method.  Valid clustering algorithms are furthest, nearest, average, and weighted."); m->mothurOutEndLine(); abort = true; }
253             
254             //use more than one multiple type. do not check to make sure the entry is valid.
255             string calc = validParameter.validFile(parameters, "calc", false);                  
256                         if (calc == "not found") { calc = "sobs-chao-ace-jack-shannon-npshannon-simpson";  }
257                         else { 
258                 if (calc == "default")  {  calc = "sobs-chao-ace-jack-shannon-npshannon-simpson";  }
259                         }
260                         m->splitAtDash(calc, Estimators);
261             
262             //Boolean type - m->isTrue looks for t, true, f or false and is case insensitive
263                         string timing = validParameter.validFile(parameters, "timing", false);
264                         if (timing == "not found") { timing = "F"; }
265             useTiming = m->isTrue(timing);
266                         
267             //Number type - mothurConvert makes sure the convert can happen to avoid a crash.
268             string temp = validParameter.validFile(parameters, "processors", false);    if (temp == "not found"){       temp = m->getProcessors();      }
269                         m->setProcessors(temp);
270                         m->mothurConvert(temp, processors);
271             
272             //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?
273             string groups = validParameter.validFile(parameters, "groups", false);                      
274                         if (groups == "not found") { groups = ""; }
275                         else { m->splitAtDash(groups, Groups); }
276                         m->setGroups(Groups);
277             
278             //Commonly used to process list, rabund, sabund, shared and relabund files.  Look at "smart distancing" examples below in the execute function.
279             string label = validParameter.validFile(parameters, "label", false);                        
280                         if (label == "not found") { label = ""; }
281                         else { 
282                                 if(label != "all") {  m->splitAtDash(label, labels);  allLines = 0;  }
283                                 else { allLines = 1;  }
284                         }
285             
286             //if your command has a namefile as an option, you may want ot check to see if there is a current namefile
287             //saved by mothur that is associated with the other files you are using as inputs.  
288             //You can do so by adding the files associated with the namefile to the files vector and then asking parser to check.  
289             //This saves our users headaches over file mismatches because they forgot to include the namefile, :)
290             if (namefile == "") {
291                                 vector<string> files; files.push_back(fastafile);
292                                 parser.getNameFile(files);
293                         }
294                         
295                 }
296                 
297         }
298         catch(exception& e) {
299                 m->errorOut(e, "NewCommand", "NewCommand");
300                 exit(1);
301         }
302 }
303 //**********************************************************************************************************************
304
305 int NewCommand::execute(){
306         try {
307                 
308                 if (abort == true) { if (calledHelp) { return 0; }  return 2;   }
309         
310         // reading and processing a shared file code example
311         // 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.
312         // 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.
313          
314          //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.
315         
316         /*
317          InputData input(sharedfile, "sharedfile");
318          vector<SharedRAbundVector*> lookup = input.getSharedRAbundVectors();
319          string lastLabel = lookup[0]->getLabel();
320          
321          //if the users enters label "0.06" and there is no "0.06" in their file use the next lowest label.
322          set<string> processedLabels;
323          set<string> userLabels = labels;
324          
325                   
326          //as long as you are not at the end of the file or done wih the lines you want
327          while((lookup[0] != NULL) && ((allLines == 1) || (userLabels.size() != 0))) {
328          
329          if (m->control_pressed) { for (int i = 0; i < lookup.size(); i++) {  delete lookup[i];  }  return 0; }
330          
331          if(allLines == 1 || labels.count(lookup[0]->getLabel()) == 1){                 
332          
333          m->mothurOut(lookup[0]->getLabel()); m->mothurOutEndLine();
334          
335          ///////////////////////////////////////////////////////////////////////////////////
336          //// Call your function to process specific distance in sharedfile, ie lookup /////
337          ///////////////////////////////////////////////////////////////////////////////////
338          
339          processedLabels.insert(lookup[0]->getLabel());
340          userLabels.erase(lookup[0]->getLabel());
341          }
342          
343          if ((m->anyLabelsToProcess(lookup[0]->getLabel(), userLabels, "") == true) && (processedLabels.count(lastLabel) != 1)) {
344          string saveLabel = lookup[0]->getLabel();
345          
346          for (int i = 0; i < lookup.size(); i++) {  delete lookup[i];  }  
347          lookup = input.getSharedRAbundVectors(lastLabel);
348          m->mothurOut(lookup[0]->getLabel()); m->mothurOutEndLine();
349          
350          ///////////////////////////////////////////////////////////////////////////////////
351          //// Call your function to process specific distance in sharedfile, ie lookup /////
352          ///////////////////////////////////////////////////////////////////////////////////
353
354          
355          processedLabels.insert(lookup[0]->getLabel());
356          userLabels.erase(lookup[0]->getLabel());
357          
358          //restore real lastlabel to save below
359          lookup[0]->setLabel(saveLabel);
360          }
361          
362          lastLabel = lookup[0]->getLabel();
363          //prevent memory leak
364          for (int i = 0; i < lookup.size(); i++) {  delete lookup[i]; lookup[i] = NULL; }
365          
366          if (m->control_pressed) { return 0; }
367          
368          //get next line to process
369          lookup = input.getSharedRAbundVectors();                               
370          }
371          
372          if (m->control_pressed) {  return 0; }
373          
374          //output error messages about any remaining user labels
375          set<string>::iterator it;
376          bool needToRun = false;
377          for (it = userLabels.begin(); it != userLabels.end(); it++) {  
378          m->mothurOut("Your file does not include the label " + *it); 
379          if (processedLabels.count(lastLabel) != 1) {
380          m->mothurOut(". I will use " + lastLabel + "."); m->mothurOutEndLine();
381          needToRun = true;
382          }else {
383          m->mothurOut(". Please refer to " + lastLabel + "."); m->mothurOutEndLine();
384          }
385          }
386          
387          //run last label if you need to
388          if (needToRun == true)  {
389          for (int i = 0; i < lookup.size(); i++) { if (lookup[i] != NULL) { delete lookup[i]; } }  
390          lookup = input.getSharedRAbundVectors(lastLabel);
391          
392          m->mothurOut(lookup[0]->getLabel()); m->mothurOutEndLine();
393          
394          ///////////////////////////////////////////////////////////////////////////////////
395          //// Call your function to process specific distance in sharedfile, ie lookup /////
396          ///////////////////////////////////////////////////////////////////////////////////
397
398          
399          for (int i = 0; i < lookup.size(); i++) {  delete lookup[i];  }
400          }
401          */
402         
403         
404         
405         //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.
406                 string currentFasta = "";
407                 itTypes = outputTypes.find("fasta");
408                 if (itTypes != outputTypes.end()) {
409                         if ((itTypes->second).size() != 0) { currentFasta = (itTypes->second)[0]; m->setFastaFile(currentFasta); }
410                 }
411                 
412         //output files created by command
413                 m->mothurOutEndLine();
414                 m->mothurOut("Output File Names: "); m->mothurOutEndLine();
415                 for (int i = 0; i < outputNames.size(); i++) {  m->mothurOut(outputNames[i]); m->mothurOutEndLine();    }
416                 m->mothurOutEndLine();
417         return 0;
418                 
419     }
420         catch(exception& e) {
421                 m->errorOut(e, "NewCommand", "NewCommand");
422                 exit(1);
423         }
424 }
425 //**********************************************************************************************************************
426
427