archaeopteryx 3.0.0 → 3.1.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.
Files changed (4) hide show
  1. package/README.md +116 -21
  2. package/archaeopteryx.js +1651 -578
  3. package/forester.js +297 -11
  4. package/package.json +1 -1
package/README.md CHANGED
@@ -16,6 +16,14 @@ they run entirely in your browser:
16
16
 
17
17
  **https://cmzmasek.github.io/archaeopteryx-js/**
18
18
 
19
+ **Try your own tree:**
20
+ [**cmzmasek.github.io/archaeopteryx-js/open.html**](https://cmzmasek.github.io/archaeopteryx-js/open.html)
21
+ — paste or open a Newick / NHX / Nexus / phyloXML / Auspice JSON file and
22
+ Archaeopteryx.js will visualize it. The tree is read locally in your browser;
23
+ nothing is uploaded. Its **Expert options** panel exercises every launch
24
+ config key live and shows the exact config JSON to copy into your own
25
+ `launch()` call.
26
+
19
27
  * [Auspice / Nextstrain JSON](https://cmzmasek.github.io/archaeopteryx-js/demo.html?tree=auspice)
20
28
  * [Swine H1 HA1 + alignment (Nexus)](https://cmzmasek.github.io/archaeopteryx-js/demo.html?tree=swh1)
21
29
  * [BEAST annotations (Nexus)](https://cmzmasek.github.io/archaeopteryx-js/demo.html?tree=beast)
@@ -24,10 +32,12 @@ they run entirely in your browser:
24
32
  * [Caliciviridae (186 strains)](https://cmzmasek.github.io/archaeopteryx-js/demo.html?tree=caliciviridae_500)
25
33
  * [Adenoviridae (321 strains)](https://cmzmasek.github.io/archaeopteryx-js/demo.html?tree=adenoviridae)
26
34
  * [Nucleotide alignment (600 columns)](https://cmzmasek.github.io/archaeopteryx-js/demo.html?tree=alignment_nt)
35
+ * [Genome alignment (150 × 30,000 columns)](https://cmzmasek.github.io/archaeopteryx-js/demo.html?tree=genome_alignment)
27
36
  * [Sequence alignment](https://cmzmasek.github.io/archaeopteryx-js/demo.html?tree=alignment)
28
37
  * [Influenza HA (annotated)](https://cmzmasek.github.io/archaeopteryx-js/demo.html?tree=influenza)
29
38
  * [Dinosaur time tree](https://cmzmasek.github.io/archaeopteryx-js/demo.html?tree=dinosaur)
30
39
  * [Ammonite time tree (fossil ranges)](https://cmzmasek.github.io/archaeopteryx-js/demo.html?tree=ammonite)
40
+ * [Late Cretaceous time tree (stages)](https://cmzmasek.github.io/archaeopteryx-js/demo.html?tree=late_cretaceous)
31
41
  * [Apaf-1 gene family](https://cmzmasek.github.io/archaeopteryx-js/demo.html?tree=apaf)
32
42
  * [Bcl-2 family](https://cmzmasek.github.io/archaeopteryx-js/demo.html?tree=bcl2)
33
43
  * [Confidence values](https://cmzmasek.github.io/archaeopteryx-js/demo.html?tree=confidences)
@@ -36,10 +46,12 @@ they run entirely in your browser:
36
46
  * [Start circular](https://cmzmasek.github.io/archaeopteryx-js/demo.html?tree=circular)
37
47
  * [Woese tree of life (start unrooted)](https://cmzmasek.github.io/archaeopteryx-js/demo.html?tree=woese)
38
48
  * [Start with collapsed controls](https://cmzmasek.github.io/archaeopteryx-js/demo.html?tree=collapsed)
49
+ * [H5N1 segment 3 (13,246 tips)](https://cmzmasek.github.io/archaeopteryx-js/demo.html?tree=flu_h5n1_seg3)
39
50
 
40
51
 
41
52
  ### Detailed developer documentation
42
- https://docs.google.com/document/d/1COVe0iYbKtcBQxGTP4_zuimpk2FH9iusOVOgd5xCJ3A/edit
53
+ To be written. For now, the [For Developers](#for-developers) section below
54
+ covers the entry points, configuration, and the visualization system.
43
55
 
44
56
  ### Dependencies
45
57
  Archaeopteryx.js has the following dependencies:
@@ -361,9 +373,8 @@ Both entry points take **exactly** the arguments shown — a call with the old
361
373
  trailing arguments (the separate settings bag, `nodeVisualizations`,
362
374
  `nodeLabels`, `specialVisualizations`, or the positional Newick parse
363
375
  options) **throws** with a message saying where each one went: everything now
364
- lives in the **one config object** (`nodeLabels`,
365
- `nhConfidenceValuesInBrackets`, `nhConfidenceValuesAsInternalNames` are
366
- config keys). `config` itself is optional — `archaeopteryx.launch('#phylogram1',
376
+ lives in the **one config object** (`nodeLabels` and
377
+ `internalNumericLabels` are config keys). `config` itself is optional — `archaeopteryx.launch('#phylogram1',
367
378
  tree)` works.
368
379
 
369
380
  `container` is a **CSS selector or the DOM element itself** (frameworks hand
@@ -372,12 +383,45 @@ render nothing and say nothing. Both entry points return a **viewer handle**:
372
383
 
373
384
  ```js
374
385
  viewer.getSelectedNodes(); // the node-menu selections (enableManualNodeSelection)
386
+ viewer.ready; // a Promise: resolved once the tree is drawn
375
387
  viewer.destroy(); // unmount COMPLETELY: the container DOM, the node
376
388
  // menu / dialogs / alignment scroller, the window
377
389
  // resize listener and every page-level key/wheel
378
390
  // handler; a later launch() works normally
379
391
  ```
380
392
 
393
+ **Big trees draw on the next frame.** Above 2,000 nodes, `launch()` does all
394
+ its validation, shows a "Drawing N nodes" card over the tree area, and
395
+ returns within milliseconds — the label analysis, visualization candidates,
396
+ control panel and the draw itself all run one frame later, so the browser
397
+ can paint the card instead of appearing frozen for the seconds a large tree
398
+ takes. Every error still throws synchronously from `launch()`
399
+ exactly as before; only the draw is deferred. `viewer.ready` resolves when it
400
+ has run (immediately for a small tree, which stays fully synchronous). Later
401
+ redraws on a big tree — a checkbox, a slider, a search — work the same way:
402
+ they show a "Redrawing" card and run on the next frame, and every redraw
403
+ requested in the same tick collapses into one. Wait on `ready` before reading
404
+ the tree's DOM after `launch()`:
405
+
406
+ ```js
407
+ const viewer = archaeopteryx.launch(container, tree, config);
408
+ await viewer.ready; // the SVG exists now
409
+ ```
410
+
411
+ The one part the library cannot defer for you is your own parse of a big
412
+ file before `launch()`. `archaeopteryx.busy()` shows the same card for that,
413
+ yields a frame so it paints, runs your work, and removes it:
414
+
415
+ ```js
416
+ archaeopteryx.busy(container, 'Reading ' + name, sizeMb + ' MB', function () {
417
+ const tree = archaeopteryx.parseTree(name, text);
418
+ viewer = archaeopteryx.launch(container, tree, config);
419
+ });
420
+ ```
421
+
422
+ Pass `document.body` as the container for a whole-page card; without the
423
+ work function it returns a remover and the yielding is up to you.
424
+
381
425
  One viewer per page: the library keeps its display state in one place, so a
382
426
  second launch — into any container — replaces the first. Launching into the
383
427
  same container is the supported way to switch trees (the demo pages do
@@ -459,6 +503,14 @@ The parser for a given input is auto-detected (see **The entry points**
459
503
  above); the Download menu offers whichever output formats the current tree
460
504
  can carry.
461
505
 
506
+ Newick and Nexus files usually carry branch support as a bare internal label
507
+ (`)100:0.05`). Archaeopteryx.js recognises those automatically and treats them
508
+ as confidence values, so support-based features work without any setup. If your
509
+ internal labels are clade names rather than support, set
510
+ `internalNumericLabels: 'label'`. Bracketed values (`)[95]:0.05`) are
511
+ always read as confidences; a bracket that is not a number is a comment and is
512
+ ignored.
513
+
462
514
  ### References
463
515
 
464
516
  1. Felsenstein, J. *PHYLIP (Phylogeny Inference Package)*. Department of
@@ -547,6 +599,11 @@ keep working; it logs a deprecation warning.
547
599
 
548
600
  ### Still used
549
601
 
602
+ Every key below can be tried live in the
603
+ [open-your-own-tree page](https://cmzmasek.github.io/archaeopteryx-js/open.html)'s
604
+ **Expert options** panel, which also emits the resulting config as
605
+ copy-pastable JSON.
606
+
550
607
  | Key | Default | What it does |
551
608
  | --- | --- | --- |
552
609
  | `collapseControlPanel` | `false` | Open with the control panel collapsed to just its header bar — the same state its own hide/show button toggles. |
@@ -571,8 +628,7 @@ keep working; it logs a deprecation warning.
571
628
  | `enableDownloads` | `true` | Offer the download buttons. |
572
629
  | `pngExportScale` | `4` | PNG export resolution multiplier. |
573
630
  | `nhExportWriteConfidences` | `true` | Write confidences into exported Newick. |
574
- | `nhConfidenceValuesInBrackets` | `true` | Newick parsing: read `[90]`-style bracketed values as confidences. |
575
- | `nhConfidenceValuesAsInternalNames` | `false` | Newick parsing: read internal node names as confidence values. |
631
+ | `internalNumericLabels` | `'auto'` | Newick / Nexus parsing: how a bare numeric internal label (`)100:0.05`) is read. `'auto'` reads them as confidence values only when *every* internal label looks like support; `'confidence'` reads every numeric label as one, whatever its value; `'label'` keeps them as names. Replaces `nhConfidenceValuesAsInternalNames` (still accepted, with a warning; its `true` maps to `'confidence'`). |
576
632
  | `nodeLabels` | `null` | Custom label-field checkboxes: `{key: {label, description, propertyRef, showButton, selected}}` — each adds a panel checkbox labelling nodes with the named property's value. (Was `launch()`'s sixth positional argument.) |
577
633
  | `enableSubtreeDeletion` | `true` | Offer node / subtree deletion in the node menu. |
578
634
  | `enableAccessToDatabases` | `true` | Offer the “Access DB” link in the node menu. |
@@ -581,7 +637,8 @@ keep working; it logs a deprecation warning.
581
637
  ### Anything else throws
582
638
 
583
639
  An unrecognised key is an error, whether it was removed in this modernization
584
- or simply mistyped:
640
+ or simply mistyped (the two deprecated keys below are the exception — they
641
+ warn rather than throw):
585
642
 
586
643
  ```
587
644
  ArchaeopteryxJS: ERROR: removed config key(s) passed to launch:
@@ -593,6 +650,17 @@ ArchaeopteryxJS: ERROR: unknown config key(s) passed to launch: "enableDownlods"
593
650
  An ignored key looks like it worked. If you are upgrading, run once and fix
594
651
  whatever it names.
595
652
 
653
+ ### Accepted, with a warning
654
+
655
+ Two keys are neither current nor removed: they are accepted so an existing
656
+ embed keeps working, and warn on the console. Both concern Newick support
657
+ values.
658
+
659
+ | Key | What happens |
660
+ |---|---|
661
+ | `nhConfidenceValuesAsInternalNames` | Translated to `internalNumericLabels`. **`true` becomes `'confidence'`, not `'auto'`** — `'auto'` is all-or-nothing and promotes nothing in a tree that mixes clade names with support, so a caller moved to it silently would lose promotions they had. An explicit `internalNumericLabels` always wins. |
662
+ | `nhConfidenceValuesInBrackets` | Retired: ignored. It gated whether `[95]` is read as a confidence, but setting it `false` never reinterpreted the bracket — it *discarded* it, so the option's only effect was to throw support values away. A bracket that is not a number is a Newick comment and was ignored either way, and NHX / BEAST blobs go through a different path. Bracketed values are now always read as confidences. |
663
+
596
664
  ### What replaced the rest
597
665
 
598
666
  A few of these are worth spelling out, because they are decisions rather than
@@ -1152,9 +1220,18 @@ denominator); information = `(log₂K − H)/log₂K × nonGapFraction`, K = 4 o
1152
1220
  20; consensus = most common non-gap residue, ties alphabetical. The hover
1153
1221
  readout (`forester.msaResidueInfo`, `msaUngappedPosition`) names the residue
1154
1222
  (desktop vocabulary, selenocysteine and pyrrolysine included), its class
1155
- (purine/pyrimidine for bases) and Kyte-Doolittle hydropathy. Scrolling: a
1156
- lazily-created fixed HTML range input plus wheel-over-track, both moving
1157
- `_msaColOffset`; the tree never moves.
1223
+ (purine/pyrimidine for bases) and Kyte-Doolittle hydropathy.
1224
+
1225
+ Navigation: a lazily-created bar fixed at the viewport bottom — first / page
1226
+ back / slider / page forward / last, a jump-to-column box (1-based, matching
1227
+ the hover readout) and a live "column N – M of total" — plus wheel-over-track
1228
+ at a tenth of a screen per notch. Every route lands in one `msaScrollTo()`,
1229
+ which clamps and redraws; the tree never moves. A faint dashed guide runs
1230
+ from each tip's label (or its node, when labels are hidden) across to that
1231
+ tip's row, so a row reads back to its sequence without counting.
1232
+
1233
+ The conservation bar, consensus row and column ruler are a **floating strip**
1234
+ (see the time axes below); the residue rows stay with their tips.
1158
1235
 
1159
1236
  ### The time axes
1160
1237
 
@@ -1191,6 +1268,31 @@ etc., 69 intervals, frozen) is byte-identical to the desktop's; reference:
1191
1268
  Cohen, K.M., Harper, D.A.T., Gibbard, P.L. & Car, N. (2025, updated),
1192
1269
  Episodes 48: 105-115; www.stratigraphy.org.
1193
1270
 
1271
+ Banding ranks (`forester.geoBandRanks(youngMa, oldMa)`, shared with the
1272
+ desktop — change both or neither) take the span the tree actually occupies,
1273
+ youngest tip to root, not zero to root, so a fossil-only clade bands on its
1274
+ own window. A window overlapping one or two Series bands Series over **Stage**
1275
+ (the 101 ratified Phanerozoic stages plus the Pridoli, standing in for its own
1276
+ span as the printed ICS chart does); wider windows fall through the
1277
+ Period/Epoch → Era/Period → Eon/Era ladder, the finest pair that still fully
1278
+ covers the range. The overlap test is strict at both ends, so a window that
1279
+ merely touches a Series does not count it. A band label is drawn only where it
1280
+ fits its cell; a narrow stage keeps its colour and loses its name.
1281
+
1282
+ **Floating strips.** The axes and the alignment's conservation/consensus/ruler
1283
+ strip live on `_floatGroup`, a sibling of the zoomed tree group that is not
1284
+ itself transformed. Each is drawn in tree coordinates as usual and registered
1285
+ with `floatStripGroup(cls, top, height)`; `placeFloatingOverlays()` then gives
1286
+ it the tree's x and scale but a **sticky** y — `min(tree y, viewport bottom −
1287
+ strip)` — so it rides at the tree's bottom edge until that edge would leave
1288
+ the viewport and holds there instead. Each carries an opaque backdrop with a
1289
+ top rule, so tips panned underneath do not show through. Grid lines, per-node
1290
+ age bars and the alignment rows stay in the tree group, being bound to tips or
1291
+ spanning the tree's height. Exports re-anchor every strip to the tree, so a
1292
+ figure never carries an artefact of where the view happened to be scrolled.
1293
+ (The desktop pins its axes to the viewport bottom always; sticky is a
1294
+ deliberate difference.)
1295
+
1194
1296
  ## Node selection
1195
1297
 
1196
1298
  With `enableManualNodeSelection` on, the node menu gains **Select/Deselect Node**
@@ -1204,14 +1306,7 @@ var selected = archaeopteryx.getSelectedNodes(); // array of node objects
1204
1306
  Selected nodes are drawn in the selection colour, which is fixed so that it
1205
1307
  stays distinguishable from the two search colours.
1206
1308
 
1207
- ### The "Submit Selected" button is dormant
1208
-
1209
- There is also a **Submit Selected** button in the source, which would dispatch a
1210
- `submit_selected_nodes_event` on `document` for the surrounding application to
1211
- listen for. **It is not wired up**: the call that would add the button to the
1212
- control panel is commented out, so the button never appears and the event is
1213
- never fired. Poll `getSelectedNodes()` instead.
1214
-
1215
- This is left as it is on purpose, rather than either finished or deleted, until
1216
- there is a reason to decide one way or the other. If you are looking for the
1217
- event because something upstream expects it, that is the reason — say so.
1309
+ There is no push mechanism (no button or event that announces "the user is done
1310
+ selecting") — the embedding application reads the selection whenever it wants,
1311
+ typically from its own button. (Versions before 3.0 carried a dormant,
1312
+ never-rendered "Submit Selected" button in the source; it was removed.)