OpenMS
GridBasedClustering.h
Go to the documentation of this file.
1 // Copyright (c) 2002-2023, The OpenMS Team -- EKU Tuebingen, ETH Zurich, and FU Berlin
2 // SPDX-License-Identifier: BSD-3-Clause
3 //
4 // --------------------------------------------------------------------------
5 // $Maintainer: Lars Nilse $
6 // $Authors: Lars Nilse, Johannes Veit $
7 // --------------------------------------------------------------------------
8 
9 #pragma once
10 
17 
18 #include <cmath>
19 #include <limits>
20 #include <map>
21 #include <set>
22 #include <queue>
23 #include <vector>
24 #include <algorithm>
25 #include <iostream>
26 #include <unordered_map>
27 
28 namespace OpenMS
29 {
30 
34  class OPENMS_DLLAPI MinimumDistance
35  {
36 public:
37 
41  MinimumDistance(const int& cluster_index, const int& nearest_neighbour_index, const double& distance);
42 
46  int getClusterIndex() const;
47 
52 
57  bool operator<(const MinimumDistance& other) const;
58  bool operator>(const MinimumDistance& other) const;
59  bool operator==(const MinimumDistance& other) const;
60 
61 private:
62 
65 
70 
75 
79  double distance_;
80 
81  };
82 
98  template <typename Metric>
100  public ProgressLogger
101  {
102 public:
106  typedef GridBasedCluster::Point Point; // DPosition<2>
107  typedef GridBasedCluster::Rectangle Rectangle; // DBoundingBox<2>
108  typedef ClusteringGrid::CellIndex CellIndex; // std::pair<int,int>
109  typedef std::multiset<MinimumDistance>::const_iterator MultisetIterator;
110  typedef std::unordered_multimap<int, MultisetIterator>::const_iterator NNIterator;
111 
122  GridBasedClustering(Metric metric, const std::vector<double>& data_x,
123  const std::vector<double>& data_y, const std::vector<int>& properties_A,
124  const std::vector<int>& properties_B, std::vector<double> grid_spacing_x,
125  std::vector<double> grid_spacing_y) :
126  metric_(metric),
127  grid_(grid_spacing_x, grid_spacing_y)
128  {
129  init_(data_x, data_y, properties_A, properties_B);
130  }
131 
140  GridBasedClustering(Metric metric, const std::vector<double>& data_x,
141  const std::vector<double>& data_y, std::vector<double> grid_spacing_x,
142  std::vector<double> grid_spacing_y) :
143  metric_(metric),
144  grid_(grid_spacing_x, grid_spacing_y)
145  {
146  // set properties A and B to -1, i.e. ignore properties when clustering
147  std::vector<int> properties_A(data_x.size(), -1);
148  std::vector<int> properties_B(data_x.size(), -1);
149  init_(data_x, data_y, properties_A, properties_B);
150  }
151 
156  void cluster()
157  {
158  // progress logger
159  // NOTE: for some reason, gcc7 chokes if we remove the OpenMS::String
160  // below, so lets just not change it.
161  Size clusters_start = clusters_.size();
162  startProgress(0, clusters_start, OpenMS::String("clustering"));
163 
164  MinimumDistance zero_distance(-1, -1, 0);
165 
166  // combine clusters until all have been moved to the final list
167  while (!clusters_.empty())
168  {
169  setProgress(clusters_start - clusters_.size());
170 
171  MultisetIterator smallest_distance_it = distances_.lower_bound(zero_distance);
172 
173  int cluster_index1 = smallest_distance_it->getClusterIndex();
174  int cluster_index2 = smallest_distance_it->getNearestNeighbourIndex();
175 
176  eraseMinDistance_(smallest_distance_it);
177 
178  // update cluster list
179  std::map<int, GridBasedCluster>::iterator cluster1_it = clusters_.find(cluster_index1);
180  std::map<int, GridBasedCluster>::iterator cluster2_it = clusters_.find(cluster_index2);
181  const GridBasedCluster& cluster1 = cluster1_it->second;
182  const GridBasedCluster& cluster2 = cluster2_it->second;
183  const std::vector<int>& points1 = cluster1.getPoints();
184  const std::vector<int>& points2 = cluster2.getPoints();
185  std::vector<int> new_points;
186  new_points.reserve(points1.size() + points2.size());
187  new_points.insert(new_points.end(), points1.begin(), points1.end());
188  new_points.insert(new_points.end(), points2.begin(), points2.end());
189 
190  double new_x = (cluster1.getCentre().getX() * points1.size() + cluster2.getCentre().getX() * points2.size()) / (points1.size() + points2.size());
191  double new_y = (cluster1.getCentre().getY() * points1.size() + cluster2.getCentre().getY() * points2.size()) / (points1.size() + points2.size());
192 
193  // update grid
194  CellIndex cell_for_cluster1 = grid_.getIndex(cluster1.getCentre());
195  CellIndex cell_for_cluster2 = grid_.getIndex(cluster2.getCentre());
196  CellIndex cell_for_new_cluster = grid_.getIndex(DPosition<2>(new_x, new_y));
197  grid_.removeCluster(cell_for_cluster1, cluster_index1);
198  grid_.removeCluster(cell_for_cluster2, cluster_index2);
199  grid_.addCluster(cell_for_new_cluster, cluster_index1);
200 
201  // merge clusters
202  const Rectangle& box1 = cluster1.getBoundingBox();
203  const Rectangle& box2 = cluster2.getBoundingBox();
204  Rectangle new_box(box1);
205  new_box.enlarge(box2.minPosition());
206  new_box.enlarge(box2.maxPosition());
207 
208  // Properties A of both clusters should by now be the same. The merge veto has been checked
209  // when a new entry to the minimum distance list was added, @see findNearestNeighbour_.
210  if (cluster1.getPropertyA() != cluster2.getPropertyA())
211  {
212  throw Exception::InvalidValue(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, "Property A of both clusters not the same. ", "A");
213  }
214  int new_A = cluster1.getPropertyA();
215 
216  const std::vector<int>& B1 = cluster1.getPropertiesB();
217  const std::vector<int>& B2 = cluster2.getPropertiesB();
218  std::vector<int> new_B;
219  new_B.reserve(B1.size() + B2.size());
220  new_B.insert(new_B.end(), B1.begin(), B1.end());
221  new_B.insert(new_B.end(), B2.begin(), B2.end());
222 
223  GridBasedCluster new_cluster(DPosition<2>(new_x, new_y), new_box, new_points, new_A, new_B);
224 
225  clusters_.erase(cluster1_it);
226  clusters_.erase(cluster2_it);
227  clusters_.insert(std::make_pair(cluster_index1, new_cluster));
228 
229  std::set<int> clusters_to_be_updated;
230  clusters_to_be_updated.insert(cluster_index1);
231 
232  // erase distance object of cluster with cluster_index2 without updating (does not exist anymore!)
233  // (the one with cluster_index1 has already been erased at the top of the while loop)
235 
236  // find out which clusters need to be updated
237  std::pair<NNIterator, NNIterator> nn_range = reverse_nns_.equal_range(cluster_index1);
238  for (NNIterator nn_it = nn_range.first; nn_it != nn_range.second;)
239  {
240  clusters_to_be_updated.insert(nn_it->second->getClusterIndex());
241  eraseMinDistance_((nn_it++)->second);
242  }
243  nn_range = reverse_nns_.equal_range(cluster_index2);
244  for (NNIterator nn_it = nn_range.first; nn_it != nn_range.second;)
245  {
246  clusters_to_be_updated.insert(nn_it->second->getClusterIndex());
247  eraseMinDistance_((nn_it++)->second);
248  }
249 
250  // update clusters
251  for (std::set<int>::const_iterator cluster_index = clusters_to_be_updated.begin(); cluster_index != clusters_to_be_updated.end(); ++cluster_index)
252  {
253  std::map<int, GridBasedCluster>::iterator c_it = clusters_.find(*cluster_index);
254  const GridBasedCluster& c = c_it->second;
255  if (findNearestNeighbour_(c, *cluster_index))
256  {
257  grid_.removeCluster(grid_.getIndex(c.getCentre()), *cluster_index); // remove from grid
258  clusters_.erase(c_it); // remove from cluster list
259  }
260  }
261  }
262 
263  endProgress();
264  }
265 
271  {
272 
273  // construct new grid (grid only in x-direction, single cell in y-direction)
274  std::vector<double> grid_spacing_x = grid_.getGridSpacingX();
275  std::vector<double> grid_spacing_y = grid_.getGridSpacingY();
276  std::vector<double> grid_spacing_y_new;
277  grid_spacing_y_new.push_back(grid_spacing_y.front());
278  grid_spacing_y_new.push_back(grid_spacing_y.back());
279  ClusteringGrid grid_x_only(grid_spacing_x, grid_spacing_y_new);
280 
281  // register final clusters on the new grid
282  for (std::map<int, GridBasedCluster>::const_iterator it = clusters_final_.begin(); it != clusters_final_.end(); ++it)
283  {
284  int cluster_index = it->first;
285  GridBasedCluster cluster = it->second;
286  grid_x_only.addCluster(grid_x_only.getIndex(cluster.getCentre()), cluster_index);
287  }
288 
289 
290  // scan through x on the grid
291  for (unsigned cell = 0; cell < grid_spacing_x.size(); ++cell)
292  {
293  CellIndex grid_index(cell, 1);
294  if (grid_x_only.isNonEmptyCell(grid_index))
295  {
296  std::list<int> cluster_indices = grid_x_only.getClusters(grid_index); // indices of clusters in this x-range
297  if (cluster_indices.size() > 1)
298  {
299  // First, order the clusters in ascending y.
300  std::list<GridBasedCluster> cluster_list; // list to order clusters in y
301  std::map<GridBasedCluster, int> index_list; // allows us to keep track of cluster indices after sorting
302  for (std::list<int>::const_iterator it = cluster_indices.begin(); it != cluster_indices.end(); ++it)
303  {
304  cluster_list.push_back(clusters_final_.find(*it)->second);
305  index_list.insert(std::make_pair(clusters_final_.find(*it)->second, *it));
306  }
307  cluster_list.sort();
308 
309  // Now check if two adjacent clusters c1 and c2 can be merged.
310  std::list<GridBasedCluster>::const_iterator c1 = cluster_list.begin();
311  std::list<GridBasedCluster>::const_iterator c2 = cluster_list.begin();
312  ++c1;
313  while (c1 != cluster_list.end())
314  {
315  double centre1x = (*c1).getCentre().getX();
316  double centre1y = (*c1).getCentre().getY();
317  double centre2x = (*c2).getCentre().getX();
318  double centre2y = (*c2).getCentre().getY();
319 
320  double box1x_min = (*c1).getBoundingBox().minX();
321  double box1x_max = (*c1).getBoundingBox().maxX();
322  double box1y_min = (*c1).getBoundingBox().minY();
323  double box1y_max = (*c1).getBoundingBox().maxY();
324  double box2x_min = (*c2).getBoundingBox().minX();
325  double box2x_max = (*c2).getBoundingBox().maxX();
326  double box2y_min = (*c2).getBoundingBox().minY();
327  double box2y_max = (*c2).getBoundingBox().maxY();
328 
329  //double y_range1 = box1y_max - box1y_min;
330  //double y_range2 = box2y_max - box2y_min;
331  //double y_gap = box1y_min - box2y_max;
332 
333  // Is there an overlap of the two clusters in x?
334  bool overlap = (box1x_min <= box2x_max && box1x_min >= box2x_min) || (box1x_max >= box2x_min && box1x_max <= box2x_max);
335 
336  // Is the x-centre of one cluster in the x-range of the other?
337  //bool centre_in_range1 = (box2x_min <= centre1x && centre1x <= box2x_max);
338  //bool centre_in_range2 = (box1x_min <= centre2x && centre2x <= box1x_max);
339 
340  // Is the y-gap between the two clusters smaller than 1/s of their average y-range?
341  //double s = 6; // scaling factor
342  //bool clusters_close = (y_gap * s <= (y_range1 - y_range2)/2);
343 
344  // Shall we merge the two adjacent clusters?
345  //if ((centre_in_range1 || centre_in_range2) && clusters_close)
346  if (overlap)
347  {
348  std::vector<int> points1 = (*c1).getPoints();
349  std::vector<int> points2 = (*c2).getPoints();
350  std::vector<int> new_points;
351  new_points.reserve(points1.size() + points2.size());
352  new_points.insert(new_points.end(), points1.begin(), points1.end());
353  new_points.insert(new_points.end(), points2.begin(), points2.end());
354 
355  double new_x = (centre1x * points1.size() + centre2x * points2.size()) / (points1.size() + points2.size());
356  double new_y = (centre1y * points1.size() + centre2y * points2.size()) / (points1.size() + points2.size());
357 
358  double min_x = std::min(box1x_min, box2x_min);
359  double min_y = std::min(box1y_min, box2y_min);
360  double max_x = std::max(box1x_max, box2x_max);
361  double max_y = std::max(box1y_max, box2y_max);
362 
363  Point new_centre(new_x, new_y);
364  Point position_min(min_x, min_y);
365  Point position_max(max_x, max_y);
366  Rectangle new_bounding_box(position_min, position_max);
367 
368  GridBasedCluster new_cluster(new_centre, new_bounding_box, new_points);
369 
370  // update final cluster list
371  clusters_final_.erase(clusters_final_.find(index_list.find(*c1)->second));
372  clusters_final_.erase(clusters_final_.find(index_list.find(*c2)->second));
373  clusters_final_.insert(std::make_pair(index_list.find(*c1)->second, new_cluster));
374 
375  // update grid
376  CellIndex cell_for_cluster1 = grid_x_only.getIndex((*c1).getCentre());
377  CellIndex cell_for_cluster2 = grid_x_only.getIndex((*c2).getCentre());
378  CellIndex cell_for_new_cluster = grid_x_only.getIndex(new_centre);
379 
380  grid_x_only.removeCluster(cell_for_cluster1, index_list.find(*c1)->second);
381  grid_x_only.removeCluster(cell_for_cluster2, index_list.find(*c2)->second);
382  grid_x_only.addCluster(cell_for_new_cluster, index_list.find(*c1)->second);
383  }
384  ++c1;
385  ++c2;
386  }
387  }
388  }
389  }
390 
391  }
392 
397  void removeSmallClustersY(double threshold_y)
398  {
399  std::map<int, GridBasedCluster>::iterator it = clusters_final_.begin();
400  while (it != clusters_final_.end())
401  {
402  Rectangle box = it->second.getBoundingBox();
403  if (box.maxY() - box.minY() < threshold_y)
404  {
405  clusters_final_.erase(it++);
406  }
407  else
408  {
409  ++it;
410  }
411  }
412  }
413 
417  std::map<int, GridBasedCluster> getResults() const
418  {
419  return clusters_final_;
420  }
421 
422 private:
423 
427  Metric metric_;
428 
434 
439  std::map<int, GridBasedCluster> clusters_;
440 
445  std::map<int, GridBasedCluster> clusters_final_;
446 
451  std::multiset<MinimumDistance> distances_;
452 
457  std::unordered_multimap<int, std::multiset<MinimumDistance>::const_iterator> reverse_nns_;
458 
463  std::unordered_map<int, std::multiset<MinimumDistance>::const_iterator> distance_it_for_cluster_idx_;
464 
473  void init_(const std::vector<double>& data_x, const std::vector<double>& data_y,
474  const std::vector<int>& properties_A, const std::vector<int>& properties_B)
475  {
476  // fill the grid with points to be clustered (initially each cluster contains a single point)
477  for (unsigned i = 0; i < data_x.size(); ++i)
478  {
479  Point position(data_x[i], data_y[i]);
480  Rectangle box(position, position);
481 
482  std::vector<int> pi; // point indices
483  pi.push_back(i);
484  std::vector<int> pb; // properties B
485  pb.push_back(properties_B[i]);
486 
487  // add to cluster list
488  GridBasedCluster cluster(position, box, pi, properties_A[i], pb);
489  clusters_.insert(std::make_pair(i, cluster));
490 
491  // register on grid
492  grid_.addCluster(grid_.getIndex(position), i);
493  }
494 
495  // fill list of minimum distances
496  std::map<int, GridBasedCluster>::iterator iterator = clusters_.begin();
497  while (iterator != clusters_.end())
498  {
499  int cluster_index = iterator->first;
500  const GridBasedCluster& cluster = iterator->second;
501 
502  if (findNearestNeighbour_(cluster, cluster_index))
503  {
504  // remove from grid
505  grid_.removeCluster(grid_.getIndex(cluster.getCentre()), cluster_index);
506  // remove from cluster list
507  clusters_.erase(iterator++);
508  }
509  else
510  {
511  ++iterator;
512  }
513  }
514  }
515 
529  bool mergeVeto_(const GridBasedCluster& c1, const GridBasedCluster& c2) const
530  {
531  int A1 = c1.getPropertyA();
532  int A2 = c2.getPropertyA();
533 
534  // check if properties A of both clusters is set or not (not set := -1)
535  if (A1 == -1 || A2 == -1)
536  {
537  return false;
538  }
539 
540  // Will the merged cluster have the same properties A?
541  if (A1 != A2) return true;
542 
543  std::vector<int> B1 = c1.getPropertiesB();
544  std::vector<int> B2 = c2.getPropertiesB();
545 
546  // check if properties B of both clusters is set or not (not set := -1)
547  if (std::find(B1.begin(), B1.end(), -1) != B1.end() || std::find(B2.begin(), B2.end(), -1) != B2.end())
548  {
549  return false;
550  }
551 
552  // Will the merged cluster have different properties B?
553  // (Hence the intersection of properties B of cluster 1 and cluster 2 should be empty.)
554  std::vector<int> B_intersection;
555  sort(B1.begin(), B1.end());
556  sort(B2.begin(), B2.end());
557  set_intersection(B1.begin(), B1.end(), B2.begin(), B2.end(), back_inserter(B_intersection));
558 
559  return !B_intersection.empty();
560  }
561 
575  bool findNearestNeighbour_(const GridBasedCluster& cluster, int cluster_index)
576  {
577  const Point& centre = cluster.getCentre();
578  const CellIndex& cell_index = grid_.getIndex(centre);
579  double min_dist = 0;
580  int nearest_neighbour = -1;
581 
582  // search in the grid cell and its 8 neighbouring cells for the nearest neighbouring cluster
583  for (int i = -1; i <= 1; ++i)
584  {
585  for (int j = -1; j <= 1; ++j)
586  {
587  CellIndex cell_index2(cell_index);
588  cell_index2.first += i;
589  cell_index2.second += j;
590  if (grid_.isNonEmptyCell(cell_index2))
591  {
592  const std::list<int>& cluster_indices = grid_.getClusters(cell_index2);
593  for (std::list<int>::const_iterator cluster_index2 = cluster_indices.begin(); cluster_index2 != cluster_indices.end(); ++cluster_index2)
594  {
595  if (*cluster_index2 != cluster_index)
596  {
597  const GridBasedCluster& cluster2 = clusters_.find(*cluster_index2)->second;
598  const Point& centre2 = cluster2.getCentre();
599  double distance = metric_(centre, centre2);
600 
601  if (distance < min_dist || nearest_neighbour == -1)
602  {
603  bool veto = mergeVeto_(cluster, cluster2); // If clusters cannot be merged anyhow, they are no nearest neighbours.
604  if (!veto)
605  {
606  min_dist = distance;
607  nearest_neighbour = *cluster_index2;
608  }
609  }
610  }
611  }
612  }
613  }
614  }
615 
616  if (nearest_neighbour == -1)
617  {
618  // no other cluster nearby, hence move the cluster to the final results
619  clusters_final_.insert(std::make_pair(cluster_index, clusters_.find(cluster_index)->second));
620  return true;
621  }
622 
623  // add to the list of minimal distances
624  std::multiset<MinimumDistance>::const_iterator it = distances_.insert(MinimumDistance(cluster_index, nearest_neighbour, min_dist));
625  // add to reverse nearest neighbor lookup table
626  reverse_nns_.insert(std::make_pair(nearest_neighbour, it));
627  // add to cluster index -> distance lookup table
628  distance_it_for_cluster_idx_[cluster_index] = it;
629 
630  return false;
631  }
632 
642  void eraseMinDistance_(const std::multiset<MinimumDistance>::const_iterator it)
643  {
644  // remove corresponding entries from nearest neighbor lookup table
645  std::pair<NNIterator, NNIterator> nn_range = reverse_nns_.equal_range(it->getNearestNeighbourIndex());
646  for (NNIterator nn_it = nn_range.first; nn_it != nn_range.second; ++nn_it)
647  {
648  if (nn_it->second == it)
649  {
650  reverse_nns_.erase(nn_it);
651  break;
652  }
653  }
654 
655  // remove corresponding entry from cluster index -> distance lookup table
656  distance_it_for_cluster_idx_.erase(it->getClusterIndex());
657 
658  // remove from distances_
659  distances_.erase(it);
660  }
661  };
662 }
data structure to store 2D data to be clustered e.g. (m/z, retention time) coordinates from multiplex...
Definition: ClusteringGrid.h:31
std::vector< double > getGridSpacingX() const
returns grid spacing in x direction
CellIndex getIndex(const Point &position) const
returns grid cell index (i,j) for the positions (x,y)
void removeCluster(const CellIndex &cell_index, const int &cluster_index)
removes a cluster from this grid cell and removes the cell if no other cluster left
std::list< int > getClusters(const CellIndex &cell_index) const
returns clusters in this grid cell
std::pair< int, int > CellIndex
Definition: ClusteringGrid.h:36
std::vector< double > getGridSpacingY() const
returns grid spacing in y direction
bool isNonEmptyCell(const CellIndex &cell_index) const
checks if there are clusters at this cell index
void addCluster(const CellIndex &cell_index, const int &cluster_index)
adds a cluster to this grid cell
void enlarge(const PositionType &p)
Enlarges the bounding box such that it contains a position.
Definition: DBoundingBox.h:95
CoordinateType getY() const
Name accessor for the second dimension. Only for DPosition<2>, for visualization.
Definition: DPosition.h:149
CoordinateType getX() const
Name accessor for the first dimension. Only for DPosition<2>, for visualization.
Definition: DPosition.h:142
Invalid value exception.
Definition: Exception.h:303
basic data structure for clustering
Definition: GridBasedCluster.h:24
const Point & getCentre() const
returns cluster centre
const std::vector< int > & getPoints() const
returns indices of points in cluster
const std::vector< int > & getPropertiesB() const
returns properties B of all points
const Rectangle & getBoundingBox() const
returns bounding box
int getPropertyA() const
returns property A
2D hierarchical clustering implementation optimized for large data sets containing many small cluster...
Definition: GridBasedClustering.h:101
void removeSmallClustersY(double threshold_y)
removes clusters with bounding box dimension in y-direction below certain threshold
Definition: GridBasedClustering.h:397
bool findNearestNeighbour_(const GridBasedCluster &cluster, int cluster_index)
determines the nearest neighbour for each cluster
Definition: GridBasedClustering.h:575
std::unordered_map< int, std::multiset< MinimumDistance >::const_iterator > distance_it_for_cluster_idx_
cluster index to distance iterator lookup table for finding out which clusters need to be updated fas...
Definition: GridBasedClustering.h:463
bool mergeVeto_(const GridBasedCluster &c1, const GridBasedCluster &c2) const
checks if two clusters can be merged Each point in a cluster can (optionally) have two properties A a...
Definition: GridBasedClustering.h:529
void init_(const std::vector< double > &data_x, const std::vector< double > &data_y, const std::vector< int > &properties_A, const std::vector< int > &properties_B)
initialises all data structures
Definition: GridBasedClustering.h:473
ClusteringGrid grid_
grid on which the position of the clusters are registered used in cluster method
Definition: GridBasedClustering.h:433
void extendClustersY()
extends clusters in y-direction if possible (merges clusters further in y-direction,...
Definition: GridBasedClustering.h:270
Metric metric_
metric for measuring the distance between points in the 2D plane
Definition: GridBasedClustering.h:427
GridBasedClustering(Metric metric, const std::vector< double > &data_x, const std::vector< double > &data_y, std::vector< double > grid_spacing_x, std::vector< double > grid_spacing_y)
initialises all data structures
Definition: GridBasedClustering.h:140
GridBasedCluster::Rectangle Rectangle
Definition: GridBasedClustering.h:107
std::multiset< MinimumDistance > distances_
list of minimum distances stores the smallest of the distances in the head
Definition: GridBasedClustering.h:451
GridBasedClustering(Metric metric, const std::vector< double > &data_x, const std::vector< double > &data_y, const std::vector< int > &properties_A, const std::vector< int > &properties_B, std::vector< double > grid_spacing_x, std::vector< double > grid_spacing_y)
initialises all data structures
Definition: GridBasedClustering.h:122
void cluster()
performs the hierarchical clustering (merges clusters until their dimension exceeds that of cell)
Definition: GridBasedClustering.h:156
GridBasedCluster::Point Point
cluster centre, cluster bounding box, grid index
Definition: GridBasedClustering.h:106
std::unordered_multimap< int, std::multiset< MinimumDistance >::const_iterator > reverse_nns_
reverse nearest neighbor lookup table for finding out which clusters need to be updated faster
Definition: GridBasedClustering.h:457
std::multiset< MinimumDistance >::const_iterator MultisetIterator
Definition: GridBasedClustering.h:109
std::map< int, GridBasedCluster > clusters_
list of clusters maps cluster indices to clusters
Definition: GridBasedClustering.h:439
std::unordered_multimap< int, MultisetIterator >::const_iterator NNIterator
Definition: GridBasedClustering.h:110
std::map< int, GridBasedCluster > clusters_final_
list of final clusters i.e. clusters that are no longer merged
Definition: GridBasedClustering.h:445
void eraseMinDistance_(const std::multiset< MinimumDistance >::const_iterator it)
remove minimum distance object and its related data
Definition: GridBasedClustering.h:642
ClusteringGrid::CellIndex CellIndex
Definition: GridBasedClustering.h:108
std::map< int, GridBasedCluster > getResults() const
returns final results (mapping of cluster indices to clusters)
Definition: GridBasedClustering.h:417
PositionType const & maxPosition() const
Accessor to maximum position.
Definition: DIntervalBase.h:104
CoordinateType maxY() const
Accessor for max_ coordinate maximum.
Definition: DIntervalBase.h:286
CoordinateType minY() const
Accessor for max_ coordinate minimum.
Definition: DIntervalBase.h:274
PositionType const & minPosition() const
Accessor to minimum position.
Definition: DIntervalBase.h:98
basic data structure for distances between clusters
Definition: GridBasedClustering.h:35
MinimumDistance()
hide default constructor
bool operator>(const MinimumDistance &other) const
int getClusterIndex() const
returns cluster index
MinimumDistance(const int &cluster_index, const int &nearest_neighbour_index, const double &distance)
constructor
int nearest_neighbour_index_
index of the nearest neighbour of the above cluster
Definition: GridBasedClustering.h:74
int getNearestNeighbourIndex() const
returns index of nearest cluster
double distance_
distance between cluster and its nearest neighbour
Definition: GridBasedClustering.h:79
bool operator==(const MinimumDistance &other) const
int cluster_index_
index in the cluster list
Definition: GridBasedClustering.h:69
bool operator<(const MinimumDistance &other) const
operators for comparisons (for multiset)
Base class for all classes that want to report their progress.
Definition: ProgressLogger.h:27
void setProgress(SignedSize value) const
Sets the current progress.
void startProgress(SignedSize begin, SignedSize end, const String &label) const
Initializes the progress display.
void endProgress(UInt64 bytes_processed=0) const
A more convenient string class.
Definition: String.h:34
size_t Size
Size type e.g. used as variable which can hold result of size()
Definition: Types.h:101
const double c
Definition: Constants.h:188
Main OpenMS namespace.
Definition: FeatureDeconvolution.h:22