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 ldReference 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,
  sumstatsFilterParam = SumstatsFilterParam(),
  panelFilterParam = PanelFilterParam(),
  keepVariants = NULL,
  skipRegion = NULL,
  signalScreenParam = SignalScreenParam(),
  ldMismatchQcMethod = c("none", "slalom", "dentist"),
  alleleFlipKriging = FALSE,
  effectiveN = TRUE,
  impute = FALSE,
  raissParam = RaissParam(),
  matchMinProp = 0,
  sumstatsCleaningParam = SumstatsCleaningParam()
)

Arguments

sumstats

A QtlSumStats or GwasSumStats collection.

sumstatsFilterParam

Row filters applied to the summary statistics themselves, built with SumstatsFilterParam: removeIndels drops indels during panel harmonization, removeStrandAmbiguous drops A/T and C/G variants, infoCutoff is an INFO-score floor (requiring an INFO column when non-zero), and nCutoff drops variants whose N is more than that many median-absolute-deviations from the median (0 disables it).

panelFilterParam

LD-reference-panel filters, built with PanelFilterParam. macCutoff is converted to a MAF equivalent using macCutoff / (2 * nSamples) and the stricter of it and mafCutoff applies; nSamples counts the panel's real samples, which for a stochastic LD sketch are those its .afreq records rather than its pseudo-samples. imissCutoff is a per-variant missingness ceiling. See the panel-filters section below.

mafCutoff is the one setting that reaches past the panel: it is measured wherever it can be, against the summary statistics' own AF / MAF / FRQ column when one is present and against the panel. It has always been a single knob, so it lives here rather than being split into two that could disagree.

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.

signalScreenParam

Whether to skip an entry before fitting it, built with SignalScreenParam — the same bundle fineMappingPipeline and colocboostPipeline take. pip runs an LD-independent single-effect SER screen and skips the entry if no PIP exceeds the cutoff (< 0 resolves to 3 / nVariants); absZ skips when max(abs(Z)) does not exceed the cutoff, with no model fit; bf and logBf screen the largest per-variant single-effect Bayes factor from that same susie_ser fit, on the raw and log scales respectively. One metric at a time — the constructor rejects a conflicting pair. Unset (the default) screens nothing.

ldMismatchQcMethod

Which LD-mismatch check to run: "none" (default), "slalom" or "dentist", or the matching constructor – SlalomParam / DentistParam – to configure it at the same time. Exactly one engine is selected either way, since the constructor carries the choice.

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 ldReference's genotype panel as the last QC step, adding z-scores for panel variants the input lacks (see raissParam). The audit records how many variants were imputed. Default FALSE.

raissParam

RAISS settings, built with RaissParam. A bare list is refused, since it cannot be checked.

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

mafCutoff, macCutoff and imissCutoff 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 raissParam = RaissParam(mafCutoff = 0.01). A variant present in the sumstats is never dropped here: RAISS derives its LD basis from those same panel rows.

lamb, svdTol, r2Threshold and minimumLd are forwarded to raiss itself.

matchMinProp

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

sumstatsCleaningParam

What makes a row a well-formed record, built with SumstatsCleaningParam: coerceNumeric, normalizeChr / dropNonstandardChr, dropMissData, dropPOutOfRange, clampSmallP / smallPFloor, dropZeroEffect and dropNonpositiveSe. Applied before any filter or screen. Distinct from sumstatsFilterParam, which applies quality thresholds to rows that are already well formed.

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(qcInfo(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 reference: plink1 @ pecotmr://extdata/toy_canonical