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