Skip to content

Examples ​

These are the charts of the R package's examples, drawn live by geneviewer from their specs. Hover a gene for its tooltip, or the chart for its save button. Each chart has its code in JavaScript, R and Python, and all three draw the same chart.

E.coli Lac operon ​

Show the code
js
// <div id="chart" style="height: 140px"></div>
const chart = geneviewer.newChart("#chart", {
  data: [
    {
      start: 361249,
      end: 361860,
      Gene_symbol: "lacA",
      Strand: "minus",
      NCBI_Gene_ID: "945674",
      Description: "galactoside O-acetyltransferase",
    },
    {
      start: 361926,
      end: 363179,
      Gene_symbol: "lacY",
      Strand: "minus",
      NCBI_Gene_ID: "949083",
      Description: "lactose permease",
    },
    {
      start: 363231,
      end: 366305,
      Gene_symbol: "lacZ",
      Strand: "minus",
      NCBI_Gene_ID: "945006",
      Description: "beta-galactosidase",
    },
    {
      start: 366428,
      end: 367510,
      Gene_symbol: "lacI",
      Strand: "minus",
      NCBI_Gene_ID: "945007",
      Description: "DNA-binding transcriptional repressor LacI",
    },
  ],
  fields: { group: "Gene_symbol" },
  labels: {},
  scaleBar: { title: "0.2 kb", unit: 200, y: 30 },
  tooltip: {
    formatter: "\n    <b>ID:</b> {NCBI_Gene_ID}<br>\n    <b>Description:</b> {Description}<br>\n    <b>Start:</b> {start}<br>\n    <b>End:</b> {end}",
  },
  clusterFooter: {
    subtitle: "<i>Escherichia coli</i> str. K-12 substr. MG1655",
    align: "center",
    y: -30,
  },
  coordinates: {
    tickValuesBottom: [361249, 367510],
    tickStyle: { lineLength: 10 },
    textStyle: { fontSize: "10px", x: -2.2, y: 1.2 },
    rotate: 0,
  },
  legend: { show: false },
});
r
lacZ_operon <- data.frame(
  start = c(361249, 361926, 363231, 366428), 
  end = c(361860, 363179, 366305, 367510), 
  Gene_symbol = c("lacA", "lacY", "lacZ", "lacI"), 
  Strand = c("minus", "minus", "minus", "minus"), 
  NCBI_Gene_ID = as.character(c(945674, 949083, 945006, 945007)), 
  Description = c("galactoside O-acetyltransferase", 
                  "lactose permease", "beta-galactosidase", 
                  "DNA-binding transcriptional repressor LacI")
)

GC_chart(lacZ_operon, group = "Gene_symbol", height = "140px") %>%
  GC_labels() %>%
  GC_scaleBar(title = "0.2 kb", scaleBarUnit = 200, y=30) %>%
  GC_tooltip(
    formatter = "
    <b>ID:</b> {NCBI_Gene_ID}<br>
    <b>Description:</b> {Description}<br>
    <b>Start:</b> {start}<br>
    <b>End:</b> {end}",
  ) %>%
  GC_clusterFooter(
    align = "center",
    y = -30,
    subtitle = "<i>Escherichia coli</i> str. K-12 substr. MG1655" 
  ) %>%
  GC_coordinates(
    rotate = 0,
    tickValuesBottom = c(min(lacZ_operon$start), max(lacZ_operon$end)),
    textStyle = list(fontSize = "10px", x = -2.2, y = 1.2),
    tickStyle = list(lineLength = 10)
    ) %>%
  GC_legend(FALSE)
python
import pandas as pd

from geneviewer import GC

lacZ_operon = pd.DataFrame(
    {
        "start": [361249, 361926, 363231, 366428],
        "end": [361860, 363179, 366305, 367510],
        "Gene_symbol": ["lacA", "lacY", "lacZ", "lacI"],
        "Strand": ["minus", "minus", "minus", "minus"],
        "NCBI_Gene_ID": ["945674", "949083", "945006", "945007"],
        "Description": [
            "galactoside O-acetyltransferase",
            "lactose permease",
            "beta-galactosidase",
            "DNA-binding transcriptional repressor LacI",
        ],
    }
)

(
    GC(lacZ_operon, group="Gene_symbol", height="140px")
    .labels()
    .scale_bar(title="0.2 kb", scale_bar_unit=200, y=30)
    .tooltip(
        formatter="\n    <b>ID:</b> {NCBI_Gene_ID}<br>\n    <b>Description:</b> {Description}<br>\n    <b>Start:</b> {start}<br>\n    <b>End:</b> {end}"
    )
    .cluster_footer(
        align="center",
        y=-30,
        subtitle="<i>Escherichia coli</i> str. K-12 substr. MG1655",
    )
    .coordinates(
        rotate=0,
        tick_values_bottom=[lacZ_operon["start"].min(), lacZ_operon["end"].max()],
        text_style={"fontSize": "10px", "x": -2.2, "y": 1.2},
        tick_style={"lineLength": 10},
    )
    .legend(False)
)

Omphalotin gene clusters ​

Show the code
js
// <div id="chart" style="height: 400px"></div>
const { data } = await fetch("https://nvelden.github.io/geneviewer-docs/charts/data/omphalotin-gene-clusters.json")
  .then((response) => response.json());

const chart = geneviewer.newChart("#chart", {
  data,
  fields: { cluster: "cluster", group: "class" },
  clusterFooter: {
    title: ["<i>Omphalotus olearius</i>", "<i>Dendrothele bispora</i>"],
    subtitle: ["Locus: 2,522 - 21,484", "Locus: 19,236 - 43,005"],
    align: "left",
  },
  legend: { position: "top" },
  labels: { label: "name" },
  scaleBar: { y: 20 },
  scale: [
    { clusters: [1], hidden: true, autoBreaks: true },
    { clusters: [2], hidden: true, reverse: true },
  ],
  tooltip: {
    formatter: "<b>Gene:</b> {name}<br> <b>Start:</b> {start}<br><b>end:</b> {end}",
  },
  theme: { base: "vintage" },
});
r
GC_chart(ophA_clusters, group = "class", cluster = "cluster") %>%
  GC_clusterFooter(
    title = c("<i>Omphalotus olearius</i>", "<i>Dendrothele bispora</i>"), 
    subtitle = c("Locus: 2,522 - 21,484", "Locus: 19,236 - 43,005"),
    align = "left") %>%
  GC_legend(position = "top") %>%
  GC_labels(label = "name") %>%
  GC_scaleBar(y = 20) %>%
  GC_scale(cluster = 1,  scale_breaks = TRUE, hidden = TRUE) %>%
  GC_scale(cluster = 2, reverse = TRUE, hidden = TRUE) %>%
  GC_tooltip(
    formatter = "<b>Gene:</b> {name}<br> <b>Start:</b> {start}<br><b>end:</b> {end}"
  ) %>%
  GC_theme("vintage")
python
from geneviewer import GC, datasets

ophA_clusters = datasets.load("ophA_clusters")

(
    GC(ophA_clusters, group="class", cluster="cluster")
    .cluster_footer(
        title=["<i>Omphalotus olearius</i>", "<i>Dendrothele bispora</i>"],
        subtitle=["Locus: 2,522 - 21,484", "Locus: 19,236 - 43,005"],
        align="left",
    )
    .legend(position="top")
    .labels(label="name")
    .scale_bar(y=20)
    .scale(cluster=1, scale_breaks=True, hidden=True)
    .scale(cluster=2, reverse=True, hidden=True)
    .tooltip(
        formatter="<b>Gene:</b> {name}<br> <b>Start:</b> {start}<br><b>end:</b> {end}"
    )
    .theme("vintage")
)
Show the code
js
// <div id="chart" style="height: 400px"></div>
const { data } = await fetch("https://nvelden.github.io/geneviewer-docs/charts/data/omphalotin-gene-clusters-2.json")
  .then((response) => response.json());

const chart = geneviewer.newChart("#chart", {
  data,
  fields: { start: "start", end: "end", cluster: "cluster", group: "class" },
  clusterFooter: {
    title: ["<i>Omphalotus olearius</i>", "<i>Dendrothele bispora</i>"],
    subtitle: ["Locus: 2,522 - 21,484", "Locus: 19,236 - 43,005"],
    align: "left",
  },
  legend: { position: "top" },
  labels: { label: "name" },
  scaleBar: { y: 20 },
  scale: [
    { clusters: [1], hidden: true, autoBreaks: true },
    { clusters: [2], hidden: true, reverse: true },
  ],
  theme: { base: "bw" },
});
r
GC_chart(ophA_clusters, 
           start = "start",
           end = "end",
           group = "class",
           cluster = "cluster") %>%
  GC_clusterFooter(
    title = c("<i>Omphalotus olearius</i>", "<i>Dendrothele bispora</i>"), 
    subtitle = c("Locus: 2,522 - 21,484", "Locus: 19,236 - 43,005"),
    align = "left") %>%
  GC_legend(position = "top") %>%
  GC_labels(label = "name") %>%
  GC_scaleBar(y = 20) %>%
  GC_scale(cluster = 1,  scale_breaks = TRUE, hidden = TRUE) %>%
  GC_scale(cluster = 2, reverse = TRUE, hidden = TRUE) %>%
  GC_theme("bw")
python
from geneviewer import GC, datasets

ophA_clusters = datasets.load("ophA_clusters")

(
    GC(ophA_clusters, start="start", end="end", group="class", cluster="cluster")
    .cluster_footer(
        title=["<i>Omphalotus olearius</i>", "<i>Dendrothele bispora</i>"],
        subtitle=["Locus: 2,522 - 21,484", "Locus: 19,236 - 43,005"],
        align="left",
    )
    .legend(position="top")
    .labels(label="name")
    .scale_bar(y=20)
    .scale(cluster=1, scale_breaks=True, hidden=True)
    .scale(cluster=2, reverse=True, hidden=True)
    .theme("bw")
)
Show the code
js
// <div id="chart" style="height: 400px"></div>
const { data, links1 } = await fetch("https://nvelden.github.io/geneviewer-docs/charts/data/omphalotin-gene-clusters-3.json")
  .then((response) => response.json());

const chart = geneviewer.newChart("#chart", {
  data,
  fields: { cluster: "cluster", group: "class" },
  labels: { label: "name", clusters: [1] },
  links: [
    {
      data: links1,
      group: "class",
      curve: true,
      measure: "none",
      label: false,
      normalColor: "#969696",
      invertedColor: "#969696",
      useGroupColors: false,
      linkWidth: 0.2,
    },
    {
      data: [
        {
          name1: "ophA",
          start1: 9536,
          end1: 10904,
          class1: "Methyltransferase",
          cluster1: "ophA",
          rowID1: 3,
          strand1: "forward",
          name2: "dbophA",
          start2: 28937,
          end2: 30516,
          class2: "Methyltransferase",
          cluster2: "dbophA",
          rowID2: 13,
          strand2: "forward",
        },
      ],
      group: "name",
      value1: "ophA",
      value2: "dbophA",
      useGroupColors: true,
      linkStyle: { stroke: "black", strokeWidth: 2 },
    },
  ],
  clusterLabel: {
    title: ["<i>O.</i> <i>olearius</i>", "<i>D. bispora</i>"],
    wrapLabel: false,
  },
  grid: { height: "25%", clusters: [2] },
  legend: { textStyle: { fontSize: "14px" } },
  annotation: [
    {
      type: "text",
      clusters: [1],
      x: 10884,
      y: 11,
      text: "90%",
      style: { fontSize: "16px", fill: "#1c641c" },
    },
  ],
  trackMouse: {},
});
r
GC_chart(
    ophA_clusters,
    cluster = "cluster",
    group = "class",
    width = "800px",
    height = "400px"
  ) %>%
  GC_labels(
    cluster = 1,
    label = "name"
  ) %>%
  GC_links(
    "class",
    use_group_colors = FALSE,
    measure = "none",
    normal_color = "#969696",
    inverted_color = "#969696",
    curve = TRUE,
    label = FALSE,
    linkWidth = 0.2,
  ) %>%
  GC_links(
    group = "name",
    value1 = "ophA",
    value2 = "dbophA",
    use_group_colors = TRUE,
    linkStyle = list(
      stroke = "black",
      strokeWidth = 2
    )
  ) %>%
  GC_clusterLabel(
    title = c("<i>O.</i> <i>olearius</i>", "<i>D. bispora</i>"),
    wrapLabel = FALSE
  ) %>%
  # Reduce space between legend and cluster
  GC_grid(
    cluster = 2,
    height = "25%"
  ) %>%
  GC_legend(
    legendTextOptions = list(fontSize = "14px")
  ) %>%
  GC_annotation(
    cluster = 1,
    x = 10884,
    y = 11,
    type = "text",
    text = "90%",
    style = list(fontSize = "16px", fill = "#1c641c")
  ) %>%
  GC_trackMouse()
python
from geneviewer import GC, datasets

ophA_clusters = datasets.load("ophA_clusters")

(
    GC(ophA_clusters, cluster="cluster", group="class", width="800px", height="400px")
    .labels(cluster=1, label="name")
    .links(
        "class",
        use_group_colors=False,
        measure="none",
        normal_color="#969696",
        inverted_color="#969696",
        curve=True,
        label=False,
        link_width=0.2,
    )
    .links(
        group="name",
        value1="ophA",
        value2="dbophA",
        use_group_colors=True,
        link_style={"stroke": "black", "strokeWidth": 2},
    )
    .cluster_label(
        title=["<i>O.</i> <i>olearius</i>", "<i>D. bispora</i>"], wrap_label=False
    )
    # Reduce space between legend and cluster
    .grid(cluster=2, height="25%")
    .legend(legend_text_options={"fontSize": "14px"})
    .annotation(
        cluster=1,
        x=10884,
        y=11,
        type="text",
        text="90%",
        style={"fontSize": "16px", "fill": "#1c641c"},
    )
    .track_mouse()
)

H. sapiens Hox genes using biomaRt ​

Show the code
js
// <div id="chart" style="height: 400px"></div>
const { data } = await fetch("https://nvelden.github.io/geneviewer-docs/charts/data/h-sapiens-hox-genes-using-biomart.json")
  .then((response) => response.json());

const chart = geneviewer.newChart("#chart", {
  data,
  fields: { cluster: "cluster", group: "cluster", strand: "strand" },
  clusterLabel: {},
  legend: { show: false },
  genes: {
    marker: "boxarrow",
    markerHeight: 10,
    arrowheadHeight: 10,
    arrowheadWidth: 6,
  },
  labels: { label: "name", fontSize: "10px" },
  scale: { clusters: [1, 2], hidden: true, reverse: true },
  cluster: { preventGeneOverlap: true },
  theme: { base: "dark" },
});
r
# Get HOX gene positions 
library(biomaRt)

ensembl <- useMart("ensembl", dataset = "hsapiens_gene_ensembl")

hox_gene_sets <- list(
  HOXA = c("HOXA1", "HOXA2", "HOXA3", "HOXA4", "HOXA5", "HOXA6", "HOXA7", "HOXA9", "HOXA10", "HOXA11", "HOXA13"),
  HOXB = c("HOXB1", "HOXB2", "HOXB3", "HOXB4", "HOXB5", "HOXB6", "HOXB7", "HOXB8", "HOXB9", "HOXB13"),
  HOXC = c("HOXC4", "HOXC5", "HOXC6", "HOXC8", "HOXC9", "HOXC10", "HOXC11", "HOXC12", "HOXC13"),
  HOXD = c("HOXD1", "HOXD3", "HOXD4", "HOXD8", "HOXD9", "HOXD10", "HOXD11", "HOXD12", "HOXD13")
)

get_gene_positions <- function(gene_list, cluster_name) {

  result <- getBM(attributes = c('hgnc_symbol', 'chromosome_name', 'strand', 'start_position', 'end_position'),
                  filters = 'hgnc_symbol',
                  values = gene_list,
                  mart = ensembl)
  transform(result, cluster = cluster_name)
}

# Apply get_gene_positions to each gene set
hox_gene_positions <- base::lapply(names(hox_gene_sets), function(cluster_name) {
  get_gene_positions(hox_gene_sets[[cluster_name]], cluster_name)
})

# Combine the results into a single data frame
combined_hox_genes <- do.call(rbind, hox_gene_positions)

# Add gene names
combined_hox_genes$name <- paste0(substr(combined_hox_genes$hgnc_symbol, 1, 3), substr(combined_hox_genes$hgnc_symbol, 5, nchar(combined_hox_genes$hgnc_symbol)))

GC_chart(
  combined_hox_genes,
  start = "start_position",
  end = "end_position",
  group = "cluster",
  strand = "strand",
  cluster = "cluster",
  height = "400px") %>%
  GC_clusterLabel() %>%
  GC_legend(FALSE) %>%
  GC_genes(
    marker = "boxarrow",
    markerHeight = 10,
    arrowheadHeight = 10,
    arrowheadWidth = 6
  ) %>%
  GC_labels("name", fontSize = "10px") %>%
  GC_scale(cluster = c(1, 2), hidden = TRUE, reverse = TRUE) %>%
  GC_cluster(prevent_gene_overlap = TRUE) %>%
  GC_theme("dark")
python
from geneviewer import GC, datasets

# The positions of the HOX genes, from Ensembl
human_hox_genes = datasets.load("human_hox_genes")

(
    GC(
        human_hox_genes,
        group="cluster",
        strand="strand",
        cluster="cluster",
        height="400px",
    )
    .cluster_label()
    .legend(False)
    .genes(marker="boxarrow", marker_height=10, arrowhead_height=10, arrowhead_width=6)
    .labels("name", font_size="10px")
    .scale(cluster=[1, 2], hidden=True, reverse=True)
    .cluster(prevent_gene_overlap=True)
    .theme("dark")
)

BRCA1 splice variants ​

Show the code
js
// <div id="chart" style="height: 600px"></div>
const { data } = await fetch("https://nvelden.github.io/geneviewer-docs/charts/data/brca1-splice-variants.json")
  .then((response) => response.json());

const chart = geneviewer.newChart("#chart", {
  data,
  transcript: { transcript: "ensembl_transcript_id", type: "type", strand: "strand" },
  clusterTitle: {
    title: [
      "ENST00000357654",
      "ENST00000489037",
      "ENST00000473961",
      "ENST00000497488",
      "ENST00000478531",
    ],
    titleFont: { fontSize: "12px" },
  },
  clusterFooter: { title: ["0.8%", "0.1%", "0.07%", "0.02%", "0.01%"], align: "center" },
  theme: { base: "infographic", textColor: "#333333" },
});
r
GC_chart(BRCA1_splice_variants, height = "600px") %>%
  GC_transcript(
    transcript = "ensembl_transcript_id", 
    strand = "strand", 
    type = "type",
  ) %>%
  GC_clusterTitle(
    title = unique(BRCA1_splice_variants$ensembl_transcript_id),
    titleFont = list(
      fontSize = "12px"
    )
  ) %>%
  GC_clusterFooter(
    title = c("0.8%", "0.1%", "0.07%", "0.02%", "0.01%"),
    align = "center"
  ) %>%
  GC_theme("infographic", textColor = "#333333")
python
from geneviewer import GC, datasets

BRCA1_splice_variants = datasets.load("BRCA1_splice_variants")

(
    GC(BRCA1_splice_variants, height="600px")
    .transcript(transcript="ensembl_transcript_id", strand="strand", type="type")
    .cluster_title(
        title=list(BRCA1_splice_variants["ensembl_transcript_id"].unique()),
        title_font={"fontSize": "12px"},
    )
    .cluster_footer(title=["0.8%", "0.1%", "0.07%", "0.02%", "0.01%"], align="center")
    .theme("infographic", text_color="#333333")
)

Saccharopolyspora erythraea Erythromycin ​

Show the code
js
// <div id="chart" style="height: 170px"></div>
const { data } = await fetch("https://nvelden.github.io/geneviewer-docs/charts/data/saccharopolyspora-erythraea-erythromycin.json")
  .then((response) => response.json());

const chart = geneviewer.newChart("#chart", {
  data,
  fields: { start: "Start", end: "End", group: "Functions" },
  title: {
    title: "Erythromycin A biosynthetic gene cluster from <i>Saccharopolyspora erythraea</i>",
    align: "left",
  },
  genes: { marker: "boxarrow", markerSize: "small" },
  tooltip: {
    formatter: "<b>{Identifiers}</b><br>{Product}<br>{start} - {end}({Strand})",
  },
  scale: { start: 778000, end: 832000, ticksCount: 8 },
  legend: {
    order: [
      "Activation / processing",
      "Precursor biosynthesis",
      "Resistance / immunity",
      "Scaffold biosynthesis",
      "Tailoring (Glycosylation)",
      "Tailoring (Hydroxylation)",
      "Tailoring (Methylation)",
      "Other",
    ],
  },
  color: { customColors: { Other: "grey" } },
  theme: { base: "classic" },
});
r
GC_chart(erythromycin_cluster,
         start = "Start",
         end = "End",
         group = "Functions",
         height = "170px") %>%
  GC_title(
    title = "Erythromycin A biosynthetic gene cluster from <i>Saccharopolyspora erythraea</i>",
    align = "left"
  ) %>%
  GC_genes(marker = "boxarrow", marker_size = "small") %>%
  GC_tooltip(
    formatter = "<b>{Identifiers}</b><br>{Product}<br>{start} - {end}({Strand})"
  ) %>%
  GC_scale(start = 778000, end = 832000, ticksCount = 8) %>%
  GC_legend(order = c(setdiff(sort(erythromycin_cluster$Functions), "Other"), "Other")) %>%
  GC_color(customColors = list(Other = "grey")) %>%
  GC_theme("classic")
python
from geneviewer import GC, datasets

erythromycin_cluster = datasets.load("erythromycin_cluster")

(
    GC(
        erythromycin_cluster,
        start="Start",
        end="End",
        group="Functions",
        height="170px",
    )
    .title(
        title="Erythromycin A biosynthetic gene cluster from <i>Saccharopolyspora erythraea</i>",
        align="left",
    )
    .genes(marker="boxarrow", marker_size="small")
    .tooltip(formatter="<b>{Identifiers}</b><br>{Product}<br>{start} - {end}({Strand})")
    .scale(start=778000, end=832000, ticks_count=8)
    .legend(
        order=[*sorted(set(erythromycin_cluster["Functions"]) - {"Other"}), "Other"]
    )
    .color(custom_colors={"Other": "grey"})
    .theme("classic")
)

Saccharopolyspora erythraea Erythromycin protein alignment ​

Show the code
js
// <div id="chart" style="height: 700"></div>
const { data, links } = await fetch("https://nvelden.github.io/geneviewer-docs/charts/data/saccharopolyspora-erythraea-erythromycin-protein-alignment.json")
  .then((response) => response.json());

const chart = geneviewer.newChart("#chart", {
  data,
  fields: { cluster: "cluster", group: "Functions", strand: "strand" },
  title: { title: "Protein Alignment Results" },
  labels: { label: "Gene", clusters: [1] },
  links: {
    data: links,
    group: "Gene",
    show: false,
    colorBar: false,
    labelStyle: { fontSize: "10px" },
  },
  clusterLabel: {},
  genes: { stroke: "#6E7079", strokeWidth: 0.5 },
  legend: {
    order: [
      "Activation / Processing",
      "Other",
      "Precursor biosynthesis",
      "Resistance/Immunity",
      "Scaffold biosynthesis",
      "Tailoring (Glycosylation)",
      "Tailoring (Hydroxylation)",
      "Tailoring (Methylation)",
      "No Hit",
    ],
  },
  color: { customColors: { "No Hit": "white" } },
  theme: { base: "infographic", textColor: "#333333", palette: "okabeIto" },
});
r
### Erythromycin protein alignment
# Genes without a hit have no function: give them their own group
blastp <- erythromycin_BlastP
blastp$Functions[is.na(blastp$Functions)] <- "No Hit"

GC_chart(blastp, 
         cluster = "cluster",
         strand = "strand",
         group = "Functions",
         height = 700) %>%
  GC_title(
    title = "Protein Alignment Results"
  ) %>%
  GC_labels("Gene", cluster = 1) %>%
  GC_links(group = "Gene", 
           show_links = FALSE,
           color_bar = FALSE,
           labelStyle = list(fontSize = "10px")
           ) %>%
  GC_clusterLabel() %>%
  GC_genes(stroke = "#6E7079", strokeWidth = 0.5) %>%
  GC_legend(order = c(setdiff(sort(unique(blastp$Functions)), "No Hit"), "No Hit")) %>%
  GC_color(customColors = list("No Hit" = "white")) %>%
  GC_theme("infographic", textColor = "#333333", palette = "okabeIto")
python
from geneviewer import GC, datasets

# Genes without a hit have no function: give them their own group
blastp = datasets.load("erythromycin_BlastP")
blastp["Functions"] = blastp["Functions"].fillna("No Hit")

(
    GC(blastp, cluster="cluster", strand="strand", group="Functions", height=700)
    .title(title="Protein Alignment Results")
    .labels("Gene", cluster=1)
    .links(
        group="Gene",
        show_links=False,
        color_bar=False,
        label_style={"fontSize": "10px"},
    )
    .cluster_label()
    .genes(stroke="#6E7079", stroke_width=0.5)
    .legend(order=[*sorted(set(blastp["Functions"]) - {"No Hit"}), "No Hit"])
    .color(custom_colors={"No Hit": "white"})
    .theme("infographic", text_color="#333333", palette="okabeIto")
)
Show the code
js
// <div id="chart" style="height: 250"></div>
const { data, links } = await fetch("https://nvelden.github.io/geneviewer-docs/charts/data/saccharopolyspora-erythraea-erythromycin-protein-alignment-2.json")
  .then((response) => response.json());

const chart = geneviewer.newChart("#chart", {
  data,
  fields: { cluster: "cluster", group: "Functions", strand: "strand" },
  labels: { label: "Gene", clusters: [1] },
  genes: {
    marker: "rbox",
    markerSize: "small",
    markerHeight: 15,
    stroke: "#6E7079",
    strokeWidth: 0.5,
  },
  links: { data: links, group: "BlastP", label: false, colorBar: false },
  clusterLabel: {},
  legend: { show: false },
  color: { customColors: { "No Hit": "white" } },
  theme: { base: "classic", textColor: "#333333", palette: "okabeIto" },
});
r
library(dplyr)
### Erythromycin protein alignment
# Genes without a hit have no function: give them their own group
blastp <- erythromycin_BlastP %>% dplyr::filter(cluster %in% c("BGC0000055", "BGC0000054"))
blastp$Functions[is.na(blastp$Functions)] <- "No Hit"

GC_chart(blastp, 
         cluster = "cluster",
         strand = "strand",
         group = "Functions",
         height = 250) %>%
  GC_labels("Gene", cluster = 1) %>%
  GC_genes(marker_size = "small", marker = "rbox", markerHeight = 15,
           stroke = "#6E7079", strokeWidth = 0.5) %>%
  GC_links(group = "BlastP", 
           label = FALSE,
           color_bar = FALSE
           ) %>%
  GC_clusterLabel() %>%
  GC_legend(FALSE) %>%
  GC_color(customColors = list("No Hit" = "white")) %>%
  GC_theme("classic", textColor = "#333333", palette = "okabeIto")
python
from geneviewer import GC, datasets

# Genes without a hit have no function: give them their own group
blastp = datasets.load("erythromycin_BlastP")
blastp = blastp[blastp["cluster"].isin(["BGC0000055", "BGC0000054"])]
blastp["Functions"] = blastp["Functions"].fillna("No Hit")

(
    GC(blastp, cluster="cluster", strand="strand", group="Functions", height=250)
    .labels("Gene", cluster=1)
    .genes(
        marker_size="small",
        marker="rbox",
        marker_height=15,
        stroke="#6E7079",
        stroke_width=0.5,
    )
    .links(group="BlastP", label=False, color_bar=False)
    .cluster_label()
    .legend(False)
    .color(custom_colors={"No Hit": "white"})
    .theme("classic", text_color="#333333", palette="okabeIto")
)

blaKPC-2 plasmid pQEB1 and its variants ​

Show the code
js
// <div id="chart" style="height: 760px"></div>
const { data, links } = await fetch("https://nvelden.github.io/geneviewer-docs/charts/data/blakpc-2-plasmid-pqeb1-and-its-variants.json")
  .then((response) => response.json());

const chart = geneviewer.newChart("#chart", {
  data,
  fields: { cluster: "cluster", group: "category", strand: "strand" },
  links: {
    data: links,
    measure: "none",
    label: false,
    normalColor: "#7f9cbf",
    invertedColor: "#e6894e",
    colorBar: false,
  },
  genes: { markerSize: "small" },
  scale: { axisType: "range" },
  clusterLabel: {
    title: [
      "pQEB1_inv3_Tn5403",
      "pQEB1",
      "pQEB1_inv1",
      "pQEB1_inv1_inv2",
      "pQEB1_inv1_arsTn",
    ],
    width: "175px",
    align: "right",
    subtitle: [
      "E. cloacae ECL-21",
      "E. cloacae",
      "E. cloacae ECL-26",
      "E. cloacae ECL-22",
      "K. oxytoca KOX-3",
    ],
    subtitleFont: { fontSize: "12px", fontStyle: "italic" },
    fontSize: "13px",
    x: -10,
  },
  title: {
    title: "<i>bla</i>KPC-2 plasmid pQEB1 and its rearranged variants",
    subtitle: "IncN plasmids aligned with nucmer (all blocks ≥ 99.2% identity); orange links mark inversions",
    subtitleFont: { fontSize: "15px", fontStyle: "italic" },
    titleFont: { fontSize: "20px", fontWeight: "bold" },
    height: "70px",
  },
  tooltip: { formatter: "<b>{gene}</b> {product}<br>{start} - {end}" },
  color: {
    customColors: {
      "Carbapenemase (KPC)": "#d62728",
      "Other resistance": "#ff7f0e",
      "Arsenic resistance": "#8c564b",
      "Mobile element": "#9467bd",
      Conjugation: "#1f77b4",
      "Replication & maintenance": "#2ca02c",
      Hypothetical: "#d9d9d9",
      Other: "#9e9e9e",
    },
  },
  legend: {
    order: [
      "Carbapenemase (KPC)",
      "Other resistance",
      "Arsenic resistance",
      "Mobile element",
      "Conjugation",
      "Replication & maintenance",
      "Hypothetical",
      "Other",
    ],
    position: "top",
    align: "center",
    textStyle: { fontSize: "14px" },
  },
  theme: { base: "publication" },
});
r
plasmids <- dplyr::distinct(pQEB1_plasmids, cluster, host)
colors <- list(
  "Carbapenemase (KPC)" = "#d62728",
  "Other resistance" = "#ff7f0e",
  "Arsenic resistance" = "#8c564b",
  "Mobile element" = "#9467bd",
  "Conjugation" = "#1f77b4",
  "Replication & maintenance" = "#2ca02c",
  "Hypothetical" = "#d9d9d9",
  "Other" = "#9e9e9e"
)

GC_chart(pQEB1_plasmids, cluster = "cluster", group = "category",
         strand = "strand", height = "760px") %>%
  GC_links(data = pQEB1_alignment, measure = "none", label = FALSE,
           color_bar = FALSE, normal_color = "#7f9cbf",
           inverted_color = "#e6894e") %>%
  GC_genes(marker_size = "small") %>%
  GC_scale(axis_type = "range") %>%
  GC_clusterLabel(
    title = plasmids$cluster,
    subtitle = plasmids$host,
    width = "175px",
    fontSize = "13px",
    subtitleFont = list(fontSize = "12px", fontStyle = "italic"),
    align = "right",
    x = -10
  ) %>%
  GC_title(
    "<i>bla</i>KPC-2 plasmid pQEB1 and its rearranged variants",
    subtitle = paste("IncN plasmids aligned with nucmer",
                     "(all blocks \u2265 99.2% identity);",
                     "orange links mark inversions"),
    height = "70px",
    titleFont = list(fontSize = "20px", fontWeight = "bold"),
    subtitleFont = list(fontSize = "15px", fontStyle = "italic")
  ) %>%
  GC_tooltip(formatter = "<b>{gene}</b> {product}<br>{start} - {end}") %>%
  GC_color(customColors = colors) %>%
  GC_legend(position = "top", align = "center", order = names(colors),
            legendTextOptions = list(fontSize = "14px")) %>%
  GC_theme("publication")
python
from geneviewer import GC, datasets

pQEB1_plasmids = datasets.load("pQEB1_plasmids")
pQEB1_alignment = datasets.load("pQEB1_alignment")

plasmids = pQEB1_plasmids[["cluster", "host"]].drop_duplicates()

colors = {
    "Carbapenemase (KPC)": "#d62728",
    "Other resistance": "#ff7f0e",
    "Arsenic resistance": "#8c564b",
    "Mobile element": "#9467bd",
    "Conjugation": "#1f77b4",
    "Replication & maintenance": "#2ca02c",
    "Hypothetical": "#d9d9d9",
    "Other": "#9e9e9e",
}

(
    GC(
        pQEB1_plasmids,
        cluster="cluster",
        group="category",
        strand="strand",
        height="760px",
    )
    .links(
        data=pQEB1_alignment,
        measure="none",
        label=False,
        color_bar=False,
        normal_color="#7f9cbf",
        inverted_color="#e6894e",
    )
    .genes(marker_size="small")
    .scale(axis_type="range")
    .cluster_label(
        title=list(plasmids["cluster"]),
        subtitle=list(plasmids["host"]),
        width="175px",
        font_size="13px",
        subtitle_font={"fontSize": "12px", "fontStyle": "italic"},
        align="right",
        x=-10,
    )
    .title(
        "<i>bla</i>KPC-2 plasmid pQEB1 and its rearranged variants",
        subtitle="IncN plasmids aligned with nucmer (all blocks ≥ 99.2% identity); orange links mark inversions",
        height="70px",
        title_font={"fontSize": "20px", "fontWeight": "bold"},
        subtitle_font={"fontSize": "15px", "fontStyle": "italic"},
    )
    .tooltip(formatter="<b>{gene}</b> {product}<br>{start} - {end}")
    .color(custom_colors=colors)
    .legend(
        position="top",
        align="center",
        order=list(colors),
        legend_text_options={"fontSize": "14px"},
    )
    .theme("publication")
)

Tn7-like transposons carrying a CRISPR-Cas system ​

Redrawn from Figure 3 of Peters et al. (2017). The tutorial builds this chart step by step.

Show the code
js
// <div id="chart" style="height: 900px"></div>
const { data } = await fetch("https://nvelden.github.io/geneviewer-docs/charts/data/tn7-like-transposons-carrying-a-crispr-cas-system.json")
  .then((response) => response.json());

const chart = geneviewer.newChart("#chart", {
  data,
  fields: { cluster: "cluster", group: "category", strand: "strand" },
  genes: {
    markerSize: "small",
    groupStyle: {
      R: { marker: "box", markerHeight: 38, arrowheadHeight: 38 },
      L: { marker: "box", markerHeight: 38, arrowheadHeight: 38 },
      CRISPR: {
        marker: "box",
        markerHeight: 20,
        arrowheadHeight: 20,
        stroke: "black",
        strokeWidth: 1,
      },
      "tnsA (fused)": { marker: "box", markerHeight: 20, arrowheadHeight: 20 },
    },
    styleBy: "gene",
    markerHeight: 20,
  },
  labels: {
    label: "label",
    groupStyle: {
      tnsA: { fill: "white" },
      cas8f: { fill: "white" },
      cas6f: { fill: "white" },
      cas5: { fill: "white" },
      "SRP-RNA": { y: 55, dy: "0px", textAnchor: "end", x: -4 },
    },
    styleBy: "label",
    fontSize: "9px",
    y: 50,
    dy: "14.5px",
    adjustLabels: false,
  },
  scale: {
    hidden: true,
    axisType: "range",
    autoBreaks: true,
    breakPadding: "500bp",
  },
  align: { idColumn: "gene", id: "R", align: "left" },
  clusterLabel: {
    title: [
      "Tn7",
      "Tn6022",
      "#2",
      "#141",
      "#199",
      "#262",
      "#298",
      "#330",
      "#340",
      "#375",
      "#409",
      "#424",
      "#438",
      "#446",
      "#2757",
      "#5291",
    ],
    width: "190px",
    align: "right",
    subtitle: [
      "A. baumannii UC20804",
      "A. baumannii NIPH 1734",
      "V. parahaemolyticus RIMD 2210633",
      "V. campbellii ATCC BAA-1116",
      "V. parahaemolyticus O1:Kuk FDA_R31",
      "V. fluvialis ATCC 33809",
      "V. cholerae VC35",
      "V. natriegens NBRC 15636",
      "V. crassostreae J5-20",
      "P. translucida KMM 520",
      "V. cholerae YB2A06",
      "V. hyugaensis 151112A",
      "Vibrio sp. EJY3",
      "Shewanella sp. ANA-3",
      "R. orientalis PCC 8801",
      "T. variabilis ATCC 29413",
    ],
    subtitleFont: { fontSize: "10px", fontStyle: "italic" },
    fontSize: "12px",
    x: -10,
  },
  title: {
    title: "Tn7-like transposons that carry a minimal CRISPR-Cas system",
    subtitle: "Redrawn from Fig. 3 of Peters et al. (2017), Proc Natl Acad Sci USA 114:E7358-E7366",
    subtitleFont: { fontSize: "14px", fontStyle: "italic" },
    titleFont: { fontSize: "19px", fontWeight: "bold" },
    height: "70px",
  },
  tooltip: { formatter: "<b>{gene}</b> {product}<br>{start} - {end}" },
  color: {
    customColors: {
      "insertion site": "#F3C79B",
      tnsA: "#D62728",
      tnsB: "#AEB6F0",
      tnsC: "#D7F2F2",
      "tniQ / tnsD": "#2CA02C",
      tnsE: "#C7E02C",
      "cas8f / cas5f": "#8C1515",
      cas7f: "#F2A5C4",
      cas6f: "#7B3FD4",
      cas5: "#B5651D",
      "cas, other": "#C9A0DC",
      "CRISPR array": "#555555",
      "right end": "#9FD4DE",
      "left end": "#F28E2B",
      other: "#E8E8E8",
    },
  },
  pattern: {
    patterns: { "right end": "diagonal", "left end": "diagonal" },
    background: null,
    size: 4,
  },
  legend: {
    order: [
      "insertion site",
      "tnsA",
      "tnsB",
      "tnsC",
      "tniQ / tnsD",
      "tnsE",
      "cas8f / cas5f",
      "cas7f",
      "cas6f",
      "cas5",
      "cas, other",
      "CRISPR array",
      "right end",
      "left end",
      "other",
    ],
    position: "bottom",
    align: "center",
    textStyle: { fontSize: "12px" },
    groupStyle: {
      tnsA: { fontStyle: "italic" },
      tnsB: { fontStyle: "italic" },
      tnsC: { fontStyle: "italic" },
      "tniQ / tnsD": { fontStyle: "italic" },
      tnsE: { fontStyle: "italic" },
      "cas8f / cas5f": { fontStyle: "italic" },
      cas7f: { fontStyle: "italic" },
      cas6f: { fontStyle: "italic" },
      cas5: { fontStyle: "italic" },
    },
  },
  theme: { base: "publication" },
});
r
# The element ends are single positions in the data. They are drawn as tall
# bars, the way the inverted repeats at the ends of a transposon are often
# drawn: 100 bp wide, from the end into the element, so they stay clear of the
# gene next to them.
genes <- tn7_crispr_elements %>%
  dplyr::mutate(end = ifelse(gene == "R", end + 100, end),
                start = ifelse(gene == "L", start - 100, start))

elements <- dplyr::distinct(genes, cluster, strain_short)

colors <- list(
  "insertion site" = "#F3C79B",
  "tnsA" = "#D62728",
  "tnsB" = "#AEB6F0",
  "tnsC" = "#D7F2F2",
  "tniQ / tnsD" = "#2CA02C",
  "tnsE" = "#C7E02C",
  "cas8f / cas5f" = "#8C1515",
  "cas7f" = "#F2A5C4",
  "cas6f" = "#7B3FD4",
  "cas5" = "#B5651D",
  "cas, other" = "#C9A0DC",
  "CRISPR array" = "#555555",
  "right end" = "#9FD4DE",
  "left end" = "#F28E2B",
  "other" = "#E8E8E8"
)

# In the legend the gene names are italic, the other entries upright
gene_names <- c("tnsA", "tnsB", "tnsC", "tniQ / tnsD", "tnsE", "cas8f / cas5f",
                "cas7f", "cas6f", "cas5")
legend_styles <- lapply(stats::setNames(nm = gene_names),
                        function(x) list(fontStyle = "italic"))

# The labels by their text: white on the dark genes, and above the SRP RNA
# genes, which are too short for it, ending clear of the right end beside them
white <- list(fill = "white")
label_styles <- list(
  tnsA = white, cas8f = white, cas6f = white, cas5 = white,
  "SRP-RNA" = list(y = 55, dy = "0px", textAnchor = "end", x = -4)
)

# By gene: the ends (R and L) are tall bars, the CRISPR arrays and the fused
# tnsA boxes the height of the genes
end_bar <- list(marker = "box", markerHeight = 38, arrowheadHeight = 38)
gene_box <- list(marker = "box", markerHeight = 20, arrowheadHeight = 20)
shapes <- list(
  R = end_bar,
  L = end_bar,
  CRISPR = c(gene_box, stroke = "black", strokeWidth = 1),
  "tnsA (fused)" = gene_box
)

chart <- GC_chart(genes, cluster = "cluster", group = "category",
                  strand = "strand", height = "900px") %>%
  # tall arrows, with the labels inside them
  GC_genes(marker_size = "small", markerHeight = 20,
           style_by = "gene", groupStyle = shapes) %>%
  GC_labels(label = "label", fontSize = "9px", y = 50, dy = "14.5px",
            adjustLabels = FALSE, style_by = "label", groupStyle = label_styles) %>%
  # most elements run on far beyond the genes shown, up to ~100 kb: scale breaks
  # (//) leave out such long stretches, as in the published figure
  GC_scale(axis_type = "range", hidden = TRUE, scale_breaks = TRUE,
           scale_break_padding = "500bp") %>%
  # line the elements up on their right end, as in the published figure
  GC_align("gene", "R", align = "left") %>%
  GC_clusterLabel(
    title = elements$cluster,
    subtitle = elements$strain_short,
    width = "190px",
    fontSize = "12px",
    subtitleFont = list(fontSize = "10px", fontStyle = "italic"),
    align = "right",
    x = -10
  ) %>%
  GC_title(
    "Tn7-like transposons that carry a minimal CRISPR-Cas system",
    subtitle = paste("Redrawn from Fig. 3 of Peters et al. (2017),",
                     "Proc Natl Acad Sci USA 114:E7358-E7366"),
    height = "70px",
    titleFont = list(fontSize = "19px", fontWeight = "bold"),
    subtitleFont = list(fontSize = "14px", fontStyle = "italic")
  ) %>%
  GC_tooltip(formatter = "<b>{gene}</b> {product}<br>{start} - {end}") %>%
  GC_color(customColors = colors) %>%
  # the two ends share a pattern and are told apart by their colour
  GC_pattern(patterns = list("right end" = "diagonal", "left end" = "diagonal"),
             background = NULL, size = 4) %>%
  GC_legend(position = "bottom", align = "center", order = names(colors),
            legendTextOptions = list(fontSize = "12px"),
            groupStyle = legend_styles) %>%
  GC_theme("publication")

chart
python
from geneviewer import GC, datasets

# The element ends are single positions in the data. They are drawn as tall
# bars, the way the inverted repeats at the ends of a transposon are often
# drawn: 100 bp wide, from the end into the element, so they stay clear of the
# gene next to them.
genes = datasets.load("tn7_crispr_elements")
genes.loc[genes["gene"] == "R", "end"] += 100
genes.loc[genes["gene"] == "L", "start"] -= 100

elements = genes[["cluster", "strain_short"]].drop_duplicates()

colors = {
    "insertion site": "#F3C79B",
    "tnsA": "#D62728",
    "tnsB": "#AEB6F0",
    "tnsC": "#D7F2F2",
    "tniQ / tnsD": "#2CA02C",
    "tnsE": "#C7E02C",
    "cas8f / cas5f": "#8C1515",
    "cas7f": "#F2A5C4",
    "cas6f": "#7B3FD4",
    "cas5": "#B5651D",
    "cas, other": "#C9A0DC",
    "CRISPR array": "#555555",
    "right end": "#9FD4DE",
    "left end": "#F28E2B",
    "other": "#E8E8E8",
}

# In the legend the gene names are italic, the other entries upright
gene_names = [
    "tnsA",
    "tnsB",
    "tnsC",
    "tniQ / tnsD",
    "tnsE",
    "cas8f / cas5f",
    "cas7f",
    "cas6f",
    "cas5",
]

legend_styles = {name: {"fontStyle": "italic"} for name in gene_names}

# The labels by their text: white on the dark genes, and above the SRP RNA
# genes, which are too short for it, ending clear of the right end beside them
white = {"fill": "white"}

label_styles = {
    "tnsA": white,
    "cas8f": white,
    "cas6f": white,
    "cas5": white,
    "SRP-RNA": {"y": 55, "dy": "0px", "textAnchor": "end", "x": -4},
}

# By gene: the ends (R and L) are tall bars, the CRISPR arrays and the fused
# tnsA boxes the height of the genes
end_bar = {"marker": "box", "markerHeight": 38, "arrowheadHeight": 38}

gene_box = {"marker": "box", "markerHeight": 20, "arrowheadHeight": 20}

shapes = {
    "R": end_bar,
    "L": end_bar,
    "CRISPR": {**gene_box, "stroke": "black", "strokeWidth": 1},
    "tnsA (fused)": gene_box,
}

chart = (
    GC(genes, cluster="cluster", group="category", strand="strand", height="900px")
    # tall arrows, with the labels inside them
    .genes(marker_size="small", marker_height=20, style_by="gene", group_style=shapes)
    .labels(
        label="label",
        font_size="9px",
        y=50,
        dy="14.5px",
        adjust_labels=False,
        style_by="label",
        group_style=label_styles,
    )
    # most elements run on far beyond the genes shown, up to ~100 kb: scale breaks
    # (//) leave out such long stretches, as in the published figure
    .scale(
        axis_type="range", hidden=True, scale_breaks=True, scale_break_padding="500bp"
    )
    # line the elements up on their right end, as in the published figure
    .align("gene", "R", align="left")
    .cluster_label(
        title=list(elements["cluster"]),
        subtitle=list(elements["strain_short"]),
        width="190px",
        font_size="12px",
        subtitle_font={"fontSize": "10px", "fontStyle": "italic"},
        align="right",
        x=-10,
    )
    .title(
        "Tn7-like transposons that carry a minimal CRISPR-Cas system",
        subtitle="Redrawn from Fig. 3 of Peters et al. (2017), Proc Natl Acad Sci USA 114:E7358-E7366",
        height="70px",
        title_font={"fontSize": "19px", "fontWeight": "bold"},
        subtitle_font={"fontSize": "14px", "fontStyle": "italic"},
    )
    .tooltip(formatter="<b>{gene}</b> {product}<br>{start} - {end}")
    .color(custom_colors=colors)
    # the two ends share a pattern and are told apart by their colour
    .pattern(
        patterns={"right end": "diagonal", "left end": "diagonal"},
        background=None,
        size=4,
    )
    .legend(
        position="bottom",
        align="center",
        order=list(colors),
        legend_text_options={"fontSize": "12px"},
        group_style=legend_styles,
    )
    .theme("publication")
)

chart

Genomes of the four coronavirus genera ​

After Figure 1 of Chazal (2021). Drag the slider below the genomes to zoom in on the accessory genes.

Show the code
js
// <div id="chart" style="height: 700px"></div>
const { data, links } = await fetch("https://nvelden.github.io/geneviewer-docs/charts/data/genomes-of-the-four-coronavirus-genera.json")
  .then((response) => response.json());

const chart = geneviewer.newChart("#chart", {
  data,
  fields: { cluster: "cluster", group: "category" },
  color: {
    customColors: {
      "5' UTR": "#1A1A1A",
      ORF1a: "#4E79A7",
      ORF1b: "#A0CBE8",
      spike: "#E15759",
      "hemagglutinin-esterase": "#F28E2B",
      envelope: "#EDC948",
      membrane: "#59A14F",
      nucleocapsid: "#2F4B7C",
      accessory: "#B07AA1",
      "3' UTR": "#BDBDBD",
    },
  },
  cluster: { preventGeneOverlap: "nested", overlapMin: "50%", overlapSpacing: -4 },
  genes: {
    marker: "box",
    groupStyle: {
      "2": {
        markerHeight: 13,
        arrowheadHeight: 13,
        fill: "#E8DCE6",
        stroke: "#B07AA1",
      },
      "3": {
        markerHeight: 13,
        arrowheadHeight: 13,
        fill: "#E8DCE6",
        stroke: "#B07AA1",
      },
    },
    styleBy: "geneTrack",
    markerHeight: 18,
    arrowheadHeight: 18,
  },
  labels: {
    label: "gene",
    groupStyle: {
      "2": { dy: "-1.6em", fontSize: "8px" },
      "3": { dy: "-1.6em", fontSize: "8px" },
    },
    styleBy: "geneTrack",
  },
  links: {
    data: links,
    group: "homolog",
    curve: true,
    measure: "identity",
    label: true,
    labelPosition: "link",
    vmin: 20,
    colorBarOptions: { position: "legend", legendSide: "right" },
    labelStyle: { fontSize: "9px" },
  },
  grid: {
    margin: { top: 22 },
    height: 85.63636363636363,
    clusters: ["HCoV-229E", "MHV", "IBV", "PDCoV"],
  },
  clusterLabel: {
    title: [
      "HCoV-229E",
      "HCoV-NL63",
      "MHV",
      "HCoV-OC43",
      "HCoV-HKU1",
      "MERS-CoV",
      "SARS-CoV-1",
      "SARS-CoV-2",
      "RaTG13",
      "IBV",
      "PDCoV",
    ],
    width: "170px",
    align: "right",
    subtitle: [
      "<i>Duvinacovirus</i>, human",
      "<i>Setracovirus</i>, human",
      "<i>Embecovirus</i>, mouse",
      "<i>Embecovirus</i>, human",
      "<i>Embecovirus</i>, human",
      "<i>Merbecovirus</i>, human",
      "<i>Sarbecovirus</i>, human",
      "<i>Sarbecovirus</i>, human",
      "<i>Sarbecovirus</i>, bat",
      "<i>Igacovirus</i>, chicken",
      "<i>Buldecovirus</i>, pig",
    ],
    subtitleFont: { fontSize: "11px" },
    fontSize: "13px",
    x: -10,
  },
  clusterTitle: {
    title: [
      "Alphacoronavirus",
      "Betacoronavirus",
      "Gammacoronavirus",
      "Deltacoronavirus",
    ],
    titleFont: { fontSize: "13px", fontWeight: "bold" },
    height: "0px",
    clusters: ["HCoV-229E", "MHV", "IBV", "PDCoV"],
    align: "left",
    x: -165,
    y: -16,
  },
  title: {
    title: "Conserved core, variable accessory genes: coronaviruses of the four genera",
    subtitle: "Homologous proteins of close relatives linked by identity; after Fig. 1 of Chazal (2021)",
    subtitleFont: { fontSize: "12px", fontStyle: "italic" },
    titleFont: { fontSize: "16px", fontWeight: "bold" },
    height: "55px",
  },
  tooltip: {
    formatter: "<b>{gene}</b> {product}<br>{virus} {strain}<br>{start} - {end}",
  },
  legend: {
    order: [
      "5' UTR",
      "ORF1a",
      "ORF1b",
      "spike",
      "hemagglutinin-esterase",
      "envelope",
      "membrane",
      "nucleocapsid",
      "accessory",
      "3' UTR",
    ],
    position: "top",
    align: "center",
    textStyle: { fontSize: "12px" },
    groupStyle: {
      "5' UTR": { text: "5' UTR (L)" },
      spike: { text: "spike (S)" },
      "hemagglutinin-esterase": { text: "hemagglutinin-esterase (HE)" },
      envelope: { text: "envelope (E)" },
      membrane: { text: "membrane (M)" },
      nucleocapsid: { text: "nucleocapsid (N)" },
    },
  },
  pattern: {
    patterns: { "5' UTR": "diagonal", "3' UTR": "diagonal" },
    color: { "5' UTR": "#8C8C8C", "3' UTR": "#6E6E6E" },
    background: null,
    size: 4,
    strokeWidth: 1,
  },
  zoom: { height: 44 },
  theme: { base: "publication" },
});
r
genomes <- distinct(coronavirus_genomes, cluster, genus, subgenus, host)
# Name the genus above its first genome; the others get no title, nor room
# for one
first_of_genus <- genomes[!duplicated(genomes$genus), ]

colors <- list(
  "5' UTR" = "#1A1A1A", ORF1a = "#4E79A7", ORF1b = "#A0CBE8", spike = "#E15759",
  "hemagglutinin-esterase" = "#F28E2B", envelope = "#EDC948",
  membrane = "#59A14F", nucleocapsid = "#2F4B7C", accessory = "#B07AA1",
  "3' UTR" = "#BDBDBD"
)

# The ORFs on the tracks below: smaller boxes, with their label inside
nested <- list(markerHeight = 13, arrowheadHeight = 13, fill = "#E8DCE6",
               stroke = "#B07AA1")
nested_label <- list(dy = "-1.6em", fontSize = "8px")

chart <- GC_chart(coronavirus_genomes, cluster = "cluster", group = "category",
                  height = "700px") %>%
  GC_color(customColors = colors) %>%
  # Every gene a box; ORFs that lie inside another gene, e.g. 9b inside N,
  # go on the tracks below. 3c and 3d of SARS-CoV-2 overlap by less than
  # half, so they share a track
  GC_cluster(prevent_gene_overlap = "nested", overlap_min = "50%",
             overlap_spacing = -4) %>%
  GC_genes(marker = "box", markerHeight = 18, arrowheadHeight = 18,
           style_by = "geneTrack",
           groupStyle = list("2" = nested, "3" = nested)) %>%
  GC_labels("gene", style_by = "geneTrack",
            groupStyle = list("2" = nested_label, "3" = nested_label)) %>%
  # Homologous genes of neighbouring genomes, coloured by the protein
  # identity, written on each link where it fits
  GC_links(group = "homolog", measure = "identity", label = TRUE,
           label_position = "link", vmin = 20, curve = TRUE,
           labelStyle = list(fontSize = "9px"),
           colorBarOptions = list(position = "legend", legendSide = "right")) %>%
  # Room above the first genome of each genus for its name: 22 pixels more
  # height, taken up by a margin
  GC_grid(margin = list(top = 22), height = 700 / 11 + 22,
          cluster = first_of_genus$cluster) %>%
  GC_clusterLabel(title = genomes$cluster,
                  subtitle = paste0("<i>", genomes$subgenus, "</i>, ", genomes$host),
                  width = "170px", fontSize = "13px",
                  subtitleFont = list(fontSize = "11px"),
                  align = "right", x = -10) %>%
  GC_clusterTitle(title = first_of_genus$genus, cluster = first_of_genus$cluster,
                  align = "left", height = "0px", x = -165, y = -16,
                  titleFont = list(fontSize = "13px", fontWeight = "bold")) %>%
  GC_title("Conserved core, variable accessory genes: coronaviruses of the four genera",
           subtitle = paste("Homologous proteins of close relatives linked by identity;",
                            "after Fig. 1 of Chazal (2021)"),
           height = "55px",
           titleFont = list(fontSize = "16px", fontWeight = "bold"),
           subtitleFont = list(fontSize = "12px", fontStyle = "italic")) %>%
  GC_tooltip(formatter = "<b>{gene}</b> {product}<br>{virus} {strain}<br>{start} - {end}") %>%
  # The legend names each category with its gene
  GC_legend(position = "top", align = "center", order = names(colors),
            legendTextOptions = list(fontSize = "12px"),
            groupStyle = list(
              "5' UTR" = list(text = "5' UTR (L)"),
              spike = list(text = "spike (S)"),
              "hemagglutinin-esterase" = list(text = "hemagglutinin-esterase (HE)"),
              envelope = list(text = "envelope (E)"),
              membrane = list(text = "membrane (M)"),
              nucleocapsid = list(text = "nucleocapsid (N)")
            )) %>%
  # The untranslated ends share a pattern, in a shade that shows on each
  GC_pattern(patterns = list("5' UTR" = "diagonal", "3' UTR" = "diagonal"),
             color = list("5' UTR" = "#8C8C8C", "3' UTR" = "#6E6E6E"),
             background = NULL, size = 4, strokeWidth = 1) %>%
  GC_zoom(height = 44) %>%
  GC_theme("publication")
chart
python
from geneviewer import GC, datasets

coronavirus_genomes = datasets.load("coronavirus_genomes")

genomes = coronavirus_genomes[
    ["cluster", "genus", "subgenus", "host"]
].drop_duplicates()

# Name the genus above its first genome; the others get no title, nor room
# for one
first_of_genus = genomes.drop_duplicates("genus")

colors = {
    "5' UTR": "#1A1A1A",
    "ORF1a": "#4E79A7",
    "ORF1b": "#A0CBE8",
    "spike": "#E15759",
    "hemagglutinin-esterase": "#F28E2B",
    "envelope": "#EDC948",
    "membrane": "#59A14F",
    "nucleocapsid": "#2F4B7C",
    "accessory": "#B07AA1",
    "3' UTR": "#BDBDBD",
}

# The ORFs on the tracks below: smaller boxes, with their label inside
nested = {
    "markerHeight": 13,
    "arrowheadHeight": 13,
    "fill": "#E8DCE6",
    "stroke": "#B07AA1",
}

nested_label = {"dy": "-1.6em", "fontSize": "8px"}

chart = (
    GC(coronavirus_genomes, cluster="cluster", group="category", height="700px")
    .color(custom_colors=colors)
    # Every gene a box; ORFs that lie inside another gene, e.g. 9b inside N,
    # go on the tracks below. 3c and 3d of SARS-CoV-2 overlap by less than
    # half, so they share a track
    .cluster(prevent_gene_overlap="nested", overlap_min="50%", overlap_spacing=-4)
    .genes(
        marker="box",
        marker_height=18,
        arrowhead_height=18,
        style_by="geneTrack",
        group_style={"2": nested, "3": nested},
    )
    .labels(
        "gene", style_by="geneTrack", group_style={"2": nested_label, "3": nested_label}
    )
    # Homologous genes of neighbouring genomes, coloured by the protein
    # identity, written on each link where it fits
    .links(
        group="homolog",
        measure="identity",
        label=True,
        label_position="link",
        vmin=20,
        curve=True,
        label_style={"fontSize": "9px"},
        color_bar_options={"position": "legend", "legendSide": "right"},
    )
    # Room above the first genome of each genus for its name: 22 pixels more
    # height, taken up by a margin
    .grid(
        margin={"top": 22},
        height=700 / 11 + 22,
        cluster=list(first_of_genus["cluster"]),
    )
    .cluster_label(
        title=list(genomes["cluster"]),
        subtitle=[
            f"<i>{subgenus}</i>, {host}"
            for subgenus, host in zip(genomes["subgenus"], genomes["host"])
        ],
        width="170px",
        font_size="13px",
        subtitle_font={"fontSize": "11px"},
        align="right",
        x=-10,
    )
    .cluster_title(
        title=list(first_of_genus["genus"]),
        cluster=list(first_of_genus["cluster"]),
        align="left",
        height="0px",
        x=-165,
        y=-16,
        title_font={"fontSize": "13px", "fontWeight": "bold"},
    )
    .title(
        "Conserved core, variable accessory genes: coronaviruses of the four genera",
        subtitle="Homologous proteins of close relatives linked by identity; after Fig. 1 of Chazal (2021)",
        height="55px",
        title_font={"fontSize": "16px", "fontWeight": "bold"},
        subtitle_font={"fontSize": "12px", "fontStyle": "italic"},
    )
    .tooltip(formatter="<b>{gene}</b> {product}<br>{virus} {strain}<br>{start} - {end}")
    # The legend names each category with its gene
    .legend(
        position="top",
        align="center",
        order=list(colors),
        legend_text_options={"fontSize": "12px"},
        group_style={
            "5' UTR": {"text": "5' UTR (L)"},
            "spike": {"text": "spike (S)"},
            "hemagglutinin-esterase": {"text": "hemagglutinin-esterase (HE)"},
            "envelope": {"text": "envelope (E)"},
            "membrane": {"text": "membrane (M)"},
            "nucleocapsid": {"text": "nucleocapsid (N)"},
        },
    )
    # The untranslated ends share a pattern, in a shade that shows on each
    .pattern(
        patterns={"5' UTR": "diagonal", "3' UTR": "diagonal"},
        color={"5' UTR": "#8C8C8C", "3' UTR": "#6E6E6E"},
        background=None,
        size=4,
        stroke_width=1,
    )
    .zoom(height=44)
    .theme("publication")
)

chart

Mitochondrial gene order: locust and human ​

Show the code
js
// <div id="chart" style="height: 320px"></div>
const { data } = await fetch("https://nvelden.github.io/geneviewer-docs/charts/data/mitochondrial-gene-order-locust-and-human.json")
  .then((response) => response.json());

const chart = geneviewer.newChart("#chart", {
  data,
  fields: {
    start: "plot_start",
    end: "plot_end",
    cluster: "cluster",
    group: "block",
    strand: "strand",
  },
  genes: {
    marker: "box",
    markerHeight: 18,
    arrowheadHeight: 18,
    cornerRadius: 0,
  },
  cluster: { separateStrands: true, strandSpacing: -18 },
  labels: {
    label: "label",
    fontStyle: "normal",
    adjustLabels: "spread",
    leaderLine: { length: 12 },
  },
  color: {
    customColors: {
      "Conserved flanks": "#D9D5D2",
      "ND4L / ND4 / ND5": "#F22228",
      ND6: "#FFF000",
      CYTB: "#00AC52",
      "RNS / RNL / ND1": "#36328C",
    },
  },
  scale: { hidden: true, axisType: "range" },
  grid: { margin: { top: 0, bottom: 0 } },
  clusterFooter: {
    title: ["Locusta migratoria", "Homo sapiens"],
    subtitle: ["13 proteins; 2 rRNAs; 15,722 bp", "13 proteins; 2 rRNAs; 16,569 bp"],
    align: "left",
    y: 10,
  },
  title: {
    title: "Mitochondrial gene order: locust and human",
    subtitle: "Redrawn from Fig. 3 of Jameson et al. (2003), Nucleic Acids Res 31:202-206",
    titleFont: { fontSize: "19px" },
  },
  tooltip: {
    formatter: "<b>{gene}</b>: {product}<br>{cluster}<br>RefSeq: {accession}<br>Original coordinates: {genomic_start} - {genomic_end} ({strand})",
  },
  legend: { show: false },
  theme: { base: "publication", fontFamily: "Courier New, Courier, monospace" },
});
r
# Rotate each circular genome to start at COX1, preserving genomic spacing,
# and label reverse-strand genes with a leading minus, as in the published
# figure. The original coordinates are kept for the tooltips.
genes <- mitochondrial_gene_order %>%
  group_by(cluster) %>%
  mutate(genomic_start = start, genomic_end = end,
         plot_start = (start - start[gene == "COX1"]) %% genome_length + 1,
         plot_end = plot_start + end - start,
         label = ifelse(strand == "complement", paste0("-", gene), gene)) %>%
  ungroup()

genomes <- distinct(genes, cluster, genome_length)
colors <- list("Conserved flanks" = "#D9D5D2",
               "ND4L / ND4 / ND5" = "#F22228", ND6 = "#FFF000",
               CYTB = "#00AC52", "RNS / RNL / ND1" = "#36328C")

chart <- GC_chart(genes, start = "plot_start", end = "plot_end",
                  cluster = "cluster", group = "block", strand = "strand",
                  height = "320px") %>%
  GC_genes(marker = "box", markerHeight = 18, arrowheadHeight = 18,
           cornerRadius = 0) %>%
  # A negative spacing puts reverse-strand genes above the baseline and
  # forward-strand genes below it, as in the published figure.
  GC_cluster(separate_strands = TRUE, strand_spacing = -18) %>%
  # The labels go on one line below the genes, with a line to each gene
  GC_labels("label", fontStyle = "normal", adjustLabels = "spread",
            leaderLine = list(length = 12)) %>%
  GC_color(customColors = colors) %>%
  GC_scale(axis_type = "range", hidden = TRUE) %>%
  GC_grid(margin = list(top = 0, bottom = 0)) %>%
  GC_clusterFooter(
    title = genomes$cluster,
    subtitle = paste0("13 proteins; 2 rRNAs; ",
                      format(genomes$genome_length, big.mark = ","), " bp"),
    align = "left", y = 10
  ) %>%
  GC_title("Mitochondrial gene order: locust and human",
           subtitle = paste("Redrawn from Fig. 3 of Jameson et al. (2003),",
                            "Nucleic Acids Res 31:202-206"),
           titleFont = list(fontSize = "19px")) %>%
  GC_tooltip(formatter = paste0("<b>{gene}</b>: {product}<br>{cluster}<br>",
                                "RefSeq: {accession}<br>",
                                "Original coordinates: {genomic_start} - {genomic_end} ({strand})")) %>%
  GC_legend(FALSE) %>%
  GC_theme("publication", fontFamily = "Courier New, Courier, monospace")
chart
python
from geneviewer import GC, datasets

# Rotate each circular genome to start at COX1, preserving genomic spacing,
# and label reverse-strand genes with a leading minus, as in the published
# figure. The original coordinates are kept for the tooltips.
genes = datasets.load("mitochondrial_gene_order")
cox1_start = genes[genes["gene"] == "COX1"].set_index("cluster")["start"]
genes["genomic_start"] = genes["start"]
genes["genomic_end"] = genes["end"]
genes["plot_start"] = (genes["start"] - genes["cluster"].map(cox1_start)) % genes[
    "genome_length"
] + 1
genes["plot_end"] = genes["plot_start"] + genes["end"] - genes["start"]
genes["label"] = [
    "-" + gene if strand == "complement" else gene
    for gene, strand in zip(genes["gene"], genes["strand"])
]

genomes = genes[["cluster", "genome_length"]].drop_duplicates()

colors = {
    "Conserved flanks": "#D9D5D2",
    "ND4L / ND4 / ND5": "#F22228",
    "ND6": "#FFF000",
    "CYTB": "#00AC52",
    "RNS / RNL / ND1": "#36328C",
}

chart = (
    GC(
        genes,
        start="plot_start",
        end="plot_end",
        cluster="cluster",
        group="block",
        strand="strand",
        height="320px",
    )
    .genes(marker="box", marker_height=18, arrowhead_height=18, corner_radius=0)
    # A negative spacing puts reverse-strand genes above the baseline and
    # forward-strand genes below it, as in the published figure.
    .cluster(separate_strands=True, strand_spacing=-18)
    # The labels go on one line below the genes, with a line to each gene
    .labels(
        "label", font_style="normal", adjust_labels="spread", leader_line={"length": 12}
    )
    .color(custom_colors=colors)
    .scale(axis_type="range", hidden=True)
    .grid(margin={"top": 0, "bottom": 0})
    .cluster_footer(
        title=list(genomes["cluster"]),
        subtitle=[
            f"13 proteins; 2 rRNAs; {length:,} bp"
            for length in genomes["genome_length"]
        ],
        align="left",
        y=10,
    )
    .title(
        "Mitochondrial gene order: locust and human",
        subtitle="Redrawn from Fig. 3 of Jameson et al. (2003), Nucleic Acids Res 31:202-206",
        title_font={"fontSize": "19px"},
    )
    .tooltip(
        formatter="<b>{gene}</b>: {product}<br>{cluster}<br>RefSeq: {accession}<br>Original coordinates: {genomic_start} - {genomic_end} ({strand})"
    )
    .legend(False)
    .theme("publication", font_family="Courier New, Courier, monospace")
)

chart