Skip to content

About

Linkage disequilibrium (LD) browser: Explore LD patterns at genome-wide scale

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

magenpy LD Browser

A standalone JavaScript reader and browser UI for the Zarr hierarchy produced by magenpy.LDMatrix. The folder has no coupling to the Python package and can be moved to its own repository later.

The reader understands magenpy's compact CSR-like representation:

matrix/
  data       strict upper-triangle correlations
  indptr     row offsets
metadata/
  snps, a1, a2, maf, bp, cm, ldscore
root attrs   Chromosome, Sample size, Genome build, LD estimator, ...

It uses Zarrita for lazy, chunk-aware access to Zarr v2 and v3 stores. Integer LD values are dequantized using the same scale as magenpy.

Variant metadata used for filtering and matching (snps, alleles, MAF, BP, cM, and stored LD scores) is read once during validation and retained for the life of the matrix. Concurrent requests for the same field share one read. Root metadata such as chromosome is already resident in the opened Zarr group.

Consolidated metadata is enabled by default. For ZIP archives whose Zarr root is nested (for example chr_22/.zmetadata), the archive store is scoped to that directory before metadata discovery. Array and group descriptors are therefore served from .zmetadata instead of separate HTTP range requests.

Remote ZIP initialization caches the archive tail and coalesces adjacent indptr and variant-metadata entries into as few byte-range requests as possible. matrix/data entries are excluded from this cache and from coalescing, preserving exact lazy chunk reads during analysis.

Range reads map the requested variant pairs to physical matrix/data chunks, fetch each relevant chunk once, and never scan the rest of the LD array. Dense block assembly runs in an embedded WebAssembly kernel. Its auditable source is native/ld_range.wat; after changing it, regenerate the embedded module with npm run build:wasm.

Run the browser

Requires Node.js 20.19 or newer.

cd ld_browser
npm install
npm run dev

Open the URL printed by Vite. You can select a local .zarr directory or Zarr ZIP (the files stay in the browser), or enter an hf://, s3://, gs://, gcs://, or HTTP(S) source. The built-in UK Biobank preset streams directly from the Hugging Face archive.

In browsers that support showDirectoryPicker(), directory-backed Zarr stores are read lazily through a read-only filesystem handle. Other browsers fall back to the webkitdirectory file selector. The handle-based picker requires HTTPS or a trusted local development origin such as localhost.

npm test
npm run build

The normal test suite is offline. To additionally check the live public UKB archive on Hugging Face and Oxford HTTPS Zarr directory:

LD_BROWSER_LIVE_TEST=1 npm test

JavaScript API

import { LDMatrix } from "./src/LDMatrix.js";

const ld = await LDMatrix.fromUrl("https://example.org/chr_22.zarr/");
await ld.validate();

console.log(ld.summary());
console.log(await ld.get("rs123", "rs456"));
console.log(await ld.getRow("rs123", { symmetric: true, returnIndices: true }));

const upper = await ld.denseBlock(1000, 1100, { symmetric: false });
const symmetric = await ld.denseBlock(1000, 1100);
const product = await ld.dot(new Float64Array(ld.nSnps).fill(1));
const scores = await ld.computeLdScores();

HTTPS, Hugging Face, S3, and Google Cloud Storage

Directory-style Zarr v2 stores can be streamed directly over HTTP(S):

const ukb = await LDMatrix.fromUrl(
  "https://www.stats.ox.ac.uk/publication-data/sge/plmgrp/temp/LD_matrices/EUR/chr_22/",
);

fromUri() accepts the same Hugging Face URI form as huggingface_hub. It translates the URI to the Hub download endpoint and opens the nested chr_N group used by the magenpy archives:

const ukb = await LDMatrix.fromUri(
  "hf://datasets/shz9/ukb-ld/EUR/chr_22.zip",
);

// Pin a branch, tag, or full commit after the repository name.
const pinned = await LDMatrix.fromUri(
  "hf://datasets/shz9/ukb-ld@18d7b11873dbccd9ba463004f4e48e0dcb46f04b/EUR/chr_22.zip",
);

// Private or gated repositories can use a read token.
const privateLd = await LDMatrix.fromHuggingFace(uri, { token: hfToken });

Public S3 stores use virtual-hosted HTTPS URLs. The default region is us-east-2, matching magenpy's Python S3 reader:

const s3Ld = await LDMatrix.fromUri(
  "s3://my-public-bucket/ld/EUR/chr_22.zarr",
  { region: "eu-west-2" },
);

// Path-style S3-compatible service, such as MinIO or institutional storage.
const compatible = await LDMatrix.fromS3("s3://bucket/ld/chr_22.zarr", {
  endpoint: "https://objects.example.org",
  pathStyle: true,
});

Public Google Cloud Storage directories and ZIPs accept either gs:// or gcs://. Protected buckets may be opened with an OAuth bearer token:

const publicGcs = await LDMatrix.fromUri(
  "gs://my-public-bucket/ld/EUR/chr_22.zarr",
);
const protectedGcs = await LDMatrix.fromGcs(
  "gcs://my-protected-bucket/ld/EUR/chr_22.zarr",
  { token: googleOAuthToken },
);

Browser sources must allow CORS. In particular, the Oxford HTTPS directory shown above does not return an Access-Control-Allow-Origin header, so browsers block direct reads from it; use the built-in Hugging Face archive or configure the server to allow the browser application's origin. Remote ZIPs must also support HEAD and byte-range requests. Private S3 stores require pre-signed URLs or a custom Zarrita fetchOptions.fetch function that applies AWS SigV4 signing.

Node.js also has a local-path entry point:

import { fromPath } from "magenpy-ld-browser/node";

const directory = await fromPath("./chr_22.zarr");
const zipped = await fromPath("./chr_22.zip");

LDMatrix.fromStore(store) accepts any Zarrita-compatible readable store. This is useful for S3 gateways, reference stores, authenticated fetch wrappers, or embedding the library in another application.

Supported operations

  • Lazy metadata and upper-triangle row reads
  • Numeric-index and rsID lookup
  • Pairwise correlations with implicit symmetry and unit diagonal
  • BP-range selection with the native upper triangle shown by default; symmetrization mirrors the cached block without another store read
  • CSV export of the current heatmap (unmaterialized lower-triangle cells remain blank)
  • Boolean/index masks and comma/newline-delimited SNP filtering
  • Hosted UKB ancestry and chromosome presets
  • Comparison of up to four same-chromosome matrices from any mix of local directories, local ZIPs, hosted presets, and custom cloud sources; shared variants are selected automatically, and matrices can be paired into upper/lower triangle heatmaps
  • Variant metadata display including stored LD scores
  • Interactive tagging-variant discovery from comma/newline-delimited rsIDs using an r² threshold, with CSV export
  • Order-aware LD pruning of a supplied variant set using an r² threshold, with CSV export
  • Streaming matrix-vector multiplication
  • Corrected or uncorrected LD-score calculation
  • Greedy LD pruning and tagging-variant discovery
  • SNP-table generation and structural validation
  • Async row iteration

After a matrix opens, the browser presents three analysis modes: regional LD visualization, variant pruning, and tagging-variant discovery. The latter two run against the primary matrix. Their sparse computations read correlation chunks in batches and do not construct a dense chromosome-wide matrix.

Hosted references are defined in src/hosted-references.json. Each entry supplies its dataset details, matrix-structure note, population choices, available chromosomes, defaults, and URI template; the hosted-matrix controls are generated from that catalog. URI templates support {population} and {chromosome} placeholders, whose selected values are URL-encoded before use. Vite bundles this JSON during the static build, so it does not add a runtime network request.

The implementation is intentionally read-only. Constructing or mutating an LD store remains the responsibility of magenpy/Python, where validation and quantization behavior are already established.

About

Linkage disequilibrium (LD) browser: Explore LD patterns at genome-wide scale

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages