]> git.donarmstrong.com Git - mothur.git/blob - newcommandtemplate.cpp
fixes while testing 1.33.0
[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 // Test Change.
13 //**********************************************************************************************************************
14 vector<string> NewCommand::setParameters(){     
15         try {
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);
18         
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);                
26
27         
28         CommandParameter pgroups("groups", "String", "", "", "", "", "","",false,false); parameters.push_back(pgroups);
29                 CommandParameter plabel("label", "String", "", "", "", "", "","",false,false); parameters.push_back(plabel);
30                 
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);
35         
36         CommandParameter ptiming("timing", "Boolean", "", "F", "", "", "","",false,false); parameters.push_back(ptiming);
37         
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);
41                 
42                 vector<string> myArray;
43                 for (int i = 0; i < parameters.size(); i++) {   myArray.push_back(parameters[i].name);          }
44                 return myArray;
45         }
46         catch(exception& e) {
47                 m->errorOut(e, "NewCommand", "setParameters");
48                 exit(1);
49         }
50 }
51 //**********************************************************************************************************************
52 string NewCommand::getHelpString(){     
53         try {
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";
60                 return helpString;
61         }
62         catch(exception& e) {
63                 m->errorOut(e, "NewCommand", "getHelpString");
64                 exit(1);
65         }
66 }
67 //**********************************************************************************************************************
68 string NewCommand::getOutputPattern(string type) {
69     try {
70         string pattern = "";
71         
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;  }
76         
77         return pattern;
78     }
79     catch(exception& e) {
80         m->errorOut(e, "NewCommand", "getOutputPattern");
81         exit(1);
82     }
83 }
84 //**********************************************************************************************************************
85 NewCommand::NewCommand(){       
86         try {
87                 abort = true; calledHelp = true;
88                 setParameters();
89         vector<string> tempOutNames;
90                 outputTypes["fileType1"] = tempOutNames; //filetypes should be things like: shared, fasta, accnos...
91                 outputTypes["fileType2"] = tempOutNames;
92                 outputTypes["FileType3"] = tempOutNames;
93         }
94         catch(exception& e) {
95                 m->errorOut(e, "NewCommand", "NewCommand");
96                 exit(1);
97         }
98 }
99 //**********************************************************************************************************************
100 NewCommand::NewCommand(string option)  {
101         try {
102 ////////////////////////////////////////////////////////
103 /////////////////// start leave alone block ////////////
104 ////////////////////////////////////////////////////////
105                 abort = false; calledHelp = false;   
106                 
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;}
110                 
111                 else {
112                         //valid paramters for this command
113                         vector<string> myArray = setParameters();
114                         
115                         OptionParser parser(option);
116                         map<string,string> parameters = parser.getParameters();
117                         
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;  }
123                         }
124                         
125                         
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 = "";          }
129                         else {
130                 
131 ///////////////////////////////////////////////////////////////
132 //////////////// stop leave alone block ///////////////////////
133 ///////////////////////////////////////////////////////////////
134                 
135 //edit file types below to include only the types you added as parameters
136                 
137                                 string path;
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;           }
144                                 }
145                                 
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;           }
152                                 }
153                                 
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;            }
160                                 }
161                                                                 
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;             }
168                                 }
169                 
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;           }
176                                 }
177             }
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 ///////////////////////////////////////////////////////////////////////////////
183             
184             
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;
188             int processors;
189             bool useTiming, allLines;
190             vector<string> Estimators, Groups;
191             set<string> labels;
192             //if allLines is used it should be initialized to 1 above.
193             
194             
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); }
200                         
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);  }
205                         
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); }
210             
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); }
216
217                         
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(); }
223                                 else { 
224                                         phylipfile = m->getPhylipFile(); 
225                                         if (phylipfile != "") {  m->mothurOut("Using " + phylipfile + " as input file for the phylip parameter."); m->mothurOutEndLine(); }
226                                         else { 
227                                                 m->mothurOut("No valid current files. You must provide a phylip or column file before you can use the cluster command."); m->mothurOutEndLine(); 
228                                                 abort = true;
229                                         }
230                                 }
231                         }
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; }
233                         
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(); }
238                                         else { 
239                                                 m->mothurOut("You need to provide a namefile if you are going to use the column format."); m->mothurOutEndLine(); 
240                                                 abort = true; 
241                                         }       
242                                 }
243                         }
244             
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); }
254             
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       
258                         }
259
260                         
261 //////////////////////////////////////////////////////////////////////
262 ////////// example of getting other types of parameters //////////////
263 //////////////////////////////////////////////////////////////////////
264             
265                         //use only one Mutliple type
266                         method = validParameter.validFile(parameters, "method", false);
267                         if (method == "not found") { method = "average"; }
268                         
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; }
271             
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";  }
275                         else { 
276                 if (calc == "default")  {  calc = "sobs-chao-ace-jack-shannon-npshannon-simpson";  }
277                         }
278                         m->splitAtDash(calc, Estimators);
279             
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);
284                         
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);
289             
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);
295             
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 = ""; }
299                         else { 
300                                 if(label != "all") {  m->splitAtDash(label, labels);  allLines = 0;  }
301                                 else { allLines = 1;  }
302                         }
303             
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);
312                 }
313             }
314
315                         
316                 }
317                 
318         }
319         catch(exception& e) {
320                 m->errorOut(e, "NewCommand", "NewCommand");
321                 exit(1);
322         }
323 }
324 //**********************************************************************************************************************
325
326 int NewCommand::execute(){
327         try {
328                 
329                 if (abort == true) { if (calledHelp) { return 0; }  return 2;   }
330         
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.
334          
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.
336         
337         /*
338          InputData input(sharedfile, "sharedfile");
339          vector<SharedRAbundVector*> lookup = input.getSharedRAbundVectors();
340          string lastLabel = lookup[0]->getLabel();
341          
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;
345          
346                   
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))) {
349          
350          if (m->control_pressed) { for (int i = 0; i < lookup.size(); i++) {  delete lookup[i];  }  return 0; }
351          
352          if(allLines == 1 || labels.count(lookup[0]->getLabel()) == 1){                 
353          
354          m->mothurOut(lookup[0]->getLabel()); m->mothurOutEndLine();
355          
356          ///////////////////////////////////////////////////////////////////////////////////
357          //// Call your function to process specific distance in sharedfile, ie lookup /////
358          ///////////////////////////////////////////////////////////////////////////////////
359          
360          processedLabels.insert(lookup[0]->getLabel());
361          userLabels.erase(lookup[0]->getLabel());
362          }
363          
364          if ((m->anyLabelsToProcess(lookup[0]->getLabel(), userLabels, "") == true) && (processedLabels.count(lastLabel) != 1)) {
365          string saveLabel = lookup[0]->getLabel();
366          
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();
370          
371          ///////////////////////////////////////////////////////////////////////////////////
372          //// Call your function to process specific distance in sharedfile, ie lookup /////
373          ///////////////////////////////////////////////////////////////////////////////////
374
375          
376          processedLabels.insert(lookup[0]->getLabel());
377          userLabels.erase(lookup[0]->getLabel());
378          
379          //restore real lastlabel to save below
380          lookup[0]->setLabel(saveLabel);
381          }
382          
383          lastLabel = lookup[0]->getLabel();
384          //prevent memory leak
385          for (int i = 0; i < lookup.size(); i++) {  delete lookup[i]; lookup[i] = NULL; }
386          
387          if (m->control_pressed) { return 0; }
388          
389          //get next line to process
390          lookup = input.getSharedRAbundVectors();                               
391          }
392          
393          if (m->control_pressed) {  return 0; }
394          
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();
402          needToRun = true;
403          }else {
404          m->mothurOut(". Please refer to " + lastLabel + "."); m->mothurOutEndLine();
405          }
406          }
407          
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);
412          
413          m->mothurOut(lookup[0]->getLabel()); m->mothurOutEndLine();
414          
415          ///////////////////////////////////////////////////////////////////////////////////
416          //// Call your function to process specific distance in sharedfile, ie lookup /////
417          ///////////////////////////////////////////////////////////////////////////////////
418
419          
420          for (int i = 0; i < lookup.size(); i++) {  delete lookup[i];  }
421          }
422          */
423         
424         
425         
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); }
431                 }
432                 
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();
438         return 0;
439                 
440     }
441         catch(exception& e) {
442                 m->errorOut(e, "NewCommand", "NewCommand");
443                 exit(1);
444         }
445 }
446 //**********************************************************************************************************************
447
448