Guangchuang Yu
School of Basic Medical Sciences, Southern Medical University
2026-08-28
Reassortment is an important strategy for influenza A viruses to introduce a HA subtype that is new to human populations, which creates the possibilities of pandemic.
A diagram showed above (Figure 2 of doi:10.1038/srep25549) is widely used to illustrate the reassortment events. While such diagrams are mostly manually draw and edit without software tool to automatically generate. Here, I implemented the hybrid_plot function for producing publication quality figure of reassortment events.
Recommended workflow
For most new projects, the recommended entry point is a table-based workflow:
Prepare a long-format virus-segment table.
Build virus_info with build_virus_info_from_long().
Build flow_info with build_flow_info_from_long() when reassortment edges also come from tables.
Wrap both objects with as_seqcombo_data().
Start with autoplot() and only switch to hybrid_plot() when you need fine-grained control.
The hybrid_plot requires two tibble data frame of virus information and genetic flow information.
Users need to provide x and y positions to plot the virus, this make sense for geographically and temporally information are usually available in such phylodynamic study and can be employed to set x or y to provide more information and help interpretation of the reassortment events.
Customizing the appearance
We use hexagon to represent virus. Users can set the virus outer boundary color by v_color and fill the virus by v_fill. Color of line segments that indicate the genetic flow relationship can be specify via l_color parameter.
We usually have more information to present, for example host information and HA subtype etc. and these information can be used to color the virus either by v_color or v_fill
When your x-axis already encodes time, you can preserve it and only arrange the y positions automatically. Viruses sharing the same time point (here 1990 and 2000) are spread into evenly spaced slots instead of stacking on top of each other:
For workflows that start from long-format segment records, you can build virus_info directly from a virus-segment table:
segment_df <-data.frame(id =rep(c("avian", "human"), each =8),segment =rep(c("PB2", "PB1", "PA", "HA", "NP", "NA", "M", "NS"), 2),color =c(rep("purple", 8), rep("red", 8)),x =rep(c(1990, 2009), each =8),y =rep(c(1, 2), each =8),host =rep(c("Avian", "Human"), each =8))build_virus_info_from_long( segment_df,x ="x",y ="y",keep ="host")
id x y segment_color virus_size segment_name host
avian avian 1990 1 purple, .... 1 PB2, PB1.... Avian
human human 2009 2 red, red.... 1 PB2, PB1.... Human
You can construct flow_info from long-format reassortment records as well:
from to segment_name weight
1 1 5 PB2, HA 2
2 2 5 NA 2
3 3 6 PB1 1
4 3 7 NP 1
5 4 7 M 1
Plotting time-course reassortment data
In a typical reassortment study you know when each virus was sampled, but you rarely know where it should sit on the canvas. This section walks through the full path from two plain tables (one row per virus-segment record, one row per reassortment flow) to a publication-ready figure with time on the x-axis. If you only want a quick look, example_seqcombo_data("timeline") returns ready-to-plot demo data.
Step 1: prepare long-format tables
The first table stores segment records. Each row is one virus-segment combination:
That is the complete workflow: two tables in, one figure out.
Polishing the figure
Host colors work better with an explicit palette. The built-in scale_seqcombo_host() wires both colour and fill aesthetics to a curated host palette, and build_segment_caption() turns segment names into a readable caption:
autoplot(tl_data, v_color =~host, v_fill =~host, link_style ="curve") +scale_seqcombo_host() +labs(title ="Reassortment events leading to the 2009 H1N1 pandemic",caption =build_segment_caption(c("PB2", "PB1", "PA", "HA","NP", "NA", "M", "NS"))) +scale_x_continuous(breaks =c(1990, 2000, 2009)) +theme_seqcombo_pub()
Labels can be added by attaching label and label_position columns before building the plot:
Sampling times do not need to be years; dates (e.g., "2024-03-01") or any numeric encoding works, since the values are passed through to ggplot2.
If you prefer manual control at every step, replace as_seqcombo_data() + autoplot() with direct calls to hybrid_plot() — as shown in the sections above.
Segment labels inside the glyphs
If your virus_info carries segment names, you can show them directly inside the virus glyphs:
When virus_info carries a grouping variable, you can facet reassortment histories by group. Flows that cross facets are drawn in each panel, so transitions between lineages remain visible:
example_seqcombo_data() also ships dedicated teaching datasets. Type "long" starts from tidy tables (attached as attr(demo, "long_tables")) and walks through the recommended build-and-arrange pipeline, so you can inspect each intermediate step:
Warning in geom_curve(mapping = mapping, data = flow_params$data, arrow =
arrow(length = unit(0.3, : Ignoring empty aesthetic: `linewidth`.
Type "genotype" provides parents plus reassortants without flows, handy for genotype-only charts through geom_genotype() or autoplot(as_seqcombo_data(virus_info)).