X-Git-Url: https://git.donarmstrong.com/?p=mothur.git;a=blobdiff_plain;f=singlelinkage.cpp;h=3af1ea0c346030eb6f8eda3527ffc7a882c1b950;hp=3c2697714f4e252a7e2aa0ee06002ba4a8a6fa46;hb=a8e2df1b96a57f5f29576b08361b86a96a8eff4f;hpb=20a2d0350a737a434c89f303662d64a8eeea7b05 diff --git a/singlelinkage.cpp b/singlelinkage.cpp index 3c26977..3af1ea0 100644 --- a/singlelinkage.cpp +++ b/singlelinkage.cpp @@ -1,70 +1,97 @@ +#include "mothur.h" #include "cluster.hpp" -#include + /***********************************************************************/ -SingleLinkage::SingleLinkage(RAbundVector* rav, ListVector* lv, SparseMatrix* dm) : -Cluster(rav, lv, dm) +SingleLinkage::SingleLinkage(RAbundVector* rav, ListVector* lv, SparseDistanceMatrix* dm, float c, string s) : +Cluster(rav, lv, dm, c, s) {} + +/***********************************************************************/ +//This function returns the tag of the method. +string SingleLinkage::getTag() { + return("nn"); +} + /***********************************************************************/ -//This function clusters based on nearest method. -void SingleLinkage::update(){ +//This function clusters based on the single linkage method. +void SingleLinkage::update(double& cutOFF){ try { - getRowColCells(); + smallCol = dMatrix->getSmallestCell(smallRow); + nColCells = dMatrix->seqVec[smallCol].size(); + nRowCells = dMatrix->seqVec[smallRow].size(); - for(int i=1;irow == smallRow){ - search = rowCells[i]->column; - } - else{ - search = rowCells[i]->row; - } - - for(int j=1;jrow == search || colCells[j]->column == search){ - - if(colCells[j]->dist > rowCells[i]->dist){ - colCells[j]->dist = rowCells[i]->dist; - - if(colCells[j]->vectorMap != NULL){ - *(colCells[j]->vectorMap) = NULL; - colCells[j]->vectorMap = NULL; - } - - } - dMatrix->rmCell(rowCells[i]); - break; - } - } - - if(search < smallCol){ - rowCells[i]->row = smallCol; - rowCells[i]->column = search; - } - else{ - rowCells[i]->row = search; - rowCells[i]->column = smallCol; - } - - } + vector deleted(nRowCells, false); + int rowInd; + int search; + bool changed; + + // The vector has to be traversed in reverse order to preserve the index + // for faster removal in removeCell() + for (int i=nRowCells-1;i>=0;i--) { + if (dMatrix->seqVec[smallRow][i].index == smallCol) { + rowInd = i; // The index of the smallest distance cell in rowCells + } else { + search = dMatrix->seqVec[smallRow][i].index; + + for (int j=0;jseqVec[smallCol][j].index != smallRow) { //if you are not the small cell + if (dMatrix->seqVec[smallCol][j].index == search) { + changed = updateDistance(dMatrix->seqVec[smallCol][j], dMatrix->seqVec[smallRow][i]); + dMatrix->updateCellCompliment(smallCol, j); + dMatrix->rmCell(smallRow, i); + deleted[i] = true; + break; + } + } + } + if (!deleted[i]) { + // Assign the cell to the new cluster + // remove the old cell from seqVec and add the cell + // with the new row and column assignment again + float distance = dMatrix->seqVec[smallRow][i].dist; + dMatrix->rmCell(smallRow, i); + if (search < smallCol){ + PDistCell value(smallCol, distance); + dMatrix->addCell(search, value); + } else { + PDistCell value(search, distance); + dMatrix->addCell(smallCol, value); + } + sort(dMatrix->seqVec[smallCol].begin(), dMatrix->seqVec[smallCol].end(), compareIndexes); + sort(dMatrix->seqVec[search].begin(), dMatrix->seqVec[search].end(), compareIndexes); + } + } + } clusterBins(); clusterNames(); - dMatrix->rmCell(rowCells[0]); + // remove also the cell with the smallest distance + + dMatrix->rmCell(smallRow, rowInd); } catch(exception& e) { - cout << "Standard Error: " << e.what() << " has occurred in the SingleLinkage class Function update. Please contact Pat Schloss at pschloss@microbio.umass.edu." << "\n"; + m->errorOut(e, "SingleLinkage", "update"); exit(1); } - catch(...) { - cout << "An unknown error has occurred in the SingleLinkage class function update. Please contact Pat Schloss at pschloss@microbio.umass.edu." << "\n"; - exit(1); - } } + +/***********************************************************************/ +//This function updates the distance based on the nearest neighbor method. +bool SingleLinkage::updateDistance(PDistCell& colCell, PDistCell& rowCell) { + try { + bool changed = false; + if (colCell.dist > rowCell.dist) { + colCell.dist = rowCell.dist; + } + return(changed); + } + catch(exception& e) { + m->errorOut(e, "SingleLinkage", "updateDistance"); + exit(1); + } +} /***********************************************************************/