archaeopteryx 3.15.0 → 3.16.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 CHANGED
@@ -256,11 +256,38 @@ the mouse wheel zooms too, and never rotates), **X− / X+ become rotate** (a
256
256
  32nd of a turn per press), and the fit-width slot becomes the **node label
257
257
  direction** flip — labels riding their spokes or standing upright — while
258
258
  vertical expansion greys out. **Fit** centres and scales the fan; **Esc**
259
- also resets rotation and label direction. Unrooted
260
- additionally greys out the aligned-phylogram option (there is no common label
261
- edge). Auto-hide Labels stays live: the tip-label thinning it governs needs
262
- even row spacing and so does nothing in unrooted, but the crowded-branch-data
263
- rule it also governs applies in every layout.
259
+ also resets rotation and label direction. **Each radial layout greys out the
260
+ display type it cannot show.** Circular always aligns — its external labels are
261
+ pulled out to a shared ring, with dashed connectors to match, whichever type is
262
+ chosen — so the circular phylogram is the aligned one, and the greyed button
263
+ there is the *unaligned* phylogram. Unrooted is the other way round: it has no
264
+ common edge to align to, so the aligned type is the one greyed. The button shown
265
+ as chosen describes the picture, and choosing the phylogram in circular leaves
266
+ your aligned-or-not preference for the other layouts untouched. Auto-hide Labels
267
+ stays live in every layout.
268
+
269
+ ### The control-panel cheat sheet
270
+
271
+ The card button in the panel header opens **Control panel**: one row for every
272
+ control the panel is currently showing, in the order it shows them, each with
273
+ the control's own glyph or name and the sentence that explains it — the layout
274
+ and display-type buttons included, drawn with the very glyph they carry in the
275
+ panel. The About box has a row for it too.
276
+
277
+ The display types say what they do and when they are greyed, whether or not
278
+ they are greyed in the view you are looking at: *"phylogram: branch lengths
279
+ drawn to scale, so the tips end ragged. Greyed in the circular layout, which
280
+ always carries its labels to the outer ring, so there the aligned phylogram is
281
+ the one drawn."*
282
+
283
+ It is **modeless** and sits beside the panel, so a row can be read while the
284
+ control it names is used. It describes what is on the screen: fold a section
285
+ and its controls leave the sheet, open a tree that offers no alignment and the
286
+ alignment controls are not listed. Nothing on it is written twice — a row's
287
+ words are the tooltip the control already carries, so a control added later
288
+ needs no edit here, only a tooltip. And no row shows a live value, so a sheet
289
+ that is saved or printed does not go wrong for every reader but the one who
290
+ made it.
264
291
 
265
292
  ## Rooting
266
293
 
@@ -538,9 +565,13 @@ phyloXML's domain `id` is optional, and a file with names alone (our own
538
565
  accessions and not Pfam identifiers. Only the domain boxes take the mouse, so
539
566
  the tree behind the track stays clickable.
540
567
 
541
- In the circular and unrooted layouts the tracks ride each tip's spoke
542
- outward and carry no names (the legend still works); they need radial
543
- labels, which switching layouts turns on. A malformed domain — a missing or
568
+ In the circular and unrooted layouts the tracks ride each named tip's spoke
569
+ outward and carry no names of their own (the legend still works); they need
570
+ radial labels, which switching layouts turns on. An architecture goes with
571
+ its name: where the crowding rule has taken a tip's name away, its track is
572
+ left out too, since a track with no name beside it can only be identified by
573
+ which spoke it sits on. Switching the name fields off is not the same thing —
574
+ nothing is hidden by the rule then, and every track is still drawn. A malformed domain — a missing or
544
575
  impossible position or E-value — is skipped and counted in a console
545
576
  warning, never fatal. The tracks ride into the SVG, PDF and PNG exports.
546
577
  This is the desktop's domain display, drawn to the same numbers
@@ -1111,6 +1142,54 @@ mark claims the box it is about to occupy, and one that would overlap a box
1111
1142
  already claimed in that pass is left out. The claim order is the tree's own,
1112
1143
  root first, so the mark nearer the root keeps its place and the same tree at
1113
1144
  the same size always drops the same marks — on screen and in every export.
1145
+
1146
+ **The Auto-hide Labels toggle lights up while it is taking something away**,
1147
+ and its tooltip says what. The switch governs three rules and the light asks
1148
+ all three: *1 in k labels shown* in the rectangular layout, which thins by
1149
+ index; *n names that would overprint* in the two radial layouts, which thin by
1150
+ overlap; and *n branch values that would overlap*, in any layout. It stays dark
1151
+ on a tree with room for everything.
1152
+
1153
+ **In the circular and unrooted layouts, crowded tip labels are hidden by
1154
+ whether they actually overprint.** A name is drawn only where its own outline
1155
+ overlaps no name already drawn; the order is the tree's own, root first, so
1156
+ the same tree at the same size always keeps the same names. **A name found by
1157
+ a search is the exception**: it is drawn without being asked, so what you
1158
+ searched for is always on the screen — and since the names it would have
1159
+ yielded to are already down, a hit can be drawn across one. That is the rule
1160
+ both programs agreed on, the hit being the thing you are looking for, and it
1161
+ is the one case where the sentence above does not hold. The outlines are compared as they are drawn, turned, not as the
1162
+ upright boxes that enclose them — the bounds of a turned name are several
1163
+ times its own area, and comparing those would drop names that are plainly
1164
+ clear of each other.
1165
+
1166
+ The rectangular layout keeps the every-k-th thinning, where it belongs: its
1167
+ rows really are evenly spaced, and `k` is read from the font size against the
1168
+ row pitch. A fan has no rows, and until 2026-09-27 the circular layout
1169
+ borrowed that rule anyway — thinning a ring by the display's *height* over the
1170
+ node count, a quantity with nothing to do with a ring's circumference. It was
1171
+ wrong in both directions. Measured at 1100×850: on `Caliciviridae_100.xml` it
1172
+ kept 48 of 97 names where all 97 fit the ring with **not one** overlapping
1173
+ pair; on `flu_h5.xml` it kept 59 of 354 where 118 are readable. Both now draw
1174
+ what fits.
1175
+
1176
+ Both fans lose names where a fan is crowded — circular takes 236 of 354 on
1177
+ `flu_h5.xml`, and unrooted is the harsher of the two: on `Caliciviridae_100.xml`
1178
+ its 97 names had 172 overlapping pairs, the deepest printing 9.5 px through
1179
+ its neighbour, and 34 remain with none overlapping by more than the width of
1180
+ the measurement itself. Where there is room, nothing is dropped:
1181
+ `woese-tree-of-life.xml` keeps all 23 in every layout.
1182
+
1183
+ **Names go down first, and numbers yield to them.** Every node label that will
1184
+ be drawn — a tip name or a clade name — reserves its space before any mark is
1185
+ placed, and it is never asked: a label is drawn whatever else is there, so a
1186
+ number that would print through a name is the one left out. A value that has
1187
+ landed across a name is worse than a value not drawn at all, and it is the
1188
+ name that says what the tree is about. Measured at 1100×850 with both numbers
1189
+ on, before this: 44 of 93 numbers printed through a name in the rectangular
1190
+ view of `flu_h5.xml`, 30 of 55 on `confidences.xml`, 10 of 15 in the unrooted
1191
+ view. Now none, in any of the three layouts, and no number is refused unless
1192
+ something drawn is in its way.
1114
1193
  Numbers and symbols are kept in separate maps, since the symbol sits on the
1115
1194
  branch and the numbers just above and below it. Symbols are never shrunk to
1116
1195
  fit: where a symbol's size means something, a smaller one would report
@@ -1334,7 +1413,7 @@ All 118 of them, alphabetically:
1334
1413
  | `showBranchVisualizations` | Node and branch visualizations are one switch now; use the Visualizations checkbox. |
1335
1414
  | `showConfidenceValues` | Shown when the tree has confidences. |
1336
1415
  | `showDistributions` | Off by default. |
1337
- | `showDynahideButton` | Shown automatically once the tree has enough tips to need it. |
1416
+ | `showDynahideButton` | The Auto-hide Labels checkbox is always shown. |
1338
1417
  | `showExternalLabels` | On by default; use the Ext. Labels checkbox. |
1339
1418
  | `showExternalLabelsButton` | Always shown. |
1340
1419
  | `showExternalNodes` | Node shapes now appear wherever a node visualization applies. |
@@ -1354,7 +1433,7 @@ All 118 of them, alphabetically:
1354
1433
  | `showSequenceGeneSymbol` | Sequence labelling follows what the tree contains. |
1355
1434
  | `showSequenceName` | Sequence labelling follows what the tree contains. |
1356
1435
  | `showSequenceSymbol` | Sequence labelling follows what the tree contains. |
1357
- | `showShortenNodeNamesButton` | Shown automatically when the tree has long node names. |
1436
+ | `showShortenNodeNamesButton` | The Short Names checkbox is always shown; it starts on when the tree has long node names. |
1358
1437
  | `showTaxonomy` | Shown when the tree has taxonomies. |
1359
1438
  | `showTaxonomyButton` | Shown automatically when the tree has taxonomies. |
1360
1439
  | `showTaxonomyCode` | Taxonomy labelling follows what the tree contains. |
@@ -1732,6 +1811,22 @@ The 2026 additions beyond the visualization system, specified tightly enough
1732
1811
  to rebuild. All pure logic lives in forester.js under `npm test`; the viewer
1733
1812
  draws.
1734
1813
 
1814
+ The counts quoted above are measurements on one machine, and how many names
1815
+ fit a ring depends on how wide the system draws them: the same tree keeps 34
1816
+ in the unrooted view here and 33 on a Linux CI runner, with the crowding
1817
+ identical on both (97 names, 172 overlapping pairs with the rule off). The
1818
+ rule is the same; the font is not.
1819
+
1820
+ What the viewer draws is checked separately, by driving it in headless Chrome:
1821
+ `npm run test:browser` (or `test:browser:quick`, one case per harness, which is
1822
+ what CI runs). Those harnesses open a real tree, work the controls and measure
1823
+ the result — which marks are drawn, where they sit, whether a control lights.
1824
+ They exist because `npm test` cannot reach any of it: it covers the arithmetic,
1825
+ and the defects this code has actually had were wiring. A connector drawn out
1826
+ to the ring for a name that was hidden, an Auto-hide indicator dark over a tree
1827
+ it was thinning, a domain architecture left beside a tip whose name had gone —
1828
+ each of those passed every node test and every lint.
1829
+
1735
1830
  ### The unrooted layout
1736
1831
 
1737
1832
  `forester.equalAngleLayout(root, startAngle, lengthOf)` — Meacham's
@@ -1754,8 +1849,12 @@ mathematics — `spokeAngle(d)` is `uangle` in unrooted and the cluster angle
1754
1849
  minus π/2 in circular; `labelAngleDeg` rotates a label along its spoke and
1755
1850
  `labelFlip` adds 180° on the left half (`spokeAngle mod 2π ∈ (π/2, 3π/2)`).
1756
1851
  `layoutPointXY(d)` resolves a node's position in any layout for every
1757
- consumer (overview dots, hit navigator, node transforms). Unrooted disables
1758
- aligned phylograms and label auto-hiding, as the desktop does.
1852
+ consumer (overview dots, hit navigator, node transforms). Unrooted has no
1853
+ common edge to align labels to, so the aligned phylogram is the display type
1854
+ it greys out (circular greys the unaligned one instead, since it always
1855
+ aligns). Neither radial layout has even rows, so the every-k-th
1856
+ tip-label thinning runs in the rectangular layout alone — both fans hide their
1857
+ crowded names by overlap instead, as on the desktop.
1759
1858
 
1760
1859
  ### The domain tracks
1761
1860
 
@@ -1766,7 +1865,10 @@ drawable when `from` and `to` are integers with `to > from` and `confidence`
1766
1865
  (its E-value) is a number; otherwise it is skipped and counted
1767
1866
  (`forester.domainArchitectureDomains`). Gate: `showDomainArchitectures`
1768
1867
  state (auto-on when `_basicTreeProperties.domainArchitectures`) AND external
1769
- labels shown AND, in a radial layout, radial rather than upright labels.
1868
+ labels shown AND, in a radial layout, radial rather than upright labels AND,
1869
+ per tip, a name the crowding rule has not taken (`_labelDropped`) — note
1870
+ "taken by the rule", not "absent": with the name fields switched off nothing
1871
+ is hidden by the rule and every track is still drawn.
1770
1872
 
1771
1873
  Scale: one factor for the tree, `f = W_eff / Lmax × 0.9` px per residue.
1772
1874
  `W` (the track width) starts at `0.25 × viewport width`; `d+` / `d−` scale it
@@ -1779,8 +1881,8 @@ threshold never rescales. The rectangular layout reserves `20 + W + 10` px
1779
1881
  from `_w` past the label reservation (`_domainReserve`, counted wherever `_w`
1780
1882
  is), so the tree compresses to make room; the radial fit adds
1781
1883
  `4 + W_eff + 10` to the ring. Placement: rectangular `start = _w +
1782
- nodeLabelGap + labelSpace + 20` for every tip (one aligned column) with box
1783
- height `clamp(round(tipPitch / 2), 6, 16)`; circular `r0 = maxRad +
1884
+ nodeLabelGap + labelSpace + 20` for every tip still showing its name (one
1885
+ aligned column) with box height `clamp(round(tipPitch / 2), 6, 16)`; circular `r0 = maxRad +
1784
1886
  labelSpace + 4` under `rotate(spoke)`; unrooted `translate(tip)
1785
1887
  rotate(spoke)` with `start = labelSpace + 4`. A domain `from..to` covers
1786
1888
  `[start + (from − 1) f, start + to f]` — residue `r` is `[(r − 1) f, r f]`,