archaeopteryx 3.2.0 → 3.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.
Files changed (4) hide show
  1. package/README.md +96 -8
  2. package/archaeopteryx.js +1106 -183
  3. package/forester.js +895 -437
  4. package/package.json +3 -3
package/README.md CHANGED
@@ -31,6 +31,7 @@ config key live and shows the exact config JSON to copy into your own
31
31
  * [Herpesviridae DNA polymerase (201 tips)](https://cmzmasek.github.io/archaeopteryx-js/demo.html?tree=herpes_dnapol)
32
32
  * [Caliciviridae (186 strains)](https://cmzmasek.github.io/archaeopteryx-js/demo.html?tree=caliciviridae_500)
33
33
  * [Adenoviridae (321 strains)](https://cmzmasek.github.io/archaeopteryx-js/demo.html?tree=adenoviridae)
34
+ * [Apaf-1 gene family (domain architectures)](https://cmzmasek.github.io/archaeopteryx-js/demo.html?tree=apaf)
34
35
  * [Nucleotide alignment (600 columns)](https://cmzmasek.github.io/archaeopteryx-js/demo.html?tree=alignment_nt)
35
36
  * [Genome alignment (150 × 30,000 columns)](https://cmzmasek.github.io/archaeopteryx-js/demo.html?tree=genome_alignment)
36
37
  * [Sequence alignment](https://cmzmasek.github.io/archaeopteryx-js/demo.html?tree=alignment)
@@ -38,7 +39,6 @@ config key live and shows the exact config JSON to copy into your own
38
39
  * [Dinosaur time tree](https://cmzmasek.github.io/archaeopteryx-js/demo.html?tree=dinosaur)
39
40
  * [Ammonite time tree (fossil ranges)](https://cmzmasek.github.io/archaeopteryx-js/demo.html?tree=ammonite)
40
41
  * [Late Cretaceous time tree (stages)](https://cmzmasek.github.io/archaeopteryx-js/demo.html?tree=late_cretaceous)
41
- * [Apaf-1 gene family](https://cmzmasek.github.io/archaeopteryx-js/demo.html?tree=apaf)
42
42
  * [Bcl-2 family](https://cmzmasek.github.io/archaeopteryx-js/demo.html?tree=bcl2)
43
43
  * [Confidence values](https://cmzmasek.github.io/archaeopteryx-js/demo.html?tree=confidences)
44
44
  * [Branch events](https://cmzmasek.github.io/archaeopteryx-js/demo.html?tree=branch_events)
@@ -177,15 +177,19 @@ and decides by itself what is worth showing. There is nothing to configure.
177
177
  two where both make sense.
178
178
  * The **legend** is a card you can **drag anywhere**. It shows a colour and
179
179
  a **count** per value, `[by count]` / `[A-Z]` toggles the order, a dashed
180
- **no value** row counts the nodes the field does not cover, and very long
180
+ **no value** row counts the nodes the field does not cover (a value that is
181
+ nothing but underscores or a `;`/`:` qualifier counts as no value), and very long
181
182
  legends show the top 20 with a `[+N more]` chip. Legends are part of PNG,
182
183
  PDF
183
184
  and SVG exports (exports always come out light).
184
- * **Switch into a subtree** (or delete part of the tree) and the menus,
185
- counts and legends are re-derived for what is on screen — a field with too
186
- many values on the full tree may become available inside a clade. Colours
187
- never change when you do this: a value keeps its colour for the whole
188
- session.
185
+ * **Switch into a subtree** and the legend re-describes what is on screen —
186
+ rows, counts, the **no value** row, and a numeric field's colours-or-gradient
187
+ band — while the menus and your Color / Shape choice stand exactly as they
188
+ were: colouring by Genus and entering a one-genus clade shows a one-row
189
+ legend, not a grey tree. A category value keeps its colour for the whole
190
+ session; a gradient re-spans the values on screen. **Deleting** part of the
191
+ tree re-derives the menus from what is left, and keeps your choice as long
192
+ as its field still has a value somewhere.
189
193
  * The **Visualizations** checkbox hides the chosen colours/shapes; the
190
194
  **Visual Styles** checkbox controls colours embedded in the tree file
191
195
  itself (and phyloXML branch colours). Search hits and selections always
@@ -235,6 +239,37 @@ Ctrl+Shift: font size). Everything else is a button; the old Alt+letter
235
239
  combos are gone (macOS labels that key Option and types glyphs with it).
236
240
  Nothing fires while the cursor is in a text box.
237
241
 
242
+ ## Protein domain architectures
243
+
244
+ A tree whose tips carry `<domain_architecture>` elements (a protein's length
245
+ and its domains, each with a position and an E-value) draws them as **domain
246
+ tracks** beside the tips: a thin grey backbone, `L` residues long, with a
247
+ rounded box per domain, placed at its residues on one scale shared by the
248
+ whole tree so lengths compare across tips, coloured by domain name from the
249
+ Tableau palette, with the name written on the box when it fits. The tracks
250
+ appear from the start whenever a tree carries them; the **Domain
251
+ Architectures** checkbox under Display Data toggles them, and their own
252
+ section holds the controls:
253
+
254
+ * **Track width** `−` / `+` — the longest architecture's track starts at a
255
+ quarter of the window and scales by 0.8 / 1.2 per press (hold to repeat).
256
+ * **E-value ≤** `−` `10⁻³` `+` — only domains at or under the threshold are
257
+ drawn; each press moves it by a factor of ten, from `10⁻²⁰` to `10³`. The
258
+ colours are dealt again to the names that remain, in sorted order.
259
+ * **Labels** — `On domains` (the default), `Legend` (a card, at home in the
260
+ bottom-right corner, draggable, double-click to send it back: one row per
261
+ drawn name with its box count, in the order the names first appear down
262
+ the tree), or `None`.
263
+ * **Glow** — a soft glow in each domain's own colour around its box.
264
+
265
+ In the circular and unrooted layouts the tracks ride each tip's spoke
266
+ outward and carry no names (the legend still works); they need radial
267
+ labels, which switching layouts turns on. A malformed domain — a missing or
268
+ impossible position or E-value — is skipped and counted in a console
269
+ warning, never fatal. The tracks ride into the SVG, PDF and PNG exports.
270
+ This is the desktop's domain display, drawn to the same numbers
271
+ (`test/domain_test.js` holds them).
272
+
238
273
  ## Sequence alignments
239
274
 
240
275
  A tree whose tips carry `<mol_seq is_aligned="true">` shows the alignment as
@@ -390,7 +425,7 @@ viewer.destroy(); // unmount COMPLETELY: the container DOM, the node
390
425
  // handler; a later launch() works normally
391
426
  ```
392
427
 
393
- **Big trees draw on the next frame.** Above 2,000 nodes, `launch()` does all
428
+ **Big trees draw on the next frame.** Above 3,000 nodes, `launch()` does all
394
429
  its validation, shows a "Drawing N nodes" card over the tree area, and
395
430
  returns within milliseconds — the label analysis, visualization candidates,
396
431
  control panel and the draw itself all run one frame later, so the browser
@@ -615,6 +650,10 @@ copy-pastable JSON.
615
650
  | `layout` | `'rectangular'` | The starting layout: `'rectangular'`, `'circular'`, or `'unrooted'`. |
616
651
  | `ladderizeTree` | `true` | Ladderize the tree on load: at each node, the larger clade first (any number of children, so a polytomy sorts too). |
617
652
  | `showMsa` | tree-derived | Open with the alignment track shown. Default: on when the tree carries an aligned `mol_seq`, off otherwise — an explicit `true`/`false` overrides that. |
653
+ | `showDomainArchitectures` | tree-derived | Open with the domain tracks shown. Default: on when any tip carries a `<domain_architecture>`, off otherwise — an explicit `true`/`false` overrides that. |
654
+ | `domainLabels` | `'domains'` | Where domain names go: `'domains'` (on the boxes), `'legend'` (a card), or `'none'`. |
655
+ | `domainGlow` | `false` | Open with the glow around each domain box on. |
656
+ | `domainEvalueExponent` | `-3` | The E-value threshold's exponent at launch, an integer from `-20` to `3`: domains with an E-value at or under `10^exponent` are drawn. |
618
657
  | `showTimeAxis` | tree-derived | Open with the time axis shown. Default: on when the tree carries `<date>` elements, off otherwise — an explicit `true`/`false` overrides that. |
619
658
  | `timeAxisGrid` | `false` | Open with the Time Grid vertical lines on (only meaningful — and only offered as a checkbox — while the time axis itself is shown). |
620
659
  | `showSupportDots` | `false` | Open with the Support Dots marks on (the checkbox appears whenever the tree has confidences). |
@@ -1188,6 +1227,55 @@ minus π/2 in circular; `labelAngleDeg` rotates a label along its spoke and
1188
1227
  consumer (overview dots, hit navigator, node transforms). Unrooted disables
1189
1228
  aligned phylograms and label auto-hiding, as the desktop does.
1190
1229
 
1230
+ ### The domain tracks
1231
+
1232
+ Data model: per-tip `sequences[i].domain_architecture = {length, domains:
1233
+ [{name, from, to, confidence}]}` — the first sequence carrying one; `length`
1234
+ must be a positive integer or the architecture is not drawn. A domain is
1235
+ drawable when `from` and `to` are integers with `to > from` and `confidence`
1236
+ (its E-value) is a number; otherwise it is skipped and counted
1237
+ (`forester.domainArchitectureDomains`). Gate: `showDomainArchitectures`
1238
+ state (auto-on when `_basicTreeProperties.domainArchitectures`) AND external
1239
+ labels shown AND, in a radial layout, radial rather than upright labels.
1240
+
1241
+ Scale: one factor for the tree, `f = W_eff / Lmax × 0.9` px per residue.
1242
+ `W` (the track width) starts at `0.25 × viewport width`; `d+` / `d−` scale it
1243
+ by 1.2 / 0.8 and stop at 2000 / 20. `W_eff = W` in the rectangular layout,
1244
+ `min(W, 0.2 × radius)` in the radial ones. `Lmax` is the longest architecture
1245
+ in the displayed tree, counting every domain whatever its E-value, so the
1246
+ threshold never rescales. The rectangular layout reserves `20 + W + 10` px
1247
+ from `_w` past the label reservation (`_domainReserve`, counted wherever `_w`
1248
+ is), so the tree compresses to make room; the radial fit adds
1249
+ `4 + W_eff + 10` to the ring. Placement: rectangular `start = _w +
1250
+ nodeLabelGap + labelSpace + 20` for every tip (one aligned column) with box
1251
+ height `clamp(round(tipPitch / 2), 6, 16)`; circular `r0 = maxRad +
1252
+ labelSpace + 4` under `rotate(spoke)`; unrooted `translate(tip)
1253
+ rotate(spoke)` with `start = labelSpace + 4`. A domain `from..to` covers
1254
+ `[start + (from − 1) f, start + to f]` — residue `r` is `[(r − 1) f, r f]`,
1255
+ decided jointly with the desktop on 2026-09-12.
1256
+
1257
+ Drawing, per box, in this order: three stepped shadow rects (`rgb(8,18,21)`
1258
+ at 40 / 28 / 17 of 255, offset 0.4/0.7, 0.9/1.5, 1.6/2.5), the optional two
1259
+ glow rects (the base colour at 20 then 34 of 255, grown by 3.2 then 1.6),
1260
+ the body (a vertical gradient `lighten(base, 0.12)` → `darken(base, 0.10)`,
1261
+ corner radius `min(2, min(w, h) / 2)`) with a 1 px `darken(base, 0.24)`
1262
+ border, and the name — rectangular only, in `min(external font, h − 2)` px
1263
+ when that is over 4 px and the text is at most `w − 4` wide, in near-black
1264
+ when the base luminance is over 0.55 and white otherwise. Colours: the drawn
1265
+ names over the whole tree, sorted by code unit, take Tableau 10 in order,
1266
+ then the same ten shifted toward white (odd cycles) or black (even cycles)
1267
+ by `min(0.55, 0.2 × cycle)`; an unnamed domain is `#808080`; dealt at load,
1268
+ after an edit and on every threshold change, and a name met later takes the
1269
+ next unused index. Legend (`'legend'` mode): title `Protein domains
1270
+ (E ≤ 1e<exp>)`, rows `NAME (count)` in first-appearance order over the tips
1271
+ in display order, clipped to 240 px; home bottom-right, inset 10; a drag
1272
+ keeps its place as a fraction of the view, a double-click sends it home.
1273
+ Everything is plain rects plus one `<linearGradient>` per colour in the
1274
+ track group's own `<defs>`, so exports match the screen. The acceptance
1275
+ numbers — apaf.xml: 31 tips, `Lmax` 2080, 202 domains; 9 names / 166 boxes
1276
+ at 1e−3; the palette; 22_MOUSE's box offsets at `W = 300` — are the
1277
+ desktop's, in `test/domain_test.js`.
1278
+
1191
1279
  ### The alignment track
1192
1280
 
1193
1281
  Data model: per-tip `sequences[0].mol_seq = {is_aligned, value}` (the gapped