Skip to content

2.2 Joining and Statistics

coding man edited this page Nov 4, 2026 · 1 revision

Joining and Statistics

Relevant source files

The following files were used as context for generating this wiki page:

Purpose and Scope

This page covers the data transformation core of VariantScope, located in src/core. It details how raw ClinVar variant records are joined with gnomAD allele frequencies and validated against UniProt reference sequences (src/core/join.js src/core/join.js:1-92), how statistical metrics, rarity categories, and spatial density windows are computed (src/core/stats.js src/core/stats.js:1-92), how natural-language summary sentences are built (src/core/summaryText.js src/core/summaryText.js:1-73), and how data is prepared for tabular display (src/core/tableModel.js src/core/tableModel.js:1-82), CSV serialization (src/core/csv.js src/core/csv.js:1-35), and UI rendering (src/core/format.js src/core/format.js:1-45).


1. Variant Joining and Numbering Validation (join.js)

The src/core/join.js module integrates multiple disparate data sources into a single unified variant schema. It performs coordinate- or protein-change matching against gnomAD and checks residue numbering validity against UniProt sequences [src/core/join.js:1-3()].

Coordinate vs. Protein-Change Matching

When linking ClinVar variants to gnomAD records, findGnomad prioritizes genomic coordinates (coordKey). If coordinates are absent, it falls back to protein-change matching (proteinKey), provided that exactly one gnomAD variant shares that exact amino acid change src/core/join.js:41-51. Ambiguous matches (multiple gnomAD variants sharing a protein change) are flagged as unknown to prevent incorrect frequency assignment src/core/join.js:70-74.

Numbering Validation

The function checkNumbering validates whether the reference amino acid (refAA) in a variant matches the UniProt sequence at the specified 1-based position src/core/join.js:9-11. The aggregate numberingReport evaluates the overall match rate against NUMBERING_MIN_RATE (0.95), flagging datasets where fewer than 95% of variants match the expected sequence residue src/core/join.js:6-23.

Diagram: Joining and Matching Architecture

graph TD
    ClinVarData["ClinVar Records (clinvar)"] --> joinVariants["joinVariants() src/core/join.js:66"]
    GnomadData["gnomad.variants"] --> indexGnomad["indexGnomad() src/core/join.js:26"]
    SequenceData["UniProt sequence"] --> checkNumbering["checkNumbering() src/core/join.js:9"]
    
    indexGnomad --> findGnomad["findGnomad() src/core/join.js:41"]
    ClinVarData --> findGnomad
    findGnomad --> gnomadPart["gnomadPart() src/core/join.js:56"]
    
    checkNumbering --> numberingReport["numberingReport() src/core/join.js:14"]
    gnomadPart --> UnifiedOutput["Unified Variant Object"]
    numberingReport --> UnifiedOutput
    
    subCode1["src/core/join.js"]
    subCode2["src/core/parse.js"]
Loading

Sources: src/core/join.js:1-92


2. Rarity Buckets, Density Windows, and Statistics (stats.js)

The src/core/stats.js module computes allele frequency categorizations, spatial variant density across the protein sequence, and summary statistics [src/core/stats.js:1-1()] linkages.

Rarity Thresholds and Buckets

Allele frequencies (AF) are binned into defined rarity categories using rarityFromAf based on constants defined in RARITY_THRESHOLDS src/core/stats.js:4-26:

Density Windows and Prefix Sums

To calculate local clustering of pathogenic variants along a sequence of length length, densityWindows constructs a sliding window of half-width DENSITY_HALF_WINDOW (10 residues) src/core/stats.js:13-14, src/core/stats.js:38-39. It utilizes prefix sums to achieve $O(1)$ lookup per residue instead of repeated scanning src/core/stats.js:44-56.

Summary Aggregation

The summarize function filters variants by numberingOk and aggregates total counts, pathogenic shares, proportions in confident AlphaFold regions (PLDDT_CONFIDENT $\ge 70$), and counts of absent/ultra-rare pathogenic variants src/core/stats.js:11-12, src/core/stats.js:71-92.

Diagram: Statistical Metric and Summary Pipeline

graph TD
    UnifiedVariants["Unified Variants Array"] --> summarize["summarize() src/core/stats.js:72"]
    summarize --> filterValid["filter(v => v.numberingOk)"]
    filterValid --> pathogenicShare["pathogenicShare"]
    filterValid --> pathogenicInConfidentRegions["pathogenicInConfidentRegions"]
    filterValid --> pathogenicAbsentOrUltraRare["pathogenicAbsentOrUltraRaw"]
    
    PositionsArray["Pathogenic Positions"] --> densityWindows["densityWindows() src/core/stats.js:38"]
    densityWindows --> PrefixSums["Prefix Sum Array O(1)"]
    PrefixSumArray --> WindowCounts["Counts & Max Density"]
    
    subCode1["src/core/stats.js"]
Loading

Sources: src/core/stats.js:1-92


3. Rule-Based Summary Generation (summaryText.js)

The src/core/summaryText.js module translates statistical aggregates and variant lists into readable sentences for UI panels src/core/summaryText.js:1-30.

Key Functions

  • densestRegion(variants, length): Filters for pathogenic variants with valid numbering, executes densityWindows, and identifies the central residue with the maximum local density cluster src/core/summaryText.js:14-27.
  • buildSummarySentences({ gene, summary, variants, length, constraint, plddt }): Constructs a deterministic list of text statements summarizing total analysed counts, pathogenic proportions, AlphaFold confidence coverage, gnomAD rarity distributions, densest cluster locations, gnomAD constraint metrics (obsMis, expMis, oeMis, misZ), and legend clarifications src/core/summaryText.js:30-73.

Sources: src/core/summaryText.js:1-73


4. Table Model, Filtering, and Pagination (tableModel.js)

The src/core/tableModel.js module implements decoupled state logic for tabular interfaces, allowing filtering, sorting, and pagination without DOM dependencies src/core/tableModel.js:1-2.

Core Operations

  • filterVariants(variants, options): Filters a variant list based on text search queries (matching protein changes, classifications, labels, review statuses, and rarity), selected classification/rarity filter chips, and the onlyNumberingOk toggle src/core/tableModel.js:25-37.
  • sortVariants(variants, key, direction): Sorts variants using defined property accessors in SORT_KEYS (change, classification, review rank, allele frequency, rarity, pLDDT, matchedBy), defaulting secondary sorts to variant position src/core/tableModel.js:47-64.
  • paginate(list, page, size): Slices arrays into pages of size PAGE_SIZE (50), returning pagination metadata (rows, page, pageCount, total) src/core/tableModel.js:12, src/core/tableModel.js:66-76.
  • pageOfVariant(list, clinvarId, size): Locates the 1-based page number containing a specific clinvarId for view synchronization src/core/tableModel.js:78-82.

Sources: src/core/tableModel.js:1-82


5. CSV Export and Data Sanitization (csv.js)

The src/core/csv.js module manages the export of unified variant arrays into comma-separated values format src/core/csv.js:1-35.

Spreadsheet Injection Prevention

The csvCell(value) helper sanitizes output values. Cells beginning with formula injection characters (=, +, -, @, \t, \r) that are not standard numeric strings are prefixed with a single quote ('), and interior quotes are escaped to prevent spreadsheet execution vulnerabilities src/core/csv.js:4-9. The variantsToCsv function maps columns including gene, clinvar ID, protein change, position, classification, review status, gnomad attributes, rarity, pLDDT, and numbering status src/core/csv.js:11-35.

Sources: src/core/csv.js:1-35


6. Formatting Utilities (format.js)

The src/core/format.js module provides pure formatting helper functions for numbers, percentages, dates, scores, and byte sizes src/core/format.js:1-45.

Key Functions

  • formatAf(af): Formats allele frequencies into exponential notation or '0' or NOT_AVAILABLE ('not available') src/core/format.js:3-8.
  • formatPct(share): Formats percentage share objects into string representations (e.g., "17.7%") src/core/format.js:10-13.
  • formatCount(n): Applies US locale thousands separators (e.g., "1,500") src/core/format.js:15-18.
  • formatScore(value, digits): Formats scores to significant digits or exponential notation for very small values ($< 0.001$) src/core/format.js:20-25.
  • formatAge(fetchedAt, now): Computes relative time stamps (e.g., "today", "1 day ago") src/core/format.js:27-32.
  • formatBytes(bytes): Converts raw byte counts into human-readable strings ("0 B", "820 KB", "14.2 MB") src/core/format.js:39-45.

Sources: src/core/format.js:1-45


Clone this wiki locally