35- DML gene-model figure (Table 2)

Steven Roberts 11 June, 2026


1 Overview

Publication-quality, multi-panel figure of the 10 annotated gene models that harbor the 12 differentially methylated loci (DMLs) reported in paper.md Table 2, with each DML denoted on its gene model. Companion to 30-dml-dmr-methylkit.Rmd and 31-dml-dmr-annotation.Rmd.

rtracklayer/GenomicFeatures are not installed in this environment, so the GFF is parsed directly with data.table/awk.

mkdir -p ../output/35-dml-gene-model-figure

2 Download the NCBI GFF annotation

Downloads GCF_036588685.1_..._genomic.gff from the NCBI FTP if not already present, then carves out the lines for the 10 genes of interest so the rest of the script stays fast and reproducible.

out="../output/35-dml-gene-model-figure"
gff="$out/genomic.gff"

if [ ! -s "$gff" ]; then
  url="https://ftp.ncbi.nlm.nih.gov/genomes/all/GCF/036/588/685/GCF_036588685.1_PNRI_Mtr1.1.1.hap1/GCF_036588685.1_PNRI_Mtr1.1.1.hap1_genomic.gff.gz"
  curl -sS -L -o "$gff.gz" "$url"
  gunzip -f "$gff.gz"
fi
ls -la "$gff"
## -rw-r--r--@ 1 sr320  staff  331324929 Jun 11 06:52 ../output/35-dml-gene-model-figure/genomic.gff
out="../output/35-dml-gene-model-figure"

awk -F'\t' '
BEGIN{ s="LOC134725187 LOC134690221 LOC134714536 LOC134695637 LOC134707074 LOC134720671 LOC134711256 LOC134685297 LOC134712818 LOC134724475 LOC134687110 LOC134687290";
       n=split(s,g," "); for(i=1;i<=n;i++) want[g[i]]=1 }
/^#/{next}
{ if(match($9,/gene=[^;]+/)){ gname=substr($9,RSTART+5,RLENGTH-5); if(gname in want) print } }
' "$out/genomic.gff" > "$out/gene_models_raw.gff"

echo "feature lines: $(wc -l < "$out/gene_models_raw.gff")"
cut -f3 "$out/gene_models_raw.gff" | sort | uniq -c
## feature lines:     1269
##  596 CDS
##  624 exon
##   12 gene
##   37 mRNA

3 Parse gene models

library(data.table)
library(dplyr)
library(ggplot2)
library(patchwork)

out_dir <- "../output/35-dml-gene-model-figure"
raw <- fread(file.path(out_dir, "gene_models_raw.gff"), sep = "\t", header = FALSE,
             quote = "", col.names = c("chr","src","type","start","end",
                                       "score","strand","frame","attr"))

get_attr <- function(attr, key) {
  out <- rep(NA_character_, length(attr))
  m   <- regexpr(paste0(key, "=[^;]+"), attr)
  hit <- m > 0
  out[hit] <- sub(paste0(key, "="), "", regmatches(attr, m))
  out
}

raw[, gene := get_attr(attr, "gene")]
raw[, ID := get_attr(attr, "ID")]
raw[, Parent := get_attr(attr, "Parent")]
raw[, product := get_attr(attr, "product")]
raw[, description := get_attr(attr, "description")]

genes <- raw[type == "gene",
             .(gene, chr, start, end, strand,
               gene_desc = description, gene_id_full = ID)]

mrna  <- raw[type == "mRNA",
             .(gene, tx = ID, chr, start, end, strand, product)]

# exon / CDS counts per transcript to help pick the primary isoform
exon_counts <- raw[type == "exon", .N, by = .(tx = Parent)]
setnames(exon_counts, "N", "n_exon")

mrna <- merge(mrna, exon_counts, by = "tx", all.x = TRUE)
mrna[, span := end - start]

# Primary transcript = longest genomic span, tie-break by most exons, then ID
setorder(mrna, gene, -span, -n_exon, tx)
primary <- mrna[, .SD[1], by = gene]
primary[]
##             gene                 tx         chr     start       end strand
##           <char>             <char>      <char>     <int>     <int> <char>
##  1: LOC134685297 rna-XM_063544925.1 NC_086381.1  21116727  21261455      -
##  2: LOC134687110 rna-XM_063547109.1 NC_086382.1  25951921  25959192      +
##  3: LOC134687290 rna-XM_063547445.1 NC_086382.1  36708321  36799106      +
##  4: LOC134690221 rna-XM_063550200.1 NC_086373.1  90602585  90632630      +
##  5: LOC134695637 rna-XM_063556955.1 NC_086373.1 105380391 105513502      -
##  6: LOC134707074 rna-XM_063566562.1 NC_086374.1  34630047  34756161      -
##  7: LOC134711256 rna-XM_063571761.1 NC_086375.1  31935064  31941257      -
##  8: LOC134712818 rna-XM_063574731.1 NC_086375.1  90867638  90891015      +
##  9: LOC134714536 rna-XM_063575859.1 NC_086376.1   5626113   5639140      +
## 10: LOC134720671 rna-XM_063583078.1 NC_086378.1   6588729   6697712      +
## 11: LOC134724475 rna-XM_063587507.1 NC_086379.1   1585149   1617685      +
## 12: LOC134725187 rna-XM_063588806.1 NC_086379.1  47959226  47965210      -
##                                                                         product
##                                                                          <char>
##  1:        tumor protein p53-inducible protein 11-like%2C transcript variant X4
##  2:               alpha-ketoglutarate-dependent dioxygenase alkB homolog 3-like
##  3:                       mitogen-activated protein kinase kinase kinase 5-like
##  4:                                       GRAM domain-containing protein 4-like
##  5:                                     otoferlin-like%2C transcript variant X1
##  6: receptor-type tyrosine-protein phosphatase N2-like%2C transcript variant X1
##  7:   cancer-related nucleoside-triphosphatase homolog%2C transcript variant X1
##  8:                                                uncharacterized LOC134712818
##  9:                                               coatomer subunit epsilon-like
## 10:                          roundabout homolog 1-like%2C transcript variant X2
## 11:                       uncharacterized LOC134724475%2C transcript variant X1
## 12:                                                  membrane protein BRI3-like
##     n_exon   span
##      <int>  <int>
##  1:      7 144728
##  2:      7   7271
##  3:     42  90785
##  4:     18  30045
##  5:     45 133111
##  6:     21 126114
##  7:      6   6193
##  8:     16  23377
##  9:     11  13027
## 10:     26 108983
## 11:      9  32536
## 12:      4   5984
prim_tx <- primary$tx

exons <- raw[type == "exon" & Parent %in% prim_tx,
             .(gene, tx = Parent, start, end, strand)]
cds   <- raw[type == "CDS"  & Parent %in% prim_tx,
             .(gene, tx = Parent, start, end, strand)]

# attach gene to features via primary transcript map
tx2gene <- setNames(primary$gene, primary$tx)
exons[, gene := tx2gene[tx]]
cds[,   gene := tx2gene[tx]]

cat("exons per primary transcript:\n"); print(exons[, .N, by = gene])
## exons per primary transcript:

##             gene     N
##           <char> <int>
##  1: LOC134690221    18
##  2: LOC134695637    45
##  3: LOC134707074    21
##  4: LOC134711256     6
##  5: LOC134712818    16
##  6: LOC134714536    11
##  7: LOC134720671    26
##  8: LOC134724475     9
##  9: LOC134725187     4
## 10: LOC134685297     7
## 11: LOC134687110     7
## 12: LOC134687290    42

4 DML set (Table 2) and coordinate verification

The 12 DMLs of Table 2 are pulled from myDiff_1055p.tab by matching q-values, then each is checked for containment within its assigned gene span.

# Corrected genic DML set: 12 DMLs, each inside a unique gene (see
# 35a-dml-assignment-audit.R). The two intergenic loci previously assigned to
# LOC134725187 / LOC134711256 are dropped, and the two genic loci on
# NC_086382.1 (LOC134687110 alkB, LOC134687290 MAP3K5/ASK1) are added.
dml <- data.table(
  qvalue       = c(5.77e-14, 1.16e-11, 2.92e-13, 4.17e-14, 1.10e-13,
                   7.20e-13, 8.98e-18, 1.06e-12, 1.32e-13, 2.52e-16,
                   6.02e-14, 5.83e-13),
  chr          = c("NC_086379.1","NC_086373.1","NC_086376.1","NC_086373.1","NC_086374.1",
                   "NC_086378.1","NC_086375.1","NC_086381.1","NC_086375.1","NC_086379.1",
                   "NC_086382.1","NC_086382.1"),
  pos          = c(47961734, 90626338, 5631156, 105503509, 34742951,
                   6633121, 31938079, 21212100, 90876604, 1603830,
                   25952234, 36708761),
  assigned_gene= c("LOC134725187","LOC134690221","LOC134714536","LOC134695637","LOC134707074",
                   "LOC134720671","LOC134711256","LOC134685297","LOC134712818","LOC134724475",
                   "LOC134687110","LOC134687290"),
  meth_diff    = c(56.45, 56.32, 59, -57.86, 58.27,
                   -55.24, -60.69, -56.07, 55.88, -60.82,
                   -55.83, -56.50),
  status_paper = c("Hyper","Hyper","Hyper","Hypo","Hyper",
                   "Hypo","Hypo","Hypo","Hyper","Hypo",
                   "Hypo","Hypo")
)

# direction from the sign of meth.diff (hyper = +, hypo = -)
dml[, direction := factor(ifelse(meth_diff >= 0, "Hyper-methylated", "Hypo-methylated"),
                          levels = c("Hyper-methylated", "Hypo-methylated"))]

# verify each DML against its assigned gene span
gspan <- genes[, .(assigned_gene = gene, g_chr = chr, g_start = start,
                   g_end = end, g_strand = strand, gene_desc)]
dml <- merge(dml, gspan, by = "assigned_gene", all.x = TRUE, sort = FALSE)
dml[, in_gene_span := (chr == g_chr & pos >= g_start & pos <= g_end)]

dml[, .(assigned_gene, chr, pos, meth_diff, direction, status_paper,
        g_start, g_end, in_gene_span)][order(assigned_gene, pos)]
##     assigned_gene         chr       pos meth_diff        direction status_paper
##            <char>      <char>     <num>     <num>           <fctr>       <char>
##  1:  LOC134685297 NC_086381.1  21212100    -56.07  Hypo-methylated         Hypo
##  2:  LOC134687110 NC_086382.1  25952234    -55.83  Hypo-methylated         Hypo
##  3:  LOC134687290 NC_086382.1  36708761    -56.50  Hypo-methylated         Hypo
##  4:  LOC134690221 NC_086373.1  90626338     56.32 Hyper-methylated        Hyper
##  5:  LOC134695637 NC_086373.1 105503509    -57.86  Hypo-methylated         Hypo
##  6:  LOC134707074 NC_086374.1  34742951     58.27 Hyper-methylated        Hyper
##  7:  LOC134711256 NC_086375.1  31938079    -60.69  Hypo-methylated         Hypo
##  8:  LOC134712818 NC_086375.1  90876604     55.88 Hyper-methylated        Hyper
##  9:  LOC134714536 NC_086376.1   5631156     59.00 Hyper-methylated        Hyper
## 10:  LOC134720671 NC_086378.1   6633121    -55.24  Hypo-methylated         Hypo
## 11:  LOC134724475 NC_086379.1   1603830    -60.82  Hypo-methylated         Hypo
## 12:  LOC134725187 NC_086379.1  47961734     56.45 Hyper-methylated        Hyper
##       g_start     g_end in_gene_span
##         <int>     <int>       <lgcl>
##  1:  21116727  21261455         TRUE
##  2:  25951921  25959192         TRUE
##  3:  36708321  36799106         TRUE
##  4:  90602585  90632630         TRUE
##  5: 105380391 105513502         TRUE
##  6:  34630047  34756161         TRUE
##  7:  31935064  31941257         TRUE
##  8:  90867638  90891015         TRUE
##  9:   5626113   5639140         TRUE
## 10:   6588729   6697712         TRUE
## 11:   1585149   1617687         TRUE
## 12:  47959226  47965210         TRUE
cat("DMLs inside their assigned gene span:", sum(dml$in_gene_span), "of", nrow(dml), "\n\n")
## DMLs inside their assigned gene span: 12 of 12
cat("DMLs NOT inside assigned gene span:\n")
## DMLs NOT inside assigned gene span:
print(dml[in_gene_span == FALSE, .(assigned_gene, chr, pos, meth_diff)])
## Empty data.table (0 rows and 4 cols): assigned_gene,chr,pos,meth_diff

Note. This is the corrected DML set (see 35a-dml-assignment-audit.R). All 12 DMLs fall cleanly inside a unique gene body — i.e. 12 DMLs across 12 genes, none bidirectional. An earlier version of the manuscript Table 2 assigned two intergenic loci (NC_086379.1:64017640 and NC_086375.1:43581688, ~16 Mb / ~11 Mb from their listed genes) to LOC134725187 and LOC134711256, making them appear bidirectional, while omitting two genuinely genic loci on NC_086382.1 (LOC134687110 alkB homolog 3-like and LOC134687290 MAP3K5 / ASK1-like). The intergenic loci are dropped here and the two genic loci added.

5 Build the figure

# warm = hyper, cool = hypo
dml_cols <- c("Hyper-methylated" = "#D6604D", "Hypo-methylated" = "#2166AC")
feat_cols <- c("CDS" = "grey25", "UTR (exon)" = "grey75")

short_name <- function(desc) {
  desc <- sub(", transcript variant.*$", "", desc)
  desc
}

build_panel <- function(gid) {
  g  <- genes[gene == gid]
  tx <- primary[gene == gid]
  ex <- exons[gene == gid]
  cd <- cds[gene == gid]
  dd <- dml[assigned_gene == gid & in_gene_span == TRUE]

  # plot coordinates in kb (absolute genomic position)
  x0 <- tx$start / 1e3
  x1 <- tx$end   / 1e3

  ymax_dml <- 1.15
  # invisible layer carrying both DML levels so every panel yields an
  # identical colour guide (patchwork then collapses it to one legend)
  dummy <- data.frame(
    direction = factor(c("Hyper-methylated", "Hypo-methylated"),
                       levels = c("Hyper-methylated", "Hypo-methylated")),
    x = x0, y = 0)

  p <- ggplot() +
    # intron line spanning the primary transcript
    geom_segment(aes(x = x0, xend = x1, y = 0, yend = 0),
                 linewidth = 0.4, colour = "grey40") +
    geom_point(data = dummy, aes(x = x, y = y, colour = direction),
               alpha = 0, shape = 18, size = 3) +
    # exon boxes (UTR height)
    geom_rect(data = ex,
              aes(xmin = start/1e3, xmax = end/1e3, ymin = -0.22, ymax = 0.22,
                  fill = "UTR (exon)"), colour = NA) +
    # CDS boxes (full height, drawn over exons)
    geom_rect(data = cd,
              aes(xmin = start/1e3, xmax = end/1e3, ymin = -0.38, ymax = 0.38,
                  fill = "CDS"), colour = NA)

  # strand direction arrow above the model
  arr_y <- 0.62
  if (tx$strand == "+") {
    p <- p + annotate("segment", x = x0, xend = x1, y = arr_y, yend = arr_y,
                      colour = "grey55", linewidth = 0.3,
                      arrow = arrow(length = unit(0.10, "cm"), type = "closed"))
  } else {
    p <- p + annotate("segment", x = x1, xend = x0, y = arr_y, yend = arr_y,
                      colour = "grey55", linewidth = 0.3,
                      arrow = arrow(length = unit(0.10, "cm"), type = "closed"))
  }

  # DML lollipops
  if (nrow(dd) > 0) {
    p <- p +
      geom_segment(data = dd,
                   aes(x = pos/1e3, xend = pos/1e3, y = 0.38, yend = ymax_dml,
                       colour = direction), linewidth = 0.6, show.legend = FALSE) +
      geom_point(data = dd,
                 aes(x = pos/1e3, y = ymax_dml, colour = direction),
                 size = 3, shape = 18, show.legend = FALSE) +
      geom_text(data = dd,
                aes(x = pos/1e3, y = ymax_dml + 0.22,
                    label = sprintf("%+.1f%%", meth_diff), colour = direction),
                size = 2.7, fontface = "bold", show.legend = FALSE)
  }

  lab <- sprintf("%s  \u2014  %s  (%s strand)",
                 gid, short_name(g$gene_desc), tx$strand)
  # wrap long titles so adjacent column panels don't collide
  lab <- paste(strwrap(lab, width = 52), collapse = "\n")
  span_kb <- (tx$end - tx$start) / 1e3

  p +
    scale_fill_manual(values = feat_cols, name = "Gene structure",
                      breaks = c("CDS","UTR (exon)")) +
    scale_colour_manual(values = dml_cols, name = "DML methylation",
                        drop = FALSE) +
    guides(colour = guide_legend(
      override.aes = list(alpha = 1, shape = 18, size = 3, linetype = 0))) +
    scale_y_continuous(limits = c(-0.7, ymax_dml + 0.45), expand = c(0,0)) +
    labs(title = lab,
         x = sprintf("%s position (kb)   \u2022   transcript span %.1f kb",
                     g$chr, span_kb)) +
    theme_minimal(base_size = 10) +
    theme(
      plot.title = element_text(size = 9.2, face = "bold"),
      axis.title.x = element_text(size = 7.5, colour = "grey30"),
      axis.text.x = element_text(size = 7),
      axis.title.y = element_blank(),
      axis.text.y = element_blank(),
      panel.grid.major.y = element_blank(),
      panel.grid.minor = element_blank(),
      panel.grid.major.x = element_line(colour = "grey92", linewidth = 0.3),
      legend.position = "bottom"
    )
}
# order panels by paper functional grouping
gene_order <- c(
  # Membrane dynamics and vesicle trafficking
  "LOC134725187","LOC134690221","LOC134714536","LOC134695637",
  # Cell signaling and regulation
  "LOC134707074","LOC134720671",
  # Stress response, apoptosis, and nucleic acid metabolism
  "LOC134711256","LOC134685297","LOC134687110","LOC134687290",
  # Uncharacterized
  "LOC134712818","LOC134724475")

panels <- lapply(gene_order, build_panel)

fig <- wrap_plots(panels, ncol = 2) +
  plot_layout(guides = "collect") +
  plot_annotation(
    title = "Gene models harboring differentially methylated loci (DMLs) in Mytilus trossulus mantle",
    subtitle = "High- vs low-\u03a316 PAH sites \u00b7 NCBI GCF_036588685.1 \u00b7 exons (boxes), CDS (dark), introns (line); lollipops mark DMLs (\u0394 methylation %)",
    caption = "DML positions from methylKit (q<0.01, |\u0394meth|\u226555%). Each panel drawn to its own bp scale.",
    theme = theme(plot.title = element_text(face = "bold", size = 13),
                  plot.subtitle = element_text(size = 9, colour = "grey30"))
  ) &
  theme(legend.position = "bottom")

ggsave(file.path(out_dir, "dml_gene_models.png"), fig,
       width = 10, height = 14.4, dpi = 300, bg = "white")
ggsave(file.path(out_dir, "dml_gene_models.pdf"), fig,
       width = 10, height = 14.4, bg = "white")

fig

6 Summary table

# nearest-gene context for the two intergenic loci (computed from the GFF)
nearest_note <- c(
  "NC_086379.1:64017640" = "intergenic; nearest gene LOC134725550 (protein chibby homolog 1-like), ~3.7 kb",
  "NC_086375.1:43581688" = "intergenic; nearest gene LOC134711544 (solute carrier family 40 member 1-like), ~1.0 kb"
)

n_exon_map <- exons[, .N, by = gene]
setnames(n_exon_map, "N", "exon_count")

summary_tab <- dml |>
  merge(n_exon_map, by.x = "assigned_gene", by.y = "gene", all.x = TRUE, sort = FALSE) |>
  merge(primary[, .(assigned_gene = gene, primary_tx = tx)], by = "assigned_gene",
        all.x = TRUE, sort = FALSE)

summary_tab[, gene_span := paste0(g_start, "-", g_end)]
summary_tab[, locus := paste0(chr, ":", pos)]
summary_tab[, note := ifelse(in_gene_span, "DML within gene body",
                             nearest_note[locus])]

summary_out <- summary_tab[order(assigned_gene, pos),
  .(gene_id = assigned_gene, gene_description = gene_desc, chr,
    gene_span, strand = g_strand, primary_tx, exon_count,
    dml_position = pos, qvalue, meth_diff, direction,
    status_paper, in_gene_span, note)]

fwrite(summary_out, file.path(out_dir, "dml_gene_model_summary.tsv"), sep = "\t")
fwrite(summary_out, file.path(out_dir, "dml_gene_model_summary.csv"))
knitr::kable(summary_out)
gene_id gene_description chr gene_span strand primary_tx exon_count dml_position qvalue meth_diff direction status_paper in_gene_span note
LOC134685297 tumor protein p53-inducible protein 11-like NC_086381.1 21116727-21261455 - rna-XM_063544925.1 7 21212100 0 -56.07 Hypo-methylated Hypo TRUE DML within gene body
LOC134687110 alpha-ketoglutarate-dependent dioxygenase alkB homolog 3-like NC_086382.1 25951921-25959192 + rna-XM_063547109.1 7 25952234 0 -55.83 Hypo-methylated Hypo TRUE DML within gene body
LOC134687290 mitogen-activated protein kinase kinase kinase 5-like NC_086382.1 36708321-36799106 + rna-XM_063547445.1 42 36708761 0 -56.50 Hypo-methylated Hypo TRUE DML within gene body
LOC134690221 GRAM domain-containing protein 4-like NC_086373.1 90602585-90632630 + rna-XM_063550200.1 18 90626338 0 56.32 Hyper-methylated Hyper TRUE DML within gene body
LOC134695637 otoferlin-like NC_086373.1 105380391-105513502 - rna-XM_063556955.1 45 105503509 0 -57.86 Hypo-methylated Hypo TRUE DML within gene body
LOC134707074 receptor-type tyrosine-protein phosphatase N2-like NC_086374.1 34630047-34756161 - rna-XM_063566562.1 21 34742951 0 58.27 Hyper-methylated Hyper TRUE DML within gene body
LOC134711256 cancer-related nucleoside-triphosphatase homolog NC_086375.1 31935064-31941257 - rna-XM_063571761.1 6 31938079 0 -60.69 Hypo-methylated Hypo TRUE DML within gene body
LOC134712818 uncharacterized LOC134712818 NC_086375.1 90867638-90891015 + rna-XM_063574731.1 16 90876604 0 55.88 Hyper-methylated Hyper TRUE DML within gene body
LOC134714536 coatomer subunit epsilon-like NC_086376.1 5626113-5639140 + rna-XM_063575859.1 11 5631156 0 59.00 Hyper-methylated Hyper TRUE DML within gene body
LOC134720671 roundabout homolog 1-like NC_086378.1 6588729-6697712 + rna-XM_063583078.1 26 6633121 0 -55.24 Hypo-methylated Hypo TRUE DML within gene body
LOC134724475 uncharacterized LOC134724475 NC_086379.1 1585149-1617687 + rna-XM_063587507.1 9 1603830 0 -60.82 Hypo-methylated Hypo TRUE DML within gene body
LOC134725187 membrane protein BRI3-like NC_086379.1 47959226-47965210 - rna-XM_063588806.1 4 47961734 0 56.45 Hyper-methylated Hyper TRUE DML within gene body

7 Session info

sessionInfo()
## R version 4.3.2 (2023-10-31)
## Platform: aarch64-apple-darwin20 (64-bit)
## Running under: macOS Sonoma 14.7.6
## 
## Matrix products: default
## BLAS:   /Library/Frameworks/R.framework/Versions/4.3-arm64/Resources/lib/libRblas.0.dylib 
## LAPACK: /Library/Frameworks/R.framework/Versions/4.3-arm64/Resources/lib/libRlapack.dylib;  LAPACK version 3.11.0
## 
## locale:
## [1] C
## 
## time zone: America/Los_Angeles
## tzcode source: internal
## 
## attached base packages:
## [1] stats     graphics  grDevices utils     datasets  methods   base     
## 
## other attached packages:
## [1] patchwork_1.3.1   ggplot2_3.5.1     dplyr_1.1.4       data.table_1.16.0
## [5] knitr_1.48       
## 
## loaded via a namespace (and not attached):
##  [1] vctrs_0.6.5       cli_3.6.3         rlang_1.1.4       xfun_0.48        
##  [5] highr_0.11        generics_0.1.3    textshaping_0.4.0 labeling_0.4.3   
##  [9] glue_1.8.0        colorspace_2.1-1  htmltools_0.5.8.1 ragg_1.3.3       
## [13] scales_1.3.0      fansi_1.0.6       rmarkdown_2.28    grid_4.3.2       
## [17] munsell_0.5.1     evaluate_1.0.0    tibble_3.2.1      fastmap_1.2.0    
## [21] yaml_2.3.10       lifecycle_1.0.4   compiler_4.3.2    pkgconfig_2.0.3  
## [25] systemfonts_1.1.0 farver_2.1.2      digest_0.6.37     R6_2.5.1         
## [29] tidyselect_1.2.1  utf8_1.2.4        pillar_1.9.0      magrittr_2.0.3   
## [33] withr_3.0.1       tools_4.3.2       gtable_0.3.6