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