Complete candidate-locus workflow

Introduction

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:

  1. define and read the input files;
  2. validate and summarize the core objects;
  3. inspect the locus with annotation, signal, features, and variants;
  4. retrieve the gene-body variants used for haplotype analysis;
  5. construct and visualize GeneA haplotypes;
  6. test haplotype and single-variant phenotype associations;
  7. inspect the regional LD gradient;
  8. refine genetically similar haplotypes using phenotype evidence;
  9. rank regional variant effects and integrate the evidence;
  10. export the results and adapt the workflow to large real datasets.

Step 1. Define and read the inputs

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.

Step 2. Validate and summarize the core objects

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         11414

The most important consistency checks are:

  • chromosome names agree among annotation, variants, and signal tracks;
  • VCF genotype columns are retained for LD and haplotype analysis;
  • phenotype sample IDs overlap the VCF/haplotype sample IDs;
  • coordinate conventions have already been normalized by the GeneTrackR readers.

The demo phenotype order is intentionally different from the VCF sample order. Downstream phenotype functions align records by sample_id, not by row position.

Step 3. Inspect the locus in a browser-like view

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_geneA

All 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.

Step 4. Retrieve the gene-body variants

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          DEL

The 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.

Step 5. Construct and visualize the GeneA haplotypes

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;S36

The 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_figure

Keep the full HapVariant object. Its sample assignments and genotype tables are the input for phenotype association, refinement, and variant-effect analysis.

Step 6. Test phenotype associations

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$figure

hap_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.test

For 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$figure

These functions return structured result objects. Retain $pvalue, $summary, and $plot_data together with $figure rather than saving only the visual result.

Step 7. Inspect the regional LD gradient

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$figure

Inspect 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.

Step 8. Refine haplotypes with phenotype evidence

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:  mixed

The 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.42

A 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.

Step 9. Rank variant effects and integrate the evidence

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$figure

Rank 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+00

Several 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

Step 10. Export results and scale the workflow to real datasets

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 bgzip-compressed indexed VCF files with read_vcf(mode = "lazy") and always query a defined genomic interval before LD or haplotype analysis;
  • use lazy bigWig access when genome-wide signal should not be loaded into memory;
  • select only relevant signal samples before plotting;
  • use bin_size, heatmap_bin_size, or heatmap_max_bins for long/high-density signal regions;
  • prefer hap_gene_variant() and hap_region_variant() for new code; hap_variant() remains a compatibility wrapper;
  • remember that direct plotting functions return ggplot/patchwork figures, whereas phenotype/variant-effect results and 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.

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       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