]> git.donarmstrong.com Git - mothur.git/blobdiff - chimerauchimecommand.cpp
1.21.0
[mothur.git] / chimerauchimecommand.cpp
index abd699eff98156435de11ad2f3cf891b09ffa76e..4c1db20ac23105ad29652a3f1feedfc38237c3a6 100644 (file)
@@ -11,6 +11,7 @@
 #include "deconvolutecommand.h"
 #include "uc.h"
 #include "sequence.hpp"
+#include "referencedb.h"
 
 
 //**********************************************************************************************************************
@@ -22,7 +23,25 @@ vector<string> ChimeraUchimeCommand::setParameters(){
                CommandParameter pprocessors("processors", "Number", "", "1", "", "", "",false,false); parameters.push_back(pprocessors);
                CommandParameter pinputdir("inputdir", "String", "", "", "", "", "",false,false); parameters.push_back(pinputdir);
                CommandParameter poutputdir("outputdir", "String", "", "", "", "", "",false,false); parameters.push_back(poutputdir);
-               
+               CommandParameter pabskew("abskew", "Number", "", "1.9", "", "", "",false,false); parameters.push_back(pabskew);
+               CommandParameter pchimealns("chimealns", "Boolean", "", "F", "", "", "",false,false); parameters.push_back(pchimealns);
+               CommandParameter pminh("minh", "Number", "", "0.3", "", "", "",false,false); parameters.push_back(pminh);
+               CommandParameter pmindiv("mindiv", "Number", "", "0.5", "", "", "",false,false); parameters.push_back(pmindiv);
+               CommandParameter pxn("xn", "Number", "", "8.0", "", "", "",false,false); parameters.push_back(pxn);
+               CommandParameter pdn("dn", "Number", "", "1.4", "", "", "",false,false); parameters.push_back(pdn);
+               CommandParameter pxa("xa", "Number", "", "1", "", "", "",false,false); parameters.push_back(pxa);
+               CommandParameter pchunks("chunks", "Number", "", "4", "", "", "",false,false); parameters.push_back(pchunks);
+               CommandParameter pminchunk("minchunk", "Number", "", "64", "", "", "",false,false); parameters.push_back(pminchunk);
+               CommandParameter pidsmoothwindow("idsmoothwindow", "Number", "", "32", "", "", "",false,false); parameters.push_back(pidsmoothwindow);
+               //CommandParameter pminsmoothid("minsmoothid", "Number", "", "0.95", "", "", "",false,false); parameters.push_back(pminsmoothid);
+               CommandParameter pmaxp("maxp", "Number", "", "2", "", "", "",false,false); parameters.push_back(pmaxp);
+               CommandParameter pskipgaps("skipgaps", "Boolean", "", "T", "", "", "",false,false); parameters.push_back(pskipgaps);
+               CommandParameter pskipgaps2("skipgaps2", "Boolean", "", "T", "", "", "",false,false); parameters.push_back(pskipgaps2);
+               CommandParameter pminlen("minlen", "Number", "", "10", "", "", "",false,false); parameters.push_back(pminlen);
+               CommandParameter pmaxlen("maxlen", "Number", "", "10000", "", "", "",false,false); parameters.push_back(pmaxlen);
+               CommandParameter pucl("ucl", "Boolean", "", "F", "", "", "",false,false); parameters.push_back(pucl);
+               CommandParameter pqueryfract("queryfract", "Number", "", "0.5", "", "", "",false,false); parameters.push_back(pqueryfract);
+
                vector<string> myArray;
                for (int i = 0; i < parameters.size(); i++) {   myArray.push_back(parameters[i].name);          }
                return myArray;
@@ -38,12 +57,30 @@ string ChimeraUchimeCommand::getHelpString(){
                string helpString = "";
                helpString += "The chimera.uchime command reads a fastafile and referencefile and outputs potentially chimeric sequences.\n";
                helpString += "This command is a wrapper for uchime written by Robert C. Edgar.\n";
-               helpString += "The chimera.uchime command parameters are fasta, name, reference and processors.\n";
+               helpString += "The chimera.uchime command parameters are fasta, name, reference, processors, abskew, chimealns, minh, mindiv, xn, dn, xa, chunks, minchunk, idsmoothwindow, minsmoothid, maxp, skipgaps, skipgaps2, minlen, maxlen, ucl and queryfact.\n";
                helpString += "The fasta parameter allows you to enter the fasta file containing your potentially chimeric sequences, and is required, unless you have a valid current fasta file. \n";
                helpString += "The name parameter allows you to provide a name file, if you are using template=self. \n";
                helpString += "You may enter multiple fasta files by separating their names with dashes. ie. fasta=abrecovery.fasta-amazon.fasta \n";
                helpString += "The reference parameter allows you to enter a reference file containing known non-chimeric sequences, and is required. You may also set template=self, in this case the abundant sequences will be used as potential parents. \n";
                helpString += "The processors parameter allows you to specify how many processors you would like to use.  The default is 1. \n";
+               helpString += "The abskew parameter can only be used with template=self. Minimum abundance skew. Default 1.9. Abundance skew is: min [ abund(parent1), abund(parent2) ] / abund(query).\n";
+               helpString += "The chimealns parameter allows you to indicate you would like a file containing multiple alignments of query sequences to parents in human readable format. Alignments show columns with differences that support or contradict a chimeric model.\n";
+               helpString += "The minh parameter - mininum score to report chimera. Default 0.3. Values from 0.1 to 5 might be reasonable. Lower values increase sensitivity but may report more false positives. If you decrease xn you may need to increase minh, and vice versa.\n";
+               helpString += "The mindiv parameter - minimum divergence ratio, default 0.5. Div ratio is 100%% - %%identity between query sequence and the closest candidate for being a parent. If you don't care about very close chimeras, then you could increase mindiv to, say, 1.0 or 2.0, and also decrease minh, say to 0.1, to increase sensitivity. How well this works will depend on your data. Best is to tune parameters on a good benchmark.\n";
+               helpString += "The xn parameter - weight of a no vote. Default 8.0. Decreasing this weight to around 3 or 4 may give better performance on denoised data.\n";
+               helpString += "The dn parameter - pseudo-count prior on number of no votes. Default 1.4. Probably no good reason to change this unless you can retune to a good benchmark for your data. Reasonable values are probably in the range from 0.2 to 2.\n";
+               helpString += "The xa parameter - weight of an abstain vote. Default 1. So far, results do not seem to be very sensitive to this parameter, but if you have a good training set might be worth trying. Reasonable values might range from 0.1 to 2.\n";
+               helpString += "The chunks parameter is the number of chunks to extract from the query sequence when searching for parents. Default 4.\n";
+               helpString += "The minchunk parameter is the minimum length of a chunk. Default 64.\n";
+               helpString += "The idsmoothwindow parameter is the length of id smoothing window. Default 32.\n";
+               //helpString += "The minsmoothid parameter - minimum factional identity over smoothed window of candidate parent. Default 0.95.\n";
+               helpString += "The maxp parameter - maximum number of candidate parents to consider. Default 2. In tests so far, increasing maxp gives only a very small improvement in sensivity but tends to increase the error rate quite a bit.\n";
+               helpString += "The skipgaps parameter controls how gapped columns affect counting of diffs. If skipgaps is set to T, columns containing gaps do not found as diffs. Default = T.\n";
+               helpString += "The skipgaps2 parameter controls how gapped columns affect counting of diffs. If skipgaps2 is set to T, if column is immediately adjacent to a column containing a gap, it is not counted as a diff. Default = T.\n";
+               helpString += "The minlen parameter is the minimum unaligned sequence length. Defaults 10. Applies to both query and reference sequences.\n";
+               helpString += "The maxlen parameter is the maximum unaligned sequence length. Defaults 10000. Applies to both query and reference sequences.\n";
+               helpString += "The ucl parameter - use local-X alignments. Default is global-X or false. On tests so far, global-X is always better; this option is retained because it just might work well on some future type of data.\n";
+               helpString += "The queryfract parameter - minimum fraction of the query sequence that must be covered by a local-X alignment. Default 0.5. Applies only when ucl is true.\n";
 #ifdef USE_MPI
                helpString += "When using MPI, the processors parameter is set to the number of MPI processes running. \n";
 #endif
@@ -66,6 +103,7 @@ ChimeraUchimeCommand::ChimeraUchimeCommand(){
                vector<string> tempOutNames;
                outputTypes["chimera"] = tempOutNames;
                outputTypes["accnos"] = tempOutNames;
+               outputTypes["alns"] = tempOutNames;
        }
        catch(exception& e) {
                m->errorOut(e, "ChimeraUchimeCommand", "ChimeraUchimeCommand");
@@ -75,7 +113,8 @@ ChimeraUchimeCommand::ChimeraUchimeCommand(){
 //***************************************************************************************************************
 ChimeraUchimeCommand::ChimeraUchimeCommand(string option)  {
        try {
-               abort = false; calledHelp = false;   
+               abort = false; calledHelp = false; 
+               ReferenceDB* rdb = ReferenceDB::getInstance();
                
                //allow user to run help
                if(option == "help") { help(); abort = true; calledHelp = true; }
@@ -98,6 +137,7 @@ ChimeraUchimeCommand::ChimeraUchimeCommand(string option)  {
                        vector<string> tempOutNames;
                        outputTypes["chimera"] = tempOutNames;
                        outputTypes["accnos"] = tempOutNames;
+                       outputTypes["alns"] = tempOutNames;
                        
                        //if the user changes the input directory command factory will send this info to us in the output parameter 
                        string inputDir = validParameter.validFile(parameters, "inputdir", false);              
@@ -171,6 +211,8 @@ ChimeraUchimeCommand::ChimeraUchimeCommand(string option)  {
                                                        //erase from file list
                                                        fastaFileNames.erase(fastaFileNames.begin()+i);
                                                        i--;
+                                               }else {
+                                                       m->setFastaFile(fastaFileNames[i]);
                                                }
                                        }
                                }
@@ -245,6 +287,8 @@ ChimeraUchimeCommand::ChimeraUchimeCommand(string option)  {
                                                        //erase from file list
                                                        nameFileNames.erase(nameFileNames.begin()+i);
                                                        i--;
+                                               }else {
+                                                       m->setNameFile(nameFileNames[i]);
                                                }
                                        }
                                }
@@ -258,7 +302,6 @@ ChimeraUchimeCommand::ChimeraUchimeCommand(string option)  {
                        //if the user changes the output directory command factory will send this info to us in the output parameter 
                        outputDir = validParameter.validFile(parameters, "outputdir", false);           if (outputDir == "not found"){  outputDir = ""; }
                        
-                       
                        string path;
                        it = parameters.find("reference");
                        //user has given a template file
@@ -271,13 +314,65 @@ ChimeraUchimeCommand::ChimeraUchimeCommand(string option)  {
                                        
                                        templatefile = validParameter.validFile(parameters, "reference", true);
                                        if (templatefile == "not open") { abort = true; }
-                                       else if (templatefile == "not found") { templatefile = "";  m->mothurOut("reference is a required parameter for the chimera.slayer command."); m->mothurOutEndLine(); abort = true;  }  
+                                       else if (templatefile == "not found") { //check for saved reference sequences
+                                               if (rdb->getSavedReference() != "") {
+                                                       templatefile = rdb->getSavedReference();
+                                                       m->mothurOutEndLine();  m->mothurOut("Using sequences from " + rdb->getSavedReference() + "."); m->mothurOutEndLine();
+                                               }else {
+                                                       m->mothurOut("[ERROR]: You don't have any saved reference sequences and the reference parameter is a required."); 
+                                                       m->mothurOutEndLine();
+                                                       abort = true; 
+                                               }
+                                       }
                                }
+                       }else if (hasName) {  templatefile = "self"; }
+                       else { 
+                               if (rdb->getSavedReference() != "") {
+                                       templatefile = rdb->getSavedReference();
+                                       m->mothurOutEndLine();  m->mothurOut("Using sequences from " + rdb->getSavedReference() + "."); m->mothurOutEndLine();
+                               }else {
+                                       m->mothurOut("[ERROR]: You don't have any saved reference sequences and the reference parameter is a required."); 
+                                       m->mothurOutEndLine();
+                                       templatefile = ""; abort = true; 
+                               } 
                        }
-                       
+                               
                        string temp = validParameter.validFile(parameters, "processors", false);        if (temp == "not found"){       temp = m->getProcessors();      }
                        m->setProcessors(temp);
                        convert(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; }
+                       
+                       temp = validParameter.validFile(parameters, "chimealns", false);                        if (temp == "not found") { temp = "f"; }
+                       chimealns = m->isTrue(temp); 
+                       
+                       minh = validParameter.validFile(parameters, "minh", false);                                             if (minh == "not found")                        { useMinH = false; minh = "0.3";                                        }       else{ useMinH = true;                   }
+                       mindiv = validParameter.validFile(parameters, "mindiv", false);                                 if (mindiv == "not found")                      { useMindiv = false; mindiv = "0.5";                            }       else{ useMindiv = true;                 }
+                       xn = validParameter.validFile(parameters, "xn", false);                                                 if (xn == "not found")                          { useXn = false; xn = "8.0";                                            }       else{ useXn = true;                             }
+                       dn = validParameter.validFile(parameters, "dn", false);                                                 if (dn == "not found")                          { useDn = false; dn = "1.4";                                            }       else{ useDn = true;                             }
+                       xa = validParameter.validFile(parameters, "xa", false);                                                 if (xa == "not found")                          { useXa = false; xa = "1";                                                      }       else{ useXa = true;                             }
+                       chunks = validParameter.validFile(parameters, "chunks", false);                                 if (chunks == "not found")                      { useChunks = false; chunks = "4";                                      }       else{ useChunks = true;                 }
+                       minchunk = validParameter.validFile(parameters, "minchunk", false);                             if (minchunk == "not found")            { useMinchunk = false; minchunk = "64";                         }       else{ useMinchunk = true;               }
+                       idsmoothwindow = validParameter.validFile(parameters, "idsmoothwindow", false); if (idsmoothwindow == "not found")      { useIdsmoothwindow = false; idsmoothwindow = "32";     }       else{ useIdsmoothwindow = true; }
+                       //minsmoothid = validParameter.validFile(parameters, "minsmoothid", false);             if (minsmoothid == "not found")         { useMinsmoothid = false; minsmoothid = "0.95";         }       else{ useMinsmoothid = true;    }
+                       maxp = validParameter.validFile(parameters, "maxp", false);                                             if (maxp == "not found")                        { useMaxp = false; maxp = "2";                                          }       else{ useMaxp = true;                   }
+                       minlen = validParameter.validFile(parameters, "minlen", false);                                 if (minlen == "not found")                      { useMinlen = false; minlen = "10";                                     }       else{ useMinlen = true;                 }
+                       maxlen = validParameter.validFile(parameters, "maxlen", false);                                 if (maxlen == "not found")                      { useMaxlen = false; maxlen = "10000";                          }       else{ useMaxlen = true;                 }
+                       
+                       temp = validParameter.validFile(parameters, "ucl", false);                                              if (temp == "not found") { temp = "f"; }
+                       ucl = m->isTrue(temp);
+                       
+                       queryfract = validParameter.validFile(parameters, "queryfract", false);                 if (queryfract == "not found")          { useQueryfract = false; queryfract = "0.5";            }       else{ useQueryfract = true;             }
+                       if (!ucl && useQueryfract) { m->mothurOut("queryfact may only be used when ucl=t, ignoring."); m->mothurOutEndLine(); useQueryfract = false; }
+                       
+                       temp = validParameter.validFile(parameters, "skipgaps", false);                                 if (temp == "not found") { temp = "t"; }
+                       skipgaps = m->isTrue(temp); 
+
+                       temp = validParameter.validFile(parameters, "skipgaps2", false);                                if (temp == "not found") { temp = "t"; }
+                       skipgaps2 = m->isTrue(temp); 
+                       
+                       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; }
                }
        }
        catch(exception& e) {
@@ -291,6 +386,8 @@ int ChimeraUchimeCommand::execute(){
        try{
                if (abort == true) { if (calledHelp) { return 0; }  return 2;   }
                
+               m->mothurOut("\nuchime by Robert C. Edgar\nhttp://drive5.com/uchime\nThis code is donated to the public domain.\n\n");
+               
                for (int s = 0; s < fastaFileNames.size(); s++) {
                        
                        m->mothurOut("Checking sequences from " + fastaFileNames[s] + " ..." ); m->mothurOutEndLine();
@@ -298,7 +395,7 @@ int ChimeraUchimeCommand::execute(){
                        int start = time(NULL); 
                        string nameFile = "";
                        
-                       if (templatefile == "self") { //you want to run slayer with a refernce template
+                       if (templatefile == "self") { //you want to run uchime with a reference template
                                
                                #ifdef USE_MPI  
                                        int pid; 
@@ -338,7 +435,7 @@ int ChimeraUchimeCommand::execute(){
                                
                                while (!in.eof()) {
                                        
-                                       if (m->control_pressed) { in.close(); for (int j = 0; j < outputNames.size(); j++) {    remove(outputNames[j].c_str()); }  return 0; }
+                                       if (m->control_pressed) { in.close(); for (int j = 0; j < outputNames.size(); j++) {    m->mothurRemove(outputNames[j]);        }  return 0; }
                                        
                                        Sequence seq(in); m->gobble(in);
                                        seqs[seq.getName()] = seq.getAligned();
@@ -349,14 +446,14 @@ int ChimeraUchimeCommand::execute(){
                                vector<seqPriorityNode> nameMapCount;
                                int error = m->readNames(nameFile, nameMapCount, seqs);
                                
-                               if (m->control_pressed) { for (int j = 0; j < outputNames.size(); j++) {        remove(outputNames[j].c_str()); }  return 0; }
+                               if (m->control_pressed) { for (int j = 0; j < outputNames.size(); j++) {        m->mothurRemove(outputNames[j]);        }  return 0; }
                                
-                               if (error == 1) { for (int j = 0; j < outputNames.size(); j++) {        remove(outputNames[j].c_str()); }  return 0; }
-                               if (seqs.size() != nameMapCount.size()) { m->mothurOut( "The number of sequences in your fastafile does not match the number of sequences in your namefile, aborting."); m->mothurOutEndLine(); for (int j = 0; j < outputNames.size(); j++) {  remove(outputNames[j].c_str()); }  return 0; }
+                               if (error == 1) { for (int j = 0; j < outputNames.size(); j++) {        m->mothurRemove(outputNames[j]);        }  return 0; }
+                               if (seqs.size() != nameMapCount.size()) { m->mothurOut( "The number of sequences in your fastafile does not match the number of sequences in your namefile, aborting."); m->mothurOutEndLine(); for (int j = 0; j < outputNames.size(); j++) {  m->mothurRemove(outputNames[j]);        }  return 0; }
                                
                                sort(nameMapCount.begin(), nameMapCount.end(), compareSeqPriorityNodes);
                                
-                               string newFasta = fastaFileNames[s] + ".temp";
+                               string newFasta = m->getRootName(fastaFileNames[s]) + "temp";
                                ofstream out;
                                m->openOutputFile(newFasta, out);
                                
@@ -371,28 +468,33 @@ int ChimeraUchimeCommand::execute(){
                                #ifdef USE_MPI  
                                        }
                                #endif
-                               if (m->control_pressed) {  for (int j = 0; j < outputNames.size(); j++) {       remove(outputNames[j].c_str()); }  return 0;    }                               
+                               if (m->control_pressed) {  for (int j = 0; j < outputNames.size(); j++) {       m->mothurRemove(outputNames[j]);        }  return 0;    }                               
                        }
                        
                        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])) + "slayer.chimera";
-                       string accnosFileName = outputDir + m->getRootName(m->getSimpleName(fastaFileNames[s]))  + "slayer.accnos";
+                       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";
                        
-                       if (m->control_pressed) {  for (int j = 0; j < outputNames.size(); j++) {       remove(outputNames[j].c_str()); }  return 0;    }
+                       if (m->control_pressed) {  for (int j = 0; j < outputNames.size(); j++) {       m->mothurRemove(outputNames[j]);        }  return 0;    }
                        
+                       int numSeqs = 0;
 #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux)
-                       if(processors == 1){ driver(outputFileName, fastaFileNames[s], accnosFileName); }
-                       else{   createProcesses(outputFileName, fastaFileNames[s], accnosFileName); }
+                       if(processors == 1){ numSeqs = driver(outputFileName, fastaFileNames[s], accnosFileName, alnsFileName); }
+                       else{   numSeqs = createProcesses(outputFileName, fastaFileNames[s], accnosFileName, alnsFileName); }
 #else
-                       driver(outputFileName, fastaFileNames[s], accnosFileName);
+                       numSeqs = driver(outputFileName, fastaFileNames[s], accnosFileName, alnsFileName);
 #endif
-                       if (m->control_pressed) { for (int j = 0; j < outputNames.size(); j++) {        remove(outputNames[j].c_str()); } return 0; }
-
+                       if (m->control_pressed) { for (int j = 0; j < outputNames.size(); j++) {        m->mothurRemove(outputNames[j]);        } return 0; }
+                       
+                       //remove file made for uchime
+                       if (templatefile == "self") {  m->mothurRemove(fastaFileNames[s]); }
                        
                        outputNames.push_back(outputFileName); outputTypes["chimera"].push_back(outputFileName);
                        outputNames.push_back(accnosFileName); outputTypes["accnos"].push_back(accnosFileName);
+                       if (chimealns) { outputNames.push_back(alnsFileName); outputTypes["alns"].push_back(alnsFileName); }
                        
-                       m->mothurOutEndLine(); m->mothurOut("It took " + toString(time(NULL) - start) + " secs to check your sequences.");      m->mothurOutEndLine();
+                       m->mothurOutEndLine(); m->mothurOut("It took " + toString(time(NULL) - start) + " secs to check " + toString(numSeqs) + " sequences."); m->mothurOutEndLine();
                }
                
                //set accnos file as new current accnosfile
@@ -417,7 +519,7 @@ int ChimeraUchimeCommand::execute(){
 }
 //**********************************************************************************************************************
 
-int ChimeraUchimeCommand::driver(string outputFName, string filename, string accnos){
+int ChimeraUchimeCommand::driver(string outputFName, string filename, string accnos, string alns){
        try {
                
                vector<char*> cPara;
@@ -426,35 +528,226 @@ int ChimeraUchimeCommand::driver(string outputFName, string filename, string acc
                strcpy(tempUchime, "./uchime "); 
                cPara.push_back(tempUchime);
                
-               char* tempIn = new char[7];  
-               strcpy(tempIn, "--input"); 
+               char* tempIn = new char[8]; 
+               *tempIn = '\0'; strncat(tempIn, "--input", 7);
+               //strcpy(tempIn, "--input"); 
                cPara.push_back(tempIn);
-               char* temp = new char[filename.length()];
-               strcpy(temp, filename.c_str());
+               char* temp = new char[filename.length()+1];
+               *temp = '\0'; strncat(temp, filename.c_str(), filename.length());
+               //strcpy(temp, filename.c_str());
                cPara.push_back(temp);
                
                //are you using a reference file
                if (templatefile != "self") {
-                                               
                        //add reference file
-                       char* tempRef = new char[4]; 
-                       strcpy(tempRef, "--db"); 
+                       char* tempRef = new char[5]; 
+                       //strcpy(tempRef, "--db"); 
+                       *tempRef = '\0'; strncat(tempRef, "--db", 4);
                        cPara.push_back(tempRef);  
-                       char* tempR = new char[templatefile.length()];
-                       strcpy(tempR, templatefile.c_str());
+                       char* tempR = new char[templatefile.length()+1];
+                       //strcpy(tempR, templatefile.c_str());
+                       *tempR = '\0'; strncat(tempR, templatefile.c_str(), templatefile.length());
                        cPara.push_back(tempR);
                }
                
-               char* tempO = new char[11]; 
-               strcpy(tempO, "--uchimeout"); 
+               char* tempO = new char[12]; 
+               *tempO = '\0'; strncat(tempO, "--uchimeout", 11);
+               //strcpy(tempO, "--uchimeout"); 
                cPara.push_back(tempO);
-               char* tempout = new char[outputFName.length()];
-               strcpy(tempout, outputFName.c_str());
+               char* tempout = new char[outputFName.length()+1];
+               //strcpy(tempout, outputFName.c_str());
+               *tempout = '\0'; strncat(tempout, outputFName.c_str(), outputFName.length());
                cPara.push_back(tempout);
                
+               if (chimealns) {
+                       char* tempA = new char[13]; 
+                       *tempA = '\0'; strncat(tempA, "--uchimealns", 12);
+                       //strcpy(tempA, "--uchimealns"); 
+                       cPara.push_back(tempA);
+                       char* tempa = new char[alns.length()+1];
+                       //strcpy(tempa, alns.c_str());
+                       *tempa = '\0'; strncat(tempa, alns.c_str(), alns.length());
+                       cPara.push_back(tempa);
+               }
+               
+               if (useAbskew) {
+                       char* tempskew = new char[9];
+                       *tempskew = '\0'; strncat(tempskew, "--abskew", 8);
+                       //strcpy(tempskew, "--abskew"); 
+                       cPara.push_back(tempskew);
+                       char* tempSkew = new char[abskew.length()+1];
+                       //strcpy(tempSkew, abskew.c_str());
+                       *tempSkew = '\0'; strncat(tempSkew, abskew.c_str(), abskew.length());
+                       cPara.push_back(tempSkew);
+               }
+               
+               if (useMinH) {
+                       char* tempminh = new char[7]; 
+                       *tempminh = '\0'; strncat(tempminh, "--minh", 6);
+                       //strcpy(tempminh, "--minh"); 
+                       cPara.push_back(tempminh);
+                       char* tempMinH = new char[minh.length()+1];
+                       *tempMinH = '\0'; strncat(tempMinH, minh.c_str(), minh.length());
+                       //strcpy(tempMinH, minh.c_str());
+                       cPara.push_back(tempMinH);
+               }
+               
+               if (useMindiv) {
+                       char* tempmindiv = new char[9]; 
+                       *tempmindiv = '\0'; strncat(tempmindiv, "--mindiv", 8);
+                       //strcpy(tempmindiv, "--mindiv"); 
+                       cPara.push_back(tempmindiv);
+                       char* tempMindiv = new char[mindiv.length()+1];
+                       *tempMindiv = '\0'; strncat(tempMindiv, mindiv.c_str(), mindiv.length());
+                       //strcpy(tempMindiv, mindiv.c_str());
+                       cPara.push_back(tempMindiv);
+               }
+               
+               if (useXn) {
+                       char* tempxn = new char[5]; 
+                       //strcpy(tempxn, "--xn"); 
+                       *tempxn = '\0'; strncat(tempxn, "--xn", 4);
+                       cPara.push_back(tempxn);
+                       char* tempXn = new char[xn.length()+1];
+                       //strcpy(tempXn, xn.c_str());
+                       *tempXn = '\0'; strncat(tempXn, xn.c_str(), xn.length());
+                       cPara.push_back(tempXn);
+               }
+               
+               if (useDn) {
+                       char* tempdn = new char[5]; 
+                       //strcpy(tempdn, "--dn"); 
+                       *tempdn = '\0'; strncat(tempdn, "--dn", 4);
+                       cPara.push_back(tempdn);
+                       char* tempDn = new char[dn.length()+1];
+                       *tempDn = '\0'; strncat(tempDn, dn.c_str(), dn.length());
+                       //strcpy(tempDn, dn.c_str());
+                       cPara.push_back(tempDn);
+               }
+               
+               if (useXa) {
+                       char* tempxa = new char[5]; 
+                       //strcpy(tempxa, "--xa"); 
+                       *tempxa = '\0'; strncat(tempxa, "--xa", 4);
+                       cPara.push_back(tempxa);
+                       char* tempXa = new char[xa.length()+1];
+                       *tempXa = '\0'; strncat(tempXa, xa.c_str(), xa.length());
+                       //strcpy(tempXa, xa.c_str());
+                       cPara.push_back(tempXa);
+               }
+               
+               if (useChunks) {
+                       char* tempchunks = new char[9]; 
+                       //strcpy(tempchunks, "--chunks"); 
+                       *tempchunks = '\0'; strncat(tempchunks, "--chunks", 8);
+                       cPara.push_back(tempchunks);
+                       char* tempChunks = new char[chunks.length()+1];
+                       *tempChunks = '\0'; strncat(tempChunks, chunks.c_str(), chunks.length());
+                       //strcpy(tempChunks, chunks.c_str());
+                       cPara.push_back(tempChunks);
+               }
+               
+               if (useMinchunk) {
+                       char* tempminchunk = new char[11]; 
+                       //strcpy(tempminchunk, "--minchunk"); 
+                       *tempminchunk = '\0'; strncat(tempminchunk, "--minchunk", 10);
+                       cPara.push_back(tempminchunk);
+                       char* tempMinchunk = new char[minchunk.length()+1];
+                       *tempMinchunk = '\0'; strncat(tempMinchunk, minchunk.c_str(), minchunk.length());
+                       //strcpy(tempMinchunk, minchunk.c_str());
+                       cPara.push_back(tempMinchunk);
+               }
+               
+               if (useIdsmoothwindow) {
+                       char* tempidsmoothwindow = new char[17]; 
+                       *tempidsmoothwindow = '\0'; strncat(tempidsmoothwindow, "--idsmoothwindow", 16);
+                       //strcpy(tempidsmoothwindow, "--idsmoothwindow"); 
+                       cPara.push_back(tempidsmoothwindow);
+                       char* tempIdsmoothwindow = new char[idsmoothwindow.length()+1];
+                       *tempIdsmoothwindow = '\0'; strncat(tempIdsmoothwindow, idsmoothwindow.c_str(), idsmoothwindow.length());
+                       //strcpy(tempIdsmoothwindow, idsmoothwindow.c_str());
+                       cPara.push_back(tempIdsmoothwindow);
+               }
+               
+               /*if (useMinsmoothid) {
+                       char* tempminsmoothid = new char[14]; 
+                       //strcpy(tempminsmoothid, "--minsmoothid"); 
+                       *tempminsmoothid = '\0'; strncat(tempminsmoothid, "--minsmoothid", 13);
+                       cPara.push_back(tempminsmoothid);
+                       char* tempMinsmoothid = new char[minsmoothid.length()+1];
+                       *tempMinsmoothid = '\0'; strncat(tempMinsmoothid, minsmoothid.c_str(), minsmoothid.length());
+                       //strcpy(tempMinsmoothid, minsmoothid.c_str());
+                       cPara.push_back(tempMinsmoothid);
+               }*/
+               
+               if (useMaxp) {
+                       char* tempmaxp = new char[7]; 
+                       //strcpy(tempmaxp, "--maxp"); 
+                       *tempmaxp = '\0'; strncat(tempmaxp, "--maxp", 6);
+                       cPara.push_back(tempmaxp);
+                       char* tempMaxp = new char[maxp.length()+1];
+                       *tempMaxp = '\0'; strncat(tempMaxp, maxp.c_str(), maxp.length());
+                       //strcpy(tempMaxp, maxp.c_str());
+                       cPara.push_back(tempMaxp);
+               }
+               
+               if (!skipgaps) {
+                       char* tempskipgaps = new char[13]; 
+                       //strcpy(tempskipgaps, "--[no]skipgaps");
+                       *tempskipgaps = '\0'; strncat(tempskipgaps, "--noskipgaps", 12);
+                       cPara.push_back(tempskipgaps);
+               }
+               
+               if (!skipgaps2) {
+                       char* tempskipgaps2 = new char[14]; 
+                       //strcpy(tempskipgaps2, "--[no]skipgaps2"); 
+                       *tempskipgaps2 = '\0'; strncat(tempskipgaps2, "--noskipgaps2", 13);
+                       cPara.push_back(tempskipgaps2);
+               }
+               
+               if (useMinlen) {
+                       char* tempminlen = new char[9]; 
+                       *tempminlen = '\0'; strncat(tempminlen, "--minlen", 8);
+                       //strcpy(tempminlen, "--minlen"); 
+                       cPara.push_back(tempminlen);
+                       char* tempMinlen = new char[minlen.length()+1];
+                       //strcpy(tempMinlen, minlen.c_str());
+                       *tempMinlen = '\0'; strncat(tempMinlen, minlen.c_str(), minlen.length());
+                       cPara.push_back(tempMinlen);
+               }
+               
+               if (useMaxlen) {
+                       char* tempmaxlen = new char[9]; 
+                       //strcpy(tempmaxlen, "--maxlen"); 
+                       *tempmaxlen = '\0'; strncat(tempmaxlen, "--maxlen", 8);
+                       cPara.push_back(tempmaxlen);
+                       char* tempMaxlen = new char[maxlen.length()+1];
+                       *tempMaxlen = '\0'; strncat(tempMaxlen, maxlen.c_str(), maxlen.length());
+                       //strcpy(tempMaxlen, maxlen.c_str());
+                       cPara.push_back(tempMaxlen);
+               }
+               
+               if (ucl) {
+                       char* tempucl = new char[5]; 
+                       strcpy(tempucl, "--ucl"); 
+                       cPara.push_back(tempucl);
+               }
+               
+               if (useQueryfract) {
+                       char* tempqueryfract = new char[13]; 
+                       *tempqueryfract = '\0'; strncat(tempqueryfract, "--queryfract", 12);
+                       //strcpy(tempqueryfract, "--queryfract"); 
+                       cPara.push_back(tempqueryfract);
+                       char* tempQueryfract = new char[queryfract.length()+1];
+                       *tempQueryfract = '\0'; strncat(tempQueryfract, queryfract.c_str(), queryfract.length());
+                       //strcpy(tempQueryfract, queryfract.c_str());
+                       cPara.push_back(tempQueryfract);
+               }
+               
+               
                char** uchimeParameters;
                uchimeParameters = new char*[cPara.size()];
-               for (int i = 0; i < cPara.size(); i++) {  uchimeParameters[i] = cPara[i]; cout << cPara[i]; } cout << endl;
+               for (int i = 0; i < cPara.size(); i++) {  uchimeParameters[i] = cPara[i];  } 
                int numArgs = cPara.size();
                
                uchime_main(numArgs, uchimeParameters); 
@@ -463,6 +756,8 @@ int ChimeraUchimeCommand::driver(string outputFName, string filename, string acc
                for(int i = 0; i < cPara.size(); i++)  {  delete[] cPara[i];  }
                delete[] uchimeParameters; 
                
+               if (m->control_pressed) { return 0; }
+               
                //create accnos file from uchime results
                ifstream in; 
                m->openInputFile(outputFName, in);
@@ -480,7 +775,7 @@ int ChimeraUchimeCommand::driver(string outputFName, string filename, string acc
                        in >> chimeraFlag >> name;
                        
                        //fix name if needed
-                       if (templatefile != "self") { 
+                       if (templatefile == "self") { 
                                name = name.substr(0, name.length()-1); //rip off last /
                                name = name.substr(0, name.find_last_of('/'));
                        }
@@ -503,13 +798,13 @@ int ChimeraUchimeCommand::driver(string outputFName, string filename, string acc
 }
 /**************************************************************************************************/
 
-int ChimeraUchimeCommand::createProcesses(string outputFileName, string filename, string accnos) {
+int ChimeraUchimeCommand::createProcesses(string outputFileName, string filename, string accnos, string alns) {
        try {
                
                processIDS.clear();
                int process = 1;
                int num = 0;
-               
+#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux)          
                //break up file into multiple files
                vector<string> files;
                m->divideFile(filename, processors, files);
@@ -525,7 +820,7 @@ int ChimeraUchimeCommand::createProcesses(string outputFileName, string filename
                MPI_Comm_size(MPI_COMM_WORLD, &processors); 
                                
                if (pid == 0) { //you are the root process 
-                       num = driver(outputFileName, files[0], accnos);
+                       num = driver(outputFileName, files[0], accnos, alns);
                        
                        if (templatefile != "self") {
                                //wait on chidren
@@ -535,15 +830,20 @@ int ChimeraUchimeCommand::createProcesses(string outputFileName, string filename
                                        num += temp;
                                        
                                        m->appendFiles((outputFileName + toString(j) + ".temp"), outputFileName);
-                                       remove((outputFileName + toString(j) + ".temp").c_str());
+                                       m->mothurRemove((outputFileName + toString(j) + ".temp"));
                                        
                                        m->appendFiles((accnos + toString(j) + ".temp"), accnos);
-                                       remove((accnos + toString(j) + ".temp").c_str());
+                                       m->mothurRemove((accnos + toString(j) + ".temp"));
+                                       
+                                       if (chimealns) {
+                                               m->appendFiles((alns + toString(j) + ".temp"), alns);
+                                               m->mothurRemove((alns + toString(j) + ".temp"));
+                                       }
                                }
                        }
                }else{ //you are a child process
                        if (templatefile != "self") { //if template=self we can only use 1 processor
-                               num = driver(outputFileName+toString(pid) + ".temp", files[pid], accnos+toString(pid) + ".temp");       
+                               num = driver(outputFileName+toString(pid) + ".temp", files[pid], accnos+toString(pid) + ".temp", alns+toString(pid) + ".temp"); 
                                
                                //send numSeqs to parent
                                MPI_Send(&num, 1, MPI_INT, 0, tag, MPI_COMM_WORLD);
@@ -561,7 +861,7 @@ int ChimeraUchimeCommand::createProcesses(string outputFileName, string filename
                                processIDS.push_back(pid);  //create map from line number to pid so you can append files in correct order later
                                process++;
                        }else if (pid == 0){
-                               num = driver(outputFileName + toString(getpid()) + ".temp", files[process], accnos + toString(getpid()) + ".temp");
+                               num = driver(outputFileName + toString(getpid()) + ".temp", files[process], accnos + toString(getpid()) + ".temp", alns + toString(getpid()) + ".temp");
                                
                                //pass numSeqs to parent
                                ofstream out;
@@ -579,7 +879,7 @@ int ChimeraUchimeCommand::createProcesses(string outputFileName, string filename
                }
                
                //do my part
-               num = driver(outputFileName, files[0], accnos);
+               num = driver(outputFileName, files[0], accnos, alns);
                
                //force parent to wait until all the processes are done
                for (int i=0;i<processIDS.size();i++) { 
@@ -592,22 +892,27 @@ int ChimeraUchimeCommand::createProcesses(string outputFileName, string filename
                        string tempFile =  outputFileName + toString(processIDS[i]) + ".num.temp";
                        m->openInputFile(tempFile, in);
                        if (!in.eof()) { int tempNum = 0; in >> tempNum; num += tempNum; }
-                       in.close(); remove(tempFile.c_str());
+                       in.close(); m->mothurRemove(tempFile);
                }
                
                
                //append output files
                for(int i=0;i<processIDS[i];i++){
                        m->appendFiles((outputFileName + toString(processIDS[i]) + ".temp"), outputFileName);
-                       remove((outputFileName + toString(processIDS[i]) + ".temp").c_str());
+                       m->mothurRemove((outputFileName + toString(processIDS[i]) + ".temp"));
                        
                        m->appendFiles((accnos + toString(processIDS[i]) + ".temp"), accnos);
-                       remove((accnos + toString(processIDS[i]) + ".temp").c_str());
+                       m->mothurRemove((accnos + toString(processIDS[i]) + ".temp"));
+                       
+                       if (chimealns) {
+                               m->appendFiles((alns + toString(processIDS[i]) + ".temp"), alns);
+                               m->mothurRemove((alns + toString(processIDS[i]) + ".temp"));
+                       }
                }
 #endif         
                //get rid of the file pieces.
-               for (int i = 0; i < files.size(); i++) { remove(files[i].c_str()); }
-               
+               for (int i = 0; i < files.size(); i++) { m->mothurRemove(files[i]); }
+#endif         
                return num;     
        }
        catch(exception& e) {