diff --git a/NAMESPACE b/NAMESPACE index 88b6b056..93446530 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -6,8 +6,6 @@ S3method(postprocessFinemappingFit,susiF) S3method(postprocessFinemappingFit,susie) S3method(postprocessFinemappingFit,susieInf) S3method(postprocessFinemappingFit,susieRss) -export(.fullFitColumns) -export(.overlapPrefixNonKey) export(AnnotationMatrix) export(CtwasResult) export(CtwasResultEntry) @@ -41,6 +39,7 @@ export(bayesLWeights) export(bayesNWeights) export(bayesRWeights) export(buildMrmashPriorMatrices) +export(buildTopLoci) export(calculateFeatureScores) export(causalInferencePipeline) export(checkLd) @@ -255,6 +254,7 @@ export(mvsusieWeights) export(nSignificantScore) export(nSnps) export(normalizeVariantId) +export(overlapTopLoci) export(parseCsCorr) export(parseRegion) export(parseVariantId) diff --git a/R/fineMappingWrappers.R b/R/fineMappingWrappers.R index 6827379e..b0d79d7b 100644 --- a/R/fineMappingWrappers.R +++ b/R/fineMappingWrappers.R @@ -539,53 +539,6 @@ computeCsTable <- function(fit, dataX, coverage, csInput = c("X", "Xcorr", "fsus out } -#' Build the unified top-loci table for one fit and one method. -#' -#' Returns the per-fit, per-method contribution to the unified \code{top_loci} -#' table in the fixed 22-column shape. \code{postprocessFinemappingFits()} -#' calls this once per method per fit and row-binds the results into the -#' single \code{top_loci} returned by \code{formatFinemappingOutput()}. -#' -#' Output columns, in order: \code{#chr}, \code{start}, \code{end}, \code{a1}, -#' \code{a2}, \code{variant}, \code{gene}, \code{event}, \code{n}, \code{af}, -#' \code{beta}, \code{se}, \code{pip}, \code{posterior_effect_mean}, -#' \code{posterior_effect_se}, \code{cs_95}, \code{cs_70}, \code{cs_50}, -#' \code{cs_95_purity}, \code{method}, \code{grange_start}, \code{grange_end}. -#' -#' \code{cs_95} / \code{cs_70} / \code{cs_50} are character strings of the -#' form \code{"_"} where each method numbers credible sets -#' independently from 1. Variants retained by the PIP cutoff but not in any -#' credible set at a coverage carry \code{"_0"}. \code{cs_95_purity} -#' is the 0.95-coverage purity for the row's \code{(method, cs_95)}; rows -#' whose \code{cs_95} is \code{"_0"} carry \code{0}. -#' -#' Row uniqueness is \code{(variant, gene, cs_membership)} at the given -#' \code{method}; overlapping CS within the same method produces one row per -#' CS. -#' -#' @param fit Fitted SuSiE-family object (must expose \code{alpha}, -#' \code{mu}, \code{mu2}, \code{pip}). -#' @param csTables List of CS tables (one per coverage) from -#' \code{computeCsTables()}. -#' @param variantNames Character vector of variant IDs -#' (\code{chr:pos:A2:A1}). -#' @param sumstats Optional marginal-association summary (\code{betahat}, -#' \code{sebetahat}) filling \code{beta} / \code{se}. -#' @param af Optional numeric vector of effect-allele frequencies (frequency of -#' the final effect allele / \code{a1} after allele harmonization against the -#' LD/reference variants). Exported directly as the \code{af} column. MAF is -#' never exported; derive it from \code{af} at filter time. Default NULL -> -#' \code{af = NA_real_}. -#' @param method Method name (e.g. \code{"susie"}, \code{"susieInf"}). Required. -#' @param signalCutoff PIP cutoff for retaining PIP-only (non-CS) variants. -#' @param dataX Optional regional genotype matrix. -#' @param dataY Optional regional phenotype matrix; \code{nrow(dataY)} fills -#' \code{n}, \code{colnames(dataY)[1]} fills \code{gene}. -#' @param otherQuantities Optional list. Default is NULL. -#' @param region Optional \code{"chr:start-end"} string. Default is NULL. -#' @return A data frame in the fixed 22-column shape for this fit and method, -#' or an empty data frame if nothing is retained. -#' @export # Per-effect (per credible set) variant-level columns from the susie fit. Always # returns `within_cs_pip` (the variant's alpha in the single effect of its # assigned primary-coverage CS; NA for non-CS variants -- alpha is a probability, @@ -678,6 +631,53 @@ computeCsTable <- function(fit, dataX, coverage, csInput = c("X", "Xcorr", "fsus }, numeric(1)) } +#' Build the unified top-loci table for one fit and one method. +#' +#' Returns the per-fit, per-method contribution to the unified \code{top_loci} +#' table in the fixed 22-column shape. \code{postprocessFinemappingFits()} +#' calls this once per method per fit and row-binds the results into the +#' single \code{top_loci} returned by \code{formatFinemappingOutput()}. +#' +#' Output columns, in order: \code{#chr}, \code{start}, \code{end}, \code{a1}, +#' \code{a2}, \code{variant}, \code{gene}, \code{event}, \code{n}, \code{af}, +#' \code{beta}, \code{se}, \code{pip}, \code{posterior_effect_mean}, +#' \code{posterior_effect_se}, \code{cs_95}, \code{cs_70}, \code{cs_50}, +#' \code{cs_95_purity}, \code{method}, \code{grange_start}, \code{grange_end}. +#' +#' \code{cs_95} / \code{cs_70} / \code{cs_50} are character strings of the +#' form \code{"_"} where each method numbers credible sets +#' independently from 1. Variants retained by the PIP cutoff but not in any +#' credible set at a coverage carry \code{"_0"}. \code{cs_95_purity} +#' is the 0.95-coverage purity for the row's \code{(method, cs_95)}; rows +#' whose \code{cs_95} is \code{"_0"} carry \code{0}. +#' +#' Row uniqueness is \code{(variant, gene, cs_membership)} at the given +#' \code{method}; overlapping CS within the same method produces one row per +#' CS. +#' +#' @param fit Fitted SuSiE-family object (must expose \code{alpha}, +#' \code{mu}, \code{mu2}, \code{pip}). +#' @param csTables List of CS tables (one per coverage) from +#' \code{computeCsTables()}. +#' @param variantNames Character vector of variant IDs +#' (\code{chr:pos:A2:A1}). +#' @param sumstats Optional marginal-association summary (\code{betahat}, +#' \code{sebetahat}) filling \code{beta} / \code{se}. +#' @param af Optional numeric vector of effect-allele frequencies (frequency of +#' the final effect allele / \code{a1} after allele harmonization against the +#' LD/reference variants). Exported directly as the \code{af} column. MAF is +#' never exported; derive it from \code{af} at filter time. Default NULL -> +#' \code{af = NA_real_}. +#' @param method Method name (e.g. \code{"susie"}, \code{"susieInf"}). Required. +#' @param signalCutoff PIP cutoff for retaining PIP-only (non-CS) variants. +#' @param dataX Optional regional genotype matrix. +#' @param dataY Optional regional phenotype matrix; \code{nrow(dataY)} fills +#' \code{n}, \code{colnames(dataY)[1]} fills \code{gene}. +#' @param otherQuantities Optional list. Default is NULL. +#' @param region Optional \code{"chr:start-end"} string. Default is NULL. +#' @return A data frame in the fixed 22-column shape for this fit and method, +#' or an empty data frame if nothing is retained. +#' @export buildTopLoci <- function(fit, csTables, variantNames, sumstats = NULL, af = NULL, method, signalCutoff = 0, dataX = NULL, dataY = NULL, diff --git a/R/overlapTopLoci.R b/R/overlapTopLoci.R index 70279c29..240affd3 100644 --- a/R/overlapTopLoci.R +++ b/R/overlapTopLoci.R @@ -1,29 +1,3 @@ -#' Overlap QTL and GWAS top loci by allele-aware variant matching -#' -#' Intersect the top-loci tables of a \code{QtlFineMappingResult} and a -#' \code{GwasFineMappingResult} on shared variants, matched with pecotmr's -#' allele-aware \code{\link{matchVariants}} (handling strand flips / ref-alt -#' swaps rather than naive id equality). The GWAS side is harmonized to the QTL -#' orientation: its signed effect columns (\code{beta}, \code{z}, -#' \code{conditional_effect}) are sign-flipped and its effect-allele frequency -#' (\code{af}) is complemented wherever a swap occurred. The result keeps the -#' variant key columns once (from the QTL, the reference orientation) and -#' prefixes every other column \code{qtl_} / \code{gwas_}. A variant shared -#' across several QTL contexts and/or GWAS studies yields one row per -#' (QTL entry x GWAS entry) pair (a wide cross-product per variant). -#' -#' @param qtl A \code{QtlFineMappingResult}. -#' @param gwas A \code{GwasFineMappingResult}. -#' @param signalCutoff PIP cutoff forwarded to \code{\link{getTopLoci}} for both -#' inputs. Default 0.025. -#' @param type \code{"data.frame"} (default) or \code{"GRanges"}. -#' @param ... Ignored. -#' @return A \code{data.frame} (or \code{GRanges}) keyed on the QTL variant -#' (\code{variant_id, chrom, pos, A1, A2}) with all other columns prefixed -#' \code{qtl_} / \code{gwas_}. Zero rows when there is no allele-aware overlap. -#' @seealso \code{\link{getTopLoci}}, \code{\link{matchVariants}} -#' @include AllGenerics.R AllClasses.R QtlFineMappingResult.R GwasFineMappingResult.R -#' @export # Prefix a top-loci frame's NON-key columns with `pfx` (key columns unchanged). # @noRd .overlapPrefixNonKey <- function(df, pfx, keyCols) @@ -50,6 +24,32 @@ # @noRd .overlapFinish <- function(df, type) if (type == "GRanges") .overlapToGRanges(df) else df +#' Overlap QTL and GWAS top loci by allele-aware variant matching +#' +#' Intersect the top-loci tables of a \code{QtlFineMappingResult} and a +#' \code{GwasFineMappingResult} on shared variants, matched with pecotmr's +#' allele-aware \code{\link{matchVariants}} (handling strand flips / ref-alt +#' swaps rather than naive id equality). The GWAS side is harmonized to the QTL +#' orientation: its signed effect columns (\code{beta}, \code{z}, +#' \code{conditional_effect}) are sign-flipped and its effect-allele frequency +#' (\code{af}) is complemented wherever a swap occurred. The result keeps the +#' variant key columns once (from the QTL, the reference orientation) and +#' prefixes every other column \code{qtl_} / \code{gwas_}. A variant shared +#' across several QTL contexts and/or GWAS studies yields one row per +#' (QTL entry x GWAS entry) pair (a wide cross-product per variant). +#' +#' @param qtl A \code{QtlFineMappingResult}. +#' @param gwas A \code{GwasFineMappingResult}. +#' @param signalCutoff PIP cutoff forwarded to \code{\link{getTopLoci}} for both +#' inputs. Default 0.025. +#' @param type \code{"data.frame"} (default) or \code{"GRanges"}. +#' @param ... Ignored. +#' @return A \code{data.frame} (or \code{GRanges}) keyed on the QTL variant +#' (\code{variant_id, chrom, pos, A1, A2}) with all other columns prefixed +#' \code{qtl_} / \code{gwas_}. Zero rows when there is no allele-aware overlap. +#' @seealso \code{\link{getTopLoci}}, \code{\link{matchVariants}} +#' @include AllGenerics.R AllClasses.R QtlFineMappingResult.R GwasFineMappingResult.R +#' @export setGeneric("overlapTopLoci", function(qtl, gwas, ...) standardGeneric("overlapTopLoci")) diff --git a/_pkgdown.yml b/_pkgdown.yml index eb0e6ada..61e1cd74 100644 --- a/_pkgdown.yml +++ b/_pkgdown.yml @@ -213,7 +213,7 @@ reference: - getMaf - getN - getP - - getSE + - getSe - getSumStats - getSumstatDf - getVarY @@ -389,6 +389,7 @@ reference: - enforceDesignFullRank - ldClumpByScore - ldLoader + - loadLdBlock - ldPruneByCorrelation - filterVariantsByLdReference @@ -620,7 +621,7 @@ reference: # Implementation details with .Rd topics but no front-facing role. - as.data.frame.GwasSumStats - rescaleCovW0 - - ".fullFitColumns" + - buildTopLoci - "getSumStats,GwasSumStats-method" footer: diff --git a/man/dot-fullFitColumns.Rd b/man/buildTopLoci.Rd similarity index 91% rename from man/dot-fullFitColumns.Rd rename to man/buildTopLoci.Rd index f9e51111..d8cb1fb6 100644 --- a/man/dot-fullFitColumns.Rd +++ b/man/buildTopLoci.Rd @@ -1,17 +1,22 @@ % Generated by roxygen2: do not edit by hand % Please edit documentation in R/fineMappingWrappers.R -\name{.fullFitColumns} -\alias{.fullFitColumns} +\name{buildTopLoci} +\alias{buildTopLoci} \title{Build the unified top-loci table for one fit and one method.} \usage{ -.fullFitColumns( - alpha, - mu, - mu2, - lbfMat, - scale, - primaryCsPos, - effectOf, +buildTopLoci( + fit, + csTables, + variantNames, + sumstats = NULL, + af = NULL, + method, + signalCutoff = 0, + dataX = NULL, + dataY = NULL, + otherQuantities = NULL, + region = NULL, + conditionIdx = NULL, fullFit = FALSE, fullFitAlphaOnly = TRUE, includeAllCs = FALSE diff --git a/man/dot-overlapPrefixNonKey.Rd b/man/overlapTopLoci.Rd similarity index 83% rename from man/dot-overlapPrefixNonKey.Rd rename to man/overlapTopLoci.Rd index 2ee01590..7e336750 100644 --- a/man/dot-overlapPrefixNonKey.Rd +++ b/man/overlapTopLoci.Rd @@ -1,22 +1,31 @@ % Generated by roxygen2: do not edit by hand % Please edit documentation in R/overlapTopLoci.R -\name{.overlapPrefixNonKey} -\alias{.overlapPrefixNonKey} +\name{overlapTopLoci} +\alias{overlapTopLoci} +\alias{overlapTopLoci,QtlFineMappingResult,GwasFineMappingResult-method} \title{Overlap QTL and GWAS top loci by allele-aware variant matching} \usage{ -.overlapPrefixNonKey(df, pfx, keyCols) +overlapTopLoci(qtl, gwas, ...) + +\S4method{overlapTopLoci}{QtlFineMappingResult,GwasFineMappingResult}( + qtl, + gwas, + signalCutoff = 0.025, + type = c("data.frame", "GRanges"), + ... +) } \arguments{ \item{qtl}{A \code{QtlFineMappingResult}.} \item{gwas}{A \code{GwasFineMappingResult}.} +\item{...}{Ignored.} + \item{signalCutoff}{PIP cutoff forwarded to \code{\link{getTopLoci}} for both inputs. Default 0.025.} \item{type}{\code{"data.frame"} (default) or \code{"GRanges"}.} - -\item{...}{Ignored.} } \value{ A \code{data.frame} (or \code{GRanges}) keyed on the QTL variant