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