Haplotype analysis

Introduction

library(GeneTrackR)

GeneTrackR builds haplotypes directly from VCF sample genotypes and keeps the complete analysis state in a HapVariant object. The stable workflow is to define the biological interval once, construct one canonical haplotype object, inspect the retained variants and samples, and pass that same object to phenotype association, refinement, and variant-effect analysis.

This article follows that object-centered workflow rather than rebuilding genotype matrices for each downstream task.

This article follows one continuous workflow:

  1. prepare VCF genotype data and gene annotation;
  2. build the primary gene-body haplotypes;
  3. inspect the HapVariant object and its core tables;
  4. choose an appropriate genotype representation;
  5. control missing-genotype filtering;
  6. construct transcript, flanking-region, or custom-region haplotypes;
  7. draw the haplotype-variant figure;
  8. pass the haplotype object to downstream phenotype and refinement workflows.

The main example uses the designed GeneA locus. Its gene body contains 11 variants and 36 complete samples that form four balanced haplotypes with nine samples per haplotype.

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.

Step 1. Prepare VCF genotypes and annotation

Locate and read the bundled demo files:

vcf_file <- system.file(
  "extdata",
  "gtr_demo_variants.vcf",
  package = "GeneTrackR"
)

gp_file <- system.file(
  "extdata",
  "gtr_demo.genePredExt",
  package = "GeneTrackR"
)

vcf <- read_vcf(
  vcf_file,
  mode = "memory",
  keep_genotype = TRUE,
  verbose = FALSE,
  progress = FALSE
)

gp <- read_genepred(
  gp_file,
  format = "genePredExt",
  verbose = FALSE,
  progress = FALSE
)

Haplotype construction requires VCF sample genotype columns. If a VCF was previously read with keep_genotype = FALSE, read it again with keep_genotype = TRUE before calling the haplotype functions.

For indexed large VCF files, the input can also be a lazy VariantTrack or a VCF file path. GeneTrackR retrieves only the requested haplotype region before constructing the genotype matrix.

Step 2. Build the primary GeneA haplotypes

For gene- or transcript-defined analysis, use hap_gene_variant(). The primary GeneA workflow intentionally uses the gene body only so that the haplotype definition is based on variants inside the annotated locus:

hap_gene <- hap_gene_variant(
  vcf = vcf,
  annotation = gp,
  gene_id = "GeneA",
  genotype_mode = "string"
)
#> [GeneTrackR] Retrieved variants: 11.

hap_gene
#> <HapVariant>
#>   region    : chr1:12340001-12352000
#>   variants  : 11
#>   samples   : 36
#>   haplotypes: 4

The demo is designed so that this call contains:

  • 11 GeneA gene-body variants;
  • 36 retained samples;
  • four haplotype groups;
  • nine samples in each haplotype group.

The four genotype patterns are intentionally hierarchical: Hap1/Hap2 are the closest pair, Hap3/Hap4 are the second closest pair, and cross-pair comparisons differ at many more GeneA variants. This structure is used later by the phenotype-refinement demo.

Check these values directly from the returned object rather than assuming a fixed number for real datasets:

hap_gene$meta
#> $genotype_mode
#> [1] "string"
#> 
#> $missing_genotype
#> [1] NA
#> 
#> $min_variant_number
#> [1] 11
#> 
#> $sample_n
#> [1] 36
#> 
#> $variant_n
#> [1] 11
#> 
#> $haplotype_n
#> [1] 4
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;S36

hap_id is assigned from the observed genotype patterns after grouping. Treat the genotype pattern and sample membership as the biological result; do not assume that Hap1, Hap2, and so on have the same biological meaning across independently constructed regions.

Step 3. Inspect the HapVariant object

A HapVariant keeps the complete state needed by downstream GeneTrackR functions:

hap_gene$region
#> $locator
#> [1] "gene"
#> 
#> $id
#> [1] "GeneA"
#> 
#> $chrom
#> [1] "chr1"
#> 
#> $start
#> [1] 12340001
#> 
#> $end
#> [1] 12352000
#> 
#> $core_start
#> [1] 12340001
#> 
#> $core_end
#> [1] 12352000
#> 
#> $upstream
#> [1] 0
#> 
#> $downstream
#> [1] 0
#> 
#> $strand
#> [1] "+"
#> 
#> $strand_aware
#> [1] TRUE
hap_gene$variants
#>      chrom      pos variant_id    ref    alt  qual filter
#>     <char>    <int>     <char> <char> <char> <num> <char>
#>  1:   chr1 12340250     varA01      A      G    60   PASS
#>  2:   chr1 12340600     varA02      T      C    60   PASS
#>  3:   chr1 12342550     varA03      C      G    60   PASS
#>  4:   chr1 12342620    varLD01      G      A    60   PASS
#>  5:   chr1 12342710    varLD02      A      T    60   PASS
#>  6:   chr1 12342805    varLD03      C      T    60   PASS
#>  7:   chr1 12342920    varLD04      G      C    60   PASS
#>  8:   chr1 12343040    varLD05      T      G    60   PASS
#>  9:   chr1 12343180    varLD06      A      C    60   PASS
#> 10:   chr1 12344500     varA04      A    ATG    60   PASS
#> 11:   chr1 12351050     varA05    ATG      A    60   PASS
#>                                   info FORMAT    S01    S02    S03    S04
#>                                 <char> <char> <char> <char> <char> <char>
#>  1:        ROLE=core_haplotype,high_ld     GT    0/0    0/0    0/0    0/0
#>  2:                ROLE=core_haplotype     GT    0/0    0/0    0/0    0/0
#>  3: ROLE=core_haplotype,protein_effect     GT    0/0    0/0    0/0    0/0
#>  4:           ROLE=high_ld,ld_gradient     GT    0/0    0/0    0/0    0/0
#>  5:           ROLE=high_ld,ld_gradient     GT    0/0    0/0    0/0    0/0
#>  6:           ROLE=high_ld,ld_gradient     GT    0/0    0/0    0/0    0/0
#>  7:           ROLE=high_ld,ld_gradient     GT    0/0    0/0    0/0    0/0
#>  8:           ROLE=high_ld,ld_gradient     GT    0/0    0/0    0/0    0/0
#>  9:           ROLE=high_ld,ld_gradient     GT    0/0    0/0    0/0    0/0
#> 10:          ROLE=core_haplotype,indel     GT    0/0    0/0    0/0    0/0
#> 11:          ROLE=core_haplotype,indel     GT    0/0    0/0    0/0    0/0
#>        S05    S06    S07    S08    S09    S10    S11    S12    S13    S14
#>     <char> <char> <char> <char> <char> <char> <char> <char> <char> <char>
#>  1:    0/0    0/0    0/0    0/0    0/0    0/0    0/0    0/0    0/0    0/0
#>  2:    0/0    0/0    0/0    0/0    0/0    1/1    1/1    1/1    1/1    1/1
#>  3:    0/0    0/0    0/0    0/0    0/0    0/0    0/0    0/0    0/0    0/0
#>  4:    0/0    0/0    0/0    0/0    0/0    0/0    0/0    0/0    0/0    0/0
#>  5:    0/0    0/0    0/0    0/0    0/0    0/0    0/0    0/0    0/0    0/0
#>  6:    0/0    0/0    0/0    0/0    0/0    0/0    0/0    0/0    0/0    0/0
#>  7:    0/0    0/0    0/0    0/0    0/0    0/0    0/0    0/0    0/0    0/0
#>  8:    0/0    0/0    0/0    0/0    0/0    0/0    0/0    0/0    0/0    0/0
#>  9:    0/0    0/0    0/0    0/0    0/0    0/0    0/0    0/0    0/0    0/0
#> 10:    0/0    0/0    0/0    0/0    0/0    0/0    0/0    0/0    0/0    0/0
#> 11:    0/0    0/0    0/0    0/0    0/0    0/0    0/0    0/0    0/0    0/0
#>        S15    S16    S17    S18    S19    S20    S21    S22    S23    S24
#>     <char> <char> <char> <char> <char> <char> <char> <char> <char> <char>
#>  1:    0/0    0/0    0/0    0/0    1/1    1/1    1/1    1/1    1/1    1/1
#>  2:    1/1    1/1    1/1    1/1    1/1    1/1    1/1    1/1    1/1    1/1
#>  3:    0/0    0/0    0/0    0/0    1/1    1/1    1/1    1/1    1/1    1/1
#>  4:    0/0    0/0    0/0    0/0    1/1    1/1    1/1    1/1    1/1    1/1
#>  5:    0/0    0/0    0/0    0/0    1/1    1/1    1/1    1/1    1/1    1/1
#>  6:    0/0    0/0    0/0    0/0    1/1    1/1    1/1    1/1    1/1    1/1
#>  7:    0/0    0/0    0/0    0/0    1/1    1/1    1/1    1/1    1/1    1/1
#>  8:    0/0    0/0    0/0    0/0    1/1    1/1    1/1    1/1    1/1    1/1
#>  9:    0/0    0/0    0/0    0/0    1/1    1/1    1/1    1/1    1/1    1/1
#> 10:    0/0    0/0    0/0    0/0    1/1    1/1    1/1    1/1    1/1    1/1
#> 11:    0/0    0/0    0/0    0/0    0/0    0/0    0/0    0/0    0/0    0/0
#>        S25    S26    S27    S28    S29    S30    S31    S32    S33    S34
#>     <char> <char> <char> <char> <char> <char> <char> <char> <char> <char>
#>  1:    1/1    1/1    1/1    1/1    1/1    1/1    1/1    1/1    1/1    1/1
#>  2:    1/1    1/1    1/1    0/0    0/0    0/0    0/0    0/0    0/0    0/0
#>  3:    1/1    1/1    1/1    1/1    1/1    1/1    1/1    1/1    1/1    1/1
#>  4:    1/1    1/1    1/1    1/1    1/1    1/1    1/1    1/1    1/1    1/1
#>  5:    1/1    1/1    1/1    1/1    1/1    1/1    1/1    1/1    1/1    1/1
#>  6:    1/1    1/1    1/1    1/1    1/1    1/1    1/1    1/1    1/1    1/1
#>  7:    1/1    1/1    1/1    1/1    1/1    1/1    1/1    1/1    1/1    1/1
#>  8:    1/1    1/1    1/1    1/1    1/1    1/1    1/1    1/1    1/1    1/1
#>  9:    1/1    1/1    1/1    1/1    1/1    1/1    1/1    1/1    1/1    1/1
#> 10:    1/1    1/1    1/1    1/1    1/1    1/1    1/1    1/1    1/1    1/1
#> 11:    0/0    0/0    0/0    1/1    1/1    1/1    1/1    1/1    1/1    1/1
#>        S35    S36 variant_type    start      end
#>     <char> <char>       <char>    <int>    <int>
#>  1:    1/1    1/1          SNP 12340250 12340250
#>  2:    0/0    0/0          SNP 12340600 12340600
#>  3:    1/1    1/1          SNP 12342550 12342550
#>  4:    1/1    1/1          SNP 12342620 12342620
#>  5:    1/1    1/1          SNP 12342710 12342710
#>  6:    1/1    1/1          SNP 12342805 12342805
#>  7:    1/1    1/1          SNP 12342920 12342920
#>  8:    1/1    1/1          SNP 12343040 12343040
#>  9:    1/1    1/1          SNP 12343180 12343180
#> 10:    1/1    1/1          INS 12344500 12344500
#> 11:    1/1    1/1          DEL 12351050 12351050
hap_gene$genotype_long
#>      sample_id  chrom      pos variant_id    ref    alt variant_type genotype
#>         <char> <char>    <int>     <char> <char> <char>       <char>   <char>
#>   1:       S01   chr1 12340250     varA01      A      G          SNP        A
#>   2:       S01   chr1 12340600     varA02      T      C          SNP        T
#>   3:       S01   chr1 12342550     varA03      C      G          SNP        C
#>   4:       S01   chr1 12342620    varLD01      G      A          SNP        G
#>   5:       S01   chr1 12342710    varLD02      A      T          SNP        A
#>  ---                                                                         
#> 392:       S36   chr1 12342920    varLD04      G      C          SNP        C
#> 393:       S36   chr1 12343040    varLD05      T      G          SNP        G
#> 394:       S36   chr1 12343180    varLD06      A      C          SNP        C
#> 395:       S36   chr1 12344500     varA04      A    ATG          INS       i3
#> 396:       S36   chr1 12351050     varA05    ATG      A          DEL        A
#>      genotype_missing
#>                <lgcl>
#>   1:            FALSE
#>   2:            FALSE
#>   3:            FALSE
#>   4:            FALSE
#>   5:            FALSE
#>  ---                 
#> 392:            FALSE
#> 393:            FALSE
#> 394:            FALSE
#> 395:            FALSE
#> 396:            FALSE
hap_gene$genotype_wide
#> Key: <hap_pattern>
#>     sample_id hap_id             hap_pattern non_missing_variant_n varA01
#>        <char> <char>                  <char>                 <int> <char>
#>  1:       S10   Hap1  A|C|C|G|A|C|G|T|A|A|i3                    11      A
#>  2:       S11   Hap1  A|C|C|G|A|C|G|T|A|A|i3                    11      A
#>  3:       S12   Hap1  A|C|C|G|A|C|G|T|A|A|i3                    11      A
#>  4:       S13   Hap1  A|C|C|G|A|C|G|T|A|A|i3                    11      A
#>  5:       S14   Hap1  A|C|C|G|A|C|G|T|A|A|i3                    11      A
#>  6:       S15   Hap1  A|C|C|G|A|C|G|T|A|A|i3                    11      A
#>  7:       S16   Hap1  A|C|C|G|A|C|G|T|A|A|i3                    11      A
#>  8:       S17   Hap1  A|C|C|G|A|C|G|T|A|A|i3                    11      A
#>  9:       S18   Hap1  A|C|C|G|A|C|G|T|A|A|i3                    11      A
#> 10:       S01   Hap2  A|T|C|G|A|C|G|T|A|A|i3                    11      A
#> 11:       S02   Hap2  A|T|C|G|A|C|G|T|A|A|i3                    11      A
#> 12:       S03   Hap2  A|T|C|G|A|C|G|T|A|A|i3                    11      A
#> 13:       S04   Hap2  A|T|C|G|A|C|G|T|A|A|i3                    11      A
#> 14:       S05   Hap2  A|T|C|G|A|C|G|T|A|A|i3                    11      A
#> 15:       S06   Hap2  A|T|C|G|A|C|G|T|A|A|i3                    11      A
#> 16:       S07   Hap2  A|T|C|G|A|C|G|T|A|A|i3                    11      A
#> 17:       S08   Hap2  A|T|C|G|A|C|G|T|A|A|i3                    11      A
#> 18:       S09   Hap2  A|T|C|G|A|C|G|T|A|A|i3                    11      A
#> 19:       S19   Hap3 G|C|G|A|T|T|C|G|C|i3|i3                    11      G
#> 20:       S20   Hap3 G|C|G|A|T|T|C|G|C|i3|i3                    11      G
#> 21:       S21   Hap3 G|C|G|A|T|T|C|G|C|i3|i3                    11      G
#> 22:       S22   Hap3 G|C|G|A|T|T|C|G|C|i3|i3                    11      G
#> 23:       S23   Hap3 G|C|G|A|T|T|C|G|C|i3|i3                    11      G
#> 24:       S24   Hap3 G|C|G|A|T|T|C|G|C|i3|i3                    11      G
#> 25:       S25   Hap3 G|C|G|A|T|T|C|G|C|i3|i3                    11      G
#> 26:       S26   Hap3 G|C|G|A|T|T|C|G|C|i3|i3                    11      G
#> 27:       S27   Hap3 G|C|G|A|T|T|C|G|C|i3|i3                    11      G
#> 28:       S28   Hap4  G|T|G|A|T|T|C|G|C|i3|A                    11      G
#> 29:       S29   Hap4  G|T|G|A|T|T|C|G|C|i3|A                    11      G
#> 30:       S30   Hap4  G|T|G|A|T|T|C|G|C|i3|A                    11      G
#> 31:       S31   Hap4  G|T|G|A|T|T|C|G|C|i3|A                    11      G
#> 32:       S32   Hap4  G|T|G|A|T|T|C|G|C|i3|A                    11      G
#> 33:       S33   Hap4  G|T|G|A|T|T|C|G|C|i3|A                    11      G
#> 34:       S34   Hap4  G|T|G|A|T|T|C|G|C|i3|A                    11      G
#> 35:       S35   Hap4  G|T|G|A|T|T|C|G|C|i3|A                    11      G
#> 36:       S36   Hap4  G|T|G|A|T|T|C|G|C|i3|A                    11      G
#>     sample_id hap_id             hap_pattern non_missing_variant_n varA01
#>        <char> <char>                  <char>                 <int> <char>
#>     varA02 varA03 varLD01 varLD02 varLD03 varLD04 varLD05 varLD06 varA04 varA05
#>     <char> <char>  <char>  <char>  <char>  <char>  <char>  <char> <char> <char>
#>  1:      C      C       G       A       C       G       T       A      A     i3
#>  2:      C      C       G       A       C       G       T       A      A     i3
#>  3:      C      C       G       A       C       G       T       A      A     i3
#>  4:      C      C       G       A       C       G       T       A      A     i3
#>  5:      C      C       G       A       C       G       T       A      A     i3
#>  6:      C      C       G       A       C       G       T       A      A     i3
#>  7:      C      C       G       A       C       G       T       A      A     i3
#>  8:      C      C       G       A       C       G       T       A      A     i3
#>  9:      C      C       G       A       C       G       T       A      A     i3
#> 10:      T      C       G       A       C       G       T       A      A     i3
#> 11:      T      C       G       A       C       G       T       A      A     i3
#> 12:      T      C       G       A       C       G       T       A      A     i3
#> 13:      T      C       G       A       C       G       T       A      A     i3
#> 14:      T      C       G       A       C       G       T       A      A     i3
#> 15:      T      C       G       A       C       G       T       A      A     i3
#> 16:      T      C       G       A       C       G       T       A      A     i3
#> 17:      T      C       G       A       C       G       T       A      A     i3
#> 18:      T      C       G       A       C       G       T       A      A     i3
#> 19:      C      G       A       T       T       C       G       C     i3     i3
#> 20:      C      G       A       T       T       C       G       C     i3     i3
#> 21:      C      G       A       T       T       C       G       C     i3     i3
#> 22:      C      G       A       T       T       C       G       C     i3     i3
#> 23:      C      G       A       T       T       C       G       C     i3     i3
#> 24:      C      G       A       T       T       C       G       C     i3     i3
#> 25:      C      G       A       T       T       C       G       C     i3     i3
#> 26:      C      G       A       T       T       C       G       C     i3     i3
#> 27:      C      G       A       T       T       C       G       C     i3     i3
#> 28:      T      G       A       T       T       C       G       C     i3      A
#> 29:      T      G       A       T       T       C       G       C     i3      A
#> 30:      T      G       A       T       T       C       G       C     i3      A
#> 31:      T      G       A       T       T       C       G       C     i3      A
#> 32:      T      G       A       T       T       C       G       C     i3      A
#> 33:      T      G       A       T       T       C       G       C     i3      A
#> 34:      T      G       A       T       T       C       G       C     i3      A
#> 35:      T      G       A       T       T       C       G       C     i3      A
#> 36:      T      G       A       T       T       C       G       C     i3      A
#>     varA02 varA03 varLD01 varLD02 varLD03 varLD04 varLD05 varLD06 varA04 varA05
#>     <char> <char>  <char>  <char>  <char>  <char>  <char>  <char> <char> <char>
hap_gene$haplotypes
#> Key: <hap_id>
#>    hap_id sample_n                             samples varA01 varA02 varA03
#>    <char>    <int>                              <char> <char> <char> <char>
#> 1:   Hap1        9 S10;S11;S12;S13;S14;S15;S16;S17;S18      A      C      C
#> 2:   Hap2        9 S01;S02;S03;S04;S05;S06;S07;S08;S09      A      T      C
#> 3:   Hap3        9 S19;S20;S21;S22;S23;S24;S25;S26;S27      G      C      G
#> 4:   Hap4        9 S28;S29;S30;S31;S32;S33;S34;S35;S36      G      T      G
#>    varLD01 varLD02 varLD03 varLD04 varLD05 varLD06 varA04 varA05
#>     <char>  <char>  <char>  <char>  <char>  <char> <char> <char>
#> 1:       G       A       C       G       T       A      A     i3
#> 2:       G       A       C       G       T       A      A     i3
#> 3:       A       T       T       C       G       C     i3     i3
#> 4:       A       T       T       C       G       C     i3      A
hap_gene$sample_haplotypes
#> Key: <hap_pattern>
#>     sample_id hap_id             hap_pattern non_missing_variant_n
#>        <char> <char>                  <char>                 <int>
#>  1:       S10   Hap1  A|C|C|G|A|C|G|T|A|A|i3                    11
#>  2:       S11   Hap1  A|C|C|G|A|C|G|T|A|A|i3                    11
#>  3:       S12   Hap1  A|C|C|G|A|C|G|T|A|A|i3                    11
#>  4:       S13   Hap1  A|C|C|G|A|C|G|T|A|A|i3                    11
#>  5:       S14   Hap1  A|C|C|G|A|C|G|T|A|A|i3                    11
#>  6:       S15   Hap1  A|C|C|G|A|C|G|T|A|A|i3                    11
#>  7:       S16   Hap1  A|C|C|G|A|C|G|T|A|A|i3                    11
#>  8:       S17   Hap1  A|C|C|G|A|C|G|T|A|A|i3                    11
#>  9:       S18   Hap1  A|C|C|G|A|C|G|T|A|A|i3                    11
#> 10:       S01   Hap2  A|T|C|G|A|C|G|T|A|A|i3                    11
#> 11:       S02   Hap2  A|T|C|G|A|C|G|T|A|A|i3                    11
#> 12:       S03   Hap2  A|T|C|G|A|C|G|T|A|A|i3                    11
#> 13:       S04   Hap2  A|T|C|G|A|C|G|T|A|A|i3                    11
#> 14:       S05   Hap2  A|T|C|G|A|C|G|T|A|A|i3                    11
#> 15:       S06   Hap2  A|T|C|G|A|C|G|T|A|A|i3                    11
#> 16:       S07   Hap2  A|T|C|G|A|C|G|T|A|A|i3                    11
#> 17:       S08   Hap2  A|T|C|G|A|C|G|T|A|A|i3                    11
#> 18:       S09   Hap2  A|T|C|G|A|C|G|T|A|A|i3                    11
#> 19:       S19   Hap3 G|C|G|A|T|T|C|G|C|i3|i3                    11
#> 20:       S20   Hap3 G|C|G|A|T|T|C|G|C|i3|i3                    11
#> 21:       S21   Hap3 G|C|G|A|T|T|C|G|C|i3|i3                    11
#> 22:       S22   Hap3 G|C|G|A|T|T|C|G|C|i3|i3                    11
#> 23:       S23   Hap3 G|C|G|A|T|T|C|G|C|i3|i3                    11
#> 24:       S24   Hap3 G|C|G|A|T|T|C|G|C|i3|i3                    11
#> 25:       S25   Hap3 G|C|G|A|T|T|C|G|C|i3|i3                    11
#> 26:       S26   Hap3 G|C|G|A|T|T|C|G|C|i3|i3                    11
#> 27:       S27   Hap3 G|C|G|A|T|T|C|G|C|i3|i3                    11
#> 28:       S28   Hap4  G|T|G|A|T|T|C|G|C|i3|A                    11
#> 29:       S29   Hap4  G|T|G|A|T|T|C|G|C|i3|A                    11
#> 30:       S30   Hap4  G|T|G|A|T|T|C|G|C|i3|A                    11
#> 31:       S31   Hap4  G|T|G|A|T|T|C|G|C|i3|A                    11
#> 32:       S32   Hap4  G|T|G|A|T|T|C|G|C|i3|A                    11
#> 33:       S33   Hap4  G|T|G|A|T|T|C|G|C|i3|A                    11
#> 34:       S34   Hap4  G|T|G|A|T|T|C|G|C|i3|A                    11
#> 35:       S35   Hap4  G|T|G|A|T|T|C|G|C|i3|A                    11
#> 36:       S36   Hap4  G|T|G|A|T|T|C|G|C|i3|A                    11
#>     sample_id hap_id             hap_pattern non_missing_variant_n
#>        <char> <char>                  <char>                 <int>

The components have distinct purposes:

Component Content Typical use
region locator, chromosome, boundaries, strand, and flank settings confirm the biological interval
variants retained VCF variant records inspect variant order and REF/ALT alleles
genotype_long one sample × variant genotype per row detailed genotype inspection
genotype_wide one sample per row with variant columns inspect the full genotype matrix
haplotypes one row per unique haplotype with sample counts summarize haplotype groups
sample_haplotypes sample-to-haplotype assignment join with phenotype or other metadata

The meta list records the genotype representation, missing-value policy, retained sample number, variant number, and haplotype number:

hap_gene$meta
#> $genotype_mode
#> [1] "string"
#> 
#> $missing_genotype
#> [1] NA
#> 
#> $min_variant_number
#> [1] 11
#> 
#> $sample_n
#> [1] 36
#> 
#> $variant_n
#> [1] 11
#> 
#> $haplotype_n
#> [1] 4

This object is already the canonical input for plot_hap_variant(), plot_hap_pheno(), refine_haplotype(), and plot_variant_effect(). There is no need to rebuild a genotype matrix manually.

Step 4. Choose the genotype representation

GeneTrackR provides two genotype representations through genotype_mode.

Allele-string mode

genotype_mode = "string" is recommended when the haplotype table itself is important for interpretation:

hap_gene_string <- hap_gene_variant(
  vcf = vcf,
  annotation = gp,
  gene_id = "GeneA",
  genotype_mode = "string"
)
#> [GeneTrackR] Retrieved variants: 11.

hap_gene_string$haplotypes
#> Key: <hap_id>
#>    hap_id sample_n                             samples varA01 varA02 varA03
#>    <char>    <int>                              <char> <char> <char> <char>
#> 1:   Hap1        9 S10;S11;S12;S13;S14;S15;S16;S17;S18      A      C      C
#> 2:   Hap2        9 S01;S02;S03;S04;S05;S06;S07;S08;S09      A      T      C
#> 3:   Hap3        9 S19;S20;S21;S22;S23;S24;S25;S26;S27      G      C      G
#> 4:   Hap4        9 S28;S29;S30;S31;S32;S33;S34;S35;S36      G      T      G
#>    varLD01 varLD02 varLD03 varLD04 varLD05 varLD06 varA04 varA05
#>     <char>  <char>  <char>  <char>  <char>  <char> <char> <char>
#> 1:       G       A       C       G       T       A      A     i3
#> 2:       G       A       C       G       T       A      A     i3
#> 3:       A       T       T       C       G       C     i3     i3
#> 4:       A       T       T       C       G       C     i3      A

Single-base alleles are displayed directly as A, T, C, or G. Longer REF/ALT alleles are compressed to iN, where N is the displayed allele length. The haplotype plot maps allele classes in the stable order A, T, C, G, and indel.

String mode is also a compact display representation rather than a phased dosage representation: if a genotype contains an alternate allele, GeneTrackR displays the first observed ALT allele label for that variant. Inspect the original genotype columns in vcf$data when zygosity, phase, or multi-allelic dosage must be retained explicitly.

Binary code mode

genotype_mode = "code" collapses each genotype to reference versus alternate presence:

hap_gene_code <- hap_gene_variant(
  vcf = vcf,
  annotation = gp,
  gene_id = "GeneA",
  genotype_mode = "code"
)
#> [GeneTrackR] Retrieved variants: 11.

hap_gene_code$haplotypes
#> Key: <hap_id>
#>    hap_id sample_n                             samples varA01 varA02 varA03
#>    <char>    <int>                              <char> <char> <char> <char>
#> 1:   Hap1        9 S01;S02;S03;S04;S05;S06;S07;S08;S09      0      0      0
#> 2:   Hap2        9 S10;S11;S12;S13;S14;S15;S16;S17;S18      0      1      0
#> 3:   Hap3        9 S28;S29;S30;S31;S32;S33;S34;S35;S36      1      0      1
#> 4:   Hap4        9 S19;S20;S21;S22;S23;S24;S25;S26;S27      1      1      1
#>    varLD01 varLD02 varLD03 varLD04 varLD05 varLD06 varA04 varA05
#>     <char>  <char>  <char>  <char>  <char>  <char> <char> <char>
#> 1:       0       0       0       0       0       0      0      0
#> 2:       0       0       0       0       0       0      0      0
#> 3:       1       1       1       1       1       1      1      1
#> 4:       1       1       1       1       1       1      1      0

In code mode:

  • 0 means the genotype contains only the reference allele;
  • 1 means at least one alternate allele is present.

Therefore code mode is a binary REF/ALT-presence representation, not allele dosage. A heterozygous genotype and a homozygous alternate genotype both become 1. Use allele-string mode when the displayed allele identity is more important than compact binary grouping.

Step 5. Control missing-genotype filtering

By default, min_variant_number = NULL requires a sample to have non-missing genotypes at all retained variants. This is the safest default for defining complete haplotypes.

The GeneA gene body has complete demo genotypes, so all 36 samples are retained:

hap_gene$meta$sample_n
#> [1] 36
hap_gene$meta$min_variant_number
#> [1] 11

Flanking regions can introduce additional variants with missing data. The demo upstream variant varAup01 is intentionally designed with missing/heterozygous genotypes. Adding it changes the haplotype definition:

hap_gene_upstream <- hap_gene_variant(
  vcf = vcf,
  annotation = gp,
  gene_id = "GeneA",
  upstream = 500,
  downstream = 0,
  strand_aware = TRUE,
  genotype_mode = "string"
)
#> [GeneTrackR] Retrieved variants: 12.

hap_gene_upstream$region
#> $locator
#> [1] "gene"
#> 
#> $id
#> [1] "GeneA"
#> 
#> $chrom
#> [1] "chr1"
#> 
#> $start
#> [1] 12339501
#> 
#> $end
#> [1] 12352000
#> 
#> $core_start
#> [1] 12340001
#> 
#> $core_end
#> [1] 12352000
#> 
#> $upstream
#> [1] 500
#> 
#> $downstream
#> [1] 0
#> 
#> $strand
#> [1] "+"
#> 
#> $strand_aware
#> [1] TRUE
hap_gene_upstream$meta
#> $genotype_mode
#> [1] "string"
#> 
#> $missing_genotype
#> [1] NA
#> 
#> $min_variant_number
#> [1] 12
#> 
#> $sample_n
#> [1] 32
#> 
#> $variant_n
#> [1] 12
#> 
#> $haplotype_n
#> [1] 6

To retain samples that are missing a limited number of variants, set an explicit threshold. The extended demo region contains 12 variants, so min_variant_number = 11 allows one missing genotype:

hap_gene_upstream_relaxed <- hap_gene_variant(
  vcf = vcf,
  annotation = gp,
  gene_id = "GeneA",
  upstream = 500,
  genotype_mode = "string",
  min_variant_number = 11
)
#> [GeneTrackR] Retrieved variants: 12.

hap_gene_upstream_relaxed$sample_haplotypes
#> Key: <hap_pattern>
#>     sample_id hap_id                hap_pattern non_missing_variant_n
#>        <char> <char>                     <char>                 <int>
#>  1:       S10   Hap3   A|A|C|C|G|A|C|G|T|A|A|i3                    12
#>  2:       S11   Hap3   A|A|C|C|G|A|C|G|T|A|A|i3                    12
#>  3:       S13   Hap3   A|A|C|C|G|A|C|G|T|A|A|i3                    12
#>  4:       S15   Hap3   A|A|C|C|G|A|C|G|T|A|A|i3                    12
#>  5:       S16   Hap3   A|A|C|C|G|A|C|G|T|A|A|i3                    12
#>  6:       S17   Hap3   A|A|C|C|G|A|C|G|T|A|A|i3                    12
#>  7:       S18   Hap3   A|A|C|C|G|A|C|G|T|A|A|i3                    12
#>  8:       S01   Hap4   A|A|T|C|G|A|C|G|T|A|A|i3                    12
#>  9:       S02   Hap4   A|A|T|C|G|A|C|G|T|A|A|i3                    12
#> 10:       S04   Hap4   A|A|T|C|G|A|C|G|T|A|A|i3                    12
#> 11:       S06   Hap4   A|A|T|C|G|A|C|G|T|A|A|i3                    12
#> 12:       S07   Hap4   A|A|T|C|G|A|C|G|T|A|A|i3                    12
#> 13:       S08   Hap4   A|A|T|C|G|A|C|G|T|A|A|i3                    12
#> 14:       S09   Hap4   A|A|T|C|G|A|C|G|T|A|A|i3                    12
#> 15:       S12   Hap5  NA|A|C|C|G|A|C|G|T|A|A|i3                    11
#> 16:       S03   Hap6  NA|A|T|C|G|A|C|G|T|A|A|i3                    11
#> 17:       S21   Hap7 NA|G|C|G|A|T|T|C|G|C|i3|i3                    11
#> 18:       S30   Hap8  NA|G|T|G|A|T|T|C|G|C|i3|A                    11
#> 19:       S14   Hap9   T|A|C|C|G|A|C|G|T|A|A|i3                    12
#> 20:       S05  Hap10   T|A|T|C|G|A|C|G|T|A|A|i3                    12
#> 21:       S19   Hap1  T|G|C|G|A|T|T|C|G|C|i3|i3                    12
#> 22:       S20   Hap1  T|G|C|G|A|T|T|C|G|C|i3|i3                    12
#> 23:       S22   Hap1  T|G|C|G|A|T|T|C|G|C|i3|i3                    12
#> 24:       S23   Hap1  T|G|C|G|A|T|T|C|G|C|i3|i3                    12
#> 25:       S24   Hap1  T|G|C|G|A|T|T|C|G|C|i3|i3                    12
#> 26:       S25   Hap1  T|G|C|G|A|T|T|C|G|C|i3|i3                    12
#> 27:       S26   Hap1  T|G|C|G|A|T|T|C|G|C|i3|i3                    12
#> 28:       S27   Hap1  T|G|C|G|A|T|T|C|G|C|i3|i3                    12
#> 29:       S28   Hap2   T|G|T|G|A|T|T|C|G|C|i3|A                    12
#> 30:       S29   Hap2   T|G|T|G|A|T|T|C|G|C|i3|A                    12
#> 31:       S31   Hap2   T|G|T|G|A|T|T|C|G|C|i3|A                    12
#> 32:       S32   Hap2   T|G|T|G|A|T|T|C|G|C|i3|A                    12
#> 33:       S33   Hap2   T|G|T|G|A|T|T|C|G|C|i3|A                    12
#> 34:       S34   Hap2   T|G|T|G|A|T|T|C|G|C|i3|A                    12
#> 35:       S35   Hap2   T|G|T|G|A|T|T|C|G|C|i3|A                    12
#> 36:       S36   Hap2   T|G|T|G|A|T|T|C|G|C|i3|A                    12
#>     sample_id hap_id                hap_pattern non_missing_variant_n
#>        <char> <char>                     <char>                 <int>

Use relaxed thresholds deliberately. Missing values become part of the observed haplotype pattern and may create additional haplotype groups. For the main GeneA tutorial, the unextended gene-body object hap_gene remains the recommended analysis object.

A custom missing label can be supplied for display:

hap_missing_label <- hap_gene_variant(
  vcf = vcf,
  annotation = gp,
  gene_id = "GeneA",
  upstream = 500,
  genotype_mode = "code",
  missing_genotype = "-",
  min_variant_number = 11
)
#> [GeneTrackR] Retrieved variants: 12.

Internally, GeneTrackR still tracks which genotypes are biologically missing, so a custom display label does not convert missing values into valid genotype calls.

Step 6. Construct transcript, flanking-region, and custom-region haplotypes

Transcript-defined haplotypes

Use transcript_id instead of gene_id when variants should be restricted to one transcript locus:

hap_tx <- hap_gene_variant(
  vcf = vcf,
  annotation = gp,
  transcript_id = "TxA1",
  genotype_mode = "string"
)
#> [GeneTrackR] Retrieved variants: 11.

hap_tx$region
#> $locator
#> [1] "transcript"
#> 
#> $id
#> [1] "TxA1"
#> 
#> $chrom
#> [1] "chr1"
#> 
#> $start
#> [1] 12340001
#> 
#> $end
#> [1] 12352000
#> 
#> $core_start
#> [1] 12340001
#> 
#> $core_end
#> [1] 12352000
#> 
#> $upstream
#> [1] 0
#> 
#> $downstream
#> [1] 0
#> 
#> $strand
#> [1] "+"
#> 
#> $strand_aware
#> [1] TRUE

Supply exactly one of gene_id or transcript_id.

Strand-aware flanking regions

upstream and downstream are interpreted relative to transcription direction when strand_aware = TRUE:

hap_gene_flank <- hap_gene_variant(
  vcf = vcf,
  annotation = gp,
  gene_id = "GeneA",
  upstream = 1000,
  downstream = 500,
  strand_aware = TRUE,
  genotype_mode = "string",
  min_variant_number = 1
)
#> [GeneTrackR] Retrieved variants: 13.

hap_gene_flank$region
#> $locator
#> [1] "gene"
#> 
#> $id
#> [1] "GeneA"
#> 
#> $chrom
#> [1] "chr1"
#> 
#> $start
#> [1] 12339001
#> 
#> $end
#> [1] 12352500
#> 
#> $core_start
#> [1] 12340001
#> 
#> $core_end
#> [1] 12352000
#> 
#> $upstream
#> [1] 1000
#> 
#> $downstream
#> [1] 500
#> 
#> $strand
#> [1] "+"
#> 
#> $strand_aware
#> [1] TRUE

For a negative-strand gene, biological upstream is toward increasing genomic coordinates. GeneTrackR handles this reversal automatically when strand_aware = TRUE.

Explicit genomic regions

Use hap_region_variant() when the interval is defined directly rather than by annotation:

hap_region <- hap_region_variant(
  vcf = vcf,
  chrom = "chr1",
  start = 12340001,
  end = 12352000,
  genotype_mode = "code"
)
#> [GeneTrackR] Retrieved variants: 11.

hap_region
#> <HapVariant>
#>   region    : chr1:12340001-12352000
#>   variants  : 11
#>   samples   : 36
#>   haplotypes: 4

This is useful for GWAS/LD intervals, promoter windows, QTL regions, or any custom locus that does not correspond exactly to one annotated gene or transcript.

Sample and variant-type filtering

The haplotype can be restricted before grouping. For example, analyze a subset of samples:

hap_sample_subset <- hap_gene_variant(
  vcf = vcf,
  annotation = gp,
  gene_id = "GeneA",
  samples = sprintf("S%02d", 1:18),
  genotype_mode = "string"
)
#> [GeneTrackR] Retrieved variants: 11.

hap_sample_subset$meta
#> $genotype_mode
#> [1] "string"
#> 
#> $missing_genotype
#> [1] NA
#> 
#> $min_variant_number
#> [1] 11
#> 
#> $sample_n
#> [1] 18
#> 
#> $variant_n
#> [1] 11
#> 
#> $haplotype_n
#> [1] 2

Or construct haplotypes using only SNPs:

hap_snp <- hap_gene_variant(
  vcf = vcf,
  annotation = gp,
  gene_id = "GeneA",
  variant_type = "SNP",
  genotype_mode = "string"
)
#> [GeneTrackR] Retrieved variants: 9.

hap_snp$variants
#>     chrom      pos variant_id    ref    alt  qual filter
#>    <char>    <int>     <char> <char> <char> <num> <char>
#> 1:   chr1 12340250     varA01      A      G    60   PASS
#> 2:   chr1 12340600     varA02      T      C    60   PASS
#> 3:   chr1 12342550     varA03      C      G    60   PASS
#> 4:   chr1 12342620    varLD01      G      A    60   PASS
#> 5:   chr1 12342710    varLD02      A      T    60   PASS
#> 6:   chr1 12342805    varLD03      C      T    60   PASS
#> 7:   chr1 12342920    varLD04      G      C    60   PASS
#> 8:   chr1 12343040    varLD05      T      G    60   PASS
#> 9:   chr1 12343180    varLD06      A      C    60   PASS
#>                                  info FORMAT    S01    S02    S03    S04    S05
#>                                <char> <char> <char> <char> <char> <char> <char>
#> 1:        ROLE=core_haplotype,high_ld     GT    0/0    0/0    0/0    0/0    0/0
#> 2:                ROLE=core_haplotype     GT    0/0    0/0    0/0    0/0    0/0
#> 3: ROLE=core_haplotype,protein_effect     GT    0/0    0/0    0/0    0/0    0/0
#> 4:           ROLE=high_ld,ld_gradient     GT    0/0    0/0    0/0    0/0    0/0
#> 5:           ROLE=high_ld,ld_gradient     GT    0/0    0/0    0/0    0/0    0/0
#> 6:           ROLE=high_ld,ld_gradient     GT    0/0    0/0    0/0    0/0    0/0
#> 7:           ROLE=high_ld,ld_gradient     GT    0/0    0/0    0/0    0/0    0/0
#> 8:           ROLE=high_ld,ld_gradient     GT    0/0    0/0    0/0    0/0    0/0
#> 9:           ROLE=high_ld,ld_gradient     GT    0/0    0/0    0/0    0/0    0/0
#>       S06    S07    S08    S09    S10    S11    S12    S13    S14    S15    S16
#>    <char> <char> <char> <char> <char> <char> <char> <char> <char> <char> <char>
#> 1:    0/0    0/0    0/0    0/0    0/0    0/0    0/0    0/0    0/0    0/0    0/0
#> 2:    0/0    0/0    0/0    0/0    1/1    1/1    1/1    1/1    1/1    1/1    1/1
#> 3:    0/0    0/0    0/0    0/0    0/0    0/0    0/0    0/0    0/0    0/0    0/0
#> 4:    0/0    0/0    0/0    0/0    0/0    0/0    0/0    0/0    0/0    0/0    0/0
#> 5:    0/0    0/0    0/0    0/0    0/0    0/0    0/0    0/0    0/0    0/0    0/0
#> 6:    0/0    0/0    0/0    0/0    0/0    0/0    0/0    0/0    0/0    0/0    0/0
#> 7:    0/0    0/0    0/0    0/0    0/0    0/0    0/0    0/0    0/0    0/0    0/0
#> 8:    0/0    0/0    0/0    0/0    0/0    0/0    0/0    0/0    0/0    0/0    0/0
#> 9:    0/0    0/0    0/0    0/0    0/0    0/0    0/0    0/0    0/0    0/0    0/0
#>       S17    S18    S19    S20    S21    S22    S23    S24    S25    S26    S27
#>    <char> <char> <char> <char> <char> <char> <char> <char> <char> <char> <char>
#> 1:    0/0    0/0    1/1    1/1    1/1    1/1    1/1    1/1    1/1    1/1    1/1
#> 2:    1/1    1/1    1/1    1/1    1/1    1/1    1/1    1/1    1/1    1/1    1/1
#> 3:    0/0    0/0    1/1    1/1    1/1    1/1    1/1    1/1    1/1    1/1    1/1
#> 4:    0/0    0/0    1/1    1/1    1/1    1/1    1/1    1/1    1/1    1/1    1/1
#> 5:    0/0    0/0    1/1    1/1    1/1    1/1    1/1    1/1    1/1    1/1    1/1
#> 6:    0/0    0/0    1/1    1/1    1/1    1/1    1/1    1/1    1/1    1/1    1/1
#> 7:    0/0    0/0    1/1    1/1    1/1    1/1    1/1    1/1    1/1    1/1    1/1
#> 8:    0/0    0/0    1/1    1/1    1/1    1/1    1/1    1/1    1/1    1/1    1/1
#> 9:    0/0    0/0    1/1    1/1    1/1    1/1    1/1    1/1    1/1    1/1    1/1
#>       S28    S29    S30    S31    S32    S33    S34    S35    S36 variant_type
#>    <char> <char> <char> <char> <char> <char> <char> <char> <char>       <char>
#> 1:    1/1    1/1    1/1    1/1    1/1    1/1    1/1    1/1    1/1          SNP
#> 2:    0/0    0/0    0/0    0/0    0/0    0/0    0/0    0/0    0/0          SNP
#> 3:    1/1    1/1    1/1    1/1    1/1    1/1    1/1    1/1    1/1          SNP
#> 4:    1/1    1/1    1/1    1/1    1/1    1/1    1/1    1/1    1/1          SNP
#> 5:    1/1    1/1    1/1    1/1    1/1    1/1    1/1    1/1    1/1          SNP
#> 6:    1/1    1/1    1/1    1/1    1/1    1/1    1/1    1/1    1/1          SNP
#> 7:    1/1    1/1    1/1    1/1    1/1    1/1    1/1    1/1    1/1          SNP
#> 8:    1/1    1/1    1/1    1/1    1/1    1/1    1/1    1/1    1/1          SNP
#> 9:    1/1    1/1    1/1    1/1    1/1    1/1    1/1    1/1    1/1          SNP
#>       start      end
#>       <int>    <int>
#> 1: 12340250 12340250
#> 2: 12340600 12340600
#> 3: 12342550 12342550
#> 4: 12342620 12342620
#> 5: 12342710 12342710
#> 6: 12342805 12342805
#> 7: 12342920 12342920
#> 8: 12343040 12343040
#> 9: 12343180 12343180

Filtering variants changes the haplotype definition and may merge previously distinct haplotypes. Always inspect haplotypes and sample_haplotypes after changing the retained variant set.

hap_variant() remains available as a compatibility wrapper, but new code should prefer hap_gene_variant() for gene/transcript queries and hap_region_variant() for direct genomic intervals.

Step 7. Draw the haplotype-variant figure

plot_hap_variant() combines the gene model, natural-variant markers, connector lines, REF/ALT reference rows, and haplotype genotype table:

hap_variant_figure <- plot_hap_variant(
  hap_gene,
  annotation = gp,
  min_hap_samples = 3,
  show_reference_row = TRUE,
  variant_label = "pos",
  gene_pos_x_angle = 90,
  gene_track_legend_position = "top",
  direction_mode = "gene",
  table_x_angle = 90,
  text_size = 9
)

hap_variant_figure

General plotting palettes default to Paired; plot_ld_block() is the deliberate package-level exception and defaults to Reds. The main haplotype visual controls can still be changed independently:

hap_variant_custom <- plot_hap_variant(
  hap_gene,
  annotation = gp,
  min_hap_samples = 3,
  show_reference_row = TRUE,
  gene_palette = "Paired",
  table_palette = "Paired",
  variant_palette = "Paired",
  table_alpha = 0.7,
  variant_alpha = 0.8,
  genotype_text_size = 3,
  variant_marker_size = 3,
  gene_track_height = 1.4,
  connector_height = 0.4,
  text_size = 9
)

hap_variant_custom

For allele-string haplotypes, table colors always follow the stable biological class order A, T, C, G, and indel. Custom colors can be supplied explicitly with those names:

plot_hap_variant(
  hap_gene,
  annotation = gp,
  min_hap_samples = 3,
  table_colors = c(
    A = "#1B9E77",
    T = "#D95F02",
    C = "#7570B3",
    G = "#E7298A",
    indel = "#66A61E"
  ),
  text_size = 9
)

Use show_variant_marker = FALSE to hide natural-variant triangles, or adjust variant_marker_size when the locus contains many variants.

Step 8. Pass the same haplotype object downstream

Do not reconstruct haplotypes separately for each downstream analysis. The hap_gene object created in Step 2 is the input for the following modules:

# Haplotype-phenotype association
# hap_res <- plot_hap_pheno(
#   hap_gene,
#   phenotype = pheno,
#   traits = "seed_weight",
#   min_hap_samples = 3
# )

# Phenotype-guided refinement
# refined <- refine_haplotype(
#   hap_gene,
#   phenotype = pheno,
#   traits = "seed_weight",
#   min_hap_samples = 3
# )

# Variant-effect prioritization
# effect <- plot_variant_effect(
#   hap_gene,
#   phenotype = pheno,
#   traits = "protein_content",
#   min_group_samples = 3
# )

Keeping one well-defined HapVariant as the common input ensures that the variant set, sample set, missing-data rule, and haplotype assignment remain consistent across visualization, phenotype association, refinement, and variant-effect analysis.

Session information

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       zip_3.0.2            Rcpp_1.1.2          
#>  [7] Biostrings_2.81.9    bitops_1.1-0         Rsamtools_2.29.0    
#> [10] GenomicRanges_1.65.4 parallel_4.6.1       jquerylib_0.1.4     
#> [13] IRanges_2.47.5       Seqinfo_1.3.2        scales_1.4.0        
#> [16] BiocParallel_1.47.0  yaml_2.3.12          fastmap_1.2.0       
#> [19] XVector_0.53.0       ggplot2_4.0.3        R6_2.6.1            
#> [22] patchwork_1.3.2      labeling_0.4.3       generics_0.1.4      
#> [25] openxlsx_4.2.9       knitr_1.52           BiocGenerics_0.59.12
#> [28] maketools_1.3.2      bslib_0.12.0         RColorBrewer_1.1-3  
#> [31] rlang_1.3.0          stringi_1.8.9        cachem_1.1.0        
#> [34] xfun_0.61            sass_0.4.10          sys_3.4.3           
#> [37] S7_0.2.2             otel_0.2.0           cli_3.6.6           
#> [40] withr_3.0.3          digest_0.6.39        grid_4.6.1          
#> [43] lifecycle_1.0.5      S4Vectors_0.51.10    vctrs_0.7.3         
#> [46] evaluate_1.0.5       glue_1.8.1           data.table_1.18.6.1 
#> [49] farver_2.1.2         codetools_0.2-20     buildtools_1.0.0    
#> [52] stats4_4.6.1         tools_4.6.1          htmltools_0.5.9