mecfs_bio.build_system.task.gwaslab.ldsc_diagnostic_plot_task
Task that draws the LD-score-regression diagnostic plot for a heritability analysis.
LD score regression fits E[chi^2_j] = intercept + (N * h2 / M) * ld_j but, because there are millions of variants, the fit is never shown -- standard regression diagnostics are essentially never performed (see the discussion in gwaslab_snp_heritability_by_ldsc_task). This task supplies one: it bins the analysis's variants into equal-count LD-score bins and plots each bin's mean chi-square against the fitted line, so model misfit (bins drifting off the line) and confounding (an intercept away from one, or a low-LD bin sitting below one) are visible by eye.
It is a sibling of SNPHeritabilityByLDSCTask rather than a reader of its output: it takes that task purely to reach a single, consistent definition of the analysis (which summary statistics, which LD reference, the preprocessing pipe, the sample size), and re-runs LD-score regression on that definition to draw the fitted line.
The fit is re-run with gwaslab -- the same estimator the heritability task uses -- so the line and the annotated intercept/heritability match what that task reports, rather than an independent solver that differs in its treatment of extreme chi-square (gwaslab keeps all variants and uses a two-step intercept estimator with a cutoff at chi-square 30; the repo's GenomicSEM port cuts variants above max(0.001*N, 80) and fits a single-step intercept). The re-run passes NaN prevalences so gwaslab reports observed-scale heritability, sidestepping the liability-scale rescaling it applies to binary traits, which would otherwise make the fitted slope hard to reconstruct. Consistently, the binned points keep every merged variant -- no high-chi-square cut -- to match the variant set gwaslab's slope regression uses.
The left y-axis is chi-square; the right y-axis is the same points rescaled to chi^2 * M / N, in which the fitted slope equals the observed-scale heritability and the axis is comparable across traits of different sample size. The two axes are one affine relabeling of a single set of marks, not two independent measures.
Classes:
-
LdscDiagnosticPlotConfig–How the diagnostic is binned and framed.
-
LdscDiagnosticPlotTask–Draw the LD-score-regression diagnostic plot for a SNPHeritabilityByLDSCTask analysis.
-
LdscFit–The observed-scale LD-score-regression fit needed to draw the line and annotate it.
-
LdscSumstats–The slice of a gwaslab Sumstats the diagnostic uses: its mutable variant table (which the
-
MergedDiagnosticData–Per-variant chi-square and LD score for the variants shared by the summary statistics and
Functions:
-
build_diagnostic_figure–Assemble the interactive figure: binned mean chi-square, the fitted line, a chi^2 = 1
-
compute_chi2–The per-variant chi-square. Prefer an existing Z column -- the same precedence
-
gwaslab_observed_fit–Run gwaslab's LD-score regression on the observed scale and return its intercept and
-
liability_h2–The liability-scale heritability for a binary phenotype, or None for a quantitative one
-
merge_chi2_with_ld_scores–Inner-join the summary statistics to the LD reference on rsID, pairing each variant's
-
resolve_sample_size–The scalar N the fit and the right-axis rescaling use, mirroring how the heritability task
LdscDiagnosticPlotConfig
How the diagnostic is binned and framed.
x_range and chi2_m_over_n_range are left unset for per-trait autoscaling; pin them to a shared window to make a set of plots comparable across traits (equal LD-score and heritability-unit axes). chi2_m_over_n_range is given in the right-axis units (chi^2 * M / N).
Attributes:
-
chi2_m_over_n_range(tuple[float, float] | None) – -
n_bins(int) – -
show_error_bars(bool) – -
title(str | None) – -
x_range(tuple[float, float] | None) –
chi2_m_over_n_range
class-attribute
instance-attribute
LdscDiagnosticPlotTask
Bases: Task
Draw the LD-score-regression diagnostic plot for a SNPHeritabilityByLDSCTask analysis.
Methods:
Attributes:
-
config(LdscDiagnosticPlotConfig) – -
deps(list[Task]) – -
fit_estimator(Callable[[LdscSumstats, str, GenomeBuild], LdscFit]) – -
ldsc_task(SNPHeritabilityByLDSCTask) – -
meta(Meta) – -
sumstats_reader(Callable[[Asset], LdscSumstats]) –
fit_estimator
class-attribute
instance-attribute
fit_estimator: Callable[
[LdscSumstats, str, GenomeBuild], LdscFit
] = field(default=gwaslab_observed_fit)
sumstats_reader
class-attribute
instance-attribute
create
classmethod
create(
asset_id: str,
ldsc_task: SNPHeritabilityByLDSCTask,
config: LdscDiagnosticPlotConfig = LdscDiagnosticPlotConfig(),
sumstats_reader: Callable[
[Asset], LdscSumstats
] = _read_sumstats,
fit_estimator: Callable[
[LdscSumstats, str, GenomeBuild], LdscFit
] = gwaslab_observed_fit,
) -> LdscDiagnosticPlotTask
Source code in mecfs_bio/build_system/task/gwaslab/ldsc_diagnostic_plot_task.py
execute
Source code in mecfs_bio/build_system/task/gwaslab/ldsc_diagnostic_plot_task.py
LdscFit
LdscSumstats
Bases: Protocol
The slice of a gwaslab Sumstats the diagnostic uses: its mutable variant table (which the task reads and rewrites through the preprocessing pipe) plus enough to run observed-scale LD-score regression and read back its summary. gwaslab's Sumstats satisfies this; a test can inject a stand-in. ldsc_h2 is declared read-only (a property) so gwaslab's plain DataFrame attribute satisfies the pd.DataFrame | None slot covariantly.
Methods:
Attributes:
MergedDiagnosticData
build_diagnostic_figure
build_diagnostic_figure(
bins: LdscDiagnosticBins,
fit: LdscFit,
n: float,
m: float,
config: LdscDiagnosticPlotConfig,
h2_liability: float | None = None,
) -> go.Figure
Assemble the interactive figure: binned mean chi-square, the fitted line, a chi^2 = 1 reference, and a right-hand axis in chi^2 * M / N units whose slope reads as heritability.
h2_liability, when given (a binary phenotype), is annotated as a second heritability line.
Source code in mecfs_bio/build_system/task/gwaslab/ldsc_diagnostic_plot_task.py
264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 | |
compute_chi2
The per-variant chi-square. Prefer an existing Z column -- the same precedence drop_variants_with_degenerate_z uses -- and otherwise form Z from BETA / SE.
Source code in mecfs_bio/build_system/task/gwaslab/ldsc_diagnostic_plot_task.py
gwaslab_observed_fit
Run gwaslab's LD-score regression on the observed scale and return its intercept and heritability -- the same estimator the heritability task uses, so the drawn line matches what that task reports. None (not NaN) prevalences keep gwaslab on the observed scale: its summary labels the result 'Liability' whenever both prevalences are not None, which renames the h2 column, whereas None reports plain observed-scale h2 -- the scale in which the chi-square-units slope is reconstructable.
sumstats is a gwaslab Sumstats already carrying the analysis's preprocessing and sample size.
Source code in mecfs_bio/build_system/task/gwaslab/ldsc_diagnostic_plot_task.py
liability_h2
The liability-scale heritability for a binary phenotype, or None for a quantitative one (which has no liability scale). Uses gwaslab's own observed-to-liability conversion so the value matches the liability heritability the heritability task reports, with the sample prevalence as P and the estimated population prevalence as K.
Source code in mecfs_bio/build_system/task/gwaslab/ldsc_diagnostic_plot_task.py
merge_chi2_with_ld_scores
Inner-join the summary statistics to the LD reference on rsID, pairing each variant's chi-square with its LD score. Variants missing from either side drop out, which restricts the plot to the LD reference's variant set (HapMap3, in the standard reference).
Source code in mecfs_bio/build_system/task/gwaslab/ldsc_diagnostic_plot_task.py
resolve_sample_size
resolve_sample_size(
sumstats: DataFrame,
set_n: int | None,
phenotype_info: PhenotypeInfo,
) -> float
The scalar N the fit and the right-axis rescaling use, mirroring how the heritability task sources it: an explicit override, then a per-variant N column (averaged), then the phenotype's total sample size.