ATTPCROOT  0.3.0-alpha
A ROOT-based framework for analyzing data from active target detectors
fastcluster_R_dm.cxx
Go to the documentation of this file.
1 //
2 // Excerpt from fastcluster_R.cpp
3 //
4 // Copyright: Daniel Müllner, 2011 <http://danifold.net>
5 //
6 
7 struct pos_node {
8  t_index pos;
9  int node;
10 };
11 
12 void order_nodes(const int N, const int *const merge, const t_index *const node_size, int *const order)
13 {
14  /* Parameters:
15  N : number of data points
16  merge : (N-1)×2 array which specifies the node indices which are
17  merged in each step of the clustering procedure.
18  Negative entries -1...-N point to singleton nodes, while
19  positive entries 1...(N-1) point to nodes which are themselves
20  parents of other nodes.
21  node_size : array of node sizes - makes it easier
22  order : output array of size N
23 
24  Runtime: Θ(N)
25  */
26  auto_array_ptr<pos_node> queue(N / 2);
27 
28  int parent;
29  int child;
30  t_index pos = 0;
31 
32  queue[0].pos = 0;
33  queue[0].node = N - 2;
34  t_index idx = 1;
35 
36  do {
37  --idx;
38  pos = queue[idx].pos;
39  parent = queue[idx].node;
40 
41  // First child
42  child = merge[parent];
43  if (child < 0) { // singleton node, write this into the 'order' array.
44  order[pos] = -child;
45  ++pos;
46  } else { /* compound node: put it on top of the queue and decompose it
47  in a later iteration. */
48  queue[idx].pos = pos;
49  queue[idx].node = child - 1; // convert index-1 based to index-0 based
50  ++idx;
51  pos += node_size[child - 1];
52  }
53  // Second child
54  child = merge[parent + N - 1];
55  if (child < 0) {
56  order[pos] = -child;
57  } else {
58  queue[idx].pos = pos;
59  queue[idx].node = child - 1;
60  ++idx;
61  }
62  } while (idx > 0);
63 }
64 
65 #define size_(r_) (((r_ < N) ? 1 : node_size[r_ - N]))
66 
67 template <const bool sorted>
68 void generate_R_dendrogram(int *const merge, double *const height, int *const order, cluster_result &Z2, const int N)
69 {
70  // The array "nodes" is a union-find data structure for the cluster
71  // identites (only needed for unsorted cluster_result input).
72  union_find nodes(sorted ? 0 : N);
73  if (!sorted) {
74  std::stable_sort(Z2[0], Z2[N - 1]);
75  }
76 
77  t_index node1, node2;
78  auto_array_ptr<t_index> node_size(N - 1);
79 
80  for (t_index i = 0; i < N - 1; ++i) {
81  // Get two data points whose clusters are merged in step i.
82  // Find the cluster identifiers for these points.
83  if (sorted) {
84  node1 = Z2[i]->node1;
85  node2 = Z2[i]->node2;
86  } else {
87  node1 = nodes.Find(Z2[i]->node1);
88  node2 = nodes.Find(Z2[i]->node2);
89  // Merge the nodes in the union-find data structure by making them
90  // children of a new node.
91  nodes.Union(node1, node2);
92  }
93  // Sort the nodes in the output array.
94  if (node1 > node2) {
95  t_index tmp = node1;
96  node1 = node2;
97  node2 = tmp;
98  }
99  /* Conversion between labeling conventions.
100  Input: singleton nodes 0,...,N-1
101  compound nodes N,...,2N-2
102  Output: singleton nodes -1,...,-N
103  compound nodes 1,...,N
104  */
105  merge[i] = (node1 < N) ? -static_cast<int>(node1) - 1 : static_cast<int>(node1) - N + 1;
106  merge[i + N - 1] = (node2 < N) ? -static_cast<int>(node2) - 1 : static_cast<int>(node2) - N + 1;
107  height[i] = Z2[i]->dist;
108  node_size[i] = size_(node1) + size_(node2);
109  }
110 
111  order_nodes(N, merge, node_size, order);
112 }
auto_array_ptr
Definition: fastcluster_dm.cxx:177
order_nodes
void order_nodes(const int N, const int *const merge, const t_index *const node_size, int *const order)
Definition: fastcluster_R_dm.cxx:12
union_find::Find
t_index Find(t_index idx) const
Definition: fastcluster_dm.cxx:363
union_find::Union
void Union(const t_index node1, const t_index node2)
Definition: fastcluster_dm.cxx:383
t_index
int_fast32_t t_index
Definition: fastcluster_dm.cxx:129
cluster_result
Definition: fastcluster_dm.cxx:223
union_find
Definition: fastcluster_dm.cxx:355
pos_node::pos
t_index pos
Definition: fastcluster_R_dm.cxx:8
pos_node
Definition: fastcluster_R_dm.cxx:7
generate_R_dendrogram
void generate_R_dendrogram(int *const merge, double *const height, int *const order, cluster_result &Z2, const int N)
Definition: fastcluster_R_dm.cxx:68
size_
#define size_(r_)
Definition: fastcluster_R_dm.cxx:65
pos_node::node
int node
Definition: fastcluster_R_dm.cxx:9