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. */
48 #include <readline/readline.h>
49 #include <readline/history.h>
51 /***********************************************************************/
53 #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux)
57 #include <conio.h> //allows unbuffered screen capture from stdin
62 #define exp(x) (exp((double) x))
63 #define sqrt(x) (sqrt((double) x))
64 #define log10(x) (log10((double) x))
65 #define log2(x) (log10(x)/log10(2))
66 #define isnan(x) ((x) != (x))
67 #define isinf(x) (fabs(x) == std::numeric_limits<double>::infinity())
70 typedef unsigned long ull;
80 IntNode(int lv, int rv, IntNode* l, IntNode* r) : lvalue(lv), rvalue(rv), left(l), right(r) {};
90 /************************************************************/
94 int smallChild; //used to make linkTable work with list and rabund. represents bin number of this cluster node
95 clusterNode(int num, int par, int kid) : numSeq(num), parent(par), smallChild(kid) {};
98 /***********************************************************************/
100 // snagged from http://www.parashift.com/c++-faq-lite/misc-technical-issues.html#faq-39.2
101 // works for now, but there should be a way to do it without killing the whole program
103 class BadConversion : public runtime_error {
105 BadConversion(const string& s) : runtime_error(s){ }
108 //**********************************************************************************************************************
111 inline void convert(const string& s, T& x, bool failIfLeftoverChars = true){
114 if (!(i >> x) || (failIfLeftoverChars && i.get(c)))
115 throw BadConversion(s);
118 //**********************************************************************************************************************
121 inline bool convertTestFloat(const string& s, T& x, bool failIfLeftoverChars = true){
124 if (!(i >> x) || (failIfLeftoverChars && i.get(c)))
131 //**********************************************************************************************************************
134 inline bool convertTest(const string& s, T& x, bool failIfLeftoverChars = true){
137 if (!(i >> x) || (failIfLeftoverChars && i.get(c)))
139 cout << "unable to be converted into an integer.\n" << endl;
145 //**********************************************************************************************************************
148 string toString(const T&x){
154 //**********************************************************************************************************************
157 string toHex(const T&x){
164 //**********************************************************************************************************************
167 string toString(const T&x, int i){
171 output << fixed << x;
175 /***********************************************************************/
177 inline int openOutputFileAppend(string fileName, ofstream& fileHandle){
179 fileHandle.open(fileName.c_str(), ios::app);
181 cout << "Error: Could not open " << fileName << endl;
189 /***********************************************************************/
191 inline void gobble(istream& f){
194 while(isspace(d=f.get())) {;}
199 /***********************************************************************/
201 inline string getline(ifstream& fileHandle) {
206 while (!fileHandle.eof()) {
208 char c = fileHandle.get();
210 //are you at the end of the line
211 if ((c == '\n') || (c == '\r') || (c == '\f')){ break; }
218 catch(exception& e) {
219 cout << "Error in mothur function getline" << endl;
224 /**************************************************************************************************/
226 inline void mothurOut(string message) {
229 string logFileName = "mothur.logFile";
230 openOutputFileAppend(logFileName, out);
237 catch(exception& e) {
238 cout << "Error in mothur class mothurOut" << endl;
242 /**************************************************************************************************/
244 inline void mothurOut(string message, string precision) {
247 string logFileName = "mothur.logFile";
248 openOutputFileAppend(logFileName, out);
250 cout << precision << message;
251 out << precision << message;
255 catch(exception& e) {
256 cout << "Error in mothur class mothurOut" << endl;
261 /**************************************************************************************************/
263 inline void mothurOutEndLine() {
266 string logFileName = "mothur.logFile";
267 openOutputFileAppend(logFileName, out);
274 catch(exception& e) {
275 cout << "error in mothur mothurOutEndLine" << endl;
281 /**************************************************************************************************/
283 inline void errorOut(exception& e, string object, string function) {
285 mothurOut("Error: ");
286 mothurOut(toString(e.what()));
287 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.");
292 /***********************************************************************/
294 inline bool isTrue(string f){
296 if ((f == "TRUE") || (f == "T") || (f == "true") || (f == "t")) { return true; }
297 else { return false; }
300 /***********************************************************************/
302 inline float roundDist(float dist, int precision){
304 return int(dist * precision + 0.5)/float(precision);
308 /***********************************************************************/
310 inline int getNumNames(string names){
316 for(int i=0;i<names.size();i++){
327 /**************************************************************************************************/
329 inline vector<vector<double> > binomial(int maxOrder){
331 vector<vector<double> > binomial(maxOrder+1);
333 for(int i=0;i<=maxOrder;i++){
334 binomial[i].resize(maxOrder+1);
343 for(int i=2;i<=maxOrder;i++){
347 for(int i=2;i<=maxOrder;i++){
348 for(int j=1;j<=maxOrder;j++){
349 if(i==j){ binomial[i][j]=1; }
350 if(j>i) { binomial[i][j]=0; }
351 else { binomial[i][j]=binomial[i-1][j-1]+binomial[i-1][j]; }
358 /***********************************************************************/
360 inline string getRootName(string longName){
362 string rootName = longName;
364 if(longName.find_last_of(".") != longName.npos){
365 int pos = longName.find_last_of('.')+1;
366 rootName = longName.substr(0, pos);
371 /***********************************************************************/
373 inline string getSimpleName(string longName){
375 string simpleName = longName;
377 if(longName.find_last_of("/") != longName.npos){
378 int pos = longName.find_last_of('/')+1;
379 simpleName = longName.substr(pos, longName.length());
385 /***********************************************************************/
387 inline int factorial(int num){
390 for (int i = 1; i <= num; i++) {
396 /**************************************************************************************************
398 double min(double x, double y)
404 /***********************************************************************/
406 inline string getPathName(string longName){
408 string rootPathName = longName;
410 if(longName.find_last_of('/') != longName.npos){
411 int pos = longName.find_last_of('/')+1;
412 rootPathName = longName.substr(0, pos);
418 /***********************************************************************/
420 inline string getExtension(string longName){
422 string extension = longName;
424 if(longName.find_last_of('.') != longName.npos){
425 int pos = longName.find_last_of('.');
426 extension = longName.substr(pos, longName.length());
431 /***********************************************************************/
432 inline bool isBlank(string fileName){
435 fileHandle.open(fileName.c_str());
437 mothurOut("Error: Could not open " + fileName); mothurOutEndLine();
440 //check for blank file
442 if (fileHandle.eof()) { fileHandle.close(); return true; }
446 /***********************************************************************/
448 inline int openInputFile(string fileName, ifstream& fileHandle){
450 fileHandle.open(fileName.c_str());
452 mothurOut("Error: Could not open " + fileName); mothurOutEndLine();
456 //check for blank file
458 if (fileHandle.eof()) { mothurOut(fileName + " is blank. Please correct."); mothurOutEndLine(); return 1; }
465 /***********************************************************************/
467 inline int openOutputFile(string fileName, ofstream& fileHandle){
469 fileHandle.open(fileName.c_str(), ios::trunc);
471 mothurOut("Error: Could not open " + fileName); mothurOutEndLine();
480 /***********************************************************************/
482 inline int getNumSeqs(ifstream& file){
484 int numSeqs = count(istreambuf_iterator<char>(file),istreambuf_iterator<char>(), '>');
489 /***********************************************************************/
491 inline bool inVector(string member, vector<string> group){
493 for (int i = 0; i < group.size(); i++) {
494 if (group[i] == member) { return true; }
500 /***********************************************************************/
502 //This function parses the estimator options and puts them in a vector
503 inline void splitAtDash(string& estim, vector<string>& container) {
507 while (estim.find_first_of('-') != -1) {
508 individual = estim.substr(0,estim.find_first_of('-'));
509 if ((estim.find_first_of('-')+1) <= estim.length()) { //checks to make sure you don't have dash at end of string
510 estim = estim.substr(estim.find_first_of('-')+1, estim.length());
511 container.push_back(individual);
515 container.push_back(estim);
517 catch(exception& e) {
518 errorOut(e, "mothur", "splitAtDash");
523 /***********************************************************************/
524 //This function parses the label options and puts them in a set
525 inline void splitAtDash(string& estim, set<string>& container) {
529 while (estim.find_first_of('-') != -1) {
530 individual = estim.substr(0,estim.find_first_of('-'));
531 if ((estim.find_first_of('-')+1) <= estim.length()) { //checks to make sure you don't have dash at end of string
532 estim = estim.substr(estim.find_first_of('-')+1, estim.length());
533 container.insert(individual);
537 container.insert(estim);
539 catch(exception& e) {
540 errorOut(e, "mothur", "splitAtDash");
544 /***********************************************************************/
545 //This function parses the line options and puts them in a set
546 inline void splitAtDash(string& estim, set<int>& container) {
551 while (estim.find_first_of('-') != -1) {
552 individual = estim.substr(0,estim.find_first_of('-'));
553 if ((estim.find_first_of('-')+1) <= estim.length()) { //checks to make sure you don't have dash at end of string
554 estim = estim.substr(estim.find_first_of('-')+1, estim.length());
555 convert(individual, lineNum); //convert the string to int
556 container.insert(lineNum);
560 convert(estim, lineNum); //convert the string to int
561 container.insert(lineNum);
563 catch(exception& e) {
564 errorOut(e, "mothur", "splitAtDash");
568 /***********************************************************************/
569 //This function parses the a string and puts peices in a vector
570 inline void splitAtComma(string& estim, vector<string>& container) {
574 while (estim.find_first_of(',') != -1) {
575 individual = estim.substr(0,estim.find_first_of(','));
576 if ((estim.find_first_of(',')+1) <= estim.length()) { //checks to make sure you don't have comma at end of string
577 estim = estim.substr(estim.find_first_of(',')+1, estim.length());
578 container.push_back(individual);
582 container.push_back(estim);
584 catch(exception& e) {
585 errorOut(e, "mothur", "splitAtComma");
589 /***********************************************************************/
591 //This function splits up the various option parameters
592 inline void splitAtComma(string& prefix, string& suffix){
594 prefix = suffix.substr(0,suffix.find_first_of(','));
595 if ((suffix.find_first_of(',')+2) <= suffix.length()) { //checks to make sure you don't have comma at end of string
596 suffix = suffix.substr(suffix.find_first_of(',')+1, suffix.length());
598 while(suffix.at(0) == ' ')
599 suffix = suffix.substr(1, suffix.length());
603 catch(exception& e) {
604 errorOut(e, "mothur", "splitAtComma");
608 /***********************************************************************/
610 //This function separates the key value from the option value i.e. dist=96_...
611 inline void splitAtEquals(string& key, string& value){
613 if(value.find_first_of('=') != -1){
614 key = value.substr(0,value.find_first_of('='));
615 if ((value.find_first_of('=')+1) <= value.length()) {
616 value = value.substr(value.find_first_of('=')+1, value.length());
623 catch(exception& e) {
624 errorOut(e, "mothur", "splitAtEquals");
628 /**************************************************************************************************/
630 inline bool inUsersGroups(string groupname, vector<string> Groups) {
632 for (int i = 0; i < Groups.size(); i++) {
633 if (groupname == Groups[i]) { return true; }
637 catch(exception& e) {
638 errorOut(e, "mothur", "inUsersGroups");
643 /**************************************************************************************************/
645 inline void mothurOutJustToLog(string message) {
648 string logFileName = "mothur.logFile";
649 openOutputFileAppend(logFileName, out);
655 catch(exception& e) {
656 errorOut(e, "mothur", "mothurOutJustToLog");
662 /**************************************************************************************************/
664 inline void mothurOut(float num) {
667 string logFileName = "mothur.logFile";
668 openOutputFileAppend(logFileName, out);
675 catch(exception& e) {
676 cout << "Error in mothur class mothurOut float" << endl;
680 /***********************************************************************/
681 inline void mothurOut(double value) {
684 string logFileName = "mothur.logFile";
685 openOutputFileAppend(logFileName, out);
692 catch(exception& e) {
693 cout << "Error in mothur class mothurOut double" << endl;
698 /***********************************************************************/
699 //this function determines if the user has given us labels that are smaller than the given label.
700 //if so then it returns true so that the calling function can run the previous valid distance.
701 //it's a "smart" distance function. It also checks for invalid labels.
702 inline bool anyLabelsToProcess(string label, set<string>& userLabels, string errorOff) {
704 set<string>::iterator it;
705 vector<float> orderFloat;
706 map<string, float> userMap; //the conversion process removes trailing 0's which we need to put back
707 map<string, float>::iterator it2;
709 bool smaller = false;
711 //unique is the smallest line
712 if (label == "unique") { return false; }
713 else { convert(label, labelFloat); }
715 //go through users set and make them floats
716 for(it = userLabels.begin(); it != userLabels.end(); ++it) {
719 if ((*it != "unique") && (convertTestFloat(*it, temp) == true)){
721 orderFloat.push_back(temp);
723 }else if (*it == "unique") {
724 orderFloat.push_back(-1.0);
725 userMap["unique"] = -1.0;
727 if (errorOff == "") { mothurOut(*it + " is not a valid label."); mothurOutEndLine(); }
728 userLabels.erase(*it);
734 sort(orderFloat.begin(), orderFloat.end());
736 /*************************************************/
737 //is this label bigger than any of the users labels
738 /*************************************************/
740 //loop through order until you find a label greater than label
741 for (int i = 0; i < orderFloat.size(); i++) {
742 if (orderFloat[i] < labelFloat) {
744 if (orderFloat[i] == -1) {
745 if (errorOff == "") { mothurOut("Your file does not include the label unique."); mothurOutEndLine(); }
746 userLabels.erase("unique");
749 if (errorOff == "") { mothurOut("Your file does not include the label "); mothurOutEndLine(); }
751 for (it2 = userMap.begin(); it2!= userMap.end(); it2++) {
752 if (it2->second == orderFloat[i]) {
754 //remove small labels
759 if (errorOff == "") { mothurOut(s + ". I will use the next smallest distance. "); mothurOutEndLine(); }
761 //since they are sorted once you find a bigger one stop looking
768 catch(exception& e) {
769 errorOut(e, "mothur", "anyLabelsToProcess");
774 /**************************************************************************************************/