Skip to contents

Applies a single QC pass to a QtlSumStats or GwasSumStats collection: per-row sanity checks via .applySanityChecks (drop rows with out-of-range / zero P, BETA == 0, SE <= 0, NA in vital columns; clamp tiny P; normalize CHR; coerce signed columns to numeric), variant-content filters (MAF / INFO / N) via .applyContentFilters, optional skipRegion drop, optional PIP screen, panel-vs-sumstats allele harmonization against the ldSketch via harmonizeAlleles (which handles indels, strand-ambiguous variants, sign / strand flips, and duplicate drops in a single sweep), optional SLALOM/DENTIST LD-mismatch QC, and optional RAISS imputation. No Bioconductor genome / dbSNP packages required.

Usage

summaryStatsQc(
  sumstats,
  removeIndels = FALSE,
  removeStrandAmbiguous = TRUE,
  mafCutoff = 0,
  macCutoff = 0,
  imissCutoff = 1,
  infoCutoff = 0,
  nCutoff = 5,
  keepVariants = NULL,
  skipRegion = NULL,
  pipCutoffToSkip = 0,
  absZCutoffToSkip = 0,
  bfCutoffToSkip = 0,
  logBfCutoffToSkip = 0,
  zMismatchQc = c("none", "slalom", "dentist"),
  alleleFlipKriging = FALSE,
  effectiveN = TRUE,
  impute = FALSE,
  imputeOpts = list(rcond = 0.01, r2Threshold = 0.6, minimumLd = 5, lamb = 0.01),
  matchMinProp = 0,
  coerceNumeric = TRUE,
  normalizeChr = TRUE,
  dropNonstandardChr = TRUE,
  dropMissData = TRUE,
  dropPOutOfRange = TRUE,
  clampSmallP = TRUE,
  smallPFloor = 4.94065645841247e-324,
  dropZeroEffect = TRUE,
  dropNonpositiveSe = TRUE
)

Arguments

sumstats

A QtlSumStats or GwasSumStats collection.

removeIndels

Logical (length 1). When TRUE, drop indels during panel harmonization. Default FALSE.

removeStrandAmbiguous

Logical (length 1). When TRUE, drop A/T and C/G strand-ambiguous variants. Default TRUE.

mafCutoff

Numeric (length 1). Minor-allele-frequency threshold, measured wherever it can be: against the summary statistics' own AF / MAF / FRQ column when one is present, and against the LD reference panel. Default 0 (off). See the panel-filters section below.

macCutoff

Numeric (length 1). Minor-allele-count threshold for the LD reference panel, converted to a MAF equivalent using macCutoff / (2 * nSamples); the stricter of it and mafCutoff applies. Default 0 (off).

imissCutoff

Numeric (length 1). Per-variant missingness-rate ceiling for the LD reference panel. Default 1 (off).

infoCutoff

Numeric (length 1). INFO score threshold. Default 0. Requires INFO column when non-zero.

nCutoff

Numeric (length 1). Sample-size deviation threshold: drop variants whose N is more than nCutoff median-absolute-deviations from the median. Set to 0 to disable. Default 5.

keepVariants

Optional character vector of variant IDs (SNP column) to retain prior to harmonization.

skipRegion

Optional character vector of "chr:start-end" strings, or a GRanges, of regions to drop.

pipCutoffToSkip

Numeric (length 1). When != 0, run an LD-independent single-effect SER screen and skip the entry if no PIP exceeds the cutoff. < 0 resolves to 3 / nVariants. Default 0 (no screen).

absZCutoffToSkip

Numeric (length 1). Alternative signal screen: skip the entry when max(abs(Z)) does not exceed the cutoff. No model fit. Default 0 (off).

bfCutoffToSkip

Numeric (length 1). Alternative signal screen: skip the entry when the largest per-variant single-effect Bayes factor (from the same susie_ser fit as the PIP screen) does not exceed the cutoff. Compared in log space (maxlogBF > log(cutoff)). Must be > 0. Default 0 (off).

logBfCutoffToSkip

Numeric (length 1). As bfCutoffToSkip but the cutoff is on the log Bayes factor scale (maxlogBF > cutoff). Default 0 (off). Exactly one of pipCutoffToSkip / absZCutoffToSkip / bfCutoffToSkip / logBfCutoffToSkip may be non-zero (one screening metric at a time); enabling more than one is an error.

zMismatchQc

One of "none" (default), "slalom", "dentist".

alleleFlipKriging

Logical (length 1). Opt-in kriging LD-consistency prefilter run before SLALOM/DENTIST. Default FALSE.

effectiveN

Logical (length 1). When TRUE (default) and the input carries case/control counts — per-variant N_CASE / N_CONTROL mcols, else the study-level nCase / nControl scalars — the working per-variant N is set to the effective sample size effectiveN(nCase, nControl) BEFORE the N-cutoff filter, so the filter, kriging, and the downstream fit all use N_eff. When both counts and an N column are present the counts win: N is overridden and the override is logged. Inputs with no counts (quantitative traits) are unchanged. The escape hatch effectiveN = FALSE restores the raw N column (or, when there is no N, the raw total nCase + nControl) with no override. qcInfo$options$effectiveN records the setting and each entry's nSource is one of "effective", "column", "total", or NA.

impute

Logical (length 1). Run RAISS imputation against the ldSketch. Default FALSE. (Note: RAISS against the sketch is not yet fully wired for the new path; the option is accepted but currently emits a warning and is skipped.)

imputeOpts

Named list of RAISS parameters. RAISS imputation scopes its reference panel to the analysis-region window (so a per-chromosome / genome-wide ldSketch does not materialize its full dosage); flank (default 0) widens that window by the given number of base pairs on each side to retain LD context for edge variants.

mafCutoff (default 0), macCutoff (default 0) and imissCutoff (default 1) bound which panel variants RAISS will attempt to impute. Without them every rare variant in the window of a large LD sketch becomes an imputation target, which is slow and of little value when the study is far smaller than the panel. The stricter of mafCutoff and macCutoff / (2 * nSamples) applies, matching QtlDataset.

These are a further tightening applied to imputation targets only, on top of the panel filter the top-level cutoffs already applied: the panel handed to RAISS holds nothing below those. Use them to impute only common variants from a panel deliberately kept wider than that — e.g. mafCutoff = 0.001 with imputeOpts = list(mafCutoff = 0.01). A variant present in the sumstats is never dropped here: RAISS derives its LD basis from those same panel rows.

matchMinProp

Minimum proportion of LD panel variants that must be matched by the sumstats; default 0.

coerceNumeric

Logical. Coerce signed columns (Z/BETA/SE/OR/LOG_ODDS/SIGNED_SUMSTAT/P/MAF/FRQ/INFO/N) to numeric. Default TRUE.

normalizeChr

Logical. Strip "chr" prefix, uppercase the chromosome label, and map 23->X, 24->Y, M->MT. Default TRUE.

dropNonstandardChr

Logical. Drop variants whose CHR (after normalization) is outside 1..22, X, Y, MT. Default TRUE.

dropMissData

Logical. Drop rows with NA in any vital column (chrom, pos, A1, A2, and at least one of Z / BETA). Default TRUE.

dropPOutOfRange

Logical. Drop rows where P < 0 or P > 1. Default TRUE.

clampSmallP

Logical. Floor non-negative P values below smallPFloor to smallPFloor so -log10(P) stays finite. Applied to both input and Z-derived P values. Default TRUE.

smallPFloor

Numeric (length 1). Floor for clampSmallP. Default 5e-324 (R's smallest positive double).

dropZeroEffect

Logical. Drop rows where any effect column is exactly 0 (BETA, LOG_ODDS, SIGNED_SUMSTAT) or OR is exactly 1. Default TRUE.

dropNonpositiveSe

Logical. Drop rows where SE <= 0. Default TRUE.

Value

A new QtlSumStats / GwasSumStats with cleaned entries and qcInfo populated.

Details

The returned collection has its qcInfo slot populated with a per-entry audit record (variant counts, drop counts at each step, which filters fired, etc.). Fine-mapping and TWAS-weights pipelines reject SumStats inputs where length(getQcInfo(x)) == 0L.

Column-availability error contract: a non-zero infoCutoff requires every entry to carry an INFO column, and a non-zero nCutoff requires N; a missing column with a non-zero cutoff is a hard error. mafCutoff is exempt — a study with no frequency column is still filtered against the reference panel (see below).

Panel filters

mafCutoff / macCutoff / imissCutoff are measured against the LD reference panel, the same way fineMappingPipeline and twasWeightsPipeline measure them on the RSS path, so one number means the same thing wherever it is set. MAC is converted to a MAF equivalent and the stricter of the two applies, matching QtlDataset. Defaults (0, 0, 1) filter nothing.

The panel is filtered once, before any entry is harmonized, so a variant the panel cannot support is absent from the LD used by kriging, SLALOM/DENTIST and RAISS, and is never an imputation target. Because harmonization drops summary-statistic variants the panel does not cover, this also discards observed variants — the intended behaviour: a variant whose LD cannot be estimated is not usable downstream.

mafCutoff additionally filters the summary statistics' own AF / MAF / FRQ column when one is present, so a variant common in the panel but rare in the study is dropped as well.

Examples

data(gwasSumStatsS4Example)
summaryStatsQc(gwasSumStatsS4Example)
#> [trait1] QC track: harmonization kept 200 of 200 variant(s) (corrected: sign-flipped 0, strand-flipped 0; dropped 0).
#> [trait1] QC summary: 200 in -> 200 out | corrected: sign-flip 0, strand-flip 0
#> GwasSumStats: 1 studies, genome build hg19
#>   LD sketch: plink1 @ pecotmr://extdata/toy_canonical