@figtreejs/core 0.0.1-alpha.1 → 0.0.1-beta.1
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 -8874
- package/dist/index.d.ts +461 -233
- package/dist/index.mjs +4432 -6624
- package/package.json +7 -4
- package/src/bauble-makers/set-up-baubles.ts +1 -1
- package/src/components/baubles/clades/highlight.tsx +1 -1
- package/src/components/decorations/axis/polar-axis.tsx +1 -1
- package/src/components/decorations/axis/rectangular-axis.tsx +1 -1
- package/src/components/figtree/figtree.tsx +1 -1
- package/src/components/hoc/with-node.tsx +1 -1
- package/src/evo/tree/normalized-tree/immutable-tree-helpers.ts +2 -2
- package/src/evo/tree/normalized-tree/immutable-tree.test.ts +1 -1
- package/src/evo/tree/normalized-tree/immutable-tree.ts +3 -5
- package/src/evo/tree/parsers/annotation-parser.ts +6 -0
- package/src/evo/tree/parsers/newick-character-parser.ts +9 -1
- package/src/evo/tree/parsers/newick-parsing.ts +6 -0
- package/src/evo/tree/parsers/nexus-parsing.ts +8 -3
- package/src/evo/tree/parsers/parsing.test.ts +1 -1
- package/src/evo/tree/parsers/stream-reader/nexus-importer.ts +9 -2
- package/src/evo/tree/parsers/stream-reader/nexus-tokenizer.ts +6 -1
- package/src/evo/tree/taxa/helper-functions.ts +16 -2
- package/src/evo/tree/taxa/taxon.ts +41 -2
- package/src/evo/tree/traversals/preorder-traversal.ts +5 -0
- package/src/evo/tree/traversals/traversal-types.ts +3 -0
- package/src/evo/tree/tree-types.ts +259 -20
- package/src/index.ts +1 -1
- package/src/layouts/functional/radial-layout.ts +15 -11
- package/src/layouts/functional/rectangular-layout.ts +8 -1
- package/src/layouts/layout-interface.ts +0 -73
- package/src/path.helpers.ts +76 -59
- package/src/tests/clades/cartoon.test.tsx +1 -1
- package/src/tests/clades/highlight.test.tsx +1 -1
- package/src/tests/layouts/rectangularlayout.test.ts +1 -1
- package/src/tests/shapes/label.test.tsx +1 -1
- package/src/utils/dateUtils.ts +41 -0
- package/src/utils/index.ts +2 -0
- package/src/utils/maybe.ts +67 -0
- package/CHANGELOG.md +0 -17
- package/eslint.config.js +0 -9
- package/src/utils.ts +0 -57
- package/tsconfig.json +0 -12
- package/vite.config.ts +0 -34
- package/vitetest.config.ts +0 -11
|
@@ -1,9 +1,17 @@
|
|
|
1
1
|
import type { Taxon, TaxonSet } from "./taxa/taxon";
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* The base interface for a node.
|
|
5
|
+
* Information about the node will be provided by the tree.
|
|
6
|
+
*/
|
|
3
7
|
export interface NodeRef {
|
|
4
8
|
number: number;
|
|
5
9
|
_id: string;
|
|
6
10
|
}
|
|
11
|
+
/**
|
|
12
|
+
* Types of annotations that can exist on nodes in a tree.
|
|
13
|
+
* Each type corresponds to a value type.
|
|
14
|
+
*/
|
|
7
15
|
export enum BaseAnnotationType {
|
|
8
16
|
DISCRETE = "DISCRETE", // string could also be stringy numbers
|
|
9
17
|
BOOLEAN = "BOOLEAN", // true false
|
|
@@ -17,6 +25,8 @@ export enum BaseAnnotationType {
|
|
|
17
25
|
}
|
|
18
26
|
export type MarkovJumpValue = { from: string; to: string; time?: number };
|
|
19
27
|
|
|
28
|
+
// A helper type function that returns the value type of an annotation given its
|
|
29
|
+
// figtree type.
|
|
20
30
|
export type ValueOf<T extends BaseAnnotationType> =
|
|
21
31
|
T extends BaseAnnotationType.DISCRETE
|
|
22
32
|
? string
|
|
@@ -34,6 +44,9 @@ export type ValueOf<T extends BaseAnnotationType> =
|
|
|
34
44
|
? Record<string, number>
|
|
35
45
|
: never;
|
|
36
46
|
|
|
47
|
+
// A helper function that returns the raw value type that corresponds to a figtreejs annotation type.
|
|
48
|
+
// This generally is the same as the value type, but some annotations such as markov jumps are transformed
|
|
49
|
+
// between being read from a nexus file and stored in the tree.
|
|
37
50
|
export type RawValueOf<T extends BaseAnnotationType> =
|
|
38
51
|
T extends BaseAnnotationType.DISCRETE
|
|
39
52
|
? string
|
|
@@ -51,6 +64,10 @@ export type RawValueOf<T extends BaseAnnotationType> =
|
|
|
51
64
|
? Record<string, number>
|
|
52
65
|
: never;
|
|
53
66
|
|
|
67
|
+
/**
|
|
68
|
+
* A helper type function that returns the domain of an annotation based on the
|
|
69
|
+
* type of an annotation.
|
|
70
|
+
*/
|
|
54
71
|
export type DomainOf<T extends BaseAnnotationType> =
|
|
55
72
|
T extends BaseAnnotationType.DISCRETE
|
|
56
73
|
? string[]
|
|
@@ -79,25 +96,42 @@ export type Annotation = {
|
|
|
79
96
|
[K in BaseAnnotationType]: AbstractAnnotation<K>;
|
|
80
97
|
}[BaseAnnotationType];
|
|
81
98
|
|
|
99
|
+
/**
|
|
100
|
+
* The type of summary information that can be provided by a tree.
|
|
101
|
+
*/
|
|
82
102
|
export interface AbstractAnnotationSummary<T extends BaseAnnotationType> {
|
|
83
103
|
id: string;
|
|
84
104
|
type: T;
|
|
85
105
|
domain: DomainOf<T>;
|
|
86
106
|
}
|
|
87
107
|
|
|
108
|
+
/**
|
|
109
|
+
* unions across all types of annotations.
|
|
110
|
+
*/
|
|
88
111
|
export type AnnotationDomain = {
|
|
89
112
|
[K in BaseAnnotationType]: DomainOf<K>;
|
|
90
113
|
}[BaseAnnotationType];
|
|
114
|
+
|
|
91
115
|
export type AnnotationValue = {
|
|
92
116
|
[K in BaseAnnotationType]: ValueOf<K>;
|
|
93
117
|
}[BaseAnnotationType];
|
|
118
|
+
|
|
94
119
|
export type AnnotationSummary = {
|
|
95
120
|
[K in BaseAnnotationType]: AbstractAnnotationSummary<K>;
|
|
96
121
|
}[BaseAnnotationType];
|
|
122
|
+
|
|
97
123
|
export type RawAnnotationValue = {
|
|
98
124
|
[K in BaseAnnotationType]: RawValueOf<K>;
|
|
99
125
|
}[BaseAnnotationType];
|
|
100
126
|
|
|
127
|
+
/**
|
|
128
|
+
* A object for the parsing options available for importing a newick string.
|
|
129
|
+
* dateFormat : string if provided with date prefix the data will be parsed from the taxon label and stored in an annotation called 'date'
|
|
130
|
+
* datePrefix : string The character immediately preceding the date assuming the date is at the end of the taxon label
|
|
131
|
+
* labelName : If there are node labels they will be parsed as annotations and stored with this annotation name
|
|
132
|
+
* tipNameMap : If taxon are present as number or some other encoding this map will be used to insert the full taxon name.
|
|
133
|
+
* taxonSet : If provided this taxon set will be used to link taxa across trees.
|
|
134
|
+
*/
|
|
101
135
|
export interface newickParsingOptions {
|
|
102
136
|
dateFormat?: string;
|
|
103
137
|
datePrefix?: string;
|
|
@@ -106,92 +140,297 @@ export interface newickParsingOptions {
|
|
|
106
140
|
tipNameMap?: Map<string, string>;
|
|
107
141
|
taxonSet?: TaxonSet;
|
|
108
142
|
}
|
|
143
|
+
/**
|
|
144
|
+
* A representation of a phylogenetic tree.
|
|
145
|
+
* Trees may represent unrooted tree, but all trees nominally have a root node.
|
|
146
|
+
* Functions do not return 'undefined' or 'null'.
|
|
147
|
+
* If a value that does not exist is accessed the tree will throw an error.
|
|
148
|
+
* Helper functions are provided to check if a value exists.
|
|
149
|
+
*/
|
|
109
150
|
export interface Tree {
|
|
151
|
+
/**
|
|
152
|
+
* Return the root of the tree.
|
|
153
|
+
*/
|
|
110
154
|
getRoot(): NodeRef;
|
|
111
|
-
isRooted(): boolean;
|
|
155
|
+
// isRooted(): boolean;
|
|
156
|
+
/**
|
|
157
|
+
* Return the number of nodes in the tree.
|
|
158
|
+
*/
|
|
112
159
|
getNodeCount(): number;
|
|
160
|
+
/**
|
|
161
|
+
* Return the number of internal nodes.
|
|
162
|
+
*/
|
|
113
163
|
getInternalNodeCount(): number;
|
|
164
|
+
/**
|
|
165
|
+
* Return the number of tips / external nodes
|
|
166
|
+
*/
|
|
114
167
|
getExternalNodeCount(): number;
|
|
168
|
+
/**
|
|
169
|
+
* Get Node by name/label, taxon, or index (in full node list)
|
|
170
|
+
* @param i: string | Taxon | number
|
|
171
|
+
*/
|
|
115
172
|
getNode(i: string | Taxon | number): NodeRef;
|
|
173
|
+
/**
|
|
174
|
+
* Get an array of internal nodes
|
|
175
|
+
*/
|
|
116
176
|
getInternalNodes(): NodeRef[];
|
|
177
|
+
/**
|
|
178
|
+
* Get an array of external nodes
|
|
179
|
+
*/
|
|
117
180
|
getExternalNodes(): NodeRef[];
|
|
181
|
+
/**
|
|
182
|
+
* Get an array of all nodes.
|
|
183
|
+
*/
|
|
118
184
|
getNodes(): NodeRef[];
|
|
185
|
+
/**
|
|
186
|
+
* Get the taxon affiliated with a node or by it's index
|
|
187
|
+
* @param id: number | NodeRef
|
|
188
|
+
*/
|
|
119
189
|
getTaxon(id: number | NodeRef): Taxon;
|
|
120
|
-
|
|
190
|
+
/**
|
|
191
|
+
* Helper to function to determine if a node in an external node
|
|
192
|
+
* @param node
|
|
193
|
+
*/
|
|
121
194
|
isExternal(node: NodeRef): boolean;
|
|
195
|
+
/**
|
|
196
|
+
* A helper function to determine if an node is an internal node
|
|
197
|
+
* @param node
|
|
198
|
+
*/
|
|
122
199
|
isInternal(node: NodeRef): boolean;
|
|
200
|
+
/**
|
|
201
|
+
* A helper function to determine if a node is the root node.
|
|
202
|
+
* @param node
|
|
203
|
+
*/
|
|
123
204
|
isRoot(node: NodeRef): boolean;
|
|
124
|
-
|
|
205
|
+
/**
|
|
206
|
+
* Return the number of children an given node has.
|
|
207
|
+
* @param node
|
|
208
|
+
*/
|
|
125
209
|
getChildCount(node: NodeRef): number;
|
|
210
|
+
/**
|
|
211
|
+
* Access the ith child of a node
|
|
212
|
+
* @param node - NodeRef
|
|
213
|
+
* @param i - index of the child
|
|
214
|
+
*/
|
|
126
215
|
getChild(node: NodeRef, i: number): NodeRef;
|
|
127
|
-
|
|
216
|
+
/**
|
|
217
|
+
* An explicit function to get a node by it's Taxon
|
|
218
|
+
* @param taxon
|
|
219
|
+
*/
|
|
128
220
|
getNodeByTaxon(taxon: Taxon): NodeRef;
|
|
221
|
+
/**
|
|
222
|
+
* An explicit function to access a node by it's label
|
|
223
|
+
* @param label - string
|
|
224
|
+
*/
|
|
129
225
|
getNodeByLabel(label: string): NodeRef;
|
|
130
226
|
// getLevel(node:NodeRef):number;
|
|
131
|
-
|
|
227
|
+
/**
|
|
228
|
+
* Return the distance from this node to the root.
|
|
229
|
+
* @param node -NodeRef
|
|
230
|
+
*/
|
|
132
231
|
getDivergence(node: NodeRef): number;
|
|
232
|
+
/**
|
|
233
|
+
* Return the distance between a node and the node furthest from the root
|
|
234
|
+
* @param node -NodeRef
|
|
235
|
+
*/
|
|
133
236
|
getHeight(node: NodeRef): number;
|
|
237
|
+
/**
|
|
238
|
+
* Return the length of the branch subtending a node
|
|
239
|
+
* @param node -NodeRef
|
|
240
|
+
*/
|
|
134
241
|
getLength(node: NodeRef): number;
|
|
135
|
-
|
|
242
|
+
/**
|
|
243
|
+
* Return a node's parent
|
|
244
|
+
* @param node -NodeRef
|
|
245
|
+
*/
|
|
136
246
|
getParent(node: NodeRef): NodeRef;
|
|
247
|
+
/**
|
|
248
|
+
* Get an array of the node's children
|
|
249
|
+
* @param node -NodeRef
|
|
250
|
+
*/
|
|
137
251
|
getChildren(node: NodeRef): NodeRef[];
|
|
138
|
-
|
|
252
|
+
/**
|
|
253
|
+
* Get the annotation value for a node.
|
|
254
|
+
* If the default value is not provided, and the node is not annotated, the function will throw an error.
|
|
255
|
+
* @param node - NodeRef
|
|
256
|
+
* @param name - string the name of the annotation
|
|
257
|
+
* @param d - AnnotationValue - The default value to return if the node does not have the provided annotation.
|
|
258
|
+
*/
|
|
139
259
|
getAnnotation(
|
|
140
260
|
node: NodeRef,
|
|
141
261
|
name: string,
|
|
142
262
|
d?: AnnotationValue,
|
|
143
263
|
): AnnotationValue; // what about or undefined?
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
264
|
+
/**
|
|
265
|
+
* Annotate a node with a value.
|
|
266
|
+
* @param node - NodeRef
|
|
267
|
+
* @param name -string - Name of the annotation
|
|
268
|
+
* @param value - the annotation value for a node.
|
|
269
|
+
*/
|
|
148
270
|
annotateNode(node: NodeRef, name: string, value: RawAnnotationValue): Tree;
|
|
149
271
|
annotateNode(
|
|
150
272
|
node: NodeRef,
|
|
151
273
|
annotation: Record<string, RawAnnotationValue>,
|
|
152
274
|
): Tree;
|
|
153
|
-
|
|
275
|
+
/**
|
|
276
|
+
* Get the label for a given node
|
|
277
|
+
* @param node
|
|
278
|
+
*/
|
|
154
279
|
getLabel(node: NodeRef): string;
|
|
280
|
+
/**
|
|
281
|
+
* Check if a node has a label
|
|
282
|
+
* @param node
|
|
283
|
+
*/
|
|
155
284
|
hasLabel(node: NodeRef): boolean;
|
|
156
|
-
|
|
285
|
+
/**
|
|
286
|
+
* Get all the names of annotations in the tree
|
|
287
|
+
*/
|
|
157
288
|
getAnnotationKeys(): string[];
|
|
289
|
+
/**
|
|
290
|
+
* Get the type of an annotation found in the tree.
|
|
291
|
+
* @param name string - Name of the annotation
|
|
292
|
+
*/
|
|
158
293
|
getAnnotationType(name: string): BaseAnnotationType;
|
|
159
294
|
|
|
295
|
+
/**
|
|
296
|
+
* Return an array of summary data for all annotations in the tree.
|
|
297
|
+
*/
|
|
160
298
|
getAnnotations(): AnnotationSummary[];
|
|
299
|
+
/**
|
|
300
|
+
* Return a summary of an annotation in the tree
|
|
301
|
+
* @param name - name of the annotation
|
|
302
|
+
*/
|
|
161
303
|
getAnnotationSummary(name: string): AnnotationSummary;
|
|
162
|
-
|
|
304
|
+
/**
|
|
305
|
+
* Add nodes to a tree.
|
|
306
|
+
* The nodes can be accessed by their indices, but have no relationships with other nodes in the tree.
|
|
307
|
+
* Returns an object with {tree: the new tree with nodes,node: An array of the new nodes}
|
|
308
|
+
* @param n - number of nodes to add default 1
|
|
309
|
+
*/
|
|
163
310
|
addNodes(n?: number): { tree: Tree; nodes: NodeRef[] };
|
|
311
|
+
/**
|
|
312
|
+
* Delete a node from a tree.
|
|
313
|
+
* It is not possible to delete the root node.
|
|
314
|
+
* @param n - NodeRef
|
|
315
|
+
*/
|
|
164
316
|
deleteNode(n: NodeRef): Tree;
|
|
317
|
+
/**
|
|
318
|
+
* Remove a child node from a parent node's descendants
|
|
319
|
+
* @param parent - The node whose child will be removed
|
|
320
|
+
* @param child - The child that is removed from the parent.
|
|
321
|
+
*/
|
|
165
322
|
removeChild(parent: NodeRef, child: NodeRef): Tree;
|
|
166
|
-
deleteClade(n: NodeRef): Tree;
|
|
323
|
+
// deleteClade(n: NodeRef): Tree;
|
|
167
324
|
// hasNextSibling(node:Node)
|
|
325
|
+
/**
|
|
326
|
+
* Get the next sibling.
|
|
327
|
+
* This will wrap back to the first sibling if the provided node is the last sibling.
|
|
328
|
+
* @param node - NodeRef
|
|
329
|
+
*/
|
|
168
330
|
getNextSibling(node: NodeRef): NodeRef;
|
|
331
|
+
/**
|
|
332
|
+
* A checker function to determine if a node has a right sibling
|
|
333
|
+
* @param node - NodeRef
|
|
334
|
+
*/
|
|
169
335
|
hasRightSibling(node: NodeRef): boolean;
|
|
336
|
+
/**
|
|
337
|
+
* Return a node's right sibling (if it has one) or error.
|
|
338
|
+
* @param node
|
|
339
|
+
*/
|
|
170
340
|
getRightSibling(node: NodeRef): NodeRef;
|
|
341
|
+
/**
|
|
342
|
+
* Check if a node has a left sibling
|
|
343
|
+
* @param node
|
|
344
|
+
*/
|
|
171
345
|
hasLeftSibling(node: NodeRef): boolean;
|
|
346
|
+
/**
|
|
347
|
+
* Return a node's left sibling (if it has one) or throw an error.
|
|
348
|
+
* @param node
|
|
349
|
+
*/
|
|
172
350
|
getLeftSibling(node: NodeRef): NodeRef;
|
|
173
351
|
|
|
352
|
+
/**
|
|
353
|
+
* Set the distance between a node and the node furthest from the root.
|
|
354
|
+
* @param node
|
|
355
|
+
* @param height number - the new node height
|
|
356
|
+
*/
|
|
174
357
|
setHeight(node: NodeRef, height: number): Tree;
|
|
358
|
+
/**
|
|
359
|
+
* Set the distance between a node and the root node.
|
|
360
|
+
* @param node
|
|
361
|
+
* @param divergence number - new divergence
|
|
362
|
+
*/
|
|
175
363
|
setDivergence(node: NodeRef, divergence: number): Tree;
|
|
364
|
+
/**
|
|
365
|
+
* Set the length of the branch subtending a node
|
|
366
|
+
* @param node NodeRef
|
|
367
|
+
* @param length - number - the new length
|
|
368
|
+
*/
|
|
176
369
|
setLength(node: NodeRef, length: number): Tree;
|
|
370
|
+
/**
|
|
371
|
+
* Assign a taxon to a node.
|
|
372
|
+
* @param node NodRef
|
|
373
|
+
* @param taxon Taxon
|
|
374
|
+
*/
|
|
177
375
|
setTaxon(node: NodeRef, taxon: Taxon): Tree;
|
|
376
|
+
/**
|
|
377
|
+
* Set the label on a node.
|
|
378
|
+
* @param node Noderf
|
|
379
|
+
* @param label string
|
|
380
|
+
*/
|
|
178
381
|
setLabel(node: NodeRef, label: string): Tree;
|
|
179
|
-
|
|
382
|
+
/**
|
|
383
|
+
* Add a child to a node.
|
|
384
|
+
* @param parent the parent that gets a new child
|
|
385
|
+
* @param child The child added to a parent
|
|
386
|
+
*/
|
|
180
387
|
addChild(parent: NodeRef, child: NodeRef): Tree;
|
|
181
388
|
// root(node: NodeRef,portion:number): Tree
|
|
182
|
-
unroot(node: NodeRef): Tree;
|
|
389
|
+
// unroot(node: NodeRef): Tree;
|
|
390
|
+
|
|
391
|
+
/**
|
|
392
|
+
*
|
|
393
|
+
* @param node - An optional node start writing from. If not provided the whole tree will be written.
|
|
394
|
+
* @param options { includeAnnotations: boolean } - include annotations in newick string
|
|
395
|
+
*/
|
|
183
396
|
toNewick(node?: NodeRef, options?: { includeAnnotations: boolean }): string;
|
|
397
|
+
/**
|
|
398
|
+
* Sort children arrays by the number of offspring.
|
|
399
|
+
* @param down Boolean to sort down or up.
|
|
400
|
+
*/
|
|
184
401
|
orderNodesByDensity(down: boolean): Tree;
|
|
402
|
+
/**
|
|
403
|
+
*
|
|
404
|
+
* @param node Node whose children will be sorted
|
|
405
|
+
* @param compare - A function which compares two nodes. Will be used as in an array sort
|
|
406
|
+
*/
|
|
185
407
|
sortChildren(
|
|
186
408
|
node: NodeRef,
|
|
187
409
|
compare: (a: NodeRef, b: NodeRef) => number,
|
|
188
410
|
): Tree;
|
|
189
|
-
|
|
411
|
+
/**
|
|
412
|
+
* Get the most recent common ancestor of two nodes
|
|
413
|
+
* @param node1
|
|
414
|
+
* @param node2
|
|
415
|
+
*/
|
|
190
416
|
getMRCA(node1: NodeRef, node2: NodeRef): NodeRef;
|
|
417
|
+
/**
|
|
418
|
+
* Get the most recent common ancestor of an array of nodes
|
|
419
|
+
* @param nodes
|
|
420
|
+
*/
|
|
191
421
|
getMRCA(nodes: NodeRef[]): NodeRef;
|
|
422
|
+
/**
|
|
423
|
+
* Rotate a node's children
|
|
424
|
+
* @param node
|
|
425
|
+
* @param recursive - rotate the children as well down the tree
|
|
426
|
+
*/
|
|
192
427
|
rotate(node: NodeRef, recursive: boolean): Tree;
|
|
428
|
+
/**
|
|
429
|
+
* Reroot a tree along a branch subtending a new node.
|
|
430
|
+
* @param node The root will be inserted along the branch subtending this node
|
|
431
|
+
* @param proportion - proportion along the branch to place the root.
|
|
432
|
+
*/
|
|
193
433
|
reroot(node: NodeRef, proportion: number): Tree;
|
|
194
434
|
}
|
|
195
|
-
export type TreeListener = (tree: Tree, node: NodeRef) => void;
|
|
196
435
|
|
|
197
|
-
|
|
436
|
+
export type TreeListener = (tree: Tree, node: NodeRef) => void;
|
package/src/index.ts
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
// export function layout (tree:ImmutableTree,node?:NodeRef):Map<NodeRef,FunctionalVertex>{
|
|
2
|
-
|
|
3
1
|
import type { ImmutableTree, NodeRef } from "../../evo";
|
|
4
2
|
import { preOrderIterator, tipIterator } from "../../evo";
|
|
5
3
|
import type { NodeLabelType } from "../types";
|
|
6
|
-
import { notNull } from "../../utils";
|
|
4
|
+
import { notNull } from "../../utils/maybe";
|
|
7
5
|
import type { FunctionalVertex } from "../types";
|
|
8
6
|
import { layoutClass } from "../types";
|
|
9
7
|
|
|
@@ -18,6 +16,13 @@ type data = {
|
|
|
18
16
|
number: number;
|
|
19
17
|
};
|
|
20
18
|
|
|
19
|
+
/**
|
|
20
|
+
* The radial (unrooted) layout
|
|
21
|
+
* @param tree
|
|
22
|
+
* @param options {spread: number} - increases this increases the space between tips
|
|
23
|
+
* @returns (node)=>FunctionalVertex
|
|
24
|
+
*/
|
|
25
|
+
|
|
21
26
|
export function radialLayout(
|
|
22
27
|
tree: ImmutableTree,
|
|
23
28
|
options: { spread?: number } = {},
|
|
@@ -59,21 +64,20 @@ export function radialLayout(
|
|
|
59
64
|
dx = Math.cos(branchAngle);
|
|
60
65
|
dy = Math.sin(branchAngle);
|
|
61
66
|
}
|
|
67
|
+
|
|
68
|
+
const nTheta = normalizeAngle(branchAngle);
|
|
62
69
|
const vertex = {
|
|
63
70
|
x,
|
|
64
71
|
y,
|
|
65
72
|
layoutClass: layoutClass.Radial,
|
|
66
|
-
theta:
|
|
73
|
+
theta: nTheta,
|
|
67
74
|
nodeLabel: {
|
|
68
75
|
dxFactor: dx,
|
|
69
76
|
dyFactor: dy,
|
|
70
77
|
alignmentBaseline: "middle",
|
|
71
78
|
textAnchor:
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
? "end"
|
|
75
|
-
: "start",
|
|
76
|
-
rotation: 0, // textSafeDegrees(normalizeAngle(branchAngle))
|
|
79
|
+
nTheta > Math.PI / 2 && nTheta < (3 * Math.PI) / 2 ? "end" : " start",
|
|
80
|
+
rotation: textSafeDegrees(nTheta) * 2, // why is this magic 2 needed?
|
|
77
81
|
} as NodeLabelType,
|
|
78
82
|
};
|
|
79
83
|
|
|
@@ -130,9 +134,9 @@ export function textSafeDegrees(radians: number) {
|
|
|
130
134
|
//trial and error - must be a better way
|
|
131
135
|
if (d > 90 && d < 270) {
|
|
132
136
|
return (d - 180) / 2;
|
|
133
|
-
} else if (d > 0 && d <
|
|
137
|
+
} else if (d > 0 && d < 90) {
|
|
134
138
|
return d / 2;
|
|
135
|
-
} else if (d < 360 && d >
|
|
139
|
+
} else if (d < 360 && d > 270) {
|
|
136
140
|
return (360 + d) / 2;
|
|
137
141
|
} else {
|
|
138
142
|
return d;
|
|
@@ -3,8 +3,15 @@ import type { ImmutableTree, NodeRef } from "../../evo";
|
|
|
3
3
|
import { postOrderIterator } from "../../evo";
|
|
4
4
|
import type { NodeLabelType, FunctionalVertex } from "../types";
|
|
5
5
|
import { layoutClass } from "../types";
|
|
6
|
-
import { unNullify } from "../../utils";
|
|
6
|
+
import { unNullify } from "../../utils/maybe";
|
|
7
7
|
|
|
8
|
+
/**
|
|
9
|
+
* This is the base class for layouts that place the parent nodes at the mean of their children.
|
|
10
|
+
* It forms the basis of the polar and rectangular layouts.
|
|
11
|
+
* The difference between the two is handled by the scaling functions.
|
|
12
|
+
* @param lc - layoutClass rectangular / polar
|
|
13
|
+
* @returns
|
|
14
|
+
*/
|
|
8
15
|
export function baseLayout(lc: layoutClass) {
|
|
9
16
|
function layout(tree: ImmutableTree): (node: NodeRef) => FunctionalVertex {
|
|
10
17
|
const map = new Map<NodeRef, FunctionalVertex>();
|
|
@@ -1,76 +1,3 @@
|
|
|
1
|
-
import type { layoutOptions } from "../components/figtree/figtree-types";
|
|
2
|
-
//TODO make tree
|
|
3
|
-
|
|
4
|
-
// TODO caching
|
|
5
|
-
|
|
6
|
-
//
|
|
7
|
-
export interface Label {
|
|
8
|
-
x: number;
|
|
9
|
-
y: number;
|
|
10
|
-
alignmentBaseline: string;
|
|
11
|
-
textAnchor: string;
|
|
12
|
-
rotation: number;
|
|
13
|
-
alignedPos?: { x: number; y: number };
|
|
14
|
-
}
|
|
15
|
-
export interface Vertex {
|
|
16
|
-
number: number;
|
|
17
|
-
x: number;
|
|
18
|
-
y: number;
|
|
19
|
-
hidden: boolean | undefined;
|
|
20
|
-
labelHidden: boolean | undefined;
|
|
21
|
-
level: number;
|
|
22
|
-
branch?: {
|
|
23
|
-
d: string;
|
|
24
|
-
label: Label;
|
|
25
|
-
};
|
|
26
|
-
theta?: number; //angle
|
|
27
|
-
r?: number; //radius
|
|
28
|
-
nodeLabel: Label;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export interface ArbitraryVertex {
|
|
32
|
-
hidden: boolean;
|
|
33
|
-
labelHidden: boolean;
|
|
34
|
-
number: number;
|
|
35
|
-
x: number;
|
|
36
|
-
y: number;
|
|
37
|
-
level: number;
|
|
38
|
-
theta?: number; //angle
|
|
39
|
-
pathPoints: { x: number; y: number }[];
|
|
40
|
-
nodeLabel: {
|
|
41
|
-
dx: number;
|
|
42
|
-
dy: number;
|
|
43
|
-
alignmentBaseline: string;
|
|
44
|
-
textAnchor: string;
|
|
45
|
-
rotation?: number;
|
|
46
|
-
};
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
//ids match node ids
|
|
50
|
-
export interface Vertices {
|
|
51
|
-
type: "Rectangular" | "Polar" | "Radial";
|
|
52
|
-
vertices: Vertex[];
|
|
53
|
-
origin?: { x: number; y: number }; // used by polar layout to denote the position of the root (or stem) which can change
|
|
54
|
-
theta?: [number, number]; // used by polar layout to denote the range of angles
|
|
55
|
-
axisLength?: number; // provided by layouts that support axis
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
export interface ArbitraryVertices {
|
|
59
|
-
vertices: ArbitraryVertex[];
|
|
60
|
-
extent: { x: [number, number]; y: [number, number] };
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
export interface internalLayoutOptions extends layoutOptions {
|
|
64
|
-
// all layout options plus width and height of drawable area
|
|
65
|
-
width?: number;
|
|
66
|
-
height?: number;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
export interface CartoonData {
|
|
70
|
-
cartooned: boolean;
|
|
71
|
-
collapseFactor: number;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
1
|
export const defaultInternalLayoutOptions = {
|
|
75
2
|
width: 1000,
|
|
76
3
|
height: 1000,
|