]> git.donarmstrong.com Git - mothur.git/blob - phylotypecommand.cpp
fbc7c6003989044eba397ba7d8d6d58fa37c768a
[mothur.git] / phylotypecommand.cpp
1 /*
2  *  phylotypecommand.cpp
3  *  Mothur
4  *
5  *  Created by westcott on 11/20/09.
6  *  Copyright 2009 Schloss Lab. All rights reserved.
7  *
8  */
9
10 #include "phylotypecommand.h"
11 #include "phylotree.h"
12 #include "listvector.hpp"
13 #include "rabundvector.hpp"
14 #include "sabundvector.hpp"
15
16 //**********************************************************************************************************************
17 vector<string> PhylotypeCommand::setParameters(){       
18         try {
19                 CommandParameter ptaxonomy("taxonomy", "InputTypes", "", "", "none", "none", "none","list-rabund-sabund",false,true,true); parameters.push_back(ptaxonomy);
20                 CommandParameter pname("name", "InputTypes", "", "", "none", "none", "none","",false,false,true); parameters.push_back(pname);
21                 CommandParameter pcutoff("cutoff", "Number", "", "-1", "", "", "","",false,false,true); parameters.push_back(pcutoff);
22                 CommandParameter plabel("label", "String", "", "", "", "", "","",false,false); parameters.push_back(plabel);
23                 CommandParameter pinputdir("inputdir", "String", "", "", "", "", "","",false,false); parameters.push_back(pinputdir);
24                 CommandParameter poutputdir("outputdir", "String", "", "", "", "", "","",false,false); parameters.push_back(poutputdir);
25                 
26                 vector<string> myArray;
27                 for (int i = 0; i < parameters.size(); i++) {   myArray.push_back(parameters[i].name);          }
28                 return myArray;
29         }
30         catch(exception& e) {
31                 m->errorOut(e, "PhylotypeCommand", "setParameters");
32                 exit(1);
33         }
34 }
35 //**********************************************************************************************************************
36 string PhylotypeCommand::getHelpString(){       
37         try {
38                 string helpString = "";
39                 helpString += "The phylotype command reads a taxonomy file and outputs a .list, .rabund and .sabund file. \n";
40                 helpString += "The phylotype command parameter options are taxonomy, cutoff and label. The taxonomy parameter is required.\n";
41                 helpString += "The cutoff parameter allows you to specify the level you want to stop at.  The default is the highest level in your taxonomy file. \n";
42                 helpString += "For example: taxonomy = Bacteria;Bacteroidetes-Chlorobi;Bacteroidetes; - cutoff=2, would truncate the taxonomy to Bacteria;Bacteroidetes-Chlorobi; \n";
43                 helpString += "For the cutoff parameter levels count up from the root of the phylotree. This enables you to look at the grouping down to a specific resolution, say the genus level.\n";
44                 helpString += "The label parameter allows you to specify which level you would like, and are separated by dashes.  The default all levels in your taxonomy file. \n";
45                 helpString += "For the label parameter, levels count down from the root to keep the output similiar to mothur's other commands which report information from finer resolution to coarser resolutions.\n";
46                 helpString += "The phylotype command should be in the following format: \n";
47                 helpString += "phylotype(taxonomy=yourTaxonomyFile, cutoff=yourCutoff, label=yourLabels) \n";
48                 helpString += "Eaxample: phylotype(taxonomy=amazon.taxonomy, cutoff=5, label=1-3-5).\n";
49                 return helpString;
50         }
51         catch(exception& e) {
52                 m->errorOut(e, "PhylotypeCommand", "getHelpString");
53                 exit(1);
54         }
55 }
56 //**********************************************************************************************************************
57 string PhylotypeCommand::getOutputPattern(string type) {
58     try {
59         string pattern = "";
60         
61         if (type == "list") {  pattern = "[filename],[tag],list"; } 
62         else if (type == "rabund") {  pattern = "[filename],[tag],rabund"; } 
63         else if (type == "sabund") {  pattern = "[filename],[tag],sabund"; }
64         else { m->mothurOut("[ERROR]: No definition for type " + type + " output pattern.\n"); m->control_pressed = true;  }
65         
66         return pattern;
67     }
68     catch(exception& e) {
69         m->errorOut(e, "PhylotypeCommand", "getOutputPattern");
70         exit(1);
71     }
72 }
73 //**********************************************************************************************************************
74 PhylotypeCommand::PhylotypeCommand(){   
75         try {
76                 abort = true; calledHelp = true; 
77                 setParameters();
78                 vector<string> tempOutNames;
79                 outputTypes["list"] = tempOutNames;
80                 outputTypes["sabund"] = tempOutNames;
81                 outputTypes["rabund"] = tempOutNames;
82         }
83         catch(exception& e) {
84                 m->errorOut(e, "PhylotypeCommand", "PhylotypeCommand");
85                 exit(1);
86         }
87 }
88 /**********************************************************************************************************************/
89 PhylotypeCommand::PhylotypeCommand(string option)  {
90         try {
91                 abort = false; calledHelp = false;   
92                 
93                 //allow user to run help
94                 if(option == "help") { help(); abort = true; calledHelp = true; }
95                 else if(option == "citation") { citation(); abort = true; calledHelp = true;}
96                 
97                 else {
98                         vector<string> myArray = setParameters();
99                         
100                         OptionParser parser(option);
101                         map<string, string> parameters = parser.getParameters(); 
102                         
103                         ValidParameters validParameter;
104                         map<string, string>::iterator it;
105                         
106                         //check to make sure all parameters are valid for command
107                         for (it = parameters.begin(); it != parameters.end(); it++) { 
108                                 if (validParameter.isValidParameter(it->first, myArray, it->second) != true) {  abort = true;  }
109                         }
110                         
111                         //initialize outputTypes
112                         vector<string> tempOutNames;
113                         outputTypes["list"] = tempOutNames;
114                         outputTypes["sabund"] = tempOutNames;
115                         outputTypes["rabund"] = tempOutNames;
116                         
117                         //if the user changes the input directory command factory will send this info to us in the output parameter 
118                         string inputDir = validParameter.validFile(parameters, "inputdir", false);              
119                         if (inputDir == "not found"){   inputDir = "";          }
120                         else {
121                                 string path;
122                                 it = parameters.find("taxonomy");
123                                 //user has given a template file
124                                 if(it != parameters.end()){ 
125                                         path = m->hasPath(it->second);
126                                         //if the user has not given a path then, add inputdir. else leave path alone.
127                                         if (path == "") {       parameters["taxonomy"] = inputDir + it->second;         }
128                                 }
129                                 
130                                 it = parameters.find("name");
131                                 //user has given a template file
132                                 if(it != parameters.end()){ 
133                                         path = m->hasPath(it->second);
134                                         //if the user has not given a path then, add inputdir. else leave path alone.
135                                         if (path == "") {       parameters["name"] = inputDir + it->second;             }
136                                 }
137                         }
138
139                         taxonomyFileName = validParameter.validFile(parameters, "taxonomy", true);
140                         if (taxonomyFileName == "not found") { 
141                                 taxonomyFileName = m->getTaxonomyFile(); 
142                                 if (taxonomyFileName != "") {  m->mothurOut("Using " + taxonomyFileName + " as input file for the taxonomy parameter."); m->mothurOutEndLine(); }
143                                 else { 
144                                         m->mothurOut("No valid current files. taxonomy is a required parameter."); m->mothurOutEndLine(); 
145                                         abort = true; 
146                                 }
147                         }else if (taxonomyFileName == "not open") { taxonomyFileName = ""; abort = true; }      
148                         else { m->setTaxonomyFile(taxonomyFileName); }
149                         
150                         namefile = validParameter.validFile(parameters, "name", true);
151                         if (namefile == "not open") { namefile = ""; abort = true; }
152                         else if (namefile == "not found") { namefile = ""; }
153                         else { readNamesFile(); m->setNameFile(namefile); }     
154                         
155                         //if the user changes the output directory command factory will send this info to us in the output parameter 
156                         outputDir = validParameter.validFile(parameters, "outputdir", false);           if (outputDir == "not found"){  
157                                 outputDir = ""; 
158                                 outputDir += m->hasPath(taxonomyFileName); //if user entered a file with a path then preserve it        
159                         }
160                         
161                         string temp = validParameter.validFile(parameters, "cutoff", false);
162                         if (temp == "not found") { temp = "-1"; }
163                         m->mothurConvert(temp, cutoff); 
164                         
165                         label = validParameter.validFile(parameters, "label", false);                   
166                         if (label == "not found") { label = ""; allLines = 1; }
167                         else { 
168                                 if(label != "all") {  m->splitAtDash(label, labels);  allLines = 0;  }
169                                 else { allLines = 1;  }
170                         }
171                         
172                         if (namefile == "") {
173                                 vector<string> files; files.push_back(taxonomyFileName);
174                                 parser.getNameFile(files);
175                         }
176                         
177                 }
178         }
179         catch(exception& e) {
180                 m->errorOut(e, "PhylotypeCommand", "PhylotypeCommand");
181                 exit(1);
182         }
183 }
184 /**********************************************************************************************************************/
185
186 int PhylotypeCommand::execute(){
187         try {
188         
189                 if (abort == true) { if (calledHelp) { return 0; }  return 2;   }
190                 
191                 //reads in taxonomy file and makes all the taxonomies the same length 
192                 //by appending the last taxon to a given taxonomy as many times as needed to 
193                 //make it as long as the longest taxonomy in the file 
194                 TaxEqualizer* taxEqual = new TaxEqualizer(taxonomyFileName, cutoff, outputDir);
195                 
196                 if (m->control_pressed) { delete taxEqual; return 0; }
197                 
198                 string equalizedTaxFile = taxEqual->getEqualizedTaxFile();
199                 
200                 delete taxEqual;
201                 
202                 //build taxonomy tree from equalized file
203                 PhyloTree* tree = new PhyloTree(equalizedTaxFile);
204                 vector<int> leaves = tree->getGenusNodes();
205                 
206                 //store leaf nodes in current map
207                 for (int i = 0; i < leaves.size(); i++)         {       currentNodes[leaves[i]] = leaves[i];    }
208                 
209                 bool done = false;
210                 if (tree->get(leaves[0]).parent == -1) {  m->mothurOut("Empty Tree"); m->mothurOutEndLine();    done = true;    }
211                 
212                 if (m->control_pressed) { delete tree; return 0; }
213                 
214                 string fileroot = outputDir + m->getRootName(m->getSimpleName(taxonomyFileName));
215                 map<string, string> variables; 
216         variables["[filename]"] = fileroot;
217         variables["[tag]"] = "tx";
218         ofstream outList;
219                 string outputListFile = getOutputFileName("list",variables);
220                 m->openOutputFile(outputListFile, outList);
221                 ofstream outSabund;
222                 string outputSabundFile = getOutputFileName("sabund",variables);
223                 m->openOutputFile(outputSabundFile, outSabund);
224                 ofstream outRabund;
225                 string outputRabundFile = getOutputFileName("rabund",variables);
226                 m->openOutputFile(outputRabundFile, outRabund);
227                 
228                 outputNames.push_back(outputListFile); outputTypes["list"].push_back(outputListFile);
229                 outputNames.push_back(outputSabundFile); outputTypes["sabund"].push_back(outputSabundFile);
230                 outputNames.push_back(outputRabundFile); outputTypes["rabund"].push_back(outputRabundFile);
231                 
232                 int count = 1;          
233                 //start at leaves of tree and work towards root, processing the labels the user wants
234                 while((!done) && ((allLines == 1) || (labels.size() != 0))) {
235                 
236                         string level = toString(count); 
237                         count++;
238                         
239                         if (m->control_pressed) { 
240                                 outRabund.close(); outSabund.close(); outList.close();
241                                 for (int i = 0; i < outputNames.size(); i++) {  m->mothurRemove(outputNames[i]);  }
242                                 delete tree; return 0; 
243                         }
244                         
245                         //is this a level the user want output for
246                         if(allLines == 1 || labels.count(level) == 1){  
247                                 
248                                 //output level
249                                 m->mothurOut(level); m->mothurOutEndLine();
250                                 
251                                 ListVector list;
252                                 list.setLabel(level);
253                 
254                                 //go through nodes and build listvector 
255                                 for (itCurrent = currentNodes.begin(); itCurrent != currentNodes.end(); itCurrent++) {
256                         
257                                         //get parents
258                                         TaxNode node = tree->get(itCurrent->first);
259                                         parentNodes[node.parent] = node.parent;
260                                         
261                                         vector<string> names = node.accessions;
262                                         
263                                         //make the names compatable with listvector
264                                         string name = "";
265                                         for (int i = 0; i < names.size(); i++) {  
266                         
267                         if (names[i] != "unknown") {
268                             if (namefile != "") {       
269                                 map<string, string>::iterator itNames = namemap.find(names[i]);  //make sure this name is in namefile
270                                 
271                                 if (itNames != namemap.end()) {  name += namemap[names[i]] + ",";   } //you found it in namefile
272                                 else { m->mothurOut("[ERROR]: " + names[i] + " is not in your namefile, please correct."); m->mothurOutEndLine(); m->control_pressed = true;  }
273                                 
274                             }else{   name += names[i] + ",";    }
275                         }
276                                         }
277                     
278                     if (m->control_pressed) { break; }
279                     
280                                         name = name.substr(0, name.length()-1);  //rip off extra ','
281                                         //add bin to list vector
282                                         if (name != "") { list.push_back(name); } //caused by unknown
283                                 }       
284                                 
285                                 //print listvector
286                                 list.print(outList);
287                                 //print rabund
288                                 list.getRAbundVector().print(outRabund);
289                                 //print sabund
290                                 list.getSAbundVector().print(outSabund);
291                         
292                                 labels.erase(level);
293                                 
294                         }else {
295                                 
296                                 //just get parents
297                                 for (itCurrent = currentNodes.begin(); itCurrent != currentNodes.end(); itCurrent++) {
298                                         int parent = tree->get(itCurrent->first).parent;
299                                         parentNodes[parent] = parent;
300                                 }
301                         }
302                         
303                         //move up a level
304                         currentNodes = parentNodes;
305                         parentNodes.clear();
306                         
307                         //have we reached the rootnode
308                         if (tree->get(currentNodes.begin()->first).parent == -1)  {  done = true;  }
309                 }
310                         
311                 outList.close();
312                 outSabund.close();
313                 outRabund.close();      
314                 
315                 delete tree;
316                 
317                 if (m->control_pressed) { 
318                         for (int i = 0; i < outputNames.size(); i++) {  m->mothurRemove(outputNames[i]);  }
319                         return 0; 
320                 }
321                 
322                 //set list file as new current listfile
323                 string current = "";
324                 itTypes = outputTypes.find("list");
325                 if (itTypes != outputTypes.end()) {
326                         if ((itTypes->second).size() != 0) { current = (itTypes->second)[0]; m->setListFile(current); }
327                 }
328                 
329                 //set rabund file as new current rabundfile
330                 itTypes = outputTypes.find("rabund");
331                 if (itTypes != outputTypes.end()) {
332                         if ((itTypes->second).size() != 0) { current = (itTypes->second)[0]; m->setRabundFile(current); }
333                 }
334                 
335                 //set sabund file as new current sabundfile
336                 itTypes = outputTypes.find("sabund");
337                 if (itTypes != outputTypes.end()) {
338                         if ((itTypes->second).size() != 0) { current = (itTypes->second)[0]; m->setSabundFile(current); }
339                 }               
340                 
341                 m->mothurOutEndLine();
342                 m->mothurOut("Output File Names: "); m->mothurOutEndLine();
343                 for (int i = 0; i < outputNames.size(); i++) {  m->mothurOut(outputNames[i]); m->mothurOutEndLine();    }
344                 m->mothurOutEndLine();
345                 
346                 return 0;               
347         }
348
349         catch(exception& e) {
350                 m->errorOut(e, "PhylotypeCommand", "execute");
351                 exit(1);
352         }
353 }
354 /*****************************************************************/
355 int PhylotypeCommand::readNamesFile() {
356         try {
357                                 
358                 ifstream in;
359                 m->openInputFile(namefile, in);
360                 
361                 string first, second;
362                 map<string, string>::iterator itNames;
363                 
364                 while(!in.eof()) {
365                         in >> first >> second; m->gobble(in);
366                         
367                         itNames = namemap.find(first);
368                         if (itNames == namemap.end()) {  
369                                 namemap[first] = second; 
370                         }else {  m->mothurOut(first + " has already been seen in namefile, disregarding names file."); m->mothurOutEndLine(); in.close(); namemap.clear(); namefile = ""; return 1; }                   
371                 }
372                 in.close();
373                 
374                 return 0;
375         }
376         catch(exception& e) {
377                 m->errorOut(e, "PhylotypeCommand", "readNamesFile");
378                 exit(1);
379         }
380 }
381
382 /**********************************************************************************************************************/