An interactive NGS sequencing-QC dashboard in R with canvasXpress
R
canvasXpress
dashboard
bioinformatics
visualization
Triage a 96-sample sequencing run in R: an overview QC heatmap plus linked, cross-filtering panels that flag failing samples and batch effects — from portable specs, no Shiny.
Author
Isaac Neuhaus
Published
October 29, 2026
After a sequencing run you get a QC table — one row per sample, a dozen metrics — and you need to answer three questions fast: which samples fail, is a whole batch off, and are the failures correlated? A single scatter can’t do it; you want several views that talk to each other — select a suspicious sample in one and see it light up in the rest. In R that usually means Shiny (a server, reactive wiring). canvasXpress does it client-side: give every panel the same broadcast group and a selection broadcasts to all of them. Here we build a real QC dashboard for 96 RNA/exome samples.
The QC table
96 samples with mapping rate, duplication, Q30, GC, insert size and contamination (VerifyBamID freemix), plus lane / batch / library annotations. (Download: ngs-qc.csv.)
Z-score each metric and cluster: outlier samples and any batch/library structure jump out at a glance. This is the “is anything wrong, and where” view.
Four panels over the same samples, all sharing broadcastGroup = "qc". The sample is the unit, so each sample is a point (varAnnot carries its lane/batch/library). Select points in any panel — drag a box in a scatter, click a bar — and the same samples re-mark everywhere.
qc_panel(list(graphType ="Scatter2D", xAxis =list("gc_content"),yAxis =list("pct_q30"), colorBy ="Library",title ="Q30 vs GC content, coloured by library"),width =640, height =360)
4 — Sequencing depth per sample
qc_panel(list(graphType ="Bar", graphOrientation ="vertical",xAxis =list("total_reads"), colorBy ="Batch",title ="Total reads per sample (flag the short ones)"),width =820, height =300)
Put the four panels on one page (this document, a Shiny app, a flex layout). Lasso the bad cluster in panel 1 and panels 2–4 immediately restrict to those samples — you can read their contamination, their library, and their depth without a single callback. The “wiring” is one shared group id.
Why “reproducible”
Each panel is a portable data + config spec; the cross-filter is just a shared broadcastGroup. The same specs reproduce the dashboard from Python or JavaScript, against the same ngs-qc.csv.