diff --git a/data/viz_ts_selection.trees b/data/viz_ts_selection.trees
new file mode 100644
index 00000000..d1420307
Binary files /dev/null and b/data/viz_ts_selection.trees differ
diff --git a/viz.md b/viz.md
index f3ed7c1a..5516fe59 100644
--- a/viz.md
+++ b/viz.md
@@ -44,6 +44,19 @@ def viz_ts():
assert ts_small_mutated.site(8).mutations[0].node == 16
ts_small_mutated.dump("data/viz_ts_small_mutated.trees")
+def viz_selection():
+ sequence_length = 5e4
+ sweep_model = msprime.SweepGenicSelection(position=sequence_length/2,
+ s=0.01, start_frequency=0.5e-4, end_frequency=0.99, dt=1e-6)
+ ts_selection = msprime.sim_ancestry(9,
+ model=[sweep_model, msprime.StandardCoalescent()],
+ population_size=1e4,
+ recombination_rate=1e-8,
+ sequence_length=sequence_length,
+ random_seed=9,
+ )
+ ts_selection.dump("data/viz_ts_selection.trees")
+
def viz_root_mut():
"""
Taken from the drawing unit tests
@@ -120,6 +133,7 @@ def viz_spr_animation():
def create_notebook_data():
viz_ts()
+ viz_selection()
viz_root_mut()
viz_spr_animation()
@@ -455,14 +469,53 @@ the following element:
...
```
-This makes it easy to e.g. colour branches that are shared between trees (i.e. that
-have the same parent and child):
+#### Styling graphical elements
+
+The classes above make it easy to target specific nodes or edges in one or multiple
+trees. For example, we can colour branches that are shared between trees
+(identified here as ones that have the same parent and child):
```{code-cell} ipython3
css_string = ".a15.n9 > .edge {stroke: cyan; stroke-width: 2px}" # branches from 15->9
SVG(ts_small.draw_svg(time_scale="rank", size=wide_fmt, style=css_string))
```
+By generating the css string programatically, you can target all the edges present in a
+particular tree, and see how they gradually disappear from adjacent trees. Here, for
+example the branches in the central tree have been coloured red, as have the identical
+branches in adjacent trees. The central tree represents a location in the genome
+that has seen a selective sweep, and therefore has short branch lengths: adjacent trees
+are not under direct selection and thus the black branches tend to be longer.
+These (red) shared branches extending far on either side represent shared haplotypes,
+and this shows how long, shared haplotypes can extend much further away from a sweep
+than the region of reduced diversity (which is the region spanned by the short tree in the middle).
+For visual clarity, node symbols and labels have been turned off.
+
+```{code-cell} ipython3
+:"tags": ["hide-input"]
+# See the notebook code if you want to know how these tree sequences were produced
+ts_selection = tskit.load("data/viz_ts_selection.trees")
+```
+
+```{code-cell} ipython3
+css_edge_targets = [] # collect the css targets of all the edges in the selected tree
+sweep_location = ts_selection.sequence_length / 2 # NB: sweep is in the middle of the ts
+focal_tree = ts_selection.at(sweep_location)
+for node_id in focal_tree.nodes():
+ parent_id = focal_tree.parent(node_id)
+ if parent_id != tskit.NULL:
+ css_edge_targets.append(f".a{parent_id}.n{node_id}>.edge")
+css_string = ",".join(css_edge_targets) + "{stroke: red} .sym {display: none}"
+
+wide_tall_fmt = (1200, 400)
+SVG(ts_selection.draw_svg(
+ style=css_string,
+ size=wide_tall_fmt,
+ x_lim=[1.74e4, 3.25e4],
+ node_labels={},
+))
+```
+
:::{note}
Branches in multiple trees that have the same parent and child do not always
correspond to a single {ref}`edge `