svf-tools 1.0.285 → 1.0.286
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.TXT +6 -4
- package/SVF-doxygen/html/html/dir_63dba4c559aa5986900c35e27974bafc.html +83 -0
- package/SVF-doxygen/html/html/dir_97aefd0d527b934f1d99a682da8fe6a9.html +2 -0
- package/SVF-doxygen/html/html/dir_d1b325ac671111a54e189ae033ba710d.html +87 -0
- package/SVF-doxygen/html/html/dir_d44c64559bbebec7f509842c48db8b23.html +2 -0
- package/SVF-doxygen/html/html/fastcluster_8cpp.html +263 -0
- package/SVF-doxygen/html/html/fastcluster_8cpp_source.html +88 -0
- package/SVF-doxygen/html/html/fastcluster_8h.html +278 -0
- package/SVF-doxygen/html/html/fastcluster_8h_source.html +86 -0
- package/SVF-doxygen/html/html/fastcluster__R__dm_8cpp_8inc.html +79 -0
- package/SVF-doxygen/html/html/fastcluster__R__dm_8cpp_8inc_source.html +77 -0
- package/SVF-doxygen/html/html/fastcluster__dm_8cpp_8inc.html +89 -0
- package/SVF-doxygen/html/html/fastcluster__dm_8cpp_8inc_source.html +80 -0
- package/SVF-doxygen/html/html/files.html +220 -214
- package/SVF-doxygen/html/html/globals_c.html +82 -74
- package/SVF-doxygen/html/html/globals_enum.html +3 -0
- package/SVF-doxygen/html/html/globals_eval.html +19 -0
- package/SVF-doxygen/html/html/globals_f.html +6 -3
- package/SVF-doxygen/html/html/globals_func_c.html +46 -38
- package/SVF-doxygen/html/html/globals_func_f.html +3 -0
- package/SVF-doxygen/html/html/globals_func_h.html +4 -0
- package/SVF-doxygen/html/html/globals_h.html +22 -0
- package/SVF-doxygen/html/html/globals_r.html +3 -3
- package/SVF-doxygen/html/html/globals_s.html +7 -9
- package/SVF-doxygen/html/html/menudata.js +1 -0
- package/SVF-doxygen/html/html/search/all_12.js +1 -1
- package/SVF-doxygen/html/html/search/all_13.js +4 -4
- package/SVF-doxygen/html/html/search/all_3.js +2 -0
- package/SVF-doxygen/html/html/search/all_6.js +5 -0
- package/SVF-doxygen/html/html/search/all_8.js +7 -0
- package/SVF-doxygen/html/html/search/enums_4.js +1 -2
- package/SVF-doxygen/html/html/search/enums_5.js +2 -2
- package/SVF-doxygen/html/html/search/enums_6.js +2 -3
- package/SVF-doxygen/html/html/search/enums_7.js +3 -6
- package/SVF-doxygen/html/html/search/enums_8.js +6 -1
- package/SVF-doxygen/html/html/search/enums_9.js +1 -5
- package/SVF-doxygen/html/html/search/enums_a.js +5 -1
- package/SVF-doxygen/html/html/search/enums_b.js +1 -4
- package/SVF-doxygen/html/html/search/enums_c.html +26 -0
- package/SVF-doxygen/html/html/search/enums_c.js +7 -0
- package/SVF-doxygen/html/html/search/enumvalues_7.js +5 -0
- package/SVF-doxygen/html/html/search/files_5.js +4 -0
- package/SVF-doxygen/html/html/search/functions_2.js +2 -0
- package/SVF-doxygen/html/html/search/functions_5.js +1 -0
- package/SVF-doxygen/html/html/search/functions_7.js +1 -0
- package/SVF-doxygen/html/html/search/searchdata.js +1 -1
- package/include/FastCluster/LICENSE.TXT +13 -0
- package/include/FastCluster/fastcluster.h +79 -0
- package/lib/CMakeLists.txt +4 -1
- package/lib/FastCluster/LICENSE.TXT +13 -0
- package/lib/FastCluster/fastcluster.cpp +170 -0
- package/lib/FastCluster/fastcluster_R_dm.cpp.inc +115 -0
- package/lib/FastCluster/fastcluster_dm.cpp.inc +1795 -0
- package/package.json +1 -1
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
//
|
|
2
|
+
// C++ standalone verion of fastcluster by Daniel Müllner
|
|
3
|
+
//
|
|
4
|
+
// Copyright: Christoph Dalitz, 2020
|
|
5
|
+
// Daniel Müllner, 2011
|
|
6
|
+
// License: BSD style license
|
|
7
|
+
// (see the file LICENSE for details)
|
|
8
|
+
//
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
#include <assert.h>
|
|
12
|
+
#include <vector>
|
|
13
|
+
#include <algorithm>
|
|
14
|
+
|
|
15
|
+
#include "FastCluster/fastcluster.h"
|
|
16
|
+
|
|
17
|
+
// Code by Daniel Müllner
|
|
18
|
+
// workaround to make it usable as a standalone version (without R)
|
|
19
|
+
bool fc_isnan(double x) { return false; }
|
|
20
|
+
#include "fastcluster_dm.cpp.inc"
|
|
21
|
+
#include "fastcluster_R_dm.cpp.inc"
|
|
22
|
+
|
|
23
|
+
//
|
|
24
|
+
// Assigns cluster labels (0, ..., nclust-1) to the n points such
|
|
25
|
+
// that the cluster result is split into nclust clusters.
|
|
26
|
+
//
|
|
27
|
+
// Input arguments:
|
|
28
|
+
// n = number of observables
|
|
29
|
+
// merge = clustering result in R format
|
|
30
|
+
// nclust = number of clusters
|
|
31
|
+
// Output arguments:
|
|
32
|
+
// labels = allocated integer array of size n for result
|
|
33
|
+
//
|
|
34
|
+
void cutree_k(int n, const int* merge, int nclust, int* labels) {
|
|
35
|
+
|
|
36
|
+
int k,m1,m2,j,l;
|
|
37
|
+
|
|
38
|
+
if (nclust > n || nclust < 2) {
|
|
39
|
+
for (j=0; j<n; j++) labels[j] = 0;
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// assign to each observable the number of its last merge step
|
|
44
|
+
// beware: indices of observables in merge start at 1 (R convention)
|
|
45
|
+
std::vector<int> last_merge(n, 0);
|
|
46
|
+
for (k=1; k<=(n-nclust); k++) {
|
|
47
|
+
// (m1,m2) = merge[k,]
|
|
48
|
+
m1 = merge[k-1];
|
|
49
|
+
m2 = merge[n-1+k-1];
|
|
50
|
+
if (m1 < 0 && m2 < 0) { // both single observables
|
|
51
|
+
last_merge[-m1-1] = last_merge[-m2-1] = k;
|
|
52
|
+
}
|
|
53
|
+
else if (m1 < 0 || m2 < 0) { // one is a cluster
|
|
54
|
+
if(m1 < 0) { j = -m1; m1 = m2; } else j = -m2;
|
|
55
|
+
// merging single observable and cluster
|
|
56
|
+
for(l = 0; l < n; l++)
|
|
57
|
+
if (last_merge[l] == m1)
|
|
58
|
+
last_merge[l] = k;
|
|
59
|
+
last_merge[j-1] = k;
|
|
60
|
+
}
|
|
61
|
+
else { // both cluster
|
|
62
|
+
for(l=0; l < n; l++) {
|
|
63
|
+
if( last_merge[l] == m1 || last_merge[l] == m2 )
|
|
64
|
+
last_merge[l] = k;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// assign cluster labels
|
|
70
|
+
int label = 0;
|
|
71
|
+
std::vector<int> z(n,-1);
|
|
72
|
+
for (j=0; j<n; j++) {
|
|
73
|
+
if (last_merge[j] == 0) { // still singleton
|
|
74
|
+
labels[j] = label++;
|
|
75
|
+
} else {
|
|
76
|
+
if (z[last_merge[j]] < 0) {
|
|
77
|
+
z[last_merge[j]] = label++;
|
|
78
|
+
}
|
|
79
|
+
labels[j] = z[last_merge[j]];
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
//
|
|
85
|
+
// Assigns cluster labels (0, ..., nclust-1) to the n points such
|
|
86
|
+
// that the hierarchical clustering is stopped when cluster distance >= cdist
|
|
87
|
+
//
|
|
88
|
+
// Input arguments:
|
|
89
|
+
// n = number of observables
|
|
90
|
+
// merge = clustering result in R format
|
|
91
|
+
// height = cluster distance at each merge step
|
|
92
|
+
// cdist = cutoff cluster distance
|
|
93
|
+
// Output arguments:
|
|
94
|
+
// labels = allocated integer array of size n for result
|
|
95
|
+
//
|
|
96
|
+
void cutree_cdist(int n, const int* merge, double* height, double cdist, int* labels) {
|
|
97
|
+
|
|
98
|
+
int k;
|
|
99
|
+
|
|
100
|
+
for (k=0; k<(n-1); k++) {
|
|
101
|
+
if (height[k] >= cdist) {
|
|
102
|
+
break;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
cutree_k(n, merge, n-k, labels);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
//
|
|
110
|
+
// Hierarchical clustering with one of Daniel Muellner's fast algorithms
|
|
111
|
+
//
|
|
112
|
+
// Input arguments:
|
|
113
|
+
// n = number of observables
|
|
114
|
+
// distmat = condensed distance matrix, i.e. an n*(n-1)/2 array representing
|
|
115
|
+
// the upper triangle (without diagonal elements) of the distance
|
|
116
|
+
// matrix, e.g. for n=4:
|
|
117
|
+
// d00 d01 d02 d03
|
|
118
|
+
// d10 d11 d12 d13 -> d01 d02 d03 d12 d13 d23
|
|
119
|
+
// d20 d21 d22 d23
|
|
120
|
+
// d30 d31 d32 d33
|
|
121
|
+
// method = cluster metric (see enum hclust_fast_methods)
|
|
122
|
+
// Output arguments:
|
|
123
|
+
// merge = allocated (n-1)x2 matrix (2*(n-1) array) for storing result.
|
|
124
|
+
// Result follows R hclust convention:
|
|
125
|
+
// - observabe indices start with one
|
|
126
|
+
// - merge[i][] contains the merged nodes in step i
|
|
127
|
+
// - merge[i][j] is negative when the node is an atom
|
|
128
|
+
// height = allocated (n-1) array with distances at each merge step
|
|
129
|
+
// Return code:
|
|
130
|
+
// 0 = ok
|
|
131
|
+
// 1 = invalid method
|
|
132
|
+
//
|
|
133
|
+
int hclust_fast(int n, double* distmat, int method, int* merge, double* height) {
|
|
134
|
+
|
|
135
|
+
// call appropriate culstering function
|
|
136
|
+
cluster_result Z2(n-1);
|
|
137
|
+
if (method == HCLUST_METHOD_SINGLE) {
|
|
138
|
+
// single link
|
|
139
|
+
MST_linkage_core(n, distmat, Z2);
|
|
140
|
+
}
|
|
141
|
+
else if (method == HCLUST_METHOD_COMPLETE) {
|
|
142
|
+
// complete link
|
|
143
|
+
NN_chain_core<METHOD_METR_COMPLETE, t_float>(n, distmat, NULL, Z2);
|
|
144
|
+
}
|
|
145
|
+
else if (method == HCLUST_METHOD_AVERAGE) {
|
|
146
|
+
// best average distance
|
|
147
|
+
double* members = new double[n];
|
|
148
|
+
for (int i=0; i<n; i++) members[i] = 1;
|
|
149
|
+
NN_chain_core<METHOD_METR_AVERAGE, t_float>(n, distmat, members, Z2);
|
|
150
|
+
delete[] members;
|
|
151
|
+
}
|
|
152
|
+
else if (method == HCLUST_METHOD_MEDIAN) {
|
|
153
|
+
// best median distance (beware: O(n^3))
|
|
154
|
+
generic_linkage<METHOD_METR_MEDIAN, t_float>(n, distmat, NULL, Z2);
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
return 1;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
int* order = new int[n];
|
|
161
|
+
if (method == HCLUST_METHOD_MEDIAN) {
|
|
162
|
+
generate_R_dendrogram<true>(merge, height, order, Z2, n);
|
|
163
|
+
} else {
|
|
164
|
+
generate_R_dendrogram<false>(merge, height, order, Z2, n);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
delete[] order; // only needed for visualization
|
|
168
|
+
|
|
169
|
+
return 0;
|
|
170
|
+
}
|
|
@@ -0,0 +1,115 @@
|
|
|
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
|
+
/* Parameters:
|
|
14
|
+
N : number of data points
|
|
15
|
+
merge : (N-1)×2 array which specifies the node indices which are
|
|
16
|
+
merged in each step of the clustering procedure.
|
|
17
|
+
Negative entries -1...-N point to singleton nodes, while
|
|
18
|
+
positive entries 1...(N-1) point to nodes which are themselves
|
|
19
|
+
parents of other nodes.
|
|
20
|
+
node_size : array of node sizes - makes it easier
|
|
21
|
+
order : output array of size N
|
|
22
|
+
|
|
23
|
+
Runtime: Θ(N)
|
|
24
|
+
*/
|
|
25
|
+
auto_array_ptr<pos_node> queue(N/2);
|
|
26
|
+
|
|
27
|
+
int parent;
|
|
28
|
+
int child;
|
|
29
|
+
t_index pos = 0;
|
|
30
|
+
|
|
31
|
+
queue[0].pos = 0;
|
|
32
|
+
queue[0].node = N-2;
|
|
33
|
+
t_index idx = 1;
|
|
34
|
+
|
|
35
|
+
do {
|
|
36
|
+
--idx;
|
|
37
|
+
pos = queue[idx].pos;
|
|
38
|
+
parent = queue[idx].node;
|
|
39
|
+
|
|
40
|
+
// First child
|
|
41
|
+
child = merge[parent];
|
|
42
|
+
if (child<0) { // singleton node, write this into the 'order' array.
|
|
43
|
+
order[pos] = -child;
|
|
44
|
+
++pos;
|
|
45
|
+
}
|
|
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
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
queue[idx].pos = pos;
|
|
60
|
+
queue[idx].node = child-1;
|
|
61
|
+
++idx;
|
|
62
|
+
}
|
|
63
|
+
} while (idx>0);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
#define size_(r_) ( ((r_<N) ? 1 : node_size[r_-N]) )
|
|
67
|
+
|
|
68
|
+
template <const bool sorted>
|
|
69
|
+
void generate_R_dendrogram(int * const merge, double * const height, int * const order, cluster_result & Z2, const int N) {
|
|
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
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
node1 = nodes.Find(Z2[i]->node1);
|
|
89
|
+
node2 = nodes.Find(Z2[i]->node2);
|
|
90
|
+
// Merge the nodes in the union-find data structure by making them
|
|
91
|
+
// children of a new node.
|
|
92
|
+
nodes.Union(node1, node2);
|
|
93
|
+
}
|
|
94
|
+
// Sort the nodes in the output array.
|
|
95
|
+
if (node1>node2) {
|
|
96
|
+
t_index tmp = node1;
|
|
97
|
+
node1 = node2;
|
|
98
|
+
node2 = tmp;
|
|
99
|
+
}
|
|
100
|
+
/* Conversion between labeling conventions.
|
|
101
|
+
Input: singleton nodes 0,...,N-1
|
|
102
|
+
compound nodes N,...,2N-2
|
|
103
|
+
Output: singleton nodes -1,...,-N
|
|
104
|
+
compound nodes 1,...,N
|
|
105
|
+
*/
|
|
106
|
+
merge[i] = (node1<N) ? -static_cast<int>(node1)-1
|
|
107
|
+
: static_cast<int>(node1)-N+1;
|
|
108
|
+
merge[i+N-1] = (node2<N) ? -static_cast<int>(node2)-1
|
|
109
|
+
: static_cast<int>(node2)-N+1;
|
|
110
|
+
height[i] = Z2[i]->dist;
|
|
111
|
+
node_size[i] = size_(node1) + size_(node2);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
order_nodes(N, merge, node_size, order);
|
|
115
|
+
}
|