]> git.donarmstrong.com Git - mothur.git/blobdiff - clustersplitcommand.cpp
update .gitignore
[mothur.git] / clustersplitcommand.cpp
index b097f382024d5be9c56bd346723e398b10ef3725..546d633d4fb9c4fa61460c5d8ac87814fce5f660 100644 (file)
 //**********************************************************************************************************************
 vector<string> ClusterSplitCommand::setParameters(){   
        try {
-               CommandParameter ptaxonomy("taxonomy", "InputTypes", "", "", "none", "none", "FastaTaxName",false,false); parameters.push_back(ptaxonomy);
-               CommandParameter pphylip("phylip", "InputTypes", "", "", "PhylipColumnFasta", "PhylipColumnFasta", "none",false,false); parameters.push_back(pphylip);
-               CommandParameter pfasta("fasta", "InputTypes", "", "", "PhylipColumnFasta", "PhylipColumnFasta", "FastaTaxName",false,false); parameters.push_back(pfasta);
-               CommandParameter pname("name", "InputTypes", "", "", "none", "none", "ColumnName-FastaTaxName",false,false); parameters.push_back(pname);
-               CommandParameter pcolumn("column", "InputTypes", "", "", "PhylipColumnFasta", "PhylipColumnFasta", "ColumnName",false,false); parameters.push_back(pcolumn);
-               CommandParameter ptaxlevel("taxlevel", "Number", "", "3", "", "", "",false,false); parameters.push_back(ptaxlevel);
-               CommandParameter psplitmethod("splitmethod", "Multiple", "classify-fasta-distance", "distance", "", "", "",false,false); parameters.push_back(psplitmethod);
-               CommandParameter plarge("large", "Boolean", "", "F", "", "", "",false,false); parameters.push_back(plarge);
-               CommandParameter pshowabund("showabund", "Boolean", "", "T", "", "", "",false,false); parameters.push_back(pshowabund);
-               CommandParameter ptiming("timing", "Boolean", "", "F", "", "", "",false,false); parameters.push_back(ptiming);
-               CommandParameter pprocessors("processors", "Number", "", "1", "", "", "",false,false); parameters.push_back(pprocessors);
-               CommandParameter pcutoff("cutoff", "Number", "", "0.25", "", "", "",false,false); parameters.push_back(pcutoff);
-               CommandParameter pprecision("precision", "Number", "", "100", "", "", "",false,false); parameters.push_back(pprecision);
-               CommandParameter pmethod("method", "Multiple", "furthest-nearest-average-weighted", "average", "", "", "",false,false); parameters.push_back(pmethod);
-               CommandParameter phard("hard", "Boolean", "", "T", "", "", "",false,false); parameters.push_back(phard);
-        CommandParameter pclassic("classic", "Boolean", "", "F", "", "", "",false,false); parameters.push_back(pclassic);
-               CommandParameter pinputdir("inputdir", "String", "", "", "", "", "",false,false); parameters.push_back(pinputdir);
-               CommandParameter poutputdir("outputdir", "String", "", "", "", "", "",false,false); parameters.push_back(poutputdir);
+        CommandParameter pfile("file", "InputTypes", "", "", "PhylipColumnFasta", "PhylipColumnFasta", "none","",false,false,true); parameters.push_back(pfile);
+               CommandParameter ptaxonomy("taxonomy", "InputTypes", "", "", "none", "none", "FastaTaxName","",false,false,true); parameters.push_back(ptaxonomy);
+               CommandParameter pphylip("phylip", "InputTypes", "", "", "PhylipColumnFasta", "PhylipColumnFasta", "none","list",false,false,true); parameters.push_back(pphylip);
+               CommandParameter pfasta("fasta", "InputTypes", "", "", "PhylipColumnFasta", "PhylipColumnFasta", "FastaTaxName","list",false,false,true); parameters.push_back(pfasta);
+               CommandParameter pname("name", "InputTypes", "", "", "NameCount", "none", "ColumnName-FastaTaxName","rabund-sabund",false,false,true); parameters.push_back(pname);
+        CommandParameter pcount("count", "InputTypes", "", "", "NameCount", "none", "","",false,false,true); parameters.push_back(pcount);
+               CommandParameter pcolumn("column", "InputTypes", "", "", "PhylipColumnFasta", "PhylipColumnFasta", "ColumnName","list",false,false,true); parameters.push_back(pcolumn);
+               CommandParameter ptaxlevel("taxlevel", "Number", "", "3", "", "", "","",false,false,true); parameters.push_back(ptaxlevel);
+               CommandParameter psplitmethod("splitmethod", "Multiple", "classify-fasta-distance", "distance", "", "", "","",false,false,true); parameters.push_back(psplitmethod);
+               CommandParameter plarge("large", "Boolean", "", "F", "", "", "","",false,false); parameters.push_back(plarge);
+               CommandParameter pshowabund("showabund", "Boolean", "", "T", "", "", "","",false,false); parameters.push_back(pshowabund);
+        CommandParameter pcluster("cluster", "Boolean", "", "T", "", "", "","",false,false); parameters.push_back(pcluster);
+               CommandParameter ptiming("timing", "Boolean", "", "F", "", "", "","",false,false); parameters.push_back(ptiming);
+               CommandParameter pprocessors("processors", "Number", "", "1", "", "", "","",false,false,true); parameters.push_back(pprocessors);
+               CommandParameter pcutoff("cutoff", "Number", "", "0.25", "", "", "","",false,false,true); parameters.push_back(pcutoff);
+               CommandParameter pprecision("precision", "Number", "", "100", "", "", "","",false,false); parameters.push_back(pprecision);
+               CommandParameter pmethod("method", "Multiple", "furthest-nearest-average-weighted", "average", "", "", "","",false,false); parameters.push_back(pmethod);
+               CommandParameter phard("hard", "Boolean", "", "T", "", "", "","",false,false); parameters.push_back(phard);
+        CommandParameter pclassic("classic", "Boolean", "", "F", "", "", "","",false,false); parameters.push_back(pclassic);
+               CommandParameter pinputdir("inputdir", "String", "", "", "", "", "","",false,false); parameters.push_back(pinputdir);
+               CommandParameter poutputdir("outputdir", "String", "", "", "", "", "","",false,false); parameters.push_back(poutputdir);
                        
                vector<string> myArray;
                for (int i = 0; i < parameters.size(); i++) {   myArray.push_back(parameters[i].name);          }
@@ -45,19 +48,22 @@ vector<string> ClusterSplitCommand::setParameters(){
 string ClusterSplitCommand::getHelpString(){   
        try {
                string helpString = "";
-               helpString += "The cluster.split command parameter options are fasta, phylip, column, name, cutoff, precision, method, splitmethod, taxonomy, taxlevel, showabund, timing, hard, large, processors. Fasta or Phylip or column and name are required.\n";
+               helpString += "The cluster.split command parameter options are file, fasta, phylip, column, name, count, cutoff, precision, method, splitmethod, taxonomy, taxlevel, showabund, timing, hard, large, cluster, processors. Fasta or Phylip or column and name are required.\n";
                helpString += "The cluster.split command can split your files in 3 ways. Splitting by distance file, by classification, or by classification also using a fasta file. \n";
                helpString += "For the distance file method, you need only provide your distance file and mothur will split the file into distinct groups. \n";
                helpString += "For the classification method, you need to provide your distance file and taxonomy file, and set the splitmethod to classify.  \n";
                helpString += "You will also need to set the taxlevel you want to split by. mothur will split the sequences into distinct taxonomy groups, and split the distance file based on those groups. \n";
                helpString += "For the classification method using a fasta file, you need to provide your fasta file, names file and taxonomy file.  \n";
                helpString += "You will also need to set the taxlevel you want to split by. mothur will split the sequence into distinct taxonomy groups, and create distance files for each grouping. \n";
+        helpString += "The file option allows you to enter your file containing your list of column and names/count files as well as the singleton file.  This file is mothur generated, when you run cluster.split() with the cluster=f parameter.  This can be helpful when you have a large dataset that you may be able to use all your processors for the splitting step, but have to reduce them for the cluster step due to RAM constraints. For example: cluster.split(fasta=yourFasta, taxonomy=yourTax, count=yourCount, taxlevel=3, cluster=f, processors=8) then cluster.split(file=yourFile, processors=4).  This allows your to maximize your processors during the splitting step.  Also, if you are unsure if the cluster step will have RAM issue with multiple processors, you can avoid running the first part of the command multiple times.\n";
                helpString += "The phylip and column parameter allow you to enter your distance file. \n";
                helpString += "The fasta parameter allows you to enter your aligned fasta file. \n";
-               helpString += "The name parameter allows you to enter your name file and is required if your distance file is in column format. \n";
+               helpString += "The name parameter allows you to enter your name file. \n";
+        helpString += "The count parameter allows you to enter your count file. \n A count or name file is required if your distance file is in column format";
+        helpString += "The cluster parameter allows you to indicate whether you want to run the clustering or just split the distance matrix, default=t";
                helpString += "The cutoff parameter allow you to set the distance you want to cluster to, default is 0.25. \n";
                helpString += "The precision parameter allows you specify the precision of the precision of the distances outputted, default=100, meaning 2 decimal places. \n";
-               helpString += "The method allows you to specify what clustering algorythm you want to use, default=average, option furthest, nearest, or average. \n";
+               helpString += "The method allows you to specify what clustering algorithm you want to use, default=average, option furthest, nearest, or average. \n";
                helpString += "The splitmethod parameter allows you to specify how you want to split your distance file before you cluster, default=distance, options distance, classify or fasta. \n";
                helpString += "The taxonomy parameter allows you to enter the taxonomy file for your sequences, this is only valid if you are using splitmethod=classify. Be sure your taxonomy file does not include the probability scores. \n";
                helpString += "The taxlevel parameter allows you to specify the taxonomy level you want to use to split the distance file, default=3, meaning use the first taxon in each list. \n";
@@ -77,27 +83,23 @@ string ClusterSplitCommand::getHelpString(){
        }
 }
 //**********************************************************************************************************************
-string ClusterSplitCommand::getOutputFileNameTag(string type, string inputName=""){    
-       try {
-        string outputFileName = "";
-               map<string, vector<string> >::iterator it;
+string ClusterSplitCommand::getOutputPattern(string type) {
+    try {
+        string pattern = "";
         
-        //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 == "list") {  outputFileName =  "list"; }
-            else if (type == "rabund") {  outputFileName =  "rabund"; }
-            else if (type == "sabund") {  outputFileName =  "sabund"; }
-            else if (type == "column") {  outputFileName =  "dist"; }
-            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, "ClusterSplitCommand", "getOutputFileNameTag");
-               exit(1);
-       }
+        if (type == "list") {  pattern = "[filename],[clustertag],list-[filename],[clustertag],[tag2],list"; } 
+        else if (type == "rabund") {  pattern = "[filename],[clustertag],rabund"; } 
+        else if (type == "sabund") {  pattern = "[filename],[clustertag],sabund"; }
+        else if (type == "column") {  pattern = "[filename],dist"; }
+        else if (type == "file")   {  pattern = "[filename],file"; }
+        else { m->mothurOut("[ERROR]: No definition for type " + type + " output pattern.\n"); m->control_pressed = true;  }
+        
+        return pattern;
+    }
+    catch(exception& e) {
+        m->errorOut(e, "ClusterSplitCommand", "getOutputPattern");
+        exit(1);
+    }
 }
 //**********************************************************************************************************************
 ClusterSplitCommand::ClusterSplitCommand(){    
@@ -109,6 +111,7 @@ ClusterSplitCommand::ClusterSplitCommand(){
                outputTypes["rabund"] = tempOutNames;
                outputTypes["sabund"] = tempOutNames;
                outputTypes["column"] = tempOutNames;
+        outputTypes["file"] = tempOutNames;
        }
        catch(exception& e) {
                m->errorOut(e, "ClusterSplitCommand", "ClusterSplitCommand");
@@ -148,6 +151,7 @@ ClusterSplitCommand::ClusterSplitCommand(string option)  {
                        outputTypes["rabund"] = tempOutNames;
                        outputTypes["sabund"] = tempOutNames;
                        outputTypes["column"] = tempOutNames;
+            outputTypes["file"] = tempOutNames;
                        
                        //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 = "";         }
@@ -196,12 +200,33 @@ ClusterSplitCommand::ClusterSplitCommand(string option)  {
                                        //if the user has not given a path then, add inputdir. else leave path alone.
                                        if (path == "") {       parameters["fasta"] = inputDir + it->second;            }
                                }
+                
+                it = parameters.find("count");
+                               //user has given a template file
+                               if(it != parameters.end()){ 
+                                       path = m->hasPath(it->second);
+                                       //if the user has not given a path then, add inputdir. else leave path alone.
+                                       if (path == "") {       parameters["count"] = inputDir + it->second;            }
+                               }
+                
+                it = parameters.find("file");
+                               //user has given a template file
+                               if(it != parameters.end()){
+                                       path = m->hasPath(it->second);
+                                       //if the user has not given a path then, add inputdir. else leave path alone.
+                                       if (path == "") {       parameters["file"] = inputDir + it->second;             }
+                               }
                        }
                        
                        //check for required parameters
-                       phylipfile = validParameter.validFile(parameters, "phylip", true);
+                       file = validParameter.validFile(parameters, "file", true);
+                       if (file == "not open") { file = ""; abort = true; }
+                       else if (file == "not found") { file = ""; }
+            else { distfile = file; }
+            
+            phylipfile = validParameter.validFile(parameters, "phylip", true);
                        if (phylipfile == "not open") { abort = true; }
-                       else if (phylipfile == "not found") { phylipfile = ""; }        
+                       else if (phylipfile == "not found") { phylipfile = ""; }
                        else {  distfile = phylipfile;  format = "phylip";      m->setPhylipFile(phylipfile); }
                        
                        columnfile = validParameter.validFile(parameters, "column", true);
@@ -210,9 +235,14 @@ ClusterSplitCommand::ClusterSplitCommand(string option)  {
                        else {  distfile = columnfile; format = "column";       m->setColumnFile(columnfile); }
                        
                        namefile = validParameter.validFile(parameters, "name", true);
-                       if (namefile == "not open") { abort = true; }   
+                       if (namefile == "not open") { abort = true; namefile = "";}     
                        else if (namefile == "not found") { namefile = "";  }
                        else { m->setNameFile(namefile); }
+            
+            countfile = validParameter.validFile(parameters, "count", true);
+                       if (countfile == "not open") { abort = true; countfile = "";}   
+                       else if (countfile == "not found") { countfile = "";  }
+                       else { m->setCountTableFile(countfile); }
                        
                        fastafile = validParameter.validFile(parameters, "fasta", true);
                        if (fastafile == "not open") { abort = true; }  
@@ -224,7 +254,7 @@ ClusterSplitCommand::ClusterSplitCommand(string option)  {
                        else if (taxFile == "not found") { taxFile = ""; }
                        else {  m->setTaxonomyFile(taxFile); if (splitmethod != "fasta") { splitmethod = "classify"; } }
                        
-                       if ((phylipfile == "") && (columnfile == "") && (fastafile == "")) { 
+                       if ((phylipfile == "") && (columnfile == "") && (fastafile == "") && (file == "")) {
                                //is there are current file available for either of these?
                                //give priority to column, then phylip, then fasta
                                columnfile = m->getColumnFile(); 
@@ -236,21 +266,27 @@ ClusterSplitCommand::ClusterSplitCommand(string option)  {
                                                fastafile = m->getFastaFile(); 
                                                if (fastafile != "") {  m->mothurOut("Using " + fastafile + " as input file for the fasta parameter."); m->mothurOutEndLine(); }
                                                else { 
-                                                       m->mothurOut("No valid current files. When executing a cluster.split command you must enter a phylip or a column or fastafile."); m->mothurOutEndLine(); 
+                                                       m->mothurOut("No valid current files. When executing a cluster.split command you must enter a file, phylip or a column or fastafile."); m->mothurOutEndLine();
                                                        abort = true; 
                                                }
                                        }
                                }
                        }
-                       else if ((phylipfile != "") && (columnfile != "") && (fastafile != "")) { m->mothurOut("When executing a cluster.split command you must enter ONLY ONE of the following: fasta, phylip or column."); m->mothurOutEndLine(); abort = true; }
-               
+                       else if ((phylipfile != "") && (columnfile != "") && (fastafile != "") && (file != "")) { m->mothurOut("When executing a cluster.split command you must enter ONLY ONE of the following: file, fasta, phylip or column."); m->mothurOutEndLine(); abort = true; }
+            
+            if ((countfile != "") && (namefile != "")) { m->mothurOut("When executing a cluster.split command you must enter ONLY ONE of the following: count or name."); m->mothurOutEndLine(); abort = true; }
+            
                        if (columnfile != "") {
-                               if (namefile == "") { 
+                               if ((namefile == "") && (countfile == "")) { 
                                        namefile = m->getNameFile(); 
                                        if (namefile != "") {  m->mothurOut("Using " + namefile + " as input file for the name parameter."); m->mothurOutEndLine(); }
                                        else { 
-                                               m->mothurOut("You need to provide a namefile if you are going to use the column format."); m->mothurOutEndLine(); 
-                                               abort = true; 
+                                               countfile = m->getCountTableFile();
+                        if (countfile != "") {  m->mothurOut("Using " + countfile + " as input file for the count parameter."); m->mothurOutEndLine(); }
+                        else { 
+                            m->mothurOut("You need to provide a namefile or countfile if you are going to use the column format."); m->mothurOutEndLine(); 
+                            abort = true; 
+                        }      
                                        }       
                                }
                        }
@@ -265,12 +301,16 @@ ClusterSplitCommand::ClusterSplitCommand(string option)  {
                                        }       
                                }
                                
-                               if (namefile == "") { 
+                               if ((namefile == "") && (countfile == "")) { 
                                        namefile = m->getNameFile(); 
                                        if (namefile != "") {  m->mothurOut("Using " + namefile + " as input file for the name parameter."); m->mothurOutEndLine(); }
                                        else { 
-                                               m->mothurOut("You need to provide a namefile if you are if you are using a fasta file to generate the split."); m->mothurOutEndLine(); 
-                                               abort = true; 
+                                               countfile = m->getCountTableFile();
+                        if (countfile != "") {  m->mothurOut("Using " + countfile + " as input file for the count parameter."); m->mothurOutEndLine(); }
+                        else { 
+                            m->mothurOut("You need to provide a namefile or countfile if you are going to use the fasta file to generate the split."); m->mothurOutEndLine(); 
+                            abort = true; 
+                        }      
                                        }       
                                }
                        }
@@ -325,6 +365,9 @@ ClusterSplitCommand::ClusterSplitCommand(string option)  {
 
                        showabund = validParameter.validFile(parameters, "showabund", false);
                        if (showabund == "not found") { showabund = "T"; }
+            
+            temp = validParameter.validFile(parameters, "cluster", false);  if (temp == "not found") { temp = "T"; }
+            runCluster = m->isTrue(temp);
 
                        timing = validParameter.validFile(parameters, "timing", false);
                        if (timing == "not found") { timing = "F"; }
@@ -343,86 +386,104 @@ int ClusterSplitCommand::execute(){
        try {
        
                if (abort == true) { if (calledHelp) { return 0; }  return 2;   }
-               
-               time_t estart;
-               vector<string> listFileNames;
-               set<string> labels;
-               string singletonName = "";
-               double saveCutoff = cutoff;
+        
+        time_t estart;
+        vector<string> listFileNames;
+        vector< map<string, string> > distName;
+        set<string> labels;
+        string singletonName = "";
+        
+        double saveCutoff = cutoff;
 
-               //****************** file prep work ******************************//
-               #ifdef USE_MPI
+        if (file != "") {  deleteFiles = false; estart = time(NULL); singletonName = readFile(distName); }
+        else {
+                         
+            //****************** file prep work ******************************//
+#ifdef USE_MPI
                        int pid;
                        int tag = 2001;
-                       MPI_Status status; 
+                       MPI_Status status;
                        MPI_Comm_size(MPI_COMM_WORLD, &processors); //set processors to the number of mpi processes running
                        MPI_Comm_rank(MPI_COMM_WORLD, &pid); //find out who we are
                        
                        if (pid == 0) { //only process 0 converts and splits
-                       
-               #endif
-               
-               //if user gave a phylip file convert to column file
-               if (format == "phylip") {
-                       estart = time(NULL);
-                       m->mothurOut("Converting to column format..."); m->mothurOutEndLine();
-                       
-                       ReadCluster* convert = new ReadCluster(distfile, cutoff, outputDir, false);
-                       
-                       NameAssignment* nameMap = NULL;
-                       convert->setFormat("phylip");
-                       convert->read(nameMap);
-                       
-                       if (m->control_pressed) {  delete convert;  return 0;  }
-                       
-                       distfile = convert->getOutputFile();
-               
-                       //if no names file given with phylip file, create it
-                       ListVector* listToMakeNameFile =  convert->getListVector();
-                       if (namefile == "") {  //you need to make a namefile for split matrix
-                               ofstream out;
-                               namefile = phylipfile + ".names";
-                               m->openOutputFile(namefile, out);
-                               for (int i = 0; i < listToMakeNameFile->getNumBins(); i++) {
-                                       string bin = listToMakeNameFile->get(i);
-                                       out << bin << '\t' << bin << endl;
-                               }
-                               out.close();
-                       }
-                       delete listToMakeNameFile;
-                       delete convert;
-                       
-                       m->mothurOut("It took " + toString(time(NULL) - estart) + " seconds to convert the distance file."); m->mothurOutEndLine();
-               }
-               if (m->control_pressed) { return 0; }
-               
-               estart = time(NULL);
-               m->mothurOut("Splitting the file..."); m->mothurOutEndLine();
-               
-               //split matrix into non-overlapping groups
-               SplitMatrix* split;
-               if (splitmethod == "distance")                  {       split = new SplitMatrix(distfile, namefile, taxFile, cutoff, splitmethod, large);                                                       }
-               else if (splitmethod == "classify")             {       split = new SplitMatrix(distfile, namefile, taxFile, taxLevelCutoff, splitmethod, large);                                       }
-               else if (splitmethod == "fasta")                {       split = new SplitMatrix(fastafile, namefile, taxFile, taxLevelCutoff, cutoff, splitmethod, processors, classic, outputDir);     }
-               else { m->mothurOut("Not a valid splitting method.  Valid splitting algorithms are distance, classify or fasta."); m->mothurOutEndLine(); return 0;             }
-               
-               split->split();
-               
-               if (m->control_pressed) { delete split; return 0; }
-               
-               singletonName = split->getSingletonNames();
-               vector< map<string, string> > distName = split->getDistanceFiles();  //returns map of distance files -> namefile sorted by distance file size
-               delete split;
-               
-               //output a merged distance file
-               if (splitmethod == "fasta")             { createMergedDistanceFile(distName); }
-                       
+                
+#endif
+                
+                //if user gave a phylip file convert to column file
+                if (format == "phylip") {
+                    estart = time(NULL);
+                    m->mothurOut("Converting to column format..."); m->mothurOutEndLine();
+                    
+                    ReadCluster* convert = new ReadCluster(distfile, cutoff, outputDir, false);
+                    
+                    NameAssignment* nameMap = NULL;
+                    convert->setFormat("phylip");
+                    convert->read(nameMap);
+                    
+                    if (m->control_pressed) {  delete convert;  return 0;  }
+                    
+                    distfile = convert->getOutputFile();
+                    
+                    //if no names file given with phylip file, create it
+                    ListVector* listToMakeNameFile =  convert->getListVector();
+                    if ((namefile == "") && (countfile == "")) {  //you need to make a namefile for split matrix
+                        ofstream out;
+                        namefile = phylipfile + ".names";
+                        m->openOutputFile(namefile, out);
+                        for (int i = 0; i < listToMakeNameFile->getNumBins(); i++) {
+                            string bin = listToMakeNameFile->get(i);
+                            out << bin << '\t' << bin << endl;
+                        }
+                        out.close();
+                    }
+                    delete listToMakeNameFile;
+                    delete convert;
+                    
+                    m->mothurOut("It took " + toString(time(NULL) - estart) + " seconds to convert the distance file."); m->mothurOutEndLine();
+                }
+                if (m->control_pressed) { return 0; }
+                
+                estart = time(NULL);
+                m->mothurOut("Splitting the file..."); m->mothurOutEndLine();
+                
+                //split matrix into non-overlapping groups
+                SplitMatrix* split;
+                if (splitmethod == "distance")                 {       split = new SplitMatrix(distfile, namefile, countfile, taxFile, cutoff, splitmethod, large);                                                    }
+                else if (splitmethod == "classify")            {       split = new SplitMatrix(distfile, namefile, countfile, taxFile, taxLevelCutoff, splitmethod, large);                                    }
+                else if (splitmethod == "fasta")               {       split = new SplitMatrix(fastafile, namefile, countfile, taxFile, taxLevelCutoff, cutoff, splitmethod, processors, classic, outputDir);  }
+                else { m->mothurOut("Not a valid splitting method.  Valid splitting algorithms are distance, classify or fasta."); m->mothurOutEndLine(); return 0;            }
+                
+                split->split();
+                
+                if (m->control_pressed) { delete split; return 0; }
+                
+                singletonName = split->getSingletonNames();
+                distName = split->getDistanceFiles();  //returns map of distance files -> namefile sorted by distance file size
+                delete split;
+                
+                if (m->debug) { m->mothurOut("[DEBUG]: distName.size() = " + toString(distName.size()) + ".\n"); }
+                
+                //output a merged distance file
+                //if (splitmethod == "fasta")          { createMergedDistanceFile(distName); }
                                
-               if (m->control_pressed) { return 0; }
-               
-               m->mothurOut("It took " + toString(time(NULL) - estart) + " seconds to split the distance file."); m->mothurOutEndLine();
-               estart = time(NULL);
-               
+                if (m->control_pressed) { return 0; }
+                
+                m->mothurOut("It took " + toString(time(NULL) - estart) + " seconds to split the distance file."); m->mothurOutEndLine();
+                estart = time(NULL);
+                
+                if (!runCluster) { 
+                    printFile(singletonName, distName);
+                    
+                    m->mothurOutEndLine();
+                    m->mothurOut("Output File Names: "); m->mothurOutEndLine();
+                    for (int i = 0; i < distName.size(); i++) {        m->mothurOut(distName[i].begin()->first); m->mothurOutEndLine(); m->mothurOut(distName[i].begin()->second); m->mothurOutEndLine();      }
+                    m->mothurOutEndLine();
+                    return 0;
+                    
+                }
+                deleteFiles = true;
+            }
                //****************** break up files between processes and cluster each file set ******************************//
        #ifdef USE_MPI
                        ////you are process 0 from above////
@@ -615,6 +676,9 @@ int ClusterSplitCommand::execute(){
                mergeLists(listFileNames, labelBins, listSingle);
 
                if (m->control_pressed) { for (int i = 0; i < outputNames.size(); i++) { m->mothurRemove(outputNames[i]); } return 0; }
+        
+        //delete after all are complete incase a crash happens
+        if (!deleteFiles) { for (int i = 0; i < distName.size(); i++) {        m->mothurRemove(distName[i].begin()->first); m->mothurRemove(distName[i].begin()->second);      } }
                
                m->mothurOut("It took " + toString(time(NULL) - estart) + " seconds to merge."); m->mothurOutEndLine();
                
@@ -666,15 +730,21 @@ map<float, int> ClusterSplitCommand::completeListFile(vector<string> listNames,
                
                //read in singletons
                if (singleton != "none") {
-                       ifstream in;
-                       m->openInputFile(singleton, in);
+            
+            ifstream in;
+            m->openInputFile(singleton, in);
                                
                        string firstCol, secondCol;
                        listSingle = new ListVector();
+            
+            if (countfile != "") { m->getline(in); m->gobble(in); }
+            
                        while (!in.eof()) {
-                               in >> firstCol >> secondCol; m->gobble(in);
-                               listSingle->push_back(secondCol);
+                               in >> firstCol >> secondCol; m->getline(in); m->gobble(in);
+                               if (countfile == "") { listSingle->push_back(secondCol); }
+                else { listSingle->push_back(firstCol); }
                        }
+            
                        in.close();
                        m->mothurRemove(singleton);
                        
@@ -773,18 +843,28 @@ int ClusterSplitCommand::mergeLists(vector<string> listNames, map<float, int> us
                if (outputDir == "") { outputDir += m->hasPath(distfile); }
                fileroot = outputDir + m->getRootName(m->getSimpleName(distfile));
                
-        string sabundFileName = fileroot+ tag + "." + getOutputFileNameTag("sabund");
-        string rabundFileName = fileroot+ tag + "." + getOutputFileNameTag("rabund");
-        string listFileName = fileroot+ tag + "." + getOutputFileNameTag("list");
+        map<string, string> variables; 
+        variables["[filename]"] = fileroot;
+        variables["[clustertag]"] = tag;
+        string sabundFileName = getOutputFileName("sabund", variables);
+        string rabundFileName = getOutputFileName("rabund", variables);
+        if (countfile != "") { variables["[tag2]"] = "unique_list"; }
+        string listFileName = getOutputFileName("list", variables);
         
-               m->openOutputFile(sabundFileName,       outSabund);
-               m->openOutputFile(rabundFileName,       outRabund);
+        if (countfile == "") {
+            m->openOutputFile(sabundFileName,  outSabund);
+            m->openOutputFile(rabundFileName,  outRabund);
+            outputNames.push_back(sabundFileName); outputTypes["sabund"].push_back(sabundFileName);
+            outputNames.push_back(rabundFileName); outputTypes["rabund"].push_back(rabundFileName);
+            
+        }
                m->openOutputFile(listFileName, outList);
+        outputNames.push_back(listFileName); outputTypes["list"].push_back(listFileName);
                
-               outputNames.push_back(sabundFileName); outputTypes["sabund"].push_back(sabundFileName);
-               outputNames.push_back(rabundFileName); outputTypes["rabund"].push_back(rabundFileName);
-               outputNames.push_back(listFileName); outputTypes["list"].push_back(listFileName);               
                map<float, int>::iterator itLabel;
+        
+        //clears out junk for autocompleting of list files above.  Perhaps there is a beter way to handle this from within the data structure?
+        m->printedListHeaders = false;
 
                //for each label needed
                for(itLabel = userLabels.begin(); itLabel != userLabels.end(); itLabel++) {
@@ -793,23 +873,30 @@ int ClusterSplitCommand::mergeLists(vector<string> listNames, map<float, int> us
                        if (itLabel->first == -1) { thisLabel = "unique"; }
                        else { thisLabel = toString(itLabel->first,  length-1);  } 
                        
-                       outList << thisLabel << '\t' << itLabel->second << '\t';
-
-                       RAbundVector* rabund = new RAbundVector();
-                       rabund->setLabel(thisLabel);
+                       //outList << thisLabel << '\t' << itLabel->second << '\t';
+            
+            RAbundVector* rabund = NULL;
+            ListVector completeList;
+            completeList.setLabel(thisLabel);
+            
+            if (countfile == "") {
+                rabund = new RAbundVector();
+                rabund->setLabel(thisLabel);
+            }
 
                        //add in singletons
                        if (listSingle != NULL) {
                                for (int j = 0; j < listSingle->getNumBins(); j++) {
-                                       outList << listSingle->get(j) << '\t';
-                                       rabund->push_back(m->getNumNames(listSingle->get(j)));
+                                       //outList << listSingle->get(j) << '\t';
+                    completeList.push_back(listSingle->get(j));
+                                       if (countfile == "") { rabund->push_back(m->getNumNames(listSingle->get(j))); }
                                }
                        }
                        
                        //get the list info from each file
                        for (int k = 0; k < listNames.size(); k++) {
        
-                               if (m->control_pressed) {  if (listSingle != NULL) { delete listSingle;   } for (int i = 0; i < listNames.size(); i++) { m->mothurRemove(listNames[i]);  } delete rabund; return 0; }
+                               if (m->control_pressed) {  if (listSingle != NULL) { delete listSingle;   } for (int i = 0; i < listNames.size(); i++) { m->mothurRemove(listNames[i]);  } if (rabund != NULL) { delete rabund; } return 0; }
                                
                                InputData* input = new InputData(listNames[k], "list");
                                ListVector* list = input->getListVector(thisLabel);
@@ -818,27 +905,33 @@ int ClusterSplitCommand::mergeLists(vector<string> listNames, map<float, int> us
                                if (list == NULL) { m->mothurOut("Error merging listvectors in file " + listNames[k]); m->mothurOutEndLine();  }        
                                else {          
                                        for (int j = 0; j < list->getNumBins(); j++) {
-                                               outList << list->get(j) << '\t';
-                                               rabund->push_back(m->getNumNames(list->get(j)));
+                                               //outList << list->get(j) << '\t';
+                        completeList.push_back(list->get(j));
+                                               if (countfile == "") { rabund->push_back(m->getNumNames(list->get(j))); }
                                        }
                                        delete list;
                                }
                                delete input;
                        }
                        
-                       SAbundVector sabund = rabund->getSAbundVector();
-                       
-                       sabund.print(outSabund);
-                       rabund->print(outRabund);
-                       outList << endl;
+            if (countfile == "") {
+                SAbundVector sabund = rabund->getSAbundVector();
+                sabund.print(outSabund);
+                rabund->print(outRabund);
+            }
+                       //outList << endl;
+            if (!m->printedListHeaders) { 
+                m->listBinLabelsInFile.clear(); completeList.printHeaders(outList); }
+            completeList.print(outList);
                        
-                       delete rabund;
+                       if (rabund != NULL) { delete rabund; }
                }
                
                outList.close();
-               outRabund.close();
-               outSabund.close();
-               
+        if (countfile == "") {
+            outRabund.close();
+            outSabund.close();
+               }
                if (listSingle != NULL) { delete listSingle;  }
                
                for (int i = 0; i < listNames.size(); i++) {  m->mothurRemove(listNames[i]);  }
@@ -891,7 +984,7 @@ vector<string>  ClusterSplitCommand::createProcesses(vector< map<string, string>
             if ((processToAssign-1) == 1) { m->mothurOut(distName[i].begin()->first + "\n"); }
         }
         
-        //not lets reverse the order of ever other process, so we balance big files running with little ones
+        //now lets reverse the order of ever other process, so we balance big files running with little ones
         for (int i = 0; i < processors; i++) {
             //cout << i << endl;
             int remainder = ((i+1) % processors);
@@ -906,7 +999,7 @@ vector<string>  ClusterSplitCommand::createProcesses(vector< map<string, string>
                
                //loop through and create all the processes you want
                while (process != processors) {
-                       int pid = fork();
+                       pid_t pid = fork();
                        
                        if (pid > 0) {
                                processIDS.push_back(pid);  //create map from line number to pid so you can append files in correct order later
@@ -916,7 +1009,7 @@ vector<string>  ClusterSplitCommand::createProcesses(vector< map<string, string>
                                vector<string> listFileNames = cluster(dividedNames[process], labels);
                                
                                //write out names to file
-                               string filename = toString(getpid()) + ".temp";
+                               string filename = m->mothurGetpid(process) + ".temp";
                                ofstream out;
                                m->openOutputFile(filename, out);
                                out << tag << endl;
@@ -925,7 +1018,7 @@ vector<string>  ClusterSplitCommand::createProcesses(vector< map<string, string>
                                
                                //print out labels
                                ofstream outLabels;
-                               filename = toString(getpid()) + ".temp.labels";
+                               filename = m->mothurGetpid(process) + ".temp.labels";
                                m->openOutputFile(filename, outLabels);
                                
                                outLabels << cutoff << endl;
@@ -993,7 +1086,7 @@ vector<string>  ClusterSplitCommand::createProcesses(vector< map<string, string>
                //Above fork() will clone, so memory is separate, but that's not the case with windows, 
                //Taking advantage of shared memory to allow both threads to add labels.
                //////////////////////////////////////////////////////////////////////////////////////////////////////
-               
+               /*
                vector<clusterData*> pDataArray; 
                DWORD   dwThreadIdArray[processors-1];
                HANDLE  hThreadArray[processors-1]; 
@@ -1031,7 +1124,7 @@ vector<string>  ClusterSplitCommand::createProcesses(vector< map<string, string>
                        CloseHandle(hThreadArray[i]);
                        delete pDataArray[i];
                }
-
+*/
        #endif          
         
         return listFiles;
@@ -1101,16 +1194,25 @@ string ClusterSplitCommand::clusterClassicFile(string thisDistFile, string thisN
 
         m->mothurOutEndLine(); m->mothurOut("Reading " + thisDistFile); m->mothurOutEndLine();
         
-        NameAssignment* nameMap = new NameAssignment(thisNamefile);
-        nameMap->readMap();
-                               
-               //reads phylip file storing data in 2D vector, also fills list and rabund
+        //reads phylip file storing data in 2D vector, also fills list and rabund
         bool sim = false;
                ClusterClassic* cluster = new ClusterClassic(cutoff, method, sim);
-               cluster->readPhylipFile(thisDistFile, nameMap);
-               tag = cluster->getTag();
         
-               if (m->control_pressed) { delete cluster; return 0; }
+        NameAssignment* nameMap = NULL;
+        CountTable* ct = NULL;
+        if(namefile != ""){    
+                       nameMap = new NameAssignment(thisNamefile);
+                       nameMap->readMap();
+            cluster->readPhylipFile(thisDistFile, nameMap);
+               }else if (countfile != "") {
+            ct = new CountTable();
+            ct->readTable(thisNamefile, false, false);
+            cluster->readPhylipFile(thisDistFile, ct);
+        }
+        tag = cluster->getTag();
+        
+               if (m->control_pressed) { if(namefile != ""){   delete nameMap; }
+            else { delete ct; } delete cluster; return 0; }
                
                list = cluster->getListVector();
                rabund = cluster->getRAbundVector();
@@ -1136,7 +1238,8 @@ string ClusterSplitCommand::clusterClassicFile(string thisDistFile, string thisN
         m->mothurOutEndLine(); m->mothurOut("Clustering " + thisDistFile); m->mothurOutEndLine();
         
                while ((cluster->getSmallDist() < cutoff) && (cluster->getNSeqs() > 1)){
-                       if (m->control_pressed) { delete cluster; delete list; delete rabund; listFile.close();  return listFileName;  }
+                       if (m->control_pressed) { delete cluster; delete list; delete rabund; listFile.close();  if(namefile != ""){    delete nameMap; }
+                else { delete ct; } return listFileName;  }
             
                        cluster->update(cutoff);
             
@@ -1179,9 +1282,14 @@ string ClusterSplitCommand::clusterClassicFile(string thisDistFile, string thisN
         
                listFile.close();
                
-               delete cluster; delete nameMap; delete list; delete rabund;
-
+               delete cluster;  delete list; delete rabund;
+        if(namefile != ""){    delete nameMap; }
+        else { delete ct; }
         
+        if (deleteFiles) {
+            m->mothurRemove(thisDistFile);
+            m->mothurRemove(thisNamefile);
+        }
         return listFileName;
         
        }
@@ -1219,18 +1327,30 @@ string ClusterSplitCommand::clusterFile(string thisDistFile, string thisNamefile
         ReadMatrix* read = new ReadColumnMatrix(thisDistFile);         
         read->setCutoff(cutoff);
         
-        NameAssignment* nameMap = new NameAssignment(thisNamefile);
-        nameMap->readMap();
-        read->read(nameMap);
-        
-        if (m->control_pressed) {  delete read; delete nameMap; return listFileName; }
-        
-        list = read->getListVector();
+        NameAssignment* nameMap = NULL;
+        CountTable* ct = NULL;
+               if(namefile != ""){     
+                       nameMap = new NameAssignment(thisNamefile);
+                       nameMap->readMap();
+            read->read(nameMap);
+               }else if (countfile != "") {
+            ct = new CountTable();
+            ct->readTable(thisNamefile, false, false);
+            read->read(ct);
+        }else { read->read(nameMap); }
+               
+               list = read->getListVector();
         oldList = *list;
-        matrix = read->getDMatrix();
+               matrix = read->getDMatrix();
         
+               if(countfile != "") {
+            rabund = new RAbundVector();
+            createRabund(ct, list, rabund); //creates an rabund that includes the counts for the unique list
+            delete ct;
+        }else { rabund = new RAbundVector(list->getRAbundVector()); }
+
         delete read;  read = NULL;
-        delete nameMap; nameMap = NULL;
+        if (namefile != "") { delete nameMap; nameMap = NULL; }
         
         
 #ifdef USE_MPI
@@ -1242,12 +1362,11 @@ string ClusterSplitCommand::clusterFile(string thisDistFile, string thisNamefile
         
         m->mothurOutEndLine(); m->mothurOut("Clustering " + thisDistFile); m->mothurOutEndLine();
                
-        rabund = new RAbundVector(list->getRAbundVector());
-        
         //create cluster
-        if (method == "furthest")      {       cluster = new CompleteLinkage(rabund, list, matrix, cutoff, method); }
-        else if(method == "nearest"){  cluster = new SingleLinkage(rabund, list, matrix, cutoff, method); }
-        else if(method == "average"){  cluster = new AverageLinkage(rabund, list, matrix, cutoff, method);     }
+        float adjust = -1.0;
+        if (method == "furthest")      {       cluster = new CompleteLinkage(rabund, list, matrix, cutoff, method, adjust); }
+        else if(method == "nearest"){  cluster = new SingleLinkage(rabund, list, matrix, cutoff, method, adjust); }
+        else if(method == "average"){  cluster = new AverageLinkage(rabund, list, matrix, cutoff, method, adjust);     }
         tag = cluster->getTag();
                
         if (outputDir == "") { outputDir += m->hasPath(thisDistFile); }
@@ -1323,8 +1442,10 @@ string ClusterSplitCommand::clusterFile(string thisDistFile, string thisNamefile
             return listFileName;
         }
         
-        m->mothurRemove(thisDistFile);
-        m->mothurRemove(thisNamefile);
+        if (deleteFiles) {
+            m->mothurRemove(thisDistFile);
+            m->mothurRemove(thisNamefile);
+        }
         
         if (saveCutoff != cutoff) { 
             if (hard)  {  saveCutoff = m->ceilDist(saveCutoff, precision);     }
@@ -1357,7 +1478,9 @@ int ClusterSplitCommand::createMergedDistanceFile(vector< map<string, string> >
                
                string thisOutputDir = outputDir;
                if (outputDir == "") { thisOutputDir = m->hasPath(fastafile); }
-               string outputFileName = thisOutputDir + m->getRootName(m->getSimpleName(fastafile)) + getOutputFileNameTag("column");
+        map<string, string> variables; 
+        variables["[filename]"] = thisOutputDir + m->getRootName(m->getSimpleName(fastafile));
+               string outputFileName = getOutputFileName("column", variables);
                m->mothurRemove(outputFileName);
                
                
@@ -1385,3 +1508,87 @@ int ClusterSplitCommand::createMergedDistanceFile(vector< map<string, string> >
        }
 }
 //**********************************************************************************************************************
+int ClusterSplitCommand::createRabund(CountTable*& ct, ListVector*& list, RAbundVector*& rabund){
+    try {
+        rabund->setLabel(list->getLabel());        
+        for(int i = 0; i < list->getNumBins(); i++) { 
+            if (m->control_pressed) { break; }
+            vector<string> binNames;
+            string bin = list->get(i);
+            m->splitAtComma(bin, binNames);
+            int total = 0;
+            for (int j = 0; j < binNames.size(); j++) { total += ct->getNumSeqs(binNames[j]);  }
+            rabund->push_back(total);   
+        }
+        return 0;
+    }
+    catch(exception& e) {
+               m->errorOut(e, "ClusterCommand", "createRabund");
+               exit(1);
+       }
+    
+}
+//**********************************************************************************************************************
+int ClusterSplitCommand::printFile(string singleton, vector< map<string, string> >& distName){
+    try {
+        ofstream out;
+        map<string, string> variables;
+        string thisOutputDir = outputDir;
+               if (outputDir == "") { thisOutputDir = m->hasPath(distfile); }
+        variables["[filename]"] = thisOutputDir + m->getRootName(m->getSimpleName(distfile));
+               string outputFileName = getOutputFileName("file", variables);
+        m->openOutputFile(outputFileName, out);
+        
+        out << singleton << endl;
+        if (namefile != "") { out << "name" << endl; }
+        else if (countfile != "") { out << "count" << endl; }
+        else { out << "unknown" << endl; }
+        
+        for (int i = 0; i < distName.size(); i++) {    out << distName[i].begin()->first << '\t' << distName[i].begin()->second << endl;       }
+        out.close();
+        
+        return 0;
+    }
+    catch(exception& e) {
+               m->errorOut(e, "ClusterCommand", "printFile");
+               exit(1);
+       }
+    
+}
+//**********************************************************************************************************************
+string ClusterSplitCommand::readFile(vector< map<string, string> >& distName){
+    try {
+        string singleton, thiscolumn, thisname, type;
+        
+        ifstream in;
+        m->openInputFile(file, in);
+        
+        in >> singleton; m->gobble(in);
+        in >> type; m->gobble(in);
+        
+        if (type == "name") { namefile = "name"; }
+        else if (type == "count") { countfile = "count"; }
+        else {  m->mothurOut("[ERROR]: unknown file type. Are the files in column 2 of the file name files or count files? Please change unknown to name or count.\n"); m->control_pressed = true; }
+        
+        
+        while(!in.eof()) {
+            if (m->control_pressed) { break; }
+            
+            in >> thiscolumn; m->gobble(in);
+            in >> thisname; m->gobble(in);
+            
+            map<string, string> temp;
+            temp[thiscolumn] = thisname;
+            distName.push_back(temp);
+        }
+        in.close();
+        
+        return singleton;
+    }
+    catch(exception& e) {
+               m->errorOut(e, "ClusterCommand", "readFile");
+               exit(1);
+       }
+    
+}
+//**********************************************************************************************************************