The new pecotmr interface #1385
danielnachun
started this conversation in
Workflow logic
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
-
I wanted to start a discussion here in a place that is more visible than Slack to clarify what remains to be done bring xqtl-protocol into alignment with
pecotmr. There have been many changes that needed to be made forpecotmrto be compliant with Bioconductor as well as general bioinformatics engineering best practices, and that will require some changes to both xqtl-protocol and other custom users ofpecotmr. I will first start by laying out the basic structure ofpecotmrnow, and then discuss places where changes are still needed.Classes
A key requirement of Bioconductor is usage of S4 classes. These classes are powerful abstractions for complex data structures like the ones we encounter with
pecotmr. I will not describe all the classes inpecotmr, just the ones that are relevant to us right now:GenotypeHandle: this is a file handle that points to genotype data on disk that is any of plink1 (.bed/.bim/.fam), plink2 (.pgen/.pvar/.psam), GDS or VCF. When genotypes are requested for downstream analysis, they are lazily loaded from those files. This handle can point to either a single file, or a set of files if the genotypes are split by chromosome.QtlDataset: this is the main container for individual-level data for a single study. Each context is stored as aSummarizedExperimentobject with the actual molecular trait measurements as the main assay, the molecular PCs and other covariates ascolData, and the gene positions asrowData. There also slots for aGenotypeHandlefrom which genotypes can be requested, and andgenotypeCovariatesslot to hold the genotype PCs. The most important functions related this class are:getResidualizedPhenotypes(context, traitId/region): this returns a list of phenotype matrices adjusted for (by default) genotype and phenotype covariates. The list is named by context, and multiple traits can be requested simultaneously (to support multi-trait analysis withmr.mash,mvsusieandfsusie. The multi-trait selection can be with either a list of traits, or by instead providing a GRanges range.getResidualizedGenotypes(context, traitId/region, cisWindows): this is the same idea asgetResidualizedPhenotypesbut for genotypes. The genomic range to extract is either directly taken from a region if given, or by getting the positions of traitIds from the rowData and then adding the cis-window.QtlSumStats/GwasSumStats: these classes hold Granges objects with summary statistics for QTL and GWAS, respectively. For QTL, we keep the summary statistics separate by study, context, and trait, while for GWAS, we only need to track study. The only other large structure in these classes is aGenotypeHandlefor the LD sketch.MultiStudyQtlDataset: this classes has slots for aQtlSumStatsobject and a list ofQtlDatasetobjects, one per study. The requirement here is that the instantiation of this class requires either at least twoQtlDatasetobjects, or at least oneQtlDatasetobject and oneQtlSumStatsobject. You can of course have both a list ofQtlDatasetobjects and aQtlSumStatsobject too.QtlFineMappingResult/GwasFineMappingResult: These classes hold the results of a fine-mapping analysis withfineMappingPipeline. This is includes the SuSiE fits as well as thetopLocislot which can be returned as a data frame or GRanges object.TwasWeights: This class holds the results of atwasWeightsPipelineanalysis, which are mainly just regression fits from which TWAS weights can be extracted.Pipeline functions
sumStatsQc: This is the sole home of all of our summary statistics QC now. It takes aQtlSumStatsorGwasSumStatsobject and returns another with QC applied to it.mashPipeline: This pipeline takes either aQtlSumStatsobject or aQtlFineMappingResultand usesmashrto estimate themashprior for input tomr.mashandmvsusie. It returns an object of typeMashPrior.fineMappingPipeline: This pipeline takes in any of aQtlDataset,QtlSumStats,GwasSumStatsorMultiStudyQtlDatasetobject, and returns aFineMappingResultafter running any ofsusie,mvsusieorfsusie. When aMultiStudyQtlDatasetobject is given, the fine-mapping is run separately perQtlDatasetobject (since there is no "multi-study" individual-level fine-mapping right now). Multi-trait and multi-context fine-mapping are handled automatically whenmvsusieandfsusieare selected as methods. Multi-study fine-mapping can be done with mvSuSIE RSS on aQtlSumStats/GwasSumStats) object (including if the theQtlSumStatsobject is inside of aMultiStudyQtlDatasetobject).twasWeightsPipeline: This pipeline takes in any of aQtlDataset,QtlSumStats, orMultiStudyQtlDataset, and optionally aFineMappingResultobject and learns TWAS weights with regularized regression. Multi-trait and multi-context regression is handled automatically whenmr.mashis requested.MultiStudyQtlDatasetobjects are handled the same way as infineMappingPipeline, with multi-study regularized regression being possible only with mr.mash RSS. The ensemble method is run automatically if more than regression model is requested. If aFineMappingResultis provided, the weights can be extracted from this object and added to the ensemble model.qtlEnrichmentPipeline: This pipeline takes aQtlFineMappingResultand aGwasFineMappingResultand computes heritability enrichment of the GWAS for QTLs as originally implemented byfastenloc.colocboostPipeline: This pipeline takes in any of aQtlDataset,QtlSumStats,GwasSumStatsorMultiStudyQtlDatasetand runs colocboost. Since colocboost is able to directly handle all of these types, the main thing this pipeline does is just extract all the right inputs and passes them tocolocboost. We may still need to discuss options for making the return value of this nicer.causalInferencePipeline: This pipeline takes at least one of aTwasWeightsandQtlFineMappingResultobject and aGwasSumStatsobject and computes TWAS Z-scores, and if aQtlFineMappingResultobject was provided, MR Wald ratios. The return value is just a data frame, though we can iterate on this more if needed.ctwasPipeline: This pipeline takes a TWAS Z-scores and aGwasSumStatsobject and runs CTWAS on them. If multiple TWAS Z-scores exist for the same context and trait (this means multiple methods were used), it can iterate over these. And the user can request either marginal CTWAS per-context or multi-context CTWAS.colocPipeline: This pipeline takes at least one of aTwasWeightsandQtlFineMappingResultobject and either aGwasSumStatsobject or aGwasFineMappingResultobject. When aGwasSumStatsobject is provided, window-level fine-mapping of the GWAS is run, while when aGwasFineMappingResultis provided, window-level fine-mapping is skipped. If the enrichment information fromqtlEnrichmentPipelineis provided, then the pipeline is running SuSiE-enloc while when it is absent, it is just running the regular SuSiE-coloc.Pipeline ordering - shared
This is the key logic everyone needs to understand moving forward. The above class and pipeline definitions are to make this section interpretable:
QtlDataset,QtlSumStats,MultiStudyDatasetandGwasSumStatsobjects.QtlDatasetconstruction should not be parallelized or split by gene/region, because our classes now know how to extract specific columns from the phenotype data.QtlSumStatsandGwasSumStatsobjects do need to be constructed per gene/region because loading a full GWAS summary statistic would use a lot of memory.MultiStudyQtlDatasetobjects that only containQtlDatasetobjects should also be constructed once without splitting over gene/region. If they need to also containQtlSumStats, those should be made per gene and added afterward.sumStatsQctoQtlSumStats(if used) andGwasSumStatsobjects. For now, ifQtlSumStatsneed to be added to aMultiStudyQtlDataset, the QC should be done before adding the object to theMultiStudyQtlDataset.Pipeline ordering - TWAS/MR
mr.mash/mvsusieonly and optional) Run the univariatefineMappingPipelineper-trait/per-context on theQtlDataset/QtlSumStats/MultiStudyQtlDatasetobject to get aFineMappingResultto pass to themashPipeline. This can also double as a screening step to decide where muti-trait/multi-context fine-mapping should be performedmr.mash/mvsusieonly) Run themashPipelineto get aMashPrior. Step 3 is needed if the user wants to use aFineMappingResultto make it easier to select strong signals.mvsusieonly) Run thetwasWeightsPipelineformr.mashwith theQtlDataset/QtlSumStats/MultiStudyQtlDatasetto get aTwasWeightsobject with amr.mashfit with mixture weights and residual variance to pass tomvsusie.fineMappingPipelinecall on theQtlDataset/QtlSumStats/MultiStudyQtlDatasetto get aFineMappingResult. If the analysis is univariate only, then this is the only timefineMappingPipelineneeds to be called. Otherwise if step 1 was already run, theFineMappingResultfrom there can be provided here and only new methods (multivariate or additional univariate) are run.mvsusierequires the output of steps 2 and 3 as additional inputs.twasWeightsPipelinecall on theQtlDataset/QtlSumStats/MultiStudyQtlDatasetto get aTwasWeightsobject. If aFineMappingResultis provided, its weights are extracted and used in the ensemble model without rerunning fine-mapping. For the multivariate case,mr.mashandmvsusiewill have already been run, so the only thing left to do there is the ensemble model between those two methods.causalInferencePipelineon theFineMappingResultfrom step 4 (can get TWAS Z-scores and MR) and/or theTwasWeightsoutput from step 5 (TWAS Z-scores only).Pipeline ordering - genome-wide GWAS fine-mapping
fineMappingPipelineon theGwasSumStatsobject from step 2 of the shared pipeline per LD block.Pipeline ordering - univariate colocalization
qtlEnrichmentPipelineon theQtlFineMappingResultfrom step 2/step 4 of the TWAS/MR pipeline and theGwasFineMappingResultof step 1 of the genome-wide GWAS fine-mapping pipeline.colocPipeline, optionally with the enrichment from step 1, on theQtlFineMappingResultfrom step 2/step 4 of the TWAS/MR pipeline and either theGwasSumStatsobject from step 2 of the shared pipeline or theGwasFineMappingResultfrom step 1 of the genome-wide GWAS fine-mapping pipeline.Pipeline ordering - colocboost
colocBoostPipelineon one of: theQtlDatasetobject from step 1 of the shared pipeline, theQtlSumStatsobject from step 2 of the shared pipeline, or theMultiStudyQtlDatasetobject from step 1 or 2 of the shared pipeline and theGwasSumStatsobject from step 2 of the shared pipeline.Key improvements from before
There are several critical improvements that have made or will make the protocol more intuitive and make unit-testing and development much easier:
QtlDataset/QtlSumStats/MultiStudyQtlDatasetand forcing users to strictly organize their data is a sensible way, we greatly reduce failures in later steps due to data management issuesQtlDataset/QtlSumStats/MultiStudyQtlDatasetobjects requires dealing with messy I/O. Once that is done, all subsequent pipeline steps are only reading RDS objects or raw genotypes.Future improvements
There is room for improvement here. My current ideas:
loadQtlDatasetFromManifest/loadQtlSumStatsFromManifest/loadGwasSumStatsFromManifest/loadMultiStudyQtlDatasetFromManifestfunctions: These functions would take in a manifest file with the right columns and call the constructors for the user. A couple of restrictions:This is a huge document so please ask as many questions as needed to clarify things!
Beta Was this translation helpful? Give feedback.
All reactions