]> git.donarmstrong.com Git - mothur.git/blob - mothur.h
fixed some bugs found while testing 1.8
[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         
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;
507                         size_t size;
508                         cwdpath=getcwd(cwdpath,size);
509                         cwd = cwdpath;
510                 
511                         //rip off first '/'
512                         string simpleCWD;
513                         if (cwd.length() > 0) { simpleCWD = cwd.substr(1); }
514                         
515                         //break apart the current working directory
516                         vector<string> dirs;
517                         while (simpleCWD.find_first_of('/') != -1) {
518                                 string dir = simpleCWD.substr(0,simpleCWD.find_first_of('/'));
519                                 simpleCWD = simpleCWD.substr(simpleCWD.find_first_of('/')+1, simpleCWD.length());
520                                 dirs.push_back(dir);
521                         }
522                         //get last one              // ex. ../../../filename = /user/work/desktop/filename
523                         dirs.push_back(simpleCWD);  //ex. dirs[0] = user, dirs[1] = work, dirs[2] = desktop
524                                 
525                         int index = dirs.size()-1;
526                                 
527                         while((pos = path.rfind("./")) != -1) { //while you don't have a complete path
528                                 if (path[(pos-1)] == '.') { //you want your parent directory ../
529                                         path = path.substr(0, pos-1);
530                                         index--;
531                                         if (index == 0) {  break; }
532                                 }else if (path[(pos-1)] == '/') { //you want the current working dir ./
533                                         path = path.substr(0, pos);
534                                 }else if (pos == 1) { break; 
535                                 }else {  mothurOut("cannot resolve path for " + fileName); mothurOutEndLine(); return fileName; }
536                         }
537                 
538                         for (int i = index; i >= 0; i--) {
539                                 newFileName = dirs[i] +  "/" + newFileName;             
540                         }
541                         
542                         newFileName =  "/" +  newFileName;
543                         return newFileName;
544                                 
545                 #else
546                         if (path.rfind(".\\") == -1) { return fileName; } //already complete name
547                         else { newFileName = fileName.substr(fileName.rfind(".\\")+2); } //save the complete part of the name
548                                                 
549                         char *cwdpath = NULL;
550                         cwdpath = getcwd(NULL, 0); // or _getcwd
551                         if ( cwdpath != NULL) { cwd = cwdpath; }
552                         else { cwd = "";  }
553                         
554                         //break apart the current working directory
555                         vector<string> dirs;
556                         while (cwd.find_first_of('\\') != -1) {
557                                 string dir = cwd.substr(0,cwd.find_first_of('\\'));
558                                 cwd = cwd.substr(cwd.find_first_of('\\')+1, cwd.length());
559                                 dirs.push_back(dir);
560         
561                         }
562                         //get last one
563                         dirs.push_back(cwd);  //ex. dirs[0] = user, dirs[1] = work, dirs[2] = desktop
564                                 
565                         int index = dirs.size()-1;
566                                 
567                         while((pos = path.rfind(".\\")) != -1) { //while you don't have a complete path
568                                 if (path[(pos-1)] == '.') { //you want your parent directory ../
569                                         path = path.substr(0, pos-1);
570                                         index--;
571                                         if (index == 0) {  break; }
572                                 }else if (path[(pos-1)] == '\\') { //you want the current working dir ./
573                                         path = path.substr(0, pos);
574                                 }else if (pos == 1) { break; 
575                                 }else {  mothurOut("cannot resolve path for " + fileName); mothurOutEndLine(); return fileName; }
576                         }
577                 
578                         for (int i = index; i >= 0; i--) {
579                                 newFileName = dirs[i] +  "\\" + newFileName;            
580                         }
581                         
582                         return newFileName;
583                         
584                 #endif
585         }
586         
587 }
588 /***********************************************************************/
589
590 inline int openInputFile(string fileName, ifstream& fileHandle, string m){
591         
592         //get full path name
593         string completeFileName = getFullPathName(fileName);
594
595         fileHandle.open(completeFileName.c_str());
596         if(!fileHandle) {
597                 return 1;
598         }else {
599                 //check for blank file
600                 gobble(fileHandle);
601                 return 0;
602         }       
603 }
604 /***********************************************************************/
605
606 inline int openInputFile(string fileName, ifstream& fileHandle){
607         //get full path name
608         string completeFileName = getFullPathName(fileName);
609         
610         fileHandle.open(completeFileName.c_str());
611         if(!fileHandle) {
612                 mothurOut("Error: Could not open " + completeFileName);  mothurOutEndLine();
613                 return 1;
614         }
615         else {
616                 //check for blank file
617                 gobble(fileHandle);
618                 if (fileHandle.eof()) { mothurOut(completeFileName + " is blank. Please correct."); mothurOutEndLine();  return 1;  }
619                 
620                 return 0;
621         }
622         
623 }
624 /***********************************************************************/
625
626 inline int renameFile(string oldName, string newName){
627         
628         ifstream inTest;
629         int exist = openInputFile(newName, inTest, "");
630         
631 #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux)           
632         if (exist == 0) { //you could open it so you want to delete it
633                 inTest.close();
634                 string command = "rm " + newName;
635                 system(command.c_str());
636         }
637                         
638         string command = "mv " + oldName + " " + newName;
639         system(command.c_str());
640 #else
641         remove(newName.c_str());
642         renameOk = rename(oldName.c_str(), newName.c_str());
643 #endif
644         return 0;
645 }
646
647 /***********************************************************************/
648
649 inline int openOutputFile(string fileName, ofstream& fileHandle){
650
651         string completeFileName = getFullPathName(fileName);
652         
653         fileHandle.open(completeFileName.c_str(), ios::trunc);
654         if(!fileHandle) {
655                 mothurOut("Error: Could not open " + completeFileName);  mothurOutEndLine();
656                 return 1;
657         }
658         else {
659                 return 0;
660         }
661
662 }
663
664 /***********************************************************************/
665
666 inline int getNumSeqs(ifstream& file){
667         
668         int numSeqs = count(istreambuf_iterator<char>(file),istreambuf_iterator<char>(), '>');
669         file.seekg(0);
670         return numSeqs;
671
672 }
673 /***********************************************************************/
674
675 inline bool inVector(string member, vector<string> group){
676         
677         for (int i = 0; i < group.size(); i++) {
678                 if (group[i] == member) {  return true;         }
679         }
680         
681         return false;
682 }
683 /***********************************************************************/
684
685 //This function parses the estimator options and puts them in a vector
686 inline void splitAtDash(string& estim, vector<string>& container) {
687         try {
688                 string individual;
689                 
690                 while (estim.find_first_of('-') != -1) {
691                         individual = estim.substr(0,estim.find_first_of('-'));
692                         if ((estim.find_first_of('-')+1) <= estim.length()) { //checks to make sure you don't have dash at end of string
693                                 estim = estim.substr(estim.find_first_of('-')+1, estim.length());
694                                 container.push_back(individual);
695                         }
696                 }
697                 //get last one
698                 container.push_back(estim);
699         }
700         catch(exception& e) {
701                 errorOut(e, "mothur", "splitAtDash");
702                 exit(1);
703         }
704 }
705
706 /***********************************************************************/
707 //This function parses the label options and puts them in a set
708 inline void splitAtDash(string& estim, set<string>& container) {
709         try {
710                 string individual;
711                 
712                 while (estim.find_first_of('-') != -1) {
713                         individual = estim.substr(0,estim.find_first_of('-'));
714                         if ((estim.find_first_of('-')+1) <= estim.length()) { //checks to make sure you don't have dash at end of string
715                                 estim = estim.substr(estim.find_first_of('-')+1, estim.length());
716                                 container.insert(individual);
717                         }
718                 }
719                 //get last one
720                 container.insert(estim);
721         }
722         catch(exception& e) {
723                 errorOut(e, "mothur", "splitAtDash");
724                 exit(1);
725         }
726 }
727 /***********************************************************************/
728 //This function parses the line options and puts them in a set
729 inline void splitAtDash(string& estim, set<int>& container) {
730         try {
731                 string individual;
732                 int lineNum;
733                 
734                 while (estim.find_first_of('-') != -1) {
735                         individual = estim.substr(0,estim.find_first_of('-'));
736                         if ((estim.find_first_of('-')+1) <= estim.length()) { //checks to make sure you don't have dash at end of string
737                                 estim = estim.substr(estim.find_first_of('-')+1, estim.length());
738                                 convert(individual, lineNum); //convert the string to int
739                                 container.insert(lineNum);
740                         }
741                 }
742                 //get last one
743                 convert(estim, lineNum); //convert the string to int
744                 container.insert(lineNum);
745         }
746         catch(exception& e) {
747                 errorOut(e, "mothur", "splitAtDash");
748                 exit(1);
749         }
750 }
751 /***********************************************************************/
752 //This function parses the a string and puts peices in a vector
753 inline void splitAtComma(string& estim, vector<string>& container) {
754         try {
755                 string individual;
756                 
757                 while (estim.find_first_of(',') != -1) {
758                         individual = estim.substr(0,estim.find_first_of(','));
759                         if ((estim.find_first_of(',')+1) <= estim.length()) { //checks to make sure you don't have comma at end of string
760                                 estim = estim.substr(estim.find_first_of(',')+1, estim.length());
761                                 container.push_back(individual);
762                         }
763                 }
764                 //get last one
765                 container.push_back(estim);
766         }
767         catch(exception& e) {
768                 errorOut(e, "mothur", "splitAtComma");
769                 exit(1);
770         }
771 }
772 /***********************************************************************/
773
774 //This function splits up the various option parameters
775 inline void splitAtComma(string& prefix, string& suffix){
776         try {
777                 prefix = suffix.substr(0,suffix.find_first_of(','));
778                 if ((suffix.find_first_of(',')+2) <= suffix.length()) {  //checks to make sure you don't have comma at end of string
779                         suffix = suffix.substr(suffix.find_first_of(',')+1, suffix.length());
780                         string space = " ";
781                         while(suffix.at(0) == ' ')
782                                 suffix = suffix.substr(1, suffix.length());
783                 }
784
785         }
786         catch(exception& e) {
787                 errorOut(e, "mothur", "splitAtComma");
788                 exit(1);
789         }
790 }
791 /***********************************************************************/
792
793 //This function separates the key value from the option value i.e. dist=96_...
794 inline void splitAtEquals(string& key, string& value){          
795         try {
796                 if(value.find_first_of('=') != -1){
797                         key = value.substr(0,value.find_first_of('='));
798                         if ((value.find_first_of('=')+1) <= value.length()) {
799                                 value = value.substr(value.find_first_of('=')+1, value.length());
800                         }
801                 }else{
802                         key = value;
803                         value = 1;
804                 }
805         }
806         catch(exception& e) {
807                 errorOut(e, "mothur", "splitAtEquals");
808                 exit(1);
809         }
810 }
811 /**************************************************************************************************/
812
813 inline bool inUsersGroups(string groupname, vector<string> Groups) {
814         try {
815                 for (int i = 0; i < Groups.size(); i++) {
816                         if (groupname == Groups[i]) { return true; }
817                 }
818                 return false;
819         }
820         catch(exception& e) {
821                 errorOut(e, "mothur", "inUsersGroups");
822                 exit(1);
823         }
824 }
825
826 /**************************************************************************************************/
827
828 inline void mothurOutJustToLog(string message) {
829         try {
830                 ofstream out;
831                 string logFileName = "mothur.logFile";
832                 openOutputFileAppend(logFileName, out);
833                 
834                 out << message;
835                 
836                 out.close();
837         }
838         catch(exception& e) {
839                 errorOut(e, "mothur", "mothurOutJustToLog");
840                 exit(1);
841         }
842 }
843
844
845 /**************************************************************************************************/
846
847 inline void mothurOut(float num) {
848         try {
849                 ofstream out;
850                 string logFileName = "mothur.logFile";
851                 openOutputFileAppend(logFileName, out);
852                 
853                 cout << num;  
854                 out << num;
855                 
856                 out.close();
857         }
858         catch(exception& e) {
859                 cout << "Error in mothur class mothurOut float" << endl;
860                 exit(1);
861         }
862 }
863 /***********************************************************************/
864 inline void mothurOut(double value) {
865         try {
866                 ofstream out;
867                 string logFileName = "mothur.logFile";
868                 openOutputFileAppend(logFileName, out);
869                 
870                 cout << value;  
871                 out << value;
872                 
873                 out.close();
874         }
875         catch(exception& e) {
876                 cout << "Error in mothur class mothurOut double" << endl;
877                 exit(1);
878         }
879 }
880
881 /***********************************************************************/
882 //this function determines if the user has given us labels that are smaller than the given label.
883 //if so then it returns true so that the calling function can run the previous valid distance.
884 //it's a "smart" distance function.  It also checks for invalid labels.
885 inline bool anyLabelsToProcess(string label, set<string>& userLabels, string errorOff) {
886         try {
887                 set<string>::iterator it;
888                 vector<float> orderFloat;
889                 map<string, float> userMap;  //the conversion process removes trailing 0's which we need to put back
890                 map<string, float>::iterator it2;
891                 float labelFloat;
892                 bool smaller = false;
893                 
894                 //unique is the smallest line
895                 if (label == "unique") {  return false;  }
896                 else { convert(label, labelFloat); }
897                 
898                 //go through users set and make them floats
899                 for(it = userLabels.begin(); it != userLabels.end(); ++it) {
900                         
901                         float temp;
902                         if ((*it != "unique") && (convertTestFloat(*it, temp) == true)){
903                                 convert(*it, temp);
904                                 orderFloat.push_back(temp);
905                                 userMap[*it] = temp;
906                         }else if (*it == "unique") { 
907                                 orderFloat.push_back(-1.0);
908                                 userMap["unique"] = -1.0;
909                         }else {
910                                 if (errorOff == "") {  mothurOut(*it + " is not a valid label."); mothurOutEndLine();  }
911                                 userLabels.erase(*it); 
912                                 it--;
913                         }
914                 }
915                 
916                 //sort order
917                 sort(orderFloat.begin(), orderFloat.end());
918                 
919                 /*************************************************/
920                 //is this label bigger than any of the users labels
921                 /*************************************************/
922                                 
923                 //loop through order until you find a label greater than label
924                 for (int i = 0; i < orderFloat.size(); i++) {
925                         if (orderFloat[i] < labelFloat) {
926                                 smaller = true;
927                                 if (orderFloat[i] == -1) { 
928                                         if (errorOff == "") { mothurOut("Your file does not include the label unique."); mothurOutEndLine(); }
929                                         userLabels.erase("unique");
930                                 }
931                                 else {  
932                                         if (errorOff == "") { mothurOut("Your file does not include the label "); mothurOutEndLine(); }
933                                         string s = "";
934                                         for (it2 = userMap.begin(); it2!= userMap.end(); it2++) {  
935                                                 if (it2->second == orderFloat[i]) {  
936                                                         s = it2->first;  
937                                                         //remove small labels
938                                                         userLabels.erase(s);
939                                                         break;
940                                                 }
941                                         }
942                                         if (errorOff == "") { mothurOut(s + ". I will use the next smallest distance. "); mothurOutEndLine(); }
943                                 }
944                         //since they are sorted once you find a bigger one stop looking
945                         }else { break; }
946                 }
947                 
948                 return smaller;
949                                                 
950         }
951         catch(exception& e) {
952                 errorOut(e, "mothur", "anyLabelsToProcess");
953                 exit(1);
954         }
955 }
956
957 /**************************************************************************************************/
958 inline void appendFiles(string temp, string filename) {
959         try{
960                 ofstream output;
961                 ifstream input;
962         
963                 //open output file in append mode
964                 openOutputFileAppend(filename, output);
965                 openInputFile(temp, input);
966                 
967                 while(char c = input.get()){
968                         if(input.eof())         {       break;                  }
969                         else                            {       output << c;    }
970                 }
971                 
972                 input.close();
973                 output.close();
974         }
975         catch(exception& e) {
976                 errorOut(e, "mothur", "appendFiles");
977                 exit(1);
978         }
979 }
980
981 /**************************************************************************************************/
982 inline string sortFile(string distFile){
983         try {   
984                 string outfile = getRootName(distFile) + "sorted.dist";
985                 
986                 //if you can, use the unix sort since its been optimized for years
987                 #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux)
988                         string command = "sort -n -k +3 " + distFile + " -o " + outfile;
989                         system(command.c_str());
990                 #else //you are stuck with my best attempt...
991                         //windows sort does not have a way to specify a column, only a character in the line
992                         //since we cannot assume that the distance will always be at the the same character location on each line
993                         //due to variable sequence name lengths, I chose to force the distance into first position, then sort and then put it back.
994                 
995                         //read in file line by file and put distance first
996                         string tempDistFile = distFile + ".temp";
997                         ifstream input;
998                         ofstream output;
999                         openInputFile(distFile, input);
1000                         openOutputFile(tempDistFile, output);
1001
1002                         string firstName, secondName;
1003                         float dist;
1004                         while (input) {
1005                                 input >> firstName >> secondName >> dist;
1006                                 output << dist << '\t' << firstName << '\t' << secondName << endl;
1007                                 gobble(input);
1008                         }
1009                         input.close();
1010                         output.close();
1011                 
1012         
1013                         //sort using windows sort
1014                         string tempOutfile = outfile + ".temp";
1015                         string command = "sort " + tempDistFile + " /O " + tempOutfile;
1016                         system(command.c_str());
1017                 
1018                         //read in sorted file and put distance at end again
1019                         ifstream input2;
1020                         openInputFile(tempOutfile, input2);
1021                         openOutputFile(outfile, output);
1022                 
1023                         while (input2) {
1024                                 input2 >> dist >> firstName >> secondName;
1025                                 output << firstName << '\t' << secondName << '\t' << dist << endl;
1026                                 gobble(input2);
1027                         }
1028                         input2.close();
1029                         output.close();
1030                 
1031                         //remove temp files
1032                         remove(tempDistFile.c_str());
1033                         remove(tempOutfile.c_str());
1034                 #endif
1035                 
1036                 return outfile;
1037         }
1038         catch(exception& e) {
1039                 errorOut(e, "mothur", "sortFile");
1040                 exit(1);
1041         }
1042 }
1043 /**************************************************************************************************/
1044 #endif
1045