Skip to content

Commit 0bf9582

Browse files
committed
Simplify the topology drawing code in popgen.md
Useful for others to copy
1 parent 6d15a19 commit 0bf9582

1 file changed

Lines changed: 21 additions & 63 deletions

File tree

popgen.md

Lines changed: 21 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -438,69 +438,27 @@ embedded_topologies = topology_counter[range(simplified_ts.num_populations)]
438438

439439
```{code-cell}
440440
:"tags": ["hide-input"]
441-
# This helper is copied from the side-by-side SVG example in the visualization tutorial.
442-
def draw_svg_side_by_side(
443-
drawables,
444-
*,
445-
size=(200, 200),
446-
sizes=None,
447-
padding=40,
448-
canvas_size=None,
449-
per_svg_kwargs=None,
450-
**kwargs,
451-
):
452-
if len(drawables) == 0:
453-
raise ValueError("Need at least one drawable")
454-
if per_svg_kwargs is None:
455-
per_svg_kwargs = [{} for _ in drawables]
456-
if len(per_svg_kwargs) != len(drawables):
457-
raise ValueError("per_svg_kwargs must have the same length as drawables")
458-
if sizes is None:
459-
sizes = [size for _ in drawables]
460-
if len(sizes) != len(drawables):
461-
raise ValueError("sizes must have the same length as drawables")
462-
if canvas_size is None:
463-
canvas_size = (
464-
sum(s[0] for s in sizes) + (len(drawables) - 1) * padding,
465-
max(s[1] for s in sizes),
466-
)
467-
468-
preamble = []
469-
x_offset = sizes[0][0] + padding
470-
for j, drawable in enumerate(drawables[1:], start=1):
471-
svg_kwargs = dict(kwargs)
472-
svg_kwargs.update(per_svg_kwargs[j])
473-
svg_kwargs["size"] = sizes[j]
474-
svg_kwargs["root_svg_attributes"] = {
475-
**svg_kwargs.get("root_svg_attributes", {}),
476-
"x": x_offset,
477-
}
478-
preamble.append(drawable.draw_svg(**svg_kwargs))
479-
x_offset += sizes[j][0] + padding
480-
481-
first_kwargs = dict(kwargs)
482-
first_kwargs.update(per_svg_kwargs[0])
483-
first_kwargs["size"] = sizes[0]
484-
first_kwargs["canvas_size"] = canvas_size
485-
first_kwargs["preamble"] = first_kwargs.get("preamble", "") + "".join(preamble)
486-
return drawables[0].draw_svg(**first_kwargs)
487-
488-
489-
all_trees = list(tskit.all_trees(simplified_ts.num_populations))
490-
style = "".join(styles) + ".sample text.lab {baseline-shift: super; font-size: 0.7em;}"
491-
style = style.replace(".leaf.p", ".leaf.n") # Hack to map node IDs to population colours
492-
draw_svg_side_by_side(
493-
all_trees,
494-
size=(160, 150),
495-
padding=10,
496-
style=style,
497-
per_svg_kwargs=[
498-
{
499-
"node_labels": {pop.id: pop.metadata["name"] for pop in simplified_ts.populations()},
500-
"title": f"{embedded_topologies[t.rank()]} trees",
501-
}
502-
for t in all_trees
503-
],
441+
# Here we concatenate trees together into a pseudo tree sequence, simply for plotting
442+
# Alternatively there is code to plot side-by-side trees in the visualization tutorial.
443+
def tree_centre_x(i, n):
444+
# calc the centre X plot position of tree i in a default tree sequence viz of n trees
445+
w = tskit.drawing.SvgPlot.default_width
446+
l, r = tskit.drawing.SvgTree.margin_left, tskit.drawing.SvgTree.margin_right
447+
return l + (w - (l+r)/n) * i + w/2
448+
449+
trees = list(tskit.all_trees(3))
450+
concat_trees = trees[0].tree_sequence.concatenate(*[t.tree_sequence for t in trees[1:]])
451+
style = "".join(styles) + ".sample text.lab {font-size: 0.7em;}"
452+
453+
concat_trees.draw_svg(
454+
title="", # Make room for labels
455+
x_axis=False, # this is not "along the genome", so X axis is meaningless
456+
style=style.replace(".leaf.p", ".leaf.n"), # Hack to map node IDs to population colours
457+
node_labels = {pop.id: pop.metadata["name"] for pop in simplified_ts.populations()},
458+
preamble="".join([
459+
f'<text text-anchor="middle" y="15" x="{tree_centre_x(i, ts.num_trees)}">{embedded_topologies[t.rank()]} trees</text>'
460+
for i, t in enumerate(trees)
461+
]),
504462
)
505463
```
506464

0 commit comments

Comments
 (0)