@figtreejs/core 0.1.0-beta.2 → 0.1.0-beta.4
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/dist/index.cjs +2 -2
- package/dist/index.d.ts +12 -2
- package/dist/index.mjs +1955 -1887
- package/package.json +1 -1
- package/src/evo/tree/normalized-tree/immutable-tree.test.ts +46 -1
- package/src/evo/tree/normalized-tree/immutable-tree.ts +149 -23
- package/src/layouts/functional/radial-layout.ts +54 -26
- package/src/tests/baubles/__snapshots__/branch-labels.test.tsx.snap +16 -16
- package/src/tests/baubles/__snapshots__/node-labels.test.tsx.snap +34 -34
- package/src/tests/layouts/radiallayout.test.ts +4 -4
package/package.json
CHANGED
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
//TODO test immutable tree include tests that check nodes to roots update as well.
|
|
2
2
|
|
|
3
3
|
import { notNull, u } from "../../../utils/maybe";
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
ImmutableTree,
|
|
6
|
+
postOrderIterator,
|
|
7
|
+
preOrderIterator,
|
|
8
|
+
psuedoRootPostOrderIterator,
|
|
9
|
+
psuedoRootPreOrderIterator,
|
|
10
|
+
} from "./immutable-tree";
|
|
5
11
|
import { describe, it, expect } from "vitest";
|
|
6
12
|
|
|
7
13
|
describe("ImmutableTree", () => {
|
|
@@ -156,3 +162,42 @@ describe("testing annotating", () => {
|
|
|
156
162
|
annotatedTree.getAnnotation(A, "state");
|
|
157
163
|
});
|
|
158
164
|
});
|
|
165
|
+
//. -----2 (A)
|
|
166
|
+
// |
|
|
167
|
+
// -------1
|
|
168
|
+
// | |
|
|
169
|
+
// 0 ------3 (B)
|
|
170
|
+
// |
|
|
171
|
+
// -----4 (C)
|
|
172
|
+
describe("Tree traversals", () => {
|
|
173
|
+
it("preOrder", () => {
|
|
174
|
+
const tree = ImmutableTree.fromNewick("((A:1,B:1):1,C:2);");
|
|
175
|
+
const nodes = [...preOrderIterator(tree)];
|
|
176
|
+
expect(nodes.map((n) => n.number)).toEqual([0, 1, 2, 3, 4]);
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
it("postOrder", () => {
|
|
180
|
+
const tree = ImmutableTree.fromNewick("((A:1,B:1):1,C:2);");
|
|
181
|
+
const nodes = [...postOrderIterator(tree)];
|
|
182
|
+
expect(nodes.map((n) => n.number)).toEqual([2, 3, 1, 4, 0]);
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
it("pseudoRootPostOrder", () => {
|
|
186
|
+
const tree = ImmutableTree.fromNewick("((A:1,B:1):1,C:2);");
|
|
187
|
+
const nodes = [...psuedoRootPostOrderIterator(tree, tree.getNode("A"))];
|
|
188
|
+
expect(nodes.map((n) => n.number)).toEqual([3, 4, 0, 1, 2]);
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
it("pseudoRootPreOrder", () => {
|
|
192
|
+
const tree = ImmutableTree.fromNewick("((A:1,B:1):1,C:2);");
|
|
193
|
+
const nodes = [...psuedoRootPreOrderIterator(tree, tree.getNode("A"))];
|
|
194
|
+
expect(nodes.map((n) => n.number)).toEqual([2, 1, 3, 0, 4]);
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
it("pseudoRootPreOrder", () => {
|
|
198
|
+
const tree = ImmutableTree.fromNewick("((A:1,B:1):1,C:2);");
|
|
199
|
+
const rooted = tree.reroot(tree.getNode("A"));
|
|
200
|
+
const nodes = [...psuedoRootPreOrderIterator(rooted, tree.getNode("A"))];
|
|
201
|
+
expect(nodes.map((n) => n.number)).toEqual([2, 0, 1, 3, 4]);
|
|
202
|
+
});
|
|
203
|
+
});
|
|
@@ -21,7 +21,7 @@ import { immerable, produce } from "immer";
|
|
|
21
21
|
import type { Taxon, TaxonSetInterface } from "../taxa/taxon";
|
|
22
22
|
import { TaxonSet } from "../taxa/taxon";
|
|
23
23
|
import { format } from "d3-format";
|
|
24
|
-
import { extent } from "d3-array";
|
|
24
|
+
import { extent, min } from "d3-array";
|
|
25
25
|
|
|
26
26
|
import {
|
|
27
27
|
MaybeType,
|
|
@@ -1200,24 +1200,69 @@ export function* preOrderIterator(
|
|
|
1200
1200
|
yield* traverse(node);
|
|
1201
1201
|
}
|
|
1202
1202
|
|
|
1203
|
-
//
|
|
1204
|
-
|
|
1203
|
+
// we want to traverse the tree in a consistent order
|
|
1204
|
+
// this requires ignoring the root when we hit it.
|
|
1205
|
+
function stableNodeNumber(tree: Tree, a: NodeRef, node: NodeRef) {
|
|
1206
|
+
let num;
|
|
1207
|
+
if (tree.isRoot(a)) {
|
|
1208
|
+
num = min(
|
|
1209
|
+
tree.getChildren(a).filter((child) => child.number != node.number),
|
|
1210
|
+
(n) => n.number,
|
|
1211
|
+
);
|
|
1212
|
+
} else {
|
|
1213
|
+
num = a.number;
|
|
1214
|
+
}
|
|
1215
|
+
return unNullify(
|
|
1216
|
+
num,
|
|
1217
|
+
"There was an error finding the path through the root. check the children",
|
|
1218
|
+
);
|
|
1219
|
+
}
|
|
1220
|
+
|
|
1221
|
+
type PseudoNode = NodeRef & {
|
|
1222
|
+
pseudoChildren: NodeRef[];
|
|
1223
|
+
pseudoLength: number | undefined;
|
|
1224
|
+
pseudoParent: NodeRef | undefined;
|
|
1225
|
+
};
|
|
1226
|
+
// children order will matter but parents are always added after children
|
|
1227
|
+
export function* psuedoRootPostOrderIterator(
|
|
1205
1228
|
tree: Tree,
|
|
1206
1229
|
node: NodeRef | undefined = undefined,
|
|
1207
|
-
sort: (a: NodeRef, b: NodeRef) => number = (a, b) => a.number - b.number,
|
|
1208
|
-
): Generator<
|
|
1230
|
+
// sort: (a: NodeRef, b: NodeRef) => number = (a, b) => a.number - b.number,
|
|
1231
|
+
): Generator<PseudoNode> {
|
|
1209
1232
|
const traverse = function* (
|
|
1210
1233
|
node: NodeRef,
|
|
1211
1234
|
visited: number | undefined = undefined,
|
|
1212
|
-
): Generator<
|
|
1213
|
-
|
|
1214
|
-
const branches = [...tree.getChildren(node)
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1235
|
+
): Generator<PseudoNode> {
|
|
1236
|
+
// get from tree so we keep proxy when used in draft
|
|
1237
|
+
const branches = [...tree.getChildren(node)];
|
|
1238
|
+
if (!tree.isRoot(node)) {
|
|
1239
|
+
branches.push(tree.getParent(node));
|
|
1240
|
+
}
|
|
1241
|
+
const pseudoChildren = branches.filter((n) => n.number !== visited);
|
|
1242
|
+
const pseudoParent = branches.find((node) => node.number === visited);
|
|
1243
|
+
// branches.sort(sort);
|
|
1244
|
+
pseudoChildren.sort(
|
|
1245
|
+
(a, b) =>
|
|
1246
|
+
stableNodeNumber(tree, a, node) - stableNodeNumber(tree, b, node),
|
|
1247
|
+
);
|
|
1248
|
+
let pseudoLength = undefined;
|
|
1249
|
+
if (!tree.isRoot(node) && pseudoParent === tree.getParent(node)) {
|
|
1250
|
+
// the root will not have a parent
|
|
1251
|
+
pseudoLength = tree.getLength(node);
|
|
1252
|
+
} else {
|
|
1253
|
+
if (pseudoParent !== undefined) {
|
|
1254
|
+
pseudoLength = tree.getLength(pseudoParent);
|
|
1255
|
+
}
|
|
1256
|
+
}
|
|
1257
|
+
for (const someKid of pseudoChildren) {
|
|
1258
|
+
yield* traverse(someKid, node.number);
|
|
1220
1259
|
}
|
|
1260
|
+
yield {
|
|
1261
|
+
...tree.getNode(node.number),
|
|
1262
|
+
pseudoLength,
|
|
1263
|
+
pseudoChildren,
|
|
1264
|
+
pseudoParent,
|
|
1265
|
+
};
|
|
1221
1266
|
};
|
|
1222
1267
|
|
|
1223
1268
|
if (node === undefined) {
|
|
@@ -1226,24 +1271,48 @@ export function* psuedoRootPreOrderIterator(
|
|
|
1226
1271
|
yield* traverse(node);
|
|
1227
1272
|
}
|
|
1228
1273
|
|
|
1229
|
-
|
|
1274
|
+
// children order will matter but parents are always added after children
|
|
1275
|
+
export function* psuedoRootPreOrderIterator(
|
|
1230
1276
|
tree: Tree,
|
|
1231
1277
|
node: NodeRef | undefined = undefined,
|
|
1232
|
-
sort: (a: NodeRef, b: NodeRef) => number = (a, b) => a.number - b.number,
|
|
1233
|
-
): Generator<
|
|
1278
|
+
// sort: (a: NodeRef, b: NodeRef) => number = (a, b) => a.number - b.number,
|
|
1279
|
+
): Generator<PseudoNode> {
|
|
1234
1280
|
const traverse = function* (
|
|
1235
1281
|
node: NodeRef,
|
|
1236
1282
|
visited: number | undefined = undefined,
|
|
1237
|
-
): Generator<
|
|
1283
|
+
): Generator<PseudoNode> {
|
|
1238
1284
|
// get from tree so we keep proxy when used in draft
|
|
1239
|
-
const branches = [...tree.getChildren(node)
|
|
1240
|
-
|
|
1285
|
+
const branches = [...tree.getChildren(node)];
|
|
1286
|
+
if (!tree.isRoot(node)) {
|
|
1287
|
+
branches.push(tree.getParent(node));
|
|
1288
|
+
}
|
|
1289
|
+
|
|
1290
|
+
const pseudoChildren = branches.filter((n) => n.number !== visited);
|
|
1291
|
+
const pseudoParent = branches.find((node) => node.number === visited);
|
|
1292
|
+
pseudoChildren.sort(
|
|
1293
|
+
(a, b) =>
|
|
1294
|
+
stableNodeNumber(tree, a, node) - stableNodeNumber(tree, b, node),
|
|
1241
1295
|
);
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1296
|
+
let pseudoLength = undefined;
|
|
1297
|
+
if (!tree.isRoot(node) && pseudoParent === tree.getParent(node)) {
|
|
1298
|
+
// the root will not have a parent
|
|
1299
|
+
pseudoLength = tree.getLength(node);
|
|
1300
|
+
} else {
|
|
1301
|
+
if (pseudoParent !== undefined) {
|
|
1302
|
+
pseudoLength = tree.getLength(pseudoParent);
|
|
1303
|
+
}
|
|
1304
|
+
}
|
|
1305
|
+
|
|
1306
|
+
yield {
|
|
1307
|
+
...tree.getNode(node.number),
|
|
1308
|
+
pseudoLength,
|
|
1309
|
+
pseudoChildren,
|
|
1310
|
+
pseudoParent,
|
|
1311
|
+
};
|
|
1312
|
+
|
|
1313
|
+
for (const someKid of pseudoChildren) {
|
|
1314
|
+
yield* traverse(someKid, node.number);
|
|
1245
1315
|
}
|
|
1246
|
-
yield tree.getNode(node.number);
|
|
1247
1316
|
};
|
|
1248
1317
|
|
|
1249
1318
|
if (node === undefined) {
|
|
@@ -1251,6 +1320,63 @@ export function* psuedoRootPostOrderIterator(
|
|
|
1251
1320
|
}
|
|
1252
1321
|
yield* traverse(node);
|
|
1253
1322
|
}
|
|
1323
|
+
|
|
1324
|
+
// children order will matter but parents are always added after children
|
|
1325
|
+
export function* pseudoTipIterator(
|
|
1326
|
+
tree: Tree,
|
|
1327
|
+
node: NodeRef | undefined,
|
|
1328
|
+
pseudoParent: NodeRef | undefined,
|
|
1329
|
+
): Generator<PseudoNode> {
|
|
1330
|
+
const traverse = function* (
|
|
1331
|
+
node: NodeRef,
|
|
1332
|
+
visited: number | undefined = undefined,
|
|
1333
|
+
): Generator<PseudoNode> {
|
|
1334
|
+
// get from tree so we keep proxy when used in draft
|
|
1335
|
+
const branches = [...tree.getChildren(node)];
|
|
1336
|
+
if (!tree.isRoot(node)) {
|
|
1337
|
+
branches.push(tree.getParent(node));
|
|
1338
|
+
}
|
|
1339
|
+
// branches.sort((a,b)=>a.number-b.number)
|
|
1340
|
+
const pseudoChildren = branches.filter((n) => n.number !== visited);
|
|
1341
|
+
const pseudoParent = branches.find((node) => node.number === visited);
|
|
1342
|
+
pseudoChildren.sort(
|
|
1343
|
+
(a, b) =>
|
|
1344
|
+
stableNodeNumber(tree, a, node) - stableNodeNumber(tree, b, node),
|
|
1345
|
+
);
|
|
1346
|
+
let pseudoLength = undefined;
|
|
1347
|
+
if (!tree.isRoot(node) && pseudoParent === tree.getParent(node)) {
|
|
1348
|
+
// the root will not have a parent
|
|
1349
|
+
pseudoLength = tree.getLength(node);
|
|
1350
|
+
} else {
|
|
1351
|
+
if (pseudoParent !== undefined) {
|
|
1352
|
+
pseudoLength = tree.getLength(pseudoParent);
|
|
1353
|
+
}
|
|
1354
|
+
}
|
|
1355
|
+
|
|
1356
|
+
if (pseudoChildren.length == 0) {
|
|
1357
|
+
yield {
|
|
1358
|
+
...tree.getNode(node.number),
|
|
1359
|
+
pseudoLength,
|
|
1360
|
+
pseudoChildren,
|
|
1361
|
+
pseudoParent,
|
|
1362
|
+
};
|
|
1363
|
+
} else {
|
|
1364
|
+
for (const someKid of pseudoChildren) {
|
|
1365
|
+
yield* traverse(someKid, node.number);
|
|
1366
|
+
}
|
|
1367
|
+
}
|
|
1368
|
+
};
|
|
1369
|
+
|
|
1370
|
+
if (node === undefined) {
|
|
1371
|
+
node = tree.getRoot();
|
|
1372
|
+
}
|
|
1373
|
+
if (pseudoParent !== undefined) {
|
|
1374
|
+
yield* traverse(node, pseudoParent.number);
|
|
1375
|
+
} else {
|
|
1376
|
+
yield* traverse(node);
|
|
1377
|
+
}
|
|
1378
|
+
}
|
|
1379
|
+
|
|
1254
1380
|
export function* postOrderIterator(
|
|
1255
1381
|
tree: Tree,
|
|
1256
1382
|
node: NodeRef | undefined = undefined,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ImmutableTree, NodeRef } from "../../evo";
|
|
2
|
-
import {
|
|
2
|
+
import { pseudoTipIterator, psuedoRootPreOrderIterator } from "../../evo";
|
|
3
3
|
import type { NodeLabelType } from "../types";
|
|
4
4
|
import { notNull } from "../../utils/maybe";
|
|
5
5
|
import type { FunctionalVertex } from "../types";
|
|
@@ -25,47 +25,63 @@ type data = {
|
|
|
25
25
|
|
|
26
26
|
export function radialLayout(
|
|
27
27
|
tree: ImmutableTree,
|
|
28
|
-
options: { spread?: number } = {},
|
|
28
|
+
options: { spread?: number; root?: NodeRef; startAngle?: number } = {},
|
|
29
29
|
): (node: NodeRef) => FunctionalVertex {
|
|
30
|
-
const {
|
|
30
|
+
const {
|
|
31
|
+
spread = 1,
|
|
32
|
+
root = tree.getRoot(),
|
|
33
|
+
startAngle = (2.5 * Math.PI) / 2,
|
|
34
|
+
} = options;
|
|
35
|
+
|
|
31
36
|
console.log("radial layout with spread", spread);
|
|
32
37
|
const map = new Map<NodeRef, FunctionalVertex>();
|
|
33
38
|
|
|
39
|
+
const fakeThroughRoot = tree.isRoot(root) && tree.getChildCount(root) == 2;
|
|
40
|
+
|
|
34
41
|
const dataStack: data[] = [
|
|
35
42
|
{
|
|
36
|
-
angleStart:
|
|
37
|
-
angleEnd: 2 * Math.PI,
|
|
43
|
+
angleStart: startAngle,
|
|
44
|
+
angleEnd: startAngle + 2 * Math.PI,
|
|
38
45
|
xpos: 0,
|
|
39
46
|
ypos: 0,
|
|
40
47
|
level: 0,
|
|
41
|
-
number:
|
|
48
|
+
number: root.number,
|
|
42
49
|
},
|
|
43
50
|
]; // TODO start tree.
|
|
44
|
-
|
|
51
|
+
|
|
52
|
+
for (const node of psuedoRootPreOrderIterator(tree, root)) {
|
|
45
53
|
const data = dataStack.pop();
|
|
46
54
|
notNull(data, `Internal Error, hit the end of the data stack unexpectedly`);
|
|
47
55
|
const { angleStart, angleEnd, xpos, ypos, level } = data;
|
|
48
56
|
|
|
49
|
-
const branchAngle = (
|
|
57
|
+
const branchAngle = (angleEnd + angleStart) / 2.0;
|
|
50
58
|
|
|
51
|
-
const length =
|
|
59
|
+
const length = node.pseudoLength !== undefined ? node.pseudoLength : 0;
|
|
52
60
|
|
|
53
61
|
const directionX = Math.cos(branchAngle);
|
|
54
62
|
const directionY = Math.sin(branchAngle);
|
|
55
63
|
const x = xpos + length * directionX;
|
|
56
64
|
const y = ypos + length * directionY;
|
|
57
65
|
|
|
58
|
-
|
|
66
|
+
// we want to give the impression we are traversing from the root.
|
|
67
|
+
const directionalUpdate = tree.isRoot(tree.getNode(node.number))
|
|
68
|
+
? 0
|
|
69
|
+
: node.pseudoParent === undefined ||
|
|
70
|
+
node.pseudoParent.number !== tree.getParent(node).number
|
|
71
|
+
? -Math.PI
|
|
72
|
+
: 0;
|
|
73
|
+
const nTheta = normalizeAngle(branchAngle - directionalUpdate);
|
|
74
|
+
|
|
75
|
+
const leftLabel = node.pseudoChildren.length > 0;
|
|
59
76
|
let dx, dy;
|
|
60
77
|
if (!leftLabel) {
|
|
61
|
-
dx = Math.cos(
|
|
62
|
-
dy = Math.sin(
|
|
78
|
+
dx = Math.cos(nTheta);
|
|
79
|
+
dy = Math.sin(nTheta);
|
|
63
80
|
} else {
|
|
64
|
-
dx = Math.cos(
|
|
65
|
-
dy = Math.sin(
|
|
81
|
+
dx = Math.cos(nTheta);
|
|
82
|
+
dy = Math.sin(nTheta);
|
|
66
83
|
}
|
|
67
84
|
|
|
68
|
-
const nTheta = normalizeAngle(branchAngle);
|
|
69
85
|
const vertex = {
|
|
70
86
|
x,
|
|
71
87
|
y,
|
|
@@ -81,11 +97,13 @@ export function radialLayout(
|
|
|
81
97
|
} as NodeLabelType,
|
|
82
98
|
};
|
|
83
99
|
|
|
84
|
-
if (
|
|
100
|
+
if (node.pseudoChildren.length > 0) {
|
|
85
101
|
const childLeafs: number[] = [];
|
|
86
102
|
let totalLeafs = 0;
|
|
87
|
-
for (let i = 0; i <
|
|
88
|
-
const leafCount = [
|
|
103
|
+
for (let i = 0; i < node.pseudoChildren.length; i++) {
|
|
104
|
+
const leafCount = [
|
|
105
|
+
...pseudoTipIterator(tree, node.pseudoChildren[i], node.pseudoParent),
|
|
106
|
+
].length;
|
|
89
107
|
childLeafs[i] = leafCount;
|
|
90
108
|
totalLeafs += leafCount;
|
|
91
109
|
}
|
|
@@ -93,15 +111,25 @@ export function radialLayout(
|
|
|
93
111
|
let span = angleEnd - angleStart;
|
|
94
112
|
let updatedAngleStart = angleStart;
|
|
95
113
|
|
|
96
|
-
|
|
114
|
+
// We don't want to adjust our path when we hit a degree 2 node or the root
|
|
115
|
+
// if we start at the root has 2 children. In that case we want the roo
|
|
116
|
+
// to sit on the middle of branch (even though it is really encoded as two branches)
|
|
117
|
+
|
|
118
|
+
if (node.pseudoChildren.length > 1) {
|
|
97
119
|
// span *= 1.0 + ((safeOpts.spread * Math.PI / 180) / 10.0);
|
|
98
|
-
|
|
99
|
-
|
|
120
|
+
console.log(fakeThroughRoot);
|
|
121
|
+
if (!fakeThroughRoot || !tree.isRoot(tree.getNode(node.number))) {
|
|
122
|
+
// this bumps the start angle so branches don't make a straight line.
|
|
123
|
+
// we want to inheret the open space from out parent, but also we want
|
|
124
|
+
// between 0 and 0.1 PI seem to be OK.
|
|
125
|
+
// this shoots for numbers between 0 and 100
|
|
126
|
+
span *= 1.0 + (spread / 1000) * Math.PI;
|
|
127
|
+
updatedAngleStart = branchAngle - span / 2.0;
|
|
128
|
+
}
|
|
100
129
|
}
|
|
101
|
-
|
|
130
|
+
console.log("here");
|
|
102
131
|
let a2 = updatedAngleStart;
|
|
103
|
-
|
|
104
|
-
for (let i = tree.getChildCount(node) - 1; i > -1; i--) {
|
|
132
|
+
for (let i = node.pseudoChildren.length - 1; i > -1; i--) {
|
|
105
133
|
// i think we need to go in reverse order here
|
|
106
134
|
const a1 = a2;
|
|
107
135
|
a2 = a1 + (span * childLeafs[i]) / totalLeafs;
|
|
@@ -111,11 +139,11 @@ export function radialLayout(
|
|
|
111
139
|
xpos: x,
|
|
112
140
|
ypos: y,
|
|
113
141
|
level: level + 1,
|
|
114
|
-
number:
|
|
142
|
+
number: node.pseudoChildren[i].number,
|
|
115
143
|
});
|
|
116
144
|
}
|
|
117
145
|
}
|
|
118
|
-
map.set(node, vertex);
|
|
146
|
+
map.set(tree.getNode(node.number), vertex);
|
|
119
147
|
}
|
|
120
148
|
|
|
121
149
|
return function (node: NodeRef): FunctionalVertex {
|
|
@@ -469,25 +469,25 @@ exports[`Branch labels > renders a tree node labels in radial layout 1`] = `
|
|
|
469
469
|
class="branch-layer"
|
|
470
470
|
>
|
|
471
471
|
<path
|
|
472
|
-
d="M
|
|
472
|
+
d="M 306.5924779152444 95.03594795523999 C306.5924779152444,95.03594795523999 233.18495583048883,190.07189591047998 233.18495583048883,190.07189591047998 C233.18495583048883,190.07189591047998 196.48119478811105,237.5898698881 178.12931426692217,261.34885687690996 C178.12931426692217,261.34885687690996 168.95337400632775,273.22835037131495 164.36540387603054,279.1680971185175 C164.36540387603054,279.1680971185175 162.07141881088194,282.1379704921187 160.92442627830764,283.6229071789194 C160.92442627830764,283.6229071789194 160.35093001202046,284.3653755223197 160.06418187887687,284.7366096940199 C160.06418187887687,284.7366096940199 159.7774337457333,285.10784386572 159.7774337457333,285.10784386572 "
|
|
473
473
|
fill="none"
|
|
474
474
|
stroke="black"
|
|
475
475
|
stroke-width="2"
|
|
476
476
|
/>
|
|
477
477
|
<path
|
|
478
|
-
d="M
|
|
478
|
+
d="M 159.7774337457333 285.10784386572 C159.7774337457333,285.10784386572 79.88871687286665,293.2946004927189 79.88871687286665,293.2946004927189 C79.88871687286665,293.2946004927189 39.944358436433326,297.38797880621837 19.972179218216663,299.4346679629681 C19.972179218216663,299.4346679629681 9.986089609108332,300.45801254134295 4.993044804554166,300.96968483053035 C4.993044804554166,300.96968483053035 2.496522402277083,301.2255209751241 1.2482612011385414,301.3534390474209 C1.2482612011385414,301.3534390474209 0.6241306005692707,301.41739808356937 0.31206530028463536,301.4493776016436 C0.31206530028463536,301.4493776016436 0,301.4813571197178 0,301.4813571197178 "
|
|
479
479
|
fill="none"
|
|
480
480
|
stroke="black"
|
|
481
481
|
stroke-width="2"
|
|
482
482
|
/>
|
|
483
483
|
<path
|
|
484
|
-
d="M
|
|
484
|
+
d="M 159.7774337457333 285.10784386572 C159.7774337457333,285.10784386572 196.69432122862028,332.55392193286 196.69432122862028,332.55392193286 C196.69432122862028,332.55392193286 215.15276497006377,356.27696096643 224.38198684078552,368.138480483215 C224.38198684078552,368.138480483215 228.9965977761464,374.06924024160753 231.30390324382682,377.03462012080377 C231.30390324382682,377.03462012080377 232.45755597766703,378.5173100604019 233.03438234458713,379.25865503020094 C233.03438234458713,379.25865503020094 233.3227955280472,379.6293275151005 233.46700211977725,379.81466375755025 C233.46700211977725,379.81466375755025 233.61120871150726,380 233.61120871150726,380 "
|
|
485
485
|
fill="none"
|
|
486
486
|
stroke="black"
|
|
487
487
|
stroke-width="2"
|
|
488
488
|
/>
|
|
489
489
|
<path
|
|
490
|
-
d="M
|
|
490
|
+
d="M 306.5924779152444 95.03594795523999 C306.5924779152444,95.03594795523999 343.2962389576222,47.517973977619995 343.2962389576222,47.517973977619995 C343.2962389576222,47.517973977619995 361.6481194788111,23.758986988809998 370.8240597394056,11.879493494404999 C370.8240597394056,11.879493494404999 375.4120298697028,5.939746747202499 377.7060149348514,2.9698733736012497 C377.7060149348514,2.9698733736012497 378.8530074674257,1.4849366868006248 379.4265037337128,0.7424683434003124 C379.4265037337128,0.7424683434003124 379.7132518668564,0.3712341717001562 379.8566259334282,0.1856170858500781 C379.8566259334282,0.1856170858500781 380,0 380,0 "
|
|
491
491
|
fill="none"
|
|
492
492
|
stroke="black"
|
|
493
493
|
stroke-width="2"
|
|
@@ -500,7 +500,7 @@ exports[`Branch labels > renders a tree node labels in radial layout 1`] = `
|
|
|
500
500
|
<text
|
|
501
501
|
alignment-baseline="baseline"
|
|
502
502
|
text-anchor="middle"
|
|
503
|
-
transform="translate(
|
|
503
|
+
transform="translate(233.18495583048883,184.07189591047998) rotate(0)"
|
|
504
504
|
>
|
|
505
505
|
Label!
|
|
506
506
|
</text>
|
|
@@ -509,7 +509,7 @@ exports[`Branch labels > renders a tree node labels in radial layout 1`] = `
|
|
|
509
509
|
<text
|
|
510
510
|
alignment-baseline="baseline"
|
|
511
511
|
text-anchor="middle"
|
|
512
|
-
transform="translate(
|
|
512
|
+
transform="translate(79.88871687286665,287.2946004927189) rotate(0)"
|
|
513
513
|
>
|
|
514
514
|
Label!
|
|
515
515
|
</text>
|
|
@@ -518,7 +518,7 @@ exports[`Branch labels > renders a tree node labels in radial layout 1`] = `
|
|
|
518
518
|
<text
|
|
519
519
|
alignment-baseline="baseline"
|
|
520
520
|
text-anchor="middle"
|
|
521
|
-
transform="translate(
|
|
521
|
+
transform="translate(196.69432122862028,326.55392193286) rotate(0)"
|
|
522
522
|
>
|
|
523
523
|
Label!
|
|
524
524
|
</text>
|
|
@@ -527,7 +527,7 @@ exports[`Branch labels > renders a tree node labels in radial layout 1`] = `
|
|
|
527
527
|
<text
|
|
528
528
|
alignment-baseline="baseline"
|
|
529
529
|
text-anchor="middle"
|
|
530
|
-
transform="translate(
|
|
530
|
+
transform="translate(343.2962389576222,41.517973977619995) rotate(0)"
|
|
531
531
|
>
|
|
532
532
|
Label!
|
|
533
533
|
</text>
|
|
@@ -553,25 +553,25 @@ exports[`Branch labels > renders a tree node labels in radial layout 1`] = `
|
|
|
553
553
|
class="branch-layer"
|
|
554
554
|
>
|
|
555
555
|
<path
|
|
556
|
-
d="M
|
|
556
|
+
d="M 306.5924779152444 95.03594795523999 C306.5924779152444,95.03594795523999 233.18495583048883,190.07189591047998 233.18495583048883,190.07189591047998 C233.18495583048883,190.07189591047998 196.48119478811105,237.5898698881 178.12931426692217,261.34885687690996 C178.12931426692217,261.34885687690996 168.95337400632775,273.22835037131495 164.36540387603054,279.1680971185175 C164.36540387603054,279.1680971185175 162.07141881088194,282.1379704921187 160.92442627830764,283.6229071789194 C160.92442627830764,283.6229071789194 160.35093001202046,284.3653755223197 160.06418187887687,284.7366096940199 C160.06418187887687,284.7366096940199 159.7774337457333,285.10784386572 159.7774337457333,285.10784386572 "
|
|
557
557
|
fill="none"
|
|
558
558
|
stroke="black"
|
|
559
559
|
stroke-width="2"
|
|
560
560
|
/>
|
|
561
561
|
<path
|
|
562
|
-
d="M
|
|
562
|
+
d="M 159.7774337457333 285.10784386572 C159.7774337457333,285.10784386572 79.88871687286665,293.2946004927189 79.88871687286665,293.2946004927189 C79.88871687286665,293.2946004927189 39.944358436433326,297.38797880621837 19.972179218216663,299.4346679629681 C19.972179218216663,299.4346679629681 9.986089609108332,300.45801254134295 4.993044804554166,300.96968483053035 C4.993044804554166,300.96968483053035 2.496522402277083,301.2255209751241 1.2482612011385414,301.3534390474209 C1.2482612011385414,301.3534390474209 0.6241306005692707,301.41739808356937 0.31206530028463536,301.4493776016436 C0.31206530028463536,301.4493776016436 0,301.4813571197178 0,301.4813571197178 "
|
|
563
563
|
fill="none"
|
|
564
564
|
stroke="black"
|
|
565
565
|
stroke-width="2"
|
|
566
566
|
/>
|
|
567
567
|
<path
|
|
568
|
-
d="M
|
|
568
|
+
d="M 159.7774337457333 285.10784386572 C159.7774337457333,285.10784386572 196.69432122862028,332.55392193286 196.69432122862028,332.55392193286 C196.69432122862028,332.55392193286 215.15276497006377,356.27696096643 224.38198684078552,368.138480483215 C224.38198684078552,368.138480483215 228.9965977761464,374.06924024160753 231.30390324382682,377.03462012080377 C231.30390324382682,377.03462012080377 232.45755597766703,378.5173100604019 233.03438234458713,379.25865503020094 C233.03438234458713,379.25865503020094 233.3227955280472,379.6293275151005 233.46700211977725,379.81466375755025 C233.46700211977725,379.81466375755025 233.61120871150726,380 233.61120871150726,380 "
|
|
569
569
|
fill="none"
|
|
570
570
|
stroke="black"
|
|
571
571
|
stroke-width="2"
|
|
572
572
|
/>
|
|
573
573
|
<path
|
|
574
|
-
d="M
|
|
574
|
+
d="M 306.5924779152444 95.03594795523999 C306.5924779152444,95.03594795523999 343.2962389576222,47.517973977619995 343.2962389576222,47.517973977619995 C343.2962389576222,47.517973977619995 361.6481194788111,23.758986988809998 370.8240597394056,11.879493494404999 C370.8240597394056,11.879493494404999 375.4120298697028,5.939746747202499 377.7060149348514,2.9698733736012497 C377.7060149348514,2.9698733736012497 378.8530074674257,1.4849366868006248 379.4265037337128,0.7424683434003124 C379.4265037337128,0.7424683434003124 379.7132518668564,0.3712341717001562 379.8566259334282,0.1856170858500781 C379.8566259334282,0.1856170858500781 380,0 380,0 "
|
|
575
575
|
fill="none"
|
|
576
576
|
stroke="black"
|
|
577
577
|
stroke-width="2"
|
|
@@ -584,7 +584,7 @@ exports[`Branch labels > renders a tree node labels in radial layout 1`] = `
|
|
|
584
584
|
<text
|
|
585
585
|
alignment-baseline="baseline"
|
|
586
586
|
text-anchor="middle"
|
|
587
|
-
transform="translate(
|
|
587
|
+
transform="translate(233.18495583048883,184.07189591047998) rotate(0)"
|
|
588
588
|
>
|
|
589
589
|
Label!
|
|
590
590
|
</text>
|
|
@@ -593,7 +593,7 @@ exports[`Branch labels > renders a tree node labels in radial layout 1`] = `
|
|
|
593
593
|
<text
|
|
594
594
|
alignment-baseline="baseline"
|
|
595
595
|
text-anchor="middle"
|
|
596
|
-
transform="translate(
|
|
596
|
+
transform="translate(79.88871687286665,287.2946004927189) rotate(0)"
|
|
597
597
|
>
|
|
598
598
|
Label!
|
|
599
599
|
</text>
|
|
@@ -602,7 +602,7 @@ exports[`Branch labels > renders a tree node labels in radial layout 1`] = `
|
|
|
602
602
|
<text
|
|
603
603
|
alignment-baseline="baseline"
|
|
604
604
|
text-anchor="middle"
|
|
605
|
-
transform="translate(
|
|
605
|
+
transform="translate(196.69432122862028,326.55392193286) rotate(0)"
|
|
606
606
|
>
|
|
607
607
|
Label!
|
|
608
608
|
</text>
|
|
@@ -611,7 +611,7 @@ exports[`Branch labels > renders a tree node labels in radial layout 1`] = `
|
|
|
611
611
|
<text
|
|
612
612
|
alignment-baseline="baseline"
|
|
613
613
|
text-anchor="middle"
|
|
614
|
-
transform="translate(
|
|
614
|
+
transform="translate(343.2962389576222,41.517973977619995) rotate(0)"
|
|
615
615
|
>
|
|
616
616
|
Label!
|
|
617
617
|
</text>
|