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