
Bio Workflows Gwas Pipeline
- 3 installs
- 1.1k repo stars
- Updated July 25, 2026
- gptomics/bioskills
Run an end-to-end GWAS from VCF through PLINK QC, population structure correction, and association testing.
About
Orchestrates sample/variant QC, PCA-based population stratification correction, and association testing with PLINK2 for case-control or quantitative traits. A developer uses it to run genome-wide association studies with Manhattan/QQ visualization and lambda checks.
- PLINK2 QC, PCA structure correction, and association testing
- QC checkpoints on call rates, HWE, stratification, and lambda
Bio Workflows Gwas Pipeline by the numbers
- 3 all-time installs (skills.sh)
- Ranked #1,661 of 2,064 Data Science & ML skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/gptomics/bioskills --skill bio-workflows-gwas-pipelineAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 3 |
|---|---|
| repo stars | ★ 1.1k |
| Last updated | July 25, 2026 |
| Repository | gptomics/bioskills ↗ |
What it does
Run an end-to-end GWAS from VCF through PLINK QC, population structure correction, and association testing.
Files
Version Compatibility
Reference examples tested with: ggplot2 3.5+
Before using code patterns, verify installed versions match. If versions differ:
- R:
packageVersion('<pkg>')then?function_nameto verify parameters - CLI:
<tool> --versionthen<tool> --helpto confirm flags
If code throws ImportError, AttributeError, or TypeError, introspect the installed package and adapt the example to match the actual API rather than retrying.
GWAS Pipeline
"Run a GWAS from my genotype data" -> Orchestrate sample/variant QC (PLINK2), population stratification (PCA), association testing (linear/logistic regression), multiple testing correction, and Manhattan/QQ plot visualization.
Complete workflow for genome-wide association studies from genotype data to significant associations.
Workflow Overview
VCF/PLINK files
|
v
[1. QC Filtering] ------> Sample and variant QC
|
v
[2. LD Pruning] --------> Independent variants for PCA
|
v
[3. Population Structure] --> PCA for covariates
|
v
[4. Association Testing] --> Logistic/linear regression
|
v
[5. Results] -----------> Manhattan plot, QQ plot
|
v
Significant associationsStep 1: Data Import and QC
Convert VCF to PLINK
# VCF to PLINK binary format
plink2 --vcf input.vcf.gz \
--make-bed \
--out study
# Or with phenotype/covariate files
plink2 --vcf input.vcf.gz \
--pheno phenotypes.txt \
--make-bed \
--out studySample QC
# Calculate sample statistics
plink2 --bfile study \
--missing \
--out study_stats
# Remove samples with high missing rate (>5%)
plink2 --bfile study \
--mind 0.05 \
--make-bed \
--out study_sample_qc
# Check for sex discrepancies (if sex chromosome data available)
plink2 --bfile study_sample_qc \
--check-sex \
--out study_sex_check
# Remove related individuals (optional, requires IBD)
plink2 --bfile study_sample_qc \
--king-cutoff 0.0884 \
--make-bed \
--out study_unrelatedVariant QC
# Apply standard variant filters
plink2 --bfile study_sample_qc \
--geno 0.05 \
--maf 0.01 \
--hwe 1e-6 \
--make-bed \
--out study_qc
# Summary
plink2 --bfile study_qc --freq --out study_qcQC Checkpoint:
- Sample call rate >95%
- Variant call rate >95%
- MAF >1%
- HWE p-value >1e-6 (controls only for case-control)
Step 2: LD Pruning for PCA
# Identify independent variants
plink2 --bfile study_qc \
--indep-pairwise 50 5 0.2 \
--out pruned
# Extract pruned variants
plink2 --bfile study_qc \
--extract pruned.prune.in \
--make-bed \
--out study_prunedStep 3: Population Structure (PCA)
# Calculate principal components
plink2 --bfile study_pruned \
--pca 10 \
--out study_pca
# The eigenvec file contains PCs for use as covariatesVisualize PCA
library(ggplot2)
# Load PCA results
pca <- read.table('study_pca.eigenvec', header = FALSE)
colnames(pca) <- c('FID', 'IID', paste0('PC', 1:10))
# Load phenotype for coloring
pheno <- read.table('phenotypes.txt', header = TRUE)
pca <- merge(pca, pheno, by = c('FID', 'IID'))
# Plot
ggplot(pca, aes(x = PC1, y = PC2, color = as.factor(PHENO))) +
geom_point(alpha = 0.5) +
labs(title = 'PCA of Study Samples', color = 'Phenotype') +
theme_minimal()
ggsave('pca_plot.pdf', width = 8, height = 6)Step 4: Association Testing
Case-Control (Binary Trait)
# Logistic regression with PCA covariates
plink2 --bfile study_qc \
--pheno phenotypes.txt \
--covar study_pca.eigenvec \
--covar-col-nums 3-12 \
--glm hide-covar \
--out gwas_results
# Results in gwas_results.PHENO.glm.logisticQuantitative Trait
# Linear regression
plink2 --bfile study_qc \
--pheno phenotypes.txt \
--pheno-name BMI \
--covar study_pca.eigenvec \
--covar-col-nums 3-12 \
--glm hide-covar \
--out gwas_bmi
# Results in gwas_bmi.BMI.glm.linearWith Additional Covariates
# Include age, sex, and PCs
plink2 --bfile study_qc \
--pheno phenotypes.txt \
--covar covariates.txt \
--covar-name AGE,SEX,PC1-PC10 \
--glm hide-covar \
--out gwas_adjustedStep 5: Results Visualization
Manhattan Plot
library(qqman)
# Load results
results <- read.table('gwas_results.PHENO.glm.logistic', header = TRUE)
results <- results[!is.na(results$P),]
# Manhattan plot
png('manhattan.png', width = 1200, height = 600)
manhattan(results, chr = 'X.CHROM', bp = 'POS', snp = 'ID', p = 'P',
suggestiveline = -log10(1e-5), genomewideline = -log10(5e-8))
dev.off()
# QQ plot
png('qq_plot.png', width = 600, height = 600)
qq(results$P)
dev.off()Calculate Genomic Inflation
# Lambda (genomic inflation factor)
chisq <- qchisq(1 - results$P, 1)
lambda <- median(chisq) / qchisq(0.5, 1)
cat('Lambda:', round(lambda, 3), '\n')
# Lambda should be close to 1.0 (1.0-1.1 acceptable)Extract Significant Hits
# Genome-wide significant (p < 5e-8)
awk '$12 < 5e-8' gwas_results.PHENO.glm.logistic > significant_hits.txt
# Suggestive (p < 1e-5)
awk '$12 < 1e-5' gwas_results.PHENO.glm.logistic > suggestive_hits.txtParameter Recommendations
| Step | Parameter | Value |
|---|---|---|
| Sample QC | --mind | 0.05 |
| Variant QC | --geno | 0.05 |
| Variant QC | --maf | 0.01 |
| Variant QC | --hwe | 1e-6 |
| LD pruning | --indep-pairwise | 50 5 0.2 |
| PCA | --pca | 10 |
| Significance | p-value | 5e-8 |
Troubleshooting
| Issue | Likely Cause | Solution |
|---|---|---|
| High lambda (>1.1) | Population stratification | Add more PCs, check ancestry |
| No significant hits | Low power | Increase sample size, meta-analysis |
| Deflated lambda (<1) | Over-correction | Reduce PC covariates |
| QQ deviation at low end | Batch effects | Check for technical artifacts |
Complete Pipeline Script
#!/bin/bash
set -e
INPUT_VCF="genotypes.vcf.gz"
PHENO="phenotypes.txt"
OUTDIR="gwas_results"
mkdir -p ${OUTDIR}
# Step 1: Convert and QC
plink2 --vcf ${INPUT_VCF} --make-bed --out ${OUTDIR}/raw
plink2 --bfile ${OUTDIR}/raw --mind 0.05 --geno 0.05 --maf 0.01 --hwe 1e-6 \
--make-bed --out ${OUTDIR}/qc
# Step 2: LD pruning
plink2 --bfile ${OUTDIR}/qc --indep-pairwise 50 5 0.2 --out ${OUTDIR}/pruned
plink2 --bfile ${OUTDIR}/qc --extract ${OUTDIR}/pruned.prune.in \
--make-bed --out ${OUTDIR}/pruned
# Step 3: PCA
plink2 --bfile ${OUTDIR}/pruned --pca 10 --out ${OUTDIR}/pca
# Step 4: Association
plink2 --bfile ${OUTDIR}/qc --pheno ${PHENO} \
--covar ${OUTDIR}/pca.eigenvec --covar-col-nums 3-12 \
--glm hide-covar --out ${OUTDIR}/gwas
echo "=== GWAS Complete ==="
echo "Results: ${OUTDIR}/gwas.*.glm.*"Related Skills
- database-access/ensembl-rest - VEP annotation for top GWAS variants (per-variant); local VEP for >1K
- database-access/biomart-queries - Bulk SNP-to-gene mapping via BioMart
- population-genetics/plink-basics - PLINK file formats and commands
- population-genetics/population-structure - PCA and admixture
- population-genetics/association-testing - Statistical models
- population-genetics/linkage-disequilibrium - LD concepts
#!/bin/bash
# Reference: ggplot2 3.5+ | Verify API if version differs
# Complete GWAS workflow with PLINK2
set -e
INPUT_VCF="genotypes.vcf.gz"
PHENO_FILE="phenotypes.txt"
OUTDIR="gwas_results"
mkdir -p ${OUTDIR}
echo "=== GWAS Pipeline ==="
# === Step 1: Import and Initial QC ===
echo "=== Step 1: Data Import and QC ==="
# Convert VCF to PLINK
plink2 --vcf ${INPUT_VCF} \
--make-bed \
--out ${OUTDIR}/raw
echo "Initial variants: $(wc -l < ${OUTDIR}/raw.bim)"
echo "Initial samples: $(wc -l < ${OUTDIR}/raw.fam)"
# Sample QC: remove high missing rate
plink2 --bfile ${OUTDIR}/raw \
--mind 0.05 \
--make-bed \
--out ${OUTDIR}/sample_qc
# Variant QC
plink2 --bfile ${OUTDIR}/sample_qc \
--geno 0.05 \
--maf 0.01 \
--hwe 1e-6 \
--make-bed \
--out ${OUTDIR}/qc
echo "After QC variants: $(wc -l < ${OUTDIR}/qc.bim)"
echo "After QC samples: $(wc -l < ${OUTDIR}/qc.fam)"
# === Step 2: LD Pruning ===
echo "=== Step 2: LD Pruning ==="
plink2 --bfile ${OUTDIR}/qc \
--indep-pairwise 50 5 0.2 \
--out ${OUTDIR}/ld_prune
echo "Independent variants: $(wc -l < ${OUTDIR}/ld_prune.prune.in)"
plink2 --bfile ${OUTDIR}/qc \
--extract ${OUTDIR}/ld_prune.prune.in \
--make-bed \
--out ${OUTDIR}/pruned
# === Step 3: Population Structure ===
echo "=== Step 3: PCA ==="
plink2 --bfile ${OUTDIR}/pruned \
--pca 10 \
--out ${OUTDIR}/pca
# === Step 4: Association Testing ===
echo "=== Step 4: Association Testing ==="
# With PCA covariates (columns 3-12 are PC1-PC10)
plink2 --bfile ${OUTDIR}/qc \
--pheno ${PHENO_FILE} \
--covar ${OUTDIR}/pca.eigenvec \
--covar-col-nums 3-12 \
--glm hide-covar \
--out ${OUTDIR}/gwas
# === Step 5: Extract Results ===
echo "=== Step 5: Processing Results ==="
# Find result file
result_file=$(ls ${OUTDIR}/gwas.*.glm.* 2>/dev/null | head -1)
if [ -f "$result_file" ]; then
# Genome-wide significant
awk 'NR==1 || $12 < 5e-8' "$result_file" > ${OUTDIR}/significant_5e8.txt
sig_count=$(tail -n +2 ${OUTDIR}/significant_5e8.txt | wc -l)
# Suggestive
awk 'NR==1 || $12 < 1e-5' "$result_file" > ${OUTDIR}/suggestive_1e5.txt
sug_count=$(tail -n +2 ${OUTDIR}/suggestive_1e5.txt | wc -l)
echo ""
echo "=== Results Summary ==="
echo "Genome-wide significant (p < 5e-8): ${sig_count}"
echo "Suggestive (p < 1e-5): ${sug_count}"
else
echo "Warning: No result file found"
fi
echo ""
echo "=== GWAS Complete ==="
echo "Results directory: ${OUTDIR}/"
echo " - QC'd data: ${OUTDIR}/qc.{bed,bim,fam}"
echo " - PCA: ${OUTDIR}/pca.eigenvec"
echo " - Association: ${OUTDIR}/gwas.*.glm.*"
GWAS Pipeline - Usage Guide
Overview
This workflow performs genome-wide association studies (GWAS) to identify genetic variants associated with traits or diseases.
Prerequisites
conda install -c bioconda plink plink2
# R packages for visualization
install.packages(c('qqman', 'ggplot2'))Quick Start
Tell your AI agent what you want to do:
- "Run a GWAS on my genotype data"
- "Find variants associated with my phenotype"
- "Perform case-control association testing"
Example Prompts
GWAS workflow
"Run QC and association testing on my VCF"
"Create Manhattan and QQ plots for my GWAS"
"Adjust for population structure using PCA"
Analysis options
"Run GWAS for a quantitative trait"
"Include age and sex as covariates"
"Extract genome-wide significant hits"
Input Requirements
| Input | Format | Description |
|---|---|---|
| Genotypes | VCF or PLINK | SNP genotype data |
| Phenotypes | Text file | Case/control or quantitative |
| Covariates | Text file | Age, sex, PCs (optional) |
What the Workflow Does
1. QC Filtering - Remove poor quality samples/variants 2. LD Pruning - Get independent variants for PCA 3. PCA - Calculate population structure covariates 4. Association - Test variant-phenotype associations 5. Visualization - Manhattan and QQ plots
Case-Control vs Quantitative
| Feature | Case-Control | Quantitative |
|---|---|---|
| Phenotype | 1=control, 2=case | Continuous value |
| Model | Logistic regression | Linear regression |
| Output | Odds ratio | Beta coefficient |
Tips
- Sample size: Need thousands of samples for common variants
- Lambda: Should be ~1.0; high values indicate stratification
- Multiple testing: Genome-wide threshold is p < 5e-8
- Replication: Always validate findings in independent cohort