seg_multi: Parallelized likelihood ratio test for segregation distortion...

View source: R/higher_freq.R

seg_multiR Documentation

Parallelized likelihood ratio test for segregation distortion for arbitrary (even) ploidies.

Description

Uses the future package to implement parallelization support for the likelihood ratio tests for segregation distortion. Details of this test are provided in the seg_lrt() function's documentation. See Gerard et al. (2025) for details of the methods.

Usage

seg_multi(
  g,
  p1_ploidy,
  p2_ploidy = p1_ploidy,
  p1 = NULL,
  p2 = NULL,
  model = c("seg", "auto", "auto_dr", "allo", "allo_pp", "auto_allo"),
  outlier = TRUE,
  ret_out = FALSE,
  ob = 0.03,
  db = c("ces", "prcs"),
  ntry = 3,
  df_tol = 0.001
)

Arguments

g

One of two inputs

  • A matrix of genotype counts. The rows index the loci and the columns index the genotypes.

  • An array of genotype log-likelihoods. The rows index the loci, the columns index the individuals, and the slices index the genotypes. Log-likelihoods are base e (natural log).

p1_ploidy, p2_ploidy

The ploidy of the first or second parent. Should be even.

p1

One of three inputs

  • A vector of parent 1's genotypes.

  • A matrix of parent 1's genotype log-likelihoods. The rows index the loci and the columns index the genotypes. Logs are in base e (natural log).

  • NULL (only supported when using genotype likelihoods for the offspring)

p2

One of three inputs

  • A vector of parent 1's genotypes.

  • A matrix of parent 1's genotype log-likelihoods. The rows index the loci and the columns index the genotypes. Logs are in base e (natural log).

  • NULL (only supported when using genotype likelihoods for the offspring)

model

One of six forms:

"seg"

Segmental allopolyploid. Allows for arbitrary levels of polysomic and disomic inheritance. This can account for partial preferential pairing. It also accounts for double reduction at simplex loci.

"auto"

Autopolyploid. Allows only for polysomic inheritance. No double reduction.

"auto_dr"

Autopolyploid, allowing for the effects of double reduction.

"allo"

Allopolyploid. Only complete disomic inheritance is explored.

"allo_pp"

Allopolyploid, allowing for the effects of partial preferential pairing. Though, autopolyploid (with complete bivalent pairing and no double reduction) is a special case of this model.

"auto_allo"

Only complete disomic and complete polysomic inheritance is studied.

outlier

A logical. Should we allow for outliers (TRUE) or not (FALSE)?

ret_out

A logical. Should we return the probability that each individual is an outlier (TRUE) or not (FALSE)?

ob

The default upper bound on the outlier proportion.

db

Should we use the complete equational segregation model ("ces") or the pure random chromatid segregation model ("prcs") to determine the upper bound(s) on the double reduction rate(s). See drbounds() for details.

ntry

The number of times to try the optimization. You probably do not want to touch this.

df_tol

Threshold for the rank of the Jacobian for the degrees of freedom calculation. This accounts for weak identifiability in the null model. You probably do not want to touch this.

Value

A data frame with the following elements:

statistic

The likelihood ratio test statistic

p_value

The p-value of the likelihood ratio test.

df

The (estimated) degrees of freedom of the test.

null_bic

The BIC of the null model (no segregation distortion).

df0

The (estimated) number of parameters under null.

df1

The (estimated) number of parameters under the alternative.

p1

The (estimated) genotype of parent 1.

p2

The (estimated) genotype of parent 2.

q0

The MLE of the genotype frequencies under the null.

q1

The MLE of the genotype frequencies under the alternative.

outprob

Outlier probabilities. Only returned in ret_out = TRUE.

  • If using genotype counts, element i is the probability that an individual with genotype i-1 is an outlier. So the return vector has length ploidy plus 1.

  • If using genotype log-likelihoods, element i is the probability that individual i is an outlier. So the return vector has the same length as the number of individuals.

These outlier probabilities are only valid if the null of no segregation is true.

Note that since this data frame contains the list-columns q0 and q1, you cannot use write.csv() to save it. You have to either remove those columns first or use something like saveRDS()

Parallel Computation

The seg_multi() function supports parallel computing. It does so through the future package.

You first specify the evaluation plan with plan() from the future package. On a local machine, this is typically just future::plan(future::multisession, workers = nc) where nc is the number of workers you want. You can find the maximum number of possible workers with availableCores(). You then run seg_multi(), then shut down the workers with future::plan(future::sequential). The pseudo code is

  future::plan(future::multisession, workers = nc)
  seg_multi()
  future::plan(future::sequential)

Null Model

The gamete frequencies under the null model can be calculated via gamfreq(). The genotype frequencies, which are just a discrete linear convolution (convolve()) of the gamete frequencies, can be calculated via gf_freq().

The null model's gamete frequencies for true autopolyploids (model = "auto") or true allopolyploids (model = "allo") are given in the seg data frame that comes with this package. I only made that data frame go up to ploidy 20, but let me know if you need it for higher ploidies.

The polyRAD folks test for full autopolyploid and full allopolyploid, so I included that as an option (model = "auto_allo").

We can account for arbitrary levels of double reduction in autopolyploids (model = "auto_dr") using the gamete frequencies from Huang et al (2019).

The null model for segmental allopolyploids (model = "allo_pp") is the mixture model of the possible allopolyploid gamete frequencies. The autopolyploid model (without double reduction) is a subset of this mixture model.

In the above mixture model, we can account for double reduction for simplex loci (model = "seg") by just slightly reducing the number of simplex gametes and increasing the number of duplex and nullplex gametes. That is, the frequencies for (nullplex, simplex, duplex) gametes go from (0.5, 0.5, 0) to (0.5 + b, 0.5 - 2 * b, b).

model = "seg" is the most general, so it is the default. But you should use other models if you have more information on your species. E.g. if you know you have an autopolyploid, use either model = "auto" or model = "auto_dr".

Unidentified Parameters

Do NOT interpret the estimated parameters in the null$gam list. These parameters are weakly identified (I had to do some fancy spectral methods to account for this in the null distribution of the tests). Even though they are technically identified, you would need a massive data set to be able to estimate them accurately.

Author(s)

David Gerard

References

  • Gerard, D, Ambrosano, GB, Pereira, GdS, & Garcia, AAF (2025). Tests for segregation distortion in higher ploidy F1 populations. bioRxiv, p. 1-20. \Sexpr[results=rd]{tools:::Rd_expr_doi("10.1101/2025.06.23.661114")}

See Also

  • seg_lrt() Single locus LRT for segregation distortion.

  • gamfreq() Gamete frequencies under various models of meiosis

  • gf_freq() F1 genotype frequencies under various models of meiosis.

  • multidog_to_g() Converts the output of updog::multidog() into something that you can input into seg_multi().

Examples


## Assuming genotypes are known (typically a bad idea)
glist <- multidog_to_g(
  mout = ufit,
  ploidy = 4,
  type = "all_g",
  p1 = "indigocrisp",
  p2 = "sweetcrisp")
p1_1 <- glist$p1
p2_1 <- glist$p2
g_1 <- glist$g
s1 <- seg_multi(
  g = g_1,
  p1_ploidy = 4,
  p2_ploidy = 4,
  p1 = p1_1,
  p2 = p2_1)
s1[, c("snp", "p_value")]

## Put NULL if you have absolutely no information on the parents
s2 <- seg_multi(g = g_1, p1_ploidy = 4, p2_ploidy = 4, p1 = NULL, p2 = NULL)
s2[, c("snp", "p_value")]

## Using genotype likelihoods (typically a good idea)
## Also demonstrate parallelization through future package.
glist <- multidog_to_g(
  mout = ufit,
  ploidy = 4,
  type = "all_gl",
  p1 = "indigocrisp",
  p2 = "sweetcrisp")
p1_2 <- glist$p1
p2_2 <- glist$p2
g_2 <- glist$g

# future::plan(future::multisession, workers = 2)
# s3 <- seg_multi(
#   g = g_2,
#   p1_ploidy = 4,
#   p2_ploidy = 4,
#   p1 = p1_2,
#   p2 = p2_2,
#   ret_out = TRUE)
# future::plan(future::sequential)
# s3[, c("snp", "p_value")]

## Outlier probabilities are returned if `ret_out = TRUE`
# graphics::plot(s3$outprob[[6]], ylim = c(0, 1))



segtest documentation built on July 1, 2025, 1:07 a.m.