@euphrasiologist/lwphylo 1.2.26 → 1.3.0
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/README.md +5 -6
- package/dist/index.cjs +80 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +80 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -938,6 +938,85 @@ function parentFisheye(d, data) {
|
|
|
938
938
|
return parent ? { px: parent.fisheye.x, py: parent.fisheye.y } : null;
|
|
939
939
|
}
|
|
940
940
|
|
|
941
|
+
/**
|
|
942
|
+
* Generate a random bifurcating tree with `nTips` tips, in the same
|
|
943
|
+
* parent/children node shape produced by readTree().
|
|
944
|
+
*
|
|
945
|
+
* Topology is grown by repeatedly picking a random extant lineage to split
|
|
946
|
+
* (a Yule/coalescent-style process), so internal branching order is random
|
|
947
|
+
* rather than a fixed balanced/caterpillar shape. Branch lengths are drawn
|
|
948
|
+
* uniformly from [0, maxBranchLength).
|
|
949
|
+
*/
|
|
950
|
+
|
|
951
|
+
function randomTree(nTips = 10, {
|
|
952
|
+
maxBranchLength = 1,
|
|
953
|
+
labelPrefix = 't',
|
|
954
|
+
seed = null
|
|
955
|
+
} = {}) {
|
|
956
|
+
if (!Number.isInteger(nTips) || nTips < 1) {
|
|
957
|
+
throw new Error("nTips must be a positive integer");
|
|
958
|
+
}
|
|
959
|
+
|
|
960
|
+
const random = seed == null ? Math.random : mulberry32(seed);
|
|
961
|
+
|
|
962
|
+
let nodeId = 0;
|
|
963
|
+
const makeNode = (parent) => ({
|
|
964
|
+
parent,
|
|
965
|
+
children: [],
|
|
966
|
+
id: nodeId++,
|
|
967
|
+
label: '',
|
|
968
|
+
branchLength: null
|
|
969
|
+
});
|
|
970
|
+
|
|
971
|
+
const root = makeNode(null);
|
|
972
|
+
|
|
973
|
+
if (nTips === 1) {
|
|
974
|
+
root.label = `${labelPrefix}1`;
|
|
975
|
+
return root;
|
|
976
|
+
}
|
|
977
|
+
|
|
978
|
+
// start with two lineages hanging off the root
|
|
979
|
+
let lineages = [makeNode(root), makeNode(root)];
|
|
980
|
+
root.children.push(...lineages);
|
|
981
|
+
|
|
982
|
+
// repeatedly split a random lineage until we have nTips of them
|
|
983
|
+
while (lineages.length < nTips) {
|
|
984
|
+
const i = Math.floor(random() * lineages.length);
|
|
985
|
+
const parent = lineages[i];
|
|
986
|
+
const left = makeNode(parent);
|
|
987
|
+
const right = makeNode(parent);
|
|
988
|
+
parent.children.push(left, right);
|
|
989
|
+
lineages.splice(i, 1, left, right);
|
|
990
|
+
}
|
|
991
|
+
|
|
992
|
+
// assign branch lengths to every non-root node, and tip labels in
|
|
993
|
+
// left-to-right order
|
|
994
|
+
let tipIndex = 0;
|
|
995
|
+
const assign = (node) => {
|
|
996
|
+
for (const child of node.children) {
|
|
997
|
+
child.branchLength = random() * maxBranchLength;
|
|
998
|
+
assign(child);
|
|
999
|
+
}
|
|
1000
|
+
if (node.children.length === 0) {
|
|
1001
|
+
node.label = `${labelPrefix}${++tipIndex}`;
|
|
1002
|
+
}
|
|
1003
|
+
};
|
|
1004
|
+
assign(root);
|
|
1005
|
+
|
|
1006
|
+
return root;
|
|
1007
|
+
}
|
|
1008
|
+
|
|
1009
|
+
// small deterministic PRNG so `seed` gives reproducible trees
|
|
1010
|
+
function mulberry32(seed) {
|
|
1011
|
+
let a = seed >>> 0;
|
|
1012
|
+
return function () {
|
|
1013
|
+
a |= 0; a = (a + 0x6D2B79F5) | 0;
|
|
1014
|
+
let t = Math.imul(a ^ (a >>> 15), 1 | a);
|
|
1015
|
+
t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;
|
|
1016
|
+
return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
|
|
1017
|
+
};
|
|
1018
|
+
}
|
|
1019
|
+
|
|
941
1020
|
/**
|
|
942
1021
|
* Parse a Newick tree string into a doubly-linked list of JS Objects.
|
|
943
1022
|
* Assigns labels, branch lengths, and node IDs (tips before internals if input emits them that way).
|
|
@@ -1834,5 +1913,5 @@ function drawPhylogeny(
|
|
|
1834
1913
|
}
|
|
1835
1914
|
}
|
|
1836
1915
|
|
|
1837
|
-
export { describeArc, describeArcSweep, drawPhylogeny, parentFisheye, phisheye, polarToCartesian, radialLayout, readTree, rectangleLayout, subTree, unrooted };
|
|
1916
|
+
export { describeArc, describeArcSweep, drawPhylogeny, parentFisheye, phisheye, polarToCartesian, radialLayout, randomTree, readTree, rectangleLayout, subTree, unrooted };
|
|
1838
1917
|
//# sourceMappingURL=index.js.map
|