mecfs_bio.build_system.task.ppp_ldsc.trait_alignment
Align an external trait's signed z-score onto the shared UKB-PPP LDSC context SNP set.
The batched rg kernel needs the trait's z-score in the SAME row order and the SAME effect-allele orientation as the per-protein z-scores. Protein betas are already oriented to the variant index's effect allele (see align_protein_to_index), so we orient the trait to the index effect allele too: join the trait to the context variants on rsID, keep z = BETA/SE where the trait's alleles match the index orientation, negate it where they are swapped, and drop it (NaN) where the alleles do not match at all or the trait lacks the variant. Strand-ambiguous variants are already removed from the context, so no palindrome handling is needed here.
The trait sample size is taken per-SNP from the trait's N column when present, otherwise from a caller-supplied constant. A collapsed trait/context overlap almost always means a harmonization failure upstream (wrong genome build, malformed rsIDs, or systematic allele mismatch), so we fail fast when fewer than min_trait_snps context variants match.
The trait arrives lazily and is narrowed to the context variants before anything is materialized. Only a small fraction of a trait's variants are HapMap3 ones, and a GWAS on whole-genome sequencing data can carry hundreds of millions of rows, so restricting to the context first is what keeps that input's size off the peak memory of the run.
The trait is a narwhals LazyFrame because it has been through a DataProcessingPipe, which is free to change the backend. The filter is therefore expressed in narwhals and only the (small) filtered result is collected into polars, where the allele-orientation helpers live. Converting to polars any earlier would mean collecting the whole trait first, which is exactly what the filter exists to avoid.
Classes:
-
TraitAligned–The trait aligned to the context SNP set (parallel (S,) arrays in context row order).
Functions:
-
align_trait_to_context–Align a trait sumstats dataframe onto the context SNP set.
Attributes:
-
logger–
TraitAligned
The trait aligned to the context SNP set (parallel (S,) arrays in context row order).
z: signed trait z-score oriented to the index effect allele, NaN where the trait lacks the variant or its alleles do not match. n: trait sample size per SNP, NaN where z is NaN.
Attributes:
align_trait_to_context
align_trait_to_context(
trait_df: LazyFrame,
context_variants: DataFrame,
*,
trait_total_sample_size: int | None,
min_trait_snps: int,
) -> TraitAligned
Align a trait sumstats dataframe onto the context SNP set.
trait_df: a LAZY narwhals frame with gwaslab-standard columns rsID, EA, NEA, BETA, SE, and optionally N. Kept lazy so the filter down to the context variants happens during the scan, and backend-agnostic because a DataProcessingPipe may have produced it. context_variants: the context SNPs in row order, with rsID and the index EA/NEA. trait_total_sample_size: constant N to use when trait_df has no N column (else None).
Source code in mecfs_bio/build_system/task/ppp_ldsc/trait_alignment.py
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 | |