1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
|
#include "mothur.h"
#include "cluster.hpp"
/***********************************************************************/
SingleLinkage::SingleLinkage(RAbundVector* rav, ListVector* lv, SparseDistanceMatrix* dm, float c, string s, float a) :
Cluster(rav, lv, dm, c, s, a)
{}
/***********************************************************************/
//This function returns the tag of the method.
string SingleLinkage::getTag() {
return("nn");
}
/***********************************************************************/
//This function clusters based on the single linkage method.
void SingleLinkage::update(double& cutOFF){
try {
smallCol = dMatrix->getSmallestCell(smallRow);
nColCells = dMatrix->seqVec[smallCol].size();
nRowCells = dMatrix->seqVec[smallRow].size();
vector<bool> 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;j<nColCells;j++) {
if (dMatrix->seqVec[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();
// remove also the cell with the smallest distance
dMatrix->rmCell(smallRow, rowInd);
}
catch(exception& e) {
m->errorOut(e, "SingleLinkage", "update");
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);
}
}
/***********************************************************************/
|