]> git.donarmstrong.com Git - mothur.git/blob - mothurout.cpp
added phylip as output file type for commands that output distance matrices. added...
[mothur.git] / mothurout.cpp
1 /*
2  *  mothurOut.cpp
3  *  Mothur
4  *
5  *  Created by westcott on 2/25/10.
6  *  Copyright 2010 Schloss Lab. All rights reserved.
7  *
8  */
9
10 #include "mothurout.h"
11
12
13 /******************************************************/
14 MothurOut* MothurOut::getInstance() {
15         if( _uniqueInstance == 0) {
16                 _uniqueInstance = new MothurOut();
17         }
18         return _uniqueInstance;
19 }
20 /*********************************************************************************************/
21 set<string> MothurOut::getCurrentTypes()  {
22         try {
23         
24         set<string> types;
25         types.insert("fasta");
26         types.insert("accnos");
27         types.insert("column");
28         types.insert("design");
29         types.insert("group");
30         types.insert("list");
31         types.insert("name");
32         types.insert("oligos");
33         types.insert("order");
34         types.insert("ordergroup");
35         types.insert("phylip");
36         types.insert("qfile");
37         types.insert("relabund");
38         types.insert("sabund");
39         types.insert("rabund");
40         types.insert("sff");
41         types.insert("shared");
42         types.insert("taxonomy");
43         types.insert("tree");
44         types.insert("flow");
45         types.insert("biom");
46         types.insert("processors");
47
48                 return types;
49         }
50         catch(exception& e) {
51                 errorOut(e, "MothurOut", "getCurrentTypes");
52                 exit(1);
53         }
54 }
55 /*********************************************************************************************/
56 void MothurOut::printCurrentFiles()  {
57         try {
58         
59         
60                 if (accnosfile != "")           {  mothurOut("accnos=" + accnosfile); mothurOutEndLine();                       }
61                 if (columnfile != "")           {  mothurOut("column=" + columnfile); mothurOutEndLine();                       }
62                 if (designfile != "")           {  mothurOut("design=" + designfile); mothurOutEndLine();                       }
63                 if (fastafile != "")            {  mothurOut("fasta=" + fastafile); mothurOutEndLine();                         }
64                 if (groupfile != "")            {  mothurOut("group=" + groupfile); mothurOutEndLine();                         }
65                 if (listfile != "")                     {  mothurOut("list=" + listfile); mothurOutEndLine();                           }
66                 if (namefile != "")                     {  mothurOut("name=" + namefile); mothurOutEndLine();                           }
67                 if (oligosfile != "")           {  mothurOut("oligos=" + oligosfile); mothurOutEndLine();                       }
68                 if (orderfile != "")            {  mothurOut("order=" + orderfile); mothurOutEndLine();                         }
69                 if (ordergroupfile != "")       {  mothurOut("ordergroup=" + ordergroupfile); mothurOutEndLine();       }
70                 if (phylipfile != "")           {  mothurOut("phylip=" + phylipfile); mothurOutEndLine();                       }
71                 if (qualfile != "")                     {  mothurOut("qfile=" + qualfile); mothurOutEndLine();                          }
72                 if (rabundfile != "")           {  mothurOut("rabund=" + rabundfile); mothurOutEndLine();                       }
73                 if (relabundfile != "")         {  mothurOut("relabund=" + relabundfile); mothurOutEndLine();           }
74                 if (sabundfile != "")           {  mothurOut("sabund=" + sabundfile); mothurOutEndLine();                       }
75                 if (sfffile != "")                      {  mothurOut("sff=" + sfffile); mothurOutEndLine();                                     }
76                 if (sharedfile != "")           {  mothurOut("shared=" + sharedfile); mothurOutEndLine();                       }
77                 if (taxonomyfile != "")         {  mothurOut("taxonomy=" + taxonomyfile); mothurOutEndLine();           }
78                 if (treefile != "")                     {  mothurOut("tree=" + treefile); mothurOutEndLine();                           }
79                 if (flowfile != "")                     {  mothurOut("flow=" + flowfile); mothurOutEndLine();                           }
80         if (biomfile != "")                     {  mothurOut("biom=" + biomfile); mothurOutEndLine();                           }
81                 if (processors != "1")          {  mothurOut("processors=" + processors); mothurOutEndLine();           }
82                 
83         }
84         catch(exception& e) {
85                 errorOut(e, "MothurOut", "printCurrentFiles");
86                 exit(1);
87         }
88 }
89 /*********************************************************************************************/
90 bool MothurOut::hasCurrentFiles()  {
91         try {
92                 bool hasCurrent = false;
93                 
94                 if (accnosfile != "")           {  return true;                 }
95                 if (columnfile != "")           {  return true;                 }
96                 if (designfile != "")           {  return true;                 }
97                 if (fastafile != "")            {  return true;                 }
98                 if (groupfile != "")            {  return true;                 }
99                 if (listfile != "")                     {  return true;                 }
100                 if (namefile != "")                     {  return true;                 }
101                 if (oligosfile != "")           {  return true;                 }
102                 if (orderfile != "")            {  return true;                 }
103                 if (ordergroupfile != "")       {  return true;                 }
104                 if (phylipfile != "")           {  return true;                 }
105                 if (qualfile != "")                     {  return true;                 }
106                 if (rabundfile != "")           {  return true;                 }
107                 if (relabundfile != "")         {  return true;                 }
108                 if (sabundfile != "")           {  return true;                 }
109                 if (sfffile != "")                      {  return true;                 }
110                 if (sharedfile != "")           {  return true;                 }
111                 if (taxonomyfile != "")         {  return true;                 }
112                 if (treefile != "")                     {  return true;                 }
113                 if (flowfile != "")                     {  return true;                 }
114         if (biomfile != "")                     {  return true;                 }
115                 if (processors != "1")          {  return true;                 }
116                 
117                 return hasCurrent;
118                 
119         }
120         catch(exception& e) {
121                 errorOut(e, "MothurOut", "hasCurrentFiles");
122                 exit(1);
123         }
124 }
125
126 /*********************************************************************************************/
127 void MothurOut::clearCurrentFiles()  {
128         try {
129                 phylipfile = "";
130                 columnfile = "";
131                 listfile = "";
132                 rabundfile = "";
133                 sabundfile = "";
134                 namefile = "";
135                 groupfile = "";
136                 designfile = "";
137                 orderfile = "";
138                 treefile = "";
139                 sharedfile = "";
140                 ordergroupfile = "";
141                 relabundfile = "";
142                 fastafile = "";
143                 qualfile = "";
144                 sfffile = "";
145                 oligosfile = "";
146                 accnosfile = "";
147                 taxonomyfile = "";      
148                 flowfile = "";
149         biomfile = "";
150                 processors = "1";
151         }
152         catch(exception& e) {
153                 errorOut(e, "MothurOut", "clearCurrentFiles");
154                 exit(1);
155         }
156 }
157 /***********************************************************************/
158 string MothurOut::findProgramPath(string programName){
159         try { 
160                 
161                 string envPath = getenv("PATH");
162                 string pPath = "";
163                 
164                 //delimiting path char
165                 char delim;
166 #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix)
167         delim = ':';
168 #else
169         delim = ';';
170 #endif
171                 
172                 //break apart path variable by ':'
173                 vector<string> dirs;
174                 splitAtChar(envPath, dirs, delim);
175                 
176         if (debug) { mothurOut("[DEBUG]: dir's in path: \n"); }
177         
178                 //get path related to mothur
179                 for (int i = 0; i < dirs.size(); i++) {
180             
181             if (debug) { mothurOut("[DEBUG]: " + dirs[i] + "\n"); }
182             
183                         //to lower so we can find it
184                         string tempLower = "";
185                         for (int j = 0; j < dirs[i].length(); j++) {  tempLower += tolower(dirs[i][j]);  }
186                         
187                         //is this mothurs path?
188                         if (tempLower.find(programName) != -1) {  pPath = dirs[i]; break;  }
189                 }
190         
191                 if (debug) { mothurOut("[DEBUG]: programPath = " + pPath + "\n"); }
192         
193                 if (pPath != "") {
194                         //add programName so it looks like what argv would look like
195 #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix)
196             pPath += "/" + programName;
197 #else
198             pPath += "\\" + programName;
199 #endif
200                 }else {
201                         //okay programName is not in the path, so the folder programName is in must be in the path
202                         //lets find out which one
203                         
204                         //get path related to the program
205                         for (int i = 0; i < dirs.size(); i++) {
206                 
207                 if (debug) { mothurOut("[DEBUG]: looking in " + dirs[i] + " for " + programName + " \n"); }
208                 
209                                 //is this the programs path?
210                                 ifstream in;
211                                 string tempIn = dirs[i];
212 #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix)
213                 tempIn += "/" + programName;
214 #else
215                 tempIn += "\\" + programName;
216 #endif
217                                 openInputFile(tempIn, in, "");
218                                 
219                                 //if this file exists
220                                 if (in) { in.close(); pPath = tempIn; if (debug) { mothurOut("[DEBUG]: found it, programPath = " + pPath + "\n"); } break;   }
221                         }
222                 }
223                 
224                 return pPath;
225                 
226         }
227         catch(exception& e) {
228                 errorOut(e, "MothurOut", "findProgramPath");
229                 exit(1);
230         }
231 }
232 /*********************************************************************************************/
233 void MothurOut::setFileName(string filename)  {
234         try {
235                 logFileName = filename;
236                 
237                 #ifdef USE_MPI
238                         int pid;
239                         MPI_Comm_rank(MPI_COMM_WORLD, &pid); 
240                                         
241                         if (pid == 0) { //only one process should output to screen
242                 #endif
243                 
244                 openOutputFile(filename, out);
245                 
246                 #ifdef USE_MPI
247                         }
248                 #endif
249         }
250         catch(exception& e) {
251                 errorOut(e, "MothurOut", "setFileName");
252                 exit(1);
253         }
254 }
255 /*********************************************************************************************/
256 void MothurOut::setDefaultPath(string pathname)  {
257         try {
258         
259                 //add / to name if needed
260                 string lastChar = pathname.substr(pathname.length()-1);
261                 #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix)
262                         if (lastChar != "/") { pathname += "/"; }
263                 #else
264                         if (lastChar != "\\") { pathname += "\\"; }     
265                 #endif
266                 
267                 defaultPath = pathname;
268                 
269         }
270         catch(exception& e) {
271                 errorOut(e, "MothurOut", "setDefaultPath");
272                 exit(1);
273         }
274 }
275 /*********************************************************************************************/
276 void MothurOut::setOutputDir(string pathname)  {
277         try {
278                 outputDir = pathname;
279         }
280         catch(exception& e) {
281                 errorOut(e, "MothurOut", "setOutputDir");
282                 exit(1);
283         }
284 }
285 /*********************************************************************************************/
286 void MothurOut::closeLog()  {
287         try {
288                 
289                 #ifdef USE_MPI
290                         int pid;
291                         MPI_Comm_rank(MPI_COMM_WORLD, &pid); 
292                                         
293                         if (pid == 0) { //only one process should output to screen
294                 #endif
295                 
296                 out.close();
297                 
298                 #ifdef USE_MPI
299                         }
300                 #endif
301         }
302         catch(exception& e) {
303                 errorOut(e, "MothurOut", "closeLog");
304                 exit(1);
305         }
306 }
307
308 /*********************************************************************************************/
309 MothurOut::~MothurOut() {
310         try {
311                 _uniqueInstance = 0;
312                 
313         }
314         catch(exception& e) {
315                 errorOut(e, "MothurOut", "MothurOut");
316                 exit(1);
317         }
318 }
319 /*********************************************************************************************/
320 void MothurOut::mothurOut(string output) {
321         try {
322                 
323                 #ifdef USE_MPI
324                         int pid;
325                         MPI_Comm_rank(MPI_COMM_WORLD, &pid); 
326                                         
327                         if (pid == 0) { //only one process should output to screen
328                 #endif
329                 
330                 out << output;
331         logger() << output;
332                 
333                 #ifdef USE_MPI
334                         }
335                 #endif
336         }
337         catch(exception& e) {
338                 errorOut(e, "MothurOut", "MothurOut");
339                 exit(1);
340         }
341 }
342 /*********************************************************************************************/
343 void MothurOut::mothurOutEndLine() {
344         try {
345                 #ifdef USE_MPI
346                         int pid;
347                         MPI_Comm_rank(MPI_COMM_WORLD, &pid); 
348                                         
349                         if (pid == 0) { //only one process should output to screen
350                 #endif
351                 
352                 out << endl;
353         logger() << endl;
354                 
355                 #ifdef USE_MPI
356                         }
357                 #endif
358         }
359         catch(exception& e) {
360                 errorOut(e, "MothurOut", "MothurOutEndLine");
361                 exit(1);
362         }
363 }
364 /*********************************************************************************************/
365 void MothurOut::mothurOut(string output, ofstream& outputFile) {
366         try {
367                 
368 #ifdef USE_MPI
369                 int pid;
370                 MPI_Comm_rank(MPI_COMM_WORLD, &pid); 
371                 
372                 if (pid == 0) { //only one process should output to screen
373 #endif
374                         
375                         
376                         out << output;
377                         outputFile << output;
378             logger() << output;
379                         
380 #ifdef USE_MPI
381                 }
382 #endif
383         
384         }
385         catch(exception& e) {
386                 errorOut(e, "MothurOut", "MothurOut");
387                 exit(1);
388         }
389 }
390 /*********************************************************************************************/
391 void MothurOut::mothurOutEndLine(ofstream& outputFile) {
392         try {
393 #ifdef USE_MPI
394                 int pid;
395                 MPI_Comm_rank(MPI_COMM_WORLD, &pid); 
396                 
397                 if (pid == 0) { //only one process should output to screen
398 #endif
399                         
400                         out << endl;
401                         outputFile << endl;
402             logger() << endl;
403                         
404 #ifdef USE_MPI
405                 }
406 #endif
407         }
408         catch(exception& e) {
409                 errorOut(e, "MothurOut", "MothurOutEndLine");
410                 exit(1);
411         }
412 }
413 /*********************************************************************************************/
414 void MothurOut::mothurOutJustToLog(string output) {
415         try {
416                 #ifdef USE_MPI
417                         int pid;
418                         MPI_Comm_rank(MPI_COMM_WORLD, &pid); 
419                                         
420                         if (pid == 0) { //only one process should output to screen
421                 #endif
422                 
423                 out << output;
424                 
425                 #ifdef USE_MPI
426                         }
427                 #endif
428         }
429         catch(exception& e) {
430                 errorOut(e, "MothurOut", "MothurOutJustToLog");
431                 exit(1);
432         }
433 }
434 /*********************************************************************************************/
435 void MothurOut::errorOut(exception& e, string object, string function) {
436         //double vm, rss;
437         //mem_usage(vm, rss);
438         
439         mothurOut("[ERROR]: ");
440         mothurOut(toString(e.what()));
441         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.");
442         mothurOutEndLine();
443 }
444 /*********************************************************************************************/
445 //The following was originally from http://stackoverflow.com/questions/669438/how-to-get-memory-usage-at-run-time-in-c 
446 // process_mem_usage(double &, double &) - takes two doubles by reference,
447 // attempts to read the system-dependent data for a process' virtual memory
448 // size and resident set size, and return the results in KB.
449 //
450 // On failure, returns 0.0, 0.0
451 int MothurOut::mem_usage(double& vm_usage, double& resident_set) {
452   #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix)
453   
454            vm_usage     = 0.0;
455            resident_set = 0.0;
456
457            // 'file' stat seems to give the most reliable results
458            //
459            ifstream stat_stream("/proc/self/stat",ios_base::in);
460
461            // dummy vars for leading entries in stat that we don't care about
462            //
463            string pid, comm, state, ppid, pgrp, session, tty_nr;
464            string tpgid, flags, minflt, cminflt, majflt, cmajflt;
465            string utime, stime, cutime, cstime, priority, nice;
466            string O, itrealvalue, starttime;
467
468            // the two fields we want
469            //
470            unsigned long vsize;
471            long rss;
472
473            stat_stream >> pid >> comm >> state >> ppid >> pgrp >> session >> tty_nr
474                                    >> tpgid >> flags >> minflt >> cminflt >> majflt >> cmajflt
475                                    >> utime >> stime >> cutime >> cstime >> priority >> nice
476                                    >> O >> itrealvalue >> starttime >> vsize >> rss; // don't care about the rest
477
478            long page_size_kb = sysconf(_SC_PAGE_SIZE) / 1024; // in case x86-64 is configured to use 2MB pages
479            vm_usage     = vsize / 1024.0;
480            resident_set = rss * page_size_kb;
481            
482            mothurOut("Memory Usage: vm = " + toString(vm_usage) + " rss = " + toString(resident_set) + "\n");
483                 return 0;
484
485         #else
486 /*              //windows memory usage
487                 // Get the list of process identifiers.
488                 DWORD aProcesses[1024], cbNeeded, cProcesses;
489                 
490                 if ( !EnumProcesses( aProcesses, sizeof(aProcesses), &cbNeeded ) ){ return 1; }
491
492                 // Calculate how many process identifiers were returned.
493                 cProcesses = cbNeeded / sizeof(DWORD);
494
495                 // Print the memory usage for each process
496                 for (int i = 0; i < cProcesses; i++ ) {
497                         DWORD processID = aProcesses[i];
498                         
499                         PROCESS_MEMORY_COUNTERS pmc;
500
501                         HANDLE hProcess = OpenProcess((PROCESS_QUERY_INFORMATION | PROCESS_VM_READ), FALSE, processID);
502
503                         // Print the process identifier.
504                         printf( "\nProcess ID: %u\n", processID);
505                         
506                         if (NULL != hProcess) {
507
508                                 if ( GetProcessMemoryInfo( hProcess, &pmc, sizeof(pmc)) ) {
509                                         printf( "\tPageFaultCount: 0x%08X\n", pmc.PageFaultCount );
510                                         printf( "\tPeakWorkingSetSize: 0x%08X\n", pmc.PeakWorkingSetSize );
511                                         printf( "\tWorkingSetSize: 0x%08X\n", pmc.WorkingSetSize );
512                                         printf( "\tQuotaPeakPagedPoolUsage: 0x%08X\n", pmc.QuotaPeakPagedPoolUsage );
513                                         printf( "\tQuotaPagedPoolUsage: 0x%08X\n", pmc.QuotaPagedPoolUsage );
514                                         printf( "\tQuotaPeakNonPagedPoolUsage: 0x%08X\n", pmc.QuotaPeakNonPagedPoolUsage );
515                                         printf( "\tQuotaNonPagedPoolUsage: 0x%08X\n", pmc.QuotaNonPagedPoolUsage );
516                                         printf( "\tPagefileUsage: 0x%08X\n", pmc.PagefileUsage ); 
517                                         printf( "\tPeakPagefileUsage: 0x%08X\n", pmc.PeakPagefileUsage );
518                                 }
519                                 CloseHandle(hProcess);
520                         }
521                 }
522 */
523                         return 0;
524
525         #endif
526 }
527
528
529 /***********************************************************************/
530 int MothurOut::openOutputFileAppend(string fileName, ofstream& fileHandle){
531         try {
532                 fileName = getFullPathName(fileName);
533                 
534                 fileHandle.open(fileName.c_str(), ios::app);
535                 if(!fileHandle) {
536                         mothurOut("[ERROR]: Could not open " + fileName); mothurOutEndLine();
537                         return 1;
538                 }
539                 else {
540                         return 0;
541                 }
542         }
543         catch(exception& e) {
544                 errorOut(e, "MothurOut", "openOutputFileAppend");
545                 exit(1);
546         }
547 }
548 /***********************************************************************/
549 void MothurOut::gobble(istream& f){
550         try {
551                 
552                 char d;
553                 while(isspace(d=f.get()))               { ;}
554                 if(!f.eof()) { f.putback(d); }
555         }
556         catch(exception& e) {
557                 errorOut(e, "MothurOut", "gobble");
558                 exit(1);
559         }
560 }
561 /***********************************************************************/
562 void MothurOut::gobble(istringstream& f){
563         try {
564                 char d;
565                 while(isspace(d=f.get()))               {;}
566                 if(!f.eof()) { f.putback(d); }
567         }
568         catch(exception& e) {
569                 errorOut(e, "MothurOut", "gobble");
570                 exit(1);
571         }
572 }
573
574 /***********************************************************************/
575
576 string MothurOut::getline(istringstream& fileHandle) {
577         try {
578         
579                 string line = "";
580                 
581                 while (!fileHandle.eof())       {
582                         //get next character
583                         char c = fileHandle.get(); 
584                         
585                         //are you at the end of the line
586                         if ((c == '\n') || (c == '\r') || (c == '\f')){  break; }       
587                         else {          line += c;              }
588                 }
589                 
590                 return line;
591                 
592         }
593         catch(exception& e) {
594                 errorOut(e, "MothurOut", "getline");
595                 exit(1);
596         }
597 }
598 /***********************************************************************/
599
600 string MothurOut::getline(ifstream& fileHandle) {
601         try {
602         
603                 string line = "";
604                 
605                 while (fileHandle)      {
606                         //get next character
607                         char c = fileHandle.get(); 
608                         
609                         //are you at the end of the line
610                         if ((c == '\n') || (c == '\r') || (c == '\f') || (c == EOF)){  break;   }       
611                         else {          line += c;              }
612                 }
613                 
614                 return line;
615                 
616         }
617         catch(exception& e) {
618                 errorOut(e, "MothurOut", "getline");
619                 exit(1);
620         }
621 }
622 /***********************************************************************/
623
624 #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix)
625 #ifdef USE_COMPRESSION
626 inline bool endsWith(string s, const char * suffix){
627   size_t suffixLength = strlen(suffix);
628   return s.size() >= suffixLength && s.substr(s.size() - suffixLength, suffixLength).compare(suffix) == 0;
629 }
630 #endif
631 #endif
632
633 string MothurOut::getRootName(string longName){
634         try {
635         
636                 string rootName = longName;
637
638 #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix)
639 #ifdef USE_COMPRESSION
640     if (endsWith(rootName, ".gz") || endsWith(rootName, ".bz2")) {
641       int pos = rootName.find_last_of('.');
642       rootName = rootName.substr(0, pos);
643       cerr << "shortening " << longName << " to " << rootName << "\n";
644     }
645 #endif
646 #endif
647                 if(rootName.find_last_of(".") != rootName.npos){
648                         int pos = rootName.find_last_of('.')+1;
649                         rootName = rootName.substr(0, pos);
650                 }
651
652                 return rootName;
653         }
654         catch(exception& e) {
655                 errorOut(e, "MothurOut", "getRootName");
656                 exit(1);
657         }
658 }
659 /***********************************************************************/
660
661 string MothurOut::getSimpleName(string longName){
662         try {
663                 string simpleName = longName;
664                 
665                 size_t found;
666                 found=longName.find_last_of("/\\");
667
668                 if(found != longName.npos){
669                         simpleName = longName.substr(found+1);
670                 }
671                 
672                 return simpleName;
673         }
674         catch(exception& e) {
675                 errorOut(e, "MothurOut", "getSimpleName");
676                 exit(1);
677         }
678 }
679
680 /***********************************************************************/
681
682 int MothurOut::getRandomIndex(int highest){
683         try {
684                 
685                 int random = (int) ((float)(highest+1) * (float)(rand()) / ((float)RAND_MAX+1.0));
686                 
687                 return random;
688         }
689         catch(exception& e) {
690                 errorOut(e, "MothurOut", "getRandomIndex");
691                 exit(1);
692         }       
693         
694 }
695 /**********************************************************************/
696
697 string MothurOut::getPathName(string longName){
698         try {
699                 string rootPathName = longName;
700                 
701                 if(longName.find_last_of("/\\") != longName.npos){
702                         int pos = longName.find_last_of("/\\")+1;
703                         rootPathName = longName.substr(0, pos);
704                 }
705                 
706                 return rootPathName;
707         }
708         catch(exception& e) {
709                 errorOut(e, "MothurOut", "getPathName");
710                 exit(1);
711         }       
712
713 }
714 /***********************************************************************/
715
716 bool MothurOut::dirCheck(string& dirName){
717         try {
718         
719         string tag = "";
720         #ifdef USE_MPI
721             int pid; 
722             MPI_Comm_rank(MPI_COMM_WORLD, &pid); //find out who we are
723                 
724             tag = toString(pid);
725         #endif
726
727         //add / to name if needed
728         string lastChar = dirName.substr(dirName.length()-1);
729         #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix)
730         if (lastChar != "/") { dirName += "/"; }
731         #else
732         if (lastChar != "\\") { dirName += "\\"; }      
733         #endif
734
735         //test to make sure directory exists
736         dirName = getFullPathName(dirName);
737         string outTemp = dirName + tag + "temp";
738         ofstream out;
739         out.open(outTemp.c_str(), ios::trunc);
740         if(!out) {
741             mothurOut(dirName + " directory does not exist or is not writable."); mothurOutEndLine(); 
742         }else{
743             out.close();
744             mothurRemove(outTemp);
745             return true;
746         }
747         
748         return false;
749     }
750         catch(exception& e) {
751                 errorOut(e, "MothurOut", "dirCheck");
752                 exit(1);
753         }       
754     
755 }
756 /***********************************************************************/
757
758 string MothurOut::hasPath(string longName){
759         try {
760                 string path = "";
761                 
762                 size_t found;
763                 found=longName.find_last_of("~/\\");
764
765                 if(found != longName.npos){
766                         path = longName.substr(0, found+1);
767                 }
768                 
769                 return path;
770         }
771         catch(exception& e) {
772                 errorOut(e, "MothurOut", "hasPath");
773                 exit(1);
774         }       
775 }
776
777 /***********************************************************************/
778
779 string MothurOut::getExtension(string longName){
780         try {
781                 string extension = "";
782                 
783                 if(longName.find_last_of('.') != longName.npos){
784                         int pos = longName.find_last_of('.');
785                         extension = longName.substr(pos, longName.length());
786                 }
787                 
788                 return extension;
789         }
790         catch(exception& e) {
791                 errorOut(e, "MothurOut", "getExtension");
792                 exit(1);
793         }       
794 }
795 /***********************************************************************/
796 bool MothurOut::isBlank(string fileName){
797         try {
798                 
799                 fileName = getFullPathName(fileName);
800                 
801                 ifstream fileHandle;
802                 fileHandle.open(fileName.c_str());
803                 if(!fileHandle) {
804                         mothurOut("[ERROR]: Could not open " + fileName); mothurOutEndLine();
805                         return false;
806                 }else {
807                         //check for blank file
808                         gobble(fileHandle);
809                         if (fileHandle.eof()) { fileHandle.close(); return true;  }
810                         fileHandle.close();
811                 }
812                 return false;
813         }
814         catch(exception& e) {
815                 errorOut(e, "MothurOut", "isBlank");
816                 exit(1);
817         }       
818 }
819 /***********************************************************************/
820
821 string MothurOut::getFullPathName(string fileName){
822         try{
823         
824         string path = hasPath(fileName);
825         string newFileName;
826         int pos;
827         
828         if (path == "") { return fileName; } //its a simple name
829         else { //we need to complete the pathname
830                 // ex. ../../../filename 
831                 // cwd = /user/work/desktop
832                                 
833                 string cwd;
834                 //get current working directory 
835                 #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix)  
836                         
837                         if (path.find("~") != -1) { //go to home directory
838                                 string homeDir;
839                         
840                                 char *homepath = NULL;
841                                 homepath = getenv ("HOME");
842                                 if ( homepath != NULL) { homeDir = homepath; }
843                                 else { homeDir = "";  }
844
845                                 newFileName = homeDir + fileName.substr(fileName.find("~")+1);
846                                 return newFileName;
847                         }else { //find path
848                                 if (path.rfind("./") == string::npos) { return fileName; } //already complete name
849                                 else { newFileName = fileName.substr(fileName.rfind("./")+2); } //save the complete part of the name
850                                 
851                                 //char* cwdpath = new char[1024];
852                                 //size_t size;
853                                 //cwdpath=getcwd(cwdpath,size);
854                                 //cwd = cwdpath;
855                                 
856                                 char *cwdpath = NULL;
857                                 cwdpath = getcwd(NULL, 0); // or _getcwd
858                                 if ( cwdpath != NULL) { cwd = cwdpath; }
859                                 else { cwd = "";  }
860
861                                 
862                                 //rip off first '/'
863                                 string simpleCWD;
864                                 if (cwd.length() > 0) { simpleCWD = cwd.substr(1); }
865                                 
866                                 //break apart the current working directory
867                                 vector<string> dirs;
868                                 while (simpleCWD.find_first_of('/') != string::npos) {
869                                         string dir = simpleCWD.substr(0,simpleCWD.find_first_of('/'));
870                                         simpleCWD = simpleCWD.substr(simpleCWD.find_first_of('/')+1, simpleCWD.length());
871                                         dirs.push_back(dir);
872                                 }
873                                 //get last one              // ex. ../../../filename = /user/work/desktop/filename
874                                 dirs.push_back(simpleCWD);  //ex. dirs[0] = user, dirs[1] = work, dirs[2] = desktop
875                                 
876                         
877                                 int index = dirs.size()-1;
878                 
879                                 while((pos = path.rfind("./")) != string::npos) { //while you don't have a complete path
880                                         if (pos == 0) { break;  //you are at the end
881                                         }else if (path[(pos-1)] == '.') { //you want your parent directory ../
882                                                 path = path.substr(0, pos-1);
883                                                 index--;
884                                                 if (index == 0) {  break; }
885                                         }else if (path[(pos-1)] == '/') { //you want the current working dir ./
886                                                 path = path.substr(0, pos);
887                                         }else if (pos == 1) { break;  //you are at the end
888                                         }else { mothurOut("cannot resolve path for " +  fileName + "\n"); return fileName; }
889                                 }
890                         
891                                 for (int i = index; i >= 0; i--) {
892                                         newFileName = dirs[i] +  "/" + newFileName;             
893                                 }
894                                 
895                                 newFileName =  "/" +  newFileName;
896                                 return newFileName;
897                         }       
898                 #else
899                         if (path.find("~") != string::npos) { //go to home directory
900                                 string homeDir = getenv ("HOMEPATH");
901                                 newFileName = homeDir + fileName.substr(fileName.find("~")+1);
902                                 return newFileName;
903                         }else { //find path
904                                 if (path.rfind(".\\") == string::npos) { return fileName; } //already complete name
905                                 else { newFileName = fileName.substr(fileName.rfind(".\\")+2); } //save the complete part of the name
906                                                         
907                                 char *cwdpath = NULL;
908                                 cwdpath = getcwd(NULL, 0); // or _getcwd
909                                 if ( cwdpath != NULL) { cwd = cwdpath; }
910                                 else { cwd = "";  }
911                                 
912                                 //break apart the current working directory
913                                 vector<string> dirs;
914                                 while (cwd.find_first_of('\\') != -1) {
915                                         string dir = cwd.substr(0,cwd.find_first_of('\\'));
916                                         cwd = cwd.substr(cwd.find_first_of('\\')+1, cwd.length());
917                                         dirs.push_back(dir);
918                 
919                                 }
920                                 //get last one
921                                 dirs.push_back(cwd);  //ex. dirs[0] = user, dirs[1] = work, dirs[2] = desktop
922                                         
923                                 int index = dirs.size()-1;
924                                         
925                                 while((pos = path.rfind(".\\")) != string::npos) { //while you don't have a complete path
926                                         if (pos == 0) { break;  //you are at the end
927                                         }else if (path[(pos-1)] == '.') { //you want your parent directory ../
928                                                 path = path.substr(0, pos-1);
929                                                 index--;
930                                                 if (index == 0) {  break; }
931                                         }else if (path[(pos-1)] == '\\') { //you want the current working dir ./
932                                                 path = path.substr(0, pos);
933                                         }else if (pos == 1) { break;  //you are at the end
934                                         }else { mothurOut("cannot resolve path for " +  fileName + "\n"); return fileName; }
935                                 }
936                         
937                                 for (int i = index; i >= 0; i--) {
938                                         newFileName = dirs[i] +  "\\" + newFileName;            
939                                 }
940                                 
941                                 return newFileName;
942                         }
943                         
944                 #endif
945         }
946         }
947         catch(exception& e) {
948                 errorOut(e, "MothurOut", "getFullPathName");
949                 exit(1);
950         }       
951 }
952 /***********************************************************************/
953
954 int MothurOut::openInputFile(string fileName, ifstream& fileHandle, string m){
955         try {
956                         //get full path name
957                         string completeFileName = getFullPathName(fileName);
958 #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix)
959 #ifdef USE_COMPRESSION
960       // check for gzipped or bzipped file
961       if (endsWith(completeFileName, ".gz") || endsWith(completeFileName, ".bz2")) {
962         string tempName = string(tmpnam(0));
963         mkfifo(tempName.c_str(), 0666);
964         int fork_result = fork();
965         if (fork_result < 0) {
966           cerr << "Error forking.\n";
967           exit(1);
968         } else if (fork_result == 0) {
969           string command = (endsWith(completeFileName, ".gz") ? "zcat " : "bzcat ") + completeFileName + string(" > ") + tempName;
970           cerr << "Decompressing " << completeFileName << " via temporary named pipe " << tempName << "\n";
971           system(command.c_str());
972           cerr << "Done decompressing " << completeFileName << "\n";
973           mothurRemove(tempName);
974           exit(EXIT_SUCCESS);
975         } else {
976           cerr << "waiting on child process " << fork_result << "\n";
977           completeFileName = tempName;
978         }
979       }
980 #endif
981 #endif
982                         fileHandle.open(completeFileName.c_str());
983                         if(!fileHandle) {
984                                 //mothurOut("[ERROR]: Could not open " + completeFileName); mothurOutEndLine();
985                                 return 1;
986                         }else {
987                                 //check for blank file
988                                 gobble(fileHandle);
989                                 return 0;
990                         }
991         }
992         catch(exception& e) {
993                 errorOut(e, "MothurOut", "openInputFile - no Error");
994                 exit(1);
995         }
996 }
997 /***********************************************************************/
998
999 int MothurOut::openInputFile(string fileName, ifstream& fileHandle){
1000         try {
1001
1002                 //get full path name
1003                 string completeFileName = getFullPathName(fileName);
1004 #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix)
1005 #ifdef USE_COMPRESSION
1006   // check for gzipped or bzipped file
1007   if (endsWith(completeFileName, ".gz") || endsWith(completeFileName, ".bz2")) {
1008     string tempName = string(tmpnam(0));
1009     mkfifo(tempName.c_str(), 0666);
1010     int fork_result = fork();
1011     if (fork_result < 0) {
1012       cerr << "Error forking.\n";
1013       exit(1);
1014     } else if (fork_result == 0) {
1015       string command = (endsWith(completeFileName, ".gz") ? "zcat " : "bzcat ") + completeFileName + string(" > ") + tempName;
1016       cerr << "Decompressing " << completeFileName << " via temporary named pipe " << tempName << "\n";
1017       system(command.c_str());
1018       cerr << "Done decompressing " << completeFileName << "\n";
1019       mothurRemove(tempName);
1020       exit(EXIT_SUCCESS);
1021     } else {
1022       cerr << "waiting on child process " << fork_result << "\n";
1023       completeFileName = tempName;
1024     }
1025   }
1026 #endif
1027 #endif
1028
1029                 fileHandle.open(completeFileName.c_str());
1030                 if(!fileHandle) {
1031                         mothurOut("[ERROR]: Could not open " + completeFileName); mothurOutEndLine();
1032                         return 1;
1033                 }
1034                 else {
1035                         //check for blank file
1036                         gobble(fileHandle);
1037                         if (fileHandle.eof()) { mothurOut("[ERROR]: " + completeFileName + " is blank. Please correct."); mothurOutEndLine();  }
1038                         
1039                         return 0;
1040                 }
1041         }
1042         catch(exception& e) {
1043                 errorOut(e, "MothurOut", "openInputFile");
1044                 exit(1);
1045         }       
1046 }
1047 /***********************************************************************/
1048
1049 int MothurOut::renameFile(string oldName, string newName){
1050         try {
1051                 ifstream inTest;
1052                 int exist = openInputFile(newName, inTest, "");
1053                 inTest.close();
1054                 
1055         #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix)          
1056                 if (exist == 0) { //you could open it so you want to delete it
1057                         string command = "rm " + newName;
1058                         system(command.c_str());
1059                 }
1060                                 
1061                 string command = "mv " + oldName + " " + newName;
1062                 system(command.c_str());
1063         #else
1064                 mothurRemove(newName);
1065                 int renameOk = rename(oldName.c_str(), newName.c_str());
1066         #endif
1067                 return 0;
1068                 
1069         }
1070         catch(exception& e) {
1071                 errorOut(e, "MothurOut", "renameFile");
1072                 exit(1);
1073         }       
1074 }
1075
1076 /***********************************************************************/
1077
1078 int MothurOut::openOutputFile(string fileName, ofstream& fileHandle){
1079         try { 
1080         
1081                 string completeFileName = getFullPathName(fileName);
1082 #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix)
1083 #ifdef USE_COMPRESSION
1084     // check for gzipped file
1085     if (endsWith(completeFileName, ".gz") || endsWith(completeFileName, ".bz2")) {
1086       string tempName = string(tmpnam(0));
1087       mkfifo(tempName.c_str(), 0666);
1088       cerr << "Compressing " << completeFileName << " via temporary named pipe " << tempName << "\n";
1089       int fork_result = fork();
1090       if (fork_result < 0) {
1091         cerr << "Error forking.\n";
1092         exit(1);
1093       } else if (fork_result == 0) {
1094         string command = string(endsWith(completeFileName, ".gz") ?  "gzip" : "bzip2") + " -v > " + completeFileName + string(" < ") + tempName;
1095         system(command.c_str());
1096         exit(0);
1097       } else {
1098         completeFileName = tempName;
1099       }
1100     }
1101 #endif
1102 #endif
1103                 fileHandle.open(completeFileName.c_str(), ios::trunc);
1104                 if(!fileHandle) {
1105                         mothurOut("[ERROR]: Could not open " + completeFileName); mothurOutEndLine();
1106                         return 1;
1107                 }
1108                 else {
1109                         return 0;
1110                 }
1111         }
1112         catch(exception& e) {
1113                 errorOut(e, "MothurOut", "openOutputFile");
1114                 exit(1);
1115         }       
1116
1117 }
1118
1119 /**************************************************************************************************/
1120 int MothurOut::appendFiles(string temp, string filename) {
1121         try{
1122                 ofstream output;
1123                 ifstream input;
1124         
1125                 //open output file in append mode
1126                 openOutputFileAppend(filename, output);
1127                 int ableToOpen = openInputFile(temp, input, "no error");
1128                 //int ableToOpen = openInputFile(temp, input);
1129                 
1130                 int numLines = 0;
1131                 if (ableToOpen == 0) { //you opened it
1132             
1133             char buffer[4096];        
1134             while (!input.eof()) {
1135                 input.read(buffer, 4096);
1136                 output.write(buffer, input.gcount());
1137                 //count number of lines
1138                 for (int i = 0; i < input.gcount(); i++) {  if (buffer[i] == '\n') {numLines++;} }
1139             }
1140                         input.close();
1141                 }
1142                 
1143                 output.close();
1144                 
1145                 return numLines;
1146         }
1147         catch(exception& e) {
1148                 errorOut(e, "MothurOut", "appendFiles");
1149                 exit(1);
1150         }       
1151 }
1152
1153 /**************************************************************************************************/
1154 string MothurOut::sortFile(string distFile, string outputDir){
1155         try {   
1156         
1157                 //if (outputDir == "") {  outputDir += hasPath(distFile);  }
1158                 string outfile = getRootName(distFile) + "sorted.dist";
1159
1160                 
1161                 //if you can, use the unix sort since its been optimized for years
1162                 #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix)
1163                         string command = "sort -n -k +3 " + distFile + " -o " + outfile;
1164                         system(command.c_str());
1165                 #else //you are stuck with my best attempt...
1166                         //windows sort does not have a way to specify a column, only a character in the line
1167                         //since we cannot assume that the distance will always be at the the same character location on each line
1168                         //due to variable sequence name lengths, I chose to force the distance into first position, then sort and then put it back.
1169                 
1170                         //read in file line by file and put distance first
1171                         string tempDistFile = distFile + ".temp";
1172                         ifstream input;
1173                         ofstream output;
1174                         openInputFile(distFile, input);
1175                         openOutputFile(tempDistFile, output);
1176
1177                         string firstName, secondName;
1178                         float dist;
1179                         while (input) {
1180                                 input >> firstName >> secondName >> dist;
1181                                 output << dist << '\t' << firstName << '\t' << secondName << endl;
1182                                 gobble(input);
1183                         }
1184                         input.close();
1185                         output.close();
1186                 
1187         
1188                         //sort using windows sort
1189                         string tempOutfile = outfile + ".temp";
1190                         string command = "sort " + tempDistFile + " /O " + tempOutfile;
1191                         system(command.c_str());
1192                 
1193                         //read in sorted file and put distance at end again
1194                         ifstream input2;
1195                         openInputFile(tempOutfile, input2);
1196                         openOutputFile(outfile, output);
1197                 
1198                         while (input2) {
1199                                 input2 >> dist >> firstName >> secondName;
1200                                 output << firstName << '\t' << secondName << '\t' << dist << endl;
1201                                 gobble(input2);
1202                         }
1203                         input2.close();
1204                         output.close();
1205                 
1206                         //remove temp files
1207                         mothurRemove(tempDistFile);
1208                         mothurRemove(tempOutfile);
1209                 #endif
1210                 
1211                 return outfile;
1212         }
1213         catch(exception& e) {
1214                 errorOut(e, "MothurOut", "sortFile");
1215                 exit(1);
1216         }       
1217 }
1218 /**************************************************************************************************/
1219 vector<unsigned long long> MothurOut::setFilePosFasta(string filename, int& num) {
1220         try {
1221                         vector<unsigned long long> positions;
1222                         ifstream inFASTA;
1223                         //openInputFile(filename, inFASTA);
1224                         inFASTA.open(filename.c_str(), ios::binary);
1225                                                 
1226                         string input;
1227                         unsigned long long count = 0;
1228                         while(!inFASTA.eof()){
1229                                 //input = getline(inFASTA); 
1230                                 //cout << input << '\t' << inFASTA.tellg() << endl;
1231                                 //if (input.length() != 0) {
1232                                 //      if(input[0] == '>'){    unsigned long int pos = inFASTA.tellg(); positions.push_back(pos - input.length() - 1);  cout << (pos - input.length() - 1) << endl; }
1233                                 //}
1234                                 //gobble(inFASTA); //has to be here since windows line endings are 2 characters and mess up the positions
1235                                 char c = inFASTA.get(); count++;
1236                                 if (c == '>') {
1237                                         positions.push_back(count-1);
1238                                         //cout << count << endl;
1239                                 }
1240                         }
1241                         inFASTA.close();
1242                 
1243                         num = positions.size();
1244                 
1245                         /*FILE * pFile;
1246                         long size;
1247                 
1248                         //get num bytes in file
1249                         pFile = fopen (filename.c_str(),"rb");
1250                         if (pFile==NULL) perror ("Error opening file");
1251                         else{
1252                                 fseek (pFile, 0, SEEK_END);
1253                                 size=ftell (pFile);
1254                                 fclose (pFile);
1255                         }*/
1256                         
1257                         unsigned long long size = positions[(positions.size()-1)];
1258                         ifstream in;
1259                         openInputFile(filename, in);
1260                         
1261                         in.seekg(size);
1262                 
1263                         while(in.get()){
1264                                 if(in.eof())            {       break;  }
1265                                 else                            {       size++; }
1266                         }
1267                         in.close();
1268                 
1269                         positions.push_back(size);
1270                         positions[0] = 0;
1271                 
1272                         return positions;
1273         }
1274         catch(exception& e) {
1275                 errorOut(e, "MothurOut", "setFilePosFasta");
1276                 exit(1);
1277         }
1278 }
1279 /**************************************************************************************************/
1280 vector<unsigned long long> MothurOut::setFilePosEachLine(string filename, int& num) {
1281         try {
1282                         filename = getFullPathName(filename);
1283                         
1284                         vector<unsigned long long> positions;
1285                         ifstream in;
1286                         //openInputFile(filename, in);
1287                         in.open(filename.c_str(), ios::binary);
1288                 
1289                         string input;
1290                         unsigned long long count = 0;
1291                         positions.push_back(0);
1292                 
1293                         while(!in.eof()){
1294                                 //unsigned long long lastpos = in.tellg();
1295                                 //input = getline(in); 
1296                                 //if (input.length() != 0) {
1297                                         //unsigned long long pos = in.tellg(); 
1298                                         //if (pos != -1) { positions.push_back(pos - input.length() - 1);       }
1299                                         //else {  positions.push_back(lastpos);  }
1300                                 //}
1301                                 //gobble(in); //has to be here since windows line endings are 2 characters and mess up the positions
1302                                 
1303                                 
1304                                 //getline counting reads
1305                                 char d = in.get(); count++;
1306                                 while ((d != '\n') && (d != '\r') && (d != '\f') && (d != in.eof()))    {
1307                                         //get next character
1308                                         d = in.get(); 
1309                                         count++;
1310                                 }
1311                                 
1312                                 if (!in.eof()) {
1313                                         d=in.get(); count++;
1314                                         while(isspace(d) && (d != in.eof()))            { d=in.get(); count++;}
1315                                 }
1316                                 positions.push_back(count-1);
1317                                 //cout << count-1 << endl;
1318                         }
1319                         in.close();
1320                 
1321                         num = positions.size()-1;
1322                 
1323                         FILE * pFile;
1324                         unsigned long long size;
1325                         
1326                         //get num bytes in file
1327                         pFile = fopen (filename.c_str(),"rb");
1328                         if (pFile==NULL) perror ("Error opening file");
1329                         else{
1330                                 fseek (pFile, 0, SEEK_END);
1331                                 size=ftell (pFile);
1332                                 fclose (pFile);
1333                         }
1334                 
1335                         positions[(positions.size()-1)] = size;
1336                 
1337                         return positions;
1338         }
1339         catch(exception& e) {
1340                 errorOut(e, "MothurOut", "setFilePosEachLine");
1341                 exit(1);
1342         }
1343 }
1344 /**************************************************************************************************/
1345
1346 vector<unsigned long long> MothurOut::divideFile(string filename, int& proc) {
1347         try{
1348                 vector<unsigned long long> filePos;
1349                 filePos.push_back(0);
1350                 
1351                 FILE * pFile;
1352                 unsigned long long size;
1353                 
1354                 filename = getFullPathName(filename);
1355         
1356                 //get num bytes in file
1357                 pFile = fopen (filename.c_str(),"rb");
1358                 if (pFile==NULL) perror ("Error opening file");
1359                 else{
1360                         fseek (pFile, 0, SEEK_END);
1361                         size=ftell (pFile);
1362                         fclose (pFile);
1363                 }
1364                 
1365         #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix)
1366                                 
1367                 //estimate file breaks
1368                 unsigned long long chunkSize = 0;
1369                 chunkSize = size / proc;
1370
1371                 //file to small to divide by processors
1372                 if (chunkSize == 0)  {  proc = 1;       filePos.push_back(size); return filePos;        }
1373         
1374                 //for each process seekg to closest file break and search for next '>' char. make that the filebreak
1375                 for (int i = 0; i < proc; i++) {
1376                         unsigned long long spot = (i+1) * chunkSize;
1377                         
1378                         ifstream in;
1379                         openInputFile(filename, in);
1380                         in.seekg(spot);
1381                         
1382                         //look for next '>'
1383                         unsigned long long newSpot = spot;
1384                         while (!in.eof()) {
1385                            char c = in.get();
1386                                 
1387                            if (c == '>') {   in.putback(c); newSpot = in.tellg(); break;  }
1388                            else if (int(c) == -1) { break; }
1389                                 
1390                         }
1391                 
1392                         //there was not another sequence before the end of the file
1393                         unsigned long long sanityPos = in.tellg();
1394
1395                         if (sanityPos == -1) {  break;  }
1396                         else {  filePos.push_back(newSpot);  }
1397                         
1398                         in.close();
1399                 }
1400                 
1401                 //save end pos
1402                 filePos.push_back(size);
1403                 
1404                 //sanity check filePos
1405                 for (int i = 0; i < (filePos.size()-1); i++) {
1406                         if (filePos[(i+1)] <= filePos[i]) {  filePos.erase(filePos.begin()+(i+1)); i--; }
1407                 }
1408
1409                 proc = (filePos.size() - 1);
1410 #else
1411                 mothurOut("[ERROR]: Windows version should not be calling the divideFile function."); mothurOutEndLine();
1412                 proc=1;
1413                 filePos.push_back(size);
1414 #endif
1415                 return filePos;
1416         }
1417         catch(exception& e) {
1418                 errorOut(e, "MothurOut", "divideFile");
1419                 exit(1);
1420         }
1421 }
1422 /**************************************************************************************************/
1423 int MothurOut::divideFile(string filename, int& proc, vector<string>& files) {
1424         try{
1425                 
1426                 vector<unsigned long long> filePos = divideFile(filename, proc);
1427                 
1428                 for (int i = 0; i < (filePos.size()-1); i++) {
1429                         
1430                         //read file chunk
1431                         ifstream in;
1432                         openInputFile(filename, in);
1433                         in.seekg(filePos[i]);
1434                         unsigned long long size = filePos[(i+1)] - filePos[i];
1435                         char* chunk = new char[size];
1436                         in.read(chunk, size);
1437                         in.close();
1438                         
1439                         //open new file
1440                         string fileChunkName = filename + "." + toString(i) + ".tmp";
1441                         ofstream out; 
1442                         openOutputFile(fileChunkName, out);
1443                         
1444                         out << chunk << endl;
1445                         out.close();
1446                         delete[] chunk;
1447                         
1448                         //save name
1449                         files.push_back(fileChunkName);
1450                 }
1451                                 
1452                 return 0;
1453         }
1454         catch(exception& e) {
1455                 errorOut(e, "MothurOut", "divideFile");
1456                 exit(1);
1457         }
1458 }
1459 /***********************************************************************/
1460
1461 bool MothurOut::isTrue(string f){
1462         try {
1463                 
1464                 for (int i = 0; i < f.length(); i++) { f[i] = toupper(f[i]); }
1465                 
1466                 if ((f == "TRUE") || (f == "T")) {      return true;    }
1467                 else {  return false;  }
1468         }
1469         catch(exception& e) {
1470                 errorOut(e, "MothurOut", "isTrue");
1471                 exit(1);
1472         }
1473 }
1474
1475 /***********************************************************************/
1476
1477 float MothurOut::roundDist(float dist, int precision){
1478         try {
1479                 return int(dist * precision + 0.5)/float(precision);
1480         }
1481         catch(exception& e) {
1482                 errorOut(e, "MothurOut", "roundDist");
1483                 exit(1);
1484         }
1485 }
1486 /***********************************************************************/
1487
1488 float MothurOut::ceilDist(float dist, int precision){
1489         try {
1490                 return int(ceil(dist * precision))/float(precision);
1491         }
1492         catch(exception& e) {
1493                 errorOut(e, "MothurOut", "ceilDist");
1494                 exit(1);
1495         }
1496 }
1497 /***********************************************************************/
1498
1499 vector<string> MothurOut::splitWhiteSpace(string& rest, char buffer[], int size){
1500         try {
1501         vector<string> pieces;
1502         
1503         for (int i = 0; i < size; i++) {
1504             if (!isspace(buffer[i]))  { rest += buffer[i];  }
1505             else {
1506                 pieces.push_back(rest);  rest = "";
1507                 while (i < size) {  //gobble white space
1508                     if (isspace(buffer[i])) { i++; }
1509                     else { rest = buffer[i];  break; } //cout << "next piece buffer = " << nextPiece << endl;
1510                 } 
1511             }
1512         }
1513         
1514         return pieces;
1515         }
1516         catch(exception& e) {
1517                 errorOut(e, "MothurOut", "splitWhiteSpace");
1518                 exit(1);
1519         }
1520 }
1521 /***********************************************************************/
1522 vector<string> MothurOut::splitWhiteSpace(string input){
1523         try {
1524         vector<string> pieces;
1525         string rest = "";
1526         
1527         for (int i = 0; i < input.length(); i++) {
1528             if (!isspace(input[i]))  { rest += input[i];  }
1529             else {
1530                 pieces.push_back(rest);  rest = "";
1531                 while (i < input.length()) {  //gobble white space
1532                     if (isspace(input[i])) { i++; }
1533                     else { rest = input[i];  break; } //cout << "next piece buffer = " << nextPiece << endl;
1534                 } 
1535             }
1536         }
1537         
1538         if (rest != "") { pieces.push_back(rest); }
1539         
1540         return pieces;
1541         }
1542         catch(exception& e) {
1543                 errorOut(e, "MothurOut", "splitWhiteSpace");
1544                 exit(1);
1545         }
1546 }
1547 //**********************************************************************************************************************
1548 int MothurOut::readTax(string namefile, map<string, string>& taxMap) {
1549         try {
1550                 
1551         //open input file
1552                 ifstream in;
1553                 openInputFile(namefile, in);
1554         
1555         string rest = "";
1556         char buffer[4096];
1557         bool pairDone = false;
1558         bool columnOne = true;
1559         string firstCol, secondCol;
1560         
1561                 while (!in.eof()) {
1562                         if (control_pressed) { break; }
1563                         
1564             in.read(buffer, 4096);
1565             vector<string> pieces = splitWhiteSpace(rest, buffer, in.gcount());
1566             
1567             for (int i = 0; i < pieces.size(); i++) {
1568                 if (columnOne) {  firstCol = pieces[i]; columnOne=false; }
1569                 else  { secondCol = pieces[i]; pairDone = true; columnOne=true; }
1570                 
1571                 if (pairDone) { 
1572                     //are there confidence scores, if so remove them
1573                     if (secondCol.find_first_of('(') != -1) {  removeConfidences(secondCol);    }
1574                     taxMap[firstCol] = secondCol;
1575                     if (debug) {  mothurOut("[DEBUG]: name = '" + firstCol + "' tax = '" + secondCol + "'\n");  }
1576                     pairDone = false; 
1577                 }
1578             }
1579                 }
1580                 in.close();
1581                 
1582                 return taxMap.size();
1583
1584         }
1585         catch(exception& e) {
1586                 errorOut(e, "MothurOut", "readTax");
1587                 exit(1);
1588         }
1589 }
1590 /**********************************************************************************************************************/
1591 int MothurOut::readNames(string namefile, map<string, string>& nameMap, bool redund) { 
1592         try {
1593                 
1594                 //open input file
1595                 ifstream in;
1596                 openInputFile(namefile, in);
1597         
1598         string rest = "";
1599         char buffer[4096];
1600         bool pairDone = false;
1601         bool columnOne = true;
1602         string firstCol, secondCol;
1603         
1604                 while (!in.eof()) {
1605                         if (control_pressed) { break; }
1606                         
1607             in.read(buffer, 4096);
1608             vector<string> pieces = splitWhiteSpace(rest, buffer, in.gcount());
1609             
1610             for (int i = 0; i < pieces.size(); i++) {
1611                 if (columnOne) {  firstCol = pieces[i]; columnOne=false; }
1612                 else  { secondCol = pieces[i]; pairDone = true; columnOne=true; }
1613                 
1614                 if (pairDone) { 
1615                     //parse names into vector
1616                     vector<string> theseNames;
1617                     splitAtComma(secondCol, theseNames);
1618                     for (int i = 0; i < theseNames.size(); i++) {  nameMap[theseNames[i]] = firstCol;  }
1619                     pairDone = false; 
1620                 }
1621             }
1622                 }
1623                 in.close();
1624                 
1625                 return nameMap.size();
1626                 
1627         }
1628         catch(exception& e) {
1629                 errorOut(e, "MothurOut", "readNames");
1630                 exit(1);
1631         }
1632 }
1633 /**********************************************************************************************************************/
1634 int MothurOut::readNames(string namefile, map<string, string>& nameMap, int flip) { 
1635         try {
1636                 
1637                 //open input file
1638                 ifstream in;
1639                 openInputFile(namefile, in);
1640         
1641         string rest = "";
1642         char buffer[4096];
1643         bool pairDone = false;
1644         bool columnOne = true;
1645         string firstCol, secondCol;
1646         
1647                 while (!in.eof()) {
1648                         if (control_pressed) { break; }
1649                         
1650             in.read(buffer, 4096);
1651             vector<string> pieces = splitWhiteSpace(rest, buffer, in.gcount());
1652             
1653             for (int i = 0; i < pieces.size(); i++) {
1654                 if (columnOne) {  firstCol = pieces[i]; columnOne=false; }
1655                 else  { secondCol = pieces[i]; pairDone = true; columnOne=true; }
1656                 
1657                 if (pairDone) { 
1658                     nameMap[secondCol] = firstCol;
1659                     pairDone = false; 
1660                 }
1661             }
1662                 }
1663                 in.close();
1664                 
1665                 return nameMap.size();
1666                 
1667         }
1668         catch(exception& e) {
1669                 errorOut(e, "MothurOut", "readNames");
1670                 exit(1);
1671         }
1672 }
1673 /**********************************************************************************************************************/
1674 int MothurOut::readNames(string namefile, map<string, string>& nameMap, map<string, int>& nameCount) { 
1675         try {
1676                 nameMap.clear(); nameCount.clear();
1677                 //open input file
1678                 ifstream in;
1679                 openInputFile(namefile, in);
1680         
1681         string rest = "";
1682         char buffer[4096];
1683         bool pairDone = false;
1684         bool columnOne = true;
1685         string firstCol, secondCol;
1686         
1687                 while (!in.eof()) {
1688                         if (control_pressed) { break; }
1689                         
1690             in.read(buffer, 4096);
1691             vector<string> pieces = splitWhiteSpace(rest, buffer, in.gcount());
1692             
1693             for (int i = 0; i < pieces.size(); i++) {
1694                 if (columnOne) {  firstCol = pieces[i]; columnOne=false; }
1695                 else  { secondCol = pieces[i]; pairDone = true; columnOne=true; }
1696                 
1697                 if (pairDone) { 
1698                     //parse names into vector
1699                     vector<string> theseNames;
1700                     splitAtComma(secondCol, theseNames);
1701                     for (int i = 0; i < theseNames.size(); i++) {  nameMap[theseNames[i]] = firstCol;  }
1702                     nameCount[firstCol] = theseNames.size();
1703                     pairDone = false; 
1704                 }
1705             }
1706                 }
1707                 in.close();
1708                 
1709                 return nameMap.size();
1710                 
1711         }
1712         catch(exception& e) {
1713                 errorOut(e, "MothurOut", "readNames");
1714                 exit(1);
1715         }
1716 }
1717 /**********************************************************************************************************************/
1718 int MothurOut::readNames(string namefile, map<string, string>& nameMap) { 
1719         try {
1720                 
1721                 //open input file
1722                 ifstream in;
1723                 openInputFile(namefile, in);
1724
1725         string rest = "";
1726         char buffer[4096];
1727         bool pairDone = false;
1728         bool columnOne = true;
1729         string firstCol, secondCol;
1730         
1731                 while (!in.eof()) {
1732                         if (control_pressed) { break; }
1733                         
1734             in.read(buffer, 4096);
1735             vector<string> pieces = splitWhiteSpace(rest, buffer, in.gcount());
1736              
1737             for (int i = 0; i < pieces.size(); i++) {
1738                 if (columnOne) {  firstCol = pieces[i]; columnOne=false; }
1739                 else  { secondCol = pieces[i]; pairDone = true; columnOne=true; }
1740                 
1741                 if (pairDone) { nameMap[firstCol] = secondCol; pairDone = false; }
1742             }
1743                 }
1744                 in.close();
1745                 
1746                 return nameMap.size();
1747                 
1748         }
1749         catch(exception& e) {
1750                 errorOut(e, "MothurOut", "readNames");
1751                 exit(1);
1752         }
1753 }
1754 /**********************************************************************************************************************/
1755 int MothurOut::readNames(string namefile, map<string, vector<string> >& nameMap) { 
1756         try {
1757                 
1758                 //open input file
1759                 ifstream in;
1760                 openInputFile(namefile, in);
1761                 
1762         string rest = "";
1763         char buffer[4096];
1764         bool pairDone = false;
1765         bool columnOne = true;
1766         string firstCol, secondCol;
1767         
1768                 while (!in.eof()) {
1769                         if (control_pressed) { break; }
1770                         
1771             in.read(buffer, 4096);
1772             vector<string> pieces = splitWhiteSpace(rest, buffer, in.gcount());
1773             
1774             for (int i = 0; i < pieces.size(); i++) {
1775                 if (columnOne) {  firstCol = pieces[i]; columnOne=false; }
1776                 else  { secondCol = pieces[i]; pairDone = true; columnOne=true; }
1777                 
1778                 if (pairDone) { 
1779                     vector<string> temp;
1780                     splitAtComma(secondCol, temp);
1781                     nameMap[firstCol] = temp;
1782                     pairDone = false;  
1783                 } 
1784             }
1785                 }
1786                 in.close();
1787         
1788                 return nameMap.size();
1789         }
1790         catch(exception& e) {
1791                 errorOut(e, "MothurOut", "readNames");
1792                 exit(1);
1793         }
1794 }
1795 /**********************************************************************************************************************/
1796 map<string, int> MothurOut::readNames(string namefile) { 
1797         try {
1798                 
1799                 map<string, int> nameMap;
1800                 
1801                 //open input file
1802                 ifstream in;
1803                 openInputFile(namefile, in);
1804                 
1805         string rest = "";
1806         char buffer[4096];
1807         bool pairDone = false;
1808         bool columnOne = true;
1809         string firstCol, secondCol;
1810         
1811                 while (!in.eof()) {
1812                         if (control_pressed) { break; }
1813                         
1814             in.read(buffer, 4096);
1815             vector<string> pieces = splitWhiteSpace(rest, buffer, in.gcount());
1816             
1817             for (int i = 0; i < pieces.size(); i++) {
1818                 if (columnOne) {  firstCol = pieces[i]; columnOne=false; }
1819                 else  { secondCol = pieces[i]; pairDone = true; columnOne=true; }
1820                 
1821                 if (pairDone) { 
1822                     int num = getNumNames(secondCol);
1823                     nameMap[firstCol] = num;
1824                     pairDone = false;  
1825                 } 
1826             }
1827                 }
1828         in.close();
1829                 
1830                 return nameMap;
1831                 
1832         }
1833         catch(exception& e) {
1834                 errorOut(e, "MothurOut", "readNames");
1835                 exit(1);
1836         }
1837 }
1838 /**********************************************************************************************************************/
1839 int MothurOut::readNames(string namefile, vector<seqPriorityNode>& nameVector, map<string, string>& fastamap) { 
1840         try {
1841                 int error = 0;
1842                 
1843                 //open input file
1844                 ifstream in;
1845                 openInputFile(namefile, in);
1846                 
1847         string rest = "";
1848         char buffer[4096];
1849         bool pairDone = false;
1850         bool columnOne = true;
1851         string firstCol, secondCol;
1852         
1853                 while (!in.eof()) {
1854                         if (control_pressed) { break; }
1855                         
1856             in.read(buffer, 4096);
1857             vector<string> pieces = splitWhiteSpace(rest, buffer, in.gcount());
1858             
1859             for (int i = 0; i < pieces.size(); i++) {
1860                 if (columnOne) {  firstCol = pieces[i]; columnOne=false; }
1861                 else  { secondCol = pieces[i]; pairDone = true; columnOne=true; }
1862                 
1863                 if (pairDone) { 
1864                     int num = getNumNames(secondCol);
1865                     
1866                     map<string, string>::iterator it = fastamap.find(firstCol);
1867                     if (it == fastamap.end()) {
1868                         error = 1;
1869                         mothurOut("[ERROR]: " + firstCol + " is not in your fastafile, but is in your namesfile, please correct."); mothurOutEndLine();
1870                     }else {
1871                         seqPriorityNode temp(num, it->second, firstCol);
1872                         nameVector.push_back(temp);
1873                     }
1874                     
1875                     pairDone = false;  
1876                 } 
1877             }
1878                 }
1879         in.close();
1880         
1881                 return error;
1882         }
1883         catch(exception& e) {
1884                 errorOut(e, "MothurOut", "readNames");
1885                 exit(1);
1886         }
1887 }
1888 //**********************************************************************************************************************
1889 set<string> MothurOut::readAccnos(string accnosfile){
1890         try {
1891                 set<string> names;
1892                 ifstream in;
1893                 openInputFile(accnosfile, in);
1894                 string name;
1895                 
1896         string rest = "";
1897         char buffer[4096];
1898         
1899                 while (!in.eof()) {
1900                         if (control_pressed) { break; }
1901                         
1902             in.read(buffer, 4096);
1903             vector<string> pieces = splitWhiteSpace(rest, buffer, in.gcount());
1904             
1905             for (int i = 0; i < pieces.size(); i++) {  names.insert(pieces[i]);  }
1906         }
1907                 in.close();     
1908                 
1909                 return names;
1910         }
1911         catch(exception& e) {
1912                 errorOut(e, "MothurOut", "readAccnos");
1913                 exit(1);
1914         }
1915 }
1916 //**********************************************************************************************************************
1917 int MothurOut::readAccnos(string accnosfile, vector<string>& names){
1918         try {
1919         names.clear();
1920                 ifstream in;
1921                 openInputFile(accnosfile, in);
1922                 string name;
1923                 
1924         string rest = "";
1925         char buffer[4096];
1926         
1927                 while (!in.eof()) {
1928                         if (control_pressed) { break; }
1929                         
1930             in.read(buffer, 4096);
1931             vector<string> pieces = splitWhiteSpace(rest, buffer, in.gcount());
1932             
1933             for (int i = 0; i < pieces.size(); i++) {  names.push_back(pieces[i]);  }
1934         }
1935                 in.close();     
1936                 
1937                 return 0;
1938         }
1939         catch(exception& e) {
1940                 errorOut(e, "MothurOut", "readAccnos");
1941                 exit(1);
1942         }
1943 }
1944 /***********************************************************************/
1945
1946 int MothurOut::getNumNames(string names){
1947         try {
1948                 int count = 0;
1949                 
1950                 if(names != ""){
1951                         count = 1;
1952                         for(int i=0;i<names.size();i++){
1953                                 if(names[i] == ','){
1954                                         count++;
1955                                 }
1956                         }
1957                 }
1958                 
1959                 return count;
1960         }
1961         catch(exception& e) {
1962                 errorOut(e, "MothurOut", "getNumNames");
1963                 exit(1);
1964         }
1965 }
1966 /***********************************************************************/
1967
1968 int MothurOut::getNumChar(string line, char c){
1969         try {
1970                 int count = 0;
1971                 
1972                 if(line != ""){
1973                         for(int i=0;i<line.size();i++){
1974                                 if(line[i] == c){
1975                                         count++;
1976                                 }
1977                         }
1978                 }
1979                 
1980                 return count;
1981         }
1982         catch(exception& e) {
1983                 errorOut(e, "MothurOut", "getNumChar");
1984                 exit(1);
1985         }
1986 }
1987 /***********************************************************************/
1988 int MothurOut::mothurRemove(string filename){
1989         try {
1990                 filename = getFullPathName(filename);
1991                 int error = remove(filename.c_str());
1992                 //if (error != 0) { 
1993                 //      if (errno != ENOENT) { //ENOENT == file does not exist
1994                 //              string message = "Error deleting file " + filename;
1995                 //              perror(message.c_str()); 
1996                 //      }
1997                 //}
1998                 return error;
1999         }
2000         catch(exception& e) {
2001                 errorOut(e, "MothurOut", "mothurRemove");
2002                 exit(1);
2003         }
2004 }
2005 /***********************************************************************/
2006 bool MothurOut::mothurConvert(string item, int& num){
2007         try {
2008                 bool error = false;
2009                 
2010                 if (isNumeric1(item)) {
2011                         convert(item, num);
2012                 }else {
2013                         num = 0;
2014                         error = true;
2015                         mothurOut("[ERROR]: cannot convert " + item + " to an integer."); mothurOutEndLine();
2016                         commandInputsConvertError = true;
2017                 }
2018                 
2019                 return error;
2020         }
2021         catch(exception& e) {
2022                 errorOut(e, "MothurOut", "mothurConvert");
2023                 exit(1);
2024         }
2025 }
2026 /***********************************************************************/
2027 bool MothurOut::isNumeric1(string stringToCheck){
2028         try {
2029                 bool numeric = false;
2030                 
2031                 if(stringToCheck.find_first_not_of("0123456789.-") == string::npos) { numeric = true; }
2032                         
2033                 return numeric;
2034         }
2035         catch(exception& e) {
2036                 errorOut(e, "MothurOut", "isNumeric1");
2037                 exit(1);
2038         }
2039         
2040 }
2041 /***********************************************************************/
2042 bool MothurOut::mothurConvert(string item, float& num){
2043         try {
2044                 bool error = false;
2045                 
2046                 if (isNumeric1(item)) {
2047                         convert(item, num);
2048                 }else {
2049                         num = 0;
2050                         error = true;
2051                         mothurOut("[ERROR]: cannot convert " + item + " to a float."); mothurOutEndLine();
2052                         commandInputsConvertError = true;
2053                 }
2054                 
2055                 return error;
2056         }
2057         catch(exception& e) {
2058                 errorOut(e, "MothurOut", "mothurConvert");
2059                 exit(1);
2060         }
2061 }
2062 /***********************************************************************/
2063 bool MothurOut::mothurConvert(string item, double& num){
2064         try {
2065                 bool error = false;
2066                 
2067                 if (isNumeric1(item)) {
2068                         convert(item, num);
2069                 }else {
2070                         num = 0;
2071                         error = true;
2072                         mothurOut("[ERROR]: cannot convert " + item + " to a double."); mothurOutEndLine();
2073                         commandInputsConvertError = true;
2074                 }
2075                 
2076                 return error;
2077         }
2078         catch(exception& e) {
2079                 errorOut(e, "MothurOut", "mothurConvert");
2080                 exit(1);
2081         }
2082 }
2083 /**************************************************************************************************/
2084
2085 vector<vector<double> > MothurOut::binomial(int maxOrder){
2086         try {
2087         vector<vector<double> > binomial(maxOrder+1);
2088         
2089     for(int i=0;i<=maxOrder;i++){
2090                 binomial[i].resize(maxOrder+1);
2091                 binomial[i][0]=1;
2092                 binomial[0][i]=0;
2093     }
2094     binomial[0][0]=1;
2095         
2096     binomial[1][0]=1;
2097     binomial[1][1]=1;
2098         
2099     for(int i=2;i<=maxOrder;i++){
2100                 binomial[1][i]=0;
2101     }
2102         
2103     for(int i=2;i<=maxOrder;i++){
2104                 for(int j=1;j<=maxOrder;j++){
2105                         if(i==j){       binomial[i][j]=1;                                                                       }
2106                         if(j>i) {       binomial[i][j]=0;                                                                       }
2107                         else    {       binomial[i][j]=binomial[i-1][j-1]+binomial[i-1][j];     }
2108                 }
2109     }
2110         
2111         return binomial;
2112         
2113         }
2114         catch(exception& e) {
2115                 errorOut(e, "MothurOut", "binomial");
2116                 exit(1);
2117         }
2118 }
2119 /**************************************************************************************************/
2120 unsigned int MothurOut::fromBase36(string base36){
2121         try {
2122                 unsigned int num = 0;
2123                 
2124                 map<char, int> converts;
2125                 converts['A'] = 0;
2126                 converts['a'] = 0;
2127                 converts['B'] = 1;
2128                 converts['b'] = 1;
2129                 converts['C'] = 2;
2130                 converts['c'] = 2;
2131                 converts['D'] = 3;
2132                 converts['d'] = 3;
2133                 converts['E'] = 4;
2134                 converts['e'] = 4;
2135                 converts['F'] = 5;
2136                 converts['f'] = 5;
2137                 converts['G'] = 6;
2138                 converts['g'] = 6;
2139                 converts['H'] = 7;
2140                 converts['h'] = 7;
2141                 converts['I'] = 8;
2142                 converts['i'] = 8;
2143                 converts['J'] = 9;
2144                 converts['j'] = 9;
2145                 converts['K'] = 10;
2146                 converts['k'] = 10;
2147                 converts['L'] = 11;
2148                 converts['l'] = 11;
2149                 converts['M'] = 12;
2150                 converts['m'] = 12;
2151                 converts['N'] = 13;
2152                 converts['n'] = 13;
2153                 converts['O'] = 14;
2154                 converts['o'] = 14;
2155                 converts['P'] = 15;
2156                 converts['p'] = 15;
2157                 converts['Q'] = 16;
2158                 converts['q'] = 16;
2159                 converts['R'] = 17;
2160                 converts['r'] = 17;
2161                 converts['S'] = 18;
2162                 converts['s'] = 18;
2163                 converts['T'] = 19;
2164                 converts['t'] = 19;
2165                 converts['U'] = 20;
2166                 converts['u'] = 20;
2167                 converts['V'] = 21;
2168                 converts['v'] = 21;
2169                 converts['W'] = 22;
2170                 converts['w'] = 22;
2171                 converts['X'] = 23;
2172                 converts['x'] = 23;
2173                 converts['Y'] = 24;
2174                 converts['y'] = 24;
2175                 converts['Z'] = 25;
2176                 converts['z'] = 25;
2177                 converts['0'] = 26;
2178                 converts['1'] = 27;
2179                 converts['2'] = 28;
2180                 converts['3'] = 29;
2181                 converts['4'] = 30;
2182                 converts['5'] = 31;
2183                 converts['6'] = 32;
2184                 converts['7'] = 33;
2185                 converts['8'] = 34;
2186                 converts['9'] = 35;             
2187                 
2188                 int i = 0;
2189                 while (i < base36.length()) {
2190                         char c = base36[i];
2191                         num = 36 * num + converts[c];
2192                         i++;
2193                 }
2194                 
2195                 return num;
2196                 
2197         }
2198         catch(exception& e) {
2199                 errorOut(e, "MothurOut", "fromBase36");
2200                 exit(1);
2201         }
2202 }
2203 /***********************************************************************/
2204
2205 int MothurOut::factorial(int num){
2206         try {
2207                 int total = 1;
2208                 
2209                 for (int i = 1; i <= num; i++) {
2210                         total *= i;
2211                 }
2212                 
2213                 return total;
2214         }
2215         catch(exception& e) {
2216                 errorOut(e, "MothurOut", "factorial");
2217                 exit(1);
2218         }
2219 }
2220 /***********************************************************************/
2221
2222 int MothurOut::getNumSeqs(ifstream& file){
2223         try {
2224                 int numSeqs = count(istreambuf_iterator<char>(file),istreambuf_iterator<char>(), '>');
2225                 file.seekg(0);
2226                 return numSeqs;
2227         }
2228         catch(exception& e) {
2229                 errorOut(e, "MothurOut", "getNumSeqs");
2230                 exit(1);
2231         }       
2232 }
2233 /***********************************************************************/
2234 void MothurOut::getNumSeqs(ifstream& file, int& numSeqs){
2235         try {
2236                 string input;
2237                 numSeqs = 0;
2238                 while(!file.eof()){
2239                         input = getline(file);
2240                         if (input.length() != 0) {
2241                                 if(input[0] == '>'){ numSeqs++; }
2242                         }
2243                 }
2244         }
2245         catch(exception& e) {
2246                 errorOut(e, "MothurOut", "getNumSeqs");
2247                 exit(1);
2248         }       
2249 }
2250 /***********************************************************************/
2251
2252 //This function parses the estimator options and puts them in a vector
2253 void MothurOut::splitAtChar(string& estim, vector<string>& container, char symbol) {
2254         try {
2255                 string individual = "";
2256                 int estimLength = estim.size();
2257                 for(int i=0;i<estimLength;i++){
2258                         if(estim[i] == symbol){
2259                                 container.push_back(individual);
2260                                 individual = "";                                
2261                         }
2262                         else{
2263                                 individual += estim[i];
2264                         }
2265                 }
2266                 container.push_back(individual);
2267
2268         }
2269         catch(exception& e) {
2270                 errorOut(e, "MothurOut", "splitAtChar");
2271                 exit(1);
2272         }       
2273 }
2274
2275 /***********************************************************************/
2276
2277 //This function parses the estimator options and puts them in a vector
2278 void MothurOut::splitAtDash(string& estim, vector<string>& container) {
2279         try {
2280                 string individual = "";
2281                 int estimLength = estim.size();
2282                 for(int i=0;i<estimLength;i++){
2283                         if(estim[i] == '-'){
2284                                 container.push_back(individual);
2285                                 individual = "";                                
2286                         }
2287                         else{
2288                                 individual += estim[i];
2289                         }
2290                 }
2291                 container.push_back(individual);
2292
2293         
2294         /*      string individual;
2295                 
2296                 while (estim.find_first_of('-') != -1) {
2297                         individual = estim.substr(0,estim.find_first_of('-'));
2298                         if ((estim.find_first_of('-')+1) <= estim.length()) { //checks to make sure you don't have dash at end of string
2299                                 estim = estim.substr(estim.find_first_of('-')+1, estim.length());
2300                                 container.push_back(individual);
2301                         }
2302                 }
2303                 //get last one
2304                 container.push_back(estim); */
2305         }
2306         catch(exception& e) {
2307                 errorOut(e, "MothurOut", "splitAtDash");
2308                 exit(1);
2309         }       
2310 }
2311
2312 /***********************************************************************/
2313 //This function parses the label options and puts them in a set
2314 void MothurOut::splitAtDash(string& estim, set<string>& container) {
2315         try {
2316                 string individual = "";
2317                 int estimLength = estim.size();
2318                 for(int i=0;i<estimLength;i++){
2319                         if(estim[i] == '-'){
2320                                 container.insert(individual);
2321                                 individual = "";                                
2322                         }
2323                         else{
2324                                 individual += estim[i];
2325                         }
2326                 }
2327                 container.insert(individual);
2328
2329         //      string individual;
2330                 
2331         //      while (estim.find_first_of('-') != -1) {
2332         //              individual = estim.substr(0,estim.find_first_of('-'));
2333         //              if ((estim.find_first_of('-')+1) <= estim.length()) { //checks to make sure you don't have dash at end of string
2334         //                      estim = estim.substr(estim.find_first_of('-')+1, estim.length());
2335         //                      container.insert(individual);
2336         //              }
2337         //      }
2338                 //get last one
2339         //      container.insert(estim);
2340         
2341         }
2342         catch(exception& e) {
2343                 errorOut(e, "MothurOut", "splitAtDash");
2344                 exit(1);
2345         }       
2346 }
2347 /***********************************************************************/
2348 //This function parses the line options and puts them in a set
2349 void MothurOut::splitAtDash(string& estim, set<int>& container) {
2350         try {
2351                 string individual;
2352                 int lineNum;
2353                 
2354                 while (estim.find_first_of('-') != -1) {
2355                         individual = estim.substr(0,estim.find_first_of('-'));
2356                         if ((estim.find_first_of('-')+1) <= estim.length()) { //checks to make sure you don't have dash at end of string
2357                                 estim = estim.substr(estim.find_first_of('-')+1, estim.length());
2358                                 convert(individual, lineNum); //convert the string to int
2359                                 container.insert(lineNum);
2360                         }
2361                 }
2362                 //get last one
2363                 convert(estim, lineNum); //convert the string to int
2364                 container.insert(lineNum);
2365         }
2366         catch(exception& e) {
2367                 errorOut(e, "MothurOut", "splitAtDash");
2368                 exit(1);
2369         }       
2370 }
2371 /***********************************************************************/
2372 string MothurOut::makeList(vector<string>& names) {
2373         try {
2374                 string list = "";
2375         
2376         if (names.size() == 0) { return list; }
2377                 
2378         for (int i = 0; i < names.size()-1; i++) { list += names[i] + ",";  }
2379         
2380         //get last name
2381         list += names[names.size()-1];
2382         
2383         return list;
2384     }
2385         catch(exception& e) {
2386                 errorOut(e, "MothurOut", "makeList");
2387                 exit(1);
2388         }       
2389 }
2390
2391 /***********************************************************************/
2392 //This function parses the a string and puts peices in a vector
2393 void MothurOut::splitAtComma(string& estim, vector<string>& container) {
2394         try {
2395                 string individual = "";
2396                 int estimLength = estim.size();
2397                 for(int i=0;i<estimLength;i++){
2398                         if(estim[i] == ','){
2399                                 container.push_back(individual);
2400                                 individual = "";                                
2401                         }
2402                         else{
2403                                 individual += estim[i];
2404                         }
2405                 }
2406                 container.push_back(individual);
2407                 
2408                 
2409                 
2410                 
2411 //              string individual;
2412 //              
2413 //              while (estim.find_first_of(',') != -1) {
2414 //                      individual = estim.substr(0,estim.find_first_of(','));
2415 //                      if ((estim.find_first_of(',')+1) <= estim.length()) { //checks to make sure you don't have comma at end of string
2416 //                              estim = estim.substr(estim.find_first_of(',')+1, estim.length());
2417 //                              container.push_back(individual);
2418 //                      }
2419 //              }
2420 //              //get last one
2421 //              container.push_back(estim);
2422         }
2423         catch(exception& e) {
2424                 errorOut(e, "MothurOut", "splitAtComma");
2425                 exit(1);
2426         }       
2427 }
2428 /***********************************************************************/
2429 //This function splits up the various option parameters
2430 void MothurOut::splitAtChar(string& prefix, string& suffix, char c){
2431         try {
2432                 prefix = suffix.substr(0,suffix.find_first_of(c));
2433                 if ((suffix.find_first_of(c)+2) <= suffix.length()) {  //checks to make sure you don't have comma at end of string
2434                         suffix = suffix.substr(suffix.find_first_of(c)+1, suffix.length());
2435                         string space = " ";
2436                         while(suffix.at(0) == ' ')
2437                                 suffix = suffix.substr(1, suffix.length());
2438                 }
2439         
2440         }
2441         catch(exception& e) {
2442                 errorOut(e, "MothurOut", "splitAtComma");
2443                 exit(1);
2444         }       
2445 }
2446
2447 /***********************************************************************/
2448
2449 //This function splits up the various option parameters
2450 void MothurOut::splitAtComma(string& prefix, string& suffix){
2451         try {
2452                 prefix = suffix.substr(0,suffix.find_first_of(','));
2453                 if ((suffix.find_first_of(',')+2) <= suffix.length()) {  //checks to make sure you don't have comma at end of string
2454                         suffix = suffix.substr(suffix.find_first_of(',')+1, suffix.length());
2455                         string space = " ";
2456                         while(suffix.at(0) == ' ')
2457                                 suffix = suffix.substr(1, suffix.length());
2458                 }
2459
2460         }
2461         catch(exception& e) {
2462                 errorOut(e, "MothurOut", "splitAtComma");
2463                 exit(1);
2464         }       
2465 }
2466 /***********************************************************************/
2467
2468 //This function separates the key value from the option value i.e. dist=96_...
2469 void MothurOut::splitAtEquals(string& key, string& value){              
2470         try {
2471                 if(value.find_first_of('=') != -1){
2472                         key = value.substr(0,value.find_first_of('='));
2473                         if ((value.find_first_of('=')+1) <= value.length()) {
2474                                 value = value.substr(value.find_first_of('=')+1, value.length());
2475                         }
2476                 }else{
2477                         key = value;
2478                         value = 1;
2479                 }
2480         }
2481         catch(exception& e) {
2482                 errorOut(e, "MothurOut", "splitAtEquals");
2483                 exit(1);
2484         }       
2485 }
2486
2487 /**************************************************************************************************/
2488
2489 bool MothurOut::inUsersGroups(string groupname, vector<string> Groups) {
2490         try {
2491                 for (int i = 0; i < Groups.size(); i++) {
2492                         if (groupname == Groups[i]) { return true; }
2493                 }
2494                 return false;
2495         }
2496         catch(exception& e) {
2497                 errorOut(e, "MothurOut", "inUsersGroups");
2498                 exit(1);
2499         }       
2500 }
2501 /**************************************************************************************************/
2502 //returns true if any of the strings in first vector are in second vector
2503 bool MothurOut::inUsersGroups(vector<string> groupnames, vector<string> Groups) {
2504         try {
2505                 
2506                 for (int i = 0; i < groupnames.size(); i++) {
2507                         if (inUsersGroups(groupnames[i], Groups)) { return true; }
2508                 }
2509                 return false;
2510         }
2511         catch(exception& e) {
2512                 errorOut(e, "MothurOut", "inUsersGroups");
2513                 exit(1);
2514         }       
2515 }
2516 /***********************************************************************/
2517 //this function determines if the user has given us labels that are smaller than the given label.
2518 //if so then it returns true so that the calling function can run the previous valid distance.
2519 //it's a "smart" distance function.  It also checks for invalid labels.
2520 bool MothurOut::anyLabelsToProcess(string label, set<string>& userLabels, string errorOff) {
2521         try {
2522                 
2523                 set<string>::iterator it;
2524                 vector<float> orderFloat;
2525                 map<string, float> userMap;  //the conversion process removes trailing 0's which we need to put back
2526                 map<string, float>::iterator it2;
2527                 float labelFloat;
2528                 bool smaller = false;
2529                 
2530                 //unique is the smallest line
2531                 if (label == "unique") {  return false;  }
2532                 else { 
2533                         if (convertTestFloat(label, labelFloat)) {
2534                                 convert(label, labelFloat); 
2535                         }else { //cant convert 
2536                                 return false;
2537                         }
2538                 }
2539                 
2540                 //go through users set and make them floats
2541                 for(it = userLabels.begin(); it != userLabels.end();) {
2542                         
2543                         float temp;
2544                         if ((*it != "unique") && (convertTestFloat(*it, temp) == true)){
2545                                 convert(*it, temp);
2546                                 orderFloat.push_back(temp);
2547                                 userMap[*it] = temp;
2548                                 it++;
2549                         }else if (*it == "unique") { 
2550                                 orderFloat.push_back(-1.0);
2551                                 userMap["unique"] = -1.0;
2552                                 it++;
2553                         }else {
2554                                 if (errorOff == "") {  mothurOut(*it + " is not a valid label."); mothurOutEndLine();  }
2555                                 userLabels.erase(it++); 
2556                         }
2557                 }
2558                 
2559                 //sort order
2560                 sort(orderFloat.begin(), orderFloat.end());
2561                 
2562                 /*************************************************/
2563                 //is this label bigger than any of the users labels
2564                 /*************************************************/
2565                                 
2566                 //loop through order until you find a label greater than label
2567                 for (int i = 0; i < orderFloat.size(); i++) {
2568                         if (orderFloat[i] < labelFloat) {
2569                                 smaller = true;
2570                                 if (orderFloat[i] == -1) { 
2571                                         if (errorOff == "") { mothurOut("Your file does not include the label unique."); mothurOutEndLine(); }
2572                                         userLabels.erase("unique");
2573                                 }
2574                                 else {  
2575                                         if (errorOff == "") { mothurOut("Your file does not include the label "); mothurOutEndLine(); }
2576                                         string s = "";
2577                                         for (it2 = userMap.begin(); it2!= userMap.end(); it2++) {  
2578                                                 if (it2->second == orderFloat[i]) {  
2579                                                         s = it2->first;  
2580                                                         //remove small labels
2581                                                         userLabels.erase(s);
2582                                                         break;
2583                                                 }
2584                                         }
2585                                         if (errorOff == "") {mothurOut( s +  ". I will use the next smallest distance. "); mothurOutEndLine(); }
2586                                 }
2587                         //since they are sorted once you find a bigger one stop looking
2588                         }else { break; }
2589                 }
2590                 
2591                 return smaller;
2592                                                 
2593         }
2594         catch(exception& e) {
2595                 errorOut(e, "MothurOut", "anyLabelsToProcess");
2596                 exit(1);
2597         }       
2598 }
2599
2600 /**************************************************************************************************/
2601 bool MothurOut::checkReleaseVersion(ifstream& file, string version) {
2602         try {
2603                 
2604                 bool good = true;
2605                 
2606                 string line = getline(file);  
2607
2608                 //before we added this check
2609                 if (line[0] != '#') {  good = false;  }
2610                 else {
2611                         //rip off #
2612                         line = line.substr(1);
2613                         
2614                         vector<string> versionVector;
2615                         splitAtChar(version, versionVector, '.');
2616                         
2617                         //check file version
2618                         vector<string> linesVector;
2619                         splitAtChar(line, linesVector, '.');
2620                         
2621                         if (versionVector.size() != linesVector.size()) { good = false; }
2622                         else {
2623                                 for (int j = 0; j < versionVector.size(); j++) {
2624                                         int num1, num2;
2625                                         convert(versionVector[j], num1);
2626                                         convert(linesVector[j], num2);
2627                                         
2628                                         //if mothurs version is newer than this files version, then we want to remake it
2629                                         if (num1 > num2) {  good = false; break;  }
2630                                 }
2631                         }
2632                         
2633                 }
2634                 
2635                 if (!good) {  file.close();  }
2636                 else { file.seekg(0);  }
2637                 
2638                 return good;
2639         }
2640         catch(exception& e) {
2641                 errorOut(e, "MothurOut", "checkReleaseVersion");                
2642                 exit(1);
2643         }
2644 }
2645 /**************************************************************************************************/
2646 bool MothurOut::isContainingOnlyDigits(string input) {
2647         try{
2648                 
2649                 //are you a digit in ascii code
2650                 for (int i = 0;i < input.length(); i++){
2651                         if( input[i]>47 && input[i]<58){}
2652                         else { return false; }
2653                 }
2654                 
2655                 return true;
2656         }
2657         catch(exception& e) {
2658                 errorOut(e, "MothurOut", "isContainingOnlyDigits");             
2659                 exit(1);
2660         }
2661 }
2662 /**************************************************************************************************/
2663 int MothurOut::removeConfidences(string& tax) {
2664         try {
2665                 
2666                 string taxon;
2667                 string newTax = "";
2668                 
2669                 while (tax.find_first_of(';') != -1) {
2670                         
2671                         if (control_pressed) { return 0; }
2672                         
2673                         //get taxon
2674                         taxon = tax.substr(0,tax.find_first_of(';'));
2675         
2676                         int pos = taxon.find_last_of('(');
2677                         if (pos != -1) {
2678                                 //is it a number?
2679                                 int pos2 = taxon.find_last_of(')');
2680                                 if (pos2 != -1) {
2681                                         string confidenceScore = taxon.substr(pos+1, (pos2-(pos+1)));
2682                                         if (isNumeric1(confidenceScore)) {
2683                                                 taxon = taxon.substr(0, pos); //rip off confidence 
2684                                         }
2685                                 }
2686                         }
2687                         taxon += ";";
2688                         
2689                         tax = tax.substr(tax.find_first_of(';')+1, tax.length());
2690                         newTax += taxon;
2691                 }
2692                 
2693                 tax = newTax;
2694                 
2695                 return 0;
2696         }
2697         catch(exception& e) {
2698                 errorOut(e, "MothurOut", "removeConfidences");
2699                 exit(1);
2700         }
2701 }
2702 /**************************************************************************************************/
2703
2704
2705
2706
2707