]> git.donarmstrong.com Git - mothur.git/blob - parselistscommand.cpp
moved utilities out of mothur.h and into mothurOut class.
[mothur.git] / parselistscommand.cpp
1 /*
2  *  parselistcommand.cpp
3  *  Mothur
4  *
5  *  Created by westcott on 2/24/10.
6  *  Copyright 2010 Schloss Lab. All rights reserved.
7  *
8  */
9
10 #include "parselistscommand.h"
11
12 //**********************************************************************************************************************
13 ParseListCommand::ParseListCommand(string option)  {
14         try {
15                 abort = false;
16                 allLines = 1;
17                         
18                 //allow user to run help
19                 if(option == "help") { help(); abort = true; }
20                 
21                 else {
22                         //valid paramters for this command
23                         string Array[] =  {"list","group", "label", "outputdir","inputdir"};
24                         vector<string> myArray (Array, Array+(sizeof(Array)/sizeof(string)));
25                         
26                         OptionParser parser(option);
27                         map<string, string> parameters = parser.getParameters();
28                         
29                         ValidParameters validParameter;
30                         map<string, string>::iterator it;
31                 
32                         //check to make sure all parameters are valid for command
33                         for (it = parameters.begin(); it != parameters.end(); it++) { 
34                                 if (validParameter.isValidParameter(it->first, myArray, it->second) != true) {  abort = true;  }
35                         }
36                                                 
37                         //if the user changes the input directory command factory will send this info to us in the output parameter 
38                         string inputDir = validParameter.validFile(parameters, "inputdir", false);              
39                         if (inputDir == "not found"){   inputDir = "";          }
40                         else {
41                                 string path;
42                                 it = parameters.find("list");
43                                 //user has given a template file
44                                 if(it != parameters.end()){ 
45                                         path = m->hasPath(it->second);
46                                         //if the user has not given a path then, add inputdir. else leave path alone.
47                                         if (path == "") {       parameters["list"] = inputDir + it->second;             }
48                                 }
49                                 
50                                 it = parameters.find("group");
51                                 //user has given a template file
52                                 if(it != parameters.end()){ 
53                                         path = m->hasPath(it->second);
54                                         //if the user has not given a path then, add inputdir. else leave path alone.
55                                         if (path == "") {       parameters["group"] = inputDir + it->second;            }
56                                 }
57                         }
58
59                         
60                         //if the user changes the output directory command factory will send this info to us in the output parameter 
61                         outputDir = validParameter.validFile(parameters, "outputdir", false);           if (outputDir == "not found"){  outputDir = ""; }
62
63                         //check for required parameters
64                         listfile = validParameter.validFile(parameters, "list", true);
65                         if (listfile == "not open") { abort = true; }
66                         else if (listfile == "not found") { listfile = ""; }    
67                         
68                         groupfile = validParameter.validFile(parameters, "group", true);
69                         if (groupfile == "not open") { abort = true; }  
70                         else if (groupfile == "not found") { groupfile = ""; }
71                         else {  
72                                 groupMap = new GroupMap(groupfile);
73                                 
74                                 int error = groupMap->readMap();
75                                 if (error == 1) { abort = true; }
76                         }
77                         
78                         //do you have all files needed
79                         if ((listfile == "") || (groupfile == "")) { m->mothurOut("You must enter both a listfile and groupfile for the parse.list command. "); m->mothurOutEndLine(); abort = true;  }
80                         
81                         //check for optional parameter and set defaults
82                         // ...at some point should added some additional type checking...
83                         label = validParameter.validFile(parameters, "label", false);                   
84                         if (label == "not found") { label = "";  allLines = 1; }
85                         else { 
86                                 if(label != "all") {  m->splitAtDash(label, labels);  allLines = 0;  }
87                                 else { allLines = 1;  }
88                         }
89                 }
90
91         }
92         catch(exception& e) {
93                 m->errorOut(e, "ParseListCommand", "ParseListCommand");
94                 exit(1);
95         }
96 }
97 //**********************************************************************************************************************
98 void ParseListCommand::help(){
99         try {
100                 m->mothurOut("The parse.list command reads a list and group file and generates a list file for each group in the groupfile. \n");
101                 m->mothurOut("The parse.list command parameters are list, group and label.\n");
102                 m->mothurOut("The list and group parameters are required.\n");
103                 m->mothurOut("The label parameter is used to read specific labels in your input you want to use.\n");
104                 m->mothurOut("The parse.list command should be used in the following format: parse.list(list=yourListFile, group=yourGroupFile, label=yourLabels).\n");
105                 m->mothurOut("Example: parse.list(list=abrecovery.fn.list, group=abrecovery.groups, label=0.03).\n");
106                 m->mothurOut("Note: No spaces between parameter labels (i.e. list), '=' and parameters (i.e.yourListfile).\n\n");
107
108         }
109         catch(exception& e) {
110                 m->errorOut(e, "ParseListCommand", "help");
111                 exit(1);
112         }
113 }
114 //**********************************************************************************************************************
115 ParseListCommand::~ParseListCommand(){}
116 //**********************************************************************************************************************
117 int ParseListCommand::execute(){
118         try {
119         
120                 if (abort == true) {    return 0;       }
121                 
122                 //set fileroot
123                 string fileroot = outputDir + m->getRootName(m->getSimpleName(listfile));
124                 vector<string> outputNames;
125                 
126                 //fill filehandles with neccessary ofstreams
127                 int i;
128                 ofstream* temp;
129                 for (i=0; i<groupMap->namesOfGroups.size(); i++) {
130                         temp = new ofstream;
131                         filehandles[groupMap->namesOfGroups[i]] = temp;
132                         
133                         string filename = fileroot +  groupMap->namesOfGroups[i] + ".list";
134                         outputNames.push_back(filename);
135                         m->openOutputFile(filename, *temp);
136                 }
137                 
138                 //if the users enters label "0.06" and there is no "0.06" in their file use the next lowest label.
139                 set<string> processedLabels;
140                 set<string> userLabels = labels;        
141         
142                 input = new InputData(listfile, "list");
143                 list = input->getListVector();
144                 string lastLabel = list->getLabel();
145                 
146                 if (m->control_pressed) { 
147                         delete input; delete list; delete groupMap;
148                         for (i=0; i<groupMap->namesOfGroups.size(); i++) {  (*(filehandles[groupMap->namesOfGroups[i]])).close();  delete filehandles[groupMap->namesOfGroups[i]]; } 
149                         for (int i = 0; i < outputNames.size(); i++) {  remove(outputNames[i].c_str()); }
150                         return 0;
151                 }
152                 
153                 while((list != NULL) && ((allLines == 1) || (userLabels.size() != 0))) {
154                 
155                         if (m->control_pressed) { 
156                                 delete input; delete list; delete groupMap;
157                                 for (i=0; i<groupMap->namesOfGroups.size(); i++) {  (*(filehandles[groupMap->namesOfGroups[i]])).close();  delete filehandles[groupMap->namesOfGroups[i]]; } 
158                                 for (int i = 0; i < outputNames.size(); i++) {  remove(outputNames[i].c_str()); }
159                                 return 0;
160                         }
161                         
162                         if(allLines == 1 || labels.count(list->getLabel()) == 1){
163                                         
164                                         m->mothurOut(list->getLabel()); m->mothurOutEndLine();
165                                         parse(list);
166                                                                                 
167                                         processedLabels.insert(list->getLabel());
168                                         userLabels.erase(list->getLabel());
169                         }
170                         
171                         if ((m->anyLabelsToProcess(list->getLabel(), userLabels, "") == true) && (processedLabels.count(lastLabel) != 1)) {
172                                         string saveLabel = list->getLabel();
173                                         
174                                         delete list;
175                                         list = input->getListVector(lastLabel); //get new list vector to process
176                                         
177                                         m->mothurOut(list->getLabel()); m->mothurOutEndLine();
178                                         parse(list);
179                                         
180                                         processedLabels.insert(list->getLabel());
181                                         userLabels.erase(list->getLabel());
182                                         
183                                         //restore real lastlabel to save below
184                                         list->setLabel(saveLabel);
185                         }
186                         
187                 
188                         lastLabel = list->getLabel();
189                                 
190                         delete list;
191                         list = input->getListVector(); //get new list vector to process
192                 }
193                 
194                 if (m->control_pressed) { 
195                                 delete input; delete groupMap;
196                                 for (i=0; i<groupMap->namesOfGroups.size(); i++) { (*(filehandles[groupMap->namesOfGroups[i]])).close();  delete filehandles[groupMap->namesOfGroups[i]]; } 
197                                 for (int i = 0; i < outputNames.size(); i++) {  remove(outputNames[i].c_str()); }
198                                 return 0;
199                 }
200                 
201                 //output error messages about any remaining user labels
202                 set<string>::iterator it;
203                 bool needToRun = false;
204                 for (it = userLabels.begin(); it != userLabels.end(); it++) {  
205                         m->mothurOut("Your file does not include the label " + *it); 
206                         if (processedLabels.count(lastLabel) != 1) {
207                                 m->mothurOut(". I will use " + lastLabel + "."); m->mothurOutEndLine();
208                                 needToRun = true;
209                         }else {
210                                 m->mothurOut(". Please refer to " + lastLabel + "."); m->mothurOutEndLine();
211                         }
212
213                 }
214                 
215                 if (m->control_pressed) { 
216                                 delete input; delete groupMap;
217                                 for (i=0; i<groupMap->namesOfGroups.size(); i++) {  (*(filehandles[groupMap->namesOfGroups[i]])).close();  delete filehandles[groupMap->namesOfGroups[i]]; } 
218                                 for (int i = 0; i < outputNames.size(); i++) {  remove(outputNames[i].c_str()); }
219                                 return 0;
220                 }
221                 
222                 //run last label if you need to
223                 if (needToRun == true)  {
224                         if (list != NULL) {     delete list;    }
225                         list = input->getListVector(lastLabel); //get new list vector to process
226                         
227                         m->mothurOut(list->getLabel()); m->mothurOutEndLine();
228                         parse(list);            
229                         
230                         delete list;
231                 }
232                 
233                 for (it3 = filehandles.begin(); it3 != filehandles.end(); it3++) {
234                         (*(filehandles[it3->first])).close();
235                         delete it3->second;
236                 }
237                 
238                 
239                 delete groupMap;
240                 delete input;
241                 
242                 if (m->control_pressed) { 
243                         for (int i = 0; i < outputNames.size(); i++) {  remove(outputNames[i].c_str()); }
244                         return 0;
245                 }
246                 
247                 m->mothurOutEndLine();
248                 m->mothurOut("Output File Names: "); m->mothurOutEndLine();
249                 for (int i = 0; i < outputNames.size(); i++) {  m->mothurOut(outputNames[i]); m->mothurOutEndLine();    }
250                 m->mothurOutEndLine();
251                 
252                 return 0;
253         }
254         catch(exception& e) {
255                 m->errorOut(e, "ParseListCommand", "execute");
256                 exit(1);
257         }
258 }
259 /**********************************************************************************************************************/
260 int ParseListCommand::parse(ListVector* thisList) {
261         try {
262         
263                 map<string, string> groupVector;
264                 map<string, string>::iterator itGroup;
265                 map<string, int> groupNumBins;
266                 
267                 //print label
268                 for (it3 = filehandles.begin(); it3 != filehandles.end(); it3++) {
269                         groupNumBins[it3->first] = 0;
270                         groupVector[it3->first] = "";
271                 }
272
273                 
274                 for (int i = 0; i < thisList->getNumBins(); i++) {
275                         if (m->control_pressed) { return 0; }
276                         
277                         map<string, string> groupBins;
278                         string bin = list->get(i); 
279                         
280                         vector<string> names;
281                         m->splitAtComma(bin, names);  //parses bin into individual sequence names
282                         
283                         //parse bin into list of sequences in each group
284                         for (int j = 0; j < names.size(); j++) {
285                                 string group = groupMap->getGroup(names[j]);
286                                 
287                                 if (group == "not found") { m->mothurOut(names[j] + " is not in your groupfile. please correct."); m->mothurOutEndLine(); exit(1); }
288                                 
289                                 itGroup = groupBins.find(group);
290                                 if(itGroup == groupBins.end()) {
291                                         groupBins[group] = names[j];  //add first name
292                                         groupNumBins[group]++;
293                                 }else{ //add another name
294                                         groupBins[group] = groupBins[group] + "," + names[j];
295                                 }
296                         }
297                         
298                         //print parsed bin info to files
299                         for (itGroup = groupBins.begin(); itGroup != groupBins.end(); itGroup++) {
300                                 groupVector[itGroup->first] +=  itGroup->second + '\t'; 
301                         }
302                 
303                 }
304                 
305                 //end list vector
306                 for (it3 = filehandles.begin(); it3 != filehandles.end(); it3++) {
307                         (*(filehandles[it3->first])) << thisList->getLabel() << '\t' << groupNumBins[it3->first] << '\t' << groupVector[it3->first] << endl;  // label numBins  listvector for that group
308                 }
309                 
310                 return 0;
311
312         }
313         catch(exception& e) {
314                 m->errorOut(e, "ParseListCommand", "parse");
315                 exit(1);
316         }
317 }
318
319 /**********************************************************************************************************************/
320
321