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