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