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