Skip to content

Commit 71c4794

Browse files
committed
Add titles to plots, showcase legends
1 parent e0a3ecd commit 71c4794

1 file changed

Lines changed: 61 additions & 11 deletions

File tree

viz.md

Lines changed: 61 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,7 @@ svg_string = ts_tiny.draw_svg(
162162
size=svg_size,
163163
y_axis=True, y_label=" ", # optional: show a time scale on the left
164164
time_scale="rank", x_scale="treewise", # Force same axis settings as the text view
165+
title="A basic SVG plot",
165166
)
166167
display(svg_string) # If the last line in a cell, wrapping this in display() is not needed
167168
```
@@ -201,14 +202,18 @@ with 8 samples, but where we've restricted the amount of the tree sequence we pl
201202
```{code-cell} ipython3
202203
x_limits = [5000, 15000]
203204
# Create evenly-spaced y tick positions to avoid overlap
204-
y_tick_pos = [0, 1000, 2000, 3000, 4000]
205+
y_tick_pos = [0, 1000, 2000, 3000]
205206
206-
print("The tree sequence between positions {} and {} ...".format(*x_limits))
207-
display(ts_small.draw_svg(y_axis=True, y_ticks=y_tick_pos, x_lim=x_limits))
207+
display(ts_small.draw_svg(
208+
size=svg_size,
209+
y_axis=True,
210+
y_ticks=y_tick_pos,
211+
x_lim=x_limits,
212+
title="The tree sequence between positions {} and {}".format(*x_limits)
213+
))
208214
209215
third_tree = ts_small.at_index(2)
210-
print("... or just look at (say) the third tree")
211-
display(third_tree.draw_svg())
216+
display(third_tree.draw_svg(title="A plot of the third tree"))
212217
```
213218

214219
As the number of sample nodes increases, internal nodes often bunch up at recent time
@@ -225,20 +230,21 @@ styling is detailed {ref}`later in this tutorial <sec_tskit_viz_styling>`).
225230
(sec_tskit_viz_large_tree_sequence)=
226231

227232
```{code-cell} ipython3
228-
print("A larger tree, on a log timescale")
229233
wide_fmt = (1200, 250)
230234
# Create a stylesheet that shrinks labels and rotates leaf labels, to avoid overlap
231235
node_label_style = (
232236
".node > .lab {font-size: 80%}"
233237
".leaf > .lab {text-anchor: start; transform: rotate(90deg) translate(6px)}"
234238
)
239+
235240
ts_full.first().draw_svg(
236241
size=wide_fmt,
237242
time_scale="log_time",
238243
y_gridlines=True,
239244
y_axis=True,
240245
y_ticks=[1, 10, 100, 1000],
241-
style=node_label_style,
246+
style=node_label_style + "svg > .title text {font-size: 150%}",
247+
title="A larger tree, on a log timescale",
242248
)
243249
```
244250

@@ -290,9 +296,11 @@ plot region, or simply plotting the tree itself:
290296

291297

292298
```{code-cell} ipython3
293-
third_tree = ts_mutated.at_index(2)
294-
print(f"The third tree in the mutated tree sequence, which covers {third_tree.interval}")
295-
third_tree.draw_svg(size=(200, 300))
299+
tree3 = ts_mutated.at_index(2)
300+
tree3.draw_svg(
301+
size=(320, 300),
302+
title=f"3rd tree, from position {int(tree3.interval.left)} to {int(tree3.interval.right)}",
303+
)
296304
```
297305

298306
(sec_tskit_viz_extra_mutations)=
@@ -308,7 +316,11 @@ associated with an edge in the tree but which fall outside the interval of that
308316
default these mutations are drawn in a slightly different shade (e.g. mutation 64 below).
309317

310318
```{code-cell} ipython3
311-
third_tree.draw_svg(size=(200, 300), all_edge_mutations=True)
319+
tree3.draw_svg(
320+
size=(320, 300),
321+
all_edge_mutations=True,
322+
title="As above, but with all mutations on visible edges"
323+
)
312324
```
313325

314326
(sec_tskit_viz_labelling)=
@@ -337,6 +349,7 @@ for mut in ts_mutated.mutations(): # Make pretty labels showing the change in s
337349
mut_labels[mut.id] = f"{prev}→{mut.derived_state}"
338350
339351
ts_mutated.draw_svg(
352+
size=(1000, 300),
340353
y_axis=True, y_ticks=y_tick_pos, x_lim=x_limits,
341354
node_labels=nd_labels,
342355
mutation_labels=mut_labels,
@@ -1064,6 +1077,43 @@ means that there can be sample nodes which are "isolated" in a tree. These are d
10641077
unconnected to the main topology in one or more trees (e.g. nodes 7 and 8 above).
10651078
:::
10661079

1080+
#### Adding imagery
1081+
1082+
The `preamble` argument allows arbitrary SVG commands to be included in an SVG plot.
1083+
This can be used, for instance, to annotate parts of the plot or construct legends:
1084+
1085+
```{code-cell} ipython3
1086+
:"tags": ["hide-input"]
1087+
ts = tskit.load("data/viz_ts_full.trees")
1088+
1089+
styles = [
1090+
f".node.p{p.id} > .sym " + "{" + f"fill: {colour}" + "}"
1091+
for colour, p in zip(['red', 'green', 'blue'], ts_full.populations())
1092+
] # styles created as in previous examples
1093+
1094+
# Make a legend: first create a surrounding box and a title
1095+
legend = '<rect width="145" height="75" x="2" y="10" fill="#EEE" stroke="grey" />'
1096+
legend += '<text x="65" y="25" font-weight="bold">Key</text>'
1097+
# Now make the legend lines, one for each population. Setting classes that match those
1098+
# used for normal nodes means that styled colours are automatically picked-up.
1099+
legend += "".join([
1100+
f'<g transform="translate(5, {40 + 15*p.id})" class="node p{p.id}">' # an SVG group
1101+
f'<rect width="6" height="6" class="sym" />' # Square symbol
1102+
f'<text x="10" y="7">Population {p.metadata["name"]} (id={p.id})</text></g>' # Label
1103+
for p in ts_full.populations()
1104+
if p.id < 3
1105+
])
1106+
1107+
ts.first().draw_svg(
1108+
size=(1200, 250),
1109+
node_labels={}, # Remove all node labels for a clearer viz
1110+
style="".join(styles), # Apply the stylesheet
1111+
preamble=legend,
1112+
)
1113+
```
1114+
1115+
SVGs can be nested, so it is even possible to add an entire SVG in the `preamble`.
1116+
10671117
#### A fancy formatted plot
10681118

10691119
Here we have activated the Y axis, and changed the node style. In particular, we have

0 commit comments

Comments
 (0)