]> git.donarmstrong.com Git - mothur.git/blobdiff - corraxescommand.cpp
added mantel command
[mothur.git] / corraxescommand.cpp
index 9ffc4b6ee1ce5cec5440264ae2b0f35f04e3aa49..4f8dccb167fc8e8e6d08597f11504d4df2b26f24 100644 (file)
 #include "corraxescommand.h"
 #include "sharedutilities.h"
 
-//********************************************************************************************************************
-//sorts highes to lowest
-inline bool compareSpearman(spearmanRank left, spearmanRank right){
-       return (left.score > right.score);      
-} 
 //**********************************************************************************************************************
 vector<string> CorrAxesCommand::getValidParameters(){  
        try {
@@ -42,8 +37,7 @@ vector<string> CorrAxesCommand::getRequiredParameters(){
 //**********************************************************************************************************************
 CorrAxesCommand::CorrAxesCommand(){    
        try {
-               abort = true;
-               //initialize outputTypes
+               abort = true; calledHelp = true; 
                vector<string> tempOutNames;
                outputTypes["corr.axes"] = tempOutNames;
        }
@@ -67,11 +61,11 @@ vector<string> CorrAxesCommand::getRequiredFiles(){
 //**********************************************************************************************************************
 CorrAxesCommand::CorrAxesCommand(string option)  {
        try {
-               abort = false;
+               abort = false; calledHelp = false;   
                globaldata = GlobalData::getInstance();
                
                //allow user to run help
-               if(option == "help") { help(); abort = true; }
+               if(option == "help") { help(); abort = true; calledHelp = true; }
                
                else {
                        //valid paramters for this command
@@ -190,7 +184,7 @@ CorrAxesCommand::CorrAxesCommand(string option)  {
 
 void CorrAxesCommand::help(){
        try {
-               m->mothurOut("The corr.axes command reads a shared or relabund file as well as a pcoa file and calculates the correlation coefficient.\n");
+               m->mothurOut("The corr.axes command reads a shared, relabund or metadata file as well as an axes file and calculates the correlation coefficient.\n");
                m->mothurOut("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");
                m->mothurOut("The groups parameter allows you to specify which of the groups you would like included. The group names are separated by dashes.\n");
                m->mothurOut("The label parameter allows you to select what distance level you would like used, if none is given the first distance is used.\n");
@@ -216,28 +210,27 @@ 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;
                        
-                       //fills lookupFloat with relative abundance values from lookup
-                       convertToRelabund();
-                       
-                       for (int i = 0; i < lookup.size(); i++) {  delete lookup[i];  }
+                       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 (relabundfile != "") { 
-                       getSharedFloat(); 
+                       InputData* input = new InputData(relabundfile, "relabund");
+                       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; }
                        
-                       if (pickedGroups) { eliminateZeroOTUS(lookupFloat); }
-                       
                }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; }
@@ -284,11 +277,11 @@ int CorrAxesCommand::execute(){
                out.setf(ios::fixed, ios::floatfield); out.setf(ios::showpoint);
                
                //output headings
-               if (metadatafile == "") {  out << "OTU\t";      }
-               else {  out << "Feature\t";                                             }
+               if (metadatafile == "") {  out << "OTU";        }
+               else {  out << "Feature";                                               }
 
-               for (int i = 0; i < numaxes; i++) { out << "axis" << (i+1) << '\t'; }
-               out << endl;
+               for (int i = 0; i < numaxes; i++) { out << '\t' << "axis" << (i+1); }
+               out << "\tlength" << endl;
                
                if (method == "pearson")                {  calcPearson(axes, out);      }
                else if (method == "spearman")  {  calcSpearman(axes, out); }
@@ -330,9 +323,9 @@ int CorrAxesCommand::calcPearson(map<string, vector<float> >& axes, ofstream& ou
           //for each otu
           for (int i = 0; i < lookupFloat[0]->getNumBins(); i++) {
                   
-                  if (metadatafile == "") {  out << i+1 << '\t';       }
-                  else {  out << metadataLabels[i] << '\t';            }
-                  
+                  if (metadatafile == "") {  out << i+1;       }
+                  else {  out << metadataLabels[i];            }
+                                  
                   //find the averages this otu - Y
                   float sumOtu = 0.0;
                   for (int j = 0; j < lookupFloat.size(); j++) {
@@ -340,6 +333,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++) {
                           
@@ -359,11 +354,15 @@ int CorrAxesCommand::calcPearson(map<string, vector<float> >& axes, ofstream& ou
                           double denom = (sqrt(denomTerm1) * sqrt(denomTerm2));
                           
                           r = numerator / denom;
-                          
-                          out << r << '\t'
+                          rValues[k] = r;
+                          out << '\t' << r
                   }
                   
-                  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;
@@ -378,12 +377,32 @@ int CorrAxesCommand::calcSpearman(map<string, vector<float> >& axes, ofstream& o
        try {
                
                //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++) {
                                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);
                        }
                }
                
@@ -397,11 +416,12 @@ int CorrAxesCommand::calcSpearman(map<string, vector<float> >& axes, ofstream& o
                        vector<spearmanRank> ties;
                        int rankTotal = 0;
                        for (int j = 0; j < scores[i].size(); j++) {
-                               rankTotal += j;
+                               rankTotal += (j+1);
                                ties.push_back(scores[i][j]);
                                
-                               if (j != scores.size()-1) { // you are not the last so you can look ahead
+                               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);
@@ -410,27 +430,44 @@ int CorrAxesCommand::calcSpearman(map<string, vector<float> >& axes, ofstream& o
                                                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);
+                                               
                                        }
                                }
                        }
                }
                
                                
-               
                //for each otu
                for (int i = 0; i < lookupFloat[0]->getNumBins(); i++) {
                        
-                       if (metadatafile == "") {  out << i+1 << '\t';  }
-                       else {  out << metadataLabels[i] << '\t';               }
+                       if (metadatafile == "") {  out << i+1;  }
+                       else {  out << metadataLabels[i];               }
                        
                        //find the ranks of this otu - Y
                        vector<spearmanRank> otuScores;
+                       map<float, int> tableY;
                        for (int j = 0; j < lookupFloat.size(); j++) {
                                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);
                        }
                        
                        sort(otuScores.begin(), otuScores.end(), compareSpearman);
@@ -439,11 +476,12 @@ int CorrAxesCommand::calcSpearman(map<string, vector<float> >& axes, ofstream& o
                        vector<spearmanRank> ties;
                        int rankTotal = 0;
                        for (int j = 0; j < otuScores.size(); j++) {
-                               rankTotal += j;
+                               rankTotal += (j+1);
                                ties.push_back(otuScores[j]);
                                
-                               if (j != scores.size()-1) { // you are not the last so you can look ahead
+                               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;
@@ -452,13 +490,15 @@ int CorrAxesCommand::calcSpearman(map<string, vector<float> >& axes, ofstream& o
                                                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++) {
                                
@@ -471,14 +511,25 @@ int CorrAxesCommand::calcSpearman(map<string, vector<float> >& axes, ofstream& o
                                        di += ((xi - yi) * (xi - yi));
                                }
                                
-                               int n = lookupFloat.size();
-                               double p = 1.0 - ((6 * di) / (float) (n * ((n*n) - 1)));
+                               double p = 0.0;
                                
-                               out << p << '\t';
+                               double n = (double) lookupFloat.size();
+                               
+                               double SX2 = ((pow(n, 3.0) - n) / 12.0) - Lx[j];
+                               double SY2 = ((pow(n, 3.0) - n) / 12.0) - Ly;
+                               
+                               p = (SX2 + SY2 - di) / (2.0 * sqrt((SX2*SY2)));
+                               
+                               out  << '\t' << p;
+                               
+                               pValues[j] = p;
                        }
-                       
-                       
-                       out << endl;
+
+                       double sum = 0;
+                       for(int k=0;k<numaxes;k++){
+                               sum += pValues[k] * pValues[k];
+                       }
+                       out << '\t' << sqrt(sum) << endl;
                }
                
                return 0;
@@ -511,10 +562,10 @@ int CorrAxesCommand::calcKendall(map<string, vector<float> >& axes, ofstream& ou
                        vector<spearmanRank*> ties;
                        int rankTotal = 0;
                        for (int j = 0; j < scores[i].size(); j++) {
-                               rankTotal += j;
+                               rankTotal += (j+1);
                                ties.push_back(&(scores[i][j]));
                                
-                               if (j != scores.size()-1) { // you are not the last so you can look ahead
+                               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();
@@ -535,8 +586,8 @@ int CorrAxesCommand::calcKendall(map<string, vector<float> >& axes, ofstream& ou
                //for each otu
                for (int i = 0; i < lookupFloat[0]->getNumBins(); i++) {
                
-                       if (metadatafile == "") {  out << i+1 << '\t';  }
-                       else {  out << metadataLabels[i] << '\t';               }
+                       if (metadatafile == "") {  out << i+1;  }
+                       else {  out << metadataLabels[i];               }
                        
                        //find the ranks of this otu - Y
                        vector<spearmanRank> otuScores;
@@ -551,10 +602,10 @@ int CorrAxesCommand::calcKendall(map<string, vector<float> >& axes, ofstream& ou
                        vector<spearmanRank> ties;
                        int rankTotal = 0;
                        for (int j = 0; j < otuScores.size(); j++) {
-                               rankTotal += j;
+                               rankTotal += (j+1);
                                ties.push_back(otuScores[j]);
                                
-                               if (j != scores.size()-1) { // you are not the last so you can look ahead
+                               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();
@@ -571,130 +622,70 @@ int CorrAxesCommand::calcKendall(map<string, vector<float> >& axes, ofstream& ou
                                }
                        }
                        
+                       
+                       vector<double> pValues(numaxes);
+                       
                        //calc spearman ranks for each axis for this otu
                        for (int j = 0; j < numaxes; j++) {
                        
-                               int P = 0;
-                               //assemble otus ranks in same order as axis ranks
+                               int numCoor = 0;
+                               int numDisCoor = 0;
+                               
                                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);
                                }
                                
+                               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; u < scores[j].size(); u++) {
                                                if (otus[u].score > thisrank) { numWithHigherRank++; }
+                                               else if (otus[u].score < thisrank) { numWithLowerRank++; }
+                                               count++;
                                        }
                                        
-                                       P += numWithHigherRank;
+                                       numCoor += numWithHigherRank;
+                                       numDisCoor += numWithLowerRank;
                                }
                                
-                               int n = lookupFloat.size();
-                               
-                               double p = ( (4 * P) / (float) (n * (n - 1)) ) - 1.0;
+                               //comparing to yourself
+                               count -= lookupFloat.size();
                                
-                               out << p << '\t';
-                       }
-                       
-                       out << endl;
-               }
-               
-               return 0;
-       }
-       catch(exception& e) {
-               m->errorOut(e, "CorrAxesCommand", "calcKendall");
-               exit(1);
-       }
-}
-//**********************************************************************************************************************
-int CorrAxesCommand::getShared(){
-       try {
-               InputData* input = new InputData(sharedfile, "sharedfile");
-               lookup = input->getSharedRAbundVectors();
-               string lastLabel = lookup[0]->getLabel();
-               
-               if (label == "") { label = lastLabel; delete input; 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);
-               set<string> processedLabels;
-               set<string> userLabels = labels;
-               
-               //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;  }
-                       
-                       if(labels.count(lookup[0]->getLabel()) == 1){
-                               processedLabels.insert(lookup[0]->getLabel());
-                               userLabels.erase(lookup[0]->getLabel());
-                               break;
-                       }
-                       
-                       if ((m->anyLabelsToProcess(lookup[0]->getLabel(), userLabels, "") == true) && (processedLabels.count(lastLabel) != 1)) {
-                               string saveLabel = lookup[0]->getLabel();
-                               
-                               for (int i = 0; i < lookup.size(); i++) {  delete lookup[i];  } 
-                               lookup = input->getSharedRAbundVectors(lastLabel);
-                               
-                               processedLabels.insert(lookup[0]->getLabel());
-                               userLabels.erase(lookup[0]->getLabel());
-                               
-                               //restore real lastlabel to save below
-                               lookup[0]->setLabel(saveLabel);
-                               break;
+                               double p = (numCoor - numDisCoor) / (float) count;
+
+                               out << '\t' << p;
+                               pValues[j] = p;
+
                        }
                        
-                       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);
@@ -704,7 +695,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());
@@ -735,7 +726,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;
@@ -756,7 +747,6 @@ int CorrAxesCommand::getSharedFloat(){
                        lookupFloat = input->getSharedRAbundFloatVectors(lastLabel);
                }       
                
-               delete input;
                return 0;
        }
        catch(exception& e) {
@@ -764,43 +754,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 {