]> git.donarmstrong.com Git - mothur.git/blob - phylotypecommand.cpp
added name parameter to phylotype command
[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 PhylotypeCommand::PhylotypeCommand(string option)  {
18         try {
19                 abort = false;
20                 
21                 //allow user to run help
22                 if(option == "help") { help(); abort = true; }
23                 
24                 else {
25                         
26                         //valid paramters for this command
27                         string AlignArray[] =  {"taxonomy","cutoff","label","name","outputdir","inputdir"};
28                         vector<string> myArray (AlignArray, AlignArray+(sizeof(AlignArray)/sizeof(string)));
29                         
30                         OptionParser parser(option);
31                         map<string, string> parameters = parser.getParameters(); 
32                         
33                         ValidParameters validParameter;
34                         map<string, string>::iterator it;
35                         
36                         //check to make sure all parameters are valid for command
37                         for (it = parameters.begin(); it != parameters.end(); it++) { 
38                                 if (validParameter.isValidParameter(it->first, myArray, it->second) != true) {  abort = true;  }
39                         }
40                         
41                         //if the user changes the input directory command factory will send this info to us in the output parameter 
42                         string inputDir = validParameter.validFile(parameters, "inputdir", false);              
43                         if (inputDir == "not found"){   inputDir = "";          }
44                         else {
45                                 string path;
46                                 it = parameters.find("taxonomy");
47                                 //user has given a template file
48                                 if(it != parameters.end()){ 
49                                         path = hasPath(it->second);
50                                         //if the user has not given a path then, add inputdir. else leave path alone.
51                                         if (path == "") {       parameters["taxonomy"] = inputDir + it->second;         }
52                                 }
53                                 
54                                 it = parameters.find("name");
55                                 //user has given a template file
56                                 if(it != parameters.end()){ 
57                                         path = hasPath(it->second);
58                                         //if the user has not given a path then, add inputdir. else leave path alone.
59                                         if (path == "") {       parameters["name"] = inputDir + it->second;             }
60                                 }
61                         }
62
63                         taxonomyFileName = validParameter.validFile(parameters, "taxonomy", true);
64                         if (taxonomyFileName == "not found") { 
65                                 m->mothurOut("taxonomy is a required parameter for the phylotype command."); 
66                                 m->mothurOutEndLine();
67                                 abort = true; 
68                         }else if (taxonomyFileName == "not open") { abort = true; }     
69                         
70                         namefile = validParameter.validFile(parameters, "name", true);
71                         if (namefile == "not open") { abort = true; }
72                         else if (namefile == "not found") { namefile = ""; }
73                         else { readNamesFile(); }       
74                         
75                         //if the user changes the output directory command factory will send this info to us in the output parameter 
76                         outputDir = validParameter.validFile(parameters, "outputdir", false);           if (outputDir == "not found"){  
77                                 outputDir = ""; 
78                                 outputDir += hasPath(taxonomyFileName); //if user entered a file with a path then preserve it   
79                         }
80                         
81                         string temp = validParameter.validFile(parameters, "cutoff", false);
82                         if (temp == "not found") { temp = "-1"; }
83                         convert(temp, cutoff); 
84                         
85                         label = validParameter.validFile(parameters, "label", false);                   
86                         if (label == "not found") { label = ""; allLines = 1; }
87                         else { 
88                                 if(label != "all") {  splitAtDash(label, labels);  allLines = 0;  }
89                                 else { allLines = 1;  }
90                         }
91                         
92                 }
93         }
94         catch(exception& e) {
95                 m->errorOut(e, "PhylotypeCommand", "PhylotypeCommand");
96                 exit(1);
97         }
98 }
99 /**********************************************************************************************************************/
100
101 void PhylotypeCommand::help(){
102         try {
103                 m->mothurOut("The phylotype command reads a taxonomy file and outputs a .list, .rabund and .sabund file. \n");
104                 m->mothurOut("The phylotype command parameter options are taxonomy, cutoff and label. The taxonomy parameter is required.\n");
105                 m->mothurOut("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");
106                 m->mothurOut("For example: taxonomy = Bacteria;Bacteroidetes-Chlorobi;Bacteroidetes; - cutoff=2, would truncate the taxonomy to Bacteria;Bacteroidetes-Chlorobi; \n");
107                 m->mothurOut("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");
108                 m->mothurOut("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");
109                 m->mothurOut("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");
110                 m->mothurOut("The phylotype command should be in the following format: \n");
111                 m->mothurOut("phylotype(taxonomy=yourTaxonomyFile, cutoff=yourCutoff, label=yourLabels) \n");
112                 m->mothurOut("Eaxample: phylotype(taxonomy=amazon.taxonomy, cutoff=5, label=1-3-5).\n\n");
113         }
114         catch(exception& e) {
115                 m->errorOut(e, "PhylotypeCommand", "help");
116                 exit(1);
117         }
118 }
119 /**********************************************************************************************************************/
120
121 PhylotypeCommand::~PhylotypeCommand(){}
122
123 /**********************************************************************************************************************/
124
125 int PhylotypeCommand::execute(){
126         try {
127         
128                 if (abort == true) { return 0; }
129                 
130                 vector<string> outputNames;
131                 
132                 //reads in taxonomy file and makes all the taxonomies the same length 
133                 //by appending the last taxon to a given taxonomy as many times as needed to 
134                 //make it as long as the longest taxonomy in the file 
135                 TaxEqualizer* taxEqual = new TaxEqualizer(taxonomyFileName, cutoff, outputDir);
136                 
137                 if (m->control_pressed) { delete taxEqual; return 0; }
138                 
139                 string equalizedTaxFile = taxEqual->getEqualizedTaxFile();
140                 
141                 delete taxEqual;
142                 
143                 //build taxonomy tree from equalized file
144                 PhyloTree* tree = new PhyloTree(equalizedTaxFile);
145                 vector<int> leaves = tree->getGenusNodes();
146                 
147                 //store leaf nodes in current map
148                 for (int i = 0; i < leaves.size(); i++)         {       currentNodes[leaves[i]] = leaves[i];    }
149                 
150                 bool done = false;
151                 if (tree->get(leaves[0]).parent == -1) {  m->mothurOut("Empty Tree"); m->mothurOutEndLine();    done = true;    }
152                 
153                 if (m->control_pressed) { delete tree; return 0; }
154                 
155                 string fileroot = outputDir + getRootName(getSimpleName(taxonomyFileName));
156                 
157                 ofstream outList;
158                 string outputListFile = fileroot + "tx.list";
159                 openOutputFile(outputListFile, outList);
160                 ofstream outSabund;
161                 string outputSabundFile = fileroot + "tx.sabund";
162                 openOutputFile(outputSabundFile, outSabund);
163                 ofstream outRabund;
164                 string outputRabundFile = fileroot + "tx.rabund";
165                 openOutputFile(outputRabundFile, outRabund);
166                 
167                 outputNames.push_back(outputListFile);
168                 outputNames.push_back(outputSabundFile);
169                 outputNames.push_back(outputRabundFile);
170                 
171                 int count = 1;          
172                 //start at leaves of tree and work towards root, processing the labels the user wants
173                 while((!done) && ((allLines == 1) || (labels.size() != 0))) {
174                 
175                         string level = toString(count); 
176                         count++;
177                         
178                         if (m->control_pressed) { 
179                                 outRabund.close(); outSabund.close(); outList.close();
180                                 for (int i = 0; i < outputNames.size(); i++) {  remove(outputNames[i].c_str());  }
181                                 delete tree; return 0; 
182                         }
183                         
184                         //is this a level the user want output for
185                         if(allLines == 1 || labels.count(level) == 1){  
186                                 
187                                 //output level
188                                 m->mothurOut(level); m->mothurOutEndLine();
189                                 
190                                 ListVector list;
191                                 list.setLabel(level);
192                                 //go through nodes and build listvector 
193                                 for (itCurrent = currentNodes.begin(); itCurrent != currentNodes.end(); itCurrent++) {
194                         
195                                         //get parents
196                                         TaxNode node = tree->get(itCurrent->first);
197                                         parentNodes[node.parent] = node.parent;
198                                         
199                                         vector<string> names = node.accessions;
200                                         
201                                         //make the names compatable with listvector
202                                         string name = "";
203                                         for (int i = 0; i < names.size(); i++) {  
204                                                 if (namefile != "") {   
205                                                         map<string, string>::iterator itNames = namemap.find(names[i]);  //make sure this name is in namefile
206                 
207                                                         if (itNames != namemap.end()) {  name += namemap[names[i]] + ",";   } //you found it in namefile
208                                                         else { m->mothurOut(names[i] + " is not in your namefile, please correct."); m->mothurOutEndLine(); exit(1);  }
209                                                         
210                                                 }else{   name += names[i] + ",";        }
211                                         }
212                                         name = name.substr(0, name.length()-1);  //rip off extra ','
213                                         
214                                         //add bin to list vector
215                                         list.push_back(name);
216                                 }       
217                                 
218                                 //print listvector
219                                 list.print(outList);
220                                 //print rabund
221                                 list.getRAbundVector().print(outRabund);
222                                 //print sabund
223                                 list.getSAbundVector().print(outSabund);
224                         
225                                 labels.erase(level);
226                                 
227                         }else {
228                                 
229                                 //just get parents
230                                 for (itCurrent = currentNodes.begin(); itCurrent != currentNodes.end(); itCurrent++) {
231                                         int parent = tree->get(itCurrent->first).parent;
232                                         parentNodes[parent] = parent;
233                                 }
234                         }
235                         
236                         //move up a level
237                         currentNodes = parentNodes;
238                         parentNodes.clear();
239                         
240                         //have we reached the rootnode
241                         if (tree->get(currentNodes.begin()->first).parent == -1)  {  done = true;  }
242                 }
243                         
244                 outList.close();
245                 outSabund.close();
246                 outRabund.close();      
247                 
248                 delete tree;
249                 
250                 if (m->control_pressed) { 
251                         for (int i = 0; i < outputNames.size(); i++) {  remove(outputNames[i].c_str());  }
252                         return 0; 
253                 }
254                 
255                 m->mothurOutEndLine();
256                 m->mothurOut("Output File Names: "); m->mothurOutEndLine();
257                 for (int i = 0; i < outputNames.size(); i++) {  m->mothurOut(outputNames[i]); m->mothurOutEndLine();    }
258                 m->mothurOutEndLine();
259                 
260                 return 0;               
261         }
262
263         catch(exception& e) {
264                 m->errorOut(e, "PhylotypeCommand", "execute");
265                 exit(1);
266         }
267 }
268 /*****************************************************************/
269 int PhylotypeCommand::readNamesFile() {
270         try {
271                                 
272                 ifstream in;
273                 openInputFile(namefile, in);
274                 
275                 string first, second;
276                 map<string, string>::iterator itNames;
277                 
278                 while(!in.eof()) {
279                         in >> first >> second; gobble(in);
280                         
281                         itNames = namemap.find(first);
282                         if (itNames == namemap.end()) {  
283                                 namemap[first] = second; 
284                         }else {  m->mothurOut(first + " has already been seen in namefile, disregarding names file."); m->mothurOutEndLine(); in.close(); namemap.clear(); namefile = ""; return 1; }                   
285                 }
286                 in.close();
287                 
288                 return 0;
289         }
290         catch(exception& e) {
291                 m->errorOut(e, "PhylotypeCommand", "readNamesFile");
292                 exit(1);
293         }
294 }
295
296 /**********************************************************************************************************************/