make_families <- function (af, nfam) {
nsnp <- length (af)
dads <- matrix (0 , nfam, nsnp)
mums <- matrix (0 , nfam, nsnp)
sibs1 <- matrix (0 , nfam, nsnp)
sibs2 <- matrix (0 , nfam, nsnp)
ibd <- matrix (0 , nfam, nsnp)
ibs <- matrix (0 , nfam, nsnp)
for (i in 1 : nsnp)
{
dad1 <- rbinom (nfam, 1 , af[i]) + 1
dad2 <- (rbinom (nfam, 1 , af[i]) + 1 ) * - 1
mum1 <- rbinom (nfam, 1 , af[i]) + 1
mum2 <- (rbinom (nfam, 1 , af[i]) + 1 ) * - 1
dadindex <- sample (c (TRUE , FALSE ), nfam, replace= TRUE )
dadh <- rep (NA , nfam)
dadh[dadindex] <- dad1[dadindex]
dadh[! dadindex] <- dad2[! dadindex]
mumindex <- sample (c (TRUE , FALSE ), nfam, replace= TRUE )
mumh <- rep (NA , nfam)
mumh[mumindex] <- mum1[mumindex]
mumh[! mumindex] <- mum2[! mumindex]
sib1 <- cbind (dadh, mumh)
dadindex <- sample (c (TRUE , FALSE ), nfam, replace= TRUE )
dadh <- rep (NA , nfam)
dadh[dadindex] <- dad1[dadindex]
dadh[! dadindex] <- dad2[! dadindex]
mumindex <- sample (c (TRUE , FALSE ), nfam, replace= TRUE )
mumh <- rep (NA , nfam)
mumh[mumindex] <- mum1[mumindex]
mumh[! mumindex] <- mum2[! mumindex]
sib2 <- cbind (dadh, mumh)
ibd[,i] <- (as.numeric (sib1[,1 ] == sib2[,1 ]) + as.numeric (sib1[,2 ] == sib2[,2 ])) / 2
sibs1[,i] <- rowSums (abs (sib1) - 1 )
sibs2[,i] <- rowSums (abs (sib2) - 1 )
dads[,i] <- dad1 - 1 + abs (dad2) - 1
mums[,i] <- mum1 - 1 + abs (mum2) - 1
# l[[i]] <- (sum(sib1[,1] == sib2[,1]) / nsnp + sum(sib1[,2] == sib2[,2]) / nsnp) / 2
}
# This may not be correct - getting some really large values
ibs <- scale (sibs1) * scale (sibs2)
# Just count how many alleles are in common
ibs_unw <- abs (abs (sibs1 - sibs2) - 2 ) / 2
return (list (dads= dads, mums= mums, sibs1= sibs1, sibs2= sibs2, ibd= ibd, ibs= ibs, ibs_unw= ibs_unw))
}
makePhen <- function (effs, indep, vy= 1 , vx= rep (1 , length (effs)), my= 0 ) {
if (is.null (dim (indep))) indep <- cbind (indep)
stopifnot (ncol (indep) == length (effs))
stopifnot (length (vx) == length (effs))
cors <- effs * vx / sqrt (vx) / sqrt (vy)
stopifnot (sum (cors^ 2 ) <= 1 )
cors <- c (cors, sqrt (1 - sum (cors^ 2 )))
indep <- t (t (scale (cbind (indep, rnorm (nrow (indep))))) * cors * c (vx, 1 ))
y <- drop (scale (rowSums (indep)) * sqrt (vy)) + my
return (y)
}
chooseEffects <- function (nsnp, totvar, sqrt= TRUE ) {
eff <- rnorm (nsnp)
aeff <- abs (eff)
sc <- sum (aeff) / totvar
out <- eff / sc
if (sqrt)
{
out <- sqrt (abs (out)) * sign (out)
}
return (out)
}
make_phenotypes <- function (fam, eff_gx, eff_xy, vx, vy, mx, my) {
lapply (fam, function (g)
{
u <- rnorm (nrow (g))
x <- makePhen (c (eff_gx), cbind (g), vy= vx, my= mx)
y <- makePhen (c (eff_xy), cbind (x), vy= vy, my= my)
return (data.frame (x= x, y= y))
})
}
join_populations <- function (l) {
dads <- do.call (rbind, lapply (l, function (x) x$ dads))
mums <- do.call (rbind, lapply (l, function (x) x$ mums))
sibs1 <- do.call (rbind, lapply (l, function (x) x$ sibs1))
sibs2 <- do.call (rbind, lapply (l, function (x) x$ sibs2))
ibd <- do.call (rbind, lapply (l, function (x) x$ ibd))
ibs <- do.call (rbind, lapply (l, function (x) x$ ibs))
return (list (dads= dads, mums= mums, sibs1= sibs1, sibs2= sibs2, ibd= ibd, ibs= ibs))
}
sample_populations <- function (l, n) {
x <- nrow (l$ dads)
index <- sort (sample (1 : x, n, replace= FALSE ))
l$ dads <- l$ dads[index,]
l$ mums <- l$ mums[index,]
l$ sibs1 <- l$ sibs1[index,]
l$ sibs2 <- l$ sibs2[index,]
l$ ibd <- l$ ibd[index,]
l$ ibs <- l$ ibs[index,]
l$ ibs_unw <- l$ ibs_unw[index,]
return (l)
}
makephen <- function (b, g, vx= 1 ) {
pred <- b * g
e <- rnorm (length (g), 0 , sqrt (1 - var (pred)))
return (pred+ e)
}
# Dynastic effects
dynastic_phen <- function (fam, eff_gx, eff_xy, eff_ux, eff_uy, eff_xu) {
n <- nrow (fam$ sibs1)
# parents x
# umums <- rnorm(n)
# udads <- rnorm(n)
# xmums <- makePhen(c(eff_gx, eff_ux), cbind(fam$mums, umums))
# xdads <- makePhen(c(eff_gx, eff_ux), cbind(fam$dads, udads))
x1 <- makephen (eff_gx, fam$ sibs1)
x2 <- makephen (eff_gx, fam$ sibs2)
l <- list ()
# l$dads <- data.frame(x=xdads)
# l$mums <- data.frame(x=xmums)
l$ sibs1 <- data.frame (x= x1)
l$ sibs2 <- data.frame (x= x2)
return (l)
}
sibreg <- function (g1, g2, y1, y2) {
d <- bind_rows (
tibble (
y= y1, fg= (g1+ g2)/ 2 , cg= g1- fg
),
tibble (
y= y2, fg= (g1+ g2)/ 2 , cg= g2- fg
)
)
m <- summary (lm (y ~ cg + fg, data= d))$ coef
tibble (bhat= m[2 ,1 ], se= m[2 ,2 ], pval= m[2 ,4 ], n= nrow (d), method= "sibreg" )
}
popreg <- function (y, x) {
index <- is.finite (y) & is.finite (x)
n <- sum (index)
y <- y[index]
x <- x[index]
vx <- var (x)
bhat <- cov (y, x) / vx
ahat <- mean (y) - bhat * mean (x)
# fitted <- ahat + x * bhat
# residuals <- y - fitted
# SSR <- sum((residuals - mean(residuals))^2)
# SSF <- sum((fitted - mean(fitted))^2)
rsq <- (bhat * vx)^ 2 / (vx * var (y))
fval <- rsq * (n-2 ) / (1 - rsq)
tval <- sqrt (fval)
se <- abs (bhat / tval)
# Fval <- (SSF) / (SSR/(n-2))
# pval <- pf(Fval, 1, n-2, lowe=F)
p <- pf (fval, 1 , n-2 , lowe= F)
return (tibble (
bhat= bhat, se= se, fval= fval, pval= p, n= n, method= "popreg"
))
}
sibreg2 <- function (fam, phen) {
sdiffgx <- fam$ sibs1[,1 ] - fam$ sibs2[,1 ]
sdiffx <- phen$ sibs1$ x - phen$ sibs2$ x
popreg (sdiffx, sdiffgx) %>% mutate (method= "sibreg" )
}
reg <- function (f, p) {
# sibreg(f$sibs1[,1], f$sibs2[,1], p$sibs1$x, p$sibs2$x)
bind_rows (
sibreg2 (f, p),
popreg (p$ sibs1[,1 ], f$ sibs1[,1 ])
)
}
r2 <- 0.001
param <- tibble (
af= seq (0.0001 , 0.01 , by= 0.00005 ),
vg= r2,
varg= 2 * af* (1 - af),
b= sqrt (r2/ varg)
)
res <- lapply (1 : nrow (param), \(i) {
f <- make_families (param$ af[i], 500000 )
p <- dynastic_phen (f, param$ b[i], 0 , 0 , 0 , 0 )
r <- reg (f, p)
r$ af= param$ af[i]
return (r)
}) %>% bind_rows ()