Parent-offspring conflicts between the genotypes and the pedigree
Source:R/io_qc.R
parentage_check.RdFor every animal whose sire or dam is genotyped together with it, counts the markers
called in both and, among them, the opposite homozygotes (0 in one, 2 in the other),
which Mendel forbids between a parent and its offspring, genotyping error aside. A
rate above exclusion_threshold says the pedigree or the sample is wrong: a parent
recorded by mistake, a sample swap. The rule and the default 1% are the exclusion test
of preGSf90 (verify_parentage, exclusion_threshold 1; Hayes 2011), with one
difference: preGSf90 divides by every SNP, and here the denominator is the markers
called in both, so a pair with many missing calls is not diluted. A true pair shows only
the genotyping error, and an unrelated pair 2 p^2 q^2 per marker (12.5% at
p = 0.5), some 5% to 10% over a common panel. The column of maternal grandsires of a
sire_mgs() pedigree is left out, since grandparent and grandchild can be opposite
homozygotes.
Usage
parentage_check(
pedigree,
genotypes,
exclusion_threshold = 0.01,
sex_markers = genotypes[["sex_markers", exact = TRUE]]
)Arguments
- pedigree
data.frame animal, sire, dam (or a
sire_mgs()pedigree). A repeated animal is refused; a genotyped animal missing from it is a warning, and none at all an error, because no pair would read as no conflict- genotypes
list with
idsandm(0/1/2, NA for missing), and optionallysex_markers- exclusion_threshold
fraction of opposite homozygotes, among the markers called in both, above which the pair is a conflict
- sex_markers
the columns of
mon the sex chromosomes (indices, names or a logical vector), left out of the test; by defaultgenotypes$sex_markers, andNULLtests every marker
Value
a data.frame with one row per genotyped parent-offspring pair, in pedigree
order: id (the offspring), parent, type ("sire" or "dam"), markers
(called in both), opposite (opposite homozygotes), rate (their fraction) and
conflict (rate > exclusion_threshold)
Details
Use autosomal markers: PLINK codes a male hemizygous X as homozygous, and a son takes
his X from the dam, so a sire and son are opposite homozygotes on about 2pq of the X
markers with no error at all; with 3% of a chip on the X that alone is about 1%, the
threshold. preGSf90 skips the sex chromosomes in this test (sex_chr); here
sex_markers = does it, with the map that read_plink() returns, or a
genotypes$sex_markers element, which qc_genotypes() sets when it is given them.
Unlike the fitters, this function does not refuse an animal with a low call rate: it imputes nothing, and each pair is counted over the markers called in both.
Every single-step fitter runs the same check, on every marker it is given but those
that genotypes$sex_markers names, and warns, naming the pairs, when one exceeds 1%;
it then fits the data as given. The two remedies:
set the wrong parent unknown in the pedigree (below), or drop the offspring's genotype,
which is what preGSf90 does by default and what qc_genotypes(genotypes, pedigree = )
does. options(BreedingR.verify_parentage = FALSE) (or 0, the verify_parentage 0 of
preGSf90) turns the fitters' check off, for genotypes simulated without the pedigree,
where every pair conflicts by construction; this function and qc_genotypes() still run
it.
References
Hayes, B.J. (2011). Technical note: Efficient parentage assignment and pedigree reconstruction with dense single nucleotide polymorphism data. Journal of Dairy Science 94:2114-2117.
Misztal, I. et al. (2018). Manual for BLUPF90 family of programs, preGSf90 (verify_parentage, exclusion_threshold, sex_chr).
Examples
s <- simulate_breeding(20, 2, 20, n_markers = 300, seed = 1)
g <- s$genotypes
ped <- s$pedigree
# a wrong sire for the first genotyped offspring
filho <- which(ped$sire %in% g$ids & ped$id %in% g$ids)[1]
ped$sire[filho] <- setdiff(g$ids, c(ped$id[filho], ped$sire[filho]))[1]
ck <- parentage_check(ped, g)
ck[ck$conflict, ]
#> id parent type markers opposite rate conflict
#> 1 G1_001 F001 sire 300 23 0.07666667 TRUE
# one remedy: the parent in conflict becomes unknown
ruim <- ck[ck$conflict & ck$type == "sire", ]
ped$sire[match(ruim$id, ped$id)] <- "0"