This is the production-oriented GeneTrackR workflow for a candidate gene or locus. The shorter GeneTrackR core workflow in Getting Started demonstrates the central package objects with fewer branches; this page additionally integrates signal tracks, interval features, browser inspection, explicit QC gates, evidence synthesis, reproducible export, and large-data adaptations. Individual Articles remain the detailed reference for module-specific parameters and interpretation limits.
The central rule is to read each source dataset once, keep the unmodified source objects, and derive locus-specific objects from them. The same annotation, VCF, signal, phenotype, region definition, and sample identifiers should then flow through downstream steps rather than being silently rebuilt with slightly different boundaries or sample sets.
The demo workflow uses GeneA and follows ten steps:
Use one explicit set of source files at the start of the analysis:
library(GeneTrackR)
gp_file <- system.file(
"extdata",
"gtr_demo.genePredExt",
package = "GeneTrackR"
)
feature_file <- system.file(
"extdata",
"gtr_demo_features.bed",
package = "GeneTrackR"
)
vcf_file <- system.file(
"extdata",
"gtr_demo_variants.vcf",
package = "GeneTrackR"
)
pheno_file <- system.file(
"extdata",
"gtr_demo_pheno.tsv",
package = "GeneTrackR"
)
signal_files <- system.file(
"extdata",
c(
"gtr_demo_rnaseq_plus.bedgraph",
"gtr_demo_rnaseq_minus.bedgraph",
"gtr_demo_riboseq_plus.bedgraph",
"gtr_demo_riboseq_minus.bedgraph"
),
package = "GeneTrackR"
)Read the objects once:
gp <- read_genepred(
gp_file,
format = "genePredExt",
verbose = FALSE,
progress = FALSE
)
features <- read_bed(
feature_file,
verbose = FALSE,
progress = FALSE
)
vcf <- read_vcf(
vcf_file,
mode = "memory",
keep_genotype = TRUE,
verbose = FALSE,
progress = FALSE
)
pheno <- read_pheno(
pheno_file,
verbose = FALSE,
progress = FALSE
)
signal_all <- read_bwg(
signal_files,
format = "bedgraph",
sample_names = c(
"RNA_seq_plus",
"RNA_seq_minus",
"Ribo_seq_plus",
"Ribo_seq_minus"
),
strand = c("+", "-", "+", "-"),
mode = "memory",
verbose = FALSE
)For real projects, keep these source objects unchanged and create filtered/retrieved objects for each downstream question. This makes it clear which transformations were applied at each step.
Inspect the annotation and VCF before defining haplotypes or LD regions:
validate_feature(gp)
#> $invalid_records
#> Empty data.table (0 rows and 2 cols): row_id,reason
#>
#> $invalid_summary
#> Empty data.table (0 rows and 2 cols): reason,N
#>
#> $warnings
#> character(0)
validate_vcf(vcf)
#> $invalid_records
#> Empty data.table (0 rows and 2 cols): row_id,reason
#>
#> $invalid_summary
#> Empty data.table (0 rows and 2 cols): reason,N
#>
#> $warnings
#> character(0)
summary_feature(gp)
#> chrom type n_features median_feature_length
#> <char> <char> <int> <num>
#> 1: chr1 3UTR 11 200
#> 2: chr1 5UTR 11 200
#> 3: chr1 CDS 37 900
#> 4: chr1 exon 43 1000
#> 5: chr1 gene 10 9000
#> 6: chr1 start_codon 11 3
#> 7: chr1 stop_codon 11 3
#> 8: chr1 transcript 12 9000
#> 9: chr2 3UTR 11 300
#> 10: chr2 5UTR 11 300
#> 11: chr2 CDS 33 900
#> 12: chr2 exon 39 1000
#> 13: chr2 gene 10 8500
#> 14: chr2 start_codon 11 3
#> 15: chr2 stop_codon 11 3
#> 16: chr2 transcript 12 9000
summary_vcf(vcf)
#> chrom variant_type n_variants
#> <char> <char> <int>
#> 1: chr1 DEL 1
#> 2: chr1 INS 2
#> 3: chr1 SNP 33
#> 4: chr2 SNP 20
summary_pheno(pheno)
#> trait type sample_n missing_n missing_rate unique_n min
#> <char> <char> <int> <int> <num> <int> <num>
#> 1: seed_weight numeric 36 0 0 32 18.80
#> 2: protein_content numeric 36 0 0 18 37.58
#> 3: plant_height numeric 36 0 0 36 98.20
#> 4: flowering_time numeric 36 0 0 5 43.00
#> 5: flower_color categorical 36 0 0 2 NA
#> mean median max
#> <num> <num> <num>
#> 1: 25 25 31.20
#> 2: 41 41 44.42
#> 3: 104 104 109.80
#> 4: 45 45 47.00
#> 5: NA NA NA
summary_bwg(signal_all)
#> sample_id sum_signal mean_signal max_signal covered_bases
#> <char> <num> <num> <num> <int>
#> 1: RNA_seq_plus 632305.6 13.715957 33.264 46100
#> 2: RNA_seq_minus 361448.2 12.463731 28.512 29000
#> 3: Ribo_seq_plus 83318.0 4.124858 21.000 20199
#> 4: Ribo_seq_minus 45395.0 3.977133 19.000 11414The most important consistency checks are:
The demo phenotype order is intentionally different from the VCF
sample order. Downstream phenotype functions align records by
sample_id, not by row position.
Start by viewing the candidate gene in its genomic context.
plot_tracks() can combine the gene model, RNA/Ribo signal,
BED-like features, and VCF variants:
browser_geneA <- plot_tracks(
annotation = gp,
signal = signal_all,
features = features,
variants = vcf,
gene_id = "GeneA",
samples = c("RNA_seq_plus", "Ribo_seq_plus"),
strand = "+",
signal_type = "bar",
feature_color_by = "auto",
feature_max_legend_levels = 5,
direction_mode = "transcript",
text_size = 9
)
#> [GeneTrackR] Retrieved variants: 11.
browser_geneAAll general plotting palettes default to Paired;
plot_ld_block() is the deliberate exception and defaults to
the sequential Reds palette. For transcript-centered
Ribo-seq inspection, supply transcript_id to
plot_tracks() or use plot_signal_transcript()
so reading-frame information can be displayed explicitly.
Inspect the exact variants that will define the GeneA haplotypes:
geneA_variants <- retrieve_vcf(
vcf,
annotation = gp,
gene_id = "GeneA",
as = "data.table",
verbose = FALSE,
progress = FALSE
)
geneA_variants[, .(
variant_id,
chrom,
pos,
ref,
alt,
variant_type
)]
#> variant_id chrom pos ref alt variant_type
#> <char> <char> <int> <char> <char> <char>
#> 1: varA01 chr1 12340250 A G SNP
#> 2: varA02 chr1 12340600 T C SNP
#> 3: varA03 chr1 12342550 C G SNP
#> 4: varLD01 chr1 12342620 G A SNP
#> 5: varLD02 chr1 12342710 A T SNP
#> 6: varLD03 chr1 12342805 C T SNP
#> 7: varLD04 chr1 12342920 G C SNP
#> 8: varLD05 chr1 12343040 T G SNP
#> 9: varLD06 chr1 12343180 A C SNP
#> 10: varA04 chr1 12344500 A ATG INS
#> 11: varA05 chr1 12351050 ATG A DELThe canonical GeneA gene body contains 11 demo variants. Do not silently add flanking variants to the primary haplotype definition: the upstream demo variant contains missing/heterogeneous genotypes and intentionally changes the resulting haplotype structure.
Use the gene body and allele-string representation for the main biological haplotype display:
hap_gene <- hap_gene_variant(
vcf,
annotation = gp,
gene_id = "GeneA",
genotype_mode = "string"
)
#> [GeneTrackR] Retrieved variants: 11.
hap_gene$haplotypes[, c(
"hap_id",
"sample_n",
"samples"
), with = FALSE]
#> Key: <hap_id>
#> hap_id sample_n samples
#> <char> <int> <char>
#> 1: Hap1 9 S10;S11;S12;S13;S14;S15;S16;S17;S18
#> 2: Hap2 9 S01;S02;S03;S04;S05;S06;S07;S08;S09
#> 3: Hap3 9 S19;S20;S21;S22;S23;S24;S25;S26;S27
#> 4: Hap4 9 S28;S29;S30;S31;S32;S33;S34;S35;S36The deterministic demo contains four balanced haplotypes with nine samples each.
Plot their variant patterns together with the gene structure:
hap_gene_figure <- plot_hap_variant(
hap_gene,
annotation = gp,
min_hap_samples = 3,
variant_label = "pos",
show_reference_row = TRUE,
text_size = 9
)
hap_gene_figureKeep the full HapVariant object. Its sample assignments
and genotype tables are the input for phenotype association, refinement,
and variant-effect analysis.
Test the original GeneA haplotypes against a trait with a designed haplotype effect:
hap_seed <- plot_hap_pheno(
hap_gene,
phenotype = pheno,
traits = "seed_weight",
min_hap_samples = 3,
test_method = "t.test",
p_adjust = "BH",
p_value_type = "adjusted",
text_size = 9
)
hap_seed$figurehap_seed$pvalue
#> trait group1 group2 p_value p_adj method
#> <char> <char> <char> <num> <num> <char>
#> 1: seed_weight Hap2 Hap1 7.740671e-05 7.740671e-05 t.test
#> 2: seed_weight Hap2 Hap3 1.344894e-14 8.069366e-14 t.test
#> 3: seed_weight Hap2 Hap4 4.343207e-13 8.686413e-13 t.test
#> 4: seed_weight Hap1 Hap3 4.343207e-13 8.686413e-13 t.test
#> 5: seed_weight Hap1 Hap4 3.540311e-11 5.310467e-11 t.test
#> 6: seed_weight Hap3 Hap4 7.740671e-05 7.740671e-05 t.testFor a specific natural variant, use the VCF genotype directly. The
demo varA03 separates the two major GeneA
genotype/phenotype clusters for protein_content:
varA03_protein <- plot_variant_pheno(
variant = vcf,
phenotype = pheno,
variant_id = "varA03",
traits = "protein_content",
genotype_mode = "code",
min_group_samples = 3,
p_adjust = "BH",
p_value_type = "adjusted",
text_size = 9
)
varA03_protein$figureThese functions return structured result objects. Retain
$pvalue, $summary, and $plot_data
together with $figure rather than saving only the visual
result.
The primary demo LD interval contains 12 SNPs. Six form a perfect
high-LD core and the remaining variants progressively decorrelate,
producing high, intermediate, and low r2 values:
ld_gradient <- compute_ld_block(
vcf,
chrom = "chr1",
start = 12342620,
end = 12355500,
variant_type = "snp",
method = "r2",
verbose = FALSE
)
ld_gradient <- plot_ld_block(
ld_gradient,
annotation = gp,
show_region = TRUE,
connect_region = TRUE,
show_variant_marker = TRUE,
show_variant_labels = FALSE,
font = 9
)
ld_gradient$figureInspect the numerical result as well as the heatmap:
ld_gradient$data[, .(
variant_i,
variant_j,
distance_bp,
r2
)]
#> variant_i variant_j distance_bp r2
#> <char> <char> <int> <num>
#> 1: varLD01 varLD02 90 1.00000000
#> 2: varLD01 varLD03 185 1.00000000
#> 3: varLD01 varLD04 300 1.00000000
#> 4: varLD01 varLD05 420 1.00000000
#> 5: varLD01 varLD06 560 1.00000000
#> 6: varLD01 varLD07 9880 0.79012346
#> 7: varLD01 varLD08 10480 0.60493827
#> 8: varLD01 varLD09 11080 0.44444444
#> 9: varLD01 varLD10 11680 0.25077399
#> 10: varLD01 varLD11 12280 0.11111111
#> 11: varLD01 varLD12 12880 0.00000000
#> 12: varLD02 varLD03 95 1.00000000
#> 13: varLD02 varLD04 210 1.00000000
#> 14: varLD02 varLD05 330 1.00000000
#> 15: varLD02 varLD06 470 1.00000000
#> 16: varLD02 varLD07 9790 0.79012346
#> 17: varLD02 varLD08 10390 0.60493827
#> 18: varLD02 varLD09 10990 0.44444444
#> 19: varLD02 varLD10 11590 0.25077399
#> 20: varLD02 varLD11 12190 0.11111111
#> 21: varLD02 varLD12 12790 0.00000000
#> 22: varLD03 varLD04 115 1.00000000
#> 23: varLD03 varLD05 235 1.00000000
#> 24: varLD03 varLD06 375 1.00000000
#> 25: varLD03 varLD07 9695 0.79012346
#> 26: varLD03 varLD08 10295 0.60493827
#> 27: varLD03 varLD09 10895 0.44444444
#> 28: varLD03 varLD10 11495 0.25077399
#> 29: varLD03 varLD11 12095 0.11111111
#> 30: varLD03 varLD12 12695 0.00000000
#> 31: varLD04 varLD05 120 1.00000000
#> 32: varLD04 varLD06 260 1.00000000
#> 33: varLD04 varLD07 9580 0.79012346
#> 34: varLD04 varLD08 10180 0.60493827
#> 35: varLD04 varLD09 10780 0.44444444
#> 36: varLD04 varLD10 11380 0.25077399
#> 37: varLD04 varLD11 11980 0.11111111
#> 38: varLD04 varLD12 12580 0.00000000
#> 39: varLD05 varLD06 140 1.00000000
#> 40: varLD05 varLD07 9460 0.79012346
#> 41: varLD05 varLD08 10060 0.60493827
#> 42: varLD05 varLD09 10660 0.44444444
#> 43: varLD05 varLD10 11260 0.25077399
#> 44: varLD05 varLD11 11860 0.11111111
#> 45: varLD05 varLD12 12460 0.00000000
#> 46: varLD06 varLD07 9320 0.79012346
#> 47: varLD06 varLD08 9920 0.60493827
#> 48: varLD06 varLD09 10520 0.44444444
#> 49: varLD06 varLD10 11120 0.25077399
#> 50: varLD06 varLD11 11720 0.11111111
#> 51: varLD06 varLD12 12320 0.00000000
#> 52: varLD07 varLD08 600 0.79012346
#> 53: varLD07 varLD09 1200 0.60493827
#> 54: varLD07 varLD10 1800 0.37461300
#> 55: varLD07 varLD11 2400 0.19753086
#> 56: varLD07 varLD12 3000 0.01234568
#> 57: varLD08 varLD09 600 0.79012346
#> 58: varLD08 varLD10 1200 0.52321981
#> 59: varLD08 varLD11 1800 0.30864198
#> 60: varLD08 varLD12 2400 0.04938272
#> 61: varLD09 varLD10 600 0.69659443
#> 62: varLD09 varLD11 1200 0.44444444
#> 63: varLD09 varLD12 1800 0.11111111
#> 64: varLD10 varLD11 600 0.69659443
#> 65: varLD10 varLD12 1200 0.25077399
#> 66: varLD11 varLD12 600 0.44444444
#> variant_i variant_j distance_bp r2
#> <char> <char> <int> <num>GeneTrackR calculates pairwise LD; it does not automatically declare a biological block boundary from a hard-coded threshold. Define the downstream interval using the lead variant, LD pattern, gene context, and the biological question.
The GeneA genotype structure contains two close haplotype pairs:
Hap1/Hap2 and Hap3/Hap4. Their
protein_content values follow the same two-cluster
structure, making this trait appropriate for phenotype-guided
refinement:
refined_protein <- refine_haplotype(
hap_gene,
phenotype = pheno,
traits = "protein_content",
min_hap_samples = 3,
test_method = "t.test",
p_adjust = "BH",
alpha = 0.05,
effect_threshold = 0.5
)
refined_protein$haplotype_map
#> hap_id refined_hap_id refined_key protein_content
#> <char> <char> <char> <char>
#> 1: Hap1 RHap1 G1 G1
#> 2: Hap2 RHap1 G1 G1
#> 3: Hap3 RHap2 G2 G2
#> 4: Hap4 RHap2 G2 G2
refined_protein$refined_haplotypes
#> hap_id original_hap_n original_hap_ids sample_n
#> <char> <int> <char> <int>
#> 1: RHap1 2 Hap1;Hap2 18
#> 2: RHap2 2 Hap3;Hap4 18
#> samples
#> <char>
#> 1: S10;S11;S12;S13;S14;S15;S16;S17;S18;S01;S02;S03;S04;S05;S06;S07;S08;S09
#> 2: S19;S20;S21;S22;S23;S24;S25;S26;S27;S28;S29;S30;S31;S32;S33;S34;S35;S36
#> varA01 varA02 varA03 varLD01 varLD02 varLD03 varLD04 varLD05 varLD06 varA04
#> <char> <char> <char> <char> <char> <char> <char> <char> <char> <char>
#> 1: A mixed C G A C G T A A
#> 2: G mixed G A T T C G C i3
#> varA05
#> <char>
#> 1: i3
#> 2: mixedThe expected deterministic grouping is:
Hap1 + Hap2 -> refined group 1
Hap3 + Hap4 -> refined group 2
Inspect the decision evidence rather than reporting only the final group number:
refined_protein$pairwise_test
#> Index: <trait>
#> trait group2 group1 p_value p_adj method mean_group1
#> <char> <char> <char> <num> <num> <char> <num>
#> 1: protein_content Hap1 Hap2 1.000000e+00 1.000000e+00 t.test 38
#> 2: protein_content Hap3 Hap2 2.707879e-18 4.061818e-18 t.test 38
#> 3: protein_content Hap4 Hap2 2.707879e-18 4.061818e-18 t.test 38
#> 4: protein_content Hap3 Hap1 2.707879e-18 4.061818e-18 t.test 38
#> 5: protein_content Hap4 Hap1 2.707879e-18 4.061818e-18 t.test 38
#> 6: protein_content Hap4 Hap3 1.000000e+00 1.000000e+00 t.test 44
#> mean_group2 mean_diff abs_mean_diff can_merge
#> <num> <num> <num> <lgcl>
#> 1: 38 0 0 TRUE
#> 2: 44 6 6 FALSE
#> 3: 44 6 6 FALSE
#> 4: 44 6 6 FALSE
#> 5: 44 6 6 FALSE
#> 6: 44 0 0 TRUE
refined_protein$phenotype_summary
#> Index: <trait>
#> trait hap_id sample_n mean_value median_value sd_value min_value
#> <char> <char> <int> <num> <num> <num> <num>
#> 1: protein_content Hap2 9 38 38 0.282179 37.58
#> 2: protein_content Hap1 9 38 38 0.282179 37.58
#> 3: protein_content Hap3 9 44 44 0.282179 43.58
#> 4: protein_content Hap4 9 44 44 0.282179 43.58
#> max_value
#> <num>
#> 1: 38.42
#> 2: 38.42
#> 3: 44.42
#> 4: 44.42A non-significant pairwise test alone is not proof of biological
equivalence. effect_threshold adds an explicit
phenotype-distance requirement and should be chosen in the context of
the trait scale and experimental precision.
For interpretable two-group effect direction, rebuild the same GeneA region in binary REF/ALT-presence mode:
hap_effect <- hap_gene_variant(
vcf,
annotation = gp,
gene_id = "GeneA",
genotype_mode = "code"
)
#> [GeneTrackR] Retrieved variants: 11.
effect_protein <- plot_variant_effect(
hap_effect,
phenotype = pheno,
traits = "protein_content",
min_group_samples = 3,
test_method = "t.test",
p_adjust = "BH",
effect_type = "absolute",
top_n = 10,
variant_label = "variant_id",
x_axis = "position",
text_size = 9
)
effect_protein$figureRank the numerical results directly:
protein_candidates <- effect_protein$effect[
trait == "protein_content"
][order(-abs_effect, p_adj)]
protein_candidates[, .(
variant_id,
effect,
abs_effect,
p_adj
)]
#> variant_id effect abs_effect p_adj
#> <char> <num> <num> <num>
#> 1: varA01 6 6 2.455019e-37
#> 2: varA03 6 6 2.455019e-37
#> 3: varLD01 6 6 2.455019e-37
#> 4: varLD02 6 6 2.455019e-37
#> 5: varLD03 6 6 2.455019e-37
#> 6: varLD04 6 6 2.455019e-37
#> 7: varLD05 6 6 2.455019e-37
#> 8: varLD06 6 6 2.455019e-37
#> 9: varA04 6 6 2.455019e-37
#> 10: varA05 4 4 1.309843e-07
#> 11: varA02 0 0 1.000000e+00Several GeneA variants share the same large effect because they
encode the same Hap1/Hap2 versus Hap3/Hap4
genotype partition. A large phenotype effect therefore identifies an
associated variant set, not necessarily a unique causal
variant.
The preferred interpretation combines all preceding evidence:
variant effect
+ pairwise LD
+ gene/feature annotation
+ single-variant phenotype association
+ haplotype structure
+ phenotype-guided refinement
-> candidate variants for biological validation
At the end of the analysis, retain the main objects together so the result can be reopened without reconstructing the workflow:
analysis_bundle <- list(
annotation = gp,
features = features,
haplotype = hap_gene,
haplotype_pheno = hap_seed,
variant_pheno = varA03_protein,
ld = ld_gradient,
refined = refined_protein,
variant_effect = effect_protein
)
saveRDS(
analysis_bundle,
file = file.path(tempdir(), "GeneA.GeneTrackR_workflow.rds")
)Use the export module for a complete project directory containing standard genomic tracks, PDF/PNG figures, tabular results, optional Excel workbooks, complete RDS objects, and session information.
For large real-world datasets, adapt the same workflow rather than changing its logic:
read_vcf(mode = "lazy") and always query a defined genomic
interval before LD or haplotype analysis;bin_size, heatmap_bin_size, or
heatmap_max_bins for long/high-density signal regions;hap_gene_variant() and
hap_region_variant() for new code;
hap_variant() remains a compatibility wrapper;LDTrack store figures inside structured result
objects.The complete recommended chain is therefore:
annotation + signal + VCF + phenotype
-> locus inspection
-> gene/region variant definition
-> haplotype construction
-> phenotype association
-> LD interpretation
-> phenotype-guided refinement
-> variant-effect prioritization
-> biological candidate selection
-> reproducible export
Package documentation: https://renscq.github.io/GeneTrackR/. ## Installation
After Bioconductor acceptance, install GeneTrackR with
BiocManager:
if (!requireNamespace("BiocManager", quietly = TRUE)) {
install.packages("BiocManager")
}
BiocManager::install("GeneTrackR")
library(GeneTrackR)The development version remains available from the GeneTrackR GitHub repository.
sessionInfo()
#> R version 4.6.1 (2026-06-24)
#> Platform: x86_64-pc-linux-gnu
#> Running under: Ubuntu 26.04.1 LTS
#>
#> Matrix products: default
#> BLAS: /usr/lib/x86_64-linux-gnu/openblas-pthread/libblas.so.3
#> LAPACK: /usr/lib/x86_64-linux-gnu/openblas-pthread/libopenblasp-r0.3.32.so; LAPACK version 3.12.0
#>
#> locale:
#> [1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C
#> [3] LC_TIME=en_US.UTF-8 LC_COLLATE=en_US.UTF-8
#> [5] LC_MONETARY=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8
#> [7] LC_PAPER=en_US.UTF-8 LC_NAME=C
#> [9] LC_ADDRESS=C LC_TELEPHONE=C
#> [11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C
#>
#> time zone: Etc/UTC
#> tzcode source: system (glibc)
#>
#> attached base packages:
#> [1] stats graphics grDevices utils datasets methods base
#>
#> other attached packages:
#> [1] GeneTrackR_0.99.2 rmarkdown_2.32
#>
#> loaded via a namespace (and not attached):
#> [1] gtable_0.3.6 jsonlite_2.0.0 crayon_1.5.3
#> [4] compiler_4.6.1 Biostrings_2.81.9 bitops_1.1-0
#> [7] Rsamtools_2.29.0 GenomicRanges_1.65.4 parallel_4.6.1
#> [10] jquerylib_0.1.4 IRanges_2.47.5 Seqinfo_1.3.2
#> [13] scales_1.4.0 BiocParallel_1.47.0 yaml_2.3.12
#> [16] fastmap_1.2.0 XVector_0.53.0 ggplot2_4.0.3
#> [19] R6_2.6.1 patchwork_1.3.2 labeling_0.4.3
#> [22] generics_0.1.4 knitr_1.52 BiocGenerics_0.59.12
#> [25] maketools_1.3.2 bslib_0.12.0 RColorBrewer_1.1-3
#> [28] rlang_1.3.0 cachem_1.1.0 xfun_0.61
#> [31] sass_0.4.10 sys_3.4.3 S7_0.2.2
#> [34] otel_0.2.0 cli_3.6.6 withr_3.0.3
#> [37] digest_0.6.39 grid_4.6.1 lifecycle_1.0.5
#> [40] S4Vectors_0.51.10 vctrs_0.7.3 evaluate_1.0.5
#> [43] glue_1.8.1 data.table_1.18.6.1 farver_2.1.2
#> [46] codetools_0.2-20 buildtools_1.0.0 stats4_4.6.1
#> [49] tools_4.6.1 htmltools_0.5.9