Exploring genetic and spatial competition with


Saulo Chaves

Assistant Professor

Data Science for Plant Breeding Lab

Objective

At the end of this short-course, you will be able understand the genetic competition effects on the selection process in forest tree breeding. Additionally, you will be capable of running spatial and genetic competition models, and correctly interpret their outputs.

Plants compete for above- and below-ground resources

Competition can mislead selection

  • Competitive plants can impair sensitive neighbours to express their full genetic potential
    • Challenging environments
  • Selection of aggressive individuals can decrease the correspondence between trials and commercial farms
    • Clonal mixture
  • Weak correlation between growth and quality traits

Competition models are not trivial

Quantitative genetics base of the variance-component model (Griffing, 1967):

\[ \begin{align} u_{A_1a_1} = & \; \alpha_{A_1} + \alpha_{a_1} + \delta_{A_1a_1} + \alpha_{A_2} + \alpha_{a_2} + \delta_{A_2a_2} + \\ & \; \left(\alpha \alpha \right)_{A_1A_2} + \left(\alpha \alpha \right)_{A_1a_2} + \left(\alpha \alpha \right)_{a_1A_2} + \left(\alpha \alpha \right)_{a_1a_2} +\\ & \; \left(\alpha \delta \right)_{A_1A_2a_2} + \left(\alpha \delta \right)_{a_1A_2a_2} + \left(\delta \alpha \right)_{A_1 a_1 A_2} + \left( \delta \alpha\right)_{A_1a_1a_2} + \\ & \; \left(\delta \delta \right)_{A_1a_1A_2a_2} \end{align} \]

\[ P_v = DGE_v + \sum_{k=1}^n IGE_k + e_v \]

Fear not, presenting gencomp!

# install.packages("devtools")
devtools::install_github("Kaio-Olimpio/gencomp", build_vignettes = TRUE)


library(gencomp)
library(ggplot2)

Example dataset

str(cpt)
'data.frame':   3000 obs. of  9 variables:
 $ prog       : Factor w/ 60 levels "F01xF02","F01xF03",..: 50 35 55 33 51 60 7 35 17 42 ...
 $ id         : Factor w/ 600 levels "F01xF02_13","F01xF02_19",..: 500 345 542 325 505 597 64 347 169 420 ...
 $ col        : Factor w/ 75 levels "1","2","3","4",..: 1 2 3 4 5 6 7 8 9 10 ...
 $ row        : Factor w/ 40 levels "1","2","3","4",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ block      : Factor w/ 5 levels "1","2","3","4",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ direct     : num  0.406 -8.96 7.913 -5.263 -0.219 ...
 $ competition: num  0.578 2.277 -2.677 2.348 2.139 ...
 $ e.Trait1   : num  1.37 9.97 4.81 3.07 -2.48 ...
 $ pheno      : num  29 24.4 39.5 21.8 22.8 ...
  • Simulated data
  • Partial diallel with 20 founders
  • Clonal progeny trials
  • 600 clones from 60 families
  • RCBD, single-tree plots, five replicates

1st step: Competition matrix

\[ {{\boldsymbol{Z}}}_{{c}_{1}}=\left[\begin{array}{cccccc}0&1&0&0&0&0\\ 1&1&0&0&0&0\\ 0&1&0&1&0&0\\ 0&1&0&0&0&0\\ 0&0&0&0&0&1\\ 0&0&1&0&1&0\\ 0&0&1&0&0&1\\ 0&0&0&1&0&0\\ 0&0&0&0&0&1\\ 1&0&0&0&1&0\\ 0&0&1&0&0&1\\ 1&0&0&0&0&0\end{array}\right]\quad {{\boldsymbol{Z}}}_{{c}_{2}}=\left[\begin{array}{cccccc}0&0&1&0&0&0\\ 0&0&0&1&0&0\\ 0&0&0&0&0&1\\ 0&0&0&0&1&0\\ 0&0&1&1&0&0\\ 1&1&0&0&0&0\\ 0&1&0&0&0&1\\ 1&0&0&0&1&0\\ 0&0&1&0&0&0\\ 0&0&0&1&0&0\\ 0&0&0&0&0&1\\ 0&0&0&0&1&0\end{array}\right] \]

1st step: Competition matrix

  • For trees, distance-based weights (directional competition intensity factors):
Direction Muir (2005) Cappa & Cantet (2008) Costa e Silva & Kerr (2013)
Diagonal \(\left(f_d\right)\) \(\frac{1}{\sqrt{\mathcal{D}^2_r + \mathcal{D}^2_c}}\) \(\frac{1}{\sqrt{2 \left(n_c + n_r\right) + n_d}}\) \(\frac{p}{\sqrt{\left(n_r p^4 \right) + \left(n_r p^2 \right) + \left(n_c p^2 \right) + \left(n_d p^2 \right) + n_c}}\)
Row \(\left(f_r\right)\) \(\frac{1}{\mathcal{D}_r}\) \(\sqrt{\frac{2}{2 \left(n_c + n_r\right) + n_d}}\) \(f_d \sqrt{1 + p^2}\)
Column \(\left(f_c\right)\) \(\frac{1}{\mathcal{D}_c}\) \(\sqrt{\frac{2}{2 \left(n_c + n_r\right) + n_d}}\) \(\frac{f_d \sqrt{1 + p^2}}{p}\)

\(p = {\mathcal{D}_c}/{\mathcal{D}_r}\)

1st step: Competition matrix



1st step: Competition matrix

Function prepfor

compmat = prepfor(
  data = cpt,
  gen = "id",
  row = "row",
  col = "col",
  trait = "pheno",
  plt = NULL,
  effs = "block",
  dist.row = 2,
  dist.col = 3,
  method = "SK",
  area = NULL,
  age = NULL,
  n.dec = 2,
  verbose = TRUE
)

1st step: Competition matrix

Function prepfor

plot(compmat)

1st step: Competition matrix

Function prepfor

plot(compmat, category = "boxplot") + theme(axis.text.x = element_blank(), 
                                            axis.ticks.x = element_blank())

1st step: Competition matrix

Function prepfor

  • Competition matrix:
str(compmat$Z)
 num [1:3000, 1:600] 0 0 0 0 0 0 0 0 0 0 ...
 - attr(*, "dimnames")=List of 2
  ..$ : chr [1:3000] "1" "2" "3" "4" ...
  ..$ : chr [1:600] "F01xF02_13" "F01xF02_19" "F01xF02_22" "F01xF02_47" ...
  • Competition intensity factor \(\left(\hat{\phi}=\bar{{n}_{r}}{\bar{f}}_{r}+{\bar{n}}_{c}{\bar{f}}_{c}+{\bar{n}}_{d}{\bar{f}}_{d} \right)\)
compmat$CIF
[1] 2.675279

1st step: Competition matrix

Function prepfor

  • Neighbourhood check of each tree
str(compmat$neigh_check)
'data.frame':   3000 obs. of  11 variables:
 $ gen    : Factor w/ 600 levels "F01xF02_13","F01xF02_19",..: 500 345 542 325 505 597 64 347 169 420 ...
 $ row    : num  1 1 1 1 1 1 1 1 1 1 ...
 $ col    : num  1 2 3 4 5 6 7 8 9 10 ...
 $ y_focal: num  29 24.4 39.5 21.8 22.8 ...
 $ y_row  : num  24.4 34.2 23.1 31.2 23.5 ...
 $ n_row  : num  1 2 2 2 2 2 2 2 2 2 ...
 $ y_col  : num  21.9 34.9 27.5 18.6 17.6 ...
 $ n_col  : num  1 1 1 1 1 1 1 1 1 1 ...
 $ y_diag : num  34.9 24.7 26.7 22.5 21.4 ...
 $ n_diag : num  1 2 2 2 2 2 2 2 2 2 ...
 $ y_neigh: num  27.1 30.5 25.4 25.2 21.5 ...

2nd step: Fitting the model

\[ {\boldsymbol{y}}={\boldsymbol{X}}{\boldsymbol{\beta }}+{{\boldsymbol{Z}}}_{1}{\boldsymbol{u}}+{{\boldsymbol{Z}}}_{2}{\boldsymbol{p}}+{\boldsymbol{\varepsilon}} \]

\[ \begin{align} {{\boldsymbol{u}}}^{{\prime} }=\begin{bmatrix}{\underbrace{\boldsymbol g^\prime}_{\mbox{DGE}}} & \underbrace{\boldsymbol c^\prime}_{\mbox{IGE}}\end{bmatrix} && \boldsymbol Z_1 = \begin{bmatrix} \underbrace{\boldsymbol Z_g}_{\mbox{DGE}} & \underbrace{\boldsymbol Z_c}_{\mbox{IGE}} \end{bmatrix} \end{align} \]

\[ \boldsymbol{u} \sim \mathcal{N} \left(\underbrace{\begin{bmatrix} \boldsymbol 0 \\ \boldsymbol 0 \end{bmatrix}}_{\mu}, \underbrace{\begin{bmatrix} \sigma^2_g & \sigma_{gc} \\ \sigma_{gc} & \sigma^2_c\end{bmatrix} \otimes \boldsymbol K}_{\operatorname{Var}\left(\boldsymbol u\right)}\right) \]

\[ \boldsymbol \varepsilon \sim \left[\boldsymbol 0, \sigma^2_\varepsilon \left(\boldsymbol{AR1}_R \otimes \boldsymbol{AR1}_C \right)\right] \]

2nd step: Fitting the model

Function asr: No relationship matrix

mod1 = asr(
  prep.out = compmat,
  fixed = pheno ~ block,
  random = ~ 1,
  spatial = TRUE,
  cor = TRUE,
  lrtest = TRUE
)

Function asr: With relationship ⚠️ Major Feature Release ⚠️

ped = unique(as.data.frame(cbind(
  do.call(rbind, strsplit(as.character(cpt[, 1]), split = "x")), as.character(cpt[, 2])
)))
ped = ped[, c(3, 1, 2)]
ainv = asreml::ainverse(ped)

mod2 = asr(
  prep.out = compmat,
  fixed = pheno ~ block,
  random = ~ 1,
  spatial = TRUE,
  cor = TRUE,
  lrtest = TRUE,
  K = ainv
)

2nd step: Fitting the model

About the relationship matrix

A sparse inverse variance matrix held in three-column coordinate form in row-major order. For backwards compatibility, a three-column data frame is also accepted. In either case, the source must have a rowNames attribute. This object must have class ginv from a call to asreml::ainverse(), or have attribute INVERSE set to TRUE. If the attribute INVERSE is not set then FALSE is assumed. We recommend using the ASRgenomics package to set the genomic relationship matrix (see ASRgenomics::G.matrix() and ASRgenomics::G.inverse()). If there is no relationship information, K = NULL (default)

str(ainv)
 'matrix' num [1:1880, 1:3] 1 2 3 3 4 4 5 5 5 6 ...
 - attr(*, "inbreeding")= Named num [1:620] 0 0 0 0 0 0 0 0 0 0 ...
  ..- attr(*, "names")= chr [1:620] "F17" "F12" "F19" "F11" ...
 - attr(*, "logdet")= num -416
 - attr(*, "dimnames")=List of 2
  ..$ : NULL
  ..$ : chr [1:3] "Row" "Column" "Ainverse"
 - attr(*, "rowNames")= chr [1:620] "F17" "F12" "F19" "F11" ...
 - attr(*, "geneticGroups")= num [1:2] 0 0

3rd step: Extracting the outputs

Function resp

outs = resp(
  prep.out = compmat,
  model = mod2,
  weight.tgv = TRUE,
  sd.class = 1
)

outs$lrt
  effect LR-statistic    Pr(Chisq)
1    DGE     541.2104 0.000000e+00
2    IGE      40.3012 1.088375e-10
outs$varcomp
                  component  std.error   z.ratio bound %ch
cor(IGE_DGE)    -0.73740806 0.07773369 -9.486338     U 0.1
DGE             21.52088403 2.11141011 10.192659     P 0.1
IGE              4.01501998 0.77251608  5.197329     P 0.0
R               37.72756142 1.16113954 32.491841     P 0.0
R=autocor(row): -0.14501420 0.02162016 -6.707362     U 0.1
R=autocor(col): -0.04126034 0.02236380 -1.844961     U 0.2

3rd step: Extracting the outputs

If competition is significant, selection should be based on the Total Genetic Value (TGV):

  • Unweighted (weight.tgv = FALSE):

\[ TGV_v = \hat{g}_v + \hat{\phi} \times \hat{c}_v \]

  • Weighted by the reliability (weight.tgv = TRUE):

\[ {wTGV}_{v}={\hat{g}}_{v}\times {r}_{{g}_{v}}^{2}+\hat{\phi }\times {\hat{c}}_{v}\times {r}_{{c}_{V}}^{2} \]

3rd step: Extracting the outputs

Competition classes

\[ \,{\text{Classes}}\,=\left\{\begin{array}{l}\bar{{\rm{c}}}-\tau \; {\rm{sd}}({\rm{c}}) \,<\,{\hat{{\rm{c}}}}_{{\rm{v}}} \,<\, \bar{{\rm{c}}}+\tau \; {\rm{sd}}({\rm{c}})\to \,{\text{Homeostatic}}\,\quad \\ {\hat{{\rm{c}}}}_{{\rm{v}}} \,<\,\bar{{\rm{c}}}-\tau \; {\rm{sd}}({\rm{c}})\to \,{\text{Aggressive}}\,\quad \\ {\hat{{\rm{c}}}}_{{\rm{v}}} \,>\, \bar{{\rm{c}}}+\tau \; {\rm{sd}}({\rm{c}})\to \,{\text{Sensitive}}\,\quad \end{array}\right. \]

\(\tau \to\) weight defining the classifier sensitivity

Function resp

head(outs$blups$main[,-c(3,6)])
             id        DGE   rel.DGE       IGE   rel.IGE       class      TGV
1           F01 -3.2758934 0.8973572 3.2176001 0.8295542   Sensitive 4.201138
497         F17 -2.3111288 0.8973443 2.6525694 0.8303412   Sensitive 3.818525
155  F05xF08_93  2.2160810 0.7484024 1.1821025 0.6314346 Homeostatic 3.655404
22  F01xF04_100  3.7465442 0.7495402 0.4777074 0.6272911 Homeostatic 3.609864
218         F08  0.5368863 0.8978368 1.4116096 0.8274290 Homeostatic 3.606780
27   F01xF04_56  2.7817749 0.7493080 0.8514380 0.6304831 Homeostatic 3.520542

3rd step: Extracting the outputs

  • Broad- or narrow-sense heritability

\[ H^2_g = \frac{\sigma^2_g}{\sigma^2_y} \]

\[ H^2_t = \frac{\sigma^2_g + 2 \phi \sigma_{gc} + \phi^2 \sigma^2_c}{\sigma^2_y} \]

outs$heritability
       Heritability
direct    0.3401787
total     0.2146729

3rd step: Extracting the outputs

Function resp

plot(outs, category = "DGE.IGE") + theme(axis.text.x = element_blank(), 
                                         axis.ticks.x = element_blank())

3rd step: Extracting the outputs

Function resp

plot(outs, category = "TGV") + theme(axis.text.x = element_blank(), 
                                         axis.ticks.x = element_blank())

3rd step: Extracting the outputs

Function resp

plot(outs, category = "class")

3rd step: Extracting the outputs

Function resp

plot(outs, category = "DGEvIGE")

3rd step: Extracting the outputs

Function resp

plot(outs, category = "nneigh")  + theme(axis.text.x = element_blank(), 
                                         axis.ticks.x = element_blank())

3rd step: Extracting the outputs

Function resp

ggpubr::ggarrange(
  plot(outs, category = "grid.res"),
  plot(outs, category = "grid.dge"),
  plot(outs, category = "grid.ige"),
  plot(outs, category = "grid.class")
)

Concluding remarks

gencomp is a user-friendly tool that facilitates the fitting and utilization of (spatial-) genetic competition models. It is worth mentioning that gencomp is a work in progress and will continue to evolve as we introduce additional functionalities

Acknowledgements