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