]> git.donarmstrong.com Git - mothur.git/blob - mothur.h
added check for blank files in openInputFile, add check for groupfiles that contain...
[mothur.git] / mothur.h
1 #ifndef MOTHUR_H
2 #define MOTHUR_H
3
4
5
6 /*
7  *  mothur.h
8  *  Mothur
9  *
10  *  Created by Sarah Westcott on 2/19/09.
11  *  Copyright 2009 Schloss Lab UMASS Amherst. All rights reserved.
12  *
13  */
14
15 /* This file contains all the standard incudes we use in the project as well as some common utilities. */
16
17 //#include <cstddef>
18
19 //io libraries
20 #include <iostream>
21 #include <iomanip>
22 #include <fstream>
23 #include <sstream>
24
25 //exception
26 #include <stdexcept>
27 #include <exception>
28 #include <cstdlib> 
29
30
31 //containers
32 #include <vector>
33 #include <set>
34 #include <map>
35 #include <string>
36 #include <list>
37
38 //math
39 #include <cmath>
40 #include <math.h>
41 #include <algorithm>
42
43 //misc
44 #include <cerrno>
45 #include <ctime>
46 #include <limits>
47
48
49 #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux)
50         #include <sys/wait.h>
51         #include <unistd.h>
52 #endif
53
54 using namespace std;
55
56 #define exp(x) (exp((double) x))
57 #define sqrt(x) (sqrt((double) x))
58 #define log10(x) (log10((double) x))
59 #define log2(x) (log10(x)/log10(2))
60 #define isnan(x) ((x) != (x))
61 #define isinf(x) (fabs(x) == std::numeric_limits<double>::infinity())
62
63
64 typedef unsigned long ull;
65
66 struct IntNode {
67         int lvalue;
68         int rvalue;
69         int lcoef;
70         int rcoef;
71         IntNode* left;
72         IntNode* right;
73 };
74
75 struct ThreadNode {
76         int* pid;
77         IntNode* left;
78         IntNode* right;
79 };
80
81 /***********************************************************************/
82
83 // snagged from http://www.parashift.com/c++-faq-lite/misc-technical-issues.html#faq-39.2
84 // works for now, but there should be a way to do it without killing the whole program
85
86 class BadConversion : public runtime_error {
87 public:
88         BadConversion(const string& s) : runtime_error(s){ }
89 };
90
91 //**********************************************************************************************************************
92
93 template<typename T>
94 inline void convert(const string& s, T& x, bool failIfLeftoverChars = true){
95         istringstream i(s);
96         char c;
97         if (!(i >> x) || (failIfLeftoverChars && i.get(c)))
98                 throw BadConversion(s);
99 }
100
101 //**********************************************************************************************************************
102
103 template<typename T>
104 inline bool convertTestFloat(const string& s, T& x, bool failIfLeftoverChars = true){
105         istringstream i(s);
106         char c;
107         if (!(i >> x) || (failIfLeftoverChars && i.get(c)))
108         {
109                 return false;
110         } 
111         return true;
112 }
113
114 //**********************************************************************************************************************
115
116 template<typename T>
117 inline bool convertTest(const string& s, T& x, bool failIfLeftoverChars = true){
118         istringstream i(s);
119         char c;
120         if (!(i >> x) || (failIfLeftoverChars && i.get(c)))
121         {
122                 cout << "unable to be converted into an integer.\n" << endl;
123                 return false;
124         } 
125         return true;
126 }
127
128 //**********************************************************************************************************************
129
130 template<typename T>
131 string toString(const T&x){
132     stringstream output;
133     output << x;
134     return output.str();
135 }
136
137 //**********************************************************************************************************************
138
139 template<typename T>
140 string toHex(const T&x){
141         stringstream output;
142         
143         output << hex << x;
144
145     return output.str();
146 }
147 //**********************************************************************************************************************
148
149 template<typename T>
150 string toString(const T&x, int i){
151         stringstream output;
152         
153         output.precision(i);
154     output << fixed << x;
155         
156     return output.str();
157 }
158 /***********************************************************************/
159
160 inline int openOutputFileAppend(string fileName, ofstream& fileHandle){
161         
162         fileHandle.open(fileName.c_str(), ios::app);
163         if(!fileHandle) {
164                 cout << "Error: Could not open " <<  fileName << endl; 
165                 return 1;
166         }
167         else {
168                 return 0;
169         }
170
171 }
172 /***********************************************************************/
173
174 inline void gobble(istream& f){
175         
176         char d;
177     while(isspace(d=f.get()))           {;}
178         f.putback(d);
179         
180 }
181
182 /***********************************************************************/
183
184 inline string getline(ifstream& fileHandle) {
185         try {
186         
187                 string line = "";
188                 
189                 while (!fileHandle.eof())       {
190                         //get next character
191                         char c = fileHandle.get(); 
192                         
193                         //are you at the end of the line
194                         if ((c == '\n') || (c == '\r') || (c == '\f')){  break; }       
195                         else {          line += c;              }
196                 }
197                 
198                 return line;
199                 
200         }
201         catch(exception& e) {
202                 cout << "Error in mothur function getline" << endl;
203                 exit(1);
204         }
205 }
206
207 /**************************************************************************************************/
208
209 inline void mothurOut(string message) {
210         try{
211                 ofstream out;
212                 string logFileName = "mothur.logFile";
213                 openOutputFileAppend(logFileName, out);
214                 
215                 cout << message;
216                 out << message;
217                 
218                 out.close();
219         }
220         catch(exception& e) {
221                 cout << "Error in mothur class mothurOut" << endl;
222                 exit(1);
223         }
224 }
225 /**************************************************************************************************/
226
227 inline void mothurOut(string message, string precision) {
228         try{
229                 ofstream out;
230                 string logFileName = "mothur.logFile";
231                 openOutputFileAppend(logFileName, out);
232                 
233                 cout << precision << message;
234                 out << precision << message;
235                 
236                 out.close();
237         }
238         catch(exception& e) {
239                 cout << "Error in mothur class mothurOut" << endl;
240                 exit(1);
241         }
242 }
243
244 /**************************************************************************************************/
245
246 inline void mothurOutEndLine() {
247         try {
248                 ofstream out;
249                 string logFileName = "mothur.logFile";
250                 openOutputFileAppend(logFileName, out);
251                 
252                 cout << endl;  
253                 out << endl;
254                 
255                 out.close();
256         }
257         catch(exception& e) {
258                 cout << "error in mothur mothurOutEndLine" << endl;
259                 exit(1);
260         }
261 }
262
263
264 /**************************************************************************************************/
265
266 inline void errorOut(exception& e, string object, string function) {
267         
268                 mothurOut("Error: ");
269                 mothurOut(toString(e.what()));
270                 mothurOut(" has occurred in the " + object + " class function " + function + ". Please contact Pat Schloss at pschloss@umich.edu, and be sure to include the mothur.logFile with your inquiry.");
271                 mothurOutEndLine();
272         
273 }
274
275
276
277
278 /***********************************************************************/
279
280 inline bool isTrue(string f){
281         
282         if ((f == "TRUE") || (f == "T") || (f == "true") || (f == "t")) {       return true;    }
283         else {  return false;  }
284 }
285
286 /***********************************************************************/
287
288 inline float roundDist(float dist, int precision){
289         
290         return int(dist * precision + 0.5)/float(precision);
291         
292 }
293
294 /***********************************************************************/
295
296 inline int getNumNames(string names){
297         
298         int count = 0;
299         
300         if(names != ""){
301                 count = 1;
302                 for(int i=0;i<names.size();i++){
303                         if(names[i] == ','){
304                                 count++;
305                         }
306                 }
307         }
308         
309         return count;
310         
311 }
312
313 /**************************************************************************************************/
314
315 inline vector<vector<double> > binomial(int maxOrder){
316         
317         vector<vector<double> > binomial(maxOrder+1);
318         
319     for(int i=0;i<=maxOrder;i++){
320                 binomial[i].resize(maxOrder+1);
321                 binomial[i][0]=1;
322                 binomial[0][i]=0;
323     }
324     binomial[0][0]=1;
325         
326     binomial[1][0]=1;
327     binomial[1][1]=1;
328         
329     for(int i=2;i<=maxOrder;i++){
330                 binomial[1][i]=0;
331     }
332         
333     for(int i=2;i<=maxOrder;i++){
334                 for(int j=1;j<=maxOrder;j++){
335                         if(i==j){       binomial[i][j]=1;                                                                       }
336                         if(j>i) {       binomial[i][j]=0;                                                                       }
337                         else    {       binomial[i][j]=binomial[i-1][j-1]+binomial[i-1][j];     }
338                 }
339     }
340         
341         return binomial;
342 }
343
344 /***********************************************************************/
345
346 inline string getRootName(string longName){
347  
348         string rootName = longName;
349         
350         if(longName.find_last_of(".") != longName.npos){
351                 int pos = longName.find_last_of('.')+1;
352                 rootName = longName.substr(0, pos);
353         }
354
355         return rootName;
356 }
357 /***********************************************************************/
358
359 inline string getSimpleName(string longName){
360  
361         string simpleName = longName;
362         
363         if(longName.find_last_of("/") != longName.npos){
364                 int pos = longName.find_last_of('/')+1;
365                 simpleName = longName.substr(pos, longName.length());
366         }
367
368         return simpleName;
369 }
370
371 /***********************************************************************/
372
373 inline int factorial(int num){
374         int total = 1;
375         
376         for (int i = 1; i <= num; i++) {
377                 total *= i;
378         }
379         
380         return total;
381 }
382 /**************************************************************************************************
383
384 double min(double x, double y)
385 {
386     if(x<y){    return x;    }
387     else   {    return y;    }
388 }
389
390 /***********************************************************************/
391
392 inline string getPathName(string longName){
393  
394         string rootPathName = longName;
395         
396         if(longName.find_last_of('/') != longName.npos){
397                 int pos = longName.find_last_of('/')+1;
398                 rootPathName = longName.substr(0, pos);
399         }
400
401         return rootPathName;
402 }
403
404 /***********************************************************************/
405
406 inline string getExtension(string longName){
407         
408         string extension = longName;
409         
410         if(longName.find_last_of('.') != longName.npos){
411                 int pos = longName.find_last_of('.');
412                 extension = longName.substr(pos, longName.length());
413         }
414         
415         return extension;
416 }
417
418 /***********************************************************************/
419
420 inline int openInputFile(string fileName, ifstream& fileHandle){
421
422         fileHandle.open(fileName.c_str());
423         if(!fileHandle) {
424                 mothurOut("Error: Could not open " + fileName);  mothurOutEndLine();
425                 return 1;
426         }
427         else {
428                 //check for blank file
429                 gobble(fileHandle);
430                 if (fileHandle.eof()) { mothurOut(fileName + " is blank. Please correct."); mothurOutEndLine();  return 1;  }
431                 
432                 return 0;
433         }
434         
435 }
436
437 /***********************************************************************/
438
439 inline int openOutputFile(string fileName, ofstream& fileHandle){
440         
441         fileHandle.open(fileName.c_str(), ios::trunc);
442         if(!fileHandle) {
443                 mothurOut("Error: Could not open " + fileName);  mothurOutEndLine();
444                 return 1;
445         }
446         else {
447                 return 0;
448         }
449
450 }
451
452 /***********************************************************************/
453
454 inline int getNumSeqs(ifstream& file){
455         
456         int numSeqs = count(istreambuf_iterator<char>(file),istreambuf_iterator<char>(), '>');
457         file.seekg(0);
458         return numSeqs;
459
460 }
461
462 /***********************************************************************/
463
464 //This function parses the estimator options and puts them in a vector
465 inline void splitAtDash(string& estim, vector<string>& container) {
466         try {
467                 string individual;
468                 
469                 while (estim.find_first_of('-') != -1) {
470                         individual = estim.substr(0,estim.find_first_of('-'));
471                         if ((estim.find_first_of('-')+1) <= estim.length()) { //checks to make sure you don't have dash at end of string
472                                 estim = estim.substr(estim.find_first_of('-')+1, estim.length());
473                                 container.push_back(individual);
474                         }
475                 }
476                 //get last one
477                 container.push_back(estim);
478         }
479         catch(exception& e) {
480                 errorOut(e, "mothur", "splitAtDash");
481                 exit(1);
482         }
483 }
484
485 /***********************************************************************/
486 //This function parses the label options and puts them in a set
487 inline void splitAtDash(string& estim, set<string>& container) {
488         try {
489                 string individual;
490                 
491                 while (estim.find_first_of('-') != -1) {
492                         individual = estim.substr(0,estim.find_first_of('-'));
493                         if ((estim.find_first_of('-')+1) <= estim.length()) { //checks to make sure you don't have dash at end of string
494                                 estim = estim.substr(estim.find_first_of('-')+1, estim.length());
495                                 container.insert(individual);
496                         }
497                 }
498                 //get last one
499                 container.insert(estim);
500         }
501         catch(exception& e) {
502                 errorOut(e, "mothur", "splitAtDash");
503                 exit(1);
504         }
505 }
506 /***********************************************************************/
507 //This function parses the line options and puts them in a set
508 inline void splitAtDash(string& estim, set<int>& container) {
509         try {
510                 string individual;
511                 int lineNum;
512                 
513                 while (estim.find_first_of('-') != -1) {
514                         individual = estim.substr(0,estim.find_first_of('-'));
515                         if ((estim.find_first_of('-')+1) <= estim.length()) { //checks to make sure you don't have dash at end of string
516                                 estim = estim.substr(estim.find_first_of('-')+1, estim.length());
517                                 convert(individual, lineNum); //convert the string to int
518                                 container.insert(lineNum);
519                         }
520                 }
521                 //get last one
522                 convert(estim, lineNum); //convert the string to int
523                 container.insert(lineNum);
524         }
525         catch(exception& e) {
526                 errorOut(e, "mothur", "splitAtDash");
527                 exit(1);
528         }
529 }
530 /***********************************************************************/
531 //This function parses the a string and puts peices in a vector
532 inline void splitAtComma(string& estim, vector<string>& container) {
533         try {
534                 string individual;
535                 
536                 while (estim.find_first_of(',') != -1) {
537                         individual = estim.substr(0,estim.find_first_of(','));
538                         if ((estim.find_first_of(',')+1) <= estim.length()) { //checks to make sure you don't have comma at end of string
539                                 estim = estim.substr(estim.find_first_of(',')+1, estim.length());
540                                 container.push_back(individual);
541                         }
542                 }
543                 //get last one
544                 container.push_back(estim);
545         }
546         catch(exception& e) {
547                 errorOut(e, "mothur", "splitAtComma");
548                 exit(1);
549         }
550 }
551 /***********************************************************************/
552
553 //This function splits up the various option parameters
554 inline void splitAtComma(string& prefix, string& suffix){
555         try {
556                 prefix = suffix.substr(0,suffix.find_first_of(','));
557                 if ((suffix.find_first_of(',')+2) <= suffix.length()) {  //checks to make sure you don't have comma at end of string
558                         suffix = suffix.substr(suffix.find_first_of(',')+1, suffix.length());
559                         string space = " ";
560                         while(suffix.at(0) == ' ')
561                                 suffix = suffix.substr(1, suffix.length());
562                 }
563
564         }
565         catch(exception& e) {
566                 errorOut(e, "mothur", "splitAtComma");
567                 exit(1);
568         }
569 }
570 /***********************************************************************/
571
572 //This function separates the key value from the option value i.e. dist=96_...
573 inline void splitAtEquals(string& key, string& value){          
574         try {
575                 if(value.find_first_of('=') != -1){
576                         key = value.substr(0,value.find_first_of('='));
577                         if ((value.find_first_of('=')+1) <= value.length()) {
578                                 value = value.substr(value.find_first_of('=')+1, value.length());
579                         }
580                 }else{
581                         key = value;
582                         value = 1;
583                 }
584         }
585         catch(exception& e) {
586                 errorOut(e, "mothur", "splitAtEquals");
587                 exit(1);
588         }
589 }
590 /**************************************************************************************************/
591
592 inline bool inUsersGroups(string groupname, vector<string> Groups) {
593         try {
594                 for (int i = 0; i < Groups.size(); i++) {
595                         if (groupname == Groups[i]) { return true; }
596                 }
597                 return false;
598         }
599         catch(exception& e) {
600                 errorOut(e, "mothur", "inUsersGroups");
601                 exit(1);
602         }
603 }
604
605 /**************************************************************************************************/
606
607 inline void mothurOutJustToLog(string message) {
608         try {
609                 ofstream out;
610                 string logFileName = "mothur.logFile";
611                 openOutputFileAppend(logFileName, out);
612                 
613                 out << message;
614                 
615                 out.close();
616         }
617         catch(exception& e) {
618                 errorOut(e, "mothur", "mothurOutJustToLog");
619                 exit(1);
620         }
621 }
622
623
624 /**************************************************************************************************/
625
626 inline void mothurOut(float num) {
627         try {
628                 ofstream out;
629                 string logFileName = "mothur.logFile";
630                 openOutputFileAppend(logFileName, out);
631                 
632                 cout << num;  
633                 out << num;
634                 
635                 out.close();
636         }
637         catch(exception& e) {
638                 cout << "Error in mothur class mothurOut float" << endl;
639                 exit(1);
640         }
641 }
642 /***********************************************************************/
643 inline void mothurOut(double value) {
644         try {
645                 ofstream out;
646                 string logFileName = "mothur.logFile";
647                 openOutputFileAppend(logFileName, out);
648                 
649                 cout << value;  
650                 out << value;
651                 
652                 out.close();
653         }
654         catch(exception& e) {
655                 cout << "Error in mothur class mothurOut double" << endl;
656                 exit(1);
657         }
658 }
659
660 /***********************************************************************/
661 //this function determines if the user has given us labels that are smaller than the given label.
662 //if so then it returns true so that the calling function can run the previous valid distance.
663 //it's a "smart" distance function.  It also checks for invalid labels.
664 inline bool anyLabelsToProcess(string label, set<string>& userLabels, string errorOff) {
665         try {
666                 set<string>::iterator it;
667                 vector<float> orderFloat;
668                 map<string, float> userMap;  //the conversion process removes trailing 0's which we need to put back
669                 map<string, float>::iterator it2;
670                 float labelFloat;
671                 bool smaller = false;
672                 
673                 //unique is the smallest line
674                 if (label == "unique") {  return false;  }
675                 else { convert(label, labelFloat); }
676                 
677                 //go through users set and make them floats
678                 for(it = userLabels.begin(); it != userLabels.end(); ++it) {
679                         
680                         float temp;
681                         if ((*it != "unique") && (convertTestFloat(*it, temp) == true)){
682                                 convert(*it, temp);
683                                 orderFloat.push_back(temp);
684                                 userMap[*it] = temp;
685                         }else if (*it == "unique") { 
686                                 orderFloat.push_back(-1.0);
687                                 userMap["unique"] = -1.0;
688                         }else {
689                                 if (errorOff == "") {  mothurOut(*it + " is not a valid label."); mothurOutEndLine();  }
690                                 userLabels.erase(*it); 
691                                 it--;
692                         }
693                 }
694                 
695                 //sort order
696                 sort(orderFloat.begin(), orderFloat.end());
697                 
698                 /*************************************************/
699                 //is this label bigger than any of the users labels
700                 /*************************************************/
701                                 
702                 //loop through order until you find a label greater than label
703                 for (int i = 0; i < orderFloat.size(); i++) {
704                         if (orderFloat[i] < labelFloat) {
705                                 smaller = true;
706                                 if (orderFloat[i] == -1) { 
707                                         if (errorOff == "") { mothurOut("Your file does not include the label unique."); mothurOutEndLine(); }
708                                         userLabels.erase("unique");
709                                 }
710                                 else {  
711                                         if (errorOff == "") { mothurOut("Your file does not include the label "); mothurOutEndLine(); }
712                                         string s = "";
713                                         for (it2 = userMap.begin(); it2!= userMap.end(); it2++) {  
714                                                 if (it2->second == orderFloat[i]) {  
715                                                         s = it2->first;  
716                                                         //remove small labels
717                                                         userLabels.erase(s);
718                                                         break;
719                                                 }
720                                         }
721                                         if (errorOff == "") { mothurOut(s + ". I will use the next smallest distance. "); mothurOutEndLine(); }
722                                 }
723                         //since they are sorted once you find a bigger one stop looking
724                         }else { break; }
725                 }
726                 
727                 return smaller;
728                                                 
729         }
730         catch(exception& e) {
731                 errorOut(e, "mothur", "anyLabelsToProcess");
732                 exit(1);
733         }
734 }
735
736 /**************************************************************************************************/
737 #endif
738