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