Genomic Data Smoothing
LOWESS for methylation profiles, ChIP-seq signals, and other genomic data.
Overview
Section titled “Overview”Genomic data often contains noise from sequencing depth variation, PCR artifacts, or biological heterogeneity. LOWESS smoothing helps reveal underlying patterns.
Methylation Profile Smoothing
Section titled “Methylation Profile Smoothing”The Challenge
Section titled “The Challenge”DNA methylation data (from bisulfite sequencing or arrays) shows position-dependent patterns that can be obscured by measurement noise.
Solution
Section titled “Solution”A small fraction = 0.1 lets LOWESS follow fine-scale spatial structure without smearing the transitions between methylated and unmethylated regions. confidence_intervals = 0.95 produces uncertainty bands that naturally widen at positions with sparser CpG coverage, making low-confidence segments immediately apparent in the plot.
const { Lowess } = require('fastlowess-wasm');
const n = 100;const positions = Float64Array.from({ length: n }, (_, i) => i * 100.0);const observed = Float64Array.from(positions, p => 50 + Math.sin(p / 100) * 20 + ((p * 7 % 17) / 17 - 0.5) * 5);
// positions and observed are your methylation data (Float64Array)const model = new Lowess({ fraction: 0.1, iterations: 3, confidence_intervals: 0.95});const result = model.fit(positions, observed);console.log("CI lower[0]:", result.confidence_lower[0].toFixed(4));CI lower[0]: 44.8225ChIP-seq Signal Smoothing
Section titled “ChIP-seq Signal Smoothing”Application
Section titled “Application”ChIP-seq experiments produce sparse, noisy coverage data. LOWESS can help identify binding regions.
fraction = 0.05 provides high spatial resolution — important for resolving narrow binding peaks that would otherwise be smeared into the background. The larger iterations = 5 is deliberate: Poisson-distributed read counts produce tall, isolated spikes, and extra robustness iterations progressively down-weight them so the estimated background level is not inflated by a handful of extreme counts.
const { Lowess } = require('fastlowess-wasm');
const n = 100;const positions = Float64Array.from({ length: n }, (_, i) => i * 100.0);const observed = Float64Array.from(positions, p => 50 + Math.sin(p / 100) * 20 + ((p * 7 % 17) / 17 - 0.5) * 5);
const model = new Lowess({ fraction: 0.05, iterations: 5});const result = model.fit(positions, observed);
// Find peaksconst smoothed = result.y;const peaks = positions.filter((p, i) => smoothed[i] > 25.0);console.log("Peak count:", peaks.length);Peak count: 100Large Genome Coverage (Streaming)
Section titled “Large Genome Coverage (Streaming)”For whole-genome data that doesn’t fit in memory:
const { StreamingLowess } = require('fastlowess-wasm');
const xChunk = Float64Array.from({ length: 1001 }, (_, i) => i * 10.0);const yChunk = Float64Array.from(xChunk, p => 50 + Math.sin(p / 100) * 20 + 5.0);
const processor = new StreamingLowess( { fraction: 0.05, iterations: 3 }, { chunk_size: 100, overlap: 10 });
processor.process_chunk(xChunk, yChunk);const result = processor.finalize();console.log("y[0]:", result.y[0].toFixed(4));y[0]: 41.2977Best Practices for Genomic Data
Section titled “Best Practices for Genomic Data”| Consideration | Recommendation |
|---|---|
| Fraction | 0.05–0.15 (preserve local features) |
| Iterations | 3–5 (handle sequencing outliers) |
| Large data | Use streaming mode |
| Sparse regions | Use boundary_policy="extend" |
| Multiple chromosomes | Process separately or ensure sorted |
See Also
Section titled “See Also”- Concepts — How LOWESS works
- Parameters — All options
- Robustness — Outlier downweighting in depth
- Merge Strategies — Streaming chunk reconciliation
- Boundary Handling — Edge handling for sparse regions
- Real-Time Processing — For sequencing runs