Linking an alignment, its distances and its tree
The alignment below was turned into p-distances and a neighbour-joining tree in the browser. All three views share one row order: drag a tree node, an alignment label or a matrix label and the other two follow. When you reorder the alignment, the tree rotates to match as closely as its topology allows, and the other views then settle on the tree’s order.
How it works
Section titled “How it works”The alignment and matrix take the same rowOrder shape — ids in display order — so they can bind
the same store:
const rowOrder = createControllableStore<string[]>([]);
<MultipleSequenceAlignment msa={alignment} rowOrderStore={rowOrder} /><DistanceMatrix labels={labels} matrix={distances} rowOrderStore={rowOrder} />The tree’s order isn’t a list — it’s its topology plus which way each node’s children face — so it joins in both directions with two small bridges:
const [selection, setSelection] = useState<TreeSelection>({ collapsed: [], ...midpointRoot(tree) });const order = useSyncExternalStore(rowOrder.subscribe, rowOrder.getValue);
// tree → rows: report the leaf order whenever the tree is rearranged<PhyloTree tree={tree} interactive selection={selection} onSelectionChange={setSelection} onLeafOrderChange={(names) => rowOrder.setValue(names)}/>;
// rows → tree: rotate the tree to follow a reordered alignment, as far as its topology allowsuseEffect(() => { if (order.join() !== leafOrder(tree, selection).join()) { setSelection((s) => ({ ...s, order: orderForLeafNames(tree, s, order) })); }}, [order]);The loop settles immediately: the tree reports the order closest to the one requested, which it already matches.
Leaf names and row ids must agree. rowOrder ignores ids it doesn’t know and appends rows it
isn’t given, so a tree covering only some sequences still works.
The analysis used here
pDistances and neighborJoining live in this site’s source
(src/lib/phylo.ts) —
the library only visualizes. A real app would use a dedicated tool; acacia, for example, runs
nj.rs in a web worker.