Performs the SKAT (Sequence Kernel Association Test) using optimal weights derived from the GLOW framework. SKAT is most powerful when causal variants have effects in mixed directions (some positive, some negative) or when effect sizes are heterogeneous.
The test statistic is: $$S_{SKAT} = \sum_{i=1}^{m} w_i Z_i^2$$
where \(w_i\) are optimal weights and \(Z_i\) are marginal score Z-scores.
CRITICAL: The SKAT test statistic is a QUADRATIC form (sum of SQUARED Z-scores). The p-value is calculated using p.GFisher from the GFisher package with df=1. This is NOT the Liu method. This is NOT liu.mod. The test uses the GFisher framework which properly accounts for correlation among Z-scores.
GLOW_SKAT(marg_score_stats, B, PI, ...)List output from getZ_marg_score or
getZ_marg_score_binary_SPA containing:
Numeric vector of marginal score Z-scores
Correlation matrix of Z-scores
Covariance matrix of score statistics
Scalar standard deviation under null
Numeric vector of effect size estimates (length m). These can be from external studies, meta-analysis, or prior information. Should be on the standardized scale (e.g., log odds ratio, standardized beta).
Numeric vector of variant-importance scores (length m, values in
\([0,1]\)), each variant's annotation-derived relative importance. Can be
computed using get_PI based on annotation data.
Additional arguments passed to the internal omni_SgZ_test
and eventually to p.GFisher (e.g., method, nsim for GFisher package options)
A list with two elements:
Matrix (k x 1) of test statistics, where k is the number of weight schemes (4 optimal + 1 equal). Last row is labeled "GLOW_SKAT" and corresponds to equal weights.
Matrix (k x 1) of p-values corresponding to each test statistic. All p-values are computed using p.GFisher with df=1. Last row is the final GLOW SKAT test p-value.
Algorithm (EXACT port from legacy lines 26-52):
Compute scaled effect sizes: \(B^* = \sqrt{diag(M_s)} \times B / s_0\)
Define transformation function: g(x) = x^2 (SQUARING function)
Set degrees of freedom: df = 1 (SKAT uses df=1)
Calculate optimal weights using Optimal_Weights_M with:
Transformation g(x) = x^2
Effect size estimates B*
Variant-importance scores PI
Correlation matrix M
is.posi.wts = TRUE (forces non-negative weights)
Construct weight matrix with optimal weights and equal weights
Call omni_SgZ_test which routes to skat_test() for df=1
skat_test() calls p.GFisher with df=1 (NOT Liu method)
Optimal Weight Schemes:
wts_BE_N: Best Estimator using normal approximation
wts_APE_N: Asymptotically Powerful Estimator using normal approximation
wts_BE_sparse: Best Estimator using sparse mixture approximation
wts_APE_sparse: APE using sparse mixture approximation
wts_equ: Equal weights baseline (simple sum of Z^2)
The final SKAT p-value is from the equal weights row (last row).
When SKAT Test is Optimal:
Causal variants have effects in mixed directions (some protective, some deleterious)
Effect sizes are heterogeneous across variants
No strong prior on direction of effects
Variance component model is appropriate
P-value Calculation (MANDATORY - DO NOT MODIFY): The p-value is computed using p.GFisher from the GFisher package with df=1: $$p = p.GFisher(q = S, df = 1, w = weights, M = correlation, ...)$$
This is a quadratic form test. The statistic S is a weighted sum of SQUARED Z-scores. The GFisher framework with df=1 provides the correct null distribution accounting for the correlation structure.
What this is NOT:
NOT Liu's method for weighted chi-square mixtures
NOT liu.mod method
NOT Davies method applied directly
The transformation is g(x) = x^2 (NOT g(x) = x as in Burden)
The df = 1 (NOT df = Inf as in Burden, NOT df = 2 as in Fisher)
Computational Complexity: O(m^2) for weight calculation, O(m^2) for p-value
Assumptions:
Z-scores are standard normal under null hypothesis
M is the correlation matrix of Z-scores
Effect sizes B are on the standardized scale
Variant-importance scores PI are in \([0,1]\)
For new code, consider using glow_test with appropriate
test_specs instead. The glow_test() interface supports
flexible test composition via default_test_specs and is the
preferred entry point for the GLOW test system. This function remains
available for direct use and backward compatibility.
Zhang, H., Liu, M., Landers, J. E., and Wu, Z. (2026). Integrated weighted association test with application to genetic association studies. The Annals of Applied Statistics, 20(3), 2074-2097. doi:10.1214/26-AOAS2223
Wu, M. C., Lee, S., Cai, T., Li, Y., Boehnke, M., & Lin, X. (2011). Rare-variant association testing for sequencing data with the sequence kernel association test. The American Journal of Human Genetics, 89(1), 82-93.
Zhang, H., & Wu, Z. (2023). The generalized Fisher's combination and accurate p-value calculation under dependence. Biometrics, 79(2), 1159-1172.
glow_test for the preferred high-level interface
getZ_marg_score for computing marginal score statistics
getZ_marg_score_binary_SPA for binary traits with SPA
get_B for estimating effect sizes from external data
get_PI for computing variant-importance scores from annotations
Optimal_Weights_M for optimal weight calculation
GLOW_Burden for Burden test
GLOW_Fisher for Fisher test
GLOW_Omni for omnibus test combining all methods
if (FALSE) { # \dontrun{
# Simulate data
set.seed(123)
n <- 500 # sample size
m <- 20 # number of variants
# Genotype matrix (n x m)
G <- matrix(rbinom(n*m, 2, 0.1), n, m)
# Covariates
X <- matrix(rnorm(n*2), n, 2)
# Binary trait
Y <- rbinom(n, 1, 0.3)
# Compute marginal score statistics
marg_stats <- getZ_marg_score(G, X, Y, trait="binary")
# External effect sizes (e.g., from meta-analysis)
B <- rnorm(m, mean=0, sd=0.2)
# Variant-importance scores (e.g., from annotation)
PI <- runif(m, 0.1, 0.9)
# Run GLOW SKAT test
result <- GLOW_SKAT(marg_score_stats=marg_stats, B=B, PI=PI)
# View results
print(result$STAT)
print(result$PVAL)
} # }