]> git.donarmstrong.com Git - mothur.git/blob - mothur.h
pat's ../ bug fix
[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 /**************************************************************************************************/
836
837 inline void mothurOutJustToLog(string message) {
838         try {
839                 ofstream out;
840                 string logFileName = "mothur.logFile";
841                 openOutputFileAppend(logFileName, out);
842                 
843                 out << message;
844                 
845                 out.close();
846         }
847         catch(exception& e) {
848                 errorOut(e, "mothur", "mothurOutJustToLog");
849                 exit(1);
850         }
851 }
852
853
854 /**************************************************************************************************/
855
856 inline void mothurOut(float num) {
857         try {
858                 ofstream out;
859                 string logFileName = "mothur.logFile";
860                 openOutputFileAppend(logFileName, out);
861                 
862                 cout << num;  
863                 out << num;
864                 
865                 out.close();
866         }
867         catch(exception& e) {
868                 cout << "Error in mothur class mothurOut float" << endl;
869                 exit(1);
870         }
871 }
872 /***********************************************************************/
873 inline void mothurOut(double value) {
874         try {
875                 ofstream out;
876                 string logFileName = "mothur.logFile";
877                 openOutputFileAppend(logFileName, out);
878                 
879                 cout << value;  
880                 out << value;
881                 
882                 out.close();
883         }
884         catch(exception& e) {
885                 cout << "Error in mothur class mothurOut double" << endl;
886                 exit(1);
887         }
888 }
889
890 /***********************************************************************/
891 //this function determines if the user has given us labels that are smaller than the given label.
892 //if so then it returns true so that the calling function can run the previous valid distance.
893 //it's a "smart" distance function.  It also checks for invalid labels.
894 inline bool anyLabelsToProcess(string label, set<string>& userLabels, string errorOff) {
895         try {
896                 set<string>::iterator it;
897                 vector<float> orderFloat;
898                 map<string, float> userMap;  //the conversion process removes trailing 0's which we need to put back
899                 map<string, float>::iterator it2;
900                 float labelFloat;
901                 bool smaller = false;
902                 
903                 //unique is the smallest line
904                 if (label == "unique") {  return false;  }
905                 else { convert(label, labelFloat); }
906                 
907                 //go through users set and make them floats
908                 for(it = userLabels.begin(); it != userLabels.end(); ++it) {
909                         
910                         float temp;
911                         if ((*it != "unique") && (convertTestFloat(*it, temp) == true)){
912                                 convert(*it, temp);
913                                 orderFloat.push_back(temp);
914                                 userMap[*it] = temp;
915                         }else if (*it == "unique") { 
916                                 orderFloat.push_back(-1.0);
917                                 userMap["unique"] = -1.0;
918                         }else {
919                                 if (errorOff == "") {  mothurOut(*it + " is not a valid label."); mothurOutEndLine();  }
920                                 userLabels.erase(*it); 
921                                 it--;
922                         }
923                 }
924                 
925                 //sort order
926                 sort(orderFloat.begin(), orderFloat.end());
927                 
928                 /*************************************************/
929                 //is this label bigger than any of the users labels
930                 /*************************************************/
931                                 
932                 //loop through order until you find a label greater than label
933                 for (int i = 0; i < orderFloat.size(); i++) {
934                         if (orderFloat[i] < labelFloat) {
935                                 smaller = true;
936                                 if (orderFloat[i] == -1) { 
937                                         if (errorOff == "") { mothurOut("Your file does not include the label unique."); mothurOutEndLine(); }
938                                         userLabels.erase("unique");
939                                 }
940                                 else {  
941                                         if (errorOff == "") { mothurOut("Your file does not include the label "); mothurOutEndLine(); }
942                                         string s = "";
943                                         for (it2 = userMap.begin(); it2!= userMap.end(); it2++) {  
944                                                 if (it2->second == orderFloat[i]) {  
945                                                         s = it2->first;  
946                                                         //remove small labels
947                                                         userLabels.erase(s);
948                                                         break;
949                                                 }
950                                         }
951                                         if (errorOff == "") { mothurOut(s + ". I will use the next smallest distance. "); mothurOutEndLine(); }
952                                 }
953                         //since they are sorted once you find a bigger one stop looking
954                         }else { break; }
955                 }
956                 
957                 return smaller;
958                                                 
959         }
960         catch(exception& e) {
961                 errorOut(e, "mothur", "anyLabelsToProcess");
962                 exit(1);
963         }
964 }
965
966 /**************************************************************************************************/
967 inline void appendFiles(string temp, string filename) {
968         try{
969                 ofstream output;
970                 ifstream input;
971         
972                 //open output file in append mode
973                 openOutputFileAppend(filename, output);
974                 openInputFile(temp, input);
975                 
976                 while(char c = input.get()){
977                         if(input.eof())         {       break;                  }
978                         else                            {       output << c;    }
979                 }
980                 
981                 input.close();
982                 output.close();
983         }
984         catch(exception& e) {
985                 errorOut(e, "mothur", "appendFiles");
986                 exit(1);
987         }
988 }
989
990 /**************************************************************************************************/
991 inline string sortFile(string distFile){
992         try {   
993                 string outfile = getRootName(distFile) + "sorted.dist";
994                 
995                 //if you can, use the unix sort since its been optimized for years
996                 #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux)
997                         string command = "sort -n -k +3 " + distFile + " -o " + outfile;
998                         system(command.c_str());
999                 #else //you are stuck with my best attempt...
1000                         //windows sort does not have a way to specify a column, only a character in the line
1001                         //since we cannot assume that the distance will always be at the the same character location on each line
1002                         //due to variable sequence name lengths, I chose to force the distance into first position, then sort and then put it back.
1003                 
1004                         //read in file line by file and put distance first
1005                         string tempDistFile = distFile + ".temp";
1006                         ifstream input;
1007                         ofstream output;
1008                         openInputFile(distFile, input);
1009                         openOutputFile(tempDistFile, output);
1010
1011                         string firstName, secondName;
1012                         float dist;
1013                         while (input) {
1014                                 input >> firstName >> secondName >> dist;
1015                                 output << dist << '\t' << firstName << '\t' << secondName << endl;
1016                                 gobble(input);
1017                         }
1018                         input.close();
1019                         output.close();
1020                 
1021         
1022                         //sort using windows sort
1023                         string tempOutfile = outfile + ".temp";
1024                         string command = "sort " + tempDistFile + " /O " + tempOutfile;
1025                         system(command.c_str());
1026                 
1027                         //read in sorted file and put distance at end again
1028                         ifstream input2;
1029                         openInputFile(tempOutfile, input2);
1030                         openOutputFile(outfile, output);
1031                 
1032                         while (input2) {
1033                                 input2 >> dist >> firstName >> secondName;
1034                                 output << firstName << '\t' << secondName << '\t' << dist << endl;
1035                                 gobble(input2);
1036                         }
1037                         input2.close();
1038                         output.close();
1039                 
1040                         //remove temp files
1041                         remove(tempDistFile.c_str());
1042                         remove(tempOutfile.c_str());
1043                 #endif
1044                 
1045                 return outfile;
1046         }
1047         catch(exception& e) {
1048                 errorOut(e, "mothur", "sortFile");
1049                 exit(1);
1050         }
1051 }
1052 /**************************************************************************************************/
1053 #endif
1054