Lays out the loci of a population opened with open_pop(): how many,
on which chromosomes, at which physical and genetic positions. It is the
second step of every simulation, and runs once per population:
pop <- open_pop(pop_name = "pigs", db_name = ":memory:") |>
define_genome(n_loci = 50000, n_chr = 18, chr_len_Mb = 100)Next come define_chromosome() for any sex chromosomes or organelles,
define_founder_haplotypes() for the founder allele pool, and
add_founders().
Usage
define_genome(
pop,
n_loci,
n_chr,
chr_len_Mb,
cM_per_Mb = 1,
locus_names = NULL,
chr_names = NULL,
recombines_M = TRUE,
recombines_F = TRUE
)Arguments
- pop
A
tidybreed_popfromopen_pop()with no genome yet;define_genome()is refused on a population that already has one.- n_loci
Whole number: the total number of loci (SNPs) across the genome, at least
n_chr.- n_chr
Whole number: the number of chromosomes, including any sex chromosomes or organelles you will set up with
define_chromosome().- chr_len_Mb
Chromosome length(s) in megabases: one number for every chromosome, or a vector of
n_chrvalues in chromosome order. Sets the physical positions, and withcM_per_Mbthe genetic map. It does not change how many loci a chromosome gets.- cM_per_Mb
Recombination rate in centiMorgans per megabase: one number, or a vector of
n_chrvalues. Must be positive. Default1, about one crossover per 100 Mb per meiosis.- locus_names
Optional character vector of
n_lociunique, non-empty names, in genome order (chromosome 1 first).NULL(default) gives"Locus_1","Locus_2", ...- chr_names
Optional vector of
n_chrunique, non-empty chromosome names, in order, e.g.c(1:18, "X", "Y")(stored as text).NULL(default) gives"1","2", ... Name sex chromosomes and organelles here sodefine_chromosome()can refer to them.- recombines_M, recombines_F
Logical: whether a male (
M) or female (F) parent recombines its chromosomes when making gametes, genome-wide. Both defaultTRUE. Set one toFALSEfor a species where one sex has no crossing over at all, e.g.recombines_M = FALSEfor Drosophila males orrecombines_F = FALSEfor silkworm females. For single chromosomes (a Y or W), usedefine_chromosome()instead.
Details
Where the loci go. Loci are divided as evenly as possible across the
chromosomes, whatever their lengths (50 loci on 3 chromosomes gives
17, 16, 17), and spaced evenly within each chromosome, never at either end.
Each gets an id (locus_id, 1 to n_loci in genome order), a name, a
chromosome and a physical position pos_bp, stored in genome_meta. To
make some of them QTL or markers later, filter get_table(pop, "genome_meta") and pipe it into define_additive_effects(),
define_genome_effects() or define_chip().
Genetic map and recombination. Each locus's genetic position is
pos_cM = pos_bp / 1e6 * cM_per_Mb, stored in genome_map. In
add_offspring() a chromosome's number of crossovers per meiosis is
Poisson with mean equal to its genetic length in Morgans (the last locus's
pos_cM / 100), placed uniformly in cM (the Haldane model). So the
default 1 cM/Mb gives a 100 Mb chromosome about one crossover per meiosis.
What is created. define_genome() writes genome_meta, genome_map,
the seeded chromosome rules chr_inheritance and chr_recombination, and
the empty tables later functions fill: ind_haplotype (alleles, written by
add_founders() and add_offspring()), ind_genotype (dosages, filled
on demand by add_dosage()), ind_crossover and the three genome-effect
tables with their views genome_effect_terms and genome_effect_loci.
Every chromosome starts as a diploid autosome: one copy from each parent,
recombining in both sexes unless recombines_M / recombines_F say
otherwise.
The call is atomic: everything is written in one transaction, so an error (an invalid argument, loci too dense to place) leaves the database as it was and you can simply call again with corrected arguments.
See also
define_chromosome(), define_founder_haplotypes(),
add_founders(); get_table(pop, "genome_meta") and
get_table(pop, "genome_map") to look at the result.
Examples
# 1,000 loci on 10 chromosomes of 100 Mb each
pop <- open_pop(pop_name = "A", db_name = ":memory:") |>
define_genome(n_loci = 1000, n_chr = 10, chr_len_Mb = 100)
#> duckdb keeps downloaded extensions and secrets in a temporary directory:
#> ℹ /tmp/RtmpvvfSjW/duckdb
#> This is removed when the R session ends.
#> • Extensions are re-downloaded each session.
#> • Secrets are lost.
#> ℹ Run duckdb(shared_home = TRUE) (or create ~/.duckdb) to keep them (suitable for most users).
#> ℹ Run duckdb(shared_home = FALSE) to accept the temporary directory (and silence this message).
#> ℹ See ?duckdb_storage for details and alternatives.
#> Opened in-memory population 'A'
#> Defined genome: 1000 loci across 10 chromosomes | chr lengths (Mb): all equal to 100 Mb
#> Tables written: genome_meta, genome_map, ind_haplotype, ind_genotype, ind_crossover, chr_inheritance, chr_recombination, genome_effects, genome_effect_members, genome_effect_member_origins
#> Views created: genome_effect_terms, genome_effect_loci
get_table(pop, "genome_meta")
#> <tidybreed_table: genome_meta> [1000 rows × 5 fields]
#> # A tibble: 10 × 5
#> locus_id locus_name chr chr_name pos_bp
#> <int> <chr> <int> <chr> <dbl>
#> 1 1 Locus_1 1 1 990099
#> 2 2 Locus_2 1 1 1980198
#> 3 3 Locus_3 1 1 2970297
#> 4 4 Locus_4 1 1 3960396
#> 5 5 Locus_5 1 1 4950495
#> 6 6 Locus_6 1 1 5940594
#> 7 7 Locus_7 1 1 6930693
#> 8 8 Locus_8 1 1 7920792
#> 9 9 Locus_9 1 1 8910891
#> 10 10 Locus_10 1 1 9900990
get_table(pop, "genome_map")
#> <tidybreed_table: genome_map> [1000 rows × 7 fields]
#> # A tibble: 10 × 7
#> id_genome_map locus_id locus_name sex line_name map_name pos_cM
#> <int> <int> <chr> <chr> <chr> <chr> <dbl>
#> 1 1 1 Locus_1 NA NA default 0.990
#> 2 2 2 Locus_2 NA NA default 1.98
#> 3 3 3 Locus_3 NA NA default 2.97
#> 4 4 4 Locus_4 NA NA default 3.96
#> 5 5 5 Locus_5 NA NA default 4.95
#> 6 6 6 Locus_6 NA NA default 5.94
#> 7 7 7 Locus_7 NA NA default 6.93
#> 8 8 8 Locus_8 NA NA default 7.92
#> 9 9 9 Locus_9 NA NA default 8.91
#> 10 10 10 Locus_10 NA NA default 9.90
close_pop(pop)
# Chromosomes of different lengths, a higher recombination rate and
# your own names (the first three cattle autosomes plus X)
pop <- open_pop(pop_name = "B", db_name = ":memory:") |>
define_genome(n_loci = 400, n_chr = 4,
chr_len_Mb = c(158, 137, 121, 139),
cM_per_Mb = 1.2,
chr_names = c("1", "2", "3", "X"))
#> duckdb keeps downloaded extensions and secrets in a temporary directory:
#> ℹ /tmp/RtmpvvfSjW/duckdb
#> This is removed when the R session ends.
#> • Extensions are re-downloaded each session.
#> • Secrets are lost.
#> ℹ Run duckdb(shared_home = TRUE) (or create ~/.duckdb) to keep them (suitable for most users).
#> ℹ Run duckdb(shared_home = FALSE) to accept the temporary directory (and silence this message).
#> ℹ See ?duckdb_storage for details and alternatives.
#> Opened in-memory population 'B'
#> Defined genome: 400 loci across 4 chromosomes | chr lengths (Mb): 1:158, 2:137, 3:121, X:139
#> Tables written: genome_meta, genome_map, ind_haplotype, ind_genotype, ind_crossover, chr_inheritance, chr_recombination, genome_effects, genome_effect_members, genome_effect_member_origins
#> Views created: genome_effect_terms, genome_effect_loci
close_pop(pop)
# The usual next steps: a founder pool, then founders
set.seed(1)
pop <- open_pop(pop_name = "C", db_name = ":memory:") |>
define_genome(n_loci = 1000, n_chr = 10, chr_len_Mb = 100) |>
define_founder_haplotypes(n_haplotypes = 100,
min_allele_freq = 0.05,
max_allele_freq = 0.95)
#> duckdb keeps downloaded extensions and secrets in a temporary directory:
#> ℹ /tmp/RtmpvvfSjW/duckdb
#> This is removed when the R session ends.
#> • Extensions are re-downloaded each session.
#> • Secrets are lost.
#> ℹ Run duckdb(shared_home = TRUE) (or create ~/.duckdb) to keep them (suitable for most users).
#> ℹ Run duckdb(shared_home = FALSE) to accept the temporary directory (and silence this message).
#> ℹ See ?duckdb_storage for details and alternatives.
#> Opened in-memory population 'C'
#> Defined genome: 1000 loci across 10 chromosomes | chr lengths (Mb): all equal to 100 Mb
#> Tables written: genome_meta, genome_map, ind_haplotype, ind_genotype, ind_crossover, chr_inheritance, chr_recombination, genome_effects, genome_effect_members, genome_effect_member_origins
#> Views created: genome_effect_terms, genome_effect_loci
#> Generating 100 founder haplotypes (method = "uniform")...
#> Created founder_haplotypes (100 haplotypes x 1000 loci)
pop <- pop |>
get_table("founder_haplotypes") |>
add_founders(n_males = 10, n_females = 10, line_name = "A")
#> Added 20 founders (10 males, 10 females) to line 'A'
close_pop(pop)
# No crossing over in males on any chromosome (Drosophila); a single
# non-recombining chromosome goes through define_chromosome() instead
pop <- open_pop(pop_name = "fly", db_name = ":memory:") |>
define_genome(n_loci = 400, n_chr = 4, chr_len_Mb = c(23, 46, 50, 1.4),
recombines_M = FALSE)
#> duckdb keeps downloaded extensions and secrets in a temporary directory:
#> ℹ /tmp/RtmpvvfSjW/duckdb
#> This is removed when the R session ends.
#> • Extensions are re-downloaded each session.
#> • Secrets are lost.
#> ℹ Run duckdb(shared_home = TRUE) (or create ~/.duckdb) to keep them (suitable for most users).
#> ℹ Run duckdb(shared_home = FALSE) to accept the temporary directory (and silence this message).
#> ℹ See ?duckdb_storage for details and alternatives.
#> Opened in-memory population 'fly'
#> Defined genome: 400 loci across 4 chromosomes | chr lengths (Mb): 1:23, 2:46, 3:50, 4:1.4
#> Tables written: genome_meta, genome_map, ind_haplotype, ind_genotype, ind_crossover, chr_inheritance, chr_recombination, genome_effects, genome_effect_members, genome_effect_member_origins
#> Views created: genome_effect_terms, genome_effect_loci
get_table(pop, "chr_recombination")
#> <tidybreed_table: chr_recombination> [8 rows × 4 fields]
#> # A tibble: 8 × 4
#> chr_name parent_sex line_name recombines
#> <chr> <chr> <chr> <lgl>
#> 1 1 M NA FALSE
#> 2 1 F NA TRUE
#> 3 2 M NA FALSE
#> 4 2 F NA TRUE
#> 5 3 M NA FALSE
#> 6 3 F NA TRUE
#> 7 4 M NA FALSE
#> 8 4 F NA TRUE
close_pop(pop)
