]> git.donarmstrong.com Git - mothur.git/blobdiff - chimerauchimecommand.cpp
Merge remote-tracking branch 'mothur/master'
[mothur.git] / chimerauchimecommand.cpp
index 73e7ace9860eeb6410517497b5e0495e9fdb1b96..bd31c193e82aa0725cc8920336ec310cc19db820 100644 (file)
@@ -9,10 +9,10 @@
 
 #include "chimerauchimecommand.h"
 #include "deconvolutecommand.h"
-#include "uc.h"
+//#include "uc.h"
 #include "sequence.hpp"
 #include "referencedb.h"
-
+#include "systemcommand.h"
 
 //**********************************************************************************************************************
 vector<string> ChimeraUchimeCommand::setParameters(){  
@@ -98,6 +98,28 @@ string ChimeraUchimeCommand::getHelpString(){
        }
 }
 //**********************************************************************************************************************
+string ChimeraUchimeCommand::getOutputFileNameTag(string type, string inputName=""){   
+       try {
+        string outputFileName = "";
+               map<string, vector<string> >::iterator it;
+        
+        //is this a type this command creates
+        it = outputTypes.find(type);
+        if (it == outputTypes.end()) {  m->mothurOut("[ERROR]: this command doesn't create a " + type + " output file.\n"); }
+        else {
+            if (type == "chimera") {  outputFileName =  "uchime.chimeras"; }
+            else if (type == "accnos") {  outputFileName =  "uchime.accnos"; }
+            else if (type == "alns") {  outputFileName =  "uchime.alns"; }
+            else { m->mothurOut("[ERROR]: No definition for type " + type + " output file tag.\n"); m->control_pressed = true;  }
+        }
+        return outputFileName;
+       }
+       catch(exception& e) {
+               m->errorOut(e, "ChimeraUchimeCommand", "getOutputFileNameTag");
+               exit(1);
+       }
+}
+//**********************************************************************************************************************
 ChimeraUchimeCommand::ChimeraUchimeCommand(){  
        try {
                abort = true; calledHelp = true;
@@ -418,7 +440,7 @@ ChimeraUchimeCommand::ChimeraUchimeCommand(string option)  {
                                
                        string temp = validParameter.validFile(parameters, "processors", false);        if (temp == "not found"){       temp = m->getProcessors();      }
                        m->setProcessors(temp);
-                       convert(temp, processors);
+                       m->mothurConvert(temp, processors);
                        
                        abskew = validParameter.validFile(parameters, "abskew", false); if (abskew == "not found"){     useAbskew = false;  abskew = "1.9";     }else{  useAbskew = true;  }
                        if (useAbskew && templatefile != "self") { m->mothurOut("The abskew parameter is only valid with template=self, ignoring."); m->mothurOutEndLine(); useAbskew = false; }
@@ -453,8 +475,54 @@ ChimeraUchimeCommand::ChimeraUchimeCommand(string option)  {
                        
                        if (hasName && (templatefile != "self")) { m->mothurOut("You have provided a namefile and the reference parameter is not set to self. I am not sure what reference you are trying to use, aborting."); m->mothurOutEndLine(); abort=true; }
                        if (hasGroup && (templatefile != "self")) { m->mothurOut("You have provided a group file and the reference parameter is not set to self. I am not sure what reference you are trying to use, aborting."); m->mothurOutEndLine(); abort=true; }
+                       
+                       //look for uchime exe
+                       path = m->argv;
+                       string tempPath = path;
+                       for (int i = 0; i < path.length(); i++) { tempPath[i] = tolower(path[i]); }
+                       path = path.substr(0, (tempPath.find_last_of('m')));
+                       
+                       string uchimeCommand;
+#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix)
+                       uchimeCommand = path + "uchime";        //      format the database, -o option gives us the ability
+            if (m->debug) { 
+                m->mothurOut("[DEBUG]: Uchime location using \"which uchime\" = "); 
+                Command* newCommand = new SystemCommand("which uchime"); m->mothurOutEndLine();
+                newCommand->execute();
+                delete newCommand;
+                m->mothurOut("[DEBUG]: Mothur's location using \"which mothur\" = "); 
+                newCommand = new SystemCommand("which mothur"); m->mothurOutEndLine();
+                newCommand->execute();
+                delete newCommand;
+            }
+#else
+                       uchimeCommand = path + "uchime.exe";
+#endif
+        
+                       //test to make sure uchime exists
+                       ifstream in;
+                       uchimeCommand = m->getFullPathName(uchimeCommand);
+                       int ableToOpen = m->openInputFile(uchimeCommand, in, "no error"); in.close();
+                       if(ableToOpen == 1) {   
+                m->mothurOut(uchimeCommand + " file does not exist. Checking path... \n");
+                //check to see if uchime is in the path??
+                
+                string uLocation = m->findProgramPath("uchime");
+                
+                
+                ifstream in2;
+#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix)
+                ableToOpen = m->openInputFile(uLocation, in2, "no error"); in2.close();
+#else
+                ableToOpen = m->openInputFile((uLocation + ".exe"), in2, "no error"); in2.close();
+#endif
 
-               }
+                if(ableToOpen == 1) { m->mothurOut("[ERROR]: " + uLocation + " file does not exist. mothur requires the uchime executable."); m->mothurOutEndLine(); abort = true; } 
+                else {  m->mothurOut("Found uchime in your path, using " + uLocation + "\n");uchimeLocation = uLocation; }
+            }else {  uchimeLocation = uchimeCommand; }
+            
+            uchimeLocation = m->getFullPathName(uchimeLocation);
+        }
        }
        catch(exception& e) {
                m->errorOut(e, "ChimeraSlayerCommand", "ChimeraSlayerCommand");
@@ -476,9 +544,9 @@ int ChimeraUchimeCommand::execute(){
                        int start = time(NULL); 
                        string nameFile = "";
                        if (outputDir == "") { outputDir = m->hasPath(fastaFileNames[s]);  }//if user entered a file with a path then preserve it                               
-                       string outputFileName = outputDir + m->getRootName(m->getSimpleName(fastaFileNames[s])) + "uchime.chimera";
-                       string accnosFileName = outputDir + m->getRootName(m->getSimpleName(fastaFileNames[s]))  + "uchime.accnos";
-                       string alnsFileName = outputDir + m->getRootName(m->getSimpleName(fastaFileNames[s]))  + "uchime.alns";
+                       string outputFileName = outputDir + m->getRootName(m->getSimpleName(fastaFileNames[s])) + getOutputFileNameTag("chimera");
+                       string accnosFileName = outputDir + m->getRootName(m->getSimpleName(fastaFileNames[s])) + getOutputFileNameTag("accnos");
+                       string alnsFileName = outputDir + m->getRootName(m->getSimpleName(fastaFileNames[s]))  + getOutputFileNameTag("alns");
                        string newFasta = m->getRootName(fastaFileNames[s]) + "temp";
                                
                        //you provided a groupfile
@@ -491,7 +559,7 @@ int ChimeraUchimeCommand::execute(){
                                if (nameFileNames.size() != 0) { //you provided a namefile and we don't need to create one
                                        nameFile = nameFileNames[s];
                                }else { nameFile = getNamesFile(fastaFileNames[s]); }
-                                                                       
+                                                                               
                                map<string, string> seqs;  
                                readFasta(fastaFileNames[s], seqs);  if (m->control_pressed) { for (int j = 0; j < outputNames.size(); j++) {   m->mothurRemove(outputNames[j]);        }  return 0; }
 
@@ -525,12 +593,9 @@ int ChimeraUchimeCommand::execute(){
                                if (chimealns) { m->openOutputFile(alnsFileName, out2); out2.close(); }
                                int totalSeqs = 0;
                                
-       #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux)
                                if(processors == 1)     {       totalSeqs = driverGroups(parser, outputFileName, newFasta, accnosFileName, alnsFileName, 0, groups.size(), groups);     }
-                               else                            {       totalSeqs = createProcessesGroups(parser, outputFileName, newFasta, accnosFileName, alnsFileName, groups);                      }
-       #else
-                               totalSeqs = driverGroups(parser, outputFileName, newFasta, accnosFileName, alnsFileName, 0, groups.size(), groups);
-       #endif
+                               else                            {       totalSeqs = createProcessesGroups(parser, outputFileName, newFasta, accnosFileName, alnsFileName, groups, nameFile, groupFile, fastaFileNames[s]);                      }
+
                                if (m->control_pressed) {  for (int j = 0; j < outputNames.size(); j++) {       m->mothurRemove(outputNames[j]);        }  return 0;    }                               
 
                                int totalChimeras = deconvoluteResults(parser, outputFileName, accnosFileName, alnsFileName);
@@ -545,12 +610,19 @@ int ChimeraUchimeCommand::execute(){
                        
                                int numSeqs = 0;
                                int numChimeras = 0;
-       #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux)
+
                                if(processors == 1){ numSeqs = driver(outputFileName, fastaFileNames[s], accnosFileName, alnsFileName, numChimeras); }
                                else{   numSeqs = createProcesses(outputFileName, fastaFileNames[s], accnosFileName, alnsFileName, numChimeras); }
-       #else
-                               numSeqs = driver(outputFileName, fastaFileNames[s], accnosFileName, alnsFileName, numChimeras);
-       #endif
+                               
+                               //add headings
+                               ofstream out;
+                               m->openOutputFile(outputFileName+".temp", out); 
+                               out << "Score\tQuery\tParentA\tParentB\tIdQM\tIdQA\tIdQB\tIdAB\tIdQT\tLY\tLN\tLA\tRY\tRN\tRA\tDiv\tYN\n";
+                               out.close();
+                               
+                               m->appendFiles(outputFileName, outputFileName+".temp");
+                               m->mothurRemove(outputFileName); rename((outputFileName+".temp").c_str(), outputFileName.c_str());
+                               
                                if (m->control_pressed) { for (int j = 0; j < outputNames.size(); j++) {        m->mothurRemove(outputNames[j]);        } return 0; }
                        
                                //remove file made for uchime
@@ -591,20 +663,61 @@ int ChimeraUchimeCommand::deconvoluteResults(SequenceParser& parser, string outp
                map<string, string>::iterator itUnique;
                int total = 0;
                
+               //edit accnos file
+               ifstream in2; 
+               m->openInputFile(accnosFileName, in2);
+               
+               ofstream out2;
+               m->openOutputFile(accnosFileName+".temp", out2);
+               
+               string name;
+               set<string> namesInFile; //this is so if a sequence is found to be chimera in several samples we dont write it to the results file more than once
+               set<string>::iterator itNames;
+               set<string> chimerasInFile;
+               set<string>::iterator itChimeras;
+
+               
+               while (!in2.eof()) {
+                       if (m->control_pressed) { in2.close(); out2.close(); m->mothurRemove(outputFileName); m->mothurRemove((accnosFileName+".temp")); return 0; }
+                       
+                       in2 >> name; m->gobble(in2);
+                       
+                       //find unique name
+                       itUnique = uniqueNames.find(name);
+                       
+                       if (itUnique == uniqueNames.end()) { m->mothurOut("[ERROR]: trouble parsing accnos results. Cannot find "+ name + "."); m->mothurOutEndLine(); m->control_pressed = true; }
+                       else {
+                               itChimeras = chimerasInFile.find((itUnique->second));
+                               
+                               if (itChimeras == chimerasInFile.end()) {
+                                       out2 << itUnique->second << endl;
+                                       chimerasInFile.insert((itUnique->second));
+                                       total++;
+                               }
+                       }
+               }
+               in2.close();
+               out2.close();
+               
+               m->mothurRemove(accnosFileName);
+               rename((accnosFileName+".temp").c_str(), accnosFileName.c_str());
+               
+               
+               
                //edit chimera file
                ifstream in; 
                m->openInputFile(outputFileName, in);
                
                ofstream out;
                m->openOutputFile(outputFileName+".temp", out); out.setf(ios::fixed, ios::floatfield); out.setf(ios::showpoint);
+               out << "Score\tQuery\tParentA\tParentB\tIdQM\tIdQA\tIdQB\tIdAB\tIdQT\tLY\tLN\tLA\tRY\tRN\tRA\tDiv\tYN\n";
                
                float temp1;
-               string name, rest, parent1, parent2;
-               set<string> namesInFile; //this is so if a sequence is found to be chimera in several samples we dont write it to the results file more than once
-               set<string>::iterator itNames;
-               
+               string parent1, parent2, temp2, temp3, temp4, temp5, temp6, temp7, temp8, temp9, temp10, temp11, temp12, temp13, flag;
+               name = "";
+               namesInFile.clear();    
                //assumptions - in file each read will always look like - if uchime source is updated, revisit this code.
-               /*
+               /*                                                                              1       2       3       4       5       6       7       8       9       10      11      12      13      14      15
                 0.000000       F11Fcsw_33372/ab=18/            *       *       *       *       *       *       *       *       *       *       *       *       *       *       N
                 0.018300       F11Fcsw_14980/ab=16/            F11Fcsw_1915/ab=35/     F11Fcsw_6032/ab=42/     79.9    78.7    78.2    78.7    79.2    3       0       5       11      10      20      1.46    N
                */
@@ -613,11 +726,13 @@ int ChimeraUchimeCommand::deconvoluteResults(SequenceParser& parser, string outp
                        
                        if (m->control_pressed) { in.close(); out.close(); m->mothurRemove((outputFileName+".temp")); return 0; }
                        
+                       bool print = false;
                        in >> temp1;    m->gobble(in);
                        in >> name;             m->gobble(in);
                        in >> parent1;  m->gobble(in);
                        in >> parent2;  m->gobble(in);
-                       rest = m->getline(in); m->gobble(in);
+                       in >> temp2 >> temp3 >> temp4 >> temp5 >> temp6 >> temp7 >> temp8 >> temp9 >> temp10 >> temp11 >> temp12 >> temp13 >> flag;
+                       m->gobble(in);
                        
                        //parse name - name will look like U68590/ab=1/
                        string restOfName = "";
@@ -632,46 +747,54 @@ int ChimeraUchimeCommand::deconvoluteResults(SequenceParser& parser, string outp
                        
                        if (itUnique == uniqueNames.end()) { m->mothurOut("[ERROR]: trouble parsing chimera results. Cannot find "+ name + "."); m->mothurOutEndLine(); m->control_pressed = true; }
                        else {
-                               itNames = namesInFile.find((itUnique->second));
+                               name = itUnique->second;
+                               //is this name already in the file
+                               itNames = namesInFile.find((name));
                                
-                               if (itNames == namesInFile.end()) {
-                                       out << temp1 << '\t' << itUnique->second << restOfName << '\t';
-                                       namesInFile.insert((itUnique->second));
-                                       
-                                       //parse parent1 names
-                                       if (parent1 != "*") {
-                                               restOfName = "";
-                                               pos = parent1.find_first_of('/');
-                                               if (pos != string::npos) {
-                                                       restOfName = parent1.substr(pos);
-                                                       parent1 = parent1.substr(0, pos);
-                                               }
+                               if (itNames == namesInFile.end()) { //no not in file
+                                       if (flag == "N") { //are you really a no??
+                                               //is this sequence really not chimeric??
+                                               itChimeras = chimerasInFile.find(name);
                                                
-                                               itUnique = uniqueNames.find(parent1);
-                                               if (itUnique == uniqueNames.end()) { m->mothurOut("[ERROR]: trouble parsing chimera results. Cannot find parentA "+ parent1 + "."); m->mothurOutEndLine(); m->control_pressed = true; }
-                                               else {
-                                                       out << itUnique->second << restOfName << '\t';
-                                               }
-                                       }else { out << parent1 << '\t'; }
+                                               //then you really are a no so print, otherwise skip
+                                               if (itChimeras == chimerasInFile.end()) { print = true; }
+                                       }else{ print = true; }
+                               }
+                       }
+                       
+                       if (print) {
+                               out << temp1 << '\t' << name << restOfName << '\t';
+                               namesInFile.insert(name);
+                               
+                               //parse parent1 names
+                               if (parent1 != "*") {
+                                       restOfName = "";
+                                       pos = parent1.find_first_of('/');
+                                       if (pos != string::npos) {
+                                               restOfName = parent1.substr(pos);
+                                               parent1 = parent1.substr(0, pos);
+                                       }
                                        
-                                       //parse parent2 names
-                                       if (parent2 != "*") {
-                                               restOfName = "";
-                                               pos = parent2.find_first_of('/');
-                                               if (pos != string::npos) {
-                                                       restOfName = parent2.substr(pos);
-                                                       parent2 = parent2.substr(0, pos);
-                                               }
-                                               
-                                               itUnique = uniqueNames.find(parent2);
-                                               if (itUnique == uniqueNames.end()) { m->mothurOut("[ERROR]: trouble parsing chimera results. Cannot find parentB "+ parent2 + "."); m->mothurOutEndLine(); m->control_pressed = true; }
-                                               else {
-                                                       out << itUnique->second << restOfName << '\t';
-                                               }
-                                       }else { out << parent2 << '\t'; }
+                                       itUnique = uniqueNames.find(parent1);
+                                       if (itUnique == uniqueNames.end()) { m->mothurOut("[ERROR]: trouble parsing chimera results. Cannot find parentA "+ parent1 + "."); m->mothurOutEndLine(); m->control_pressed = true; }
+                                       else {  out << itUnique->second << restOfName << '\t';  }
+                               }else { out << parent1 << '\t'; }
+                               
+                               //parse parent2 names
+                               if (parent2 != "*") {
+                                       restOfName = "";
+                                       pos = parent2.find_first_of('/');
+                                       if (pos != string::npos) {
+                                               restOfName = parent2.substr(pos);
+                                               parent2 = parent2.substr(0, pos);
+                                       }
                                        
-                                       out  << rest << endl;
-                               }
+                                       itUnique = uniqueNames.find(parent2);
+                                       if (itUnique == uniqueNames.end()) { m->mothurOut("[ERROR]: trouble parsing chimera results. Cannot find parentB "+ parent2 + "."); m->mothurOutEndLine(); m->control_pressed = true; }
+                                       else {  out << itUnique->second << restOfName << '\t';  }
+                               }else { out << parent2 << '\t'; }
+                               
+                               out << temp2 << '\t' << temp3 << '\t' << temp4 << '\t' << temp5 << '\t' << temp6 << '\t' << temp7 << '\t' << temp8 << '\t' << temp9 << '\t' << temp10 << '\t' << temp11 << '\t' << temp12 << temp13 << '\t' << flag << endl;    
                        }
                }
                in.close();
@@ -680,41 +803,7 @@ int ChimeraUchimeCommand::deconvoluteResults(SequenceParser& parser, string outp
                m->mothurRemove(outputFileName);
                rename((outputFileName+".temp").c_str(), outputFileName.c_str());
                
-               //edit accnos file
-               ifstream in2; 
-               m->openInputFile(accnosFileName, in2);
-               
-               ofstream out2;
-               m->openOutputFile(accnosFileName+".temp", out2);
-               
-               name = "";
-               namesInFile.clear();
-               
-               while (!in2.eof()) {
-                       if (m->control_pressed) { in2.close(); out2.close(); m->mothurRemove(outputFileName); m->mothurRemove((accnosFileName+".temp")); return 0; }
-                       
-                       in2 >> name; m->gobble(in2);
-                       
-                       //find unique name
-                       itUnique = uniqueNames.find(name);
-                       
-                       if (itUnique == uniqueNames.end()) { m->mothurOut("[ERROR]: trouble parsing accnos results. Cannot find "+ name + "."); m->mothurOutEndLine(); m->control_pressed = true; }
-                       else {
-                               itNames = namesInFile.find((itUnique->second));
-       
-                               if (itNames == namesInFile.end()) {
-                                       out2 << itUnique->second << endl;
-                                       namesInFile.insert((itUnique->second));
-                                       total++;
-                               }
-                       }
-               }
-               in2.close();
-               out2.close();
-               
-               m->mothurRemove(accnosFileName);
-               rename((accnosFileName+".temp").c_str(), accnosFileName.c_str());
-               
+                               
                //edit anls file
                //assumptions - in file each read will always look like - if uchime source is updated, revisit this code.
                /*
@@ -888,14 +977,15 @@ string ChimeraUchimeCommand::getNamesFile(string& inputFile){
                string inputString = "fasta=" + inputFile;
                m->mothurOut("/******************************************/"); m->mothurOutEndLine(); 
                m->mothurOut("Running command: unique.seqs(" + inputString + ")"); m->mothurOutEndLine(); 
-               
+               m->mothurCalling = true;
+        
                Command* uniqueCommand = new DeconvoluteCommand(inputString);
                uniqueCommand->execute();
                
                map<string, vector<string> > filenames = uniqueCommand->getOutputFiles();
                
                delete uniqueCommand;
-               
+               m->mothurCalling = false;
                m->mothurOut("/******************************************/"); m->mothurOutEndLine(); 
                
                nameFile = filenames["name"][0];
@@ -926,7 +1016,8 @@ int ChimeraUchimeCommand::driverGroups(SequenceParser& parser, string outputFNam
                        if (m->control_pressed) { return 0; }
                        
                        //remove file made for uchime
-                       m->mothurRemove(filename);
+                       if (!m->debug) {  m->mothurRemove(filename);  }
+            else { m->mothurOut("[DEBUG]: saving file: " + filename + ".\n"); }
                        
                        //append files
                        m->appendFiles((outputFName+groups[i]), outputFName); m->mothurRemove((outputFName+groups[i]));
@@ -949,10 +1040,28 @@ int ChimeraUchimeCommand::driverGroups(SequenceParser& parser, string outputFNam
 int ChimeraUchimeCommand::driver(string outputFName, string filename, string accnos, string alns, int& numChimeras){
        try {
                
+               outputFName = m->getFullPathName(outputFName);
+               filename = m->getFullPathName(filename);
+               alns = m->getFullPathName(alns);
+               
+               //to allow for spaces in the path
+               outputFName = "\"" + outputFName + "\"";
+               filename = "\"" + filename + "\"";
+               alns = "\"" + alns + "\"";
+                               
                vector<char*> cPara;
                
-               char* tempUchime = new char[8];  
-               strcpy(tempUchime, "./uchime "); 
+               string uchimeCommand = uchimeLocation;
+#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix)
+               uchimeCommand += " ";
+#else
+               uchimeCommand = "\"" + uchimeCommand + "\"";
+#endif
+               
+               char* tempUchime;
+               tempUchime= new char[uchimeCommand.length()+1]; 
+               *tempUchime = '\0';
+               strncat(tempUchime, uchimeCommand.c_str(), uchimeCommand.length());
                cPara.push_back(tempUchime);
                
                char* tempIn = new char[8]; 
@@ -1174,15 +1283,28 @@ int ChimeraUchimeCommand::driver(string outputFName, string filename, string acc
                
                char** uchimeParameters;
                uchimeParameters = new char*[cPara.size()];
-               for (int i = 0; i < cPara.size(); i++) {  uchimeParameters[i] = cPara[i];  } 
-               int numArgs = cPara.size();
-               
-               uchime_main(numArgs, uchimeParameters); 
+               string commandString = "";
+               for (int i = 0; i < cPara.size(); i++) {  uchimeParameters[i] = cPara[i];  commandString += toString(cPara[i]) + " "; } 
+               //int numArgs = cPara.size();
+               
+               //uchime_main(numArgs, uchimeParameters); 
+               //cout << "commandString = " << commandString << endl;
+#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix)
+#else
+               commandString = "\"" + commandString + "\"";
+#endif
+        if (m->debug) { m->mothurOut("[DEBUG]: uchime command = " + commandString + ".\n"); }
+               system(commandString.c_str());
                
                //free memory
-               for(int i = 0; i < cPara.size(); i++)  {  delete[] cPara[i];  }
+               for(int i = 0; i < cPara.size(); i++)  {  delete cPara[i];  }
                delete[] uchimeParameters; 
                
+               //remove "" from filenames
+               outputFName = outputFName.substr(1, outputFName.length()-2);
+               filename = filename.substr(1, filename.length()-2);
+               alns = alns.substr(1, alns.length()-2);
+               
                if (m->control_pressed) { return 0; }
                
                //create accnos file from uchime results
@@ -1232,9 +1354,10 @@ int ChimeraUchimeCommand::createProcesses(string outputFileName, string filename
                processIDS.clear();
                int process = 1;
                int num = 0;
-#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux)          
-               //break up file into multiple files
                vector<string> files;
+               
+#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix)         
+               //break up file into multiple files
                m->divideFile(filename, processors, files);
                
                if (m->control_pressed) {  return 0;  }
@@ -1287,10 +1410,92 @@ int ChimeraUchimeCommand::createProcesses(string outputFileName, string filename
                        }
                        in.close(); m->mothurRemove(tempFile);
                }
+#else
+               //////////////////////////////////////////////////////////////////////////////////////////////////////
+               //Windows version shared memory, so be careful when passing variables through the preClusterData struct. 
+               //Above fork() will clone, so memory is separate, but that's not the case with windows, 
+               //////////////////////////////////////////////////////////////////////////////////////////////////////
+               
+               //divide file
+               int count = 0;
+               int spot = 0;
+               map<int, ofstream*> filehandles;
+               map<int, ofstream*>::iterator it3;
+               
+               ofstream* temp;
+               for (int i = 0; i < processors; i++) {
+                       temp = new ofstream;
+                       filehandles[i] = temp;
+                       m->openOutputFile(filename+toString(i)+".temp", *(temp));
+                       files.push_back(filename+toString(i)+".temp");
+               }
+               
+               ifstream in;
+               m->openInputFile(filename, in);
+               
+               while(!in.eof()) {
+                       
+                       if (m->control_pressed) { in.close(); for (it3 = filehandles.begin(); it3 != filehandles.end(); it3++) { (*(it3->second)).close(); delete it3->second; } return 0; }
+                       
+                       Sequence tempSeq(in); m->gobble(in); 
+                       
+                       if (tempSeq.getName() != "") {
+                               tempSeq.printSequence(*(filehandles[spot])); 
+                               spot++; count++;
+                               if (spot == processors) { spot = 0; }
+                       }
+               }
+               in.close();
+               
+               //delete memory
+               for (it3 = filehandles.begin(); it3 != filehandles.end(); it3++) {
+                       (*(it3->second)).close();
+                       delete it3->second;
+               }
+               
+               //sanity check for number of processors
+               if (count < processors) { processors = count; }
+               
+               vector<uchimeData*> pDataArray; 
+               DWORD   dwThreadIdArray[processors-1];
+               HANDLE  hThreadArray[processors-1]; 
+               vector<string> dummy; //used so that we can use the same struct for MyUchimeSeqsThreadFunction and MyUchimeThreadFunction
+               
+               //Create processor worker threads.
+               for( int i=1; i<processors; i++ ){
+                       // Allocate memory for thread data.
+                       string extension = toString(i) + ".temp";
+                       
+                       uchimeData* tempUchime = new uchimeData(outputFileName+extension, uchimeLocation, templatefile, files[i], "", "", "", accnos+extension, alns+extension, dummy, m, 0, 0,  i);
+                       tempUchime->setBooleans(useAbskew, chimealns, useMinH, useMindiv, useXn, useDn, useXa, useChunks, useMinchunk, useIdsmoothwindow, useMinsmoothid, useMaxp, skipgaps, skipgaps2, useMinlen, useMaxlen, ucl, useQueryfract);
+                       tempUchime->setVariables(abskew, minh, mindiv, xn, dn, xa, chunks, minchunk, idsmoothwindow, minsmoothid, maxp, minlen, maxlen, queryfract);
+                       
+                       pDataArray.push_back(tempUchime);
+                       processIDS.push_back(i);
+                       
+                       //MySeqSumThreadFunction is in header. It must be global or static to work with the threads.
+                       //default security attributes, thread function name, argument to thread function, use default creation flags, returns the thread identifier
+                       hThreadArray[i-1] = CreateThread(NULL, 0, MyUchimeSeqsThreadFunction, pDataArray[i-1], 0, &dwThreadIdArray[i-1]);   
+               }
                
                
+               //using the main process as a worker saves time and memory
+               num = driver(outputFileName, files[0], accnos, alns, numChimeras);
+               
+               //Wait until all threads have terminated.
+               WaitForMultipleObjects(processors-1, hThreadArray, TRUE, INFINITE);
+               
+               //Close all thread handles and free memory allocations.
+               for(int i=0; i < pDataArray.size(); i++){
+                       num += pDataArray[i]->count;
+                       numChimeras += pDataArray[i]->numChimeras;
+                       CloseHandle(hThreadArray[i]);
+                       delete pDataArray[i];
+               }
+#endif         
+               
                //append output files
-               for(int i=0;i<processIDS[i];i++){
+               for(int i=0;i<processIDS.size();i++){
                        m->appendFiles((outputFileName + toString(processIDS[i]) + ".temp"), outputFileName);
                        m->mothurRemove((outputFileName + toString(processIDS[i]) + ".temp"));
                        
@@ -1305,7 +1510,6 @@ int ChimeraUchimeCommand::createProcesses(string outputFileName, string filename
                
                //get rid of the file pieces.
                for (int i = 0; i < files.size(); i++) { m->mothurRemove(files[i]); }
-#endif         
                return num;     
        }
        catch(exception& e) {
@@ -1315,7 +1519,7 @@ int ChimeraUchimeCommand::createProcesses(string outputFileName, string filename
 }
 /**************************************************************************************************/
 
-int ChimeraUchimeCommand::createProcessesGroups(SequenceParser& parser, string outputFName, string filename, string accnos, string alns, vector<string> groups) {
+int ChimeraUchimeCommand::createProcessesGroups(SequenceParser& parser, string outputFName, string filename, string accnos, string alns, vector<string> groups, string nameFile, string groupFile, string fastaFile) {
        try {
                
                processIDS.clear();
@@ -1335,7 +1539,7 @@ int ChimeraUchimeCommand::createProcessesGroups(SequenceParser& parser, string o
                        lines.push_back(linePair(startIndex, endIndex));
                }
                
-#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux)          
+#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix)         
                                
                //loop through and create all the processes you want
                while (process != processors) {
@@ -1370,7 +1574,6 @@ int ChimeraUchimeCommand::createProcessesGroups(SequenceParser& parser, string o
                        int temp = processIDS[i];
                        wait(&temp);
                }
-#endif         
                
                for (int i = 0; i < processIDS.size(); i++) {
                        ifstream in;
@@ -1379,10 +1582,52 @@ int ChimeraUchimeCommand::createProcessesGroups(SequenceParser& parser, string o
                        if (!in.eof()) { int tempNum = 0; in >> tempNum; num += tempNum; }
                        in.close(); m->mothurRemove(tempFile);
                }
+                               
+#else
+               //////////////////////////////////////////////////////////////////////////////////////////////////////
+               //Windows version shared memory, so be careful when passing variables through the uchimeData struct. 
+               //Above fork() will clone, so memory is separate, but that's not the case with windows, 
+               //////////////////////////////////////////////////////////////////////////////////////////////////////
+               
+               vector<uchimeData*> pDataArray; 
+               DWORD   dwThreadIdArray[processors-1];
+               HANDLE  hThreadArray[processors-1]; 
+               
+               //Create processor worker threads.
+               for( int i=1; i<processors; i++ ){
+                       // Allocate memory for thread data.
+                       string extension = toString(i) + ".temp";
+                       
+                       uchimeData* tempUchime = new uchimeData(outputFName+extension, uchimeLocation, templatefile, filename+extension, fastaFile, nameFile, groupFile, accnos+extension, alns+extension, groups, m, lines[i].start, lines[i].end,  i);
+                       tempUchime->setBooleans(useAbskew, chimealns, useMinH, useMindiv, useXn, useDn, useXa, useChunks, useMinchunk, useIdsmoothwindow, useMinsmoothid, useMaxp, skipgaps, skipgaps2, useMinlen, useMaxlen, ucl, useQueryfract);
+                       tempUchime->setVariables(abskew, minh, mindiv, xn, dn, xa, chunks, minchunk, idsmoothwindow, minsmoothid, maxp, minlen, maxlen, queryfract);
+                       
+                       pDataArray.push_back(tempUchime);
+                       processIDS.push_back(i);
+                       
+                       //MyUchimeThreadFunction is in header. It must be global or static to work with the threads.
+                       //default security attributes, thread function name, argument to thread function, use default creation flags, returns the thread identifier
+                       hThreadArray[i-1] = CreateThread(NULL, 0, MyUchimeThreadFunction, pDataArray[i-1], 0, &dwThreadIdArray[i-1]);   
+               }
+               
+               
+               //using the main process as a worker saves time and memory
+               num = driverGroups(parser, outputFName, filename, accnos, alns, lines[0].start, lines[0].end, groups);
                
+               //Wait until all threads have terminated.
+               WaitForMultipleObjects(processors-1, hThreadArray, TRUE, INFINITE);
                
+               //Close all thread handles and free memory allocations.
+               for(int i=0; i < pDataArray.size(); i++){
+                       num += pDataArray[i]->count;
+                       CloseHandle(hThreadArray[i]);
+                       delete pDataArray[i];
+               }
+#endif         
+               
+                               
                //append output files
-               for(int i=0;i<processIDS[i];i++){
+               for(int i=0;i<processIDS.size();i++){
                        m->appendFiles((outputFName + toString(processIDS[i]) + ".temp"), outputFName);
                        m->mothurRemove((outputFName + toString(processIDS[i]) + ".temp"));