]> git.donarmstrong.com Git - mothur.git/blob - getrelabundcommand.cpp
fixes while testing
[mothur.git] / getrelabundcommand.cpp
1 /*
2  *  getrelabundcommand.cpp
3  *  Mothur
4  *
5  *  Created by westcott on 6/21/10.
6  *  Copyright 2010 Schloss Lab. All rights reserved.
7  *
8  */
9
10 #include "getrelabundcommand.h"
11
12 //**********************************************************************************************************************
13 vector<string> GetRelAbundCommand::getValidParameters(){        
14         try {
15                 string Array[] =  {"groups","label","scale","outputdir","inputdir"};
16                 vector<string> myArray (Array, Array+(sizeof(Array)/sizeof(string)));
17                 return myArray;
18         }
19         catch(exception& e) {
20                 m->errorOut(e, "GetRelAbundCommand", "getValidParameters");
21                 exit(1);
22         }
23 }
24 //**********************************************************************************************************************
25 GetRelAbundCommand::GetRelAbundCommand(){       
26         try {
27                 abort = true;
28                 //initialize outputTypes
29                 vector<string> tempOutNames;
30                 outputTypes["relabund"] = tempOutNames;
31         }
32         catch(exception& e) {
33                 m->errorOut(e, "GetRelAbundCommand", "GetRelAbundCommand");
34                 exit(1);
35         }
36 }
37 //**********************************************************************************************************************
38 vector<string> GetRelAbundCommand::getRequiredParameters(){     
39         try {
40                 vector<string> myArray;
41                 return myArray;
42         }
43         catch(exception& e) {
44                 m->errorOut(e, "GetRelAbundCommand", "getRequiredParameters");
45                 exit(1);
46         }
47 }
48 //**********************************************************************************************************************
49 vector<string> GetRelAbundCommand::getRequiredFiles(){  
50         try {
51                 string Array[] =  {"shared"};
52                 vector<string> myArray (Array, Array+(sizeof(Array)/sizeof(string)));
53                 return myArray;
54         }
55         catch(exception& e) {
56                 m->errorOut(e, "GetRelAbundCommand", "getRequiredFiles");
57                 exit(1);
58         }
59 }
60 //**********************************************************************************************************************
61 GetRelAbundCommand::GetRelAbundCommand(string option) {
62         try {
63                 globaldata = GlobalData::getInstance();
64                 abort = false;
65                 allLines = 1;
66                 labels.clear();
67                 
68                 //allow user to run help
69                 if(option == "help") { help(); abort = true; }
70                 
71                 else {
72                         //valid paramters for this command
73                         string AlignArray[] =  {"groups","label","scale","outputdir","inputdir"};
74                         vector<string> myArray (AlignArray, AlignArray+(sizeof(AlignArray)/sizeof(string)));
75                         
76                         OptionParser parser(option);
77                         map<string,string> parameters = parser.getParameters();
78                         
79                         ValidParameters validParameter;
80                         
81                         //check to make sure all parameters are valid for command
82                         for (map<string,string>::iterator it = parameters.begin(); it != parameters.end(); it++) { 
83                                 if (validParameter.isValidParameter(it->first, myArray, it->second) != true) {  abort = true;  }
84                         }
85                         
86                         //initialize outputTypes
87                         vector<string> tempOutNames;
88                         outputTypes["relabund"] = tempOutNames;
89                 
90                         //if the user changes the output directory command factory will send this info to us in the output parameter 
91                         outputDir = validParameter.validFile(parameters, "outputdir", false);           if (outputDir == "not found"){  
92                                 outputDir = ""; 
93                                 outputDir += m->hasPath(globaldata->inputFileName); //if user entered a file with a path then preserve it       
94                         }
95                         
96                         //make sure the user has already run the read.otu command
97                         if ((globaldata->getSharedFile() == "")) {
98                                  m->mothurOut("You must read a list and a group, or a shared file before you can use the get.relabund command."); m->mothurOutEndLine(); abort = true; 
99                         }
100
101                         //check for optional parameter and set defaults
102                         // ...at some point should added some additional type checking...
103                         label = validParameter.validFile(parameters, "label", false);                   
104                         if (label == "not found") { label = ""; }
105                         else { 
106                                 if(label != "all") {  m->splitAtDash(label, labels);  allLines = 0;  }
107                                 else { allLines = 1;  }
108                         }
109                         
110                         //if the user has not specified any labels use the ones from read.otu
111                         if (label == "") {  
112                                 allLines = globaldata->allLines; 
113                                 labels = globaldata->labels; 
114                         }
115                         
116                         groups = validParameter.validFile(parameters, "groups", false);                 
117                         if (groups == "not found") { groups = ""; pickedGroups = false; }
118                         else { 
119                                 pickedGroups = true;
120                                 m->splitAtDash(groups, Groups);
121                                 globaldata->Groups = Groups;
122                         }
123                         
124                         scale = validParameter.validFile(parameters, "scale", false);                           if (scale == "not found") { scale = "totalgroup"; }
125                         
126                         if ((scale != "totalgroup") && (scale != "totalotu") && (scale != "averagegroup") && (scale != "averageotu")) {
127                                 m->mothurOut(scale + " is not a valid scaling option for the get.relabund command. Choices are totalgroup, totalotu, averagegroup, averageotu."); m->mothurOutEndLine(); abort = true; 
128                         }
129                 }
130
131         }
132         catch(exception& e) {
133                 m->errorOut(e, "GetRelAbundCommand", "GetRelAbundCommand");
134                 exit(1);
135         }
136 }
137
138 //**********************************************************************************************************************
139
140 void GetRelAbundCommand::help(){
141         try {
142                 m->mothurOut("The get.relabund command can only be executed after a successful read.otu command of a list and group or shared file.\n");
143                 m->mothurOut("The get.relabund command parameters are groups, scale and label.  No parameters are required.\n");
144                 m->mothurOut("The groups parameter allows you to specify which of the groups in your groupfile you would like included. The group names are separated by dashes.\n");
145                 m->mothurOut("The label parameter allows you to select what distance levels you would like, and are also separated by dashes.\n");
146                 m->mothurOut("The scale parameter allows you to select what scale you would like to use. Choices are totalgroup, totalotu, averagegroup, averageotu, default is totalgroup.\n");
147                 m->mothurOut("The get.relabund command should be in the following format: get.relabund(groups=yourGroups, label=yourLabels).\n");
148                 m->mothurOut("Example get.relabund(groups=A-B-C, scale=averagegroup).\n");
149                 m->mothurOut("The default value for groups is all the groups in your groupfile, and all labels in your inputfile will be used.\n");
150                 m->mothurOut("The get.relabund command outputs a .relabund file.\n");
151                 m->mothurOut("Note: No spaces between parameter labels (i.e. groups), '=' and parameters (i.e.yourGroups).\n\n");
152
153         }
154         catch(exception& e) {
155                 m->errorOut(e, "GetRelAbundCommand", "help");
156                 exit(1);
157         }
158 }
159
160 //**********************************************************************************************************************
161
162 GetRelAbundCommand::~GetRelAbundCommand(){
163 }
164
165 //**********************************************************************************************************************
166
167 int GetRelAbundCommand::execute(){
168         try {
169         
170                 if (abort == true) { return 0; }
171                 
172                 string outputFileName = outputDir + m->getRootName(m->getSimpleName(globaldata->inputFileName)) + "relabund";
173                 ofstream out;
174                 m->openOutputFile(outputFileName, out);
175                 out.setf(ios::fixed, ios::floatfield); out.setf(ios::showpoint);
176                 
177                 read = new ReadOTUFile(globaldata->inputFileName);      
178                 read->read(&*globaldata); 
179                 input = globaldata->ginput;
180                 lookup = input->getSharedRAbundVectors();
181                 string lastLabel = lookup[0]->getLabel();
182                 
183                 //if the users enters label "0.06" and there is no "0.06" in their file use the next lowest label.
184                 set<string> processedLabels;
185                 set<string> userLabels = labels;
186
187                 //as long as you are not at the end of the file or done wih the lines you want
188                 while((lookup[0] != NULL) && ((allLines == 1) || (userLabels.size() != 0))) {
189                         
190                         if (m->control_pressed) {  outputTypes.clear();  for (int i = 0; i < lookup.size(); i++) {  delete lookup[i];  } globaldata->Groups.clear(); delete read;  out.close(); remove(outputFileName.c_str()); return 0; }
191         
192                         if(allLines == 1 || labels.count(lookup[0]->getLabel()) == 1){                  
193
194                                 m->mothurOut(lookup[0]->getLabel()); m->mothurOutEndLine();
195                                 getRelAbundance(lookup, out);
196                                 
197                                 processedLabels.insert(lookup[0]->getLabel());
198                                 userLabels.erase(lookup[0]->getLabel());
199                         }
200                         
201                         if ((m->anyLabelsToProcess(lookup[0]->getLabel(), userLabels, "") == true) && (processedLabels.count(lastLabel) != 1)) {
202                                 string saveLabel = lookup[0]->getLabel();
203                         
204                                 for (int i = 0; i < lookup.size(); i++) {  delete lookup[i];  }  
205                                 lookup = input->getSharedRAbundVectors(lastLabel);
206                                 m->mothurOut(lookup[0]->getLabel()); m->mothurOutEndLine();
207                                 
208                                 getRelAbundance(lookup, out);
209                                 
210                                 processedLabels.insert(lookup[0]->getLabel());
211                                 userLabels.erase(lookup[0]->getLabel());
212                                 
213                                 //restore real lastlabel to save below
214                                 lookup[0]->setLabel(saveLabel);
215                         }
216                         
217                         lastLabel = lookup[0]->getLabel();
218                         //prevent memory leak
219                         for (int i = 0; i < lookup.size(); i++) {  delete lookup[i]; lookup[i] = NULL; }
220                         
221                         if (m->control_pressed) {  outputTypes.clear();  globaldata->Groups.clear(); delete read;  out.close(); remove(outputFileName.c_str()); return 0; }
222
223                         //get next line to process
224                         lookup = input->getSharedRAbundVectors();                               
225                 }
226                 
227                 if (m->control_pressed) { outputTypes.clear(); globaldata->Groups.clear(); delete read;  out.close(); remove(outputFileName.c_str());  return 0; }
228
229                 //output error messages about any remaining user labels
230                 set<string>::iterator it;
231                 bool needToRun = false;
232                 for (it = userLabels.begin(); it != userLabels.end(); it++) {  
233                         m->mothurOut("Your file does not include the label " + *it); 
234                         if (processedLabels.count(lastLabel) != 1) {
235                                 m->mothurOut(". I will use " + lastLabel + "."); m->mothurOutEndLine();
236                                 needToRun = true;
237                         }else {
238                                 m->mothurOut(". Please refer to " + lastLabel + "."); m->mothurOutEndLine();
239                         }
240                 }
241         
242                 //run last label if you need to
243                 if (needToRun == true)  {
244                         for (int i = 0; i < lookup.size(); i++) { if (lookup[i] != NULL) { delete lookup[i]; } }  
245                         lookup = input->getSharedRAbundVectors(lastLabel);
246                         
247                         m->mothurOut(lookup[0]->getLabel()); m->mothurOutEndLine();
248                         
249                         getRelAbundance(lookup, out);
250                         
251                         for (int i = 0; i < lookup.size(); i++) {  delete lookup[i];  }
252                 }
253         
254                 //reset groups parameter
255                 globaldata->Groups.clear();  
256                 delete input; globaldata->ginput = NULL;
257                 delete read;
258                 out.close();
259                 
260                 if (m->control_pressed) { outputTypes.clear(); remove(outputFileName.c_str()); return 0;}
261                 
262                 m->mothurOutEndLine();
263                 m->mothurOut("Output File Names: "); m->mothurOutEndLine();
264                 m->mothurOut(outputFileName); m->mothurOutEndLine(); outputNames.push_back(outputFileName); outputTypes["relabund"].push_back(outputFileName);
265                 m->mothurOutEndLine();
266                 
267                 return 0;
268         }
269         catch(exception& e) {
270                 m->errorOut(e, "GetRelAbundCommand", "execute");
271                 exit(1);
272         }
273 }
274 //**********************************************************************************************************************
275
276 int GetRelAbundCommand::getRelAbundance(vector<SharedRAbundVector*>& thisLookUp, ofstream& out){
277         try {
278                 if (pickedGroups) { eliminateZeroOTUS(thisLookUp); }
279
280                 
281                  for (int i = 0; i < thisLookUp.size(); i++) {
282                         out << thisLookUp[i]->getLabel() << '\t' << thisLookUp[i]->getGroup() << '\t' << thisLookUp[i]->getNumBins() << '\t';
283                         
284                         for (int j = 0; j < thisLookUp[i]->getNumBins(); j++) {
285                         
286                                 if (m->control_pressed) { return 0; }
287                         
288                                 int abund = thisLookUp[i]->getAbundance(j);
289                                 
290                                 float relabund = 0.0;
291                                 
292                                 if (scale == "totalgroup") { 
293                                         relabund = abund / (float) thisLookUp[i]->getNumSeqs();
294                                 }else if (scale == "totalotu") {
295                                         //calc the total in this otu
296                                         int totalOtu = 0;
297                                         for (int l = 0; l < thisLookUp.size(); l++) {  totalOtu += thisLookUp[l]->getAbundance(j); }
298                                         relabund = abund / (float) totalOtu;
299                                 }else if (scale == "averagegroup") {
300                                         relabund = abund / (float) (thisLookUp[i]->getNumSeqs() / (float) thisLookUp[i]->getNumBins());
301                                 }else if (scale == "averageotu") {
302                                         //calc the total in this otu
303                                         int totalOtu = 0;
304                                         for (int l = 0; l < thisLookUp.size(); l++) {  totalOtu += thisLookUp[l]->getAbundance(j); }
305                                         float averageOtu = totalOtu / (float) thisLookUp.size();
306                                         
307                                         relabund = abund / (float) averageOtu;
308                                 }else{ m->mothurOut(scale + " is not a valid scaling option."); m->mothurOutEndLine(); m->control_pressed = true; return 0; }
309                                 
310                                 out << relabund << '\t';
311                         }
312                         out << endl;
313                  }
314         
315                  return 0;
316         }
317         catch(exception& e) {
318                 m->errorOut(e, "GetRelAbundCommand", "getRelAbundance");
319                 exit(1);
320         }
321 }
322 //**********************************************************************************************************************
323 int GetRelAbundCommand::eliminateZeroOTUS(vector<SharedRAbundVector*>& thislookup) {
324         try {
325                 
326                 vector<SharedRAbundVector*> newLookup;
327                 for (int i = 0; i < thislookup.size(); i++) {
328                         SharedRAbundVector* temp = new SharedRAbundVector();
329                         temp->setLabel(thislookup[i]->getLabel());
330                         temp->setGroup(thislookup[i]->getGroup());
331                         newLookup.push_back(temp);
332                 }
333                 
334                 //for each bin
335                 for (int i = 0; i < thislookup[0]->getNumBins(); i++) {
336                         if (m->control_pressed) { for (int j = 0; j < newLookup.size(); j++) {  delete newLookup[j];  } return 0; }
337                 
338                         //look at each sharedRabund and make sure they are not all zero
339                         bool allZero = true;
340                         for (int j = 0; j < thislookup.size(); j++) {
341                                 if (thislookup[j]->getAbundance(i) != 0) { allZero = false;  break;  }
342                         }
343                         
344                         //if they are not all zero add this bin
345                         if (!allZero) {
346                                 for (int j = 0; j < thislookup.size(); j++) {
347                                         newLookup[j]->push_back(thislookup[j]->getAbundance(i), thislookup[j]->getGroup());
348                                 }
349                         }
350                 }
351
352                 for (int j = 0; j < thislookup.size(); j++) {  delete thislookup[j];  }
353
354                 thislookup = newLookup;
355                 
356                 return 0;
357  
358         }
359         catch(exception& e) {
360                 m->errorOut(e, "GetRelAbundCommand", "eliminateZeroOTUS");
361                 exit(1);
362         }
363 }
364
365 //**********************************************************************************************************************
366
367