I had been running my mixed-model GWAS with GCTA’s --mlma-loco for a while, quite happily, until I tried to be clever about the GRM and ran straight into a wall. Sorting out why led me to fastGWA (Jiang et al., Nature Genetics 2019), and to finally understanding a word I’d been nodding along to for years without really getting: polygenicity. So this post is half a tooling decision and half a concept I should have learned ages ago.
1. The wall I hit with --mlma-loco
A mixed-model GWAS fits, for every individual, roughly this:
phenotype = (effect of the SNP being tested) + g + e
That middle term g is a per-individual genetic value modeled through a GRM (genetic relationship matrix) — a big matrix of “how genetically similar is every pair of individuals.” It’s the thing that lets the model say these two people resemble each other genetically, so don’t get excited when their phenotypes resemble each other either. It’s how you stop relatedness and population structure from manufacturing fake associations.
--mlma-loco builds that GRM in a clever leave-one-chromosome-out way: when testing SNPs on chromosome 1, it builds the GRM from chromosomes 2–N (and so on), so a SNP is never used to correct itself. Good design.
Here was my problem. I have tens of millions of variants, and I did not want to build the GRM from all of them — partly cost, partly because a GRM doesn’t need every redundant SNP in an LD block. I wanted to feed --mlma-loco a nice LD-pruned, common-SNP set for the GRM, while still testing every variant. And --mlma-loco simply won’t let you: it takes one --bfile and uses it for both the GRM and the association tests. The GRM SNPs and the test SNPs are welded together.
(There’s a manual workaround — build per-chromosome GRMs yourself and stitch LOCO back together with --mlma-subtract-grm — but it’s fiddly, and it turned out I was solving the wrong problem.)
2. Enter fastGWA, with a different philosophy
fastGWA was built for biobank-scale data (hundreds of thousands of samples), where a dense GRM is simply too big to compute or store. Its trick is a sparse GRM: compute the relationships, then zero out every relationship below a cutoff (default 0.05). What survives is only close relatives — sibs, half-sibs, parent–offspring, cousins. Everyone else is treated as unrelated.
That sounds reckless until you see the division of labour:
- Population structure → handled by principal components as fixed-effect covariates (you supply them).
- Close family relatedness → handled by the sparse GRM random effect.
So fastGWA splits the job that --mlma-loco does with one dense GRM into two specialised pieces. And crucially for me: the GRM is a separate input from the genotypes you test. You build the sparse GRM once, from whatever (pruned) set you like, and point the association step at the full set:
# sparse GRM, built once, from a pruned common-SNP set
gcta64 --bfile grm_snps --make-grm --out grm_full
gcta64 --grm grm_full --make-bK-sparse 0.05 --out grm_sparse
# test the FULL set; GRM supplied separately
gcta64 --fastGWA-mlm --bfile full_set --grm-sparse grm_sparse \
--qcovar pcs.txt --pheno pheno.txt --out result
The exact decoupling I’d been fighting --mlma-loco for is just… how the tool works. The GRM is built once instead of rebuilt per chromosome, and LOCO stops being a worry — because a sparse GRM barely contains the tested SNP’s signal in the first place, there’s nothing meaningful to leak.
3. The thing I finally understood: polygenicity
Here’s where I had to stop and learn something. The difference between the dense GRM and the sparse GRM is really a difference in how much polygenicity they model. So what is it?
A trait is polygenic when it’s shaped by many variants — hundreds to thousands — each nudging the trait by a tiny amount, instead of a few big-effect genes. Basically every complex quantitative trait is like this. The causal alleles are sprinkled all over the genome and none of them is a smoking gun.
That g term above is the polygenic background: the summed effect of all those tiny variants for a given individual. We never estimate them one by one. Instead we say: two people who are genetically similar overall (high GRM value) probably share a lot of those small alleles, so their g should be similar too. Modeling g does two jobs — it removes confounding (structure/relatedness that would otherwise fake associations) and it buys power (it soaks up variance explained by the rest of the genome, so the SNP you’re testing stands out against a quieter background).
Now the dense-vs-sparse difference becomes clear:
- Dense GRM (
--mlma-loco) uses every pairwise similarity, including the faint, diffuse resemblance among people who aren’t relatives at all. Sogcaptures the full genome-wide polygenic background. - Sparse GRM (fastGWA) keeps only close-kin similarities. Its
gis really just family resemblance. The diffuse polygenic sharing across the whole sample is not in the random effect — fastGWA leans on the PCs to handle the structure part of it.
So when people say fastGWA “doesn’t model the full polygenic background,” that’s what they mean: it deliberately drops the diffuse genome-wide term and trusts your PCs to mop up structure instead.
4. So which should I use?
My case: a quantitative trait, a few thousand individuals (not biobank-scale), lots of real family structure from pedigree, and several distinct populations. I already add PCs to my model either way. Pulling it apart:
- I’m not in the regime where fastGWA is required — at a few thousand samples a dense GRM is perfectly affordable. So speed isn’t the deciding factor.
- My biggest confounders are family relatedness (handled by both) and gross population structure (handled by my PCs either way). Those do almost all of the work.
- What I’d give up by going sparse is only the diffuse polygenic-background term — usually a modest power difference, not a correctness problem.
- What I’d gain is the clean GRM/test-set separation, a GRM built once, and a tool that’s literally designed around family data via its sparse GRM.
For me that trade comes out in fastGWA’s favour, mostly because it solves my original problem by design instead of by workaround. The one discipline it demands: since fastGWA relies on the PCs to control structure rather than a dense GRM, I need enough PCs and I need to actually check the QQ plot / λ_GC to confirm structure is controlled. With a dense GRM that check is a bit more forgiving; with fastGWA it’s on me.
A quick way to hold the whole decision in your head:
--mlma-loco |
fastGWA | |
|---|---|---|
| GRM | dense, rebuilt per chromosome | sparse, built once |
| Polygenic background | full (diffuse + family) | family only |
| Structure control | dense GRM (+ PCs) | PCs (+ sparse GRM for kin) |
| GRM vs test set | same --bfile |
separate inputs |
| Sweet spot | moderate N, want full polygenic modeling | large N, or you want GRM/test decoupled |
5. Takeaway
I went looking for a way to feed --mlma-loco a pruned GRM and a full test set, and the real answer wasn’t a clever flag — it was a different tool with a different theory of where confounding comes from. --mlma-loco says “one dense GRM models everything, including polygenic background.” fastGWA says “let PCs handle structure, let a sparse GRM handle family, and don’t bother modeling diffuse polygenicity at all.” For biobank scale that’s a necessity; for my structured, pedigree-heavy, moderate-N quantitative dataset it’s just a cleaner fit — as long as I keep an eye on my PCs.