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