archaeopteryx 3.25.0 → 3.26.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 +28 -10
- package/archaeopteryx.d.ts +3 -0
- package/archaeopteryx.js +85 -32
- package/forester.js +8 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -255,10 +255,14 @@ program's.
|
|
|
255
255
|
|
|
256
256
|
A phylogram carries a **scale bar** at the bottom left: a round number of
|
|
257
257
|
branch-length units (1, 2 or 5 × 10ᵏ, whichever makes the bar about 100 px)
|
|
258
|
-
with its length written above it
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
the
|
|
258
|
+
with its length written above it, followed by the unit the tree states
|
|
259
|
+
(phyloXML's `branch_length_unit`, e.g. `0.05 subs/site`) and by nothing when
|
|
260
|
+
it states none: a tree that does not say what its lengths measure gets no
|
|
261
|
+
guess. It is drawn with the tree, so it zooms and exports with it and its
|
|
262
|
+
label always holds. A cladogram has nothing to measure and shows none, and a
|
|
263
|
+
tree under a scale axis leaves the measuring to the axis. **Scale** under
|
|
264
|
+
Display Data > Options hides it (on by default; config `showScaleBar`, view
|
|
265
|
+
key `scaleBar`; the desktop's switch has the same name and defaults to off).
|
|
262
266
|
|
|
263
267
|
**Scale Axis** under Display Data (off by default, as on the desktop) draws a
|
|
264
268
|
labelled ruler under a phylogram, from 0 at the root out to the deepest tip, in
|
|
@@ -1552,6 +1556,7 @@ copy-pastable JSON.
|
|
|
1552
1556
|
| `geneFamily` | `'auto'` | The annotation namespace that colours the genes and anchors the rows: `'auto'` (the one most genes carry) or a prefix such as `'pgfam'`. |
|
|
1553
1557
|
| `geneLabels` | `'genes'` | Where gene symbols go: `'genes'` (on the arrows), `'legend'` (a card of the families), or `'none'`. |
|
|
1554
1558
|
| `showScaleAxis` | tree-derived | Open with the scale axis shown: the time axis on a time tree whose branches show time, a distance axis on any other phylogram. Default: on when the tree carries `<date>` elements and opens shown in time, off otherwise (a dated tree that opens in divergence is a divergence tree on screen) — an explicit `true`/`false` overrides that. |
|
|
1559
|
+
| `showScaleBar` | `true` | Open with the scale bar at the bottom left of a phylogram (a round length in the tree's branch-length unit). It gives way while the scale axis is shown either way. |
|
|
1555
1560
|
| `showScaleGrid` | `false` | Open with the Scale Grid lines on (only meaningful — and only offered as a checkbox — while the scale axis itself is shown). |
|
|
1556
1561
|
| `showSupportDots` | `false` | Open with the Support Dots marks on (the checkbox appears whenever the tree has confidences). |
|
|
1557
1562
|
| `supportDotMinimum` | `95` | Support Dots threshold, as a percentage. On a tree whose confidences top out at 1 (posterior probabilities) it is read on the 0–1 scale, so the default means ≥ 0.95 there and ≥ 95 on a bootstrap tree. |
|
|
@@ -1919,17 +1924,29 @@ exists, and clears the per-legend chip states.
|
|
|
1919
1924
|
Highest first, at each paint:
|
|
1920
1925
|
|
|
1921
1926
|
* **Label colour**: search/selection highlight → active Color visualization
|
|
1922
|
-
|
|
1927
|
+
(its colour; the theme ink for a node without a value) → `style:font_color`
|
|
1928
|
+
→ phyloXML branch colour → theme ink.
|
|
1923
1929
|
* **Node fill**: highlight → duplication/speciation event colour → active
|
|
1924
|
-
Color visualization
|
|
1925
|
-
|
|
1930
|
+
Color visualization (its colour; a node without a value draws no dot,
|
|
1931
|
+
or a hollow one while Node events are shown) → `style:node_color` (else
|
|
1932
|
+
`style:font_color`) → background.
|
|
1926
1933
|
* **Node outline**: darkened highlight → event colour → visualization fill
|
|
1927
|
-
→ style colour
|
|
1934
|
+
→ style colour (not while a Color visualization is active) → branch colour
|
|
1935
|
+
→ branch default.
|
|
1928
1936
|
* **Node shape path**: suppressed for highlighted/event nodes; chosen Shape
|
|
1929
1937
|
visualization → `style:node_shape`. A node earns its default dot when a
|
|
1930
1938
|
Color visualization is active (and no shape was drawn), or when it
|
|
1931
1939
|
carries `style:node_color` — `font_color` alone paints only the label.
|
|
1932
1940
|
|
|
1941
|
+
While a Color visualization is active the style colours are **not consulted
|
|
1942
|
+
for any node**, valued or not: not for the label, the dot, its outline, the
|
|
1943
|
+
hover glow or the clock plot's points. The visualization owns the colours and
|
|
1944
|
+
its legend explains them; a node without a value takes the default label
|
|
1945
|
+
colour and draws no dot. That is the desktop's rule (its TreePanel.setColor).
|
|
1946
|
+
Clearing the Color menu brings the file's colours back. Branch colours,
|
|
1947
|
+
shapes, font sizes and styles are not colours of the visualization's kind
|
|
1948
|
+
and stay.
|
|
1949
|
+
|
|
1933
1950
|
### Legend anatomy
|
|
1934
1951
|
|
|
1935
1952
|
One draggable SVG card per active visualization (colour, then shape,
|
|
@@ -2126,8 +2143,9 @@ honoured: `style:font_color`, `style:node_color`, `style:node_shape`
|
|
|
2126
2143
|
The **Visual Styles** checkbox — the desktop's "Visual Styles/Branch Colors",
|
|
2127
2144
|
shown when the tree carries either, on by default — turns them off and on,
|
|
2128
2145
|
and gates phyloXML `<color>` branch colours too, exactly as on the desktop.
|
|
2129
|
-
An active Color visualization outranks
|
|
2130
|
-
|
|
2146
|
+
An active Color visualization outranks the style colours for every node,
|
|
2147
|
+
valued or not, on labels and node dots alike, as on the desktop: set the
|
|
2148
|
+
Color menu to default to see the tree as its file styled it.
|
|
2131
2149
|
`style:` never appears in the Color / Shape menus — it is rendering, not data.
|
|
2132
2150
|
|
|
2133
2151
|
### Moving the legends
|
package/archaeopteryx.d.ts
CHANGED
|
@@ -138,6 +138,8 @@ export interface ArchaeopteryxConfig {
|
|
|
138
138
|
* branches show time, a distance axis on any other. Default: on for a
|
|
139
139
|
* time tree, off otherwise. */
|
|
140
140
|
showScaleAxis?: boolean;
|
|
141
|
+
/** The scale bar at the bottom left of a phylogram; on unless false. */
|
|
142
|
+
showScaleBar?: boolean;
|
|
141
143
|
/** Grid lines (rings, in circular) at the scale axis's ticks. */
|
|
142
144
|
showScaleGrid?: boolean;
|
|
143
145
|
showSupportDots?: boolean;
|
|
@@ -213,6 +215,7 @@ export interface ViewState {
|
|
|
213
215
|
geneLabels?: 'none' | 'genes' | 'legend';
|
|
214
216
|
scaleAxis?: boolean;
|
|
215
217
|
scaleGrid?: boolean;
|
|
218
|
+
scaleBar?: boolean;
|
|
216
219
|
/** @deprecated the name of scaleAxis in older links; still read. */
|
|
217
220
|
timeAxis?: boolean;
|
|
218
221
|
/** @deprecated the name of scaleGrid in older links; still read. */
|
package/archaeopteryx.js
CHANGED
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
*
|
|
21
21
|
*/
|
|
22
22
|
|
|
23
|
-
// v 3.
|
|
23
|
+
// v 3.26.0
|
|
24
24
|
// 2026-09-17
|
|
25
25
|
//
|
|
26
26
|
// Archaeopteryx.js is a software tool for the visualization and
|
|
@@ -103,7 +103,7 @@ function (root, d3, forester, phyloXml) {
|
|
|
103
103
|
// IIFE's own function name -- a plain object says what it is.)
|
|
104
104
|
let archaeopteryx = {};
|
|
105
105
|
|
|
106
|
-
const VERSION = '3.
|
|
106
|
+
const VERSION = '3.26.0';
|
|
107
107
|
const WEBSITE = 'https://cmzmasek.github.io/archaeopteryx-js/';
|
|
108
108
|
const DESKTOP_WEBSITE = 'https://cmzmasek.github.io/archaeopteryx/';
|
|
109
109
|
const SOURCE_WEBSITE = 'https://github.com/cmzmasek/archaeopteryx-js';
|
|
@@ -390,6 +390,7 @@ function (root, d3, forester, phyloXml) {
|
|
|
390
390
|
const GENE_LABELS_SELECT = 'gene_labels';
|
|
391
391
|
const SCALE_AXIS_CB = 'scaleaxis_cb';
|
|
392
392
|
const SCALE_GRID_CB = 'scalegrid_cb';
|
|
393
|
+
const SCALE_BAR_CB = 'scalebar_cb';
|
|
393
394
|
const MSA_SCROLL_ID = 'aptxmsascroll';
|
|
394
395
|
const FONT_SIZE_SLIDER = 'fs_sl';
|
|
395
396
|
const EXTERNAL_LABEL_CB = 'extl_cb';
|
|
@@ -1447,8 +1448,9 @@ function (root, d3, forester, phyloXml) {
|
|
|
1447
1448
|
// a node coloured by Host Group glows in its host colour -- and the UI
|
|
1448
1449
|
// accent otherwise. As on the desktop (TreePanel.hoverGlowColor). The
|
|
1449
1450
|
// precedence is the one the node itself is painted by: the Color-by
|
|
1450
|
-
// value, then a per-node visual style
|
|
1451
|
-
//
|
|
1451
|
+
// value, then a per-node visual style (not while a Color-by is active,
|
|
1452
|
+
// see nodeStyleColor), then an event colour, then a colourised clade's
|
|
1453
|
+
// branch colour. NEVER the found/search colour: a
|
|
1452
1454
|
// focus ring must not read as a selection state.
|
|
1453
1455
|
//
|
|
1454
1456
|
// The glow is a 13-23% alpha wash, so a dark or a pale colour would
|
|
@@ -1462,10 +1464,7 @@ function (root, d3, forester, phyloXml) {
|
|
|
1462
1464
|
c = vis;
|
|
1463
1465
|
}
|
|
1464
1466
|
if (!c) {
|
|
1465
|
-
|
|
1466
|
-
if (style && (style.nodeColor || style.fontColor)) {
|
|
1467
|
-
c = style.nodeColor || style.fontColor;
|
|
1468
|
-
}
|
|
1467
|
+
c = nodeStyleColor(d);
|
|
1469
1468
|
}
|
|
1470
1469
|
if (!c && _state.showNodeEvents && d.events && d.children) {
|
|
1471
1470
|
c = makeNodeEventsDependentColor(d.events);
|
|
@@ -2430,6 +2429,36 @@ function (root, d3, forester, phyloXml) {
|
|
|
2430
2429
|
return ((_vis && _vis.colorId) ? _vis.byId[_vis.colorId] : null) || null;
|
|
2431
2430
|
}
|
|
2432
2431
|
|
|
2432
|
+
// A Color visualization is on screen: it owns every node's colour, and the
|
|
2433
|
+
// file's style colours wait until the Color menu is cleared (the desktop's
|
|
2434
|
+
// rule; see makeLabelColor and makeNodeFillColor).
|
|
2435
|
+
function colorVisActive() {
|
|
2436
|
+
return !!_state.showVisualizations && !!currentColorVis();
|
|
2437
|
+
}
|
|
2438
|
+
|
|
2439
|
+
// The colour a node's style gives it, or null: style:node_color (else
|
|
2440
|
+
// style:font_color) for the node's mark, style:font_color for its label.
|
|
2441
|
+
// Null while a Color visualization is active -- the desktop's rule
|
|
2442
|
+
// (TreePanel.setColor): the visualization owns every node's colour and
|
|
2443
|
+
// its legend explains them; a node without a value takes the default ink
|
|
2444
|
+
// and no dot rather than the file's colour. Until 2026-10-08 the valueless
|
|
2445
|
+
// nodes fell through to the file's colour on their dots, so BV-BRC's
|
|
2446
|
+
// trees -- style:font_color on every tip, following Genus -- showed two
|
|
2447
|
+
// palettes under Color by Host (Christian: adopt the desktop's rule).
|
|
2448
|
+
// EVERY reader of a style colour goes through here, so none can forget
|
|
2449
|
+
// the rule: the label, the dot, its outline, the hover glow, the clock
|
|
2450
|
+
// plot's points (which a first version of the rule missed).
|
|
2451
|
+
function nodeStyleColor(node, forLabel) {
|
|
2452
|
+
if (colorVisActive()) {
|
|
2453
|
+
return null;
|
|
2454
|
+
}
|
|
2455
|
+
let style = nodeStyle(node);
|
|
2456
|
+
if (!style) {
|
|
2457
|
+
return null;
|
|
2458
|
+
}
|
|
2459
|
+
return (forLabel ? style.fontColor : (style.nodeColor || style.fontColor)) || null;
|
|
2460
|
+
}
|
|
2461
|
+
|
|
2433
2462
|
function currentShapeVis() {
|
|
2434
2463
|
return ((_vis && _vis.shapeId) ? _vis.byId[_vis.shapeId] : null) || null;
|
|
2435
2464
|
}
|
|
@@ -3676,11 +3705,9 @@ function (root, d3, forester, phyloXml) {
|
|
|
3676
3705
|
if (visColor !== _state.backgroundColorDefault) {
|
|
3677
3706
|
return visColor;
|
|
3678
3707
|
}
|
|
3679
|
-
|
|
3680
|
-
|
|
3681
|
-
|
|
3682
|
-
}
|
|
3683
|
-
return visColor;
|
|
3708
|
+
// the style colour, or the background -- which, under an active Color
|
|
3709
|
+
// visualization, drawTreeGeometry turns into no dot at all
|
|
3710
|
+
return nodeStyleColor(phynode) || visColor;
|
|
3684
3711
|
};
|
|
3685
3712
|
|
|
3686
3713
|
// A darker shade of a node's found/selected highlight color, used as a thin
|
|
@@ -3713,10 +3740,11 @@ function (root, d3, forester, phyloXml) {
|
|
|
3713
3740
|
return v;
|
|
3714
3741
|
}
|
|
3715
3742
|
}
|
|
3716
|
-
let
|
|
3717
|
-
if (
|
|
3718
|
-
return
|
|
3743
|
+
let styleColor = nodeStyleColor(phynode);
|
|
3744
|
+
if (styleColor) {
|
|
3745
|
+
return styleColor;
|
|
3719
3746
|
}
|
|
3747
|
+
// the branch colour, unlike a style colour, holds under a Color-by (desktop)
|
|
3720
3748
|
if (_state.useVisualStyles && phynode.color) {
|
|
3721
3749
|
let c = phynode.color;
|
|
3722
3750
|
return "rgb(" + c.red + "," + c.green + "," + c.blue + ")";
|
|
@@ -3729,17 +3757,15 @@ function (root, d3, forester, phyloXml) {
|
|
|
3729
3757
|
if (foundColor) {
|
|
3730
3758
|
return foundColor;
|
|
3731
3759
|
}
|
|
3732
|
-
|
|
3733
|
-
|
|
3734
|
-
|
|
3735
|
-
|
|
3736
|
-
|
|
3760
|
+
// an active Color visualization owns the colours: its colour where
|
|
3761
|
+
// the node has a value, the default ink where it has none (and
|
|
3762
|
+
// nodeStyleColor is null meanwhile, see there)
|
|
3763
|
+
if (colorVisActive()) {
|
|
3764
|
+
return makeVisLabelColor(phynode);
|
|
3737
3765
|
}
|
|
3738
|
-
|
|
3739
|
-
|
|
3740
|
-
|
|
3741
|
-
if (style && style.fontColor) {
|
|
3742
|
-
return style.fontColor;
|
|
3766
|
+
let fontColor = nodeStyleColor(phynode, true);
|
|
3767
|
+
if (fontColor) {
|
|
3768
|
+
return fontColor;
|
|
3743
3769
|
}
|
|
3744
3770
|
if (_state.useVisualStyles && phynode.color) {
|
|
3745
3771
|
let c = phynode.color;
|
|
@@ -5747,6 +5773,7 @@ function (root, d3, forester, phyloXml) {
|
|
|
5747
5773
|
'geneFamily',
|
|
5748
5774
|
'geneLabels',
|
|
5749
5775
|
'showScaleAxis',
|
|
5776
|
+
'showScaleBar',
|
|
5750
5777
|
'showScaleGrid',
|
|
5751
5778
|
'showSupportDots',
|
|
5752
5779
|
'searchAinitialValue',
|
|
@@ -6113,6 +6140,8 @@ function (root, d3, forester, phyloXml) {
|
|
|
6113
6140
|
_state.showScaleAxis = !!(_timeInfo && _timeInfo.type) && !branchesShowDivergence();
|
|
6114
6141
|
}
|
|
6115
6142
|
_state.showScaleGrid = _state.showScaleGrid === true; // desktop default: off
|
|
6143
|
+
// the scale bar is on unless the caller says no; it gives way to the axis anyway
|
|
6144
|
+
_state.showScaleBar = _state.showScaleBar !== false;
|
|
6116
6145
|
_state.showSupportDots = _state.showSupportDots === true;
|
|
6117
6146
|
_state.showNodeEvents = _basicTreeProperties.nodeEvents === true;
|
|
6118
6147
|
_state.showBranchEvents = _basicTreeProperties.branchEvents === true;
|
|
@@ -10018,6 +10047,7 @@ function (root, d3, forester, phyloXml) {
|
|
|
10018
10047
|
if (_basicTreeProperties.branchLengths === true) {
|
|
10019
10048
|
s.scaleAxis = _state.showScaleAxis === true;
|
|
10020
10049
|
s.scaleGrid = _state.showScaleGrid === true;
|
|
10050
|
+
s.scaleBar = _state.showScaleBar === true;
|
|
10021
10051
|
}
|
|
10022
10052
|
if (_branchScaleAvailable) {
|
|
10023
10053
|
s.scale = _state.branchScale; // time or divergence: which layout the branches show
|
|
@@ -10199,6 +10229,9 @@ function (root, d3, forester, phyloXml) {
|
|
|
10199
10229
|
if (typeof grid === 'boolean') {
|
|
10200
10230
|
_state.showScaleGrid = grid;
|
|
10201
10231
|
}
|
|
10232
|
+
if (typeof s.scaleBar === 'boolean') {
|
|
10233
|
+
_state.showScaleBar = s.scaleBar;
|
|
10234
|
+
}
|
|
10202
10235
|
if (!radialDisplay()) {
|
|
10203
10236
|
_radialLabelsHorizontal = false;
|
|
10204
10237
|
} else if ((_state.showDomainArchitectures && _basicTreeProperties.domainArchitectures)
|
|
@@ -10275,6 +10308,7 @@ function (root, d3, forester, phyloXml) {
|
|
|
10275
10308
|
syncHeatmapControls();
|
|
10276
10309
|
setCheckboxValue(SCALE_AXIS_CB, _state.showScaleAxis === true);
|
|
10277
10310
|
setCheckboxValue(SCALE_GRID_CB, _state.showScaleGrid === true);
|
|
10311
|
+
setCheckboxValue(SCALE_BAR_CB, _state.showScaleBar === true);
|
|
10278
10312
|
setCheckboxValue(DOMAIN_GLOW_CB, _state.domainGlow === true);
|
|
10279
10313
|
setValue(DOMAIN_LABELS_SELECT, _state.domainLabels);
|
|
10280
10314
|
syncDomainControls();
|
|
@@ -10355,7 +10389,7 @@ function (root, d3, forester, phyloXml) {
|
|
|
10355
10389
|
const VIEW_INT_KEYS = ['tree', 'subtree', 'rotation', 'domainEvalue'];
|
|
10356
10390
|
const VIEW_NUMBER_KEYS = ['font', 'node', 'branch'];
|
|
10357
10391
|
const VIEW_BOOL_KEYS = ['horizontalLabels', 'msa', 'msaLogo', 'heatmap', 'domains', 'domainGlow', 'genes',
|
|
10358
|
-
'scaleAxis', 'scaleGrid', 'timeAxis', 'timeGrid', 'matchCase', 'inverse'];
|
|
10392
|
+
'scaleAxis', 'scaleGrid', 'scaleBar', 'timeAxis', 'timeGrid', 'matchCase', 'inverse'];
|
|
10359
10393
|
// Lists of strings, comma-joined. A property ref carries ':' but never a
|
|
10360
10394
|
// comma, and encodeViewValue leaves both readable in a hash.
|
|
10361
10395
|
const VIEW_LIST_KEYS = ['heatmapManual', 'labelFields'];
|
|
@@ -11350,9 +11384,9 @@ function (root, d3, forester, phyloXml) {
|
|
|
11350
11384
|
if (vis) {
|
|
11351
11385
|
return vis;
|
|
11352
11386
|
}
|
|
11353
|
-
let
|
|
11354
|
-
if (
|
|
11355
|
-
return
|
|
11387
|
+
let styleColor = nodeStyleColor(node); // null under an active Color-by, as in the tree
|
|
11388
|
+
if (styleColor) {
|
|
11389
|
+
return styleColor;
|
|
11356
11390
|
}
|
|
11357
11391
|
if (_state.useVisualStyles && node.color) {
|
|
11358
11392
|
return 'rgb(' + node.color.red + ',' + node.color.green + ',' + node.color.blue + ')';
|
|
@@ -13501,7 +13535,8 @@ function (root, d3, forester, phyloXml) {
|
|
|
13501
13535
|
const SCALE_BAR_RESERVE = 30;
|
|
13502
13536
|
|
|
13503
13537
|
function scaleBarShown() {
|
|
13504
|
-
return _state.phylogram === true && _basicTreeProperties.branchLengths === true && !scaleAxisShown()
|
|
13538
|
+
return _state.phylogram === true && _basicTreeProperties.branchLengths === true && !scaleAxisShown()
|
|
13539
|
+
&& _state.showScaleBar !== false;
|
|
13505
13540
|
}
|
|
13506
13541
|
|
|
13507
13542
|
// pixels per branch-length unit in the current layout's own coordinates
|
|
@@ -13527,7 +13562,9 @@ function (root, d3, forester, phyloXml) {
|
|
|
13527
13562
|
if (!scaleBarShown()) {
|
|
13528
13563
|
return;
|
|
13529
13564
|
}
|
|
13530
|
-
|
|
13565
|
+
// the unit the file states, as the distance axis prints it; none when it states none
|
|
13566
|
+
let unit = _treeData && typeof _treeData.branch_length_unit === 'string' ? _treeData.branch_length_unit.trim() : '';
|
|
13567
|
+
let bar = forester.scaleBarLength(branchLengthPixelsPerUnit(), SCALE_BAR_TARGET_PX, unit);
|
|
13531
13568
|
if (!bar) {
|
|
13532
13569
|
return;
|
|
13533
13570
|
}
|
|
@@ -14161,6 +14198,11 @@ function (root, d3, forester, phyloXml) {
|
|
|
14161
14198
|
scheduleUpdate(null, 0);
|
|
14162
14199
|
}
|
|
14163
14200
|
|
|
14201
|
+
function scaleBarCbClicked() {
|
|
14202
|
+
_state.showScaleBar = getCheckboxValue(SCALE_BAR_CB);
|
|
14203
|
+
scheduleUpdate(null, 0);
|
|
14204
|
+
}
|
|
14205
|
+
|
|
14164
14206
|
// Fit the circular tree into the viewport, centred. The root is at the
|
|
14165
14207
|
// group origin (0,0), so we place that at the viewport centre and scale so
|
|
14166
14208
|
// the outer label ring fits. Computed from the known radial extent rather
|
|
@@ -15319,6 +15361,12 @@ function (root, d3, forester, phyloXml) {
|
|
|
15319
15361
|
gridCb.disabled = _state.unrootedDisplay === true || _state.phylogram !== true
|
|
15320
15362
|
|| _state.showScaleAxis !== true;
|
|
15321
15363
|
}
|
|
15364
|
+
let barCb = byId(SCALE_BAR_CB);
|
|
15365
|
+
if (barCb) {
|
|
15366
|
+
// a cladogram has nothing to measure, and under the axis the bar
|
|
15367
|
+
// has given way; every layout can carry it otherwise
|
|
15368
|
+
barCb.disabled = _state.phylogram !== true || scaleAxisShown();
|
|
15369
|
+
}
|
|
15322
15370
|
let minus = byId(ZOOM_OUT_X);
|
|
15323
15371
|
let plus = byId(ZOOM_IN_X);
|
|
15324
15372
|
let expandV = byId(ZOOM_TO_EXPAND_Y);
|
|
@@ -18407,6 +18455,7 @@ function (root, d3, forester, phyloXml) {
|
|
|
18407
18455
|
on(GENE_ANCHOR_SELECT, 'change', geneAnchorChanged);
|
|
18408
18456
|
on(GENE_FAMILY_SELECT, 'change', geneFamilyChanged);
|
|
18409
18457
|
on(GENE_LABELS_SELECT, 'change', geneLabelsChanged);
|
|
18458
|
+
on(SCALE_BAR_CB, 'click', scaleBarCbClicked);
|
|
18410
18459
|
on(SCALE_AXIS_CB, 'click', scaleAxisCbClicked);
|
|
18411
18460
|
on(SCALE_GRID_CB, 'click', scaleGridCbClicked);
|
|
18412
18461
|
|
|
@@ -18944,6 +18993,9 @@ function (root, d3, forester, phyloXml) {
|
|
|
18944
18993
|
let timeAxis = _timeInfo && _timeInfo.type
|
|
18945
18994
|
? (_timeInfo.type === 'geologic' ? 'the geologic (ICS) time axis' : 'the calendar time axis')
|
|
18946
18995
|
: null;
|
|
18996
|
+
// "Scale", the desktop's label for the same switch (its Settings > Overlays > Scale & Grid)
|
|
18997
|
+
opts.push(makeCheckboxItem('Scale', SCALE_BAR_CB, 'to show/hide the scale bar at the bottom left of a'
|
|
18998
|
+
+ ' phylogram: a round length in the tree\'s branch-length unit (it gives way while the scale axis is on)'));
|
|
18947
18999
|
opts.push(makeCheckboxItem('Scale Axis', SCALE_AXIS_CB, 'to show/hide '
|
|
18948
19000
|
+ (timeAxis ? timeAxis + ' and node-age bars (a distance axis while the branches show divergence)'
|
|
18949
19001
|
: 'a labeled distance axis from the root to the deepest tip')
|
|
@@ -19359,6 +19411,7 @@ function (root, d3, forester, phyloXml) {
|
|
|
19359
19411
|
syncHeatmapControls();
|
|
19360
19412
|
setCheckboxValue(SCALE_AXIS_CB, _state.showScaleAxis);
|
|
19361
19413
|
setCheckboxValue(SCALE_GRID_CB, _state.showScaleGrid);
|
|
19414
|
+
setCheckboxValue(SCALE_BAR_CB, _state.showScaleBar);
|
|
19362
19415
|
setCheckboxValue(SHORTEN_NODE_NAME_CB, _state.shortenNodeNames);
|
|
19363
19416
|
populateVisualizationMenus();
|
|
19364
19417
|
initializeSearchOptions();
|
package/forester.js
CHANGED
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
*
|
|
21
21
|
*/
|
|
22
22
|
|
|
23
|
-
// v 3.
|
|
23
|
+
// v 3.26.0
|
|
24
24
|
// 2026-09-17
|
|
25
25
|
//
|
|
26
26
|
// forester.js is a general suite for dealing with phylogenetic trees.
|
|
@@ -8784,7 +8784,11 @@
|
|
|
8784
8784
|
// -- 1, 2 or 5 times a power of ten -- chosen so the bar comes out about
|
|
8785
8785
|
// targetPx long at pxPerUnit pixels per unit. Returns {length, label,
|
|
8786
8786
|
// px}, or null when the scale is unusable (zero, negative or infinite).
|
|
8787
|
-
|
|
8787
|
+
// The label carries the tree's stated unit after the number ("0.05
|
|
8788
|
+
// subs/site"), as the distance axis does at its end, and nothing when
|
|
8789
|
+
// the file states none: a tree that does not say what its lengths
|
|
8790
|
+
// measure gets no guess (a BV-BRC user asked for units, 2026-10-08).
|
|
8791
|
+
forester.scaleBarLength = function (pxPerUnit, targetPx, unit) {
|
|
8788
8792
|
if (!(pxPerUnit > 0) || !isFinite(pxPerUnit)) {
|
|
8789
8793
|
return null;
|
|
8790
8794
|
}
|
|
@@ -8793,7 +8797,8 @@
|
|
|
8793
8797
|
let base = raw / Math.pow(10, k);
|
|
8794
8798
|
let nice = base < 1.5 ? 1 : (base < 3.5 ? 2 : (base < 7.5 ? 5 : 10));
|
|
8795
8799
|
let length = Number((nice * Math.pow(10, k)).toPrecision(2));
|
|
8796
|
-
|
|
8800
|
+
let u = typeof unit === 'string' ? unit.trim() : '';
|
|
8801
|
+
return {length: length, label: String(length) + (u ? ' ' + u : ''), px: length * pxPerUnit};
|
|
8797
8802
|
};
|
|
8798
8803
|
|
|
8799
8804
|
// --------------------------------------------------------------
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "archaeopteryx",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.26.0",
|
|
4
4
|
"description": "Archaeopteryx.js is a software tool for the visualization and analysis of highly annotated phylogenetic trees.",
|
|
5
5
|
"main": "archaeopteryx.js",
|
|
6
6
|
"types": "archaeopteryx.d.ts",
|