]> git.donarmstrong.com Git - mothur.git/blob - mothurout.cpp
fixes while testing 1.33.0
[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("summary");
27         types.insert("accnos");
28         types.insert("column");
29         types.insert("design");
30         types.insert("group");
31         types.insert("list");
32         types.insert("name");
33         types.insert("oligos");
34         types.insert("order");
35         types.insert("ordergroup");
36         types.insert("phylip");
37         types.insert("qfile");
38         types.insert("relabund");
39         types.insert("sabund");
40         types.insert("rabund");
41         types.insert("sff");
42         types.insert("shared");
43         types.insert("taxonomy");
44         types.insert("tree");
45         types.insert("flow");
46         types.insert("biom");
47         types.insert("count");
48         types.insert("processors");
49
50                 return types;
51         }
52         catch(exception& e) {
53                 errorOut(e, "MothurOut", "getCurrentTypes");
54                 exit(1);
55         }
56 }
57 /*********************************************************************************************/
58 void MothurOut::printCurrentFiles()  {
59         try {
60         
61         
62                 if (accnosfile != "")           {  mothurOut("accnos=" + accnosfile); mothurOutEndLine();                       }
63                 if (columnfile != "")           {  mothurOut("column=" + columnfile); mothurOutEndLine();                       }
64                 if (designfile != "")           {  mothurOut("design=" + designfile); mothurOutEndLine();                       }
65                 if (fastafile != "")            {  mothurOut("fasta=" + fastafile); mothurOutEndLine();                         }
66                 if (groupfile != "")            {  mothurOut("group=" + groupfile); mothurOutEndLine();                         }
67                 if (listfile != "")                     {  mothurOut("list=" + listfile); mothurOutEndLine();                           }
68                 if (namefile != "")                     {  mothurOut("name=" + namefile); mothurOutEndLine();                           }
69                 if (oligosfile != "")           {  mothurOut("oligos=" + oligosfile); mothurOutEndLine();                       }
70                 if (orderfile != "")            {  mothurOut("order=" + orderfile); mothurOutEndLine();                         }
71                 if (ordergroupfile != "")       {  mothurOut("ordergroup=" + ordergroupfile); mothurOutEndLine();       }
72                 if (phylipfile != "")           {  mothurOut("phylip=" + phylipfile); mothurOutEndLine();                       }
73                 if (qualfile != "")                     {  mothurOut("qfile=" + qualfile); mothurOutEndLine();                          }
74                 if (rabundfile != "")           {  mothurOut("rabund=" + rabundfile); mothurOutEndLine();                       }
75                 if (relabundfile != "")         {  mothurOut("relabund=" + relabundfile); mothurOutEndLine();           }
76                 if (sabundfile != "")           {  mothurOut("sabund=" + sabundfile); mothurOutEndLine();                       }
77                 if (sfffile != "")                      {  mothurOut("sff=" + sfffile); mothurOutEndLine();                                     }
78                 if (sharedfile != "")           {  mothurOut("shared=" + sharedfile); mothurOutEndLine();                       }
79                 if (taxonomyfile != "")         {  mothurOut("taxonomy=" + taxonomyfile); mothurOutEndLine();           }
80                 if (treefile != "")                     {  mothurOut("tree=" + treefile); mothurOutEndLine();                           }
81                 if (flowfile != "")                     {  mothurOut("flow=" + flowfile); mothurOutEndLine();                           }
82         if (biomfile != "")                     {  mothurOut("biom=" + biomfile); mothurOutEndLine();                           }
83         if (counttablefile != "")       {  mothurOut("count=" + counttablefile); mothurOutEndLine();    }
84                 if (processors != "1")          {  mothurOut("processors=" + processors); mothurOutEndLine();           }
85         if (summaryfile != "")          {  mothurOut("summary=" + summaryfile); mothurOutEndLine();             }
86                 
87         }
88         catch(exception& e) {
89                 errorOut(e, "MothurOut", "printCurrentFiles");
90                 exit(1);
91         }
92 }
93 /*********************************************************************************************/
94 bool MothurOut::hasCurrentFiles()  {
95         try {
96                 bool hasCurrent = false;
97                 
98                 if (accnosfile != "")           {  return true;                 }
99                 if (columnfile != "")           {  return true;                 }
100                 if (designfile != "")           {  return true;                 }
101                 if (fastafile != "")            {  return true;                 }
102                 if (groupfile != "")            {  return true;                 }
103                 if (listfile != "")                     {  return true;                 }
104                 if (namefile != "")                     {  return true;                 }
105                 if (oligosfile != "")           {  return true;                 }
106                 if (orderfile != "")            {  return true;                 }
107                 if (ordergroupfile != "")       {  return true;                 }
108                 if (phylipfile != "")           {  return true;                 }
109                 if (qualfile != "")                     {  return true;                 }
110                 if (rabundfile != "")           {  return true;                 }
111                 if (relabundfile != "")         {  return true;                 }
112                 if (sabundfile != "")           {  return true;                 }
113                 if (sfffile != "")                      {  return true;                 }
114                 if (sharedfile != "")           {  return true;                 }
115                 if (taxonomyfile != "")         {  return true;                 }
116                 if (treefile != "")                     {  return true;                 }
117                 if (flowfile != "")                     {  return true;                 }
118         if (biomfile != "")                     {  return true;                 }
119         if (counttablefile != "")       {  return true;                 }
120         if (summaryfile != "")  {  return true;                 }
121                 if (processors != "1")          {  return true;                 }
122                 
123                 return hasCurrent;
124                 
125         }
126         catch(exception& e) {
127                 errorOut(e, "MothurOut", "hasCurrentFiles");
128                 exit(1);
129         }
130 }
131
132 /*********************************************************************************************/
133 void MothurOut::clearCurrentFiles()  {
134         try {
135                 phylipfile = "";
136                 columnfile = "";
137                 listfile = "";
138                 rabundfile = "";
139                 sabundfile = "";
140                 namefile = "";
141                 groupfile = "";
142                 designfile = "";
143                 orderfile = "";
144                 treefile = "";
145                 sharedfile = "";
146                 ordergroupfile = "";
147                 relabundfile = "";
148                 fastafile = "";
149                 qualfile = "";
150                 sfffile = "";
151                 oligosfile = "";
152                 accnosfile = "";
153                 taxonomyfile = "";      
154                 flowfile = "";
155         biomfile = "";
156         counttablefile = "";
157         summaryfile = "";
158                 processors = "1";
159         }
160         catch(exception& e) {
161                 errorOut(e, "MothurOut", "clearCurrentFiles");
162                 exit(1);
163         }
164 }
165 /***********************************************************************/
166 string MothurOut::findProgramPath(string programName){
167         try { 
168                 
169                 string envPath = getenv("PATH");
170                 string pPath = "";
171                 
172                 //delimiting path char
173                 char delim;
174 #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix)
175         delim = ':';
176 #else
177         delim = ';';
178 #endif
179                 
180                 //break apart path variable by ':'
181                 vector<string> dirs;
182                 splitAtChar(envPath, dirs, delim);
183                 
184         if (debug) { mothurOut("[DEBUG]: dir's in path: \n"); }
185         
186                 //get path related to mothur
187                 for (int i = 0; i < dirs.size(); i++) {
188             
189             if (debug) { mothurOut("[DEBUG]: " + dirs[i] + "\n"); }
190             
191                         //to lower so we can find it
192                         string tempLower = "";
193                         for (int j = 0; j < dirs[i].length(); j++) {  tempLower += tolower(dirs[i][j]);  }
194                         
195                         //is this mothurs path?
196                         if (tempLower.find(programName) != -1) {  pPath = dirs[i]; break;  }
197                 }
198         
199                 if (debug) { mothurOut("[DEBUG]: programPath = " + pPath + "\n"); }
200         
201                 if (pPath != "") {
202                         //add programName so it looks like what argv would look like
203 #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix)
204             pPath += "/" + programName;
205 #else
206             pPath += "\\" + programName;
207 #endif
208                 }else {
209                         //okay programName is not in the path, so the folder programName is in must be in the path
210                         //lets find out which one
211                         
212                         //get path related to the program
213                         for (int i = 0; i < dirs.size(); i++) {
214                 
215                 if (debug) { mothurOut("[DEBUG]: looking in " + dirs[i] + " for " + programName + " \n"); }
216                 
217                                 //is this the programs path?
218                                 ifstream in;
219                                 string tempIn = dirs[i];
220 #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix)
221                 tempIn += "/" + programName;
222 #else
223                 tempIn += "\\" + programName;
224 #endif
225                                 openInputFile(tempIn, in, "");
226                                 
227                                 //if this file exists
228                                 if (in) { in.close(); pPath = tempIn; if (debug) { mothurOut("[DEBUG]: found it, programPath = " + pPath + "\n"); } break;   }
229                         }
230                 }
231                 
232                 return pPath;
233                 
234         }
235         catch(exception& e) {
236                 errorOut(e, "MothurOut", "findProgramPath");
237                 exit(1);
238         }
239 }
240 /*********************************************************************************************/
241 void MothurOut::setFileName(string filename)  {
242         try {
243                 logFileName = filename;
244                 
245                 #ifdef USE_MPI
246                         int pid;
247                         MPI_Comm_rank(MPI_COMM_WORLD, &pid); 
248                                         
249                         if (pid == 0) { //only one process should output to screen
250                 #endif
251                 
252                 openOutputFile(filename, out);
253                 
254                 #ifdef USE_MPI
255                         }
256                 #endif
257         }
258         catch(exception& e) {
259                 errorOut(e, "MothurOut", "setFileName");
260                 exit(1);
261         }
262 }
263 /*********************************************************************************************/
264 void MothurOut::setDefaultPath(string pathname)  {
265         try {
266         
267                 //add / to name if needed
268                 string lastChar = pathname.substr(pathname.length()-1);
269                 #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix)
270                         if (lastChar != "/") { pathname += "/"; }
271                 #else
272                         if (lastChar != "\\") { pathname += "\\"; }     
273                 #endif
274                 
275                 defaultPath = pathname;
276                 
277         }
278         catch(exception& e) {
279                 errorOut(e, "MothurOut", "setDefaultPath");
280                 exit(1);
281         }
282 }
283 /*********************************************************************************************/
284 void MothurOut::setOutputDir(string pathname)  {
285         try {
286                 outputDir = pathname;
287         }
288         catch(exception& e) {
289                 errorOut(e, "MothurOut", "setOutputDir");
290                 exit(1);
291         }
292 }
293 /*********************************************************************************************/
294 void MothurOut::closeLog()  {
295         try {
296                 
297                 #ifdef USE_MPI
298                         int pid;
299                         MPI_Comm_rank(MPI_COMM_WORLD, &pid); 
300                                         
301                         if (pid == 0) { //only one process should output to screen
302                 #endif
303                 
304                 out.close();
305                 
306                 #ifdef USE_MPI
307                         }
308                 #endif
309         }
310         catch(exception& e) {
311                 errorOut(e, "MothurOut", "closeLog");
312                 exit(1);
313         }
314 }
315
316 /*********************************************************************************************/
317 MothurOut::~MothurOut() {
318         try {
319                 _uniqueInstance = 0;
320                 
321         }
322         catch(exception& e) {
323                 errorOut(e, "MothurOut", "MothurOut");
324                 exit(1);
325         }
326 }
327 /*********************************************************************************************/
328 void MothurOut::mothurOut(string output) {
329         try {
330                 
331                 #ifdef USE_MPI
332                         int pid;
333                         MPI_Comm_rank(MPI_COMM_WORLD, &pid); 
334                                         
335                         if (pid == 0) { //only one process should output to screen
336                 #endif
337                 
338                 out << output;
339         logger() << output;
340                 
341                 #ifdef USE_MPI
342                         }
343                 #endif
344         }
345         catch(exception& e) {
346                 errorOut(e, "MothurOut", "MothurOut");
347                 exit(1);
348         }
349 }
350 /*********************************************************************************************/
351 void MothurOut::mothurOutJustToScreen(string output) {
352         try {
353                 
354 #ifdef USE_MPI
355         int pid;
356         MPI_Comm_rank(MPI_COMM_WORLD, &pid);
357         
358         if (pid == 0) { //only one process should output to screen
359 #endif
360             logger() << output;
361             
362 #ifdef USE_MPI
363         }
364 #endif
365         }
366         catch(exception& e) {
367                 errorOut(e, "MothurOut", "MothurOut");
368                 exit(1);
369         }
370 }
371 /*********************************************************************************************/
372 void MothurOut::mothurOutEndLine() {
373         try {
374                 #ifdef USE_MPI
375                         int pid;
376                         MPI_Comm_rank(MPI_COMM_WORLD, &pid); 
377                                         
378                         if (pid == 0) { //only one process should output to screen
379                 #endif
380                 
381                 out << endl;
382         logger() << endl;
383                 
384                 #ifdef USE_MPI
385                         }
386                 #endif
387         }
388         catch(exception& e) {
389                 errorOut(e, "MothurOut", "MothurOutEndLine");
390                 exit(1);
391         }
392 }
393 /*********************************************************************************************/
394 void MothurOut::mothurOut(string output, ofstream& outputFile) {
395         try {
396                 
397 #ifdef USE_MPI
398                 int pid;
399                 MPI_Comm_rank(MPI_COMM_WORLD, &pid); 
400                 
401                 if (pid == 0) { //only one process should output to screen
402 #endif
403                         
404                         
405                         out << output;
406                         outputFile << output;
407             logger() << output;
408                         
409 #ifdef USE_MPI
410                 }
411 #endif
412         
413         }
414         catch(exception& e) {
415                 errorOut(e, "MothurOut", "MothurOut");
416                 exit(1);
417         }
418 }
419 /*********************************************************************************************/
420 void MothurOut::mothurOutEndLine(ofstream& outputFile) {
421         try {
422 #ifdef USE_MPI
423                 int pid;
424                 MPI_Comm_rank(MPI_COMM_WORLD, &pid); 
425                 
426                 if (pid == 0) { //only one process should output to screen
427 #endif
428                         
429                         out << endl;
430                         outputFile << endl;
431             logger() << endl;
432                         
433 #ifdef USE_MPI
434                 }
435 #endif
436         }
437         catch(exception& e) {
438                 errorOut(e, "MothurOut", "MothurOutEndLine");
439                 exit(1);
440         }
441 }
442 /*********************************************************************************************/
443 void MothurOut::mothurOutJustToLog(string output) {
444         try {
445                 #ifdef USE_MPI
446                         int pid;
447                         MPI_Comm_rank(MPI_COMM_WORLD, &pid); 
448                                         
449                         if (pid == 0) { //only one process should output to screen
450                 #endif
451                 
452                 out << output;
453                 
454                 #ifdef USE_MPI
455                         }
456                 #endif
457         }
458         catch(exception& e) {
459                 errorOut(e, "MothurOut", "MothurOutJustToLog");
460                 exit(1);
461         }
462 }
463 /*********************************************************************************************/
464 void MothurOut::errorOut(exception& e, string object, string function) {
465         //double vm, rss;
466         //mem_usage(vm, rss);
467         
468     string errorType = toString(e.what());
469     
470     int pos = errorType.find("bad_alloc");
471     mothurOut("[ERROR]: ");
472     mothurOut(errorType);
473     
474     if (pos == string::npos) { //not bad_alloc
475         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.");
476         mothurOutEndLine();
477     }else { //bad alloc
478         if (object == "cluster"){
479             mothurOut(" has occurred in the " + object + " class function " + function + ". This error indicates your computer is running out of memory.  There are two common causes for this, file size and format.\n\nFile Size:\nThe cluster command loads your distance matrix into RAM, and your distance file is most likely too large to fit in RAM. There are two options to help with this. The first is to use a cutoff. By using a cutoff mothur will only load distances that are below the cutoff. If that is still not enough, there is a command called cluster.split, http://www.mothur.org/wiki/cluster.split which divides the distance matrix, and clusters the smaller pieces separately. You may also be able to reduce the size of the original distance matrix by using the commands outlined in the Schloss SOP, http://www.mothur.org/wiki/Schloss_SOP. \n\nWrong Format:\nThis error can be caused by trying to read a column formatted distance matrix using the phylip parameter. By default, the dist.seqs command generates a column formatted distance matrix. To make a phylip formatted matrix set the dist.seqs command parameter output to lt.  \n\nIf you are uable to resolve the issue, please contact Pat Schloss at mothur.bugs@gmail.com, and be sure to include the mothur.logFile with your inquiry.");
480         }else if (object == "shhh.flows"){
481                 mothurOut(" has occurred in the " + object + " class function " + function + ". This error indicates your computer is running out of memory. The shhh.flows command is very memory intensive. This error is most commonly caused by trying to process a dataset too large, using multiple processors, or failing to run trim.flows before shhh.flows. If you are running our 32bit version, your memory usage is limited to 4G.  If you have more than 4G of RAM and are running a 64bit OS, using our 64bit version may resolve your issue.  If you are using multiple processors, try running the command with processors=1, the more processors you use the more memory is required. Running trim.flows with an oligos file, and then shhh.flows with the file option may also resolve the issue. If for some reason you are unable to run shhh.flows with your data, a good alternative is to use the trim.seqs command using a 50-bp sliding window and to trim the sequence when the average quality score over that window drops below 35. Our results suggest that the sequencing error rates by this method are very good, but not quite as good as by shhh.flows and that the resulting sequences tend to be a bit shorter. If you are uable to resolve the issue, please contact Pat Schloss at mothur.bugs@gmail.com, and be sure to include the mothur.logFile with your inquiry. ");
482         }else {
483             mothurOut(" has occurred in the " + object + " class function " + function + ". This error indicates your computer is running out of memory.  This is most commonly caused by trying to process a dataset too large, using multiple processors, or a file format issue. If you are running our 32bit version, your memory usage is limited to 4G.  If you have more than 4G of RAM and are running a 64bit OS, using our 64bit version may resolve your issue.  If you are using multiple processors, try running the command with processors=1, the more processors you use the more memory is required. Also, you may be able to reduce the size of your dataset by using the commands outlined in the Schloss SOP, http://www.mothur.org/wiki/Schloss_SOP. If you are uable to resolve the issue, please contact Pat Schloss at mothur.bugs@gmail.com, and be sure to include the mothur.logFile with your inquiry.");
484         }
485     }
486 }
487 /*********************************************************************************************/
488 //The following was originally from http://stackoverflow.com/questions/669438/how-to-get-memory-usage-at-run-time-in-c 
489 // process_mem_usage(double &, double &) - takes two doubles by reference,
490 // attempts to read the system-dependent data for a process' virtual memory
491 // size and resident set size, and return the results in KB.
492 //
493 // On failure, returns 0.0, 0.0
494 int MothurOut::mem_usage(double& vm_usage, double& resident_set) {
495   #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix)
496   
497            vm_usage     = 0.0;
498            resident_set = 0.0;
499
500            // 'file' stat seems to give the most reliable results
501            //
502            ifstream stat_stream("/proc/self/stat",ios_base::in);
503
504            // dummy vars for leading entries in stat that we don't care about
505            //
506            string pid, comm, state, ppid, pgrp, session, tty_nr;
507            string tpgid, flags, minflt, cminflt, majflt, cmajflt;
508            string utime, stime, cutime, cstime, priority, nice;
509            string O, itrealvalue, starttime;
510
511            // the two fields we want
512            //
513            unsigned long vsize;
514            long rss;
515
516            stat_stream >> pid >> comm >> state >> ppid >> pgrp >> session >> tty_nr
517                                    >> tpgid >> flags >> minflt >> cminflt >> majflt >> cmajflt
518                                    >> utime >> stime >> cutime >> cstime >> priority >> nice
519                                    >> O >> itrealvalue >> starttime >> vsize >> rss; // don't care about the rest
520
521            long page_size_kb = sysconf(_SC_PAGE_SIZE) / 1024; // in case x86-64 is configured to use 2MB pages
522            vm_usage     = vsize / 1024.0;
523            resident_set = rss * page_size_kb;
524            
525            mothurOut("Memory Usage: vm = " + toString(vm_usage) + " rss = " + toString(resident_set) + "\n");
526                 return 0;
527
528         #else
529 /*              //windows memory usage
530                 // Get the list of process identifiers.
531                 DWORD aProcesses[1024], cbNeeded, cProcesses;
532                 
533                 if ( !EnumProcesses( aProcesses, sizeof(aProcesses), &cbNeeded ) ){ return 1; }
534
535                 // Calculate how many process identifiers were returned.
536                 cProcesses = cbNeeded / sizeof(DWORD);
537
538                 // Print the memory usage for each process
539                 for (int i = 0; i < cProcesses; i++ ) {
540                         DWORD processID = aProcesses[i];
541                         
542                         PROCESS_MEMORY_COUNTERS pmc;
543
544                         HANDLE hProcess = OpenProcess((PROCESS_QUERY_INFORMATION | PROCESS_VM_READ), FALSE, processID);
545
546                         // Print the process identifier.
547                         printf( "\nProcess ID: %u\n", processID);
548                         
549                         if (NULL != hProcess) {
550
551                                 if ( GetProcessMemoryInfo( hProcess, &pmc, sizeof(pmc)) ) {
552                                         printf( "\tPageFaultCount: 0x%08X\n", pmc.PageFaultCount );
553                                         printf( "\tPeakWorkingSetSize: 0x%08X\n", pmc.PeakWorkingSetSize );
554                                         printf( "\tWorkingSetSize: 0x%08X\n", pmc.WorkingSetSize );
555                                         printf( "\tQuotaPeakPagedPoolUsage: 0x%08X\n", pmc.QuotaPeakPagedPoolUsage );
556                                         printf( "\tQuotaPagedPoolUsage: 0x%08X\n", pmc.QuotaPagedPoolUsage );
557                                         printf( "\tQuotaPeakNonPagedPoolUsage: 0x%08X\n", pmc.QuotaPeakNonPagedPoolUsage );
558                                         printf( "\tQuotaNonPagedPoolUsage: 0x%08X\n", pmc.QuotaNonPagedPoolUsage );
559                                         printf( "\tPagefileUsage: 0x%08X\n", pmc.PagefileUsage ); 
560                                         printf( "\tPeakPagefileUsage: 0x%08X\n", pmc.PeakPagefileUsage );
561                                 }
562                                 CloseHandle(hProcess);
563                         }
564                 }
565 */
566                         return 0;
567
568         #endif
569 }
570
571
572 /***********************************************************************/
573 int MothurOut::openOutputFileAppend(string fileName, ofstream& fileHandle){
574         try {
575                 fileName = getFullPathName(fileName);
576                 
577                 fileHandle.open(fileName.c_str(), ios::app);
578                 if(!fileHandle) {
579                         mothurOut("[ERROR]: Could not open " + fileName); mothurOutEndLine();
580                         return 1;
581                 }
582                 else {
583                         return 0;
584                 }
585         }
586         catch(exception& e) {
587                 errorOut(e, "MothurOut", "openOutputFileAppend");
588                 exit(1);
589         }
590 }
591 /***********************************************************************/
592 int MothurOut::openOutputFileBinaryAppend(string fileName, ofstream& fileHandle){
593         try {
594                 fileName = getFullPathName(fileName);
595                 
596                 fileHandle.open(fileName.c_str(), ios::app | ios::binary);
597                 if(!fileHandle) {
598                         mothurOut("[ERROR]: Could not open " + fileName); mothurOutEndLine();
599                         return 1;
600                 }
601                 else {
602                         return 0;
603                 }
604         }
605         catch(exception& e) {
606                 errorOut(e, "MothurOut", "openOutputFileAppend");
607                 exit(1);
608         }
609 }
610
611 /***********************************************************************/
612 void MothurOut::gobble(istream& f){
613         try {
614                 
615                 char d;
616                 while(isspace(d=f.get()))               { ;}
617                 if(!f.eof()) { f.putback(d); }
618         }
619         catch(exception& e) {
620                 errorOut(e, "MothurOut", "gobble");
621                 exit(1);
622         }
623 }
624 /***********************************************************************/
625 void MothurOut::gobble(istringstream& f){
626         try {
627                 char d;
628                 while(isspace(d=f.get()))               {;}
629                 if(!f.eof()) { f.putback(d); }
630         }
631         catch(exception& e) {
632                 errorOut(e, "MothurOut", "gobble");
633                 exit(1);
634         }
635 }
636
637 /***********************************************************************/
638
639 string MothurOut::getline(istringstream& fileHandle) {
640         try {
641         
642                 string line = "";
643                 
644                 while (!fileHandle.eof())       {
645                         //get next character
646                         char c = fileHandle.get(); 
647                         
648                         //are you at the end of the line
649                         if ((c == '\n') || (c == '\r') || (c == '\f')){  break; }       
650                         else {          line += c;              }
651                 }
652                 
653                 return line;
654                 
655         }
656         catch(exception& e) {
657                 errorOut(e, "MothurOut", "getline");
658                 exit(1);
659         }
660 }
661 /***********************************************************************/
662
663 string MothurOut::getline(ifstream& fileHandle) {
664         try {
665         
666                 string line = "";
667                 
668                 while (fileHandle)      {
669                         //get next character
670                         char c = fileHandle.get(); 
671                         
672                         //are you at the end of the line
673                         if ((c == '\n') || (c == '\r') || (c == '\f') || (c == EOF)){  break;   }       
674                         else {          line += c;              }
675                 }
676                 
677                 return line;
678                 
679         }
680         catch(exception& e) {
681                 errorOut(e, "MothurOut", "getline");
682                 exit(1);
683         }
684 }
685 /***********************************************************************/
686
687 #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix)
688 #ifdef USE_COMPRESSION
689 inline bool endsWith(string s, const char * suffix){
690   size_t suffixLength = strlen(suffix);
691   return s.size() >= suffixLength && s.substr(s.size() - suffixLength, suffixLength).compare(suffix) == 0;
692 }
693 #endif
694 #endif
695
696 string MothurOut::getRootName(string longName){
697         try {
698         
699                 string rootName = longName;
700
701 #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix)
702 #ifdef USE_COMPRESSION
703     if (endsWith(rootName, ".gz") || endsWith(rootName, ".bz2")) {
704       int pos = rootName.find_last_of('.');
705       rootName = rootName.substr(0, pos);
706       cerr << "shortening " << longName << " to " << rootName << "\n";
707     }
708 #endif
709 #endif
710                 if(rootName.find_last_of(".") != rootName.npos){
711                         int pos = rootName.find_last_of('.')+1;
712                         rootName = rootName.substr(0, pos);
713                 }
714
715                 return rootName;
716         }
717         catch(exception& e) {
718                 errorOut(e, "MothurOut", "getRootName");
719                 exit(1);
720         }
721 }
722 /***********************************************************************/
723
724 string MothurOut::getSimpleName(string longName){
725         try {
726                 string simpleName = longName;
727                 
728                 size_t found;
729                 found=longName.find_last_of("/\\");
730
731                 if(found != longName.npos){
732                         simpleName = longName.substr(found+1);
733                 }
734                 
735                 return simpleName;
736         }
737         catch(exception& e) {
738                 errorOut(e, "MothurOut", "getSimpleName");
739                 exit(1);
740         }
741 }
742
743 /***********************************************************************/
744
745 int MothurOut::getRandomIndex(int highest){
746         try {
747                 
748                 int random = (int) ((float)(highest+1) * (float)(rand()) / ((float)RAND_MAX+1.0));
749                 
750                 return random;
751         }
752         catch(exception& e) {
753                 errorOut(e, "MothurOut", "getRandomIndex");
754                 exit(1);
755         }       
756         
757 }
758 /**********************************************************************/
759
760 string MothurOut::getPathName(string longName){
761         try {
762                 string rootPathName = longName;
763                 
764                 if(longName.find_last_of("/\\") != longName.npos){
765                         int pos = longName.find_last_of("/\\")+1;
766                         rootPathName = longName.substr(0, pos);
767                 }
768                 
769                 return rootPathName;
770         }
771         catch(exception& e) {
772                 errorOut(e, "MothurOut", "getPathName");
773                 exit(1);
774         }       
775
776 }
777 /***********************************************************************/
778
779 bool MothurOut::dirCheck(string& dirName){
780         try {
781         
782         if (dirName == "") { return false; }
783         
784         string tag = "";
785         #ifdef USE_MPI
786             int pid; 
787             MPI_Comm_rank(MPI_COMM_WORLD, &pid); //find out who we are
788                 
789             tag = toString(pid);
790         #endif
791
792         //add / to name if needed
793         string lastChar = dirName.substr(dirName.length()-1);
794         #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix)
795         if (lastChar != "/") { dirName += "/"; }
796         #else
797         if (lastChar != "\\") { dirName += "\\"; }      
798         #endif
799
800         //test to make sure directory exists
801         dirName = getFullPathName(dirName);
802         string outTemp = dirName + tag + "temp"+ toString(time(NULL));
803         ofstream out;
804         out.open(outTemp.c_str(), ios::trunc);
805         if(!out) {
806             mothurOut(dirName + " directory does not exist or is not writable."); mothurOutEndLine(); 
807         }else{
808             out.close();
809             mothurRemove(outTemp);
810             return true;
811         }
812         
813         return false;
814     }
815         catch(exception& e) {
816                 errorOut(e, "MothurOut", "dirCheck");
817                 exit(1);
818         }       
819     
820 }
821 //**********************************************************************************************************************
822
823 map<string, vector<string> > MothurOut::parseClasses(string classes){
824         try {
825         map<string, vector<string> > parts;
826         
827         //treatment<Early|Late>-age<young|old>
828         vector<string> pieces; splitAtDash(classes, pieces); // -> treatment<Early|Late>, age<young|old>
829         
830         for (int i = 0; i < pieces.size(); i++) {
831             string category = ""; string value = "";
832             bool foundOpen = false;
833             for (int j = 0; j < pieces[i].length(); j++) {
834                 if (control_pressed) { return parts; }
835                 
836                 if (pieces[i][j] == '<')        { foundOpen = true;         }
837                 else if (pieces[i][j] == '>')   { j += pieces[i].length();  }
838                 else {
839                     if (!foundOpen) { category += pieces[i][j]; }
840                     else { value += pieces[i][j]; }
841                 }
842             }
843             vector<string> values; splitAtChar(value, values, '|');
844             parts[category] = values;
845         }
846         
847         return parts;
848     }
849         catch(exception& e) {
850                 errorOut(e, "MothurOut", "parseClasses");
851                 exit(1);
852         }
853 }
854 /***********************************************************************/
855
856 string MothurOut::hasPath(string longName){
857         try {
858                 string path = "";
859                 
860                 size_t found;
861                 found=longName.find_last_of("~/\\");
862
863                 if(found != longName.npos){
864                         path = longName.substr(0, found+1);
865                 }
866                 
867                 return path;
868         }
869         catch(exception& e) {
870                 errorOut(e, "MothurOut", "hasPath");
871                 exit(1);
872         }       
873 }
874
875 /***********************************************************************/
876
877 string MothurOut::getExtension(string longName){
878         try {
879                 string extension = "";
880                 
881                 if(longName.find_last_of('.') != longName.npos){
882                         int pos = longName.find_last_of('.');
883                         extension = longName.substr(pos, longName.length());
884                 }
885                 
886                 return extension;
887         }
888         catch(exception& e) {
889                 errorOut(e, "MothurOut", "getExtension");
890                 exit(1);
891         }       
892 }
893 /***********************************************************************/
894 bool MothurOut::isBlank(string fileName){
895         try {
896                 
897                 fileName = getFullPathName(fileName);
898                 
899                 ifstream fileHandle;
900                 fileHandle.open(fileName.c_str());
901                 if(!fileHandle) {
902                         mothurOut("[ERROR]: Could not open " + fileName); mothurOutEndLine();
903                         return false;
904                 }else {
905                         //check for blank file
906                         gobble(fileHandle);
907                         if (fileHandle.eof()) { fileHandle.close(); return true;  }
908                         fileHandle.close();
909                 }
910                 return false;
911         }
912         catch(exception& e) {
913                 errorOut(e, "MothurOut", "isBlank");
914                 exit(1);
915         }       
916 }
917 /***********************************************************************/
918
919 string MothurOut::getFullPathName(string fileName){
920         try{
921         
922         string path = hasPath(fileName);
923         string newFileName;
924         int pos;
925         
926         if (path == "") { return fileName; } //its a simple name
927         else { //we need to complete the pathname
928                 // ex. ../../../filename 
929                 // cwd = /user/work/desktop
930                                 
931                 string cwd;
932                 //get current working directory 
933                 #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix)  
934                         
935                         if (path.find("~") != -1) { //go to home directory
936                                 string homeDir;
937                         
938                                 char *homepath = NULL;
939                                 homepath = getenv ("HOME");
940                                 if ( homepath != NULL) { homeDir = homepath; }
941                                 else { homeDir = "";  }
942
943                                 newFileName = homeDir + fileName.substr(fileName.find("~")+1);
944                                 return newFileName;
945                         }else { //find path
946                                 if (path.rfind("./") == string::npos) { return fileName; } //already complete name
947                                 else { newFileName = fileName.substr(fileName.rfind("./")+2); } //save the complete part of the name
948                                 
949                                 //char* cwdpath = new char[1024];
950                                 //size_t size;
951                                 //cwdpath=getcwd(cwdpath,size);
952                                 //cwd = cwdpath;
953                                 
954                                 char *cwdpath = NULL;
955                                 cwdpath = getcwd(NULL, 0); // or _getcwd
956                                 if ( cwdpath != NULL) { cwd = cwdpath; }
957                                 else { cwd = "";  }
958
959                                 
960                                 //rip off first '/'
961                                 string simpleCWD;
962                                 if (cwd.length() > 0) { simpleCWD = cwd.substr(1); }
963                                 
964                                 //break apart the current working directory
965                                 vector<string> dirs;
966                                 while (simpleCWD.find_first_of('/') != string::npos) {
967                                         string dir = simpleCWD.substr(0,simpleCWD.find_first_of('/'));
968                                         simpleCWD = simpleCWD.substr(simpleCWD.find_first_of('/')+1, simpleCWD.length());
969                                         dirs.push_back(dir);
970                                 }
971                                 //get last one              // ex. ../../../filename = /user/work/desktop/filename
972                                 dirs.push_back(simpleCWD);  //ex. dirs[0] = user, dirs[1] = work, dirs[2] = desktop
973                                 
974                         
975                                 int index = dirs.size()-1;
976                 
977                                 while((pos = path.rfind("./")) != string::npos) { //while you don't have a complete path
978                                         if (pos == 0) { break;  //you are at the end
979                                         }else if (path[(pos-1)] == '.') { //you want your parent directory ../
980                                                 path = path.substr(0, pos-1);
981                                                 index--;
982                                                 if (index == 0) {  break; }
983                                         }else if (path[(pos-1)] == '/') { //you want the current working dir ./
984                                                 path = path.substr(0, pos);
985                                         }else if (pos == 1) { break;  //you are at the end
986                                         }else { mothurOut("cannot resolve path for " +  fileName + "\n"); return fileName; }
987                                 }
988                         
989                                 for (int i = index; i >= 0; i--) {
990                                         newFileName = dirs[i] +  "/" + newFileName;             
991                                 }
992                                 
993                                 newFileName =  "/" +  newFileName;
994                                 return newFileName;
995                         }       
996                 #else
997                         if (path.find("~") != string::npos) { //go to home directory
998                                 string homeDir = getenv ("HOMEPATH");
999                                 newFileName = homeDir + fileName.substr(fileName.find("~")+1);
1000                                 return newFileName;
1001                         }else { //find path
1002                                 if (path.rfind(".\\") == string::npos) { return fileName; } //already complete name
1003                                 else { newFileName = fileName.substr(fileName.rfind(".\\")+2); } //save the complete part of the name
1004                                                         
1005                                 char *cwdpath = NULL;
1006                                 cwdpath = getcwd(NULL, 0); // or _getcwd
1007                                 if ( cwdpath != NULL) { cwd = cwdpath; }
1008                                 else { cwd = "";  }
1009                                 
1010                                 //break apart the current working directory
1011                                 vector<string> dirs;
1012                                 while (cwd.find_first_of('\\') != -1) {
1013                                         string dir = cwd.substr(0,cwd.find_first_of('\\'));
1014                                         cwd = cwd.substr(cwd.find_first_of('\\')+1, cwd.length());
1015                                         dirs.push_back(dir);
1016                 
1017                                 }
1018                                 //get last one
1019                                 dirs.push_back(cwd);  //ex. dirs[0] = user, dirs[1] = work, dirs[2] = desktop
1020                                         
1021                                 int index = dirs.size()-1;
1022                                         
1023                                 while((pos = path.rfind(".\\")) != string::npos) { //while you don't have a complete path
1024                                         if (pos == 0) { break;  //you are at the end
1025                                         }else if (path[(pos-1)] == '.') { //you want your parent directory ../
1026                                                 path = path.substr(0, pos-1);
1027                                                 index--;
1028                                                 if (index == 0) {  break; }
1029                                         }else if (path[(pos-1)] == '\\') { //you want the current working dir ./
1030                                                 path = path.substr(0, pos);
1031                                         }else if (pos == 1) { break;  //you are at the end
1032                                         }else { mothurOut("cannot resolve path for " +  fileName + "\n"); return fileName; }
1033                                 }
1034                         
1035                                 for (int i = index; i >= 0; i--) {
1036                                         newFileName = dirs[i] +  "\\" + newFileName;            
1037                                 }
1038                                 
1039                                 return newFileName;
1040                         }
1041                         
1042                 #endif
1043         }
1044         }
1045         catch(exception& e) {
1046                 errorOut(e, "MothurOut", "getFullPathName");
1047                 exit(1);
1048         }       
1049 }
1050 /***********************************************************************/
1051
1052 int MothurOut::openInputFile(string fileName, ifstream& fileHandle, string m){
1053         try {
1054                         //get full path name
1055                         string completeFileName = getFullPathName(fileName);
1056 #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix)
1057 #ifdef USE_COMPRESSION
1058       // check for gzipped or bzipped file
1059       if (endsWith(completeFileName, ".gz") || endsWith(completeFileName, ".bz2")) {
1060         string tempName = string(tmpnam(0));
1061         mkfifo(tempName.c_str(), 0666);
1062         int fork_result = fork();
1063         if (fork_result < 0) {
1064           cerr << "Error forking.\n";
1065           exit(1);
1066         } else if (fork_result == 0) {
1067           string command = (endsWith(completeFileName, ".gz") ? "zcat " : "bzcat ") + completeFileName + string(" > ") + tempName;
1068           cerr << "Decompressing " << completeFileName << " via temporary named pipe " << tempName << "\n";
1069           system(command.c_str());
1070           cerr << "Done decompressing " << completeFileName << "\n";
1071           mothurRemove(tempName);
1072           exit(EXIT_SUCCESS);
1073         } else {
1074           cerr << "waiting on child process " << fork_result << "\n";
1075           completeFileName = tempName;
1076         }
1077       }
1078 #endif
1079 #endif
1080                         fileHandle.open(completeFileName.c_str());
1081                         if(!fileHandle) {
1082                                 //mothurOut("[ERROR]: Could not open " + completeFileName); mothurOutEndLine();
1083                                 return 1;
1084                         }else {
1085                                 //check for blank file
1086                                 gobble(fileHandle);
1087                                 return 0;
1088                         }
1089         }
1090         catch(exception& e) {
1091                 errorOut(e, "MothurOut", "openInputFile - no Error");
1092                 exit(1);
1093         }
1094 }
1095 /***********************************************************************/
1096
1097 int MothurOut::openInputFile(string fileName, ifstream& fileHandle){
1098         try {
1099
1100                 //get full path name
1101                 string completeFileName = getFullPathName(fileName);
1102 #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix)
1103 #ifdef USE_COMPRESSION
1104   // check for gzipped or bzipped file
1105   if (endsWith(completeFileName, ".gz") || endsWith(completeFileName, ".bz2")) {
1106     string tempName = string(tmpnam(0));
1107     mkfifo(tempName.c_str(), 0666);
1108     int fork_result = fork();
1109     if (fork_result < 0) {
1110       cerr << "Error forking.\n";
1111       exit(1);
1112     } else if (fork_result == 0) {
1113       string command = (endsWith(completeFileName, ".gz") ? "zcat " : "bzcat ") + completeFileName + string(" > ") + tempName;
1114       cerr << "Decompressing " << completeFileName << " via temporary named pipe " << tempName << "\n";
1115       system(command.c_str());
1116       cerr << "Done decompressing " << completeFileName << "\n";
1117       mothurRemove(tempName);
1118       exit(EXIT_SUCCESS);
1119     } else {
1120       cerr << "waiting on child process " << fork_result << "\n";
1121       completeFileName = tempName;
1122     }
1123   }
1124 #endif
1125 #endif
1126
1127                 fileHandle.open(completeFileName.c_str());
1128                 if(!fileHandle) {
1129                         mothurOut("[ERROR]: Could not open " + completeFileName); mothurOutEndLine();
1130                         return 1;
1131                 }
1132                 else {
1133                         //check for blank file
1134                         gobble(fileHandle);
1135                         if (fileHandle.eof()) { mothurOut("[ERROR]: " + completeFileName + " is blank. Please correct."); mothurOutEndLine();  }
1136                         
1137                         return 0;
1138                 }
1139         }
1140         catch(exception& e) {
1141                 errorOut(e, "MothurOut", "openInputFile");
1142                 exit(1);
1143         }       
1144 }
1145 /***********************************************************************/
1146 int MothurOut::openInputFileBinary(string fileName, ifstream& fileHandle){
1147         try {
1148         
1149                 //get full path name
1150                 string completeFileName = getFullPathName(fileName);
1151 #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix)
1152 #ifdef USE_COMPRESSION
1153         // check for gzipped or bzipped file
1154         if (endsWith(completeFileName, ".gz") || endsWith(completeFileName, ".bz2")) {
1155             string tempName = string(tmpnam(0));
1156             mkfifo(tempName.c_str(), 0666);
1157             int fork_result = fork();
1158             if (fork_result < 0) {
1159                 cerr << "Error forking.\n";
1160                 exit(1);
1161             } else if (fork_result == 0) {
1162                 string command = (endsWith(completeFileName, ".gz") ? "zcat " : "bzcat ") + completeFileName + string(" > ") + tempName;
1163                 cerr << "Decompressing " << completeFileName << " via temporary named pipe " << tempName << "\n";
1164                 system(command.c_str());
1165                 cerr << "Done decompressing " << completeFileName << "\n";
1166                 mothurRemove(tempName);
1167                 exit(EXIT_SUCCESS);
1168             } else {
1169                 cerr << "waiting on child process " << fork_result << "\n";
1170                 completeFileName = tempName;
1171             }
1172         }
1173 #endif
1174 #endif
1175         
1176                 fileHandle.open(completeFileName.c_str(), ios::binary);
1177                 if(!fileHandle) {
1178                         mothurOut("[ERROR]: Could not open " + completeFileName); mothurOutEndLine();
1179                         return 1;
1180                 }
1181                 else {
1182                         //check for blank file
1183                         gobble(fileHandle);
1184                         if (fileHandle.eof()) { mothurOut("[ERROR]: " + completeFileName + " is blank. Please correct."); mothurOutEndLine();  }
1185                         
1186                         return 0;
1187                 }
1188         }
1189         catch(exception& e) {
1190                 errorOut(e, "MothurOut", "openInputFileBinary");
1191                 exit(1);
1192         }       
1193 }
1194 /***********************************************************************/
1195 int MothurOut::openInputFileBinary(string fileName, ifstream& fileHandle, string noerror){
1196         try {
1197         
1198                 //get full path name
1199                 string completeFileName = getFullPathName(fileName);
1200 #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix)
1201 #ifdef USE_COMPRESSION
1202         // check for gzipped or bzipped file
1203         if (endsWith(completeFileName, ".gz") || endsWith(completeFileName, ".bz2")) {
1204             string tempName = string(tmpnam(0));
1205             mkfifo(tempName.c_str(), 0666);
1206             int fork_result = fork();
1207             if (fork_result < 0) {
1208                 cerr << "Error forking.\n";
1209                 exit(1);
1210             } else if (fork_result == 0) {
1211                 string command = (endsWith(completeFileName, ".gz") ? "zcat " : "bzcat ") + completeFileName + string(" > ") + tempName;
1212                 cerr << "Decompressing " << completeFileName << " via temporary named pipe " << tempName << "\n";
1213                 system(command.c_str());
1214                 cerr << "Done decompressing " << completeFileName << "\n";
1215                 mothurRemove(tempName);
1216                 exit(EXIT_SUCCESS);
1217             } else {
1218                 cerr << "waiting on child process " << fork_result << "\n";
1219                 completeFileName = tempName;
1220             }
1221         }
1222 #endif
1223 #endif
1224         
1225                 fileHandle.open(completeFileName.c_str(), ios::binary);
1226                 if(!fileHandle) {
1227                         //mothurOut("[ERROR]: Could not open " + completeFileName); mothurOutEndLine();
1228                         return 1;
1229                 }
1230                 else {
1231                         //check for blank file
1232                         gobble(fileHandle);
1233                         //if (fileHandle.eof()) { mothurOut("[ERROR]: " + completeFileName + " is blank. Please correct."); mothurOutEndLine();  }
1234                         
1235                         return 0;
1236                 }
1237         }
1238         catch(exception& e) {
1239                 errorOut(e, "MothurOut", "openInputFileBinary - no error");
1240                 exit(1);
1241         }
1242 }
1243
1244 /***********************************************************************/
1245
1246 int MothurOut::renameFile(string oldName, string newName){
1247         try {
1248         
1249         if (oldName == newName) { return 0; }
1250         
1251                 ifstream inTest;
1252                 int exist = openInputFile(newName, inTest, "");
1253                 inTest.close();
1254                 
1255         #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix)          
1256                 if (exist == 0) { //you could open it so you want to delete it
1257                         string command = "rm " + newName;
1258                         system(command.c_str());
1259                 }
1260                                 
1261                 string command = "mv " + oldName + " " + newName;
1262                 system(command.c_str());
1263         #else
1264                 mothurRemove(newName);
1265                 int renameOk = rename(oldName.c_str(), newName.c_str());
1266         #endif
1267                 return 0;
1268                 
1269         }
1270         catch(exception& e) {
1271                 errorOut(e, "MothurOut", "renameFile");
1272                 exit(1);
1273         }       
1274 }
1275
1276 /***********************************************************************/
1277
1278 int MothurOut::openOutputFile(string fileName, ofstream& fileHandle){
1279         try { 
1280         
1281                 string completeFileName = getFullPathName(fileName);
1282 #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix)
1283 #ifdef USE_COMPRESSION
1284     // check for gzipped file
1285     if (endsWith(completeFileName, ".gz") || endsWith(completeFileName, ".bz2")) {
1286       string tempName = string(tmpnam(0));
1287       mkfifo(tempName.c_str(), 0666);
1288       cerr << "Compressing " << completeFileName << " via temporary named pipe " << tempName << "\n";
1289       int fork_result = fork();
1290       if (fork_result < 0) {
1291         cerr << "Error forking.\n";
1292         exit(1);
1293       } else if (fork_result == 0) {
1294         string command = string(endsWith(completeFileName, ".gz") ?  "gzip" : "bzip2") + " -v > " + completeFileName + string(" < ") + tempName;
1295         system(command.c_str());
1296         exit(0);
1297       } else {
1298         completeFileName = tempName;
1299       }
1300     }
1301 #endif
1302 #endif
1303                 fileHandle.open(completeFileName.c_str(), ios::trunc);
1304                 if(!fileHandle) {
1305                         mothurOut("[ERROR]: Could not open " + completeFileName); mothurOutEndLine();
1306                         return 1;
1307                 }
1308                 else {
1309                         return 0;
1310                 }
1311         }
1312         catch(exception& e) {
1313                 errorOut(e, "MothurOut", "openOutputFile");
1314                 exit(1);
1315         }       
1316
1317 }
1318 /***********************************************************************/
1319
1320 int MothurOut::openOutputFileBinary(string fileName, ofstream& fileHandle){
1321         try {
1322         
1323                 string completeFileName = getFullPathName(fileName);
1324 #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix)
1325 #ifdef USE_COMPRESSION
1326         // check for gzipped file
1327         if (endsWith(completeFileName, ".gz") || endsWith(completeFileName, ".bz2")) {
1328             string tempName = string(tmpnam(0));
1329             mkfifo(tempName.c_str(), 0666);
1330             cerr << "Compressing " << completeFileName << " via temporary named pipe " << tempName << "\n";
1331             int fork_result = fork();
1332             if (fork_result < 0) {
1333                 cerr << "Error forking.\n";
1334                 exit(1);
1335             } else if (fork_result == 0) {
1336                 string command = string(endsWith(completeFileName, ".gz") ?  "gzip" : "bzip2") + " -v > " + completeFileName + string(" < ") + tempName;
1337                 system(command.c_str());
1338                 exit(0);
1339             } else {
1340                 completeFileName = tempName;
1341             }
1342         }
1343 #endif
1344 #endif
1345                 fileHandle.open(completeFileName.c_str(), ios::trunc | ios::binary);
1346                 if(!fileHandle) {
1347                         mothurOut("[ERROR]: Could not open " + completeFileName); mothurOutEndLine();
1348                         return 1;
1349                 }
1350                 else {
1351                         return 0;
1352                 }
1353         }
1354         catch(exception& e) {
1355                 errorOut(e, "MothurOut", "openOutputFileBinary");
1356                 exit(1);
1357         }       
1358     
1359 }
1360 /**************************************************************************************************/
1361 int MothurOut::appendFiles(string temp, string filename) {
1362         try{
1363                 ofstream output;
1364                 ifstream input;
1365         
1366                 //open output file in append mode
1367                 openOutputFileAppend(filename, output);
1368                 int ableToOpen = openInputFile(temp, input, "no error");
1369                 //int ableToOpen = openInputFile(temp, input);
1370                 
1371                 int numLines = 0;
1372                 if (ableToOpen == 0) { //you opened it
1373             
1374             char buffer[4096];        
1375             while (!input.eof()) {
1376                 input.read(buffer, 4096);
1377                 output.write(buffer, input.gcount());
1378                 //count number of lines
1379                 for (int i = 0; i < input.gcount(); i++) {  if (buffer[i] == '\n') {numLines++;} }
1380             }
1381                         input.close();
1382                 }
1383                 
1384                 output.close();
1385                 
1386                 return numLines;
1387         }
1388         catch(exception& e) {
1389                 errorOut(e, "MothurOut", "appendFiles");
1390                 exit(1);
1391         }       
1392 }
1393 /**************************************************************************************************/
1394 int MothurOut::appendBinaryFiles(string temp, string filename) {
1395         try{
1396                 ofstream output;
1397                 ifstream input;
1398         
1399                 //open output file in append mode
1400                 openOutputFileBinaryAppend(filename, output);
1401                 int ableToOpen = openInputFileBinary(temp, input, "no error");
1402                 
1403                 if (ableToOpen == 0) { //you opened it
1404             
1405             char buffer[4096];
1406             while (!input.eof()) {
1407                 input.read(buffer, 4096);
1408                 output.write(buffer, input.gcount());
1409             }
1410                         input.close();
1411                 }
1412                 
1413                 output.close();
1414                 
1415                 return ableToOpen;
1416         }
1417         catch(exception& e) {
1418                 errorOut(e, "MothurOut", "appendBinaryFiles");
1419                 exit(1);
1420         }       
1421 }
1422
1423 /**************************************************************************************************/
1424 int MothurOut::appendFilesWithoutHeaders(string temp, string filename) {
1425         try{
1426                 ofstream output;
1427                 ifstream input;
1428         
1429                 //open output file in append mode
1430                 openOutputFileAppend(filename, output);
1431                 int ableToOpen = openInputFile(temp, input, "no error");
1432                 //int ableToOpen = openInputFile(temp, input);
1433                 
1434                 int numLines = 0;
1435                 if (ableToOpen == 0) { //you opened it
1436         
1437             string headers = getline(input); gobble(input);
1438             if (debug) { mothurOut("[DEBUG]: skipping headers " + headers +'\n'); }
1439             
1440             char buffer[4096];
1441             while (!input.eof()) {
1442                 input.read(buffer, 4096);
1443                 output.write(buffer, input.gcount());
1444                 //count number of lines
1445                 for (int i = 0; i < input.gcount(); i++) {  if (buffer[i] == '\n') {numLines++;} }
1446             }
1447                         input.close();
1448                 }
1449                 
1450                 output.close();
1451                 
1452                 return numLines;
1453         }
1454         catch(exception& e) {
1455                 errorOut(e, "MothurOut", "appendFiles");
1456                 exit(1);
1457         }       
1458 }
1459 /**************************************************************************************************/
1460 string MothurOut::sortFile(string distFile, string outputDir){
1461         try {   
1462         
1463                 //if (outputDir == "") {  outputDir += hasPath(distFile);  }
1464                 string outfile = getRootName(distFile) + "sorted.dist";
1465
1466                 
1467                 //if you can, use the unix sort since its been optimized for years
1468                 #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix)
1469                         string command = "sort -n -k +3 " + distFile + " -o " + outfile;
1470                         system(command.c_str());
1471                 #else //you are stuck with my best attempt...
1472                         //windows sort does not have a way to specify a column, only a character in the line
1473                         //since we cannot assume that the distance will always be at the the same character location on each line
1474                         //due to variable sequence name lengths, I chose to force the distance into first position, then sort and then put it back.
1475                 
1476                         //read in file line by file and put distance first
1477                         string tempDistFile = distFile + ".temp";
1478                         ifstream input;
1479                         ofstream output;
1480                         openInputFile(distFile, input);
1481                         openOutputFile(tempDistFile, output);
1482
1483                         string firstName, secondName;
1484                         float dist;
1485                         while (!input.eof()) {
1486                                 input >> firstName >> secondName >> dist;
1487                                 output << dist << '\t' << firstName << '\t' << secondName << endl;
1488                                 gobble(input);
1489                         }
1490                         input.close();
1491                         output.close();
1492                 
1493         
1494                         //sort using windows sort
1495                         string tempOutfile = outfile + ".temp";
1496                         string command = "sort " + tempDistFile + " /O " + tempOutfile;
1497                         system(command.c_str());
1498                 
1499                         //read in sorted file and put distance at end again
1500                         ifstream input2;
1501             ofstream output2;
1502                         openInputFile(tempOutfile, input2);
1503                         openOutputFile(outfile, output2);
1504                 
1505             while (!input2.eof()) {
1506                                 input2 >> dist >> firstName >> secondName;
1507                                 output2 << firstName << '\t' << secondName << '\t' << dist << endl;
1508                                 gobble(input2);
1509                         }
1510                         input2.close();
1511                         output2.close();
1512                 
1513                         //remove temp files
1514                         mothurRemove(tempDistFile);
1515                         mothurRemove(tempOutfile);
1516                 #endif
1517                 
1518                 return outfile;
1519         }
1520         catch(exception& e) {
1521                 errorOut(e, "MothurOut", "sortFile");
1522                 exit(1);
1523         }       
1524 }
1525 /**************************************************************************************************/
1526 vector<unsigned long long> MothurOut::setFilePosFasta(string filename, int& num) {
1527         try {
1528                         vector<unsigned long long> positions;
1529                         ifstream inFASTA;
1530                         //openInputFile(filename, inFASTA);
1531                         inFASTA.open(filename.c_str(), ios::binary);
1532                                                 
1533                         string input;
1534                         unsigned long long count = 0;
1535                         while(!inFASTA.eof()){
1536                                 //input = getline(inFASTA); 
1537                                 //cout << input << '\t' << inFASTA.tellg() << endl;
1538                                 //if (input.length() != 0) {
1539                                 //      if(input[0] == '>'){    unsigned long int pos = inFASTA.tellg(); positions.push_back(pos - input.length() - 1);  cout << (pos - input.length() - 1) << endl; }
1540                                 //}
1541                                 //gobble(inFASTA); //has to be here since windows line endings are 2 characters and mess up the positions
1542                                 char c = inFASTA.get(); count++;
1543                                 if (c == '>') {
1544                                         positions.push_back(count-1);
1545                                         if (debug) { mothurOut("[DEBUG]: numSeqs = " + toString(positions.size()) +  " count = " + toString(count) + ".\n"); }
1546                                 }
1547                         }
1548                         inFASTA.close();
1549                 
1550                         num = positions.size();
1551             if (debug) { mothurOut("[DEBUG]: num = " + toString(num) + ".\n"); }
1552                         FILE * pFile;
1553                         unsigned long long size;
1554                 
1555                         //get num bytes in file
1556                         pFile = fopen (filename.c_str(),"rb");
1557                         if (pFile==NULL) perror ("Error opening file");
1558                         else{
1559                                 fseek (pFile, 0, SEEK_END);
1560                                 size=ftell (pFile);
1561                                 fclose (pFile);
1562                         }
1563                         
1564                         /*unsigned long long size = positions[(positions.size()-1)];
1565                         ifstream in;
1566                         openInputFile(filename, in);
1567                         
1568                         in.seekg(size);
1569                 
1570                         while(in.get()){
1571                                 if(in.eof())            {       break;  }
1572                                 else                            {       size++; }
1573                         }
1574                         in.close();*/
1575         
1576             if (debug) { mothurOut("[DEBUG]: size = " + toString(size) + ".\n"); }
1577         
1578                         positions.push_back(size);
1579                         positions[0] = 0;
1580                 
1581                         return positions;
1582         }
1583         catch(exception& e) {
1584                 errorOut(e, "MothurOut", "setFilePosFasta");
1585                 exit(1);
1586         }
1587 }
1588 //**********************************************************************************************************************
1589 vector<consTax> MothurOut::readConsTax(string inputfile){
1590         try {
1591                 
1592         vector<consTax> taxes;
1593         
1594         ifstream in;
1595         openInputFile(inputfile, in);
1596         
1597         //read headers
1598         getline(in);
1599         
1600         while (!in.eof()) {
1601             
1602             if (control_pressed) { break; }
1603             
1604             string otu = ""; string tax = "unknown";
1605             int size = 0;
1606             
1607             in >> otu >> size >> tax; gobble(in);
1608             consTax temp(otu, tax, size);
1609             taxes.push_back(temp);
1610         }
1611         in.close();
1612         
1613         return taxes;
1614     }
1615         catch(exception& e) {
1616                 errorOut(e, "MothurOut", "readConsTax");
1617                 exit(1);
1618         }
1619 }
1620 //**********************************************************************************************************************
1621 int MothurOut::readConsTax(string inputfile, map<string, consTax2>& taxes){
1622         try {
1623         ifstream in;
1624         openInputFile(inputfile, in);
1625         
1626         //read headers
1627         getline(in);
1628         
1629         while (!in.eof()) {
1630             
1631             if (control_pressed) { break; }
1632             
1633             string otu = ""; string tax = "unknown";
1634             int size = 0;
1635             
1636             in >> otu >> size >> tax; gobble(in);
1637             consTax2 temp(tax, size);
1638             taxes[otu] = temp;
1639         }
1640         in.close();
1641         
1642         return 0;
1643     }
1644         catch(exception& e) {
1645                 errorOut(e, "MothurOut", "readConsTax");
1646                 exit(1);
1647         }
1648 }
1649 /**************************************************************************************************/
1650 vector<unsigned long long> MothurOut::setFilePosEachLine(string filename, int& num) {
1651         try {
1652                         filename = getFullPathName(filename);
1653                         
1654                         vector<unsigned long long> positions;
1655                         ifstream in;
1656                         //openInputFile(filename, in);
1657                         in.open(filename.c_str(), ios::binary);
1658                 
1659                         string input;
1660                         unsigned long long count = 0;
1661                         positions.push_back(0);
1662                 
1663                         while(!in.eof()){
1664                                 //getline counting reads
1665                                 char d = in.get(); count++;
1666                                 while ((d != '\n') && (d != '\r') && (d != '\f') && (d != in.eof()))    {
1667                                         //get next character
1668                                         d = in.get(); 
1669                                         count++;
1670                                 }
1671                                 
1672                                 if (!in.eof()) {
1673                                         d=in.get(); count++;
1674                                         while(isspace(d) && (d != in.eof()))            { d=in.get(); count++;}
1675                                 }
1676                                 positions.push_back(count-1);
1677                                 //cout << count-1 << endl;
1678                         }
1679                         in.close();
1680                 
1681                         num = positions.size()-1;
1682                 
1683                         FILE * pFile;
1684                         unsigned long long size;
1685                         
1686                         //get num bytes in file
1687                         pFile = fopen (filename.c_str(),"rb");
1688                         if (pFile==NULL) perror ("Error opening file");
1689                         else{
1690                                 fseek (pFile, 0, SEEK_END);
1691                                 size=ftell (pFile);
1692                                 fclose (pFile);
1693                         }
1694                 
1695                         positions[(positions.size()-1)] = size;
1696                 
1697                         return positions;
1698         }
1699         catch(exception& e) {
1700                 errorOut(e, "MothurOut", "setFilePosEachLine");
1701                 exit(1);
1702         }
1703 }
1704 /**************************************************************************************************/
1705
1706 vector<unsigned long long> MothurOut::divideFile(string filename, int& proc) {
1707         try{
1708                 vector<unsigned long long> filePos;
1709                 filePos.push_back(0);
1710                 
1711                 FILE * pFile;
1712                 unsigned long long size;
1713                 
1714                 filename = getFullPathName(filename);
1715         
1716                 //get num bytes in file
1717                 pFile = fopen (filename.c_str(),"rb");
1718                 if (pFile==NULL) perror ("Error opening file");
1719                 else{
1720                         fseek (pFile, 0, SEEK_END);
1721                         size=ftell (pFile);
1722                         fclose (pFile);
1723                 }
1724                 
1725         #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix)
1726                                 
1727                 //estimate file breaks
1728                 unsigned long long chunkSize = 0;
1729                 chunkSize = size / proc;
1730
1731                 //file to small to divide by processors
1732                 if (chunkSize == 0)  {  proc = 1;       filePos.push_back(size); return filePos;        }
1733         
1734                 //for each process seekg to closest file break and search for next '>' char. make that the filebreak
1735                 for (int i = 0; i < proc; i++) {
1736                         unsigned long long spot = (i+1) * chunkSize;
1737                         
1738                         ifstream in;
1739                         openInputFile(filename, in);
1740                         in.seekg(spot);
1741                         
1742                         //look for next '>'
1743                         unsigned long long newSpot = spot;
1744                         while (!in.eof()) {
1745                            char c = in.get();
1746                                 
1747                            if (c == '>') {   in.putback(c); newSpot = in.tellg(); break;  }
1748                            else if (int(c) == -1) { break; }
1749                                 
1750                         }
1751                 
1752                         //there was not another sequence before the end of the file
1753                         unsigned long long sanityPos = in.tellg();
1754
1755                         if (sanityPos == -1) {  break;  }
1756                         else {  filePos.push_back(newSpot);  }
1757                         
1758                         in.close();
1759                 }
1760                 
1761                 //save end pos
1762                 filePos.push_back(size);
1763                 
1764                 //sanity check filePos
1765                 for (int i = 0; i < (filePos.size()-1); i++) {
1766                         if (filePos[(i+1)] <= filePos[i]) {  filePos.erase(filePos.begin()+(i+1)); i--; }
1767                 }
1768
1769                 proc = (filePos.size() - 1);
1770 #else
1771                 mothurOut("[ERROR]: Windows version should not be calling the divideFile function."); mothurOutEndLine();
1772                 proc=1;
1773                 filePos.push_back(size);
1774 #endif
1775                 return filePos;
1776         }
1777         catch(exception& e) {
1778                 errorOut(e, "MothurOut", "divideFile");
1779                 exit(1);
1780         }
1781 }
1782 /**************************************************************************************************/
1783
1784 vector<unsigned long long> MothurOut::divideFilePerLine(string filename, int& proc) {
1785         try{
1786                 vector<unsigned long long> filePos;
1787                 filePos.push_back(0);
1788                 
1789                 FILE * pFile;
1790                 unsigned long long size;
1791                 
1792                 filename = getFullPathName(filename);
1793         
1794                 //get num bytes in file
1795                 pFile = fopen (filename.c_str(),"rb");
1796                 if (pFile==NULL) perror ("Error opening file");
1797                 else{
1798                         fseek (pFile, 0, SEEK_END);
1799                         size=ftell (pFile);
1800                         fclose (pFile);
1801                 }
1802                 
1803 #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix)
1804         
1805                 //estimate file breaks
1806                 unsigned long long chunkSize = 0;
1807                 chunkSize = size / proc;
1808         
1809                 //file to small to divide by processors
1810                 if (chunkSize == 0)  {  proc = 1;       filePos.push_back(size); return filePos;        }
1811         
1812                 //for each process seekg to closest file break and search for next '>' char. make that the filebreak
1813                 for (int i = 0; i < proc; i++) {
1814                         unsigned long long spot = (i+1) * chunkSize;
1815                         
1816                         ifstream in;
1817                         openInputFile(filename, in);
1818                         in.seekg(spot);
1819                         
1820                         //look for next line break
1821                         unsigned long long newSpot = spot;
1822                         while (!in.eof()) {
1823                 char c = in.get();
1824                                 
1825                                 if ((c == '\n') || (c == '\r') || (c == '\f'))  { gobble(in); newSpot = in.tellg(); break; }
1826                 else if (int(c) == -1) { break; }
1827             }
1828             
1829                         //there was not another line before the end of the file
1830                         unsigned long long sanityPos = in.tellg();
1831             
1832                         if (sanityPos == -1) {  break;  }
1833                         else {  filePos.push_back(newSpot);  }
1834                         
1835                         in.close();
1836                 }
1837                 
1838                 //save end pos
1839                 filePos.push_back(size);
1840                 
1841                 //sanity check filePos
1842                 for (int i = 0; i < (filePos.size()-1); i++) {
1843                         if (filePos[(i+1)] <= filePos[i]) {  filePos.erase(filePos.begin()+(i+1)); i--; }
1844                 }
1845         
1846                 proc = (filePos.size() - 1);
1847 #else
1848                 mothurOut("[ERROR]: Windows version should not be calling the divideFile function."); mothurOutEndLine();
1849                 proc=1;
1850                 filePos.push_back(size);
1851 #endif
1852                 return filePos;
1853         }
1854         catch(exception& e) {
1855                 errorOut(e, "MothurOut", "divideFile");
1856                 exit(1);
1857         }
1858 }
1859 /**************************************************************************************************/
1860 int MothurOut::divideFile(string filename, int& proc, vector<string>& files) {
1861         try{
1862                 
1863                 vector<unsigned long long> filePos = divideFile(filename, proc);
1864                 
1865                 for (int i = 0; i < (filePos.size()-1); i++) {
1866                         
1867                         //read file chunk
1868                         ifstream in;
1869                         openInputFile(filename, in);
1870                         in.seekg(filePos[i]);
1871                         unsigned long long size = filePos[(i+1)] - filePos[i];
1872                         char* chunk = new char[size];
1873                         in.read(chunk, size);
1874                         in.close();
1875                         
1876                         //open new file
1877                         string fileChunkName = filename + "." + toString(i) + ".tmp";
1878                         ofstream out; 
1879                         openOutputFile(fileChunkName, out);
1880                         
1881                         out << chunk << endl;
1882                         out.close();
1883                         delete[] chunk;
1884                         
1885                         //save name
1886                         files.push_back(fileChunkName);
1887                 }
1888                                 
1889                 return 0;
1890         }
1891         catch(exception& e) {
1892                 errorOut(e, "MothurOut", "divideFile");
1893                 exit(1);
1894         }
1895 }
1896 /***********************************************************************/
1897
1898 bool MothurOut::isTrue(string f){
1899         try {
1900                 
1901                 for (int i = 0; i < f.length(); i++) { f[i] = toupper(f[i]); }
1902                 
1903                 if ((f == "TRUE") || (f == "T")) {      return true;    }
1904                 else {  return false;  }
1905         }
1906         catch(exception& e) {
1907                 errorOut(e, "MothurOut", "isTrue");
1908                 exit(1);
1909         }
1910 }
1911
1912 /***********************************************************************/
1913
1914 float MothurOut::roundDist(float dist, int precision){
1915         try {
1916                 return int(dist * precision + 0.5)/float(precision);
1917         }
1918         catch(exception& e) {
1919                 errorOut(e, "MothurOut", "roundDist");
1920                 exit(1);
1921         }
1922 }
1923 /***********************************************************************/
1924
1925 float MothurOut::ceilDist(float dist, int precision){
1926         try {
1927                 return int(ceil(dist * precision))/float(precision);
1928         }
1929         catch(exception& e) {
1930                 errorOut(e, "MothurOut", "ceilDist");
1931                 exit(1);
1932         }
1933 }
1934 /***********************************************************************/
1935
1936 vector<string> MothurOut::splitWhiteSpace(string& rest, char buffer[], int size){
1937         try {
1938         vector<string> pieces;
1939         
1940         for (int i = 0; i < size; i++) {
1941             if (!isspace(buffer[i]))  { rest += buffer[i];  }
1942             else {
1943                 if (rest != "") { pieces.push_back(rest);  rest = ""; }
1944                 while (i < size) {  //gobble white space
1945                     if (isspace(buffer[i])) { i++; }
1946                     else { rest = buffer[i];  break; } //cout << "next piece buffer = " << nextPiece << endl;
1947                 } 
1948             }
1949         }
1950         
1951         return pieces;
1952         }
1953         catch(exception& e) {
1954                 errorOut(e, "MothurOut", "splitWhiteSpace");
1955                 exit(1);
1956         }
1957 }
1958 /***********************************************************************/
1959 vector<string> MothurOut::splitWhiteSpace(string input){
1960         try {
1961         vector<string> pieces;
1962         string rest = "";
1963         
1964         for (int i = 0; i < input.length(); i++) {
1965             if (!isspace(input[i]))  { rest += input[i];  }
1966             else {
1967                 if (rest != "") { pieces.push_back(rest);  rest = ""; }
1968                 while (i < input.length()) {  //gobble white space
1969                     if (isspace(input[i])) { i++; }
1970                     else { rest = input[i];  break; } //cout << "next piece buffer = " << nextPiece << endl;
1971                 } 
1972             }
1973         }
1974         
1975         if (rest != "") { pieces.push_back(rest); }
1976         
1977         return pieces;
1978         }
1979         catch(exception& e) {
1980                 errorOut(e, "MothurOut", "splitWhiteSpace");
1981                 exit(1);
1982         }
1983 }
1984 /***********************************************************************/
1985 vector<string> MothurOut::splitWhiteSpaceWithQuotes(string input){
1986         try {
1987         vector<string> pieces;
1988         string rest = "";
1989         
1990         int pos = input.find('\'');
1991         int pos2 = input.find('\"');
1992         
1993         if ((pos == string::npos) && (pos2 == string::npos)) { return splitWhiteSpace(input); } //no quotes to worry about
1994         else {
1995             for (int i = 0; i < input.length(); i++) {
1996                 if ((input[i] == '\'') || (input[i] == '\"') || (rest == "\'") || (rest == "\"")) { //grab everything til end or next ' or "
1997                     rest += input[i];
1998                     for (int j = i+1; j < input.length(); j++) {
1999                         if ((input[j] == '\'') || (input[j] == '\"')) {  //then quit
2000                             rest += input[j];
2001                             i = j+1;
2002                             j+=input.length();
2003                         }else { rest += input[j]; }
2004                     }
2005                 }else if (!isspace(input[i]))  { rest += input[i];  }
2006                 else {
2007                     if (rest != "") { pieces.push_back(rest);  rest = ""; }
2008                     while (i < input.length()) {  //gobble white space
2009                         if (isspace(input[i])) { i++; }
2010                         else { rest = input[i];  break; } //cout << "next piece buffer = " << nextPiece << endl;
2011                     } 
2012                 }
2013             }
2014             
2015             if (rest != "") { pieces.push_back(rest); }
2016         }
2017         return pieces;
2018         }
2019         catch(exception& e) {
2020                 errorOut(e, "MothurOut", "splitWhiteSpace");
2021                 exit(1);
2022         }
2023 }
2024 //**********************************************************************************************************************
2025 int MothurOut::readTax(string namefile, map<string, string>& taxMap) {
2026         try {
2027         //open input file
2028                 ifstream in;
2029                 openInputFile(namefile, in);
2030         
2031         string rest = "";
2032         char buffer[4096];
2033         bool pairDone = false;
2034         bool columnOne = true;
2035         string firstCol, secondCol;
2036         bool error = false;
2037         
2038                 while (!in.eof()) {
2039                         if (control_pressed) { break; }
2040                         
2041             in.read(buffer, 4096);
2042             vector<string> pieces = splitWhiteSpace(rest, buffer, in.gcount());
2043             
2044             for (int i = 0; i < pieces.size(); i++) {
2045                 if (columnOne) {  firstCol = pieces[i]; columnOne=false; }
2046                 else  { secondCol = pieces[i]; pairDone = true; columnOne=true; }
2047                 
2048                 if (pairDone) { 
2049                     checkName(firstCol);
2050                     //are there confidence scores, if so remove them
2051                     if (secondCol.find_first_of('(') != -1) {  removeConfidences(secondCol);    }
2052                     map<string, string>::iterator itTax = taxMap.find(firstCol);
2053                     
2054                     if(itTax == taxMap.end()) {
2055                         bool ignore = false;
2056                         if (secondCol != "") { if (secondCol[secondCol.length()-1] != ';') { mothurOut("[ERROR]: " + firstCol + " is missing the final ';', ignoring.\n"); ignore=true; }
2057                         }
2058                         if (!ignore) { taxMap[firstCol] = secondCol; }
2059                         if (debug) {  mothurOut("[DEBUG]: name = '" + firstCol + "' tax = '" + secondCol + "'\n");  }
2060                     }else {
2061                         mothurOut("[ERROR]: " + firstCol + " is already in your taxonomy file, names must be unique.\n"); error = true;
2062                     }
2063                     pairDone = false; 
2064                 }
2065             }
2066                 }
2067                 in.close();
2068         
2069         if (rest != "") {
2070             vector<string> pieces = splitWhiteSpace(rest);
2071             
2072             for (int i = 0; i < pieces.size(); i++) {
2073                 if (columnOne) {  firstCol = pieces[i]; columnOne=false; }
2074                 else  { secondCol = pieces[i]; pairDone = true; columnOne=true; }
2075                 
2076                 if (pairDone) { 
2077                     checkName(firstCol);
2078                     //are there confidence scores, if so remove them
2079                     if (secondCol.find_first_of('(') != -1) {  removeConfidences(secondCol);    }
2080                     map<string, string>::iterator itTax = taxMap.find(firstCol);
2081                     
2082                     if(itTax == taxMap.end()) {
2083                         bool ignore = false;
2084                         if (secondCol != "") { if (secondCol[secondCol.length()-1] != ';') { mothurOut("[ERROR]: " + firstCol + " is missing the final ';', ignoring.\n"); ignore=true; }
2085                         }
2086                         if (!ignore) { taxMap[firstCol] = secondCol; }
2087                         if (debug) {  mothurOut("[DEBUG]: name = '" + firstCol + "' tax = '" + secondCol + "'\n");  }
2088                     }else {
2089                         mothurOut("[ERROR]: " + firstCol + " is already in your taxonomy file, names must be unique./n"); error = true;
2090                     }
2091
2092                     pairDone = false; 
2093                 }
2094             } 
2095         }
2096                 
2097         if (error) { control_pressed = true; }
2098         if (debug) {  mothurOut("[DEBUG]: numSeqs saved = '" + toString(taxMap.size()) + "'\n"); }
2099                 return taxMap.size();
2100
2101         }
2102         catch(exception& e) {
2103                 errorOut(e, "MothurOut", "readTax");
2104                 exit(1);
2105         }
2106 }
2107 /**********************************************************************************************************************/
2108 int MothurOut::readNames(string namefile, map<string, string>& nameMap, bool redund) { 
2109         try {
2110                 //open input file
2111                 ifstream in;
2112                 openInputFile(namefile, in);
2113         
2114         string rest = "";
2115         char buffer[4096];
2116         bool pairDone = false;
2117         bool columnOne = true;
2118         string firstCol, secondCol;
2119         
2120                 while (!in.eof()) {
2121                         if (control_pressed) { break; }
2122                         
2123             in.read(buffer, 4096);
2124             vector<string> pieces = splitWhiteSpace(rest, buffer, in.gcount());
2125             
2126             for (int i = 0; i < pieces.size(); i++) {
2127                 if (columnOne) {  firstCol = pieces[i]; columnOne=false; }
2128                 else  { secondCol = pieces[i]; pairDone = true; columnOne=true; }
2129                 
2130                 if (pairDone) { 
2131                     checkName(firstCol);
2132                     checkName(secondCol);
2133                     
2134                     //parse names into vector
2135                     vector<string> theseNames;
2136                     splitAtComma(secondCol, theseNames);
2137                     for (int i = 0; i < theseNames.size(); i++) {  nameMap[theseNames[i]] = firstCol;  }
2138                     pairDone = false; 
2139                 }
2140             }
2141                 }
2142                 in.close();
2143         
2144         if (rest != "") {
2145             vector<string> pieces = splitWhiteSpace(rest);
2146             
2147             for (int i = 0; i < pieces.size(); i++) {
2148                 if (columnOne) {  firstCol = pieces[i]; columnOne=false; }
2149                 else  { secondCol = pieces[i]; pairDone = true; columnOne=true; }
2150                 
2151                 if (pairDone) { 
2152                     checkName(firstCol);
2153                     checkName(secondCol);
2154                     
2155                     //parse names into vector
2156                     vector<string> theseNames;
2157                     splitAtComma(secondCol, theseNames);
2158                     for (int i = 0; i < theseNames.size(); i++) {   nameMap[theseNames[i]] = firstCol;  }
2159                     pairDone = false; 
2160                 }
2161             }  
2162         }
2163                 
2164                 return nameMap.size();
2165                 
2166         }
2167         catch(exception& e) {
2168                 errorOut(e, "MothurOut", "readNames");
2169                 exit(1);
2170         }
2171 }
2172 /**********************************************************************************************************************/
2173 int MothurOut::readNames(string namefile, map<string, string>& nameMap, int flip) { 
2174         try {
2175                 //open input file
2176                 ifstream in;
2177                 openInputFile(namefile, in);
2178         
2179         string rest = "";
2180         char buffer[4096];
2181         bool pairDone = false;
2182         bool columnOne = true;
2183         string firstCol, secondCol;
2184         
2185                 while (!in.eof()) {
2186                         if (control_pressed) { break; }
2187                         
2188             in.read(buffer, 4096);
2189             vector<string> pieces = splitWhiteSpace(rest, buffer, in.gcount());
2190             
2191             for (int i = 0; i < pieces.size(); i++) {
2192                 if (columnOne) {  firstCol = pieces[i]; columnOne=false; }
2193                 else  { secondCol = pieces[i]; pairDone = true; columnOne=true; }
2194                 
2195                 if (pairDone) { 
2196                     checkName(firstCol);
2197                     checkName(secondCol);
2198                     nameMap[secondCol] = firstCol;
2199                     pairDone = false; 
2200                 }
2201             }
2202                 }
2203                 in.close();
2204         
2205         if (rest != "") {
2206             vector<string> pieces = splitWhiteSpace(rest);
2207             
2208             for (int i = 0; i < pieces.size(); i++) {
2209                 if (columnOne) {  firstCol = pieces[i]; columnOne=false; }
2210                 else  { secondCol = pieces[i]; pairDone = true; columnOne=true; }
2211                 
2212                 if (pairDone) { 
2213                     checkName(firstCol);
2214                     checkName(secondCol);
2215                     nameMap[secondCol] = firstCol;
2216                     pairDone = false; 
2217                 }
2218             } 
2219         }
2220                 
2221                 return nameMap.size();
2222                 
2223         }
2224         catch(exception& e) {
2225                 errorOut(e, "MothurOut", "readNames");
2226                 exit(1);
2227         }
2228 }
2229 /**********************************************************************************************************************/
2230 int MothurOut::readNames(string namefile, map<string, string>& nameMap, map<string, int>& nameCount) { 
2231         try {
2232                 nameMap.clear(); nameCount.clear();
2233                 //open input file
2234                 ifstream in;
2235                 openInputFile(namefile, in);
2236         
2237         string rest = "";
2238         char buffer[4096];
2239         bool pairDone = false;
2240         bool columnOne = true;
2241         string firstCol, secondCol;
2242         
2243                 while (!in.eof()) {
2244                         if (control_pressed) { break; }
2245                         
2246             in.read(buffer, 4096);
2247             vector<string> pieces = splitWhiteSpace(rest, buffer, in.gcount());
2248             
2249             for (int i = 0; i < pieces.size(); i++) {
2250                 if (columnOne) {  firstCol = pieces[i]; columnOne=false; }
2251                 else  { secondCol = pieces[i]; pairDone = true; columnOne=true; }
2252                 
2253                 if (pairDone) { 
2254                     checkName(firstCol);
2255                     checkName(secondCol);
2256                     //parse names into vector
2257                     vector<string> theseNames;
2258                     splitAtComma(secondCol, theseNames);
2259                     for (int i = 0; i < theseNames.size(); i++) {  nameMap[theseNames[i]] = firstCol;  }
2260                     nameCount[firstCol] = theseNames.size();
2261                     pairDone = false; 
2262                 }
2263             }
2264                 }
2265                 in.close();
2266                 
2267         if (rest != "") {
2268             vector<string> pieces = splitWhiteSpace(rest);
2269             
2270             for (int i = 0; i < pieces.size(); i++) {
2271                 if (columnOne) {  firstCol = pieces[i]; columnOne=false; }
2272                 else  { secondCol = pieces[i]; pairDone = true; columnOne=true; }
2273                 
2274                 if (pairDone) { 
2275                     checkName(firstCol);
2276                     checkName(secondCol);
2277                     //parse names into vector
2278                     vector<string> theseNames;
2279                     splitAtComma(secondCol, theseNames);
2280                     for (int i = 0; i < theseNames.size(); i++) {  nameMap[theseNames[i]] = firstCol;  }
2281                     nameCount[firstCol] = theseNames.size();
2282                     pairDone = false; 
2283                 }
2284             }
2285
2286         }
2287                 return nameMap.size();
2288                 
2289         }
2290         catch(exception& e) {
2291                 errorOut(e, "MothurOut", "readNames");
2292                 exit(1);
2293         }
2294 }
2295 /**********************************************************************************************************************/
2296 int MothurOut::readNames(string namefile, map<string, string>& nameMap) { 
2297         try {
2298                 //open input file
2299                 ifstream in;
2300                 openInputFile(namefile, in);
2301
2302         string rest = "";
2303         char buffer[4096];
2304         bool pairDone = false;
2305         bool columnOne = true;
2306         string firstCol, secondCol;
2307         
2308                 while (!in.eof()) {
2309                         if (control_pressed) { break; }
2310                         
2311             in.read(buffer, 4096);
2312             vector<string> pieces = splitWhiteSpace(rest, buffer, in.gcount());
2313              
2314             for (int i = 0; i < pieces.size(); i++) {
2315                 if (columnOne) {  firstCol = pieces[i]; columnOne=false; }
2316                 else  { secondCol = pieces[i]; pairDone = true; columnOne=true; }
2317                 
2318                 if (pairDone) { 
2319                     checkName(firstCol);
2320                     checkName(secondCol);
2321                     nameMap[firstCol] = secondCol; pairDone = false; }
2322             }
2323                 }
2324                 in.close();
2325         
2326         if (rest != "") {
2327             vector<string> pieces = splitWhiteSpace(rest);
2328             
2329             for (int i = 0; i < pieces.size(); i++) {
2330                 if (columnOne) {  firstCol = pieces[i]; columnOne=false; }
2331                 else  { secondCol = pieces[i]; pairDone = true; columnOne=true; }
2332                 
2333                 if (pairDone) { 
2334                     checkName(firstCol);
2335                     checkName(secondCol);
2336                     nameMap[firstCol] = secondCol; pairDone = false; }
2337             }
2338         }
2339                 
2340                 return nameMap.size();
2341                 
2342         }
2343         catch(exception& e) {
2344                 errorOut(e, "MothurOut", "readNames");
2345                 exit(1);
2346         }
2347 }
2348 /**********************************************************************************************************************/
2349 int MothurOut::readNames(string namefile, map<string, vector<string> >& nameMap) { 
2350         try {        
2351                 //open input file
2352                 ifstream in;
2353                 openInputFile(namefile, in);
2354                 
2355         string rest = "";
2356         char buffer[4096];
2357         bool pairDone = false;
2358         bool columnOne = true;
2359         string firstCol, secondCol;
2360         
2361                 while (!in.eof()) {
2362                         if (control_pressed) { break; }
2363                         
2364             in.read(buffer, 4096);
2365             vector<string> pieces = splitWhiteSpace(rest, buffer, in.gcount());
2366             
2367             for (int i = 0; i < pieces.size(); i++) {
2368                 if (columnOne) {  firstCol = pieces[i]; columnOne=false; }
2369                 else  { secondCol = pieces[i]; pairDone = true; columnOne=true; }
2370                 
2371                 if (pairDone) { 
2372                     checkName(firstCol);
2373                     checkName(secondCol);
2374                     vector<string> temp;
2375                     splitAtComma(secondCol, temp);
2376                     nameMap[firstCol] = temp;
2377                     pairDone = false;  
2378                 } 
2379             }
2380                 }
2381                 in.close();
2382         
2383         if (rest != "") {
2384             vector<string> pieces = splitWhiteSpace(rest);
2385             
2386             for (int i = 0; i < pieces.size(); i++) {
2387                 if (columnOne) {  firstCol = pieces[i]; columnOne=false; }
2388                 else  { secondCol = pieces[i]; pairDone = true; columnOne=true; }
2389                 
2390                 if (pairDone) { 
2391                     checkName(firstCol);
2392                     checkName(secondCol);
2393                     vector<string> temp;
2394                     splitAtComma(secondCol, temp);
2395                     nameMap[firstCol] = temp;
2396                     pairDone = false;  
2397                 } 
2398             }
2399         }
2400         
2401                 return nameMap.size();
2402         }
2403         catch(exception& e) {
2404                 errorOut(e, "MothurOut", "readNames");
2405                 exit(1);
2406         }
2407 }
2408 /**********************************************************************************************************************/
2409 map<string, int> MothurOut::readNames(string namefile) { 
2410         try {
2411                 map<string, int> nameMap;
2412                 
2413                 //open input file
2414                 ifstream in;
2415                 openInputFile(namefile, in);
2416                 
2417         string rest = "";
2418         char buffer[4096];
2419         bool pairDone = false;
2420         bool columnOne = true;
2421         string firstCol, secondCol;
2422         
2423                 while (!in.eof()) {
2424                         if (control_pressed) { break; }
2425                         
2426             in.read(buffer, 4096);
2427             vector<string> pieces = splitWhiteSpace(rest, buffer, in.gcount());
2428             
2429             for (int i = 0; i < pieces.size(); i++) {
2430                 if (columnOne) {  firstCol = pieces[i]; columnOne=false; }
2431                 else  { secondCol = pieces[i]; pairDone = true; columnOne=true; }
2432                 
2433                 if (pairDone) { 
2434                     checkName(firstCol);
2435                     checkName(secondCol);
2436                     int num = getNumNames(secondCol);
2437                     nameMap[firstCol] = num;
2438                     pairDone = false;  
2439                 } 
2440             }
2441                 }
2442         in.close();
2443         
2444         if (rest != "") {
2445             vector<string> pieces = splitWhiteSpace(rest);
2446             for (int i = 0; i < pieces.size(); i++) {
2447                 if (columnOne) {  firstCol = pieces[i]; columnOne=false; }
2448                 else  { secondCol = pieces[i]; pairDone = true; columnOne=true; }
2449                 
2450                 if (pairDone) { 
2451                     checkName(firstCol);
2452                     checkName(secondCol);
2453                     int num = getNumNames(secondCol);
2454                     nameMap[firstCol] = num;
2455                     pairDone = false;  
2456                 } 
2457             }
2458         }
2459                 
2460                 return nameMap;
2461                 
2462         }
2463         catch(exception& e) {
2464                 errorOut(e, "MothurOut", "readNames");
2465                 exit(1);
2466         }
2467 }
2468 /**********************************************************************************************************************/
2469 map<string, int> MothurOut::readNames(string namefile, unsigned long int& numSeqs) { 
2470         try {
2471                 map<string, int> nameMap;
2472         numSeqs = 0;
2473                 
2474                 //open input file
2475                 ifstream in;
2476                 openInputFile(namefile, in);
2477                 
2478         string rest = "";
2479         char buffer[4096];
2480         bool pairDone = false;
2481         bool columnOne = true;
2482         string firstCol, secondCol;
2483         
2484                 while (!in.eof()) {
2485                         if (control_pressed) { break; }
2486                         
2487             in.read(buffer, 4096);
2488             vector<string> pieces = splitWhiteSpace(rest, buffer, in.gcount());
2489             
2490             for (int i = 0; i < pieces.size(); i++) {
2491                 if (columnOne) {  firstCol = pieces[i]; columnOne=false; }
2492                 else  { secondCol = pieces[i]; pairDone = true; columnOne=true; }
2493                 
2494                 if (pairDone) { 
2495                     checkName(firstCol);
2496                     checkName(secondCol);
2497                     int num = getNumNames(secondCol);
2498                     nameMap[firstCol] = num;
2499                     pairDone = false;  
2500                     numSeqs += num;
2501                 } 
2502             }
2503                 }
2504         in.close();
2505         
2506         if (rest != "") {
2507             vector<string> pieces = splitWhiteSpace(rest);
2508             for (int i = 0; i < pieces.size(); i++) {
2509                 if (columnOne) {  firstCol = pieces[i]; columnOne=false; }
2510                 else  { secondCol = pieces[i]; pairDone = true; columnOne=true; }
2511                 
2512                 if (pairDone) { 
2513                     checkName(firstCol);
2514                     checkName(secondCol);
2515                     int num = getNumNames(secondCol);
2516                     nameMap[firstCol] = num;
2517                     pairDone = false;  
2518                     numSeqs += num;
2519                 } 
2520             }
2521         }
2522                 
2523                 return nameMap;
2524                 
2525         }
2526         catch(exception& e) {
2527                 errorOut(e, "MothurOut", "readNames");
2528                 exit(1);
2529         }
2530 }
2531 /************************************************************/
2532 int MothurOut::checkName(string& name) {
2533     try {
2534         if (modifyNames) {
2535             for (int i = 0; i < name.length(); i++) {
2536                 if (name[i] == ':') { name[i] = '_'; changedSeqNames = true; }
2537             }
2538         }
2539         return 0;
2540     }
2541         catch(exception& e) {
2542                 errorOut(e, "MothurOut", "checkName");
2543                 exit(1);
2544         }
2545 }
2546 /**********************************************************************************************************************/
2547 int MothurOut::readNames(string namefile, vector<seqPriorityNode>& nameVector, map<string, string>& fastamap) { 
2548         try {
2549                 int error = 0;
2550                 
2551                 //open input file
2552                 ifstream in;
2553                 openInputFile(namefile, in);
2554                 
2555         string rest = "";
2556         char buffer[4096];
2557         bool pairDone = false;
2558         bool columnOne = true;
2559         string firstCol, secondCol;
2560         
2561                 while (!in.eof()) {
2562                         if (control_pressed) { break; }
2563                         
2564             in.read(buffer, 4096);
2565             vector<string> pieces = splitWhiteSpace(rest, buffer, in.gcount());
2566             
2567             for (int i = 0; i < pieces.size(); i++) {
2568                 if (columnOne) {  firstCol = pieces[i]; columnOne=false; }
2569                 else  { secondCol = pieces[i]; pairDone = true; columnOne=true; }
2570                 
2571                 if (pairDone) { 
2572                     checkName(firstCol);
2573                     checkName(secondCol);
2574                     int num = getNumNames(secondCol);
2575                     
2576                     map<string, string>::iterator it = fastamap.find(firstCol);
2577                     if (it == fastamap.end()) {
2578                         error = 1;
2579                         mothurOut("[ERROR]: " + firstCol + " is not in your fastafile, but is in your namesfile, please correct."); mothurOutEndLine();
2580                     }else {
2581                         seqPriorityNode temp(num, it->second, firstCol);
2582                         nameVector.push_back(temp);
2583                     }
2584                     
2585                     pairDone = false;  
2586                 } 
2587             }
2588                 }
2589         in.close();
2590         
2591         if (rest != "") {
2592             vector<string> pieces = splitWhiteSpace(rest);
2593             
2594             for (int i = 0; i < pieces.size(); i++) {
2595                 if (columnOne) {  firstCol = pieces[i]; columnOne=false; }
2596                 else  { secondCol = pieces[i]; pairDone = true; columnOne=true; }
2597                 
2598                 if (pairDone) { 
2599                     checkName(firstCol);
2600                     checkName(secondCol);
2601                     int num = getNumNames(secondCol);
2602                     
2603                     map<string, string>::iterator it = fastamap.find(firstCol);
2604                     if (it == fastamap.end()) {
2605                         error = 1;
2606                         mothurOut("[ERROR]: " + firstCol + " is not in your fastafile, but is in your namesfile, please correct."); mothurOutEndLine();
2607                     }else {
2608                         seqPriorityNode temp(num, it->second, firstCol);
2609                         nameVector.push_back(temp);
2610                     }
2611                     
2612                     pairDone = false;  
2613                 } 
2614             }
2615         }
2616                 return error;
2617         }
2618         catch(exception& e) {
2619                 errorOut(e, "MothurOut", "readNames");
2620                 exit(1);
2621         }
2622 }
2623 //**********************************************************************************************************************
2624 set<string> MothurOut::readAccnos(string accnosfile){
2625         try {
2626                 set<string> names;
2627                 ifstream in;
2628                 openInputFile(accnosfile, in);
2629                 string name;
2630                 
2631         string rest = "";
2632         char buffer[4096];
2633         
2634                 while (!in.eof()) {
2635                         if (control_pressed) { break; }
2636                         
2637             in.read(buffer, 4096);
2638             vector<string> pieces = splitWhiteSpace(rest, buffer, in.gcount());
2639             
2640             for (int i = 0; i < pieces.size(); i++) {  checkName(pieces[i]);
2641                 names.insert(pieces[i]);
2642             }
2643         }
2644                 in.close();     
2645                 
2646         if (rest != "") {
2647             vector<string> pieces = splitWhiteSpace(rest);
2648             for (int i = 0; i < pieces.size(); i++) {  checkName(pieces[i]); names.insert(pieces[i]);  } 
2649         }
2650                 return names;
2651         }
2652         catch(exception& e) {
2653                 errorOut(e, "MothurOut", "readAccnos");
2654                 exit(1);
2655         }
2656 }
2657 //**********************************************************************************************************************
2658 int MothurOut::readAccnos(string accnosfile, vector<string>& names){
2659         try {
2660         names.clear();
2661                 ifstream in;
2662                 openInputFile(accnosfile, in);
2663                 string name;
2664                 
2665         string rest = "";
2666         char buffer[4096];
2667         
2668                 while (!in.eof()) {
2669                         if (control_pressed) { break; }
2670                         
2671             in.read(buffer, 4096);
2672             vector<string> pieces = splitWhiteSpace(rest, buffer, in.gcount());
2673             
2674             for (int i = 0; i < pieces.size(); i++) {  checkName(pieces[i]); names.push_back(pieces[i]);  }
2675         }
2676                 in.close();     
2677         
2678         if (rest != "") {
2679             vector<string> pieces = splitWhiteSpace(rest);
2680             for (int i = 0; i < pieces.size(); i++) {  checkName(pieces[i]); names.push_back(pieces[i]);  }
2681         }
2682                 
2683                 return 0;
2684         }
2685         catch(exception& e) {
2686                 errorOut(e, "MothurOut", "readAccnos");
2687                 exit(1);
2688         }
2689 }
2690 /***********************************************************************/
2691
2692 int MothurOut::getNumNames(string names){
2693         try {
2694                 int count = 0;
2695                 
2696                 if(names != ""){
2697                         count = 1;
2698                         for(int i=0;i<names.size();i++){
2699                                 if(names[i] == ','){
2700                                         count++;
2701                                 }
2702                         }
2703                 }
2704                 
2705                 return count;
2706         }
2707         catch(exception& e) {
2708                 errorOut(e, "MothurOut", "getNumNames");
2709                 exit(1);
2710         }
2711 }
2712 /***********************************************************************/
2713
2714 int MothurOut::getNumChar(string line, char c){
2715         try {
2716                 int count = 0;
2717                 
2718                 if(line != ""){
2719                         for(int i=0;i<line.size();i++){
2720                                 if(line[i] == c){
2721                                         count++;
2722                                 }
2723                         }
2724                 }
2725                 
2726                 return count;
2727         }
2728         catch(exception& e) {
2729                 errorOut(e, "MothurOut", "getNumChar");
2730                 exit(1);
2731         }
2732 }
2733 /***********************************************************************/
2734 string MothurOut::getSimpleLabel(string label){
2735         try {
2736                 string simple = "";
2737         
2738         //remove OTU or phylo tag
2739         string newLabel1 = "";
2740         for (int i = 0; i < label.length(); i++) {
2741             if(label[i]>47 && label[i]<58) { //is a digit
2742                 newLabel1 += label[i];
2743             }
2744         }
2745         
2746         int num1;
2747         mothurConvert(newLabel1, num1);
2748         
2749         simple = toString(num1);
2750         
2751                 return simple;
2752         }
2753         catch(exception& e) {
2754                 errorOut(e, "MothurOut", "isLabelEquivalent");
2755                 exit(1);
2756         }
2757 }
2758 /***********************************************************************/
2759
2760 bool MothurOut::isLabelEquivalent(string label1,  string label2){
2761         try {
2762                 bool same = false;
2763         
2764         //remove OTU or phylo tag
2765         string newLabel1 = "";
2766         for (int i = 0; i < label1.length(); i++) {
2767             if(label1[i]>47 && label1[i]<58) { //is a digit
2768                 newLabel1 += label1[i];
2769             }
2770         }
2771         
2772         string newLabel2 = "";
2773         for (int i = 0; i < label2.length(); i++) {
2774             if(label2[i]>47 && label2[i]<58) { //is a digit
2775                 newLabel2 += label2[i];
2776             }
2777         }
2778         
2779         int num1, num2;
2780         mothurConvert(newLabel1, num1);
2781         mothurConvert(newLabel2, num2);
2782         
2783         if (num1 == num2) { same = true; }
2784                 
2785                 return same;
2786         }
2787         catch(exception& e) {
2788                 errorOut(e, "MothurOut", "isLabelEquivalent");
2789                 exit(1);
2790         }
2791 }
2792 //**********************************************************************************************************************
2793 bool MothurOut::isSubset(vector<string> bigset, vector<string> subset) {
2794         try {
2795                 
2796         
2797                 if (subset.size() > bigset.size()) { return false;  }
2798                 
2799                 //check if each guy in suset is also in bigset
2800                 for (int i = 0; i < subset.size(); i++) {
2801                         bool match = false;
2802                         for (int j = 0; j < bigset.size(); j++) {
2803                                 if (subset[i] == bigset[j]) { match = true; break; }
2804                         }
2805                         
2806                         //you have a guy in subset that had no match in bigset
2807                         if (match == false) { return false; }
2808                 }
2809                 
2810                 return true;
2811         
2812         }
2813         catch(exception& e) {
2814                 errorOut(e, "MothurOut", "isSubset");
2815                 exit(1);
2816         }
2817 }
2818 /***********************************************************************/
2819 int MothurOut::mothurRemove(string filename){
2820         try {
2821                 filename = getFullPathName(filename);
2822                 int error = remove(filename.c_str());
2823                 //if (error != 0) { 
2824                 //      if (errno != ENOENT) { //ENOENT == file does not exist
2825                 //              string message = "Error deleting file " + filename;
2826                 //              perror(message.c_str()); 
2827                 //      }
2828                 //}
2829                 return error;
2830         }
2831         catch(exception& e) {
2832                 errorOut(e, "MothurOut", "mothurRemove");
2833                 exit(1);
2834         }
2835 }
2836 /***********************************************************************/
2837 bool MothurOut::mothurConvert(string item, int& num){
2838         try {
2839                 bool error = false;
2840                 
2841                 if (isNumeric1(item)) {
2842                         convert(item, num);
2843                 }else {
2844                         num = 0;
2845                         error = true;
2846                         mothurOut("[ERROR]: cannot convert " + item + " to an integer."); mothurOutEndLine();
2847                         commandInputsConvertError = true;
2848                 }
2849                 
2850                 return error;
2851         }
2852         catch(exception& e) {
2853                 errorOut(e, "MothurOut", "mothurConvert");
2854                 exit(1);
2855         }
2856 }
2857 /***********************************************************************/
2858 bool MothurOut::mothurConvert(string item, intDist& num){
2859         try {
2860                 bool error = false;
2861                 
2862                 if (isNumeric1(item)) {
2863                         convert(item, num);
2864                 }else {
2865                         num = 0;
2866                         error = true;
2867                         mothurOut("[ERROR]: cannot convert " + item + " to an integer."); mothurOutEndLine();
2868                         commandInputsConvertError = true;
2869                 }
2870                 
2871                 return error;
2872         }
2873         catch(exception& e) {
2874                 errorOut(e, "MothurOut", "mothurConvert");
2875                 exit(1);
2876         }
2877 }
2878
2879 /***********************************************************************/
2880 bool MothurOut::isNumeric1(string stringToCheck){
2881         try {
2882                 bool numeric = false;
2883                 
2884                 if(stringToCheck.find_first_not_of("0123456789.-") == string::npos) { numeric = true; }
2885                         
2886                 return numeric;
2887         }
2888         catch(exception& e) {
2889                 errorOut(e, "MothurOut", "isNumeric1");
2890                 exit(1);
2891         }
2892         
2893 }
2894 /***********************************************************************/
2895 bool MothurOut::mothurConvert(string item, float& num){
2896         try {
2897                 bool error = false;
2898                 
2899                 if (isNumeric1(item)) {
2900                         convert(item, num);
2901                 }else {
2902                         num = 0;
2903                         error = true;
2904                         mothurOut("[ERROR]: cannot convert " + item + " to a float."); mothurOutEndLine();
2905                         commandInputsConvertError = true;
2906                 }
2907                 
2908                 return error;
2909         }
2910         catch(exception& e) {
2911                 errorOut(e, "MothurOut", "mothurConvert");
2912                 exit(1);
2913         }
2914 }
2915 /***********************************************************************/
2916 bool MothurOut::mothurConvert(string item, double& num){
2917         try {
2918                 bool error = false;
2919                 
2920                 if (isNumeric1(item)) {
2921                         convert(item, num);
2922                 }else {
2923                         num = 0;
2924                         error = true;
2925                         mothurOut("[ERROR]: cannot convert " + item + " to a double."); mothurOutEndLine();
2926                         commandInputsConvertError = true;
2927                 }
2928                 
2929                 return error;
2930         }
2931         catch(exception& e) {
2932                 errorOut(e, "MothurOut", "mothurConvert");
2933                 exit(1);
2934         }
2935 }
2936 /**************************************************************************************************/
2937
2938 vector<vector<double> > MothurOut::binomial(int maxOrder){
2939         try {
2940         vector<vector<double> > binomial(maxOrder+1);
2941         
2942     for(int i=0;i<=maxOrder;i++){
2943                 binomial[i].resize(maxOrder+1);
2944                 binomial[i][0]=1;
2945                 binomial[0][i]=0;
2946     }
2947     binomial[0][0]=1;
2948         
2949     binomial[1][0]=1;
2950     binomial[1][1]=1;
2951         
2952     for(int i=2;i<=maxOrder;i++){
2953                 binomial[1][i]=0;
2954     }
2955         
2956     for(int i=2;i<=maxOrder;i++){
2957                 for(int j=1;j<=maxOrder;j++){
2958                         if(i==j){       binomial[i][j]=1;                                                                       }
2959                         if(j>i) {       binomial[i][j]=0;                                                                       }
2960                         else    {       binomial[i][j]=binomial[i-1][j-1]+binomial[i-1][j];     }
2961                 }
2962     }
2963         
2964         return binomial;
2965         
2966         }
2967         catch(exception& e) {
2968                 errorOut(e, "MothurOut", "binomial");
2969                 exit(1);
2970         }
2971 }
2972 /**************************************************************************************************/
2973 unsigned int MothurOut::fromBase36(string base36){
2974         try {
2975                 unsigned int num = 0;
2976                 
2977                 map<char, int> converts;
2978                 converts['A'] = 0;
2979                 converts['a'] = 0;
2980                 converts['B'] = 1;
2981                 converts['b'] = 1;
2982                 converts['C'] = 2;
2983                 converts['c'] = 2;
2984                 converts['D'] = 3;
2985                 converts['d'] = 3;
2986                 converts['E'] = 4;
2987                 converts['e'] = 4;
2988                 converts['F'] = 5;
2989                 converts['f'] = 5;
2990                 converts['G'] = 6;
2991                 converts['g'] = 6;
2992                 converts['H'] = 7;
2993                 converts['h'] = 7;
2994                 converts['I'] = 8;
2995                 converts['i'] = 8;
2996                 converts['J'] = 9;
2997                 converts['j'] = 9;
2998                 converts['K'] = 10;
2999                 converts['k'] = 10;
3000                 converts['L'] = 11;
3001                 converts['l'] = 11;
3002                 converts['M'] = 12;
3003                 converts['m'] = 12;
3004                 converts['N'] = 13;
3005                 converts['n'] = 13;
3006                 converts['O'] = 14;
3007                 converts['o'] = 14;
3008                 converts['P'] = 15;
3009                 converts['p'] = 15;
3010                 converts['Q'] = 16;
3011                 converts['q'] = 16;
3012                 converts['R'] = 17;
3013                 converts['r'] = 17;
3014                 converts['S'] = 18;
3015                 converts['s'] = 18;
3016                 converts['T'] = 19;
3017                 converts['t'] = 19;
3018                 converts['U'] = 20;
3019                 converts['u'] = 20;
3020                 converts['V'] = 21;
3021                 converts['v'] = 21;
3022                 converts['W'] = 22;
3023                 converts['w'] = 22;
3024                 converts['X'] = 23;
3025                 converts['x'] = 23;
3026                 converts['Y'] = 24;
3027                 converts['y'] = 24;
3028                 converts['Z'] = 25;
3029                 converts['z'] = 25;
3030                 converts['0'] = 26;
3031                 converts['1'] = 27;
3032                 converts['2'] = 28;
3033                 converts['3'] = 29;
3034                 converts['4'] = 30;
3035                 converts['5'] = 31;
3036                 converts['6'] = 32;
3037                 converts['7'] = 33;
3038                 converts['8'] = 34;
3039                 converts['9'] = 35;             
3040                 
3041                 int i = 0;
3042                 while (i < base36.length()) {
3043                         char c = base36[i];
3044                         num = 36 * num + converts[c];
3045                         i++;
3046                 }
3047                 
3048                 return num;
3049                 
3050         }
3051         catch(exception& e) {
3052                 errorOut(e, "MothurOut", "fromBase36");
3053                 exit(1);
3054         }
3055 }
3056 /***********************************************************************/
3057 string  MothurOut::findEdianness() {
3058     try {
3059         // find real endian type
3060         unsigned char EndianTest[2] = {1,0};
3061         short x = *(short *)EndianTest;
3062         
3063         string endianType = "unknown";
3064         if(x == 1) { endianType = "BIG_ENDIAN"; }
3065         else { endianType = "LITTLE_ENDIAN";    }
3066     
3067         return endianType;
3068     }
3069         catch(exception& e) {
3070                 errorOut(e, "MothurOut", "findEdianness");
3071                 exit(1);
3072         }
3073 }
3074 /***********************************************************************/
3075 double  MothurOut::median(vector<double> x) {
3076     try {
3077         double value = 0.0;
3078         
3079         if (x.size() == 0) { } //error
3080         else {
3081             //For example, if a < b < c, then the median of the list {a, b, c} is b, and, if a < b < c < d, then the median of the list {a, b, c, d} is the mean of b and c; i.e., it is (b + c)/2.
3082             sort(x.begin(), x.end());
3083             //is x.size even?
3084             if ((x.size()%2) == 0) { //size() is even. median = average of 2 midpoints
3085                 int midIndex1 = (x.size()/2)-1;
3086                 int midIndex2 = (x.size()/2);
3087                 value = (x[midIndex1]+ x[midIndex2]) / 2.0;
3088             }else { 
3089                 int midIndex = (x.size()/2);
3090                 value = x[midIndex];
3091             }
3092         }
3093         return value;
3094     }
3095         catch(exception& e) {
3096                 errorOut(e, "MothurOut", "median");
3097                 exit(1);
3098         }
3099 }
3100 /***********************************************************************/
3101 int MothurOut::factorial(int num){
3102         try {
3103                 int total = 1;
3104                 
3105                 for (int i = 1; i <= num; i++) {
3106                         total *= i;
3107                 }
3108                 
3109                 return total;
3110         }
3111         catch(exception& e) {
3112                 errorOut(e, "MothurOut", "factorial");
3113                 exit(1);
3114         }
3115 }
3116 /***********************************************************************/
3117
3118 int MothurOut::getNumSeqs(ifstream& file){
3119         try {
3120                 int numSeqs = count(istreambuf_iterator<char>(file),istreambuf_iterator<char>(), '>');
3121                 file.seekg(0);
3122                 return numSeqs;
3123         }
3124         catch(exception& e) {
3125                 errorOut(e, "MothurOut", "getNumSeqs");
3126                 exit(1);
3127         }       
3128 }
3129 /***********************************************************************/
3130 void MothurOut::getNumSeqs(ifstream& file, int& numSeqs){
3131         try {
3132                 string input;
3133                 numSeqs = 0;
3134                 while(!file.eof()){
3135                         input = getline(file);
3136                         if (input.length() != 0) {
3137                                 if(input[0] == '>'){ numSeqs++; }
3138                         }
3139                 }
3140         }
3141         catch(exception& e) {
3142                 errorOut(e, "MothurOut", "getNumSeqs");
3143                 exit(1);
3144         }       
3145 }
3146 /***********************************************************************/
3147 bool MothurOut::checkLocations(string& filename, string inputDir){
3148         try {
3149                 filename = getFullPathName(filename);
3150         
3151         int ableToOpen;
3152         ifstream in;
3153         ableToOpen = openInputFile(filename, in, "noerror");
3154         in.close();
3155         
3156         //if you can't open it, try input location
3157         if (ableToOpen == 1) {
3158             if (inputDir != "") { //default path is set
3159                 string tryPath = inputDir + getSimpleName(filename);
3160                 mothurOut("Unable to open " + filename + ". Trying input directory " + tryPath); mothurOutEndLine();
3161                 ifstream in2;
3162                 ableToOpen = openInputFile(tryPath, in2, "noerror");
3163                 in2.close();
3164                 filename = tryPath;
3165             }
3166         }
3167         
3168         //if you can't open it, try default location
3169         if (ableToOpen == 1) {
3170             if (getDefaultPath() != "") { //default path is set
3171                 string tryPath = getDefaultPath() + getSimpleName(filename);
3172                 mothurOut("Unable to open " + filename + ". Trying default " + tryPath); mothurOutEndLine();
3173                 ifstream in2;
3174                 ableToOpen = openInputFile(tryPath, in2, "noerror");
3175                 in2.close();
3176                 filename = tryPath;
3177             }
3178         }
3179         
3180         //if you can't open it its not in current working directory or inputDir, try mothur excutable location
3181         if (ableToOpen == 1) {
3182             string exepath = argv;
3183             string tempPath = exepath;
3184             for (int i = 0; i < exepath.length(); i++) { tempPath[i] = tolower(exepath[i]); }
3185             exepath = exepath.substr(0, (tempPath.find_last_of('m')));
3186             
3187             string tryPath = getFullPathName(exepath) + getSimpleName(filename);
3188             mothurOut("Unable to open " + filename + ". Trying mothur's executable location " + tryPath); mothurOutEndLine();
3189             ifstream in2;
3190             ableToOpen = openInputFile(tryPath, in2, "noerror");
3191             in2.close();
3192             filename = tryPath;
3193         }
3194         
3195         if (ableToOpen == 1) { mothurOut("Unable to open " + filename + "."); mothurOutEndLine(); return false;  }
3196         
3197         return true;
3198         }
3199         catch(exception& e) {
3200                 errorOut(e, "MothurOut", "checkLocations");
3201                 exit(1);
3202         }
3203 }
3204 /***********************************************************************/
3205
3206 //This function parses the estimator options and puts them in a vector
3207 void MothurOut::splitAtChar(string& estim, vector<string>& container, char symbol) {
3208         try {
3209         
3210         if (symbol == '-') { splitAtDash(estim, container); return; }
3211         
3212                 string individual = "";
3213                 int estimLength = estim.size();
3214                 for(int i=0;i<estimLength;i++){
3215                         if(estim[i] == symbol){
3216                                 container.push_back(individual);
3217                                 individual = "";                                
3218                         }
3219                         else{
3220                                 individual += estim[i];
3221                         }
3222                 }
3223                 container.push_back(individual);
3224
3225         }
3226         catch(exception& e) {
3227                 errorOut(e, "MothurOut", "splitAtChar");
3228                 exit(1);
3229         }       
3230 }
3231
3232 /***********************************************************************/
3233
3234 //This function parses the estimator options and puts them in a vector
3235 void MothurOut::splitAtDash(string& estim, vector<string>& container) {
3236         try {
3237                 string individual = "";
3238                 int estimLength = estim.size();
3239                 bool prevEscape = false;
3240                 /*for(int i=0;i<estimLength;i++){
3241                         if(prevEscape){
3242                                 individual += estim[i];
3243                                 prevEscape = false;
3244                         }
3245                         else{
3246                                 if(estim[i] == '\\'){
3247                                         prevEscape = true;
3248                                 }
3249                                 else if(estim[i] == '-'){
3250                                         container.push_back(individual);
3251                                         individual = "";
3252                                         prevEscape = false;                             
3253                                 }
3254                                 else{
3255                                         individual += estim[i];
3256                                         prevEscape = false;
3257                                 }
3258                         }
3259                 }*/
3260         
3261         
3262         for(int i=0;i<estimLength;i++){
3263             if(estim[i] == '-'){
3264                 if (prevEscape) {  individual += estim[i]; prevEscape = false;  } //add in dash because it was escaped.
3265                 else {
3266                     container.push_back(individual);
3267                     individual = "";
3268                 }
3269             }else if(estim[i] == '\\'){
3270                 if (i < estimLength-1) { 
3271                     if (estim[i+1] == '-') { prevEscape=true; }  //are you a backslash before a dash, if yes ignore
3272                     else { individual += estim[i]; prevEscape = false;  } //if no, add in
3273                 }else { individual += estim[i]; }
3274             }else {
3275                 individual += estim[i];
3276             }
3277         }
3278         
3279
3280         
3281                 container.push_back(individual);
3282         }
3283         catch(exception& e) {
3284                 errorOut(e, "MothurOut", "splitAtDash");
3285                 exit(1);
3286         }       
3287 }
3288
3289 /***********************************************************************/
3290 //This function parses the label options and puts them in a set
3291 void MothurOut::splitAtDash(string& estim, set<string>& container) {
3292         try {
3293                 string individual = "";
3294                 int estimLength = estim.size();
3295                 bool prevEscape = false;
3296         /*
3297                 for(int i=0;i<estimLength;i++){
3298                         if(prevEscape){
3299                                 individual += estim[i];
3300                                 prevEscape = false;
3301                         }
3302                         else{
3303                                 if(estim[i] == '\\'){
3304                                         prevEscape = true;
3305                                 }
3306                                 else if(estim[i] == '-'){
3307                                         container.insert(individual);
3308                                         individual = "";
3309                                         prevEscape = false;                             
3310                                 }
3311                                 else{
3312                                         individual += estim[i];
3313                                         prevEscape = false;
3314                                 }
3315                         }
3316                 }
3317                 */
3318         
3319         for(int i=0;i<estimLength;i++){
3320             if(estim[i] == '-'){
3321                 if (prevEscape) {  individual += estim[i]; prevEscape = false;  } //add in dash because it was escaped.
3322                 else {
3323                     container.insert(individual);
3324                     individual = "";
3325                 }
3326             }else if(estim[i] == '\\'){
3327                 if (i < estimLength-1) { 
3328                     if (estim[i+1] == '-') { prevEscape=true; }  //are you a backslash before a dash, if yes ignore
3329                     else { individual += estim[i]; prevEscape = false;  } //if no, add in
3330                 }else { individual += estim[i]; }
3331             }else {
3332                 individual += estim[i];
3333             }
3334         }
3335         container.insert(individual);
3336         
3337         }
3338         catch(exception& e) {
3339                 errorOut(e, "MothurOut", "splitAtDash");
3340                 exit(1);
3341         }       
3342 }
3343 /***********************************************************************/
3344 //This function parses the line options and puts them in a set
3345 void MothurOut::splitAtDash(string& estim, set<int>& container) {
3346         try {
3347                 string individual = "";
3348                 int lineNum;
3349                 int estimLength = estim.size();
3350                 bool prevEscape = false;
3351         /*
3352                 for(int i=0;i<estimLength;i++){
3353                         if(prevEscape){
3354                                 individual += estim[i];
3355                                 prevEscape = false;
3356                         }
3357                         else{
3358                                 if(estim[i] == '\\'){
3359                                         prevEscape = true;
3360                                 }
3361                                 else if(estim[i] == '-'){
3362                                         convert(individual, lineNum); //convert the string to int
3363                                         container.insert(lineNum);
3364                                         individual = "";
3365                                         prevEscape = false;                             
3366                                 }
3367                                 else{
3368                                         individual += estim[i];
3369                                         prevEscape = false;
3370                                 }
3371                         }
3372                 }*/
3373         
3374         for(int i=0;i<estimLength;i++){
3375             if(estim[i] == '-'){
3376                 if (prevEscape) {  individual += estim[i]; prevEscape = false;  } //add in dash because it was escaped.
3377                 else {
3378                     convert(individual, lineNum); //convert the string to int
3379                     container.insert(lineNum);
3380                     individual = "";
3381                 }
3382             }else if(estim[i] == '\\'){
3383                 if (i < estimLength-1) { 
3384                     if (estim[i+1] == '-') { prevEscape=true; }  //are you a backslash before a dash, if yes ignore
3385                     else { individual += estim[i]; prevEscape = false;  } //if no, add in
3386                 }else { individual += estim[i]; }
3387             }else {
3388                 individual += estim[i];
3389             }
3390         }
3391         
3392                 convert(individual, lineNum); //convert the string to int
3393                 container.insert(lineNum);
3394         }
3395         catch(exception& e) {
3396                 errorOut(e, "MothurOut", "splitAtDash");
3397                 exit(1);
3398         }       
3399 }
3400
3401 /***********************************************************************/
3402 string MothurOut::makeList(vector<string>& names) {
3403         try {
3404                 string list = "";
3405         
3406         if (names.size() == 0) { return list; }
3407                 
3408         for (int i = 0; i < names.size()-1; i++) { list += names[i] + ",";  }
3409         
3410         //get last name
3411         list += names[names.size()-1];
3412         
3413         return list;
3414     }
3415         catch(exception& e) {
3416                 errorOut(e, "MothurOut", "makeList");
3417                 exit(1);
3418         }       
3419 }
3420
3421 /***********************************************************************/
3422 //This function parses the a string and puts peices in a vector
3423 void MothurOut::splitAtComma(string& estim, vector<string>& container) {
3424         try {
3425                 string individual = "";
3426                 int estimLength = estim.size();
3427                 for(int i=0;i<estimLength;i++){
3428                         if(estim[i] == ','){
3429                                 container.push_back(individual);
3430                                 individual = "";                                
3431                         }
3432                         else{
3433                                 individual += estim[i];
3434                         }
3435                 }
3436                 container.push_back(individual);
3437                 
3438                 
3439                 
3440                 
3441 //              string individual;
3442 //              
3443 //              while (estim.find_first_of(',') != -1) {
3444 //                      individual = estim.substr(0,estim.find_first_of(','));
3445 //                      if ((estim.find_first_of(',')+1) <= estim.length()) { //checks to make sure you don't have comma at end of string
3446 //                              estim = estim.substr(estim.find_first_of(',')+1, estim.length());
3447 //                              container.push_back(individual);
3448 //                      }
3449 //              }
3450 //              //get last one
3451 //              container.push_back(estim);
3452         }
3453         catch(exception& e) {
3454                 errorOut(e, "MothurOut", "splitAtComma");
3455                 exit(1);
3456         }       
3457 }
3458 /***********************************************************************/
3459 //This function splits up the various option parameters
3460 void MothurOut::splitAtChar(string& prefix, string& suffix, char c){
3461         try {
3462                 prefix = suffix.substr(0,suffix.find_first_of(c));
3463                 if ((suffix.find_first_of(c)+2) <= suffix.length()) {  //checks to make sure you don't have comma at end of string
3464                         suffix = suffix.substr(suffix.find_first_of(c)+1, suffix.length());
3465                         string space = " ";
3466                         while(suffix.at(0) == ' ')
3467                                 suffix = suffix.substr(1, suffix.length());
3468                 }else {  suffix = "";  }
3469         
3470     }
3471         catch(exception& e) {
3472                 errorOut(e, "MothurOut", "splitAtChar");
3473                 exit(1);
3474         }       
3475 }
3476
3477 /***********************************************************************/
3478
3479 //This function splits up the various option parameters
3480 void MothurOut::splitAtComma(string& prefix, string& suffix){
3481         try {
3482                 prefix = suffix.substr(0,suffix.find_first_of(','));
3483                 if ((suffix.find_first_of(',')+2) <= suffix.length()) {  //checks to make sure you don't have comma at end of string
3484                         suffix = suffix.substr(suffix.find_first_of(',')+1, suffix.length());
3485                         string space = " ";
3486                         while(suffix.at(0) == ' ')
3487                                 suffix = suffix.substr(1, suffix.length());
3488                 }else {  suffix = "";  }
3489
3490         }
3491         catch(exception& e) {
3492                 errorOut(e, "MothurOut", "splitAtComma");
3493                 exit(1);
3494         }       
3495 }
3496 /***********************************************************************/
3497
3498 //This function separates the key value from the option value i.e. dist=96_...
3499 void MothurOut::splitAtEquals(string& key, string& value){              
3500         try {
3501                 if(value.find_first_of('=') != -1){
3502                         key = value.substr(0,value.find_first_of('='));
3503                         if ((value.find_first_of('=')+1) <= value.length()) {
3504                                 value = value.substr(value.find_first_of('=')+1, value.length());
3505                         }
3506                 }else{
3507                         key = value;
3508                         value = 1;
3509                 }
3510         }
3511         catch(exception& e) {
3512                 errorOut(e, "MothurOut", "splitAtEquals");
3513                 exit(1);
3514         }       
3515 }
3516
3517 /**************************************************************************************************/
3518
3519 bool MothurOut::inUsersGroups(string groupname, vector<string> Groups) {
3520         try {
3521                 for (int i = 0; i < Groups.size(); i++) {
3522                         if (groupname == Groups[i]) { return true; }
3523                 }
3524                 return false;
3525         }
3526         catch(exception& e) {
3527                 errorOut(e, "MothurOut", "inUsersGroups");
3528                 exit(1);
3529         }       
3530 }
3531 /**************************************************************************************************/
3532
3533 bool MothurOut::inUsersGroups(vector<int> set, vector< vector<int> > sets) {
3534         try {
3535                 for (int i = 0; i < sets.size(); i++) {
3536                         if (set == sets[i]) { return true; }
3537                 }
3538                 return false;
3539         }
3540         catch(exception& e) {
3541                 errorOut(e, "MothurOut", "inUsersGroups");
3542                 exit(1);
3543         }       
3544 }
3545 /**************************************************************************************************/
3546
3547 bool MothurOut::inUsersGroups(int groupname, vector<int> Groups) {
3548         try {
3549                 for (int i = 0; i < Groups.size(); i++) {
3550                         if (groupname == Groups[i]) { return true; }
3551                 }
3552                 return false;
3553         }
3554         catch(exception& e) {
3555                 errorOut(e, "MothurOut", "inUsersGroups");
3556                 exit(1);
3557         }       
3558 }
3559
3560 /**************************************************************************************************/
3561 //returns true if any of the strings in first vector are in second vector
3562 bool MothurOut::inUsersGroups(vector<string> groupnames, vector<string> Groups) {
3563         try {
3564                 
3565                 for (int i = 0; i < groupnames.size(); i++) {
3566                         if (inUsersGroups(groupnames[i], Groups)) { return true; }
3567                 }
3568                 return false;
3569         }
3570         catch(exception& e) {
3571                 errorOut(e, "MothurOut", "inUsersGroups");
3572                 exit(1);
3573         }       
3574 }
3575 /***********************************************************************/
3576 //this function determines if the user has given us labels that are smaller than the given label.
3577 //if so then it returns true so that the calling function can run the previous valid distance.
3578 //it's a "smart" distance function.  It also checks for invalid labels.
3579 bool MothurOut::anyLabelsToProcess(string label, set<string>& userLabels, string errorOff) {
3580         try {
3581                 
3582                 set<string>::iterator it;
3583                 vector<float> orderFloat;
3584                 map<string, float> userMap;  //the conversion process removes trailing 0's which we need to put back
3585                 map<string, float>::iterator it2;
3586                 float labelFloat;
3587                 bool smaller = false;
3588                 
3589                 //unique is the smallest line
3590                 if (label == "unique") {  return false;  }
3591                 else { 
3592                         if (convertTestFloat(label, labelFloat)) {
3593                                 convert(label, labelFloat); 
3594                         }else { //cant convert 
3595                                 return false;
3596                         }
3597                 }
3598                 
3599                 //go through users set and make them floats
3600                 for(it = userLabels.begin(); it != userLabels.end();) {
3601                         
3602                         float temp;
3603                         if ((*it != "unique") && (convertTestFloat(*it, temp) == true)){
3604                                 convert(*it, temp);
3605                                 orderFloat.push_back(temp);
3606                                 userMap[*it] = temp;
3607                                 it++;
3608                         }else if (*it == "unique") { 
3609                                 orderFloat.push_back(-1.0);
3610                                 userMap["unique"] = -1.0;
3611                                 it++;
3612                         }else {
3613                                 if (errorOff == "") {  mothurOut(*it + " is not a valid label."); mothurOutEndLine();  }
3614                                 userLabels.erase(it++); 
3615                         }
3616                 }
3617                 
3618                 //sort order
3619                 sort(orderFloat.begin(), orderFloat.end());
3620                 
3621                 /*************************************************/
3622                 //is this label bigger than any of the users labels
3623                 /*************************************************/
3624                                 
3625                 //loop through order until you find a label greater than label
3626                 for (int i = 0; i < orderFloat.size(); i++) {
3627                         if (orderFloat[i] < labelFloat) {
3628                                 smaller = true;
3629                                 if (orderFloat[i] == -1) { 
3630                                         if (errorOff == "") { mothurOut("Your file does not include the label unique."); mothurOutEndLine(); }
3631                                         userLabels.erase("unique");
3632                                 }
3633                                 else {  
3634                                         if (errorOff == "") { mothurOut("Your file does not include the label "); mothurOutEndLine(); }
3635                                         string s = "";
3636                                         for (it2 = userMap.begin(); it2!= userMap.end(); it2++) {  
3637                                                 if (it2->second == orderFloat[i]) {  
3638                                                         s = it2->first;  
3639                                                         //remove small labels
3640                                                         userLabels.erase(s);
3641                                                         break;
3642                                                 }
3643                                         }
3644                                         if (errorOff == "") {mothurOut( s +  ". I will use the next smallest distance. "); mothurOutEndLine(); }
3645                                 }
3646                         //since they are sorted once you find a bigger one stop looking
3647                         }else { break; }
3648                 }
3649                 
3650                 return smaller;
3651                                                 
3652         }
3653         catch(exception& e) {
3654                 errorOut(e, "MothurOut", "anyLabelsToProcess");
3655                 exit(1);
3656         }       
3657 }
3658
3659 /**************************************************************************************************/
3660 bool MothurOut::checkReleaseVersion(ifstream& file, string version) {
3661         try {
3662                 
3663                 bool good = true;
3664                 
3665                 string line = getline(file);  
3666
3667                 //before we added this check
3668                 if (line[0] != '#') {  good = false;  }
3669                 else {
3670                         //rip off #
3671                         line = line.substr(1);
3672                         
3673                         vector<string> versionVector;
3674                         splitAtChar(version, versionVector, '.');
3675                         
3676                         //check file version
3677                         vector<string> linesVector;
3678                         splitAtChar(line, linesVector, '.');
3679                         
3680                         if (versionVector.size() != linesVector.size()) { good = false; }
3681                         else {
3682                                 for (int j = 0; j < versionVector.size(); j++) {
3683                                         int num1, num2;
3684                                         convert(versionVector[j], num1);
3685                                         convert(linesVector[j], num2);
3686                                         
3687                                         //if mothurs version is newer than this files version, then we want to remake it
3688                                         if (num1 > num2) {  good = false; break;  }
3689                                 }
3690                         }
3691                         
3692                 }
3693                 
3694                 if (!good) {  file.close();  }
3695                 else { file.seekg(0);  }
3696                 
3697                 return good;
3698         }
3699         catch(exception& e) {
3700                 errorOut(e, "MothurOut", "checkReleaseVersion");                
3701                 exit(1);
3702         }
3703 }
3704 /**************************************************************************************************/
3705 vector<double> MothurOut::getAverages(vector< vector<double> >& dists) {
3706         try{
3707         vector<double> averages; //averages.resize(numComp, 0.0);
3708         for (int i = 0; i < dists[0].size(); i++) { averages.push_back(0.0); }
3709       
3710         for (int thisIter = 0; thisIter < dists.size(); thisIter++) {
3711             for (int i = 0; i < dists[thisIter].size(); i++) {  
3712                 averages[i] += dists[thisIter][i];
3713             }
3714         }
3715         
3716         //finds average.
3717         for (int i = 0; i < averages.size(); i++) {  averages[i] /= (double) dists.size(); }
3718         
3719         return averages;
3720     }
3721         catch(exception& e) {
3722                 errorOut(e, "MothurOut", "getAverages");                
3723                 exit(1);
3724         }
3725 }
3726 /**************************************************************************************************/
3727 double MothurOut::getAverage(vector<double> dists) {
3728         try{
3729         double average = 0;
3730         
3731         for (int i = 0; i < dists.size(); i++) {
3732             average += dists[i];
3733         }
3734        
3735         //finds average.
3736         average /= (double) dists.size(); 
3737         
3738         return average;
3739     }
3740         catch(exception& e) {
3741                 errorOut(e, "MothurOut", "getAverage");
3742                 exit(1);
3743         }
3744 }
3745
3746 /**************************************************************************************************/
3747 vector<double> MothurOut::getStandardDeviation(vector< vector<double> >& dists) {
3748         try{
3749         
3750         vector<double> averages = getAverages(dists);
3751         
3752         //find standard deviation
3753         vector<double> stdDev; //stdDev.resize(numComp, 0.0);
3754         for (int i = 0; i < dists[0].size(); i++) { stdDev.push_back(0.0); }
3755         
3756         for (int thisIter = 0; thisIter < dists.size(); thisIter++) { //compute the difference of each dist from the mean, and square the result of each
3757             for (int j = 0; j < dists[thisIter].size(); j++) {
3758                 stdDev[j] += ((dists[thisIter][j] - averages[j]) * (dists[thisIter][j] - averages[j]));
3759             }
3760         }
3761         for (int i = 0; i < stdDev.size(); i++) {  
3762             stdDev[i] /= (double) dists.size(); 
3763             stdDev[i] = sqrt(stdDev[i]);
3764         }
3765         
3766         return stdDev;
3767     }
3768         catch(exception& e) {
3769                 errorOut(e, "MothurOut", "getAverages");                
3770                 exit(1);
3771         }
3772 }
3773 /**************************************************************************************************/
3774 vector<double> MothurOut::getStandardDeviation(vector< vector<double> >& dists, vector<double>& averages) {
3775         try{
3776         //find standard deviation
3777         vector<double> stdDev; //stdDev.resize(numComp, 0.0);
3778         for (int i = 0; i < dists[0].size(); i++) { stdDev.push_back(0.0); }
3779         
3780         for (int thisIter = 0; thisIter < dists.size(); thisIter++) { //compute the difference of each dist from the mean, and square the result of each
3781             for (int j = 0; j < dists[thisIter].size(); j++) {
3782                 stdDev[j] += ((dists[thisIter][j] - averages[j]) * (dists[thisIter][j] - averages[j]));
3783             }
3784         }
3785         for (int i = 0; i < stdDev.size(); i++) {  
3786             stdDev[i] /= (double) dists.size(); 
3787             stdDev[i] = sqrt(stdDev[i]);
3788         }
3789         
3790         return stdDev;
3791     }
3792         catch(exception& e) {
3793                 errorOut(e, "MothurOut", "getStandardDeviation");               
3794                 exit(1);
3795         }
3796 }
3797 /**************************************************************************************************/
3798 vector< vector<seqDist> > MothurOut::getAverages(vector< vector< vector<seqDist> > >& calcDistsTotals, string mode) {
3799         try{
3800         
3801         vector< vector<seqDist>  > calcAverages; //calcAverages.resize(calcDistsTotals[0].size()); 
3802         for (int i = 0; i < calcDistsTotals[0].size(); i++) {  //initialize sums to zero.
3803             //calcAverages[i].resize(calcDistsTotals[0][i].size());
3804             vector<seqDist> temp;
3805             for (int j = 0; j < calcDistsTotals[0][i].size(); j++) {
3806                 seqDist tempDist;
3807                 tempDist.seq1 = calcDistsTotals[0][i][j].seq1;
3808                 tempDist.seq2 = calcDistsTotals[0][i][j].seq2;
3809                 tempDist.dist = 0.0;
3810                 temp.push_back(tempDist);
3811             }
3812             calcAverages.push_back(temp);
3813         }
3814         
3815         if (mode == "average") {
3816             for (int thisIter = 0; thisIter < calcDistsTotals.size(); thisIter++) { //sum all groups dists for each calculator
3817                 for (int i = 0; i < calcAverages.size(); i++) {  //initialize sums to zero.
3818                     for (int j = 0; j < calcAverages[i].size(); j++) {
3819                         calcAverages[i][j].dist += calcDistsTotals[thisIter][i][j].dist;
3820                     }
3821                 }
3822             }
3823             
3824             for (int i = 0; i < calcAverages.size(); i++) {  //finds average.
3825                 for (int j = 0; j < calcAverages[i].size(); j++) {
3826                     calcAverages[i][j].dist /= (float) calcDistsTotals.size();
3827                 }
3828             }
3829         }else { //find median
3830             for (int i = 0; i < calcAverages.size(); i++) { //for each calc
3831                 for (int j = 0; j < calcAverages[i].size(); j++) {  //for each comparison
3832                     vector<double> dists;
3833                     for (int thisIter = 0; thisIter < calcDistsTotals.size(); thisIter++) { //for each subsample
3834                         dists.push_back(calcDistsTotals[thisIter][i][j].dist);
3835                     }
3836                     sort(dists.begin(), dists.end());
3837                     calcAverages[i][j].dist = dists[(calcDistsTotals.size()/2)];
3838                 }
3839             }
3840         }
3841
3842         return calcAverages;
3843     }
3844         catch(exception& e) {
3845                 errorOut(e, "MothurOut", "getAverages");                
3846                 exit(1);
3847         }
3848 }
3849 /**************************************************************************************************/
3850 vector< vector<seqDist> > MothurOut::getAverages(vector< vector< vector<seqDist> > >& calcDistsTotals) {
3851         try{
3852         
3853         vector< vector<seqDist>  > calcAverages; //calcAverages.resize(calcDistsTotals[0].size()); 
3854         for (int i = 0; i < calcDistsTotals[0].size(); i++) {  //initialize sums to zero.
3855             //calcAverages[i].resize(calcDistsTotals[0][i].size());
3856             vector<seqDist> temp;
3857             for (int j = 0; j < calcDistsTotals[0][i].size(); j++) {
3858                 seqDist tempDist;
3859                 tempDist.seq1 = calcDistsTotals[0][i][j].seq1;
3860                 tempDist.seq2 = calcDistsTotals[0][i][j].seq2;
3861                 tempDist.dist = 0.0;
3862                 temp.push_back(tempDist);
3863             }
3864             calcAverages.push_back(temp);
3865         }
3866         
3867         
3868         for (int thisIter = 0; thisIter < calcDistsTotals.size(); thisIter++) { //sum all groups dists for each calculator
3869                 for (int i = 0; i < calcAverages.size(); i++) {  //initialize sums to zero.
3870                     for (int j = 0; j < calcAverages[i].size(); j++) {
3871                         calcAverages[i][j].dist += calcDistsTotals[thisIter][i][j].dist;
3872                     }
3873                 }
3874         }
3875             
3876         for (int i = 0; i < calcAverages.size(); i++) {  //finds average.
3877                 for (int j = 0; j < calcAverages[i].size(); j++) {
3878                     calcAverages[i][j].dist /= (float) calcDistsTotals.size();
3879                 }
3880         }
3881         
3882         return calcAverages;
3883     }
3884         catch(exception& e) {
3885                 errorOut(e, "MothurOut", "getAverages");                
3886                 exit(1);
3887         }
3888 }
3889 /**************************************************************************************************/
3890 vector< vector<seqDist> > MothurOut::getStandardDeviation(vector< vector< vector<seqDist> > >& calcDistsTotals) {
3891         try{
3892         
3893         vector< vector<seqDist> > calcAverages = getAverages(calcDistsTotals);
3894         
3895         //find standard deviation
3896         vector< vector<seqDist>  > stdDev;  
3897         for (int i = 0; i < calcDistsTotals[0].size(); i++) {  //initialize sums to zero.
3898             vector<seqDist> temp;
3899             for (int j = 0; j < calcDistsTotals[0][i].size(); j++) {
3900                 seqDist tempDist;
3901                 tempDist.seq1 = calcDistsTotals[0][i][j].seq1;
3902                 tempDist.seq2 = calcDistsTotals[0][i][j].seq2;
3903                 tempDist.dist = 0.0;
3904                 temp.push_back(tempDist);
3905             }
3906             stdDev.push_back(temp);
3907         }
3908         
3909         for (int thisIter = 0; thisIter < calcDistsTotals.size(); thisIter++) { //compute the difference of each dist from the mean, and square the result of each
3910             for (int i = 0; i < stdDev.size(); i++) {  
3911                 for (int j = 0; j < stdDev[i].size(); j++) {
3912                     stdDev[i][j].dist += ((calcDistsTotals[thisIter][i][j].dist - calcAverages[i][j].dist) * (calcDistsTotals[thisIter][i][j].dist - calcAverages[i][j].dist));
3913                 }
3914             }
3915         }
3916         
3917         for (int i = 0; i < stdDev.size(); i++) {  //finds average.
3918             for (int j = 0; j < stdDev[i].size(); j++) {
3919                 stdDev[i][j].dist /= (float) calcDistsTotals.size();
3920                 stdDev[i][j].dist = sqrt(stdDev[i][j].dist);
3921             }
3922         }
3923
3924         return stdDev;
3925     }
3926         catch(exception& e) {
3927                 errorOut(e, "MothurOut", "getAverages");                
3928                 exit(1);
3929         }
3930 }
3931 /**************************************************************************************************/
3932 vector< vector<seqDist> > MothurOut::getStandardDeviation(vector< vector< vector<seqDist> > >& calcDistsTotals, vector< vector<seqDist> >& calcAverages) {
3933         try{
3934         //find standard deviation
3935         vector< vector<seqDist>  > stdDev;  
3936         for (int i = 0; i < calcDistsTotals[0].size(); i++) {  //initialize sums to zero.
3937             vector<seqDist> temp;
3938             for (int j = 0; j < calcDistsTotals[0][i].size(); j++) {
3939                 seqDist tempDist;
3940                 tempDist.seq1 = calcDistsTotals[0][i][j].seq1;
3941                 tempDist.seq2 = calcDistsTotals[0][i][j].seq2;
3942                 tempDist.dist = 0.0;
3943                 temp.push_back(tempDist);
3944             }
3945             stdDev.push_back(temp);
3946         }
3947         
3948         for (int thisIter = 0; thisIter < calcDistsTotals.size(); thisIter++) { //compute the difference of each dist from the mean, and square the result of each
3949             for (int i = 0; i < stdDev.size(); i++) {  
3950                 for (int j = 0; j < stdDev[i].size(); j++) {
3951                     stdDev[i][j].dist += ((calcDistsTotals[thisIter][i][j].dist - calcAverages[i][j].dist) * (calcDistsTotals[thisIter][i][j].dist - calcAverages[i][j].dist));
3952                 }
3953             }
3954         }
3955         
3956         for (int i = 0; i < stdDev.size(); i++) {  //finds average.
3957             for (int j = 0; j < stdDev[i].size(); j++) {
3958                 stdDev[i][j].dist /= (float) calcDistsTotals.size();
3959                 stdDev[i][j].dist = sqrt(stdDev[i][j].dist);
3960             }
3961         }
3962         
3963         return stdDev;
3964     }
3965         catch(exception& e) {
3966                 errorOut(e, "MothurOut", "getAverages");                
3967                 exit(1);
3968         }
3969 }
3970
3971 /**************************************************************************************************/
3972 bool MothurOut::isContainingOnlyDigits(string input) {
3973         try{
3974                 
3975                 //are you a digit in ascii code
3976                 for (int i = 0;i < input.length(); i++){
3977                         if( input[i]>47 && input[i]<58){}
3978                         else { return false; }
3979                 }
3980                 
3981                 return true;
3982         }
3983         catch(exception& e) {
3984                 errorOut(e, "MothurOut", "isContainingOnlyDigits");             
3985                 exit(1);
3986         }
3987 }
3988 /**************************************************************************************************/
3989 int MothurOut::removeConfidences(string& tax) {
3990         try {
3991                 
3992                 string taxon;
3993                 string newTax = "";
3994                 
3995                 while (tax.find_first_of(';') != -1) {
3996                         
3997                         if (control_pressed) { return 0; }
3998                         
3999                         //get taxon
4000                         taxon = tax.substr(0,tax.find_first_of(';'));
4001         
4002                         int pos = taxon.find_last_of('(');
4003                         if (pos != -1) {
4004                                 //is it a number?
4005                                 int pos2 = taxon.find_last_of(')');
4006                                 if (pos2 != -1) {
4007                                         string confidenceScore = taxon.substr(pos+1, (pos2-(pos+1)));
4008                                         if (isNumeric1(confidenceScore)) {
4009                                                 taxon = taxon.substr(0, pos); //rip off confidence 
4010                                         }
4011                                 }
4012                         }
4013                         taxon += ";";
4014                         
4015                         tax = tax.substr(tax.find_first_of(';')+1, tax.length());
4016                         newTax += taxon;
4017                 }
4018                 
4019                 tax = newTax;
4020                 
4021                 return 0;
4022         }
4023         catch(exception& e) {
4024                 errorOut(e, "MothurOut", "removeConfidences");
4025                 exit(1);
4026         }
4027 }
4028 /**************************************************************************************************/
4029 string MothurOut::removeQuotes(string tax) {
4030         try {
4031                 
4032                 string taxon;
4033                 string newTax = "";
4034                 
4035                 for (int i = 0; i < tax.length(); i++) {
4036                         
4037                         if (control_pressed) { return newTax; }
4038             
4039             if ((tax[i] != '\'') && (tax[i] != '\"')) { newTax += tax[i]; }
4040                         
4041         }
4042                 
4043                 return newTax;
4044         }
4045         catch(exception& e) {
4046                 errorOut(e, "MothurOut", "removeQuotes");
4047                 exit(1);
4048         }
4049 }
4050 /**************************************************************************************************/
4051 // function for calculating standard deviation
4052 double MothurOut::getStandardDeviation(vector<int>& featureVector){
4053     try {
4054         //finds sum
4055         double average = 0; 
4056         for (int i = 0; i < featureVector.size(); i++) { average += featureVector[i]; }
4057         average /= (double) featureVector.size();
4058         
4059         //find standard deviation
4060         double stdDev = 0;
4061         for (int i = 0; i < featureVector.size(); i++) { //compute the difference of each dist from the mean, and square the result of each
4062             stdDev += ((featureVector[i] - average) * (featureVector[i] - average));
4063         }
4064           
4065         stdDev /= (double) featureVector.size(); 
4066         stdDev = sqrt(stdDev);
4067         
4068         return stdDev;
4069     }
4070         catch(exception& e) {
4071                 errorOut(e, "MothurOut", "getStandardDeviation");
4072                 exit(1);
4073         }
4074 }
4075 /**************************************************************************************************/
4076 // returns largest value in vector
4077 double MothurOut::max(vector<double>& featureVector){
4078     try {
4079         if (featureVector.size() == 0) { mothurOut("[ERROR]: vector size = 0!\n"); control_pressed=true; return 0.0; }
4080         
4081         //finds largest
4082         double largest = featureVector[0];
4083         for (int i = 1; i < featureVector.size(); i++) {
4084             if (featureVector[i] > largest) { largest = featureVector[i]; }
4085         }
4086                 
4087         return largest;
4088     }
4089         catch(exception& e) {
4090                 errorOut(e, "MothurOut", "max");
4091                 exit(1);
4092         }
4093 }
4094 /**************************************************************************************************/
4095 // returns smallest value in vector
4096 double MothurOut::min(vector<double>& featureVector){
4097     try {
4098         if (featureVector.size() == 0) { mothurOut("[ERROR]: vector size = 0!\n"); control_pressed=true; return 0.0; }
4099         
4100         //finds smallest
4101         double smallest = featureVector[0];
4102         for (int i = 1; i < featureVector.size(); i++) {
4103             if (featureVector[i] < smallest) { smallest = featureVector[i]; }
4104         }
4105         
4106         return smallest;
4107     }
4108         catch(exception& e) {
4109                 errorOut(e, "MothurOut", "min");
4110                 exit(1);
4111         }
4112 }
4113 /**************************************************************************************************/
4114
4115
4116