]> git.donarmstrong.com Git - mothur.git/blob - removeotuscommand.cpp
added getCommandInfoCommand for gui
[mothur.git] / removeotuscommand.cpp
1 /*
2  *  removeotuscommand.cpp
3  *  Mothur
4  *
5  *  Created by westcott on 11/12/10.
6  *  Copyright 2010 Schloss Lab. All rights reserved.
7  *
8  */
9
10 #include "removeotuscommand.h"
11 #include "inputdata.h"
12 #include "sharedutilities.h"
13
14 //**********************************************************************************************************************
15 vector<string> RemoveOtusCommand::setParameters(){      
16         try {
17                 CommandParameter pgroup("group", "InputTypes", "", "", "none", "none", "none",false,true); parameters.push_back(pgroup);
18                 CommandParameter plist("list", "InputTypes", "", "", "none", "none", "none",false,true); parameters.push_back(plist);
19                 CommandParameter paccnos("accnos", "InputTypes", "", "", "none", "none", "none",false,false); parameters.push_back(paccnos);
20                 CommandParameter pgroups("groups", "String", "", "", "", "", "",false,false); parameters.push_back(pgroups);
21                 CommandParameter plabel("label", "String", "", "", "", "", "",false,false); parameters.push_back(plabel);
22                 CommandParameter pinputdir("inputdir", "String", "", "", "", "", "",false,false); parameters.push_back(pinputdir);
23                 CommandParameter poutputdir("outputdir", "String", "", "", "", "", "",false,false); parameters.push_back(poutputdir);
24                 
25                 vector<string> myArray;
26                 for (int i = 0; i < parameters.size(); i++) {   myArray.push_back(parameters[i].name);          }
27                 return myArray;
28         }
29         catch(exception& e) {
30                 m->errorOut(e, "RemoveOtusCommand", "setParameters");
31                 exit(1);
32         }
33 }
34 //**********************************************************************************************************************
35 string RemoveOtusCommand::getHelpString(){      
36         try {
37                 string helpString = "";
38                 helpString += "The remove.otus command removes otus containing sequences from a specfic group or set of groups.\n";
39                 helpString += "It outputs a new list file containing the otus containing sequences NOT from in the those specified groups.\n";
40                 helpString += "The remove.otus command parameters are accnos, group, list, label and groups. The group and list parameters are required, unless you have valid current files.\n";
41                 helpString += "You must also provide an accnos containing the list of groups to get or set the groups parameter to the groups you wish to select.\n";
42                 helpString += "The groups parameter allows you to specify which of the groups in your groupfile you would like.  You can separate group names with dashes.\n";
43                 helpString += "The label parameter allows you to specify which distance you want to process.\n";
44                 helpString += "The remove.otus command should be in the following format: remove.otus(accnos=yourAccnos, list=yourListFile, group=yourGroupFile, label=yourLabel).\n";
45                 helpString += "Example remove.otus(accnos=amazon.accnos, list=amazon.fn.list, group=amazon.groups, label=0.03).\n";
46                 helpString += "or remove.otus(groups=pasture, list=amazon.fn.list, amazon.groups, label=0.03).\n";
47                 helpString += "Note: No spaces between parameter labels (i.e. list), '=' and parameters (i.e.yourListFile).\n";
48                 return helpString;
49         }
50         catch(exception& e) {
51                 m->errorOut(e, "RemoveOtusCommand", "getHelpString");
52                 exit(1);
53         }
54 }
55
56 ///**********************************************************************************************************************
57 RemoveOtusCommand::RemoveOtusCommand(){ 
58         try {
59                 abort = true; calledHelp = true; 
60                 setParameters();
61                 vector<string> tempOutNames;
62                 outputTypes["group"] = tempOutNames;
63                 outputTypes["list"] = tempOutNames;
64         }
65         catch(exception& e) {
66                 m->errorOut(e, "RemoveOtusCommand", "RemoveOtusCommand");
67                 exit(1);
68         }
69 }
70
71 //**********************************************************************************************************************
72 RemoveOtusCommand::RemoveOtusCommand(string option)  {
73         try {
74                 abort = false; calledHelp = false;   
75                 
76                 //allow user to run help
77                 if(option == "help") { help(); abort = true; calledHelp = true; }
78                 
79                 else {
80                         vector<string> myArray = setParameters();
81                         
82                         OptionParser parser(option);
83                         map<string,string> parameters = parser.getParameters();
84                         
85                         ValidParameters validParameter;
86                         map<string,string>::iterator it;
87                         
88                         //check to make sure all parameters are valid for command
89                         for (it = parameters.begin(); it != parameters.end(); it++) { 
90                                 if (validParameter.isValidParameter(it->first, myArray, it->second) != true) {  abort = true;  }
91                         }
92                         
93                         //initialize outputTypes
94                         vector<string> tempOutNames;
95                         outputTypes["group"] = tempOutNames;
96                         outputTypes["list"] = tempOutNames;
97                         
98                         
99                         //if the user changes the output directory command factory will send this info to us in the output parameter 
100                         outputDir = validParameter.validFile(parameters, "outputdir", false);           if (outputDir == "not found"){  outputDir = "";         }
101                         
102                         //if the user changes the input directory command factory will send this info to us in the output parameter 
103                         string inputDir = validParameter.validFile(parameters, "inputdir", false);              
104                         if (inputDir == "not found"){   inputDir = "";          }
105                         else {
106                                 string path;
107                                 it = parameters.find("accnos");
108                                 //user has given a template file
109                                 if(it != parameters.end()){ 
110                                         path = m->hasPath(it->second);
111                                         //if the user has not given a path then, add inputdir. else leave path alone.
112                                         if (path == "") {       parameters["accnos"] = inputDir + it->second;           }
113                                 }
114                                 
115                                 it = parameters.find("list");
116                                 //user has given a template file
117                                 if(it != parameters.end()){ 
118                                         path = m->hasPath(it->second);
119                                         //if the user has not given a path then, add inputdir. else leave path alone.
120                                         if (path == "") {       parameters["list"] = inputDir + it->second;             }
121                                 }
122                                 
123                                 it = parameters.find("group");
124                                 //user has given a template file
125                                 if(it != parameters.end()){ 
126                                         path = m->hasPath(it->second);
127                                         //if the user has not given a path then, add inputdir. else leave path alone.
128                                         if (path == "") {       parameters["group"] = inputDir + it->second;            }
129                                 }
130                         }
131                         
132                         
133                         //check for required parameters
134                         accnosfile = validParameter.validFile(parameters, "accnos", true);
135                         if (accnosfile == "not open") { abort = true; }
136                         else if (accnosfile == "not found") {  accnosfile = ""; }       
137                         
138                         groupfile = validParameter.validFile(parameters, "group", true);
139                         if (groupfile == "not open") { abort = true; }
140                         else if (groupfile == "not found") {                            
141                                 groupfile = m->getGroupFile(); 
142                                 if (groupfile != "") { m->mothurOut("Using " + groupfile + " as input file for the group parameter."); m->mothurOutEndLine(); }
143                                 else {  m->mothurOut("You have no current group file and the group parameter is required."); m->mothurOutEndLine(); abort = true; }
144                         }       
145                         
146                         listfile = validParameter.validFile(parameters, "list", true);
147                         if (listfile == "not open") { abort = true; }
148                         else if (listfile == "not found") {                             
149                                 listfile = m->getListFile(); 
150                                 if (listfile != "") { m->mothurOut("Using " + listfile + " as input file for the list parameter."); m->mothurOutEndLine(); }
151                                 else {  m->mothurOut("You have no current list file and the list parameter is required."); m->mothurOutEndLine(); abort = true; }
152                         }       
153                         
154                         groups = validParameter.validFile(parameters, "groups", false);                 
155                         if (groups == "not found") { groups = ""; }
156                         else { 
157                                 m->splitAtDash(groups, Groups);
158                         }
159                         
160                         label = validParameter.validFile(parameters, "label", false);                   
161                         if (label == "not found") { label = ""; m->mothurOut("You did not provide a label, I will use the first label in your inputfile."); m->mothurOutEndLine(); label=""; }  
162                         
163                         if ((accnosfile == "") && (Groups.size() == 0)) { m->mothurOut("You must provide an accnos file or specify groups using the groups parameter."); m->mothurOutEndLine(); abort = true; }
164                 }
165                 
166         }
167         catch(exception& e) {
168                 m->errorOut(e, "RemoveOtusCommand", "RemoveOtusCommand");
169                 exit(1);
170         }
171 }
172 //**********************************************************************************************************************
173
174 int RemoveOtusCommand::execute(){
175         try {
176                 
177                 if (abort == true) { if (calledHelp) { return 0; }  return 2;   }
178                 
179                 groupMap = new GroupMap(groupfile);
180                 groupMap->readMap();
181                 
182                 //get groups you want to remove
183                 if (accnosfile != "") { readAccnos(); }
184                 
185                 //make sure groups are valid
186                 //takes care of user setting groupNames that are invalid or setting groups=all
187                 SharedUtil* util = new SharedUtil();
188                 util->setGroups(Groups, groupMap->namesOfGroups);
189                 delete util;
190                 
191                 if (m->control_pressed) { delete groupMap; return 0; }
192                 
193                 //read through the list file keeping any otus that contain any sequence from the groups selected
194                 readListGroup();
195                 
196                 if (m->control_pressed) { for (int i = 0; i < outputNames.size(); i++) {        remove(outputNames[i].c_str()); } return 0; }
197                 
198                 if (outputNames.size() != 0) {
199                         m->mothurOutEndLine();
200                         m->mothurOut("Output File names: "); m->mothurOutEndLine();
201                         for (int i = 0; i < outputNames.size(); i++) {  m->mothurOut(outputNames[i]); m->mothurOutEndLine();    }
202                         m->mothurOutEndLine();
203                         
204                         //set fasta file as new current fastafile
205                         string current = "";
206                         itTypes = outputTypes.find("group");
207                         if (itTypes != outputTypes.end()) {
208                                 if ((itTypes->second).size() != 0) { current = (itTypes->second)[0]; m->setGroupFile(current); }
209                         }
210                         
211                         itTypes = outputTypes.find("list");
212                         if (itTypes != outputTypes.end()) {
213                                 if ((itTypes->second).size() != 0) { current = (itTypes->second)[0]; m->setListFile(current); }
214                         }
215                 }
216                 
217                 return 0;               
218         }
219         
220         catch(exception& e) {
221                 m->errorOut(e, "RemoveOtusCommand", "execute");
222                 exit(1);
223         }
224 }
225 //**********************************************************************************************************************
226 int RemoveOtusCommand::readListGroup(){
227         try {
228                 string thisOutputDir = outputDir;
229                 if (outputDir == "") {  thisOutputDir += m->hasPath(listfile);  }
230                 string outputFileName = thisOutputDir + m->getRootName(m->getSimpleName(listfile)) + "pick." + label +  m->getExtension(listfile);
231                 
232                 ofstream out;
233                 m->openOutputFile(outputFileName, out);
234                 
235                 string GroupOutputDir = outputDir;
236                 if (outputDir == "") {  GroupOutputDir += m->hasPath(groupfile);  }
237                 string outputGroupFileName = GroupOutputDir + m->getRootName(m->getSimpleName(groupfile)) + "pick." + label  + m->getExtension(groupfile);
238                 
239                 ofstream outGroup;
240                 m->openOutputFile(outputGroupFileName, outGroup);
241                 
242                 InputData* input = new InputData(listfile, "list");
243                 ListVector* list = input->getListVector();
244                 string lastLabel = list->getLabel();
245                 
246                 //using first label seen if none is provided
247                 if (label == "") { label = lastLabel; }
248                 
249                 //if the users enters label "0.06" and there is no "0.06" in their file use the next lowest label.
250                 set<string> labels; labels.insert(label);
251                 set<string> processedLabels;
252                 set<string> userLabels = labels;
253                 
254                 bool wroteSomething = false;
255                 
256                 //as long as you are not at the end of the file or done wih the lines you want
257                 while((list != NULL) && (userLabels.size() != 0)) {
258                         
259                         if (m->control_pressed) {  delete list; delete input; out.close();  outGroup.close(); remove(outputFileName.c_str());  remove(outputGroupFileName.c_str());return 0;  }
260                         
261                         if(labels.count(list->getLabel()) == 1){
262                                 processList(list, groupMap, out, outGroup, wroteSomething);
263                                 
264                                 processedLabels.insert(list->getLabel());
265                                 userLabels.erase(list->getLabel());
266                         }
267                         
268                         if ((m->anyLabelsToProcess(list->getLabel(), userLabels, "") == true) && (processedLabels.count(lastLabel) != 1)) {
269                                 string saveLabel = list->getLabel();
270                                 
271                                 delete list; 
272                                 
273                                 list = input->getListVector(lastLabel);
274                                 
275                                 processList(list, groupMap, out, outGroup, wroteSomething);
276                                 
277                                 processedLabels.insert(list->getLabel());
278                                 userLabels.erase(list->getLabel());
279                                 
280                                 //restore real lastlabel to save below
281                                 list->setLabel(saveLabel);
282                         }
283                         
284                         lastLabel = list->getLabel();
285                         
286                         delete list; list = NULL;
287                         
288                         //get next line to process
289                         list = input->getListVector();                          
290                 }
291                 
292                 
293                 if (m->control_pressed) {  if (list != NULL) { delete list; } delete input; out.close(); outGroup.close(); remove(outputFileName.c_str());  remove(outputGroupFileName.c_str()); return 0;  }
294                 
295                 //output error messages about any remaining user labels
296                 set<string>::iterator it;
297                 bool needToRun = false;
298                 for (it = userLabels.begin(); it != userLabels.end(); it++) {  
299                         m->mothurOut("Your file does not include the label " + *it); 
300                         if (processedLabels.count(lastLabel) != 1) {
301                                 m->mothurOut(". I will use " + lastLabel + "."); m->mothurOutEndLine();
302                                 needToRun = true;
303                         }else {
304                                 m->mothurOut(". Please refer to " + lastLabel + "."); m->mothurOutEndLine();
305                         }
306                 }
307                 
308                 //run last label if you need to
309                 if (needToRun == true)  {
310                         if (list != NULL) { delete list; }
311                         
312                         list = input->getListVector(lastLabel);
313                         
314                         processList(list, groupMap, out, outGroup, wroteSomething);
315                         
316                         delete list; list = NULL;
317                 }
318                 
319                 out.close();
320                 outGroup.close();
321                 
322                 if (wroteSomething == false) {  m->mothurOut("At distance " + label + " your file ONLY contains otus containing sequences from the groups you wish to remove."); m->mothurOutEndLine();  }
323                 outputTypes["list"].push_back(outputFileName); outputNames.push_back(outputFileName);
324                 outputTypes["group"].push_back(outputGroupFileName); outputNames.push_back(outputGroupFileName);
325                 
326                 return 0;
327                 
328         }
329         catch(exception& e) {
330                 m->errorOut(e, "RemoveOtusCommand", "readList");
331                 exit(1);
332         }
333 }
334 //**********************************************************************************************************************
335 int RemoveOtusCommand::processList(ListVector*& list, GroupMap*& groupMap, ofstream& out, ofstream& outGroup, bool& wroteSomething){
336         try {
337                 
338                 //make a new list vector
339                 ListVector newList;
340                 newList.setLabel(list->getLabel());
341                 
342                 int numOtus = 0;
343                 //for each bin
344                 for (int i = 0; i < list->getNumBins(); i++) {
345                         if (m->control_pressed) { return 0; }
346                         
347                         //parse out names that are in accnos file
348                         string binnames = list->get(i);
349                         
350                         bool removeBin = false;
351                         string groupFileOutput = "";
352                         
353                         //parse names
354                         string individual = "";
355                         int length = binnames.length();
356                         for(int j=0;j<length;j++){
357                                 if(binnames[j] == ','){
358                                         string group = groupMap->getGroup(individual);
359                                         if (group == "not found") { m->mothurOut("[ERROR]: " + individual + " is not in your groupfile. please correct."); m->mothurOutEndLine(); group = "NOTFOUND"; }
360                                         
361                                         if (m->inUsersGroups(group, Groups)) {  removeBin = true; break; }
362                                         groupFileOutput += individual + "\t" + group + "\n";
363                                         individual = "";        
364                                         
365                                 }
366                                 else{  individual += binnames[j];  }
367                         }
368                         
369                         if (!removeBin) { 
370                                 //get last name
371                                 string group = groupMap->getGroup(individual);
372                                 if (group == "not found") { m->mothurOut("[ERROR]: " + individual + " is not in your groupfile. please correct."); m->mothurOutEndLine(); group = "NOTFOUND"; }
373                                 
374                                 if (m->inUsersGroups(group, Groups)) {  removeBin = true; }
375                                 groupFileOutput += individual + "\t" + group + "\n";                            
376                                 
377                                 if (!removeBin) {
378                                         //if there are no sequences from the groups we want to remove in this bin add to new list, output to groupfile
379                                         newList.push_back(binnames);    
380                                         outGroup << groupFileOutput;
381                                 }else {
382                                         numOtus++;
383                                 }
384                         }else {
385                                 numOtus++;
386                         }
387                         
388                 }
389                 
390                 //print new listvector
391                 if (newList.getNumBins() != 0) {
392                         wroteSomething = true;
393                         newList.print(out);
394                 }
395                 
396                 m->mothurOut(newList.getLabel() + " - removed " + toString(numOtus) + " of the " + toString(list->getNumBins()) + " OTUs."); m->mothurOutEndLine();
397                 
398                 return 0;
399                 
400         }
401         catch(exception& e) {
402                 m->errorOut(e, "RemoveOtusCommand", "processList");
403                 exit(1);
404         }
405 }
406 //**********************************************************************************************************************
407 void RemoveOtusCommand::readAccnos(){
408         try {
409                 Groups.clear();
410                 
411                 ifstream in;
412                 m->openInputFile(accnosfile, in);
413                 string name;
414                 
415                 while(!in.eof()){
416                         in >> name;
417                         
418                         Groups.push_back(name);
419                         
420                         m->gobble(in);
421                 }
422                 in.close();             
423                 
424         }
425         catch(exception& e) {
426                 m->errorOut(e, "RemoveOtusCommand", "readAccnos");
427                 exit(1);
428         }
429 }
430 //**********************************************************************************************************************
431
432
433