]> git.donarmstrong.com Git - mothur.git/blob - mothur.h
working on chimeras
[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 #include <signal.h>
25
26
27 //exception
28 #include <stdexcept>
29 #include <exception>
30 #include <cstdlib> 
31
32
33 //containers
34 #include <vector>
35 #include <set>
36 #include <map>
37 #include <string>
38 #include <list>
39
40 //math
41 #include <cmath>
42 #include <math.h>
43 #include <algorithm>
44
45 //misc
46 #include <cerrno>
47 #include <ctime>
48 #include <limits>
49
50 /***********************************************************************/
51
52 #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux)
53         #include <sys/wait.h>
54         #include <unistd.h>
55         
56         #ifdef USE_READLINE
57                 #include <readline/readline.h>
58                 #include <readline/history.h>
59         #endif
60
61         //#include <readline/readline.h>
62         //#include <readline/history.h>
63 #else
64         #include <conio.h> //allows unbuffered screen capture from stdin
65         #include <direct.h> //get cwd
66 #endif
67
68 using namespace std;
69
70 #define exp(x) (exp((double) x))
71 #define sqrt(x) (sqrt((double) x))
72 #define log10(x) (log10((double) x))
73 #define log2(x) (log10(x)/log10(2))
74 #define isnan(x) ((x) != (x))
75 #define isinf(x) (fabs(x) == std::numeric_limits<double>::infinity())
76
77 typedef unsigned long ull;
78
79 struct IntNode {
80         int lvalue;
81         int rvalue;
82         int lcoef;
83         int rcoef;
84         IntNode* left;
85         IntNode* right;
86         
87         IntNode(int lv, int rv, IntNode* l, IntNode* r) : lvalue(lv), rvalue(rv), left(l), right(r) {};
88         IntNode() {};
89 };
90
91 struct ThreadNode {
92         int* pid;
93         IntNode* left;
94         IntNode* right;
95 };
96
97 /************************************************************/
98 struct clusterNode {
99         int numSeq;
100         int parent;
101         int smallChild; //used to make linkTable work with list and rabund. represents bin number of this cluster node
102         clusterNode(int num, int par, int kid) : numSeq(num), parent(par), smallChild(kid) {};
103 };
104 /************************************************************/
105 struct seqDist {
106         int seq1;
107         int seq2;
108         float dist;
109         seqDist() {}
110         seqDist(int s1, int s2, float d) : seq1(s1), seq2(s2), dist(d) {}
111         ~seqDist() {}
112 };
113 //********************************************************************************************************************
114 //sorts lowest to highest
115 inline bool compareSequenceDistance(seqDist left, seqDist right){
116         return (left.dist < right.dist);        
117
118 /***********************************************************************/
119
120 // snagged from http://www.parashift.com/c++-faq-lite/misc-technical-issues.html#faq-39.2
121 // works for now, but there should be a way to do it without killing the whole program
122
123 class BadConversion : public runtime_error {
124 public:
125         BadConversion(const string& s) : runtime_error(s){ }
126 };
127
128 //**********************************************************************************************************************
129
130 template<typename T>
131 inline void convert(const string& s, T& x, bool failIfLeftoverChars = true){
132         istringstream i(s);
133         char c;
134         if (!(i >> x) || (failIfLeftoverChars && i.get(c)))
135                 throw BadConversion(s);
136 }
137
138 //**********************************************************************************************************************
139
140 template<typename T>
141 inline bool convertTestFloat(const string& s, T& x, bool failIfLeftoverChars = true){
142         istringstream i(s);
143         char c;
144         if (!(i >> x) || (failIfLeftoverChars && i.get(c)))
145         {
146                 return false;
147         } 
148         return true;
149 }
150
151 //**********************************************************************************************************************
152
153 template<typename T>
154 inline bool convertTest(const string& s, T& x, bool failIfLeftoverChars = true){
155         istringstream i(s);
156         char c;
157         if (!(i >> x) || (failIfLeftoverChars && i.get(c)))
158         {
159                 cout << "unable to be converted into an integer.\n" << endl;
160                 return false;
161         } 
162         return true;
163 }
164
165 //**********************************************************************************************************************
166
167 template<typename T>
168 string toString(const T&x){
169     stringstream output;
170     output << x;
171     return output.str();
172 }
173
174 //**********************************************************************************************************************
175
176 template<typename T>
177 string toHex(const T&x){
178         stringstream output;
179         
180         output << hex << x;
181
182     return output.str();
183 }
184 //**********************************************************************************************************************
185
186 template<typename T>
187 string toString(const T&x, int i){
188         stringstream output;
189         
190         output.precision(i);
191     output << fixed << x;
192         
193     return output.str();
194 }
195 /***********************************************************************/
196
197 inline int openOutputFileAppend(string fileName, ofstream& fileHandle){
198         
199         fileHandle.open(fileName.c_str(), ios::app);
200         if(!fileHandle) {
201                 cout << "Error: Could not open " <<  fileName << endl; 
202                 return 1;
203         }
204         else {
205                 return 0;
206         }
207
208 }
209 /***********************************************************************/
210
211 inline void gobble(istream& f){
212         
213         char d;
214     while(isspace(d=f.get()))           {;}
215         f.putback(d);
216         
217 }
218 /***********************************************************************/
219
220 inline string getline(ifstream& fileHandle) {
221         try {
222         
223                 string line = "";
224                 
225                 while (!fileHandle.eof())       {
226                         //get next character
227                         char c = fileHandle.get(); 
228                         
229                         //are you at the end of the line
230                         if ((c == '\n') || (c == '\r') || (c == '\f')){  break; }       
231                         else {          line += c;              }
232                 }
233                 
234                 return line;
235                 
236         }
237         catch(exception& e) {
238                 cout << "Error in mothur function getline" << endl;
239                 exit(1);
240         }
241 }
242
243 /**************************************************************************************************/
244
245 inline void mothurOut(string message) {
246         try{
247                 ofstream out;
248                 string logFileName = "mothur.logFile";
249                 openOutputFileAppend(logFileName, out);
250                 
251                 cout << message;
252                 out << message;
253                 
254                 out.close();
255         }
256         catch(exception& e) {
257                 cout << "Error in mothur class mothurOut" << endl;
258                 exit(1);
259         }
260 }
261 /**************************************************************************************************/
262
263 inline void mothurOut(string message, string precision) {
264         try{
265                 ofstream out;
266                 string logFileName = "mothur.logFile";
267                 openOutputFileAppend(logFileName, out);
268                 
269                 cout << precision << message;
270                 out << precision << message;
271                 
272                 out.close();
273         }
274         catch(exception& e) {
275                 cout << "Error in mothur class mothurOut" << endl;
276                 exit(1);
277         }
278 }
279
280 /**************************************************************************************************/
281
282 inline void mothurOutEndLine() {
283         try {
284                 ofstream out;
285                 string logFileName = "mothur.logFile";
286                 openOutputFileAppend(logFileName, out);
287                 
288                 cout << endl;  
289                 out << endl;
290                 
291                 out.close();
292         }
293         catch(exception& e) {
294                 cout << "error in mothur mothurOutEndLine" << endl;
295                 exit(1);
296         }
297 }
298
299
300 /**************************************************************************************************/
301
302 inline void errorOut(exception& e, string object, string function) {
303         
304                 mothurOut("Error: ");
305                 mothurOut(toString(e.what()));
306                 mothurOut(" has occurred in the " + object + " class function " + function + ". Please contact Pat Schloss at mothur.bugs@gmail.com, and be sure to include the mothur.logFile with your inquiry.");
307                 mothurOutEndLine();
308         
309 }
310
311 /***********************************************************************/
312
313 inline bool isTrue(string f){
314         
315         if ((f == "TRUE") || (f == "T") || (f == "true") || (f == "t")) {       return true;    }
316         else {  return false;  }
317 }
318
319 /***********************************************************************/
320
321 inline float roundDist(float dist, int precision){
322         
323         return int(dist * precision + 0.5)/float(precision);
324         
325 }
326
327 /***********************************************************************/
328
329 inline int getNumNames(string names){
330         
331         int count = 0;
332         
333         if(names != ""){
334                 count = 1;
335                 for(int i=0;i<names.size();i++){
336                         if(names[i] == ','){
337                                 count++;
338                         }
339                 }
340         }
341         
342         return count;
343         
344 }
345
346 /**************************************************************************************************/
347
348 inline vector<vector<double> > binomial(int maxOrder){
349         
350         vector<vector<double> > binomial(maxOrder+1);
351         
352     for(int i=0;i<=maxOrder;i++){
353                 binomial[i].resize(maxOrder+1);
354                 binomial[i][0]=1;
355                 binomial[0][i]=0;
356     }
357     binomial[0][0]=1;
358         
359     binomial[1][0]=1;
360     binomial[1][1]=1;
361         
362     for(int i=2;i<=maxOrder;i++){
363                 binomial[1][i]=0;
364     }
365         
366     for(int i=2;i<=maxOrder;i++){
367                 for(int j=1;j<=maxOrder;j++){
368                         if(i==j){       binomial[i][j]=1;                                                                       }
369                         if(j>i) {       binomial[i][j]=0;                                                                       }
370                         else    {       binomial[i][j]=binomial[i-1][j-1]+binomial[i-1][j];     }
371                 }
372     }
373         
374         return binomial;
375 }
376
377 /***********************************************************************/
378
379 inline string getRootName(string longName){
380  
381         string rootName = longName;
382         
383         if(longName.find_last_of(".") != longName.npos){
384                 int pos = longName.find_last_of('.')+1;
385                 rootName = longName.substr(0, pos);
386         }
387
388         return rootName;
389 }
390 /***********************************************************************/
391
392 inline string getSimpleName(string longName){
393  
394         string simpleName = longName;
395         
396         size_t found;
397         found=longName.find_last_of("/\\");
398
399         if(found != longName.npos){
400                 simpleName = longName.substr(found+1);
401         }
402         
403                 //if(longName.find_last_of("/") != longName.npos){
404                 //      int pos = longName.find_last_of('/')+1;
405                 //      simpleName = longName.substr(pos, longName.length());
406                 //}
407         
408         return simpleName;
409 }
410
411 /***********************************************************************/
412
413 inline int factorial(int num){
414         int total = 1;
415         
416         for (int i = 1; i <= num; i++) {
417                 total *= i;
418         }
419         
420         return total;
421 }
422 /**************************************************************************************************
423
424 double min(double x, double y)
425 {
426     if(x<y){    return x;    }
427     else   {    return y;    }
428 }
429
430 /***********************************************************************/
431
432 inline string getPathName(string longName){
433  
434         string rootPathName = longName;
435         
436         if(longName.find_last_of("/\\") != longName.npos){
437                 int pos = longName.find_last_of("/\\")+1;
438                 rootPathName = longName.substr(0, pos);
439         }
440         
441         return rootPathName;
442 }
443 /***********************************************************************/
444
445 inline string hasPath(string longName){
446         
447         string path = "";
448         
449         size_t found;
450         found=longName.find_last_of("/\\");
451
452         if(found != longName.npos){
453                 path = longName.substr(0, found+1);
454         }
455         
456         return path;
457 }
458
459 /***********************************************************************/
460
461 inline string getExtension(string longName){
462         
463         string extension = longName;
464         
465         if(longName.find_last_of('.') != longName.npos){
466                 int pos = longName.find_last_of('.');
467                 extension = longName.substr(pos, longName.length());
468         }
469         
470         return extension;
471 }
472 /***********************************************************************/
473 inline bool isBlank(string fileName){
474         
475         ifstream fileHandle;
476         fileHandle.open(fileName.c_str());
477         if(!fileHandle) {
478                 mothurOut("Error: Could not open " + fileName);  mothurOutEndLine();
479                 return false;
480         }else {
481                 //check for blank file
482                 gobble(fileHandle);
483                 if (fileHandle.eof()) { fileHandle.close(); return true;  }
484         }
485         return false;
486 }
487 /***********************************************************************/
488
489 inline string getFullPathName(string fileName){
490         try{
491         string path = hasPath(fileName);
492         string newFileName;
493         int pos;
494         
495         if (path == "") { return fileName; } //its a simple name
496         else { //we need to complete the pathname
497                 // ex. ../../../filename 
498                 // cwd = /user/work/desktop
499                                 
500                 string cwd;
501                 //get current working directory 
502                 #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux)   
503                         if (path.rfind("./") == -1) { return fileName; } //already complete name
504                         else { newFileName = fileName.substr(fileName.rfind("./")+2); } //save the complete part of the name
505                         
506                         char* cwdpath = new char[1024];
507
508                         size_t size;
509                         cwdpath=getcwd(cwdpath,size);
510                 
511                         cwd = cwdpath;
512                         
513                         //rip off first '/'
514                         string simpleCWD;
515                         if (cwd.length() > 0) { simpleCWD = cwd.substr(1); }
516                         
517                         //break apart the current working directory
518                         vector<string> dirs;
519                         while (simpleCWD.find_first_of('/') != -1) {
520                                 string dir = simpleCWD.substr(0,simpleCWD.find_first_of('/'));
521                                 simpleCWD = simpleCWD.substr(simpleCWD.find_first_of('/')+1, simpleCWD.length());
522                                 dirs.push_back(dir);
523                         }
524                         //get last one              // ex. ../../../filename = /user/work/desktop/filename
525                         dirs.push_back(simpleCWD);  //ex. dirs[0] = user, dirs[1] = work, dirs[2] = desktop
526                         
527                 
528                         int index = dirs.size()-1;
529                 
530                         while((pos = path.rfind("./")) != -1) { //while you don't have a complete path
531                                 if (path[(pos-1)] == '.') { //you want your parent directory ../
532                                         path = path.substr(0, pos-1);
533                                         index--;
534                                         if (index == 0) {  break; }
535                                 }else if (path[(pos-1)] == '/') { //you want the current working dir ./
536                                         path = path.substr(0, pos);
537                                 }else if (pos == 1) { break; 
538                                 }else {  mothurOut("cannot resolve path for " + fileName); mothurOutEndLine(); return fileName; }
539                         }
540                 
541                         for (int i = index; i >= 0; i--) {
542                                 newFileName = dirs[i] +  "/" + newFileName;             
543                         }
544                         
545                         newFileName =  "/" +  newFileName;
546                         return newFileName;
547                                 
548                 #else
549                         if (path.rfind(".\\") == -1) { return fileName; } //already complete name
550                         else { newFileName = fileName.substr(fileName.rfind(".\\")+2); } //save the complete part of the name
551                                                 
552                         char *cwdpath = NULL;
553                         cwdpath = getcwd(NULL, 0); // or _getcwd
554                         if ( cwdpath != NULL) { cwd = cwdpath; }
555                         else { cwd = "";  }
556                         
557                         //break apart the current working directory
558                         vector<string> dirs;
559                         while (cwd.find_first_of('\\') != -1) {
560                                 string dir = cwd.substr(0,cwd.find_first_of('\\'));
561                                 cwd = cwd.substr(cwd.find_first_of('\\')+1, cwd.length());
562                                 dirs.push_back(dir);
563         
564                         }
565                         //get last one
566                         dirs.push_back(cwd);  //ex. dirs[0] = user, dirs[1] = work, dirs[2] = desktop
567                                 
568                         int index = dirs.size()-1;
569                                 
570                         while((pos = path.rfind(".\\")) != -1) { //while you don't have a complete path
571                                 if (path[(pos-1)] == '.') { //you want your parent directory ../
572                                         path = path.substr(0, pos-1);
573                                         index--;
574                                         if (index == 0) {  break; }
575                                 }else if (path[(pos-1)] == '\\') { //you want the current working dir ./
576                                         path = path.substr(0, pos);
577                                 }else if (pos == 1) { break; 
578                                 }else {  mothurOut("cannot resolve path for " + fileName); mothurOutEndLine(); return fileName; }
579                         }
580                 
581                         for (int i = index; i >= 0; i--) {
582                                 newFileName = dirs[i] +  "\\" + newFileName;            
583                         }
584                         
585                         return newFileName;
586                         
587                 #endif
588         }
589         }
590         catch(exception& e) {
591                 errorOut(e, "getFullPathName", "getFullPathName");
592                 exit(1);
593         }
594         
595         
596 }
597 /***********************************************************************/
598
599 inline int openInputFile(string fileName, ifstream& fileHandle, string m){
600         
601         //get full path name
602         string completeFileName = getFullPathName(fileName);
603
604         fileHandle.open(completeFileName.c_str());
605         if(!fileHandle) {
606                 return 1;
607         }else {
608                 //check for blank file
609                 gobble(fileHandle);
610                 return 0;
611         }       
612 }
613 /***********************************************************************/
614
615 inline int openInputFile(string fileName, ifstream& fileHandle){
616         //get full path name
617         string completeFileName = getFullPathName(fileName);
618
619         fileHandle.open(completeFileName.c_str());
620         if(!fileHandle) {
621                 mothurOut("Error: Could not open " + completeFileName);  mothurOutEndLine();
622                 return 1;
623         }
624         else {
625                 //check for blank file
626                 gobble(fileHandle);
627                 if (fileHandle.eof()) { mothurOut(completeFileName + " is blank. Please correct."); mothurOutEndLine();  return 1;  }
628                 
629                 return 0;
630         }
631         
632 }
633 /***********************************************************************/
634
635 inline int renameFile(string oldName, string newName){
636         
637         ifstream inTest;
638         int exist = openInputFile(newName, inTest, "");
639         
640 #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux)           
641         if (exist == 0) { //you could open it so you want to delete it
642                 inTest.close();
643                 string command = "rm " + newName;
644                 system(command.c_str());
645         }
646                         
647         string command = "mv " + oldName + " " + newName;
648         system(command.c_str());
649 #else
650         remove(newName.c_str());
651         int renameOk = rename(oldName.c_str(), newName.c_str());
652 #endif
653         return 0;
654 }
655
656 /***********************************************************************/
657
658 inline int openOutputFile(string fileName, ofstream& fileHandle){
659
660         string completeFileName = getFullPathName(fileName);
661         
662         fileHandle.open(completeFileName.c_str(), ios::trunc);
663         if(!fileHandle) {
664                 mothurOut("Error: Could not open " + completeFileName);  mothurOutEndLine();
665                 return 1;
666         }
667         else {
668                 return 0;
669         }
670
671 }
672
673 /***********************************************************************/
674
675 inline int getNumSeqs(ifstream& file){
676         
677         int numSeqs = count(istreambuf_iterator<char>(file),istreambuf_iterator<char>(), '>');
678         file.seekg(0);
679         return numSeqs;
680
681 }
682 /***********************************************************************/
683
684 inline bool inVector(string member, vector<string> group){
685         
686         for (int i = 0; i < group.size(); i++) {
687                 if (group[i] == member) {  return true;         }
688         }
689         
690         return false;
691 }
692 /***********************************************************************/
693
694 //This function parses the estimator options and puts them in a vector
695 inline void splitAtDash(string& estim, vector<string>& container) {
696         try {
697                 string individual;
698                 
699                 while (estim.find_first_of('-') != -1) {
700                         individual = estim.substr(0,estim.find_first_of('-'));
701                         if ((estim.find_first_of('-')+1) <= estim.length()) { //checks to make sure you don't have dash at end of string
702                                 estim = estim.substr(estim.find_first_of('-')+1, estim.length());
703                                 container.push_back(individual);
704                         }
705                 }
706                 //get last one
707                 container.push_back(estim);
708         }
709         catch(exception& e) {
710                 errorOut(e, "mothur", "splitAtDash");
711                 exit(1);
712         }
713 }
714
715 /***********************************************************************/
716 //This function parses the label options and puts them in a set
717 inline void splitAtDash(string& estim, set<string>& container) {
718         try {
719                 string individual;
720                 
721                 while (estim.find_first_of('-') != -1) {
722                         individual = estim.substr(0,estim.find_first_of('-'));
723                         if ((estim.find_first_of('-')+1) <= estim.length()) { //checks to make sure you don't have dash at end of string
724                                 estim = estim.substr(estim.find_first_of('-')+1, estim.length());
725                                 container.insert(individual);
726                         }
727                 }
728                 //get last one
729                 container.insert(estim);
730         }
731         catch(exception& e) {
732                 errorOut(e, "mothur", "splitAtDash");
733                 exit(1);
734         }
735 }
736 /***********************************************************************/
737 //This function parses the line options and puts them in a set
738 inline void splitAtDash(string& estim, set<int>& container) {
739         try {
740                 string individual;
741                 int lineNum;
742                 
743                 while (estim.find_first_of('-') != -1) {
744                         individual = estim.substr(0,estim.find_first_of('-'));
745                         if ((estim.find_first_of('-')+1) <= estim.length()) { //checks to make sure you don't have dash at end of string
746                                 estim = estim.substr(estim.find_first_of('-')+1, estim.length());
747                                 convert(individual, lineNum); //convert the string to int
748                                 container.insert(lineNum);
749                         }
750                 }
751                 //get last one
752                 convert(estim, lineNum); //convert the string to int
753                 container.insert(lineNum);
754         }
755         catch(exception& e) {
756                 errorOut(e, "mothur", "splitAtDash");
757                 exit(1);
758         }
759 }
760 /***********************************************************************/
761 //This function parses the a string and puts peices in a vector
762 inline void splitAtComma(string& estim, vector<string>& container) {
763         try {
764                 string individual;
765                 
766                 while (estim.find_first_of(',') != -1) {
767                         individual = estim.substr(0,estim.find_first_of(','));
768                         if ((estim.find_first_of(',')+1) <= estim.length()) { //checks to make sure you don't have comma at end of string
769                                 estim = estim.substr(estim.find_first_of(',')+1, estim.length());
770                                 container.push_back(individual);
771                         }
772                 }
773                 //get last one
774                 container.push_back(estim);
775         }
776         catch(exception& e) {
777                 errorOut(e, "mothur", "splitAtComma");
778                 exit(1);
779         }
780 }
781 /***********************************************************************/
782
783 //This function splits up the various option parameters
784 inline void splitAtComma(string& prefix, string& suffix){
785         try {
786                 prefix = suffix.substr(0,suffix.find_first_of(','));
787                 if ((suffix.find_first_of(',')+2) <= suffix.length()) {  //checks to make sure you don't have comma at end of string
788                         suffix = suffix.substr(suffix.find_first_of(',')+1, suffix.length());
789                         string space = " ";
790                         while(suffix.at(0) == ' ')
791                                 suffix = suffix.substr(1, suffix.length());
792                 }
793
794         }
795         catch(exception& e) {
796                 errorOut(e, "mothur", "splitAtComma");
797                 exit(1);
798         }
799 }
800 /***********************************************************************/
801
802 //This function separates the key value from the option value i.e. dist=96_...
803 inline void splitAtEquals(string& key, string& value){          
804         try {
805                 if(value.find_first_of('=') != -1){
806                         key = value.substr(0,value.find_first_of('='));
807                         if ((value.find_first_of('=')+1) <= value.length()) {
808                                 value = value.substr(value.find_first_of('=')+1, value.length());
809                         }
810                 }else{
811                         key = value;
812                         value = 1;
813                 }
814         }
815         catch(exception& e) {
816                 errorOut(e, "mothur", "splitAtEquals");
817                 exit(1);
818         }
819 }
820 /**************************************************************************************************/
821
822 inline bool inUsersGroups(string groupname, vector<string> Groups) {
823         try {
824                 for (int i = 0; i < Groups.size(); i++) {
825                         if (groupname == Groups[i]) { return true; }
826                 }
827                 return false;
828         }
829         catch(exception& e) {
830                 errorOut(e, "mothur", "inUsersGroups");
831                 exit(1);
832         }
833 }
834 /**************************************************************************************************/
835 //returns true if any of the strings in first vector are in second vector
836 inline bool inUsersGroups(vector<string> groupnames, vector<string> Groups) {
837         try {
838                 
839                 for (int i = 0; i < groupnames.size(); i++) {
840                         if (inUsersGroups(groupnames[i], Groups)) { return true; }
841                 }
842                 return false;
843         }
844         catch(exception& e) {
845                 errorOut(e, "mothur", "inUsersGroups");
846                 exit(1);
847         }
848 }
849
850 /**************************************************************************************************/
851
852 inline void mothurOutJustToLog(string message) {
853         try {
854                 ofstream out;
855                 string logFileName = "mothur.logFile";
856                 openOutputFileAppend(logFileName, out);
857                 
858                 out << message;
859                 
860                 out.close();
861         }
862         catch(exception& e) {
863                 errorOut(e, "mothur", "mothurOutJustToLog");
864                 exit(1);
865         }
866 }
867
868
869 /**************************************************************************************************/
870
871 inline void mothurOut(float num) {
872         try {
873                 ofstream out;
874                 string logFileName = "mothur.logFile";
875                 openOutputFileAppend(logFileName, out);
876                 
877                 cout << num;  
878                 out << num;
879                 
880                 out.close();
881         }
882         catch(exception& e) {
883                 cout << "Error in mothur class mothurOut float" << endl;
884                 exit(1);
885         }
886 }
887 /***********************************************************************/
888 inline void mothurOut(double value) {
889         try {
890                 ofstream out;
891                 string logFileName = "mothur.logFile";
892                 openOutputFileAppend(logFileName, out);
893                 
894                 cout << value;  
895                 out << value;
896                 
897                 out.close();
898         }
899         catch(exception& e) {
900                 cout << "Error in mothur class mothurOut double" << endl;
901                 exit(1);
902         }
903 }
904
905 /***********************************************************************/
906 //this function determines if the user has given us labels that are smaller than the given label.
907 //if so then it returns true so that the calling function can run the previous valid distance.
908 //it's a "smart" distance function.  It also checks for invalid labels.
909 inline bool anyLabelsToProcess(string label, set<string>& userLabels, string errorOff) {
910         try {
911                 set<string>::iterator it;
912                 vector<float> orderFloat;
913                 map<string, float> userMap;  //the conversion process removes trailing 0's which we need to put back
914                 map<string, float>::iterator it2;
915                 float labelFloat;
916                 bool smaller = false;
917                 
918                 //unique is the smallest line
919                 if (label == "unique") {  return false;  }
920                 else { convert(label, labelFloat); }
921                 
922                 //go through users set and make them floats
923                 for(it = userLabels.begin(); it != userLabels.end(); ++it) {
924                         
925                         float temp;
926                         if ((*it != "unique") && (convertTestFloat(*it, temp) == true)){
927                                 convert(*it, temp);
928                                 orderFloat.push_back(temp);
929                                 userMap[*it] = temp;
930                         }else if (*it == "unique") { 
931                                 orderFloat.push_back(-1.0);
932                                 userMap["unique"] = -1.0;
933                         }else {
934                                 if (errorOff == "") {  mothurOut(*it + " is not a valid label."); mothurOutEndLine();  }
935                                 userLabels.erase(*it); 
936                                 it--;
937                         }
938                 }
939                 
940                 //sort order
941                 sort(orderFloat.begin(), orderFloat.end());
942                 
943                 /*************************************************/
944                 //is this label bigger than any of the users labels
945                 /*************************************************/
946                                 
947                 //loop through order until you find a label greater than label
948                 for (int i = 0; i < orderFloat.size(); i++) {
949                         if (orderFloat[i] < labelFloat) {
950                                 smaller = true;
951                                 if (orderFloat[i] == -1) { 
952                                         if (errorOff == "") { mothurOut("Your file does not include the label unique."); mothurOutEndLine(); }
953                                         userLabels.erase("unique");
954                                 }
955                                 else {  
956                                         if (errorOff == "") { mothurOut("Your file does not include the label "); mothurOutEndLine(); }
957                                         string s = "";
958                                         for (it2 = userMap.begin(); it2!= userMap.end(); it2++) {  
959                                                 if (it2->second == orderFloat[i]) {  
960                                                         s = it2->first;  
961                                                         //remove small labels
962                                                         userLabels.erase(s);
963                                                         break;
964                                                 }
965                                         }
966                                         if (errorOff == "") { mothurOut(s + ". I will use the next smallest distance. "); mothurOutEndLine(); }
967                                 }
968                         //since they are sorted once you find a bigger one stop looking
969                         }else { break; }
970                 }
971                 
972                 return smaller;
973                                                 
974         }
975         catch(exception& e) {
976                 errorOut(e, "mothur", "anyLabelsToProcess");
977                 exit(1);
978         }
979 }
980
981 /**************************************************************************************************/
982 inline void appendFiles(string temp, string filename) {
983         try{
984                 ofstream output;
985                 ifstream input;
986         
987                 //open output file in append mode
988                 openOutputFileAppend(filename, output);
989                 openInputFile(temp, input);
990                 
991                 while(char c = input.get()){
992                         if(input.eof())         {       break;                  }
993                         else                            {       output << c;    }
994                 }
995                 
996                 input.close();
997                 output.close();
998         }
999         catch(exception& e) {
1000                 errorOut(e, "mothur", "appendFiles");
1001                 exit(1);
1002         }
1003 }
1004
1005 /**************************************************************************************************/
1006 inline string sortFile(string distFile){
1007         try {   
1008                 string outfile = getRootName(distFile) + "sorted.dist";
1009                 
1010                 //if you can, use the unix sort since its been optimized for years
1011                 #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux)
1012                         string command = "sort -n -k +3 " + distFile + " -o " + outfile;
1013                         system(command.c_str());
1014                 #else //you are stuck with my best attempt...
1015                         //windows sort does not have a way to specify a column, only a character in the line
1016                         //since we cannot assume that the distance will always be at the the same character location on each line
1017                         //due to variable sequence name lengths, I chose to force the distance into first position, then sort and then put it back.
1018                 
1019                         //read in file line by file and put distance first
1020                         string tempDistFile = distFile + ".temp";
1021                         ifstream input;
1022                         ofstream output;
1023                         openInputFile(distFile, input);
1024                         openOutputFile(tempDistFile, output);
1025
1026                         string firstName, secondName;
1027                         float dist;
1028                         while (input) {
1029                                 input >> firstName >> secondName >> dist;
1030                                 output << dist << '\t' << firstName << '\t' << secondName << endl;
1031                                 gobble(input);
1032                         }
1033                         input.close();
1034                         output.close();
1035                 
1036         
1037                         //sort using windows sort
1038                         string tempOutfile = outfile + ".temp";
1039                         string command = "sort " + tempDistFile + " /O " + tempOutfile;
1040                         system(command.c_str());
1041                 
1042                         //read in sorted file and put distance at end again
1043                         ifstream input2;
1044                         openInputFile(tempOutfile, input2);
1045                         openOutputFile(outfile, output);
1046                 
1047                         while (input2) {
1048                                 input2 >> dist >> firstName >> secondName;
1049                                 output << firstName << '\t' << secondName << '\t' << dist << endl;
1050                                 gobble(input2);
1051                         }
1052                         input2.close();
1053                         output.close();
1054                 
1055                         //remove temp files
1056                         remove(tempDistFile.c_str());
1057                         remove(tempOutfile.c_str());
1058                 #endif
1059                 
1060                 return outfile;
1061         }
1062         catch(exception& e) {
1063                 errorOut(e, "mothur", "sortFile");
1064                 exit(1);
1065         }
1066 }
1067 /**************************************************************************************************/
1068 #endif
1069