00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include <cmath>
00036 #include <limits>
00037 #include <map>
00038 #include <queue>
00039 #include <boost/unordered/unordered_set.hpp>
00040
00041 #include <OpenMS/COMPARISON/CLUSTERING/HashGrid.h>
00042 #include <OpenMS/CONCEPT/Types.h>
00043
00044 #ifndef OPENMS_COMPARISON_CLUSTERING_HIERARCHICALCLUSTERING_H
00045 #define OPENMS_COMPARISON_CLUSTERING_HIERARCHICALCLUSTERING_H
00046
00047 namespace OpenMS
00048 {
00066 template <typename PointRef>
00067 class HierarchicalClustering
00068 {
00069 public:
00074 typedef DPosition<2, DoubleReal> PointCoordinate;
00075
00080 class BoundingBox :
00081 public std::pair<PointCoordinate, PointCoordinate>
00082 {
00083 public:
00084 BoundingBox(const PointCoordinate & p) :
00085 std::pair<PointCoordinate, PointCoordinate>(std::make_pair(p, p))
00086 {}
00087
00088 BoundingBox(const BoundingBox & b) :
00089 std::pair<PointCoordinate, PointCoordinate>(b)
00090 {}
00091
00092 PointCoordinate size() const
00093 {
00094 return this->second - this->first;
00095 }
00096
00098 BoundingBox & operator|=(const BoundingBox & rhs)
00099 {
00100 typename PointCoordinate::iterator lit;
00101 typename PointCoordinate::const_iterator rit;
00102
00103
00104 lit = this->first.begin(); rit = rhs.first.begin();
00105 for (; lit != this->first.end(); ++lit, ++rit) *lit = std::min(*lit, *rit);
00106
00107
00108 lit = this->second.begin(); rit = rhs.second.begin();
00109 for (; lit != this->second.end(); ++lit, ++rit) *lit = std::max(*lit, *rit);
00110
00111 return *this;
00112 }
00113
00115 BoundingBox operator|(const BoundingBox & rhs) const
00116 {
00117 BoundingBox ret(*this);
00118 ret |= rhs;
00119 return ret;
00120 }
00121
00122 operator PointCoordinate() const
00123 {
00124
00125 return coordScalarDiv_(this->first + this->second, 2);
00126 }
00127 };
00128
00133 class Cluster :
00134 public boost::unordered_multimap<PointCoordinate, PointRef>
00135 {
00136 public:
00137 BoundingBox bbox;
00138
00139 Cluster(const BoundingBox & bbox) :
00140 bbox(bbox)
00141 {}
00142 };
00143
00147 typedef HashGrid<Cluster> Grid;
00148
00154 Grid grid;
00155
00156 protected:
00158 class TreeNode
00159 {
00160 public:
00161 const PointCoordinate coord;
00162 const BoundingBox bbox;
00163 TreeNode * left, * right;
00164 UInt points;
00165 const bool center;
00166 const PointRef ref;
00167
00168 TreeNode(const PointCoordinate & coord, const PointRef & ref, bool center) :
00169 coord(coord), bbox(coord), left(0), right(0), points(1), center(center), ref(ref)
00170 {}
00171
00172 TreeNode(const PointCoordinate & coord, const BoundingBox & bbox, TreeNode * left, TreeNode * right) :
00173 coord(coord), bbox(bbox),
00174 left(left), right(right),
00175 points(left->points + right->points),
00176 center(left->center && right->center),
00177 ref(PointRef())
00178 {}
00179 };
00180
00181 typedef std::map<typename Grid::CellIndex, std::pair<typename Grid::CellContent *, bool> > ClusterCells;
00182 typedef boost::unordered_set<TreeNode *> ClusterTrees;
00183
00185 class TreeDistance
00186 {
00187 public:
00188 DoubleReal distance;
00189 TreeNode * left, * right;
00190
00191 TreeDistance(const DoubleReal & distance, TreeNode * left, TreeNode * right) :
00192 distance(distance), left(left), right(right)
00193 {}
00194
00195 bool operator>(const TreeDistance & rhs) const
00196 {
00197 return distance > rhs.distance;
00198 }
00199
00200 };
00201
00203 typedef std::priority_queue<TreeDistance, std::vector<TreeDistance>, std::greater<TreeDistance> > TreeDistanceQueue;
00204
00205 public:
00210 HierarchicalClustering(const PointCoordinate & cluster_dimension) :
00211 grid(cluster_dimension)
00212 {}
00213
00220 typename Grid::cell_iterator insertPoint(const PointCoordinate & d, const PointRef & ref)
00221 {
00222 typename Grid::cell_iterator it = insertCluster_(d);
00223 it->second.insert(std::make_pair(d, ref));
00224 return it;
00225 }
00226
00230 void cluster()
00231 {
00232
00233 std::vector<typename Grid::CellIndex> cells;
00234 for (typename Grid::const_grid_iterator it = grid.grid_begin(); it != grid.grid_end(); ++it)
00235 cells.push_back(it->first);
00236
00237 for (typename std::vector<typename Grid::CellIndex>::const_iterator it = cells.begin(); it != cells.end(); ++it)
00238 clusterIndex_(*it);
00239 }
00240
00241 protected:
00247 template <class P>
00248 typename Grid::cell_iterator insertCluster_(const P & p)
00249 {
00250 return grid.insert(std::make_pair(p, Cluster(p)));
00251 }
00252
00257 void clusterIndex_(const typename Grid::CellIndex & p);
00258
00267 void gridCells5x5_(typename Grid::CellIndex cur, ClusterCells & cells);
00268
00276 void gridCell_(const typename Grid::CellIndex & cur, ClusterCells & cells, bool center = false, bool ignore_missing = true)
00277 {
00278 try
00279 {
00280 cells.insert(std::make_pair(cur, std::make_pair(&grid.grid_at(cur), center)));
00281 }
00282 catch (std::out_of_range &)
00283 {
00284 if (!ignore_missing) throw;
00285 }
00286 }
00287
00291 void addTreeDistance_(TreeNode * tree, ClusterTrees & trees, TreeDistanceQueue & dists)
00292 {
00293
00294 DoubleReal dist_min = std::numeric_limits<DoubleReal>::infinity();
00295 typename ClusterTrees::const_iterator dist_it = trees.end();
00296
00297
00298 for (typename ClusterTrees::const_iterator it = trees.begin(); it != trees.end(); ++it)
00299 {
00300 if (tree == *it) continue;
00301 DoubleReal dist = treeDistance_(tree, *it);
00302 if (dist < dist_min)
00303 {
00304 dist_min = dist;
00305 dist_it = it;
00306 }
00307 }
00308
00309
00310 if (dist_it != trees.end()) dists.push(TreeDistance(dist_min, tree, *dist_it));
00311
00312
00313 trees.insert(tree);
00314 }
00315
00322 DoubleReal treeDistance_(TreeNode * left, TreeNode * right)
00323 {
00324 const BoundingBox bbox = left->bbox | right->bbox;
00325 if (coordElemGreater_(bbox.size(), grid.cell_dimension))
00326 {
00327 return std::numeric_limits<DoubleReal>::infinity();
00328 }
00329
00330 const PointCoordinate left_scaled = coordElemDiv_(left->coord, grid.cell_dimension);
00331 const PointCoordinate right_scaled = coordElemDiv_(right->coord, grid.cell_dimension);
00332 return coordDist_(left_scaled, right_scaled);
00333 }
00334
00341 void tree2Cluster_(const TreeNode * tree, Cluster & cluster)
00342 {
00343 if (tree->left && tree->right)
00344 {
00345 tree2Cluster_(tree->left, cluster);
00346 tree2Cluster_(tree->right, cluster);
00347 }
00348 else
00349 {
00350 cluster.insert(std::make_pair(tree->bbox.first, tree->ref));
00351 }
00352 delete tree->left;
00353 delete tree->right;
00354 }
00355
00361 void tree2Points_(const TreeNode * tree)
00362 {
00363 if (tree->left && tree->right)
00364 {
00365 tree2Points_(tree->left);
00366 tree2Points_(tree->right);
00367 }
00368 else
00369 {
00370 insertPoint(tree->bbox.first, tree->ref);
00371 }
00372 delete tree->left;
00373 delete tree->right;
00374 }
00375
00376 static PointCoordinate coordScalarDiv_(const PointCoordinate & lhs, const DoubleReal & rhs)
00377 {
00378 PointCoordinate ret;
00379 typename PointCoordinate::iterator it = ret.begin();
00380 typename PointCoordinate::const_iterator lit = lhs.begin();
00381 for (; it != ret.end(); ++it, ++lit) *it = *lit / rhs;
00382 return ret;
00383 }
00384
00385 static PointCoordinate coordElemDiv_(const PointCoordinate & lhs, const PointCoordinate & rhs)
00386 {
00387 PointCoordinate ret;
00388 typename PointCoordinate::iterator it = ret.begin();
00389 typename PointCoordinate::const_iterator lit = lhs.begin(), rit = rhs.begin();
00390 for (; it != ret.end(); ++it, ++lit, ++rit) *it = *lit / *rit;
00391 return ret;
00392 }
00393
00394 static bool coordElemGreater_(const PointCoordinate & lhs, const PointCoordinate & rhs)
00395 {
00396 typename PointCoordinate::const_iterator lit = lhs.begin(), rit = rhs.begin();
00397 for (; lit != lhs.end(); ++lit, ++rit)
00398 {
00399 if (*lit > *rit) return true;
00400 }
00401 return false;
00402 }
00403
00404 static DoubleReal coordDist_(const PointCoordinate & lhs, const PointCoordinate & rhs)
00405 {
00406 DoubleReal ret = 0;
00407 PointCoordinate p = lhs - rhs;
00408 typename PointCoordinate::const_iterator it = p.begin();
00409 for (; it != p.end(); ++it) ret += std::pow(*it, 2.);
00410 return std::sqrt(ret);
00411 }
00412
00413 };
00414
00415 template <typename I>
00416 void HierarchicalClustering<I>::clusterIndex_(const typename Grid::CellIndex & cur)
00417 {
00418 ClusterCells cells;
00419 ClusterTrees trees;
00420 TreeDistanceQueue dists;
00421
00422
00423 try
00424 {
00425 gridCells5x5_(cur, cells);
00426 }
00427 catch (std::out_of_range &)
00428 {
00429 return;
00430 }
00431
00432
00433 for (typename ClusterCells::iterator cell_it = cells.begin(); cell_it != cells.end(); ++cell_it)
00434 {
00435 typename Grid::CellContent & cell_cur = *cell_it->second.first;
00436 const bool & cell_center = cell_it->second.second;
00437
00438
00439 typename Grid::cell_iterator cluster_tmp_it = cell_cur.begin();
00440 while (cluster_tmp_it != cell_cur.end())
00441 {
00442 typename Grid::cell_iterator cluster_it = cluster_tmp_it;
00443 ++cluster_tmp_it;
00444
00445
00446 if (cluster_it->second.size() == 1)
00447 {
00448
00449 for (typename Cluster::const_iterator point_it = cluster_it->second.begin(); point_it != cluster_it->second.end(); ++point_it)
00450 {
00451 const PointCoordinate & coord = point_it->first;
00452 TreeNode * tree(new TreeNode(coord, point_it->second, cell_center));
00453 addTreeDistance_(tree, trees, dists);
00454 }
00455
00456
00457 cell_cur.erase(cluster_it);
00458 }
00459 }
00460 }
00461
00462
00463 while (!dists.empty())
00464 {
00465 const typename TreeDistanceQueue::value_type cur_dist = dists.top();
00466 TreeNode * tree_left(cur_dist.left), *tree_right(cur_dist.right);
00467 dists.pop();
00468
00469
00470 Size count_left = trees.count(tree_left), count_right = trees.count(tree_right);
00471 if (count_left && count_right)
00472 {
00473 trees.erase(tree_left);
00474 trees.erase(tree_right);
00475
00476 const BoundingBox bbox = tree_left->bbox | tree_right->bbox;
00477
00478
00479 const PointCoordinate & left = tree_left->coord, & right = tree_right->coord;
00480 const UInt & left_points = tree_left->points, & right_points = tree_right->points;
00481 const PointCoordinate coord = coordScalarDiv_(left * left_points + right * right_points, left_points + right_points);
00482
00483 TreeNode * tree(new TreeNode(coord, bbox, tree_left, tree_right));
00484
00485 addTreeDistance_(tree, trees, dists);
00486 }
00487
00488
00489 else if (count_left)
00490 addTreeDistance_(tree_left, trees, dists);
00491 else if (count_right)
00492 addTreeDistance_(tree_right, trees, dists);
00493 }
00494
00495
00496 for (typename ClusterTrees::iterator tree_it = trees.begin(); tree_it != trees.end(); ++tree_it)
00497 {
00498
00499 if ((**tree_it).center)
00500 {
00501 Cluster & cluster = insertCluster_((**tree_it).bbox)->second;
00502 tree2Cluster_(*tree_it, cluster);
00503 }
00504
00505 else
00506 {
00507 tree2Points_(*tree_it);
00508 }
00509 delete *tree_it;
00510 }
00511 }
00512
00513 template <typename I>
00514 void HierarchicalClustering<I>::gridCells5x5_(typename Grid::CellIndex base, ClusterCells & cells)
00515 {
00516
00517 gridCell_(base, cells, true, false);
00518
00519 typename Grid::CellIndex cur = base;
00520 cur[0] -= 2;
00521
00522 cur[1] -= 2; gridCell_(cur, cells);
00523
00524 cur[1] += 1; gridCell_(cur, cells);
00525
00526 cur[1] += 1; gridCell_(cur, cells);
00527
00528 cur[1] += 1; gridCell_(cur, cells);
00529
00530 cur[1] += 1; gridCell_(cur, cells);
00531
00532 cur = base; cur[0] -= 1;
00533
00534 cur[1] -= 2; gridCell_(cur, cells);
00535
00536 cur[1] += 1; gridCell_(cur, cells, true);
00537
00538 cur[1] += 1; gridCell_(cur, cells, true);
00539
00540 cur[1] += 1; gridCell_(cur, cells, true);
00541
00542 cur[1] += 1; gridCell_(cur, cells);
00543
00544 cur = base;
00545
00546 cur[1] -= 2; gridCell_(cur, cells);
00547
00548 cur[1] += 1; gridCell_(cur, cells, true);
00549
00550 cur[1] += 1;
00551
00552 cur[1] += 1; gridCell_(cur, cells, true);
00553
00554 cur[1] += 1; gridCell_(cur, cells);
00555
00556 cur = base; cur[0] += 1;
00557
00558 cur[1] -= 2; gridCell_(cur, cells);
00559
00560 cur[1] += 1; gridCell_(cur, cells, true);
00561
00562 cur[1] += 1; gridCell_(cur, cells, true);
00563
00564 cur[1] += 1; gridCell_(cur, cells, true);
00565
00566 cur[1] += 1; gridCell_(cur, cells);
00567
00568 cur = base; cur[0] += 2;
00569
00570 cur[1] -= 2; gridCell_(cur, cells);
00571
00572 cur[1] += 1; gridCell_(cur, cells);
00573
00574 cur[1] += 1; gridCell_(cur, cells);
00575
00576 cur[1] += 1; gridCell_(cur, cells);
00577
00578 cur[1] += 1; gridCell_(cur, cells);
00579 }
00580
00581 }
00582
00583 #endif