10 * Created by Sarah Westcott on 2/19/09.
11 * Copyright 2009 Schloss Lab UMASS Amherst. All rights reserved.
15 /* This file contains all the standard incudes we use in the project as well as some common utilities. */
49 /***********************************************************************/
51 #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux)
56 #include <readline/readline.h>
57 #include <readline/history.h>
60 //#include <readline/readline.h>
61 //#include <readline/history.h>
63 #include <conio.h> //allows unbuffered screen capture from stdin
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())
76 typedef unsigned long ull;
86 IntNode(int lv, int rv, IntNode* l, IntNode* r) : lvalue(lv), rvalue(rv), left(l), right(r) {};
96 /************************************************************/
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) {};
104 /***********************************************************************/
106 // snagged from http://www.parashift.com/c++-faq-lite/misc-technical-issues.html#faq-39.2
107 // works for now, but there should be a way to do it without killing the whole program
109 class BadConversion : public runtime_error {
111 BadConversion(const string& s) : runtime_error(s){ }
114 //**********************************************************************************************************************
117 inline void convert(const string& s, T& x, bool failIfLeftoverChars = true){
120 if (!(i >> x) || (failIfLeftoverChars && i.get(c)))
121 throw BadConversion(s);
124 //**********************************************************************************************************************
127 inline bool convertTestFloat(const string& s, T& x, bool failIfLeftoverChars = true){
130 if (!(i >> x) || (failIfLeftoverChars && i.get(c)))
137 //**********************************************************************************************************************
140 inline bool convertTest(const string& s, T& x, bool failIfLeftoverChars = true){
143 if (!(i >> x) || (failIfLeftoverChars && i.get(c)))
145 cout << "unable to be converted into an integer.\n" << endl;
151 //**********************************************************************************************************************
154 string toString(const T&x){
160 //**********************************************************************************************************************
163 string toHex(const T&x){
170 //**********************************************************************************************************************
173 string toString(const T&x, int i){
177 output << fixed << x;
181 /***********************************************************************/
183 inline int openOutputFileAppend(string fileName, ofstream& fileHandle){
185 fileHandle.open(fileName.c_str(), ios::app);
187 cout << "Error: Could not open " << fileName << endl;
195 /***********************************************************************/
197 inline void gobble(istream& f){
200 while(isspace(d=f.get())) {;}
204 /***********************************************************************/
206 inline string getline(ifstream& fileHandle) {
211 while (!fileHandle.eof()) {
213 char c = fileHandle.get();
215 //are you at the end of the line
216 if ((c == '\n') || (c == '\r') || (c == '\f')){ break; }
223 catch(exception& e) {
224 cout << "Error in mothur function getline" << endl;
229 /**************************************************************************************************/
231 inline void mothurOut(string message) {
234 string logFileName = "mothur.logFile";
235 openOutputFileAppend(logFileName, out);
242 catch(exception& e) {
243 cout << "Error in mothur class mothurOut" << endl;
247 /**************************************************************************************************/
249 inline void mothurOut(string message, string precision) {
252 string logFileName = "mothur.logFile";
253 openOutputFileAppend(logFileName, out);
255 cout << precision << message;
256 out << precision << message;
260 catch(exception& e) {
261 cout << "Error in mothur class mothurOut" << endl;
266 /**************************************************************************************************/
268 inline void mothurOutEndLine() {
271 string logFileName = "mothur.logFile";
272 openOutputFileAppend(logFileName, out);
279 catch(exception& e) {
280 cout << "error in mothur mothurOutEndLine" << endl;
286 /**************************************************************************************************/
288 inline void errorOut(exception& e, string object, string function) {
290 mothurOut("Error: ");
291 mothurOut(toString(e.what()));
292 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.");
297 /***********************************************************************/
299 inline bool isTrue(string f){
301 if ((f == "TRUE") || (f == "T") || (f == "true") || (f == "t")) { return true; }
302 else { return false; }
305 /***********************************************************************/
307 inline float roundDist(float dist, int precision){
309 return int(dist * precision + 0.5)/float(precision);
313 /***********************************************************************/
315 inline int getNumNames(string names){
321 for(int i=0;i<names.size();i++){
332 /**************************************************************************************************/
334 inline vector<vector<double> > binomial(int maxOrder){
336 vector<vector<double> > binomial(maxOrder+1);
338 for(int i=0;i<=maxOrder;i++){
339 binomial[i].resize(maxOrder+1);
348 for(int i=2;i<=maxOrder;i++){
352 for(int i=2;i<=maxOrder;i++){
353 for(int j=1;j<=maxOrder;j++){
354 if(i==j){ binomial[i][j]=1; }
355 if(j>i) { binomial[i][j]=0; }
356 else { binomial[i][j]=binomial[i-1][j-1]+binomial[i-1][j]; }
363 /***********************************************************************/
365 inline string getRootName(string longName){
367 string rootName = longName;
369 if(longName.find_last_of(".") != longName.npos){
370 int pos = longName.find_last_of('.')+1;
371 rootName = longName.substr(0, pos);
376 /***********************************************************************/
378 inline string getSimpleName(string longName){
380 string simpleName = longName;
382 if(longName.find_last_of("/") != longName.npos){
383 int pos = longName.find_last_of('/')+1;
384 simpleName = longName.substr(pos, longName.length());
390 /***********************************************************************/
392 inline int factorial(int num){
395 for (int i = 1; i <= num; i++) {
401 /**************************************************************************************************
403 double min(double x, double y)
409 /***********************************************************************/
411 inline string getPathName(string longName){
413 string rootPathName = longName;
415 if(longName.find_last_of('/') != longName.npos){
416 int pos = longName.find_last_of('/')+1;
417 rootPathName = longName.substr(0, pos);
423 /***********************************************************************/
425 inline string getExtension(string longName){
427 string extension = longName;
429 if(longName.find_last_of('.') != longName.npos){
430 int pos = longName.find_last_of('.');
431 extension = longName.substr(pos, longName.length());
436 /***********************************************************************/
437 inline bool isBlank(string fileName){
440 fileHandle.open(fileName.c_str());
442 mothurOut("Error: Could not open " + fileName); mothurOutEndLine();
445 //check for blank file
447 if (fileHandle.eof()) { fileHandle.close(); return true; }
451 /***********************************************************************/
453 inline int openInputFile(string fileName, ifstream& fileHandle){
455 fileHandle.open(fileName.c_str());
457 mothurOut("Error: Could not open " + fileName); mothurOutEndLine();
461 //check for blank file
463 if (fileHandle.eof()) { mothurOut(fileName + " is blank. Please correct."); mothurOutEndLine(); return 1; }
470 /***********************************************************************/
472 inline int openOutputFile(string fileName, ofstream& fileHandle){
474 fileHandle.open(fileName.c_str(), ios::trunc);
476 mothurOut("Error: Could not open " + fileName); mothurOutEndLine();
485 /***********************************************************************/
487 inline int getNumSeqs(ifstream& file){
489 int numSeqs = count(istreambuf_iterator<char>(file),istreambuf_iterator<char>(), '>');
494 /***********************************************************************/
496 inline bool inVector(string member, vector<string> group){
498 for (int i = 0; i < group.size(); i++) {
499 if (group[i] == member) { return true; }
504 /***********************************************************************/
506 //This function parses the estimator options and puts them in a vector
507 inline void splitAtDash(string& estim, vector<string>& container) {
511 while (estim.find_first_of('-') != -1) {
512 individual = estim.substr(0,estim.find_first_of('-'));
513 if ((estim.find_first_of('-')+1) <= estim.length()) { //checks to make sure you don't have dash at end of string
514 estim = estim.substr(estim.find_first_of('-')+1, estim.length());
515 container.push_back(individual);
519 container.push_back(estim);
521 catch(exception& e) {
522 errorOut(e, "mothur", "splitAtDash");
527 /***********************************************************************/
528 //This function parses the label options and puts them in a set
529 inline void splitAtDash(string& estim, set<string>& container) {
533 while (estim.find_first_of('-') != -1) {
534 individual = estim.substr(0,estim.find_first_of('-'));
535 if ((estim.find_first_of('-')+1) <= estim.length()) { //checks to make sure you don't have dash at end of string
536 estim = estim.substr(estim.find_first_of('-')+1, estim.length());
537 container.insert(individual);
541 container.insert(estim);
543 catch(exception& e) {
544 errorOut(e, "mothur", "splitAtDash");
548 /***********************************************************************/
549 //This function parses the line options and puts them in a set
550 inline void splitAtDash(string& estim, set<int>& container) {
555 while (estim.find_first_of('-') != -1) {
556 individual = estim.substr(0,estim.find_first_of('-'));
557 if ((estim.find_first_of('-')+1) <= estim.length()) { //checks to make sure you don't have dash at end of string
558 estim = estim.substr(estim.find_first_of('-')+1, estim.length());
559 convert(individual, lineNum); //convert the string to int
560 container.insert(lineNum);
564 convert(estim, lineNum); //convert the string to int
565 container.insert(lineNum);
567 catch(exception& e) {
568 errorOut(e, "mothur", "splitAtDash");
572 /***********************************************************************/
573 //This function parses the a string and puts peices in a vector
574 inline void splitAtComma(string& estim, vector<string>& container) {
578 while (estim.find_first_of(',') != -1) {
579 individual = estim.substr(0,estim.find_first_of(','));
580 if ((estim.find_first_of(',')+1) <= estim.length()) { //checks to make sure you don't have comma at end of string
581 estim = estim.substr(estim.find_first_of(',')+1, estim.length());
582 container.push_back(individual);
586 container.push_back(estim);
588 catch(exception& e) {
589 errorOut(e, "mothur", "splitAtComma");
593 /***********************************************************************/
595 //This function splits up the various option parameters
596 inline void splitAtComma(string& prefix, string& suffix){
598 prefix = suffix.substr(0,suffix.find_first_of(','));
599 if ((suffix.find_first_of(',')+2) <= suffix.length()) { //checks to make sure you don't have comma at end of string
600 suffix = suffix.substr(suffix.find_first_of(',')+1, suffix.length());
602 while(suffix.at(0) == ' ')
603 suffix = suffix.substr(1, suffix.length());
607 catch(exception& e) {
608 errorOut(e, "mothur", "splitAtComma");
612 /***********************************************************************/
614 //This function separates the key value from the option value i.e. dist=96_...
615 inline void splitAtEquals(string& key, string& value){
617 if(value.find_first_of('=') != -1){
618 key = value.substr(0,value.find_first_of('='));
619 if ((value.find_first_of('=')+1) <= value.length()) {
620 value = value.substr(value.find_first_of('=')+1, value.length());
627 catch(exception& e) {
628 errorOut(e, "mothur", "splitAtEquals");
632 /**************************************************************************************************/
634 inline bool inUsersGroups(string groupname, vector<string> Groups) {
636 for (int i = 0; i < Groups.size(); i++) {
637 if (groupname == Groups[i]) { return true; }
641 catch(exception& e) {
642 errorOut(e, "mothur", "inUsersGroups");
647 /**************************************************************************************************/
649 inline void mothurOutJustToLog(string message) {
652 string logFileName = "mothur.logFile";
653 openOutputFileAppend(logFileName, out);
659 catch(exception& e) {
660 errorOut(e, "mothur", "mothurOutJustToLog");
666 /**************************************************************************************************/
668 inline void mothurOut(float num) {
671 string logFileName = "mothur.logFile";
672 openOutputFileAppend(logFileName, out);
679 catch(exception& e) {
680 cout << "Error in mothur class mothurOut float" << endl;
684 /***********************************************************************/
685 inline void mothurOut(double value) {
688 string logFileName = "mothur.logFile";
689 openOutputFileAppend(logFileName, out);
696 catch(exception& e) {
697 cout << "Error in mothur class mothurOut double" << endl;
702 /***********************************************************************/
703 //this function determines if the user has given us labels that are smaller than the given label.
704 //if so then it returns true so that the calling function can run the previous valid distance.
705 //it's a "smart" distance function. It also checks for invalid labels.
706 inline bool anyLabelsToProcess(string label, set<string>& userLabels, string errorOff) {
708 set<string>::iterator it;
709 vector<float> orderFloat;
710 map<string, float> userMap; //the conversion process removes trailing 0's which we need to put back
711 map<string, float>::iterator it2;
713 bool smaller = false;
715 //unique is the smallest line
716 if (label == "unique") { return false; }
717 else { convert(label, labelFloat); }
719 //go through users set and make them floats
720 for(it = userLabels.begin(); it != userLabels.end(); ++it) {
723 if ((*it != "unique") && (convertTestFloat(*it, temp) == true)){
725 orderFloat.push_back(temp);
727 }else if (*it == "unique") {
728 orderFloat.push_back(-1.0);
729 userMap["unique"] = -1.0;
731 if (errorOff == "") { mothurOut(*it + " is not a valid label."); mothurOutEndLine(); }
732 userLabels.erase(*it);
738 sort(orderFloat.begin(), orderFloat.end());
740 /*************************************************/
741 //is this label bigger than any of the users labels
742 /*************************************************/
744 //loop through order until you find a label greater than label
745 for (int i = 0; i < orderFloat.size(); i++) {
746 if (orderFloat[i] < labelFloat) {
748 if (orderFloat[i] == -1) {
749 if (errorOff == "") { mothurOut("Your file does not include the label unique."); mothurOutEndLine(); }
750 userLabels.erase("unique");
753 if (errorOff == "") { mothurOut("Your file does not include the label "); mothurOutEndLine(); }
755 for (it2 = userMap.begin(); it2!= userMap.end(); it2++) {
756 if (it2->second == orderFloat[i]) {
758 //remove small labels
763 if (errorOff == "") { mothurOut(s + ". I will use the next smallest distance. "); mothurOutEndLine(); }
765 //since they are sorted once you find a bigger one stop looking
772 catch(exception& e) {
773 errorOut(e, "mothur", "anyLabelsToProcess");
778 /**************************************************************************************************/