]> git.donarmstrong.com Git - mothur.git/blobdiff - corraxescommand.cpp
fixes while testing 1.33.0
[mothur.git] / corraxescommand.cpp
index a36f95d1ac310638a31f38e3e172e17ba5aafe09..72fa03b75edc196aafcaaa4b6ade6f95d1106d48 100644 (file)
@@ -8,69 +8,93 @@
  */
 
 #include "corraxescommand.h"
+#include "sharedutilities.h"
+#include "linearalgebra.h"
 
 //**********************************************************************************************************************
-vector<string> CorrAxesCommand::getValidParameters(){  
+vector<string> CorrAxesCommand::setParameters(){       
        try {
-               string Array[] =  {"axes","shared","relabund","numaxes","label","groups","method","metadata","outputdir","inputdir"};
-               vector<string> myArray (Array, Array+(sizeof(Array)/sizeof(string)));
+               CommandParameter paxes("axes", "InputTypes", "", "", "none", "none", "none","corraxes",false,true,true); parameters.push_back(paxes);
+               CommandParameter pshared("shared", "InputTypes", "", "", "SharedRelMeta", "SharedRelMeta", "none","",false,false,true); parameters.push_back(pshared);
+               CommandParameter prelabund("relabund", "InputTypes", "", "", "SharedRelMeta", "SharedRelMeta", "none","",false,false,true); parameters.push_back(prelabund);
+               CommandParameter pmetadata("metadata", "InputTypes", "", "", "SharedRelMeta", "SharedRelMeta", "none","",false,false); parameters.push_back(pmetadata);
+               CommandParameter pnumaxes("numaxes", "Number", "", "3", "", "", "","",false,false); parameters.push_back(pnumaxes);
+               CommandParameter plabel("label", "String", "", "", "", "", "","",false,false); parameters.push_back(plabel);
+               CommandParameter pgroups("groups", "String", "", "", "", "", "","",false,false); parameters.push_back(pgroups);
+               CommandParameter pmethod("method", "Multiple", "pearson-spearman-kendall", "pearson", "", "", "","",false,false); parameters.push_back(pmethod);
+               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);          }
                return myArray;
        }
        catch(exception& e) {
-               m->errorOut(e, "CorrAxesCommand", "getValidParameters");
+               m->errorOut(e, "CorrAxesCommand", "setParameters");
                exit(1);
        }
 }
 //**********************************************************************************************************************
-vector<string> CorrAxesCommand::getRequiredParameters(){       
+string CorrAxesCommand::getHelpString(){       
        try {
-               string Array[] =  {"axes"};
-               vector<string> myArray (Array, Array+(sizeof(Array)/sizeof(string)));
-               return myArray;
+               string helpString = "";
+               helpString += "The corr.axes command reads a shared, relabund or metadata file as well as an axes file and calculates the correlation coefficient.\n";
+               helpString += "The corr.axes command parameters are shared, relabund, axes, metadata, groups, method, numaxes and label.  The shared, relabund or metadata and axes parameters are required.  If shared is given the relative abundance is calculated.\n";
+               helpString += "The groups parameter allows you to specify which of the groups you would like included. The group names are separated by dashes.\n";
+               helpString += "The label parameter allows you to select what distance level you would like used, if none is given the first distance is used.\n";
+               helpString += "The method parameter allows you to select what method you would like to use. Options are pearson, spearman and kendall. Default=pearson.\n";
+               helpString += "The numaxes parameter allows you to select the number of axes you would like to use. Default=3.\n";
+               helpString += "The corr.axes command should be in the following format: corr.axes(axes=yourPcoaFile, shared=yourSharedFile, method=yourMethod).\n";
+               helpString += "Example corr.axes(axes=genus.pool.thetayc.genus.lt.pcoa, shared=genus.pool.shared, method=kendall).\n";
+               helpString += "The corr.axes command outputs a .corr.axes file.\n";
+               helpString += "Note: No spaces between parameter labels (i.e. groups), '=' and parameters (i.e.yourGroups).\n";
+               return helpString;
        }
        catch(exception& e) {
-               m->errorOut(e, "CorrAxesCommand", "getRequiredParameters");
+               m->errorOut(e, "CorrAxesCommand", "getHelpString");
                exit(1);
        }
 }
 //**********************************************************************************************************************
-CorrAxesCommand::CorrAxesCommand(){    
-       try {
-               abort = true;
-               //initialize outputTypes
-               vector<string> tempOutNames;
-               outputTypes["corr.axes"] = tempOutNames;
-       }
-       catch(exception& e) {
-               m->errorOut(e, "CorrAxesCommand", "CorrAxesCommand");
-               exit(1);
-       }
+string CorrAxesCommand::getOutputPattern(string type) {
+    try {
+        string pattern = "";
+        
+        if (type == "corraxes") {  pattern = "[filename],[tag],corr.axes"; }
+        else { m->mothurOut("[ERROR]: No definition for type " + type + " output pattern.\n"); m->control_pressed = true;  }
+        
+        return pattern;
+    }
+    catch(exception& e) {
+        m->errorOut(e, "CorrAxesCommand", "getOutputPattern");
+        exit(1);
+    }
 }
 
 //**********************************************************************************************************************
-vector<string> CorrAxesCommand::getRequiredFiles(){    
+CorrAxesCommand::CorrAxesCommand(){    
        try {
-               vector<string> myArray;
-               return myArray;
+               abort = true; calledHelp = true; 
+               setParameters();
+               vector<string> tempOutNames;
+               outputTypes["corraxes"] = tempOutNames;
        }
        catch(exception& e) {
-               m->errorOut(e, "CorrAxesCommand", "getRequiredFiles");
+               m->errorOut(e, "CorrAxesCommand", "CorrAxesCommand");
                exit(1);
        }
 }
 //**********************************************************************************************************************
 CorrAxesCommand::CorrAxesCommand(string option)  {
        try {
-               abort = false;
-               globaldata = GlobalData::getInstance();
+               abort = false; calledHelp = false;   
                
                //allow user to run help
-               if(option == "help") { help(); abort = true; }
+               if(option == "help") { help(); abort = true; calledHelp = true; }
+               else if(option == "citation") { citation(); abort = true; calledHelp = true;}
                
                else {
-                       //valid paramters for this command
-                       string Array[] =  {"axes","shared","relabund","numaxes","label","groups","method","metadata","outputdir","inputdir"};
-                       vector<string> myArray (Array, Array+(sizeof(Array)/sizeof(string)));
+                       vector<string> myArray = setParameters();
                        
                        OptionParser parser(option);
                        map<string, string> parameters = parser.getParameters();
@@ -84,7 +108,7 @@ CorrAxesCommand::CorrAxesCommand(string option)  {
                        }
                        
                        vector<string> tempOutNames;
-                       outputTypes["corr.axes"] = tempOutNames;
+                       outputTypes["corraxes"] = 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);              
@@ -133,16 +157,17 @@ CorrAxesCommand::CorrAxesCommand(string option)  {
                        sharedfile = validParameter.validFile(parameters, "shared", true);
                        if (sharedfile == "not open") { abort = true; }
                        else if (sharedfile == "not found") { sharedfile = ""; }
-                       else { inputFileName = sharedfile; }
+                       else { inputFileName = sharedfile; m->setSharedFile(sharedfile); }
                        
                        relabundfile = validParameter.validFile(parameters, "relabund", true);
                        if (relabundfile == "not open") { abort = true; }
                        else if (relabundfile == "not found") { relabundfile = ""; }
-                       else { inputFileName = relabundfile; }
+                       else { inputFileName = relabundfile; m->setRelAbundFile(relabundfile); }
                        
                        metadatafile = validParameter.validFile(parameters, "metadata", true);
                        if (metadatafile == "not open") { abort = true; }
                        else if (metadatafile == "not found") { metadatafile = ""; }
+                       else { inputFileName = metadatafile; }
                        
                        groups = validParameter.validFile(parameters, "groups", false);                 
                        if (groups == "not found") { groups = "";  pickedGroups = false;  }
@@ -150,20 +175,36 @@ CorrAxesCommand::CorrAxesCommand(string option)  {
                                pickedGroups = true;
                                m->splitAtDash(groups, Groups); 
                        }                       
-                       globaldata->Groups = Groups;
+                       m->setGroups(Groups);
                        
                        outputDir = validParameter.validFile(parameters, "outputdir", false);           if (outputDir == "not found"){  outputDir = m->hasPath(inputFileName);  }
                        
                        label = validParameter.validFile(parameters, "label", false);                   
                        if (label == "not found") { label = ""; m->mothurOut("You did not provide a label, I will use the first label in your inputfile."); m->mothurOutEndLine(); label=""; }  
                        
-                       if ((relabundfile == "") && (sharedfile == "")) { m->mothurOut("You must provide either a shared or relabund file."); m->mothurOutEndLine(); abort = true;  }
-                       
-                       if ((relabundfile != "") && (sharedfile != "")) { m->mothurOut("You may not use both a shared and relabund file."); m->mothurOutEndLine(); abort = true;  }
+                       if ((relabundfile == "") && (sharedfile == "") && (metadatafile == "")) { 
+                               //is there are current file available for any of these?
+                               //give priority to shared, then relabund
+                               //if there is a current shared file, use it
+                               sharedfile = m->getSharedFile(); 
+                               if (sharedfile != "") { inputFileName = sharedfile; m->mothurOut("Using " + sharedfile + " as input file for the shared parameter."); m->mothurOutEndLine(); }
+                               else { 
+                                       relabundfile = m->getRelAbundFile(); 
+                                       if (relabundfile != "") { inputFileName = relabundfile;  m->mothurOut("Using " + relabundfile + " as input file for the relabund parameter."); m->mothurOutEndLine(); }
+                                       else { 
+                                               m->mothurOut("You must provide either a shared, relabund, or metadata file."); m->mothurOutEndLine(); abort = true; 
+                                       }
+                               }
+                       }       
                        
+                       if (metadatafile != "") {
+                               if ((relabundfile != "") || (sharedfile != "")) { m->mothurOut("You may only use one of the following : shared, relabund or metadata file."); m->mothurOutEndLine(); abort = true;  }
+                       }else {
+                               if ((relabundfile != "") && (sharedfile != "")) { m->mothurOut("You may only use one of the following : shared, relabund or metadata file."); m->mothurOutEndLine(); abort = true;  }
+                       }
                        string temp;
                        temp = validParameter.validFile(parameters, "numaxes", false);          if (temp == "not found"){       temp = "3";                             }
-                       convert(temp, numaxes); 
+                       m->mothurConvert(temp, numaxes); 
                        
                        method = validParameter.validFile(parameters, "method", false);         if (method == "not found"){     method = "pearson";             }
                        
@@ -178,46 +219,38 @@ CorrAxesCommand::CorrAxesCommand(string option)  {
 }
 //**********************************************************************************************************************
 
-void CorrAxesCommand::help(){
-       try {
-
-       }
-       catch(exception& e) {
-               m->errorOut(e, "CorrAxesCommand", "help");      
-               exit(1);
-       }
-}
-
-//**********************************************************************************************************************
-
-CorrAxesCommand::~CorrAxesCommand(){}
-
-//**********************************************************************************************************************
-
 int CorrAxesCommand::execute(){
        try {
                
-               if (abort == true) { return 0; }
+               if (abort == true) { if (calledHelp) { return 0; }  return 2;   }
                
                /*************************************************************************************/
                // use smart distancing to get right sharedRabund and convert to relabund if needed  //
                /************************************************************************************/
                if (sharedfile != "") {  
-                       getShared(); 
-                       if (m->control_pressed) {  for (int i = 0; i < lookup.size(); i++) {  delete lookup[i];  } return 0; }
-                       if (lookup[0] == NULL) { m->mothurOut("[ERROR] reading shared file."); m->mothurOutEndLine(); return 0; }
+                       InputData* input = new InputData(sharedfile, "sharedfile");
+                       getSharedFloat(input); 
+                       delete input;
+                       
+                       if (m->control_pressed) {  for (int i = 0; i < lookupFloat.size(); i++) {  delete lookupFloat[i];  } return 0; }
+                       if (lookupFloat[0] == NULL) { m->mothurOut("[ERROR] reading relabund file."); m->mothurOutEndLine(); return 0; }
                        
-                       //fills lookupFloat with relative abundance values from lookup
-                       convertToRelabund();
+               }else if (relabundfile != "") { 
+                       InputData* input = new InputData(relabundfile, "relabund");
+                       getSharedFloat(input); 
+                       delete input;
                        
-                       for (int i = 0; i < lookup.size(); i++) {  delete lookup[i];  } 
-               }else { 
-                       getSharedFloat(); 
                        if (m->control_pressed) {  for (int i = 0; i < lookupFloat.size(); i++) {  delete lookupFloat[i];  } return 0; }
                        if (lookupFloat[0] == NULL) { m->mothurOut("[ERROR] reading relabund file."); m->mothurOutEndLine(); return 0; }
                        
+               }else if (metadatafile != "") { 
+                       getMetadata();  //reads metadata file and store in lookupFloat, saves column headings in metadataLabels for later
+                       if (m->control_pressed) {  for (int i = 0; i < lookupFloat.size(); i++) {  delete lookupFloat[i];  } return 0; }
+                       if (lookupFloat[0] == NULL) { m->mothurOut("[ERROR] reading metadata file."); m->mothurOutEndLine(); return 0; }
+                       
                        if (pickedGroups) { eliminateZeroOTUS(lookupFloat); }
-               }
+                       
+               }else { m->mothurOut("[ERROR]: no file given."); m->mothurOutEndLine(); return 0; }
                
                if (m->control_pressed) {  for (int i = 0; i < lookupFloat.size(); i++) {  delete lookupFloat[i];  } return 0; }
                
@@ -248,22 +281,26 @@ int CorrAxesCommand::execute(){
                /*************************************************************************************/
                // calc the r values                                                                                                                            //
                /************************************************************************************/
-               
-               string outputFileName = outputDir + m->getRootName(m->getSimpleName(inputFileName)) + "corr.axes";
-               outputNames.push_back(outputFileName); outputTypes["corr.axes"].push_back(outputFileName);      
+        map<string, string> variables; 
+        variables["[filename]"] = outputDir + m->getRootName(m->getSimpleName(inputFileName));
+        variables["[tag]"] = method;
+               string outputFileName = getOutputFileName("corraxes", variables);
+               outputNames.push_back(outputFileName); outputTypes["corraxes"].push_back(outputFileName);       
                ofstream out;
                m->openOutputFile(outputFileName, out);
                out.setf(ios::fixed, ios::floatfield); out.setf(ios::showpoint);
                
                //output headings
-               out << "OTU\t";
-               for (int i = 0; i < numaxes; i++) { out << "axis" << (i+1) << '\t'; }
-               out << endl;
+               if (metadatafile == "") {  out << "OTU";        }
+               else {  out << "Feature";                                               }
+
+               for (int i = 0; i < numaxes; i++) { out << '\t' << "axis" << (i+1) << "\tp-value"; }
+               out << "\tlength" << endl;
                
                if (method == "pearson")                {  calcPearson(axes, out);      }
                else if (method == "spearman")  {  calcSpearman(axes, out); }
-               //else if (method == "kendall") {  calcKendal(axes, out);       }
-               //else { m->mothurOut("[ERROR]: Invalid method."); m->mothurOutEndLine(); }
+               else if (method == "kendall")   {  calcKendall(axes, out);      }
+               else { m->mothurOut("[ERROR]: Invalid method."); m->mothurOutEndLine(); }
                
                out.close();
                for (int i = 0; i < lookupFloat.size(); i++) {  delete lookupFloat[i];  }
@@ -286,6 +323,8 @@ int CorrAxesCommand::execute(){
 int CorrAxesCommand::calcPearson(map<string, vector<float> >& axes, ofstream& out) {
    try {
           
+       LinearAlgebra linear;
+       
           //find average of each axis - X
           vector<float> averageAxes; averageAxes.resize(numaxes, 0.0);
           for (map<string, vector<float> >::iterator it = axes.begin(); it != axes.end(); it++) {
@@ -300,8 +339,9 @@ int CorrAxesCommand::calcPearson(map<string, vector<float> >& axes, ofstream& ou
           //for each otu
           for (int i = 0; i < lookupFloat[0]->getNumBins(); i++) {
                   
-                  out << i+1 << '\t';
-                  
+                  if (metadatafile == "") {  out << m->currentSharedBinLabels[i];      }
+                  else {  out << metadataLabels[i];            }
+                                  
                   //find the averages this otu - Y
                   float sumOtu = 0.0;
                   for (int j = 0; j < lookupFloat.size(); j++) {
@@ -309,6 +349,8 @@ int CorrAxesCommand::calcPearson(map<string, vector<float> >& axes, ofstream& ou
                   }
                   float Ybar = sumOtu / (float) lookupFloat.size();
                   
+                  vector<float> rValues(averageAxes.size());
+
                   //find r value for each axis
                   for (int k = 0; k < averageAxes.size(); k++) {
                           
@@ -328,11 +370,22 @@ int CorrAxesCommand::calcPearson(map<string, vector<float> >& axes, ofstream& ou
                           double denom = (sqrt(denomTerm1) * sqrt(denomTerm2));
                           
                           r = numerator / denom;
-                          
-                          out << r << '\t'; 
+               
+               if (isnan(r) || isinf(r)) { r = 0.0; }
+               
+                          rValues[k] = r;
+                          out << '\t' << r; 
+               
+               double sig = linear.calcPearsonSig(lookupFloat.size(), r);
+               
+               out << '\t' << sig;
                   }
                   
-                  out << endl;
+                  double sum = 0;
+                  for(int k=0;k<rValues.size();k++){
+                          sum += rValues[k] * rValues[k];
+                  }
+                  out << '\t' << sqrt(sum) << endl;
           }
                   
           return 0;
@@ -346,53 +399,176 @@ int CorrAxesCommand::calcPearson(map<string, vector<float> >& axes, ofstream& ou
 int CorrAxesCommand::calcSpearman(map<string, vector<float> >& axes, ofstream& out) {
        try {
                
-               //find average of each axis - X
-               vector<float> averageAxes; averageAxes.resize(numaxes, 0.0);
+        LinearAlgebra linear;
+        vector<double> sf; 
+        
+               //format data
+               vector< map<float, int> > tableX; tableX.resize(numaxes);
+               map<float, int>::iterator itTable;
+               vector< vector<spearmanRank> > scores; scores.resize(numaxes);
                for (map<string, vector<float> >::iterator it = axes.begin(); it != axes.end(); it++) {
                        vector<float> temp = it->second;
                        for (int i = 0; i < temp.size(); i++) {
-                               averageAxes[i] += temp[i];  
+                               spearmanRank member(it->first, temp[i]);
+                               scores[i].push_back(member);  
+                               
+                               //count number of repeats
+                               itTable = tableX[i].find(temp[i]);
+                               if (itTable == tableX[i].end()) { 
+                                       tableX[i][temp[i]] = 1;
+                               }else {
+                                       tableX[i][temp[i]]++;
+                               }
+                       }
+               }
+               
+               //calc LX
+               //for each axis
+               vector<double> Lx; Lx.resize(numaxes, 0.0);
+               for (int i = 0; i < numaxes; i++) {
+                       for (itTable = tableX[i].begin(); itTable != tableX[i].end(); itTable++) {
+                               double tx = (double) itTable->second;
+                               Lx[i] += ((pow(tx, 3.0) - tx) / 12.0);
                        }
                }
                
-               for (int i = 0; i < averageAxes.size(); i++) {  averageAxes[i] = averageAxes[i] / (float) axes.size(); }
+               //sort each axis
+               for (int i = 0; i < numaxes; i++) {  sort(scores[i].begin(), scores[i].end(), compareSpearman); }
                
+               //find ranks of xi in each axis
+               map<string, vector<float> > rankAxes;
+               for (int i = 0; i < numaxes; i++) {
+                       
+                       vector<spearmanRank> ties;
+                       int rankTotal = 0;
+            double sfTemp = 0.0;
+                       for (int j = 0; j < scores[i].size(); j++) {
+                               rankTotal += (j+1);
+                               ties.push_back(scores[i][j]);
+                               
+                               if (j != (scores[i].size()-1)) { // you are not the last so you can look ahead
+                                       if (scores[i][j].score != scores[i][j+1].score) { // you are done with ties, rank them and continue
+
+                                               for (int k = 0; k < ties.size(); k++) {
+                                                       float thisrank = rankTotal / (float) ties.size();
+                                                       rankAxes[ties[k].name].push_back(thisrank);
+                                               }
+                        int t = ties.size();
+                        sfTemp += (t*t*t-t);
+                                               ties.clear();
+                                               rankTotal = 0;
+                                       }
+                               }else { // you are the last one
+                                       
+                                       for (int k = 0; k < ties.size(); k++) {
+                                               float thisrank = rankTotal / (float) ties.size();
+                                               rankAxes[ties[k].name].push_back(thisrank);
+                                               
+                                       }
+                               }
+                       }
+            sf.push_back(sfTemp);
+               }
+               
+                               
                //for each otu
                for (int i = 0; i < lookupFloat[0]->getNumBins(); i++) {
                        
-                       out << i+1 << '\t';
+                       if (metadatafile == "") {  out << m->currentSharedBinLabels[i]; }
+                       else {  out << metadataLabels[i];               }
                        
-                       //find the averages this otu - Y
-                       float sumOtu = 0.0;
+                       //find the ranks of this otu - Y
+                       vector<spearmanRank> otuScores;
+                       map<float, int> tableY;
                        for (int j = 0; j < lookupFloat.size(); j++) {
-                               sumOtu += lookupFloat[j]->getAbundance(i);
+                               spearmanRank member(lookupFloat[j]->getGroup(), lookupFloat[j]->getAbundance(i));
+                               otuScores.push_back(member);
+                               
+                               itTable = tableY.find(member.score);
+                               if (itTable == tableY.end()) { 
+                                       tableY[member.score] = 1;
+                               }else {
+                                       tableY[member.score]++;
+                               }
+                               
+                       }
+                       
+                       //calc Ly
+                       double Ly = 0.0;
+                       for (itTable = tableY.begin(); itTable != tableY.end(); itTable++) {
+                               double ty = (double) itTable->second;
+                               Ly += ((pow(ty, 3.0) - ty) / 12.0);
                        }
-                       float Ybar = sumOtu / (float) lookupFloat.size();
                        
-                       //find r value for each axis
-                       for (int k = 0; k < averageAxes.size(); k++) {
+                       sort(otuScores.begin(), otuScores.end(), compareSpearman);
+                       
+            double sg = 0.0;
+                       map<string, float> rankOtus;
+                       vector<spearmanRank> ties;
+                       int rankTotal = 0;
+                       for (int j = 0; j < otuScores.size(); j++) {
+                               rankTotal += (j+1);
+                               ties.push_back(otuScores[j]);
+                               
+                               if (j != (otuScores.size()-1)) { // you are not the last so you can look ahead
+                                       if (otuScores[j].score != otuScores[j+1].score) { // you are done with ties, rank them and continue
+                                               
+                                               for (int k = 0; k < ties.size(); k++) {
+                                                       float thisrank = rankTotal / (float) ties.size();
+                                                       rankOtus[ties[k].name] = thisrank;
+                                               }
+                        int t = ties.size();
+                        sg += (t*t*t-t);
+                                               ties.clear();
+                                               rankTotal = 0;
+                                       }
+                               }else { // you are the last one
+                                       
+                                       for (int k = 0; k < ties.size(); k++) {
+                                               float thisrank = rankTotal / (float) ties.size();
+                                               rankOtus[ties[k].name] = thisrank;
+                                       }
+                               }
+                       }
+                       vector<double> pValues(numaxes);        
+
+                       //calc spearman ranks for each axis for this otu
+                       for (int j = 0; j < numaxes; j++) {
                                
-                               double r = 0.0;
-                               double numerator = 0.0;
-                               double denomTerm1 = 0.0;
-                               double denomTerm2 = 0.0;
-                               for (int j = 0; j < lookupFloat.size(); j++) {
-                                       float Yi = lookupFloat[j]->getAbundance(i);
-                                       float Xi = axes[lookupFloat[j]->getGroup()][k];
+                               double di = 0.0;
+                               for (int k = 0; k < lookupFloat.size(); k++) {
+                                       
+                                       float xi = rankAxes[lookupFloat[k]->getGroup()][j];
+                                       float yi = rankOtus[lookupFloat[k]->getGroup()];
                                        
-                                       numerator += ((Xi - averageAxes[k]) * (Yi - Ybar));
-                                       denomTerm1 += ((Xi - averageAxes[k]) * (Xi - averageAxes[k]));
-                                       denomTerm2 += ((Yi - Ybar) * (Yi - Ybar));
+                                       di += ((xi - yi) * (xi - yi));
                                }
                                
-                               double denom = (sqrt(denomTerm1 * denomTerm2));
+                               double p = 0.0;
+                               
+                               double n = (double) lookupFloat.size();
                                
-                               r = numerator / denom;
+                               double SX2 = ((pow(n, 3.0) - n) / 12.0) - Lx[j];
+                               double SY2 = ((pow(n, 3.0) - n) / 12.0) - Ly;
                                
-                               out << r << '\t'; 
+                               p = (SX2 + SY2 - di) / (2.0 * sqrt((SX2*SY2)));
+                               
+                if (isnan(p) || isinf(p)) { p = 0.0; }
+                
+                               out  << '\t' << p;
+                               
+                               pValues[j] = p;
+                
+                double sig = linear.calcSpearmanSig(n, sf[j], sg, di);            
+                out  << '\t' << sig;
+                
                        }
-                       
-                       out << endl;
+
+                       double sum = 0;
+                       for(int k=0;k<numaxes;k++){
+                               sum += pValues[k] * pValues[k];
+                       }
+                       out << '\t' << sqrt(sum) << endl;
                }
                
                return 0;
@@ -403,89 +579,155 @@ int CorrAxesCommand::calcSpearman(map<string, vector<float> >& axes, ofstream& o
        }
 }
 //**********************************************************************************************************************
-int CorrAxesCommand::getShared(){
+int CorrAxesCommand::calcKendall(map<string, vector<float> >& axes, ofstream& out) {
        try {
-               InputData* input = new InputData(sharedfile, "sharedfile");
-               lookup = input->getSharedRAbundVectors();
-               string lastLabel = lookup[0]->getLabel();
                
-               if (label == "") { label = lastLabel; delete input; return 0; }
+        LinearAlgebra linear;
+        
+               //format data
+               vector< vector<spearmanRank> > scores; scores.resize(numaxes);
+               for (map<string, vector<float> >::iterator it = axes.begin(); it != axes.end(); it++) {
+                       vector<float> temp = it->second;
+                       for (int i = 0; i < temp.size(); i++) {
+                               spearmanRank member(it->first, temp[i]);
+                               scores[i].push_back(member);  
+                       }
+               }
                
-               //if the users enters label "0.06" and there is no "0.06" in their file use the next lowest label.
-               set<string> labels; labels.insert(label);
-               set<string> processedLabels;
-               set<string> userLabels = labels;
+               //sort each axis
+               for (int i = 0; i < numaxes; i++) {  sort(scores[i].begin(), scores[i].end(), compareSpearman); }
                
-               //as long as you are not at the end of the file or done wih the lines you want
-               while((lookup[0] != NULL) && (userLabels.size() != 0)) {
-                       if (m->control_pressed) {  delete input; return 0;  }
+               //convert scores to ranks of xi in each axis
+               for (int i = 0; i < numaxes; i++) {
                        
-                       if(labels.count(lookup[0]->getLabel()) == 1){
-                               processedLabels.insert(lookup[0]->getLabel());
-                               userLabels.erase(lookup[0]->getLabel());
-                               break;
+                       vector<spearmanRank*> ties;
+                       int rankTotal = 0;
+                       for (int j = 0; j < scores[i].size(); j++) {
+                               rankTotal += (j+1);
+                               ties.push_back(&(scores[i][j]));
+                               
+                               if (j != scores[i].size()-1) { // you are not the last so you can look ahead
+                                       if (scores[i][j].score != scores[i][j+1].score) { // you are done with ties, rank them and continue
+                                               for (int k = 0; k < ties.size(); k++) {
+                                                       float thisrank = rankTotal / (float) ties.size();
+                                                       (*ties[k]).score = thisrank;
+                                               }
+                                               ties.clear();
+                                               rankTotal = 0;
+                                       }
+                               }else { // you are the last one
+                                       for (int k = 0; k < ties.size(); k++) {
+                                               float thisrank = rankTotal / (float) ties.size();
+                                               (*ties[k]).score = thisrank;
+                                       }
+                               }
                        }
+               }
+               
+               //for each otu
+               for (int i = 0; i < lookupFloat[0]->getNumBins(); i++) {
+               
+                       if (metadatafile == "") {  out << m->currentSharedBinLabels[i]; }
+                       else {  out << metadataLabels[i];               }
                        
-                       if ((m->anyLabelsToProcess(lookup[0]->getLabel(), userLabels, "") == true) && (processedLabels.count(lastLabel) != 1)) {
-                               string saveLabel = lookup[0]->getLabel();
+                       //find the ranks of this otu - Y
+                       vector<spearmanRank> otuScores;
+                       for (int j = 0; j < lookupFloat.size(); j++) {
+                               spearmanRank member(lookupFloat[j]->getGroup(), lookupFloat[j]->getAbundance(i));
+                               otuScores.push_back(member);
+                       }
+                                               
+                       sort(otuScores.begin(), otuScores.end(), compareSpearman);
+                       
+                       map<string, float> rankOtus;
+                       vector<spearmanRank> ties;
+                       int rankTotal = 0;
+                       for (int j = 0; j < otuScores.size(); j++) {
+                               rankTotal += (j+1);
+                               ties.push_back(otuScores[j]);
                                
-                               for (int i = 0; i < lookup.size(); i++) {  delete lookup[i];  } 
-                               lookup = input->getSharedRAbundVectors(lastLabel);
+                               if (j != otuScores.size()-1) { // you are not the last so you can look ahead
+                                       if (otuScores[j].score != otuScores[j+1].score) { // you are done with ties, rank them and continue
+                                               for (int k = 0; k < ties.size(); k++) {
+                                                       float thisrank = rankTotal / (float) ties.size();
+                                                       rankOtus[ties[k].name] = thisrank;
+                                               }
+                                               ties.clear();
+                                               rankTotal = 0;
+                                       }
+                               }else { // you are the last one
+                                       for (int k = 0; k < ties.size(); k++) {
+                                               float thisrank = rankTotal / (float) ties.size();
+                                               rankOtus[ties[k].name] = thisrank;
+                                       }
+                               }
+                       }
+                       
+                       
+                       vector<double> pValues(numaxes);
+                       
+                       //calc spearman ranks for each axis for this otu
+                       for (int j = 0; j < numaxes; j++) {
+                       
+                               int numCoor = 0;
+                               int numDisCoor = 0;
                                
-                               processedLabels.insert(lookup[0]->getLabel());
-                               userLabels.erase(lookup[0]->getLabel());
+                               vector<spearmanRank> otus; 
+                               vector<spearmanRank> otusTemp;
+                               for (int l = 0; l < scores[j].size(); l++) {   
+                                       spearmanRank member(scores[j][l].name, rankOtus[scores[j][l].name]);
+                                       otus.push_back(member);
+                               }
                                
-                               //restore real lastlabel to save below
-                               lookup[0]->setLabel(saveLabel);
-                               break;
+                               int count = 0;
+                               for (int l = 0; l < scores[j].size(); l++) {
+                                       
+                                       int numWithHigherRank = 0;
+                                       int numWithLowerRank = 0;
+                                       float thisrank = otus[l].score;
+                                       
+                                       for (int u = l+1; u < scores[j].size(); u++) {
+                                               if (otus[u].score > thisrank) { numWithHigherRank++; }
+                                               else if (otus[u].score < thisrank) { numWithLowerRank++; }
+                                               count++;
+                                       }
+                                       
+                                       numCoor += numWithHigherRank;
+                                       numDisCoor += numWithLowerRank;
+                               }
+                               
+                               double p = (numCoor - numDisCoor) / (float) count;
+                 if (isnan(p) || isinf(p)) { p = 0.0; }
+                
+                               out << '\t' << p;
+                               pValues[j] = p;
+                
+                double sig = linear.calcKendallSig(scores[j].size(), p);
+                
+                out << '\t' << sig;
                        }
                        
-                       lastLabel = lookup[0]->getLabel();                      
-                       
-                       //get next line to process
-                       //prevent memory leak
-                       for (int i = 0; i < lookup.size(); i++) {  delete lookup[i];  } 
-                       lookup = input->getSharedRAbundVectors();
-               }
-               
-               
-               if (m->control_pressed) { delete input; return 0;  }
-               
-               //output error messages about any remaining user labels
-               set<string>::iterator it;
-               bool needToRun = false;
-               for (it = userLabels.begin(); it != userLabels.end(); it++) {  
-                       m->mothurOut("Your file does not include the label " + *it); 
-                       if (processedLabels.count(lastLabel) != 1) {
-                               m->mothurOut(". I will use " + lastLabel + "."); m->mothurOutEndLine();
-                               needToRun = true;
-                       }else {
-                               m->mothurOut(". Please refer to " + lastLabel + "."); m->mothurOutEndLine();
+                       double sum = 0;
+                       for(int k=0;k<numaxes;k++){
+                               sum += pValues[k] * pValues[k];
                        }
+                       out << '\t' << sqrt(sum) << endl;
                }
                
-               //run last label if you need to
-               if (needToRun == true)  {
-                       for (int i = 0; i < lookup.size(); i++) {  if (lookup[i] != NULL) {     delete lookup[i];       } } 
-                       lookup = input->getSharedRAbundVectors(lastLabel);
-               }       
-               
-               delete input;
                return 0;
        }
        catch(exception& e) {
-               m->errorOut(e, "CorrAxesCommand", "getShared"); 
+               m->errorOut(e, "CorrAxesCommand", "calcKendall");
                exit(1);
        }
 }
 //**********************************************************************************************************************
-int CorrAxesCommand::getSharedFloat(){
+int CorrAxesCommand::getSharedFloat(InputData* input){
        try {
-               InputData* input = new InputData(relabundfile, "relabund");
                lookupFloat = input->getSharedRAbundFloatVectors();
                string lastLabel = lookupFloat[0]->getLabel();
                
-               if (label == "") { label = lastLabel; delete input; return 0; }
+               if (label == "") { label = lastLabel;  return 0; }
                
                //if the users enters label "0.06" and there is no "0.06" in their file use the next lowest label.
                set<string> labels; labels.insert(label);
@@ -495,7 +737,7 @@ int CorrAxesCommand::getSharedFloat(){
                //as long as you are not at the end of the file or done wih the lines you want
                while((lookupFloat[0] != NULL) && (userLabels.size() != 0)) {
                        
-                       if (m->control_pressed) {  delete input; return 0;  }
+                       if (m->control_pressed) {  return 0;  }
                        
                        if(labels.count(lookupFloat[0]->getLabel()) == 1){
                                processedLabels.insert(lookupFloat[0]->getLabel());
@@ -526,7 +768,7 @@ int CorrAxesCommand::getSharedFloat(){
                }
                
                
-               if (m->control_pressed) { delete input; return 0;  }
+               if (m->control_pressed) { return 0;  }
                
                //output error messages about any remaining user labels
                set<string>::iterator it;
@@ -547,7 +789,6 @@ int CorrAxesCommand::getSharedFloat(){
                        lookupFloat = input->getSharedRAbundFloatVectors(lastLabel);
                }       
                
-               delete input;
                return 0;
        }
        catch(exception& e) {
@@ -555,43 +796,6 @@ int CorrAxesCommand::getSharedFloat(){
                exit(1);
        }
 }
-/*****************************************************************/
-int CorrAxesCommand::convertToRelabund(){
-       try {
-               
-               vector<SharedRAbundFloatVector*> newLookup;
-               for (int i = 0; i < lookup.size(); i++) {
-                       SharedRAbundFloatVector* temp = new SharedRAbundFloatVector();
-                       temp->setLabel(lookup[i]->getLabel());
-                       temp->setGroup(lookup[i]->getGroup());
-                       newLookup.push_back(temp);
-               }
-               
-               for (int i = 0; i < lookup.size(); i++) {
-                       
-                       for (int j = 0; j < lookup[i]->getNumBins(); j++) {
-                               
-                               if (m->control_pressed) { return 0; }
-                               
-                               int abund = lookup[i]->getAbundance(j);
-                               
-                               float relabund = abund / (float) lookup[i]->getNumSeqs();
-                               
-                               newLookup[i]->push_back(relabund, lookup[i]->getGroup());
-                       }
-               }
-               
-               if (pickedGroups) { eliminateZeroOTUS(newLookup); }
-               
-               lookupFloat = newLookup;
-               
-               return 0;
-       }
-       catch(exception& e) {
-               m->errorOut(e, "CorrAxesCommand", "convertToRelabund"); 
-               exit(1);
-       }
-}
 //**********************************************************************************************************************
 int CorrAxesCommand::eliminateZeroOTUS(vector<SharedRAbundFloatVector*>& thislookup) {
        try {
@@ -605,6 +809,8 @@ int CorrAxesCommand::eliminateZeroOTUS(vector<SharedRAbundFloatVector*>& thisloo
                }
                
                //for each bin
+               vector<string> newBinLabels;
+               string snumBins = toString(thislookup[0]->getNumBins());
                for (int i = 0; i < thislookup[0]->getNumBins(); i++) {
                        if (m->control_pressed) { for (int j = 0; j < newLookup.size(); j++) {  delete newLookup[j];  } return 0; }
                        
@@ -619,12 +825,25 @@ int CorrAxesCommand::eliminateZeroOTUS(vector<SharedRAbundFloatVector*>& thisloo
                                for (int j = 0; j < thislookup.size(); j++) {
                                        newLookup[j]->push_back(thislookup[j]->getAbundance(i), thislookup[j]->getGroup());
                                }
+                               
+                               //if there is a bin label use it otherwise make one
+                               string binLabel = "Otu";
+                               string sbinNumber = toString(i+1);
+                               if (sbinNumber.length() < snumBins.length()) { 
+                                       int diff = snumBins.length() - sbinNumber.length();
+                                       for (int h = 0; h < diff; h++) { binLabel += "0"; }
+                               }
+                               binLabel += sbinNumber; 
+                               if (i < m->currentSharedBinLabels.size()) {  binLabel = m->currentSharedBinLabels[i]; }
+                               
+                               newBinLabels.push_back(binLabel);
                        }
                }
                
                for (int j = 0; j < thislookup.size(); j++) {  delete thislookup[j];  }
                
                thislookup = newLookup;
+               m->currentSharedBinLabels = newBinLabels;
                
                return 0;
                
@@ -655,6 +874,8 @@ map<string, vector<float> > CorrAxesCommand::readAxes(){
                        }else { done = true; }
                }
                
+               if (numaxes > count) { m->mothurOut("You requested " + toString(numaxes) + " axes, but your file only includes " + toString(count) + ". Using " + toString(count) + "."); m->mothurOutEndLine(); numaxes = count; }
+               
                while (!in.eof()) {
                        
                        if (m->control_pressed) { in.close(); return axes; }
@@ -689,7 +910,74 @@ map<string, vector<float> > CorrAxesCommand::readAxes(){
                return axes;
        }
        catch(exception& e) {
-               m->errorOut(e, "CorrAxesCommand", "convertToRelabund"); 
+               m->errorOut(e, "CorrAxesCommand", "readAxes");  
+               exit(1);
+       }
+}
+/*****************************************************************/
+int CorrAxesCommand::getMetadata(){
+       try {
+               vector<string> groupNames;
+               
+               ifstream in;
+               m->openInputFile(metadatafile, in);
+               
+               string headerLine = m->getline(in); m->gobble(in);
+               vector<string> pieces = m->splitWhiteSpace(headerLine);
+               
+               //save names of columns you are reading
+               for (int i = 1; i < pieces.size(); i++) {
+                       metadataLabels.push_back(pieces[i]);
+               }
+               int count = metadataLabels.size();
+                       
+               //read rest of file
+               while (!in.eof()) {
+                       
+                       if (m->control_pressed) { in.close(); return 0; }
+                       
+                       string group = "";
+                       in >> group; m->gobble(in);
+                       groupNames.push_back(group);
+                               
+                       SharedRAbundFloatVector* tempLookup = new SharedRAbundFloatVector();
+                       tempLookup->setGroup(group);
+                       tempLookup->setLabel("1");
+                       
+                       for (int i = 0; i < count; i++) {
+                               float temp = 0.0;
+                               in >> temp; 
+                               tempLookup->push_back(temp, group);
+                       }
+                       
+                       lookupFloat.push_back(tempLookup);
+                       
+                       m->gobble(in);
+               }
+               in.close();
+               
+               //remove any groups the user does not want, and set globaldata->groups with only valid groups
+               SharedUtil* util;
+               util = new SharedUtil();
+               Groups = m->getGroups();
+               util->setGroups(Groups, groupNames);
+               m->setGroups(Groups);
+               
+               for (int i = 0; i < lookupFloat.size(); i++) {
+                       //if this sharedrabund is not from a group the user wants then delete it.
+                       if (util->isValidGroup(lookupFloat[i]->getGroup(), m->getGroups()) == false) { 
+                               delete lookupFloat[i]; lookupFloat[i] = NULL;
+                               lookupFloat.erase(lookupFloat.begin()+i); 
+                               i--; 
+                       }
+               }
+               
+               delete util;
+               
+               return 0;
+       }
+       catch(exception& e) {
+               m->errorOut(e, "CorrAxesCommand", "getMetadata");       
                exit(1);
        }
 }